diff mbox

dwarf2out.c: For DWARF 4+, output DW_AT_high_pc as constant offset.

Message ID 1335533816.29213.26.camel@springer.wildebeest.org
State New
Headers show

Commit Message

Mark Wielaard April 27, 2012, 1:36 p.m. UTC
Hi,

The DWARF spec says (since version 4) that DW_AT_high_pc can be
represented by a constant form.

        If the value of the DW_AT_high_pc is of class address, it is the
        relocated address of the first location past the last
        instruction associated with the entity; if it is of class
        constant, the value is an unsigned integer offset which when
        added to the low PC gives the address of the first location past
        the last instruction associated with the entity.

Encoding DW_AT_high_pc as constant offset saves a lot of relocations.
Which is what this patch does. I also have patches for elfutils,
binutils and gdb to handle the new form. Jakub has a patch for dwz to
make the format encoding optimal, which saves some space too. I couldn't
figure out a way to do this from dwarf2out.c even though in almost all
cases using a full DW_FORM_data4/8 is way too much. Any ideas?

But even without this, I think the patch is worth it just to get rid of
all the relocations necessary otherwise.

At first I thought of using a dw_val_class_delta class that held two
labels (a generic form of dw_val_class_vms_delta), but that seemed
overkill since the first label is always associated with the
DW_AT_low_pc attribute of the DIE. So I just made it a special new
class.

2012-04-27  Mark Wielaard  <mjw@redhat.com>

	* dwarf2out.h (enum dw_val_class): Add dw_val_class_high_pc.
	* dwarf2out.c (dw_val_equal_p): Handle dw_val_class_high_pc.
	(add_AT_low_high_pc): New function.
	(AT_lbl): Handle dw_val_class_high_pc.
	(print_die): Likewise.
	(attr_checksum): Likewise.
	(attr_checksum_ordered): Likewise.
	(same_dw_val_p): Likewise.
	(size_of_die): Likewise.
	(value_format): Likewise.
	(output_die): Likewise.
	(gen_subprogram_die): Use add_AT_low_high_pc.
	(add_high_low_attributes): Likewise.
	(dwarf2out_finish): Likewise.

Tested on x86_64-unknown-linux-gnu.

Cheers,

Mark

Comments

Jakub Jelinek April 27, 2012, 1:43 p.m. UTC | #1
On Fri, Apr 27, 2012 at 03:36:56PM +0200, Mark Wielaard wrote:
> But even without this, I think the patch is worth it just to get rid of
> all the relocations necessary otherwise.

IMHO we should defer applying this by a few months, given that GDB support
is only being added these days and -gdwarf-4 is now the default.
Applying it in August/September when there is already GDB version with
the support would be better.

> +  attr.dw_attr = DW_AT_high_pc;
> +  if (dwarf_version < 3)

Shouldn't this be < 4?  I think DWARF 3 doesn't have constant class
DW_AT_high_pc.

	Jakub
Mark Wielaard April 27, 2012, 6:16 p.m. UTC | #2
On Fri, 2012-04-27 at 15:43 +0200, Jakub Jelinek wrote:
> On Fri, Apr 27, 2012 at 03:36:56PM +0200, Mark Wielaard wrote:
> > But even without this, I think the patch is worth it just to get rid of
> > all the relocations necessary otherwise.
> 
> IMHO we should defer applying this by a few months, given that GDB support
> is only being added these days and -gdwarf-4 is now the default.
> Applying it in August/September when there is already GDB version with
> the support would be better.

OK, I'll try to remember and ping as soon as a new GDB release is out
with the patch in.

> > +  attr.dw_attr = DW_AT_high_pc;
> > +  if (dwarf_version < 3)
> 
> Shouldn't this be < 4?  I think DWARF 3 doesn't have constant class
> DW_AT_high_pc.

Oops, yes, thanks for spotting.

Cheers,

Mark
diff mbox

Patch

