[7/10] keep track of dependencies

Tom Tromey tromey@redhat.com
Wed Apr 25 18:56:00 GMT 2012


This patch introduces the dependency-tracking code for psymtabs and
symtabs.

When scanning we keep a vector of dependencies.  Then, depending on
whether we are reading psymtabs or symtabs, we do different computations
to update the relevant new fields in the psymtab or symtab,
respectively.

There is one mildly ugly bit in dw2_do_instantiate_symtab.  The DWARF
reader can jump around a bit more now so we have to be careful not to
wind up redoing work.

Also, you may note that we track dependencies according to
dwarf2_per_cu_data, then we have a subsequent pass to fix up the
symtabs.  This is done because symtab construction is not reentrant --
buildsym relies on a whole mess of global variables.

I looked at fixing buildsym but decided the approach I took was simpler
for another reason, namely the possibility of the CU cache evicting data
before the processing was complete.

Tom

>From 1b8da2a3522e31ea61a9e52c8b5351f245ea0138 Mon Sep 17 00:00:00 2001
From: Tom Tromey <tromey@redhat.com>
Date: Mon, 23 Apr 2012 12:19:58 -0600
Subject: [PATCH 07/10] keep track of dependencies when reading psymtabs and
 symtabs this almost works but sometimes gives crashes

	* dwarf2read.c: (dwarf2_per_cu_ptr): New typedef.
	(struct dwarf2_per_objfile) <just_read_cus>: New field.
	(struct dwarf2_per_cu_data) <imported_symtabs>: New field.
	(dw2_do_instantiate_symtab): Check whether symtab was read in
	before queueing.
	(dw2_instantiate_symtab): Add assertion.  Call
	process_cu_includes.
	(process_psymtab_comp_unit): Compute 'dependencies' for psymtab.
	(partial_symtab_p): New typedef.
	(struct partial_users): New.
	(hash_partial_users, eq_partial_users, del_partial_users)
	(add_partial_user, set_partial_users): New functions.
	(dwarf2_build_psymtabs_hard): Use set_partial_users.
	(scan_partial_symbols): Add imported CU to imported_symtabs.
	(dwarf2_psymtab_to_symtab): Call process_cu_includes.
	(psymtab_to_symtab_1): Do nothing if psymtab is readin.
	(get_symtab, recursively_compute_inclusions)
	(compute_symtab_includes, process_cu_includes): New functions.
	(process_die) <DW_TAG_imported_unit>: New case.
	(dwarf2_per_objfile_free): Free 'imported_symtabs'.
---
 gdb/dwarf2read.c |  306 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 303 insertions(+), 3 deletions(-)

diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index 154d9b2..bf8eae2 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -146,6 +146,9 @@ struct mapped_index
   const char *constant_pool;
 };
 
+typedef struct dwarf2_per_cu_data *dwarf2_per_cu_ptr;
+DEF_VEC_P (dwarf2_per_cu_ptr);
+
 /* Collection of data recorded per objfile.
    This hangs off of dwarf2_objfile_data_key.  */
 
@@ -219,6 +222,9 @@ struct dwarf2_per_objfile
   /* Table mapping type .debug_types DIE sect_offset to types.
      This is NULL if not allocated yet.  */
   htab_t debug_types_type_hash;
+
+  /* The CUs we recently read.  */
+  VEC (dwarf2_per_cu_ptr) *just_read_cus;
 };
 
 static struct dwarf2_per_objfile *dwarf2_per_objfile;
@@ -445,6 +451,9 @@ struct dwarf2_per_cu_data
     /* Data needed by the "quick" functions.  */
     struct dwarf2_per_cu_quick_data *quick;
   } v;
+
+  /* The CUs we import using DW_TAG_imported_unit.  */
+  VEC (dwarf2_per_cu_ptr) *imported_symtabs;
 };
 
 /* Entry in the signatured_types hash table.  */
@@ -1275,6 +1284,9 @@ static void dwarf2_release_queue (void *dummy);
 
 static void queue_comp_unit (struct dwarf2_per_cu_data *per_cu);
 
