* 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.
	(recursively_search_psymtabs): New function.
	(expand_symtabs_matching_via_partial): Use it.
	* psympriv.h (struct partial_symtab) <user, searched_flag>: New
	fields.
	(enum psymtab_search_status): New.
This commit is contained in:
Tom Tromey 2012-05-10 19:54:45 +00:00
parent 8157b174fd
commit 9439a077be
3 changed files with 176 additions and 45 deletions

View File

@ -1,3 +1,15 @@
2012-05-10 Tom Tromey <tromey@redhat.com>
* 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.
(recursively_search_psymtabs): New function.
(expand_symtabs_matching_via_partial): Use it.
* psympriv.h (struct partial_symtab) <user, searched_flag>: New
fields.
(enum psymtab_search_status): New.
2012-05-10 Tom Tromey <tromey@redhat.com>
* tracepoint.c (scope_info): Update.

View File

@ -54,6 +54,17 @@ struct partial_symbol
#define PSYMBOL_DOMAIN(psymbol) (psymbol)->domain
#define PSYMBOL_CLASS(psymbol) (psymbol)->aclass
/* A convenience enum to give names to some constants used when
searching psymtabs. This is internal to psymtab and should not be
used elsewhere. */
enum psymtab_search_status
{
PST_NOT_SEARCHED,
PST_SEARCHED_AND_FOUND,
PST_SEARCHED_AND_NOT_FOUND
};
/* Each source file that has not been fully read in is represented by
a partial_symtab. This contains the information on where in the
executable the debugging symbols for a specific file are, and a
@ -111,6 +122,35 @@ struct partial_symtab
int number_of_dependencies;
/* If NULL, this is an ordinary partial symbol table.
If non-NULL, this holds a single includer 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.
Only a single user is needed because, when expanding a shared
psymtab, we only need to expand its "canonical" non-shared user.
The choice of which one should be canonical is left to the
debuginfo reader; it can be arbitrary. */
struct partial_symtab *user;
/* 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 +182,10 @@ struct partial_symtab
unsigned char psymtabs_addrmap_supported;
/* A flag that is temporarily used when searching psymtabs. */
ENUM_BITFIELD (psymtab_search_status) searched_flag : 2;
/* 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. */

View File

@ -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;
/* 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;
if (file_matcher && ! (*file_matcher) (ps->filename, data))
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;
/* 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);
}
}