This is the mail archive of the gdb-patches@sources.redhat.com 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]

[intercu] Handle references in full DIEs


A necessary piece of setup work.  DIE references, in particular DW_FORM_ref*
excluding DW_FORM_ref_addr, are relative to the base of the compilation unit
in which they occur.  Therefore, it is vital to keep track of which
compilation unit they occur in.  This adds a function, dwarf2_attr_with_cu,
which returns the compilation unit in which the attribute was found.  For
now, of course, it's always the current compilation unit...

All affected callers are updated to use the new function, and to use the
returned compilation unit as appropriate.

Committed to the intercu branch.

-- 
Daniel Jacobowitz
MontaVista Software                         Debian GNU/Linux Developer

2004-02-22  Daniel Jacobowitz  <drow@mvista.com>

	* dwarf2read.c (dwarf2_attr_with_cu): New function, renamed
	from dwarf2_attr.  Also return the compilation unit associated
	with the attribute if we have followed a reference.  Complain
	if we return a reference attribute and the caller does not want
	the target compilation unit.
	(dwarf2_attr): Call dwarf2_attr_with_cu.
	(die_specification, dwarf2_extension): Also return a compilation
	unit.
	(follow_die_ref): Take attribute and compilation unit arguments.
	Call dwarf2_get_ref_die_offset.  Also return the target
	compilation unit.
	(read_func_scope, read_structure_scope): Update calls to
	die_specification.  Use the result.
	(read_namespace): Update call to dwarf2_extension.
	(namespace_name): Likewise.  Use the result.
	(new_symbol): Call dwarf2_attr_with_cu to check for DIE type.
	(die_type): Likewise.  Update call to follow_die_ref.  Use the
	results.
	(dwarf2_add_member_fn, read_structure_scope): Likewise for
	DW_AT_containing_type.
	(die_containing_type): Likewise.
	(die_is_declaration): Likewise for DW_AT_specification.

Index: dwarf2read.c
===================================================================
RCS file: /cvs/src/src/gdb/dwarf2read.c,v
retrieving revision 1.135.2.21
diff -u -p -r1.135.2.21 dwarf2read.c
--- dwarf2read.c	22 Feb 2004 21:00:47 -0000	1.135.2.21
+++ dwarf2read.c	22 Feb 2004 23:01:39 -0000
@@ -776,10 +776,16 @@ static void set_cu_language (unsigned in
 static struct attribute *dwarf2_attr (struct die_info *, unsigned int,
 				      struct dwarf2_cu *);
 
+static struct attribute *dwarf2_attr_with_cu (struct die_info *,
+					      unsigned int,
+					      struct dwarf2_cu *,
+					      struct dwarf2_cu **);
+
 static int die_is_declaration (struct die_info *, struct dwarf2_cu *cu);
 
 static struct die_info *die_specification (struct die_info *die,
-					   struct dwarf2_cu *);
+					   struct dwarf2_cu *,
+					   struct dwarf2_cu **);
 
 static void free_line_header (struct line_header *lh);
 
@@ -910,7 +916,8 @@ static char *dwarf2_linkage_name (struct
 static char *dwarf2_name (struct die_info *die, struct dwarf2_cu *);
 
 static struct die_info *dwarf2_extension (struct die_info *die,
-					  struct dwarf2_cu *);
+					  struct dwarf2_cu *,
+					  struct dwarf2_cu **);
 
 static char *dwarf_tag_name (unsigned int);
 
@@ -945,7 +952,9 @@ static unsigned int dwarf2_get_ref_die_o
 
 static int dwarf2_get_attr_constant_value (struct attribute *, int);
 
-static struct die_info *follow_die_ref (unsigned int);
+static struct die_info *follow_die_ref (struct attribute *,
+					struct dwarf2_cu *,
+					struct dwarf2_cu **);
 
 static struct type *dwarf2_fundamental_type (struct objfile *, int,
 					     struct dwarf2_cu *);
