mirror of
https://github.com/darlinghq/darling-gdb.git
synced 2024-11-24 12:39:59 +00:00
* hppah-nat.c (saved_child_execd_pathname, saved_vfork_state): New.
(child_post_follow_vfork): Cancel pending exec event if we follow the parent. (child_wait): Only return TARGET_WAITKIND_VFORKED when all necessary events have been processed. Return a fake TARGET_WAITKIND_EXECD event at the following wait call if necessary. * infrun.c (follow_vfork): Don't follow_exec here. (handle_inferior_event): Add comment to TARGET_WAITKIND_EXECD case about HP/UX 10.20. Remove code pushed down to hppah-nat.c:child_wait. * infttrace.c (child_resume): Use TT_PROC_CONTINUE if vfork_in_flight is set.
This commit is contained in:
parent
8e7d2c1695
commit
7d2830a309
@ -1,4 +1,19 @@
|
||||
2002-12-06 Daniel Jacobowitz <drow@mvista.com>
|
||||
2002-12-10 Daniel Jacobowitz <drow@mvista.com>
|
||||
|
||||
* hppah-nat.c (saved_child_execd_pathname, saved_vfork_state): New.
|
||||
(child_post_follow_vfork): Cancel pending exec event if we follow
|
||||
the parent.
|
||||
(child_wait): Only return TARGET_WAITKIND_VFORKED when all necessary
|
||||
events have been processed. Return a fake TARGET_WAITKIND_EXECD
|
||||
event at the following wait call if necessary.
|
||||
* infrun.c (follow_vfork): Don't follow_exec here.
|
||||
(handle_inferior_event): Add comment to TARGET_WAITKIND_EXECD
|
||||
case about HP/UX 10.20. Remove code pushed down to
|
||||
hppah-nat.c:child_wait.
|
||||
* infttrace.c (child_resume): Use TT_PROC_CONTINUE if
|
||||
vfork_in_flight is set.
|
||||
|
||||
2002-12-10 Daniel Jacobowitz <drow@mvista.com>
|
||||
|
||||
* hppah-nat.c (child_wait): Return TARGET_WAITKIND_IGNORE
|
||||
for the parent's fork event.
|
||||
|
@ -384,6 +384,14 @@ child_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write,
|
||||
return len;
|
||||
}
|
||||
|
||||
char *saved_child_execd_pathname = NULL;
|
||||
enum {
|
||||
STATE_NONE,
|
||||
STATE_GOT_CHILD,
|
||||
STATE_GOT_EXEC,
|
||||
STATE_GOT_PARENT,
|
||||
STATE_FAKE_EXEC
|
||||
} saved_vfork_state = STATE_NONE;
|
||||
|
||||
void
|
||||
child_post_follow_vfork (int parent_pid, int followed_parent, int child_pid,
|
||||
@ -410,6 +418,13 @@ child_post_follow_vfork (int parent_pid, int followed_parent, int child_pid,
|
||||
reattach_breakpoints (parent_pid);
|
||||
}
|
||||
|
||||
/* 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. */
|
||||
@ -466,7 +481,6 @@ hppa_tid_to_str (ptid_t ptid)
|
||||
int not_same_real_pid = 1;
|
||||
/*## */
|
||||
|
||||
|
||||
/* Wait for child to do something. Return pid of child, or -1 in case
|
||||
of error; store status through argument pointer OURSTATUS. */
|
||||
|
||||
@ -482,6 +496,14 @@ child_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
|
||||
enum target_waitkind kind;
|
||||
int pid;
|
||||
|
||||
if (saved_vfork_state == STATE_FAKE_EXEC)
|
||||
{
|
||||
saved_vfork_state = STATE_NONE;
|
||||
ourstatus->kind = TARGET_WAITKIND_EXECD;
|
||||
ourstatus->value.execd_pathname = saved_child_execd_pathname;
|
||||
return inferior_ptid;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
set_sigint_trap (); /* Causes SIGINT to be passed on to the
|
||||
@ -543,17 +565,73 @@ child_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
|
||||
}
|
||||
}
|
||||
|
||||
if (hpux_has_vforked (pid, &related_pid)
|
||||
&& ((pid == PIDGET (inferior_ptid))
|
||||
|| (related_pid == PIDGET (inferior_ptid))))
|
||||
if (hpux_has_vforked (pid, &related_pid))
|
||||
{
|
||||
ourstatus->kind = TARGET_WAITKIND_VFORKED;
|
||||
ourstatus->value.related_pid = related_pid;
|
||||
return pid_to_ptid (pid);
|
||||
if (pid == PIDGET (inferior_ptid))
|
||||
{
|
||||
if (saved_vfork_state == STATE_GOT_CHILD)
|
||||
saved_vfork_state = STATE_GOT_PARENT;
|
||||
else if (saved_vfork_state == STATE_GOT_EXEC)
|
||||
saved_vfork_state = STATE_FAKE_EXEC;
|
||||
else
|
||||
fprintf_unfiltered (gdb_stdout,
|
||||
"hppah: parent vfork: confused\n");
|
||||
}
|
||||
else if (related_pid == PIDGET (inferior_ptid))
|
||||
{
|
||||
if (saved_vfork_state == STATE_NONE)
|
||||
saved_vfork_state = STATE_GOT_CHILD;
|
||||
else
|
||||
fprintf_unfiltered (gdb_stdout,
|
||||
"hppah: child vfork: confused\n");
|
||||
}
|
||||
else
|
||||
fprintf_unfiltered (gdb_stdout,
|
||||
"hppah: unknown vfork: confused\n");
|
||||
|
||||
if (saved_vfork_state == STATE_GOT_CHILD)
|
||||
{
|
||||
child_post_startup_inferior (pid_to_ptid (pid));
|
||||
ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
|
||||
return pid_to_ptid (pid);
|
||||
}
|
||||
else
|
||||
{
|
||||
ourstatus->kind = TARGET_WAITKIND_VFORKED;
|
||||
ourstatus->value.related_pid = related_pid;
|
||||
return pid_to_ptid (pid);
|
||||
}
|
||||
}
|
||||
|
||||
if (hpux_has_execd (pid, &execd_pathname))
|
||||
{
|
||||
/* 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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
/* Are we ignoring initial exec events? (This is likely because
|
||||
we're in the process of starting up the inferior, and another
|
||||
(older) mechanism handles those.) If so, we'll report this
|
||||
|
43
gdb/infrun.c
43
gdb/infrun.c
@ -534,16 +534,6 @@ static void
|
||||
follow_vfork (int parent_pid, int child_pid)
|
||||
{
|
||||
follow_inferior_fork (parent_pid, child_pid, 0, 1);
|
||||
|
||||
/* Did we follow the child? Had it exec'd before we saw the parent vfork? */
|
||||
if (pending_follow.fork_event.saw_child_exec
|
||||
&& (PIDGET (inferior_ptid) == child_pid))
|
||||
{
|
||||
pending_follow.fork_event.saw_child_exec = 0;
|
||||
pending_follow.kind = TARGET_WAITKIND_SPURIOUS;
|
||||
follow_exec (PIDGET (inferior_ptid), pending_follow.execd_pathname);
|
||||
xfree (pending_follow.execd_pathname);
|
||||
}
|
||||
}
|
||||
|
||||
/* EXECD_PATHNAME is assumed to be non-NULL. */
|
||||
@ -1555,6 +1545,9 @@ handle_inferior_event (struct execution_control_state *ecs)
|
||||
case TARGET_WAITKIND_EXECD:
|
||||
stop_signal = TARGET_SIGNAL_TRAP;
|
||||
|
||||
/* NOTE drow/2002-12-05: This code should be pushed down into the
|
||||
target_wait function. Until then following vfork on HP/UX 10.20
|
||||
is probably broken by this. Of course, it's broken anyway. */
|
||||
/* Is this a target which reports multiple exec events per actual
|
||||
call to exec()? (HP-UX using ptrace does, for example.) If so,
|
||||
ignore all but the last one. Just resume the exec'r, and wait
|
||||
@ -1576,36 +1569,6 @@ handle_inferior_event (struct execution_control_state *ecs)
|
||||
savestring (ecs->ws.value.execd_pathname,
|
||||
strlen (ecs->ws.value.execd_pathname));
|
||||
|
||||
/* Did inferior_ptid exec, or did a (possibly not-yet-followed)
|
||||
child of a vfork exec?
|
||||
|
||||
??rehrauer: This is unabashedly an HP-UX specific thing. 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 (pending_follow.kind == TARGET_WAITKIND_VFORKED)
|
||||
{
|
||||
pending_follow.fork_event.saw_child_exec = 1;
|
||||
|
||||
/* On some targets, 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 (ecs->ptid, 1, TARGET_SIGNAL_0);
|
||||
/* We expect the parent vfork event to be available now. */
|
||||
prepare_to_wait (ecs);
|
||||
return;
|
||||
}
|
||||
|
||||
/* This causes the eventpoints and symbol table to be reset. Must
|
||||
do this now, before trying to determine whether to stop. */
|
||||
follow_exec (PIDGET (inferior_ptid), pending_follow.execd_pathname);
|
||||
|
@ -4523,7 +4523,15 @@ child_resume (ptid_t ptid, int step, enum target_signal signal)
|
||||
pending signal will be passed to the inferior. interrupt.exp
|
||||
in the testsuite does this precise thing and fails due to the
|
||||
unwanted signal delivery to the inferior. */
|
||||
if (resume_all_threads)
|
||||
/* drow/2002-12-05: However, note that we must use TT_PROC_CONTINUE
|
||||
if we are tracing a vfork. */
|
||||
if (vfork_in_flight)
|
||||
{
|
||||
call_ttrace (TT_PROC_CONTINUE, tid, TT_NIL, TT_NIL, TT_NIL);
|
||||
clear_all_handled ();
|
||||
clear_all_stepping_mode ();
|
||||
}
|
||||
else if (resume_all_threads)
|
||||
{
|
||||
#ifdef THREAD_DEBUG
|
||||
if (debug_on)
|
||||
|
Loading…
Reference in New Issue
Block a user