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]

Re: [rfa/dwarf] Support for attributes pointing to a different CU


On Tue, Sep 28, 2004 at 05:40:25PM -0500, Jim Blandy wrote:
> 
> I take it the reason we can't just fill in all the per_cu->psymtab
> values when we build the psymtabs in the first place is that we don't
> actually build the CU index until we see a CU that contains (or might
> contain) inter-CU references.  So we'd have to go back and record the
> psymtabs we'd already created anyway.  Is that right?
> 
> We're constructing a psymtab for every CU we see; does it save much
> time or space to avoid creating a twenty-byte structure as well?  I
> understand that this is time- and space-critical code, but if the hair
> isn't a noticable win, I'd rather it not go in.

Hi Jim,

I think that my earlier messages this afternoon and this patch address
all of your comments.  Please let me know if I missed anything.  The
biggest change is that I removed struct dwarf2_pinfo; instead, we
create a per_cu structure for every psymtab, and use that as the
private data.  This makes a heck of a lot more sense anyway.  The
function used to search for the right per_cu for this psymtab goes
away.  The pointer back to the psymtab is now always set.  It could be
eliminated by passing psymtabs around, but I don't want to do that;
right now per_cu structures correspond one-to-one to symtabs, but
conceptually there can be compilation units that do not correspond to
symtabs (I think).  I also reworked process_queue; it's much clearer
now (and only two passes instead of three).

OK?

-- 
Daniel Jacobowitz

2004-10-03  Daniel Jacobowitz  <dan@debian.org>

	* dwarf2read.c (REF_HASH_SIZE): Move earlier.
	(die_ref_table): Remove.
	(struct dwarf2_cu): Add DIES, DEPENDENCIES, and DIE_REF_TABLE.
	(struct dwarf2_per_cu_data): Add PSYMTAB.  Add a comment describing
	the usage of this type.
	(struct dwarf2_pinfo, PST_PRIVATE, DWARF_INFO_OFFSET): Remove.
	(struct dwarf2_queue_item, dwarf2_queue, dwarf2_queue_tail): New.
	(create_all_comp_units): Take an OFFSET argument and return the per_cu
	data for the CU at that offset.  Handle already-created per_cu
	structures.
	(dwarf2_create_include_psymtab): Update comment.
	(find_partial_die): Remove third argument.  Remove unreachable call
	to error ().
	(dwarf2_find_containing_comp_unit): Update comments.  Change one
	assertion to an error.
	(dwarf2_find_comp_unit): Update comments.
	(type_at_offset): Remove dead code.
	(make_cleanup_free_die_list, dwarf2_empty_hash_tables): Remove.
	(store_in_ref_table): Add CU argument.
	(follow_die_ref): Take DIE, attribute, and CU arguments.  Handle
	inter-compilation-unit references.
	(load_full_comp_unit, process_full_comp_unit): New functions, based
	on psymtab_to_symtab_1.
	(psymtab_to_symtab_1): Use them.
	(dwarf2_add_dependence): New function.
	(dwarf2_build_psymtabs_hard): Set the psymtab in per_cu.  Always create
	a per_cu structure, and save it in READ_PSYMTAB_PRIVATE.
	(partial_die_parent_scope, guess_structure_name): Update for changes
	to find_partial_die.
	(dwarf2_psymtab_to_symtab): Initialize dwarf2_per_objfile here.
	(queue_comp_unit, process_queue, dwarf2_release_queue): New.
	(read_comp_unit): Don't call dwarf2_empty_hash_tables.
	(read_die_and_children): Update call to store_in_ref_table.
	(do_free_die_list_cleanup): Remove.
	(fixup_partial_die): Update for changes to find_partial_die.
	(read_full_die): Handle queueing absolute references.
	(read_attribute_value): Use DW_ADDR for all DW_FORM_ref* forms.
	(dwarf2_attr, die_specification, die_type)
	(die_containing_type, dwarf2_extension): Update calls to
	follow_die_ref.
	(dump_die): Update DW_FORM_ref* handling.
	(dwarf2_get_ref_die_offset): Likewise.
	(free_one_comp_unit): Release the dies list.
	(dwarf2_mark_helper): New function.
	(dwarf2_mark): Use it.

--- src/gdb/dwarf2read.c	2004-10-03 12:14:10.000000000 -0400
+++ src/gdb/dwarf2read.c	2004-10-03 13:32:36.000000000 -0400
@@ -258,6 +258,11 @@ struct comp_unit_head
     int base_known;
   };
 
+/* Fixed size for the DIE hash table.  */
+#ifndef REF_HASH_SIZE
+#define REF_HASH_SIZE 1021
+#endif
+
 /* Internal state when decoding a particular compilation unit.  */
 struct dwarf2_cu
 {
@@ -325,6 +330,17 @@ struct dwarf2_cu
   /* How many compilation units ago was this CU last referenced?  */
   int last_used;
 
+  /* A hash table of die offsets for following references.  */
+  struct die_info *die_ref_table[REF_HASH_SIZE];
+
+  /* Full DIEs if read in.  */
+  struct die_info *dies;
+
+  /* A set of pointers to dwarf2_per_cu_data objects for compilation
+     units referenced by this one.  Only set during full symbol processing;
+     partial symbol tables do not have dependencies.  */
+  htab_t dependencies;
+
   /* Mark used when releasing cached dies.  */
   unsigned int mark : 1;
 
@@ -339,6 +355,12 @@ struct dwarf2_cu
   unsigned int has_namespace_info : 1;
 };
 
+/* Persistent data held for a compilation unit, even when not
+   processing it.  We put a pointer to this structure in the
+   read_symtab_private field of the psymtab.  If we encounter
+   inter-compilation-unit references, we also maintain a sorted
+   list of all compilation units.  */
+
 struct dwarf2_per_cu_data
 {
   /* The start offset and length of this compilation unit.  2**31-1
@@ -358,8 +380,10 @@ struct dwarf2_per_cu_data
      holds a map of DIE offsets to types.  It isn't always possible
      to reconstruct this information later, so we have to preserve
      it.  */
-
   htab_t type_hash;
+
+  /* The partial symbol table associated with this compilation unit.  */
+  struct partial_symtab *psymtab;
 };
 
 /* The line number information for a compilation unit (found in the
@@ -551,13 +575,6 @@ struct dwarf_block
 #define ATTR_ALLOC_CHUNK 4
 #endif
 
-/* A hash table of die offsets for following references.  */
-#ifndef REF_HASH_SIZE
-#define REF_HASH_SIZE 1021
-#endif
-
-static struct die_info *die_ref_table[REF_HASH_SIZE];
-
 /* Allocate fields for structs, unions and enums in this size.  */
 #ifndef DW_FIELD_ALLOC_CHUNK
 #define DW_FIELD_ALLOC_CHUNK 4
