From c7a45b98a61451f05ff654c4fb72a9c9cb2fba36 Mon Sep 17 00:00:00 2001 From: Klaus Gerlicher Date: Thu, 12 Jun 2025 15:37:50 +0000 Subject: [PATCH] gdb, linespec: avoid multiple locations with same PC Setting a BP on a line like this would incorrectly yield two BP locations: 01 void two () { {int var = 0;} } (gdb) break 1 Breakpoint 1 at 0x1164: main.cpp:1. (2 locations) (gdb) info breakpoints Num Type Disp Enb Address What 1 breakpoint keep y 1.1 y 0x0000000000001164 in two() at main.cpp:1 1.2 y 0x0000000000001164 in two() at main.cpp:1 In this case decode_digits_ordinary () returns two SALs, exactly matching the requested line. One for the entry PC and one for the prologue end PC. This was tested with GCC, CLANG and ICPX. Subsequent code tries to skip the prologue on these PCs, which in turn makes them the same. To fix this, ignore SALs with the same PC and program space when adding to the list of SALs. This will then properly set only one location: (gdb) break 1 Breakpoint 1 at 0x1164: file main.cpp, line 1 (gdb) info breakpoints Num Type Disp Enb Address What 1 breakpoint keep y 0x0000000000001164 in two() at main.cpp:1 Approved-By: Simon Marchi --- gdb/linespec.c | 6 ++++++ gdb/testsuite/gdb.linespec/linespec.exp | 6 ++++++ gdb/testsuite/gdb.linespec/lspec.cc | 2 ++ 3 files changed, 14 insertions(+) diff --git a/gdb/linespec.c b/gdb/linespec.c index 824afd90983..b59c0553c34 100644 --- a/gdb/linespec.c +++ b/gdb/linespec.c @@ -1074,6 +1074,12 @@ add_sal_to_sals (struct linespec_state *self, struct 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; + sals->push_back (*sal); if (self->canonical) diff --git a/gdb/testsuite/gdb.linespec/linespec.exp b/gdb/testsuite/gdb.linespec/linespec.exp index 69744dd16ab..86b55bb9497 100644 --- a/gdb/testsuite/gdb.linespec/linespec.exp +++ b/gdb/testsuite/gdb.linespec/linespec.exp @@ -194,6 +194,12 @@ gdb_test "break lspec.h:$line" \ "Breakpoint \[0-9\]+ at $hex: file .*lspec.h, line $line." \ "set breakpoint in f1" +# This should only have a single location -- in no_multi_locs. +set line [gdb_get_line_number no_multi_locs] +gdb_test "break $line" \ + "Breakpoint \[0-9\]+ at $hex: file .*$srcfile, line $line." \ + "set breakpoint at no_multi_locs" + # # Multi-inferior tests. # diff --git a/gdb/testsuite/gdb.linespec/lspec.cc b/gdb/testsuite/gdb.linespec/lspec.cc index bb660fbc79e..ab0a193da89 100644 --- a/gdb/testsuite/gdb.linespec/lspec.cc +++ b/gdb/testsuite/gdb.linespec/lspec.cc @@ -13,6 +13,8 @@ int body_elsewhere() #include "body.h" } +void no_multi_locs () { {int var = 0;} } + int main() { return dupname(0) + m(0) + n(0) + f1() + f2() + body_elsewhere(); -- 2.47.3