* config/pa/nm-hppah.h (CHILD_POST_FOLLOW_VFORK): Change to

CHILD_FOLLOW_FORK.
	* hppah-nat.c (saved_vfork_pid): Add.
	(child_post_follow_vfork): Remove.
	(child_follow_fork): New function.
	(child_wait): Call detach_breakpoints after receiving the child vfork.
	Call child_resume directly instead of going through resume ().
	Make sure we have the exec before reporting the vfork.
	* inferior.h (follow_inferior_reset_breakpoints): Add prototype.
	* infrun.c (follow_fork, follow_vfork, follow_inferior_fork): Remove.
	(follow_fork): New function.  Call target_follow_fork.
	(follow_inferior_reset_breakpoints): New function broken out from
	old follow_inferior_fork.
	(resume): Remove hack to follow exec after vfork.
	* inftarg.c (child_post_follow_vfork): Remove.
	(child_follow_fork): New function.
	(init_child_ops): Replace to_post_follow_vfork with to_follow_fork.
	* target.c (cleanup_target): Replace to_post_follow_vfork with
	to_follow_fork.
	(update_current_target): Likewise.
	(setup_target_debug): Likewise.
	(debug_to_post_follow_vfork): Remove.
	(debug_to_follow_fork): New function.
	* target.h (struct target_ops): Replace to_post_folow_vfork with
	to_follow_fork.
	(child_post_follow_vfork): Remove prototype.
	(child_follow_fork): Add prototype.
	(target_post_follow_vfork): Remove macro.
	(target_follow_fork): Add macro.

testsuite/
	* gdb.base/foll-vfork.exp: Re-enable test on HP/UX.
This commit is contained in:
Daniel Jacobowitz 2002-12-11 02:04:45 +00:00
parent 7d2830a309
commit 6604731ba7
10 changed files with 253 additions and 252 deletions

View File

@ -1,3 +1,35 @@
2002-12-10 Daniel Jacobowitz <drow@mvista.com>
* config/pa/nm-hppah.h (CHILD_POST_FOLLOW_VFORK): Change to
CHILD_FOLLOW_FORK.
* hppah-nat.c (saved_vfork_pid): Add.
(child_post_follow_vfork): Remove.
(child_follow_fork): New function.
(child_wait): Call detach_breakpoints after receiving the child vfork.
Call child_resume directly instead of going through resume ().
Make sure we have the exec before reporting the vfork.
* inferior.h (follow_inferior_reset_breakpoints): Add prototype.
* infrun.c (follow_fork, follow_vfork, follow_inferior_fork): Remove.
(follow_fork): New function. Call target_follow_fork.
(follow_inferior_reset_breakpoints): New function broken out from
old follow_inferior_fork.
(resume): Remove hack to follow exec after vfork.
* inftarg.c (child_post_follow_vfork): Remove.
(child_follow_fork): New function.
(init_child_ops): Replace to_post_follow_vfork with to_follow_fork.
* target.c (cleanup_target): Replace to_post_follow_vfork with
to_follow_fork.
(update_current_target): Likewise.
(setup_target_debug): Likewise.
(debug_to_post_follow_vfork): Remove.
(debug_to_follow_fork): New function.
* target.h (struct target_ops): Replace to_post_folow_vfork with
to_follow_fork.
(child_post_follow_vfork): Remove prototype.
(child_follow_fork): Add prototype.
(target_post_follow_vfork): Remove macro.
(target_follow_fork): Add macro.
2002-12-10 Daniel Jacobowitz <drow@mvista.com>
* hppah-nat.c (saved_child_execd_pathname, saved_vfork_state): New.

View File

@ -65,7 +65,7 @@
/* In hppah-nat.c: */
#define FETCH_INFERIOR_REGISTERS
#define CHILD_XFER_MEMORY
#define CHILD_POST_FOLLOW_VFORK
#define CHILD_FOLLOW_FORK
/* While this is for use by threaded programs, it doesn't appear
* to hurt non-threaded ones. This is used in infrun.c: */

View File

