Patchwork [Google,Debugfission] Add pubnames and pubtypes to google/main (issue5489074)

login
register
mail settings
Submitter Sterling Augustine
Date Dec. 17, 2011, 7:26 p.m.
Message ID <20111217192650.736B6160785@sterling.mtv.corp.google.com>
Download mbox | patch
Permalink /patch/132020/
State New
Headers show

Comments

Sterling Augustine - Dec. 17, 2011, 7:26 p.m.
Enclosed for review and inclusion on the google/main and google/4_6 trees is the
first patch for the debugfission project.  It includes producing a complete and
correct set of .debug_pubnames and .debug_pubtypes, as well as switching the
default to generate .debug_pubnames and .debug_pubtypes.

It further (and the most worth of review), changes certain decl printers (which
are used to generate debug info) to be more consistent with the naming
conventions used by demanglers.

Tested:
Via complete bootstap and running the test suite. No new failures found.

ChangeLog:
2011-12-17   Sterling Augustine  <saugustine@google.com>

	* gcc/dwarf2out.c (is_cu_die, is_namespace_die, is_class_die): New
	functions.
	(add_pubname): Call is_namespace_die, is_cu_die, and is_class_die in
	conditional.
	(add_enumerator_pubname): New function.
	(add_pubtype): Call is_namespace_die. Rework name calculation.  Call
	type_tag, lang_hooks.dwarf_name and add_enumerator_pubname.
	(output_pubnames): Output debug_pubnames_section_label or
	debug_pubtypes_section_label.
	(base_type_die): Call add_pubtype.
	(gen_namespace_die): Call add_pubname_string and lang_hooks.dwarf_name.
	(dwarf2out_init): Generate debug_pubnames_section_label and
	debug_pubtypes_section_label.
	(dwarf2out_finish): Call add_AT_lineptr if pubnames or pubtypes is
	non-empty.  When dealing with pubnames, change assertion to conditional.
	Call pubtypes_section_empty.  Likewise when dealing with pubtypes.
	Move code checking for empty section to...
	(pubtypes_section_empty): ...here. New function.
	* gcc/target.def: Switch default generate pubnames and types to true.

cp-family/ChangeLog:
2011-12-17   Sterling Augustine  <saugustine@google.com>

	* gcc/c-family/c-pretty-print.c (pp_c_specifier_qualifier_list): Move
	conditional from beginning to end.

cp/ChangeLog
2011-12-17   Sterling Augustine  <saugustine@google.com>

	* gcc/cp/error.c (dump_decl): Reformat return value to
	"(anonymous namespace)".
	(lang_decl_name): Return "(anonymous namespace)" when appropriate.

include/ChangeLog
	* include/dwarf2.h (enum dwarf_form): Add forms DW_FORM_GNU_ref_index,
	DW_FORM_GNU_addr_index and DW_FORM_GNU_str_index.
	(enum dwarf_attribute): Add attributes: Add DW_AT_GNU_dwo_name,
	DW_AT_GNU_dwo_id, DW_AT_GNU_ref_base, DW_AT_GNU_addr_base,
	DW_AT_GNU_pubnames and DW_AT_GNU_pubtypes.

--
This patch is available for review at http://codereview.appspot.com/5489074
Cary Coutant - Dec. 18, 2011, 6:46 a.m.
> 2011-12-17   Sterling Augustine  <saugustine@google.com>
>
>        * gcc/dwarf2out.c (is_cu_die, is_namespace_die, is_class_die): New
>        functions.
>        (add_pubname): Call is_namespace_die, is_cu_die, and is_class_die in
>        conditional.
>        (add_enumerator_pubname): New function.
>        (add_pubtype): Call is_namespace_die. Rework name calculation.  Call
>        type_tag, lang_hooks.dwarf_name and add_enumerator_pubname.
>        (output_pubnames): Output debug_pubnames_section_label or
>        debug_pubtypes_section_label.
>        (base_type_die): Call add_pubtype.
>        (gen_namespace_die): Call add_pubname_string and lang_hooks.dwarf_name.
>        (dwarf2out_init): Generate debug_pubnames_section_label and
>        debug_pubtypes_section_label.
>        (dwarf2out_finish): Call add_AT_lineptr if pubnames or pubtypes is
>        non-empty.  When dealing with pubnames, change assertion to conditional.
>        Call pubtypes_section_empty.  Likewise when dealing with pubtypes.
>        Move code checking for empty section to...
>        (pubtypes_section_empty): ...here. New function.
>        * gcc/target.def: Switch default generate pubnames and types to true.
>
> cp-family/ChangeLog:
> 2011-12-17   Sterling Augustine  <saugustine@google.com>
>
>        * gcc/c-family/c-pretty-print.c (pp_c_specifier_qualifier_list): Move
>        conditional from beginning to end.
>
> cp/ChangeLog
> 2011-12-17   Sterling Augustine  <saugustine@google.com>
>
>        * gcc/cp/error.c (dump_decl): Reformat return value to
>        "(anonymous namespace)".
>        (lang_decl_name): Return "(anonymous namespace)" when appropriate.
>
> include/ChangeLog
>        * include/dwarf2.h (enum dwarf_form): Add forms DW_FORM_GNU_ref_index,
>        DW_FORM_GNU_addr_index and DW_FORM_GNU_str_index.
>        (enum dwarf_attribute): Add attributes: Add DW_AT_GNU_dwo_name,
>        DW_AT_GNU_dwo_id, DW_AT_GNU_ref_base, DW_AT_GNU_addr_base,
>        DW_AT_GNU_pubnames and DW_AT_GNU_pubtypes.

