diff options
-rw-r--r-- | gdb/infcmd.c | 13 | ||||
-rw-r--r-- | gdb/testsuite/gdb.mi/mi-reverse.exp | 5 | ||||
-rw-r--r-- | gdb/testsuite/gdb.reverse/finish-reverse-next.exp | 40 | ||||
-rw-r--r-- | gdb/testsuite/gdb.reverse/func-map-to-same-line.c | 37 | ||||
-rw-r--r-- | gdb/testsuite/gdb.reverse/func-map-to-same-line.exp | 140 |
5 files changed, 201 insertions, 34 deletions
diff --git a/gdb/infcmd.c b/gdb/infcmd.c index 511cf5f..a3c3279 100644 --- a/gdb/infcmd.c +++ b/gdb/infcmd.c @@ -976,6 +976,19 @@ prepare_one_step (thread_info *tp, struct step_command_fsm *sm) &tp->control.step_range_start, &tp->control.step_range_end); + if (execution_direction == EXEC_REVERSE) + { + symtab_and_line sal = find_pc_line (pc, 0); + symtab_and_line sal_start + = find_pc_line (tp->control.step_range_start, 0); + + if (sal.line == sal_start.line) + /* Executing in reverse, the step_range_start address is in + the same line. We want to stop in the previous line so + move step_range_start before the current line. */ + tp->control.step_range_start--; + } + /* There's a problem in gcc (PR gcc/98780) that causes missing line table entries, which results in a too large stepping range. Use inlined_subroutine info to make the range more narrow. */ diff --git a/gdb/testsuite/gdb.mi/mi-reverse.exp b/gdb/testsuite/gdb.mi/mi-reverse.exp index baa53a4..0630b8b 100644 --- a/gdb/testsuite/gdb.mi/mi-reverse.exp +++ b/gdb/testsuite/gdb.mi/mi-reverse.exp @@ -96,11 +96,8 @@ proc test_controlled_execution_reverse {} { "reverse finish from callme" # Test exec-reverse-next - # It takes two steps to get back to the previous line, - # as the first step moves us to the start of the current line, - # and the one after that moves back to the previous line. - mi_execute_to "exec-next --reverse 2" \ + mi_execute_to "exec-next --reverse" \ "end-stepping-range" "main" "" \ "basics.c" $line_main_hello "" \ "reverse next to get over the call to do_nothing" diff --git a/gdb/testsuite/gdb.reverse/finish-reverse-next.exp b/gdb/testsuite/gdb.reverse/finish-reverse-next.exp index 1f53b64..6488f66 100644 --- a/gdb/testsuite/gdb.reverse/finish-reverse-next.exp +++ b/gdb/testsuite/gdb.reverse/finish-reverse-next.exp @@ -76,14 +76,10 @@ gdb_continue_to_breakpoint \ repeat_cmd_until "stepi" "CALL VIA LEP" "{" "stepi into function1 call" "100" # The reverse-finish command should stop on the function call instruction -# which is the last instruction in the source code line. A reverse-next -# instruction should then stop at the first instruction in the same source -# code line. Another revers-next instruction stops at the previous source -# code line. +# which is the last instruction in the source code line. Another reverse-next +# instruction stops at the previous source code line. gdb_test "reverse-finish" ".*function1 \\(a, b\\); // CALL VIA LEP.*" \ "reverse-finish function1 LEP call from LEP " -gdb_test "reverse-next" ".*function1 \\(a, b\\); // CALL VIA LEP" \ - "reverse next 1 LEP entry point function call from LEP" gdb_test "reverse-next" ".*b = 5;.*" "reverse next 2, at b = 5, call from LEP" @@ -109,14 +105,10 @@ gdb_continue_to_breakpoint \ gdb_test "step" ".*int ret = 0;.*" "step test 1" # The reverse-finish command should stop on the function call instruction -# which is the last instruction in the source code line. A reverse-next -# instruction should then stop at the first instruction in the same source -# code line. Another revers-next instruction stops at the previous source -# code line. +# which is the last instruction in the source code line. Another reverse-next +# instruction stops at the previous source code line. gdb_test "reverse-finish" ".*function1 \\(a, b\\); // CALL VIA LEP.*" \ "reverse-finish function1 LEP call from function body" -gdb_test "reverse-next" ".*function1 \\(a, b\\); // CALL VIA LEP.*" \ - "reverse next 1 LEP from function body" gdb_test "reverse-next" ".*b = 5;.*" \ "reverse next 2 at b = 5, from function body" @@ -144,14 +136,10 @@ gdb_continue_to_breakpoint \ repeat_cmd_until "stepi" "CALL VIA GEP" "{" "stepi into funp call" # The reverse-finish command should stop on the function call instruction -# which is the last instruction in the source code line. A reverse-next -# instruction should then stop at the first instruction in the same source -# code line. Another revers-next instruction stops at the previous source -# code line. +# which is the last instruction in the source code line. Another reverse-next +# instruction stops at the previous source code line. gdb_test "reverse-finish" ".*funp \\(a, b\\);.*" \ "function1 GEP call call from GEP" -gdb_test "reverse-next" ".*funp \\(a, b\\);.*" \ - "reverse next 1 GEP entry point function call from GEP" gdb_test "reverse-next" ".*b = 50;.*" "reverse next 2 at b = 50, call from GEP" gdb_test "reverse-continue" ".*" "setup for test 4" @@ -180,14 +168,10 @@ repeat_cmd_until "stepi" "CALL VIA GEP" "{" "stepi into funp call again" gdb_test "stepi" "{" "stepi to between GEP and LEP" # The reverse-finish command should stop on the function call instruction -# which is the last instruction in the source code line. A reverse-next -# instruction should then stop at the first instruction in the same source -# code line. Another revers-next instruction stops at the previous source -# code line. +# which is the last instruction in the source code line. Another reverse-next +# instruction stops at the previous source code line. gdb_test "reverse-finish" ".*funp \\(a, b\\);.*" \ "function1 GEP call call from GEP again" -gdb_test "reverse-next" ".*funp \\(a, b\\);.*" \ - "reverse next 1 GEP entry point function call from GEP again" gdb_test "reverse-next" ".*b = 50;.*" \ "reverse next 2 at b = 50, call from GEP again" @@ -212,13 +196,9 @@ gdb_continue_to_breakpoint \ gdb_test "step" ".*int ret = 0;.*" "step test 2" # The reverse-finish command should stop on the function call instruction -# which is the last instruction in the source code line. A reverse-next -# instruction should then stop at the first instruction in the same source -# code line. Another revers-next instruction stops at the previous source -# code line. +# which is the last instruction in the source code line. Another reverse-next +# instruction stops at the previous source code line. gdb_test "reverse-finish" ".*funp \\(a, b\\);.*" \ "reverse-finish function1 GEP call, from function body " -gdb_test "reverse-next" ".*funp \\(a, b\\);.*" \ - "reverse next 1 GEP call from function body" gdb_test "reverse-next" ".*b = 50;.*" \ "reverse next 2 at b = 50 from function body" diff --git a/gdb/testsuite/gdb.reverse/func-map-to-same-line.c b/gdb/testsuite/gdb.reverse/func-map-to-same-line.c new file mode 100644 index 0000000..17fe17a --- /dev/null +++ b/gdb/testsuite/gdb.reverse/func-map-to-same-line.c @@ -0,0 +1,37 @@ +/* Copyright 2023 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/>. + + This test is used to test the reverse-step and reverse-next instruction + execution for a source line that contains multiple function calls. */ + +void +func1 (void) +{ +} /* END FUNC1 */ + +void +func2 (void) +{ +} /* END FUNC2 */ + +int +main (void) +{ + int a, b; + a = 1; + b = 2; + func1 (); func2 (); + a = a + b; /* START REVERSE TEST */ +} diff --git a/gdb/testsuite/gdb.reverse/func-map-to-same-line.exp b/gdb/testsuite/gdb.reverse/func-map-to-same-line.exp new file mode 100644 index 0000000..b538fc9 --- /dev/null +++ b/gdb/testsuite/gdb.reverse/func-map-to-same-line.exp @@ -0,0 +1,140 @@ +# Copyright 2023 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/>. */ + +# This file is part of the GDB testsuite. It tests reverse stepping. +# Lots of code borrowed from "step-test.exp". + +# This test checks to make sure there is no regression failures for +# the reverse-next command when stepping back over two functions in +# the same line. + +require supports_reverse + +# This test uses the gcc no-column-info command which was added in gcc 7.1. + +proc run_tests {} { + global testfile + + clean_restart ${testfile} + + if { ![runto_main] } { + return + } + + with_test_prefix "next-test" { + gdb_test_no_output "record" "turn on process record" + + # This regression test verifies the reverse-step and reverse-next + # commands work properly when executing backwards thru a source line + # containing two function calls on the same source line, i.e. + # func1 (); func2 ();. This test is compiled so the dwarf info + # does not contain the line table information. + + # Test 1, reverse-next command + # Set breakpoint at the line after the function calls. + set bp_start_reverse_test [gdb_get_line_number "START REVERSE TEST"] + + gdb_breakpoint $bp_start_reverse_test temporary + + # Continue to break point for reverse-next test. + # Command definition: reverse-next [count] + # Run backward to the beginning of the previous line executed in + # the current (innermost) stack frame. If the line contains + # function calls, they will be “un-executed” without stopping. + # Starting from the first line of a function, reverse-next will + # take you back to the caller of that function, before the + # function was called, just as the normal next command would take + # you from the last line of a function back to its return to its + # caller 2. + + gdb_continue_to_breakpoint \ + "stopped at command reverse-next test start location" \ + ".*$bp_start_reverse_test\r\n.*" + + # The reverse-next should step all the way back to the beginning of + # the line, i.e. at the beginning of the func1 call. + gdb_test "reverse-next" ".*func1 \\(\\); func2 \\(\\);.*" \ + " reverse-next to line with two functions" + + # We should be stopped at the first instruction of the line. A + # reverse-step should step back and stop at the beginning of the + # previous line b = 2, i.e. not in func1 (). + gdb_test "reverse-stepi" ".*b = 2;.*" \ + "reverse-stepi to previous line b = 2" + } + + # Setup for test 2 + clean_restart ${testfile} + + if { ![runto_main] } { + return + } + + with_test_prefix "step-test" { + gdb_test_no_output "record" "turn on process record" + + # Test 2, reverse-step command + # Set breakpoint at the line after the function calls. + gdb_breakpoint $bp_start_reverse_test temporary + + # Continue to the start of the reverse-step test. + # Command definition: reverse-step [count] + # Run the program backward until control reaches the start of a + # different source line; then stop it, and return control to gdb. + # Like the step command, reverse-step will only stop at the + # beginning of a source line. It “un-executes” the previously + # executed source line. If the previous source line included calls + # to debuggable functions, reverse-step will step (backward) into + # the called function, stopping at the beginning of the last + # statement in the called function (typically a return statement). + # Also, as with the step command, if non-debuggable functions are + # called, reverse-step will run thru them backward without + # stopping. + + gdb_continue_to_breakpoint \ + "stopped at command reverse-step test start location" \ + ".*$bp_start_reverse_test\r\n.*" + + # The first reverse step should take us call of func2 (). + gdb_test "reverse-step" ".*END FUNC2.*" \ + "reverse-step into func2 " + + # The second reverse step should take us into func1 (). + gdb_test "reverse-step" ".*END FUNC1.*" \ + "reverse-step into func1 " + + # The third reverse step should take us call of func1 (). + gdb_test "reverse-step" ".*func1 \\(\\); func2 \\(\\);.*" \ + "reverse-step to line func1(); func2(), at call for func1 " + # We should be stopped at the first instruction of the line. A + # reversee stepi should take us to b = 2 (). + gdb_test "reverse-stepi" ".*b = 2;.*" \ + "reverse-stepi to line b = 2 " + } +} + +standard_testfile .c + +# test with and without gcc column info enabled +foreach_with_prefix column_info_flag {column-info no-column-info} { + set options [list debug $column_info_flag] + + if {[prepare_for_testing "failed to prepare" ${testfile} ${srcfile} \ + $options]} { + return -1 + } + + run_tests +} |