From f8c4185131758306ddeb7b40479e82cab4dd7f26 Mon Sep 17 00:00:00 2001 From: Simon Marchi Date: Thu, 4 Jun 2020 13:56:55 -0400 Subject: [PATCH] gdb: really share partial symtabs when using .gdb_index or .debug_names Fix/follow-up to commit 17ee85fc2a ("Share DWARF partial symtabs"). In the non-index case, where GDB builds partial symbols from scratch, two objfiles around the same BFD correctly share partial symtabs. The first objfile, which has to do all the work, saves a reference to the created partial symtabs in the shared per_bfd object (at the end of dwarf2_build_psymtabs). The second objfile, when it reaches dwarf2_build_psymtabs, sees that there are already partial symtabs built for this BFD and just uses it. However, that commit missed implementing the same sharing for cases where GDB uses .gdb_index or .debug_names to build the partial symtabs. This patch fixes it by having the first objfile to use the BFD set per_bfd->partial_symtabs at the end of dwarf2_read_gdb_index / dwarf2_read_debug_names. For the subsequent objfiles using that BFD, the partial symtabs are then picked up in dwarf2_initialize_objfile. This patch adds a test that mimics how the issue was originally triggered: 1. Load the test file twice, such that the second objfile re-uses the per_bfd object created for the first objfile. 2. Run to some point where in the backtrace there is a frame for a function that's in a CU that's not yet read in. 3. Check that this frame's information is complete in the "backtrace" output. Step 2 requires an address -> symbol lookup which uses the addrmap at objfile->partial_symtabs->psymtabs_addrmap. If the objfile->partial_symtabs link is not properly setup (as is the case before this patch), the symbol for that frame won't be found and we'll get a frame with incomplete information. The test fails without the fix when using boards "cc-with-gdb-index" and "cc-with-debug-names". gdb/ChangeLog: * dwarf2/read.c (dwarf2_read_gdb_index): Save partial_symtabs in the per_bfd object. (dwarf2_read_debug_names): Likewise. (dwarf2_initialize_objfile): Use partial_symtabs from per_bfd object when re-using a per_bfd object with an index. gdb/testsuite/ChangeLog: * gdb.dwarf2/share-psymtabs-bt.exp: New file. * gdb.dwarf2/share-psymtabs-bt.c: New file. * gdb.dwarf2/share-psymtabs-bt-2.c: New file. Change-Id: Ibb26210e2dfc03b80ba9fa56b875ba4cc58c0352 --- gdb/ChangeLog | 8 +++ gdb/dwarf2/read.c | 56 ++++++++++++-------- gdb/testsuite/ChangeLog | 6 +++ gdb/testsuite/gdb.base/share-psymtabs-bt-2.c | 24 +++++++++ gdb/testsuite/gdb.base/share-psymtabs-bt.c | 29 ++++++++++ gdb/testsuite/gdb.base/share-psymtabs-bt.exp | 51 ++++++++++++++++++ 6 files changed, 152 insertions(+), 22 deletions(-) create mode 100644 gdb/testsuite/gdb.base/share-psymtabs-bt-2.c create mode 100644 gdb/testsuite/gdb.base/share-psymtabs-bt.c create mode 100644 gdb/testsuite/gdb.base/share-psymtabs-bt.exp diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 98f4d17412e..f1430ad1eed 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,11 @@ +2020-06-04 Simon Marchi + + * dwarf2/read.c (dwarf2_read_gdb_index): Save partial_symtabs in + the per_bfd object. + (dwarf2_read_debug_names): Likewise. + (dwarf2_initialize_objfile): Use partial_symtabs from per_bfd + object when re-using a per_bfd object with an index. + 2020-06-03 Tom de Vries PR symtab/26046 diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c index ac6c15e7b25..477c382b81b 100644 --- a/gdb/dwarf2/read.c +++ b/gdb/dwarf2/read.c @@ -3068,9 +3068,10 @@ dwarf2_read_gdb_index offset_type cu_list_elements, types_list_elements, dwz_list_elements = 0; struct dwz_file *dwz; struct objfile *objfile = per_objfile->objfile; + dwarf2_per_bfd *per_bfd = per_objfile->per_bfd; gdb::array_view main_index_contents - = get_gdb_index_contents (objfile, per_objfile->per_bfd); + = get_gdb_index_contents (objfile, per_bfd); if (main_index_contents.empty ()) return 0; @@ -3089,7 +3090,7 @@ dwarf2_read_gdb_index /* If there is a .dwz file, read it so we can get its CU list as well. */ - dwz = dwarf2_get_dwz_file (per_objfile->per_bfd); + dwz = dwarf2_get_dwz_file (per_bfd); if (dwz != NULL) { struct mapped_index dwz_map; @@ -3114,29 +3115,33 @@ dwarf2_read_gdb_index } } - create_cus_from_index (per_objfile->per_bfd, cu_list, cu_list_elements, - dwz_list, dwz_list_elements); + create_cus_from_index (per_bfd, cu_list, cu_list_elements, dwz_list, + dwz_list_elements); if (types_list_elements) { /* We can only handle a single .debug_types when we have an index. */ - if (per_objfile->per_bfd->types.size () != 1) + if (per_bfd->types.size () != 1) return 0; - dwarf2_section_info *section = &per_objfile->per_bfd->types[0]; + dwarf2_section_info *section = &per_bfd->types[0]; - create_signatured_type_table_from_index (per_objfile->per_bfd, - section, types_list, + create_signatured_type_table_from_index (per_bfd, section, types_list, types_list_elements); } create_addrmap_from_index (per_objfile, map.get ()); - per_objfile->per_bfd->index_table = std::move (map); - per_objfile->per_bfd->using_index = 1; - per_objfile->per_bfd->quick_file_names_table = - create_quick_file_names_table (per_objfile->per_bfd->all_comp_units.size ()); + per_bfd->index_table = std::move (map); + per_bfd->using_index = 1; + per_bfd->quick_file_names_table = + create_quick_file_names_table (per_bfd->all_comp_units.size ()); + + /* Save partial symtabs in the per_bfd object, for the benefit of subsequent + objfiles using the same BFD. */ + gdb_assert (per_bfd->partial_symtabs == nullptr); + per_bfd->partial_symtabs = objfile->partial_symtabs; return 1; } @@ -5205,6 +5210,7 @@ dwarf2_read_debug_names (dwarf2_per_objfile *per_objfile) std::unique_ptr map (new mapped_debug_names); mapped_debug_names dwz_map; struct objfile *objfile = per_objfile->objfile; + dwarf2_per_bfd *per_bfd = per_objfile->per_bfd; if (!read_debug_names_from_section (objfile, objfile_name (objfile), &per_objfile->per_bfd->debug_names, *map)) @@ -5216,7 +5222,7 @@ dwarf2_read_debug_names (dwarf2_per_objfile *per_objfile) /* If there is a .dwz file, read it so we can get its CU list as well. */ - dwz_file *dwz = dwarf2_get_dwz_file (per_objfile->per_bfd); + dwz_file *dwz = dwarf2_get_dwz_file (per_bfd); if (dwz != NULL) { if (!read_debug_names_from_section (objfile, @@ -5229,29 +5235,33 @@ dwarf2_read_debug_names (dwarf2_per_objfile *per_objfile) } } - create_cus_from_debug_names (per_objfile->per_bfd, *map, dwz_map); + create_cus_from_debug_names (per_bfd, *map, dwz_map); if (map->tu_count != 0) { /* We can only handle a single .debug_types when we have an index. */ - if (per_objfile->per_bfd->types.size () != 1) + if (per_bfd->types.size () != 1) return false; - dwarf2_section_info *section = &per_objfile->per_bfd->types[0]; + dwarf2_section_info *section = &per_bfd->types[0]; create_signatured_type_table_from_debug_names - (per_objfile, *map, section, &per_objfile->per_bfd->abbrev); + (per_objfile, *map, section, &per_bfd->abbrev); } - create_addrmap_from_aranges (per_objfile, - &per_objfile->per_bfd->debug_aranges); + create_addrmap_from_aranges (per_objfile, &per_bfd->debug_aranges); - per_objfile->per_bfd->debug_names_table = std::move (map); - per_objfile->per_bfd->using_index = 1; - per_objfile->per_bfd->quick_file_names_table = + per_bfd->debug_names_table = std::move (map); + per_bfd->using_index = 1; + per_bfd->quick_file_names_table = create_quick_file_names_table (per_objfile->per_bfd->all_comp_units.size ()); + /* Save partial symtabs in the per_bfd object, for the benefit of subsequent + objfiles using the same BFD. */ + gdb_assert (per_bfd->partial_symtabs == nullptr); + per_bfd->partial_symtabs = objfile->partial_symtabs; + return true; } @@ -5972,6 +5982,7 @@ dwarf2_initialize_objfile (struct objfile *objfile, dw_index_kind *index_kind) if (per_bfd->debug_names_table != nullptr) { *index_kind = dw_index_kind::DEBUG_NAMES; + per_objfile->objfile->partial_symtabs = per_bfd->partial_symtabs; per_objfile->resize_symtabs (); return true; } @@ -5981,6 +5992,7 @@ dwarf2_initialize_objfile (struct objfile *objfile, dw_index_kind *index_kind) if (per_bfd->index_table != nullptr) { *index_kind = dw_index_kind::GDB_INDEX; + per_objfile->objfile->partial_symtabs = per_bfd->partial_symtabs; per_objfile->resize_symtabs (); return true; } diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index cfdd6a6efef..2a7779b4490 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2020-06-04 Simon Marchi + + * gdb.dwarf2/share-psymtabs-bt.exp: New file. + * gdb.dwarf2/share-psymtabs-bt.c: New file. + * gdb.dwarf2/share-psymtabs-bt-2.c: New file. + 2020-06-04 Tom de Vries * lib/gdb.exp (gdb_file_cmd): Avoid path names in error messages. diff --git a/gdb/testsuite/gdb.base/share-psymtabs-bt-2.c b/gdb/testsuite/gdb.base/share-psymtabs-bt-2.c new file mode 100644 index 00000000000..c713eb22693 --- /dev/null +++ b/gdb/testsuite/gdb.base/share-psymtabs-bt-2.c @@ -0,0 +1,24 @@ +/* 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 . */ + +void bar (int x); + +void +foo (int x) +{ + bar (x); +} diff --git a/gdb/testsuite/gdb.base/share-psymtabs-bt.c b/gdb/testsuite/gdb.base/share-psymtabs-bt.c new file mode 100644 index 00000000000..97ad3457905 --- /dev/null +++ b/gdb/testsuite/gdb.base/share-psymtabs-bt.c @@ -0,0 +1,29 @@ +/* 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 . */ + +void +bar (int x) +{} + +void foo (int x); + +int +main (void) +{ + foo (12345); + return 0; +} diff --git a/gdb/testsuite/gdb.base/share-psymtabs-bt.exp b/gdb/testsuite/gdb.base/share-psymtabs-bt.exp new file mode 100644 index 00000000000..b9b62d91e60 --- /dev/null +++ b/gdb/testsuite/gdb.base/share-psymtabs-bt.exp @@ -0,0 +1,51 @@ +# 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 that a backtrace is shown correctly for an objfile that uses partial +# symtabs created by another objfile sharing the same BFD. +# +# It mimics how a bug with psymtab sharing was initially found: +# +# 1. Load the test file twice, such that the second objfile re-uses the +# per_bfd object created for the first objfile. +# 2. Run to some point where in the backtrace there is a frame for a +# function that's in a CU that's not yet read in. +# 3. Check that this frame's information is complete in the "backtrace" +# output. + +standard_testfile .c share-psymtabs-bt-2.c + +if { [prepare_for_testing "failed to prepare" $testfile "$srcfile $srcfile2" \ + {debug}] } { + untested "failed to compile" + return -1 +} + +# Load $binfile a second time. The second created objfile will re-use the +# partial symtabs created by the first one. +if { [gdb_file_cmd $binfile] != 0 } { + fail "file command failed" + return -1 +} + +gdb_breakpoint "bar" +if { ![runto "bar"] } { + fail "failed to run to bar" + return -1 +} + +# A buggy GDB would fail to find the full symbol associated to this frame's +# address, so would just show "foo ()" (from the minimal symbol). +gdb_test "bt" "foo \\(x=12345\\).*" -- 2.30.2