This is OK for google/main and google/gcc-4_6.

-cary

Patch

diff --git a/gcc/c-family/c-pretty-print.c b/gcc/c-family/c-pretty-print.c
index 621b7f6..55ed41e 100644
--- a/gcc/c-family/c-pretty-print.c
+++ b/gcc/c-family/c-pretty-print.c
@@ -446,8 +446,6 @@  pp_c_specifier_qualifier_list (c_pretty_printer *pp, tree t)
 {
   const enum tree_code code = TREE_CODE (t);
 
-  if (TREE_CODE (t) != POINTER_TYPE)
-    pp_c_type_qualifier_list (pp, t);
   switch (code)
     {
     case REFERENCE_TYPE:
@@ -494,6 +492,8 @@  pp_c_specifier_qualifier_list (c_pretty_printer *pp, tree t)
       pp_simple_type_specifier (pp, t);
       break;
     }
+  if (TREE_CODE (t) != POINTER_TYPE)
+    pp_c_type_qualifier_list (pp, t);
 }
 
 /* parameter-type-list:
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index 52c84cb..194fc76 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -988,7 +988,7 @@  dump_decl (tree t, int flags)
 	    dump_scope (CP_DECL_CONTEXT (t), flags);
 	  flags &= ~TFF_UNQUALIFIED_NAME;
 	  if (DECL_NAME (t) == NULL_TREE)
-	    pp_cxx_ws_string (cxx_pp, M_("{anonymous}"));
+	    pp_cxx_ws_string (cxx_pp, M_("(anonymous namespace)"));
 	  else
 	    pp_cxx_tree_identifier (cxx_pp, DECL_NAME (t));
 	}
@@ -2536,6 +2536,8 @@  lang_decl_name (tree decl, int v, bool translate)
 
   if (TREE_CODE (decl) == FUNCTION_DECL)
     dump_function_name (decl, TFF_PLAIN_IDENTIFIER);
+  else if (DECL_NAME (decl) == NULL && TREE_CODE (decl) == NAMESPACE_DECL)
+    pp_string (cxx_pp, M_("(anonymous namespace)"));
   else
     dump_decl (DECL_NAME (decl), TFF_PLAIN_IDENTIFIER);
 
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 844bba3..6512292 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -3343,6 +3343,7 @@  static void output_comp_unit (dw_die_ref, int);
 static void output_comdat_type_unit (comdat_type_node *);
 static const char *dwarf2_name (tree, int);
 static void add_pubname (tree, dw_die_ref);
+static void add_enumerator_pubname (const char *, const char *, dw_die_ref);
 static void add_pubname_string (const char *, dw_die_ref);
 static void add_pubtype (tree, dw_die_ref);
 static void output_pubnames (VEC (pubname_entry,gc) *);
@@ -3546,6 +3547,12 @@  static void gen_scheduled_generic_parms_dies (void);
 #ifndef COLD_TEXT_SECTION_LABEL
 #define COLD_TEXT_SECTION_LABEL         "Ltext_cold"
 #endif
+#ifndef DEBUG_PUBNAMES_SECTION_LABEL
+#define DEBUG_PUBNAMES_SECTION_LABEL	"Ldebug_pubnames"
+#endif
+#ifndef DEBUG_PUBTYPES_SECTION_LABEL
+#define DEBUG_PUBTYPES_SECTION_LABEL	"Ldebug_pubtypes"
+#endif
 #ifndef DEBUG_LINE_SECTION_LABEL
 #define DEBUG_LINE_SECTION_LABEL	"Ldebug_line"
 #endif
@@ -3582,6 +3589,8 @@  static char cold_end_label[MAX_ARTIFICIAL_LABEL_BYTES];
 static char abbrev_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
 static char debug_info_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
 static char debug_line_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
+static char debug_pubnames_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
+static char debug_pubtypes_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
 static char macinfo_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
 static char loc_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
 static char ranges_section_label[2 * MAX_ARTIFICIAL_LABEL_BYTES];
@@ -6716,6 +6725,22 @@  is_cu_die (dw_die_ref c)
   return c && c->die_tag == DW_TAG_compile_unit;
 }
 
+/* Returns true iff C is a namespace DIE.  */
+
+static inline bool
+is_namespace_die (dw_die_ref c)
+{
+  return c && c->die_tag == DW_TAG_namespace;
+}
+
+/* Returns true iff C is a class DIE.  */
+
+static inline bool
+is_class_die (dw_die_ref c)
+{
+  return c && c->die_tag == DW_TAG_class_type;
+}
+
 static char *
 gen_internal_sym (const char *prefix)
 {
@@ -8638,12 +8663,33 @@  add_pubname (tree decl, dw_die_ref die)
       && targetm.want_debug_pub_sections
       && TREE_PUBLIC (decl))
     {
-      const char *name = dwarf2_name (decl, 1);
-      if (name)
-	add_pubname_string (name, die);
+      if ((TREE_PUBLIC (decl) && !is_class_die (die->die_parent))
+          || is_cu_die (die->die_parent) || is_namespace_die (die->die_parent))
+        {
+          const char *name = dwarf2_name (decl, 1);
+          if (name)
+            add_pubname_string (name, die);
+        }
     }
 }
 
