]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
gdb, linespec: avoid multiple locations with same PC
authorKlaus Gerlicher <klaus.gerlicher@intel.com>
Thu, 12 Jun 2025 15:37:50 +0000 (15:37 +0000)
committerKlaus Gerlicher <klaus.gerlicher@intel.com>
Thu, 12 Jun 2025 15:37:50 +0000 (15:37 +0000)
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   <MULTIPLE>
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 <simon.marchi@efficios.com>
gdb/linespec.c
gdb/testsuite/gdb.linespec/linespec.exp
gdb/testsuite/gdb.linespec/lspec.cc

index 824afd90983d7e93e6b3d77150ce9285e31c857c..b59c0553c34c1344678b6ce92baeffe00420dd1f 100644 (file)
@@ -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)
index 69744dd16ab3ae39182f78ae4dd26d0fe71af2c1..86b55bb949732c3dae5e4fddef6e3f98cc8c06c0 100644 (file)
@@ -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.
 #
index bb660fbc79ee6b73483755976951823fc8ca4db2..ab0a193da8911a7ac67c6a147244b6587a87cb2d 100644 (file)
@@ -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();