This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
[3/10] introduce psymtab users
- From: Tom Tromey <tromey at redhat dot com>
- To: gdb-patches at sourceware dot org
- Date: Wed, 25 Apr 2012 12:21:23 -0600
- Subject: [3/10] introduce psymtab users
Adding support for imported PUs means modifying both symtabs and
psymtabs to understand the inclusions.
This patch adds some basic infrastructure to psymtabs. It adds a
"users" field which the psymtab readers can set. Then, it changes the
psymtab code to handle included psymtabs properly.
There are a few cases to consider. I did this by auditing all the code
in psymtab.c.
When doing lookups using the file name, we can just ignore PUs.
When doing a lookup by name or by PC, it is ok to find a PU. However,
we have a rule that we can only expand a full CU, so we modify
psymtab_to_symtab to find a user (any will do) of the PU.
Then, finally, there is some hair in expand_symtabs_matching_via_partial
to search PUs while searching CUs.
This patch has no immediate effect, because no psymtab readers are
updated yet.
Tom
>From 9d29b92217dd4e363d88f7cbc357d4cf9d28e51b Mon Sep 17 00:00:00 2001
From: Tom Tromey <tromey@redhat.com>
Date: Wed, 18 Apr 2012 14:49:36 -0600
Subject: [PATCH 03/10] introduce psymtab users notion
* psymtab.c (partial_map_expand_apply): Add assertion.
(partial_map_symtabs_matching_filename): Skip included psymtabs.
(psymtab_to_symtab): Find unshared psymtab.
(dump_psymtab): Print including psymtabs.
(PST_NOT_SEARCHED, PST_SEARCHED_AND_FOUND)
(PST_SEARCHED_AND_NOT_FOUND): New constants.
(recursively_search_psymtabs): New function.
(expand_symtabs_matching_via_partial): Use it.
* psympriv.h (struct partial_symtab) <users, searched_flag>: New
fields.
---
gdb/psympriv.h | 29 +++++++++
gdb/psymtab.c | 177 +++++++++++++++++++++++++++++++++++++++++--------------
2 files changed, 161 insertions(+), 45 deletions(-)
diff --git a/gdb/psympriv.h b/gdb/psympriv.h
index df7b874..5515d6c 100644
--- a/gdb/psympriv.h
+++ b/gdb/psympriv.h
@@ -111,6 +111,31 @@ struct partial_symtab
int number_of_dependencies;
+ /* If NULL, this is an ordinary partial symbol table.
+
+ If non-NULL, this holds a NULL-terminated vector of includers of
+ this partial symbol table, and this partial symbol table is a
+ shared one.
+
+ A shared psymtab is one that is referenced by multiple other
+ psymtabs, and which conceptually has its contents directly
+ included in those.
+
+ Shared psymtabs have special semantics. When a search finds a
+ symbol in a shared table, we instead return one of the non-shared
+ tables that include this one.
+
+ A shared psymtabs can be referred to by other shared ones.
+
+ The psymtabs that refer to a shared psymtab will list the shared
+ psymtab in their 'dependencies' array.
+
+ In DWARF terms, a shared psymtab is a DW_TAG_partial_unit; but
+ of course using a name based on that would be too confusing, so
+ "shared" was chosen instead. */
+
+ struct partial_symtab **users;
+
/* Global symbol list. This list will be sorted after readin to
improve access. Binary search will be the usual method of
finding a symbol within it. globals_offset is an integer offset
@@ -142,6 +167,10 @@ struct partial_symtab
unsigned char psymtabs_addrmap_supported;
+ /* A flag that is temporarily used when searching psymtabs. */
+
+ unsigned char searched_flag;
+
/* Pointer to symtab eventually allocated for this source file, 0 if
!readin or if we haven't looked for the symtab after it was readin. */
diff --git a/gdb/psymtab.c b/gdb/psymtab.c
index 9620de8..9e64275 100644
--- a/gdb/psymtab.c
+++ b/gdb/psymtab.c
@@ -135,6 +135,10 @@ partial_map_expand_apply (struct objfile *objfile,
{
struct symtab *last_made = objfile->symtabs;
+ /* Shared psymtabs should never be seen here. Instead they should
+ be handled properly by the caller. */
+ gdb_assert (pst->users == NULL);
+
/* Don't visit already-expanded psymtabs. */
if (pst->readin)
return 0;
@@ -165,6 +169,11 @@ partial_map_symtabs_matching_filename (struct objfile *objfile,
ALL_OBJFILE_PSYMTABS_REQUIRED (objfile, pst)
{
+ /* We can skip shared psymtabs here, because any file name will be
+ attached to the unshared psymtab. */
+ if (pst->users != NULL)
+ continue;
+
if (FILENAME_CMP (name, pst->filename) == 0
|| (!is_abs && compare_filenames_for_search (pst->filename,
name, name_len)))
@@ -760,6 +769,11 @@ lookup_partial_symbol (struct partial_symtab *pst, const char *name,
static struct symtab *
psymtab_to_symtab (struct partial_symtab *pst)
{
+ /* If it is a shared psymtab, find an unshared psymtab that includes
+ it. Any such psymtab will do. */
+ while (pst->users != NULL)
+ pst = pst->users[0];
+
/* If it's been looked up before, return it. */
if (pst->symtab)
return pst->symtab;
@@ -1000,6 +1014,16 @@ dump_psymtab (struct objfile *objfile, struct partial_symtab *psymtab,
fprintf_filtered (outfile, " %s\n",
psymtab->dependencies[i]->filename);
}
+ if (psymtab->users != NULL)
+ {
+ fprintf_filtered (outfile, " Shared partial symtab with users:\n");
+ for (i = 0; psymtab->users[i] != NULL; ++i)
+ {
+ fprintf_filtered (outfile, " ");
+ gdb_print_host_address (psymtab->users[i], outfile);
+ fprintf_filtered (outfile, "\n");
+ }
+ }
if (psymtab->n_global_syms > 0)
{
print_partial_symbols (gdbarch,
@@ -1236,6 +1260,102 @@ map_matching_symbols_psymtab (const char *name, domain_enum namespace,
}
}
+/* A convenience enum to give names to some constants used in
+ recursively_search_psymtabs. */
+
+enum
+ {
+ PST_NOT_SEARCHED,
+ PST_SEARCHED_AND_FOUND,
+ PST_SEARCHED_AND_NOT_FOUND
+ };
+
+/* A helper for expand_symtabs_matching_via_partial that handles
+ searching included psymtabs. */
+
+static int
+recursively_search_psymtabs (struct partial_symtab *ps,
+ struct objfile *objfile,
+ enum search_domain kind,
+ int (*name_matcher) (const char *, void *),
+ void *data)
+{
+ struct partial_symbol **psym;
+ struct partial_symbol **bound, **gbound, **sbound;
+ int keep_going = 1;
+ int result = PST_SEARCHED_AND_NOT_FOUND;
+ int i;
+
+ if (ps->searched_flag != PST_NOT_SEARCHED)
+ return ps->searched_flag == PST_SEARCHED_AND_FOUND;
+
+ /* Recurse into shared psymtabs first, because they may have already
+ been searched, and this could save some time. */
+ for (i = 0; i < ps->number_of_dependencies; ++i)
+ {
+ int r;
+
+ /* Skip non-shared dependencies, these are handled elsewhere. */
+ if (ps->dependencies[i]->users == NULL)
+ continue;
+
+ r = recursively_search_psymtabs (ps->dependencies[i],
+ objfile, kind, name_matcher, data);
+ if (r != 0)
+ {
+ ps->searched_flag = PST_SEARCHED_AND_FOUND;
+ return 1;
+ }
+ }
+
+ gbound = (objfile->global_psymbols.list
+ + ps->globals_offset + ps->n_global_syms);
+ sbound = (objfile->static_psymbols.list
+ + ps->statics_offset + ps->n_static_syms);
+ bound = gbound;
+
+ /* Go through all of the symbols stored in a partial
+ symtab in one loop. */
+ psym = objfile->global_psymbols.list + ps->globals_offset;
+ while (keep_going)
+ {
+ if (psym >= bound)
+ {
+ if (bound == gbound && ps->n_static_syms != 0)
+ {
+ psym = objfile->static_psymbols.list + ps->statics_offset;
+ bound = sbound;
+ }
+ else
+ keep_going = 0;
+ continue;
+ }
+ else
+ {
+ QUIT;
+
+ if ((kind == ALL_DOMAIN
+ || (kind == VARIABLES_DOMAIN
+ && SYMBOL_CLASS (*psym) != LOC_TYPEDEF
+ && SYMBOL_CLASS (*psym) != LOC_BLOCK)
+ || (kind == FUNCTIONS_DOMAIN
+ && SYMBOL_CLASS (*psym) == LOC_BLOCK)
+ || (kind == TYPES_DOMAIN
+ && SYMBOL_CLASS (*psym) == LOC_TYPEDEF))
+ && (*name_matcher) (SYMBOL_SEARCH_NAME (*psym), data))
+ {
+ /* Found a match, so notify our caller. */
+ result = PST_SEARCHED_AND_FOUND;
+ keep_going = 0;
+ }
+ }
+ psym++;
+ }
+
+ ps->searched_flag = result;
+ return result == PST_SEARCHED_AND_FOUND;
+}
+
static void
expand_symtabs_matching_via_partial
(struct objfile *objfile,
@@ -1246,60 +1366,27 @@ expand_symtabs_matching_via_partial
{
struct partial_symtab *ps;
+ /* Clear the search flags. */
ALL_OBJFILE_PSYMTABS_REQUIRED (objfile, ps)
{
- struct partial_symbol **psym;
- struct partial_symbol **bound, **gbound, **sbound;
- int keep_going = 1;
+ ps->searched_flag = PST_NOT_SEARCHED;
+ }
+ ALL_OBJFILE_PSYMTABS_REQUIRED (objfile, ps)
+ {
if (ps->readin)
continue;
- if (file_matcher && ! (*file_matcher) (ps->filename, data))
+ /* We skip shared psymtabs because file-matching doesn't apply
+ to them; but we search them later in the loop. */
+ if (ps->users != NULL)
continue;
- gbound = objfile->global_psymbols.list
- + ps->globals_offset + ps->n_global_syms;
- sbound = objfile->static_psymbols.list
- + ps->statics_offset + ps->n_static_syms;
- bound = gbound;
+ if (file_matcher && ! (*file_matcher) (ps->filename, data))
+ continue;
- /* Go through all of the symbols stored in a partial
- symtab in one loop. */
- psym = objfile->global_psymbols.list + ps->globals_offset;
- while (keep_going)
- {
- if (psym >= bound)
- {
- if (bound == gbound && ps->n_static_syms != 0)
- {
- psym = objfile->static_psymbols.list + ps->statics_offset;
- bound = sbound;
- }
- else
- keep_going = 0;
- continue;
- }
- else
- {
- QUIT;
-
- if ((kind == ALL_DOMAIN
- || (kind == VARIABLES_DOMAIN
- && SYMBOL_CLASS (*psym) != LOC_TYPEDEF
- && SYMBOL_CLASS (*psym) != LOC_BLOCK)
- || (kind == FUNCTIONS_DOMAIN
- && SYMBOL_CLASS (*psym) == LOC_BLOCK)
- || (kind == TYPES_DOMAIN
- && SYMBOL_CLASS (*psym) == LOC_TYPEDEF))
- && (*name_matcher) (SYMBOL_SEARCH_NAME (*psym), data))
- {
- psymtab_to_symtab (ps);
- keep_going = 0;
- }
- }
- psym++;
- }
+ if (recursively_search_psymtabs (ps, objfile, kind, name_matcher, data))
+ psymtab_to_symtab (ps);
}
}
--
1.7.7.6