Commit | Line | Data |
---|---|---|
c906108c SS |
1 | # Copyright (C) 1997 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 | # Please email any bugs, comments, and/or additions to this file to: | |
18 | # bug-gdb@prep.ai.mit.edu | |
19 | ||
20 | if $tracelevel then { | |
21 | strace $tracelevel | |
22 | } | |
23 | ||
24 | set prms_id 0 | |
25 | set bug_id 0 | |
26 | ||
7a292a7a | 27 | if { [skip_hp_tests] } then { continue } |
c906108c SS |
28 | |
29 | if {![istarget "hppa*-*-hpux10.30"] && ![istarget "hppa*-*-hpux11.*"]} { | |
30 | #setup_xfail "*-*.*" | |
31 | return 0 | |
32 | } | |
33 | ||
34 | set testfile "foll-exec" | |
35 | set testfile2 "execd-program" | |
36 | set srcfile ${testfile}.c | |
37 | set srcfile2 ${testfile2}.c | |
38 | set binfile ${objdir}/${subdir}/${testfile} | |
39 | set binfile2 ${objdir}/${subdir}/${testfile2} | |
40 | ||
41 | # build the first test case | |
42 | #if { [compile "-g -DNO_PROTOTYPES ${srcdir}/${subdir}/${srcfile2} -o ${binfile2} "] != "" } { | |
43 | # perror "Couldn't compile ${srcfile2}" | |
44 | # return -1 | |
45 | #} | |
46 | if { [gdb_compile "${srcdir}/${subdir}/${srcfile2}" "${binfile2}" executable {debug}] != "" } { | |
47 | gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail." | |
48 | } | |
49 | ||
50 | #if { [compile "-g ${srcdir}/${subdir}/${srcfile} -o ${binfile} "] != "" } { | |
51 | # execute_anywhere "rm -f ${objdir}/${subdir}/${testfile}.tmp" | |
52 | # built the second test case since we can't use prototypes | |
53 | # warning "Prototypes not supported, rebuilding with -DNO_PROTOTYPES" | |
54 | # execute_anywhere "echo set prototypes 0 > ${objdir}/${subdir}/${testfile}.tmp" | |
55 | # if { [compile "-g -DNO_PROTOTYPES ${srcdir}/${subdir}/${srcfile} -o ${binfile} "] != "" } { | |
56 | # perror "Couldn't compile ${testfile}.c" | |
57 | # return -1 | |
58 | # } | |
59 | #} | |
60 | ||
61 | if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } { | |
62 | gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail." | |
63 | } | |
64 | ||
65 | ||
66 | # Until "catch exec" is implemented on other targets... | |
67 | # | |
68 | if ![istarget "hppa*-hp-hpux*"] then { | |
69 | setup_xfail "*-*-*" | |
70 | } | |
71 | ||
72 | proc zap_session {} { | |
73 | global gdb_prompt | |
74 | global binfile | |
75 | ||
76 | send_gdb "kill\n" | |
77 | gdb_expect { | |
78 | -re ".*Kill the program being debugged.*y or n. $" { | |
79 | send_gdb "y\n" | |
80 | send_gdb "file $binfile\n" | |
81 | gdb_expect { | |
82 | -re ".*Load new symbol table from.*y or n. $" { | |
83 | send_gdb "y\n" | |
84 | gdb_expect { | |
85 | -re "Reading symbols from.*$gdb_prompt $" {} | |
86 | timeout { fail "loading symbols (timeout)"; return } | |
87 | } | |
88 | } | |
89 | -re ".*gdb_prompt $" {} | |
90 | timeout { fail "loading symbols (timeout)"; return } | |
91 | } | |
92 | } | |
93 | -re ".*$gdb_prompt $" {} | |
94 | timeout { fail "killing inferior (timeout)" ; return } | |
95 | } | |
96 | } | |
97 | ||
98 | proc do_exec_tests {} { | |
99 | global gdb_prompt | |
100 | global binfile | |
101 | global srcfile | |
102 | global srcfile2 | |
103 | global testfile | |
104 | global testfile2 | |
105 | ||
106 | # Start the program running, and stop at main. | |
107 | # | |
108 | if ![runto_main] then { | |
109 | perror "Couldn't run ${testfile}" | |
110 | return | |
111 | } | |
112 | ||
113 | # Verify that we can see various global and local variables | |
114 | # in this program, and that they have expected values. Some | |
115 | # of these variables are also declared in the program we'll | |
116 | # exec in a moment. | |
117 | # | |
118 | send_gdb "next 3\n" | |
119 | gdb_expect { | |
120 | -re "12.*execlp.*$gdb_prompt $"\ | |
121 | {pass "step to exec call"} | |
122 | -re "$gdb_prompt $" {fail "step to exec call"} | |
123 | timeout {fail "(timeout) step to exec call"} | |
124 | } | |
125 | send_gdb "print global_i\n" | |
126 | gdb_expect { | |
127 | -re ".* = 100.*$gdb_prompt $"\ | |
128 | {pass "print follow-exec/global_i"} | |
129 | -re "$gdb_prompt $" {fail "print follow-exec/global_i"} | |
130 | timeout {fail "(timeout) print follow-exec/global_i"} | |
131 | } | |
132 | send_gdb "print local_j\n" | |
133 | gdb_expect { | |
134 | -re ".* = 101.*$gdb_prompt $"\ | |
135 | {pass "print follow-exec/local_j"} | |
136 | -re "$gdb_prompt $" {fail "print follow-exec/local_j"} | |
137 | timeout {fail "(timeout) print follow-exec/local_j"} | |
138 | } | |
139 | send_gdb "print local_k\n" | |
140 | gdb_expect { | |
141 | -re ".* = 102.*$gdb_prompt $"\ | |
142 | {pass "print follow-exec/local_k"} | |
143 | -re "$gdb_prompt $" {fail "print follow-exec/local_k"} | |
144 | timeout {fail "(timeout) print follow-exec/local_k"} | |
145 | } | |
146 | ||
147 | # Try stepping through an execlp call, without catching it. | |
148 | # We should stop in execd-program, at its first statement. | |
149 | # | |
150 | send_gdb "next\n" | |
151 | gdb_expect { | |
152 | -re "Executing new program: .*${testfile2}.*${srcfile2}:17.*int local_j = argc;.*$gdb_prompt $"\ | |
153 | {pass "step through execlp call"} | |
154 | -re "$gdb_prompt $" {fail "step through execlp call"} | |
155 | timeout {fail "(timeout) step through execlp call"} | |
156 | } | |
157 | ||
158 | # Verify that we can see the variables defined in the newly-exec'd | |
159 | # program, and CANNOT see those defined in the exec'ing program. | |
160 | # | |
161 | send_gdb "next\n" | |
162 | gdb_expect { | |
163 | -re "20.*printf.*$gdb_prompt $"\ | |
164 | {pass "step after execlp call"} | |
165 | -re "$gdb_prompt $" {fail "step after execlp call"} | |
166 | timeout {fail "(timeout) step after execlp call"} | |
167 | } | |
168 | send_gdb "print global_i\n" | |
169 | gdb_expect { | |
170 | -re ".* = 0.*$gdb_prompt $"\ | |
171 | {pass "print execd-program/global_i (after execlp)"} | |
172 | -re "$gdb_prompt $" {fail "print execd-program/global_i (after execlp)"} | |
173 | timeout {fail "(timeout) print execd-program/global_i (after execlp)"} | |
174 | } | |
175 | send_gdb "print local_j\n" | |
176 | gdb_expect { | |
177 | -re ".* = 2.*$gdb_prompt $"\ | |
178 | {pass "print execd-program/local_j (after execlp)"} | |
179 | -re "$gdb_prompt $" {fail "print execd-program/local_j (after execlp)"} | |
180 | timeout {fail "(timeout) print execd-program/local_j (after execlp)"} | |
181 | } | |
182 | send_gdb "print local_k\n" | |
183 | gdb_expect { | |
184 | -re "No symbol \"local_k\" in current context.*$gdb_prompt $"\ | |
185 | {pass "print follow-exec/local_k (after execlp)"} | |
186 | -re "$gdb_prompt $" {fail "print follow-exec/local_k (after execlp)"} | |
187 | timeout {fail "(timeout) print follow-exec/local_k (after execlp)"} | |
188 | } | |
189 | ||
190 | # Explicitly kill this program, or a subsequent rerun actually runs | |
191 | # the exec'd program, not the original program... | |
192 | zap_session | |
193 | ||
194 | # Start the program running, and stop at main. | |
195 | # | |
196 | if ![runto_main] then { | |
197 | perror "Couldn't run ${testfile} (2nd try)" | |
198 | return | |
199 | } | |
200 | ||
201 | # Verify that we can catch an exec event, and then continue | |
202 | # to follow through the exec. (Since there's a breakpoint on | |
203 | # "main", it'll also be transferred to the exec'd program, | |
204 | # and we expect to stop there.) | |
205 | # | |
206 | send_gdb "catch exec\n" | |
207 | gdb_expect { | |
208 | -re "Catchpoint .*(exec).*$gdb_prompt $"\ | |
209 | {pass "set catch exec"} | |
210 | -re "$gdb_prompt $" {fail "set catch exec"} | |
211 | timeout {fail "(timeout) set catch exec"} | |
212 | } | |
213 | ||
214 | # Verify that the catchpoint is mentioned in an "info breakpoints", | |
215 | # and further that the catchpoint mentions no program name. | |
216 | # | |
217 | send_gdb "info breakpoints\n" | |
218 | gdb_expect { | |
219 | -re ".*catch exec.*keep y.*$gdb_prompt $"\ | |
220 | {pass "info shows catchpoint without exec pathname"} | |
221 | -re ".*catch exec.*program \"\".*$gdb_prompt $"\ | |
222 | {fail "info shows catchpoint without exec pathname"} | |
223 | -re "$gdb_prompt $" {fail "info shows catchpoint without exec pathname"} | |
224 | timeout {fail "(timeout) info shows catchpoint without exec pathname"} | |
225 | } | |
226 | ||
227 | send_gdb "continue\n" | |
228 | gdb_expect { | |
229 | -re ".*Executing new program:.*${testfile2}.*Catchpoint .*(exec\'d .*${testfile2}).*in .START..*$gdb_prompt $"\ | |
230 | {pass "hit catch exec"} | |
231 | -re "$gdb_prompt $" {fail "hit catch exec"} | |
232 | timeout {fail "(timeout) hit catch exec"} | |
233 | } | |
234 | ||
235 | # Verify that the catchpoint is mentioned in an "info breakpoints", | |
236 | # and further that the catchpoint managed to capture the exec'd | |
237 | # program's name. | |
238 | # | |
239 | send_gdb "info breakpoints\n" | |
240 | gdb_expect { | |
241 | -re ".*catch exec .*program \".*${testfile2}\".*$gdb_prompt $"\ | |
242 | {pass "info shows catchpoint exec pathname"} | |
243 | -re "$gdb_prompt $" {fail "info shows catchpoint exec pathname"} | |
244 | timeout {fail "(timeout) info shows catchpoint exec pathname"} | |
245 | } | |
246 | ||
247 | # Verify that we can continue from the catchpoint, and land in the | |
248 | # main of the newly-exec'd program. | |
249 | # | |
250 | send_gdb "continue\n" | |
251 | gdb_expect { | |
252 | -re ".*${srcfile2}:17.*$gdb_prompt $"\ | |
253 | {pass "continue after hit catch exec"} | |
254 | -re "$gdb_prompt $" {fail "continue after hit catch exec"} | |
255 | timeout {fail "(timeout) continue after hit catch exec"} | |
256 | } | |
257 | ||
258 | # Explicitly kill this program, or a subsequent rerun actually runs | |
259 | # the exec'd program, not the original program... | |
260 | zap_session | |
261 | ||
262 | # Start the program running, and stop at main. | |
263 | # | |
264 | if ![runto_main] then { | |
265 | perror "Couldn't run ${testfile} (3rd try)" | |
266 | return | |
267 | } | |
268 | ||
269 | # Verify that we can follow through follow an execl() | |
270 | # call. (We must jump around earlier exec* calls.) | |
271 | # | |
272 | send_gdb "tbreak 19\n" | |
273 | gdb_expect { | |
274 | -re "Breakpoint .*file .*${srcfile}, line 19.*$gdb_prompt $"\ | |
275 | {pass "prepare to jump to execl call"} | |
276 | -re "$gdb_prompt $" {fail "prepare to jump to execl call"} | |
277 | timeout {fail "(timeout) prepare to jump to execl call"} | |
278 | } | |
279 | send_gdb "jump 19\n" | |
280 | gdb_expect { | |
281 | -re "main.* at .*${srcfile}:19.*$gdb_prompt $"\ | |
282 | {pass "jump to execl call"} | |
283 | -re "$gdb_prompt $" {fail "jump to execl call"} | |
284 | timeout {fail "(timeout) jump to execl call"} | |
285 | } | |
286 | # Note that stepping through an exec call causes the step-count | |
287 | # to be reset to zero. I.e.: you may specify "next 2" at the | |
288 | # call, but you'll actually stop at the first breakpoint set in | |
289 | # the newly-exec'd program, not after the remaining step-count | |
290 | # reaches zero. | |
291 | # | |
292 | send_gdb "next 2\n" | |
293 | gdb_expect { | |
294 | -re "Executing new program: .*${testfile2}.*${srcfile2}:17.*int local_j = argc;.*$gdb_prompt $"\ | |
295 | {pass "step through execl call"} | |
296 | -re "$gdb_prompt $" {fail "step through execl call"} | |
297 | timeout {fail "(timeout) step through execl call"} | |
298 | } | |
299 | send_gdb "next\n" | |
300 | gdb_expect { | |
301 | -re "20.*printf.*$gdb_prompt $"\ | |
302 | {pass "step after execl call"} | |
303 | -re "$gdb_prompt $" {fail "step after execl call"} | |
304 | timeout {fail "(timeout) step after execl call"} | |
305 | } | |
306 | ||
307 | # Verify that we can print a local variable (which happens to be | |
308 | # assigned the value of main's argc). | |
309 | # | |
310 | send_gdb "print local_j\n" | |
311 | gdb_expect { | |
312 | -re ".* = 3.*$gdb_prompt $"\ | |
313 | {pass "print execd-program/local_j (after execl)"} | |
314 | -re "$gdb_prompt $" {fail "print execd-program/local_j (after execl)"} | |
315 | timeout {fail "(timeout) print execd-program/local_j (after execl)"} | |
316 | } | |
317 | ||
318 | # Explicitly kill this program, or a subsequent rerun actually runs | |
319 | # the exec'd program, not the original program... | |
320 | zap_session | |
321 | ||
322 | # Start the program running, and stop at main. | |
323 | # | |
324 | if ![runto_main] then { | |
325 | perror "Couldn't run ${testfile} (4th try)" | |
326 | return | |
327 | } | |
328 | ||
329 | # Verify that we can follow through follow an execv() | |
330 | # call. (We must jump around earlier exec* calls.) | |
331 | # | |
332 | send_gdb "tbreak 33\n" | |
333 | gdb_expect { | |
334 | -re "Breakpoint .*file .*${srcfile}, line 33.*$gdb_prompt $"\ | |
335 | {pass "prepare to jump to execv call"} | |
336 | -re "$gdb_prompt $" {fail "prepare to jump to execv call"} | |
337 | timeout {fail "(timeout) prepare to jump to execv call"} | |
338 | } | |
339 | send_gdb "jump 33\n" | |
340 | gdb_expect { | |
341 | -re "main.* at .*${srcfile}:33.*$gdb_prompt $"\ | |
342 | {pass "jump to execv call"} | |
343 | -re "$gdb_prompt $" {fail "jump to execv call"} | |
344 | timeout {fail "(timeout) jump to execv call"} | |
345 | } | |
346 | send_gdb "next\n" | |
347 | gdb_expect { | |
348 | -re "Executing new program: .*${testfile2}.*${srcfile2}:17.*int local_j = argc;.*$gdb_prompt $"\ | |
349 | {pass "step through execv call"} | |
350 | -re "$gdb_prompt $" {fail "step through execv call"} | |
351 | timeout {fail "(timeout) step through execv call"} | |
352 | } | |
353 | send_gdb "next\n" | |
354 | gdb_expect { | |
355 | -re "20.*printf.*$gdb_prompt $"\ | |
356 | {pass "step after execv call"} | |
357 | -re "$gdb_prompt $" {fail "step after execv call"} | |
358 | timeout {fail "(timeout) step after execv call"} | |
359 | } | |
360 | ||
361 | # Verify that we can print a local variable (which happens to be | |
362 | # assigned the value of main's argc). | |
363 | # | |
364 | send_gdb "print local_j\n" | |
365 | gdb_expect { | |
366 | -re ".* = 2.*$gdb_prompt $"\ | |
367 | {pass "print execd-program/local_j (after execv)"} | |
368 | -re "$gdb_prompt $" {fail "print execd-program/local_j (after execv)"} | |
369 | timeout {fail "(timeout) print execd-program/local_j (after execv)"} | |
370 | } | |
371 | ||
372 | # Explicitly kill this program, or a subsequent rerun actually runs | |
373 | # the exec'd program, not the original program... | |
374 | zap_session | |
375 | ||
376 | # Start the program running, and stop at main. | |
377 | # | |
378 | if ![runto_main] then { | |
379 | perror "Couldn't run ${testfile} (4th try)" | |
380 | return | |
381 | } | |
382 | ||
383 | # Verify that we can just continue and thereby follow through an | |
384 | # exec call. (Since the breakpoint on "main" is reset, we should | |
385 | # just stop in main of the newly-exec'd program.) | |
386 | # | |
387 | send_gdb "continue\n" | |
388 | gdb_expect { | |
389 | -re "Executing new program: .*${testfile2}.*${srcfile2}:17.*int local_j = argc;.*$gdb_prompt $"\ | |
390 | {pass "continue through exec"} | |
391 | -re "$gdb_prompt $" {fail "continue through exec"} | |
392 | timeout {fail "(timeout) continue through exec"} | |
393 | } | |
394 | } | |
395 | ||
396 | # Start with a fresh gdb | |
397 | ||
398 | gdb_exit | |
399 | gdb_start | |
400 | gdb_reinitialize_dir $srcdir/$subdir | |
401 | gdb_load ${binfile} | |
402 | ||
403 | ||
404 | # This is a test of gdb's ability to follow a process through a | |
405 | # Unix exec() system call. | |
406 | # | |
407 | do_exec_tests | |
408 | ||
409 | return 0 |