@ -385,6 +385,7 @@ child_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write,
}
char *saved_child_execd_pathname = NULL;
int saved_vfork_pid;
enum {
STATE_NONE,
STATE_GOT_CHILD,
@ -393,48 +394,121 @@ enum {
STATE_FAKE_EXEC
} saved_vfork_state = STATE_NONE;
void
child_post_follow_vfork (int parent_pid, int followed_parent, int child_pid,
int followed_child)
int
child_follow_fork (int follow_child)
{
/* Are we a debugger that followed the parent of a vfork? If so,
then recall that the child's vfork event was delivered to us
first. And, that the parent was suspended by the OS until the
child's exec or exit events were received.
ptid_t last_ptid;
struct target_waitstatus last_status;
int has_vforked;
int parent_pid, child_pid;
Upon receiving that child vfork, then, we were forced to remove
all breakpoints in the child and continue it so that it could
reach the exec or exit point.
get_last_target_status (&last_ptid, &last_status);
has_vforked = (last_status.kind == TARGET_WAITKIND_VFORKED);
parent_pid = ptid_get_pid (last_ptid);
child_pid = last_status.value.related_pid;
But also recall that the parent and child of a vfork share the
same address space. Thus, removing bp's in the child also
removed them from the parent.
/* At this point, if we are vforking, breakpoints were already
detached from the child in child_wait; and the child has already
called execve(). If we are forking, both the parent and child
have breakpoints inserted. */
Now that the child has safely exec'd or exited, we must restore
the parent's breakpoints before we continue it. Else, we may
cause it run past expected stopping points. */
if (followed_parent)
if (! follow_child)
{
reattach_breakpoints (parent_pid);
if (! has_vforked)
{
detach_breakpoints (child_pid);
#ifdef SOLIB_REMOVE_INFERIOR_HOOK
SOLIB_REMOVE_INFERIOR_HOOK (child_pid);
#endif
}
/* Detach from the child. */
target_require_detach (child_pid, "", 1);
/* The parent and child of a vfork share the same address space.
Also, on some targets the order in which vfork and exec events
are received for parent in child requires some delicate handling
of the events.
For instance, on ptrace-based HPUX we receive the child's vfork
event first, at which time the parent has been suspended by the
OS and is essentially untouchable until the child's exit or second
exec event arrives. At that time, the parent's vfork event is
delivered to us, and that's when we see and decide how to follow
the vfork. But to get to that point, we must continue the child
until it execs or exits. To do that smoothly, all breakpoints
must be removed from the child, in case there are any set between
the vfork() and exec() calls. But removing them from the child
also removes them from the parent, due to the shared-address-space
nature of a vfork'd parent and child. On HPUX, therefore, we must
take care to restore the bp's to the parent before we continue it.
Else, it's likely that we may not stop in the expected place. (The
worst scenario is when the user tries to step over a vfork() call;
the step-resume bp must be restored for the step to properly stop
in the parent after the call completes!)
Sequence of events, as reported to gdb from HPUX:
Parent Child Action for gdb to take
-------------------------------------------------------
1 VFORK Continue child
2 EXEC
3 EXEC or EXIT
4 VFORK
Now that the child has safely exec'd or exited, we must restore
the parent's breakpoints before we continue it. Else, we may
cause it run past expected stopping points. */
if (has_vforked)
reattach_breakpoints (parent_pid);
}
else
{
char child_pid_spelling[40];
/* Needed to keep the breakpoint lists in sync. */
if (! has_vforked)
detach_breakpoints (child_pid);
/* Before detaching from the parent, remove all breakpoints from it. */
remove_breakpoints ();
/* Also reset the solib inferior hook from the parent. */
#ifdef SOLIB_REMOVE_INFERIOR_HOOK
SOLIB_REMOVE_INFERIOR_HOOK (PIDGET (inferior_ptid));
#endif
/* Detach from the parent. */
target_detach (NULL, 1);
/* Attach to the child. */
inferior_ptid = pid_to_ptid (child_pid);
sprintf (child_pid_spelling, "%d", child_pid);
target_require_attach (child_pid_spelling, 1);
/* If we vforked, then we've also execed by now. The exec will be
reported momentarily. follow_exec () will handle breakpoints, so
we don't have to.. */
if (!has_vforked)
follow_inferior_reset_breakpoints ();
}
/* If we followed the parent, don't try to follow the child's exec. */
if (saved_vfork_state != STATE_GOT_PARENT && saved_vfork_state != STATE_FAKE_EXEC)
fprintf_unfiltered (gdb_stdout, "hppa: post follow vfork: confused state\n");
if (followed_parent || saved_vfork_state == STATE_GOT_PARENT)
saved_vfork_state = STATE_NONE;
/* Are we a debugger that followed the child of a vfork? If so,
then recall that we don't actually acquire control of the child
until after it has exec'd or exited. */
if (followed_child)
if (has_vforked)
{
/* If the child has exited, then there's nothing for us to do.
In the case of an exec event, we'll let that be handled by
the normal mechanism that notices and handles exec events, in
resume(). */
/* If we followed the parent, don't try to follow the child's exec. */
if (saved_vfork_state != STATE_GOT_PARENT
&& saved_vfork_state != STATE_FAKE_EXEC)
fprintf_unfiltered (gdb_stdout,
"hppa: post follow vfork: confused state\n");
if (! follow_child || saved_vfork_state == STATE_GOT_PARENT)
saved_vfork_state = STATE_NONE;
else
return 1;
}
return 0;
}
/* Format a process id, given PID. Be sure to terminate
@ -592,13 +666,26 @@ child_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
if (saved_vfork_state == STATE_GOT_CHILD)
{
child_post_startup_inferior (pid_to_ptid (pid));
ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
detach_breakpoints (pid);
#ifdef SOLIB_REMOVE_INFERIOR_HOOK
SOLIB_REMOVE_INFERIOR_HOOK (pid);
#endif
child_resume (pid_to_ptid (pid), 0, TARGET_SIGNAL_0);
ourstatus->kind = TARGET_WAITKIND_IGNORE;
return pid_to_ptid (related_pid);
}
else if (saved_vfork_state == STATE_FAKE_EXEC)
{
ourstatus->kind = TARGET_WAITKIND_VFORKED;
ourstatus->value.related_pid = related_pid;
return pid_to_ptid (pid);
}
else
{
ourstatus->kind = TARGET_WAITKIND_VFORKED;
ourstatus->value.related_pid = related_pid;
/* We saw the parent's vfork, but we haven't seen the exec yet.
Wait for it, for simplicity's sake. It should be pending. */
saved_vfork_pid = related_pid;
ourstatus->kind = TARGET_WAITKIND_IGNORE;
return pid_to_ptid (pid);
}
}
@ -608,27 +695,32 @@ child_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
/* On HP-UX, events associated with a vforking inferior come in
threes: a vfork event for the child (always first), followed
a vfork event for the parent and an exec event for the child.
The latter two can come in either order.
If we get the parent vfork event first, life's good: We follow
either the parent or child, and then the child's exec event is
a "don't care".
But if we get the child's exec event first, then we delay
responding to it until we handle the parent's vfork. Because,
otherwise we can't satisfy a "catch vfork". */
if (saved_vfork_state == STATE_GOT_CHILD)
The latter two can come in either order. Make sure we get
both. */
if (saved_vfork_state != STATE_NONE)
{
if (saved_vfork_state == STATE_GOT_CHILD)
{
saved_vfork_state = STATE_GOT_EXEC;
/* On HP/UX with ptrace, the child must be resumed before
the parent vfork event is delivered. A single-step
suffices. */
if (RESUME_EXECD_VFORKING_CHILD_TO_GET_PARENT_VFORK ())
target_resume (pid_to_ptid (pid), 1, TARGET_SIGNAL_0);
ourstatus->kind = TARGET_WAITKIND_IGNORE;
}
else if (saved_vfork_state == STATE_GOT_PARENT)
{
saved_vfork_state = STATE_FAKE_EXEC;
ourstatus->kind = TARGET_WAITKIND_VFORKED;
ourstatus->value.related_pid = saved_vfork_pid;
}
else
fprintf_unfiltered (gdb_stdout,
"hppa: exec: unexpected state\n");
saved_child_execd_pathname = execd_pathname;
saved_vfork_state = STATE_GOT_EXEC;
/* On HP/UX with ptrace, the child must be resumed before
the parent vfork event is delivered. A single-step
suffices. */
if (RESUME_EXECD_VFORKING_CHILD_TO_GET_PARENT_VFORK ())
target_resume (pid_to_ptid (pid), 1, TARGET_SIGNAL_0);
ourstatus->kind = TARGET_WAITKIND_IGNORE;
return inferior_ptid;
}