+/* Add an enumerator to the pubnames section.  */
+
+static void
+add_enumerator_pubname (const char *scope_name, const char *sep, dw_die_ref die)
+{
+  const char *name;
+  pubname_entry e;
+
+  if (scope_name)
+    name = concat (scope_name, sep, get_AT_string (die, DW_AT_name), NULL);
+  else
+    name = xstrdup (get_AT_string (die, DW_AT_name));
+  e.name = name;
+  e.die = die;
+  VEC_safe_push (pubname_entry, gc, pubtype_table, &e);
+}
+
 /* Add a new entry to .debug_pubtypes if appropriate.  */
 
 static void
@@ -8656,34 +8702,47 @@  add_pubtype (tree decl, dw_die_ref die)
 
   e.name = NULL;
   if ((TREE_PUBLIC (decl)
-       || is_cu_die (die->die_parent))
+       || is_cu_die (die->die_parent) || is_namespace_die (die->die_parent))
       && (die->die_tag == DW_TAG_typedef || COMPLETE_TYPE_P (decl)))
     {
-      e.die = die;
+      tree scope = NULL;
+      const char *scope_name = NULL;
+      const char *sep = is_cxx () ? "::" : ".";
+      const char *name = NULL;
+
       if (TYPE_P (decl))
-	{
-	  if (TYPE_NAME (decl))
-	    {
-	      if (TREE_CODE (TYPE_NAME (decl)) == IDENTIFIER_NODE)
-		e.name = IDENTIFIER_POINTER (TYPE_NAME (decl));
-	      else if (TREE_CODE (TYPE_NAME (decl)) == TYPE_DECL
-		       && DECL_NAME (TYPE_NAME (decl)))
-		e.name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (decl)));
-	      else
-	       e.name = xstrdup ((const char *) get_AT_string (die, DW_AT_name));
-	    }
-	}
+        name = type_tag (decl);
       else
-	{
-	  e.name = dwarf2_name (decl, 1);
-	  if (e.name)
-	    e.name = xstrdup (e.name);
-	}
+        name = lang_hooks.dwarf_name (decl, 1);
 
       /* If we don't have a name for the type, there's no point in adding
 	 it to the table.  */
