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