aboutsummaryrefslogtreecommitdiff
path: root/gdb
diff options
context:
space:
mode:
authorPedro Alves <palves@redhat.com>2012-11-02 18:10:29 +0000
committerPedro Alves <palves@redhat.com>2012-11-02 18:10:29 +0000
commit71ce889da907b11ec88efa3ddc93ee1f0371f8e9 (patch)
tree99df49bba46623161516f369601149d15d26e3f4 /gdb
parent1e35b1a94e55f79e3ae629dd2237224f3e230867 (diff)
downloadgdb-71ce889da907b11ec88efa3ddc93ee1f0371f8e9.zip
gdb-71ce889da907b11ec88efa3ddc93ee1f0371f8e9.tar.gz
gdb-71ce889da907b11ec88efa3ddc93ee1f0371f8e9.tar.bz2
2012-11-02 Pedro Alves <palves@redhat.com>
* gdb.base/foll-vfork-exit.c: New file. * gdb.base/foll-vfork.exp (top level): New file-describing comment. (vfork_child_follow_to_exit): New procedure. (tcatch_vfork_then_child_follow): Rename as ... (tcatch_vfork_then_child_follow_exec): ... this. (tcatch_vfork_then_child_follow_exit): New procedure. (do_vfork_and_follow_parent_tests): New procedure, factored out from do_vfork_and_exec_tests. (do_vfork_and_follow_child_tests_exec): Ditto. (do_vfork_and_exec_tests): Delete. (do_vfork_and_follow_child_tests_exit): New procedure. (top level): Run tests with both the program that has the vfork child execing, and the program has the vfork child exiting.
Diffstat (limited to 'gdb')
-rw-r--r--gdb/testsuite/ChangeLog17
-rw-r--r--gdb/testsuite/gdb.base/foll-vfork-exit.c38
-rw-r--r--gdb/testsuite/gdb.base/foll-vfork.exp155
3 files changed, 195 insertions, 15 deletions
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index ea7f891..e7e42d8 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,5 +1,22 @@
2012-11-02 Pedro Alves <palves@redhat.com>
+ * gdb.base/foll-vfork-exit.c: New file.
+ * gdb.base/foll-vfork.exp (top level): New file-describing
+ comment.
+ (vfork_child_follow_to_exit): New procedure.
+ (tcatch_vfork_then_child_follow): Rename as ...
+ (tcatch_vfork_then_child_follow_exec): ... this.
+ (tcatch_vfork_then_child_follow_exit): New procedure.
+ (do_vfork_and_follow_parent_tests): New procedure, factored out
+ from do_vfork_and_exec_tests.
+ (do_vfork_and_follow_child_tests_exec): Ditto.
+ (do_vfork_and_exec_tests): Delete.
+ (do_vfork_and_follow_child_tests_exit): New procedure.
+ (top level): Run tests with both the program that has the vfork
+ child execing, and the program has the vfork child exiting.
+
+2012-11-02 Pedro Alves <palves@redhat.com>
+
* gdb.base/foll-vfork.exp (setup_gdb): New procedure.
(check_vfork_catchpoints, vfork_parent_follow_through_step)
(vfork_parent_follow_to_bp): Call it.
diff --git a/gdb/testsuite/gdb.base/foll-vfork-exit.c b/gdb/testsuite/gdb.base/foll-vfork-exit.c
new file mode 100644
index 0000000..6aa8a5c
--- /dev/null
+++ b/gdb/testsuite/gdb.base/foll-vfork-exit.c
@@ -0,0 +1,38 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 1997, 1999, 2007-2012 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include <stdio.h>
+#include <unistd.h>
+
+int
+main ()
+{
+ int pid;
+
+ pid = vfork ();
+ if (pid == 0)
+ {
+ printf ("I'm the child!\n");
+ _exit (0);
+ }
+ else
+ {
+ printf ("I'm the proud parent of child #%d!\n", pid);
+ }
+
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.base/foll-vfork.exp b/gdb/testsuite/gdb.base/foll-vfork.exp
index 68934e7..9515d16 100644
--- a/gdb/testsuite/gdb.base/foll-vfork.exp
+++ b/gdb/testsuite/gdb.base/foll-vfork.exp
@@ -13,6 +13,11 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
+# Various tests of gdb's ability to follow the parent or child of a
+# Unix vfork system call. A vfork parent is blocked until the child
+# either execs or exits --- since those events take somewhat different
+# code paths in GDB, both variants are exercised.
+
if { [is_remote target] || ![isnative] } then {
continue
}
@@ -148,6 +153,31 @@ proc vfork_parent_follow_to_bp {} {
exec sleep 1
}}
+proc vfork_child_follow_to_exit {} {
+ with_test_prefix "vfork child follow, to exit" {
+ global gdb_prompt
+
+ setup_gdb
+
+ gdb_test_no_output "set follow-fork child"
+
+ set test "continue to child exit"
+ gdb_test_multiple "continue" $test {
+ -re "Couldn't get registers.*$gdb_prompt " {
+ setup_kfail "gdb/14766" *-*-*
+ fail "$test"
+ }
+ -re "Attaching after.* vfork to.*Detaching vfork parent .* after child exit.*$gdb_prompt " {
+ pass $test
+ }
+ }
+ # The parent has been detached; allow time for any output it might
+ # generate to arrive, so that output doesn't get confused with
+ # any gdb_expected debugger output from a subsequent testpoint.
+ #
+ exec sleep 1
+}}
+
proc vfork_and_exec_child_follow_to_main_bp {} {
with_test_prefix "vfork and exec child follow, to main bp" {
global gdb_prompt
@@ -267,7 +297,7 @@ proc tcatch_vfork_then_parent_follow {} {
exec sleep 1
}}
-proc tcatch_vfork_then_child_follow {} {
+proc tcatch_vfork_then_child_follow_exec {} {
with_test_prefix "vfork child follow, finish after tcatch vfork" {
global gdb_prompt
global srcfile
@@ -314,12 +344,56 @@ proc tcatch_vfork_then_child_follow {} {
exec sleep 1
}}
-proc do_vfork_and_exec_tests {} {
+proc tcatch_vfork_then_child_follow_exit {} {
+ with_test_prefix "vfork child follow, finish after tcatch vfork" {
global gdb_prompt
+ global srcfile
+
+ setup_gdb
+
+ gdb_test_no_output "set follow-fork child"
+
+ gdb_test "tcatch vfork" "Catchpoint .*(vfork).*"
+
+ # HP-UX 10.20 seems to stop you in "vfork", while more recent HP-UXs
+ # stop you in "_vfork".
+ set test "continue to vfork"
+ gdb_test_multiple "continue" $test {
+ -re "vfork \\(\\) at .*$gdb_prompt $" {
+ pass $test
+ }
+ -re "0x\[0-9a-fA-F\]*.*(vfork|__kernel_v?syscall).*$gdb_prompt " {
+ pass $test
+ }
+ }
+
+ set test "finish"
+ gdb_test_multiple "finish" $test {
+ -re "Couldn't get registers.*$gdb_prompt " {
+ setup_kfail "gdb/14766" *-*-*
+ fail "$test "
+ }
+ -re "Run till exit from.*vfork.*exited normally.*$gdb_prompt " {
+ setup_kfail "gdb/14762" *-*-*
+ fail $test
+ }
+ -re "Run till exit from.*vfork.*pid = vfork \\(\\).*$gdb_prompt " {
+ pass $test
+ }
+ -re "Run till exit from.*__kernel_v?syscall.*0x\[0-9a-fA-F\]* in vfork .*$gdb_prompt " {
+ send_gdb "finish\n"
+ exp_continue
+ }
+ }
+ # The parent has been detached; allow time for any output it might
+ # generate to arrive, so that output doesn't get confused with
+ # any expected debugger output from a subsequent testpoint.
+ #
+ exec sleep 1
+}}
- # Check that vfork catchpoints are supported, as an indicator for whether
- # vfork-following is supported.
- check_vfork_catchpoints
+proc do_vfork_and_follow_parent_tests {} {
+ global gdb_prompt
# Try following the parent process by stepping through a call to
# vfork. Do this without catchpoints.
@@ -330,6 +404,12 @@ proc do_vfork_and_exec_tests {} {
# without catchpoints.
vfork_parent_follow_to_bp
+ # Try catching a vfork, and stepping out to the parent.
+ #
+ tcatch_vfork_then_parent_follow
+}
+
+proc do_vfork_and_follow_child_tests_exec {} {
# Try following the child process by just continuing through the
# vfork, and letting the parent's breakpoint on "main" be auto-
# magically reset in the child.
@@ -345,13 +425,9 @@ proc do_vfork_and_exec_tests {} {
#
vfork_and_exec_child_follow_through_step
- # Try catching a vfork, and stepping out to the parent.
- #
- tcatch_vfork_then_parent_follow
-
# Try catching a vfork, and stepping out to the child.
#
- tcatch_vfork_then_child_follow
+ tcatch_vfork_then_child_follow_exec
# Test the ability to follow both child and parent of a vfork. Do
# this without catchpoints.
@@ -365,11 +441,60 @@ proc do_vfork_and_exec_tests {} {
#
}
-# This is a test of gdb's ability to follow the parent or child
-# of a Unix vfork() system call. (The child will subsequently
-# call a variant of a Unix exec() system call.)
-#
-do_vfork_and_exec_tests
+proc do_vfork_and_follow_child_tests_exit {} {
+ # Try following the child process by just continuing through the
+ # vfork, and letting the child exit.
+ #
+ vfork_child_follow_to_exit
+
+ # Try catching a vfork, and stepping out to the child.
+ #
+ tcatch_vfork_then_child_follow_exit
+}
+
+with_test_prefix "check vfork support" {
+ # Check that vfork catchpoints are supported, as an indicator for
+ # whether vfork-following is supported.
+ check_vfork_catchpoints
+}
+
+# Follow parent and follow child vfork tests with a child that execs.
+with_test_prefix "exec" {
+ # These are tests of gdb's ability to follow the parent of a Unix
+ # vfork system call. The child will subsequently call a variant
+ # of the Unix exec system call.
+ do_vfork_and_follow_parent_tests
+
+ # These are tests of gdb's ability to follow the child of a Unix
+ # vfork system call. The child will subsequently call a variant
+ # of a Unix exec system call.
+ #
+ do_vfork_and_follow_child_tests_exec
+}
+
+# Switch to test the case of the child exiting. We can't use
+# standard_testfile here because we don't want to overwrite the binary
+# of the previous tests.
+set testfile "foll-vfork-exit"
+set srcfile ${testfile}.c
+set binfile [standard_output_file ${testfile}]
+
+if {[build_executable $testfile.exp $testfile $srcfile] == -1} {
+ untested "failed to build $testfile"
+ return
+}
+
+# Follow parent and follow child vfork tests with a child that exits.
+with_test_prefix "exit" {
+ # These are tests of gdb's ability to follow the parent of a Unix
+ # vfork system call. The child will subsequently exit.
+ do_vfork_and_follow_parent_tests
+
+ # These are tests of gdb's ability to follow the child of a Unix
+ # vfork system call. The child will subsequently exit.
+ #
+ do_vfork_and_follow_child_tests_exit
+}
set timeout $oldtimeout
return 0