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