-      if (e.name && e.name[0] != '\0')
-	VEC_safe_push (pubname_entry, gc, pubtype_table, &e);
+      if (name == NULL || name[0] == '\0')
+        return;
+
+      e.die = die;
+      e.name = xstrdup (name);
+
+      scope = TYPE_P (decl) ? TYPE_CONTEXT (decl) : NULL;
+      if (scope && TREE_CODE (scope) == NAMESPACE_DECL)
+        {
+          scope_name = lang_hooks.dwarf_name (scope, 1);
+          if (scope_name != NULL)
+            e.name = concat (scope_name, sep, e.name, NULL);
+        }
+      VEC_safe_push (pubname_entry, gc, pubtype_table, &e);
+
+      /* Although it might be more consistent to add the pubinfo for the
+         enumerators as their dies are created, they should only be added if the
+         enum type meets the criteria above.  So rather than re-check the parent
+         enum type whenever an enumerator die is created, just output them all
+         here.  */
+      if (die->die_tag == DW_TAG_enumeration_type)
+        {
+          dw_die_ref c;
+
+          FOR_EACH_CHILD (die, c, add_enumerator_pubname (scope_name, sep, c));
+        }
     }
 }
 
@@ -8697,6 +8756,10 @@  output_pubnames (VEC (pubname_entry, gc) * names)
   unsigned long pubnames_length = size_of_pubnames (names);
   pubname_ref pub;
 
+  if (names == pubname_table)
+    ASM_OUTPUT_LABEL (asm_out_file, debug_pubnames_section_label);
+  else
+    ASM_OUTPUT_LABEL (asm_out_file, debug_pubtypes_section_label);
   if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4)
     dw2_asm_output_data (4, 0xffffffff,
       "Initial length escape value indicating 64-bit DWARF extension");
@@ -9608,6 +9671,7 @@  base_type_die (tree type)
   add_AT_unsigned (base_type_result, DW_AT_byte_size,
 		   int_size_in_bytes (type));
   add_AT_unsigned (base_type_result, DW_AT_encoding, encoding);
+  add_pubtype (type, base_type_result);
 
   return base_type_result;
 }
@@ -19382,6 +19446,8 @@  gen_namespace_die (tree decl, dw_die_ref context_die)
       add_AT_die_ref (namespace_die, DW_AT_import, origin_die);
       equate_decl_number_to_die (decl, namespace_die);
     }
+  /* Bypass dwarf2_name's check for DECL_NAMELESS.  */
+  add_pubname_string (lang_hooks.dwarf_name (decl, 1), namespace_die);
 }
 
 /* Generate Dwarf debug information for a decl described by DECL.
@@ -21049,6 +21115,10 @@  dwarf2out_init (const char *filename ATTRIBUTE_UNUSED)
 
   ASM_GENERATE_INTERNAL_LABEL (debug_info_section_label,
 			       DEBUG_INFO_SECTION_LABEL, 0);
+  ASM_GENERATE_INTERNAL_LABEL (debug_pubnames_section_label,
+			       DEBUG_PUBNAMES_SECTION_LABEL, 0);
+  ASM_GENERATE_INTERNAL_LABEL (debug_pubtypes_section_label,
+			       DEBUG_PUBTYPES_SECTION_LABEL, 0);
   ASM_GENERATE_INTERNAL_LABEL (debug_line_section_label,
 			       DEBUG_LINE_SECTION_LABEL, 0);
   ASM_GENERATE_INTERNAL_LABEL (ranges_section_label,
@@ -22391,6 +22461,30 @@  optimize_location_lists (dw_die_ref die)
   htab_delete (htab);
 }
 
+
+/* Report if the pubtypes_section is either empty or will be pruned to
+   empty.  */
+
+static bool
+pubtypes_section_empty (void)
+{
+  if (!VEC_empty (pubname_entry, pubtype_table))
+    {
+      if (flag_eliminate_unused_debug_types)
+	{
+	  /* The pubtypes table might be emptied by pruning unused items.  */
+	  unsigned i;
+	  pubname_ref p;
+	  FOR_EACH_VEC_ELT (pubname_entry, pubtype_table, i, p)
+	    if (p->die->die_offset != 0)
+              return false;
+	}
+      return true;
+    }
+  return false;
+}
+
+
 /* Output stuff that dwarf requires at the end of every file,
    and generate the DWARF-2 debugging info.  */
 
@@ -22654,6 +22748,22 @@  dwarf2out_finish (const char *filename)
     }
   htab_delete (comdat_type_table);
 
