aboutsummaryrefslogtreecommitdiff
path: root/gdb/infrun.c
diff options
context:
space:
mode:
authorDavid Carlton <carlton@bactrian.org>2002-12-23 19:39:59 +0000
committerDavid Carlton <carlton@bactrian.org>2002-12-23 19:39:59 +0000
commita255c93707c1325ab30ea467c92a3c08c51fc1eb (patch)
tree95ec6f713582b2e627409dbe77b6d52dd4e58147 /gdb/infrun.c
parentd268a3f5e55a74606bbb15efd9418d9ca0055bc0 (diff)
downloadgdb-a255c93707c1325ab30ea467c92a3c08c51fc1eb.zip
gdb-a255c93707c1325ab30ea467c92a3c08c51fc1eb.tar.gz
gdb-a255c93707c1325ab30ea467c92a3c08c51fc1eb.tar.bz2
2002-12-23 David Carlton <carlton@math.stanford.edu>
* Merge from mainline; tag is carlton_dictionary-20021223-merge.
Diffstat (limited to 'gdb/infrun.c')
-rw-r--r--gdb/infrun.c703
1 files changed, 191 insertions, 512 deletions
diff --git a/gdb/infrun.c b/gdb/infrun.c
index 88c59c5..aa404cf 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -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);
@@ -360,43 +355,19 @@ static struct
struct
{
int parent_pid;
- int saw_parent_fork;
int child_pid;
- int saw_child_fork;
- int saw_child_exec;
}
fork_event;
char *execd_pathname;
}
pending_follow;
-/* Some platforms don't allow us to do anything meaningful with a
- vforked child until it has exec'd. Vforked processes on such
- platforms can only be followed after they've exec'd.
-
- When this is set to 0, a vfork can be immediately followed,
- and an exec can be followed merely as an exec. When this is
- set to 1, a vfork event has been seen, but cannot be followed
- until the exec is seen.
-
- (In the latter case, inferior_ptid is still the parent of the
- vfork, and pending_follow.fork_event.child_pid is the child. The
- appropriate process is followed, according to the setting of
- follow-fork-mode.) */
-static int follow_vfork_when_exec;
-
static const char follow_fork_mode_ask[] = "ask";
-static const char follow_fork_mode_both[] = "both";
static const char follow_fork_mode_child[] = "child";
static const char follow_fork_mode_parent[] = "parent";
static const char *follow_fork_mode_kind_names[] = {
follow_fork_mode_ask,
- /* ??rehrauer: The "both" option is broken, by what may be a 10.20
- kernel problem. It's also not terribly useful without a GUI to
- help the user drive two debuggers. So for now, I'm disabling the
- "both" option. */
- /* follow_fork_mode_both, */
follow_fork_mode_child,
follow_fork_mode_parent,
NULL
@@ -405,15 +376,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)
@@ -423,175 +390,33 @@ 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.) */
- if (!has_vforked || !follow_vfork_when_exec)
- {
- 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. But only if we're forking, or if we follow vforks
- as soon as they happen. (If we're following vforks only when
- the child has exec'd, then it's very wrong to try to write
- back the "shadow contents" of inserted breakpoints now -- they
- belong to the child's pre-exec'd a.out.) */
- if (!has_vforked || !follow_vfork_when_exec)
- {
- 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... */
- if (step_resume_breakpoint && (!has_vforked || !follow_vfork_when_exec))
- 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.) */
- if (!has_vforked || !follow_vfork_when_exec)
- {
- breakpoint_re_set ();
- insert_breakpoints ();
- }
- }
-
- /* If we're to be following both parent and child, then fork ourselves,
- and attach the debugger clone to the child. */
- else if (follow_mode == follow_fork_mode_both)
- {
- char pid_suffix[100]; /* Arbitrary length. */
-
- /* Clone ourselves to follow the child. This is the end of our
- involvement with child_pid; our clone will take it from here... */
- dont_repeat ();
- target_clone_and_follow_inferior (child_pid, &followed_child);
- followed_parent = !followed_child;
-
- /* We continue to follow the parent. To help distinguish the two
- debuggers, though, both we and our clone will reset our prompts. */
- sprintf (pid_suffix, "[%d] ", PIDGET (inferior_ptid));
- set_prompt (strcat (get_prompt (), pid_suffix));
- }
-
- /* 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. */
- /* 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);
- }
+ breakpoint_re_set ();
+ insert_breakpoints ();
}
/* EXECD_PATHNAME is assumed to be non-NULL. */
@@ -605,23 +430,6 @@ follow_exec (int pid, char *execd_pathname)
if (!may_follow_exec)
return;
- /* Did this exec() follow a vfork()? If so, we must follow the
- vfork now too. Do it before following the exec. */
- if (follow_vfork_when_exec &&
- (pending_follow.kind == TARGET_WAITKIND_VFORKED))
- {
- pending_follow.kind = TARGET_WAITKIND_SPURIOUS;
- follow_vfork (PIDGET (inferior_ptid),
- pending_follow.fork_event.child_pid);
- follow_vfork_when_exec = 0;
- saved_pid = PIDGET (inferior_ptid);
-
- /* Did we follow the parent? If so, we're done. If we followed
- the child then we must also follow its exec(). */
- if (PIDGET (inferior_ptid) == pending_follow.fork_event.parent_pid)
- return;
- }
-
/* 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
momentary bp's, etc.
@@ -797,38 +605,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:
@@ -887,7 +676,7 @@ clear_proceed_status (void)
trap_expected = 0;
step_range_start = 0;
step_range_end = 0;
- step_frame_address = 0;
+ step_frame_id = null_frame_id;
step_over_calls = STEP_OVER_UNDEBUGGABLE;
stop_after_trap = 0;
stop_soon_quietly = 0;
@@ -1075,9 +864,6 @@ init_wait_for_inferior (void)
/* The first resume is not following a fork/vfork/exec. */
pending_follow.kind = TARGET_WAITKIND_SPURIOUS; /* I.e., none. */
- pending_follow.fork_event.saw_parent_fork = 0;
- pending_follow.fork_event.saw_child_fork = 0;
- pending_follow.fork_event.saw_child_exec = 0;
/* See wait_for_inferior's handling of SYSCALL_ENTRY/RETURN events. */
number_of_threads_in_syscalls = 0;
@@ -1356,7 +1142,7 @@ context_switch (struct execution_control_state *ecs)
prev_func_start, prev_func_name,
trap_expected, step_resume_breakpoint,
through_sigtramp_breakpoint, step_range_start,
- step_range_end, step_frame_address,
+ step_range_end, &step_frame_id,
ecs->handling_longjmp, ecs->another_trap,
ecs->stepping_through_solib_after_catch,
ecs->stepping_through_solib_catchpoints,
@@ -1368,7 +1154,7 @@ context_switch (struct execution_control_state *ecs)
&prev_func_start, &prev_func_name,
&trap_expected, &step_resume_breakpoint,
&through_sigtramp_breakpoint, &step_range_start,
- &step_range_end, &step_frame_address,
+ &step_range_end, &step_frame_id,
&ecs->handling_longjmp, &ecs->another_trap,
&ecs->stepping_through_solib_after_catch,
&ecs->stepping_through_solib_catchpoints,
@@ -1540,108 +1326,40 @@ handle_inferior_event (struct execution_control_state *ecs)
/* The following are the only cases in which we keep going;
the above cases end in a continue or goto. */
case TARGET_WAITKIND_FORKED:
+ case TARGET_WAITKIND_VFORKED:
stop_signal = TARGET_SIGNAL_TRAP;
pending_follow.kind = ecs->ws.kind;
- /* Ignore fork events reported for the parent; we're only
- interested in reacting to forks of the child. Note that
- we expect the child's fork event to be available if we
- waited for it now. */
- if (ptid_equal (inferior_ptid, ecs->ptid))
- {
- pending_follow.fork_event.saw_parent_fork = 1;
- pending_follow.fork_event.parent_pid = PIDGET (ecs->ptid);
- pending_follow.fork_event.child_pid = ecs->ws.value.related_pid;
- prepare_to_wait (ecs);
- return;
- }
- else
- {
- pending_follow.fork_event.saw_child_fork = 1;
- pending_follow.fork_event.child_pid = PIDGET (ecs->ptid);
- pending_follow.fork_event.parent_pid = ecs->ws.value.related_pid;
- }
+ pending_follow.fork_event.parent_pid = PIDGET (ecs->ptid);
+ pending_follow.fork_event.child_pid = ecs->ws.value.related_pid;
- stop_pc = read_pc_pid (ecs->ptid);
- ecs->saved_inferior_ptid = inferior_ptid;
- inferior_ptid = ecs->ptid;
- /* The second argument of bpstat_stop_status is meant to help
- distinguish between a breakpoint trap and a singlestep trap.
- This is only important on targets where DECR_PC_AFTER_BREAK
- is non-zero. The prev_pc test is meant to distinguish between
- singlestepping a trap instruction, and singlestepping thru a
- jump to the instruction following a trap instruction. */
-
- stop_bpstat = bpstat_stop_status (&stop_pc,
- currently_stepping (ecs) &&
- prev_pc !=
- stop_pc - DECR_PC_AFTER_BREAK);
- ecs->random_signal = !bpstat_explains_signal (stop_bpstat);
- inferior_ptid = ecs->saved_inferior_ptid;
- goto process_event_stop_test;
+ stop_pc = read_pc ();
- /* If this a platform which doesn't allow a debugger to touch a
- vfork'd inferior until after it exec's, then we'd best keep
- our fingers entirely off the inferior, other than continuing
- it. This has the unfortunate side-effect that catchpoints
- of vforks will be ignored. But since the platform doesn't
- allow the inferior be touched at vfork time, there's really
- little choice. */
- case TARGET_WAITKIND_VFORKED:
- stop_signal = TARGET_SIGNAL_TRAP;
- pending_follow.kind = ecs->ws.kind;
+ /* Assume that catchpoints are not really software breakpoints. If
+ some future target implements them using software breakpoints then
+ that target is responsible for fudging DECR_PC_AFTER_BREAK. Thus
+ we pass 1 for the NOT_A_SW_BREAKPOINT argument, so that
+ bpstat_stop_status will not decrement the PC. */
- /* Is this a vfork of the parent? If so, then give any
- vfork catchpoints a chance to trigger now. (It's
- dangerous to do so if the child canot be touched until
- it execs, and the child has not yet exec'd. We probably
- should warn the user to that effect when the catchpoint
- triggers...) */
- if (ptid_equal (ecs->ptid, inferior_ptid))
- {
- pending_follow.fork_event.saw_parent_fork = 1;
- pending_follow.fork_event.parent_pid = PIDGET (ecs->ptid);
- pending_follow.fork_event.child_pid = ecs->ws.value.related_pid;
- }
+ stop_bpstat = bpstat_stop_status (&stop_pc, 1);
- /* If we've seen the child's vfork event but cannot really touch
- the child until it execs, then we must continue the child now.
- Else, give any vfork catchpoints a chance to trigger now. */
- else
+ ecs->random_signal = !bpstat_explains_signal (stop_bpstat);
+
+ /* If no catchpoint triggered for this, then keep going. */
+ if (ecs->random_signal)
{
- pending_follow.fork_event.saw_child_fork = 1;
- pending_follow.fork_event.child_pid = PIDGET (ecs->ptid);
- pending_follow.fork_event.parent_pid = ecs->ws.value.related_pid;
- target_post_startup_inferior (pid_to_ptid
- (pending_follow.fork_event.
- child_pid));
- follow_vfork_when_exec = !target_can_follow_vfork_prior_to_exec ();
- if (follow_vfork_when_exec)
- {
- target_resume (ecs->ptid, 0, TARGET_SIGNAL_0);
- prepare_to_wait (ecs);
- return;
- }
+ stop_signal = TARGET_SIGNAL_0;
+ keep_going (ecs);
+ return;
}
-
- stop_pc = read_pc ();
- /* The second argument of bpstat_stop_status is meant to help
- distinguish between a breakpoint trap and a singlestep trap.
- This is only important on targets where DECR_PC_AFTER_BREAK
- is non-zero. The prev_pc test is meant to distinguish between
- singlestepping a trap instruction, and singlestepping thru a
- jump to the instruction following a trap instruction. */
-
- stop_bpstat = bpstat_stop_status (&stop_pc,
- currently_stepping (ecs) &&
- prev_pc !=
- stop_pc - DECR_PC_AFTER_BREAK);
- ecs->random_signal = !bpstat_explains_signal (stop_bpstat);
goto process_event_stop_test;
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
@@ -1663,36 +1381,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);
@@ -1701,19 +1389,25 @@ handle_inferior_event (struct execution_control_state *ecs)
stop_pc = read_pc_pid (ecs->ptid);
ecs->saved_inferior_ptid = inferior_ptid;
inferior_ptid = ecs->ptid;
- /* The second argument of bpstat_stop_status is meant to help
- distinguish between a breakpoint trap and a singlestep trap.
- This is only important on targets where DECR_PC_AFTER_BREAK
- is non-zero. The prev_pc test is meant to distinguish between
- singlestepping a trap instruction, and singlestepping thru a
- jump to the instruction following a trap instruction. */
-
- stop_bpstat = bpstat_stop_status (&stop_pc,
- currently_stepping (ecs) &&
- prev_pc !=
- stop_pc - DECR_PC_AFTER_BREAK);
+
+ /* Assume that catchpoints are not really software breakpoints. If
+ some future target implements them using software breakpoints then
+ that target is responsible for fudging DECR_PC_AFTER_BREAK. Thus
+ we pass 1 for the NOT_A_SW_BREAKPOINT argument, so that
+ bpstat_stop_status will not decrement the PC. */
+
+ stop_bpstat = bpstat_stop_status (&stop_pc, 1);
+
ecs->random_signal = !bpstat_explains_signal (stop_bpstat);
inferior_ptid = ecs->saved_inferior_ptid;
+
+ /* If no catchpoint triggered for this, then keep going. */
+ if (ecs->random_signal)
+ {
+ stop_signal = TARGET_SIGNAL_0;
+ keep_going (ecs);
+ return;
+ }
goto process_event_stop_test;
/* These syscall events are returned on HP-UX, as part of its
@@ -1775,13 +1469,15 @@ handle_inferior_event (struct execution_control_state *ecs)
/* We had an event in the inferior, but we are not interested
in handling it at this level. The lower layers have already
- done what needs to be done, if anything. This case can
- occur only when the target is async or extended-async. One
- of the circumstamces for this to happen is when the
- inferior produces output for the console. The inferior has
- not stopped, and we are ignoring the event. */
+ done what needs to be done, if anything.
+
+ One of the possible circumstances for this is when the
+ inferior produces output for the console. The inferior has
+ not stopped, and we are ignoring the event. Another possible
+ circumstance is any event which the lower level knows will be
+ reported multiple times without an intervening resume. */
case TARGET_WAITKIND_IGNORE:
- ecs->wait_some_more = 1;
+ prepare_to_wait (ecs);
return;
}
@@ -2124,8 +1820,8 @@ handle_inferior_event (struct execution_control_state *ecs)
= !(bpstat_explains_signal (stop_bpstat)
|| trap_expected
|| (!CALL_DUMMY_BREAKPOINT_OFFSET_P
- && PC_IN_CALL_DUMMY (stop_pc, read_sp (),
- FRAME_FP (get_current_frame ())))
+ && DEPRECATED_PC_IN_CALL_DUMMY (stop_pc, read_sp (),
+ get_frame_base (get_current_frame ())))
|| (step_range_end && step_resume_breakpoint == NULL));
else
@@ -2135,8 +1831,8 @@ handle_inferior_event (struct execution_control_state *ecs)
news) give another signal besides SIGTRAP, so
check here as well as above. */
|| (!CALL_DUMMY_BREAKPOINT_OFFSET_P
- && PC_IN_CALL_DUMMY (stop_pc, read_sp (),
- FRAME_FP
+ && DEPRECATED_PC_IN_CALL_DUMMY (stop_pc, read_sp (),
+ get_frame_base
(get_current_frame
()))));
if (!ecs->random_signal)
@@ -2150,54 +1846,8 @@ handle_inferior_event (struct execution_control_state *ecs)
else
ecs->random_signal = 1;
- /* If a fork, vfork or exec event was seen, then there are two
- possible responses we can make:
-
- 1. If a catchpoint triggers for the event (ecs->random_signal == 0),
- then we must stop now and issue a prompt. We will resume
- the inferior when the user tells us to.
- 2. If no catchpoint triggers for the event (ecs->random_signal == 1),
- then we must resume the inferior now and keep checking.
-
- In either case, we must take appropriate steps to "follow" the
- the fork/vfork/exec when the inferior is resumed. For example,
- if follow-fork-mode is "child", then we must detach from the
- parent inferior and follow the new child inferior.
-
- In either case, setting pending_follow causes the next resume()
- to take the appropriate following action. */
-process_event_stop_test:
- if (ecs->ws.kind == TARGET_WAITKIND_FORKED)
- {
- if (ecs->random_signal) /* I.e., no catchpoint triggered for this. */
- {
- trap_expected = 1;
- stop_signal = TARGET_SIGNAL_0;
- keep_going (ecs);
- return;
- }
- }
- else if (ecs->ws.kind == TARGET_WAITKIND_VFORKED)
- {
- if (ecs->random_signal) /* I.e., no catchpoint triggered for this. */
- {
- stop_signal = TARGET_SIGNAL_0;
- keep_going (ecs);
- return;
- }
- }
- else if (ecs->ws.kind == TARGET_WAITKIND_EXECD)
- {
- pending_follow.kind = ecs->ws.kind;
- if (ecs->random_signal) /* I.e., no catchpoint triggered for this. */
- {
- trap_expected = 1;
- stop_signal = TARGET_SIGNAL_0;
- keep_going (ecs);
- return;
- }
- }
+process_event_stop_test:
/* For the program's own signals, act according to
the signal handling tables. */
@@ -2315,7 +1965,7 @@ process_event_stop_test:
set_longjmp_resume_breakpoint (jmp_buf_pc, get_current_frame ());
else
#endif /* 0 */
- set_longjmp_resume_breakpoint (jmp_buf_pc, NULL);
+ set_longjmp_resume_breakpoint (jmp_buf_pc, null_frame_id);
ecs->handling_longjmp = 1; /* FIXME */
keep_going (ecs);
return;
@@ -2327,8 +1977,8 @@ process_event_stop_test:
#if 0
/* FIXME - Need to implement nested temporary breakpoints */
if (step_over_calls
- && (INNER_THAN (FRAME_FP (get_current_frame ()),
- step_frame_address)))
+ && (frame_id_inner (get_frame_id (get_current_frame ()),
+ step_frame_id)))
{
ecs->another_trap = 1;
keep_going (ecs);
@@ -2538,7 +2188,7 @@ process_event_stop_test:
case she'd better know what she's doing. */
if (CALL_DUMMY_HAS_COMPLETED (stop_pc, read_sp (),
- FRAME_FP (get_current_frame ()))
+ get_frame_base (get_current_frame ()))
&& !step_range_end)
{
stop_print_frame = 0;
@@ -2608,7 +2258,7 @@ process_event_stop_test:
check_for_old_step_resume_breakpoint ();
step_resume_breakpoint =
- set_momentary_breakpoint (sr_sal, NULL, bp_step_resume);
+ set_momentary_breakpoint (sr_sal, null_frame_id, bp_step_resume);
if (breakpoints_inserted)
insert_breakpoints ();
}
@@ -2639,9 +2289,9 @@ process_event_stop_test:
{
- CORE_ADDR current_frame = FRAME_FP (get_current_frame ());
+ struct frame_id current_frame = get_frame_id (get_current_frame ());
- if (INNER_THAN (current_frame, step_frame_address))
+ if (frame_id_inner (current_frame, step_frame_id))
{
/* We have just taken a signal; go until we are back to
the point where we took it and one more. */
@@ -2661,11 +2311,10 @@ process_event_stop_test:
sr_sal.line = 0;
sr_sal.pc = prev_pc;
/* We could probably be setting the frame to
- step_frame_address; I don't think anyone thought to
- try it. */
+ step_frame_id; I don't think anyone thought to try it. */
check_for_old_step_resume_breakpoint ();
step_resume_breakpoint =
- set_momentary_breakpoint (sr_sal, NULL, bp_step_resume);
+ set_momentary_breakpoint (sr_sal, null_frame_id, bp_step_resume);
if (breakpoints_inserted)
insert_breakpoints ();
}
@@ -2736,17 +2385,17 @@ process_event_stop_test:
/* We're doing a "next". */
if (PC_IN_SIGTRAMP (stop_pc, ecs->stop_func_name)
- && INNER_THAN (step_frame_address, read_sp ()))
+ && frame_id_inner (step_frame_id,
+ frame_id_build (read_sp (), 0)))
/* We stepped out of a signal handler, and into its
calling trampoline. This is misdetected as a
subroutine call, but stepping over the signal
- trampoline isn't such a bad idea. In order to do
- that, we have to ignore the value in
- step_frame_address, since that doesn't represent the
- frame that'll reach when we return from the signal
- trampoline. Otherwise we'll probably continue to the
- end of the program. */
- step_frame_address = 0;
+ trampoline isn't such a bad idea. In order to do that,
+ we have to ignore the value in step_frame_id, since
+ that doesn't represent the frame that'll reach when we
+ return from the signal trampoline. Otherwise we'll
+ probably continue to the end of the program. */
+ step_frame_id = null_frame_id;
step_over_function (ecs);
keep_going (ecs);
@@ -2774,7 +2423,7 @@ process_event_stop_test:
xxx.section = find_pc_overlay (xxx.pc);
check_for_old_step_resume_breakpoint ();
step_resume_breakpoint =
- set_momentary_breakpoint (xxx, NULL, bp_step_resume);
+ set_momentary_breakpoint (xxx, null_frame_id, bp_step_resume);
insert_breakpoints ();
keep_going (ecs);
return;
@@ -2852,7 +2501,7 @@ process_event_stop_test:
is where the new fp value is established. */
check_for_old_step_resume_breakpoint ();
step_resume_breakpoint =
- set_momentary_breakpoint (sr_sal, NULL, bp_step_resume);
+ set_momentary_breakpoint (sr_sal, null_frame_id, bp_step_resume);
if (breakpoints_inserted)
insert_breakpoints ();
@@ -2910,17 +2559,17 @@ process_event_stop_test:
}
step_range_start = ecs->sal.pc;
step_range_end = ecs->sal.end;
- step_frame_address = FRAME_FP (get_current_frame ());
+ step_frame_id = get_frame_id (get_current_frame ());
ecs->current_line = ecs->sal.line;
ecs->current_symtab = ecs->sal.symtab;
- /* In the case where we just stepped out of a function into the middle
- of a line of the caller, continue stepping, but step_frame_address
- must be modified to current frame */
+ /* In the case where we just stepped out of a function into the
+ middle of a line of the caller, continue stepping, but
+ step_frame_id must be modified to current frame */
{
- CORE_ADDR current_frame = FRAME_FP (get_current_frame ());
- if (!(INNER_THAN (current_frame, step_frame_address)))
- step_frame_address = current_frame;
+ struct frame_id current_frame = get_frame_id (get_current_frame ());
+ if (!(frame_id_inner (current_frame, step_frame_id)))
+ step_frame_id = current_frame;
}
keep_going (ecs);
@@ -2966,7 +2615,7 @@ check_sigtramp2 (struct execution_control_state *ecs)
/* We perhaps could set the frame if we kept track of what the
frame corresponding to prev_pc was. But we don't, so don't. */
through_sigtramp_breakpoint =
- set_momentary_breakpoint (sr_sal, NULL, bp_through_sigtramp);
+ set_momentary_breakpoint (sr_sal, null_frame_id, bp_through_sigtramp);
if (breakpoints_inserted)
insert_breakpoints ();
@@ -3024,7 +2673,7 @@ step_into_function (struct execution_control_state *ecs)
established. */
check_for_old_step_resume_breakpoint ();
step_resume_breakpoint =
- set_momentary_breakpoint (sr_sal, NULL, bp_step_resume);
+ set_momentary_breakpoint (sr_sal, null_frame_id, bp_step_resume);
if (breakpoints_inserted)
insert_breakpoints ();
@@ -3043,7 +2692,7 @@ step_into_function (struct execution_control_state *ecs)
of the call.
To do this, we set the step_resume bp's frame to our current
- caller's frame (step_frame_address, which is set by the "next" or
+ caller's frame (step_frame_id, which is set by the "next" or
"until" command, before execution begins). */
static void
@@ -3057,10 +2706,12 @@ step_over_function (struct execution_control_state *ecs)
check_for_old_step_resume_breakpoint ();
step_resume_breakpoint =
- set_momentary_breakpoint (sr_sal, get_current_frame (), bp_step_resume);
+ set_momentary_breakpoint (sr_sal, get_frame_id (get_current_frame ()),
+ bp_step_resume);
- if (step_frame_address && !IN_SOLIB_DYNSYM_RESOLVE_CODE (sr_sal.pc))
- step_resume_breakpoint->frame = step_frame_address;
+ if (frame_id_p (step_frame_id)
+ && !IN_SOLIB_DYNSYM_RESOLVE_CODE (sr_sal.pc))
+ step_resume_breakpoint->frame_id = step_frame_id;
if (breakpoints_inserted)
insert_breakpoints ();
@@ -3071,30 +2722,6 @@ stop_stepping (struct execution_control_state *ecs)
{
if (target_has_execution)
{
- /* Are we stopping for a vfork event? We only stop when we see
- the child's event. However, we may not yet have seen the
- parent's event. And, inferior_ptid is still set to the
- parent's pid, until we resume again and follow either the
- parent or child.
-
- To ensure that we can really touch inferior_ptid (aka, the
- parent process) -- which calls to functions like read_pc
- implicitly do -- wait on the parent if necessary. */
- if ((pending_follow.kind == TARGET_WAITKIND_VFORKED)
- && !pending_follow.fork_event.saw_parent_fork)
- {
- ptid_t parent_ptid;
-
- do
- {
- if (target_wait_hook)
- parent_ptid = target_wait_hook (pid_to_ptid (-1), &(ecs->ws));
- else
- parent_ptid = target_wait (pid_to_ptid (-1), &(ecs->ws));
- }
- while (!ptid_equal (parent_ptid, inferior_ptid));
- }
-
/* Assuming the inferior still exists, set these up for next
time, just like we did above if we didn't break out of the
loop. */
@@ -3114,16 +2741,6 @@ stop_stepping (struct execution_control_state *ecs)
static void
keep_going (struct execution_control_state *ecs)
{
- /* ??rehrauer: ttrace on HP-UX theoretically allows one to debug a
- vforked child between its creation and subsequent exit or call to
- exec(). However, I had big problems in this rather creaky exec
- engine, getting that to work. The fundamental problem is that
- I'm trying to debug two processes via an engine that only
- understands a single process with possibly multiple threads.
-
- Hence, this spot is known to have problems when
- target_can_follow_vfork_prior_to_exec returns 1. */
-
/* Save the pc before execution, to compare with pc after stop. */
prev_pc = read_pc (); /* Might have been DECR_AFTER_BREAK */
prev_func_start = ecs->stop_func_start; /* Ok, since if DECR_PC_AFTER
@@ -3363,8 +2980,12 @@ normal_stop (void)
/* Make sure that the current_frame's pc is correct. This
is a correction for setting up the frame info before doing
DECR_PC_AFTER_BREAK */
- if (target_has_execution && get_current_frame ())
- (get_current_frame ())->pc = read_pc ();
+ if (target_has_execution)
+ /* FIXME: cagney/2002-12-06: Has the PC changed? Thanks to
+ DECR_PC_AFTER_BREAK, the program counter can change. Ask the
+ frame code to check for this and sort out any resultant mess.
+ DECR_PC_AFTER_BREAK needs to just go away. */
+ deprecated_update_frame_pc_hack (get_current_frame (), read_pc ());
if (target_has_execution && breakpoints_inserted)
{
@@ -3424,7 +3045,7 @@ normal_stop (void)
bpstat_print() contains the logic deciding in detail
what to print, based on the event(s) that just occurred. */
- if (stop_print_frame && selected_frame)
+ if (stop_print_frame && deprecated_selected_frame)
{
int bpstat_ret;
int source_flag;
@@ -3434,8 +3055,12 @@ normal_stop (void)
switch (bpstat_ret)
{
case PRINT_UNKNOWN:
+ /* FIXME: cagney/2002-12-01: Given that a frame ID does
+ (or should) carry around the function and does (or
+ should) use that when doing a frame comparison. */
if (stop_step
- && step_frame_address == FRAME_FP (get_current_frame ())
+ && frame_id_eq (step_frame_id,
+ get_frame_id (get_current_frame ()))
&& step_start_function == find_pc_function (stop_pc))
source_flag = SRC_LINE; /* finished step, just print source line */
else
@@ -3468,7 +3093,7 @@ normal_stop (void)
LOCATION: Print only location
SRC_AND_LOC: Print location and source line */
if (do_frame_printing)
- show_and_print_stack_frame (selected_frame, -1, source_flag);
+ show_and_print_stack_frame (deprecated_selected_frame, -1, source_flag);
/* Display the auto-display expressions. */
do_displays ();
@@ -3873,7 +3498,7 @@ struct inferior_status
int trap_expected;
CORE_ADDR step_range_start;
CORE_ADDR step_range_end;
- CORE_ADDR step_frame_address;
+ struct frame_id step_frame_id;
enum step_over_calls_kind step_over_calls;
CORE_ADDR step_resume_break_address;
int stop_after_trap;
@@ -3920,7 +3545,7 @@ save_inferior_status (int restore_stack_info)
inf_status->trap_expected = trap_expected;
inf_status->step_range_start = step_range_start;
inf_status->step_range_end = step_range_end;
- inf_status->step_frame_address = step_frame_address;
+ inf_status->step_frame_id = step_frame_id;
inf_status->step_over_calls = step_over_calls;
inf_status->stop_after_trap = stop_after_trap;
inf_status->stop_soon_quietly = stop_soon_quietly;
@@ -3938,7 +3563,7 @@ save_inferior_status (int restore_stack_info)
inf_status->registers = regcache_dup (current_regcache);
- get_frame_id (selected_frame, &inf_status->selected_frame_id);
+ inf_status->selected_frame_id = get_frame_id (deprecated_selected_frame);
return inf_status;
}
@@ -3950,8 +3575,8 @@ restore_selected_frame (void *args)
frame = frame_find_by_id (*fid);
- /* If inf_status->selected_frame_address is NULL, there was no
- previously selected frame. */
+ /* If inf_status->selected_frame_id is NULL, there was no previously
+ selected frame. */
if (frame == NULL)
{
warning ("Unable to restore previously selected frame.\n");
@@ -3974,7 +3599,7 @@ restore_inferior_status (struct inferior_status *inf_status)
trap_expected = inf_status->trap_expected;
step_range_start = inf_status->step_range_start;
step_range_end = inf_status->step_range_end;
- step_frame_address = inf_status->step_frame_address;
+ step_frame_id = inf_status->step_frame_id;
step_over_calls = inf_status->step_over_calls;
stop_after_trap = inf_status->stop_after_trap;
stop_soon_quietly = inf_status->stop_soon_quietly;
@@ -4041,6 +3666,60 @@ discard_inferior_status (struct inferior_status *inf_status)
xfree (inf_status);
}
+int
+inferior_has_forked (int pid, int *child_pid)
+{
+ struct target_waitstatus last;
+ ptid_t last_ptid;
+
+ get_last_target_status (&last_ptid, &last);
+
+ if (last.kind != TARGET_WAITKIND_FORKED)
+ return 0;
+
+ if (ptid_get_pid (last_ptid) != pid)
+ return 0;
+
+ *child_pid = last.value.related_pid;
+ return 1;
+}
+
+int
+inferior_has_vforked (int pid, int *child_pid)
+{
+ struct target_waitstatus last;
+ ptid_t last_ptid;
+
+ get_last_target_status (&last_ptid, &last);
+
+ if (last.kind != TARGET_WAITKIND_VFORKED)
+ return 0;
+
+ if (ptid_get_pid (last_ptid) != pid)
+ return 0;
+
+ *child_pid = last.value.related_pid;
+ return 1;
+}
+
+int
+inferior_has_execd (int pid, char **execd_pathname)
+{
+ struct target_waitstatus last;
+ ptid_t last_ptid;
+
+ get_last_target_status (&last_ptid, &last);
+
+ if (last.kind != TARGET_WAITKIND_EXECD)
+ return 0;
+
+ if (ptid_get_pid (last_ptid) != pid)
+ return 0;
+
+ *execd_pathname = xstrdup (last.value.execd_pathname);
+ return 1;
+}
+
/* Oft used ptids */
ptid_t null_ptid;
ptid_t minus_one_ptid;