1# Copyright 2013-2023 Free Software Foundation, Inc. 2 3# This program is free software; you can redistribute it and/or modify 4# it under the terms of the GNU General Public License as published by 5# the Free Software Foundation; either version 3 of the License, or 6# (at your option) any later version. 7# 8# This program is distributed in the hope that it will be useful, 9# but WITHOUT ANY WARRANTY; without even the implied warranty of 10# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11# GNU General Public License for more details. 12# 13# You should have received a copy of the GNU General Public License 14# along with this program. If not, see <http://www.gnu.org/licenses/>. 15 16load_lib "range-stepping-support.exp" 17 18standard_testfile 19set executable $testfile 20 21if { [prepare_for_testing "failed to prepare" $testfile $srcfile {debug}] } { 22 return -1 23} 24 25if ![runto_main] { 26 return -1 27} 28 29if ![gdb_range_stepping_enabled] { 30 unsupported "range stepping not supported by the target" 31 return -1 32} 33 34# Check that range stepping can step a range of multiple instructions. 35 36with_test_prefix "multi insns" { 37 38 gdb_breakpoint [gdb_get_line_number "location 1"] 39 gdb_continue_to_breakpoint "location 1" 40 41 set pc_before_stepping "" 42 set test "pc before stepping" 43 gdb_test_multiple "print/x \$pc" $test { 44 -re "\\\$$decimal = (\[^\r\n\]*)\r\n$gdb_prompt $" { 45 set pc_before_stepping $expect_out(1,string) 46 pass $test 47 } 48 } 49 50 # When "next" is executed, GDB should send one vCont;s and vCont;r 51 # and receive two stop replies: 52 # 53 # --> vCont;s (step over breakpoint) 54 # <-- T05 55 # --> vCont;rSTART,END (range step) 56 # <-- T05 57 set result [exec_cmd_expect_vCont_count "next" 1] 58 if { $result } { 59 # This is the first range-stepping test, and the simplest 60 # one. If it fails, probably the rest of the tests would 61 # fail too, and the huge number of rsp packets in the test 62 # with the time-consuming loop would blow up the gdb.log file. 63 # Skip the rest of the tests. 64 return 65 } 66 67 set pc_after_stepping "" 68 set msg "pc after stepping" 69 gdb_test_multiple "print/x \$pc" $msg { 70 -re "\\\$$decimal = (\[^\r\n\]*)\r\n$gdb_prompt $" { 71 set pc_after_stepping $expect_out(1,string) 72 pass $msg 73 } 74 } 75 76 # There should be at least two instructions between 77 # PC_BEFORE_STEPPING and PC_AFTER_STEPPING. 78 gdb_test "disassemble ${pc_before_stepping},${pc_after_stepping}" \ 79 "${hex} <main\\+${decimal}>:.*${hex} <main\\+${decimal}>:.*" \ 80 "stepped multiple insns" 81} 82 83# Check that range stepping can step over a function. 84 85with_test_prefix "step over func" { 86 87 set line_num [gdb_get_line_number "location 2"] 88 gdb_test "where" "main \\(\\) at .*${srcfile}:${line_num}.*" 89 90 # It's expected to get three stops and two 'vCont;r's. In the C 91 # code, the line of C source produces roughly the following 92 # instructions: 93 # 94 # addr1: 95 # insn1 96 # insn2 97 # ... 98 # call func1 99 # addr2: 100 # ... 101 # insn3 102 # addr3: 103 # insn4 104 # 105 # Something like this will happen: 106 # --> vCont;rADDR1,ADDR3 (range step from ADDR1 to ADDR3) 107 # <-- T05 (target single-stepped to func, which is out of the step range) 108 # --> $Z0,ADDR2 (place step-resume breakpoint at ADDR2) 109 # --> vCont;c (resume) 110 # <-- T05 (target stops at ADDR2) 111 # --> vCont;rADDR1,ADDR3 (continues range stepping) 112 # <-- T05 113 exec_cmd_expect_vCont_count "next" 2 114} 115 116# Check that breakpoints interrupt range stepping correctly. 117 118with_test_prefix "breakpoint" { 119 gdb_breakpoint "func1" 120 # Something like this will happen: 121 # --> vCont;rADDR1,ADDR3 122 # <-- T05 (target single-steps to func1, which is out of the step range) 123 # --> $Z0,ADDR2 (step-resume breakpoint at ADDR2) 124 # --> vCont;c (resume) 125 # <-- T05 (target hits the breakpoint at func1) 126 exec_cmd_expect_vCont_count "next" 1 127 128 gdb_test "backtrace" "#0 .* func1 .*#1 .* main .*" \ 129 "backtrace from func1" 130 131 # A cancelled range step should not confuse the following 132 # execution commands. 133 exec_cmd_expect_vCont_count "stepi" 0 134 gdb_test "finish" ".*" 135 gdb_test "next" ".*" 136 delete_breakpoints 137} 138 139# Check that range stepping works well even when there's a loop in the 140# step range. 141 142with_test_prefix "loop" { 143 144 # GDB should send one vCont;r and receive one stop reply: 145 # --> vCont;rSTART,END (range step) 146 # <-- T05 147 exec_cmd_expect_vCont_count "next" 1 148 149 # Confirm the loop completed. 150 gdb_test "print a" " = 15" 151 gdb_test "print e" " = 105" 152} 153 154# Check that range stepping works well even when the target's PC was 155# already within the loop's body. 156 157with_test_prefix "loop 2" { 158 # Stepi into the loop body. 15 should be large enough to make 159 # sure the program stops within the loop's body. 160 gdb_test "stepi 15" ".*" 161 # GDB should send one vCont;r and receive one stop reply: 162 # --> vCont;rSTART,END (range step) 163 # <-- T05 164 exec_cmd_expect_vCont_count "next" 1 165 166 # Confirm the loop completed. 167 gdb_test "print a" " = 15" 168 gdb_test "print e" " = 105" 169} 170 171# Check that range stepping works well even when it is interrupted by 172# ctrl-c. 173 174if ![target_info exists gdb,nointerrupts] { 175 with_test_prefix "interrupt" { 176 gdb_test_no_output "set debug remote 1" 177 178 send_gdb "next\n" 179 sleep 1 180 send_gdb "\003" 181 182 # GDB should send one vCont;r and receive one stop reply for 183 # SIGINT: 184 # --> vCont;rSTART,END (range step) 185 # <-- T02 (SIGINT) 186 187 set vcont_r_counter 0 188 189 set test "send ctrl-c to GDB" 190 gdb_test_multiple "" $test { 191 -re "vCont;r\[^\r\n\]*\.\.\." { 192 incr vcont_r_counter 193 exp_continue 194 } 195 -re "Program received signal SIGINT.*$gdb_prompt $" { 196 pass $test 197 } 198 } 199 gdb_test_no_output "set debug remote 0" 200 201 # Check the number of 'vCont;r' packets. 202 if { $vcont_r_counter == 1 } { 203 pass "${test}: 1 vCont;r" 204 } else { 205 fail "${test}: 1 vCont;r" 206 } 207 208 # Break the loop earlier and continue range stepping. 209 gdb_test "set variable c = 0" 210 exec_cmd_expect_vCont_count "next" 1 211 } 212} 213 214# Check that range stepping doesn't break software watchpoints. With 215# those, GDB needs to be notified of all single-steps, to evaluate 216# whether the watched value changes at each step. 217with_test_prefix "software watchpoint" { 218 gdb_test "step" "soft-watch.*" "step into multiple instruction line" 219 # A software watchpoint at PC makes the thread stop before the 220 # whole line range is over (after one single-step, actually). 221 gdb_test "watch \$pc" ".*" "set watchpoint" 222 gdb_test "step" "soft-watch.*" "step still in same line" 223} 224 225return 0 226