commit 4809b16f7e629929a10ab8b15816b4f6f775aa82 Author: Jim Blandy Date: Thu Dec 13 19:02:51 2007 +0000 commit 35fb264aa9a28b8d117df1e5a19fa3bfaf5a2cc8 Author: Jim Blandy Date: Mon Dec 17 18:38:30 2007 +0000 Cherry-picked and backported these, since gdb would crash reading dwarf 3 DW_AT_data_member_location that gcc generates now. -- Lubomir Rintel diff -urp gdb-6.1.orig/gdb/ChangeLog gdb-6.1/gdb/ChangeLog --- gdb-6.1.orig/gdb/ChangeLog 2009-08-08 17:04:24.836969960 +0200 +++ gdb-6.1/gdb/ChangeLog 2009-08-08 17:00:21.682970174 +0200 @@ -1,3 +1,14 @@ +2007-12-13 Jim Blandy + + * dwarf2read.c (attr_form_is_constant): New function. + (dwarf2_add_field): Use it and attr_form_is_section_offset to + recognize DW_AT_data_member_location attributes. Use + dwarf2_get_attr_constant_value when the attribute is a constant. + + * dwarf2read.c (attr_form_is_section_offset): New function. + (dwarf_add_member_fn, read_common_block, read_partial_die) + (dwarf2_symbol_mark_computed): Use it, instead of writing it out. + 2004-04-03 GDB Administrator GDB 6.1 released. diff -urp gdb-6.1.orig/gdb/dwarf2read.c gdb-6.1/gdb/dwarf2read.c --- gdb-6.1.orig/gdb/dwarf2read.c 2009-06-30 17:31:20.000000000 +0200 +++ gdb-6.1/gdb/dwarf2read.c 2009-08-08 17:20:00.031969143 +0200 @@ -922,6 +922,10 @@ static void dwarf_decode_macros (struct static int attr_form_is_block (struct attribute *); +static int attr_form_is_section_offset (struct attribute *); + +static int attr_form_is_constant (struct attribute *); + static void dwarf2_symbol_mark_computed (struct attribute *attr, struct symbol *sym, struct dwarf2_cu *cu); @@ -2618,8 +2622,16 @@ dwarf2_add_field (struct field_info *fip attr = dwarf2_attr (die, DW_AT_data_member_location, cu); if (attr) { - FIELD_BITPOS (*fp) = - decode_locdesc (DW_BLOCK (attr), cu) * bits_per_byte; + if (attr_form_is_section_offset (attr)) + { + dwarf2_complex_location_expr_complaint (); + FIELD_BITPOS (*fp) = 0; + } + else if (attr_form_is_constant (attr)) + FIELD_BITPOS (*fp) = dwarf2_get_attr_constant_value (attr, 0); + else + FIELD_BITPOS (*fp) = + decode_locdesc (DW_BLOCK (attr), cu) * bits_per_byte; } else FIELD_BITPOS (*fp) = 0; @@ -2939,7 +2951,7 @@ dwarf2_add_member_fn (struct field_info { fnp->voffset = decode_locdesc (DW_BLOCK (attr), cu) + 2; } - else if (attr->form == DW_FORM_data4 || attr->form == DW_FORM_data8) + else if (attr_form_is_section_offset (attr)) { dwarf2_complex_location_expr_complaint (); } @@ -3482,7 +3494,7 @@ read_common_block (struct die_info *die, { base = decode_locdesc (DW_BLOCK (attr), cu); } - else if (attr->form == DW_FORM_data4 || attr->form == DW_FORM_data8) + else if (attr_form_is_section_offset (attr)) { dwarf2_complex_location_expr_complaint (); } @@ -4392,7 +4404,7 @@ read_partial_die (struct partial_die_inf { part_die->locdesc = DW_BLOCK (&attr); } - else if (attr.form == DW_FORM_data4 || attr.form == DW_FORM_data8) + else if (attr_form_is_section_offset (&attr)) { dwarf2_complex_location_expr_complaint (); } @@ -8030,11 +8042,51 @@ attr_form_is_block (struct attribute *at || attr->form == DW_FORM_block); } +/* Return non-zero if ATTR's value is a section offset (classes + lineptr, loclistptr, macptr or rangelistptr). In this case, + you may use DW_UNSND (attr) to retrieve the offset. */ +static int +attr_form_is_section_offset (struct attribute *attr) +{ + return (attr->form == DW_FORM_data4 + || attr->form == DW_FORM_data8); +} + + +/* Return non-zero if ATTR's value falls in the 'constant' class, or + zero otherwise. When this function returns true, you can apply + dwarf2_get_attr_constant_value to it. + + However, note that for some attributes you must check + attr_form_is_section_offset before using this test. DW_FORM_data4 + and DW_FORM_data8 are members of both the constant class, and of + the classes that contain offsets into other debug sections + (lineptr, loclistptr, macptr or rangelistptr). The DWARF spec says + that, if an attribute's can be either a constant or one of the + section offset classes, DW_FORM_data4 and DW_FORM_data8 should be + taken as section offsets, not constants. */ +static int +attr_form_is_constant (struct attribute *attr) +{ + switch (attr->form) + { + case DW_FORM_sdata: + case DW_FORM_udata: + case DW_FORM_data1: + case DW_FORM_data2: + case DW_FORM_data4: + case DW_FORM_data8: + return 1; + default: + return 0; + } +} + static void dwarf2_symbol_mark_computed (struct attribute *attr, struct symbol *sym, struct dwarf2_cu *cu) { - if (attr->form == DW_FORM_data4 || attr->form == DW_FORM_data8) + if (attr_form_is_section_offset (attr)) { struct dwarf2_loclist_baton *baton; diff -urp gdb-6.1.orig/gdb/ChangeLog gdb-6.1/gdb/ChangeLog --- gdb-6.1.orig/gdb/ChangeLog 2009-08-08 20:49:34.000000000 +0200 +++ gdb-6.1/gdb/ChangeLog 2009-08-09 13:04:25.842288308 +0200 @@ -1,3 +1,11 @@ +2007-12-17 Jim Blandy + + * dwarf2read.c (dwarf2_add_field): Correctly scale all byte + offsets obtained from DW_AT_data_member_location before recording + them in FIELD_BITPOS (*fp). + + * dwarf2read.c (attr_form_is_section_offset): Doc fixes. + 2007-12-13 Jim Blandy * dwarf2read.c (attr_form_is_constant): New function. diff -urp gdb-6.1.orig/gdb/dwarf2read.c gdb-6.1/gdb/dwarf2read.c --- gdb-6.1.orig/gdb/dwarf2read.c 2009-08-08 20:49:34.000000000 +0200 +++ gdb-6.1/gdb/dwarf2read.c 2009-08-09 13:04:25.864291129 +0200 @@ -2622,16 +2622,19 @@ dwarf2_add_field (struct field_info *fip attr = dwarf2_attr (die, DW_AT_data_member_location, cu); if (attr) { + int byte_offset; + if (attr_form_is_section_offset (attr)) { dwarf2_complex_location_expr_complaint (); - FIELD_BITPOS (*fp) = 0; + byte_offset = 0; } else if (attr_form_is_constant (attr)) - FIELD_BITPOS (*fp) = dwarf2_get_attr_constant_value (attr, 0); + byte_offset = dwarf2_get_attr_constant_value (attr, 0); else - FIELD_BITPOS (*fp) = - decode_locdesc (DW_BLOCK (attr), cu) * bits_per_byte; + byte_offset = decode_locdesc (DW_BLOCK (attr), cu); + + FIELD_BITPOS (*fp) = byte_offset * bits_per_byte; } else FIELD_BITPOS (*fp) = 0; @@ -8042,9 +8045,14 @@ attr_form_is_block (struct attribute *at || attr->form == DW_FORM_block); } -/* Return non-zero if ATTR's value is a section offset (classes - lineptr, loclistptr, macptr or rangelistptr). In this case, - you may use DW_UNSND (attr) to retrieve the offset. */ +/* Return non-zero if ATTR's value is a section offset --- classes + lineptr, loclistptr, macptr or rangelistptr --- or zero, otherwise. + You may use DW_UNSND (attr) to retrieve such offsets. + + Section 7.5.4, "Attribute Encodings", explains that no attribute + may have a value that belongs to more than one of these classes; it + would be ambiguous if we did, because we use the same forms for all + of them. */ static int attr_form_is_section_offset (struct attribute *attr) {