[RFAv3] Show locno for 'multi location' breakpoint hit msg+conv var $bkptno $locno.

Philippe Waroquiers philippe.waroquiers@skynet.be
Mon Jun 6 09:45:04 GMT 2022


Before this patch, when a breakpoint that has multiple locations is reached,
GDB printed:
  Thread 1 "zeoes" hit Breakpoint 1, some_func () at somefunc1.c:5

This patch changes the message so that bkpt_print_id prints the precise
encountered breakpoint:
  Thread 1 "zeoes" hit Breakpoint 1.2, some_func () at somefunc1.c:5

In mi mode, bkpt_print_id also (optionally) prints a new table field "locno":
  locno is printed when the breakpoint has more than one location.
Note that according to the GDB user manual node 'GDB/MI Development and Front
Ends', it is ok to add new fields without changing the MI version.

Also, when a breakpoint is reached, the convenience variables
$bkptno and $locno are set to the encountered breakpoint number
and location number.

$bkptno and $locno can a.o. be used in the command list of a breakpoint,
to disable the specific encountered breakpoint, e.g.
   disable $bkptno.$locno

In case the breakpoint has only one location, $locno is still set to
the value 1, so as to allow a command such as:
  disable $bkptno.$locno
even when the breakpoint has only one location.

This also fixes a strange behaviour: when a breakpoint X has only
one location,
  enable|disable X.1
is accepted but transforms the breakpoint in a multiple locations
breakpoint having only one location.

The changes in RFA v3 handle the additional comments of Eli:
 GDB/NEW:
  - Use max 80-column
  - Use 'code location' instead of 'location'.
  - Fix typo $bkpno
  - Ensure that disable $bkptno and disable $bkptno.$locno have
    each their explanation inthe example
  - Reworded the 'breakpoint-hit' paragraph.
 gdb.texinfo:
  - Use 'code location' instead of 'location'.
  - Add a note to clarify the distinction between $bkptno and $bpnum.
  - Use @kbd instead of examples with only one command.

Compared to RFA v1, the changes in v2 handle the comments given by
Keith Seitz and Eli Zaretskii:
  - Use %s for the result of paddress
  - Use bkptno_numopt_re instead of 2 different -re cases
  - use C@t{++}
  - Add index entries for $bkptno and $locno
  - Added an example for "locno" in the mi interface
  - Added examples in the Break command manual.
---
 gdb/NEWS                                      | 21 +++++
 gdb/ada-lang.c                                |  2 +-
 gdb/break-catch-syscall.c                     |  2 +-
 gdb/break-catch-throw.c                       |  2 +-
 gdb/breakpoint.c                              | 93 +++++++++++++++----
 gdb/breakpoint.h                              | 14 +++
 gdb/doc/gdb.texinfo                           | 83 ++++++++++++++++-
 gdb/infrun.c                                  | 16 +++-
 gdb/testsuite/gdb.ada/bp_inlined_func.exp     |  2 +-
 gdb/testsuite/gdb.ada/operator_bp.exp         |  4 +-
 .../gdb.base/condbreak-multi-context.exp      |  8 +-
 gdb/testsuite/gdb.base/ctxobj.exp             | 26 ++++--
 gdb/testsuite/gdb.base/ena-dis-br.exp         | 41 ++++----
 gdb/testsuite/gdb.base/foll-exec-mode.exp     |  6 +-
 gdb/testsuite/gdb.base/pie-fork.exp           |  4 +-
 gdb/testsuite/gdb.base/step-over-exit.exp     |  4 +-
 gdb/testsuite/gdb.cp/mb-inline.exp            |  4 +-
 gdb/testsuite/gdb.cp/mb-templates.exp         |  6 +-
 gdb/testsuite/gdb.cp/ovldbreak.exp            |  6 +-
 gdb/testsuite/gdb.gdb/python-helper.exp       |  4 +-
 .../gdb.mi/interrupt-thread-group.exp         |  2 +-
 .../gdb.mi/user-selected-context-sync.exp     | 35 +++++--
 gdb/testsuite/gdb.multi/multi-arch-exec.exp   |  3 +-
 .../gdb.multi/run-only-second-inf.exp         |  2 +-
 .../gdb.multi/watchpoint-multi-exit.exp       |  4 +-
 gdb/testsuite/gdb.multi/watchpoint-multi.exp  |  4 +-
 gdb/testsuite/lib/gdb.exp                     | 11 ++-
 gdb/testsuite/lib/mi-support.exp              | 20 +++-
 28 files changed, 335 insertions(+), 94 deletions(-)

diff --git a/gdb/NEWS b/gdb/NEWS
index 960f90b4387..a5602deee2b 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -34,6 +34,21 @@
      whitespace from each line before using the string as the help
      output.
 
+* When a breakpoint with multiple code locations is hit, GDB now prints
+  the code location using the syntax <breakpoint_number>.<location_number>
+  such as in:
+     Thread 1 "zeoes" hit Breakpoint 2.3, some_func () at zeoes.c:8
+
+* When a breakpoint is hit, GDB now sets the convenience variables $bkptno and
+  $locno to the hit breakpoint number and code location number.
+  This allows to disable the last hit breakpoint using
+     (gdb) disable $bkptno
+   or disable only the specific breakpoint code location using
+     (gdb) disable $bkptno.$locno
+  These commands can be used inside the command list of a breakpoint to
+  automatically disable the just encountered breakpoint (or the just
+  encountered specific breakpoint code location).
+
 * New commands
 
 maintenance set ignore-prologue-end-flag on|off
@@ -50,6 +65,12 @@ maintenance info line-table
   entry corresponds to an address where a breakpoint should be placed
   to be at the first instruction past a function's prologue.
 
+* MI changes
+
+ ** The async record stating the stopped reason 'breakpoint-hit' now
+    contains an optional field locno giving the code location number
+    when the breakpoint has multiple code locations.
+
 * Python API
 
   ** New function gdb.format_address(ADDRESS, PROGSPACE, ARCHITECTURE),
diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
index 6ab01fd27d4..bbae76f39ac 100644
--- a/gdb/ada-lang.c
+++ b/gdb/ada-lang.c
@@ -12348,7 +12348,7 @@ ada_catchpoint::print_it (const bpstat *bs) const
 
   uiout->text (disposition == disp_del
 	       ? "\nTemporary catchpoint " : "\nCatchpoint ");
