diff options
-rw-r--r-- | gdb/linespec.c | 59 | ||||
-rw-r--r-- | gdb/testsuite/gdb.base/break-on-linker-gcd-function.exp | 11 | ||||
-rw-r--r-- | gdb/testsuite/gdb.base/break.exp | 7 | ||||
-rw-r--r-- | gdb/testsuite/gdb.base/ending-run.exp | 38 | ||||
-rw-r--r-- | gdb/testsuite/gdb.base/foll-exec-mode.exp | 2 | ||||
-rw-r--r-- | gdb/testsuite/gdb.base/hbreak2.exp | 2 | ||||
-rw-r--r-- | gdb/testsuite/gdb.base/sepdebug.exp | 2 | ||||
-rw-r--r-- | gdb/testsuite/gdb.linespec/cpexplicit.exp | 2 | ||||
-rw-r--r-- | gdb/testsuite/gdb.linespec/explicit.exp | 2 | ||||
-rw-r--r-- | gdb/testsuite/gdb.linespec/line-breakpoint-outside-function.c | 51 | ||||
-rw-r--r-- | gdb/testsuite/gdb.linespec/line-breakpoint-outside-function.exp | 55 | ||||
-rw-r--r-- | gdb/testsuite/gdb.linespec/ls-errs.c | 10 | ||||
-rw-r--r-- | gdb/testsuite/gdb.linespec/ls-errs.exp | 14 | ||||
-rw-r--r-- | gdb/testsuite/gdb.python/py-breakpoint.exp | 4 | ||||
-rw-r--r-- | gdb/testsuite/gdb.trace/tfind.exp | 4 | ||||
-rw-r--r-- | gdb/testsuite/gdb.trace/tracecmd.exp | 3 |
16 files changed, 210 insertions, 56 deletions
diff --git a/gdb/linespec.c b/gdb/linespec.c index 02a754d..be85074 100644 --- a/gdb/linespec.c +++ b/gdb/linespec.c @@ -2067,12 +2067,19 @@ create_sals_line_offset (struct linespec_state *self, const linetable_entry *best_entry = NULL; int i, j; + /* True if the provided line gave an exact match. False if we had to + search for the next following line with code. */ + bool was_exact = true; + std::vector<symtab_and_line> intermediate_results = decode_digits_ordinary (self, ls, val.line, &best_entry); if (intermediate_results.empty () && best_entry != NULL) - intermediate_results = decode_digits_ordinary (self, ls, - best_entry->line, - &best_entry); + { + was_exact = false; + intermediate_results = decode_digits_ordinary (self, ls, + best_entry->line, + &best_entry); + } /* For optimized code, the compiler can scatter one source line across disjoint ranges of PC values, even when no duplicate @@ -2115,11 +2122,45 @@ create_sals_line_offset (struct linespec_state *self, struct symbol *sym = (blocks[i] ? blocks[i]->containing_function () : NULL); + symtab_and_line &sal = intermediate_results[i]; + + /* Don't consider a match if: + + - the provided line did not give an exact match (so we + started looking for lines below until we found one with + code associated to it) + - the found location is exactly the start of a function + - the provided line is above the declaration line of the + function + + Consider the following source: + + 10 } // end of a previous function + 11 + 12 int + 13 main (void) + 14 { + 15 int i = 1; + 16 + 17 return 0; + 18 } + + The intent of this heuristic is that a breakpoint requested on + line 11 and 12 will not result in a breakpoint on main, but a + breakpoint on line 13 will. A breakpoint requested on the empty + line 16 will also result in a breakpoint in main, at line 17. */ + if (!was_exact + && sym != nullptr + && sym->aclass () == LOC_BLOCK + && sal.pc == sym->value_block ()->entry_pc () + && val.line < sym->line ()) + continue; if (self->funfirstline) - skip_prologue_sal (&intermediate_results[i]); - intermediate_results[i].symbol = sym; - add_sal_to_sals (self, &values, &intermediate_results[i], + skip_prologue_sal (&sal); + + sal.symbol = sym; + add_sal_to_sals (self, &values, &sal, sym ? sym->natural_name () : NULL, 0); } } @@ -2127,10 +2168,12 @@ create_sals_line_offset (struct linespec_state *self, if (values.empty ()) { if (ls->explicit_loc.source_filename) - throw_error (NOT_FOUND_ERROR, _("No line %d in file \"%s\"."), + throw_error (NOT_FOUND_ERROR, + _("No compiled code for line %d in file \"%s\"."), val.line, ls->explicit_loc.source_filename.get ()); else - throw_error (NOT_FOUND_ERROR, _("No line %d in the current file."), + throw_error (NOT_FOUND_ERROR, + _("No compiled code for line %d in the current file."), val.line); } diff --git a/gdb/testsuite/gdb.base/break-on-linker-gcd-function.exp b/gdb/testsuite/gdb.base/break-on-linker-gcd-function.exp index 67afe4c..cf1596a 100644 --- a/gdb/testsuite/gdb.base/break-on-linker-gcd-function.exp +++ b/gdb/testsuite/gdb.base/break-on-linker-gcd-function.exp @@ -40,10 +40,13 @@ proc set_breakpoint_on_gcd_function {} { # Single hex digit set xd {[0-9a-f]} - # This accepts e.g. "Breakpoint 1 at 0x40968a" (fixed GDB) - # but rejects e.g. "Breakpoint 1 at 0x4" (broken GDB). - gdb_test "b [gdb_get_line_number "gdb break here"]" \ - "Breakpoint \[0-9\] at 0x${xd}${xd}+: .*" + set lineno [gdb_get_line_number "gdb break here"] + gdb_test "set breakpoint pending on" + gdb_test "b $lineno" \ + [multi_line \ + "^No compiled code for line $lineno in the current file\\." \ + "Breakpoint $::decimal \\($lineno\\) pending\\."] \ + "break on line in garbage collected function" } set_breakpoint_on_gcd_function diff --git a/gdb/testsuite/gdb.base/break.exp b/gdb/testsuite/gdb.base/break.exp index cdb4c22..34ac219 100644 --- a/gdb/testsuite/gdb.base/break.exp +++ b/gdb/testsuite/gdb.base/break.exp @@ -476,9 +476,6 @@ proc_with_prefix test_no_break_on_catchpoint {} { test_no_break_on_catchpoint -# Verify that GDB responds gracefully when asked to set a breakpoint -# on a nonexistent source line. - proc_with_prefix test_break_nonexistent_line {} { clean_restart break @@ -486,9 +483,11 @@ proc_with_prefix test_break_nonexistent_line {} { return } + # Verify that GDB responds gracefully when asked to set a + # breakpoint on a nonexistent source line. gdb_test_no_output "set breakpoint pending off" gdb_test "break 999" \ - "No line 999 in the current file." \ + "^No compiled code for line 999 in the current file\\." \ "break on non-existent source line" } diff --git a/gdb/testsuite/gdb.base/ending-run.exp b/gdb/testsuite/gdb.base/ending-run.exp index b9a72b0..90359fd 100644 --- a/gdb/testsuite/gdb.base/ending-run.exp +++ b/gdb/testsuite/gdb.base/ending-run.exp @@ -32,24 +32,15 @@ if { [prepare_for_testing "failed to prepare" $testfile $srcfile $flags] } { } remote_exec build "rm -f core" -# CHFts23469: Test that you can "clear" a bp set at -# a line _before_ the routine (which will default to the -# first line in the routine, which turns out to correspond -# to the prolog--that's another bug...) -# - -gdb_test "b ending-run.c:1" ".*Breakpoint.*ending-run.c, line 1.*" \ - "bpt at line before routine" - set break1_line [gdb_get_line_number "-break1-"] gdb_test "b ending-run.c:$break1_line" \ - ".*Note.*also.*Breakpoint 2.*ending-run.c, line $break1_line.*" \ + "Breakpoint 1 at ${::hex}.*" \ "b ending-run.c:$break1_line, one" # Set up to go to the next-to-last line of the program # set break2_line [gdb_get_line_number "-break2-"] -gdb_test "b ending-run.c:$break2_line" ".*Breakpoint 3.*ending-run.c, line $break2_line.*" +gdb_test "b ending-run.c:$break2_line" ".*Breakpoint 2.*ending-run.c, line $break2_line.*" # Expect to hit the bp at line "1", but symbolize this # as line "13". Then try to clear it--this should work. @@ -57,29 +48,28 @@ gdb_test "b ending-run.c:$break2_line" ".*Breakpoint 3.*ending-run.c, line $brea gdb_run_cmd gdb_test "" ".*Breakpoint.*1.*callee.*$break1_line.*" "run" -gdb_test "cle" ".*Deleted breakpoints 1 2.*" "clear worked" -gdb_test_multiple "i b" "cleared bp at line before routine" { - -re ".* breakpoint .* breakpoint .*$gdb_prompt $" { - fail "cleared bp at line before routine" +gdb_test "cle" "Deleted breakpoint 1 " "clear worked" +gdb_test_multiple "i b" "cleared bp at stopped line" { + -re ".* breakpoint .* breakpoint .*$gdb_prompt $" { + fail $gdb_test_name } - -re ".*3.*main.*$break2_line.*$gdb_prompt $" { - pass "cleared bp at line before routine" + -re ".*2.*main.*$break2_line.*$gdb_prompt $" { + pass $gdb_test_name } } # Test some other "clear" combinations # -gdb_test "b ending-run.c:1" ".*Breakpoint.*4.*" -gdb_test "b ending-run.c:$break1_line" ".*Note.*also.*Breakpoint.*5.*" "b ending-run.c:$break1_line, two" +gdb_test "b ending-run.c:$break1_line" "Breakpoint 3 at ${::hex}.*" "b ending-run.c:$break1_line, two" gdb_test "cle ending-run.c:$break1_line" \ - ".*Deleted breakpoints 4 5.*" "Cleared 2 by line" + "Deleted breakpoint 3 " "Cleared 2 by line" gdb_test_multiple "info line ending-run.c:$break1_line" "" { -re ".*address (0x\[0-9a-fA-F]*).*$gdb_prompt $" { set line_nine $expect_out(1,string) - gdb_test "b ending-run.c:$break1_line" ".*Breakpoint 6.*ending-run.c, line $break1_line.*" - gdb_test "b *$line_nine" ".*Note.*also.*Breakpoint 7.*" "breakpoint 7 at *ending-run.c:$break1_line" - gdb_test "cle" ".*Deleted breakpoints 6 7.*" "clear 2 by default" + gdb_test "b ending-run.c:$break1_line" ".*Breakpoint 4.*ending-run.c, line $break1_line.*" + gdb_test "b *$line_nine" ".*Note.*also.*Breakpoint 5.*" "breakpoint 7 at *ending-run.c:$break1_line" + gdb_test "cle" "Deleted breakpoints 4 5 " "clear 2 by default" } -re ".*$gdb_prompt $" { fail "need to fix test for new compile outcome" @@ -90,7 +80,7 @@ gdb_test_multiple "i b" "all set to continue" { -re ".* breakpoint .* breakpoint .*$gdb_prompt $" { fail "all set to continue (didn't clear bps)" } - -re ".*3.*main.*$break2_line.*$gdb_prompt $" { + -re ".*2.*main.*$break2_line.*$gdb_prompt $" { pass "all set to continue" } -re ".*$gdb_prompt $" { diff --git a/gdb/testsuite/gdb.base/foll-exec-mode.exp b/gdb/testsuite/gdb.base/foll-exec-mode.exp index 65054b5..56a2ffc 100644 --- a/gdb/testsuite/gdb.base/foll-exec-mode.exp +++ b/gdb/testsuite/gdb.base/foll-exec-mode.exp @@ -127,7 +127,7 @@ proc do_follow_exec_mode_tests { mode cmd infswitch } { # past it. # if {$cmd == "continue"} { - gdb_breakpoint "$execd_line" + gdb_breakpoint "$execd_line" "allow-pending" } # Execute past the exec call. diff --git a/gdb/testsuite/gdb.base/hbreak2.exp b/gdb/testsuite/gdb.base/hbreak2.exp index d22b363..37c001a 100644 --- a/gdb/testsuite/gdb.base/hbreak2.exp +++ b/gdb/testsuite/gdb.base/hbreak2.exp @@ -296,7 +296,7 @@ if {![runto_main]} { # gdb_test_no_output "set breakpoint pending off" gdb_test "hbreak 999" \ - "No line 999 in the current file." \ + "^No compiled code for line 999 in the current file\\." \ "hardware break on non-existent source line" # Run to the desired default location. If not positioned here, the diff --git a/gdb/testsuite/gdb.base/sepdebug.exp b/gdb/testsuite/gdb.base/sepdebug.exp index ee9bea2..eb3515b 100644 --- a/gdb/testsuite/gdb.base/sepdebug.exp +++ b/gdb/testsuite/gdb.base/sepdebug.exp @@ -296,7 +296,7 @@ gdb_test "catch exec" "Catchpoint \[0-9\]+ \\(exec\\)" \ # gdb_test_no_output "set breakpoint pending off" -gdb_test "break 999" "No line 999 in the current file." \ +gdb_test "break 999" "^No compiled code for line 999 in the current file\\." \ "break on non-existent source line" # Run to the desired default location. If not positioned here, the diff --git a/gdb/testsuite/gdb.linespec/cpexplicit.exp b/gdb/testsuite/gdb.linespec/cpexplicit.exp index 5c93c34..62033d5 100644 --- a/gdb/testsuite/gdb.linespec/cpexplicit.exp +++ b/gdb/testsuite/gdb.linespec/cpexplicit.exp @@ -80,7 +80,7 @@ namespace eval $testfile { add linespecs "-function myclass::myfunction -line 3" $location(normal) add linespecs "-function myclass::myfunction -label top -line 3" \ $location(top) - add linespecs "-line 3" $location(normal) + add linespecs "-line 25" $location(normal) add linespecs "-function myclass::operator," $location(operator) add linespecs "-function 'myclass::operator,'" $location(operator) add linespecs "-function \"myclass::operator,\"" $location(operator) diff --git a/gdb/testsuite/gdb.linespec/explicit.exp b/gdb/testsuite/gdb.linespec/explicit.exp index 625f9ce..60183e9 100644 --- a/gdb/testsuite/gdb.linespec/explicit.exp +++ b/gdb/testsuite/gdb.linespec/explicit.exp @@ -86,7 +86,7 @@ namespace eval $testfile { # These are also not yet supported; -line is silently ignored. add linespecs "-function myfunction -line 3" $location(normal) add linespecs "-function myfunction -label top -line 3" $location(top) - add linespecs "-line 3" $location(normal) + add linespecs "-line 25" $location(normal) # Fire up gdb. if {![runto_main]} { diff --git a/gdb/testsuite/gdb.linespec/line-breakpoint-outside-function.c b/gdb/testsuite/gdb.linespec/line-breakpoint-outside-function.c new file mode 100644 index 0000000..93c4383 --- /dev/null +++ b/gdb/testsuite/gdb.linespec/line-breakpoint-outside-function.c @@ -0,0 +1,51 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2022-2024 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 <http://www.gnu.org/licenses/>. */ + +/* The section where THE_LIB_PATH is not defined is compiled as a shared + library. The rest is compiled as the main executable (which loads the + shared library. */ + +#if !defined(THE_LIB_PATH) + +void +the_lib_func (void) +{ + static int x; + /* break here */ + x++; +} + +#else +#include <dlfcn.h> +#include <assert.h> +#include <stdlib.h> + +int +main (void) +{ + void *lib = dlopen (THE_LIB_PATH, RTLD_NOW); + assert (lib != NULL); + + void (*the_lib_func) (void) = dlsym (lib, "the_lib_func"); + assert (the_lib_func != NULL); + + the_lib_func (); + + return 0; +} + +#endif diff --git a/gdb/testsuite/gdb.linespec/line-breakpoint-outside-function.exp b/gdb/testsuite/gdb.linespec/line-breakpoint-outside-function.exp new file mode 100644 index 0000000..946304a --- /dev/null +++ b/gdb/testsuite/gdb.linespec/line-breakpoint-outside-function.exp @@ -0,0 +1,55 @@ +# Copyright 2022-2024 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 <http://www.gnu.org/licenses/>. + +# Test that placing a line breakpoint outside a function results in a pending +# breakpoint. More importantly, that it does "drift" and place a +# breakpoint on the next function. +# +# See the .c file for more details. + +standard_testfile + +set shlib_path [standard_output_file ${testfile}-lib.so] +if {[build_executable "build shlib" $shlib_path $srcfile {debug shlib}]} { + return +} + +set opts [list debug shlib_load additional_flags=-DTHE_LIB_PATH="${shlib_path}"] +if {[build_executable "failed to prepare" ${testfile} ${srcfile} $opts]} { + return +} + +proc do_test {} { + clean_restart $::binfile + + # To make things easier, just so we don't have to deal with the question. + gdb_test_no_output "set breakpoint pending on" + + set lineno [gdb_get_line_number "break here"] + gdb_test "break $lineno" \ + [multi_line \ + "No compiled code for line $lineno in the current file\\." \ + "Breakpoint 1 \\($lineno\\) pending\\."] \ + "breakpoint on a line outside any function" + + gdb_run_cmd + gdb_test_multiple "" "stop on lib function breakpoint" { + -re -wrap "Breakpoint 1, the_lib_func .*29.*x\\+\\+.*" { + pass $gdb_test_name + } + } +} + +do_test diff --git a/gdb/testsuite/gdb.linespec/ls-errs.c b/gdb/testsuite/gdb.linespec/ls-errs.c index 73b06fc..1dfccab 100644 --- a/gdb/testsuite/gdb.linespec/ls-errs.c +++ b/gdb/testsuite/gdb.linespec/ls-errs.c @@ -21,6 +21,16 @@ myfunction (int aa) int i; i = aa + 42; + + /* These lines are intentionally left blank such that the tests trying + to place breakpoints at line -10 relative to the "set.breakpoint.here" + line below land on a valid breakpoint location, inside the function. */ + + + + + + return i; /* set breakpoint here */ } diff --git a/gdb/testsuite/gdb.linespec/ls-errs.exp b/gdb/testsuite/gdb.linespec/ls-errs.exp index 48c8a5f..58125f3 100644 --- a/gdb/testsuite/gdb.linespec/ls-errs.exp +++ b/gdb/testsuite/gdb.linespec/ls-errs.exp @@ -71,8 +71,8 @@ proc do_test {lang} { "Undefined convenience variable or function \"%s\" not defined in \"%s\"." invalid_label "No label \"%s\" defined in function \"%s\"." invalid_parm "invalid linespec argument, \"%s\"" - invalid_offset "No line %d in the current file." - invalid_offset_f "No line %d in file \"%s\"." + invalid_offset "No compiled code for line %d in the current file." + invalid_offset_f "No compiled code for line %d in file \"%s\"." malformed_line_offset "malformed line offset: \"%s\"" source_incomplete \ "Source filename requires function, label, or line offset." @@ -135,14 +135,14 @@ proc do_test {lang} { foreach x {1 +1 +100 -10} { test_break "3 $x" unexpected_opt "number" $x - test_break "-line 3 $x" garbage $x + test_break "-line 34 $x" garbage $x test_break "+10 $x" unexpected_opt "number" $x test_break "-line +10 $x" garbage $x test_break "-10 $x" unexpected_opt "number" $x test_break "-line -10 $x" garbage $x } - foreach x {3 +10 -10} { + foreach x {34 +10 -10} { test_break "$x foo" unexpected_opt "string" "foo" test_break "-line $x foo" garbage "foo" } @@ -207,12 +207,12 @@ proc do_test {lang} { test_break "${srcfile}::" invalid_function "${srcfile}::" test_break "$srcfile:3 1" unexpected_opt "number" "1" - test_break "-source $srcfile -line 3 1" garbage "1" + test_break "-source $srcfile -line 34 1" garbage "1" test_break "$srcfile:3 +100" unexpected_opt "number" "+100" - test_break "-source $srcfile -line 3 +100" garbage "+100" + test_break "-source $srcfile -line 34 +100" garbage "+100" test_break "$srcfile:3 -100" unexpected_opt "number" "-100" test_break "$srcfile:3 foo" unexpected_opt "string" "foo" - test_break "-source $srcfile -line 3 foo" garbage "foo" + test_break "-source $srcfile -line 34 foo" garbage "foo" foreach x $invalid_offsets { test_break "$srcfile:$x" invalid_offset_f $x $srcfile diff --git a/gdb/testsuite/gdb.python/py-breakpoint.exp b/gdb/testsuite/gdb.python/py-breakpoint.exp index c44477c..934690d 100644 --- a/gdb/testsuite/gdb.python/py-breakpoint.exp +++ b/gdb/testsuite/gdb.python/py-breakpoint.exp @@ -743,7 +743,9 @@ proc_with_prefix test_bkpt_explicit_loc {} { "No source file named foo.*" \ "set invalid explicit breakpoint by missing source and line" gdb_test "python bp1 = gdb.Breakpoint (source=\"$srcfile\", line=\"900\")" \ - "No line 900 in file \"$srcfile\".*" \ + [multi_line \ + "^No compiled code for line 900 in file \"$srcfile\"\\." \ + "Breakpoint $::decimal \[^\r\n\]+ pending\\."] \ "set invalid explicit breakpoint by source and invalid line" gdb_test "python bp1 = gdb.Breakpoint (function=\"blah\")" \ "Function \"blah\" not defined.*" \ diff --git a/gdb/testsuite/gdb.trace/tfind.exp b/gdb/testsuite/gdb.trace/tfind.exp index 9d1f6e3..c6ac80b 100644 --- a/gdb/testsuite/gdb.trace/tfind.exp +++ b/gdb/testsuite/gdb.trace/tfind.exp @@ -342,10 +342,10 @@ gdb_test "disassemble gdb_c_test" \ "8.36: trace disassembly" gdb_test "tfind line 0" \ - "out of range.*|failed to find.*|No line 0 in .*" \ + "out of range.*|failed to find.*|No compiled code for line 0 in .*" \ "8.18: tfind line 0" gdb_test "tfind line 32767" \ - "out of range.*|failed to find.*|No line 32767 in .*" \ + "out of range.*|failed to find.*|No compiled code for line 32767 in .*" \ "8.27: tfind line 32767" gdb_test "tfind line NoSuChFiLe.c:$baseline" \ "No source file named.*" \ diff --git a/gdb/testsuite/gdb.trace/tracecmd.exp b/gdb/testsuite/gdb.trace/tracecmd.exp index 96596ea..688980c 100644 --- a/gdb/testsuite/gdb.trace/tracecmd.exp +++ b/gdb/testsuite/gdb.trace/tracecmd.exp @@ -64,7 +64,8 @@ gdb_test "info trace" "in gdb_recursion_test.*$srcfile:$testline2. # 1.2 trace invalid source line gdb_delete_tracepoints gdb_test_no_output "set breakpoint pending off" -gdb_test "trace $srcfile:99999" "No line 99999 in file \".*$srcfile\"." \ +gdb_test "trace $srcfile:99999" \ + "No compiled code for line 99999 in file \".*$srcfile\"\\." \ "1.2a: trace invalid line in sourcefile" gdb_test "info trace" "No tracepoints.*" \ "1.2b: reject invalid line in srcfile" |