xref: /netbsd-src/external/gpl3/gdb.old/dist/gdb/testsuite/gdb.base/range-stepping.exp (revision 32d1c65c71fbdb65a012e8392a62a757dd6853e9)
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