]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/testsuite/gdb.base/step-over-syscall.exp
Update copyright year range in header of all files managed by GDB
[thirdparty/binutils-gdb.git] / gdb / testsuite / gdb.base / step-over-syscall.exp
CommitLineData
9c317b71
YQ
1# This testcase is part of GDB, the GNU debugger.
2
1d506c26 3# Copyright 2011-2024 Free Software Foundation, Inc.
9c317b71
YQ
4
5# This program is free software; you can redistribute it and/or modify
6# it under the terms of the GNU General Public License as published by
7# the Free Software Foundation; either version 3 of the License, or
8# (at your option) any later version.
9#
10# This program is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13# GNU General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License
16# along with this program. If not, see <http://www.gnu.org/licenses/>.
17
9c317b71 18set syscall_insn ""
16b10d6e
LM
19set syscall_register ""
20array set syscall_number {}
9c317b71 21
16b10d6e 22# Define the syscall instructions, registers and numbers for each target.
9c317b71
YQ
23
24if { [istarget "i\[34567\]86-*-linux*"] || [istarget "x86_64-*-linux*"] } {
202be274 25 set syscall_insn "\[ \t\](int|syscall|sysenter)\[ \t\]*"
16b10d6e
LM
26 set syscall_register "eax"
27 array set syscall_number {fork "(56|120)" vfork "(58|190)" \
28 clone "(56|120)"}
99fd02d9 29} elseif { [istarget "aarch64*-*-linux*"] || [istarget "arm*-*-linux*"] } {
5d0a3b53 30 set syscall_insn "\[ \t\](swi|svc)\[ \t\]"
16b10d6e
LM
31
32 if { [istarget "aarch64*-*-linux*"] } {
33 set syscall_register "x8"
34 } else {
35 set syscall_register "r7"
36 }
37
38 array set syscall_number {fork "(120|220)" vfork "(190|220)" \
39 clone "(120|220)"}
9c317b71
YQ
40} else {
41 return -1
42}
43
99ba4b64 44proc_with_prefix check_pc_after_cross_syscall { displaced syscall syscall_insn_next_addr } {
0b47da9f
YQ
45 set syscall_insn_next_addr_found [get_hexadecimal_valueof "\$pc" "0"]
46
99ba4b64 47 # After the 'stepi' we expect thread 1 to still be selected.
99ba4b64 48 set curr_thread "unknown"
6bd50ebd
PA
49 gdb_test_multiple "thread" "" {
50 -re -wrap "Current thread is (\\d+) .*" {
99ba4b64 51 set curr_thread $expect_out(1,string)
6bd50ebd 52 pass $gdb_test_name
99ba4b64
AB
53 }
54 }
55
16b10d6e 56 gdb_assert {$syscall_insn_next_addr != 0 \
99ba4b64
AB
57 && $syscall_insn_next_addr == $syscall_insn_next_addr_found \
58 && $curr_thread == 1} \
16b10d6e
LM
59 "single step over $syscall final pc"
60}
61
62# Verify the syscall number is the correct one.
63
64proc syscall_number_matches { syscall } {
65 global syscall_register syscall_number
66
67 if {[gdb_test "p \$$syscall_register" ".*= $syscall_number($syscall)" \
68 "syscall number matches"] != 0} {
69 return 0
70 }
71
72 return 1
0b47da9f 73}
9c317b71 74
0b47da9f
YQ
75# Restart GDB and set up the test. Return a list in which the first one
76# is the address of syscall instruction and the second one is the address
77# of the next instruction address of syscall instruction. If anything
78# wrong, the two elements of list are -1.
9c317b71 79
0b47da9f
YQ
80proc setup { syscall } {
81 global gdb_prompt syscall_insn
9c317b71 82
16b10d6e
LM
83 global hex
84 set next_insn_addr -1
8fc8cbda 85 set testfile "step-over-$syscall"
9c317b71 86
0b47da9f 87 clean_restart $testfile
9c317b71 88
65a33d75 89 if {![runto_main]} {
0b47da9f
YQ
90 return -1
91 }
9c317b71 92
0b47da9f
YQ
93 # Delete the breakpoint on main.
94 gdb_test_no_output "delete break 1"
9c317b71 95
2b74ba5a
AB
96 gdb_test_no_output "set displaced-stepping off" \
97 "set displaced-stepping off during test setup"
9c317b71 98
16b10d6e 99 gdb_test "break \*$syscall" "Breakpoint \[0-9\]* at .*"
9c317b71 100
906c2c65 101 gdb_test "continue" "Continuing\\..*Breakpoint \[0-9\]+, (.* in )?(__libc_)?$syscall \\(\\).*" \
0b47da9f
YQ
102 "continue to $syscall (1st time)"
103 # Hit the breakpoint on $syscall for the first time. In this time,
104 # we will let PLT resolution done, and the number single steps we will
105 # do later will be reduced.
9c317b71 106
906c2c65 107 gdb_test "continue" "Continuing\\..*Breakpoint \[0-9\]+, (.* in )?(__libc_)?$syscall \\(\\).*" \
0b47da9f
YQ
108 "continue to $syscall (2nd time)"
109 # Hit the breakpoint on $syscall for the second time. In this time,
110 # the address of syscall insn and next insn of syscall are recorded.
9c317b71 111
16b10d6e
LM
112 # Check if the first instruction we stopped at is the syscall one.
113 set syscall_insn_addr -1
114 gdb_test_multiple "display/i \$pc" "fetch first stop pc" {
115 -re "display/i .*: x/i .*=> ($hex) .*:.*$syscall_insn.*$gdb_prompt $" {
116 set insn_addr $expect_out(1,string)
0b47da9f 117
16b10d6e
LM
118 # Is the syscall number the correct one?
119 if {[syscall_number_matches $syscall]} {
120 set syscall_insn_addr $insn_addr
121 }
122 pass $gdb_test_name
123 }
124 -re ".*$gdb_prompt $" {
125 pass $gdb_test_name
0b47da9f 126 }
16b10d6e
LM
127 }
128
129 # If we are not at the syscall instruction yet, keep looking for it with
130 # stepi commands.
131 if {$syscall_insn_addr == -1} {
132 # Single step until we see a syscall insn or we reach the
133 # upper bound of loop iterations.
134 set steps 0
135 set max_steps 1000
136 gdb_test_multiple "stepi" "find syscall insn in $syscall" {
137 -re ".*$syscall_insn.*$gdb_prompt $" {
138 # Is the syscall number the correct one?
139 if {[syscall_number_matches $syscall]} {
140 pass $gdb_test_name
141 } else {
142 exp_continue
143 }
9c317b71 144 }
16b10d6e
LM
145 -re "x/i .*=>.*\r\n$gdb_prompt $" {
146 incr steps
147 if {$steps == $max_steps} {
148 fail $gdb_test_name
149 } else {
150 send_gdb "stepi\n"
151 exp_continue
152 }
153 }
154 }
155
156 if {$steps == $max_steps} {
157 return { -1, -1 }
9c317b71 158 }
0b47da9f
YQ
159 }
160
16b10d6e
LM
161 # We have found the syscall instruction. Now record the next instruction.
162 # Use the X command instead of stepi since we can't guarantee
163 # stepi is working properly.
164 gdb_test_multiple "x/2i \$pc" "pc before/after syscall instruction" {
165 -re "x/2i .*=> ($hex) .*:.*$syscall_insn.* ($hex) .*:.*$gdb_prompt $" {
166 set syscall_insn_addr $expect_out(1,string)
14852123 167 set actual_syscall_insn $expect_out(2,string)
16b10d6e
LM
168 set next_insn_addr $expect_out(3,string)
169 pass $gdb_test_name
170 }
0b47da9f
YQ
171 }
172
14852123
TV
173 # If we encounter a sequence:
174 # 0xf7fd5155 <__kernel_vsyscall+5>: sysenter
175 # 0xf7fd5157 <__kernel_vsyscall+7>: int $0x80
176 # 0xf7fd5159 <__kernel_vsyscall+9>: pop %ebp
177 # then a stepi at sysenter will step over the int insn, so make sure
178 # next_insn_addr points after the int insn.
179 if { $actual_syscall_insn == "sysenter" } {
180 set test "pc after sysenter instruction"
181 set re_int_insn "\[ \t\]*int\[ \t\]\[^\r\n\]*"
182 set re [multi_line \
183 "x/2i $hex" \
184 "\[^\r\n\]* $hex \[^\r\n\]*:$re_int_insn" \
185 "\[^\r\n\]* ($hex) \[^\r\n\]*:\[^\r\n\]*"]
186 gdb_test_multiple "x/2i $next_insn_addr" $test {
187 -re -wrap $re {
188 set next_insn_addr $expect_out(1,string)
189 }
190 -re -wrap "" {
191 }
192 }
193 }
194
0b47da9f
YQ
195 if {[gdb_test "stepi" "x/i .*=>.*" "stepi $syscall insn"] != 0} {
196 return { -1, -1 }
197 }
16b10d6e
LM
198
199 set pc_after_stepi [get_hexadecimal_valueof "\$pc" "0" \
200 "pc after stepi"]
201
202 gdb_assert {$next_insn_addr == $pc_after_stepi} \
203 "pc after stepi matches insn addr after syscall"
204
205 return [list $syscall_insn_addr $pc_after_stepi]
0b47da9f 206}
9c317b71 207
8fc8cbda 208proc step_over_syscall { syscall } {
0b47da9f
YQ
209 with_test_prefix "$syscall" {
210 global syscall_insn
211 global gdb_prompt
212
8fc8cbda 213 set testfile "step-over-$syscall"
0b47da9f 214
99ba4b64
AB
215 set options [list debug]
216 if { $syscall == "clone" } {
217 lappend options "pthreads"
218 }
219
220 if [build_executable ${testfile}.exp ${testfile} ${testfile}.c $options] {
5b362f04 221 untested "failed to compile"
0a251e08
YQ
222 return -1
223 }
9c317b71 224
e197ad3c
YQ
225 foreach_with_prefix displaced {"off" "on"} {
226 if {$displaced == "on" && ![support_displaced_stepping]} {
227 continue
228 }
229
ea507862 230 set ret [setup $syscall]
0b47da9f 231
ea507862
YQ
232 set syscall_insn_addr [lindex $ret 0]
233 set syscall_insn_next_addr [lindex $ret 1]
234 if { $syscall_insn_addr == -1 } {
235 return -1
236 }
9c317b71 237
906c2c65 238 gdb_test "continue" "Continuing\\..*Breakpoint \[0-9\]+, (.* in )?(__libc_)?$syscall \\(\\).*" \
ea507862 239 "continue to $syscall (3rd time)"
9c317b71 240
ea507862
YQ
241 # Hit the breakpoint on $syscall for the third time. In this time, we'll set
242 # breakpoint on the syscall insn we recorded previously, and single step over it.
9c317b71 243
ea507862
YQ
244 set syscall_insn_bp 0
245 gdb_test_multiple "break \*$syscall_insn_addr" "break on syscall insn" {
246 -re "Breakpoint (\[0-9\]*) at .*$gdb_prompt $" {
247 set syscall_insn_bp $expect_out(1,string)
248 pass "break on syscall insns"
249 }
0a251e08 250 }
9c317b71 251
16b10d6e
LM
252 # Check if the syscall breakpoint is at the syscall instruction
253 # address. If so, no need to continue, otherwise we will run the
254 # inferior to completion.
255 if {$syscall_insn_addr != [get_hexadecimal_valueof "\$pc" "0"]} {
256 gdb_test "continue" "Continuing\\..*Breakpoint \[0-9\]+, .*" \
257 "continue to syscall insn $syscall"
258 }
9c317b71 259
ea507862 260 gdb_test_no_output "set displaced-stepping $displaced"
9c317b71 261
ea507862
YQ
262 # Check the address of next instruction of syscall.
263 if {[gdb_test "stepi" "x/i .*=>.*" "single step over $syscall"] != 0} {
264 return -1
265 }
99ba4b64 266 check_pc_after_cross_syscall $displaced $syscall $syscall_insn_next_addr
dfe2ac14 267
ea507862
YQ
268 # Delete breakpoint syscall insns to avoid interference to other syscalls.
269 delete_breakpoints
9a7f938f 270
ea507862 271 gdb_test "break marker" "Breakpoint.*at.* file .*${testfile}.c, line.*"
99ba4b64 272
ea507862
YQ
273 gdb_test "continue" "Continuing\\..*Breakpoint \[0-9\]+, marker \\(\\) at.*" \
274 "continue to marker ($syscall)"
e197ad3c 275 }
9a7f938f 276 }
0a251e08 277}
9c317b71 278
92fa70b0
YQ
279# Set a breakpoint with a condition that evals false on syscall
280# instruction. In fact, it tests GDBserver steps over syscall
21a77091
YQ
281# instruction. SYSCALL is the syscall the program calls.
282# FOLLOW_FORK is either "parent" or "child". DETACH_ON_FORK is
283# "on" or "off".
92fa70b0 284
21a77091 285proc break_cond_on_syscall { syscall follow_fork detach_on_fork } {
92fa70b0 286 with_test_prefix "break cond on target : $syscall" {
8fc8cbda 287 set testfile "step-over-$syscall"
92fa70b0
YQ
288
289 set ret [setup $syscall]
290
291 set syscall_insn_addr [lindex $ret 0]
292 set syscall_insn_next_addr [lindex $ret 1]
293 if { $syscall_insn_addr == -1 } {
294 return -1
295 }
296
906c2c65 297 gdb_test "continue" "Continuing\\..*Breakpoint \[0-9\]+, (.* in )?(__libc_)?$syscall \\(\\).*" \
92fa70b0
YQ
298 "continue to $syscall"
299 # Delete breakpoint syscall insns to avoid interference with other syscalls.
300 delete_breakpoints
301
21a77091
YQ
302 gdb_test "set follow-fork-mode $follow_fork"
303 gdb_test "set detach-on-fork $detach_on_fork"
92fa70b0
YQ
304
305 # Create a breakpoint with a condition that evals false.
306 gdb_test "break \*$syscall_insn_addr if main == 0" \
307 "Breakpoint \[0-9\]* at .*"
308
4719d415
YQ
309 if { $syscall == "clone" } {
310 # Create a breakpoint in the child with the condition that
311 # evals false, so that GDBserver can get the event from the
312 # child but GDB doesn't see it. In this way, we don't have
313 # to adjust the test flow for "clone".
314 # This is a regression test for PR server/19736. In this way,
315 # we can test that GDBserver gets an event from the child and
316 # set suspend count correctly while the parent is stepping over
317 # the breakpoint.
318 gdb_test "break clone_fn if main == 0"
319 }
320
21a77091
YQ
321 if { $syscall == "clone" } {
322 # follow-fork and detach-on-fork only make sense to
323 # fork and vfork.
324 gdb_test "break marker" "Breakpoint.*at.* file .*${testfile}.c, line.*"
325 gdb_test "continue" "Continuing\\..*Breakpoint \[0-9\]+, marker \\(\\) at.*" \
326 "continue to marker"
327 } else {
328 if { $follow_fork == "child" } {
329 gdb_test "continue" "exited normally.*" "continue to end of inf 2"
330 if { $detach_on_fork == "off" } {
331 gdb_test "inferior 1"
332 gdb_test "break marker" "Breakpoint.*at.*"
e66c9ede 333 gdb_test "continue" "Continuing\\..*Breakpoint $::bkptno_numopt_re, marker \\(\\) at.*" \
21a77091
YQ
334 "continue to marker"
335 }
336 } else {
337 gdb_test "break marker" "Breakpoint.*at.* file .*${testfile}.c, line.*"
e66c9ede 338 gdb_test "continue" "Continuing\\..*Breakpoint $::bkptno_numopt_re, marker \\(\\) at.*" \
21a77091
YQ
339 "continue to marker"
340 }
341 }
92fa70b0
YQ
342 }
343}
344
8fc8cbda
YQ
345step_over_syscall "fork"
346step_over_syscall "vfork"
4719d415 347step_over_syscall "clone"
92fa70b0 348
8fc8cbda 349set testfile "step-over-fork"
92fa70b0 350clean_restart $testfile
65a33d75 351if {![runto_main]} {
92fa70b0
YQ
352 return -1
353}
354
355set cond_bp_target 1
356
357set test "set breakpoint condition-evaluation target"
358gdb_test_multiple $test $test {
359 -re "warning: Target does not support breakpoint condition evaluation.\r\nUsing host evaluation mode instead.\r\n$gdb_prompt $" {
360 # Target doesn't support breakpoint condition
361 # evaluation on its side.
362 set cond_bp_target 0
363 }
364 -re "^$test\r\n$gdb_prompt $" {
365 }
366}
367
368if { $cond_bp_target } {
21a77091
YQ
369
370 foreach_with_prefix detach-on-fork {"on" "off"} {
371 foreach_with_prefix follow-fork {"parent" "child"} {
372 foreach syscall { "fork" "vfork" "clone" } {
373
374 if { $syscall == "vfork"
375 && ${follow-fork} == "parent"
376 && ${detach-on-fork} == "off" } {
377 # Both vforked child process and parent process are
378 # under GDB's control, but GDB follows the parent
379 # process only, which can't be run until vforked child
380 # finishes. Skip the test in this scenario.
381 continue
382 }
383 break_cond_on_syscall $syscall ${follow-fork} ${detach-on-fork}
384 }
385 }
386 }
92fa70b0 387}