1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
|
# Copyright 1997, 1998, 1999, 2003, 2004 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
if [target_info exists gdb,nosignals] {
verbose "Skipping signals.exp because of nosignals."
continue
}
if $tracelevel then {
strace $tracelevel
}
set prms_id 0
set bug_id 0
set testfile signals
set srcfile ${testfile}.c
set binfile ${objdir}/${subdir}/${testfile}
if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
}
# Create and source the file that provides information about the compiler
# used to compile the test case.
if [get_compiler_info ${binfile}] {
return -1;
}
if {$hp_cc_compiler} {
set void 0
} else {
set void void
}
proc signal_tests_1 {} {
global gdb_prompt
if [runto_main] then {
gdb_test "next" "signal \\(SIGUSR1.*" \
"next over signal call; SIGALRM handler"
gdb_test "next" "alarm \\(.*" \
"next over signal call; SIGUSR1 handler"
# Set up an alarm, wait for it to be come pending then do a
# next to see what happens.
gdb_test "next" "\\+\\+count; /\\* first \\*/" \
"next over 1st alarm"
sleep 2
gdb_test "next" "alarm .*" \
"next over first count and SIGALRM to 2nd alarm"
# Now do the same thing but with a breakpoint in the SIGALRM
# handler so that we stop there.
gdb_test "break handler" "Breakpoint \[0-9\]+ .*"
gdb_test "next" "\\+\\+count; /\\* second \\*/" \
"next over 2nd alarm"
sleep 2
gdb_test "next" "Breakpoint.*handler.*" \
"next over second count, but jump to handler"
gdb_test "backtrace" \
"#0.*handler.*#1.*signal handler.*#2.* main .*" \
"backtrace for 2nd alarm"
# Let the signal handler return allowing main to advance to
# func1.
gdb_test "break func1" "Breakpoint \[0-9\]+ .*"
gdb_test "break func2" "Breakpoint \[0-9\]+ .*"
gdb_test "continue" "Breakpoint.*func1.*" "continue to func1"
# While still in func1, force a signal, check the backtrace.
gdb_test "signal SIGUSR1" "Breakpoint.*handler.*"
gdb_test "bt" \
"#0 handler .*#1 .signal handler called.*#2 func1 .*\#3 .*main.*" \
"backtrace for SIGUSR1"
# The problem here is that the breakpoint at func1 will be
# inserted, and when the system finishes with the signal
# handler it will try to execute there. For GDB to try to
# remember that it was going to step over a breakpoint when a
# signal happened, distinguish this case from the case where
# func1 is called from the signal handler, etc., seems
# exceedingly difficult. So don't expect this to get fixed
# anytime soon.
setup_xfail "*-*-*"
set test "continue to func2"
gdb_test_multiple "continue" "$test" {
-re "Breakpoint.*func2.*$gdb_prompt $" {
pass "$test"
}
-re "Breakpoint.*func1.*$gdb_prompt $" {
fail "$test"
gdb_test "continue" "Breakpoint.*func2.*" \
"extra continue to func2"
}
}
# In running to func2, the 2rd alarm call will have been set
# up, let it be delivered.
sleep 2
gdb_test "continue" "Breakpoint.*handler.*" \
"continue to handler for 3rd alarm call"
gdb_test "backtrace" \
"#0 handler.*#1.*signal handler called.*#2 func2.*#3.*main.*" \
"backtrace for 3rd alarm"
# If we succeeded a continue will return from the handler to
# func2. GDB now has `forgotten' that it intended to step
# over the breakpoint at func2 and will stop at func2.
setup_xfail "*-*-*"
set test "continue to program exit"
gdb_test_multiple "continue" "$test" {
-re "Program exited with code 010\\." {
pass "$test"
}
-re "Breakpoint.*func2.*$gdb_prompt $" {
fail "$test"
gdb_test "continue" "Program exited with code 010\\." \
"extra continue to program exit"
}
}
}
}
gdb_exit
gdb_start
# This will need to be updated as the exact list of signals changes,
# but I want to test that TARGET_SIGNAL_0, TARGET_SIGNAL_DEFAULT, and
# TARGET_SIGNAL_UNKNOWN are skipped.
proc test_handle_all_print {} {
global timeout
# Increase timeout and expect input buffer for large output from gdb.
# Allow blank or TAB as whitespace characters.
set oldtimeout $timeout
set timeout [expr "$timeout + 360"]
verbose "Timeout is now $timeout seconds" 2
if { ![istarget "*-*-linux*"]
&& ( [istarget "*-*-gnu*"]
|| [istarget "*-*-mach*"] ) } {
gdb_test "handle all print" "Signal\[ \]+Stop\[ \]+Print\[ \]+Pass to program\[ \]+Description\r\nSIGHUP\[ \]+Yes\[ \]+Yes\[ \]+Yes\[ \]+Hangup.*SIG63\[ \]+Yes\[ \]+Yes\[ \]+Yes\[ \]+Real-time event 63.*EXC_BREAKPOINT\[ \]+Yes\[ \]+Yes\[ \]+Yes\[ \]+Breakpoint"
} else {
gdb_test "handle all print" "Signal\[ \]+Stop\[ \]+Print\[ \]+Pass to program\[ \]+Description\r\nSIGHUP\[ \]+Yes\[ \]+Yes\[ \]+Yes\[ \]+Hangup.*SIG63\[ \]+Yes\[ \]+Yes\[ \]+Yes\[ \]+Real-time event 63.*"
}
set timeout $oldtimeout
verbose "Timeout restored to $timeout seconds" 2
}
test_handle_all_print
gdb_exit
gdb_start
gdb_reinitialize_dir $srcdir/$subdir
gdb_load $binfile
signal_tests_1
if [runto_main] then {
# Since count is a static variable outside main, runto_main is no
# guarantee that count will be 0 at this point.
gdb_test "set variable count = 0" ""
# Test an inferior function call that takes a signal that hits a
# breakpoint (with a false condition). When GDB tries to run the
# stack dummy, it will hit the breakpoint at handler. Provided it
# doesn't lose its cool, this is not a problem, it just has to
# note that the breakpoint condition is false and keep going.
# ...setup an always false conditional breakpoint
gdb_test "break handler if 0" "Breakpoint \[0-9\]+ .*"
gdb_test "set \$handler_breakpoint_number = \$bpnum" ""
# ...setup the signal
gdb_test "next" "signal \\(SIGUSR1.*" "next to signal"
gdb_test "next" "alarm \\(.*" "next to alarm #1"
gdb_test "next" "\\+\\+count; /\\* first \\*/" \
"next to ++count #1"
sleep 2
# ...call the function
gdb_test "p func1 ()" "^p func1 \\(\\)\r\n.\[0-9\]* = $void" \
"p func1 () #1"
# ...veryfiy that the cout was updated
gdb_test "p count" "= 2" "p count #1"
# Now run the same test but with a breakpoint that does stop.
# ...set up the breakpoint and signal
gdb_test "condition \$handler_breakpoint_number" "now unconditional\\."
gdb_test "next" "alarm \\(.*" "next to alarm #2"
gdb_test "next" "\\+\\+count; /\\* second \\*/" \
"next to ++count #2"
sleep 2
# ...call the function, which is immediatly interrupted
gdb_test "p func1 ()" \
"Breakpoint \[0-9\]*, handler.*
The program being debugged stopped while in a function called from GDB.*" \
"p func1 () #2"
# ...verify the backtrace
gdb_test "backtrace" \
"#0 handler.*#1 .signal handler called.*#2 func1.*#3 .function called from gdb.*#4.*main.*" \
"backtrace from handler when calling func1"
# ...and continue (silently returning)
gdb_test "continue" "Continuing\\."
# ...and then count should have been incremented
gdb_test "p count" "= 5" "p count #2"
# Verify that "info signals" produces reasonable output.
gdb_test "info signals" "SIGHUP.*SIGINT.*SIGQUIT.*SIGILL.*SIGTRAP.*SIGABRT.*SIGEMT.*SIGFPE.*SIGKILL.*SIGBUS.*SIGSEGV.*SIGSYS.*SIGPIPE.*SIGALRM.*SIGTERM.*SIGURG.*SIGSTOP.*SIGTSTP.*SIGCONT.*SIGCHLD.*SIGTTIN.*SIGTTOU.*SIGIO.*SIGXCPU.*SIGXFSZ.*SIGVTALRM.*SIGPROF.*SIGWINCH.*SIGLOST.*SIGUSR1.*SIGUSR2.*SIGPWR.*SIGPOLL.*SIGWIND.*SIGPHONE.*SIGWAITING.*SIGLWP.*SIGDANGER.*SIGGRANT.*SIGRETRACT.*SIGMSG.*SIGSOUND.*SIGSAK.*SIGPRIO.*SIG33.*SIG34.*SIG35.*SIG36.*SIG37.*SIG38.*SIG39.*SIG40.*SIG41.*SIG42.*SIG43.*SIG44.*SIG45.*SIG46.*SIG47.*SIG48.*SIG49.*SIG50.*SIG51.*SIG52.*SIG53.*SIG54.*SIG55.*SIG56.*SIG57.*SIG58.*SIG59.*SIG60.*SIG61.*SIG62.*SIG63.*Use the \"handle\" command to change these tables.*" \
"info signals"
# Verify that "info signal" correctly handles an argument, be it a
# symbolic signal name, or an integer ID.
gdb_test "info signal SIGTRAP" \
"SIGTRAP\[ \t\]*Yes\[ \t\]*Yes\[ \t\]*No\[ \t\]*Trace/breakpoint trap.*" \
"info signal SIGTRAP"
gdb_test "info signal 5" \
"SIGTRAP\[ \t\]*Yes\[ \t\]*Yes\[ \t\]*No\[ \t\]*Trace/breakpoint trap.*" \
"info signal 5"
# Verify that "handle" with illegal arguments is gracefully, um,
# handled.
gdb_test "handle" \
"Argument required .signal to handle.*" \
"handle without arguments"
gdb_test "handle SIGFOO" \
"Unrecognized or ambiguous flag word: \"SIGFOO\".*" \
"handle with bogus SIG"
gdb_test "handle SIGHUP frump" \
"Unrecognized or ambiguous flag word: \"frump\".*" \
"handle SIG with bogus action"
# Verify that "handle" can take multiple actions per SIG, and that
# in the case of conflicting actions, that the rightmost action
# "wins".
gdb_test "handle SIGHUP print noprint" \
"SIGHUP\[ \t\]*No\[ \t\]*No\[ \t\]*Yes\[ \t\]*Hangup.*" \
"handle SIG with multiple conflicting actions"
# Exercise all the various actions. (We don't care what the
# outcome is, this is just to ensure that they all can be parsed.)
gdb_test "handle SIGHUP print noprint stop nostop ignore noignore pass nopass" \
"Signal.*" \
"handle SIG parses all legal actions"
# Verify that we can "handle" multiple signals at once,
# interspersed with actions.
gdb_test "handle SIG63 print SIGILL" \
"SIGILL\[ \t\]*Yes\[ \t\]*Yes\[ \t\]*Yes\[ \t\]*Illegal instruction.*SIG63\[ \t\]*Yes\[ \t\]*Yes\[ \t\]*Yes\[ \t\]*Real-time event 63.*" \
"handle multiple SIGs"
# Verify that "handle" can take a numeric argument for the signal
# ID, rather than a symbolic name. (This may not be portable;
# works for HP-UX.)
# Also note that this testpoint overrides SIGTRAP, which on HP-UX
# at least, is used to implement single-steps and breakpoints.
# Don't expect to run the inferior after this!
set test "override SIGTRAP"
gdb_test_multiple "handle 5 nopass" "$test" {
-re "SIGTRAP is used by the debugger.*Are you sure you want to change it.*y or n.*" {
gdb_test "y" \
"SIGTRAP\[ \t\]*Yes\[ \t\]*Yes\[ \t\]*No\[ \t\]*Trace/breakpoint trap.*" \
"$test"
}
}
# GDB doesn't seem to allow numeric signal IDs larger than 15. Verify
# that restriction. ??rehrauer: Not sure if this is a feature or a
# bug, actually. Why is the range 1-15?
gdb_test "handle 58" \
"Only signals 1-15 are valid as numeric signals.*Use \"info signals\" for a list of symbolic signals.*" \
"invalid signal number rejected"
# Verify that we can accept a signal ID range (number-number).
# ??rehrauer: This feature isn't documented on the quick-reference
# card.
gdb_test "handle 13-15" \
"SIGPIPE.*SIGALRM.*SIGTERM.*" \
"handle multiple SIGs via integer range"
# Bizarrely enough, GDB also allows you to reverse the range stat,
# stop IDs. E.g., "3-1" and "1-3" mean the same thing. Probably
# this isn't documented, but the code anticipates it, so we'd best
# test it...
gdb_test "handle 15-13" \
"SIGPIPE.*SIGALRM.*SIGTERM.*" \
"handle multiple SIGs via reverse integer range"
# SIGINT is used by the debugger as well. Verify that we can
# change our minds about changing it.
set test "override SIGINT"
gdb_test_multiple "handle SIGINT nopass" "$test" {
-re "SIGINT is used by the debugger.*Are you sure you want to change it.*y or n.*" {
gdb_test_multiple "n" "$test" {
-re "Not confirmed, unchanged.*Signal.*$gdb_prompt $" {
# "Signal ..." should not be in the output.
kfail gdb/1707 "$test"
}
-re "Not confirmed, unchanged.*$gdb_prompt $" {
pass "$test"
}
}
}
}
# Verify that GDB responds gracefully to the "signal" command with
# a missing argument.
gdb_test "signal" \
"Argument required .signal number..*" \
"signal without arguments disallowed"
# Verify that we can successfully send a signal other than 0 to
# the inferior. (This probably causes the inferior to run away.
# Be prepared to rerun to main for further testing.)
gdb_test "signal 5" \
"Continuing with signal SIGTRAP.*" \
"sent signal 5"
}
return 0
|