1# Copyright 2004 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 2 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, write to the Free Software
15# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
16
17
18# The program sigstep.c creates a very simple backtrace containing one
19# signal handler and signal trampoline.  A flag is set and then the
20# handler returns.  This is repeated at infinitum.
21
22# This test runs the program up to the signal handler, and then
23# attempts to step/next out of the handler and back into main.
24
25if [target_info exists gdb,nosignals] {
26    verbose "Skipping sigstep.exp because of nosignals."
27    continue
28}
29
30if $tracelevel then {
31    strace $tracelevel
32}
33
34set prms_id 0
35set bug_id 0
36
37set testfile sigstep
38set srcfile ${testfile}.c
39set binfile ${objdir}/${subdir}/${testfile}
40if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
41    untested "Couldn't compile ${module}.c"
42    return -1
43}
44
45# get things started
46gdb_exit
47gdb_start
48gdb_reinitialize_dir $srcdir/$subdir
49gdb_load ${binfile}
50
51gdb_test "display/i \$pc"
52
53# Advance to main
54if { ![runto_main] } then {
55    gdb_suppress_tests;
56}
57
58# Pass all the alarms straight through (but verbosely)
59# gdb_test "handle SIGALRM print pass nostop"
60# gdb_test "handle SIGVTALRM print pass nostop"
61# gdb_test "handle SIGPROF print pass nostop"
62
63# Run to the signal handler, validate the backtrace.
64gdb_test "break handler"
65gdb_test "continue" ".* handler .*" "continue to stepi handler"
66send_gdb "bt\n"
67gdb_expect_list "backtrace for nexti" ".*$gdb_prompt $" {
68    "\[\r\n\]+.0 \[^\r\n\]* handler "
69    "\[\r\n\]+.1  .signal handler called."
70    "\[\r\n\]+.2 \[^\r\n\]* main .*"
71}
72
73proc advance { i } {
74    global gdb_prompt
75    set prefix "$i from handler"
76
77    # Get us back into the handler
78    gdb_test "continue" ".* handler .*" "$prefix; continue to handler"
79
80    set test "$prefix; leave handler"
81    gdb_test_multiple "$i" "${test}" {
82	-re "done = 1;.*${gdb_prompt} $" {
83	    send_gdb "$i\n"
84	    exp_continue -continue_timer
85	}
86	-re "\} .. handler .*${gdb_prompt} $" {
87	    send_gdb "$i\n"
88	    exp_continue -continue_timer
89	}
90	-re "Program exited normally.*${gdb_prompt} $" {
91	    setup_kfail powerpc-*-*bsd* gdb/1639
92	    fail "$test (program exited)"
93	}
94	-re "(while ..done|done = 0).*${gdb_prompt} $" {
95	    # After stepping out of a function /r signal-handler, GDB will
96	    # advance the inferior until it is at the first instruction of
97	    # a code-line.  While typically things return to the middle of
98	    # the "while..." (and hence GDB advances the inferior to the
99	    # "return..." line) it is also possible for the return to land
100	    # on the first instruction of "while...".  Accept both cases.
101	    pass "$test"
102	}
103    }
104}
105
106proc advancei { i } {
107    global gdb_prompt
108    set prefix "$i from handleri"
109    set program_exited 0
110
111    # Get us back into the handler
112    gdb_test "continue" ".* handler .*" "$prefix; continue to handler"
113
114    set test "$prefix; leave handler"
115    gdb_test_multiple "$i" "${test}" {
116        -re "Cannot insert breakpoint 0.*${gdb_prompt} $" {
117            # Some platforms use a special read-only page for signal
118            # trampolines.  We can't set a breakpoint there, and we
119            # don't gracefully fall back to single-stepping.
120            setup_kfail "i?86-*-linux*" gdb/1736
121            fail "$test (could not set breakpoint)"
122	    return
123        }
124	-re "done = 1;.*${gdb_prompt} $" {
125	    send_gdb "$i\n"
126	    exp_continue -continue_timer
127	}
128	-re "\} .. handler .*${gdb_prompt} $" {
129	    send_gdb "$i\n"
130	    exp_continue -continue_timer
131	}
132	-re "signal handler called.*${gdb_prompt} $" {
133	    pass "$test"
134	}
135	-re "main .*${gdb_prompt} $" {
136	    fail "$test (in main)"
137	}
138	-re "Program exited normally.*${gdb_prompt} $" {
139	    fail "$test (program exited)"
140	    set program_exited 1
141	}
142	-re "Make handler return now.*y or n. $" {
143	    send_gdb "y\n"
144	    exp_continue -continue_timer
145	}
146    }
147
148    set test "$prefix; leave signal trampoline"
149    gdb_test_multiple "$i" "${test}" {
150	-re "while .*${gdb_prompt} $" {
151	    pass "$test (in main)"
152	}
153	-re "signal handler called.*${gdb_prompt} $" {
154	    send_gdb "$i\n"
155	    exp_continue -continue_timer
156	}
157	-re "return .*${gdb_prompt} $" {
158	    fail "$test (stepped)"
159	}
160	-re "Make .*frame return now.*y or n. $" {
161	    send_gdb "y\n"
162	    exp_continue -continue_timer
163	}
164	-re "Program exited normally.*${gdb_prompt} $" {
165	    kfail gdb/1639 "$test (program exited)"
166	    set program_exited 1
167	}
168	-re "The program is not being run.*${gdb_prompt} $" {
169	    if { $program_exited } {
170		# Previously kfailed with an exit
171		pass "$test (the program is not being run)"
172	    } else {
173		fail "$test (the program is not being run)"
174	    }
175	}
176    }
177}
178
179# Check that we can step/next our way out of a signal handler.
180
181advance step
182advancei stepi
183
184advance next
185advancei nexti
186
187advancei finish
188advancei return
189gdb_test "set done = 1" "" "Set done as return will have skipped it"
190
191
192# Check that we can step/next our way into / over a signal handler.
193
194# There are at least the following cases: breakpoint @pc VS breakpoint
195# in handler VS step / next / continue.
196
197# Use the real-time itimer, as otherwize the process never gets enough
198# time to expire the timer.
199
200delete_breakpoints
201set infinite_loop [gdb_get_line_number {while (!done)}]
202gdb_test "set itimer = itimer_real"
203gdb_test "break [gdb_get_line_number {done = 0}]"
204
205# Try stepping when there's a signal pending, and a breakpoint at the
206# handler.  Should step into the signal handler.
207
208proc skip_to_handler { i } {
209    global gdb_prompt
210    global infinite_loop
211    set prefix "$i to handler"
212
213    # Run around to the done
214    # You can add more patterns to this if you need them.
215    set test "$prefix; resync"
216    gdb_test_multiple "continue" "$test" {
217	-re "done = 0.*$gdb_prompt " {
218	    pass "$test"
219	}
220    }
221
222    # Advance to the infinite loop
223    gdb_test "advance $infinite_loop" "" "$prefix; advance to infinite loop"
224
225    # Make the signal pending
226    sleep 1
227
228    # Insert / remove the handler breakpoint.
229    gdb_test "break handler" "" "$prefix; break handler"
230    gdb_test "$i" " handler .*" "$prefix; performing $i"
231    gdb_test "clear handler" "" "$prefix; clear handler"
232}
233
234skip_to_handler step
235skip_to_handler next
236skip_to_handler continue
237
238# Try stepping when there's a signal pending, and a breakpoint at the
239# handler's entry-point.  Should step into the signal handler stopping
240# at the entry-point.
241
242# Some systems (e.x., GNU/Linux as of 2004-08-30), when delivering a
243# signal, resume the process at the first instruction of the signal
244# handler and not the first instruction of the signal trampoline.  The
245# stack is constructed such that the signal handler still appears to
246# have been called by the trampoline code.  This test checks that it
247# is possible to stop the inferior, even at that first instruction.
248
249proc skip_to_handler_entry { i } {
250    global gdb_prompt
251    global infinite_loop
252    set prefix "$i to handler entry"
253
254    # Run around to the done
255    # You can add more patterns to this if you need them.
256    set test "$prefix; resync"
257    gdb_test_multiple "continue" "$test" {
258	-re "done = 0.*$gdb_prompt " {
259	    pass "$test"
260	}
261    }
262
263    # Advance to the infinite loop
264    gdb_test "advance $infinite_loop" "" "$prefix; advance to infinite loop"
265
266    # Make the signal pending
267    sleep 1
268
269    # Insert / remove the handler breakpoint.
270    gdb_test "break *handler" "" "$prefix; break handler"
271    gdb_test "$i" " handler .*" "$prefix; performing $i"
272    gdb_test "clear *handler" "" "$prefix; clear handler"
273}
274
275skip_to_handler_entry step
276skip_to_handler_entry next
277skip_to_handler_entry continue
278
279# Try stepping when there's a signal pending but no breakpoints.
280# Should skip the handler advancing to the next line.
281
282proc skip_over_handler { i } {
283    global gdb_prompt
284    global infinite_loop
285    set prefix "$i over handler"
286
287    # Run around to the done
288    # You can add more patterns to this if you need them.
289    set test "$prefix; resync"
290    gdb_test_multiple "continue" "$test" {
291	-re "done = 0.*$gdb_prompt " {
292	    pass "$test"
293	}
294    }
295
296    # Advance to the infinite loop
297    gdb_test "advance $infinite_loop" "" "$prefix; advance to infinite loop"
298
299    # Make the signal pending
300    sleep 1
301
302    gdb_test "$i" "done = 0.*" "$prefix; performing $i"
303}
304
305skip_over_handler step
306skip_over_handler next
307skip_over_handler continue
308
309# Try stepping when there's a signal pending, a pre-existing
310# breakpoint at the current instruction, and a breakpoint in the
311# handler.  Should advance to the signal handler.
312
313proc breakpoint_to_handler { i } {
314    global gdb_prompt
315    global infinite_loop
316    set prefix "$i on breakpoint, to handler"
317
318    # Run around to the done
319    # You can add more patterns to this if you need them.
320    set test "$prefix; resync"
321    gdb_test_multiple "continue" "$test" {
322	-re "done = 0.*$gdb_prompt " {
323	    pass "$test"
324	}
325    }
326
327    gdb_test "break $infinite_loop" "" "$prefix; break infinite loop"
328    gdb_test "break handler" "" "$prefix; break handler"
329
330    # Continue to the infinite loop
331    gdb_test "continue" "while ..done.*" "$prefix; continue to infinite loop"
332
333    # Make the signal pending
334    sleep 1
335
336    setup_kfail "i*86-*-*" gdb/1738
337    gdb_test "$i" " handler .*" "$prefix; performing $i"
338    gdb_test "clear $infinite_loop" "" "$prefix; clear infinite loop"
339    gdb_test "clear handler" "" "$prefix; clear handler"
340}
341
342breakpoint_to_handler step
343breakpoint_to_handler next
344breakpoint_to_handler continue
345
346# Try stepping when there's a signal pending, and a breakpoint at the
347# handler's entry instruction and a breakpoint at the current
348# instruction.  Should step into the signal handler and breakpoint at
349# that entry instruction.
350
351# Some systems (e.x., GNU/Linux as of 2004-08-30), when delivering a
352# signal, resume the process at the first instruction of the signal
353# handler and not the first instruction of the signal trampoline.  The
354# stack is constructed such that the signal handler still appears to
355# have been called by the trampoline code.  This test checks that it
356# is possible to stop the inferior, even at that first instruction.
357
358proc breakpoint_to_handler_entry { i } {
359    global gdb_prompt
360    global infinite_loop
361    set prefix "$i on breakpoint, to handler entry"
362
363    # Run around to the done
364    # You can add more patterns to this if you need them.
365    set test "$prefix; resync"
366    gdb_test_multiple "continue" "$test" {
367	-re "done = 0.*$gdb_prompt " {
368	    pass "$test"
369	}
370    }
371
372    gdb_test "break $infinite_loop" "" "$prefix; break infinite loop"
373    gdb_test "break *handler" "" "$prefix; break handler"
374
375    # Continue to the infinite loop
376    gdb_test "continue" "while ..done.*" "$prefix; continue to infinite loop"
377
378    # Make the signal pending
379    sleep 1
380
381    setup_kfail "i*86-*-*" gdb/1738
382    gdb_test "$i" " handler .*" "$prefix; performing $i"
383    gdb_test "clear $infinite_loop" "" "$prefix; clear infinite loop"
384    gdb_test "clear *handler" "" "$prefix; clear handler"
385}
386
387breakpoint_to_handler_entry step
388breakpoint_to_handler_entry next
389breakpoint_to_handler_entry continue
390
391# Try stepping when there's a signal pending, and a pre-existing
392# breakpoint at the current instruction, and no breakpoint in the
393# handler.  Should advance to the next line.
394
395proc breakpoint_over_handler { i } {
396    global gdb_prompt
397    global infinite_loop
398    set prefix "$i on breakpoint, skip handler"
399
400    # Run around to the done
401    # You can add more patterns to this if you need them.
402    set test "$prefix; resync"
403    gdb_test_multiple "continue" "$test" {
404	-re "done = 0.*$gdb_prompt " {
405	    pass "$test"
406	}
407    }
408
409    gdb_test "break $infinite_loop" "" "$prefix; break infinite loop"
410
411    # Continue to the infinite loop
412    gdb_test "continue" "while ..done.*" "$prefix; continue to infinite loop"
413
414    # Make the signal pending
415    sleep 1
416
417    gdb_test "$i" "done = 0.*" "$prefix; performing $i"
418    gdb_test "clear $infinite_loop" "" "$prefix; clear infinite loop"
419}
420
421breakpoint_over_handler step
422breakpoint_over_handler next
423breakpoint_over_handler continue
424