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