Separate the job of reading the line number info statement program
authorJim Blandy <jimb@codesourcery.com>
Mon, 6 May 2002 21:00:21 +0000 (21:00 +0000)
committerJim Blandy <jimb@codesourcery.com>
Mon, 6 May 2002 21:00:21 +0000 (21:00 +0000)
header (...expialidocious) out into its own function.
* dwarf2read.c (struct line_head, struct filenames, struct
directories): Replace with...
(struct line_header): New structure, containing the full
contents of the statement program header, including the
include directory and file name tables.
(read_file_scope): If we have line number info, instead of just
calling dwarf_decode_lines to do all the work, call
dwarf_decode_line_header first to get a `struct line_header'
containing the data in the statement program header, and then
pass that to dwarf_decode_lines, which will pick up where that
left off.  Be sure to clean up the `struct line_header' object.
(dwarf_decode_line_header, free_line_header, add_include_dir,
add_file_name): New functions.
(dwarf_decode_lines): Move all the code to read the statement
program header into dwarf_decode_line_header.  Take the line
header it built as the first argument, instead of the offset to
the compilation unit's line number info.  Use the new `struct
line_header' type instead of the old structures.  No need to do
cleanups here now, since we don't allocate anything.
(dwarf2_statement_list_fits_in_line_number_section,
dwarf2_line_header_too_long): New complaints.

gdb/ChangeLog
gdb/dwarf2read.c

index 4002c8096278df2c1161feda987030c3be7f0d64..93a2353ba3c2d4a2211a649ad1d995fe2e08e2cd 100644 (file)
@@ -1,3 +1,29 @@
+2002-05-06  Jim Blandy  <jimb@redhat.com>
+
+       Separate the job of reading the line number info statement program
+       header (...expialidocious) out into its own function.
+       * dwarf2read.c (struct line_head, struct filenames, struct
+       directories): Replace with...
+       (struct line_header): New structure, containing the full
+       contents of the statement program header, including the
+       include directory and file name tables.
+       (read_file_scope): If we have line number info, instead of just
+       calling dwarf_decode_lines to do all the work, call
+       dwarf_decode_line_header first to get a `struct line_header'
+       containing the data in the statement program header, and then
+       pass that to dwarf_decode_lines, which will pick up where that
+       left off.  Be sure to clean up the `struct line_header' object.
+       (dwarf_decode_line_header, free_line_header, add_include_dir,
+       add_file_name): New functions.
+       (dwarf_decode_lines): Move all the code to read the statement
+       program header into dwarf_decode_line_header.  Take the line
+       header it built as the first argument, instead of the offset to
+       the compilation unit's line number info.  Use the new `struct
+       line_header' type instead of the old structures.  No need to do
+       cleanups here now, since we don't allocate anything.
+       (dwarf2_statement_list_fits_in_line_number_section,
+       dwarf2_line_header_too_long): New complaints.
+
 2002-05-06  Elena Zannoni  <ezannoni@redhat.com>
 
        * gdbtypes.c (init_vector_type): New function.
index 0f05c0922fcc1c077a223e294deb589fa5a683a2..5c06e9af75f92df2b1f5611e39cf63d448b4f56c 100644 (file)
@@ -175,19 +175,49 @@ struct comp_unit_head
                                          4 or 12 */
   };
 
-/* The data in the .debug_line statement prologue looks like this.  */
-struct line_head
+/* The line number information for a compilation unit (found in the
+   .debug_line section) begins with a "statement program header",
+   which contains the following information.  */
+struct line_header
+{
+  unsigned int total_length;
+  unsigned short version;
+  unsigned int header_length;
+  unsigned char minimum_instruction_length;
+  unsigned char default_is_stmt;
+  int line_base;
+  unsigned char line_range;
+  unsigned char opcode_base;
+
+  /* standard_opcode_lengths[i] is the number of operands for the
+     standard opcode whose value is i.  This means that
+     standard_opcode_lengths[0] is unused, and the last meaningful
+     element is standard_opcode_lengths[opcode_base - 1].  */
+  unsigned char *standard_opcode_lengths;
+
+  /* The include_directories table.  NOTE!  These strings are not
+     allocated with xmalloc; instead, they are pointers into
+     debug_line_buffer.  If you try to free them, `free' will get
+     indigestion.  */
+  unsigned int num_include_dirs, include_dirs_size;
+  char **include_dirs;
+
+  /* The file_names table.  NOTE!  These strings are not allocated
+     with xmalloc; instead, they are pointers into debug_line_buffer.
+     Don't try to free them directly.  */
+  unsigned int num_file_names, file_names_size;
+  struct file_entry
   {
-    unsigned int total_length;
-    unsigned short version;
-    unsigned int prologue_length;
-    unsigned char minimum_instruction_length;
-    unsigned char default_is_stmt;
-    int line_base;
-    unsigned char line_range;
-    unsigned char opcode_base;
-    unsigned char *standard_opcode_lengths;
-  };
+    char *name;
+    unsigned int dir_index;
+    unsigned int mod_time;
+    unsigned int length;
+  } *file_names;
+
+  /* The start and end of the statement program following this
+     header.  These point into dwarf_line_buffer.  */
+  char *statement_program_start, *statement_program_end;
+};
 
 /* When we construct a partial symbol table entry we only
    need this much information. */
