This is the mail archive of the binutils@sources.redhat.com 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]

[RFA] Perform relocations in dwarf2.c


Hi all,
when running following command:
$ objdump -S something.o
on rela-type dwarf2 platforms it didn't show source lines, because _bfd_dwarf2_find_nearest_line() didn't perform relocations of symbols and thus returned wrong results.
Also there was a problem when parsing .debug_info on 64b paltforms - as far as I have seen, offsets in this section are always 32b (and specification says it as well), regardless whether on 64b or on 32b platform. There was some strange magic in _bfd_dwarf2_find_nearest_line() to find out the right offset size, but it didn't work anyway.

Can someone approve or comment it, please?

Michal Ludvig
--
* SuSE CR, s.r.o * mludvig@suse.cz
* (+420) 296.545.373 * http://www.suse.cz
2002-10-24  Michal Ludvig  <mludvig@suse.cz>

	* dwarf2.c (read_indirect_string, read_attribute, 
	read_attribute_value): Added parameter relp, changed prototype,
	added handling of relocations.
	(parse_comp_unit): Added handling of RELA relocations.

Index: dwarf2.c
===================================================================
RCS file: /cvs/src/src/bfd/dwarf2.c,v
retrieving revision 1.37
diff -u -p -r1.37 dwarf2.c
--- dwarf2.c	23 Oct 2002 12:41:32 -0000	1.37
+++ dwarf2.c	24 Oct 2002 00:18:07 -0000
@@ -216,7 +216,8 @@ static unsigned int read_4_bytes PARAMS 
 static bfd_vma read_8_bytes PARAMS ((bfd *, char *));
 static char *read_n_bytes PARAMS ((bfd *, char *, unsigned int));
 static char *read_string PARAMS ((bfd *, char *, unsigned int *));
-static char *read_indirect_string PARAMS ((struct comp_unit *, char *, unsigned int *));
+static char *read_indirect_string PARAMS ((struct comp_unit *, 
+	char *, unsigned int *, arelent *));
 static unsigned int read_unsigned_leb128
   PARAMS ((bfd *, char *, unsigned int *));
 static int read_signed_leb128
@@ -228,10 +229,10 @@ static struct abbrev_info **read_abbrevs
   PARAMS ((bfd *, bfd_vma, struct dwarf2_debug *));
 static char *read_attribute
   PARAMS ((struct attribute *, struct attr_abbrev *,
-	   struct comp_unit *, char *));
+	   struct comp_unit *, char *, arelent *));
 static char *read_attribute_value
   PARAMS ((struct attribute *, unsigned,
-	   struct comp_unit *, char *));
+	   struct comp_unit *, char *, arelent *));
 static void add_line_info
   PARAMS ((struct line_info_table *, bfd_vma, char *,
 	   unsigned int, unsigned int, int));
@@ -356,10 +357,11 @@ read_string (abfd, buf, bytes_read_ptr)
 }
 
 static char *
-read_indirect_string (unit, buf, bytes_read_ptr)
+read_indirect_string (unit, buf, bytes_read_ptr, relp)
      struct comp_unit* unit;
      char *buf;
      unsigned int *bytes_read_ptr;
