RFC: Support DW_FORM_ref_addr as described in DWARF 3
Jim Blandy
jimb@codesourcery.com
Tue Jun 20 19:53:00 GMT 2006
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. */
More information about the Gdb-patches
mailing list