From patchwork Mon Oct 23 10:07:08 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Xavier Roirand X-Patchwork-Id: 23759 Received: (qmail 23248 invoked by alias); 23 Oct 2017 10:07:17 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 23230 invoked by uid 89); 23 Oct 2017 10:07:16 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-25.5 required=5.0 tests=BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_BRBL_LASTEXT, RCVD_IN_DNSWL_NONE, SPF_PASS autolearn=ham version=3.3.2 spammy=b2, $b2, 2.3, inclusive X-HELO: smtp.eu.adacore.com Received: from mel.act-europe.fr (HELO smtp.eu.adacore.com) (194.98.77.210) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 23 Oct 2017 10:07:12 +0000 Received: from localhost (localhost [127.0.0.1]) by filtered-smtp.eu.adacore.com (Postfix) with ESMTP id C8FAA81850; Mon, 23 Oct 2017 12:07:09 +0200 (CEST) Received: from smtp.eu.adacore.com ([127.0.0.1]) by localhost (smtp.eu.adacore.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 3uZl1s3c771J; Mon, 23 Oct 2017 12:07:09 +0200 (CEST) Received: from Xaviers-MacBook-Pro.local (unknown [46.18.100.10]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.eu.adacore.com (Postfix) with ESMTPSA id 7A01681399; Mon, 23 Oct 2017 12:07:09 +0200 (CEST) Subject: [RFA v4] enable/disable sub breakpoint range To: Pedro Alves , gdb-patches@sourceware.org References: <83lgks1e1h.fsf@gnu.org> <57a9cdc7-a5fc-0852-8ebe-c7c32c78d475@adacore.com> <77911433-028a-ee7c-e617-eb1fd84f65c0@redhat.com> From: Xavier Roirand Message-ID: Date: Mon, 23 Oct 2017 12:07:08 +0200 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:52.0) Gecko/20100101 Thunderbird/52.4.0 MIME-Version: 1.0 In-Reply-To: <77911433-028a-ee7c-e617-eb1fd84f65c0@redhat.com> X-IsSubscribed: yes Hello, Seems that my v3 patch sent in my previous email was not merging fine so here's a rebased version. Hope it will work better. ----- Allow enabling/disabling breakpoint location range In some cases, adding one breakpoint corresponds to multiple places in a program thus leads GDB to define main breakpoint number and other breakpoints using location number with syntax: . For example: Num Type Disp Enb Address What 1 breakpoint keep y 1.1 y 0x080486a2 in void foo()... 1.2 y 0x080486ca in void foo()... In this example, main breakpoint is breakpoint 1 where location breakpoints are 1.1 and 1.2 ones. This patch allows enable/disable a range of breakpoint locations using syntax: .- with inclusive last_location_number. For instance, if adding a breakpoint to foo() generates 5 breakpoint locations from 1.1 to 1.5 then it's now possible to enable/disable only location breakpoint 1.3 to location breakpoint 1.5 (so 1.3, 1.4 and 1.5) using syntax: enable 1.3-5 or disable 1.3-5 gdb/ChangeLog: * breakpoint.c (map_breakpoint_number_range): Create from map_breakpoint_numbers refactoring. (map_breakpoint_numbers): Refactor by calling map_breakpoint_number_range. (find_location_by_number): Change parameters from string to breakpoint number and location. (extract_bp_number_and_location): New function. (enable_disable_bp_num_loc): Create from enable/disable_command refactoring. (enable_disable_command): Create from enable/disable_command refactoring. (enable_command): Refactor using enable_disable_command. (disable_command): Refactor using enable_disable_command. * NEWS: Document enable/disable location range feature. gdb/doc/ChangeLog: * gdb.texinfo (Set Breaks): Add documentation for location breakpoint range enable/disable action. gdb/testsuite/ChangeLog: * gdb.cp/locbprange.exp: New test scenario. * gdb.cp/locbprange.cc: New test. + "breakpoint info disable 2.8 to 2.6" diff --git a/gdb/NEWS b/gdb/NEWS index fbf5591..76d7cec 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -75,6 +75,11 @@ QSetWorkingDir * The "maintenance selftest" command now takes an optional argument to filter the tests to be run. +* Breakpoint commands accept location ranges. + +The breakpoint commands ``enable'', and ``disable'' now accept a +location range of breakpoints, e.g. ``1.3-5''. + * New commands set|show cwd diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index 32ceea7..c5a84eb 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -93,9 +93,18 @@ enum exception_event_kind /* Prototypes for local functions. */ +static void disable_command (char *, int); + +static void enable_command (char *, int); + +static void map_breakpoint_number_range (std::pair &bp_num_range, + gdb::function_view); + static void map_breakpoint_numbers (const char *, gdb::function_view); +static void enable_disable_command (char *args, int from_tty, bool enable); + static void ignore_command (char *, int); static void breakpoint_re_set_default (struct breakpoint *); @@ -14160,17 +14169,51 @@ ignore_command (char *args, int from_tty) if (from_tty) printf_filtered ("\n"); } - + +/* Call FUNCTION on each of the breakpoints present in range defined by + BP_NUM_RANGE as pair of integer in which BP_NUM_RANGE.FIRST is the start + of the breakpoint number range and BP_NUM_RANGE.SECOND is the end of + the breakpoint number range. + If BP_NUM_RANGE.FIRST == BP_NUM_RANGE.SECOND then the + range is just a single breakpoint number. */ + +static void +map_breakpoint_number_range (std::pair &bp_num_range, + gdb::function_view function) +{ + if (bp_num_range.first == 0) + { + warning (_("bad breakpoint number at or near '%d'"), + bp_num_range.first); + } + else + { + struct breakpoint *b, *tmp; + + for (int i = bp_num_range.first; i <= bp_num_range.second; i++) + { + bool match = false; + + ALL_BREAKPOINTS_SAFE (b, tmp) + if (b->number == i) + { + match = true; + function (b); + break; + } + if (!match) + printf_unfiltered (_("No breakpoint number %d.\n"), i); + } + } +} + /* Call FUNCTION on each of the breakpoints whose numbers are given in ARGS. */ static void map_breakpoint_numbers (const char *args, - gdb::function_view function) + gdb::function_view function) { - int num; - struct breakpoint *b, *tmp; - if (args == 0 || *args == '\0') error_no_arg (_("one or more breakpoint numbers")); @@ -14178,43 +14221,22 @@ map_breakpoint_numbers (const char *args, while (!parser.finished ()) { - const char *p = parser.cur_tok (); - bool match = false; + int num = parser.get_number (); + std::pair range = std::make_pair (num, num); - num = parser.get_number (); - if (num == 0) - { - warning (_("bad breakpoint number at or near '%s'"), p); - } - else - { - ALL_BREAKPOINTS_SAFE (b, tmp) - if (b->number == num) - { - match = true; - function (b); - break; - } - if (!match) - printf_unfiltered (_("No breakpoint number %d.\n"), num); - } + map_breakpoint_number_range (range, function); } } +/* Return the breakpoint location structure corresponding to the + BP_NUM and LOC_NUM values. */ + static struct bp_location * -find_location_by_number (const char *number) +find_location_by_number (int bp_num, int loc_num) { - const char *p1; - int bp_num; - int loc_num; struct breakpoint *b; struct bp_location *loc; - p1 = number; - bp_num = get_number_trailer (&p1, '.'); - if (bp_num == 0 || p1[0] != '.') - error (_("Bad breakpoint number '%s'"), number); - ALL_BREAKPOINTS (b) if (b->number == bp_num) { @@ -14222,25 +14244,154 @@ find_location_by_number (const char *number) } if (!b || b->number != bp_num) - error (_("Bad breakpoint number '%s'"), number); + error (_("Bad breakpoint number '%d'"), bp_num); - /* Skip the dot. */ - ++p1; - const char *save = p1; - loc_num = get_number (&p1); if (loc_num == 0) - error (_("Bad breakpoint location number '%s'"), number); + error (_("Bad breakpoint location number '%d'"), loc_num); --loc_num; loc = b->loc; for (;loc_num && loc; --loc_num, loc = loc->next) ; if (!loc) - error (_("Bad breakpoint location number '%s'"), save); + error (_("Bad breakpoint location number '%d'"), loc_num); return loc; } +/* Extract the breakpoint range defined by ARG. Return the start of + the breakpoint range defined by BP_NUM_RANGE.FIRST and + BP_LOC_RANGE.FIRST and the end of the breakpoint range defined by + BP_NUM_RANGE.second and BP_LOC_RANGE.SECOND. + + The range may be any of the following form: + + x where x is breakpoint number. + x-y where x and y are breakpoint numbers range. + x.y where x is breakpoint number and z a location number. + x.y-z where x is breakpoint number and y and z a location number + range. */ + +static int +extract_bp_number_and_location (const std::string &arg, + std::pair &bp_num_range, + std::pair &bp_loc_range) +{ + std::size_t dot = arg.find ("."); + + if (dot != std::string::npos) + { + /* Handle x.y and x.y-z cases. */ + std::size_t dash; + std::string bp_loc; + + if (arg.length () == dot + 1 || dot == 0) + error (_("bad breakpoint number at or near: '%s'"), arg.c_str ()); + + dash = arg.find ("-", dot + 1); + + bp_loc = arg.substr (dot + 1); + const char *ptbf = arg.substr (0, dot).c_str (); + bp_num_range.first = get_number(&ptbf); + bp_num_range.second = bp_num_range.first; + + if (bp_num_range.first == 0) + error (_("Bad breakpoint number '%s'"), arg.c_str ()); + + if (dash != std::string::npos) + { + /* bp_loc is range (x-z). */ + if (arg.length () == dash + 1) + error (_("bad breakpoint number at or near: '%s'"), arg.c_str ()); + dash = bp_loc.find ("-"); + const char *ptlf = bp_loc.substr (0, dash).c_str (); + bp_loc_range.first = get_number(&ptlf); + const char *ptls= bp_loc.substr (dash + 1).c_str (); + bp_loc_range.second = get_number(&ptls); + } + else + { + /* bp_loc is single value. */ + const char *ptls= bp_loc.c_str (); + bp_loc_range.second = get_number(&ptls); + bp_loc_range.first = bp_loc_range.second; + if (bp_loc_range.first == 0) + { + warning (_("bad breakpoint number at or near '%s'"), arg.c_str ()); + return 1; + } + } + } + else + { + /* Handle x and x-y cases. */ + std::size_t dash; + + dash = arg.find ("-"); + bp_loc_range.first = 0; + bp_loc_range.second = 0; + if (dash != std::string::npos) + { + if (arg.length () == dash + 1 || dash == 0) + error (_("bad breakpoint number at or near: '%s'"), arg.c_str ()); + + const char *ptlf = arg.substr (0, dash).c_str (); + bp_num_range.first = get_number (&ptlf); + const char *ptls= arg.substr (dash + 1).c_str (); + bp_num_range.second = get_number (&ptls); + } + else + { + const char * ptlf = arg.c_str (); + bp_num_range.first = get_number (&ptlf); + bp_num_range.second = bp_num_range.first; + if (bp_num_range.first == 0) + { + warning (_("bad breakpoint number at or near '%s'"), arg.c_str ()); + return 1; + } + } + } + + if (bp_num_range.first == 0 || bp_num_range.second == 0) + error (_("bad breakpoint number at or near: '%s'"), arg.c_str ()); + + return 0; +} + +/* Enable or disable a breakpoint using BP_NUMB, LOC_NUM and enable. */ + +static void +enable_disable_bp_num_loc (int bp_num, int loc_num, bool enable) +{ + struct bp_location *loc = find_location_by_number (bp_num, loc_num); + if (loc != NULL) + { + if (loc->enabled != enable) + { + loc->enabled = enable; + mark_breakpoint_location_modified (loc); + } + if (target_supports_enable_disable_tracepoint () + && current_trace_status ()->running && loc->owner + && is_tracepoint (loc->owner)) + target_disable_tracepoint (loc); + } + update_global_location_list (UGLL_DONT_INSERT); +} + +/* Enable or disable a breakpoint location range. It uses BP_NUM, + BP_LOC_RANGE.FIRST for the start of the range, BP_LOC_RANGE.SECOND for + the end of the range and enable. */ + +static void +enable_disable_breakpoint_location_range (int bp_num, + std::pair &bp_loc_range, + bool enable) +{ + for (int i = bp_loc_range.first; i <= bp_loc_range.second; i++) + enable_disable_bp_num_loc (bp_num, i, enable); +} /* Set ignore-count of breakpoint number BPTNUM to COUNT. If from_tty is nonzero, it prints a message to that effect, @@ -14274,8 +14425,12 @@ disable_breakpoint (struct breakpoint *bpt) observer_notify_breakpoint_modified (bpt); } +/* Enable or disable breakpoint defined in ARGS. Breakpoint may be + any of the form defined in extract_bp_number_and_location. + ENABLE enable or disable breakpoint. */ + static void -disable_command (const char *args, int from_tty) +enable_disable_command (char *args, int from_tty, bool enable) { if (args == 0) { @@ -14283,43 +14438,58 @@ disable_command (const char *args, int from_tty) ALL_BREAKPOINTS (bpt) if (user_breakpoint_p (bpt)) - disable_breakpoint (bpt); + { + if (enable) + enable_breakpoint (bpt); + else + disable_breakpoint (bpt); + } } else { std::string num = extract_arg (&args); while (!num.empty ()) - { - if (num.find ('.') != std::string::npos) - { - struct bp_location *loc = find_location_by_number (num.c_str ()); - - if (loc) - { - if (loc->enabled) - { - loc->enabled = 0; - mark_breakpoint_location_modified (loc); - } - if (target_supports_enable_disable_tracepoint () - && current_trace_status ()->running && loc->owner - && is_tracepoint (loc->owner)) - target_disable_tracepoint (loc); - } - update_global_location_list (UGLL_DONT_INSERT); - } - else - map_breakpoint_numbers - (num.c_str (), [&] (breakpoint *b) - { - iterate_over_related_breakpoints (b, disable_breakpoint); - }); - num = extract_arg (&args); - } + { + std::pair bp_num_range; + std::pair bp_loc_range; + + int err_ret = extract_bp_number_and_location (num.c_str(), + bp_num_range, + bp_loc_range); + if (!err_ret) + { + if (bp_loc_range.first == bp_loc_range.second + && bp_loc_range.first == 0) + { + /* Handle breakpoint with format x or x-z only. */ + map_breakpoint_number_range (bp_num_range, + enable ? enable_breakpoint : + disable_breakpoint); + } + else + { + /* Handle breakpoint with format is x.y or x.y-z */ + enable_disable_breakpoint_location_range + (bp_num_range.first, bp_loc_range, enable); + } + } + num = extract_arg (&args); + } } } +/* The disable command disables the specified breakpoints (or all defined + breakpoints) so they once stop be effective in stopping + the inferior. ARGS may be any of the form defined in + extract_bp_number_and_location. */ + +static void +disable_command (char *args, int from_tty) +{ + enable_disable_command (args, from_tty, false); +} + static void enable_breakpoint_disp (struct breakpoint *bpt, enum bpdisp disposition, int count) @@ -14392,52 +14562,13 @@ enable_breakpoint (struct breakpoint *bpt) /* The enable command enables the specified breakpoints (or all defined breakpoints) so they once again become (or continue to be) effective - in stopping the inferior. */ + in stopping the inferior. ARGS may be any of the form defined in + extract_bp_number_and_location. */ static void enable_command (const char *args, int from_tty) { - if (args == 0) - { - struct breakpoint *bpt; - - ALL_BREAKPOINTS (bpt) - if (user_breakpoint_p (bpt)) - enable_breakpoint (bpt); - } - else - { - std::string num = extract_arg (&args); - - while (!num.empty ()) - { - if (num.find ('.') != std::string::npos) - { - struct bp_location *loc = find_location_by_number (num.c_str ()); - - if (loc) - { - if (!loc->enabled) - { - loc->enabled = 1; - mark_breakpoint_location_modified (loc); - } - if (target_supports_enable_disable_tracepoint () - && current_trace_status ()->running && loc->owner - && is_tracepoint (loc->owner)) - target_enable_tracepoint (loc); - } - update_global_location_list (UGLL_MAY_INSERT); - } - else - map_breakpoint_numbers - (num.c_str (), [&] (breakpoint *b) - { - iterate_over_related_breakpoints (b, enable_breakpoint); - }); - num = extract_arg (&args); - } - } + enable_disable_command (args, from_tty, true); } static void diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index bfeb7a9..b1346d9 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -3929,13 +3929,20 @@ Num Type Disp Enb Address What Each location can be individually enabled or disabled by passing @var{breakpoint-number}.@var{location-number} as argument to the -@code{enable} and @code{disable} commands. Note that you cannot -delete the individual locations from the list, you can only delete the -entire list of locations that belong to their parent breakpoint (with -the @kbd{delete @var{num}} command, where @var{num} is the number of -the parent breakpoint, 1 in the above example). Disabling or enabling -the parent breakpoint (@pxref{Disabling}) affects all of the locations -that belong to that breakpoint. +@code{enable} and @code{disable} commands. It's also possible to +@code{enable} and @code{disable} range of @var{location-number} +breakpoints using a @var{breakpoint-number} and two @var{location-number}, +in increasing order, separated by a hyphen, like +‘@var{breakpoint-number}.5-7’. +In this case, when a @var{location-number} range is given to this +command, all breakpoints belonging to this @var{breakpoint-number} +and inside that range are operated on. +Note that you cannot delete the individual locations from the list, +you can only delete the entire list of locations that belong to their +parent breakpoint (with the @kbd{delete @var{num}} command, where +@var{num} is the number of the parent breakpoint, 1 in the above example). +Disabling or enabling the parent breakpoint (@pxref{Disabling}) affects +all of the locations that belong to that breakpoint. @cindex pending breakpoints It's quite common to have a breakpoint inside a shared library. diff --git a/gdb/testsuite/gdb.cp/locbprange.cc b/gdb/testsuite/gdb.cp/locbprange.cc new file mode 100644 index 0000000..ff44b50 --- /dev/null +++ b/gdb/testsuite/gdb.cp/locbprange.cc @@ -0,0 +1,57 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2017 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +class foo + { + public: + static int overload (void); + static int overload (char); + static int overload (int); + static int overload (double); + }; + +void marker1() + { + } + +int main () + { + foo::overload (); + foo::overload (111); + foo::overload ('h'); + foo::overload (3.14); + + marker1 (); // marker1-returns-here + + return 0; + } + +/* Some functions to test overloading by varying one argument type. */ + +int foo::overload (void) + { + return 1; + } +int foo::overload (char arg) + { + arg = 0; + return 2; + } +int foo::overload (int arg) { arg = 0; return 3;} +int foo::overload (double arg) { arg = 0; return 4;} diff --git a/gdb/testsuite/gdb.cp/locbprange.exp b/gdb/testsuite/gdb.cp/locbprange.exp new file mode 100644 index 0000000..2a13791 --- /dev/null +++ b/gdb/testsuite/gdb.cp/locbprange.exp @@ -0,0 +1,160 @@ +# Copyright 2017 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# This file is part of the gdb testsuite + +# Tests for breakpoint location range enable/disable commands. + +set ws "\[\r\n\t \]+" +set nl "\[\r\n\]+" + + +if { [skip_cplus_tests] } { continue } + +standard_testfile .cc + +if {[prepare_for_testing "failed to prepare" $testfile $srcfile {debug c++}]} { + return -1 +} + +# Set it up at a breakpoint so we can play with the variable values. + +if ![runto 'marker1'] then { + perror "couldn't run to marker1" + continue +} + +# Prevent symbol on address 0x0 being printed. +gdb_test_no_output "set print symbol off" + +gdb_test "up" ".*main.*" "up from marker1" + +# Returns a buffer corresponding to what gdb replies when +# asking for 'info breakpoint'. The parameters are all the +# existing breakpoints enabled/disable value: 'n' or 'y'. + +proc set_info_breakpoint_reply {b1 b2 b21 b22 b23 b24} { + + set buf "Num Type\[ \]+Disp Enb Address\[ \]+What.* +1\[\t \]+breakpoint keep $b1.* in marker1\\(\\) at .* +\[\t \]+breakpoint already hit 1 time.* +2\[\t \]+breakpoint\[\t \]+keep $b2\[\t \]+.* +2.1\[\t \]+$b21.* +2.2\[\t \]+$b22.* +2.3\[\t \]+$b23.* +2.4\[\t \]+$b24.*" + + return $buf +} + +gdb_test "break foo::overload" \ + "Breakpoint \[0-9\]+ at $hex: foo::overload. .4 locations." \ + "set breakpoint at overload" + +gdb_test "info break" [set_info_breakpoint_reply y y y y y y] \ + "breakpoint info" + +# Check that we can disable a breakpoint. +gdb_test_no_output "disable 1" + +gdb_test "info break" [set_info_breakpoint_reply n y y y y y] \ + "breakpoint info disable bkpt 1" + +# Check that we can enable a breakpoint. +gdb_test_no_output "enable 1" + +gdb_test "info break" [set_info_breakpoint_reply y y y y y y] \ + "breakpoint info enable bkpt 1" + +# Check that we can disable a breakpoint containing location breakpoints. +gdb_test_no_output "disable 2" + +gdb_test "info break" [set_info_breakpoint_reply y n y y y y] \ + "breakpoint info disable bkpt 2" + +# Check that we can enable a breakpoint containing location breakpoints. +gdb_test_no_output "enable 2" + +gdb_test "info break" [set_info_breakpoint_reply y y y y y y] \ + "breakpoint info enable bkpt 2" + +# Check that we can disable a single location breakpoint. +gdb_test_no_output "disable 2.2" + +gdb_test "info break" [set_info_breakpoint_reply y y y n y y] \ + "breakpoint info disable bkpt 2.2" + +# Check that we can enable a single location breakpoint. +gdb_test_no_output "enable 2.2" + +gdb_test "info break" [set_info_breakpoint_reply y y y y y y] \ + "breakpoint info enable bkpt 2.2" + +# Check that we can disable a location breakpoint range. +gdb_test_no_output "disable 2.2-3" + +gdb_test "info break" [set_info_breakpoint_reply y y y n n y] \ + "breakpoint info disable bkpt 2.2 to 2.3" + +# Check that we can enable a location breakpoint range. +gdb_test_no_output "enable 2.2-3" + +gdb_test "info break" [set_info_breakpoint_reply y y y y y y] \ + "breakpoint info enaable bkpt 2.2 to 2.3" + +# Check that we can disable a location breakpoint range reduced +# to a single location. +gdb_test_no_output "disable 2.2-2" + +gdb_test "info break" [set_info_breakpoint_reply y y y n y y] \ + "breakpoint info disable 2.2 to 2.2" + +# Check that we can disable a location breakpoint range with max > +# existing breakpoint location. +gdb_test "disable 2.3-5" "Bad breakpoint location number '$decimal'" \ + "disable location breakpoint range with max > existing" + +gdb_test "info break" [set_info_breakpoint_reply y y y n n n] \ + "breakpoint info disable 2.3 to 2.5" + +# Check that we can enable a location breakpoint range with max > +# existing breakpoint location. +gdb_test "enable 2.3-5" "Bad breakpoint location number '$decimal'" \ + "enable location breakpoint range with max > existing" + +gdb_test "info break" [set_info_breakpoint_reply y y y n y y] \ + "breakpoint info enable 2.3 to 2.5" + +# Check that disabling an reverse location breakpoint range does +# not work. +gdb_test_no_output "disable 2.3-2" + +gdb_test "info break" [set_info_breakpoint_reply y y y n y y] \ + "breakpoint info disable 2.3 to 2.3" + +# Check that disabling an unvalid location breakpoint range does +# not cause unexpected behavior. +gdb_test "disable 2.6-7" "Bad breakpoint location number '$decimal'" \ + "disable an unvalid location breakpoint range" + +gdb_test "info break" [set_info_breakpoint_reply y y y n y y] \ + "breakpoint info disable 2.6 to 2.7" + +# Check that disabling an invalid location breakpoint range does not +# cause trouble. +gdb_test_no_output "disable 2.8-6" + +gdb_test "info break" [set_info_breakpoint_reply y y y n y y] \