[gdb] Expand symbolless symtabs using maint expand-symtabs Consider this test-case, consisting of header file hello.h: ... inline static const char* foo (void) { return "foo"; } ... and source file hello.c: ... int main (void) { printf ("hello: %s\n", foo ()); return 0; } ... compiled with -g: ... $ gcc hello.c -g ... When trying to expand the partial symtab for hello.h: ... $ gdb -batch \ -iex "set language c" \ a.out \ -ex "maint expand-symtabs hello.h" \ -ex "maint info psymtabs" ... we in fact find that the partial symtab has not been expanded: ... { psymtab hello.h ((struct partial_symtab *) 0x27cf070) readin no ... This is due to the recursively_search_psymtabs call in psym_expand_symtabs_matching: ... if (recursively_search_psymtabs (ps, objfile, domain, lookup_name, symbol_matcher)) ... which always returns false for symbolless partial symtabs. Fix this by passing a NULL symbol_matcher and lookup_name to expand_symtabs_matching in maintenance_expand_symtabs, and skipping the call to recursively_search_psymtabs if symbol_matcher == NULL and lookup_name == NULL. Build and tested on x86_64-linux, with native. In addition, tested test-case with target boards cc-with-gdb-index.exp, cc-with-debug-names.exp and readnow.exp. gdb/ChangeLog: 2020-03-29 Tom de Vries PR symtab/25720 * symmisc.c (maintenance_expand_symtabs): Call expand_symtabs_matching with NULL symbol_matcher and lookup_name. * psymtab.c (psym_expand_symtabs_matching): Handle NULL symbol_matcher and lookup_name. * dwarf2/read.c (dw2_expand_symtabs_matching) (dw2_debug_names_expand_symtabs_matching): Same. * symfile.h (struct quick_symbol_functions::expand_symtabs_matching): Make lookup_name a pointer. Update comment. * symtab.c (global_symbol_searcher::expand_symtabs): Handle lookup_name being a pointer. * symfile.c (expand_symtabs_matching): Same. * symfile-debug.c (debug_qf_expand_symtabs_matching): Same. * linespec.c (iterate_over_all_matching_symtabs): Same. gdb/testsuite/ChangeLog: 2020-03-29 Tom de Vries PR symtab/25720 * gdb.base/maint-expand-symbols-header-file.c: New test. * gdb.base/maint-expand-symbols-header-file.exp: New file. * gdb.base/maint-expand-symbols-header-file.h: New test. --- gdb/dwarf2/read.c | 32 +++++++++++++-- gdb/linespec.c | 2 +- gdb/psymtab.c | 10 ++--- gdb/symfile-debug.c | 2 +- gdb/symfile.c | 2 +- gdb/symfile.h | 13 +++--- gdb/symmisc.c | 8 +--- gdb/symtab.c | 2 +- .../gdb.base/maint-expand-symbols-header-file.c | 26 ++++++++++++ .../gdb.base/maint-expand-symbols-header-file.exp | 47 ++++++++++++++++++++++ .../gdb.base/maint-expand-symbols-header-file.h | 22 ++++++++++ 11 files changed, 142 insertions(+), 24 deletions(-) diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c index 1ec5c1e582..673f2c2904 100644 --- a/gdb/dwarf2/read.c +++ b/gdb/dwarf2/read.c @@ -4543,7 +4543,7 @@ static void dw2_expand_symtabs_matching (struct objfile *objfile, gdb::function_view file_matcher, - const lookup_name_info &lookup_name, + const lookup_name_info *lookup_name, gdb::function_view symbol_matcher, gdb::function_view expansion_notify, enum search_domain kind) @@ -4557,9 +4557,21 @@ dw2_expand_symtabs_matching dw_expand_symtabs_matching_file_matcher (dwarf2_per_objfile, file_matcher); + if (symbol_matcher == NULL && lookup_name == NULL) + { + for (dwarf2_per_cu_data *per_cu : dwarf2_per_objfile->all_comp_units) + { + QUIT; + + dw2_expand_symtabs_matching_one (per_cu, file_matcher, + expansion_notify); + } + return; + } + mapped_index &index = *dwarf2_per_objfile->index_table; - dw2_expand_symtabs_matching_symbol (index, lookup_name, + dw2_expand_symtabs_matching_symbol (index, *lookup_name, symbol_matcher, kind, [&] (offset_type idx) { @@ -5551,7 +5563,7 @@ static void dw2_debug_names_expand_symtabs_matching (struct objfile *objfile, gdb::function_view file_matcher, - const lookup_name_info &lookup_name, + const lookup_name_info *lookup_name, gdb::function_view symbol_matcher, gdb::function_view expansion_notify, enum search_domain kind) @@ -5565,9 +5577,21 @@ dw2_debug_names_expand_symtabs_matching dw_expand_symtabs_matching_file_matcher (dwarf2_per_objfile, file_matcher); + if (symbol_matcher == NULL && lookup_name == NULL) + { + for (dwarf2_per_cu_data *per_cu : dwarf2_per_objfile->all_comp_units) + { + QUIT; + + dw2_expand_symtabs_matching_one (per_cu, file_matcher, + expansion_notify); + } + return; + } + mapped_debug_names &map = *dwarf2_per_objfile->debug_names_table; - dw2_expand_symtabs_matching_symbol (map, lookup_name, + dw2_expand_symtabs_matching_symbol (map, *lookup_name, symbol_matcher, kind, [&] (offset_type namei) { diff --git a/gdb/linespec.c b/gdb/linespec.c index d853e02d8f..e1349e78a0 100644 --- a/gdb/linespec.c +++ b/gdb/linespec.c @@ -1149,7 +1149,7 @@ iterate_over_all_matching_symtabs if (objfile->sf) objfile->sf->qf->expand_symtabs_matching (objfile, NULL, - lookup_name, + &lookup_name, NULL, NULL, search_domain); diff --git a/gdb/psymtab.c b/gdb/psymtab.c index 56c1b68b54..1399edbfa7 100644 --- a/gdb/psymtab.c +++ b/gdb/psymtab.c @@ -1301,13 +1301,11 @@ static void psym_expand_symtabs_matching (struct objfile *objfile, gdb::function_view file_matcher, - const lookup_name_info &lookup_name_in, + const lookup_name_info *lookup_name, gdb::function_view symbol_matcher, gdb::function_view expansion_notify, enum search_domain domain) { - lookup_name_info lookup_name = lookup_name_in.make_ignore_params (); - /* Clear the search flags. */ for (partial_symtab *ps : require_partial_symbols (objfile, true)) ps->searched_flag = PST_NOT_SEARCHED; @@ -1344,8 +1342,10 @@ psym_expand_symtabs_matching continue; } - if (recursively_search_psymtabs (ps, objfile, domain, - lookup_name, symbol_matcher)) + if ((symbol_matcher == NULL && lookup_name == NULL) + || recursively_search_psymtabs (ps, objfile, domain, + lookup_name->make_ignore_params (), + symbol_matcher)) { struct compunit_symtab *symtab = psymtab_to_symtab (objfile, ps); diff --git a/gdb/symfile-debug.c b/gdb/symfile-debug.c index 53a77a5405..60489dbfa5 100644 --- a/gdb/symfile-debug.c +++ b/gdb/symfile-debug.c @@ -254,7 +254,7 @@ static void debug_qf_expand_symtabs_matching (struct objfile *objfile, gdb::function_view file_matcher, - const lookup_name_info &lookup_name, + const lookup_name_info *lookup_name, gdb::function_view symbol_matcher, gdb::function_view expansion_notify, enum search_domain kind) diff --git a/gdb/symfile.c b/gdb/symfile.c index 3b63887ce1..8b29516b4e 100644 --- a/gdb/symfile.c +++ b/gdb/symfile.c @@ -3786,7 +3786,7 @@ expand_symtabs_matching { if (objfile->sf) objfile->sf->qf->expand_symtabs_matching (objfile, file_matcher, - lookup_name, + &lookup_name, symbol_matcher, expansion_notify, kind); } diff --git a/gdb/symfile.h b/gdb/symfile.h index 85f8e7c155..68b1813ec5 100644 --- a/gdb/symfile.h +++ b/gdb/symfile.h @@ -242,11 +242,14 @@ struct quick_symbol_functions names (the passed file name is already only the lbasename'd part). - Otherwise, if KIND does not match, this symbol is skipped. + If the file is not skipped, and SYMBOL_MATCHER and LOOKUP_NAME are NULL, + the symbol table is expanded. - If even KIND matches, SYMBOL_MATCHER is called for each symbol - defined in the file. The symbol "search" name is passed to - SYMBOL_MATCHER. + Otherwise, individual symbols are considered. + + If KIND does not match, the symbol is skipped. + + If the symbol name does not match LOOKUP_NAME, the symbol is skipped. If SYMBOL_MATCHER returns false, then the symbol is skipped. @@ -254,7 +257,7 @@ struct quick_symbol_functions void (*expand_symtabs_matching) (struct objfile *objfile, gdb::function_view file_matcher, - const lookup_name_info &lookup_name, + const lookup_name_info *lookup_name, gdb::function_view symbol_matcher, gdb::function_view expansion_notify, enum search_domain kind); diff --git a/gdb/symmisc.c b/gdb/symmisc.c index bee136ed46..1076a0bcaf 100644 --- a/gdb/symmisc.c +++ b/gdb/symmisc.c @@ -977,12 +977,8 @@ maintenance_expand_symtabs (const char *args, int from_tty) return (!basenames && (regexp == NULL || re_exec (filename))); }, - lookup_name_info::match_any (), - [] (const char *symname) - { - /* Since we're not searching on symbols, just return true. */ - return true; - }, + NULL, + NULL, NULL, ALL_DOMAIN); } diff --git a/gdb/symtab.c b/gdb/symtab.c index f300d759e0..073b76db2d 100644 --- a/gdb/symtab.c +++ b/gdb/symtab.c @@ -4513,7 +4513,7 @@ global_symbol_searcher::expand_symtabs { return file_matches (filename, filenames, basenames); }, - lookup_name_info::match_any (), + &lookup_name_info::match_any (), [&] (const char *symname) { return (!preg.has_value () diff --git a/gdb/testsuite/gdb.base/maint-expand-symbols-header-file.c b/gdb/testsuite/gdb.base/maint-expand-symbols-header-file.c new file mode 100644 index 0000000000..649c5b97c5 --- /dev/null +++ b/gdb/testsuite/gdb.base/maint-expand-symbols-header-file.c @@ -0,0 +1,26 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2020 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include +#include "maint-expand-symbols-header-file.h" + +int +main (void) +{ + printf ("hello: %s\n", foo ()); + return 0; +} diff --git a/gdb/testsuite/gdb.base/maint-expand-symbols-header-file.exp b/gdb/testsuite/gdb.base/maint-expand-symbols-header-file.exp new file mode 100644 index 0000000000..85376662df --- /dev/null +++ b/gdb/testsuite/gdb.base/maint-expand-symbols-header-file.exp @@ -0,0 +1,47 @@ +# Copyright 2020 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# Test-case to verify that symbol-less symtabs are expanded by +# "maint expand-symtabs". + +standard_testfile .c + +if {[build_executable "failed to prepare" $testfile \ + $srcfile {debug nowarnings}]} { + return -1 +} + +clean_restart + +# Make sure that no symtabs are expanded, by setting language before +# loading exec. +gdb_test_no_output "set language c" +gdb_load ${binfile} + +set test "verify no symtabs are expanded" +if { [readnow] } { + unsupported $test + return -1 +} +gdb_test_no_output "maint info symtabs" $test + +# Expand the header file symtab. +gdb_test_no_output "maint expand-symtabs maint-expand-symbols-header-file.h" + +# Check that the header file symtab was in fact expanded. +set file_re "\[^\r\n\]*/maint-expand-symbols-header-file.h" +gdb_test "maint info symtabs" \ + "\r\n\t{ symtab $file_re \\(\\(struct symtab \\*\\) $hex\\)\r\n.*" \ + "check header file psymtab expansion" diff --git a/gdb/testsuite/gdb.base/maint-expand-symbols-header-file.h b/gdb/testsuite/gdb.base/maint-expand-symbols-header-file.h new file mode 100644 index 0000000000..d8d2517c7b --- /dev/null +++ b/gdb/testsuite/gdb.base/maint-expand-symbols-header-file.h @@ -0,0 +1,22 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2020 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +inline static const char* +foo (void) +{ + return "foo"; +}