+static int maybe_queue_comp_unit (struct dwarf2_cu *this_cu,
+				  struct dwarf2_per_cu_data *per_cu);
+
 static void process_queue (void);
 
 static void find_file_and_directory (struct die_info *die,
@@ -1294,6 +1306,8 @@ static void init_cu_die_reader (struct die_reader_specs *reader,
 
 static htab_t allocate_signatured_type_table (struct objfile *objfile);
 
+static void process_cu_includes (void);
+
 #if WORDS_BIGENDIAN
 
 /* Convert VALUE between big- and little-endian.  */
@@ -1804,9 +1818,13 @@ dw2_do_instantiate_symtab (struct dwarf2_per_cu_data *per_cu)
 
   back_to = make_cleanup (dwarf2_release_queue, NULL);
 
-  queue_comp_unit (per_cu);
-
-  load_cu (per_cu);
+  if (dwarf2_per_objfile->using_index
+      ? per_cu->v.quick->symtab == NULL
+      : (per_cu->v.psymtab == NULL || !per_cu->v.psymtab->readin))
+    {
+      queue_comp_unit (per_cu);
+      load_cu (per_cu);
+    }
 
   process_queue ();
 
@@ -1824,11 +1842,13 @@ dw2_do_instantiate_symtab (struct dwarf2_per_cu_data *per_cu)
 static struct symtab *
 dw2_instantiate_symtab (struct dwarf2_per_cu_data *per_cu)
 {
+  gdb_assert (dwarf2_per_objfile->using_index);
   if (!per_cu->v.quick->symtab)
     {
       struct cleanup *back_to = make_cleanup (free_cached_comp_units, NULL);
       increment_reading_symtab ();
       dw2_do_instantiate_symtab (per_cu);
+      process_cu_includes ();
       do_cleanups (back_to);
     }
   return per_cu->v.quick->symtab;
@@ -3589,6 +3609,25 @@ process_psymtab_comp_unit (struct dwarf2_per_cu_data *this_cu,
     (objfile->static_psymbols.list + pst->statics_offset);
   sort_pst_symbols (pst);
 
+  if (!VEC_empty (dwarf2_per_cu_ptr, this_cu->imported_symtabs))
+    {
+      int i;
+      int len = VEC_length (dwarf2_per_cu_ptr, this_cu->imported_symtabs);
+      struct dwarf2_per_cu_data *iter;
+
+      /* Fill in 'dependencies' here; we fill in 'users' in a
+	 post-pass.  */
+      pst->number_of_dependencies = len;
+      pst->dependencies = obstack_alloc (&objfile->objfile_obstack,
+					 len * sizeof (struct symtab *));
+      for (i = 0;
+	   VEC_iterate (dwarf2_per_cu_ptr, this_cu->imported_symtabs, i, iter);
+	   ++i)
+	pst->dependencies[i] = iter->v.psymtab;
+
+      VEC_free (dwarf2_per_cu_ptr, this_cu->imported_symtabs);
+    }
+
   if (is_debug_types_section)
     {
       /* It's not clear we want to do anything with stmt lists here.
@@ -3645,6 +3684,120 @@ psymtabs_addrmap_cleanup (void *o)
   objfile->psymtabs_addrmap = NULL;
 }
 
+typedef struct partial_symtab *partial_symtab_p;
+DEF_VEC_P (partial_symtab_p);
+
+/* This is used when computing the 'users' field for a psymtab.  */
+
+struct partial_users
+{
+  struct partial_symtab *pst;
+  VEC (partial_symtab_p) *users;
+};
+
+/* Hash function for struct partial_users.  */
+
+static hashval_t
+hash_partial_users (const void *p)
+{
+  const struct partial_users *u = p;
+
+  return htab_hash_pointer (u->pst);
+}
+
+/* Equality function for struct partial_users.  */
+
+static int
+eq_partial_users (const void *a, const void *b)
+{
+  const struct partial_users *pa = a;
+  const struct partial_users *pb = b;
+
+  return pa->pst == pb->pst;
+}
+
+/* Deletion function for struct partial_users.  */
+
+static void
+del_partial_users (void *p)
+{
+  struct partial_users *user = p;
+
+  VEC_free (partial_symtab_p, user->users);
+  xfree (user);
+}
+
+/* Add a user to the list of psymtab users of INCLUDED.  */
+
+static void
+add_partial_user (htab_t user_hash,
+		  struct partial_symtab *included,
+		  struct partial_symtab *using_psymtab)
+{
+  void **slot;
+  struct partial_users *user, tem;
+
+  tem.pst = included;
+  slot = htab_find_slot (user_hash, &tem, INSERT);
+  if (*slot == NULL)
+    {
+      user = XNEW (struct partial_users);
+      user->pst = included;
+      user->users = NULL;
+      *slot = user;
+    }
+  else
+    user = *slot;
+  VEC_safe_push (partial_symtab_p, user->users, using_psymtab);
+}
+
+/* Compute the 'users' field for each psymtab in OBJFILE.  */
+
+static void
+set_partial_users (struct objfile *objfile)
+{
+  htab_t user_hash;
+  int i;
+
+  user_hash = htab_create_alloc (1, hash_partial_users, eq_partial_users,
+				 del_partial_users, xcalloc, xfree);
+
+  for (i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
+    {
+      struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i);
+      struct partial_symtab *pst = per_cu->v.psymtab;
+      int j;
+
+      for (j = 0; j < pst->number_of_dependencies; ++j)
+	add_partial_user (user_hash, pst->dependencies[j], pst);
+    }
+
+  for (i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
+    {
+      struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i);
+      struct partial_symtab *pst = per_cu->v.psymtab;
+      struct partial_users *user, tem;
+
+      tem.pst = pst;
+      user = htab_find (user_hash, &tem);
+      if (user != NULL)
+	{
+	  int len = VEC_length (partial_symtab_p, user->users);
+
+	  gdb_assert (len > 0);
+	  pst->users = obstack_alloc (&objfile->objfile_obstack,
+				      (len + 1)
+				      * sizeof (struct partial_symtab *));
+	  memcpy (pst->users,
+		  VEC_address (partial_symtab_p, user->users),
+		  len * sizeof (struct partial_symtab *));
+	  pst->users[len] = NULL;
+	}
+    }
+
+  htab_delete (user_hash);
+}
+
 /* Build the partial symbol table by doing a quick pass through the
    .debug_info and .debug_abbrev sections.  */
 
@@ -3681,6 +3834,8 @@ dwarf2_build_psymtabs_hard (struct objfile *objfile)
       process_psymtab_comp_unit (per_cu, &dwarf2_per_objfile->info, 0, 0);
     }
 
+  set_partial_users (objfile);
+
   objfile->psymtabs_addrmap = addrmap_create_fixed (objfile->psymtabs_addrmap,
 						    &objfile->objfile_obstack);
   discard_cleanups (addrmap_cleanup);
@@ -3910,6 +4065,9 @@ scan_partial_symbols (struct partial_die_info *first_die, CORE_ADDR *lowpc,
 		if (per_cu->v.psymtab == NULL)
 		  process_psymtab_comp_unit (per_cu,
 					     &dwarf2_per_objfile->info, 0, 1);
+
+		VEC_safe_push (dwarf2_per_cu_ptr, cu->per_cu->imported_symtabs,
+			       per_cu);
 	      }
 	      break;
 	    default:
@@ -4598,6 +4756,8 @@ dwarf2_psymtab_to_symtab (struct partial_symtab *pst)
 	    printf_filtered (_("done.\n"));
 	}
     }
+
+  process_cu_includes ();
 }
 
 /* Reading in full CUs.  */
@@ -4684,6 +4844,9 @@ psymtab_to_symtab_1 (struct partial_symtab *pst)
   struct cleanup *back_to;
   int i;
 
+  if (pst->readin)
+    return;
+
   for (i = 0; i < pst->number_of_dependencies; i++)
     if (!pst->dependencies[i]->readin)
       {
@@ -4846,6 +5009,111 @@ compute_delayed_physnames (struct dwarf2_cu *cu)
     }
 }
 
