aboutsummaryrefslogtreecommitdiff
path: root/gdb/psymtab.c
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/psymtab.c')
-rw-r--r--gdb/psymtab.c165
1 files changed, 120 insertions, 45 deletions
diff --git a/gdb/psymtab.c b/gdb/psymtab.c
index 9620de8..814023e 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->user == 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->user != 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->user != NULL)
+ pst = pst->user;
+
/* If it's been looked up before, return it. */
if (pst->symtab)
return pst->symtab;
@@ -1000,6 +1014,12 @@ dump_psymtab (struct objfile *objfile, struct partial_symtab *psymtab,
fprintf_filtered (outfile, " %s\n",
psymtab->dependencies[i]->filename);
}
+ if (psymtab->user != NULL)
+ {
+ fprintf_filtered (outfile, " Shared partial symtab with user ");
+ gdb_print_host_address (psymtab->user, outfile);
+ fprintf_filtered (outfile, "\n");
+ }
if (psymtab->n_global_syms > 0)
{
print_partial_symbols (gdbarch,
@@ -1236,6 +1256,94 @@ map_matching_symbols_psymtab (const char *name, domain_enum namespace,
}
}
+/* A helper for expand_symtabs_matching_via_partial that handles
+ searching included psymtabs. This returns 1 if a symbol is found,
+ and zero otherwise. It also updates the 'searched_flag' on the
+ various psymtabs that it searches. */
+
+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]->user == 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 +1354,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->user != 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);
}
}