@@ -2625,7 +2634,8 @@ read_func_scope (struct die_info *die, s
 
   if (cu->language == language_cplus)
     {
-      struct die_info *spec_die = die_specification (die, cu);
+      struct dwarf2_cu *spec_cu;
+      struct die_info *spec_die = die_specification (die, cu, &spec_cu);
 
       /* NOTE: carlton/2004-01-23: We have to be careful in the
          presence of DW_AT_specification.  For example, with GCC 3.4,
@@ -2651,7 +2661,7 @@ read_func_scope (struct die_info *die, s
 	
       if (spec_die != NULL)
 	{
-	  char *specification_prefix = determine_prefix (spec_die, cu);
+	  char *specification_prefix = determine_prefix (spec_die, spec_cu);
 	  processing_current_prefix = specification_prefix;
 	  back_to = make_cleanup (xfree, specification_prefix);
 	}
@@ -3258,6 +3268,7 @@ dwarf2_add_member_fn (struct field_info 
   char *fieldname;
   char *physname;
   struct nextfnfield *new_fnfield;
+  struct dwarf2_cu *spec_cu;
 
   /* Get name of member function.  */
   attr = dwarf2_attr (die, DW_AT_name, cu);
@@ -3337,7 +3348,7 @@ dwarf2_add_member_fn (struct field_info 
 	       physname);
 
   /* Get fcontext from DW_AT_containing_type if present.  */
-  if (dwarf2_attr (die, DW_AT_containing_type, cu) != NULL)
+  if (dwarf2_attr_with_cu (die, DW_AT_containing_type, cu, &spec_cu) != NULL)
     fnp->fcontext = die_containing_type (die, cu);
 
   /* dwarf2 doesn't have stubbed physical names, so the setting of is_const
@@ -3458,11 +3469,13 @@ read_structure_scope (struct die_info *d
 
       if (cu->language == language_cplus)
 	{
-	  struct die_info *spec_die = die_specification (die, cu);
+	  struct dwarf2_cu *spec_cu;
+	  struct die_info *spec_die = die_specification (die, cu, &spec_cu);
 
 	  if (spec_die != NULL)
 	    {
-	      char *specification_prefix = determine_prefix (spec_die, cu);
+	      char *specification_prefix = determine_prefix (spec_die,
+							     spec_cu);
 	      processing_current_prefix = specification_prefix;
 	      back_to = make_cleanup (xfree, specification_prefix);
 	    }
@@ -3601,13 +3614,16 @@ read_structure_scope (struct die_info *d
 	dwarf2_attach_fields_to_type (&fi, type, cu);
       if (fi.nfnfields)
 	{
+	  struct dwarf2_cu *spec_cu;
+
 	  dwarf2_attach_fn_fields_to_type (&fi, type, cu);
 
 	  /* Get the type which refers to the base class (possibly this
 	     class itself) which contains the vtable pointer for the current
 	     class from the DW_AT_containing_type attribute.  */
 
-	  if (dwarf2_attr (die, DW_AT_containing_type, cu) != NULL)
+	  if (dwarf2_attr_with_cu (die, DW_AT_containing_type,
+				   cu, &spec_cu) != NULL)
 	    {
 	      struct type *t = die_containing_type (die, cu);
 
@@ -3913,6 +3929,7 @@ read_namespace (struct die_info *die, st
   const char *name;
   int is_anonymous;
   struct die_info *current_die;
+  struct dwarf2_cu *spec_cu;
 
   name = namespace_name (die, &is_anonymous, cu);
 
@@ -3939,7 +3956,7 @@ read_namespace (struct die_info *die, st
      before.  Also, add a using directive if it's an anonymous
      namespace.  */
 
-  if (dwarf2_extension (die, cu) == NULL)
+  if (dwarf2_extension (die, cu, &spec_cu) == NULL)
     {
       struct type *type;
 
@@ -3981,14 +3998,15 @@ namespace_name (struct die_info *die, in
 {
   struct die_info *current_die;
   const char *name = NULL;
+  struct dwarf2_cu *spec_cu;
 
   /* Loop through the extensions until we find a name.  */
 
-  for (current_die = die;
+  for (current_die = die, spec_cu = cu;
        current_die != NULL;
-       current_die = dwarf2_extension (die, cu))
+       current_die = dwarf2_extension (die, spec_cu, &spec_cu))
     {
-      name = dwarf2_name (current_die, cu);
+      name = dwarf2_name (current_die, spec_cu);
       if (name != NULL)
 	break;
     }
@@ -5679,7 +5697,8 @@ set_cu_language (unsigned int lang, stru
 /* Return the named attribute or NULL if not there.  */
 
 static struct attribute *
-dwarf2_attr (struct die_info *die, unsigned int name, struct dwarf2_cu *cu)
+dwarf2_attr_with_cu (struct die_info *die, unsigned int name,
+		     struct dwarf2_cu *cu, struct dwarf2_cu **spec_cu)
 {
   unsigned int i;
   struct attribute *spec = NULL;
@@ -5688,6 +5707,20 @@ dwarf2_attr (struct die_info *die, unsig
     {
       if (die->attrs[i].name == name)
 	{
+	  if (spec_cu == NULL
+	      && (die->attrs[i].form == DW_FORM_ref_addr
+		  || die->attrs[i].form == DW_FORM_ref1
+		  || die->attrs[i].form == DW_FORM_ref2
+		  || die->attrs[i].form == DW_FORM_ref4
+		  || die->attrs[i].form == DW_FORM_ref8
+		  || die->attrs[i].form == DW_FORM_ref_udata))
+	    internal_error (__FILE__, __LINE__,
+			    "attempt to follow a dwarf2 DIE reference "
+			    "discards compilation unit");
+
+	  if (spec_cu != NULL)
+	    *spec_cu = cu;
+
 	  return &die->attrs[i];
 	}
       if (die->attrs[i].name == DW_AT_specification
@@ -5696,35 +5729,45 @@ dwarf2_attr (struct die_info *die, unsig
     }
   if (spec)
     {
-      struct die_info *ref_die =
-      follow_die_ref (dwarf2_get_ref_die_offset (spec, cu));
+      struct dwarf2_cu *ref_cu;
+      struct die_info *ref_die = follow_die_ref (spec, cu, &ref_cu);
 
-      if (ref_die)
-	return dwarf2_attr (ref_die, name, cu);
+      return dwarf2_attr_with_cu (ref_die, name, ref_cu, spec_cu);
     }
 
   return NULL;
 }
 
+/* Return the named attribute or NULL if not there.  */
+
+static struct attribute *
+dwarf2_attr (struct die_info *die, unsigned int name, struct dwarf2_cu *cu)
+{
+  return dwarf2_attr_with_cu (die, name, cu, NULL);
+}
+
 static int
 die_is_declaration (struct die_info *die, struct dwarf2_cu *cu)
 {
+  struct dwarf2_cu *spec_cu;
   return (dwarf2_attr (die, DW_AT_declaration, cu)
-	  && ! dwarf2_attr (die, DW_AT_specification, cu));
+	  && ! dwarf2_attr_with_cu (die, DW_AT_specification, cu, &spec_cu));
 }
 
 /* Return the die giving the specification for DIE, if there is
    one.  */
 
 static struct die_info *
-die_specification (struct die_info *die, struct dwarf2_cu *cu)
+die_specification (struct die_info *die, struct dwarf2_cu *cu,
+		   struct dwarf2_cu **spec_cu)
 {
-  struct attribute *spec_attr = dwarf2_attr (die, DW_AT_specification, cu);
+  struct attribute *spec_attr
+    = dwarf2_attr_with_cu (die, DW_AT_specification, cu, spec_cu);
 
   if (spec_attr == NULL)
     return NULL;
   else
-    return follow_die_ref (dwarf2_get_ref_die_offset (spec_attr, cu));
+    return follow_die_ref (spec_attr, *spec_cu, spec_cu);
 }
 
 /* Free the line_header structure *LH, and any arrays and strings it
@@ -6334,6 +6377,8 @@ new_symbol (struct die_info *die, struct
 	    }
 	  else
 	    {
+	      struct dwarf2_cu *spec_cu;
+
 	      /* We do not know the address of this symbol.
 	         If it is an external symbol and we have type information
 	         for it, enter the symbol as a LOC_UNRESOLVED symbol.
@@ -6342,7 +6387,8 @@ new_symbol (struct die_info *die, struct
 	         referenced.  */
 	      attr2 = dwarf2_attr (die, DW_AT_external, cu);
 	      if (attr2 && (DW_UNSND (attr2) != 0)
-		  && dwarf2_attr (die, DW_AT_type, cu) != NULL)
+		  && dwarf2_attr_with_cu (die, DW_AT_type,
+					  cu, &spec_cu) != NULL)
 		{
 		  SYMBOL_CLASS (sym) = LOC_UNRESOLVED;
 		  add_symbol_to_list (sym, &global_symbols);
@@ -6608,9 +6654,9 @@ die_type (struct die_info *die, struct d
   struct type *type;
   struct attribute *type_attr;
   struct die_info *type_die;
-  unsigned int ref;
+  struct dwarf2_cu *spec_cu;
 
-  type_attr = dwarf2_attr (die, DW_AT_type, cu);
+  type_attr = dwarf2_attr_with_cu (die, DW_AT_type, cu, &spec_cu);
   if (!type_attr)
     {
       /* A missing DW_AT_type represents a void type.  */
@@ -6618,16 +6664,16 @@ die_type (struct die_info *die, struct d
     }
   else
     {
-      ref = dwarf2_get_ref_die_offset (type_attr, cu);
-      type_die = follow_die_ref (ref);
+      type_die = follow_die_ref (type_attr, spec_cu, &spec_cu);
       if (!type_die)
 	{
-	  error ("Dwarf Error: Cannot find referent at offset %d [in module %s]", 
-			  ref, cu->objfile->name);
+	  error ("Dwarf Error: Cannot find referent from DIE "
+		 "at offset %d [in module %s]",
+		 die->offset, cu->objfile->name);
 	  return NULL;
 	}
     }
-  type = tag_type_to_type (type_die, cu);
+  type = tag_type_to_type (type_die, spec_cu);
   if (!type)
     {
       dump_die (type_die);
@@ -6646,20 +6692,19 @@ die_containing_type (struct die_info *di
   struct type *type = NULL;
   struct attribute *type_attr;
   struct die_info *type_die = NULL;
-  unsigned int ref;
+  struct dwarf2_cu *spec_cu;
 
-  type_attr = dwarf2_attr (die, DW_AT_containing_type, cu);
+  type_attr = dwarf2_attr_with_cu (die, DW_AT_containing_type, cu, &spec_cu);
   if (type_attr)
     {
-      ref = dwarf2_get_ref_die_offset (type_attr, cu);
-      type_die = follow_die_ref (ref);
+      type_die = follow_die_ref (type_attr, spec_cu, &spec_cu);
       if (!type_die)
 	{
-	  error ("Dwarf Error: Cannot find referent at offset %d [in module %s]", ref, 
-			  cu->objfile->name);
+	  error ("Dwarf Error: Cannot find referent from DIE at offset %d "
+		 "[in module %s]", die->offset, cu->objfile->name);
 	  return NULL;
 	}
-      type = tag_type_to_type (type_die, cu);
+      type = tag_type_to_type (type_die, spec_cu);
     }
   if (!type)
     {
@@ -7043,21 +7088,21 @@ dwarf2_name (struct die_info *die, struc
    is none.  */
 
 static struct die_info *
-dwarf2_extension (struct die_info *die, struct dwarf2_cu *cu)
+dwarf2_extension (struct die_info *die, struct dwarf2_cu *cu,
+		  struct dwarf2_cu **spec_cu)
 {
   struct attribute *attr;
   struct die_info *extension_die;
-  unsigned int ref;
 
-  attr = dwarf2_attr (die, DW_AT_extension, cu);
+  attr = dwarf2_attr_with_cu (die, DW_AT_extension, cu, spec_cu);
   if (attr == NULL)
     return NULL;
 
-  ref = dwarf2_get_ref_die_offset (attr, cu);
-  extension_die = follow_die_ref (ref);
+  extension_die = follow_die_ref (attr, *spec_cu, spec_cu);
   if (!extension_die)
     {
-      error ("Dwarf Error: Cannot find referent at offset %d.", ref);
+      error ("Dwarf Error: Cannot find referent from DIE at offset %d.",
+	     die->offset);
     }
 
   return extension_die;
@@ -8013,17 +8058,22 @@ dwarf2_get_attr_constant_value (struct a
 }
 
 static struct die_info *
-follow_die_ref (unsigned int offset)
+follow_die_ref (struct attribute *attr, struct dwarf2_cu *cu,
+		struct dwarf2_cu **spec_cu)
 {
   struct die_info *die;
+  unsigned int offset;
   int h;
 
+  offset = dwarf2_get_ref_die_offset (attr, cu);
+
   h = (offset % REF_HASH_SIZE);
   die = die_ref_table[h];
   while (die)
     {
       if (die->offset == offset)
 	{
+	  *spec_cu = cu;
 	  return die;
 	}
       die = die->next_ref;


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