+static void compute_symtab_includes (struct dwarf2_per_cu_data *per_cu);
+
+/* Return the symtab for PER_CU.  This works properly regardless of
+   whether we're using the index or psymtabs.  */
+
+static struct symtab *
+get_symtab (struct dwarf2_per_cu_data *per_cu)
+{
+  return (dwarf2_per_objfile->using_index
+	  ? per_cu->v.quick->symtab
+	  : per_cu->v.psymtab->symtab);
+}
+
+/* A helper function for computing the list of all symbol tables
+   included by PER_CU.  */
+
+static void
+recursively_compute_inclusions (VEC (dwarf2_per_cu_ptr) **result,
+				htab_t all_children,
+				struct dwarf2_per_cu_data *per_cu)
+{
+  void **slot;
+  int ix;
+  struct dwarf2_per_cu_data *iter;
+
+  slot = htab_find_slot (all_children, per_cu, INSERT);
+  if (*slot != NULL)
+    {
+      /* This inclusion and its children have been processed.  */
+      return;
+    }
+
+  *slot = per_cu;
+  /* Only add a CU if it has a symbol table.  */
+  if (get_symtab (per_cu) != NULL)
+    VEC_safe_push (dwarf2_per_cu_ptr, *result, per_cu);
+
+  for (ix = 0;
+       VEC_iterate (dwarf2_per_cu_ptr, per_cu->imported_symtabs, ix, iter);
+       ++ix)
+    recursively_compute_inclusions (result, all_children, iter);
+}
+
+/* Compute the symtab 'includes' fields for the symtab related to
+   PER_CU.  */
+
+static void
+compute_symtab_includes (struct dwarf2_per_cu_data *per_cu)
+{
+  if (!VEC_empty (dwarf2_per_cu_ptr, per_cu->imported_symtabs))
+    {
+      int ix, len;
+      struct dwarf2_per_cu_data *iter;
+      VEC (dwarf2_per_cu_ptr) *result_children = NULL;
+      htab_t all_children;
+      struct symtab *symtab = get_symtab (per_cu);
+
+      /* If we don't have a symtab, we can just skip this case.  */
+      if (symtab == NULL)
+	return;
+
+      all_children = htab_create_alloc (1, htab_hash_pointer, htab_eq_pointer,
+					NULL, xcalloc, xfree);
+
+      for (ix = 0;
+	   VEC_iterate (dwarf2_per_cu_ptr, per_cu->imported_symtabs,
+			ix, iter);
+	   ++ix)
+	recursively_compute_inclusions (&result_children, all_children, iter);
+
+      /* Now we have a transitive closure of all the included CUs, so
+	 we can convert it to a list of symtabs.  */
+      len = VEC_length (dwarf2_per_cu_ptr, result_children);
+      symtab->includes
+	= obstack_alloc (&dwarf2_per_objfile->objfile->objfile_obstack,
+			 (len + 1) * sizeof (struct symtab *));
+      for (ix = 0;
+	   VEC_iterate (dwarf2_per_cu_ptr, result_children, ix, iter);
+	   ++ix)
+	symtab->includes[ix] = get_symtab (iter);
+      symtab->includes[len] = NULL;
+
+      VEC_free (dwarf2_per_cu_ptr, result_children);
+      htab_delete (all_children);
+    }
+}
+
+/* Compute the 'includes' field for the symtabs of all the CUs we just
+   read.  */
+
+static void
+process_cu_includes (void)
+{
+  int ix;
+  struct dwarf2_per_cu_data *iter;
+
+  for (ix = 0;
+       VEC_iterate (dwarf2_per_cu_ptr, dwarf2_per_objfile->just_read_cus,
+		    ix, iter);
+       ++ix)
+    compute_symtab_includes (iter);
+
+  VEC_free (dwarf2_per_cu_ptr, dwarf2_per_objfile->just_read_cus);
+}
+
 /* Generate full symbol information for PER_CU, whose DIEs have
    already been loaded into memory.  */
 