@@ -575,19 +592,6 @@ static int isreg;		/* Object lives in re
 				   decode_locdesc's return value is
 				   the register number.  */
 
-/* We put a pointer to this structure in the read_symtab_private field
-   of the psymtab.  */
-
-struct dwarf2_pinfo
-  {
-    /* Offset in .debug_info for this compilation unit. */
-
-    unsigned long dwarf_info_offset;
-  };
-
-#define PST_PRIVATE(p) ((struct dwarf2_pinfo *)(p)->read_symtab_private)
-#define DWARF_INFO_OFFSET(p) (PST_PRIVATE(p)->dwarf_info_offset)
-
 /* FIXME: We might want to set this from BFD via bfd_arch_bits_per_byte,
    but this would require a corresponding change in unpack_field_as_long
    and friends.  */
@@ -641,6 +645,17 @@ struct field_info
     int nfnfields;
   };
 
+/* One item on the queue of compilation units to read in full symbols
+   for.  */
+struct dwarf2_queue_item
+{
+  struct dwarf2_per_cu_data *per_cu;
+  struct dwarf2_queue_item *next;
+};
+
+/* The current queue.  */
+static struct dwarf2_queue_item *dwarf2_queue, *dwarf2_queue_tail;
+
 /* Loaded secondary compilation units are kept in memory until they
    have not been referenced for the processing of this many
    compilation units.  Set this to zero to disable caching.  Cache
@@ -755,8 +770,7 @@ static char *read_partial_die (struct pa
 			       bfd *, char *, struct dwarf2_cu *);
 
 static struct partial_die_info *find_partial_die (unsigned long,
-						  struct dwarf2_cu *,
-						  struct dwarf2_cu **);
+						  struct dwarf2_cu *);
 
 static void fixup_partial_die (struct partial_die_info *,
 			       struct dwarf2_cu *);
@@ -844,10 +858,6 @@ static struct type *die_type (struct die
 static struct type *die_containing_type (struct die_info *,
 					 struct dwarf2_cu *);
 
-#if 0
-static struct type *type_at_offset (unsigned int, struct objfile *);
-#endif
-
 static struct type *tag_type_to_type (struct die_info *, struct dwarf2_cu *);
 
 static void read_type_die (struct die_info *, struct dwarf2_cu *);
@@ -944,8 +954,6 @@ static struct die_info *read_die_and_sib
 
 static void free_die_list (struct die_info *);
 
-static struct cleanup *make_cleanup_free_die_list (struct die_info *);
-
 static void process_die (struct die_info *, struct dwarf2_cu *);
 
 static char *dwarf2_linkage_name (struct die_info *, struct dwarf2_cu *);
@@ -979,16 +987,17 @@ static void dump_die (struct die_info *)
 
 static void dump_die_list (struct die_info *);
 
-static void store_in_ref_table (unsigned int, struct die_info *);
-
-static void dwarf2_empty_hash_tables (void);
+static void store_in_ref_table (unsigned int, struct die_info *,
+				struct dwarf2_cu *);
 
 static unsigned int dwarf2_get_ref_die_offset (struct attribute *,
 					       struct dwarf2_cu *);
 
 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 die_info *,
+					struct attribute *,
+					struct dwarf2_cu *);
 
 static struct type *dwarf2_fundamental_type (struct objfile *, int,
 					     struct dwarf2_cu *);
@@ -1045,12 +1054,18 @@ static void free_one_cached_comp_unit (v
 static void set_die_type (struct die_info *, struct type *,
 			  struct dwarf2_cu *);
 
-#if 0
 static void reset_die_and_siblings_types (struct die_info *,
 					  struct dwarf2_cu *);
-#endif
 
-static void create_all_comp_units (struct objfile *);
+static struct dwarf2_per_cu_data *create_all_comp_units (struct objfile *,
+							 unsigned long);
+
+static struct dwarf2_cu *load_full_comp_unit (struct dwarf2_per_cu_data *);
+
+static void process_full_comp_unit (struct dwarf2_per_cu_data *);
+
+static void dwarf2_add_dependence (struct dwarf2_cu *,
+				   struct dwarf2_per_cu_data *);
 
 static void dwarf2_mark (struct dwarf2_cu *);
 
@@ -1336,9 +1351,7 @@ dwarf2_create_include_psymtab (char *nam
 
   /* No private part is necessary for include psymtabs.  This property
      can be used to differentiate between such include psymtabs and
-     the regular ones.  If it ever happens that a regular psymtab can
-     legitimally have a NULL private part, then we'll have to add a
-     dedicated field for that in the dwarf2_pinfo structure.  */
+     the regular ones.  */
   subpst->read_symtab_private = NULL;
 }
 
