]>
Commit | Line | Data |
---|---|---|
1d506c26 | 1 | # Copyright 2004-2024 Free Software Foundation, Inc. |
f0fd9238 AC |
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 | |
e22f8b7c | 5 | # the Free Software Foundation; either version 3 of the License, or |
f0fd9238 | 6 | # (at your option) any later version. |
e22f8b7c | 7 | # |
f0fd9238 AC |
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. | |
e22f8b7c | 12 | # |
f0fd9238 | 13 | # You should have received a copy of the GNU General Public License |
e22f8b7c | 14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
f0fd9238 AC |
15 | |
16 | ||
17 | # The program sigstep.c creates a very simple backtrace containing one | |
b04e311d AC |
18 | # signal handler and signal trampoline. A flag is set and then the |
19 | # handler returns. This is repeated at infinitum. | |
f0fd9238 AC |
20 | |
21 | # This test runs the program up to the signal handler, and then | |
b04e311d | 22 | # attempts to step/next out of the handler and back into main. |
f0fd9238 | 23 | |
450d26c8 | 24 | require {!target_info exists gdb,nosignals} |
f0fd9238 | 25 | |
f0fd9238 | 26 | |
0ab77f5f TT |
27 | standard_testfile |
28 | ||
1df4399f | 29 | if {[build_executable $testfile.exp $testfile $srcfile debug]} { |
5b362f04 | 30 | untested "failed to compile" |
f0fd9238 AC |
31 | return -1 |
32 | } | |
33 | ||
1df4399f PA |
34 | set clear_done [gdb_get_line_number {done = 0}] |
35 | set infinite_loop [gdb_get_line_number {while (!done)}] | |
abbdbd03 | 36 | set other_handler_location [gdb_get_line_number "other handler location"] |
1df4399f PA |
37 | |
38 | # Restart GDB, set a display showing $PC, and run to main. | |
39 | ||
40 | proc restart {} { | |
41 | global binfile | |
42 | ||
43 | clean_restart $binfile | |
f0fd9238 | 44 | |
1df4399f PA |
45 | gdb_test "display/i \$pc" |
46 | ||
47 | runto_main | |
f0fd9238 AC |
48 | } |
49 | ||
50 | # Pass all the alarms straight through (but verbosely) | |
51 | # gdb_test "handle SIGALRM print pass nostop" | |
52 | # gdb_test "handle SIGVTALRM print pass nostop" | |
53 | # gdb_test "handle SIGPROF print pass nostop" | |
54 | ||
55 | # Run to the signal handler, validate the backtrace. | |
1df4399f PA |
56 | |
57 | proc validate_backtrace {} { | |
58 | with_test_prefix "validate backtrace" { | |
59 | restart | |
60 | ||
61 | gdb_test "break handler" | |
62 | gdb_test "continue" ".* handler .*" "continue to stepi handler" | |
63 | gdb_test_sequence "bt" "backtrace for nexti" { | |
64 | "\[\r\n\]+.0 \[^\r\n\]* handler " | |
65 | "\[\r\n\]+.1 .signal handler called." | |
66 | "\[\r\n\]+.2 \[^\r\n\]* main " | |
67 | } | |
68 | } | |
f0fd9238 AC |
69 | } |
70 | ||
1df4399f PA |
71 | validate_backtrace |
72 | ||
abbdbd03 PA |
73 | # Goes to handler using ENTER_CMD, runs IN_HANDLER while in the signal |
74 | # hander, and then steps out of the signal handler using EXIT_CMD. | |
75 | ||
76 | proc advance { enter_cmd in_handler_prefix in_handler exit_cmd } { | |
fda326dd | 77 | global gdb_prompt inferior_exited_re |
abbdbd03 | 78 | global clear_done other_handler_location |
b626a803 | 79 | global decimal |
f0fd9238 | 80 | |
abbdbd03 | 81 | set prefix "$enter_cmd to handler, $in_handler_prefix in handler, $exit_cmd from handler" |
f0fd9238 | 82 | |
abbdbd03 PA |
83 | with_test_prefix $prefix { |
84 | restart | |
1df4399f PA |
85 | |
86 | # Get us into the handler | |
abbdbd03 PA |
87 | if { $enter_cmd == "continue" } { |
88 | gdb_test "break handler" | |
89 | } else { | |
90 | gdb_test "handle SIGALRM print pass stop" | |
91 | gdb_test "handle SIGVTALRM print pass stop" | |
92 | gdb_test "continue" "Program received signal.*" "continue to signal" | |
93 | } | |
b626a803 CL |
94 | |
95 | gdb_test_multiple "$enter_cmd" "$enter_cmd to handler" { | |
96 | -re -wrap "\r\n<signal handler called>.*" { | |
97 | send_gdb "$enter_cmd\n" | |
98 | exp_continue | |
99 | } | |
100 | -re -wrap "\r\n(Breakpoint $decimal, )?handler \\(sig=.*" { | |
101 | pass $gdb_test_name | |
102 | } | |
103 | } | |
abbdbd03 PA |
104 | |
105 | delete_breakpoints | |
106 | ||
107 | uplevel 1 $in_handler | |
108 | ||
109 | if { $exit_cmd == "continue" } { | |
110 | gdb_test "break $clear_done" ".*" "break clear done" | |
111 | } | |
1df4399f PA |
112 | |
113 | set test "leave handler" | |
abbdbd03 | 114 | gdb_test_multiple "$exit_cmd" "${test}" { |
1df4399f PA |
115 | -re "Could not insert single-step breakpoint.*$gdb_prompt $" { |
116 | setup_kfail gdb/8841 "sparc*-*-openbsd*" | |
117 | fail "$test (could not insert single-step breakpoint)" | |
118 | } | |
03346981 SL |
119 | -re "Cannot insert breakpoint.*Cannot access memory.*$gdb_prompt $" { |
120 | setup_kfail gdb/8841 "nios2*-*-linux*" | |
121 | fail "$test (could not insert single-step breakpoint)" | |
122 | } | |
1df4399f | 123 | -re "done = 1;.*${gdb_prompt} $" { |
abbdbd03 | 124 | send_gdb "$exit_cmd\n" |
1df4399f PA |
125 | exp_continue -continue_timer |
126 | } | |
127 | -re "\} .. handler .*${gdb_prompt} $" { | |
abbdbd03 | 128 | send_gdb "$exit_cmd\n" |
1df4399f PA |
129 | exp_continue -continue_timer |
130 | } | |
131 | -re "$inferior_exited_re normally.*${gdb_prompt} $" { | |
132 | setup_kfail gdb/8744 powerpc-*-*bsd* | |
133 | fail "$test (program exited)" | |
134 | } | |
135 | -re "(while ..done|done = 0).*${gdb_prompt} $" { | |
136 | # After stepping out of a function /r signal-handler, GDB will | |
137 | # advance the inferior until it is at the first instruction of | |
138 | # a code-line. While typically things return to the middle of | |
139 | # the "while..." (and hence GDB advances the inferior to the | |
140 | # "return..." line) it is also possible for the return to land | |
141 | # on the first instruction of "while...". Accept both cases. | |
142 | pass "$test" | |
143 | } | |
f0fd9238 AC |
144 | } |
145 | } | |
146 | } | |
147 | ||
abbdbd03 PA |
148 | # Map of PREFIX => "things to do within the signal handler", for the |
149 | # advance tests. | |
150 | ||
151 | set in_handler_map { | |
152 | "nothing" { | |
153 | } | |
154 | "si+advance" { | |
155 | # Advance to the second location in handler. | |
156 | gdb_test "si" "handler.*" "si in handler" | |
157 | ||
158 | set test "advance in handler" | |
159 | gdb_test_multiple "advance $other_handler_location" $test { | |
160 | -re "Program received signal SIGTRAP.*$gdb_prompt $" { | |
161 | # On some versions of Linux (observed on | |
162 | # 3.16.4-200.fc20.x86_64), using PTRACE_SINGLESTEP+sig | |
163 | # to step into a signal handler, and then issuing | |
164 | # another PTRACE_SINGLESTEP within the handler ends up | |
165 | # with $eflags.TF mistakenly set, which results in | |
166 | # subsequent PTRACE_CONTINUEs trapping after each | |
167 | # insn. | |
168 | if {$enter_cmd != "continue"} { | |
9de00a4a | 169 | setup_xfail "i?86-*-linux*" gdb/17511 |
abbdbd03 PA |
170 | setup_xfail "x86_64-*-linux*" gdb/17511 |
171 | } | |
172 | fail "$test (spurious SIGTRAP)" | |
173 | return | |
174 | } | |
175 | -re "other handler location.*$gdb_prompt $" { | |
176 | pass $test | |
177 | } | |
178 | } | |
179 | } | |
180 | } | |
181 | ||
182 | # Check that we can step/next/continue, etc. our way in and out of a | |
183 | # signal handler. Also test that we can step, and run to a breakpoint | |
184 | # within the handler. | |
185 | ||
186 | foreach enter_cmd { "stepi" "nexti" "step" "next" "continue" } { | |
187 | if { $enter_cmd != "continue" && ![can_single_step_to_signal_handler] } { | |
188 | continue | |
189 | } | |
190 | ||
191 | foreach exit_cmd { "step" "next" "continue" } { | |
192 | foreach {in_handler_prefix in_handler} $in_handler_map { | |
193 | advance $enter_cmd $in_handler_prefix $in_handler $exit_cmd | |
194 | } | |
195 | } | |
196 | } | |
197 | ||
1df4399f | 198 | proc advancei { cmd } { |
fda326dd | 199 | global gdb_prompt inferior_exited_re |
f0fd9238 | 200 | |
1df4399f PA |
201 | with_test_prefix "$cmd from handleri" { |
202 | restart | |
203 | ||
204 | # Get us into the handler. | |
205 | gdb_test "break handler" | |
206 | gdb_test "continue" ".* handler .*" "continue to handler" | |
207 | ||
208 | set program_exited 0 | |
209 | set test "leave handler" | |
210 | gdb_test_multiple "$cmd" "${test}" { | |
211 | -re "Cannot insert breakpoint 0.*${gdb_prompt} $" { | |
212 | # Some platforms use a special read-only page for signal | |
213 | # trampolines. We can't set a breakpoint there, and we | |
214 | # don't gracefully fall back to single-stepping. | |
215 | setup_kfail gdb/8841 "i?86-*-linux*" | |
216 | setup_kfail gdb/8841 "*-*-openbsd*" | |
03346981 | 217 | setup_kfail gdb/8841 "nios2-*-linux*" |
1df4399f PA |
218 | fail "$test (could not set breakpoint)" |
219 | return | |
220 | } | |
221 | -re "Could not insert single-step breakpoint.*$gdb_prompt $" { | |
222 | setup_kfail gdb/8841 "sparc*-*-openbsd*" | |
223 | fail "$test (could not insert single-step breakpoint)" | |
224 | } | |
225 | -re "Breakpoint \[0-9\]*, handler .*${gdb_prompt} $" { | |
226 | fail "$test (hit breakpoint again)" | |
227 | } | |
228 | -re "done = 1;.*${gdb_prompt} $" { | |
229 | send_gdb "$cmd\n" | |
230 | exp_continue -continue_timer | |
231 | } | |
232 | -re "\} .. handler .*${gdb_prompt} $" { | |
233 | send_gdb "$cmd\n" | |
234 | exp_continue -continue_timer | |
235 | } | |
236 | -re "signal handler called.*${gdb_prompt} $" { | |
237 | pass "$test" | |
238 | } | |
239 | -re "main .*${gdb_prompt} $" { | |
240 | fail "$test (in main)" | |
241 | } | |
242 | -re "$inferior_exited_re normally.*${gdb_prompt} $" { | |
243 | fail "$test (program exited)" | |
244 | set program_exited 1 | |
245 | } | |
246 | -re "Make handler return now.*y or n. $" { | |
247 | send_gdb "y\n" | |
248 | exp_continue -continue_timer | |
249 | } | |
42edda50 | 250 | } |
1df4399f PA |
251 | |
252 | set test "leave signal trampoline" | |
253 | gdb_test_multiple "$cmd" "${test}" { | |
254 | -re "while .*${gdb_prompt} $" { | |
255 | pass "$test (in main)" | |
256 | } | |
257 | -re "signal handler called.*${gdb_prompt} $" { | |
258 | send_gdb "$cmd\n" | |
259 | exp_continue -continue_timer | |
260 | } | |
261 | -re "return .*${gdb_prompt} $" { | |
262 | fail "$test (stepped)" | |
263 | } | |
264 | -re "Make .*frame return now.*y or n. $" { | |
265 | send_gdb "y\n" | |
266 | exp_continue -continue_timer | |
267 | } | |
268 | -re "$inferior_exited_re normally.*${gdb_prompt} $" { | |
269 | kfail gdb/8744 "$test (program exited)" | |
270 | set program_exited 1 | |
271 | } | |
272 | -re "The program is not being run.*${gdb_prompt} $" { | |
273 | if { $program_exited } { | |
274 | # Previously kfailed with an exit | |
275 | pass "$test (the program is not being run)" | |
276 | } else { | |
277 | fail "$test (the program is not being run)" | |
278 | } | |
f0fd9238 AC |
279 | } |
280 | } | |
281 | } | |
282 | } | |
283 | ||
abbdbd03 PA |
284 | # Check that we can step our way out of a signal handler, using |
285 | # commands that first step out to the signal trampoline, and then out | |
286 | # to the mainline code. | |
b04e311d | 287 | |
1df4399f PA |
288 | foreach cmd {"stepi" "nexti" "finish" "return"} { |
289 | advancei $cmd | |
290 | } | |
b04e311d AC |
291 | |
292 | # Check that we can step/next our way into / over a signal handler. | |
293 | ||
294 | # There are at least the following cases: breakpoint @pc VS breakpoint | |
295 | # in handler VS step / next / continue. | |
296 | ||
b04e311d AC |
297 | |
298 | # Try stepping when there's a signal pending, and a breakpoint at the | |
299 | # handler. Should step into the signal handler. | |
300 | ||
1df4399f | 301 | proc skip_to_handler { cmd } { |
b04e311d | 302 | global infinite_loop |
1df4399f PA |
303 | |
304 | with_test_prefix "$cmd to handler" { | |
305 | restart | |
306 | # Use the real-time itimer, as otherwize the process never gets | |
307 | # enough time to expire the timer. | |
308 | gdb_test_no_output "set itimer = itimer_real" | |
309 | ||
310 | # Advance to the infinite loop. | |
311 | gdb_test "advance $infinite_loop" ".*" "advance to infinite loop" | |
312 | ||
313 | # Make the signal pending. | |
314 | sleep 1 | |
315 | ||
316 | # Insert the handler breakpoint. | |
11af934b | 317 | gdb_test "break handler" ".*" |
1df4399f PA |
318 | |
319 | # Step into the handler. | |
320 | gdb_test "$cmd" " handler .*" "performing $cmd" | |
b04e311d | 321 | } |
b04e311d AC |
322 | } |
323 | ||
1df4399f PA |
324 | foreach cmd {"step" "next" "continue"} { |
325 | skip_to_handler $cmd | |
326 | } | |
b04e311d | 327 | |
2dedb159 AC |
328 | # Try stepping when there's a signal pending, and a breakpoint at the |
329 | # handler's entry-point. Should step into the signal handler stopping | |
330 | # at the entry-point. | |
331 | ||
332 | # Some systems (e.x., GNU/Linux as of 2004-08-30), when delivering a | |
333 | # signal, resume the process at the first instruction of the signal | |
334 | # handler and not the first instruction of the signal trampoline. The | |
335 | # stack is constructed such that the signal handler still appears to | |
336 | # have been called by the trampoline code. This test checks that it | |
337 | # is possible to stop the inferior, even at that first instruction. | |
338 | ||
1df4399f | 339 | proc skip_to_handler_entry { cmd } { |
2dedb159 | 340 | global infinite_loop |
1df4399f PA |
341 | |
342 | with_test_prefix "$cmd to handler entry" { | |
343 | restart | |
344 | # Use the real-time itimer, as otherwize the process never gets | |
345 | # enough time to expire the timer. | |
346 | gdb_test_no_output "set itimer = itimer_real" | |
347 | ||
348 | # Advance to the infinite loop. | |
349 | gdb_test "advance $infinite_loop" ".*" "advance to infinite loop" | |
350 | ||
351 | # Make the signal pending. | |
352 | sleep 1 | |
353 | ||
354 | # Insert / remove the handler breakpoint. | |
355 | gdb_test "break *handler" ".*" "break handler" | |
356 | gdb_test "$cmd" " handler .*" "performing $cmd" | |
2dedb159 | 357 | } |
2dedb159 AC |
358 | } |
359 | ||
e5f8a7cc PA |
360 | foreach cmd {"stepi" "nexti" "step" "next" "continue"} { |
361 | skip_to_handler_entry $cmd | |
362 | } | |
363 | ||
364 | # Get the address of where a single-step should land. | |
365 | ||
366 | proc get_next_pc {test} { | |
367 | global gdb_prompt | |
368 | global hex | |
369 | ||
370 | set next "" | |
371 | gdb_test_multiple "x/2i \$pc" $test { | |
372 | -re "$hex .*:\[^\r\n\]+\r\n\[ \]+($hex).*\.\r\n$gdb_prompt $" { | |
373 | set next $expect_out(1,string) | |
374 | pass $test | |
375 | } | |
376 | } | |
377 | ||
378 | return $next | |
379 | } | |
380 | ||
381 | # Test that the command skipped over the handler. | |
382 | ||
1df4399f PA |
383 | proc test_skip_handler {cmd} { |
384 | if {$cmd == "stepi" || $cmd == "nexti"} { | |
385 | set next_pc [get_next_pc "get next PC"] | |
386 | gdb_test "$cmd" "dummy = 0.*" "performing $cmd" | |
387 | gdb_test "p /x \$pc" " = $next_pc" "advanced" | |
e5f8a7cc | 388 | } else { |
1df4399f | 389 | gdb_test "$cmd" "done = 0.*" "performing $cmd" |
e5f8a7cc PA |
390 | } |
391 | } | |
2dedb159 | 392 | |
b04e311d AC |
393 | # Try stepping when there's a signal pending but no breakpoints. |
394 | # Should skip the handler advancing to the next line. | |
395 | ||
1df4399f | 396 | proc skip_over_handler { cmd } { |
b04e311d | 397 | global infinite_loop |
1df4399f PA |
398 | global clear_done |
399 | ||
400 | with_test_prefix "$cmd over handler" { | |
401 | restart | |
402 | # Use the real-time itimer, as otherwize the process never gets | |
403 | # enough time to expire the timer. | |
404 | gdb_test_no_output "set itimer = itimer_real" | |
405 | ||
406 | gdb_test "break $clear_done" ".*" "break clear done" | |
407 | ||
408 | # Advance to the infinite loop. | |
409 | gdb_test "advance $infinite_loop" ".*" "advance to infinite loop" | |
b04e311d | 410 | |
1df4399f PA |
411 | # Make the signal pending. |
412 | sleep 1 | |
e5f8a7cc | 413 | |
1df4399f PA |
414 | test_skip_handler $cmd |
415 | } | |
b04e311d AC |
416 | } |
417 | ||
e5f8a7cc PA |
418 | foreach cmd {"stepi" "nexti" "step" "next" "continue"} { |
419 | skip_over_handler $cmd | |
420 | } | |
b04e311d AC |
421 | |
422 | # Try stepping when there's a signal pending, a pre-existing | |
423 | # breakpoint at the current instruction, and a breakpoint in the | |
8f572e5c PA |
424 | # handler. Should advance to the signal handler. DISPLACED indicates |
425 | # whether to try with or without displaced stepping (to exercise the | |
426 | # different techniques of stepping over the breakpoint at the current | |
427 | # instruction). | |
b04e311d | 428 | |
8f572e5c | 429 | proc breakpoint_to_handler { displaced cmd } { |
b04e311d | 430 | global infinite_loop |
1df4399f | 431 | |
8f572e5c | 432 | with_test_prefix "displaced=$displaced: $cmd on breakpoint, to handler" { |
1df4399f | 433 | restart |
8f572e5c PA |
434 | |
435 | gdb_test_no_output "set displaced-stepping $displaced" | |
436 | ||
1df4399f PA |
437 | # Use the real-time itimer, as otherwize the process never gets |
438 | # enough time to expire the timer. | |
439 | gdb_test_no_output "set itimer = itimer_real" | |
440 | ||
441 | gdb_test "break $infinite_loop" ".*" "break infinite loop" | |
11af934b | 442 | gdb_test "break handler" ".*" |
1df4399f PA |
443 | |
444 | # Continue to the infinite loop. | |
445 | gdb_test "continue" "while ..done.*" "continue to infinite loop" | |
446 | ||
447 | # Make the signal pending. | |
448 | sleep 1 | |
449 | ||
450 | gdb_test "$cmd" " handler .*" "performing $cmd" | |
8f572e5c PA |
451 | |
452 | # Make sure we the displaced stepping scratch pad isn't in the | |
453 | # backtrace. | |
454 | gdb_test_sequence "bt" "backtrace" { | |
455 | "\[\r\n\]+.0 \[^\r\n\]* handler " | |
456 | "\[\r\n\]+.1 .signal handler called." | |
457 | "\[\r\n\]+.2 \[^\r\n\]* main " | |
458 | } | |
b04e311d | 459 | } |
b04e311d AC |
460 | } |
461 | ||
8f572e5c PA |
462 | foreach displaced {"off" "on"} { |
463 | foreach cmd {"step" "next" "continue"} { | |
464 | breakpoint_to_handler $displaced $cmd | |
465 | } | |
1df4399f | 466 | } |
b04e311d | 467 | |
2dedb159 AC |
468 | # Try stepping when there's a signal pending, and a breakpoint at the |
469 | # handler's entry instruction and a breakpoint at the current | |
470 | # instruction. Should step into the signal handler and breakpoint at | |
471 | # that entry instruction. | |
472 | ||
473 | # Some systems (e.x., GNU/Linux as of 2004-08-30), when delivering a | |
474 | # signal, resume the process at the first instruction of the signal | |
475 | # handler and not the first instruction of the signal trampoline. The | |
476 | # stack is constructed such that the signal handler still appears to | |
477 | # have been called by the trampoline code. This test checks that it | |
478 | # is possible to stop the inferior, even at that first instruction. | |
479 | ||
8f572e5c PA |
480 | # DISPLACED indicates whether to try with or without displaced |
481 | # stepping (to exercise the different techniques of stepping over the | |
482 | # breakpoint at the current instruction). | |
483 | proc breakpoint_to_handler_entry { displaced cmd } { | |
2dedb159 | 484 | global infinite_loop |
1df4399f | 485 | |
8f572e5c | 486 | with_test_prefix "displaced=$displaced: $cmd on breakpoint, to handler entry" { |
1df4399f | 487 | restart |
8f572e5c PA |
488 | |
489 | gdb_test_no_output "set displaced-stepping $displaced" | |
490 | ||
1df4399f PA |
491 | # Use the real-time itimer, as otherwize the process never gets |
492 | # enough time to expire the timer. | |
493 | gdb_test_no_output "set itimer = itimer_real" | |
494 | ||
495 | gdb_test "break $infinite_loop" ".*" "break infinite loop" | |
496 | gdb_test "break *handler" ".*" "break handler" | |
497 | ||
498 | # Continue to the infinite loop. | |
499 | gdb_test "continue" "while ..done.*" "continue to infinite loop" | |
500 | ||
501 | # Make the signal pending. | |
502 | sleep 1 | |
503 | ||
504 | gdb_test "$cmd" " handler .*" "performing $cmd" | |
8f572e5c PA |
505 | |
506 | # Make sure we the displaced stepping scratch pad isn't in the | |
507 | # backtrace. | |
508 | gdb_test_sequence "bt" "backtrace" { | |
509 | "\[\r\n\]+.0 \[^\r\n\]* handler " | |
510 | "\[\r\n\]+.1 .signal handler called." | |
511 | "\[\r\n\]+.2 \[^\r\n\]* main " | |
512 | } | |
2dedb159 | 513 | } |
2dedb159 AC |
514 | } |
515 | ||
8f572e5c PA |
516 | foreach displaced {"off" "on"} { |
517 | foreach cmd {"step" "next" "continue"} { | |
518 | breakpoint_to_handler_entry $displaced $cmd | |
519 | } | |
1df4399f | 520 | } |
2dedb159 | 521 | |
b04e311d AC |
522 | # Try stepping when there's a signal pending, and a pre-existing |
523 | # breakpoint at the current instruction, and no breakpoint in the | |
8f572e5c PA |
524 | # handler. Should advance to the next line/instruction. DISPLACED |
525 | # indicates whether to try with or without displaced stepping (to | |
526 | # exercise the different techniques of stepping over the breakpoint at | |
527 | # the current instruction). If SW_WATCH is true, set a software | |
528 | # watchpoint, which exercises stepping the breakpoint instruction | |
529 | # while delivering a signal at the same time. If NO_HANDLER, arrange | |
530 | # for the signal's handler be SIG_IGN, thus when the software | |
531 | # watchpoint is also set, testing stepping a breakpoint instruction | |
532 | # and immediately triggering the breakpoint (exercises | |
533 | # adjust_pc_after_break logic). | |
534 | ||
535 | proc breakpoint_over_handler { displaced cmd with_sw_watch no_handler } { | |
b04e311d | 536 | global infinite_loop |
1df4399f PA |
537 | global clear_done |
538 | ||
7f5ef605 PA |
539 | set prefix "$cmd on breakpoint, skip handler" |
540 | if { $with_sw_watch } { | |
541 | append prefix ", with sw-watchpoint" | |
542 | } | |
543 | if { $no_handler } { | |
544 | append prefix ", no handler" | |
545 | } | |
546 | ||
8f572e5c | 547 | with_test_prefix "displaced=$displaced: $prefix" { |
1df4399f | 548 | restart |
8f572e5c PA |
549 | |
550 | gdb_test_no_output "set displaced-stepping $displaced" | |
551 | ||
1df4399f PA |
552 | # Use the real-time itimer, as otherwize the process never gets |
553 | # enough time to expire the timer. | |
554 | gdb_test_no_output "set itimer = itimer_real" | |
555 | ||
7f5ef605 PA |
556 | if {$no_handler} { |
557 | gdb_test "print no_handler = 1" " = 1" \ | |
558 | "set no_handler" | |
559 | } | |
560 | ||
1df4399f | 561 | gdb_test "break $infinite_loop" ".*" "break infinite loop" |
b04e311d | 562 | |
1df4399f | 563 | gdb_test "break $clear_done" ".*" "break clear done" |
b04e311d | 564 | |
1df4399f PA |
565 | # Continue to the infinite loop |
566 | gdb_test "continue" "while ..done.*" "continue to infinite loop" | |
567 | ||
568 | # Make the signal pending | |
569 | sleep 1 | |
570 | ||
7f5ef605 PA |
571 | if { $with_sw_watch } { |
572 | # A watchpoint on a convenience variable is always a | |
573 | # software watchpoint. | |
574 | gdb_test "watch \$convenience" "Watchpoint .*: \\\$convenience" | |
575 | } | |
576 | ||
577 | if {$no_handler} { | |
578 | # With no handler, we need to set the global ourselves | |
579 | # manually. | |
580 | gdb_test "print done = 1" " = 1" "set done" | |
581 | } | |
582 | ||
1df4399f PA |
583 | test_skip_handler $cmd |
584 | } | |
b04e311d AC |
585 | } |
586 | ||
8f572e5c PA |
587 | foreach displaced {"off" "on"} { |
588 | foreach cmd {"stepi" "nexti" "step" "next" "continue"} { | |
589 | foreach with_sw_watch {0 1} { | |
590 | foreach no_handler {0 1} { | |
591 | breakpoint_over_handler $displaced $cmd $with_sw_watch $no_handler | |
592 | } | |
7f5ef605 PA |
593 | } |
594 | } | |
e5f8a7cc | 595 | } |