From 5e601bc28e283511b3f5d1bb1d2904251d909563 Mon Sep 17 00:00:00 2001
From: Mark Wielaard <mjw@redhat.com>
Date: Fri, 27 Apr 2012 14:27:14 +0200
Subject: [PATCH] dwarf2out.c: For DWARF 4+, output DW_AT_high_pc as constant
 offset.

        * dwarf2out.h (enum dw_val_class): Add dw_val_class_high_pc.
        * dwarf2out.c (dw_val_equal_p): Handle dw_val_class_high_pc.
        (add_AT_low_high_pc): New function.
        (AT_lbl): Handle dw_val_class_high_pc.
        (print_die): Likewise.
        (attr_checksum): Likewise.
        (attr_checksum_ordered): Likewise.
        (same_dw_val_p): Likewise.
        (size_of_die): Likewise.
        (value_format): Likewise.
        (output_die): Likewise.
        (gen_subprogram_die): Use add_AT_low_high_pc.
        (add_high_low_attributes): Likewise.
        (dwarf2out_finish): Likewise.
---
 gcc/ChangeLog   |   17 +++++++++++
 gcc/dwarf2out.c |   87 +++++++++++++++++++++++++++++++++++++++----------------
 gcc/dwarf2out.h |    3 +-
 3 files changed, 81 insertions(+), 26 deletions(-)

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index a93d3cd..66a32ad 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,20 @@ 
+2012-04-27  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf2out.h (enum dw_val_class): Add dw_val_class_high_pc.
+	* dwarf2out.c (dw_val_equal_p): Handle dw_val_class_high_pc.
+	(add_AT_low_high_pc): New function.
+	(AT_lbl): Handle dw_val_class_high_pc.
+	(print_die): Likewise.
+	(attr_checksum): Likewise.
+	(attr_checksum_ordered): Likewise.
+	(same_dw_val_p): Likewise.
+	(size_of_die): Likewise.
+	(value_format): Likewise.
+	(output_die): Likewise.
+	(gen_subprogram_die): Use add_AT_low_high_pc.
+	(add_high_low_attributes): Likewise.
+	(dwarf2out_finish): Likewise.
+
 2012-04-25  Jakub Jelinek  <jakub@redhat.com>
 
 	PR target/53110
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 766edba..fa2963b 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -1647,6 +1647,7 @@  dw_val_equal_p (dw_val_node *a, dw_val_node *b)
     case dw_val_class_fde_ref:
       return a->v.val_fde_index == b->v.val_fde_index;
     case dw_val_class_lbl_id:
+    case dw_val_class_high_pc:
       return strcmp (a->v.val_lbl_id, b->v.val_lbl_id) == 0;
     case dw_val_class_str:
       return a->v.val_str == b->v.val_str;
@@ -4350,6 +4351,26 @@  add_AT_data8 (dw_die_ref die, enum dwarf_attribute attr_kind,
   add_dwarf_attr (die, &attr);
 }
 
+/* Add DW_AT_low_pc and DW_AT_high_pc to a DIE.  */
+static inline void
+add_AT_low_high_pc (dw_die_ref die, const char *lbl_low, const char *lbl_high)
+{
+  dw_attr_node attr;
+
+  attr.dw_attr = DW_AT_low_pc;
+  attr.dw_attr_val.val_class = dw_val_class_lbl_id;
+  attr.dw_attr_val.v.val_lbl_id = xstrdup (lbl_low);
+  add_dwarf_attr (die, &attr);
+
+  attr.dw_attr = DW_AT_high_pc;
+  if (dwarf_version < 3)
+    attr.dw_attr_val.val_class = dw_val_class_lbl_id;
+  else
+    attr.dw_attr_val.val_class = dw_val_class_high_pc;
+  attr.dw_attr_val.v.val_lbl_id = xstrdup (lbl_high);
+  add_dwarf_attr (die, &attr);
+}
+
 /* Hash and equality functions for debug_str_hash.  */
 
 static hashval_t
@@ -4723,7 +4744,8 @@  AT_lbl (dw_attr_ref a)
 {
   gcc_assert (a && (AT_class (a) == dw_val_class_lbl_id
 		    || AT_class (a) == dw_val_class_lineptr
-		    || AT_class (a) == dw_val_class_macptr));
+		    || AT_class (a) == dw_val_class_macptr
+		    || AT_class (a) == dw_val_class_high_pc));
   return a->dw_attr_val.v.val_lbl_id;
 }
 
