This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB 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]

RFC: Support DW_FORM_ref_addr as described in DWARF 3


Daniel Jacobowitz <dan@codesourcery.com> writes:
> On Thu, Jun 08, 2006 at 04:25:42PM -0700, Jim Blandy wrote:
>> I think this patch is right.  It's true that GDB doesn't support all
>> of DWARF 3, but GDB's general philosophy is to garner as much
>> information as it can, and punt the rest, which works well with
>> DWARF's philosophy.  So GDB shouldn't just punt entire compilation
>> units because they're marked as DWARF 3.
>
> I agree.
>
> There seems to be one structural change in .debug_info tied to the
> version number (there's also the initial lengths, but we already
> support that).  That is:
>
> References that use the attribute form DW_FORM_ref_addr are specified
> to be four bytes in the DWARF 32-bit format and eight bytes in the
> DWARF 64-bit format, while DWARF Version 2 specifies that such
> references have the same size as anaddress on the target system (see
> Sections 7.4 and 7.5.4).
>
> I see two places (skip_one_die and read_attribute_value) that are
> affected.  So, this should be an easy item to fix.

Here's a patch for this, as promised; how does it look?

2006-06-20  Jim Blandy  <jimb@codesourcery.com>

	Support DW_FORM_ref_addr as described in DWARF 3.
	* dwarf2read.c (struct comp_unit_head): New field, ref_addr_size.
	(read_comp_unit_head): Initialize CU's ref_addr_size field.
	(skip_one_die): Use ref_addr_size for DW_FORM_ref_addr attributes.
	(read_ref_addr): New function.
	(read_attribute_value): Call it.

Index: gdb/dwarf2read.c
===================================================================
RCS file: /cvs/src/src/gdb/dwarf2read.c,v
retrieving revision 1.199
diff -u -p -r1.199 dwarf2read.c
--- gdb/dwarf2read.c	14 Jun 2006 15:06:35 -0000	1.199
+++ gdb/dwarf2read.c	20 Jun 2006 18:18:46 -0000
@@ -233,6 +233,19 @@ struct comp_unit_head
   /* Size of the length field; either 4 or 12.  */
   unsigned int initial_length_size;
 
+  /* The size of a DW_FORM_ref_addr attribute.  This depends on
+     VERSION, above.
+
+     - For versions 2 and earlier, DW_FORM_ref_addr is the size of an
+       address, as given in the 'address size' field of the compilation
+       unit header.
+
+     - For versions 3 and later, a DW_FORM_ref_addr value is four bytes
+       in the 32-bit DWARF format, and eight bytes in the 64-bit DWARF
+       format --- in other words, it matches whatever size offset is
+       otherwise used to index the debugging info.  */
+  unsigned int ref_addr_size;
+
   /* Offset to the first byte of this compilation unit header in the
      .debug_info section, for resolving relative reference dies.  */
   unsigned int offset;
@@ -804,6 +817,9 @@ static CORE_ADDR read_address (bfd *, gd
 static LONGEST read_initial_length (bfd *, gdb_byte *,
                                     struct comp_unit_head *, unsigned int *);
 
+static LONGEST read_ref_addr (bfd *, gdb_byte *, const struct comp_unit_head *,
+                              unsigned int *);
+
 static LONGEST read_offset (bfd *, gdb_byte *, const struct comp_unit_head *,
                             unsigned int *);
 
@@ -1293,6 +1309,12 @@ read_comp_unit_head (struct comp_unit_he
     internal_error (__FILE__, __LINE__,
 		    _("read_comp_unit_head: dwarf from non elf file"));
   cu_header->signed_addr_p = signed_addr;
+
+  if (cu_header->version < 3)
+    cu_header->ref_addr_size = cu_header->addr_size;
+  else
+    cu_header->ref_addr_size = cu_header->offset_size;
+
   return info_ptr;
 }
 
@@ -2224,7 +2246,7 @@ skip_one_die (gdb_byte *info_ptr, struct
 	{
 	case DW_FORM_addr:
 	case DW_FORM_ref_addr:
-	  info_ptr += cu->header.addr_size;
+	  info_ptr += cu->header.ref_addr_size;
 	  break;
 	case DW_FORM_data1:
 	case DW_FORM_ref1:
@@ -5733,7 +5755,7 @@ read_attribute_value (struct attribute *
     {
     case DW_FORM_addr:
     case DW_FORM_ref_addr:
-      DW_ADDR (attr) = read_address (abfd, info_ptr, cu, &bytes_read);
+      DW_ADDR (attr) = read_ref_addr (abfd, info_ptr, &cu->header, &bytes_read);
       info_ptr += bytes_read;
       break;
     case DW_FORM_block2:
@@ -6027,6 +6049,32 @@ read_initial_length (bfd *abfd, gdb_byte
   return length;
 }
 
+
+static LONGEST
+read_ref_addr (bfd *abfd, gdb_byte *buf, const struct comp_unit_head *cu_header,
+               unsigned int *bytes_read)
+{
+  LONGEST retval = 0;
+
+  switch (cu_header->ref_addr_size)
+    {
+    case 4:
+      retval = bfd_get_32 (abfd, buf);
+      *bytes_read = 4;
+      break;
+    case 8:
+      retval = bfd_get_64 (abfd, buf);
+      *bytes_read = 8;
+      break;
+    default:
+      internal_error (__FILE__, __LINE__,
+		      _("read_ref_addr: bad switch [in module %s]"),
+		      bfd_get_filename (abfd));
+    }
+
+  return retval;
+}
+
 /* Read an offset from the data stream.  The size of the offset is
    given by cu_header->offset_size.  */
 


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