Hi! As the attached testcase shows, we were generating invalid DWARF 3 for -gdwarf-3 for large DW_AT_data_member_location offsets. Unlike DWARF 2, DWARF 3 allows DW_AT_data_member_location to be either constant, block or loclistptr class, and for this combination it has a note there that DW_FORM_data[48] (which are used for loclistptr) aren't included then in constant class. We were generating a DW_FORM_data4 for the constant anyway, the following patch fixes it to generate DW_FORM_udata in that case instead.
Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? Would this be appropriate for 4.6 too? 2011-07-27 Jakub Jelinek <ja...@redhat.com> PR debug/49871 * dwarf2out.c (size_of_die, value_format, output_die): Use DW_FORM_udata instead of DW_FORM_data[48] for dw_val_class_unsigned_const DW_AT_data_member_location for DWARF 3. * gcc.dg/debug/dwarf2/pr49871.c: New test. --- gcc/dwarf2out.c.jj 2011-07-26 16:19:56.000000000 +0200 +++ gcc/dwarf2out.c 2011-07-27 18:55:11.000000000 +0200 @@ -7652,7 +7652,15 @@ size_of_die (dw_die_ref die) size += size_of_sleb128 (AT_int (a)); break; case dw_val_class_unsigned_const: - size += constant_size (AT_unsigned (a)); + { + int csize = constant_size (AT_unsigned (a)); + if (dwarf_version == 3 + && a->dw_attr == DW_AT_data_member_location + && csize >= 4) + size += size_of_uleb128 (AT_unsigned (a)); + else + size += csize; + } break; case dw_val_class_const_double: size += 2 * HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR; @@ -7953,8 +7961,16 @@ value_format (dw_attr_ref a) case 2: return DW_FORM_data2; case 4: + /* In DWARF3 DW_AT_data_member_location with + DW_FORM_data4 or DW_FORM_data8 is a loclistptr, not + constant, so we need to use DW_FORM_udata if we need + a large constant. */ + if (dwarf_version == 3 && a->dw_attr == DW_AT_data_member_location) + return DW_FORM_udata; return DW_FORM_data4; case 8: + if (dwarf_version == 3 && a->dw_attr == DW_AT_data_member_location) + return DW_FORM_udata; return DW_FORM_data8; default: gcc_unreachable (); @@ -8261,8 +8277,15 @@ output_die (dw_die_ref die) break; case dw_val_class_unsigned_const: - dw2_asm_output_data (constant_size (AT_unsigned (a)), - AT_unsigned (a), "%s", name); + { + int csize = constant_size (AT_unsigned (a)); + if (dwarf_version == 3 + && a->dw_attr == DW_AT_data_member_location + && csize >= 4) + dw2_asm_output_data_uleb128 (AT_unsigned (a), "%s", name); + else + dw2_asm_output_data (csize, AT_unsigned (a), "%s", name); + } break; case dw_val_class_const_double: --- gcc/testsuite/gcc.dg/debug/dwarf2/pr49871.c.jj 2011-07-27 19:14:10.000000000 +0200 +++ gcc/testsuite/gcc.dg/debug/dwarf2/pr49871.c 2011-07-27 19:15:40.000000000 +0200 @@ -0,0 +1,12 @@ +/* PR debug/49871 */ +/* { dg-do compile } */ +/* { dg-options "-gdwarf-3 -dA -fno-merge-debug-strings" } */ + +struct S +{ + char a[1 << 16]; + int b; +} s; + +/* { dg-final { scan-assembler "\\(DW_AT_data_member_location\\)\[^\\r\\n\]*\[\\r\\n\]+\[^\\r\\n\]*\\(DW_FORM_udata\\)" } } */ +/* { dg-final { scan-assembler-not "\\(DW_AT_data_member_location\\)\[^\\r\\n\]*\[\\r\\n\]+\[^\\r\\n\]*\\(DW_FORM_data\[48\]\\)" } } */ Jakub