This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[patch] Work around gcc bug 45682


Hi.

This patch works around a bug in gcc's dwarf generation when using -gdwarf-4.

ref: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45682

The error can be seen with, e.g.,

bash$ runtest namespace.exp CXX_FOR_TARGET='g++-4.5.0 -gdwarf-4'
[...]
FAIL: gdb.cp/namespace.exp: info func xyzq
FAIL: gdb.cp/namespace.exp: print 'BBB::Class::xyzq'
FAIL: gdb.cp/namespace.exp: print BBB::Class::xyzq
FAIL: gdb.cp/namespace.exp: break BBB::Class::xyzq (got interactive prompt)

I plan to check this in, but I'm going to give it a fair while for review,
at least a week.  [And if anyone has a better solution, by all means ...]

Function guess_structure_name is currently a nop, and could be deleted.
This patch resurrects its original purpose, but predicates
the effects on the presence of the .debug_types section.
I had to apply the workaround twice, once for partial dies
and once for full dies (to make sure symbols in psymtabs match their
corresponding symbols in symtabs).
Maybe there's a better way.

Regression tested on amd64-linux with/without -gdwarf-4.
[There's still some -gdwarf-4 failures, but they aren't regressions.]

2010-09-15  Doug Evans  <dje@google.com>

	* dwarf2read.c (partial_die_info): New fields fixup_called,
	linkage_name.
	(guess_partial_die_structure_name): Renamed from guess_structure_name.
	Move definition next to use.  Use linkage_name to determine if class
	is in a namespace.  All callers updated.
	(fixup_partial_die): Return early if already called.
	Set fixup_called when done.
	(guess_full_die_structure_name): New function.
	(determine_prefix): Call it for class/struct/union dies if c++ and
	.debug_types section is present and parent is DW_TAG_compile_unit.

Index: dwarf2read.c
===================================================================
RCS file: /cvs/src/src/gdb/dwarf2read.c,v
retrieving revision 1.458
diff -u -p -r1.458 dwarf2read.c
--- dwarf2read.c	15 Sep 2010 18:14:47 -0000	1.458
+++ dwarf2read.c	15 Sep 2010 18:40:45 -0000
@@ -577,10 +577,16 @@ struct partial_die_info
     /* Flag set if any of the DIE's children are template arguments.  */
     unsigned int has_template_arguments : 1;
 
+    /* Flag set if fixup_partial_die has been called on this die.  */
+    unsigned int fixup_called : 1;
+
     /* The name of this DIE.  Normally the value of DW_AT_name, but
        sometimes a default name for unnamed DIEs.  */
     char *name;
 
+    /* The linkage name, if present.  */
+    const char *linkage_name;
+
     /* The scope to prepend to our children.  This is generally
        allocated on the comp_unit_obstack, so will disappear
        when this compilation unit leaves the cache.  */
@@ -595,6 +601,8 @@ struct partial_die_info
 
     /* Pointer into the info_buffer (or types_buffer) pointing at the target of
        DW_AT_sibling, if any.  */
+    /* NOTE: This member isn't strictly necessary, read_partial_die could
+       return DW_AT_sibling values to its caller load_partial_dies.  */
     gdb_byte *sibling;
 
     /* If HAS_SPECIFICATION, the offset of the DIE referred to by
@@ -3900,40 +3908,6 @@ add_partial_subprogram (struct partial_d
     }
 }
 
-/* See if we can figure out if the class lives in a namespace.  We do
-   this by looking for a member function; its demangled name will
-   contain namespace info, if there is any.  */
-
-static void
-guess_structure_name (struct partial_die_info *struct_pdi,
-		      struct dwarf2_cu *cu)
-{
-  if ((cu->language == language_cplus
-       || cu->language == language_java)
-      && cu->has_namespace_info == 0
-      && struct_pdi->has_children)
-    {
-      /* NOTE: carlton/2003-10-07: Getting the info this way changes
-	 what template types look like, because the demangler
-	 frequently doesn't give the same name as the debug info.  We
-	 could fix this by only using the demangled name to get the
-	 prefix (but see comment in read_structure_type).  */
-
-      struct partial_die_info *real_pdi;
-
-      /* If this DIE (this DIE's specification, if any) has a parent, then
-	 we should not do this.  We'll prepend the parent's fully qualified
-         name when we create the partial symbol.  */
-
-      real_pdi = struct_pdi;
-      while (real_pdi->has_specification)
-	real_pdi = find_partial_die (real_pdi->spec_offset, cu);
-
-      if (real_pdi->die_parent != NULL)
-	return;
-    }
-}
-
 /* Read a partial die corresponding to an enumeration type.  */
 
 static void
