Find all sections containing debug information and include them in the stash.
authorNick Clifton <nickc@redhat.com>
Sat, 2 Sep 2000 20:21:40 +0000 (20:21 +0000)
committerNick Clifton <nickc@redhat.com>
Sat, 2 Sep 2000 20:21:40 +0000 (20:21 +0000)
bfd/ChangeLog
bfd/dwarf2.c

index 9255101f86cdde9e68b2fe61fadbf9bd400cf313..9e0623c05e5426c52ac353312d15d8cb55d03d59 100644 (file)
@@ -1,3 +1,10 @@
+2000-09-02  Nick Clifton  <nickc@redhat.com>
+
+       * dwarf2.c (find_debug_info): New function: Locate a section
+       containing dwarf2 debug information.
+       (bfd_dwarf2_find_nearest_line): Find all sections containing
+       debug information and include them in the stash.
+
 2000-09-01  Niibe Yutaka  <gniibe@m17n.org>, Kaz Kojima  <kkojima@rr.iij4u.or.jp>, Alexandre Oliva  <aoliva@redhat.com>
 
        * elf32-sh.c (R_SH_GOT32, R_SH_PLT32, R_SH_COPY, R_SH_GLOB_DAT,
index 1c02912d214f390804b5bffdbfae2d7ccdb41754..7c8ddfdb0d4c3af8fefba1d88792fdba9dea11fa 100644 (file)
@@ -36,36 +36,38 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #include "elf/dwarf2.h"
 
 /* The data in the .debug_line statement prologue looks like this.  */
+
 struct line_head
-  {
-    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;
-  };
-
-/* Attributes have a name and a value */
+{
+  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;
+};
+
+/* Attributes have a name and a value.  */
+
 struct attribute
+{
+  enum dwarf_attribute name;
+  enum dwarf_form form;
+  union
   {
-    enum dwarf_attribute name;
-    enum dwarf_form form;
-    union
-      {
-       char *str;
-       struct dwarf_block *blk;
-       unsigned int unsnd;
-       int snd;
-       bfd_vma addr;
-      }
-    u;
-  };
-
-/* Get at parts of an attribute structure */
+    char *str;
+    struct dwarf_block *blk;
+    unsigned int unsnd;
+    int snd;
+    bfd_vma addr;
+  }
+  u;
+};
+
+/* Get at parts of an attribute structure.  */
 
 #define DW_STRING(attr)    ((attr)->u.str)
 #define DW_UNSND(attr)     ((attr)->u.unsnd)
@@ -75,29 +77,28 @@ struct attribute
 
 /* Blocks are a bunch of untyped bytes. */
 struct dwarf_block