-  uiout->field_signed ("bkptno", number);
+  print_num_locno (bs, uiout);
   uiout->text (", ");
 
   /* ada_exception_name_addr relies on the selected frame being the
diff --git a/gdb/break-catch-syscall.c b/gdb/break-catch-syscall.c
index 06d48466de7..82229de33f7 100644
--- a/gdb/break-catch-syscall.c
+++ b/gdb/break-catch-syscall.c
@@ -218,7 +218,7 @@ syscall_catchpoint::print_it (const bpstat *bs) const
 						: EXEC_ASYNC_SYSCALL_RETURN));
       uiout->field_string ("disp", bpdisp_text (b->disposition));
     }
-  uiout->field_signed ("bkptno", b->number);
+  print_num_locno (bs, uiout);
 
   if (last.kind () == TARGET_WAITKIND_SYSCALL_ENTRY)
     uiout->text (" (call to syscall ");
diff --git a/gdb/break-catch-throw.c b/gdb/break-catch-throw.c
index 66cf80be1c5..5b6f5d9eca1 100644
--- a/gdb/break-catch-throw.c
+++ b/gdb/break-catch-throw.c
@@ -257,7 +257,7 @@ exception_catchpoint::print_it (const bpstat *bs) const
   bp_temp = disposition == disp_del;
   uiout->text (bp_temp ? "Temporary catchpoint "
 		       : "Catchpoint ");
-  uiout->field_signed ("bkptno", number);
+  print_num_locno (bs, uiout);
   uiout->text ((kind == EX_EVENT_THROW ? " (exception thrown), "
 		: (kind == EX_EVENT_CATCH ? " (exception caught), "
 		   : " (exception rethrown), ")));
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index ed932a19ed7..c89c800f32f 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -820,6 +820,19 @@ get_breakpoint (int num)
   return nullptr;
 }
 
+/* Return TRUE if NUM refer to an existing breakpoint that has
+   multiple code locations.  */
+
+static bool
+has_multiple_locations (int num)
+{
+  for (breakpoint *b : all_breakpoints ())
+    if (b->number == num)
+      return b->loc != nullptr && b->loc->next != nullptr;
+
+  return false;
+}
+
 
 
 /* Mark locations as "conditions have changed" in case the target supports
@@ -4451,15 +4464,7 @@ bpstat_explains_signal (bpstat *bsp, enum gdb_signal sig)
   return false;
 }
 
-/* Put in *NUM the breakpoint number of the first breakpoint we are
-   stopped at.  *BSP upon return is a bpstat which points to the
-   remaining breakpoints stopped at (but which is not guaranteed to be
-   good for anything but further calls to bpstat_num).
-
-   Return 0 if passed a bpstat which does not indicate any breakpoints.
-   Return -1 if stopped at a breakpoint that has been deleted since
-   we set it.
-   Return 1 otherwise.  */
+/* See breakpoint.h.  */
 
 int
 bpstat_num (bpstat **bsp, int *num)
@@ -4481,6 +4486,57 @@ bpstat_num (bpstat **bsp, int *num)
   return 1;
 }
 
+/* See breakpoint.h  */
+
+int
+bpstat_locno (const bpstat *bs)
+{
+  const struct breakpoint *b = bs->breakpoint_at;
+  const struct bp_location *bl = bs->bp_location_at.get ();
+
+  int locno = 0;
+
+  if (b != nullptr && b->loc->next != nullptr)
+    {
+      const bp_location *bl_i;
+
+      for (bl_i = b->loc;
+	   bl_i != bl && bl_i->next != nullptr;
+	   bl_i = bl_i->next)
+	locno++;
+
+      if (bl_i == bl)
+	locno++;
+      else
+	{
+	  warning (_("location number not found for breakpoint %d address %s."),
+		   b->number, paddress (bl->gdbarch, bl->address));
+	  locno = 0;
+	}
+    }
+
+  return locno;
+}
+
+/* See breakpoint.h.  */
+
+void
+print_num_locno (const bpstat *bs, struct ui_out *uiout)
+{
+  struct breakpoint *b = bs->breakpoint_at;
+
+  if (b == nullptr)
+    uiout->text (_("deleted breakpoint"));
+  else
+    {
+      uiout->field_signed ("bkptno", b->number);
+
+      int locno = bpstat_locno (bs);
+      if (locno != 0)
+	uiout->message (".%pF", signed_field ("locno", locno));
+    }
+}
+
 /* See breakpoint.h.  */
 
 void
@@ -9176,7 +9232,7 @@ ranged_breakpoint::print_it (const bpstat *bs) const
 		      async_reason_lookup (EXEC_ASYNC_BREAKPOINT_HIT));
       uiout->field_string ("disp", bpdisp_text (disposition));
     }
-  uiout->field_signed ("bkptno", number);
+  print_num_locno (bs, uiout);
   uiout->text (", ");
 
   return PRINT_SRC_AND_LOC;
@@ -11610,12 +11666,13 @@ ordinary_breakpoint::print_it (const bpstat *bs) const
 			   async_reason_lookup (EXEC_ASYNC_BREAKPOINT_HIT));
       uiout->field_string ("disp", bpdisp_text (disposition));
     }
+
   if (bp_temp)
-    uiout->message ("Temporary breakpoint %pF, ",
-		    signed_field ("bkptno", number));
+    uiout->text ("Temporary breakpoint ");
   else
-    uiout->message ("Breakpoint %pF, ",
-		    signed_field ("bkptno", number));
+    uiout->text ("Breakpoint ");
+  print_num_locno (bs, uiout);
+  uiout->text (", ");
 
   return PRINT_SRC_AND_LOC;
 }