@@ -8795,6 +8769,7 @@ read_partial_die (struct partial_die_inf
 	     one we see.  */
 	  if (cu->language == language_ada)
 	    part_die->name = DW_STRING (&attr);
+	  part_die->linkage_name = DW_STRING (&attr);
 	  break;
 	case DW_AT_low_pc:
 	  has_low_pc_attr = 1;
@@ -8978,6 +8953,57 @@ find_partial_die (unsigned int offset, s
   return pd;
 }
 
+/* See if we can figure out if the class lives in a namespace.  We do
+   this by looking for a member function; its demangled name will
+   contain namespace info, if there is any.  */
+
+static void
+guess_partial_die_structure_name (struct partial_die_info *struct_pdi,
+				  struct dwarf2_cu *cu)
+{
+  /* NOTE: carlton/2003-10-07: Getting the info this way changes
+     what template types look like, because the demangler
+     frequently doesn't give the same name as the debug info.  We
+     could fix this by only using the demangled name to get the
+     prefix (but see comment in read_structure_type).  */
+
+  struct partial_die_info *real_pdi;
+  struct partial_die_info *child_pdi;
+
+  /* If this DIE (this DIE's specification, if any) has a parent, then
+     we should not do this.  We'll prepend the parent's fully qualified
+     name when we create the partial symbol.  */
+
+  real_pdi = struct_pdi;
+  while (real_pdi->has_specification)
+    real_pdi = find_partial_die (real_pdi->spec_offset, cu);
+
+  if (real_pdi->die_parent != NULL)
+    return;
+
+  for (child_pdi = struct_pdi->die_child;
+       child_pdi != NULL;
+       child_pdi = child_pdi->die_sibling)
+    {
+      if (child_pdi->tag == DW_TAG_subprogram
+	  && child_pdi->linkage_name != NULL)
+	{
+	  char *actual_class_name
+	    = language_class_name_from_physname (cu->language_defn,
+						 child_pdi->linkage_name);
+	  if (actual_class_name != NULL)
+	    {
+	      struct_pdi->name
+		= obsavestring (actual_class_name,
+				strlen (actual_class_name),
+				&cu->objfile->objfile_obstack);
+	      xfree (actual_class_name);
+	    }
+	  break;
+	}
+    }
+}
+
 /* Adjust PART_DIE before generating a symbol for it.  This function
    may set the is_external flag or change the DIE's name.  */
 
@@ -8985,6 +9011,12 @@ static void
 fixup_partial_die (struct partial_die_info *part_die,
 		   struct dwarf2_cu *cu)
 {
+  /* Once we've fixed up a die, there's no point in doing so again.
+     This also avoids a memory leak if we were to call
+     guess_partial_die_structure_name multiple times.  */
+  if (part_die->fixup_called)
+    return;
+
   /* If we found a reference attribute and the DIE has no name, try
      to find a name in the referred to DIE.  */
 
@@ -9011,10 +9043,21 @@ fixup_partial_die (struct partial_die_in
   if (part_die->name == NULL && part_die->tag == DW_TAG_namespace)
     part_die->name = "(anonymous namespace)";
 
-  if (part_die->tag == DW_TAG_structure_type
-      || part_die->tag == DW_TAG_class_type
-      || part_die->tag == DW_TAG_union_type)
-    guess_structure_name (part_die, cu);
+  /* If there is no parent die to provide a namespace, and there are
+     children, see if we can determine the namespace from their linkage
+     name.
+     NOTE: We need to do this even if cu->has_namespace_info != 0.
+     gcc-4.5 -gdwarf-4 can drop the enclosing namespace.  */
+  if (cu->language == language_cplus
+      && dwarf2_per_objfile->types.asection != NULL
+      && part_die->die_parent == NULL
+      && part_die->has_children
+      && (part_die->tag == DW_TAG_class_type
+	  || part_die->tag == DW_TAG_structure_type
+	  || part_die->tag == DW_TAG_union_type))
+    guess_partial_die_structure_name (part_die, cu);
+
+  part_die->fixup_called = 1;
 }
 
 /* Read an attribute value described by an attribute form.  */
@@ -11257,6 +11300,77 @@ read_type_die_1 (struct die_info *die, s
   return this_type;
 }
 
+/* See if we can figure out if the class lives in a namespace.  We do
+   this by looking for a member function; its demangled name will
+   contain namespace info, if there is any.
+   Return the computed name or NULL.
+   Space for the result is allocated on the objfile's obstack.
+   This is the full-die version of guess_partial_die_structure_name.
+   In this case we know DIE has no useful parent.  */
+
+static char *
+guess_full_die_structure_name (struct die_info *die, struct dwarf2_cu *cu)
+{
+  struct die_info *spec_die;
+  struct dwarf2_cu *spec_cu;
+  struct die_info *child;
+
+  spec_cu = cu;
+  spec_die = die_specification (die, &spec_cu);
+  if (spec_die != NULL)
+    {
+      die = spec_die;
+      cu = spec_cu;
+    }
+
+  for (child = die->child;
+       child != NULL;
+       child = child->sibling)
+    {
+      if (child->tag == DW_TAG_subprogram)
+	{
+	  struct attribute *attr;
+
+	  attr = dwarf2_attr (child, DW_AT_linkage_name, cu);
+	  if (attr == NULL)
+	    attr = dwarf2_attr (child, DW_AT_MIPS_linkage_name, cu);
+	  if (attr != NULL)
+	    {
+	      char *actual_name
+		= language_class_name_from_physname (cu->language_defn,
+						     DW_STRING (attr));
+	      char *name = NULL;
+
+	      if (actual_name != NULL)
+		{
+		  char *die_name = dwarf2_name (die, cu);
+
+		  if (die_name != NULL
+		      && strcmp (die_name, actual_name) != 0)
+		    {
+		      /* Strip off the class name from the full name.
+			 We want the prefix.  */
+		      int die_name_len = strlen (die_name);
+		      int actual_name_len = strlen (actual_name);
+
+		      /* Test for '::' as a sanity check.  */
+		      if (actual_name_len > die_name_len + 2
+			  && actual_name[actual_name_len - die_name_len - 1] == ':')
+			name =
+			  obsavestring (actual_name,
+					actual_name_len - die_name_len - 2,
+					&cu->objfile->objfile_obstack);
+		    }
+		}
+	      xfree (actual_name);
+	      return name;
+	    }
+	}
+    }
+
+  return NULL;
+}
+
 /* Return the name of the namespace/class that DIE is defined within,
    or "" if we can't tell.  The caller should not xfree the result.
 
@@ -11383,6 +11497,20 @@ determine_prefix (struct die_info *die, 
 	     members; no typedefs, no member functions, et cetera.
 	     So it does not need a prefix.  */
 	  return "";
+      case DW_TAG_compile_unit:
+	/* gcc-4.5 -gdwarf-4 can drop the enclosing namespace.  Cope.  */
+	if (cu->language == language_cplus
+	    && dwarf2_per_objfile->types.asection != NULL
+	    && die->child != NULL
+	    && (die->tag == DW_TAG_class_type
+		|| die->tag == DW_TAG_structure_type
+		|| die->tag == DW_TAG_union_type))
+	  {
+	    char *name = guess_full_die_structure_name (die, cu);
+	    if (name != NULL)
+	      return name;
+	  }
+	return "";
       default:
 	return determine_prefix (parent, cu);
       }


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]