+  /* Add the DW_AT_GNU_pubnames and DW_AT_GNU_pubtypes attributes.  */
+  if (!VEC_empty (pubname_entry, pubname_table))
+    {
+      /* FIXME: Should use add_AT_pubnamesptr.  This works because
+         most targets don't care what the base section is.  */
+      add_AT_lineptr (comp_unit_die (), DW_AT_GNU_pubnames,
+		      debug_pubnames_section_label);
+    }
+  if (!pubtypes_section_empty ())
+    {
+      /* FIXME: Should use add_AT_pubtypesptr.  This works because
+         most targets don't care what the base section is.  */
+      add_AT_lineptr (comp_unit_die (), DW_AT_GNU_pubtypes,
+                      debug_pubtypes_section_label);
+    }
+
   /* Output the main compilation unit if non-empty or if .debug_macinfo
      will be emitted.  */
   output_comp_unit (comp_unit_die (), debug_info_level >= DINFO_LEVEL_VERBOSE);
@@ -22678,9 +22788,8 @@  dwarf2out_finish (const char *filename)
     }
 
   /* Output public names table if necessary.  */
-  if (!VEC_empty (pubname_entry, pubname_table))
+  if (!VEC_empty (pubname_entry, pubname_table) && info_section_emitted)
     {
-      gcc_assert (info_section_emitted);
       switch_to_section (debug_pubnames_section);
       output_pubnames (pubname_table);
     }
@@ -22689,29 +22798,10 @@  dwarf2out_finish (const char *filename)
   /* ??? Only defined by DWARF3, but emitted by Darwin for DWARF2.
      It shouldn't hurt to emit it always, since pure DWARF2 consumers
      simply won't look for the section.  */
-  if (!VEC_empty (pubname_entry, pubtype_table))
+  if (!pubtypes_section_empty () && info_section_emitted)
     {
-      bool empty = false;
-      
-      if (flag_eliminate_unused_debug_types)
-	{
-	  /* The pubtypes table might be emptied by pruning unused items.  */
-	  unsigned i;
-	  pubname_ref p;
-	  empty = true;
-	  FOR_EACH_VEC_ELT (pubname_entry, pubtype_table, i, p)
-	    if (p->die->die_offset != 0)
-	      {
-		empty = false;
-		break;
-	      }
-	}
-      if (!empty)
-	{
-	  gcc_assert (info_section_emitted);
-	  switch_to_section (debug_pubtypes_section);
-	  output_pubnames (pubtype_table);
-	}
+      switch_to_section (debug_pubtypes_section);
+      output_pubnames (pubtype_table);
     }
 
   /* Output the address range information if a CU (.debug_info section)
diff --git a/gcc/target.def b/gcc/target.def
index b72b265..7ce8555 100644
--- a/gcc/target.def
+++ b/gcc/target.def
@@ -2753,7 +2753,7 @@  DEFHOOKPOD
  "True if the @code{.debug_pubtypes} and @code{.debug_pubnames} sections\
  should be emitted.  These sections are not used on most platforms, and\
  in particular GDB does not use them.",
- bool, false)
+ bool, true)
 
 DEFHOOKPOD
 (delay_sched2, "True if sched2 is not to be run at its normal place.  \
diff --git a/include/dwarf2.h b/include/dwarf2.h
index 37cb83f..b93aebf 100644
--- a/include/dwarf2.h
+++ b/include/dwarf2.h
@@ -188,7 +188,11 @@  enum dwarf_form
     DW_FORM_sec_offset = 0x17,
     DW_FORM_exprloc = 0x18,
     DW_FORM_flag_present = 0x19,
-    DW_FORM_ref_sig8 = 0x20
+    DW_FORM_ref_sig8 = 0x20,
+    /* Extensions for Fission.  */
+    DW_FORM_GNU_ref_index = 0x70,
+    DW_FORM_GNU_addr_index = 0x71,
+    DW_FORM_GNU_str_index = 0x72
   };
 
 /* Attribute names and codes.  */
@@ -368,6 +372,13 @@  enum dwarf_attribute
     DW_AT_GNU_all_source_call_sites = 0x2118,
     /* Section offset into .debug_macro section.  */
     DW_AT_GNU_macros = 0x2119,
+    /* Extensions for Fission.  */
+    DW_AT_GNU_dwo_name = 0x2130,
+    DW_AT_GNU_dwo_id = 0x2131,
+    DW_AT_GNU_ref_base = 0x2132,
+    DW_AT_GNU_addr_base = 0x2133,
+    DW_AT_GNU_pubnames = 0x2134,
+    DW_AT_GNU_pubtypes = 0x2135,
     /* VMS extensions.  */
     DW_AT_VMS_rtnbeg_pd_address = 0x2201,
     /* GNAT extensions.  */