@@ -13220,9 +13277,13 @@ enable_disable_command (const char *args, int from_tty, bool enable)
 	  extract_bp_number_and_location (num, bp_num_range, bp_loc_range);
 
 	  if (bp_loc_range.first == bp_loc_range.second
-	      && bp_loc_range.first == 0)
+	      && (bp_loc_range.first == 0
+		  || (bp_loc_range.first == 1
+		      && bp_num_range.first == bp_num_range.second
+		      && !has_multiple_locations (bp_num_range.first))))
 	    {
-	      /* Handle breakpoint ids with formats 'x' or 'x-z'.  */
+	      /* Handle breakpoint ids with formats 'x' or 'x-z'
+		 or 'y.1' where y has only one code location.  */
 	      map_breakpoint_number_range (bp_num_range,
 					   enable
 					   ? enable_breakpoint
diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h
index 566f1285e46..96d61ef5427 100644
--- a/gdb/breakpoint.h
+++ b/gdb/breakpoint.h
@@ -1231,6 +1231,20 @@ extern enum print_stop_action bpstat_print (bpstat *, int);
    Return 1 otherwise.  */
 extern int bpstat_num (bpstat **, int *);
 
+/* If BS indicates a breakpoint and this breakpoint has several code locations,
+   return the location number of BS, otherwise return 0.  */
+
+extern int bpstat_locno (const bpstat *bs);
+
+/* Print BS breakpoint number optionally followed by a . and breakpoint locno.
+
+   For a breakpoint with only one code location, outputs the signed field
+   "bkptno" breakpoint number of BS (as returned by bpstat_num).
+   If BS has several code locations, outputs a '.' character followed by
+   the signed field "locno" (as returned by bpstat_locno).  */
+
+extern void print_num_locno (const bpstat *bs, struct ui_out *);
+
 /* Perform actions associated with the stopped inferior.  Actually, we
    just use this for breakpoint commands.  Perhaps other actions will
    go here later, but this is executed at a late time (from the
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 434add3a663..391b81f8863 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -4338,9 +4338,65 @@ are operated on.
 @cindex latest breakpoint
 Breakpoints are set with the @code{break} command (abbreviated
 @code{b}).  The debugger convenience variable @samp{$bpnum} records the
-number of the breakpoint you've set most recently; see @ref{Convenience
-Vars,, Convenience Variables}, for a discussion of what you can do with
-convenience variables.
+number of the breakpoint you've set most recently:
+@smallexample
+(gdb) b main
+Breakpoint 1 at 0x11c6: file zeoes.c, line 24.
+(gdb) p $bpnum
+$1 = 1
+@end smallexample
+
+A breakpoint may be mapped to multiple code locations for example with
+inlined functions, Ada generics, C@t{++} templates or overloaded function names.
+@value{GDBN} then indicates the number of code locations in the breakpoint
+command output:
+@smallexample
+(gdb) b some_func
+Breakpoint 2 at 0x1179: some_func. (3 locations)
+(gdb) p $bpnum
+$2 = 2
+(gdb)
+@end smallexample
+
+@vindex $bkptno@r{, convenience variable}
+@vindex $locno@r{, convenience variable}
+When your program stops on a breakpoint, the convenience variables
+@samp{$bkptno} and @samp{$locno} are respectively set to the number of
+the encountered breakpoint and the number of the breakpoint's code location:
+@smallexample
+Thread 1 "zeoes" hit Breakpoint 2.1, some_func () at zeoes.c:8
+8	  printf("some func\n");
+(gdb) p $bkptno
+$5 = 2
+(gdb) p $locno
+$6 = 1
+(gdb)
+@end smallexample
+
+Note that @samp{$bkptno} and @samp{$bpnum} are not equivalent:
+@samp{$bkptno} is set to the breakpoint number @b{last hit}, while
+@samp{$bpnum} is set to the breakpoint number @b{last set}.
+
+
+If the encountered breakpoint has only one code location, @samp{$locno} is set
+to 1:
+@smallexample
+Breakpoint 1, main (argc=1, argv=0x7fffffffe018) at zeoes.c:24
+24	  if (argc > 1)
+(gdb) p $bkptno
+$3 = 1
+(gdb) p $locno
+$4 = 1
+(gdb)
+@end smallexample
+
+The @samp{$bkptno} and @samp{$locno} variables can typically be used
+in a breakpoint command list.
+(@pxref{Break Commands, ,Breakpoint Command Lists}). For example, as
+part of the breakpoint command list, you can disable completely the
+encountered breakpoint using @samp{disable $bkptno} or disable the
+specific encountered breakpoint location using @samp{disable
+$bkptno.$locno}.
 
 @table @code
 @item break @var{locspec}
@@ -5739,6 +5795,13 @@ Expressions}).
 Pressing @key{RET} as a means of repeating the last @value{GDBN} command is
 disabled within a @var{command-list}.
 
+Inside a command list, you can use the command
+@kbd{disable $bkptno} to disable the encountered breakpoint.
+
+If your breakpoint has several code locations, the command
+@kbd{disable $bkptno.$locno} will disable the specific breakpoint code
+location encountered.
+
 You can use breakpoint commands to start your program up again.  Simply
 use the @code{continue} command, or @code{step}, or any other command
 that resumes execution.
@@ -32570,6 +32633,20 @@ line="13",arch="i386:x86_64"@}
 (gdb)
 @end smallexample
 
+For a @samp{breakpoint-hit} stopped reason, when the breakpoint
+encountered has multiple locations, the field @samp{bkptno} is
+followed by the field @samp{locno}.
+
+@smallexample
+-exec-continue
+^running
+(gdb)
+@@Hello world
+*stopped,reason="breakpoint-hit",disp="keep",bkptno="2",locno="3",frame=@{
+func="foo",args=[],file="hello.c",fullname="/home/foo/bar/hello.c",
+line="13",arch="i386:x86_64"@}
+(gdb)
+@end smallexample
 
 @subheading The @code{-exec-finish} Command
 @findex -exec-finish
diff --git a/gdb/infrun.c b/gdb/infrun.c
index 02c98b50c8c..e5ad062a914 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -8494,7 +8494,21 @@ print_stop_location (const target_waitstatus &ws)
      LOCATION: Print only location
      SRC_AND_LOC: Print location and source line.  */
   if (do_frame_printing)
-    print_stack_frame (get_selected_frame (NULL), 0, source_flag, 1);
+    {
+      if (tp->control.stop_bpstat != nullptr)
+	{
+	  const struct breakpoint *b = tp->control.stop_bpstat->breakpoint_at;
+
+	  if (b != nullptr)
+	    {
+	      int locno = bpstat_locno (tp->control.stop_bpstat);
+	      set_internalvar_integer (lookup_internalvar ("bkptno"), b->number);
+	      set_internalvar_integer (lookup_internalvar ("locno"),
+				       (locno > 0 ? locno : 1));
+	    }
+	}
+      print_stack_frame (get_selected_frame (NULL), 0, source_flag, 1);
+    }
 }
 
 /* See infrun.h.  */
diff --git a/gdb/testsuite/gdb.ada/bp_inlined_func.exp b/gdb/testsuite/gdb.ada/bp_inlined_func.exp
index 076e8c2425f..3f94c163819 100644
--- a/gdb/testsuite/gdb.ada/bp_inlined_func.exp
+++ b/gdb/testsuite/gdb.ada/bp_inlined_func.exp
@@ -42,7 +42,7 @@ gdb_test "break read_small" \
 for {set i 0} {$i < 4} {incr i} {
     with_test_prefix "iteration $i" {
 	gdb_test "continue" \
-	    "Breakpoint $decimal, b\\.read_small \\(\\).*" \
+	    "Breakpoint $bkptno_num_re, b\\.read_small \\(\\).*" \
 	    "stopped in read_small"
     }
 }
diff --git a/gdb/testsuite/gdb.ada/operator_bp.exp b/gdb/testsuite/gdb.ada/operator_bp.exp
index 655e7af479f..e3928419ed6 100644
--- a/gdb/testsuite/gdb.ada/operator_bp.exp
+++ b/gdb/testsuite/gdb.ada/operator_bp.exp
@@ -56,7 +56,7 @@ foreach op { "*" "/" "mod" "rem" "**" "<" "<=" ">" ">=" "=" "and" "or" "xor" "&"
 foreach op { "+" "-" "*" "/" "mod" "rem" "**" "<" "<=" ">" ">=" "=" "and" "or" "xor" "&" "abs" "not"} {
     set op_re [string_to_regexp $op]
     gdb_test "continue" \
-             "Breakpoint $decimal, ops\\.\"$op_re\" .*"\
+             "Breakpoint $bkptno_numopt_re, ops\\.\"$op_re\" .*"\
              "continue to \"$op\""
 }
 
@@ -86,7 +86,7 @@ foreach op { "*" "/" "mod" "rem" "**" "<" "<=" ">" ">=" "=" "and" "or" "xor" "&"
 foreach op { "+" "-" "*" "/" "mod" "rem" "**" "<" "<=" ">" ">=" "=" "and" "or" "xor" "&" "abs" "not"} {
     set op_re [string_to_regexp $op]
     gdb_test "continue" \
-             "Breakpoint $decimal, ops\\.\"$op_re\" .*"\
+             "Breakpoint $bkptno_numopt_re, ops\\.\"$op_re\" .*"\
              "continue to ops.\"$op\""
 }
 
diff --git a/gdb/testsuite/gdb.base/condbreak-multi-context.exp b/gdb/testsuite/gdb.base/condbreak-multi-context.exp
index b540df973a3..742315178e3 100644
--- a/gdb/testsuite/gdb.base/condbreak-multi-context.exp
+++ b/gdb/testsuite/gdb.base/condbreak-multi-context.exp
@@ -140,11 +140,11 @@ with_test_prefix "scenario 1" {
     gdb_run_cmd
 
     # Check our conditional breakpoints.
-    gdb_test "" ".*Breakpoint \[0-9\]+, A::func .*" \
+    gdb_test "" ".*Breakpoint $bkptno_num_re, A::func .*" \
 	"run until A::func"
     gdb_test "print a" " = 10"
 
-    gdb_test "continue" "Continuing.*Breakpoint \[0-9\]+, C::func .*" \
+    gdb_test "continue" "Continuing.*Breakpoint $bkptno_num_re, C::func .*" \
 	"run until C::func"
     gdb_test "print c" " = 30"
 
@@ -208,11 +208,11 @@ with_test_prefix "scenario 2" {
     gdb_run_cmd
 
     # Check that we hit enabled locations only.
-    gdb_test "" ".*Breakpoint \[0-9\]+, A::func .*" \
+    gdb_test "" ".*Breakpoint $bkptno_num_re, A::func .*" \
 	"run until A::func"
     gdb_test "print a" " = 10"
 
-    gdb_test "continue" "Continuing.*Breakpoint \[0-9\]+, C::func .*" \
+    gdb_test "continue" "Continuing.*Breakpoint $bkptno_num_re, C::func .*" \
 	"run until C::func"
     gdb_test "print c" " = 30"
 
diff --git a/gdb/testsuite/gdb.base/ctxobj.exp b/gdb/testsuite/gdb.base/ctxobj.exp
index 9c010f54d79..0b589a7d6e6 100644
--- a/gdb/testsuite/gdb.base/ctxobj.exp
+++ b/gdb/testsuite/gdb.base/ctxobj.exp
@@ -67,9 +67,16 @@ gdb_test "break ctxobj-f.c:$bp_location" \
          "Breakpoint \[0-9\]+ at 0x\[0-9a-fA-F\]+: .*" \
          "break in get_version functions"
 
-gdb_test "continue" \
-         "Breakpoint $decimal, get_version_1 \\(\\).*" \
-         "continue to get_version_1"
+global expect_out
+set test "continue to get_version_1"
+gdb_test_multiple "continue" $test {
+    -re "Breakpoint ($bkptno_num_re), get_version_1 \\(\\).*" {
+	set bpno $expect_out(1,string)
+	pass $test
+    }
+}
+# Verify the $bkptno.$locno convenience variables are set to the hit bpno.
+gdb_test "printf \"%d.%d\\n\", \$bkptno, \$locno" "$bpno" "$test \$bkptno.\$locno is $bpno"
 
 # Try printing "this_version_num".  There are two global variables
 # with that name, and some systems such as GNU/Linux merge them
@@ -100,10 +107,15 @@ gdb_test "print this_version_num == v" \
         "print libctxobj1's this_version_num from symtab"
 
 # Do the same, but from get_version_2.
-
-gdb_test "continue" \
-         "Breakpoint $decimal, get_version_2 \\(\\).*" \
-         "continue to get_version_2"
+set test "continue to get_version_2"
+gdb_test_multiple "continue" $test {
+    -re "Breakpoint ($bkptno_num_re), get_version_2 \\(\\).*" {
+	set bpno $expect_out(1,string)
+	pass $test
+    }
+}
+# Verify the $bkptno.$locno convenience variables are set to the hit bpno.
+gdb_test "printf \"%d.%d\\n\", \$bkptno, \$locno" "$bpno" "$test \$bkptno.\$locno is $bpno"
 
 gdb_test "print this_version_num == v" \
          " = 1" \
diff --git a/gdb/testsuite/gdb.base/ena-dis-br.exp b/gdb/testsuite/gdb.base/ena-dis-br.exp
index 24925cf7185..04b3f134b44 100644
--- a/gdb/testsuite/gdb.base/ena-dis-br.exp
+++ b/gdb/testsuite/gdb.base/ena-dis-br.exp
@@ -67,14 +67,21 @@ gdb_test "info break $bp" \
 # See the comments in condbreak.exp for "run until breakpoint at
 # marker1" for an explanation of the xfail below.
 set test "continue to break marker1"
+set bpno 0
 gdb_test_multiple "continue" "$test" {
-    -re "Breakpoint \[0-9\]*, marker1.*$gdb_prompt $" {
+    -re "Breakpoint (\[0-9\]*), marker1.*$gdb_prompt $" {
+	set bpno $expect_out(1,string)
 	pass "$test"
     }
-    -re "Breakpoint \[0-9\]*, $hex in marker1.*$gdb_prompt $" {
+    -re "Breakpoint (\[0-9\]*), $hex in marker1.*$gdb_prompt $" {
+	set bpno $expect_out(1,string)
 	xfail "$test"
     }
 }
+# Verify the $bkptno convenience variable is equal to the hit bpno.
+gdb_test "print \$bkptno" " = $bpno" "$test \$bkptno is $bpno"
+# Verify the $locno is 1, as there is only one code location.
+gdb_test "print \$locno" " = 1" "$test \$locno is 1"
 
 gdb_test_no_output "delete $bp" "delete break marker1"
 
@@ -359,7 +366,8 @@ with_test_prefix "4th breakpoint" {
 }
 
 # Perform tests for disable/enable commands on multiple
-# locations and breakpoints.
+# code locations and breakpoints.  If a breakpoint has only one code location,
+# enable/disable num  and enable/disable num.1 should be equivalent.
 #
 # WHAT - the command to test (disable/enable).
 #
@@ -372,7 +380,7 @@ proc test_ena_dis_br { what } {
     global b3
     global b4
     global gdb_prompt
-    
+
     # OPPOS    - the command opposite to WHAT.
     # WHAT_RES - whether breakpoints are expected to end
     #            up enabled or disabled.
@@ -395,13 +403,13 @@ proc test_ena_dis_br { what } {
 	set p2 "pass"
     }
 
-    # Now enable(disable) $b.1 $b2.1.
+    # Now enable(disable) $b1.1 $b2.1.
     gdb_test_no_output "$what $b1.1 $b2.1" "$what \$b1.1 \$b2.1"
     set test1 "${what}d \$b1.1 and \$b2.1"
 
     # Now $b1.1 and $b2.1 should be enabled(disabled).
     gdb_test_multiple "info break" "$test1" {
-       -re "(${b1}.1)(\[^\n\r\]*)( n.*)(${b2}.1)(\[^\n\r\]*)( n.*)$gdb_prompt $" {
+       -re "(${b1})(\[^\n\r\]*)( n.*)(${b2})(\[^\n\r\]*)( n.*)$gdb_prompt $" {
            $p1 "$test1"
        }
        -re ".*$gdb_prompt $" {
@@ -420,19 +428,16 @@ proc test_ena_dis_br { what } {
        "${what}d \$b1"
 
     gdb_test_no_output "$oppos $b3" "$oppos \$b3"
+    # Now $b4 $b3 should be enabled(disabled)
+    set test1 "${what}d \$b4 and \$b3"
+    gdb_test "info break" "(${b3})(\[^\n\r]*)( $oppos_res.*).*(${b4})(\[^\n\r\]*)( $oppos_res.*)" "$test1"
+
     gdb_test_no_output "$what $b4 $b3.1" "$what \$b4 \$b3.1"
-    set test1 "${what}d \$b4 and \$b3.1,remain ${oppos}d \$b3"
+    set test1 "${what}d \$b4 and \$b3.1, changing \$b3"
+
+    # Now $b4 $b3 should be enabled(disabled)
+    gdb_test "info break" "(${b3})(\[^\n\r]*)( $what_res.*).*(${b4})(\[^\n\r\]*)( $what_res.*)" "$test1"
 
-    # Now $b4 $b3.1 should be enabled(disabled) and
-    # $b3 should remain disabled(enabled).
-    gdb_test_multiple "info break" "$test1" {
-       -re "(${b3})(\[^\n\r]*)( $oppos_res.*)(${b3}.1)(\[^\n\r\]*)( n.*)(${b4})(\[^\n\r\]*)( $what_res.*)$gdb_prompt $" {
-           $p1 "$test1"
-       }
-       -re "(${b3})(\[^\n\r]*)( $oppos_res.*)(${b4})(\[^\n\r\]*)( $what_res.*)$gdb_prompt $" {
-           $p2 "$test1"
-       }
-    }
 
     # Now enable(disable) '$b4.1 fooobaar'.  This should error on
     # fooobaar.
@@ -443,7 +448,7 @@ proc test_ena_dis_br { what } {
 
     # $b4.1 should be enabled(disabled).
     gdb_test_multiple "info break" "$test1" {
-        -re "(${b4}.1)(\[^\n\r\]*)( n.*)$gdb_prompt $" {
+        -re "(${b4})(\[^\n\r\]*)( n.*)$gdb_prompt $" {
            $p1 "$test1"
        }
        -re ".*$gdb_prompt $" {
diff --git a/gdb/testsuite/gdb.base/foll-exec-mode.exp b/gdb/testsuite/gdb.base/foll-exec-mode.exp
index 918f3e4fd5f..cb6d975a767 100644
--- a/gdb/testsuite/gdb.base/foll-exec-mode.exp
+++ b/gdb/testsuite/gdb.base/foll-exec-mode.exp
@@ -99,7 +99,7 @@ proc do_catch_exec_test { } {
 # before re-running.
 
 proc do_follow_exec_mode_tests { mode cmd infswitch } {
-    global binfile srcfile srcfile2 testfile testfile2
+    global binfile srcfile srcfile2 testfile testfile2 bkptno_numopt_re
     global gdb_prompt
 
     with_test_prefix "$mode,$cmd,$infswitch" {
@@ -125,7 +125,7 @@ proc do_follow_exec_mode_tests { mode cmd infswitch } {
 	# Set up the output we expect to see after we execute past the exec.
 	#
 	set execd_line [gdb_get_line_number "after-exec" $srcfile2]
-	set expected_re ".*xecuting new program: .*${testfile2}.*Breakpoint .,.*${srcfile2}:${execd_line}.*$gdb_prompt $"
+	set expected_re ".*xecuting new program: .*${testfile2}.*Breakpoint ${bkptno_numopt_re},.*${srcfile2}:${execd_line}.*$gdb_prompt $"
 
 	# Set a breakpoint after the exec call if we aren't single-stepping
 	# past it.
@@ -189,7 +189,7 @@ proc do_follow_exec_mode_tests { mode cmd infswitch } {
 		send_gdb "y\n"
 		exp_continue
 	    }
-	    -re "Starting program: .*$expected_inf.*Breakpoint .,.*\r\n$gdb_prompt $" {
+	    -re "Starting program: .*$expected_inf.*Breakpoint $bkptno_numopt_re,.*\r\n$gdb_prompt $" {
 		pass $test
 	    }
 	}
diff --git a/gdb/testsuite/gdb.base/pie-fork.exp b/gdb/testsuite/gdb.base/pie-fork.exp
index efc357d39a2..19e9d3a5537 100644
--- a/gdb/testsuite/gdb.base/pie-fork.exp
+++ b/gdb/testsuite/gdb.base/pie-fork.exp
@@ -54,10 +54,10 @@ proc_with_prefix test_detach_on_fork_follow_child {} {
 proc_with_prefix test_no_detach_on_fork {} {
     setup_test "off"
 
-    gdb_test "continue" "\r\nThread 1.1 .* hit Breakpoint 2, break_here.*" \
+    gdb_test "continue" "\r\nThread 1.1 .* hit Breakpoint 2.1, break_here.*" \
 	     "continue from thread 1.1"
     gdb_test "thread 2.1"
-    gdb_test "continue" "\r\nThread 2.1 .* hit Breakpoint 2, break_here.*" \
+    gdb_test "continue" "\r\nThread 2.1 .* hit Breakpoint 2.2, break_here.*" \
 	     "continue from thread 2.1"
 }
 
diff --git a/gdb/testsuite/gdb.base/step-over-exit.exp b/gdb/testsuite/gdb.base/step-over-exit.exp
index f8bd99980fe..575319c564c 100644
--- a/gdb/testsuite/gdb.base/step-over-exit.exp
+++ b/gdb/testsuite/gdb.base/step-over-exit.exp
@@ -91,7 +91,7 @@ delete_breakpoints
 
 gdb_test "break marker"
 
-gdb_test "continue" "Continuing\\..*Breakpoint $decimal, .*" \
+gdb_test "continue" "Continuing\\..*Breakpoint $bkptno_num_re, .*" \
     "continue to marker, first time"
 
 # Step 2, create a breakpoint which evaluates false, and force it
@@ -120,5 +120,5 @@ gdb_test "inferior 1" ".*Switching to inferior 1.*" \
 # Switch back to the parent process, continue to the marker to
 # test GDBserver's state is still correct.
 
-gdb_test "continue" "Continuing\\..*Breakpoint $decimal, .*" \
+gdb_test "continue" "Continuing\\..*Breakpoint $bkptno_numopt_re, .*" \
     "continue to marker, second time"
diff --git a/gdb/testsuite/gdb.cp/mb-inline.exp b/gdb/testsuite/gdb.cp/mb-inline.exp
index 47a2a5dcb7c..fa098602c31 100644
--- a/gdb/testsuite/gdb.cp/mb-inline.exp
+++ b/gdb/testsuite/gdb.cp/mb-inline.exp
@@ -46,7 +46,7 @@ gdb_test "info break" \
     "\[\r\n\]1\.1.* y .* at .*$hdrfile:$bp_location.*\[\r\n\]1\.2.* y .* at .*$hdrfile:$bp_location.*"
 
 gdb_run_cmd
-gdb_test "" "Breakpoint \[0-9\]+,.*foo \\(i=0\\).*" "run to breakpoint"
+gdb_test "" "Breakpoint $bkptno_num_re,.*foo \\(i=0\\).*" "run to breakpoint"
 
 gdb_test "continue" \
     ".*Breakpoint.*foo \\(i=1\\).*" \
@@ -59,7 +59,7 @@ gdb_test "continue" \
 gdb_test_no_output "disable 1.2" "disabling location: disable"
 
 gdb_run_cmd
-gdb_test "" "Breakpoint \[0-9\]+,.*foo \\(i=0\\).*" "disabling location: run to breakpoint"
+gdb_test "" "Breakpoint $bkptno_num_re,.*foo \\(i=0\\).*" "disabling location: run to breakpoint"
 
 gdb_test_multiple "info break" "disabled breakpoint 1.2" {
     -re "1\.2.* n .* at .*$hdrfile:$bp_location.*$gdb_prompt $" {
diff --git a/gdb/testsuite/gdb.cp/mb-templates.exp b/gdb/testsuite/gdb.cp/mb-templates.exp
index 6c988e7335e..0c0d46fcb7a 100644
--- a/gdb/testsuite/gdb.cp/mb-templates.exp
+++ b/gdb/testsuite/gdb.cp/mb-templates.exp
@@ -42,7 +42,7 @@ gdb_run_cmd
 
 set test "initial condition: run to breakpoint"
 gdb_test_multiple "" $test {
-    -re "Breakpoint \[0-9\]+,.*foo<int> \\(i=1\\).*$gdb_prompt $" {
+    -re "Breakpoint $bkptno_num_re,.*foo<int> \\(i=1\\).*$gdb_prompt $" {
 	pass $test
 	break
     }
@@ -67,7 +67,7 @@ gdb_test_no_output {condition $bpnum i==1} \
     "separate condition: set condition"
     
 gdb_run_cmd
-gdb_test "" "Breakpoint \[0-9\]+,.*foo<int> \\(i=1\\).*" "separate condition: run to breakpoint"
+gdb_test "" "Breakpoint $bkptno_num_re,.*foo<int> \\(i=1\\).*" "separate condition: run to breakpoint"
 
 gdb_test "continue" \
     ".*Breakpoint.*foo<double> \\(i=1\\).*" \
@@ -79,7 +79,7 @@ gdb_test "continue" \
 gdb_test_no_output {disable $bpnum.1} "disabling location: disable"
 
 gdb_run_cmd
-gdb_test "" "Breakpoint \[0-9\]+,.*foo<double> \\(i=1\\).*" "disabling location: run to breakpoint"
+gdb_test "" "Breakpoint $bkptno_num_re,.*foo<double> \\(i=1\\).*" "disabling location: run to breakpoint"
 
 # Try disabling entire breakpoint
 gdb_test_no_output {enable $bpnum.1} "disabling location: enable"
diff --git a/gdb/testsuite/gdb.cp/ovldbreak.exp b/gdb/testsuite/gdb.cp/ovldbreak.exp
index 06adf82ecbb..0ed9eae055b 100644
--- a/gdb/testsuite/gdb.cp/ovldbreak.exp
+++ b/gdb/testsuite/gdb.cp/ovldbreak.exp
@@ -380,7 +380,7 @@ gdb_test "info break" $bptable "breakpoint info (after setting on all)"
 
 # Run through each breakpoint.
 proc continue_to_bp_overloaded {bpnumber might_fail line argtype argument} {
-    global gdb_prompt hex decimal srcfile
+    global gdb_prompt hex decimal srcfile bkptno_num_re
 
     if {$argument == ""} {
         set actuals ""
@@ -398,11 +398,11 @@ proc continue_to_bp_overloaded {bpnumber might_fail line argtype argument} {
     }
 
     gdb_test_multiple "continue" "continue to bp overloaded : $argtype" {
-        -re "Continuing.\r\n\r\nBreakpoint $bpnumber, foo::overload1arg \\(this=${hex}(, )?$actuals\\) at .*$srcfile:$line\r\n$decimal\[\t \]+{ $body }.*$gdb_prompt $" {
+        -re "Continuing.\r\n\r\nBreakpoint $bkptno_num_re, foo::overload1arg \\(this=${hex}(, )?$actuals\\) at .*$srcfile:$line\r\n$decimal\[\t \]+{ $body }.*$gdb_prompt $" {
             pass "continue to bp overloaded : $argtype"
         }
 
-        -re "Continuing.\r\n\r\nBreakpoint $bpnumber, foo::overload1arg \\(this=${hex}, arg=.*\\) at .*$srcfile:$line\r\n$decimal\[\t \]+{ $body }.*$gdb_prompt $" {
+        -re "Continuing.\r\n\r\nBreakpoint $bkptno_num_re, foo::overload1arg \\(this=${hex}, arg=.*\\) at .*$srcfile:$line\r\n$decimal\[\t \]+{ $body }.*$gdb_prompt $" {
             if $might_kfail {
                 kfail "c++/8130" "continue to bp overloaded : $argtype"
             } else {
diff --git a/gdb/testsuite/gdb.gdb/python-helper.exp b/gdb/testsuite/gdb.gdb/python-helper.exp
index 6db8bf0df50..30eb6038f3a 100644
--- a/gdb/testsuite/gdb.gdb/python-helper.exp
+++ b/gdb/testsuite/gdb.gdb/python-helper.exp
@@ -49,7 +49,7 @@ gdb_exit
 # The main test.  This is called by the self-test framework once GDB
 # has been started on a copy of itself.
 proc test_python_helper {} {
-    global py_helper_script decimal hex gdb_prompt
+    global py_helper_script decimal hex gdb_prompt bkptno_numopt_re
     global inferior_spawn_id
 
     # Source the python helper script.  This script registers the
@@ -233,7 +233,7 @@ proc test_python_helper {} {
     # GDB stopping at the value_print breakpoint again.
     send_inferior "ptype global_c\n"
     gdb_test_multiple "" "hit breakpoint in outer gdb again" {
-	-re "Breakpoint $decimal, c_print_type .*\\(outer-gdb\\) $" {
+	-re "Breakpoint $bkptno_numopt_re, c_print_type .*\\(outer-gdb\\) $" {
 	    pass $gdb_test_name
 	}
     }
diff --git a/gdb/testsuite/gdb.mi/interrupt-thread-group.exp b/gdb/testsuite/gdb.mi/interrupt-thread-group.exp
index 19ccbe85e04..c080955049c 100644
--- a/gdb/testsuite/gdb.mi/interrupt-thread-group.exp
+++ b/gdb/testsuite/gdb.mi/interrupt-thread-group.exp
@@ -69,7 +69,7 @@ if { $use_second_inferior } {
 	"\\^running.*" \
 	"run inferior 2"
 
-    mi_expect_stop "breakpoint-hit" "all_threads_started" ".*" ".*" ".*" {"" "disp=\"keep\""} \
+    mi_expect_stop "breakpoint-hit" "all_threads_started" ".*" ".*" ".*" {"" "disp=\"keep\"" "locno=\"[0-9]+\""} \
 	"inferior i2 stops at all_threads_started"
 
     mi_send_resuming_command "exec-continue --thread-group i2" \
diff --git a/gdb/testsuite/gdb.mi/user-selected-context-sync.exp b/gdb/testsuite/gdb.mi/user-selected-context-sync.exp
index d78c96ddef1..9eec083068b 100644
--- a/gdb/testsuite/gdb.mi/user-selected-context-sync.exp
+++ b/gdb/testsuite/gdb.mi/user-selected-context-sync.exp
@@ -307,8 +307,13 @@ proc test_continue_to_start { mode inf } {
 
 	    # Consume MI event output.
 	    with_spawn_id $mi_spawn_id {
-		mi_expect_stop "breakpoint-hit" "main" "" "$srcfile" \
-		    "$decimal" {"" "disp=\"del\""} "stop at breakpoint in main"
+		if { $inf == 1 } {
+		    mi_expect_stop "breakpoint-hit" "main" "" "$srcfile" \
+			"$decimal" {"" "disp=\"del\""} "stop at breakpoint in main"
+		} else {
+		    mi_expect_stop "breakpoint-hit" "main" "" "$srcfile" \
+			"$decimal" {"" "disp=\"del\"" "locno=\"[0-9]+\""} "stop at breakpoint in main"
+		}
 	    }
 
 	    if { $mode == "all-stop" } {
@@ -330,9 +335,15 @@ proc test_continue_to_start { mode inf } {
 
 		    # Consume MI output.
 		    with_spawn_id $mi_spawn_id {
-			mi_expect_stop "breakpoint-hit" "child_sub_function" \
-			    "" "$srcfile" "$decimal" {"" "disp=\"del\""} \
-			    "thread $inf.$thread stops MI"
+			if { $inf == 1} {
+			    mi_expect_stop "breakpoint-hit" "child_sub_function" \
+				"" "$srcfile" "$decimal" {"" "disp=\"del\""} \
+				"thread $inf.$thread stops MI"
+			} else {
+			    mi_expect_stop "breakpoint-hit" "child_sub_function" \
+				"" "$srcfile" "$decimal" {"" "disp=\"del\"" "locno=\"[0-9]+\""} \
+				"thread $inf.$thread stops MI"
+			}
 		    }
 		}
 
@@ -359,9 +370,15 @@ proc test_continue_to_start { mode inf } {
 
 		# Consume MI output.
 		with_spawn_id $mi_spawn_id {
-		    mi_expect_stop "breakpoint-hit" "child_sub_function" \
-			"" "$srcfile" "$decimal" {"" "disp=\"del\""} \
-			"thread $inf.2 stops MI"
+		    if { $inf == 1} {
+			mi_expect_stop "breakpoint-hit" "child_sub_function" \
+			    "" "$srcfile" "$decimal" {"" "disp=\"del\""} \
+			    "thread $inf.2 stops MI"
+		    } else {
+			mi_expect_stop "breakpoint-hit" "child_sub_function" \
+			    "" "$srcfile" "$decimal" {"" "disp=\"del\"" "locno=\"[0-9]+\""} \
+			    "thread $inf.2 stops MI"
+		    }
 		}
 	    }
 	}
@@ -434,7 +451,7 @@ proc_with_prefix test_setup { mode } {
 
 	with_spawn_id $mi_spawn_id {
 	    mi_expect_stop "breakpoint-hit" "main" "" "$srcfile" "$decimal" \
-		{"" "disp=\"del\""} "main stop"
+		{"" "disp=\"del\"" "locno=\"[0-9]+\""} "main stop"
 	}
 
 	# Consume CLI output.
diff --git a/gdb/testsuite/gdb.multi/multi-arch-exec.exp b/gdb/testsuite/gdb.multi/multi-arch-exec.exp
index a1496fb5571..dfdb746c65e 100644
--- a/gdb/testsuite/gdb.multi/multi-arch-exec.exp
+++ b/gdb/testsuite/gdb.multi/multi-arch-exec.exp
@@ -148,6 +148,7 @@ proc build_executables { first_arch } {
 }
 
 proc do_test { first_arch mode selected_thread } {
+        global bkptno_numopt_re
 	set from_exec "$first_arch-multi-arch-exec"
 
 	clean_restart ${from_exec}
@@ -169,7 +170,7 @@ proc do_test { first_arch mode selected_thread } {
 
 	# Test that GDB updates the target description / arch successfuly
 	# after the exec.
-	gdb_test "continue" "Breakpoint 2, main.*" "continue across exec that changes architecture"
+	gdb_test "continue" "Breakpoint $bkptno_numopt_re, main.*" "continue across exec that changes architecture"
 }
 
 # Test both arch1=>arch2 and arch2=>arch1.
diff --git a/gdb/testsuite/gdb.multi/run-only-second-inf.exp b/gdb/testsuite/gdb.multi/run-only-second-inf.exp
index fec2575f904..b94689d0bfa 100644
--- a/gdb/testsuite/gdb.multi/run-only-second-inf.exp
+++ b/gdb/testsuite/gdb.multi/run-only-second-inf.exp
@@ -46,5 +46,5 @@ gdb_load $binfile
 if {[gdb_start_cmd] < 0} {
     fail "start the second inf"
 } else {
-    gdb_test "" ".*reakpoint ., main .*${srcfile}.*" "start the second inf"
+    gdb_test "" ".*reakpoint $bkptno_numopt_re, main .*${srcfile}.*" "start the second inf"
 }
diff --git a/gdb/testsuite/gdb.multi/watchpoint-multi-exit.exp b/gdb/testsuite/gdb.multi/watchpoint-multi-exit.exp
index cbccba19d12..3c079facced 100644
--- a/gdb/testsuite/gdb.multi/watchpoint-multi-exit.exp
+++ b/gdb/testsuite/gdb.multi/watchpoint-multi-exit.exp
@@ -27,7 +27,7 @@ if {[build_executable "failed to build" $testfile $srcfile {debug}]} {
 # child.  Can be either "kill", "detach", or "exit" (to continue it to
 # normal exit).
 proc do_test {dispose} {
-    global binfile
+    global binfile bkptno_numopt_re
 
     clean_restart $binfile
 
@@ -77,7 +77,7 @@ proc do_test {dispose} {
     #  Command aborted.
     #  (gdb)
     #
-    gdb_test "continue" "Breakpoint \[0-9\]+, marker .*" \
+    gdb_test "continue" "Breakpoint $bkptno_numopt_re, marker .*" \
 	"continue in inferior 1"
 }
 
diff --git a/gdb/testsuite/gdb.multi/watchpoint-multi.exp b/gdb/testsuite/gdb.multi/watchpoint-multi.exp
index e4329dca6c2..0fc1bee762f 100644
--- a/gdb/testsuite/gdb.multi/watchpoint-multi.exp
+++ b/gdb/testsuite/gdb.multi/watchpoint-multi.exp
@@ -84,11 +84,11 @@ if [skip_hw_watchpoint_multi_tests] {
 	"Hardware access \\(read/write\\) watchpoint \[0-9\]+: c\r\n\r\nOld value = 0\r\nNew value = 3\r\n.*" \
 	"catch c on inferior 2"
 
-    gdb_test "continue" "Breakpoint \[0-9\]+, marker_exit .*" "catch marker_exit in inferior 2"
+    gdb_test "continue" "Breakpoint $bkptno_numopt_re, marker_exit .*" "catch marker_exit in inferior 2"
 
     gdb_test "inferior 1" "witching to inferior 1 .*" "switch back to inferior 1 again"
 
     gdb_test "continue" "Hardware access \\(read/write\\) watchpoint \[0-9\]+: b\r\n\r\nOld value = 0\r\nNew value = 2\r\n.*" "catch b on inferior 1"
 }
 
-gdb_test "continue" "Breakpoint \[0-9\]+, marker_exit .*" "catch marker_exit in inferior 1"
+gdb_test "continue" "Breakpoint $bkptno_numopt_re, marker_exit .*" "catch marker_exit in inferior 1"
diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
index 402450152ac..5e4c793598e 100644
--- a/gdb/testsuite/lib/gdb.exp
+++ b/gdb/testsuite/lib/gdb.exp
@@ -227,6 +227,14 @@ set inferior_exited_re "(?:\\\[Inferior \[0-9\]+ \\(\[^\n\r\]*\\) exited)"
 # E.g., $1, $2, etc.
 set valnum_re "\\\$$decimal"
 
+# A regular expression that matches a breakpoint hit with a breakpoint
+# having several code locations.
+set bkptno_num_re "$decimal\\.$decimal"
+
+# A regular expression that matches a breakpoint hit
+# with one or several code locations.
+set bkptno_numopt_re "($decimal\\.$decimal|$decimal)"
+
 ### Only procedures should come after this point.
 
 #
@@ -662,6 +670,7 @@ proc gdb_breakpoint { linespec args } {
 
 proc runto { linespec args } {
     global gdb_prompt
+    global bkptno_numopt_re
     global decimal
 
     delete_breakpoints
@@ -699,7 +708,7 @@ proc runto { linespec args } {
 	    }
 	    return 1
 	}
-	-re "Breakpoint \[0-9\]*, \[0-9xa-f\]* in .*$gdb_prompt $" { 
+	-re "Breakpoint $bkptno_numopt_re, \[0-9xa-f\]* in .*$gdb_prompt $" {
 	    if { $print_pass } {
 		pass $test_name
 	    }
diff --git a/gdb/testsuite/lib/mi-support.exp b/gdb/testsuite/lib/mi-support.exp
index e578a7e6f9b..ea66fdcabf8 100644
--- a/gdb/testsuite/lib/mi-support.exp
+++ b/gdb/testsuite/lib/mi-support.exp
@@ -1195,11 +1195,11 @@ proc mi_detect_async {} {
 # filename of a file without debug info.  ARGS should not include [] the
 # list of argument is enclosed in, and other regular expressions should
 # not include quotes.
-# If EXTRA is a list of one element, it's the regular expression
+# EXTRA can be a list of one, two or three elements.
+# The first element is the regular expression
 # for output expected right after *stopped, and before GDB prompt.
-# If EXTRA is a list of two elements, the first element is for
-# output right after *stopped, and the second element is output
-# right after reason field.  The regex after reason should not include
+# The third element is the regulation expression for the locno
+# right after bkptno field.  The locno regex should not include
 # the comma separating it from the following fields.
 #
 # When we fail to match output at all, -1 is returned.  If FILE does
@@ -1224,7 +1224,14 @@ proc mi_expect_stop { reason func args file line extra test } {
 
     set after_stopped ""
     set after_reason ""
-    if { [llength $extra] == 2 } {
+    set locno ""
+    if { [llength $extra] == 3 } {
+	set after_stopped [lindex $extra 0]
+	set after_reason [lindex $extra 1]
+	set after_reason "${after_reason},"
+	set locno [lindex $extra 2]
+	set locno "${locno},"
+    } elseif { [llength $extra] == 2 } {
 	set after_stopped [lindex $extra 0]
 	set after_reason [lindex $extra 1]
 	set after_reason "${after_reason},"
@@ -1298,10 +1305,12 @@ proc mi_expect_stop { reason func args file line extra test } {
     set ebn ""
     if { $reason == "breakpoint-hit" } {
 	set bn {bkptno="[0-9]+",}
+	set bn "${bn}${locno}"
     } elseif { $reason == "solib-event" } {
 	set bn ".*"
     } elseif { $reason == "exception-caught" } {
 	set ebn {bkptno="[0-9]+",}
+	set ebn "${ebn}${locno}"
 	set bn ".*"
 	set reason "breakpoint-hit"
     }
@@ -1315,6 +1324,7 @@ proc mi_expect_stop { reason func args file line extra test } {
     set a $after_reason
 
     verbose -log "mi_expect_stop: expecting: \\*stopped,${ebn}${r}${a}${bn}frame=\{addr=\"$hex\",func=\"$func\",args=$args,(?:file=\"$any$file\",fullname=\"${fullname_syntax}$file\",line=\"$line\",arch=\"$any\"|from=\"$file\")\}$after_stopped,thread-id=\"$decimal\",stopped-threads=$any\r\n($thread_selected_re|$breakpoint_re)*$prompt_re"
+
     gdb_expect {
 	-re "\\*stopped,${ebn}${r}${a}${bn}frame=\{addr=\"$hex\",func=\"$func\",args=$args,(?:file=\"$any$file\",fullname=\"${fullname_syntax}$file\",line=\"($line)\",arch=\"$any\"|from=\"$file\")\}$after_stopped,thread-id=\"$decimal\",stopped-threads=$any\r\n($thread_selected_re|$breakpoint_re)*$prompt_re" {
 	    pass "$test"
-- 
2.30.2



More information about the Gdb-patches mailing list