@@ -5602,6 +5624,7 @@  print_die (dw_die_ref die, FILE *outfile)
 	case dw_val_class_lbl_id:
 	case dw_val_class_lineptr:
 	case dw_val_class_macptr:
+	case dw_val_class_high_pc:
 	  fprintf (outfile, "label: %s", AT_lbl (a));
 	  break;
 	case dw_val_class_str:
@@ -5758,6 +5781,7 @@  attr_checksum (dw_attr_ref at, struct md5_ctx *ctx, int *mark)
     case dw_val_class_lbl_id:
     case dw_val_class_lineptr:
     case dw_val_class_macptr:
+    case dw_val_class_high_pc:
       break;
 
     case dw_val_class_file:
@@ -6030,6 +6054,7 @@  attr_checksum_ordered (enum dwarf_tag tag, dw_attr_ref at,
     case dw_val_class_lbl_id:
     case dw_val_class_lineptr:
     case dw_val_class_macptr:
+    case dw_val_class_high_pc:
       break;
 
     case dw_val_class_file:
@@ -6489,6 +6514,7 @@  same_dw_val_p (const dw_val_node *v1, const dw_val_node *v2, int *mark)
     case dw_val_class_lbl_id:
     case dw_val_class_lineptr:
     case dw_val_class_macptr:
+    case dw_val_class_high_pc:
       return 1;
 
     case dw_val_class_file:
@@ -7780,6 +7806,9 @@  size_of_die (dw_die_ref die)
 	case dw_val_class_vms_delta:
 	  size += DWARF_OFFSET_SIZE;
 	  break;
+	case dw_val_class_high_pc:
+	  size += DWARF2_ADDR_SIZE;
+	  break;
 	default:
 	  gcc_unreachable ();
 	}
@@ -8097,6 +8126,17 @@  value_format (dw_attr_ref a)
     case dw_val_class_data8:
       return DW_FORM_data8;
 
+    case dw_val_class_high_pc:
+      switch (DWARF2_ADDR_SIZE)
+	{
+	  case 4:
+	    return DW_FORM_data4;
+	  case 8:
+	    return DW_FORM_data8;
+	  default:
+	    gcc_unreachable ();
+	}
+
     default:
       gcc_unreachable ();
     }
@@ -8521,6 +8561,11 @@  output_die (dw_die_ref die)
 	    break;
 	  }
 
+	case dw_val_class_high_pc:
+	  dw2_asm_output_delta (DWARF2_ADDR_SIZE, AT_lbl (a),
+				get_AT_low_pc (die), "DW_AT_high_pc");
+	  break;
+
 	default:
 	  gcc_unreachable ();
 	}