@@ -1436,7 +1449,17 @@ dwarf2_build_psymtabs_hard (struct objfi
       make_cleanup (dwarf2_free_abbrev_table, &cu);
 
       if (cu.has_form_ref_addr && dwarf2_per_objfile->all_comp_units == NULL)
-	create_all_comp_units (objfile);
+	this_cu = create_all_comp_units (objfile, cu.header.offset);
+      else if (dwarf2_per_objfile->all_comp_units != NULL)
+	this_cu = dwarf2_find_comp_unit (cu.header.offset, objfile);
+      else
+	{
+	  this_cu = obstack_alloc (&objfile->objfile_obstack,
+				   sizeof (struct dwarf2_per_cu_data));
+	  memset (this_cu, 0, sizeof (*this_cu));
+	  this_cu->offset = cu.header.offset;
+	  this_cu->length = cu.header.length + cu.header.initial_length_size;
+	}
 
       /* Read the compilation unit die */
       abbrev = peek_die_abbrev (info_ptr, &bytes_read, &cu);
@@ -1456,9 +1479,8 @@ dwarf2_build_psymtabs_hard (struct objfi
       if (comp_unit_die.dirname)
 	pst->dirname = xstrdup (comp_unit_die.dirname);
 
-      pst->read_symtab_private = (char *)
-	obstack_alloc (&objfile->objfile_obstack, sizeof (struct dwarf2_pinfo));
-      DWARF_INFO_OFFSET (pst) = beg_of_comp_unit - dwarf2_per_objfile->info_buffer;
+      pst->read_symtab_private = (char *) this_cu;
+
       baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
 
       /* Store the function that reads in the rest of the symbol table */
@@ -1466,30 +1488,28 @@ dwarf2_build_psymtabs_hard (struct objfi
 
       if (dwarf2_per_objfile->all_comp_units != NULL)
 	{
-	  struct dwarf2_per_cu_data *per_cu;
-
-	  per_cu = dwarf2_find_comp_unit (cu.header.offset, objfile);
-
 	  /* If this compilation unit was already read in, free the
 	     cached copy in order to read it in again.  This is
 	     necessary because we skipped some symbols when we first
 	     read in the compilation unit (see load_partial_dies).
 	     This problem could be avoided, but the benefit is
 	     unclear.  */
-	  if (per_cu->cu != NULL)
-	    free_one_cached_comp_unit (per_cu->cu);
+	  if (this_cu->cu != NULL)
+	    free_one_cached_comp_unit (this_cu->cu);
 
-	  cu.per_cu = per_cu;
+	  cu.per_cu = this_cu;
 
 	  /* Note that this is a pointer to our stack frame, being
 	     added to a global data structure.  It will be cleaned up
 	     in free_stack_comp_unit when we finish with this
 	     compilation unit.  */
-	  per_cu->cu = &cu;
+	  this_cu->cu = &cu;
 	}
       else
 	cu.per_cu = NULL;
 
+      this_cu->psymtab = pst;
+
       /* Check if comp unit has_children.
          If so, read the rest of the partial symbols from this comp unit.
          If not, there's no more debug_info for this comp unit. */
@@ -1605,19 +1625,19 @@ load_comp_unit (struct dwarf2_per_cu_dat
    there will be many, and one will occur early in the .debug_info section.
    So there's no point in building this list incrementally.  */
 
-static void
-create_all_comp_units (struct objfile *objfile)
+static struct dwarf2_per_cu_data *
+create_all_comp_units (struct objfile *objfile, unsigned long cur_offset)
 {
   int n_allocated;
   int n_comp_units;
-  struct dwarf2_per_cu_data **all_comp_units;
+  struct dwarf2_per_cu_data **all_comp_units, *cur_cu = NULL;
   char *info_ptr = dwarf2_per_objfile->info_buffer;
 
   n_comp_units = 0;
   n_allocated = 10;
   all_comp_units = xmalloc (n_allocated
 			    * sizeof (struct dwarf2_per_cu_data *));
-  
+
   while (info_ptr < dwarf2_per_objfile->info_buffer + dwarf2_per_objfile->info_size)
     {
       struct comp_unit_head cu_header;
@@ -1628,18 +1648,48 @@ create_all_comp_units (struct objfile *o
 
       offset = info_ptr - dwarf2_per_objfile->info_buffer;
 
-      /* Read just enough information to find out where the next
-	 compilation unit is.  */
-      cu_header.length = read_initial_length (objfile->obfd, info_ptr,
-					      &cu_header, &bytes_read);
+      /* All compilation units strictly before CUR_OFFSET have already
+	 had per_cu structures (and partial symtabs) created.  Find
+	 the psymtab.  This is quadratic, but we expect that the number of
+	 symtabs not including references will be small.  */
+      if (offset < cur_offset)
+	{
+	  struct partial_symtab *pst;
+	  struct dwarf2_per_cu_data *tmp_cu;
 
-      /* Save the compilation unit for later lookup.  */
-      this_cu = obstack_alloc (&objfile->objfile_obstack,
-			       sizeof (struct dwarf2_per_cu_data));
-      memset (this_cu, 0, sizeof (*this_cu));
-      this_cu->offset = offset;
-      this_cu->length = cu_header.length + cu_header.initial_length_size;
+	  this_cu = NULL;
+	  ALL_OBJFILE_PSYMTABS (objfile, pst)
+	    {
+	      if (pst->read_symtab != dwarf2_psymtab_to_symtab)
+		continue;
+	      tmp_cu = (struct dwarf2_per_cu_data *) pst->read_symtab_private;
+	      if (tmp_cu && tmp_cu->offset == offset)
+		{
+		  this_cu = tmp_cu;
+		  break;
+		}
+	    }
+	  gdb_assert (this_cu != NULL);
+	}
+      else
+	{
+	  /* Otherwise, create a new per_cu structure.  Read just
+	     enough information to find out where the next compilation
+	     unit is.  */
+	  cu_header.length = read_initial_length (objfile->obfd, info_ptr,
+						  &cu_header, &bytes_read);
+
+	  this_cu = obstack_alloc (&objfile->objfile_obstack,
+				   sizeof (struct dwarf2_per_cu_data));
+	  memset (this_cu, 0, sizeof (*this_cu));
+	  this_cu->offset = offset;
+	  this_cu->length = cu_header.length + cu_header.initial_length_size;
+
+	  if (cur_offset == offset)
+	    cur_cu = this_cu;
+	}
 
+      /* Save the compilation unit for later lookup.  */
       if (n_comp_units == n_allocated)
 	{
 	  n_allocated *= 2;
@@ -1659,6 +1709,9 @@ create_all_comp_units (struct objfile *o
 	  n_comp_units * sizeof (struct dwarf2_per_cu_data *));
   xfree (all_comp_units);
   dwarf2_per_objfile->n_comp_units = n_comp_units;
+
+  gdb_assert (cur_cu != NULL);
+  return cur_cu;
 }
 
 /* Process all loaded DIEs for compilation unit CU, starting at FIRST_DIE.
@@ -1778,15 +1831,13 @@ partial_die_parent_scope (struct partial
 {
   char *grandparent_scope;
   struct partial_die_info *parent, *real_pdi;
-  struct dwarf2_cu *spec_cu;
 
   /* We need to look at our parent DIE; if we have a DW_AT_specification,
      then this means the parent of the specification DIE.  */
 
   real_pdi = pdi;
-  spec_cu = cu;
   while (real_pdi->has_specification)
-    real_pdi = find_partial_die (real_pdi->spec_offset, spec_cu, &spec_cu);
+    real_pdi = find_partial_die (real_pdi->spec_offset, cu);
 
   parent = real_pdi->die_parent;
   if (parent == NULL)
@@ -1797,7 +1848,7 @@ partial_die_parent_scope (struct partial
 
   fixup_partial_die (parent, cu);
 
-  grandparent_scope = partial_die_parent_scope (parent, spec_cu);
+  grandparent_scope = partial_die_parent_scope (parent, cu);
 
   if (parent->tag == DW_TAG_namespace
       || parent->tag == DW_TAG_structure_type
@@ -2071,16 +2122,14 @@ guess_structure_name (struct partial_die
 
       struct partial_die_info *child_pdi = struct_pdi->die_child;
       struct partial_die_info *real_pdi;
-      struct dwarf2_cu *spec_cu;
 
       /* 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;
-      spec_cu = cu;
       while (real_pdi->has_specification)
-	real_pdi = find_partial_die (real_pdi->spec_offset, spec_cu, &spec_cu);
+	real_pdi = find_partial_die (real_pdi->spec_offset, cu);
 
       if (real_pdi->die_parent != NULL)
 	return;
@@ -2321,6 +2370,10 @@ dwarf2_psymtab_to_symtab (struct partial
 	      gdb_flush (gdb_stdout);
 	    }
 
+	  /* Restore our global data.  */
+	  dwarf2_per_objfile = objfile_data (pst->objfile,
+					     dwarf2_objfile_data_key);
+
 	  psymtab_to_symtab_1 (pst);
 
 	  /* Finish up the debug error message.  */
@@ -2330,21 +2383,104 @@ dwarf2_psymtab_to_symtab (struct partial
     }
 }
 
+/* Add PER_CU to the queue.  */
+
+static void
+queue_comp_unit (struct dwarf2_per_cu_data *per_cu)
+{
+  struct dwarf2_queue_item *item;
+
+  per_cu->queued = 1;
+  item = xmalloc (sizeof (*item));
+  item->per_cu = per_cu;
+  item->next = NULL;
+
+  if (dwarf2_queue == NULL)
+    dwarf2_queue = item;
+  else
+    dwarf2_queue_tail->next = item;
+
+  dwarf2_queue_tail = item;
+}
+
+/* Process the queue.  */
+
+static void
+process_queue (struct objfile *objfile)
+{
+  struct dwarf2_queue_item *item, *next_item;
+
+  /* Initially, there is just one item on the queue.  Load its DIEs,
+     and the DIEs of any other compilation units it requires,
+     transitively.  */
+
+  for (item = dwarf2_queue; item != NULL; item = item->next)
+    {
+      /* Read in this compilation unit.  This may add new items to
+	 the end of the queue.  */
+      load_full_comp_unit (item->per_cu);
+
+      item->per_cu->cu->read_in_chain = dwarf2_per_objfile->read_in_chain;
+      dwarf2_per_objfile->read_in_chain = item->per_cu;
+
+      /* If this compilation unit has already had full symbols created,
+	 reset the TYPE fields in each DIE.  */
+      if (item->per_cu->psymtab->readin)
+	reset_die_and_siblings_types (item->per_cu->cu->dies,
+				      item->per_cu->cu);
+    }
+
+  /* Now everything left on the queue needs to be read in.  Process
+     them, one at a time, removing from the queue as we finish.  */
+  for (item = dwarf2_queue; item != NULL; dwarf2_queue = item = next_item)
+    {
+      if (!item->per_cu->psymtab->readin)
+	process_full_comp_unit (item->per_cu);
+
+      item->per_cu->queued = 0;
+      next_item = item->next;
+      xfree (item);
+    }
+
+  dwarf2_queue_tail = NULL;
+}
+
+/* Free all allocated queue entries.  This function only releases anything if
+   an error was thrown; if the queue was processed then it would have been
+   freed as we went along.  */
+
+static void
+dwarf2_release_queue (void *dummy)
+{
+  struct dwarf2_queue_item *item, *last;
+
+  item = dwarf2_queue;
+  while (item)
+    {
+      /* Anything still marked queued is likely to be in an
+	 inconsistent state, so discard it.  */
+      if (item->per_cu->queued)
+	{
+	  if (item->per_cu->cu != NULL)
+	    free_one_cached_comp_unit (item->per_cu->cu);
+	  item->per_cu->queued = 0;
+	}
+
+      last = item;
+      item = item->next;
+      xfree (last);
+    }
+
+  dwarf2_queue = dwarf2_queue_tail = NULL;
+}
+
+/* Read in full symbols for PST, and anything it depends on.  */
+
 static void
 psymtab_to_symtab_1 (struct partial_symtab *pst)
 {
-  struct objfile *objfile = pst->objfile;
-  bfd *abfd = objfile->obfd;
-  struct dwarf2_cu cu;
-  struct die_info *dies;
-  unsigned long offset;
-  CORE_ADDR lowpc, highpc;
-  struct die_info *child_die;
-  char *info_ptr;
-  struct symtab *symtab;
+  struct dwarf2_per_cu_data *per_cu;
   struct cleanup *back_to;
-  struct attribute *attr;
-  CORE_ADDR baseaddr;
   int i;
 
   for (i = 0; i < pst->number_of_dependencies; i++)
@@ -2364,7 +2500,9 @@ psymtab_to_symtab_1 (struct partial_symt
         psymtab_to_symtab_1 (pst->dependencies[i]);
       }
 
-  if (pst->read_symtab_private == NULL)
+  per_cu = (struct dwarf2_per_cu_data *) pst->read_symtab_private;
+
+  if (per_cu == NULL)
     {
       /* It's an include file, no symbols to read for it.
          Everything is in the parent symtab.  */
@@ -2372,40 +2510,119 @@ psymtab_to_symtab_1 (struct partial_symt
       return;
     }
 
-  dwarf2_per_objfile = objfile_data (pst->objfile, dwarf2_objfile_data_key);
+  back_to = make_cleanup (null_cleanup, NULL);
+
+  if (dwarf2_per_objfile->all_comp_units == NULL)
+    {
+      struct dwarf2_cu *cu;
+      cu = load_full_comp_unit (per_cu);
+      make_cleanup (free_one_comp_unit, cu);
+      process_full_comp_unit (per_cu);
+    }
+  else
+    {
+      make_cleanup (dwarf2_release_queue, NULL);
+
+      queue_comp_unit (per_cu);
+
+      process_queue (pst->objfile);
+
+      /* Age the cache, releasing compilation units that have not
+	 been used recently.  */
+      age_cached_comp_units ();
+    }
+
+  do_cleanups (back_to);
+}
+
+/* Load the DIEs associated with PST and PER_CU into memory.  */
+
+static struct dwarf2_cu *
+load_full_comp_unit (struct dwarf2_per_cu_data *per_cu)
+{
+  struct partial_symtab *pst = per_cu->psymtab;
+  bfd *abfd = pst->objfile->obfd;
+  struct dwarf2_cu *cu;
+  unsigned long offset;
+  char *info_ptr;
+  struct cleanup *back_to, *free_cu_cleanup;
+  struct attribute *attr;
+  CORE_ADDR baseaddr;
 
   /* Set local variables from the partial symbol table info.  */
-  offset = DWARF_INFO_OFFSET (pst);
+  offset = per_cu->offset;
 
   info_ptr = dwarf2_per_objfile->info_buffer + offset;
-  baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
-
-  /* We're in the global namespace.  */
-  processing_current_prefix = "";
 
-  memset (&cu, 0, sizeof (struct dwarf2_cu));
-  obstack_init (&cu.comp_unit_obstack);
-  back_to = make_cleanup (free_stack_comp_unit, &cu);
+  cu = xmalloc (sizeof (struct dwarf2_cu));
+  memset (cu, 0, sizeof (struct dwarf2_cu));
 
-  buildsym_init ();
-  make_cleanup (really_free_pendings, NULL);
+  /* If an error occurs while loading, release our storage.  */
+  free_cu_cleanup = make_cleanup (free_one_comp_unit, cu);
 
-  cu.objfile = objfile;
+  cu->objfile = pst->objfile;
 
   /* read in the comp_unit header  */
-  info_ptr = read_comp_unit_head (&cu.header, info_ptr, abfd);
+  info_ptr = read_comp_unit_head (&cu->header, info_ptr, abfd);
 
   /* Read the abbrevs for this compilation unit  */
-  dwarf2_read_abbrevs (abfd, &cu);
-  make_cleanup (dwarf2_free_abbrev_table, &cu);
+  dwarf2_read_abbrevs (abfd, cu);
+  back_to = make_cleanup (dwarf2_free_abbrev_table, cu);
+
+  cu->header.offset = offset;
+
+  cu->per_cu = per_cu;
+  per_cu->cu = cu;
+
+  /* We use this obstack for block values in dwarf_alloc_block.  */
+  obstack_init (&cu->comp_unit_obstack);
+
+  cu->dies = read_comp_unit (info_ptr, abfd, cu);
+
+  /* We try not to read any attributes in this function, because not
+     all objfiles needed for references have been loaded yet, and symbol
+     table processing isn't initialized.  But we have to set the CU language,
+     or we won't be able to build types correctly.  */
+  attr = dwarf2_attr (cu->dies, DW_AT_language, cu);
+  if (attr)
+    set_cu_language (DW_UNSND (attr), cu);
+  else
+    set_cu_language (language_minimal, cu);
+
+  do_cleanups (back_to);
+
+  /* We've successfully allocated this compilation unit.  Let our caller
+     clean it up when finished with it.  */
+  discard_cleanups (free_cu_cleanup);
 
-  cu.header.offset = offset;
+  return cu;
+}
+
+/* Generate full symbol information for PST and CU, whose DIEs have
+   already been loaded into memory.  */
+
+static void
+process_full_comp_unit (struct dwarf2_per_cu_data *per_cu)
+{
+  struct partial_symtab *pst = per_cu->psymtab;
+  struct dwarf2_cu *cu = per_cu->cu;
+  struct objfile *objfile = pst->objfile;
+  bfd *abfd = objfile->obfd;
+  CORE_ADDR lowpc, highpc;
+  struct symtab *symtab;
+  struct cleanup *back_to;
+  struct attribute *attr;
+  CORE_ADDR baseaddr;
 
-  cu.list_in_scope = &file_symbols;
+  baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
 
-  dies = read_comp_unit (info_ptr, abfd, &cu);
+  /* We're in the global namespace.  */
+  processing_current_prefix = "";
+
+  buildsym_init ();
+  back_to = make_cleanup (really_free_pendings, NULL);
 
-  make_cleanup_free_die_list (dies);
+  cu->list_in_scope = &file_symbols;
 
   /* Find the base address of the compilation unit for range lists and
      location lists.  It will normally be specified by DW_AT_low_pc.
@@ -2413,32 +2630,32 @@ psymtab_to_symtab_1 (struct partial_symt
      DW_AT_entry_pc.  It's been removed, but GCC still uses this for
      compilation units with discontinuous ranges.  */
 
-  cu.header.base_known = 0;
-  cu.header.base_address = 0;
+  cu->header.base_known = 0;
+  cu->header.base_address = 0;
 
-  attr = dwarf2_attr (dies, DW_AT_entry_pc, &cu);
+  attr = dwarf2_attr (cu->dies, DW_AT_entry_pc, cu);
   if (attr)
     {
-      cu.header.base_address = DW_ADDR (attr);
-      cu.header.base_known = 1;
+      cu->header.base_address = DW_ADDR (attr);
+      cu->header.base_known = 1;
     }
   else
     {
-      attr = dwarf2_attr (dies, DW_AT_low_pc, &cu);
+      attr = dwarf2_attr (cu->dies, DW_AT_low_pc, cu);
       if (attr)
 	{
-	  cu.header.base_address = DW_ADDR (attr);
-	  cu.header.base_known = 1;
+	  cu->header.base_address = DW_ADDR (attr);
+	  cu->header.base_known = 1;
 	}
     }
 
   /* Do line number decoding in read_file_scope () */
-  process_die (dies, &cu);
+  process_die (cu->dies, cu);
 
   /* Some compilers don't define a DW_AT_high_pc attribute for the
      compilation unit.  If the DW_AT_high_pc is missing, synthesize
      it, by scanning the DIE's below the compilation unit.  */
-  get_scope_pc_bounds (dies, &lowpc, &highpc, &cu);
+  get_scope_pc_bounds (cu->dies, &lowpc, &highpc, cu);
 
   symtab = end_symtab (highpc + baseaddr, objfile, SECT_OFF_TEXT (objfile));
 
@@ -2446,9 +2663,9 @@ psymtab_to_symtab_1 (struct partial_symt
      If the compilation is from a C file generated by language preprocessors,
      do not set the language if it was already deduced by start_subfile.  */
   if (symtab != NULL
-      && !(cu.language == language_c && symtab->language != language_c))
+      && !(cu->language == language_c && symtab->language != language_c))
     {
-      symtab->language = cu.language;
+      symtab->language = cu->language;
     }
   pst->symtab = symtab;
   pst->readin = 1;
@@ -4658,10 +4875,6 @@ read_subrange_type (struct die_info *die
 static struct die_info *
 read_comp_unit (char *info_ptr, bfd *abfd, struct dwarf2_cu *cu)
 {
-  /* Reset die reference table; we are
-     building new ones now.  */
-  dwarf2_empty_hash_tables ();
-
   return read_die_and_children (info_ptr, abfd, cu, &info_ptr, NULL);
 }
 
@@ -4682,7 +4895,7 @@ read_die_and_children (char *info_ptr, b
   int has_children;
 
   cur_ptr = read_full_die (&die, abfd, info_ptr, cu, &has_children);
-  store_in_ref_table (die->offset, die);
+  store_in_ref_table (die->offset, die, cu);
 
   if (has_children)
     {
@@ -4761,19 +4974,6 @@ free_die_list (struct die_info *dies)
     }
 }
 
-static void
-do_free_die_list_cleanup (void *dies)
-{
-  free_die_list (dies);
-}
-
-static struct cleanup *
-make_cleanup_free_die_list (struct die_info *dies)
-{
-  return make_cleanup (do_free_die_list_cleanup, dies);
-}
-
-
 /* Read the contents of the section at OFFSET and of size SIZE from the
    object file specified by OBJFILE into the objfile_obstack and return it.  */
 
@@ -5313,27 +5513,16 @@ find_partial_die_in_comp_unit (unsigned 
 /* Find a partial DIE at OFFSET, which may or may not be in CU.  */
 
 static struct partial_die_info *
-find_partial_die (unsigned long offset, struct dwarf2_cu *cu,
-		  struct dwarf2_cu **target_cu)
+find_partial_die (unsigned long offset, struct dwarf2_cu *cu)
 {
   struct dwarf2_per_cu_data *per_cu;
 
   if (offset >= cu->header.offset
       && offset < cu->header.offset + cu->header.length)
-    {
-      *target_cu = cu;
-      return find_partial_die_in_comp_unit (offset, cu);
-    }
+    return find_partial_die_in_comp_unit (offset, cu);
 
   per_cu = dwarf2_find_containing_comp_unit (offset, cu->objfile);
 
-  /* If this offset isn't pointing into a known compilation unit,
-     the debug information is probably corrupted.  */
-  if (per_cu == NULL)
-    error ("Dwarf Error: could not find partial DIE containing "
-	   "offset 0x%lx [in module %s]",
-	   (long) offset, bfd_get_filename (cu->objfile->obfd));
-
   if (per_cu->cu == NULL)
     {
       load_comp_unit (per_cu, cu->objfile);
@@ -5342,7 +5531,6 @@ find_partial_die (unsigned long offset, 
     }
 
   per_cu->cu->last_used = 0;
-  *target_cu = per_cu->cu;
   return find_partial_die_in_comp_unit (offset, per_cu->cu);
 }
 
@@ -5359,11 +5547,10 @@ fixup_partial_die (struct partial_die_in
   if (part_die->name == NULL && part_die->has_specification)
     {
       struct partial_die_info *spec_die;
-      struct dwarf2_cu *spec_cu;
 
-      spec_die = find_partial_die (part_die->spec_offset, cu, &spec_cu);
+      spec_die = find_partial_die (part_die->spec_offset, cu);
 
-      fixup_partial_die (spec_die, spec_cu);
+      fixup_partial_die (spec_die, cu);
 
       if (spec_die->name)
 	{
@@ -5437,6 +5624,38 @@ read_full_die (struct die_info **diep, b
     {
       info_ptr = read_attribute (&die->attrs[i], &abbrev->attrs[i],
 				 abfd, info_ptr, cu);
+
+      /* If this attribute is an absolute reference to a different
+	 compilation unit, make sure that compilation unit is loaded
+	 also.  */
+      if (die->attrs[i].form == DW_FORM_ref_addr
+	  && (DW_ADDR (&die->attrs[i]) < cu->header.offset
+	      || (DW_ADDR (&die->attrs[i])
+		  >= cu->header.offset + cu->header.length)))
+	{
+	  struct dwarf2_per_cu_data *per_cu;
+	  per_cu = dwarf2_find_containing_comp_unit (DW_ADDR (&die->attrs[i]),
+						     cu->objfile);
+
+	  /* Mark the dependence relation so that we don't flush PER_CU
+	     too early.  */
+	  dwarf2_add_dependence (cu, per_cu);
+
+	  /* If it's already on the queue, we have nothing to do.  */
+	  if (per_cu->queued)
+	    continue;
+
+	  /* If the compilation unit is already loaded, just mark it as
+	     used.  */
+	  if (per_cu->cu != NULL)
+	    {
+	      per_cu->cu->last_used = 0;
+	      continue;
+	    }
+
+	  /* Add it to the queue.  */
+	  queue_comp_unit (per_cu);
+       }
     }
 
   *diep = die;
@@ -5533,23 +5752,24 @@ read_attribute_value (struct attribute *
       info_ptr += bytes_read;
       break;
     case DW_FORM_ref1:
-      DW_UNSND (attr) = read_1_byte (abfd, info_ptr);
+      DW_ADDR (attr) = cu->header.offset + read_1_byte (abfd, info_ptr);
       info_ptr += 1;
       break;
     case DW_FORM_ref2:
-      DW_UNSND (attr) = read_2_bytes (abfd, info_ptr);
+      DW_ADDR (attr) = cu->header.offset + read_2_bytes (abfd, info_ptr);
       info_ptr += 2;
       break;
     case DW_FORM_ref4:
-      DW_UNSND (attr) = read_4_bytes (abfd, info_ptr);
+      DW_ADDR (attr) = cu->header.offset + read_4_bytes (abfd, info_ptr);
       info_ptr += 4;
       break;
     case DW_FORM_ref8:
-      DW_UNSND (attr) = read_8_bytes (abfd, info_ptr);
+      DW_ADDR (attr) = cu->header.offset + read_8_bytes (abfd, info_ptr);
       info_ptr += 8;
       break;
     case DW_FORM_ref_udata:
-      DW_UNSND (attr) = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
+      DW_ADDR (attr) = (cu->header.offset
+			+ read_unsigned_leb128 (abfd, info_ptr, &bytes_read));
       info_ptr += bytes_read;
       break;
     case DW_FORM_indirect:
@@ -5957,21 +6177,14 @@ dwarf2_attr (struct die_info *die, unsig
   for (i = 0; i < die->num_attrs; ++i)
     {
       if (die->attrs[i].name == name)
-	{
-	  return &die->attrs[i];
-	}
+	return &die->attrs[i];
       if (die->attrs[i].name == DW_AT_specification
 	  || die->attrs[i].name == DW_AT_abstract_origin)
 	spec = &die->attrs[i];
     }
-  if (spec)
-    {
-      struct die_info *ref_die =
-      follow_die_ref (dwarf2_get_ref_die_offset (spec, cu));
 
-      if (ref_die)
-	return dwarf2_attr (ref_die, name, cu);
-    }
+  if (spec)
+    return dwarf2_attr (follow_die_ref (die, spec, cu), name, cu);
 
   return NULL;
 }
@@ -6013,7 +6226,7 @@ die_specification (struct die_info *die,
   if (spec_attr == NULL)
     return NULL;
   else
-    return follow_die_ref (dwarf2_get_ref_die_offset (spec_attr, cu));
+    return follow_die_ref (die, spec_attr, cu);
 }
 
 /* Free the line_header structure *LH, and any arrays and strings it
@@ -6944,7 +7157,6 @@ die_type (struct die_info *die, struct d
   struct type *type;
   struct attribute *type_attr;
   struct die_info *type_die;
-  unsigned int ref;
 
   type_attr = dwarf2_attr (die, DW_AT_type, cu);
   if (!type_attr)
@@ -6953,16 +7165,8 @@ die_type (struct die_info *die, struct d
       return dwarf2_fundamental_type (cu->objfile, FT_VOID, cu);
     }
   else
-    {
-      ref = dwarf2_get_ref_die_offset (type_attr, cu);
-      type_die = follow_die_ref (ref);
-      if (!type_die)
-	{
-	  error ("Dwarf Error: Cannot find referent at offset %d [in module %s]", 
-			  ref, cu->objfile->name);
-	  return NULL;
-	}
-    }
+    type_die = follow_die_ref (die, type_attr, cu);
+
   type = tag_type_to_type (type_die, cu);
   if (!type)
     {
@@ -6982,19 +7186,11 @@ die_containing_type (struct die_info *di
   struct type *type = NULL;
   struct attribute *type_attr;
   struct die_info *type_die = NULL;
-  unsigned int ref;
 
   type_attr = dwarf2_attr (die, DW_AT_containing_type, cu);
   if (type_attr)
     {
-      ref = dwarf2_get_ref_die_offset (type_attr, cu);
-      type_die = follow_die_ref (ref);
-      if (!type_die)
-	{
-	  error ("Dwarf Error: Cannot find referent at offset %d [in module %s]", ref, 
-			  cu->objfile->name);
-	  return NULL;
-	}
+      type_die = follow_die_ref (die, type_attr, cu);
       type = tag_type_to_type (type_die, cu);
     }
   if (!type)
@@ -7007,24 +7203,6 @@ die_containing_type (struct die_info *di
   return type;
 }
 
-#if 0
-static struct type *
-type_at_offset (unsigned int offset, struct dwarf2_cu *cu)
-{
-  struct die_info *die;
-  struct type *type;
-
-  die = follow_die_ref (offset);
-  if (!die)
-    {
-      error ("Dwarf Error: Cannot find type referent at offset %d.", offset);
-      return NULL;
-    }
-  type = tag_type_to_type (die, cu);
-  return type;
-}
-#endif
-
 static struct type *
 tag_type_to_type (struct die_info *die, struct dwarf2_cu *cu)
 {
@@ -7378,21 +7556,12 @@ static struct die_info *
 dwarf2_extension (struct die_info *die, struct dwarf2_cu *cu)
 {
   struct attribute *attr;
-  struct die_info *extension_die;
-  unsigned int ref;
 
   attr = dwarf2_attr (die, DW_AT_extension, cu);
   if (attr == NULL)
     return NULL;
 
-  ref = dwarf2_get_ref_die_offset (attr, cu);
-  extension_die = follow_die_ref (ref);
-  if (!extension_die)
-    {
-      error ("Dwarf Error: Cannot find referent at offset %d.", ref);
-    }
-
-  return extension_die;
+  return follow_die_ref (die, attr, cu);
 }
 
 /* Convert a DIE tag into its string name.  */
@@ -8229,13 +8398,16 @@ dump_die (struct die_info *die)
 	case DW_FORM_block1:
 	  fprintf_unfiltered (gdb_stderr, "block: size %d", DW_BLOCK (&die->attrs[i])->size);
 	  break;
+	case DW_FORM_ref1:
+	case DW_FORM_ref2:
+	case DW_FORM_ref4:
+	  fprintf_unfiltered (gdb_stderr, "constant ref: %ld (adjusted)",
+			      (long) (DW_ADDR (&die->attrs[i])));
+	  break;
 	case DW_FORM_data1:
 	case DW_FORM_data2:
 	case DW_FORM_data4:
 	case DW_FORM_data8:
-	case DW_FORM_ref1:
-	case DW_FORM_ref2:
-	case DW_FORM_ref4:
 	case DW_FORM_udata:
 	case DW_FORM_sdata:
 	  fprintf_unfiltered (gdb_stderr, "constant: %ld", DW_UNSND (&die->attrs[i]));
@@ -8279,22 +8451,16 @@ dump_die_list (struct die_info *die)
 }
 
 static void
-store_in_ref_table (unsigned int offset, struct die_info *die)
+store_in_ref_table (unsigned int offset, struct die_info *die,
+		    struct dwarf2_cu *cu)
 {
   int h;
   struct die_info *old;
 
   h = (offset % REF_HASH_SIZE);
-  old = die_ref_table[h];
+  old = cu->die_ref_table[h];
   die->next_ref = old;
-  die_ref_table[h] = die;
-}
-
-
-static void
-dwarf2_empty_hash_tables (void)
-{
-  memset (die_ref_table, 0, sizeof (die_ref_table));
+  cu->die_ref_table[h] = die;
 }
 
 static unsigned int
@@ -8305,14 +8471,12 @@ dwarf2_get_ref_die_offset (struct attrib
   switch (attr->form)
     {
     case DW_FORM_ref_addr:
-      result = DW_ADDR (attr);
-      break;
     case DW_FORM_ref1:
     case DW_FORM_ref2:
     case DW_FORM_ref4:
     case DW_FORM_ref8:
     case DW_FORM_ref_udata:
-      result = cu->header.offset + DW_UNSND (attr);
+      result = DW_ADDR (attr);
       break;
     default:
       complaint (&symfile_complaints,
@@ -8345,21 +8509,41 @@ dwarf2_get_attr_constant_value (struct a
 }
 
 static struct die_info *
-follow_die_ref (unsigned int offset)
+follow_die_ref (struct die_info *src_die, struct attribute *attr,
+		struct dwarf2_cu *cu)
 {
   struct die_info *die;
+  unsigned int offset;
   int h;
+  struct die_info temp_die;
+  struct dwarf2_cu *target_cu;
+
+  offset = dwarf2_get_ref_die_offset (attr, cu);
+
+  if (DW_ADDR (attr) < cu->header.offset
+      || DW_ADDR (attr) >= cu->header.offset + cu->header.length)
+    {
+      struct dwarf2_per_cu_data *per_cu;
+      per_cu = dwarf2_find_containing_comp_unit (DW_ADDR (attr),
+						 cu->objfile);
+      target_cu = per_cu->cu;
+    }
+  else
+    target_cu = cu;
 
   h = (offset % REF_HASH_SIZE);
-  die = die_ref_table[h];
+  die = target_cu->die_ref_table[h];
   while (die)
     {
       if (die->offset == offset)
-	{
-	  return die;
-	}
+	return die;
       die = die->next_ref;
     }
+
+  error ("Dwarf Error: Cannot find DIE at 0x%lx referenced from DIE "
+	 "at 0x%lx [in module %s]",
+	 (long) src_die->offset, (long) offset, cu->objfile->name);
+
   return NULL;
 }
 
@@ -9089,7 +9273,7 @@ dwarf2_symbol_mark_computed (struct attr
 }
 
 /* Locate the compilation unit from CU's objfile which contains the
-   DIE at OFFSET.  Returns NULL on failure.  */
+   DIE at OFFSET.  Raises an error on failure.  */
 
 static struct dwarf2_per_cu_data *
 dwarf2_find_containing_comp_unit (unsigned long offset,
@@ -9116,7 +9300,11 @@ dwarf2_find_containing_comp_unit (unsign
   gdb_assert (low == high);
   if (dwarf2_per_objfile->all_comp_units[low]->offset > offset)
     {
-      gdb_assert (low > 0);
+      if (low == 0)
+	error ("Dwarf Error: could not find partial DIE containing "
+	       "offset 0x%lx [in module %s]",
+	       (long) offset, bfd_get_filename (objfile->obfd));
+
       gdb_assert (dwarf2_per_objfile->all_comp_units[low-1]->offset <= offset);
       return dwarf2_per_objfile->all_comp_units[low-1];
     }
@@ -9131,6 +9319,9 @@ dwarf2_find_containing_comp_unit (unsign
     }
 }
 
+/* Locate the compilation unit from OBJFILE which is located at exactly
+   OFFSET.  Raises an error on failure.  */
+
 static struct dwarf2_per_cu_data *
 dwarf2_find_comp_unit (unsigned long offset, struct objfile *objfile)
 {
@@ -9155,6 +9346,8 @@ free_one_comp_unit (void *data)
   cu->per_cu = NULL;
 
   obstack_free (&cu->comp_unit_obstack, NULL);
+  if (cu->dies)
+    free_die_list (cu->dies);
 
   xfree (cu);
 }
@@ -9335,8 +9528,6 @@ set_die_type (struct die_info *die, stru
   **slot = ofs;
 }
 
-#if 0
-
 /* Find the type for DIE in TYPE_HASH, or return NULL if DIE does not
    have a saved type.  */
 
@@ -9372,17 +9563,56 @@ reset_die_and_siblings_types (struct die
     }
 }
 
-#endif
+/* Set the mark field in CU and in every other compilation unit in the
+   cache that we must keep because we are keeping CU.  */
+
+/* Add a dependence relationship from CU to REF_PER_CU.  */
+
+static void
+dwarf2_add_dependence (struct dwarf2_cu *cu,
+		       struct dwarf2_per_cu_data *ref_per_cu)
+{
+  void **slot;
+
+  if (cu->dependencies == NULL)
+    cu->dependencies
+      = htab_create_alloc_ex (5, htab_hash_pointer, htab_eq_pointer,
+			      NULL, &cu->comp_unit_obstack,
+			      hashtab_obstack_allocate,
+			      dummy_obstack_deallocate);
+
+  slot = htab_find_slot (cu->dependencies, ref_per_cu, INSERT);
+  if (*slot == NULL)
+    *slot = ref_per_cu;
+}
 
 /* Set the mark field in CU and in every other compilation unit in the
    cache that we must keep because we are keeping CU.  */
 
+static int
+dwarf2_mark_helper (void **slot, void *data)
+{
+  struct dwarf2_per_cu_data *per_cu;
+
+  per_cu = (struct dwarf2_per_cu_data *) *slot;
+  if (per_cu->cu->mark)
+    return 1;
+  per_cu->cu->mark = 1;
+
+  if (per_cu->cu->dependencies != NULL)
+    htab_traverse (per_cu->cu->dependencies, dwarf2_mark_helper, NULL);
+
+  return 1;
+}
+
 static void
 dwarf2_mark (struct dwarf2_cu *cu)
 {
   if (cu->mark)
     return;
   cu->mark = 1;
+  if (cu->dependencies != NULL)
+    htab_traverse (cu->dependencies, dwarf2_mark_helper, NULL);
 }
 
 static void


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