-  {
-    unsigned int size;
-    char *data;
-  };
-
-
-struct dwarf2_debug {
+{
+  unsigned int size;
+  char *data;
+};
 
-  /* A list of all previously read comp_units. */
+struct dwarf2_debug
+{
+  /* A list of all previously read comp_units.  */
   struct comp_unit* all_comp_units;
 
   /* The next unread compilation unit within the .debug_info section.
      Zero indicates that the .debug_info section has not been loaded
-     into a buffer yet.*/
+     into a buffer yet.  */
   char* info_ptr;
 
-  /* Pointer to the end of the .debug_info section memory buffer. */
+  /* Pointer to the end of the .debug_info section memory buffer.  */
   char* info_ptr_end;
 
-  /* Pointer to the .debug_abbrev section loaded into memory. */
+  /* Pointer to the .debug_abbrev section loaded into memory.  */
   char* dwarf_abbrev_buffer;
 
-  /* Length of the loaded .debug_abbrev section. */
+  /* Length of the loaded .debug_abbrev section.  */
   unsigned long dwarf_abbrev_size;
 
   /* Buffer for decode_line_info.  */
@@ -107,69 +108,67 @@ struct dwarf2_debug {
   unsigned long dwarf_line_size;
 };
 
-struct arange {
+struct arange
+{
   struct arange *next;
   bfd_vma low;
   bfd_vma high;
 };
 
-
 /* A minimal decoding of DWARF2 compilation units.  We only decode
-   what's needed to get to the line number information. */
+   what's needed to get to the line number information.  */
 
-struct comp_unit {
-
-  /* Chain the previously read compilation units. */
+struct comp_unit
+{
+  /* Chain the previously read compilation units.  */
   struct comp_unit* next_unit;
 
-  /* Keep the bdf convenient (for memory allocation). */
+  /* Keep the bdf convenient (for memory allocation).  */
   bfd* abfd;
 
   /* The lowest and higest addresses contained in this compilation
-     unit as specified in the compilation unit header. */
+     unit as specified in the compilation unit header.  */
   struct arange arange;
 
-  /* The DW_AT_name attribute (for error messages). */
+  /* The DW_AT_name attribute (for error messages).  */
   char* name;
 
-  /* The abbrev hash table. */
+  /* The abbrev hash table.  */
   struct abbrev_info** abbrevs;
 
-  /* Note that an error was found by comp_unit_find_nearest_line. */
+  /* Note that an error was found by comp_unit_find_nearest_line.  */
   int error;
 
-  /* The DW_AT_comp_dir attribute */
+  /* The DW_AT_comp_dir attribute */
   char* comp_dir;
 
-  /* True if there is a line number table associated with this comp. unit. */
+  /* True if there is a line number table associated with this comp. unit.  */
   int stmtlist;
   
-  /* The offset into .debug_line of the line number table. */
+  /* The offset into .debug_line of the line number table.  */
   unsigned long line_offset;
 
-  /* Pointer to the first child die for the comp unit. */
+  /* Pointer to the first child die for the comp unit.  */
   char *first_child_die_ptr;
 
-  /* The end of the comp unit. */
+  /* The end of the comp unit.  */
   char *end_ptr;
 
-  /* The decoded line number, NULL if not yet decoded. */
+  /* The decoded line number, NULL if not yet decoded.  */
   struct line_info_table* line_table;
 
-  /* A list of the functions found in this comp. unit. */
+  /* A list of the functions found in this comp. unit.  */
   struct funcinfo* function_table; 
 
-  /* Address size for this unit - from unit header */
+  /* Address size for this unit - from unit header */
   unsigned char addr_size;
 };
 
-
-
 /* VERBATIM 
    The following function up to the END VERBATIM mark are 
-   copied directly from dwarf2read.c. */
+   copied directly from dwarf2read.c.  */
 
-/* read dwarf information from a buffer */
+/* Read dwarf information from a buffer.  */
 
 static unsigned int
 read_1_byte (abfd, buf)
@@ -195,9 +194,7 @@ read_2_bytes (abfd, buf)
   return bfd_get_16 (abfd, (bfd_byte *) buf);
 }
 
-#if 0
-
-/* This is not used.  */
+#if 0  /* This is not used.  */
 
 static int
 read_2_signed_bytes (abfd, buf)
@@ -217,9 +214,7 @@ read_4_bytes (abfd, buf)
   return bfd_get_32 (abfd, (bfd_byte *) buf);
 }
 
-#if 0
-
-/* This is not used.  */
+#if 0  /* This is not used.  */
 
 static int
 read_4_signed_bytes (abfd, buf)
@@ -265,6 +260,7 @@ read_string (abfd, buf, bytes_read_ptr)
       *bytes_read_ptr = 1;
       return NULL;
     }
+  
   *bytes_read_ptr = strlen (buf) + 1;
   return buf;
 }
@@ -352,26 +348,22 @@ read_address (unit, buf)
     }
 }
 
-
-
-
-
 /* This data structure holds the information of an abbrev. */
 struct abbrev_info
