* Makefile.in (symfile.o): Update.

* NEWS: Mention exec tracing support.
	* inf-ttrace.c (inf_ttrace_wait): Return TARGET_WAITKIND_EXECD for
	exec events.
	* infcmd.c (kill_if_already_running, detach_command)
	(disconnect_command): Replace SOLIB_RESTART with no_shared_libraries.
	* infrun.c (MAY_FOLLOW_EXEC, may_follow_exec): Delete.
	(follow_exec): Do not check may_follow_exec.  Do not mourn and push
	targets.  Apply the sysroot path to the loaded executable.  Use
	no_shared_libraries.
	* linux-nat.c (linux_child_follow_fork): Print fork following
	messages if verbose.
	(kill_wait_callback): Kill again before waiting a second time.
	* symfile.c (symbol_file_clear): Replace SOLIB_RESTART with
	no_shared_libraries.

	* gdb.base/foll-exec.exp: Update header.  Skip on remote targets.
	Run on GNU/Linux.
	(do_exec_tests): Check for systems which do not support catchpoints.
	Do not match START.
	* gdb.base/foll-fork.exp: Update header.  Skip on remote targets.
	Run on GNU/Linux.  Enable verbose output.
	(check_fork_catchpoints): New.
	(explicit_fork_child_follow, catch_fork_child_follow)
	(tcatch_fork_parent_follow): Update expected messages.
	(do_fork_tests): Use check_fork_catchpoints.
	* gdb.base/foll-vfork.exp: Update header.  Skip on remote targets.
	Run on GNU/Linux.  Enable verbose output.
	(check_vfork_catchpoints): New.
	(vfork_parent_follow_to_bp, tcatch_vfork_then_child_follow): Update
	expected messages.
	(do_vfork_and_exec_tests): Use check_fork_catchpoints.
This commit is contained in:
Daniel Jacobowitz
2008-01-29 22:47:20 +00:00
parent 9db13498bf
commit e85a822c15
11 changed files with 197 additions and 90 deletions

@ -1,3 +1,21 @@
2008-01-29 Daniel Jacobowitz <dan@codesourcery.com>
* Makefile.in (symfile.o): Update.
* NEWS: Mention exec tracing support.
* inf-ttrace.c (inf_ttrace_wait): Return TARGET_WAITKIND_EXECD for
exec events.
* infcmd.c (kill_if_already_running, detach_command)
(disconnect_command): Replace SOLIB_RESTART with no_shared_libraries.
* infrun.c (MAY_FOLLOW_EXEC, may_follow_exec): Delete.
(follow_exec): Do not check may_follow_exec. Do not mourn and push
targets. Apply the sysroot path to the loaded executable. Use
no_shared_libraries.
* linux-nat.c (linux_child_follow_fork): Print fork following
messages if verbose.
(kill_wait_callback): Kill again before waiting a second time.
* symfile.c (symbol_file_clear): Replace SOLIB_RESTART with
no_shared_libraries.
2008-01-29 Joel Brobecker <brobecker@adacore.com> 2008-01-29 Joel Brobecker <brobecker@adacore.com>
* amd64-tdep.c (amd64_classify): Add handling of TYPE_CODE_CHAR. * amd64-tdep.c (amd64_classify): Add handling of TYPE_CODE_CHAR.

@ -2850,7 +2850,7 @@ symfile.o: symfile.c $(defs_h) $(bfdlink_h) $(symtab_h) $(gdbtypes_h) \
$(gdb_stabs_h) $(gdb_obstack_h) $(completer_h) $(bcache_h) \ $(gdb_stabs_h) $(gdb_obstack_h) $(completer_h) $(bcache_h) \
$(hashtab_h) $(readline_h) $(gdb_assert_h) $(block_h) \ $(hashtab_h) $(readline_h) $(gdb_assert_h) $(block_h) \
$(gdb_string_h) $(gdb_stat_h) $(observer_h) $(exec_h) \ $(gdb_string_h) $(gdb_stat_h) $(observer_h) $(exec_h) \
$(parser_defs_h) $(varobj_h) $(elf_bfd_h) $(parser_defs_h) $(varobj_h) $(elf_bfd_h) $(solib_h)
symfile-mem.o: symfile-mem.c $(defs_h) $(symtab_h) $(gdbcore_h) \ symfile-mem.o: symfile-mem.c $(defs_h) $(symtab_h) $(gdbcore_h) \
$(objfiles_h) $(exceptions_h) $(gdbcmd_h) $(target_h) $(value_h) \ $(objfiles_h) $(exceptions_h) $(gdbcmd_h) $(target_h) $(value_h) \
$(symfile_h) $(observer_h) $(auxv_h) $(elf_common_h) $(symfile_h) $(observer_h) $(auxv_h) $(elf_common_h)