@@ -17310,19 +17355,18 @@  gen_subprogram_die (tree decl, dw_die_ref context_die)
 	  if (fde->dw_fde_begin)
 	    {
 	      /* We have already generated the labels.  */
-	      add_AT_lbl_id (subr_die, DW_AT_low_pc, fde->dw_fde_begin);
-	      add_AT_lbl_id (subr_die, DW_AT_high_pc, fde->dw_fde_end);
+	      add_AT_low_high_pc (subr_die, fde->dw_fde_begin, fde->dw_fde_end);
 	    }
 	  else
 	    {
 	      /* Create start/end labels and add the range.  */
-	      char label_id[MAX_ARTIFICIAL_LABEL_BYTES];
-	      ASM_GENERATE_INTERNAL_LABEL (label_id, FUNC_BEGIN_LABEL,
+	      char label_id_low[MAX_ARTIFICIAL_LABEL_BYTES];
+	      char label_id_high[MAX_ARTIFICIAL_LABEL_BYTES];
+	      ASM_GENERATE_INTERNAL_LABEL (label_id_low, FUNC_BEGIN_LABEL,
 					   current_function_funcdef_no);
-	      add_AT_lbl_id (subr_die, DW_AT_low_pc, label_id);
-	      ASM_GENERATE_INTERNAL_LABEL (label_id, FUNC_END_LABEL,
+	      ASM_GENERATE_INTERNAL_LABEL (label_id_high, FUNC_END_LABEL,
 					   current_function_funcdef_no);
-	      add_AT_lbl_id (subr_die, DW_AT_high_pc, label_id);
+	      add_AT_low_high_pc (subr_die, label_id_low, label_id_high);
 	    }
 
 #if VMS_DEBUGGING_INFO
@@ -17388,10 +17432,8 @@  gen_subprogram_die (tree decl, dw_die_ref context_die)
 		  dw_die_ref seg_die;
 
 		  /* Do the 'primary' section.   */
-		  add_AT_lbl_id (subr_die, DW_AT_low_pc,
-				 fde->dw_fde_begin);
-		  add_AT_lbl_id (subr_die, DW_AT_high_pc,
-				 fde->dw_fde_end);
+		  add_AT_low_high_pc (subr_die, fde->dw_fde_begin,
+				      fde->dw_fde_end);
 		  /* Add it.   */
 		  add_pubname (decl, subr_die);
 
@@ -17417,18 +17459,15 @@  gen_subprogram_die (tree decl, dw_die_ref context_die)
 		    add_AT_flag (seg_die, DW_AT_artificial, 1);
 
 		  name = concat ("__second_sect_of_", name, NULL); 
-		  add_AT_lbl_id (seg_die, DW_AT_low_pc,
-				 fde->dw_fde_second_begin);
-		  add_AT_lbl_id (seg_die, DW_AT_high_pc,
-				 fde->dw_fde_second_end);
+		  add_AT_low_high_pc (seg_die, fde->dw_fde_second_begin,
+				      fde->dw_fde_second_end);
 		  add_name_attribute (seg_die, name);
 		  add_pubname_string (name, seg_die);
 		}
 	    }
 	  else
 	    {
-	      add_AT_lbl_id (subr_die, DW_AT_low_pc, fde->dw_fde_begin);
-	      add_AT_lbl_id (subr_die, DW_AT_high_pc, fde->dw_fde_end);
+	      add_AT_low_high_pc (subr_die, fde->dw_fde_begin, fde->dw_fde_end);
 	      add_pubname (decl, subr_die);
 	    }
 	}
@@ -18166,12 +18205,12 @@  add_high_low_attributes (tree stmt, dw_die_ref die)
     }
   else
     {
+      char label_high[MAX_ARTIFICIAL_LABEL_BYTES];
       ASM_GENERATE_INTERNAL_LABEL (label, BLOCK_BEGIN_LABEL,
 				   BLOCK_NUMBER (stmt));
-      add_AT_lbl_id (die, DW_AT_low_pc, label);
-      ASM_GENERATE_INTERNAL_LABEL (label, BLOCK_END_LABEL,
+      ASM_GENERATE_INTERNAL_LABEL (label_high, BLOCK_END_LABEL,
 				   BLOCK_NUMBER (stmt));
-      add_AT_lbl_id (die, DW_AT_high_pc, label);
+      add_AT_low_high_pc (die, label, label_high);
     }
 }
 
@@ -22635,10 +22674,8 @@  dwarf2out_finish (const char *filename)
     {
       /* Don't add if the CU has no associated code.  */
       if (text_section_used)
-	{
-	  add_AT_lbl_id (comp_unit_die (), DW_AT_low_pc, text_section_label);
-	  add_AT_lbl_id (comp_unit_die (), DW_AT_high_pc, text_end_label);
-	}
+	add_AT_low_high_pc (comp_unit_die (), text_section_label,
+			    text_end_label);
     }
   else
     {
diff --git a/gcc/dwarf2out.h b/gcc/dwarf2out.h
index 711e8ab..da3a578 100644
--- a/gcc/dwarf2out.h
+++ b/gcc/dwarf2out.h
@@ -154,7 +154,8 @@  enum dw_val_class
   dw_val_class_file,
   dw_val_class_data8,
   dw_val_class_decl_ref,
-  dw_val_class_vms_delta
+  dw_val_class_vms_delta,
+  dw_val_class_high_pc
 };
 
 /* Describe a floating point constant value, or a vector constant value.  */
-- 
1.7.7.6