-  {
-    unsigned int number;       /* number identifying abbrev */
-    enum dwarf_tag tag;                /* dwarf tag */
-    int has_children;          /* boolean */
-    unsigned int num_attrs;    /* number of attributes */
-    struct attr_abbrev *attrs; /* an array of attribute descriptions */
-    struct abbrev_info *next;  /* next in chain */
-  };
+{
+  unsigned int number;         /* Number identifying abbrev.  */
+  enum dwarf_tag tag;          /* DWARF tag.  */
+  int has_children;            /* Boolean.  */
+  unsigned int num_attrs;      /* Number of attributes.  */
+  struct attr_abbrev *attrs;   /* An array of attribute descriptions.  */
+  struct abbrev_info *next;    /* Next in chain.  */
+};
 
 struct attr_abbrev
-  {
-    enum dwarf_attribute name;
-    enum dwarf_form form;
-  };
+{
+  enum dwarf_attribute name;
+  enum dwarf_form form;
+};
 
 #ifndef ABBREV_HASH_SIZE
 #define ABBREV_HASH_SIZE 121
@@ -400,6 +392,7 @@ lookup_abbrev (number,abbrevs)
       else
        abbrev = abbrev->next;
     }
+  
   return NULL;
 }
 
@@ -459,23 +452,24 @@ read_abbrevs (abfd, offset)
   abbrev_number = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
   abbrev_ptr += bytes_read;
 
