* [7/10] keep track of dependencies
@ 2012-04-25 18:56 Tom Tromey
2012-04-26 20:33 ` Jan Kratochvil
` (2 more replies)
0 siblings, 3 replies; 6+ messages in thread
From: Tom Tromey @ 2012-04-25 18:56 UTC (permalink / raw)
To: gdb-patches
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 ();
}
\f
/* 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
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [7/10] keep track of dependencies
2012-04-25 18:56 [7/10] keep track of dependencies Tom Tromey
@ 2012-04-26 20:33 ` Jan Kratochvil
2012-05-10 15:50 ` Tom Tromey
2012-05-10 20:13 ` Tom Tromey
2012-05-10 20:14 ` Tom Tromey
2 siblings, 1 reply; 6+ messages in thread
From: Jan Kratochvil @ 2012-04-26 20:33 UTC (permalink / raw)
To: Tom Tromey; +Cc: gdb-patches
On Wed, 25 Apr 2012 20:54:11 +0200, Tom Tromey wrote:
> @@ -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. */
Maybe to describe also its lifetime / usage.
/* Once it is filled in by scan_partial_symbols and freed by
process_psymtab_comp_unit to compute partial_symtab->dependencies, if
psymtabs are in use. It is also filled in by process_die and freed by
compute_symtab_includes to compute symtab->includes. */
> + VEC (dwarf2_per_cu_ptr) *imported_symtabs;
> };
>
> /* Entry in the signatured_types hash table. */
[...]
> +/* 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;
I think the variable name 'user' is confusing here - being exactly the
opposite. USER (matching INCLUDED) is being used by USING_PSYMTAB here.
I hope I did not mess the wording.
> +
> + 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 *));
I think here should be one more parentheses according to GCS.
> + 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. */
>
[...]
> +/* 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)
Why is RESULT_CHILDREN used here at all? Would not it be sufficient to just
call htab_traverse for ALL_CHILDREN?
> + symtab->includes[ix] = get_symtab (iter);
> + symtab->includes[len] = NULL;
> +
> + VEC_free (dwarf2_per_cu_ptr, result_children);
> + htab_delete (all_children);
> + }
> +}
[...]
> @@ -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:
process_die only calls functions in general, it would be nice to put this
block into a new function.
> + {
> + 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;
Thanks,
Jan
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [7/10] keep track of dependencies
2012-04-26 20:33 ` Jan Kratochvil
@ 2012-05-10 15:50 ` Tom Tromey
2012-05-11 14:41 ` Jan Kratochvil
0 siblings, 1 reply; 6+ messages in thread
From: Tom Tromey @ 2012-05-10 15:50 UTC (permalink / raw)
To: Jan Kratochvil; +Cc: gdb-patches
>>>>> "Jan" == Jan Kratochvil <jan.kratochvil@redhat.com> writes:
I made most of the changes you pointed out in this review.
Thanks.
[...]
Jan> Why is RESULT_CHILDREN used here at all? Would not it be
Jan> sufficient to just call htab_traverse for ALL_CHILDREN?
Maybe it isn't a great reason, but it lets us easily avoid adding CUs
without symbol tables. See recursively_compute_inclusions:
if (get_symtab (per_cu) != NULL)
VEC_safe_push (dwarf2_per_cu_ptr, *result, per_cu);
So, RESULT_CHILDREN and ALL_CHILDREN do not have identical contents.
Tom
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [7/10] keep track of dependencies
2012-04-25 18:56 [7/10] keep track of dependencies Tom Tromey
2012-04-26 20:33 ` Jan Kratochvil
@ 2012-05-10 20:13 ` Tom Tromey
2012-05-10 20:14 ` Tom Tromey
2 siblings, 0 replies; 6+ messages in thread
From: Tom Tromey @ 2012-05-10 20:13 UTC (permalink / raw)
To: gdb-patches
>>>>> "Tom" == Tom Tromey <tromey@redhat.com> writes:
Tom> This patch introduces the dependency-tracking code for psymtabs and
Tom> symtabs.
This patch changed a little while rebasing it on top of the Fission
series.
I'm going to put it into the big final commit, but here it is split out
for easier reading.
Tom
From e63a675d1fa95ec6a12d3f84e31bab2273098204 Mon Sep 17 00:00:00 2001
From: Tom Tromey <tromey@redhat.com>
Date: Tue, 17 Apr 2012 05:20:56 -0600
Subject: [PATCH 07/10] make each partial unit into a psymtab and then a
symtab
* dwarf2read.c (struct dwarf2_per_cu_data) <psymtab>: Update
comment.
(struct partial_die_info) <locdesc>: Remove.
<d>: New field.
(process_psymtab_comp_unit): Add 'read_partial' argument.
Update.
(process_type_comp_unit, dwarf2_build_psymtabs_hard): Update.
(scan_partial_symbols): Handle DW_TAG_imported_unit.
(add_partial_symbol): Update.
(process_die): Handle DW_TAG_partial_unit.
(read_file_scope): Update comment.
(load_partial_dies): Handle DW_TAG_imported_unit.
(read_partial_die): Handle DW_TAG_partial_unit, DW_AT_import.
(determine_prefix, dwarf2_name): Handle DW_TAG_partial_unit.
---
gdb/dwarf2read.c | 73 ++++++++++++++++++++++++++++++++++++++++--------------
1 files changed, 54 insertions(+), 19 deletions(-)
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index 8964b00..d34c048 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -483,8 +483,7 @@ struct dwarf2_per_cu_data
union
{
/* The partial symbol table associated with this compilation unit,
- or NULL for partial units (which do not have an associated
- symtab). */
+ or NULL for unread partial units. */
struct partial_symtab *psymtab;
/* Data needed by the "quick" functions. */
@@ -695,8 +694,15 @@ struct partial_die_info
when this compilation unit leaves the cache. */
char *scope;
- /* The location description associated with this DIE, if any. */
- struct dwarf_block *locdesc;
+ /* Some data associated with the partial DIE. The tag determines
+ which field is live. */
+ union
+ {
+ /* The location description associated with this DIE, if any. */
+ struct dwarf_block *locdesc;
+ /* The offset of an import, for DW_TAG_imported_unit. */
+ sect_offset offset;
+ } d;
/* If HAS_PC_INFO, the PC range associated with this DIE. */
CORE_ADDR lowpc;
@@ -1407,7 +1413,7 @@ static void init_cutu_and_read_dies_simple
static htab_t allocate_signatured_type_table (struct objfile *objfile);
-static void process_psymtab_comp_unit (struct dwarf2_per_cu_data *);
+static void process_psymtab_comp_unit (struct dwarf2_per_cu_data *, int);
static htab_t allocate_dwo_unit_table (struct objfile *objfile);
@@ -4014,8 +4020,11 @@ process_psymtab_comp_unit_reader (const struct die_reader_specs *reader,
struct partial_symtab *pst;
int has_pc_info;
const char *filename;
+ int *want_partial_unit_ptr = data;
- if (comp_unit_die->tag == DW_TAG_partial_unit)
+ if (comp_unit_die->tag == DW_TAG_partial_unit
+ && (want_partial_unit_ptr == NULL
+ || !*want_partial_unit_ptr))
return;
prepare_one_comp_unit (cu, comp_unit_die);
@@ -4117,7 +4126,8 @@ process_psymtab_comp_unit_reader (const struct die_reader_specs *reader,
Process compilation unit THIS_CU for a psymtab. */
static void
-process_psymtab_comp_unit (struct dwarf2_per_cu_data *this_cu)
+process_psymtab_comp_unit (struct dwarf2_per_cu_data *this_cu,
+ int want_partial_unit)
{
/* If this compilation unit was already read in, free the
cached copy in order to read it in again. This is
@@ -4129,7 +4139,7 @@ process_psymtab_comp_unit (struct dwarf2_per_cu_data *this_cu)
gdb_assert (! this_cu->is_debug_types);
init_cutu_and_read_dies (this_cu, 0, 0, process_psymtab_comp_unit_reader,
- NULL);
+ &want_partial_unit);
/* Age out any secondary CUs. */
age_cached_comp_units ();
@@ -4220,7 +4230,7 @@ dwarf2_build_psymtabs_hard (struct objfile *objfile)
{
struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i);
- process_psymtab_comp_unit (per_cu);
+ process_psymtab_comp_unit (per_cu, 0);
}
objfile->psymtabs_addrmap = addrmap_create_fixed (objfile->psymtabs_addrmap,
@@ -4350,7 +4360,8 @@ scan_partial_symbols (struct partial_die_info *first_die, CORE_ADDR *lowpc,
enums. */
if (pdi->name != NULL || pdi->tag == DW_TAG_namespace
- || pdi->tag == DW_TAG_module || pdi->tag == DW_TAG_enumeration_type)
+ || pdi->tag == DW_TAG_module || pdi->tag == DW_TAG_enumeration_type
+ || pdi->tag == DW_TAG_imported_unit)
{
switch (pdi->tag)
{
@@ -4390,6 +4401,18 @@ scan_partial_symbols (struct partial_die_info *first_die, CORE_ADDR *lowpc,
case DW_TAG_module:
add_partial_module (pdi, lowpc, highpc, need_pc, cu);
break;
+ case DW_TAG_imported_unit:
+ {
+ struct dwarf2_per_cu_data *per_cu;
+
+ per_cu = dwarf2_find_containing_comp_unit (pdi->d.offset,
+ cu->objfile);
+
+ /* Go read the partial unit, if needed. */
+ if (per_cu->v.psymtab == NULL)
+ process_psymtab_comp_unit (per_cu, 1);
+ }
+ break;
default:
break;
}
@@ -4598,10 +4621,10 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu)
}
break;
case DW_TAG_variable:
- if (pdi->locdesc)
- addr = decode_locdesc (pdi->locdesc, cu);
+ if (pdi->d.locdesc)
+ addr = decode_locdesc (pdi->d.locdesc, cu);
- if (pdi->locdesc
+ if (pdi->d.locdesc
&& addr == 0
&& !dwarf2_per_objfile->has_section_at_zero)
{
@@ -4625,7 +4648,7 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu)
used by GDB, but it comes in handy for debugging partial symbol
table building. */
- if (pdi->locdesc || pdi->has_type)
+ if (pdi->d.locdesc || pdi->has_type)
add_psymbol_to_list (actual_name, strlen (actual_name),
built_actual_name,
VAR_DOMAIN, LOC_STATIC,
@@ -4636,7 +4659,7 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu)
else
{
/* Static Variable. Skip symbols without location descriptors. */
- if (pdi->locdesc == NULL)
+ if (pdi->d.locdesc == NULL)
{
if (built_actual_name)
xfree (actual_name);
@@ -5484,6 +5507,7 @@ process_die (struct die_info *die, struct dwarf2_cu *cu)
case DW_TAG_padding:
break;
case DW_TAG_compile_unit:
+ case DW_TAG_partial_unit:
read_file_scope (die, cu);
break;
case DW_TAG_type_unit:
@@ -6226,7 +6250,7 @@ handle_DW_AT_stmt_list (struct die_info *die, struct dwarf2_cu *cu,
}
}
-/* Process DW_TAG_compile_unit. */
+/* Process DW_TAG_compile_unit or DW_TAG_partial_unit. */
static void
read_file_scope (struct die_info *die, struct dwarf2_cu *cu)
@@ -10688,7 +10712,8 @@ load_partial_dies (const struct die_reader_specs *reader,
&& abbrev->tag != DW_TAG_variable
&& abbrev->tag != DW_TAG_namespace
&& abbrev->tag != DW_TAG_module
- && abbrev->tag != DW_TAG_member)
+ && abbrev->tag != DW_TAG_member
+ && abbrev->tag != DW_TAG_imported_unit)
{
/* Otherwise we skip to the next sibling, if any. */
info_ptr = skip_one_die (reader, info_ptr + bytes_read, abbrev);
@@ -10906,6 +10931,7 @@ read_partial_die (const struct die_reader_specs *reader,
switch (part_die->tag)
{
case DW_TAG_compile_unit:
+ case DW_TAG_partial_unit:
case DW_TAG_type_unit:
/* Compilation units have a DW_AT_name that is a filename, not
a source language identifier. */
@@ -10950,7 +10976,7 @@ read_partial_die (const struct die_reader_specs *reader,
/* Support the .debug_loc offsets. */
if (attr_form_is_block (&attr))
{
- part_die->locdesc = DW_BLOCK (&attr);
+ part_die->d.locdesc = DW_BLOCK (&attr);
}
else if (attr_form_is_section_offset (&attr))
{
@@ -11019,6 +11045,12 @@ read_partial_die (const struct die_reader_specs *reader,
|| DW_UNSND (&attr) == DW_INL_declared_inlined)
part_die->may_be_inlined = 1;
break;
+
+ case DW_AT_import:
+ if (part_die->tag == DW_TAG_imported_unit)
+ part_die->d.offset = dwarf2_get_ref_die_offset (&attr);
+ break;
+
default:
break;
}
@@ -14021,6 +14053,7 @@ determine_prefix (struct die_info *die, struct dwarf2_cu *cu)
So it does not need a prefix. */
return "";
case DW_TAG_compile_unit:
+ case DW_TAG_partial_unit:
/* gcc-4.5 -gdwarf-4 can drop the enclosing namespace. Cope. */
if (cu->language == language_cplus
&& !VEC_empty (dwarf2_section_info_def, dwarf2_per_objfile->types)
@@ -14141,6 +14174,7 @@ dwarf2_name (struct die_info *die, struct dwarf2_cu *cu)
switch (die->tag)
{
case DW_TAG_compile_unit:
+ case DW_TAG_partial_unit:
/* Compilation units have a DW_AT_name that is a filename, not
a source language identifier. */
case DW_TAG_enumeration_type:
@@ -14174,7 +14208,8 @@ dwarf2_name (struct die_info *die, struct dwarf2_cu *cu)
if (die->tag == DW_TAG_class_type)
return dwarf2_name (die, cu);
}
- while (die->tag != DW_TAG_compile_unit);
+ while (die->tag != DW_TAG_compile_unit
+ && die->tag != DW_TAG_partial_unit);
}
break;
--
1.7.7.6
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [7/10] keep track of dependencies
2012-04-25 18:56 [7/10] keep track of dependencies Tom Tromey
2012-04-26 20:33 ` Jan Kratochvil
2012-05-10 20:13 ` Tom Tromey
@ 2012-05-10 20:14 ` Tom Tromey
2 siblings, 0 replies; 6+ messages in thread
From: Tom Tromey @ 2012-05-10 20:14 UTC (permalink / raw)
To: gdb-patches
>>>>> "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 ();
}
\f
/* 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
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [7/10] keep track of dependencies
2012-05-10 15:50 ` Tom Tromey
@ 2012-05-11 14:41 ` Jan Kratochvil
0 siblings, 0 replies; 6+ messages in thread
From: Jan Kratochvil @ 2012-05-11 14:41 UTC (permalink / raw)
To: Tom Tromey; +Cc: gdb-patches
On Thu, 10 May 2012 17:50:01 +0200, Tom Tromey wrote:
> Jan> Why is RESULT_CHILDREN used here at all? Would not it be
> Jan> sufficient to just call htab_traverse for ALL_CHILDREN?
>
> Maybe it isn't a great reason, but it lets us easily avoid adding CUs
> without symbol tables. See recursively_compute_inclusions:
>
> if (get_symtab (per_cu) != NULL)
> VEC_safe_push (dwarf2_per_cu_ptr, *result, per_cu);
>
> So, RESULT_CHILDREN and ALL_CHILDREN do not have identical contents.
The 'get_symtab (per_cu) != NULL' conditional evaluation is "zero-cost", it
can be moved to the RESULT_CHILDREN processing (therefore to unify it as
ALL_CHILDREN processing), just one has to do one pre-scan instead of just
VEC_length.
Thanks,
Jan
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2012-05-11 14:41 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-04-25 18:56 [7/10] keep track of dependencies Tom Tromey
2012-04-26 20:33 ` Jan Kratochvil
2012-05-10 15:50 ` Tom Tromey
2012-05-11 14:41 ` Jan Kratochvil
2012-05-10 20:13 ` Tom Tromey
2012-05-10 20:14 ` Tom Tromey
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox