PR ld/3191
authorDaniel Jacobowitz <drow@false.org>
Mon, 8 Sep 2008 21:58:29 +0000 (21:58 +0000)
committerDaniel Jacobowitz <drow@false.org>
Mon, 8 Sep 2008 21:58:29 +0000 (21:58 +0000)
* dwarf2.c (struct adjusted_section): Renamed from struct
loadable_section.
(struct dwarf2_debug): Adjust for renaming.  Add version field.
(read_attribute_value): Correctly handle DW_FORM_ref_addr for
DWARF3.
(find_abstract_instance_name): Pass a pointer to
attribute instead of offset.  For DW_FORM_ref_addr, get the
entry at the offset from the .debug_info section.
(scan_unit_for_symbols): Update.
(parse_comp_unit): Allow DWARF3.  Save the version.
(unset_sections): Update for renaming.
(place_sections): Likewise.  Set new VMAs for DWARF sections
also.

bfd/ChangeLog
bfd/dwarf2.c

index daf0ee6..b1e5697 100644 (file)
@@ -1,3 +1,21 @@
+2008-09-08  H.J. Lu  <hongjiu.lu@intel.com>
+           Daniel Jacobowitz  <dan@codesourcery.com>
+
+       PR ld/3191
+       * dwarf2.c (struct adjusted_section): Renamed from struct
+       loadable_section.
+       (struct dwarf2_debug): Adjust for renaming.  Add version field.
+       (read_attribute_value): Correctly handle DW_FORM_ref_addr for
+       DWARF3.
+       (find_abstract_instance_name): Pass a pointer to
+       attribute instead of offset.  For DW_FORM_ref_addr, get the
+       entry at the offset from the .debug_info section.
+       (scan_unit_for_symbols): Update.
+       (parse_comp_unit): Allow DWARF3.  Save the version.
+       (unset_sections): Update for renaming.
+       (place_sections): Likewise.  Set new VMAs for DWARF sections
+       also.
+
 2008-09-08  Tristan Gingold  <gingold@adacore.com>
 
        * configure.in: Update version to 2.19.50
index c53fdf0..a4918ac 100644 (file)
@@ -75,7 +75,7 @@ struct dwarf_block
   bfd_byte *data;
 };
 
