96d8539bee832eefdc1d7d840c224346fa1d4712
[deliverable/binutils-gdb.git] / gdb / testsuite / gdb.base / foll-vfork.exp
1 # Copyright 1997-2019 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 3 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, see <http://www.gnu.org/licenses/>.
15
16 # Various tests of gdb's ability to follow the parent or child of a
17 # Unix vfork system call. A vfork parent is blocked until the child
18 # either execs or exits --- since those events take somewhat different
19 # code paths in GDB, both variants are exercised.
20
21 # Until "set follow-fork-mode" and "catch vfork" are implemented on
22 # other targets...
23 #
24 if {![istarget "*-linux*"]} then {
25 continue
26 }
27
28 standard_testfile
29
30 set compile_options debug
31
32 if {[build_executable $testfile.exp $testfile $srcfile $compile_options] == -1} {
33 untested "failed to compile main testcase"
34 return -1
35 }
36
37 set testfile2 "vforked-prog"
38 set srcfile2 ${testfile2}.c
39
40 if {[build_executable $testfile.exp $testfile2 $srcfile2 $compile_options] == -1} {
41 untested "failed to compile secondary testcase"
42 return -1
43 }
44
45 # A few of these tests require a little more time than the standard
46 # timeout allows.
47 set oldtimeout $timeout
48 set timeout [expr "$timeout + 10"]
49
50 # Start with a fresh GDB, with verbosity enabled, and run to main. On
51 # error, behave as "return", so we don't try to continue testing with
52 # a borked session.
53 proc setup_gdb {} {
54 global testfile srcfile
55
56 clean_restart $testfile
57
58 if ![runto_main] {
59 return -code return
60 }
61
62 set tbreak_line [gdb_get_line_number " VFORK " $srcfile]
63 gdb_test "tbreak ${tbreak_line}"
64 gdb_continue_to_breakpoint ".*"
65 }
66
67 proc check_vfork_catchpoints {} {
68 global gdb_prompt
69 global has_vfork_catchpoints
70
71 setup_gdb
72
73 # Verify that the system supports "catch vfork".
74 gdb_test "catch vfork" "Catchpoint \[0-9\]* \\(vfork\\)" "insert first vfork catchpoint"
75 set has_vfork_catchpoints 0
76 gdb_test_multiple "continue" "continue to first vfork catchpoint" {
77 -re ".*Your system does not support this type\r\nof catchpoint.*$gdb_prompt $" {
78 unsupported "continue to first vfork catchpoint"
79 }
80 -re ".*Catchpoint.*$gdb_prompt $" {
81 set has_vfork_catchpoints 1
82 pass "continue to first vfork catchpoint"
83 }
84 }
85
86 if {$has_vfork_catchpoints == 0} {
87 unsupported "vfork catchpoints"
88 return -code return
89 }
90 }
91
92 proc vfork_parent_follow_through_step {} {
93 with_test_prefix "vfork parent follow, through step" {
94 global gdb_prompt
95
96 setup_gdb
97
98 gdb_test_no_output "set follow-fork parent"
99
100 set test "step"
101 gdb_test_multiple "next" $test {
102 -re "\\\[Detaching after vfork from.*if \\(pid == 0\\).*$gdb_prompt " {
103 pass $test
104 }
105 }
106 # The child has been detached; allow time for any output it might
107 # generate to arrive, so that output doesn't get confused with
108 # any gdb_expected debugger output from a subsequent testpoint.
109 #
110 exec sleep 1
111 }}
112
113 proc vfork_parent_follow_to_bp {} {
114 with_test_prefix "vfork parent follow, to bp" {
115 global gdb_prompt
116 global srcfile
117
118 setup_gdb
119
120 gdb_test_no_output "set follow-fork parent"
121
122 set bp_location [gdb_get_line_number "printf (\"I'm the proud parent of child"]
123 gdb_test "break ${srcfile}:${bp_location}" ".*" "break, vfork to bp"
124
125 set test "continue to bp"
126 gdb_test_multiple "continue" $test {
127 -re ".*\\\[Detaching after vfork from child process.*Breakpoint.*${bp_location}.*$gdb_prompt " {
128 pass $test
129 }
130 }
131 # The child has been detached; allow time for any output it might
132 # generate to arrive, so that output doesn't get confused with
133 # any expected debugger output from a subsequent testpoint.
134 #
135 exec sleep 1
136 }}
137
138 proc vfork_child_follow_to_exit {} {
139 with_test_prefix "vfork child follow, to exit" {
140 global gdb_prompt
141
142 setup_gdb
143
144 gdb_test_no_output "set follow-fork child"
145
146 set test "continue to child exit"
147 gdb_test_multiple "continue" $test {
148 -re "Couldn't get registers.*$gdb_prompt " {
149 # PR gdb/14766
150 fail "$test"
151 }
152 -re "\\\[Attaching after.* vfork to.*\\\[Detaching vfork parent .* after child exit.*$gdb_prompt " {
153 pass $test
154 }
155 }
156 # The parent has been detached; allow time for any output it might
157 # generate to arrive, so that output doesn't get confused with
158 # any gdb_expected debugger output from a subsequent testpoint.
159 #
160 exec sleep 1
161 }}
162
163 proc vfork_and_exec_child_follow_to_main_bp {} {
164 with_test_prefix "vfork and exec child follow, to main bp" {
165 global gdb_prompt
166 global srcfile2
167
168 setup_gdb
169
170 gdb_test_no_output "set follow-fork child"
171
172 set linenum [gdb_get_line_number "printf(\"Hello from vforked-prog" ${srcfile2}]
173
174 set test "continue to bp"
175 gdb_test_multiple "continue" $test {
176 -re "\\\[Attaching after.* vfork to.*\\\[Detaching vfork parent.*xecuting new program.*Breakpoint.*vforked-prog.c:${linenum}.*$gdb_prompt " {
177 pass $test
178 }
179 }
180 # The parent has been detached; allow time for any output it might
181 # generate to arrive, so that output doesn't get confused with
182 # any gdb_expected debugger output from a subsequent testpoint.
183 #
184 exec sleep 1
185 }}
186
187 proc vfork_and_exec_child_follow_through_step {} {
188 with_test_prefix "vfork and exec child follow, through step" {
189 global gdb_prompt
190 global srcfile2
191
192 setup_gdb
193
194 gdb_test_no_output "set follow-fork child"
195
196 set test "step over vfork"
197
198 # The ideal support is to be able to debug the child even
199 # before it execs. Thus, "next" lands on the next line after
200 # the vfork.
201 gdb_test_multiple "next" $test {
202 -re "\\\[Attaching after .* vfork to child.*if \\(pid == 0\\).*$gdb_prompt " {
203 pass "$test"
204 }
205 }
206 # The parent has been detached; allow time for any output it might
207 # generate to arrive, so that output doesn't get confused with
208 # any expected debugger output from a subsequent testpoint.
209 #
210 exec sleep 1
211 }}
212
213 proc continue_to_vfork {} {
214 global gdb_prompt
215
216 # A vfork catchpoint may stop in either "vfork" or "_vfork".
217 set test "continue to vfork"
218 gdb_test_multiple "continue" $test {
219 -re "vfork \\(\\) at .*$gdb_prompt $" {
220 pass $test
221 }
222 -re "0x\[0-9a-fA-F\]*.*(vfork|__kernel_v?syscall).*$gdb_prompt " {
223 pass $test
224 }
225 }
226 }
227
228 proc tcatch_vfork_then_parent_follow {} {
229 with_test_prefix "vfork parent follow, finish after tcatch vfork" {
230 global gdb_prompt
231 global srcfile
232
233 setup_gdb
234
235 gdb_test_no_output "set follow-fork parent"
236
237 gdb_test "tcatch vfork" "Catchpoint .*(vfork).*"
238
239 continue_to_vfork
240
241 set linenum [gdb_get_line_number "pid = vfork ();"]
242 set test "finish"
243 gdb_test_multiple "finish" $test {
244 -re "Run till exit from.*vfork.*0x\[0-9a-fA-F\]* in main .* at .*${srcfile}:${linenum}.*$gdb_prompt " {
245 pass $test
246 }
247 -re "Run till exit from.*__kernel_v?syscall.*0x\[0-9a-fA-F\]* in vfork .*$gdb_prompt " {
248 send_gdb "finish\n"
249 exp_continue
250 }
251 }
252 # The child has been detached; allow time for any output it might
253 # generate to arrive, so that output doesn't get confused with
254 # any expected debugger output from a subsequent testpoint.
255 #
256 exec sleep 1
257 }}
258
259 proc tcatch_vfork_then_child_follow_exec {} {
260 with_test_prefix "vfork child follow, finish after tcatch vfork" {
261 global gdb_prompt
262 global srcfile
263 global srcfile2
264
265 setup_gdb
266
267 gdb_test_no_output "set follow-fork child"
268
269 gdb_test "tcatch vfork" "Catchpoint .*(vfork).*"
270
271 continue_to_vfork
272
273 set linenum1 [gdb_get_line_number "pid = vfork ();"]
274 set linenum2 [gdb_get_line_number "printf(\"Hello from vforked-prog" ${srcfile2}]
275
276 set test "finish"
277 gdb_test_multiple "finish" $test {
278 -re "Run till exit from.*vfork.*${srcfile}:${linenum1}.*$gdb_prompt " {
279 pass $test
280 }
281 -re "Run till exit from.*__kernel_v?syscall.*0x\[0-9a-fA-F\]* in vfork .*$gdb_prompt " {
282 send_gdb "finish\n"
283 exp_continue
284 }
285 -re "Run till exit from.*vfork.*${srcfile2}:${linenum2}.*$gdb_prompt " {
286 pass "$test (followed exec)"
287 }
288 }
289 # The parent has been detached; allow time for any output it might
290 # generate to arrive, so that output doesn't get confused with
291 # any expected debugger output from a subsequent testpoint.
292 #
293 exec sleep 1
294 }}
295
296 proc tcatch_vfork_then_child_follow_exit {} {
297 with_test_prefix "vfork child follow, finish after tcatch vfork" {
298 global gdb_prompt
299 global srcfile
300
301 setup_gdb
302
303 gdb_test_no_output "set follow-fork child"
304
305 gdb_test "tcatch vfork" "Catchpoint .*(vfork).*"
306
307 continue_to_vfork
308
309 set test "finish"
310 gdb_test_multiple "finish" $test {
311 -re "Run till exit from.*vfork.*exited normally.*$gdb_prompt " {
312 setup_kfail "gdb/14762" *-*-*
313 fail $test
314 }
315 -re "Run till exit from.*vfork.*pid = vfork \\(\\).*$gdb_prompt " {
316 pass $test
317 }
318 -re "Run till exit from.*__kernel_v?syscall.*0x\[0-9a-fA-F\]* in vfork .*$gdb_prompt " {
319 send_gdb "finish\n"
320 exp_continue
321 }
322 }
323 # The parent has been detached; allow time for any output it might
324 # generate to arrive, so that output doesn't get confused with
325 # any expected debugger output from a subsequent testpoint.
326 #
327 exec sleep 1
328 }}
329
330 proc vfork_relations_in_info_inferiors { variant } {
331 with_test_prefix "vfork relations in info inferiors" {
332 global gdb_prompt
333
334 setup_gdb
335
336 gdb_test_no_output "set follow-fork child"
337
338 set test "step over vfork"
339 gdb_test_multiple "next" $test {
340 -re "\\\[Attaching after .* vfork to child.*if \\(pid == 0\\).*$gdb_prompt " {
341 pass "$test"
342 }
343 }
344
345 gdb_test "info inferiors" \
346 ".*is vfork parent of inferior 2.*is vfork child of inferior 1" \
347 "info inferiors shows vfork parent/child relation"
348
349 if { $variant == "exec" } {
350 global srcfile2
351
352 set linenum [gdb_get_line_number "printf(\"Hello from vforked-prog" ${srcfile2}]
353 set test "continue to bp"
354 gdb_test_multiple "continue" $test {
355 -re ".*xecuting new program.*Breakpoint.*vforked-prog.c:${linenum}.*$gdb_prompt " {
356 pass $test
357 }
358 }
359 } else {
360 set test "continue to child exit"
361 gdb_test_multiple "continue" $test {
362 -re "exited normally.*$gdb_prompt " {
363 pass $test
364 }
365 }
366 }
367
368 set test "vfork relation no longer appears in info inferiors"
369 gdb_test_multiple "info inferiors" $test {
370 -re "is vfork child of inferior 1.*$gdb_prompt $" {
371 fail $test
372 }
373 -re "is vfork parent of inferior 2.*$gdb_prompt $" {
374 fail $test
375 }
376 -re "$gdb_prompt $" {
377 pass $test
378 }
379 }
380 }}
381
382 proc do_vfork_and_follow_parent_tests {} {
383 global gdb_prompt
384
385 # Try following the parent process by stepping through a call to
386 # vfork. Do this without catchpoints.
387 vfork_parent_follow_through_step
388
389 # Try following the parent process by setting a breakpoint on the
390 # other side of a vfork, and running to that point. Do this
391 # without catchpoints.
392 vfork_parent_follow_to_bp
393
394 # Try catching a vfork, and stepping out to the parent.
395 #
396 tcatch_vfork_then_parent_follow
397 }
398
399 proc do_vfork_and_follow_child_tests_exec {} {
400 # Try following the child process by just continuing through the
401 # vfork, and letting the parent's breakpoint on "main" be auto-
402 # magically reset in the child.
403 #
404 vfork_and_exec_child_follow_to_main_bp
405
406 # Try following the child process by stepping through a call to
407 # vfork. The child also executes an exec. Since the child cannot
408 # be debugged until after it has exec'd, and since there's a bp on
409 # "main" in the parent, and since the bp's for the parent are
410 # recomputed in the exec'd child, the step through a vfork should
411 # land us in the "main" for the exec'd child, too.
412 #
413 vfork_and_exec_child_follow_through_step
414
415 # Try catching a vfork, and stepping out to the child.
416 #
417 tcatch_vfork_then_child_follow_exec
418
419 # Test the ability to follow both child and parent of a vfork. Do
420 # this without catchpoints.
421 # ??rehrauer: NYI. Will add testpoints here when implemented.
422 #
423
424 # Test the ability to have the debugger ask the user at vfork-time
425 # whether to follow the parent, child or both. Do this without
426 # catchpoints.
427 # ??rehrauer: NYI. Will add testpoints here when implemented.
428 #
429
430 # Step over a vfork in the child, do "info inferiors" and check the
431 # parent/child relation is displayed. Run the child over the exec,
432 # and confirm the relation is no longer displayed in "info
433 # inferiors".
434 #
435 vfork_relations_in_info_inferiors "exec"
436 }
437
438 proc do_vfork_and_follow_child_tests_exit {} {
439 # Try following the child process by just continuing through the
440 # vfork, and letting the child exit.
441 #
442 vfork_child_follow_to_exit
443
444 # Try catching a vfork, and stepping out to the child.
445 #
446 tcatch_vfork_then_child_follow_exit
447
448 # Step over a vfork in the child, do "info inferiors" and check the
449 # parent/child relation is displayed. Run the child to completion,
450 # and confirm the relation is no longer displayed in "info
451 # inferiors".
452 #
453 vfork_relations_in_info_inferiors "exit"
454 }
455
456 with_test_prefix "check vfork support" {
457 # Check that vfork catchpoints are supported, as an indicator for
458 # whether vfork-following is supported.
459 check_vfork_catchpoints
460 }
461
462 # Follow parent and follow child vfork tests with a child that execs.
463 with_test_prefix "exec" {
464 # These are tests of gdb's ability to follow the parent of a Unix
465 # vfork system call. The child will subsequently call a variant
466 # of the Unix exec system call.
467 do_vfork_and_follow_parent_tests
468
469 # These are tests of gdb's ability to follow the child of a Unix
470 # vfork system call. The child will subsequently call a variant
471 # of a Unix exec system call.
472 #
473 do_vfork_and_follow_child_tests_exec
474 }
475
476 # Switch to test the case of the child exiting. We can't use
477 # standard_testfile here because we don't want to overwrite the binary
478 # of the previous tests.
479 set testfile "foll-vfork-exit"
480 set srcfile ${testfile}.c
481 set binfile [standard_output_file ${testfile}]
482
483 if {[build_executable $testfile.exp $testfile $srcfile] == -1} {
484 untested "failed to build $testfile"
485 return
486 }
487
488 # Follow parent and follow child vfork tests with a child that exits.
489 with_test_prefix "exit" {
490 # These are tests of gdb's ability to follow the parent of a Unix
491 # vfork system call. The child will subsequently exit.
492 do_vfork_and_follow_parent_tests
493
494 # These are tests of gdb's ability to follow the child of a Unix
495 # vfork system call. The child will subsequently exit.
496 #
497 do_vfork_and_follow_child_tests_exit
498 }
499
500 set timeout $oldtimeout
501 return 0
This page took 0.039654 seconds and 3 git commands to generate.