1#   Copyright 1997, 1999, 2007 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# Please email any bugs, comments, and/or additions to this file to:
17# bug-gdb@prep.ai.mit.edu
18
19if $tracelevel then {
20	strace $tracelevel
21	}
22
23if { ![isnative] } then {
24    continue
25}
26
27set prms_id 0
28set bug_id 0
29
30# NOTE drow/2002-12-06: I don't know what the referenced kernel problem
31# is, but it appears to be fixed in recent HP/UX versions.
32
33##if [istarget "hppa2.0w-hp-hpux*"] {
34##  warning "Don't run gdb.base/foll-vfork.exp until JAGaa43495 kernel problem is fixed."
35##  return 0
36##}
37
38set testfile "foll-vfork"
39set testfile2 "vforked-prog"
40set srcfile ${testfile}.c
41set srcfile2 ${testfile2}.c
42set binfile ${objdir}/${subdir}/${testfile}
43set binfile2 ${objdir}/${subdir}/${testfile2}
44
45if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
46     untested foll-vfork.exp
47     return -1
48}
49
50if  { [gdb_compile "${srcdir}/${subdir}/${srcfile2}" "${binfile2}" executable {debug}] != "" } {
51     untested foll-vfork.exp
52     return -1
53}
54
55
56# Until "set follow-fork-mode" and "catch vfork" are implemented on
57# other targets...
58#
59if ![istarget "hppa*-hp-hpux*"] then {
60    continue
61}
62
63# Test to see if we are on an HP-UX 10.20 and if so,
64# do not run these tests as catching vfork is disabled for
65# 10.20.
66
67if [istarget "hppa*-hp-hpux10.20"] then {
68    return 0
69}
70
71# A few of these tests require a little more time than the standard
72# timeout allows.
73set oldtimeout $timeout
74set timeout [expr "$timeout + 10"]
75
76proc vfork_parent_follow_through_step {} {
77   global gdb_prompt
78
79   send_gdb "set follow parent\n"
80   gdb_expect {
81      -re "$gdb_prompt $" {pass "set follow parent, vfork through step"}
82      timeout         {fail "set follow parent, vfork through step"}
83   }
84   send_gdb "next\n"
85   gdb_expect {
86      -re "Detaching after fork from.*13.*$gdb_prompt "\
87                      {pass "vfork parent follow, through step"}
88      -re "$gdb_prompt $" {fail "vfork parent follow, through step"}
89      timeout         {fail "(timeout) vfork parent follow, through step" }
90   }
91   # The child has been detached; allow time for any output it might
92   # generate to arrive, so that output doesn't get confused with
93   # any gdb_expected debugger output from a subsequent testpoint.
94   #
95   exec sleep 1
96}
97
98proc vfork_parent_follow_to_bp {} {
99   global gdb_prompt
100
101   send_gdb "set follow parent\n"
102   gdb_expect {
103      -re "$gdb_prompt $" {pass "set follow parent, vfork to bp"}
104      timeout         {fail "set follow parent, vfork to bp"}
105   }
106   send_gdb "break 18\n"
107   gdb_expect {
108      -re "$gdb_prompt $" {pass "break, vfork to bp"}
109      timeout         {fail "break, vfork to bp"}
110   }
111   send_gdb "continue\n"
112   gdb_expect {
113      -re ".*Detaching after fork from process.*Breakpoint.*18.*$gdb_prompt "\
114                      {pass "vfork parent follow, to bp"}
115      -re "$gdb_prompt $" {fail "vfork parent follow, to bp"}
116      timeout         {fail "(timeout) vfork parent follow, to bp" }
117   }
118   # The child has been detached; allow time for any output it might
119   # generate to arrive, so that output doesn't get confused with
120   # any expected debugger output from a subsequent testpoint.
121   #
122   exec sleep 1
123}
124
125proc vfork_and_exec_child_follow_to_main_bp {} {
126   global gdb_prompt
127   global binfile
128
129   send_gdb "set follow child\n"
130   gdb_expect {
131      -re "$gdb_prompt $" {pass "set follow child, vfork and exec to main bp"}
132      timeout         {fail "set follow child, vfork and exec to main bp"}
133   }
134   send_gdb "continue\n"
135   gdb_expect {
136      -re "Detaching from program.*Attaching after fork to.*Executing new program.*Breakpoint.*vforked-prog.c:9.*$gdb_prompt "\
137                      {pass "vfork and exec child follow, to main bp"}
138      -re "$gdb_prompt $" {fail "vfork and exec child follow, to main bp"}
139      timeout         {fail "(timeout) vfork and exec child follow, to main bp" }
140   }
141   # The parent has been detached; allow time for any output it might
142   # generate to arrive, so that output doesn't get confused with
143   # any gdb_expected debugger output from a subsequent testpoint.
144   #
145   exec sleep 1
146
147   # Explicitly kill this child, or a subsequent rerun actually runs
148   # the exec'd child, not the original program...
149   send_gdb "kill\n"
150   gdb_expect {
151      -re ".*Kill the program being debugged.*y or n. $" {
152         send_gdb "y\n"
153         send_gdb "file $binfile\n"
154         gdb_expect {
155            -re ".*Load new symbol table from.*y or n. $" {
156               send_gdb "y\n"
157               gdb_expect {
158                  -re "Reading symbols from.*$gdb_prompt $" {}
159                  timeout { fail "loading symbols (timeout)"; return }
160               }
161            }
162            -re ".*gdb_prompt $" {}
163            timeout { fail "loading symbols (timeout)"; return }
164          }
165      }
166      -re ".*$gdb_prompt $" {}
167      timeout { fail "killing inferior (timeout)" ; return }
168    }
169}
170
171proc vfork_and_exec_child_follow_through_step {} {
172   global gdb_prompt
173   global binfile
174
175# This test cannot be performed prior to HP-UX 10.30, because ptrace-based
176# debugging of a vforking program basically doesn't allow the child to do
177# things like hit a breakpoint between a vfork and exec.  This means that
178# saying "set follow child; next" at a vfork() call won't work, because
179# the implementation of "next" sets a "step resume" breakpoint at the
180# return from the vfork(), which the child will hit on its way to exec'ing.
181#
182   if { ![istarget "hppa*-*-hpux11.*"] } {
183      verbose "vfork child-following next test ignored for non-hppa or pre-HP/UX-10.30 targets."
184      return 0
185   }
186
187   send_gdb "set follow child\n"
188   gdb_expect {
189      -re "$gdb_prompt $" {pass "set follow child, vfork and exec through step"}
190      timeout         {fail "set follow child, vfork and exec through step"}
191   }
192   send_gdb "next\n"
193   gdb_expect {
194      -re "Detaching from program.*Attaching after fork to.*Executing new program.*Breakpoint.*vforked-prog.c:9.*$gdb_prompt "\
195                      {pass "vfork and exec child follow, through step"}
196      -re "$gdb_prompt $" {fail "vfork and exec child follow, through step"}
197      timeout         {fail "(timeout) vfork and exec child follow, through step" }
198   }
199   # The parent has been detached; allow time for any output it might
200   # generate to arrive, so that output doesn't get confused with
201   # any expected debugger output from a subsequent testpoint.
202   #
203   exec sleep 1
204
205   # Explicitly kill this child, or a subsequent rerun actually runs
206   # the exec'd child, not the original program...
207   send_gdb "kill\n"
208   gdb_expect {
209      -re ".*Kill the program being debugged.*y or n. $" {
210         send_gdb "y\n"
211         send_gdb "file $binfile\n"
212         gdb_expect {
213            -re ".*Load new symbol table from.*y or n. $" {
214               send_gdb "y\n"
215               gdb_expect {
216                  -re "Reading symbols from.*$gdb_prompt $" {}
217                  timeout { fail "loading symbols (timeout)"; return }
218               }
219            }
220            -re ".*gdb_prompt $" {}
221            timeout { fail "loading symbols (timeout)"; return }
222          }
223      }
224      -re ".*$gdb_prompt $" {}
225      timeout { fail "killing inferior (timeout)" ; return }
226    }
227}
228
229proc tcatch_vfork_then_parent_follow {} {
230   global gdb_prompt
231   global srcfile
232
233   send_gdb "set follow parent\n"
234   gdb_expect {
235      -re "$gdb_prompt $" {pass "set follow parent, tcatch vfork"}
236      timeout         {fail "set follow parent, tcatch vfork"}
237   }
238   send_gdb "tcatch vfork\n"
239   gdb_expect {
240      -re "Catchpoint .*(vfork).*$gdb_prompt $"\
241                      {pass "vfork parent follow, set tcatch vfork"}
242      -re "$gdb_prompt $" {fail "vfork parent follow, set tcatch vfork"}
243      timeout         {fail "(timeout) vfork parent follow, set tcatch vfork"}
244   }
245   send_gdb "continue\n"
246# HP-UX 10.20 seems to stop you in "vfork", while more recent HP-UXs
247# stop you in "_vfork".
248   gdb_expect {
249      -re "0x\[0-9a-fA-F\]*.*vfork.*$gdb_prompt "\
250                      {pass "vfork parent follow, tcatch vfork"}
251      -re "0x\[0-9a-fA-F\]*.*_vfork.*$gdb_prompt "\
252                      {pass "vfork parent follow, tcatch vfork"}
253      -re "$gdb_prompt $" {fail "vfork parent follow, tcatch vfork"}
254      timeout         {fail "(timeout) vfork parent follow, tcatch vfork"}
255   }
256   send_gdb "finish\n"
257   gdb_expect {
258      -re "Run till exit from.*vfork.*0x\[0-9a-fA-F\]* in main .* at .*${srcfile}:12.*$gdb_prompt "\
259                      {pass "vfork parent follow, finish after tcatch vfork"}
260      -re "$gdb_prompt $" {fail "vfork parent follow, finish after tcatch vfork"}
261      timeout         {fail "(timeout) vfork parent follow, finish after tcatch vfork" }
262   }
263   # The child has been detached; allow time for any output it might
264   # generate to arrive, so that output doesn't get confused with
265   # any expected debugger output from a subsequent testpoint.
266   #
267   exec sleep 1
268}
269
270proc tcatch_vfork_then_child_follow {} {
271   global gdb_prompt
272   global srcfile2
273
274   send_gdb "set follow child\n"
275   gdb_expect {
276      -re "$gdb_prompt $" {pass "set follow child, tcatch vfork"}
277      timeout         {fail "set follow child, tcatch vfork"}
278   }
279   send_gdb "tcatch vfork\n"
280   gdb_expect {
281      -re "Catchpoint .*(vfork).*$gdb_prompt $"\
282                      {pass "vfork child follow, set tcatch vfork"}
283      -re "$gdb_prompt $" {fail "vfork child follow, set tcatch vfork"}
284      timeout         {fail "(timeout) vfork child follow, set tcatch vfork"}
285   }
286   send_gdb "continue\n"
287# HP-UX 10.20 seems to stop you in "vfork", while more recent HP-UXs
288# stop you in "_vfork".
289   gdb_expect {
290      -re "0x\[0-9a-fA-F\]*.*vfork.*$gdb_prompt "\
291                      {pass "vfork child follow, tcatch vfork"}
292      -re "0x\[0-9a-fA-F\]*.*_vfork.*$gdb_prompt "\
293                      {pass "vfork child follow, tcatch vfork"}
294      -re "$gdb_prompt $" {fail "vfork child follow, tcatch vfork"}
295      timeout         {fail "(timeout) vfork child follow, tcatch vfork"}
296   }
297   send_gdb "finish\n"
298   gdb_expect {
299      -re "Run till exit from.*vfork.*${srcfile2}:9.*$gdb_prompt "\
300                      {pass "vfork child follow, finish after tcatch vfork"}
301      -re "$gdb_prompt $" {fail "vfork child follow, finish after tcatch vfork"}
302      timeout         {fail "(timeout) vfork child follow, finish after tcatch vfork" }
303   }
304   # The parent has been detached; allow time for any output it might
305   # generate to arrive, so that output doesn't get confused with
306   # any expected debugger output from a subsequent testpoint.
307   #
308   exec sleep 1
309}
310
311proc do_vfork_and_exec_tests {} {
312   global gdb_prompt
313
314   # Try following the parent process by stepping through a call to
315   # vfork.  Do this without catchpoints.
316   if [runto_main] then { vfork_parent_follow_through_step }
317
318   # Try following the parent process by setting a breakpoint on the
319   # other side of a vfork, and running to that point.  Do this
320   # without catchpoints.
321   if [runto_main] then { vfork_parent_follow_to_bp }
322
323   # Try following the child process by just continuing through the
324   # vfork, and letting the parent's breakpoint on "main" be auto-
325   # magically reset in the child.
326   #
327   if [runto_main] then { vfork_and_exec_child_follow_to_main_bp }
328
329   # Try following the child process by stepping through a call to
330   # vfork.  The child also executes an exec.  Since the child cannot
331   # be debugged until after it has exec'd, and since there's a bp on
332   # "main" in the parent, and since the bp's for the parent are
333   # recomputed in the exec'd child, the step through a vfork should
334   # land us in the "main" for the exec'd child, too.
335   #
336   if [runto_main] then { vfork_and_exec_child_follow_through_step }
337
338   # Try catching a vfork, and stepping out to the parent.
339   #
340   if [runto_main] then { tcatch_vfork_then_parent_follow }
341
342   # Try catching a vfork, and stepping out to the child.
343   #
344   if [runto_main] then { tcatch_vfork_then_child_follow }
345
346   # Test the ability to follow both child and parent of a vfork.  Do
347   # this without catchpoints.
348   # ??rehrauer: NYI.  Will add testpoints here when implemented.
349   #
350
351   # Test the ability to have the debugger ask the user at vfork-time
352   # whether to follow the parent, child or both.  Do this without
353   # catchpoints.
354   # ??rehrauer: NYI.  Will add testpoints here when implemented.
355   #
356}
357
358# Start with a fresh gdb
359
360gdb_exit
361gdb_start
362gdb_reinitialize_dir $srcdir/$subdir
363gdb_load ${binfile}
364
365
366# This is a test of gdb's ability to follow the parent or child
367# of a Unix vfork() system call.  (The child will subsequently
368# call a variant of a Unix exec() system call.)
369#
370do_vfork_and_exec_tests
371
372set timeout $oldtimeout
373return 0
374