+     arelent *relp;
 {
   bfd_vma offset;
   struct dwarf2_debug *stash = unit->stash;
@@ -369,6 +371,7 @@ read_indirect_string (unit, buf, bytes_r
   else
     offset = read_8_bytes (unit->abfd, buf);
   *bytes_read_ptr = unit->offset_size;
+  if (relp) offset += relp->addend;
 
   if (! stash->dwarf_str_buffer)
     {
@@ -635,11 +638,12 @@ read_abbrevs (abfd, offset, stash)
 /* Read an attribute value described by an attribute form.  */
 
 static char *
-read_attribute_value (attr, form, unit, info_ptr)
+read_attribute_value (attr, form, unit, info_ptr, relp)
      struct attribute   *attr;
      unsigned form;
      struct comp_unit   *unit;
      char               *info_ptr;
+     arelent            *relp;
 {
   bfd *abfd = unit->abfd;
   unsigned int bytes_read;
@@ -654,6 +658,7 @@ read_attribute_value (attr, form, unit, 
       /* FIXME: DWARF3 draft sais DW_FORM_ref_addr is offset_size.  */
     case DW_FORM_ref_addr:
       DW_ADDR (attr) = read_address (unit, info_ptr);
+      if (relp) DW_ADDR (attr) += relp->addend;
       info_ptr += unit->addr_size;
       break;
     case DW_FORM_block2:
@@ -691,7 +696,7 @@ read_attribute_value (attr, form, unit, 
       info_ptr += bytes_read;
       break;
     case DW_FORM_strp:
-      DW_STRING (attr) = read_indirect_string (unit, info_ptr, &bytes_read);
+      DW_STRING (attr) = read_indirect_string (unit, info_ptr, &bytes_read, relp);
       info_ptr += bytes_read;
       break;
     case DW_FORM_block:
@@ -751,7 +756,7 @@ read_attribute_value (attr, form, unit, 
     case DW_FORM_indirect:
       form = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
       info_ptr += bytes_read;
-      info_ptr = read_attribute_value (attr, form, unit, info_ptr);
+      info_ptr = read_attribute_value (attr, form, unit, info_ptr, relp);
       break;
     default:
       (*_bfd_error_handler) (_("Dwarf Error: Invalid or unhandled FORM value: %u."),
@@ -764,14 +769,15 @@ read_attribute_value (attr, form, unit, 
 /* Read an attribute described by an abbreviated attribute.  */
 
 static char *
-read_attribute (attr, abbrev, unit, info_ptr)
+read_attribute (attr, abbrev, unit, info_ptr, relp)
      struct attribute   *attr;
      struct attr_abbrev *abbrev;
      struct comp_unit   *unit;
      char               *info_ptr;
+     arelent            *relp;
 {
   attr->name = abbrev->name;
-  info_ptr = read_attribute_value (attr, abbrev->form, unit, info_ptr);
+  info_ptr = read_attribute_value (attr, abbrev->form, unit, info_ptr, relp);
   return info_ptr;
 }
 
@@ -1465,7 +1471,9 @@ scan_unit_for_functions (unit)
 
       for (i = 0; i < abbrev->num_attrs; ++i)
 	{
-	  info_ptr = read_attribute (&attr, &abbrev->attrs[i], unit, info_ptr);
+	  info_ptr = read_attribute (&attr, &abbrev->attrs[i], unit, info_ptr, 
+	  /* NULL? FIXME - we may need to do some relocations... */
+		  NULL); 
 
 	  if (func)
 	    {
@@ -1599,6 +1607,11 @@ parse_comp_unit (abfd, stash, unit_lengt
   char *end_ptr = info_ptr + unit_length;
   bfd_size_type amt;
   bfd_size_type off;
+  
+  asection *a = stash->sec;
+  asymbol **syms = stash->syms;
+  arelent **relpp = NULL, *relp;
+  int relsize, relcount=0, relindex;
 
   version = read_2_bytes (abfd, info_ptr);
   info_ptr += 2;
@@ -1664,6 +1677,18 @@ parse_comp_unit (abfd, stash, unit_lengt
       return 0;
     }
 
+  if(a->flags & SEC_RELOC)
+  {
+    relsize = bfd_get_reloc_upper_bound (abfd, a);
+    if (relsize > 0)
+    {
+  	  relpp = (arelent **) xmalloc (relsize);
+  	  relcount = bfd_canonicalize_reloc (abfd, a, relpp, syms);
+  	  if (relcount < 0)
+  		  return NULL;
+    }
+  }
+
   amt = sizeof (struct comp_unit);
   unit = (struct comp_unit*) bfd_zalloc (abfd, amt);
   unit->abfd = abfd;
@@ -1673,9 +1698,20 @@ parse_comp_unit (abfd, stash, unit_lengt
   unit->end_ptr = end_ptr;
   unit->stash = stash;
 
+  relindex = 0;
   for (i = 0; i < abbrev->num_attrs; ++i)
     {
-      info_ptr = read_attribute (&attr, &abbrev->attrs[i], unit, info_ptr);
+      unsigned long xoffset = info_ptr - stash->info_ptr + offset_size;
+
+      if (relpp)
+        for (; relindex < relcount && relpp && relpp[relindex] && 
+		relpp[relindex]->address < xoffset; 
+		relindex++) /* Do nothing, just find the right record */;
+
+      relp = (relpp && relpp[relindex] && relpp[relindex]->address == xoffset) ? 
+	      relpp[relindex] : NULL;
+      
+      info_ptr = read_attribute (&attr, &abbrev->attrs[i], unit, info_ptr, relp);
 
       /* Store the data if it is of an attribute we want to keep in a
 	 partial symbol table.  */
@@ -1949,21 +1985,6 @@ _bfd_dwarf2_find_nearest_line (abfd, sec
       stash->syms = symbols;
     }
 
-  /* 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).  */
   if (! stash->info_ptr)
@@ -1981,28 +2002,14 @@ _bfd_dwarf2_find_nearest_line (abfd, sec
     {
       bfd_vma length;
       boolean found;
-      unsigned int offset_size = addr_size;
-
-      if (addr_size == 4)
-	{
-	  length = read_4_bytes (abfd, stash->info_ptr);
-	  if (length == 0xffffffff)
-	    {
-	      offset_size = 8;
-	      length = read_8_bytes (abfd, stash->info_ptr + 4);
-	      stash->info_ptr += 8;
-	    }
-	  else if (length == 0)
-	    {
-	      /* Handle (non-standard) 64-bit DWARF2 formats.  */
-	      offset_size = 8;
-	      length = read_4_bytes (abfd, stash->info_ptr + 4);
-	      stash->info_ptr += 4;
-	    }
-	}
-      else
-	length = read_8_bytes (abfd, stash->info_ptr);
-      stash->info_ptr += addr_size;
+      /* All checked 64b platforms use 32b offsets in .debug_info. 
+       * 32b platforms use this size as well, of course. Seems to be 
+       * safe to hardcode it here.
+       * Checked on x86-64, alpha, ia64, sparc64 -- mludvig */
+      unsigned int offset_size = 4;
+      
+      length = read_4_bytes (abfd, stash->info_ptr);
+      stash->info_ptr += offset_size;
 
       if (length > 0)
 	{
Index: elf.c
===================================================================
RCS file: /cvs/src/src/bfd/elf.c,v
retrieving revision 1.164
diff -u -p -r1.164 elf.c
--- elf.c	19 Oct 2002 13:52:58 -0000	1.164
+++ elf.c	24 Oct 2002 00:18:08 -0000
@@ -6030,7 +6030,7 @@ _bfd_elf_find_nearest_line (abfd, sectio
 
   if (_bfd_dwarf2_find_nearest_line (abfd, section, symbols, offset,
 				     filename_ptr, functionname_ptr,
-				     line_ptr, 0,
+				     line_ptr, get_elf_backend_data(abfd)->s->arch_size/8,
 				     &elf_tdata (abfd)->dwarf2_find_line_info))
     {
       if (!*functionname_ptr)

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