-struct loadable_section
+struct adjusted_section
 {
   asection *section;
   bfd_vma adj_vma;
@@ -143,11 +143,11 @@ struct dwarf2_debug
      use. */
   struct funcinfo *inliner_chain;
 
-  /* Number of loadable sections.  */
-  unsigned int loadable_section_count;
+  /* Number of sections whose VMA we must adjust.  */
+  unsigned int adjusted_section_count;
 
-  /* Array of loadable sections.  */
-  struct loadable_section *loadable_sections;
+  /* Array of sections with adjusted VMA.  */
+  struct adjusted_section *adjusted_sections;
 
   /* Number of times find_line is called.  This is used in
      the heuristic for enabling the info hash tables.  */
@@ -237,6 +237,9 @@ struct comp_unit
   /* Pointer to dwarf2_debug structure.  */
   struct dwarf2_debug *stash;
 
+  /* DWARF format version for this unit - from unit header.  */
+  int version;
+
   /* Address size for this unit - from unit header.  */
   unsigned char addr_size;
 
@@ -742,9 +745,20 @@ read_attribute_value (struct attribute *attr,
 
   switch (form)
     {
-    case DW_FORM_addr:
-      /* FIXME: DWARF3 draft says DW_FORM_ref_addr is offset_size.  */
     case DW_FORM_ref_addr:
+      /* DW_FORM_ref_addr is an address in DWARF2, and an offset in
+        DWARF3.  */
+      if (unit->version == 3)
+       {
+         if (unit->offset_size == 4)
+           attr->u.val = read_4_bytes (unit->abfd, info_ptr);
+         else
+           attr->u.val = read_8_bytes (unit->abfd, info_ptr);
+         info_ptr += unit->offset_size;
+         break;
+       }
+      /* FALLTHROUGH */
+    case DW_FORM_addr:
       attr->u.val = read_address (unit, info_ptr);
       info_ptr += unit->addr_size;
       break;
@@ -1705,16 +1719,30 @@ lookup_symbol_in_variable_table (struct comp_unit *unit,
 }
 
 static char *
-find_abstract_instance_name (struct comp_unit *unit, bfd_uint64_t die_ref)
+find_abstract_instance_name (struct comp_unit *unit,
+                            struct attribute *attr_ptr)
 {
   bfd *abfd = unit->abfd;
   bfd_byte *info_ptr;
   unsigned int abbrev_number, bytes_read, i;
   struct abbrev_info *abbrev;
+  bfd_uint64_t die_ref = attr_ptr->u.val;
   struct attribute attr;
   char *name = 0;
 
-  info_ptr = unit->info_ptr_unit + die_ref;
+  /* DW_FORM_ref_addr can reference an entry in a different CU. It
+     is an offset from the .debug_info section, not the current CU.  */
+  if (attr_ptr->form == DW_FORM_ref_addr)
+    {
+      /* We only support DW_FORM_ref_addr within the same file, so
+        any relocations should be resolved already.  */
+      if (!die_ref)
+       abort ();
+
+      info_ptr = unit->stash->sec_info_ptr + die_ref;
+    }
+  else 
+    info_ptr = unit->info_ptr_unit + die_ref;
   abbrev_number = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
   info_ptr += bytes_read;
 
@@ -1740,7 +1768,7 @@ find_abstract_instance_name (struct comp_unit *unit, bfd_uint64_t die_ref)
                    name = attr.u.str;
                  break;
                case DW_AT_specification:
-                 name = find_abstract_instance_name (unit, attr.u.val);
+                 name = find_abstract_instance_name (unit, &attr);
                  break;
                case DW_AT_MIPS_linkage_name:
                  name = attr.u.str;
@@ -1902,7 +1930,7 @@ scan_unit_for_symbols (struct comp_unit *unit)
                  break;
 
                case DW_AT_abstract_origin:
-                 func->name = find_abstract_instance_name (unit, attr.u.val);
+                 func->name = find_abstract_instance_name (unit, &attr);
                  break;
 
                case DW_AT_name:
@@ -2070,9 +2098,9 @@ parse_comp_unit (struct dwarf2_debug *stash,
   addr_size = read_1_byte (abfd, info_ptr);
   info_ptr += 1;
 
-  if (version != 2)
+  if (version != 2 && version != 3)
     {
-      (*_bfd_error_handler) (_("Dwarf Error: found dwarf version '%u', this reader only handles version 2 information."), version);
+      (*_bfd_error_handler) (_("Dwarf Error: found dwarf version '%u', this reader only handles version 2 and 3 information."), version);
       bfd_set_error (bfd_error_bad_value);
       return 0;
     }
@@ -2120,6 +2148,7 @@ parse_comp_unit (struct dwarf2_debug *stash,
   amt = sizeof (struct comp_unit);
   unit = bfd_zalloc (abfd, amt);
   unit->abfd = abfd;
+  unit->version = version;
   unit->addr_size = addr_size;
   unit->offset_size = offset_size;
   unit->abbrevs = abbrevs;
@@ -2472,49 +2501,63 @@ find_debug_info (bfd *abfd, asection *after_sec)
   return NULL;
 }
 
-/* Unset vmas for loadable sections in STASH.  */
+/* Unset vmas for adjusted sections in STASH.  */
 
 static void
 unset_sections (struct dwarf2_debug *stash)
 {
   unsigned int i;
-  struct loadable_section *p;
+  struct adjusted_section *p;
 
-  i = stash->loadable_section_count;
-  p = stash->loadable_sections;
+  i = stash->adjusted_section_count;
+  p = stash->adjusted_sections;
   for (; i > 0; i--, p++)
     p->section->vma = 0;
 }
 
-/* Set unique vmas for loadable sections in ABFD and save vmas in
-   STASH for unset_sections.  */
+/* Set unique VMAs for loadable and DWARF sections in ABFD and save
+   VMAs in STASH for unset_sections.  */
 
 static bfd_boolean
 place_sections (bfd *abfd, struct dwarf2_debug *stash)
 {
-  struct loadable_section *p;
+  struct adjusted_section *p;
   unsigned int i;
 
-  if (stash->loadable_section_count != 0)
+  if (stash->adjusted_section_count != 0)
     {
-      i = stash->loadable_section_count;
-      p = stash->loadable_sections;
+      i = stash->adjusted_section_count;
+      p = stash->adjusted_sections;
       for (; i > 0; i--, p++)
        p->section->vma = p->adj_vma;
     }
   else
     {
       asection *sect;
-      bfd_vma last_vma = 0;
+      bfd_vma last_vma = 0, last_dwarf = 0;
       bfd_size_type amt;
-      struct loadable_section *p;
+      struct adjusted_section *p;
 
       i = 0;
       for (sect = abfd->sections; sect != NULL; sect = sect->next)
        {
          bfd_size_type sz;
+         int is_debug_info;
+
+         if (sect->vma != 0)
+           continue;
+
+         /* We need to adjust the VMAs of any .debug_info sections.
+            Skip compressed ones, since no relocations could target
+            them - they should not appear in object files anyway.  */
+         if (strcmp (sect->name, DWARF2_DEBUG_INFO) == 0)
+           is_debug_info = 1;
+         else if (CONST_STRNEQ (sect->name, GNU_LINKONCE_INFO))
+           is_debug_info = 1;
+         else
+           is_debug_info = 0;
 
-         if (sect->vma != 0 || (sect->flags & SEC_LOAD) == 0)
+         if (!is_debug_info && (sect->flags & SEC_LOAD) == 0)
            continue;
 
          sz = sect->rawsize ? sect->rawsize : sect->size;
@@ -2524,19 +2567,33 @@ place_sections (bfd *abfd, struct dwarf2_debug *stash)
          i++;
        }
 
-      amt = i * sizeof (struct loadable_section);
-      p = (struct loadable_section *) bfd_zalloc (abfd, amt);
+      amt = i * sizeof (struct adjusted_section);
+      p = (struct adjusted_section *) bfd_zalloc (abfd, amt);
       if (! p)
        return FALSE;
 
-      stash->loadable_sections = p;
-      stash->loadable_section_count = i;
+      stash->adjusted_sections = p;
+      stash->adjusted_section_count = i;
 
       for (sect = abfd->sections; sect != NULL; sect = sect->next)
        {
          bfd_size_type sz;
+         int is_debug_info;
 
-         if (sect->vma != 0 || (sect->flags & SEC_LOAD) == 0)
+         if (sect->vma != 0)
+           continue;
+
+         /* We need to adjust the VMAs of any .debug_info sections.
+            Skip compressed ones, since no relocations could target
+            them - they should not appear in object files anyway.  */
+         if (strcmp (sect->name, DWARF2_DEBUG_INFO) == 0)
+           is_debug_info = 1;
+         else if (CONST_STRNEQ (sect->name, GNU_LINKONCE_INFO))
+           is_debug_info = 1;
+         else
+           is_debug_info = 0;
+
+         if (!is_debug_info && (sect->flags & SEC_LOAD) == 0)
            continue;
 
          sz = sect->rawsize ? sect->rawsize : sect->size;
@@ -2544,7 +2601,13 @@ place_sections (bfd *abfd, struct dwarf2_debug *stash)
            continue;
 
          p->section = sect;
-         if (last_vma != 0)
+         if (is_debug_info)
+           {
+             BFD_ASSERT (sect->alignment_power == 0);
+             sect->vma = last_dwarf;
+             last_dwarf += sz;
+           }
+         else if (last_vma != 0)
            {
              /* Align the new address to the current section
                 alignment.  */
@@ -2552,9 +2615,12 @@ place_sections (bfd *abfd, struct dwarf2_debug *stash)
                           + ~((bfd_vma) -1 << sect->alignment_power))
                          & ((bfd_vma) -1 << sect->alignment_power));
              sect->vma = last_vma;
+             last_vma += sect->vma + sz;
            }
+         else
+           last_vma += sect->vma + sz;
+
          p->adj_vma = sect->vma;
-         last_vma += sect->vma + sz;
 
          p++;
        }