@ -82,6 +82,9 @@ vFile:pwrite:
vFile:unlink: vFile:unlink:
Open, close, read, write, and delete files on the remote system. Open, close, read, write, and delete files on the remote system.
* GDB on GNU/Linux and HP/UX can now debug through "exec" of a new
process.
*** Changes in GDB 6.7 *** Changes in GDB 6.7
* Resolved 101 resource leaks, null pointer dereferences, etc. in gdb, * Resolved 101 resource leaks, null pointer dereferences, etc. in gdb,

@ -454,9 +454,7 @@ kill_if_already_running (int from_tty)
Start it from the beginning? ")) Start it from the beginning? "))
error (_("Program not restarted.")); error (_("Program not restarted."));
target_kill (); target_kill ();
#if defined(SOLIB_RESTART) no_shared_libraries (NULL, from_tty);
SOLIB_RESTART ();
#endif
init_wait_for_inferior (); init_wait_for_inferior ();
} }
} }
@ -1974,9 +1972,7 @@ detach_command (char *args, int from_tty)
{ {
dont_repeat (); /* Not for the faint of heart. */ dont_repeat (); /* Not for the faint of heart. */
target_detach (args, from_tty); target_detach (args, from_tty);
#if defined(SOLIB_RESTART) no_shared_libraries (NULL, from_tty);
SOLIB_RESTART ();
#endif
if (deprecated_detach_hook) if (deprecated_detach_hook)
deprecated_detach_hook (); deprecated_detach_hook ();
} }
@ -1994,9 +1990,7 @@ disconnect_command (char *args, int from_tty)
{ {
dont_repeat (); /* Not for the faint of heart */ dont_repeat (); /* Not for the faint of heart */
target_disconnect (args, from_tty); target_disconnect (args, from_tty);
#if defined(SOLIB_RESTART) no_shared_libraries (NULL, from_tty);
SOLIB_RESTART ();
#endif
if (deprecated_detach_hook) if (deprecated_detach_hook)
deprecated_detach_hook (); deprecated_detach_hook ();
} }

