From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mailsec201.isp.belgacom.be (mailsec201.isp.belgacom.be [195.238.22.97]) by sourceware.org (Postfix) with ESMTPS id 7A1713858D3C for ; Sun, 14 Aug 2022 14:08:11 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 7A1713858D3C X-ExtLoop: 1 X-IPAS-Result: =?us-ascii?q?A2ARAQDZAPli/1uGgG0NTYEJCYFGgXyHUJEMA4ETj0WMJ?= =?us-ascii?q?IF8CwEBAQEBAQEBAQlCBAEBhQcChHomNAkOAQIEAQEBAQMCAwEBAQEBAQMBA?= =?us-ascii?q?QYBAQEBAQEGBAGBG4Uvgnsig2wBAQEDGgEIBAsBVgkCEgYCAiYCAkkOM2KBK?= =?us-ascii?q?ZEWmxp6fzKBAYRwgyyBZYERLIZQZVCDKYQZN4FVRIEVgTyBNzc+iBqCZQSVX?= =?us-ascii?q?wGDDBw4AxorHkIDC1IICRcSEBACBBEaCwYDFj0JAgQOA0AIDQMRBAMPGAkSC?= =?us-ascii?q?BAEBgMxDCULAxQMAQYDBgUDAQMbAxQDBSQHAxkPIw0NBBgHHQMDBSUDAgIbB?= =?us-ascii?q?wICAwIGFQYCAk45CAQIBCsjDwUCBy8FBC8CHgQFBhEIAhYCBgQEBAQVAhAIA?= =?us-ascii?q?ggnFwcTGBsZAQVZEAkhHA4aCgYFBhMDIG0FCjsPKDM1PBAbHxsKgRIqKRUDB?= =?us-ascii?q?AQDAgYTAwMiAhAuMQMVBikTEi0HKnUJAgMiaQUDAwQoLAMJHx8HCSImPQUFX?= =?us-ascii?q?zoBBAMemQkBPi0HASwEKAEYAgcTARsUK0wKGy0EGwEmAR0MCx4UkWkjBwKOL?= =?us-ascii?q?4NFm2d9NAeDVYE+BgyeUTKDdpMrkUqXAqFxKwgxhQSBYYIVbVOCaFAojiwWF?= =?us-ascii?q?Y4bgS4CBgEKAQEDCYZ4LIE/XQEB?= IronPort-PHdr: A9a23:5aYMHh3PgHleYXwIsmDOVQQyDhhOgF0UFjAc5pdvsb9SaKPrp82kY BaEo68w1BSWB83y0LFts6LuqafuWGgNs96qkUspV9hybSIDktgchAc6AcSIWgXRJf/uaDEmT owZDAc2t360PlJIF8ngelbcvmO97SIIGhX4KAF5Ovn5FpTdgsip2e2+4YPfbgVUiDayY75+M gi9oBnMuMURnYZsMLs6xAHTontPdeRWxGdoKkyWkh3h+Mq+/4Nt/jpJtf45+MFOTav1f6IjT bxFFzsmKHw65NfqtRbYUwSC4GYXX3gMnRpJBwjF6wz6Xov0vyDnuOdxxDWWMMvrRr0yRD+s7 bpkSAXwhSkEKjA38H/ZhMJyg6JVvB2uqRNwzYHPbYGJN/dzZL/Rcc8ASGdDWMtaSixPApm7b 4sKF+cPJ+ZYr4j5p1sPtRu+HRejD/7vxTBSnH/22rQ60/kgEQ7YxgwgBM8FvXPMrNX1NacSV eG1zLHQzTrddf9X1y3y6JLPchA4vPGMXKx/cdDKyUQ0DAPFjVWRqYr7MDOJzOgCqHaU4vNmW OmyhGEptxt/rSKzxscwlIbJnIQVx0jF+Ch5zog7KsO0RUx0bNK6DJdeuCOXOot2T88/XWxkp SQ3x6MbtZKlYSQH1pQqygLDZvGGfYWE/BzuWPiVLDtkgn9uZbGxhw6q/ES91uHxUtO43EtUo idGiNXAq34A2hPJ5sWDV/dw+Fqq1yyV2ADJ8O5EJFg5la/cK5E83LE9joETsUHfHi/un0X2k bOWel0k+ue27+TnZa3rqZuBO4JwlA3yKLkil828DOgiLwQCRXWX9OC627H7/E35RqtFjuEun 6XErJzXId4XqrOnDwJWyIov9hiyAji83NkcgHULNFdFdwiGj4jtNVHOOvf4DfKnjlS0kDdrx vTGPrz5ApXVMHfPirngcqxn605b0Qoz0NFf6IxOCrEaO//zQUzxtdzeDhAnLwy42f3oB8tl2 oMYQm2AGrWZP7/KsV+U+uIvJPGBaJINtDbnN/cl/+LujWM+mVIFcqmmwIAYZGmgHvt8P0WWf XrsjckaEWoRpQo+S/HqiEeeXjFNaXe9Rbg86S8hBIKhF4fDSdPlvLvU0yuxW4VfemtGB0ukC nD1bY6JRP4WZWSVOMAyvCYDUO2ZS44l1Am2uUfFwqBgN/fV9zcD/cb71Nlx5vXLmFct/CZzF tmc3nuWZ3p3j2UFW3k80fYs8gRG1l6f3P0g0LRjHttJ6qYROjo= IronPort-Data: A9a23:mOUktqPMfA4JX0DvrR0NlcFynXyQoLVcMsEvi/4bfWQNrUp23zQPz mQXC2rQa/qKajeje41xO4myphxT7MKDz95lG3M5pCpnJ55oRWopJjg4wmPYZX76whjrFRo/h ykmQoCcaphyFxcwnz/1WlTbhSAUOZqgG/ytU4YoBggrHVU+EHd40ko48wIEqtcAbeaRUlvlV eza/pW31G+Ng1aY5UpNtspvADs21BjDkGtwUm4WPJinj3eC/5UhN6/zEInqR5fOria4KcbhL wrL5OnREmo0ZH7BAPv9+lrwWhVirrI/oWFih1IOM5VOjCSuqQRi1L44KPkYNHt5oG7Sv4gs7 vxunLuvHFJB0q3kwIzxUjFrSnAke/QYqPmeZyHuhKR/zWWfKyqqmq8+ShhtYctJo46bAkkXn RAcACgNbxSCn/q7hq2yUO51m8UuNtLDJ4AOvHx8izvUZRojacqfG/mStIIDtNs2ruZoEK/hP ZdEVSt+bA7GRE0UOFIFLY1ryY9EgVG6KVW0smm9qqY9pnDa0Adx3aPFK93IYNeHWsxPkwCfv G2uwojiKkBDcoXElX/cqCLp37ee2yr3Q4ZXGKy+sP9xmBuZy2gcARYRUB2xrJFVl3KDZj6WE GRMkgJGkET43BXDogXVN/FznJJIUtPwlTad/y3WJTxhEpbp3js= IronPort-HdrOrdr: A9a23:tSBwgK9x+/ZD/zFc9qpuk+AII+orL9Y04lQ7vn2ZLiYlCPBw9v re58jzsCWetN9/YhwdcK+7Sc69qB/nn6KdmLNhRYtKPzOGhILLFvAA0WK4+UyHJ8SWzIc06U 4HScZD4bbLYWSS4/yU3OD2KadF/PC3tISlgezT1B5WPGNXQpAl0D5FOj+2e3cGPTWvR/ICdK Z0TfA3wgadRQ== X-IronPort-Anti-Spam-Filtered: true Received: from 91.134-128-109.adsl-dyn.isp.belgacom.be (HELO [192.168.1.19]) ([109.128.134.91]) by relay.proximus.be with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 14 Aug 2022 16:08:19 +0200 Message-ID: <33509176030d9d99ff4dab5c52704fcee7abc7be.camel@skynet.be> Subject: Re: [RFAv3] Show locno for 'multi location' breakpoint hit msg+conv var $bkptno $locno. From: Philippe Waroquiers To: gdb-patches@sourceware.org Date: Sun, 14 Aug 2022 16:08:05 +0200 In-Reply-To: <20220606094504.744323-1-philippe.waroquiers@skynet.be> References: <20220606094504.744323-1-philippe.waroquiers@skynet.be> Content-Type: text/plain; charset="UTF-8" User-Agent: Evolution 3.38.3-1 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-11.0 required=5.0 tests=BAYES_00, BODY_8BITS, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_LOW, SPF_HELO_NONE, SPF_PASS, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 14 Aug 2022 14:08:17 -0000 Ping ^ 7 (Eli reviewed the doc, Keith did a first review) Thanks Philippe On Mon, 2022-06-06 at 11:45 +0200, Philippe Waroquiers wrote: > 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 . > + 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 \\(i=1\\).*$gdb_prompt $" { > + -re "Breakpoint $bkptno_num_re,.*foo \\(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 \\(i=1\\).*" "separate condition: run to breakpoint" > +gdb_test "" "Breakpoint $bkptno_num_re,.*foo \\(i=1\\).*" "separate condition: run to breakpoint" >   > >  gdb_test "continue" \ >      ".*Breakpoint.*foo \\(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 \\(i=1\\).*" "disabling location: run to breakpoint" > +gdb_test "" "Breakpoint $bkptno_num_re,.*foo \\(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"