This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: DWARF2 abstract origin issue


On Fri, Sep 05, 2008 at 01:24:25PM -0400, Daniel Jacobowitz wrote:
> This assertion will not be valid on PE-COFF targets where dwarf
> sections have a non-zero VMA.

Actually it's OK; I missed that this was in the object case only.
But here's a simpler patch, and I fixed another DWARF3 limitation
while I was here.

Does anyone see a problem with the attached patch?  Tested
on x86_64-linux-gnu and exercised a bit by hand with addr2line.

-- 
Daniel Jacobowitz
CodeSourcery

2008-09-05  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.

Index: dwarf2.c
===================================================================
RCS file: /cvs/src/src/bfd/dwarf2.c,v
retrieving revision 1.113
diff -u -p -r1.113 dwarf2.c
--- dwarf2.c	5 Sep 2008 17:55:07 -0000	1.113
+++ dwarf2.c	5 Sep 2008 19:01:06 -0000
@@ -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 *
 
   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 
 }
 
 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
 		    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 
 		  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 *st
   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 *st
   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 *af
   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 || (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;
@@ -2524,19 +2567,33 @@ place_sections (bfd *abfd, struct dwarf2
 	  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)
+	    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;
@@ -2544,7 +2601,13 @@ place_sections (bfd *abfd, struct dwarf2
 	    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
 			   + ~((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++;
 	}


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]