@ -105,15 +105,6 @@ int sync_execution = 0;
static ptid_t previous_inferior_ptid; static ptid_t previous_inferior_ptid;
/* This is true for configurations that may follow through execl() and
similar functions. At present this is only true for HP-UX native. */
#ifndef MAY_FOLLOW_EXEC
#define MAY_FOLLOW_EXEC (0)
#endif
static int may_follow_exec = MAY_FOLLOW_EXEC;
static int debug_infrun = 0; static int debug_infrun = 0;
static void static void
show_debug_infrun (struct ui_file *file, int from_tty, show_debug_infrun (struct ui_file *file, int from_tty,
@ -369,9 +360,6 @@ follow_exec (int pid, char *execd_pathname)
int saved_pid = pid; int saved_pid = pid;
struct target_ops *tgt; struct target_ops *tgt;
if (!may_follow_exec)
return;
/* This is an exec event that we actually wish to pay attention to. /* This is an exec event that we actually wish to pay attention to.
Refresh our symbol table to the newly exec'd program, remove any Refresh our symbol table to the newly exec'd program, remove any
momentary bp's, etc. momentary bp's, etc.
@ -406,17 +394,20 @@ follow_exec (int pid, char *execd_pathname)
/* We've followed the inferior through an exec. Therefore, the /* We've followed the inferior through an exec. Therefore, the
inferior has essentially been killed & reborn. */ inferior has essentially been killed & reborn. */
/* First collect the run target in effect. */
tgt = find_run_target ();
/* If we can't find one, things are in a very strange state... */
if (tgt == NULL)
error (_("Could find run target to save before following exec"));
gdb_flush (gdb_stdout); gdb_flush (gdb_stdout);
target_mourn_inferior (); generic_mourn_inferior ();
inferior_ptid = pid_to_ptid (saved_pid);
/* Because mourn_inferior resets inferior_ptid. */ /* Because mourn_inferior resets inferior_ptid. */
push_target (tgt); inferior_ptid = pid_to_ptid (saved_pid);
if (gdb_sysroot && *gdb_sysroot)
{
char *name = alloca (strlen (gdb_sysroot)
+ strlen (execd_pathname)
+ 1);
strcpy (name, gdb_sysroot);
strcat (name, execd_pathname);
execd_pathname = name;
}
/* That a.out is now the one to use. */ /* That a.out is now the one to use. */
exec_file_attach (execd_pathname, 0); exec_file_attach (execd_pathname, 0);
@ -427,9 +418,7 @@ follow_exec (int pid, char *execd_pathname)
/* Reset the shared library package. This ensures that we get /* Reset the shared library package. This ensures that we get
a shlib event when the child reaches "_start", at which point a shlib event when the child reaches "_start", at which point
the dld will have had a chance to initialize the child. */ the dld will have had a chance to initialize the child. */
#if defined(SOLIB_RESTART) no_shared_libraries (NULL, 0);
SOLIB_RESTART ();
#endif
#ifdef SOLIB_CREATE_INFERIOR_HOOK #ifdef SOLIB_CREATE_INFERIOR_HOOK
SOLIB_CREATE_INFERIOR_HOOK (PIDGET (inferior_ptid)); SOLIB_CREATE_INFERIOR_HOOK (PIDGET (inferior_ptid));
#else #else

@ -383,7 +383,7 @@ linux_child_follow_fork (struct target_ops *ops, int follow_child)
/* Detach new forked process? */ /* Detach new forked process? */
if (detach_fork) if (detach_fork)
{ {
if (debug_linux_nat) if (info_verbose || debug_linux_nat)
{ {
target_terminal_ours (); target_terminal_ours ();
fprintf_filtered (gdb_stdlog, fprintf_filtered (gdb_stdlog,
@ -468,7 +468,7 @@ linux_child_follow_fork (struct target_ops *ops, int follow_child)
/* Before detaching from the parent, remove all breakpoints from it. */ /* Before detaching from the parent, remove all breakpoints from it. */
remove_breakpoints (); remove_breakpoints ();
if (debug_linux_nat) if (info_verbose || debug_linux_nat)
{ {
target_terminal_ours (); target_terminal_ours ();
fprintf_filtered (gdb_stdlog, fprintf_filtered (gdb_stdlog,
@ -2348,11 +2348,18 @@ kill_wait_callback (struct lwp_info *lp, void *data)
do do
{ {
pid = my_waitpid (GET_LWP (lp->ptid), NULL, __WCLONE); pid = my_waitpid (GET_LWP (lp->ptid), NULL, __WCLONE);
if (pid != (pid_t) -1 && debug_linux_nat) if (pid != (pid_t) -1)
{ {
fprintf_unfiltered (gdb_stdlog, if (debug_linux_nat)
"KWC: wait %s received unknown.\n", fprintf_unfiltered (gdb_stdlog,
target_pid_to_str (lp->ptid)); "KWC: wait %s received unknown.\n",
target_pid_to_str (lp->ptid));
/* The Linux kernel sometimes fails to kill a thread
completely after PTRACE_KILL; that goes from the stop
point in do_fork out to the one in
get_signal_to_deliever and waits again. So kill it
again. */
kill_callback (lp, NULL);
} }
} }
while (pid == GET_LWP (lp->ptid)); while (pid == GET_LWP (lp->ptid));
@ -2363,11 +2370,14 @@ kill_wait_callback (struct lwp_info *lp, void *data)
do do
{ {
pid = my_waitpid (GET_LWP (lp->ptid), NULL, 0); pid = my_waitpid (GET_LWP (lp->ptid), NULL, 0);
if (pid != (pid_t) -1 && debug_linux_nat) if (pid != (pid_t) -1)
{ {
fprintf_unfiltered (gdb_stdlog, if (debug_linux_nat)
"KWC: wait %s received unk.\n", fprintf_unfiltered (gdb_stdlog,
target_pid_to_str (lp->ptid)); "KWC: wait %s received unk.\n",
target_pid_to_str (lp->ptid));
/* See the call to kill_callback above. */
kill_callback (lp, NULL);
} }
} }
while (pid == GET_LWP (lp->ptid)); while (pid == GET_LWP (lp->ptid));

@ -52,6 +52,7 @@
#include "parser-defs.h" #include "parser-defs.h"
#include "varobj.h" #include "varobj.h"
#include "elf-bfd.h" #include "elf-bfd.h"
#include "solib.h"
#include <sys/types.h> #include <sys/types.h>
#include <fcntl.h> #include <fcntl.h>
@ -1217,9 +1218,7 @@ symbol_file_clear (int from_tty)
storage has just been released, we'd better wipe the solib storage has just been released, we'd better wipe the solib
descriptors as well. descriptors as well.
*/ */
#if defined(SOLIB_RESTART) no_shared_libraries (NULL, from_tty);
SOLIB_RESTART ();
#endif
symfile_objfile = NULL; symfile_objfile = NULL;
if (from_tty) if (from_tty)

@ -1,3 +1,22 @@
2008-01-29 Daniel Jacobowitz <dan@codesourcery.com>
* gdb.base/foll-exec.exp: Update header. Skip on remote targets.
Run on GNU/Linux.
(do_exec_tests): Check for systems which do not support catchpoints.
Do not match START.
* gdb.base/foll-fork.exp: Update header. Skip on remote targets.
Run on GNU/Linux. Enable verbose output.
(check_fork_catchpoints): New.
(explicit_fork_child_follow, catch_fork_child_follow)
(tcatch_fork_parent_follow): Update expected messages.
(do_fork_tests): Use check_fork_catchpoints.
* gdb.base/foll-vfork.exp: Update header. Skip on remote targets.
Run on GNU/Linux. Enable verbose output.
(check_vfork_catchpoints): New.
(vfork_parent_follow_to_bp, tcatch_vfork_then_child_follow): Update
expected messages.
(do_vfork_and_exec_tests): Use check_fork_catchpoints.
2008-01-29 Jim Blandy <jimb@red-bean.com> 2008-01-29 Jim Blandy <jimb@red-bean.com>
* lib/gdbserver-support.exp (gdb_target_cmd): Recognize 'unknown * lib/gdbserver-support.exp (gdb_target_cmd): Recognize 'unknown

@ -11,16 +11,9 @@
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. */ # along with this program. If not, see <http://www.gnu.org/licenses/>.
# Please email any bugs, comments, and/or additions to this file to: if { [is_remote target] || ![isnative] } then {
# bug-gdb@prep.ai.mit.edu
if $tracelevel then {
strace $tracelevel
}
if { ![isnative] } then {
continue continue
} }
@ -48,7 +41,7 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {deb
# Until "catch exec" is implemented on other targets... # Until "catch exec" is implemented on other targets...
# #
if ![istarget "hppa*-hp-hpux*"] then { if {![istarget "hppa*-hp-hpux*"] && ![istarget "*-linux*"]} then {
continue continue
} }
@ -93,6 +86,33 @@ proc do_exec_tests {} {
return return
} }
# Verify that the system supports "catch exec".
gdb_test "catch exec" "Catchpoint \[0-9\]* \\(exec\\)" "insert first exec catchpoint"
set has_exec_catchpoints 0
gdb_test_multiple "continue" "continue to first exec catchpoint" {
-re ".*Your system does not support exec catchpoints.*$gdb_prompt $" {
unsupported "continue to first exec catchpoint"
}
-re ".*Catchpoint.*$gdb_prompt $" {
set has_exec_catchpoints 1
pass "continue to first exec catchpoint"
}
}
if {$has_exec_catchpoints == 0} {
unsupported "exec catchpoints"
return
}
zap_session
# Start the program running, and stop at main.
#
if ![runto_main] then {
perror "Couldn't run ${testfile}"
return
}
# Verify that we can see various global and local variables # Verify that we can see various global and local variables
# in this program, and that they have expected values. Some # in this program, and that they have expected values. Some
# of these variables are also declared in the program we'll # of these variables are also declared in the program we'll
@ -213,7 +233,7 @@ proc do_exec_tests {} {
setup_xfail hppa2.0w-hp-hpux* CLLbs16760 setup_xfail hppa2.0w-hp-hpux* CLLbs16760
send_gdb "continue\n" send_gdb "continue\n"
gdb_expect { gdb_expect {
-re ".*Executing new program:.*${testfile2}.*Catchpoint .*(exec\'d .*${testfile2}).*in .START..*$gdb_prompt $"\ -re ".*Executing new program:.*${testfile2}.*Catchpoint .*(exec\'d .*${testfile2}).*in .*$gdb_prompt $"\
{pass "hit catch exec"} {pass "hit catch exec"}
-re "$gdb_prompt $" {fail "hit catch exec"} -re "$gdb_prompt $" {fail "hit catch exec"}
timeout {fail "(timeout) hit catch exec"} timeout {fail "(timeout) hit catch exec"}

@ -11,22 +11,16 @@
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. */ # along with this program. If not, see <http://www.gnu.org/licenses/>.
# Please email any bugs, comments, and/or additions to this file to: if { [is_remote target] || ![isnative] } then {
# bug-gdb@prep.ai.mit.edu
if $tracelevel then {
strace $tracelevel
}
if { ![isnative] } then {
continue continue
} }
set prms_id 0 set prms_id 0
set bug_id 0 set bug_id 0
global srcfile
set testfile "foll-fork" set testfile "foll-fork"
set srcfile ${testfile}.c set srcfile ${testfile}.c
set binfile ${objdir}/${subdir}/${testfile} set binfile ${objdir}/${subdir}/${testfile}
@ -41,10 +35,32 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {deb
# Until "set follow-fork-mode" and "catch fork" are implemented on # Until "set follow-fork-mode" and "catch fork" are implemented on
# other targets... # other targets...
# #
if ![istarget "hppa*-hp-hpux*"] then { if {![istarget "hppa*-hp-hpux*"] && ![istarget "*-linux*"]} then {
continue continue
} }
proc check_fork_catchpoints {} {
global gdb_prompt
# Verify that the system supports "catch fork".
gdb_test "catch fork" "Catchpoint \[0-9\]* \\(fork\\)" "insert first fork catchpoint"
set has_fork_catchpoints 0
gdb_test_multiple "continue" "continue to first fork catchpoint" {
-re ".*Your system does not support fork catchpoints.*$gdb_prompt $" {
unsupported "continue to first fork catchpoint"
}
-re ".*Catchpoint.*$gdb_prompt $" {
set has_fork_catchpoints 1
pass "continue to first fork catchpoint"
}
}
if {$has_fork_catchpoints == 0} {
unsupported "fork catchpoints"
return -code return
}
}
proc default_fork_parent_follow {} { proc default_fork_parent_follow {} {
global gdb_prompt global gdb_prompt
@ -115,7 +131,7 @@ proc explicit_fork_child_follow {} {
} }
send_gdb "next 2\n" send_gdb "next 2\n"
gdb_expect { gdb_expect {
-re "Detaching from program:.*Attaching after fork to.*$gdb_prompt $"\ -re "Attaching after fork to.*$gdb_prompt $"\
{pass "explicit child follow, no catchpoints"} {pass "explicit child follow, no catchpoints"}
-re "$gdb_prompt $" {fail "explicit child follow, no catchpoints"} -re "$gdb_prompt $" {fail "explicit child follow, no catchpoints"}
timeout {fail "(timeout) explicit child follow, no catchpoints"} timeout {fail "(timeout) explicit child follow, no catchpoints"}
@ -129,6 +145,7 @@ proc explicit_fork_child_follow {} {
proc catch_fork_child_follow {} { proc catch_fork_child_follow {} {
global gdb_prompt global gdb_prompt
global srcfile
send_gdb "catch fork\n" send_gdb "catch fork\n"
gdb_expect { gdb_expect {
@ -153,7 +170,7 @@ proc catch_fork_child_follow {} {
send_gdb "continue\n" send_gdb "continue\n"
gdb_expect { gdb_expect {
-re "Catchpoint.*(forked process.*),.*in _fork_sys.*$gdb_prompt $"\ -re "Catchpoint.*(forked process.*),.*in .*fork.*$gdb_prompt $"\
{pass "explicit child follow, catch fork"} {pass "explicit child follow, catch fork"}
-re "$gdb_prompt $" {fail "explicit child follow, catch fork"} -re "$gdb_prompt $" {fail "explicit child follow, catch fork"}
timeout {fail "(timeout) explicit child follow, catch fork"} timeout {fail "(timeout) explicit child follow, catch fork"}
@ -175,7 +192,7 @@ proc catch_fork_child_follow {} {
-re "$gdb_prompt $" {pass "set follow child"} -re "$gdb_prompt $" {pass "set follow child"}
timeout {fail "(timeout) set follow child"} timeout {fail "(timeout) set follow child"}
} }
send_gdb "tbreak 24\n" send_gdb "tbreak ${srcfile}:24\n"
gdb_expect { gdb_expect {
-re "Breakpoint.*, line 24.*$gdb_prompt $"\ -re "Breakpoint.*, line 24.*$gdb_prompt $"\
{pass "set follow child, tbreak"} {pass "set follow child, tbreak"}
@ -184,7 +201,7 @@ proc catch_fork_child_follow {} {
} }
send_gdb "continue\n" send_gdb "continue\n"
gdb_expect { gdb_expect {
-re ".*Detaching from program:.*Attaching after fork to.* at .*24.*$gdb_prompt $"\ -re "Attaching after fork to.* at .*24.*$gdb_prompt $"\
{pass "set follow child, hit tbreak"} {pass "set follow child, hit tbreak"}
-re "$gdb_prompt $" {fail "set follow child, hit tbreak"} -re "$gdb_prompt $" {fail "set follow child, hit tbreak"}
timeout {fail "(timeout) set follow child, hit tbreak"} timeout {fail "(timeout) set follow child, hit tbreak"}
@ -211,6 +228,7 @@ proc catch_fork_child_follow {} {
proc tcatch_fork_parent_follow {} { proc tcatch_fork_parent_follow {} {
global gdb_prompt global gdb_prompt
global srcfile
send_gdb "catch fork\n" send_gdb "catch fork\n"
gdb_expect { gdb_expect {
@ -225,7 +243,7 @@ proc tcatch_fork_parent_follow {} {
send_gdb "continue\n" send_gdb "continue\n"
gdb_expect { gdb_expect {
-re ".*in _fork_sys.*$gdb_prompt $"\ -re ".*in .*fork.*$gdb_prompt $"\
{pass "explicit parent follow, tcatch fork"} {pass "explicit parent follow, tcatch fork"}
-re "$gdb_prompt $" {fail "explicit parent follow, tcatch fork"} -re "$gdb_prompt $" {fail "explicit parent follow, tcatch fork"}
timeout {fail "(timeout) explicit parent follow, tcatch fork"} timeout {fail "(timeout) explicit parent follow, tcatch fork"}
@ -235,7 +253,7 @@ proc tcatch_fork_parent_follow {} {
-re "$gdb_prompt $" {pass "set follow parent"} -re "$gdb_prompt $" {pass "set follow parent"}
timeout {fail "(timeout) set follow parent"} timeout {fail "(timeout) set follow parent"}
} }
send_gdb "tbreak 24\n" send_gdb "tbreak ${srcfile}:24\n"
gdb_expect { gdb_expect {
-re "Breakpoint.*, line 24.*$gdb_prompt $"\ -re "Breakpoint.*, line 24.*$gdb_prompt $"\
{pass "set follow parent, tbreak"} {pass "set follow parent, tbreak"}
@ -313,6 +331,10 @@ By default, the debugger will follow the parent process..*$gdb_prompt $"\
timeout {fail "set follow to nonsense is prohibited (reset parent)"} timeout {fail "set follow to nonsense is prohibited (reset parent)"}
} }
# Check that fork catchpoints are supported, as an indicator for whether
# fork-following is supported.
if [runto_main] then { check_fork_catchpoints }
# Test the default behaviour, which is to follow the parent of a # Test the default behaviour, which is to follow the parent of a
# fork, and detach from the child. Do this without catchpoints. # fork, and detach from the child. Do this without catchpoints.
# #
@ -357,6 +379,9 @@ gdb_start
gdb_reinitialize_dir $srcdir/$subdir gdb_reinitialize_dir $srcdir/$subdir
gdb_load ${binfile} gdb_load ${binfile}
# The "Detaching..." and "Attaching..." messages may be hidden by
# default.
gdb_test "set verbose" ""
# This is a test of gdb's ability to follow the parent, child or both # This is a test of gdb's ability to follow the parent, child or both
# parent and child of a Unix fork() system call. # parent and child of a Unix fork() system call.

@ -11,16 +11,9 @@
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. */ # along with this program. If not, see <http://www.gnu.org/licenses/>.
# Please email any bugs, comments, and/or additions to this file to: if { [is_remote target] || ![isnative] } then {
# bug-gdb@prep.ai.mit.edu
if $tracelevel then {
strace $tracelevel
}
if { ![isnative] } then {
continue continue
} }
@ -35,6 +28,7 @@ set bug_id 0
## return 0 ## return 0
##} ##}
global srcfile
set testfile "foll-vfork" set testfile "foll-vfork"
set testfile2 "vforked-prog" set testfile2 "vforked-prog"
set srcfile ${testfile}.c set srcfile ${testfile}.c
@ -56,7 +50,7 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile2}" "${binfile2}" executable {d
# Until "set follow-fork-mode" and "catch vfork" are implemented on # Until "set follow-fork-mode" and "catch vfork" are implemented on
# other targets... # other targets...
# #
if ![istarget "hppa*-hp-hpux*"] then { if {![istarget "hppa*-hp-hpux*"] && ![istarget "*-linux*"]} then {
continue continue
} }
@ -73,6 +67,29 @@ if [istarget "hppa*-hp-hpux10.20"] then {
set oldtimeout $timeout set oldtimeout $timeout
set timeout [expr "$timeout + 10"] set timeout [expr "$timeout + 10"]
proc check_vfork_catchpoints {} {
global gdb_prompt
global has_vfork_catchpoints
# Verify that the system supports "catch vfork".
gdb_test "catch vfork" "Catchpoint \[0-9\]* \\(vfork\\)" "insert first vfork catchpoint"
set has_vfork_catchpoints 0
gdb_test_multiple "continue" "continue to first vfork catchpoint" {
-re ".*Your system does not support vfork catchpoints.*$gdb_prompt $" {
unsupported "continue to first vfork catchpoint"
}
-re ".*Catchpoint.*$gdb_prompt $" {
set has_vfork_catchpoints 1
pass "continue to first vfork catchpoint"
}
}
if {$has_vfork_catchpoints == 0} {
unsupported "vfork catchpoints"
return -code return
}
}
proc vfork_parent_follow_through_step {} { proc vfork_parent_follow_through_step {} {
global gdb_prompt global gdb_prompt
@ -97,20 +114,21 @@ proc vfork_parent_follow_through_step {} {
proc vfork_parent_follow_to_bp {} { proc vfork_parent_follow_to_bp {} {
global gdb_prompt global gdb_prompt
global srcfile
send_gdb "set follow parent\n" send_gdb "set follow parent\n"
gdb_expect { gdb_expect {
-re "$gdb_prompt $" {pass "set follow parent, vfork to bp"} -re "$gdb_prompt $" {pass "set follow parent, vfork to bp"}
timeout {fail "set follow parent, vfork to bp"} timeout {fail "set follow parent, vfork to bp"}
} }
send_gdb "break 18\n" send_gdb "break ${srcfile}:18\n"
gdb_expect { gdb_expect {
-re "$gdb_prompt $" {pass "break, vfork to bp"} -re "$gdb_prompt $" {pass "break, vfork to bp"}
timeout {fail "break, vfork to bp"} timeout {fail "break, vfork to bp"}
} }
send_gdb "continue\n" send_gdb "continue\n"
gdb_expect { gdb_expect {
-re ".*Detaching after fork from process.*Breakpoint.*18.*$gdb_prompt "\ -re ".*Detaching after fork from child process.*Breakpoint.*18.*$gdb_prompt "\
{pass "vfork parent follow, to bp"} {pass "vfork parent follow, to bp"}
-re "$gdb_prompt $" {fail "vfork parent follow, to bp"} -re "$gdb_prompt $" {fail "vfork parent follow, to bp"}
timeout {fail "(timeout) vfork parent follow, to bp" } timeout {fail "(timeout) vfork parent follow, to bp" }
@ -133,7 +151,7 @@ proc vfork_and_exec_child_follow_to_main_bp {} {
} }
send_gdb "continue\n" send_gdb "continue\n"
gdb_expect { gdb_expect {
-re "Detaching from program.*Attaching after fork to.*Executing new program.*Breakpoint.*vforked-prog.c:9.*$gdb_prompt "\ -re "Attaching after fork to.*Executing new program.*Breakpoint.*vforked-prog.c:9.*$gdb_prompt "\
{pass "vfork and exec child follow, to main bp"} {pass "vfork and exec child follow, to main bp"}
-re "$gdb_prompt $" {fail "vfork and exec child follow, to main bp"} -re "$gdb_prompt $" {fail "vfork and exec child follow, to main bp"}
timeout {fail "(timeout) vfork and exec child follow, to main bp" } timeout {fail "(timeout) vfork and exec child follow, to main bp" }
@ -191,7 +209,7 @@ proc vfork_and_exec_child_follow_through_step {} {
} }
send_gdb "next\n" send_gdb "next\n"
gdb_expect { gdb_expect {
-re "Detaching from program.*Attaching after fork to.*Executing new program.*Breakpoint.*vforked-prog.c:9.*$gdb_prompt "\ -re "Attaching after fork to.*Executing new program.*Breakpoint.*vforked-prog.c:9.*$gdb_prompt "\
{pass "vfork and exec child follow, through step"} {pass "vfork and exec child follow, through step"}
-re "$gdb_prompt $" {fail "vfork and exec child follow, through step"} -re "$gdb_prompt $" {fail "vfork and exec child follow, through step"}
timeout {fail "(timeout) vfork and exec child follow, through step" } timeout {fail "(timeout) vfork and exec child follow, through step" }
@ -248,7 +266,7 @@ proc tcatch_vfork_then_parent_follow {} {
gdb_expect { gdb_expect {
-re "0x\[0-9a-fA-F\]*.*vfork.*$gdb_prompt "\ -re "0x\[0-9a-fA-F\]*.*vfork.*$gdb_prompt "\
{pass "vfork parent follow, tcatch vfork"} {pass "vfork parent follow, tcatch vfork"}
-re "0x\[0-9a-fA-F\]*.*_vfork.*$gdb_prompt "\ -re "vfork \\(\\) at.*$gdb_prompt "\
{pass "vfork parent follow, tcatch vfork"} {pass "vfork parent follow, tcatch vfork"}
-re "$gdb_prompt $" {fail "vfork parent follow, tcatch vfork"} -re "$gdb_prompt $" {fail "vfork parent follow, tcatch vfork"}
timeout {fail "(timeout) vfork parent follow, tcatch vfork"} timeout {fail "(timeout) vfork parent follow, tcatch vfork"}
@ -269,6 +287,7 @@ proc tcatch_vfork_then_parent_follow {} {
proc tcatch_vfork_then_child_follow {} { proc tcatch_vfork_then_child_follow {} {
global gdb_prompt global gdb_prompt
global srcfile
global srcfile2 global srcfile2
send_gdb "set follow child\n" send_gdb "set follow child\n"
@ -287,6 +306,8 @@ proc tcatch_vfork_then_child_follow {} {
# HP-UX 10.20 seems to stop you in "vfork", while more recent HP-UXs # HP-UX 10.20 seems to stop you in "vfork", while more recent HP-UXs
# stop you in "_vfork". # stop you in "_vfork".
gdb_expect { gdb_expect {
-re "vfork \\(\\) at .*$gdb_prompt $"\
{pass "vfork child follow, tcatch vfork"}
-re "0x\[0-9a-fA-F\]*.*vfork.*$gdb_prompt "\ -re "0x\[0-9a-fA-F\]*.*vfork.*$gdb_prompt "\
{pass "vfork child follow, tcatch vfork"} {pass "vfork child follow, tcatch vfork"}
-re "0x\[0-9a-fA-F\]*.*_vfork.*$gdb_prompt "\ -re "0x\[0-9a-fA-F\]*.*_vfork.*$gdb_prompt "\
@ -296,8 +317,10 @@ proc tcatch_vfork_then_child_follow {} {
} }
send_gdb "finish\n" send_gdb "finish\n"
gdb_expect { gdb_expect {
-re "Run till exit from.*vfork.*${srcfile2}:9.*$gdb_prompt "\ -re "Run till exit from.*vfork.*${srcfile}:12.*$gdb_prompt "\
{pass "vfork child follow, finish after tcatch vfork"} {pass "vfork child follow, finish after tcatch vfork"}
-re "Run till exit from.*vfork.*${srcfile2}:9.*$gdb_prompt "\
{pass "vfork child follow, finish after tcatch vfork (followed exec)"}
-re "$gdb_prompt $" {fail "vfork child follow, finish after tcatch vfork"} -re "$gdb_prompt $" {fail "vfork child follow, finish after tcatch vfork"}
timeout {fail "(timeout) vfork child follow, finish after tcatch vfork" } timeout {fail "(timeout) vfork child follow, finish after tcatch vfork" }
} }
@ -311,6 +334,10 @@ proc tcatch_vfork_then_child_follow {} {
proc do_vfork_and_exec_tests {} { proc do_vfork_and_exec_tests {} {
global gdb_prompt global gdb_prompt
# Check that vfork catchpoints are supported, as an indicator for whether
# vfork-following is supported.
if [runto_main] then { check_vfork_catchpoints }
# Try following the parent process by stepping through a call to # Try following the parent process by stepping through a call to
# vfork. Do this without catchpoints. # vfork. Do this without catchpoints.
if [runto_main] then { vfork_parent_follow_through_step } if [runto_main] then { vfork_parent_follow_through_step }
@ -362,6 +389,9 @@ gdb_start
gdb_reinitialize_dir $srcdir/$subdir gdb_reinitialize_dir $srcdir/$subdir
gdb_load ${binfile} gdb_load ${binfile}
# The "Detaching..." and "Attaching..." messages may be hidden by
# default.
gdb_test "set verbose" ""
# This is a test of gdb's ability to follow the parent or child # This is a test of gdb's ability to follow the parent or child
# of a Unix vfork() system call. (The child will subsequently # of a Unix vfork() system call. (The child will subsequently