[PATCH] Fix -gdwarf-3 DW_AT_data_member_location for >= 64KB offsets (PR debug/49871)

Jakub Jelinek jakub@redhat.com
Wed Jul 27 21:48:00 GMT 2011


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  <jakub@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



More information about the Gcc-patches mailing list