mirror of
https://github.com/bminor/binutils-gdb.git
synced 2025-12-09 00:53:10 +00:00
While working on some changes to 'info sources' I ran into a situation where I was seeing the same source files reported twice in the output of the 'info sources' command when using either .gdb_index or the .debug_name index. I traced the problem back to some caching in dwarf2_base_index_functions::map_symbol_filenames; when called GDB caches the set of filenames, but, filesnames are not removed as the index entries are expanded into full symtabs. As a result we can end up seeing filenames reported both from a full symtab _and_ from a (stale) previously cached index entry. Now, obviously, when seeing a problem like this the "correct" fix is to remove the stale entries from the cache, however, I ran a few experiments to see why this wasn't really hitting us anywhere, and, as far as I can tell, ::map_symbol_filenames is only called from three places: 1. The mi command -file-list-exec-source-files, 2. The 'info sources' command, and 3. Filename completion However, the result of this "bug" is that we will see duplicate filenames, and readline's completion mechanism already removes duplicates, so for case #3 we will never see any problems. Cases #1 and #2 are basically the same, and in each case, to see a problem we need to ensure we craft the test in a particular way, start up ensuring we have some unexpected symtabs, then run one of the commands to populate the cache, then expand one of the symtabs, and list the sources again. At this point you'll see duplicate entries in the results. Hardly surprising we haven't randomly hit this situation in testing. So, considering that use cases #1 and #2 are certainly not "high performance" code (i.e. I don't think these justify the need for caching) this leaves use case #3. Does this use justify the need for caching? Well the psymbol_functions::map_symbol_filenames function doesn't seem to do any extra caching, and within dwarf2_base_index_functions::map_symbol_filenames, the only expensive bit appears to be the call to dw2_get_file_names, and this already does its own caching via this_cu->v.quick->file_names. The upshot of all this analysis was that I'm not convinced the need for the additional caching is justified, and so, I propose that to fix the bug in GDB, I just remove the extra caching (for now). If we later find that the caching _was_ useful, then we can reintroduce it, but add it back such that it doesn't reintroduce this bug. As I was changing dwarf2_base_index_functions::map_symbol_filenames I replaced the use of htab_up with std::unordered_set. Tested using target_boards cc-with-debug-names and dwarf4-gdb-index. gdb/ChangeLog: * dwarf2/read.c: Add 'unordered_set' include. (dwarf2_base_index_functions::map_symbol_filenames): Replace 'visited' hash table with 'qfn_cache' unordered_set. Remove use of per_Bfd->filenames_cache cache, and use function local filenames_cache instead. Reindent. * dwarf2/read.h (struct dwarf2_per_bfd) <filenames_cache>: Delete. gdb/testsuite/ChangeLog: * gdb.base/info_sources.exp: Add new tests.
106 lines
3.1 KiB
Plaintext
106 lines
3.1 KiB
Plaintext
# Copyright 2019-2021 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 <http://www.gnu.org/licenses/>.
|
|
|
|
# Test 'info sources [-d | -b] [--] [REGEX]'
|
|
|
|
standard_testfile .c info_sources_base.c
|
|
|
|
if {[prepare_for_testing $testfile.exp $testfile \
|
|
[list $srcfile $srcfile2] debug]} {
|
|
untested $testfile.exp
|
|
return -1
|
|
}
|
|
|
|
# Executes "info sources " $args.
|
|
# EXPECT_SEEN_INFO_SOURCES 1 indicates that the source file info_sources.c must be seen
|
|
# in the output. Similarly, EXPECT_SEEN_INFO_SOURCES_BASE indicates that the source file
|
|
# info_sources_base.c must be seen in the output.
|
|
proc test_info_sources {args expect_seen_info_sources expect_seen_info_sources_base} {
|
|
global gdb_prompt srcfile srcfile2
|
|
|
|
set seen_info_sources 0
|
|
set seen_info_sources_base 0
|
|
set cmd [concat "info sources " $args]
|
|
gdb_test_multiple $cmd $cmd {
|
|
-re "^\[^,\]*${srcfile}(, |\[\r\n\]+)" {
|
|
incr seen_info_sources
|
|
exp_continue
|
|
}
|
|
-re "^\[^,\]*${srcfile2}(, |\[\r\n\]+)" {
|
|
incr seen_info_sources_base 1
|
|
exp_continue
|
|
}
|
|
-re ", " {
|
|
exp_continue
|
|
}
|
|
-re "$gdb_prompt $" {
|
|
if {$seen_info_sources == $expect_seen_info_sources \
|
|
&& $seen_info_sources_base == $expect_seen_info_sources_base} {
|
|
pass $cmd
|
|
} else {
|
|
fail $cmd
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if ![runto_main] {
|
|
untested $testfile.exp
|
|
return -1
|
|
}
|
|
|
|
# List both files with no regexp:
|
|
with_test_prefix "in main" {
|
|
test_info_sources "" 1 1
|
|
}
|
|
|
|
gdb_test "break some_other_func" ""
|
|
gdb_test "continue"
|
|
|
|
# List both files with no regexp:
|
|
test_info_sources "" 1 1
|
|
# Same but with option terminator:
|
|
test_info_sources "--" 1 1
|
|
|
|
# List both files with regexp matching anywhere in the filenames:
|
|
test_info_sources "info_sources" 1 1
|
|
if { ! [is_remote host] } {
|
|
test_info_sources "gdb.base" 1 1
|
|
}
|
|
|
|
# List both files with regexp matching the filename basenames,
|
|
# using various parts of the -basename option:
|
|
test_info_sources "-b info_sources" 1 1
|
|
test_info_sources "-basename info_sources" 1 1
|
|
test_info_sources "-b -- info_sources" 1 1
|
|
test_info_sources "-ba info_sources" 1 1
|
|
test_info_sources "-base -- info_sources" 1 1
|
|
test_info_sources "-basena info_sources" 1 1
|
|
test_info_sources "-basename -- info_sources" 1 1
|
|
|
|
# List only the file with basename matching regexp:
|
|
test_info_sources "-b base" 0 1
|
|
|
|
# List the files with dirname matching regexp,
|
|
# using various part of the -dirname option:
|
|
if { ! [is_remote host] } {
|
|
test_info_sources "-d base" 1 1
|
|
test_info_sources "-dirname base" 1 1
|
|
}
|
|
|
|
# Test non matching regexp, with option terminator:
|
|
test_info_sources "-b -- -d" 0 0
|
|
test_info_sources "-d -- -d" 0 0
|