@@ -4923,6 +5191,9 @@ process_full_comp_unit (struct dwarf2_per_cu_data *per_cu)
       pst->readin = 1;
     }
 
+  /* Push it for inclusion processing later.  */
+  VEC_safe_push (dwarf2_per_cu_ptr, dwarf2_per_objfile->just_read_cus, per_cu);
+
   do_cleanups (back_to);
 }
 
@@ -5005,6 +5276,31 @@ process_die (struct die_info *die, struct dwarf2_cu *cu)
 		   dwarf_tag_name (die->tag));
       read_import_statement (die, cu);
       break;
+
+    case DW_TAG_imported_unit:
+      {
+	struct attribute *attr;
+
+	attr = dwarf2_attr (die, DW_AT_import, cu);
+	if (attr != NULL)
+	  {
+	    struct dwarf2_per_cu_data *per_cu;
+	    struct symtab *imported_symtab;
+	    sect_offset offset;
+
+	    offset = dwarf2_get_ref_die_offset (attr);
+	    per_cu = dwarf2_find_containing_comp_unit (offset, cu->objfile);
+
+	    /* Queue the unit, if needed.  */
+	    if (maybe_queue_comp_unit (cu, per_cu))
+	      load_full_comp_unit (per_cu);
+
+	    VEC_safe_push (dwarf2_per_cu_ptr, cu->per_cu->imported_symtabs,
+			   per_cu);
+	  }
+      }
+      break;
+
     default:
       new_symbol (die, NULL, cu);
       break;
@@ -16467,6 +16763,10 @@ dwarf2_per_objfile_free (struct objfile *objfile, void *d)
        ++ix)
     munmap_section_buffer (section);
 
+  for (ix = 0; ix < dwarf2_per_objfile->n_comp_units; ++ix)
+    VEC_free (dwarf2_per_cu_ptr,
+	      dwarf2_per_objfile->all_comp_units[ix]->imported_symtabs);
+
   VEC_free (dwarf2_section_info_def, data->types);
 }
 
-- 
1.7.7.6



More information about the Gdb-patches mailing list