From: Andrew Burgess <aburgess@redhat.com>
To: gdb-patches@sourceware.org
Cc: Andrew Burgess <aburgess@redhat.com>
Subject: [PATCH 1/2] gdb: fix 'list' for multiple source file results
Date: Tue, 18 Nov 2025 10:28:52 +0000 [thread overview]
Message-ID: <9998f4f077aa5ea8ce683a78714ecd760bd3381c.1763461561.git.aburgess@redhat.com> (raw)
In-Reply-To: <cover.1763461561.git.aburgess@redhat.com>
This commit:
commit c7a45b98a61451f05ff654c4fb72a9c9cb2fba36
Date: Thu Jun 12 15:37:50 2025 +0000
gdb, linespec: avoid multiple locations with same PC
broke GDB's ability to list multiple source files using a 'list'
command. In GDB 16 and earlier something like 'list foo.c:10' could
print multiple results if there were multiple 'foo.c' files compiled
into the executable.
The above commit added a filter to add_sal_to_sals (linespec.c) such
that multiple sals in the same program space, but with the same pc
value, could not be added, only the first sal would actually be
recorded. The problem with this is that add_sal_to_sals is used from
decode_digits_list_mode (also linespec.c) where the pc value is forced
to zero. This force to zero makes sense I think as there might not be
any compiled code for the requested line (this is for 'list' after
all), so there might not be a valid pc to use.
I'm not a fan of using '0' as a special pc value, there are embedded
targets where 0 is a valid pc value, but given we're already using 0
here, I propose to just roll with it.
So, my proposal is that, if the pc is 0, add_sal_to_sals should always
add the sal. This fixes the decode_digits_list_mode, but should keep
the fix that c7a45b98a614 introduced.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=33647
---
gdb/linespec.c | 15 ++--
gdb/testsuite/gdb.base/list-multi-source.c | 60 +++++++++++++
gdb/testsuite/gdb.base/list-multi-source.exp | 95 ++++++++++++++++++++
3 files changed, 165 insertions(+), 5 deletions(-)
create mode 100644 gdb/testsuite/gdb.base/list-multi-source.c
create mode 100644 gdb/testsuite/gdb.base/list-multi-source.exp
diff --git a/gdb/linespec.c b/gdb/linespec.c
index 277b45b4b7f..2cbfe2fcc20 100644
--- a/gdb/linespec.c
+++ b/gdb/linespec.c
@@ -1071,11 +1071,16 @@ add_sal_to_sals (struct linespec_state *self,
const symtab_and_line &sal,
const char *symname, bool literal_canonical)
{
- /* We don't want two SALs with the same PC from the
- same program space. */
- for (const auto &s : sals)
- if (sal.pc == s.pc && sal.pspace == s.pspace)
- return;
+ /* We don't want two SALs with the same PC from the same program space.
+ However, for the 'list' command we force the pc value to be 0, and in
+ this case we do want to see all SALs. See decode_digits_list_mode
+ for where the 0 originates from. */
+ if (sal.pc != 0)
+ {
+ for (const auto &s : sals)
+ if (sal.pc == s.pc && sal.pspace == s.pspace)
+ return;
+ }
sals.push_back (sal);
diff --git a/gdb/testsuite/gdb.base/list-multi-source.c b/gdb/testsuite/gdb.base/list-multi-source.c
new file mode 100644
index 00000000000..ab2b6a01b36
--- /dev/null
+++ b/gdb/testsuite/gdb.base/list-multi-source.c
@@ -0,0 +1,60 @@
+/* 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/>. */
+
+extern int function_a (void);
+extern int function_b (void);
+
+#ifdef MAIN
+int
+main (void)
+{
+ int res;
+
+ res = function_a ();
+
+ res += function_b ();
+
+ return res;
+}
+#endif
+
+#if defined FILE_A || defined FILE_B
+static int
+get_value_common (void)
+{
+ /* NOTE: When reading this file in the source tree, the variable used in
+ the return statement below will be replaced by a constant value when
+ the file is copied into the source tree. */
+ return value_to_return; /* List this line. */
+}
+#endif
+
+#ifdef FILE_A
+int
+function_a (void)
+{
+ return get_value_common ();
+}
+#endif
+
+#ifdef FILE_B
+int
+function_b (void)
+{
+ return get_value_common ();
+}
+#endif
diff --git a/gdb/testsuite/gdb.base/list-multi-source.exp b/gdb/testsuite/gdb.base/list-multi-source.exp
new file mode 100644
index 00000000000..7809167bd0f
--- /dev/null
+++ b/gdb/testsuite/gdb.base/list-multi-source.exp
@@ -0,0 +1,95 @@
+# 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/>.
+
+# Test that 'list FILE:LINE' can print multiple results if FILE
+# matches multiple files from the source tree.
+#
+# Then test that we can use 'list DIR/FILE:LINE' to restrict the
+# results to a single source file.
+
+# This test uses a single source file that is copied into the build
+# tree 3 times. The three copies are then copied with different
+# defines set so that we see different functions in each copy.
+standard_testfile .c
+
+# Create the source tree within the build directory.
+set src_root [standard_output_file "src"]
+set src_a "$src_root/a"
+set src_b "$src_root/b"
+set file_a "$src_a/foo.c"
+set file_b "$src_b/foo.c"
+set file_main "$src_root/main.c"
+remote_exec build "mkdir -p \"$src_root\""
+remote_exec build "mkdir -p \"$src_a\""
+remote_exec build "mkdir -p \"$src_b\""
+
+# Make three copies of the single source file in the build directory
+# based source tree. Two of the source files are modified slighly to
+# make the output of 'list' unique for each copy.
+remote_exec build "cp \"$srcdir/$subdir/$srcfile\" \"$file_main\""
+remote_exec build "cp \"$srcdir/$subdir/$srcfile\" \"$file_a\""
+remote_exec build "cp \"$srcdir/$subdir/$srcfile\" \"$file_b\""
+remote_exec build "sed -i -e \"s/value_to_return/3/\" \"$file_a\""
+remote_exec build "sed -i -e \"s/value_to_return/-3/\" \"$file_b\""
+
+# Build the executable. Use defines to make the source files
+# different.
+if { [prepare_for_testing_full "failed to prepare" \
+ [list $testfile debug \
+ $file_main [list debug additional_flags=-DMAIN] \
+ $file_a [list debug additional_flags=-DFILE_A] \
+ $file_b [list debug additional_flags=-DFILE_B]]]} {
+ return
+}
+
+# The LINENUM we should list, and the first and last lines that should
+# appear in the list output.
+set linenum [gdb_get_line_number "List this line"]
+set first_linenum [expr {$linenum - 5}]
+set last_linenum [expr {$linenum + 4}]
+
+# List using FILE:LINE for a filename that is ambiguous.
+gdb_test "list foo.c:$linenum" \
+ [multi_line \
+ "file: \"\[^\r\n\]+/a/foo.c\", line number: $linenum, symbol: \"\[^\r\n\]+\"" \
+ "$first_linenum\\s+\[^\r\n\]+" \
+ ".*" \
+ "$linenum\\s+[string_to_regexp {return 3; /* List this line. */}]" \
+ ".*" \
+ "$last_linenum\\s+\[^\r\n\]+" \
+ "file: \"\[^\r\n\]+/b/foo.c\", line number: $linenum, symbol: \"\[^\r\n\]+\"" \
+ "$first_linenum\\s+\[^\r\n\]+" \
+ ".*" \
+ "$linenum\\s+[string_to_regexp {return -3; /* List this line. */}]" \
+ ".*" \
+ "$last_linenum\\s+\[^\r\n\]+"]
+
+# Now list using a more acurate filename, we should only get a single
+# result.
+gdb_test "list a/foo.c:$linenum" \
+ [multi_line \
+ "^$first_linenum\\s+\[^\r\n\]+" \
+ ".*" \
+ "$linenum\\s+[string_to_regexp {return 3; /* List this line. */}]" \
+ ".*" \
+ "$last_linenum\\s+\[^\r\n\]+"]
+
+gdb_test "list b/foo.c:$linenum" \
+ [multi_line \
+ "^$first_linenum\\s+\[^\r\n\]+" \
+ ".*" \
+ "$linenum\\s+[string_to_regexp {return -3; /* List this line. */}]" \
+ ".*" \
+ "$last_linenum\\s+\[^\r\n\]+"]
--
2.47.1
next prev parent reply other threads:[~2025-11-18 10:31 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-11-18 10:28 [PATCH 0/2] Fix regression in 'list' command Andrew Burgess
2025-11-18 10:28 ` Andrew Burgess [this message]
2025-11-18 10:42 ` [PATCH 1/2] gdb: fix 'list' for multiple source file results Andreas Schwab
2025-11-18 14:28 ` Andrew Burgess
2025-11-18 10:28 ` [PATCH 2/2] gdb: display a symbol more often in multi-file list output Andrew Burgess
2025-11-19 10:32 ` [PATCHv2 0/2] Fix regression in 'list' command Andrew Burgess
2025-11-19 10:32 ` [PATCHv2 1/2] gdb: fix 'list' for multiple source file results Andrew Burgess
2025-12-04 16:48 ` Tom Tromey
2025-12-05 10:50 ` Andrew Burgess
2025-12-04 20:18 ` Kevin Buettner
2025-12-05 7:14 ` Eli Zaretskii
2025-11-19 10:32 ` [PATCHv2 2/2] gdb: display a symbol more often in multi-file list output Andrew Burgess
2025-12-04 16:53 ` Tom Tromey
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=9998f4f077aa5ea8ce683a78714ecd760bd3381c.1763461561.git.aburgess@redhat.com \
--to=aburgess@redhat.com \
--cc=gdb-patches@sourceware.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox