diff options
-rw-r--r-- | gdb/ChangeLog | 8 | ||||
-rw-r--r-- | gdb/breakpoint.c | 141 | ||||
-rw-r--r-- | gdb/cli/cli-utils.c | 16 | ||||
-rw-r--r-- | gdb/testsuite/ChangeLog | 8 | ||||
-rw-r--r-- | gdb/testsuite/gdb.base/ena-dis-br.exp | 2 | ||||
-rw-r--r-- | gdb/testsuite/gdb.cp/ena-dis-br-range.exp | 115 |
6 files changed, 207 insertions, 83 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 5bac526..e1842d6 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,13 @@ 2017-11-07 Pedro Alves <palves@redhat.com> + * breakpoint.c (extract_bp_kind): New enum. + (extract_bp_num, extract_bp_or_bp_range): New functions, partially + factored out from ... + (extract_bp_number_and_location): ... here. + * cli/cli-utils.c (get_number_trailer): Handle '-$variable'. + +2017-11-07 Pedro Alves <palves@redhat.com> + * breakpoint.c (extract_bp_number_and_location): Change return type to void. Throw error instead of warning. (enable_disable_command): Adjust. diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index a94a0d0..9106f09 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -14212,6 +14212,87 @@ find_location_by_number (int bp_num, int loc_num) error (_("Bad breakpoint location number '%d'"), loc_num); } +/* Modes of operation for extract_bp_num. */ +enum class extract_bp_kind +{ + /* Extracting a breakpoint number. */ + bp, + + /* Extracting a location number. */ + loc, +}; + +/* Extract a breakpoint or location number (as determined by KIND) + from the string starting at START. TRAILER is a character which + can be found after the number. If you don't want a trailer, use + '\0'. If END_OUT is not NULL, it is set to point after the parsed + string. This always returns a positive integer. */ + +static int +extract_bp_num (extract_bp_kind kind, const char *start, + int trailer, const char **end_out = NULL) +{ + const char *end = start; + int num = get_number_trailer (&end, trailer); + if (num < 0) + error (kind == extract_bp_kind::bp + ? _("Negative breakpoint number '%.*s'") + : _("Negative breakpoint location number '%.*s'"), + int (end - start), start); + if (num == 0) + error (kind == extract_bp_kind::bp + ? _("Bad breakpoint number '%.*s'") + : _("Bad breakpoint location number '%.*s'"), + int (end - start), start); + + if (end_out != NULL) + *end_out = end; + return num; +} + +/* Extract a breakpoint or location range (as determined by KIND) in + the form NUM1-NUM2 stored at &ARG[arg_offset]. Returns a std::pair + representing the (inclusive) range. The returned pair's elements + are always positive integers. */ + +static std::pair<int, int> +extract_bp_or_bp_range (extract_bp_kind kind, + const std::string &arg, + std::string::size_type arg_offset) +{ + std::pair<int, int> range; + const char *bp_loc = &arg[arg_offset]; + std::string::size_type dash = arg.find ('-', arg_offset); + if (dash != std::string::npos) + { + /* bp_loc is a range (x-z). */ + if (arg.length () == dash + 1) + error (kind == extract_bp_kind::bp + ? _("Bad breakpoint number at or near: '%s'") + : _("Bad breakpoint location number at or near: '%s'"), + bp_loc); + + const char *end; + const char *start_first = bp_loc; + const char *start_second = &arg[dash + 1]; + range.first = extract_bp_num (kind, start_first, '-'); + range.second = extract_bp_num (kind, start_second, '\0', &end); + + if (range.first > range.second) + error (kind == extract_bp_kind::bp + ? _("Inverted breakpoint range at '%.*s'") + : _("Inverted breakpoint location range at '%.*s'"), + int (end - start_first), start_first); + } + else + { + /* bp_loc is a single value. */ + range.first = extract_bp_num (kind, bp_loc, '\0'); + range.second = range.first; + } + return range; +} + /* Extract the breakpoint/location range specified by ARG. Returns the breakpoint range in BP_NUM_RANGE, and the location range in BP_LOC_RANGE. @@ -14237,69 +14318,23 @@ extract_bp_number_and_location (const std::string &arg, /* Handle 'x.y' and 'x.y-z' cases. */ if (arg.length () == dot + 1 || dot == 0) - error (_("bad breakpoint number at or near: '%s'"), arg.c_str ()); - - const char *ptb = arg.c_str (); - int bp_num = get_number_trailer (&ptb, '.'); - if (bp_num == 0) - error (_("Bad breakpoint number '%s'"), arg.c_str ()); + error (_("Bad breakpoint number at or near: '%s'"), arg.c_str ()); - bp_num_range.first = bp_num; - bp_num_range.second = bp_num; + bp_num_range.first + = extract_bp_num (extract_bp_kind::bp, arg.c_str (), '.'); + bp_num_range.second = bp_num_range.first; - const char *bp_loc = &arg[dot + 1]; - std::string::size_type dash = arg.find ('-', dot + 1); - if (dash != std::string::npos) - { - /* bp_loc is a range (x-z). */ - if (arg.length () == dash + 1) - error (_("bad breakpoint number at or near: '%s'"), bp_loc); - - const char *ptlf = bp_loc; - bp_loc_range.first = get_number_trailer (&ptlf, '-'); - - const char *ptls = &arg[dash + 1]; - bp_loc_range.second = get_number_trailer (&ptls, '\0'); - } - else - { - /* bp_loc is a single value. */ - const char *ptls = bp_loc; - bp_loc_range.first = get_number_trailer (&ptls, '\0'); - if (bp_loc_range.first == 0) - error (_("bad breakpoint number at or near '%s'"), arg.c_str ()); - bp_loc_range.second = bp_loc_range.first; - } + bp_loc_range = extract_bp_or_bp_range (extract_bp_kind::loc, + arg, dot + 1); } else { /* Handle x and x-y cases. */ - std::string::size_type dash = arg.find ('-'); - 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 *ptf = arg.c_str (); - bp_num_range.first = get_number_trailer (&ptf, '-'); - const char *pts = &arg[dash + 1]; - bp_num_range.second = get_number_trailer (&pts, '\0'); - } - else - { - const char *ptf = arg.c_str (); - bp_num_range.first = get_number (&ptf); - if (bp_num_range.first == 0) - error (_("bad breakpoint number at or near '%s'"), arg.c_str ()); - bp_num_range.second = bp_num_range.first; - } + bp_num_range = extract_bp_or_bp_range (extract_bp_kind::bp, arg, 0); bp_loc_range.first = 0; bp_loc_range.second = 0; } - - if (bp_num_range.first == 0 || bp_num_range.second == 0) - error (_("bad breakpoint number at or near: '%s'"), arg.c_str ()); } /* Enable or disable a breakpoint location BP_NUM.LOC_NUM. ENABLE diff --git a/gdb/cli/cli-utils.c b/gdb/cli/cli-utils.c index d5273b5..6b36378 100644 --- a/gdb/cli/cli-utils.c +++ b/gdb/cli/cli-utils.c @@ -30,6 +30,13 @@ get_number_trailer (const char **pp, int trailer) { int retval = 0; /* default */ const char *p = *pp; + bool negative = false; + + if (*p == '-') + { + ++p; + negative = true; + } if (*p == '$') { @@ -70,11 +77,10 @@ get_number_trailer (const char **pp, int trailer) } else { - if (*p == '-') - ++p; + const char *p1 = p; while (*p >= '0' && *p <= '9') ++p; - if (p == *pp) + if (p == p1) /* There is no number here. (e.g. "cond a == b"). */ { /* Skip non-numeric token. */ @@ -84,7 +90,7 @@ get_number_trailer (const char **pp, int trailer) retval = 0; } else - retval = atoi (*pp); + retval = atoi (p1); } if (!(isspace (*p) || *p == '\0' || *p == trailer)) { @@ -95,7 +101,7 @@ get_number_trailer (const char **pp, int trailer) } p = skip_spaces (p); *pp = p; - return retval; + return negative ? -retval : retval; } /* See documentation in cli-utils.h. */ diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 5698dac..2a89733 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,5 +1,13 @@ 2017-11-07 Pedro Alves <palves@redhat.com> + * gdb.base/ena-dis-br.exp (test_ena_dis_br): Adjust test. + * gdb.cp/ena-dis-br-range.exp: Adjust tests. + (disable_invalid, disable_inverted, disable_negative): New + procedures. + ("bad numbers"): New set of tests. + +2017-11-07 Pedro Alves <palves@redhat.com> + * gdb.cp/ena-dis-br-range.exp: Add tests. 2017-11-07 Pedro Alves <palves@redhat.com> diff --git a/gdb/testsuite/gdb.base/ena-dis-br.exp b/gdb/testsuite/gdb.base/ena-dis-br.exp index 2bbb734..8655421 100644 --- a/gdb/testsuite/gdb.base/ena-dis-br.exp +++ b/gdb/testsuite/gdb.base/ena-dis-br.exp @@ -398,7 +398,7 @@ proc test_ena_dis_br { what } { # Now enable(disable) '$b4.1 fooobaar'. This should error on # fooobaar. gdb_test "$what $b4.1 fooobaar" \ - "bad breakpoint number at or near 'fooobaar'" \ + "Bad breakpoint number 'fooobaar'" \ "$what \$b4.1 fooobar" set test1 "${what}d \$b4.1" diff --git a/gdb/testsuite/gdb.cp/ena-dis-br-range.exp b/gdb/testsuite/gdb.cp/ena-dis-br-range.exp index c2a3017..8db53bd 100644 --- a/gdb/testsuite/gdb.cp/ena-dis-br-range.exp +++ b/gdb/testsuite/gdb.cp/ena-dis-br-range.exp @@ -109,9 +109,9 @@ gdb_test "enable 2.3-5" "Bad breakpoint location number '5'" \ gdb_test "info break" [make_info_breakpoint_reply_re y y y y y y] \ "breakpoint info enable 2.3 to 2.5" -# Check that disabling an reverse location breakpoint range does not +# Check that disabling an inverted breakpoint location range does not # work. -gdb_test_no_output "disable 2.3-2" +gdb_test "disable 2.3-2" "Inverted breakpoint location range at '3-2'" gdb_test "info break" [make_info_breakpoint_reply_re y y y y y y] \ "breakpoint info disable 2.3-2" @@ -126,44 +126,111 @@ gdb_test "info break" [make_info_breakpoint_reply_re y y y y y y] \ # Check that disabling an invalid breakpoint location range does not # cause trouble. -gdb_test_no_output "disable 2.8-6" +gdb_test "disable 2.8-6" "Inverted breakpoint location range at '8-6'" gdb_test "info break" [make_info_breakpoint_reply_re y y y y y y] \ "breakpoint info disable 2.8-6" # Check that invalid/open ranges are handled correctly. with_test_prefix "open range" { - gdb_test "disable -" "bad breakpoint number at or near: '-'" - gdb_test "disable -1" "bad breakpoint number at or near: '-1'" - gdb_test "disable 1-" "bad breakpoint number at or near: '1-'" - gdb_test "disable 1.-2" "Bad breakpoint location number '-2'" - gdb_test "disable 1.2-" "bad breakpoint number at or near: '2-'" - gdb_test "disable 1.-2-3" "Bad breakpoint location number '-2'" - gdb_test "disable 1-2-3" "bad breakpoint number at or near: '1-2-3'" + gdb_test "disable -" "Bad breakpoint number at or near: '-'" + gdb_test "disable -1" "Negative breakpoint number '-1'" + gdb_test "disable 1-" "Bad breakpoint number at or near: '1-'" + gdb_test "disable 1.-2" "Negative breakpoint location number '-2'" + gdb_test "disable 1.2-" "Bad breakpoint location number at or near: '2-'" + gdb_test "disable 1.-2-3" "Negative breakpoint location number '-2'" + gdb_test "disable 1-2-3" "Bad breakpoint number '2-3'" } with_test_prefix "dangling period" { - gdb_test "disable 2." "bad breakpoint number at or near: '2.'" - gdb_test "disable .2" "bad breakpoint number at or near: '.2'" - gdb_test "disable 2.3.4" "bad breakpoint number at or near '2.3.4'" + gdb_test "disable 2." "Bad breakpoint number at or near: '2.'" + gdb_test "disable .2" "Bad breakpoint number at or near: '.2'" + gdb_test "disable 2.3.4" "Bad breakpoint location number '3.4'" } # Check that 0s are handled correctly. with_test_prefix "zero" { - gdb_test "disable 0" "bad breakpoint number at or near '0'" - gdb_test "disable 0.0" "Bad breakpoint number '0.0'" - gdb_test "disable 0.1" "Bad breakpoint number '0.1'" - gdb_test "disable 0.1-2" "Bad breakpoint number '0.1-2'" - gdb_test "disable 2.0" "bad breakpoint number at or near '2.0'" + gdb_test "disable 0" "Bad breakpoint number '0'" + gdb_test "disable 0.0" "Bad breakpoint number '0'" + gdb_test "disable 0.1" "Bad breakpoint number '0'" + gdb_test "disable 0.1-2" "Bad breakpoint number '0'" + gdb_test "disable 2.0" "Bad breakpoint location number '0'" + gdb_test "disable 2.0-0" "Bad breakpoint location number '0'" + gdb_test "disable 2.0-1" "Bad breakpoint location number '0'" + gdb_test "disable 2.1-0" "Bad breakpoint location number '0'" +} + +# Test "disable BPLIST" with an invalid breakpoint/location BPLIST. +# PREFIX and SUFFIX are concatenated to form BPLIST. The invalid part +# is always in SUFFIX. + +proc disable_invalid {prefix suffix} { + set bad_re [string_to_regexp $suffix] + + if {$prefix == ""} { + gdb_test \ + "disable $suffix" \ + "Bad breakpoint number '${bad_re}'" + } else { + gdb_test \ + "disable ${prefix}$suffix" \ + "Bad breakpoint location number '${bad_re}'" + } +} - # These should really fail... - gdb_test_no_output "disable 2.0-0" - gdb_test_no_output "enable 2.0-0" +# Like disable_invalid, but expects an "inverted range" error. - gdb_test "disable 2.0-1" "Bad breakpoint location number '0'" +proc disable_inverted {prefix suffix} { + set bad_re [string_to_regexp $suffix] + + if {$prefix == ""} { + gdb_test \ + "disable $suffix" \ + "Inverted breakpoint range at '${bad_re}'" + } else { + gdb_test \ + "disable ${prefix}$suffix" \ + "Inverted breakpoint location range at '${bad_re}'" + } +} + +# Like disable_invalid, but expects a "negative number" error. + +proc disable_negative {prefix suffix} { + set bad_re [string_to_regexp $suffix] + + if {$prefix == ""} { + gdb_test \ + "disable $suffix" \ + "Negative breakpoint number '${bad_re}'" + } else { + gdb_test \ + "disable ${prefix}$suffix" \ + "Negative breakpoint location number '${bad_re}'" + } +} - # Likewise, should fail. - gdb_test_no_output "disable 2.1-0" +with_test_prefix "bad numbers" { + gdb_test "p \$zero = 0" " = 0" + gdb_test "p \$one = 1" " = 1" + gdb_test "p \$two = 2" " = 2" + gdb_test "p \$minus_one = -1" " = -1" + foreach prefix {"" "1." "$one."} { + set prefix_re [string_to_regexp $prefix] + + disable_invalid $prefix "foo" + disable_invalid $prefix "1foo" + disable_invalid $prefix "foo1" + + disable_inverted $prefix "2-1" + disable_inverted $prefix "2-\$one" + disable_inverted $prefix "\$two-1" + disable_inverted $prefix "\$two-\$one" + + disable_negative $prefix "-1" + disable_negative $prefix "-\$one" + disable_negative $prefix "\$minus_one" + } } gdb_test "info break" [make_info_breakpoint_reply_re y y y y y y] \ |