This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
Re: [7/10] keep track of dependencies
- From: Tom Tromey <tromey at redhat dot com>
- To: gdb-patches at sourceware dot org
- Date: Thu, 10 May 2012 14:14:11 -0600
- Subject: Re: [7/10] keep track of dependencies
- References: <87zk9zabho.fsf@fleche.redhat.com>
>>>>> "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