From 9439a077bef75279f4881cabc3adbe61cf057504 Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Thu, 10 May 2012 19:54:45 +0000 Subject: [PATCH] * 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) : New fields. (enum psymtab_search_status): New. --- gdb/ChangeLog | 12 ++++ gdb/psympriv.h | 44 +++++++++++++ gdb/psymtab.c | 165 +++++++++++++++++++++++++++++++++++-------------- 3 files changed, 176 insertions(+), 45 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index f62a45fb80d..151c515a6db 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,15 @@ +2012-05-10 Tom Tromey + + * 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) : New + fields. + (enum psymtab_search_status): New. + 2012-05-10 Tom Tromey * tracepoint.c (scope_info): Update. diff --git a/gdb/psympriv.h b/gdb/psympriv.h index df7b874e074..370ce86b315 100644 --- a/gdb/psympriv.h +++ b/gdb/psympriv.h @@ -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. */ diff --git a/gdb/psymtab.c b/gdb/psymtab.c index 9620de8bd35..814023e894a 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); } } -- 2.30.2