* dwarf2.c (struct dwarf2_debug): Add sec, sec_info_ptr and syms.
authorAlexandre Oliva <aoliva@redhat.com>
Wed, 8 Aug 2001 11:17:34 +0000 (11:17 +0000)
committerAlexandre Oliva <aoliva@redhat.com>
Wed, 8 Aug 2001 11:17:34 +0000 (11:17 +0000)
(find_rela_addend): New function.
(parse_comp_unit): Call it to find the abbrev offset addend.
(_bfd_dwarf2_find_nearest_line): Initialize and maintain the new
members of dwarf2_debug as debugging information is read.

bfd/ChangeLog
bfd/dwarf2.c

index a15c488a8b4d1187e583411caa47e6712d413408..9429b0282ca554cb3969cdb056d0d3c3acc78d8b 100644 (file)
@@ -1,3 +1,11 @@
+2001-08-08  Alexandre Oliva  <aoliva@redhat.com>
+
+       * dwarf2.c (struct dwarf2_debug): Add sec, sec_info_ptr and syms.
+       (find_rela_addend): New function.
+       (parse_comp_unit): Call it to find the abbrev offset addend.
+       (_bfd_dwarf2_find_nearest_line): Initialize and maintain the new
+       members of dwarf2_debug as debugging information is read.
+
 2001-08-07  Nick Clifton  <nickc@cambridge.redhat.com>
 
        * coff-sh.c (sh_coff_reloc_type_lookup): Provide for sh-coff
index 4a032732c980714d4ba7766d51fea4d5072c211d..23a51fa98c3333de540cd9160706f9e196a3c0ab 100644 (file)
@@ -96,6 +96,14 @@ struct dwarf2_debug
   /* Pointer to the end of the .debug_info section memory buffer.  */
   char* info_ptr_end;
 
+  /* Pointer to the section and address of the beginning of the
+     section.  */
+  asection* sec;
+  char* sec_info_ptr;
+
+  /* Pointer to the symbol table.  */
+  asymbol** syms;
+
   /* Pointer to the .debug_abbrev section loaded into memory.  */
   char* dwarf_abbrev_buffer;
 
@@ -1219,6 +1227,60 @@ scan_unit_for_functions (unit)
   return true;
 }
 
+/* Look for a RELA relocation to be applied on OFFSET of section SEC,
+   and return the addend if such a relocation is found.  Since this is
+   only used to find relocations referring to the .debug_abbrev
+   section, we make sure the relocation refers to this section, but
+   this is not strictly necessary, and it can probably be safely
+   removed if needed.  However, it is important to note that this
+   function only returns the addend, it doesn't serve the purpose of
+   applying a generic relocation.
+
+   If no suitable relocation is found, or if it is not a real RELA
+   relocation, this function returns 0.  */
+
+static bfd_vma
+find_rela_addend (abfd, sec, offset, syms)
+     bfd* abfd;
+     asection* sec;
+     bfd_size_type offset;
+     asymbol** syms;
+{
+  long reloc_size = bfd_get_reloc_upper_bound (abfd, sec);
+  arelent **relocs = NULL;
+  long reloc_count, relc;
+
+  if (reloc_size <= 0)
+    return 0;
+
+  relocs = (arelent **) bfd_malloc ((size_t) reloc_size);
+  if (relocs == NULL)
+    return 0;
+
+  reloc_count = bfd_canonicalize_reloc (abfd, sec, relocs, syms);
+
+  if (reloc_count <= 0)
+    {
+      free (relocs);
+      return 0;
+    }
+
+  for (relc = 0; relc < reloc_count; relc++)
+    if (relocs[relc]->address == offset
+       && (*relocs[relc]->sym_ptr_ptr)->flags & BSF_SECTION_SYM
+       && strcmp ((*relocs[relc]->sym_ptr_ptr)->name,
+                  ".debug_abbrev") == 0)
+      {
+       bfd_vma addend = (relocs[relc]->howto->partial_inplace
+                         ? 0 : relocs[relc]->addend);
+       free (relocs);
+       return addend;
+      }
+  
+  free (relocs);
+  return 0;
+}
+
 /* 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
@@ -1259,6 +1321,13 @@ parse_comp_unit (abfd, stash, unit_length, abbrev_length)
     abbrev_offset = read_4_bytes (abfd, info_ptr);
   else if (abbrev_length == 8)
     abbrev_offset = read_8_bytes (abfd, info_ptr);
+  /* The abbrev offset is generally a relocation pointing to
+     .debug_abbrev+offset.  On RELA targets, we have to find the
+     relocation and extract the addend to obtain the actual
+     abbrev_offset, so do it here.  */
+  abbrev_offset += find_rela_addend (abfd, stash->sec,
+                                    info_ptr - stash->sec_info_ptr,
+                                    stash->syms);
   info_ptr += abbrev_length;
   addr_size = read_1_byte (abfd, info_ptr);
   info_ptr += 1;
@@ -1498,7 +1567,7 @@ _bfd_dwarf2_find_nearest_line (abfd, section, symbols, offset,
                               addr_size, pinfo)
      bfd *abfd;
      asection *section;
-     asymbol **symbols ATTRIBUTE_UNUSED;
+     asymbol **symbols;
      bfd_vma offset;
      const char **filename_ptr;
      const char **functionname_ptr;
@@ -1584,7 +1653,11 @@ _bfd_dwarf2_find_nearest_line (abfd, section, symbols, offset,
          stash->info_ptr_end = stash->info_ptr + start + size;
        }
 
-      BFD_ASSERT (stash->info_ptr_end = stash->info_ptr + total_size);
+      BFD_ASSERT (stash->info_ptr_end == stash->info_ptr + total_size);
+
+      stash->sec = find_debug_info (abfd, NULL);
+      stash->sec_info_ptr = stash->info_ptr;
+      stash->syms = symbols;
     }
 
   /* FIXME: There is a problem with the contents of the
@@ -1632,6 +1705,13 @@ _bfd_dwarf2_find_nearest_line (abfd, section, symbols, offset,
          each = parse_comp_unit (abfd, stash, length, addr_size);
          stash->info_ptr += length;
 
+         if ((bfd_vma) (stash->info_ptr - stash->sec_info_ptr)
+             == stash->sec->_raw_size)
+           {
+             stash->sec = find_debug_info (abfd, stash->sec);
+             stash->sec_info_ptr = stash->info_ptr;
+           }
+
          if (each)
            {
              each->next_unit = stash->all_comp_units;