View File

@ -304,6 +304,8 @@ extern int signal_pass_update (int, int);
extern void get_last_target_status(ptid_t *ptid,
struct target_waitstatus *status);
extern void follow_inferior_reset_breakpoints (void);
/* From infcmd.c */
extern void tty_command (char *, int);

View File

@ -66,12 +66,7 @@ static int restore_selected_frame (void *);
static void build_infrun (void);
static void follow_inferior_fork (int parent_pid, int child_pid,
int has_forked, int has_vforked);
static void follow_fork (int parent_pid, int child_pid);
static void follow_vfork (int parent_pid, int child_pid);
static int follow_fork ();
static void set_schedlock_func (char *args, int from_tty,
struct cmd_list_element *c);
@ -384,15 +379,11 @@ static const char *follow_fork_mode_kind_names[] = {
static const char *follow_fork_mode_string = follow_fork_mode_parent;
static void
follow_inferior_fork (int parent_pid, int child_pid, int has_forked,
int has_vforked)
static int
follow_fork ()
{
int followed_parent = 0;
int followed_child = 0;
/* Which process did the user want us to follow? */
const char *follow_mode = follow_fork_mode_string;
int follow_child = (follow_mode == follow_fork_mode_child);
/* Or, did the user not know, and want us to ask? */
if (follow_fork_mode_string == follow_fork_mode_ask)
@ -402,138 +393,36 @@ follow_inferior_fork (int parent_pid, int child_pid, int has_forked,
/* follow_mode = follow_fork_mode_...; */
}
/* If we're to be following the parent, then detach from child_pid.
We're already following the parent, so need do nothing explicit
for it. */
if (follow_mode == follow_fork_mode_parent)
{
followed_parent = 1;
/* We're already attached to the parent, by default. */
/* Before detaching from the child, remove all breakpoints from
it. (This won't actually modify the breakpoint list, but will
physically remove the breakpoints from the child.) */
detach_breakpoints (child_pid);
#ifdef SOLIB_REMOVE_INFERIOR_HOOK
SOLIB_REMOVE_INFERIOR_HOOK (child_pid);
#endif
/* Detach from the child. */
dont_repeat ();
target_require_detach (child_pid, "", 1);
}
/* If we're to be following the child, then attach to it, detach
from inferior_ptid, and set inferior_ptid to child_pid. */
else if (follow_mode == follow_fork_mode_child)
{
char child_pid_spelling[100]; /* Arbitrary length. */
followed_child = 1;
/* Before detaching from the parent, detach all breakpoints from
the child. Note that this only works if we're following vforks
right away; if we've exec'd then the breakpoints are already detached
and the shadow contents are out of date. */
detach_breakpoints (child_pid);
/* Before detaching from the parent, remove all breakpoints from it. */
remove_breakpoints ();
/* Also reset the solib inferior hook from the parent. */
#ifdef SOLIB_REMOVE_INFERIOR_HOOK
SOLIB_REMOVE_INFERIOR_HOOK (PIDGET (inferior_ptid));
#endif
/* Detach from the parent. */
dont_repeat ();
target_detach (NULL, 1);
/* Attach to the child. */
inferior_ptid = pid_to_ptid (child_pid);
sprintf (child_pid_spelling, "%d", child_pid);
dont_repeat ();
target_require_attach (child_pid_spelling, 1);
/* Was there a step_resume breakpoint? (There was if the user
did a "next" at the fork() call.) If so, explicitly reset its
thread number.
step_resumes are a form of bp that are made to be per-thread.
Since we created the step_resume bp when the parent process
was being debugged, and now are switching to the child process,
from the breakpoint package's viewpoint, that's a switch of
"threads". We must update the bp's notion of which thread
it is for, or it'll be ignored when it triggers... */
/* As above, if we're following vforks at exec time then resetting the
step resume breakpoint is probably wrong. */
if (step_resume_breakpoint)
breakpoint_re_set_thread (step_resume_breakpoint);
/* Reinsert all breakpoints in the child. (The user may've set
breakpoints after catching the fork, in which case those
actually didn't get set in the child, but only in the parent.) */
breakpoint_re_set ();
insert_breakpoints ();
}
/* The parent and child of a vfork share the same address space.
Also, on some targets the order in which vfork and exec events
are received for parent in child requires some delicate handling
of the events.
For instance, on ptrace-based HPUX we receive the child's vfork
event first, at which time the parent has been suspended by the
OS and is essentially untouchable until the child's exit or second
exec event arrives. At that time, the parent's vfork event is
delivered to us, and that's when we see and decide how to follow
the vfork. But to get to that point, we must continue the child
until it execs or exits. To do that smoothly, all breakpoints
must be removed from the child, in case there are any set between
the vfork() and exec() calls. But removing them from the child
also removes them from the parent, due to the shared-address-space
nature of a vfork'd parent and child. On HPUX, therefore, we must
take care to restore the bp's to the parent before we continue it.
Else, it's likely that we may not stop in the expected place. (The
worst scenario is when the user tries to step over a vfork() call;
the step-resume bp must be restored for the step to properly stop
in the parent after the call completes!)
Sequence of events, as reported to gdb from HPUX:
Parent Child Action for gdb to take
-------------------------------------------------------
1 VFORK Continue child
2 EXEC
3 EXEC or EXIT
4 VFORK */
if (has_vforked)
{
target_post_follow_vfork (parent_pid,
followed_parent, child_pid, followed_child);
}
pending_follow.fork_event.saw_parent_fork = 0;
pending_follow.fork_event.saw_child_fork = 0;
return target_follow_fork (follow_child);
}
static void
follow_fork (int parent_pid, int child_pid)
void
follow_inferior_reset_breakpoints (void)
{
follow_inferior_fork (parent_pid, child_pid, 1, 0);
}
/* Was there a step_resume breakpoint? (There was if the user
did a "next" at the fork() call.) If so, explicitly reset its
thread number.
step_resumes are a form of bp that are made to be per-thread.
Since we created the step_resume bp when the parent process
was being debugged, and now are switching to the child process,
from the breakpoint package's viewpoint, that's a switch of
"threads". We must update the bp's notion of which thread
it is for, or it'll be ignored when it triggers. */
/* Forward declaration. */
static void follow_exec (int, char *);
if (step_resume_breakpoint)
breakpoint_re_set_thread (step_resume_breakpoint);
static void
follow_vfork (int parent_pid, int child_pid)
{
follow_inferior_fork (parent_pid, child_pid, 0, 1);
/* Reinsert all breakpoints in the child. The user may have set
breakpoints after catching the fork, in which case those
were never set in the child, but only in the parent. This makes
sure the inserted breakpoints match the breakpoint list. */
breakpoint_re_set ();
insert_breakpoints ();
}
/* EXECD_PATHNAME is assumed to be non-NULL. */
@ -722,38 +611,19 @@ resume (int step, enum target_signal sig)
#endif
/* If there were any forks/vforks/execs that were caught and are
now to be followed, then do so. */
now to be followed, then do so. */
switch (pending_follow.kind)
{
case (TARGET_WAITKIND_FORKED):
case TARGET_WAITKIND_FORKED:
case TARGET_WAITKIND_VFORKED:
pending_follow.kind = TARGET_WAITKIND_SPURIOUS;
follow_fork (PIDGET (inferior_ptid),
pending_follow.fork_event.child_pid);
if (follow_fork ())
should_resume = 0;
break;
case (TARGET_WAITKIND_VFORKED):
{
int saw_child_exec = pending_follow.fork_event.saw_child_exec;
pending_follow.kind = TARGET_WAITKIND_SPURIOUS;
follow_vfork (PIDGET (inferior_ptid),
pending_follow.fork_event.child_pid);
/* Did we follow the child, but not yet see the child's exec event?
If so, then it actually ought to be waiting for us; we respond to
parent vfork events. We don't actually want to resume the child
in this situation; we want to just get its exec event. */
if (!saw_child_exec &&
(PIDGET (inferior_ptid) == pending_follow.fork_event.child_pid))
should_resume = 0;
}
break;
case (TARGET_WAITKIND_EXECD):
/* If we saw a vfork event but couldn't follow it until we saw
an exec, then now might be the time! */
pending_follow.kind = TARGET_WAITKIND_SPURIOUS;
case TARGET_WAITKIND_EXECD:
/* follow_exec is called as soon as the exec event is seen. */
pending_follow.kind = TARGET_WAITKIND_SPURIOUS;
break;
default:

View File

@ -469,14 +469,12 @@ child_remove_vfork_catchpoint (int pid)
}
#endif
#if !defined(CHILD_POST_FOLLOW_VFORK)
void
child_post_follow_vfork (int parent_pid, int followed_parent, int child_pid,
int followed_child)
#if !defined(CHILD_FOLLOW_FORK)
int
child_follow_fork (int follow_child)
{
/* This version of Unix doesn't require a meaningful "post follow vfork"
operation by a clone debugger.
*/
/* This version of Unix doesn't support following fork or vfork events. */
return 0;
}
#endif
@ -645,7 +643,7 @@ init_child_ops (void)
child_ops.to_remove_fork_catchpoint = child_remove_fork_catchpoint;
child_ops.to_insert_vfork_catchpoint = child_insert_vfork_catchpoint;
child_ops.to_remove_vfork_catchpoint = child_remove_vfork_catchpoint;
child_ops.to_post_follow_vfork = child_post_follow_vfork;
child_ops.to_follow_fork = child_follow_fork;
child_ops.to_insert_exec_catchpoint = child_insert_exec_catchpoint;
child_ops.to_remove_exec_catchpoint = child_remove_exec_catchpoint;
child_ops.to_reported_exec_events_per_exec_call = child_reported_exec_events_per_exec_call;

View File

@ -473,8 +473,8 @@ cleanup_target (struct target_ops *t)
de_fault (to_remove_vfork_catchpoint,
(int (*) (int))
tcomplain);
de_fault (to_post_follow_vfork,
(void (*) (int, int, int, int))
de_fault (to_follow_fork,
(int (*) (int))
target_ignore);
de_fault (to_insert_exec_catchpoint,
(int (*) (int))
@ -597,7 +597,7 @@ update_current_target (void)
INHERIT (to_remove_fork_catchpoint, t);
INHERIT (to_insert_vfork_catchpoint, t);
INHERIT (to_remove_vfork_catchpoint, t);
INHERIT (to_post_follow_vfork, t);
INHERIT (to_follow_fork, t);
INHERIT (to_insert_exec_catchpoint, t);
INHERIT (to_remove_exec_catchpoint, t);
INHERIT (to_reported_exec_events_per_exec_call, t);
@ -2064,15 +2064,15 @@ debug_to_remove_vfork_catchpoint (int pid)
return retval;
}
static void
debug_to_post_follow_vfork (int parent_pid, int followed_parent, int child_pid,
int followed_child)
static int
debug_to_follow_fork (int follow_child)
{
debug_target.to_post_follow_vfork (parent_pid, followed_parent, child_pid, followed_child);
int retval = debug_target.to_follow_fork (follow_child);
fprintf_unfiltered (gdb_stdlog,
"target_post_follow_vfork (%d, %d, %d, %d)\n",
parent_pid, followed_parent, child_pid, followed_child);
fprintf_unfiltered (gdb_stdlog, "target_follow_fork (%d) = %d\n",
follow_child, retval);
return retval;
}
static int
@ -2285,7 +2285,7 @@ setup_target_debug (void)
current_target.to_remove_fork_catchpoint = debug_to_remove_fork_catchpoint;
current_target.to_insert_vfork_catchpoint = debug_to_insert_vfork_catchpoint;
current_target.to_remove_vfork_catchpoint = debug_to_remove_vfork_catchpoint;
current_target.to_post_follow_vfork = debug_to_post_follow_vfork;
current_target.to_follow_fork = debug_to_follow_fork;
current_target.to_insert_exec_catchpoint = debug_to_insert_exec_catchpoint;
current_target.to_remove_exec_catchpoint = debug_to_remove_exec_catchpoint;
current_target.to_reported_exec_events_per_exec_call = debug_to_reported_exec_events_per_exec_call;

View File

@ -276,7 +276,7 @@ struct target_ops
int (*to_remove_fork_catchpoint) (int);
int (*to_insert_vfork_catchpoint) (int);
int (*to_remove_vfork_catchpoint) (int);
void (*to_post_follow_vfork) (int, int, int, int);
int (*to_follow_fork) (int);
int (*to_insert_exec_catchpoint) (int);
int (*to_remove_exec_catchpoint) (int);
int (*to_reported_exec_events_per_exec_call) (void);
@ -548,7 +548,7 @@ extern int child_remove_vfork_catchpoint (int);
extern void child_acknowledge_created_inferior (int);
extern void child_post_follow_vfork (int, int, int, int);
extern int child_follow_fork (int);
extern int child_insert_exec_catchpoint (int);
@ -705,16 +705,16 @@ extern void target_load (char *arg, int from_tty);
#define target_remove_vfork_catchpoint(pid) \
(*current_target.to_remove_vfork_catchpoint) (pid)
/* An inferior process has been created via a vfork() system call.
The debugger has followed the parent, the child, or both. The
process of setting up for that follow may have required some
target-specific trickery to track the sequence of reported events.
If so, this function should be defined by those targets that
require the debugger to perform cleanup or initialization after
the vfork follow. */
/* If the inferior forks or vforks, this function will be called at
the next resume in order to perform any bookkeeping and fiddling
necessary to continue debugging either the parent or child, as
requested, and releasing the other. Information about the fork
or vfork event is available via get_last_target_status ().
This function returns 1 if the inferior should not be resumed
(i.e. there is another event pending). */
#define target_post_follow_vfork(parent_pid,followed_parent,child_pid,followed_child) \
(*current_target.to_post_follow_vfork) (parent_pid,followed_parent,child_pid,followed_child)
#define target_follow_fork(follow_child) \
(*current_target.to_follow_fork) (follow_child)
/* On some targets, we can catch an inferior exec event when it
occurs. These functions insert/remove an already-created

View File

@ -1,3 +1,7 @@
2002-12-10 Daniel Jacobowitz <drow@mvista.com>
* gdb.base/foll-vfork.exp: Re-enable test on HP/UX.
2002-12-06 David Carlton <carlton@math.stanford.edu>
* gdb.base/store.c: Don't declare functions static.

View File

@ -28,10 +28,13 @@ if { ![isnative] } then {
set prms_id 0
set bug_id 0
if [istarget "hppa2.0w-hp-hpux*"] {
warning "Don't run gdb.base/foll-vfork.exp until JAGaa43495 kernel problem is fixed."
return 0
}
# NOTE drow/2002-12-06: I don't know what the referenced kernel problem
# is, but it appears to be fixed in recent HP/UX versions.
##if [istarget "hppa2.0w-hp-hpux*"] {
## warning "Don't run gdb.base/foll-vfork.exp until JAGaa43495 kernel problem is fixed."
## return 0
##}
set testfile "foll-vfork"
set testfile2 "vforked-prog"