[patch] Add discriminator support to gas .loc directive

Cary Coutant ccoutant@google.com
Tue Apr 21 01:38:00 GMT 2009


This patch adds a "discriminator" sub-op to the .loc directive, which
provides gas with the discriminator value to use for a given line
number table entry. Discriminators are a new feature in the DWARF line
number table to support sample-based profiling of code where two or
more basic blocks would otherwise have identical line number
information. The feature has been approved for DWARF version 4, and is
described in detail on the DWARF wiki:

http://wiki.dwarfstd.org/index.php?title=Path_Discriminators

I specifically do not update the DWARF version number in this patch,
since the resulting DWARF will still be compatible with version 2
consumers (all proper consumers should be able to ignore the new
opcode). No change at all in the DWARF info will be seen if there are
no "discriminator" sub-ops in the input assembly source.

I have a related patch for binutils/dwarf.c that I'll send separately
to enable readelf and objdump to print the discriminator information,
and I have a gcc patch that I will soon send to the gcc list that
generates the discriminators when necessary. A subsequent gcc patch
will introduce the sample-based profiling support that will actually
start using this information.

Tested on i386. Is this OK for trunk?

-cary


include/elf/

	* dwarf2.h (DW_LNE_set_discriminator): New enum value.

gas/
	* dwarf2dbg.h (struct dwarf2_line_info): Add discriminator field.
	* dwarf2dbg.c (current): Add discriminator field.
	(dwarf2_where): Copy discriminator value.
	(dwarf2_consume_line_info): Set discriminator to 0.
	(dwarf2_directive_loc): Process discriminator sub-op.
	(out_leb128): New function.
	(process_entries): Output DW_LNE_set_discriminator.
-------------- next part --------------
Index: include/elf/dwarf2.h
===================================================================
RCS file: /cvs/src/src/include/elf/dwarf2.h,v
retrieving revision 1.24
diff -u -p -r1.24 dwarf2.h
--- include/elf/dwarf2.h	24 Sep 2008 23:21:04 -0000	1.24
+++ include/elf/dwarf2.h	21 Apr 2009 01:15:27 -0000
@@ -709,6 +709,7 @@ enum dwarf_line_number_x_ops
     DW_LNE_end_sequence = 1,
     DW_LNE_set_address = 2,
     DW_LNE_define_file = 3,
+    DW_LNE_set_discriminator = 4,
     /* HP extensions.  */
     DW_LNE_HP_negate_is_UV_update      = 0x11,
     DW_LNE_HP_push_context             = 0x12,
Index: gas/dwarf2dbg.c
===================================================================
RCS file: /cvs/src/src/gas/dwarf2dbg.c,v
retrieving revision 1.100
diff -u -p -r1.100 dwarf2dbg.c
--- gas/dwarf2dbg.c	3 Mar 2009 10:04:58 -0000	1.100
+++ gas/dwarf2dbg.c	21 Apr 2009 01:15:27 -0000
@@ -25,7 +25,8 @@
 
 	.file FILENO "file.c"
 	.loc  FILENO LINENO [COLUMN] [basic_block] [prologue_end] \
-	      [epilogue_begin] [is_stmt VALUE] [isa VALUE]
+	      [epilogue_begin] [is_stmt VALUE] [isa VALUE] \
+	      [discriminator VALUE]
 */
 
 #include "as.h"
@@ -194,7 +195,8 @@ bfd_boolean dwarf2_loc_mark_labels;
 /* Current location as indicated by the most recent .loc directive.  */
 static struct dwarf2_line_info current = {
   1, 1, 0, 0,
-  DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0
+  DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0,
+  0
 };
 
 /* The size of an address on the target.  */
@@ -331,6 +333,7 @@ dwarf2_where (struct dwarf2_line_info *l
       line->column = 0;
       line->flags = DWARF2_FLAG_IS_STMT;
       line->isa = current.isa;
+      line->discriminator = current.discriminator;
     }
   else
     *line = current;
@@ -379,6 +382,7 @@ dwarf2_consume_line_info (void)
   current.flags &= ~(DWARF2_FLAG_BASIC_BLOCK
 		     | DWARF2_FLAG_PROLOGUE_END
 		     | DWARF2_FLAG_EPILOGUE_BEGIN);
+  current.discriminator = 0;
 }
 
 /* Called for each (preferably code) label.  If dwarf2_loc_mark_labels
@@ -581,6 +585,7 @@ dwarf2_directive_loc (int dummy ATTRIBUT
 
   current.filenum = filenum;
   current.line = line;
+  current.discriminator = 0;
 
 #ifndef NO_LISTING
   if (listing)
@@ -659,6 +664,18 @@ dwarf2_directive_loc (int dummy ATTRIBUT
 	      return;
 	    }
 	}
+      else if (strcmp (p, "discriminator") == 0)
+	{
+	  *input_line_pointer = c;
+	  value = get_absolute_expression ();
+	  if (value >= 0)
+	    current.discriminator = value;
+	  else
+	    {
+	      as_bad (_("discriminator less than zero"));
+	      return;
+	    }
+	}
       else
 	{
 	  as_bad (_("unknown .loc sub-directive `%s'"), p);
@@ -748,6 +765,14 @@ out_uleb128 (addressT value)
   output_leb128 (frag_more (sizeof_leb128 (value, 0)), value, 0);
 }
 
+/* Emit a signed "little-endian base 128" number.  */
+
+static void
+out_leb128 (addressT value)
+{
+  output_leb128 (frag_more (sizeof_leb128 (value, 1)), value, 1);
+}
+
 /* Emit a tuple for .debug_abbrev.  */
 
 static inline void
@@ -1208,6 +1233,14 @@ process_entries (segT seg, struct line_e
 	  out_uleb128 (column);
 	}
 
+      if (e->loc.discriminator != 0)
+	{
+	  out_opcode (DW_LNS_extended_op);
+	  out_leb128 (1 + sizeof_leb128 (e->loc.discriminator, 0));
+	  out_opcode (DW_LNE_set_discriminator);
+	  out_uleb128 (e->loc.discriminator);
+	}
+
       if (isa != e->loc.isa)
 	{
 	  isa = e->loc.isa;
Index: gas/dwarf2dbg.h
===================================================================
RCS file: /cvs/src/src/gas/dwarf2dbg.h,v
retrieving revision 1.22
diff -u -p -r1.22 dwarf2dbg.h
--- gas/dwarf2dbg.h	15 Jan 2009 12:42:52 -0000	1.22
+++ gas/dwarf2dbg.h	21 Apr 2009 01:15:27 -0000
@@ -34,6 +34,7 @@ struct dwarf2_line_info {
   unsigned int column;
   unsigned int isa;
   unsigned int flags;
+  unsigned int discriminator;
 };
 
 /* Implements the .file FILENO "FILENAME" directive.  FILENO can be 0


More information about the Binutils mailing list