@@ -502,6 +532,10 @@ static struct complaint dwarf2_missing_line_number_section =
 {
   "missing .debug_line section", 0, 0
 };
+static struct complaint dwarf2_statement_list_fits_in_line_number_section =
+{
+  "statement list doesn't fit in .debug_line section", 0, 0
+};
 static struct complaint dwarf2_mangled_line_number_section =
 {
   "mangled .debug_line section", 0, 0
@@ -574,6 +608,10 @@ static struct complaint dwarf2_misplaced_line_number =
 {
   "misplaced first line number at 0x%lx for '%s'", 0, 0
 };
+static struct complaint dwarf2_line_header_too_long =
+{
+  "line number info header doesn't fit in `.debug_line' section", 0, 0
+};
 
 /* local function prototypes */
 
@@ -653,7 +691,14 @@ static struct attribute *dwarf_attr (struct die_info *, unsigned int);
 
 static int die_is_declaration (struct die_info *);
 
-static void dwarf_decode_lines (unsigned int, char *, bfd *,
+static void free_line_header (struct line_header *lh);
+
+static struct line_header *(dwarf_decode_line_header
+                            (unsigned int offset,
+                             bfd *abfd,
+                             const struct comp_unit_head *cu_header));
+
+static void dwarf_decode_lines (struct line_header *, char *, bfd *,
                                const struct comp_unit_head *);
 
 static void dwarf2_start_subfile (char *, char *);
@@ -1569,7 +1614,7 @@ static void
 read_file_scope (struct die_info *die, struct objfile *objfile,
                 const struct comp_unit_head *cu_header)
 {
-  unsigned int line_offset = 0;
+  struct cleanup *back_to = make_cleanup (null_cleanup, 0);
   CORE_ADDR lowpc = ((CORE_ADDR) -1);
   CORE_ADDR highpc = ((CORE_ADDR) 0);
   struct attribute *attr;
@@ -1577,6 +1622,7 @@ read_file_scope (struct die_info *die, struct objfile *objfile,
   char *comp_dir = NULL;
   struct die_info *child_die;
   bfd *abfd = objfile->obfd;
+  struct line_header *line_header = 0;
 
   if (!dwarf2_get_pc_bounds (die, &lowpc, &highpc, objfile))
     {
@@ -1674,9 +1720,18 @@ read_file_scope (struct die_info *die, struct objfile *objfile,
   attr = dwarf_attr (die, DW_AT_stmt_list);
   if (attr)
     {
-      line_offset = DW_UNSND (attr);
-      dwarf_decode_lines (line_offset, comp_dir, abfd, cu_header);
+      unsigned int line_offset = DW_UNSND (attr);
+      line_header = dwarf_decode_line_header (line_offset,
+                                              abfd, cu_header);
+      if (line_header)
+        {
+          make_cleanup ((make_cleanup_ftype *) free_line_header,
+                        (void *) line_header);
+          dwarf_decode_lines (line_header, comp_dir, abfd, cu_header);
+        }
     }
+
+  do_cleanups (back_to);
 }
 
 static void
@@ -3945,28 +4000,188 @@ die_is_declaration (struct die_info *die)
          && ! dwarf_attr (die, DW_AT_specification));
 }
 
-/* Decode the line number information for the compilation unit whose
-   line number info is at OFFSET in the .debug_line section.
-   The compilation directory of the file is passed in COMP_DIR.  */
 
-struct filenames
+/* Free the line_header structure *LH, and any arrays and strings it
+   refers to.  */
+static void
+free_line_header (struct line_header *lh)
+{
+  if (lh->standard_opcode_lengths)
+    free (lh->standard_opcode_lengths);
+
+  /* Remember that all the lh->file_names[i].name pointers are
+     pointers into debug_line_buffer, and don't need to be freed.  */
+  if (lh->file_names)
+    free (lh->file_names);
+
+  /* Similarly for the include directory names.  */
+  if (lh->include_dirs)
+    free (lh->include_dirs);
+
+  free (lh);
+}
+
+
+/* Add an entry to LH's include directory table.  */
+static void
+add_include_dir (struct line_header *lh, char *include_dir)
 {
-  unsigned int num_files;
-  struct fileinfo
+  /* Grow the array if necessary.  */
+  if (lh->include_dirs_size == 0)
     {
-      char *name;
-      unsigned int dir;
-      unsigned int time;
-      unsigned int size;
+      lh->include_dirs_size = 1; /* for testing */
+      lh->include_dirs = xmalloc (lh->include_dirs_size
+                                  * sizeof (*lh->include_dirs));
+    }
+  else if (lh->num_include_dirs >= lh->include_dirs_size)
+    {
+      lh->include_dirs_size *= 2;
+      lh->include_dirs = xrealloc (lh->include_dirs,
+                                   (lh->include_dirs_size
+                                    * sizeof (*lh->include_dirs)));
     }
-   *files;
-};
 
-struct directories
-  {
-    unsigned int num_dirs;
-    char **dirs;
-  };
+  lh->include_dirs[lh->num_include_dirs++] = include_dir;
+}
+
+/* Add an entry to LH's file name table.  */
+static void
+add_file_name (struct line_header *lh,
+               char *name,
+               unsigned int dir_index,
+               unsigned int mod_time,
+               unsigned int length)
+{
+  struct file_entry *fe;
+
+  /* Grow the array if necessary.  */
+  if (lh->file_names_size == 0)
+    {
+      lh->file_names_size = 1; /* for testing */
+      lh->file_names = xmalloc (lh->file_names_size
+                                * sizeof (*lh->file_names));
+    }
+  else if (lh->num_file_names >= lh->file_names_size)
+    {
+      lh->file_names_size *= 2;
+      lh->file_names = xrealloc (lh->file_names,
+                                 (lh->file_names_size
+                                  * sizeof (*lh->file_names)));
+    }
+
+  fe = &lh->file_names[lh->num_file_names++];
+  fe->name = name;
+  fe->dir_index = dir_index;
+  fe->mod_time = mod_time;
+  fe->length = length;
+}
+
+/* Read the statement program header starting at OFFSET in
+   dwarf_line_buffer, according to the endianness of ABFD.  Return a
+   pointer to a struct line_header, allocated using xmalloc.
+
+   NOTE: the strings in the include directory and file name tables of
+   the returned object point into debug_line_buffer, and must not be
+   freed.  */
+static struct line_header *
+dwarf_decode_line_header (unsigned int offset, bfd *abfd,
+                          const struct comp_unit_head *cu_header)
+{
+  struct cleanup *back_to;
+  struct line_header *lh;
+  char *line_ptr;
+  int bytes_read;
+  int i;
+  char *cur_dir, *cur_file;
+
+  if (dwarf_line_buffer == NULL)
+    {
+      complain (&dwarf2_missing_line_number_section);
+      return 0;
+    }
+
+  /* Make sure that at least there's room for the total_length field.  That
+     could be 12 bytes long, but we're just going to fudge that.  */
+  if (offset + 4 >= dwarf_line_size)
+    {
+      complain (&dwarf2_statement_list_fits_in_line_number_section);
+      return 0;
+    }
+
+  lh = xmalloc (sizeof (*lh));
+  memset (lh, 0, sizeof (*lh));
+  back_to = make_cleanup ((make_cleanup_ftype *) free_line_header,
+                          (void *) lh);
+
+  line_ptr = dwarf_line_buffer + offset;
+
+  /* read in the header */
+  lh->total_length = read_initial_length (abfd, line_ptr, NULL, &bytes_read);
+  line_ptr += bytes_read;
+  if (line_ptr + lh->total_length > dwarf_line_buffer + dwarf_line_size)
+    {
+      complain (&dwarf2_statement_list_fits_in_line_number_section);
+      return 0;
+    }
+  lh->statement_program_end = line_ptr + lh->total_length;
+  lh->version = read_2_bytes (abfd, line_ptr);
+  line_ptr += 2;
+  lh->header_length = read_offset (abfd, line_ptr, cu_header, &bytes_read);
+  line_ptr += bytes_read;
+  lh->minimum_instruction_length = read_1_byte (abfd, line_ptr);
+  line_ptr += 1;
+  lh->default_is_stmt = read_1_byte (abfd, line_ptr);
+  line_ptr += 1;
+  lh->line_base = read_1_signed_byte (abfd, line_ptr);
+  line_ptr += 1;
+  lh->line_range = read_1_byte (abfd, line_ptr);
+  line_ptr += 1;
+  lh->opcode_base = read_1_byte (abfd, line_ptr);
+  line_ptr += 1;
+  lh->standard_opcode_lengths
+    = (unsigned char *) xmalloc (lh->opcode_base * sizeof (unsigned char));
+
+  lh->standard_opcode_lengths[0] = 1;  /* This should never be used anyway.  */
+  for (i = 1; i < lh->opcode_base; ++i)
+    {
+      lh->standard_opcode_lengths[i] = read_1_byte (abfd, line_ptr);
+      line_ptr += 1;
+    }
+
+  /* Read directory table  */
+  while ((cur_dir = read_string (abfd, line_ptr, &bytes_read)) != NULL)
+    {
+      line_ptr += bytes_read;
+      add_include_dir (lh, cur_dir);
+    }
+  line_ptr += bytes_read;
+
+  /* Read file name table */
+  while ((cur_file = read_string (abfd, line_ptr, &bytes_read)) != NULL)
+    {
+      unsigned int dir_index, mod_time, length;
+
+      line_ptr += bytes_read;
+      dir_index = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+      line_ptr += bytes_read;
+      mod_time = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+      line_ptr += bytes_read;
+      length = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+      line_ptr += bytes_read;
+
+      add_file_name (lh, cur_file, dir_index, mod_time, length);
+    }
+  line_ptr += bytes_read;
+  lh->statement_program_start = line_ptr; 
+
+  if (line_ptr > dwarf_line_buffer + dwarf_line_size)
+    complain (&dwarf2_line_header_too_long);
+
+  discard_cleanups (back_to);
+  return lh;
+}
 
 /* This function exists to work around a bug in certain compilers
    (particularly GCC 2.95), in which the first line number marker of a
@@ -4013,109 +4228,22 @@ check_cu_functions (CORE_ADDR address)
   return fn->lowpc;
 }
 
+/* Decode the line number information for the compilation unit whose
+   line number info is at OFFSET in the .debug_line section.
+   The compilation directory of the file is passed in COMP_DIR.  */
+
 static void
-dwarf_decode_lines (unsigned int offset, char *comp_dir, bfd *abfd,
+dwarf_decode_lines (struct line_header *lh, char *comp_dir, bfd *abfd,
                    const struct comp_unit_head *cu_header)
 {
   char *line_ptr;
   char *line_end;
-  struct line_head lh;
-  struct cleanup *back_to;
   unsigned int i, bytes_read;
-  char *cur_file, *cur_dir;
+  char *cur_dir;
   unsigned char op_code, extended_op, adj_opcode;
 
-#define FILE_ALLOC_CHUNK 5
-#define DIR_ALLOC_CHUNK 5
-
-  struct filenames files;
-  struct directories dirs;
-
-  if (dwarf_line_buffer == NULL)
-    {
-      complain (&dwarf2_missing_line_number_section);
-      return;
-    }
-
-  files.num_files = 0;
-  files.files = NULL;
-
-  dirs.num_dirs = 0;
-  dirs.dirs = NULL;
-
-  line_ptr = dwarf_line_buffer + offset;
-
-  /* read in the prologue */
-  lh.total_length = read_initial_length (abfd, line_ptr, NULL, &bytes_read);
-  line_ptr += bytes_read;
-  line_end = line_ptr + lh.total_length;
-  lh.version = read_2_bytes (abfd, line_ptr);
-  line_ptr += 2;
-  lh.prologue_length = read_offset (abfd, line_ptr, cu_header, &bytes_read);
-  line_ptr += bytes_read;
-  lh.minimum_instruction_length = read_1_byte (abfd, line_ptr);
-  line_ptr += 1;
-  lh.default_is_stmt = read_1_byte (abfd, line_ptr);
-  line_ptr += 1;
-  lh.line_base = read_1_signed_byte (abfd, line_ptr);
-  line_ptr += 1;
-  lh.line_range = read_1_byte (abfd, line_ptr);
-  line_ptr += 1;
-  lh.opcode_base = read_1_byte (abfd, line_ptr);
-  line_ptr += 1;
-  lh.standard_opcode_lengths = (unsigned char *)
-    xmalloc (lh.opcode_base * sizeof (unsigned char));
-  back_to = make_cleanup (free_current_contents, &lh.standard_opcode_lengths);
-
-  lh.standard_opcode_lengths[0] = 1;
-  for (i = 1; i < lh.opcode_base; ++i)
-    {
-      lh.standard_opcode_lengths[i] = read_1_byte (abfd, line_ptr);
-      line_ptr += 1;
-    }
-
-  /* Read directory table  */
-  while ((cur_dir = read_string (abfd, line_ptr, &bytes_read)) != NULL)
-    {
-      line_ptr += bytes_read;
-      if ((dirs.num_dirs % DIR_ALLOC_CHUNK) == 0)
-       {
-         dirs.dirs = (char **)
-           xrealloc (dirs.dirs,
-                     (dirs.num_dirs + DIR_ALLOC_CHUNK) * sizeof (char *));
-         if (dirs.num_dirs == 0)
-           make_cleanup (free_current_contents, &dirs.dirs);
-       }
-      dirs.dirs[dirs.num_dirs++] = cur_dir;
-    }
-  line_ptr += bytes_read;
-
-  /* Read file name table */
-  while ((cur_file = read_string (abfd, line_ptr, &bytes_read)) != NULL)
-    {
-      line_ptr += bytes_read;
-      if ((files.num_files % FILE_ALLOC_CHUNK) == 0)
-       {
-         files.files = (struct fileinfo *)
-           xrealloc (files.files,
-                     (files.num_files + FILE_ALLOC_CHUNK)
-                     * sizeof (struct fileinfo));
-         if (files.num_files == 0)
-           make_cleanup (free_current_contents, &files.files);
-       }
-      files.files[files.num_files].name = cur_file;
-      files.files[files.num_files].dir =
-       read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
-      line_ptr += bytes_read;
-      files.files[files.num_files].time =
-       read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
-      line_ptr += bytes_read;
-      files.files[files.num_files].size =
-       read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
-      line_ptr += bytes_read;
-      files.num_files++;
-    }
-  line_ptr += bytes_read;
+  line_ptr = lh->statement_program_start;
+  line_end = lh->statement_program_end;
 
   /* Read the statement sequences until there's nothing left.  */
   while (line_ptr < line_end)
@@ -4125,19 +4253,23 @@ dwarf_decode_lines (unsigned int offset, char *comp_dir, bfd *abfd,
       unsigned int file = 1;
       unsigned int line = 1;
       unsigned int column = 0;
-      int is_stmt = lh.default_is_stmt;
+      int is_stmt = lh->default_is_stmt;
       int basic_block = 0;
       int end_sequence = 0;
 
       /* Start a subfile for the current file of the state machine.  */
-      if (files.num_files >= file)
+      if (lh->num_file_names >= file)
        {
-         /* The file and directory tables are 0 based, the references
-            are 1 based.  */
-         dwarf2_start_subfile (files.files[file - 1].name,
-                               (files.files[file - 1].dir
-                                ? dirs.dirs[files.files[file - 1].dir - 1]
-                                : comp_dir));
+         /* lh->include_dirs and lh->file_names are 0-based, but the
+            directory and file name numbers in the statement program
+            are 1-based.  */
+          struct file_entry *fe = &lh->file_names[file - 1];
+          char *dir;
+          if (fe->dir_index)
+            dir = lh->include_dirs[fe->dir_index - 1];
+          else
+            dir = comp_dir;
+         dwarf2_start_subfile (fe->name, dir);
        }
 
       /* Decode the table. */
@@ -4146,12 +4278,12 @@ dwarf_decode_lines (unsigned int offset, char *comp_dir, bfd *abfd,
          op_code = read_1_byte (abfd, line_ptr);
          line_ptr += 1;
 
-         if (op_code >= lh.opcode_base)
+         if (op_code >= lh->opcode_base)
            {           /* Special operand.  */
-             adj_opcode = op_code - lh.opcode_base;
-             address += (adj_opcode / lh.line_range)
-               * lh.minimum_instruction_length;
-             line += lh.line_base + (adj_opcode % lh.line_range);
+             adj_opcode = op_code - lh->opcode_base;
+             address += (adj_opcode / lh->line_range)
+               * lh->minimum_instruction_length;
+             line += lh->line_base + (adj_opcode % lh->line_range);
              /* append row to matrix using current values */
              address = check_cu_functions (address);
              record_line (current_subfile, line, address);
@@ -4175,32 +4307,27 @@ dwarf_decode_lines (unsigned int offset, char *comp_dir, bfd *abfd,
                  address += baseaddr;
                  break;
                case DW_LNE_define_file:
-                 cur_file = read_string (abfd, line_ptr, &bytes_read);
-                 line_ptr += bytes_read;
-                 if ((files.num_files % FILE_ALLOC_CHUNK) == 0)
-                   {
-                     files.files = (struct fileinfo *)
-                       xrealloc (files.files,
-                                 (files.num_files + FILE_ALLOC_CHUNK)
-                                 * sizeof (struct fileinfo));
-                     if (files.num_files == 0)
-                       make_cleanup (free_current_contents, &files.files);
-                   }
-                 files.files[files.num_files].name = cur_file;
-                 files.files[files.num_files].dir =
-                   read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
-                 line_ptr += bytes_read;
-                 files.files[files.num_files].time =
-                   read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
-                 line_ptr += bytes_read;
-                 files.files[files.num_files].size =
-                   read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
-                 line_ptr += bytes_read;
-                 files.num_files++;
+                  {
+                    char *cur_file;
+                    unsigned int dir_index, mod_time, length;
+                    
+                    cur_file = read_string (abfd, line_ptr, &bytes_read);
+                    line_ptr += bytes_read;
+                    dir_index =
+                      read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+                    line_ptr += bytes_read;
+                    mod_time =
+                      read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+                    line_ptr += bytes_read;
+                    length =
+                      read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+                    line_ptr += bytes_read;
+                    add_file_name (lh, cur_file, dir_index, mod_time, length);
+                  }
                  break;
                default:
                  complain (&dwarf2_mangled_line_number_section);
-                 goto done;
+                 return;
                }
              break;
            case DW_LNS_copy:
@@ -4209,7 +4336,7 @@ dwarf_decode_lines (unsigned int offset, char *comp_dir, bfd *abfd,
              basic_block = 0;
              break;
            case DW_LNS_advance_pc:
-             address += lh.minimum_instruction_length
+             address += lh->minimum_instruction_length
                * read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
              line_ptr += bytes_read;
              break;
@@ -4218,15 +4345,21 @@ dwarf_decode_lines (unsigned int offset, char *comp_dir, bfd *abfd,
              line_ptr += bytes_read;
              break;
            case DW_LNS_set_file:
-             /* The file and directory tables are 0 based, the references
-                are 1 based.  */
-             file = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
-             line_ptr += bytes_read;
-             dwarf2_start_subfile
-               (files.files[file - 1].name,
-                (files.files[file - 1].dir
-                 ? dirs.dirs[files.files[file - 1].dir - 1]
-                 : comp_dir));
+              {
+                /* lh->include_dirs and lh->file_names are 0-based,
+                   but the directory and file name numbers in the
+                   statement program are 1-based.  */
+                struct file_entry *fe;
+                char *dir;
+                file = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+                line_ptr += bytes_read;
+                fe = &lh->file_names[file - 1];
+                if (fe->dir_index)
+                  dir = lh->include_dirs[fe->dir_index - 1];
+                else
+                  dir = comp_dir;
+                dwarf2_start_subfile (fe->name, dir);
+              }
              break;
            case DW_LNS_set_column:
              column = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
@@ -4244,8 +4377,8 @@ dwarf_decode_lines (unsigned int offset, char *comp_dir, bfd *abfd,
               length since special opcode 255 would have scaled the
               the increment.  */
            case DW_LNS_const_add_pc:
-             address += (lh.minimum_instruction_length
-                         * ((255 - lh.opcode_base) / lh.line_range));
+             address += (lh->minimum_instruction_length
+                         * ((255 - lh->opcode_base) / lh->line_range));
              break;
            case DW_LNS_fixed_advance_pc:
              address += read_2_bytes (abfd, line_ptr);
@@ -4254,7 +4387,7 @@ dwarf_decode_lines (unsigned int offset, char *comp_dir, bfd *abfd,
            default:
              {  /* Unknown standard opcode, ignore it.  */
                int i;
-               for (i = 0; i < lh.standard_opcode_lengths[op_code]; i++)
+               for (i = 0; i < lh->standard_opcode_lengths[op_code]; i++)
                  {
                    (void) read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
                    line_ptr += bytes_read;
@@ -4263,8 +4396,6 @@ dwarf_decode_lines (unsigned int offset, char *comp_dir, bfd *abfd,
            }
        }
     }
-done:
-  do_cleanups (back_to);
 }
 
 /* Start a subfile for DWARF.  FILENAME is the name of the file and