This commit fixes the issue that is described in detail in the
previous commit; when processing a DWZ file, GDB can end up creating a
symtab associated with a compunit_symtab for a file that was never
compiled into a given compunit_symtab.
The previous commit added a test for this issue, however, things are
slightly complicated because a recent change to GDB:
commit a736ff7d886dbcc85026264c3ce11c125a8409b2
Date: Sat Sep 27 22:29:24 2025 -0600
Clean up iterate_over_symtabs
Changed GDB in such a way that the problem being discussed here
no longer appears to cause any incorrect behaviour. Still, I think
this problem is worth fixing. Adding additional symtabs that are in
the wrong place has the potential to cause problems in the future, but
also, wastes GDB memory, and increases time needed to search through
all symtabs.
The precise problem here is triggered when a DWZ file is created from
multiple object files (as is usually the case). The DWZ file will
contain a line table which can hold references to any of the source
files, from any of the object files. Note that a source file doesn't
have to be included in every object file in order to be added to the
line table of the DWZ file.
Within GDB the problem originates from the 'new_symbol' function (in
dwarf2/read.c). This function looks for the DW_AT_call_file or
DW_AT_decl_file of a symbol, uses this to lookup the line table entry,
and uses this to obtain the symtab to which the symbol should be
attached.
For an inlined subroutine instance, this information can be split
between an objfile's debug information and a shared DWZ file. For
example, from the gdb.debuginfod/solib-with-dwz.exp test case, this
first bit of DWARF is from the objfile's debug information:
<2><91>: Abbrev Number: 3 (DW_TAG_inlined_subroutine)
<92> DW_AT_abstract_origin: <alt 0x1b>
<96> DW_AT_low_pc : 0x1121
<9e> DW_AT_high_pc : 31
<9f> DW_AT_call_file : 1
<a0> DW_AT_call_line : 26
<a1> DW_AT_call_column : 15
<3><a2>: Abbrev Number: 5 (DW_TAG_formal_parameter)
<a3> DW_AT_abstract_origin: <alt 0x2c>
<a7> DW_AT_location : 2 byte block: 91 68 (DW_OP_fbreg: -24)
<3><aa>: Abbrev Number: 5 (DW_TAG_formal_parameter)
<ab> DW_AT_abstract_origin: <alt 0x25>
<af> DW_AT_location : 2 byte block: 91 6c (DW_OP_fbreg: -20)
The DW_AT_abstract_origin attributes are referencing the following
DWARF which has been placed into the DWZ file:
<1><1b>: Abbrev Number: 7 (DW_TAG_subprogram)
<1c> DW_AT_name : (indirect string, offset: 0x18a): add_some_int
<20> DW_AT_decl_file : 1
<21> DW_AT_decl_line : 24
<22> DW_AT_decl_column : 1
<23> DW_AT_prototyped : 1
<23> DW_AT_type : <0x14>
<24> DW_AT_inline : 3 (declared as inline and inlined)
<2><25>: Abbrev Number: 8 (DW_TAG_formal_parameter)
<26> DW_AT_name : a
<28> DW_AT_decl_file : 1
<29> DW_AT_decl_line : 24
<2a> DW_AT_decl_column : 19
<2b> DW_AT_type : <0x14>
<2><2c>: Abbrev Number: 8 (DW_TAG_formal_parameter)
<2d> DW_AT_name : b
<2f> DW_AT_decl_file : 1
<30> DW_AT_decl_line : 24
<31> DW_AT_decl_column : 26
<32> DW_AT_type : <0x14>
When GDB tries to create the symbols for the DW_TAG_formal_parameter
then this will find the DW_AT_decl_line in the DWZ file. This will
cause the line table of the DWZ file to be parsed. This parsing
currently creates symtabs for every file mentioned in the DWZ file's
line table, which includes files that are not part of the original
objfile.
Currently GDB creates and stores the symtabs within the file_entry
object (see dwarf2/line-header.h). I propose that we make the symtab
creation lazy; when the symtab is requested from a file_entry object,
the symtab will be created at this point.
Doing this will cause another problem though. In dwarf_decode_lines,
we specifically create all of the symtabs so that there will be a
symtab even for files that contain no code. We don't want to regress
this case.
The solution is that dwarf_decode_lines will still trigger the symtab
creation (by asking the file_entries for their symtab), unless we're
processing a DWZ file.
We don't need to worry about files that have no code, which are
mentioned in a DWZ file, as these files will also be mentioned in the
original objfile's line table. When that line table is processed (as
it will be), then symtabs for all files mentioned will be created. In
this way we will get:
(a) symtabs for every source file mentioned in the original objfile,
and
(b) symtabs for every source file that is specifically used by the
DWARF from the DWZ file.
I've update the gdb.debuginfod/solib-with-dwz.exp test to check the
symtab creation, and also added gdb.base/dwz-symtabs.exp, which is
very similar to solib-with-dwz.exp, but doesn't depend on debuginfod
and instead just focuses on which symtabs are created, this make the
test a little simpler overall.
---
gdb/dwarf2/cu.c | 13 +-
gdb/dwarf2/line-header.c | 23 +++
gdb/dwarf2/line-header.h | 13 +-
gdb/dwarf2/line-program.c | 19 +-
gdb/dwarf2/read.c | 10 +-
gdb/testsuite/gdb.base/dwz-symtabs-bar.c | 36 ++++
gdb/testsuite/gdb.base/dwz-symtabs-bar.h | 25 +++
gdb/testsuite/gdb.base/dwz-symtabs-common.h | 32 +++
gdb/testsuite/gdb.base/dwz-symtabs-foo.c | 79 ++++++++
gdb/testsuite/gdb.base/dwz-symtabs-foo.h | 27 +++
gdb/testsuite/gdb.base/dwz-symtabs-main.c | 34 ++++
gdb/testsuite/gdb.base/dwz-symtabs.exp | 188 ++++++++++++++++++
.../gdb.debuginfod/solib-with-dwz.exp | 74 +++++--
13 files changed, 532 insertions(+), 41 deletions(-)
create mode 100644 gdb/testsuite/gdb.base/dwz-symtabs-bar.c
create mode 100644 gdb/testsuite/gdb.base/dwz-symtabs-bar.h
create mode 100644 gdb/testsuite/gdb.base/dwz-symtabs-common.h
create mode 100644 gdb/testsuite/gdb.base/dwz-symtabs-foo.c
create mode 100644 gdb/testsuite/gdb.base/dwz-symtabs-foo.h
create mode 100644 gdb/testsuite/gdb.base/dwz-symtabs-main.c
create mode 100644 gdb/testsuite/gdb.base/dwz-symtabs.exp
@@ -245,19 +245,10 @@ dwarf2_cu::set_producer (const char *producer)
void
dwarf2_cu::create_subfiles_and_symtabs ()
{
- buildsym_compunit *builder = this->get_builder ();
- compunit_symtab *cust = builder->get_compunit_symtab ();
-
struct line_header *lh = this->line_header;
for (file_entry &fe : lh->file_names ())
{
- dwarf2_start_subfile (this, fe, *lh);
- subfile *sf = builder->get_current_subfile ();
-
- if (sf->symtab == nullptr)
- sf->symtab = allocate_symtab (cust, sf->name.c_str (),
- sf->name_for_id.c_str ());
-
- fe.symtab = sf->symtab;
+ struct symtab *symtab = fe.symtab (*this);
+ gdb_assert (symtab != nullptr);
}
}
@@ -421,3 +421,26 @@ dwarf_decode_line_header (sect_offset sect_off, bool is_dwz,
return lh;
}
+
+/* See dwarf2/line-header.h. */
+
+struct symtab *
+file_entry::symtab (dwarf2_cu &cu)
+{
+ if (m_symtab == nullptr)
+ {
+ buildsym_compunit *builder = cu.get_builder ();
+ compunit_symtab *cust = builder->get_compunit_symtab ();
+
+ dwarf2_start_subfile (&cu, *this, *cu.line_header);
+
+ subfile *sf = builder->get_current_subfile ();
+ if (sf->symtab == nullptr)
+ sf->symtab = allocate_symtab (cust, sf->name.c_str (),
+ sf->name_for_id.c_str ());
+
+ m_symtab = sf->symtab;
+ }
+
+ return m_symtab;
+}
@@ -23,6 +23,7 @@
#include "dwarf2/types.h"
struct dwarf2_per_objfile;
+struct dwarf2_cu;
/* dir_index is 1-based in DWARF 4 and before, and is 0-based in DWARF 5 and
later. */
@@ -65,8 +66,18 @@ struct file_entry
unsigned int length {};
+ /* Get the symtab for this file_entry. If no symtab has yet been created
+ or set (see set_symtab) for this file_entry then a new one will be
+ created. */
+ struct symtab *symtab (struct dwarf2_cu &cu);
+
+ /* Set the symtab for this file_entry. */
+ void set_symtab (struct symtab *s)
+ { m_symtab = s; }
+
+private:
/* The associated symbol table, if any. */
- struct symtab *symtab {};
+ struct symtab *m_symtab {};
};
/* The line number information for a compilation unit (found in the
@@ -700,8 +700,19 @@ dwarf_decode_lines (struct dwarf2_cu *cu, unrelocated_addr lowpc,
if (decode_mapping)
dwarf_decode_lines_1 (cu, lowpc);
- /* Make sure a symtab is created for every file, even files
- which contain only variables (i.e. no code with associated
- line numbers). */
- cu->create_subfiles_and_symtabs ();
+ /* For non DWZ CUs, make sure a symtab is created for every file, even
+ files which contain only variables (i.e. no code with associated line
+ numbers).
+
+ For DWZ CUs the line table can contain references to files that are no
+ part of the original CU. In fact, if multiple object files were used
+ to create the DWZ file (as is normal), then the DWZ CU's line table
+ can contain references to files that are in objfiles that are not part
+ of the current inferior. For DWZ we rely on lazy symtab creation. In
+ the end we should still end up with a symtab for every file as the
+ original CU (the non-DWZ CU) will still contain a line table, and that
+ line table will mention every file, so when that is processed we'll
+ create symtabs as needed. */
+ if (!cu->per_cu->is_dwz ())
+ cu->create_subfiles_and_symtabs ();
}
@@ -6277,8 +6277,8 @@ dwarf2_cu::setup_type_unit_groups (struct die_info *die)
for (i = 0; i < file_names.size (); ++i)
{
file_entry &fe = file_names[i];
- gdb_assert (fe.symtab != nullptr);
- tug_unshare->symtabs[i] = fe.symtab;
+ gdb_assert (fe.symtab (*this) != nullptr);
+ tug_unshare->symtabs[i] = fe.symtab (*this);
}
}
else
@@ -6296,7 +6296,7 @@ dwarf2_cu::setup_type_unit_groups (struct die_info *die)
for (i = 0; i < file_names.size (); ++i)
{
file_entry &fe = file_names[i];
- fe.symtab = tug_unshare->symtabs[i];
+ fe.set_symtab (tug_unshare->symtabs[i]);
}
}
@@ -11646,7 +11646,7 @@ process_structure_scope (struct die_info *die, struct dwarf2_cu *cu)
{
/* Any related symtab will do. */
symtab
- = cu->line_header->file_names ()[0].symtab;
+ = cu->line_header->file_names ()[0].symtab (*cu);
}
else
{
@@ -16228,7 +16228,7 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
if (fe == NULL)
complaint (_("file index out of range"));
else
- sym->set_symtab (fe->symtab);
+ sym->set_symtab (fe->symtab (*file_cu));
}
}
new file mode 100644
@@ -0,0 +1,36 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2025 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/>. */
+
+#include "dwz-symtabs-bar.h"
+#include "dwz-symtabs-common.h"
+
+static int bar_data = 0;
+
+void
+process_bar_data (int value)
+{
+ bar_data += add_some_int (3, value);
+
+}
+
+volatile int *ptr = 0;
+
+void bar_func (void)
+{
+ /* This will hopefully trigger a segfault. */
+ *ptr = 0; /* Crash here. */
+}
new file mode 100644
@@ -0,0 +1,25 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2025 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/>. */
+
+#ifndef SOLIB_WITH_DWZ_BAR_H
+#define SOLIB_WITH_DWZ_BAR_H
+
+extern void process_bar_data (int value);
+
+extern void bar_func (void);
+
+#endif /* SOLIB_WITH_DWZ_BAR_H */
new file mode 100644
@@ -0,0 +1,32 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2025 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/>. */
+
+#ifndef SOLIB_WITH_DWZ_COMMON_H
+#define SOLIB_WITH_DWZ_COMMON_H
+
+void breakpt (int a, int b);
+
+static inline int __attribute__((always_inline))
+add_some_int (int a, int b)
+{
+ if (a > b)
+ breakpt (a, b);
+
+ return a + b;
+}
+
+#endif /* SOLIB_WITH_DWZ_COMMON_H */
new file mode 100644
@@ -0,0 +1,79 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2025 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/>. */
+
+#include "dwz-symtabs-foo.h"
+#include "dwz-symtabs-common.h"
+
+struct foo_data_type
+{
+ int positive_value;
+ int negative_value;
+};
+
+static struct foo_data_type foo_data;
+
+void
+do_callback (foo_callback_type cb)
+{
+ cb (); /* Call line. */
+}
+
+void
+process_foo_data (int input)
+{
+#ifdef FOO2
+ int other_value = 4;
+#else
+ int other_value = 6;
+#endif
+
+ if (input > 0)
+ foo_data.positive_value += add_some_int (input, other_value);
+ else
+ foo_data.negative_value += add_some_int (other_value, input);
+}
+
+/* This comment must appear at the end of the source file with no compiled
+ code after it. When looking for a line number LINENO, GDB looks for a
+ symtab with a line table entry for LINENO or a later line. It is
+ important for this test that there be no suitable line table entry. The
+ numbers have no real meaning, I just want to ensure that the 'XXX' line,
+ which is what the test lists is far from any previous source listing.
+
+ 0
+ 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+ 10
+ XXX: Second line to list.
+ 10
+ 9
+ 8
+ 7
+ 6
+ 5
+ 4
+ 3
+ 2
+ 1
+ 0 */
new file mode 100644
@@ -0,0 +1,27 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2025 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/>. */
+
+#ifndef SOLIB_WITH_DWZ_FOO_H
+#define SOLIB_WITH_DWZ_FOO_H
+
+extern void process_foo_data (int value);
+
+typedef void (*foo_callback_type) (void);
+
+extern void do_callback (foo_callback_type cb);
+
+#endif /* SOLIB_WITH_DWZ_FOO_H */
new file mode 100644
@@ -0,0 +1,34 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2025 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/>. */
+
+#include "dwz-symtabs-foo.h"
+#include "dwz-symtabs-bar.h"
+
+void
+breakpt (int a, int b)
+{
+ (void) a;
+ (void) b;
+}
+
+int
+main (void)
+{
+ do_callback (bar_func);
+
+ return 0;
+}
new file mode 100644
@@ -0,0 +1,188 @@
+# Copyright 2025 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/>. */
+
+# This test is very similar to gdb.debuginfod/solib-with-dwz.exp,
+# except this one doesn't depend on debuginfod, and doesn't split the
+# debug information out of the shared libraries before running the dwz
+# tool.
+#
+# Three shared libraries are created, and the dwz tool is used to
+# extract common debug information from these into a common.dwz file.
+#
+# The libraries libbar, libfoo, an libfoo-2. The foo.c and foo.h
+# source files are shared between libfoo and libfoo-2, but are not
+# used to create libbar.
+#
+# There is another header, common.h, which is shared between all of
+# the libraries.
+#
+# The test starts the inferior, and runs until the symtabs of libbar
+# have been expanded, and then checks to make sure that there is no
+# symtab for foo.c or foo.h associated with libbar. Remember, these
+# source files are not used to build libbar.
+#
+# At one point, a bug in GDB would mean that symtabs for these files
+# were created and associated with libbar, this is because these files
+# are mentioned in the common.dwz file.
+
+require allow_shlib_tests
+require {istarget "*-linux*"}
+require {!is_remote host}
+require {dwz_version_at_least 0.13}
+
+standard_testfile -main.c -bar.c -foo.c -foo.h -common.h
+
+set libbar_filename [standard_output_file "libbar.so"]
+set libfoo_filename [standard_output_file "libfoo.so"]
+set libfoo_2_filename [standard_output_file "libfoo-2.so"]
+
+# Compile libbar.so.
+if {[build_executable "build libbar.so" $libbar_filename \
+ $srcfile2 { debug shlib build-id }] == -1} {
+ return
+}
+
+# If we are running with a board that splits the debug information out and
+# adds a .gnu_debuglink, then this test isn't going to work. We want to be
+# in control of splitting out the debug information, and we definitely don't
+# want a .gnu_debuglink otherwise debuginfod isn't going to be needed.
+if {[section_get $libbar_filename ".gnu_debuglink"] ne ""} {
+ unsupported "debug information has already been split out"
+ return
+}
+
+# Compile libfoo.so.
+if {[build_executable "build libfoo.so" $libfoo_filename \
+ $srcfile3 { debug shlib build-id }] == -1} {
+ return
+}
+
+# Compile libfoo-2.so.
+if {[build_executable "build libfoo-2.so" $libfoo_2_filename \
+ $srcfile3 { debug shlib build-id additional_flags=-DFOO2}] == -1} {
+ return
+}
+
+# Build the executable.
+if { [build_executable "build executable" ${binfile} ${srcfile} \
+ [list debug shlib=${libbar_filename} shlib=${libfoo_filename} shlib_load]] == -1 } {
+ return
+}
+
+gdb_download_shlib $libbar_filename
+gdb_download_shlib $libfoo_filename
+gdb_download_shlib $libfoo_2_filename
+
+# Run DWZ tool on the library files. This moves shared debug
+# information into a 'common.dwz' file.
+set dwz_file [standard_output_file "common.dwz"]
+set status \
+ [remote_exec build "dwz -m $dwz_file \
+ $libbar_filename \
+ $libfoo_filename \
+ $libfoo_2_filename"]
+if {[lindex $status 0] != 0} {
+ unsupported "unable to run dwz tool"
+ return
+}
+
+# Some earlier versions of dwz would fail to process the .debug files,
+# producing some error output, but still exit with code 0. A
+# successful execution of dwz should produce no output.
+if {[lindex $status 1] ne ""} {
+ unsupported "unexpected output from dwz tool"
+ return
+}
+
+clean_restart $testfile
+
+if { ![runto_main] } {
+ return
+}
+
+# This test relies on reading address zero triggering a SIGSEGV.
+# If address zero is readable then give up now.
+if { [is_address_zero_readable] } {
+ unsupported "address zero in readable"
+ return
+}
+
+set crash_line_num [gdb_get_line_number "Crash here" $::srcfile2]
+gdb_test "continue" \
+ "\r\n$crash_line_num\\s+[string_to_regexp {*ptr = 0; /* Crash here. */}]"
+
+set call_line_num [gdb_get_line_number "Call line" $::srcfile3]
+gdb_test "up" \
+ "\r\n$call_line_num\\s+[string_to_regexp {cb (); /* Call line. */}]"
+
+gdb_test "list" \
+ "\r\n$call_line_num\\s+[string_to_regexp {cb (); /* Call line. */}]\r\n.*" \
+ "list default location in $::srcfile3"
+
+set list_line_num [gdb_get_line_number "Second line to list" $::srcfile3]
+gdb_test "list $list_line_num" "$list_line_num\\s+XXX: Second line to list\\.\r\n.*" \
+ "list additional lines in $::srcfile3"
+
+# Use 'maint info symtabs' to list all symtabs and find the
+# symtabs that are associated with libbar.so.
+#
+# Then check that *-foo.c and *-foo.h don't appear in this list.
+#
+# But check that *-bar.c and *-common.h do appear in the list.
+set build_id [get_build_id $::libbar_filename]
+set symtabs [list]
+set collect_symtabs false
+
+gdb_test_multiple "maint info symtabs" "" {
+ -re "^maint info symtabs\r\n" {
+ exp_continue
+ }
+ -re "^\{ objfile (\[^\r\n\]+) \\(\\(struct objfile \\*\\) $::hex\\)\r\n" {
+ set objfile_name $expect_out(1,string)
+ if { [file tail $objfile_name] eq [file tail $libbar_filename] } {
+ set collect_symtabs true
+ } else {
+ set collect_symtabs false
+ }
+ exp_continue
+ }
+ -re "^\\s+\{ symtab <unknown> \[^\r\n\]+\r\n" {
+ # Ignore '<unknown>' nameless symtabs.
+ exp_continue
+ }
+ -re "^\\s+\{ symtab (\[^\r\n\]+) \\(\\(struct symtab \\*\\) $::hex\\)\r\n" {
+ if { $collect_symtabs } {
+ set symtab_name $expect_out(1,string)
+ lappend symtabs [file tail $symtab_name]
+ }
+ exp_continue
+ }
+ -re "^$::gdb_prompt $" {
+ pass $gdb_test_name
+ }
+ -re "^\[^\r\n\]+\r\n" {
+ exp_continue
+ }
+}
+
+foreach filename [list $::srcfile3 $::srcfile4] {
+ gdb_assert { [lsearch -exact $symtabs $filename] == -1 } \
+ "$filename is not in the symtab list"
+}
+
+foreach filename [list $::srcfile2 $::srcfile5] {
+ gdb_assert { [lsearch -exact $symtabs $filename] != -1 } \
+ "$filename is in the symtab list"
+}
@@ -86,7 +86,7 @@ require {istarget "*-linux*"}
require {!is_remote host}
require {dwz_version_at_least 0.13}
-standard_testfile -main.c -bar.c -foo.c
+standard_testfile -main.c -bar.c -foo.c -foo.h -common.h
set libbar_filename [standard_output_file "libbar.so"]
set libfoo_filename [standard_output_file "libfoo.so"]
@@ -291,25 +291,6 @@ proc run_test { cache db debug_dir use_filename } {
set saw_source_download [check_cache_for_foo $cache]
}
- # GDB ends up creating a symtab for solib-with-dwz-foo.c
- # associated with libbar.so. This isn't ideal as *-foo.c wasn't
- # used within libbar.so. The symtab is a result of loading the
- # file/line table from the DWZ file while processing the DWARF
- # for libbar.so.
- #
- # While performing the 'list LINENO' or 'list FILE:LINENO'
- # command GDB performs a search of all symtabs, as part of this
- # process GDB tries to establish the full source filename for
- # the *-foo.c symtab associated with libbar.so, this in turn
- # causes GDB to try and download the source from debuginfod.
- #
- # This download will fail as *-foo.c is not used within
- # libbar.so, but having GDB try to download the file is not
- # ideal, even if it is harmless.
- #
- # If/when this xfail is addressed, the comment at the start of
- # this file will need updating too.
- setup_xfail "*-*-*"
gdb_assert { !$saw_source_download } \
"$gdb_test_name, no source download"
@@ -321,6 +302,59 @@ proc run_test { cache db debug_dir use_filename } {
exp_continue
}
}
+
+ # Use 'maint info symtabs' to list all symtabs and find the
+ # symtabs that are associated with libbar.so (actually with the
+ # separate debug file for libbar.so).
+ #
+ # Then check that *-foo.c and *-foo.h don't appear in this list.
+ #
+ # But check that *-bar.c and *-common.h do appear in the list.
+ set build_id [get_build_id $::libbar_filename]
+ set symtabs [list]
+ set collect_symtabs false
+
+ gdb_test_multiple "maint info symtabs" "" {
+ -re "^maint info symtabs\r\n" {
+ exp_continue
+ }
+ -re "^\{ objfile (\[^\r\n\]+) \\(\\(struct objfile \\*\\) $::hex\\)\r\n" {
+ set objfile_name $expect_out(1,string)
+ if { [string first $build_id $objfile_name] != -1 } {
+ set collect_symtabs true
+ } else {
+ set collect_symtabs false
+ }
+ exp_continue
+ }
+ -re "^\\s+\{ symtab <unknown> \[^\r\n\]+\r\n" {
+ # Ignore '<unknown>' nameless symtabs.
+ exp_continue
+ }
+ -re "^\\s+\{ symtab (\[^\r\n\]+) \\(\\(struct symtab \\*\\) $::hex\\)\r\n" {
+ if { $collect_symtabs } {
+ set symtab_name $expect_out(1,string)
+ lappend symtabs [file tail $symtab_name]
+ }
+ exp_continue
+ }
+ -re "^$::gdb_prompt $" {
+ pass $gdb_test_name
+ }
+ -re "^\[^\r\n\]+\r\n" {
+ exp_continue
+ }
+ }
+
+ foreach filename [list $::srcfile3 $::srcfile4] {
+ gdb_assert { [lsearch -exact $symtabs $filename] == -1 } \
+ "$filename is not in the symtab list"
+ }
+
+ foreach filename [list $::srcfile2 $::srcfile5] {
+ gdb_assert { [lsearch -exact $symtabs $filename] != -1 } \
+ "$filename is in the symtab list"
+ }
}
# Create CACHE and DB directories ready for debuginfod to use.