-  /* loop until we reach an abbrev number of 0 */
+  /* Loop until we reach an abbrev number of 0.  */
   while (abbrev_number)
     {
       cur_abbrev = (struct abbrev_info*)bfd_zalloc (abfd, sizeof (struct abbrev_info));
 
-      /* read in abbrev header */
+      /* Read in abbrev header.  */
       cur_abbrev->number = abbrev_number;
       cur_abbrev->tag = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
       abbrev_ptr += bytes_read;
       cur_abbrev->has_children = read_1_byte (abfd, abbrev_ptr);
       abbrev_ptr += 1;
 
-      /* now read in declarations */
+      /* Now read in declarations.  */
       abbrev_name = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
       abbrev_ptr += bytes_read;
       abbrev_form = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
       abbrev_ptr += bytes_read;
+      
       while (abbrev_name)
        {
          if ((cur_abbrev->num_attrs % ATTR_ALLOC_CHUNK) == 0)
@@ -487,6 +481,7 @@ read_abbrevs (abfd, offset)
              if (! cur_abbrev->attrs)
                return 0;
            }
+         
          cur_abbrev->attrs[cur_abbrev->num_attrs].name = abbrev_name;
          cur_abbrev->attrs[cur_abbrev->num_attrs++].form = abbrev_form;
          abbrev_name = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
@@ -533,6 +528,7 @@ read_attribute (attr, abbrev, unit, info_ptr)
 
   attr->name = abbrev->name;
   attr->form = abbrev->form;
+  
   switch (abbrev->form)
     {
     case DW_FORM_addr:
@@ -634,35 +630,34 @@ read_attribute (attr, abbrev, unit, info_ptr)
   return info_ptr;
 }
 
-
-/* Source line information table routines. */
+/* Source line information table routines.  */
 
 #define FILE_ALLOC_CHUNK 5
 #define DIR_ALLOC_CHUNK 5
 
-struct line_info {
+struct line_info
+{
   struct line_info* prev_line;
-
   bfd_vma address;
   char* filename;
   unsigned int line;
   unsigned int column;
-  int end_sequence;            /* end of (sequential) code sequence */
+  int end_sequence;            /* End of (sequential) code sequence.  */
 };
 
-struct fileinfo {
+struct fileinfo
+{
   char *name;
   unsigned int dir;
   unsigned int time;
   unsigned int size;
 };
 
-struct line_info_table {
+struct line_info_table
+{
   bfd* abfd;
-
   unsigned int num_files;
   unsigned int num_dirs;
-
   char* comp_dir;
   char** dirs;
   struct fileinfo* files;
@@ -691,7 +686,7 @@ add_line_info (table, address, filename, line, column, end_sequence)
   info->end_sequence = end_sequence;
 }
 
-static char
+static char *
 concat_filename (table, file)
      struct line_info_table* table;
      unsigned int file;
@@ -726,8 +721,9 @@ arange_add (unit, low_pc, high_pc)
 {
   struct arange *arange;
 
-  /* first see if we can cheaply extend an existing range: */
+  /* First see if we can cheaply extend an existing range.  */
   arange = &unit->arange;
+  
   do
     {
       if (low_pc == arange->high)
@@ -746,14 +742,14 @@ arange_add (unit, low_pc, high_pc)
 
   if (unit->arange.high == 0)
     {
-      /* this is the first address range: store it in unit->arange: */
+      /* This is the first address range: store it in unit->arange.  */
       unit->arange.next = 0;
       unit->arange.low = low_pc;
       unit->arange.high = high_pc;
       return;
     }
 
-  /* need to allocate a new arange and insert it into the arange list: */
+  /* Need to allocate a new arange and insert it into the arange list.  */
   arange = bfd_zalloc (unit->abfd, sizeof (*arange));
   arange->low = low_pc;
   arange->high = high_pc;
@@ -762,18 +758,15 @@ arange_add (unit, low_pc, high_pc)
   unit->arange.next = arange;
 }
 
-/* Decode the line number information for UNIT. */
+/* Decode the line number information for UNIT.  */
 
 static struct line_info_table*
 decode_line_info (unit)
      struct comp_unit *unit;
 {
   bfd *abfd = unit->abfd;
-
   struct dwarf2_debug *stash;
-
   struct line_info_table* table;
-
   char *line_ptr;
   char *line_end;
   struct line_head lh;
@@ -806,7 +799,7 @@ decode_line_info (unit)
        return 0;
 
       /* FIXME: We ought to apply the relocs against this section before
-        we process it.... */
+        we process it...  */
     }
 
   /* Since we are using un-relocated data, it is possible to get a bad value
@@ -836,7 +829,7 @@ decode_line_info (unit)
 
   line_ptr = stash->dwarf_line_buffer + unit->line_offset;
 
-  /* read in the prologue */
+  /* Read in the prologue.  */
   lh.total_length = read_4_bytes (abfd, line_ptr);
   line_ptr += 4;
   line_end = line_ptr + lh.total_length;
@@ -858,16 +851,18 @@ decode_line_info (unit)
     bfd_alloc (abfd, lh.opcode_base * sizeof (unsigned char));
 
   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  */
+  /* Read directory table.  */
   while ((cur_dir = read_string (abfd, line_ptr, &bytes_read)) != NULL)
     {
       line_ptr += bytes_read;
+      
       if ((table->num_dirs % DIR_ALLOC_CHUNK) == 0)
        {
          table->dirs = (char **)
@@ -876,14 +871,17 @@ decode_line_info (unit)
          if (! table->dirs)
            return 0;
        }
+      
       table->dirs[table->num_dirs++] = cur_dir;
     }
+  
   line_ptr += bytes_read;
 
-  /* Read file name table */
+  /* Read file name table */
   while ((cur_file = read_string (abfd, line_ptr, &bytes_read)) != NULL)
     {
       line_ptr += bytes_read;
+      
       if ((table->num_files % FILE_ALLOC_CHUNK) == 0)
        {
          table->files = (struct fileinfo *)
@@ -893,6 +891,7 @@ decode_line_info (unit)
          if (! table->files)
            return 0;
        }
+      
       table->files[table->num_files].name = cur_file;
       table->files[table->num_files].dir =
        read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
@@ -905,12 +904,13 @@ decode_line_info (unit)
       line_ptr += bytes_read;
       table->num_files++;
     }
+  
   line_ptr += bytes_read;
 
   /* Read the statement sequences until there's nothing left.  */
   while (line_ptr < line_end)
     {
-      /* state machine registers  */
+      /* State machine registers.  */
       bfd_vma address = 0;
       char* filename = concat_filename (table, 1);
       unsigned int line = 1;
@@ -920,15 +920,16 @@ decode_line_info (unit)
       int end_sequence = 0, need_low_pc = 1;
       bfd_vma low_pc = 0;
 
-      /* Decode the table. */
+      /* Decode the table.  */
       while (! end_sequence)
        {
          op_code = read_1_byte (abfd, line_ptr);
          line_ptr += 1;
+         
          switch (op_code)
            {
            case DW_LNS_extended_op:
-             line_ptr += 1;    /* ignore length */
+             line_ptr += 1;    /* Ignore length.  */
              extended_op = read_1_byte (abfd, line_ptr);
              line_ptr += 1;
              switch (extended_op)
@@ -1025,12 +1026,12 @@ decode_line_info (unit)
              address += read_2_bytes (abfd, line_ptr);
              line_ptr += 2;
              break;
-           default:            /* special operand */
+           default:            /* 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);
-             /* append row to matrix using current values */
+             /* Append row to matrix using current values.  */
              add_line_info (table, address, filename, line, column, 0);
              basic_block = 1;
              if (need_low_pc)
@@ -1045,10 +1046,9 @@ decode_line_info (unit)
   return table;
 }
 
-
 /* If ADDR is within TABLE set the output parameters and return true,
    otherwise return false.  The output parameters, FILENAME_PTR and
-   LINENUMBER_PTR, are pointers to the objects to be filled in. */
+   LINENUMBER_PTR, are pointers to the objects to be filled in.  */
 
 static boolean
 lookup_address_in_line_info_table (table, 
@@ -1084,20 +1084,16 @@ lookup_address_in_line_info_table (table,
   return false;
 }
   
+/* Function table functions.  */
 
-
-
-/* Function table functions. */
-
-struct funcinfo {
+struct funcinfo
+{
   struct funcinfo *prev_func;
-
   char* name;
   bfd_vma low;
   bfd_vma high;
 };
 
-
 /* If ADDR is within TABLE, set FUNCTIONNAME_PTR, and return true. */
 
 static boolean
@@ -1124,14 +1120,10 @@ lookup_address_in_function_table (table,
   return false;
 }
 
-
-
-
-/* DWARF2 Compilation unit functions. */
-
+/* DWARF2 Compilation unit functions.  */
 
 /* Scan over each die in a comp. unit looking for functions to add
-   to the function table. */
+   to the function table.  */
 
 static boolean
 scan_unit_for_functions (unit)
@@ -1230,11 +1222,6 @@ scan_unit_for_functions (unit)
   return true;
 }
 
-
-
-
-
-
 /* Parse a DWARF2 compilation unit starting at INFO_PTR.  This
    includes the compilation unit header that proceeds the DIE's, but
    does not include the length field that preceeds each compilation
@@ -1299,7 +1286,7 @@ parse_comp_unit (abfd, info_ptr, end_ptr, abbrev_length)
       return 0;
     }
 
-  /* Read the abbrevs for this compilation unit into a table */
+  /* Read the abbrevs for this compilation unit into a table */
   abbrevs = read_abbrevs (abfd, abbrev_offset);
   if (! abbrevs)
       return 0;
@@ -1379,11 +1366,7 @@ parse_comp_unit (abfd, info_ptr, end_ptr, abbrev_length)
   return unit;
 }
 
-
-
-
-
-/* Return true if UNIT contains the address given by ADDR. */
+/* Return true if UNIT contains the address given by ADDR.  */
 
 static boolean
 comp_unit_contains_address (unit, addr)
@@ -1403,10 +1386,10 @@ comp_unit_contains_address (unit, addr)
       arange = arange->next;
     }
   while (arange);
+  
   return 0;
 }
 
-
 /* If UNIT contains ADDR, set the output parameters to the values for
    the line containing ADDR.  The output parameters, FILENAME_PTR,
    FUNCTIONNAME_PTR, and LINENUMBER_PTR, are pointers to the objects
@@ -1463,6 +1446,43 @@ comp_unit_find_nearest_line (unit, addr,
   return line_p || func_p;
 }
 
+/* Locate a section in a BFD containing debugging info.  The search starts from the
+   section after AFTER_SEC, or from the first section in the BFD if AFTER_SEC is
+   NULL.  The search works by examining the names of the sections.  There are two
+   permissiable names.  The first is .debug_info.  This is the standard DWARF2 name.
+   The second is a prefix .gnu.linkonce.wi.  This is a variation on the .debug_info
+   section which has a checksum describing the contents appended onto the name.  This
+   allows the linker to identify and discard duplicate debugging sections for
+   different compilation units.  */
+#define DWARF2_DEBUG_INFO ".debug_info"
+#define GNU_LINKONCE_INFO ".gnu.linkonce.wi."
+
+static asection *
+find_debug_info (abfd, after_sec)
+     bfd * abfd;
+     asection * after_sec;
+{
+  asection * msec;
+
+  if (after_sec)
+    msec = after_sec->next;
+  else
+    msec = abfd->sections;
+
+  while (msec)
+    {
+      if (strcmp (msec->name, DWARF2_DEBUG_INFO) == 0)
+       return msec;
+
+      if (strncmp (msec->name, GNU_LINKONCE_INFO, strlen (GNU_LINKONCE_INFO)) == 0)
+       return msec;
+
+      msec = msec->next;
+    }
+
+  return NULL;
+}
+
 /* The DWARF2 version of find_nearest line.  Return true if the line
    is found without error.  ADDR_SIZE is the number of bytes in the
    initial .debug_info length field and in the abbreviation offset.
@@ -1490,12 +1510,10 @@ _bfd_dwarf2_find_nearest_line (abfd, section, symbols, offset,
 
      We keep a list of all the previously read compilation units, and
      a pointer to the next un-read compilation unit.  Check the 
-     previously read units before reading more.
-     */
-
+     previously read units before reading more.  */
   struct dwarf2_debug *stash = elf_tdata (abfd)->dwarf2_find_line_info;
 
-  /* What address are we looking for? */
+  /* What address are we looking for?  */
   bfd_vma addr = offset + section->vma;
 
   struct comp_unit* each;
@@ -1513,71 +1531,84 @@ _bfd_dwarf2_find_nearest_line (abfd, section, symbols, offset,
     
   if (! stash)
     {
+      unsigned long total_size;
       asection *msec;
-      unsigned long size;
-      
+
       stash = elf_tdata (abfd)->dwarf2_find_line_info =
        (struct dwarf2_debug*) bfd_zalloc (abfd, sizeof (struct dwarf2_debug));
-      
       if (! stash)
        return false;
-      
-      msec = bfd_get_section_by_name (abfd, ".debug_info");
-      if (! msec)
-       {
-         /* No dwarf2 info.  Note that at this point the stash
-            has been allocated, but contains zeros, this lets
-            future calls to this function fail quicker. */
-         return false;
-       }
 
-      size = msec->_raw_size;
-      if (size == 0)
+      msec = find_debug_info (abfd, NULL);
+      if (! msec)
+       /* No dwarf2 info.  Note that at this point the stash
+          has been allocated, but contains zeros, this lets
+          future calls to this function fail quicker.  */
        return false;
+
+      /* There can be more than one DWARF2 info section in a BFD these days.
+         Read them all in and produce one large stash.  We do this in two
+        passes - in the first pass we just accumulate the section sizes.
+        In the second pass we read in the section's contents.  The allows
+        us to avoid reallocing the data as we add sections to the stash.  */
+      for (total_size = 0; msec; msec = find_debug_info (abfd, msec))
+       total_size += msec->_raw_size;
       
-      stash->info_ptr = (char *) bfd_alloc (abfd, size);
-      
-      if (! stash->info_ptr)
+      stash->info_ptr = (char *) bfd_alloc (abfd, total_size);
+      if (stash->info_ptr == NULL)
        return false;
 
-      if (! bfd_get_section_contents (abfd, msec, stash->info_ptr, 0, size))
+      stash->info_ptr_end = stash->info_ptr;
+
+      for (msec = find_debug_info (abfd, NULL);
+          msec;
+          msec = find_debug_info (abfd, msec))
        {
-         stash->info_ptr = 0;
-         return false;
+         unsigned long size;
+         unsigned long start;
+
+         size = msec->_raw_size;
+         if (size == 0)
+           continue;
+
+         start = stash->info_ptr_end - stash->info_ptr;
+
+         if (! bfd_get_section_contents (abfd, msec, stash->info_ptr + start, 0, size))
+           continue;
+
+         stash->info_ptr_end = stash->info_ptr + start + size;
        }
 
-      stash->info_ptr_end = stash->info_ptr + size;
-
-      /* FIXME: There is a problem with the contents of the
-        .debug_info section.  The 'low' and 'high' addresses of the
-        comp_units are computed by relocs against symbols in the
-        .text segment.  We need these addresses in order to determine
-        the nearest line number, and so we have to resolve the
-        relocs.  There is a similar problem when the .debug_line
-        section is processed as well (e.g., there may be relocs
-        against the operand of the DW_LNE_set_address operator).
-        
-        Unfortunately getting hold of the reloc information is hard...
-
-        For now, this means that disassembling object files (as
-        opposed to fully executables) does not always work as well as
-        we would like.  */
+      BFD_ASSERT (stash->info_ptr_end = stash->info_ptr + total_size);
     }
+
+  /* FIXME: There is a problem with the contents of the
+     .debug_info section.  The 'low' and 'high' addresses of the
+     comp_units are computed by relocs against symbols in the
+     .text segment.  We need these addresses in order to determine
+     the nearest line number, and so we have to resolve the
+     relocs.  There is a similar problem when the .debug_line
+     section is processed as well (e.g., there may be relocs
+     against the operand of the DW_LNE_set_address operator).
+     
+     Unfortunately getting hold of the reloc information is hard...
+     
+     For now, this means that disassembling object files (as
+     opposed to fully executables) does not always work as well as
+     we would like.  */
   
   /* A null info_ptr indicates that there is no dwarf2 info 
-     (or that an error occured while setting up the stash). */
-
+     (or that an error occured while setting up the stash).  */
   if (! stash->info_ptr)
     return false;
 
-  /* Check the previously read comp. units first. */
-
+  /* Check the previously read comp. units first.  */
   for (each = stash->all_comp_units; each; each = each->next_unit)
     if (comp_unit_contains_address (each, addr))
       return comp_unit_find_nearest_line (each, addr, filename_ptr, 
                                          functionname_ptr, linenumber_ptr);
 
-  /* Read each remaining comp. units checking each as they are read. */
+  /* Read each remaining comp. units checking each as they are read.  */
   while (stash->info_ptr < stash->info_ptr_end)
     {
       struct comp_unit* each;
@@ -1606,7 +1637,7 @@ _bfd_dwarf2_find_nearest_line (abfd, section, symbols, offset,
                 compilation units.  If we don't have them (i.e.,
                 unit->high == 0), we need to consult the line info
                 table to see if a compilation unit contains the given
-                address. */
+                address.  */
              if (each->arange.high > 0)
                {
                  if (comp_unit_contains_address (each, addr))
@@ -1630,5 +1661,3 @@ _bfd_dwarf2_find_nearest_line (abfd, section, symbols, offset,
 
   return false;
 }
-
-/* end of file */