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]

Re: [7/10] keep track of dependencies


>>>>> "Tom" == Tom Tromey <tromey@redhat.com> writes:

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

Oops, I attached the wrong patch in my last mail.  Sigh -- renumbering
was not a great idea :)

Here it is again.

I also neglected to mention that this version takes Jan's comments into
account.

Tom

>From 57377dc9e08b5a163bf4841f431e0cf393e9f3e4 Mon Sep 17 00:00:00 2001
From: Tom Tromey <tromey@redhat.com>
Date: Mon, 23 Apr 2012 12:19:58 -0600
Subject: [PATCH 08/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.
	(set_partial_user): New function.
	(dwarf2_build_psymtabs_hard): Use set_partial_user.
	(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)
	(process_imported_unit_die): New functions.
	(process_die) <DW_TAG_imported_unit>: New case.
	(dwarf2_per_objfile_free): Free 'imported_symtabs'.
---
 gdb/dwarf2read.c |  224 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 221 insertions(+), 3 deletions(-)

diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index d34c048..ff1babd 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -148,6 +148,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.  */
 
@@ -221,6 +224,9 @@ struct dwarf2_per_objfile
      This is NULL if not allocated yet.
      The mapping is done via (CU/TU signature + DIE offset) -> type.  */
   htab_t die_type_hash;
+
+  /* The CUs we recently read.  */
+  VEC (dwarf2_per_cu_ptr) *just_read_cus;
 };
 
 static struct dwarf2_per_objfile *dwarf2_per_objfile;
@@ -489,6 +495,12 @@ 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.  This is filled in
+     while reading psymtabs, used to compute the psymtab dependencies,
+     and then cleared.  Then it is filled in again while reading full
+     symbols, and only deleted when the objfile is destroyed.  */
+  VEC (dwarf2_per_cu_ptr) *imported_symtabs;
 };
 
 /* Entry in the signatured_types hash table.  */
@@ -1389,6 +1401,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,
@@ -1427,6 +1442,8 @@ static void free_dwo_file_cleanup (void *);
 
 static void munmap_section_buffer (struct dwarf2_section_info *);
 
+static void process_cu_includes (void);
+
 #if WORDS_BIGENDIAN
 
 /* Convert VALUE between big- and little-endian.  */
@@ -1948,9 +1965,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 ();
 
@@ -1968,11 +1989,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;
@@ -4109,6 +4132,26 @@ process_psymtab_comp_unit_reader (const struct die_reader_specs *reader,
     (objfile->static_psymbols.list + pst->statics_offset);
   sort_pst_symbols (pst);
 
+  if (!VEC_empty (dwarf2_per_cu_ptr, cu->per_cu->imported_symtabs))
+    {
+      int i;
+      int len = VEC_length (dwarf2_per_cu_ptr, cu->per_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, cu->per_cu->imported_symtabs,
+			i, iter);
+	   ++i)
+	pst->dependencies[i] = iter->v.psymtab;
+
+      VEC_free (dwarf2_per_cu_ptr, cu->per_cu->imported_symtabs);
+    }
+
   if (per_cu->is_debug_types)
     {
       /* It's not clear we want to do anything with stmt lists here.
@@ -4197,6 +4240,28 @@ psymtabs_addrmap_cleanup (void *o)
   objfile->psymtabs_addrmap = NULL;
 }
 
+/* Compute the 'user' field for each psymtab in OBJFILE.  */
+
+static void
+set_partial_user (struct objfile *objfile)
+{
+  int i;
+
+  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)
+	{
+	  /* Set the 'user' field only if it is not already set.  */
+	  if (pst->dependencies[j]->user == NULL)
+	    pst->dependencies[j]->user = pst;
+	}
+    }
+}
+
 /* Build the partial symbol table by doing a quick pass through the
    .debug_info and .debug_abbrev sections.  */
 
@@ -4233,6 +4298,8 @@ dwarf2_build_psymtabs_hard (struct objfile *objfile)
       process_psymtab_comp_unit (per_cu, 0);
     }
 
+  set_partial_user (objfile);
+
   objfile->psymtabs_addrmap = addrmap_create_fixed (objfile->psymtabs_addrmap,
 						    &objfile->objfile_obstack);
   discard_cleanups (addrmap_cleanup);
@@ -4411,6 +4478,9 @@ scan_partial_symbols (struct partial_die_info *first_die, CORE_ADDR *lowpc,
 		/* Go read the partial unit, if needed.  */
 		if (per_cu->v.psymtab == NULL)
 		  process_psymtab_comp_unit (per_cu, 1);
+
+		VEC_safe_push (dwarf2_per_cu_ptr, cu->per_cu->imported_symtabs,
+			       per_cu);
 	      }
 	      break;
 	    default:
@@ -5102,6 +5172,8 @@ dwarf2_psymtab_to_symtab (struct partial_symtab *pst)
 	    printf_filtered (_("done.\n"));
 	}
     }
+
+  process_cu_includes ();
 }
 
 /* Reading in full CUs.  */
@@ -5188,6 +5260,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)
       {
@@ -5413,6 +5488,111 @@ fixup_go_packaging (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.  */
 
@@ -5494,9 +5674,38 @@ 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);
 }
 
+/* Process an imported unit DIE.  */
+
+static void
+process_imported_unit_die (struct die_info *die, struct dwarf2_cu *cu)
+{
+  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);
+    }
+}
+
 /* Process a die and its children.  */
 
 static void
@@ -5576,6 +5785,11 @@ 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:
+      process_imported_unit_die (die, cu);
+      break;
+
     default:
       new_symbol (die, NULL, cu);
       break;
@@ -16868,6 +17082,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);
 
   if (data->dwo_files)
-- 
1.7.7.6


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