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