struct
{
int parent_pid;
- int saw_parent_fork;
int child_pid;
- int saw_child_fork;
- int saw_child_exec;
}
fork_event;
char *execd_pathname;
/* follow_mode = follow_fork_mode_...; */
}
- pending_follow.fork_event.saw_parent_fork = 0;
- pending_follow.fork_event.saw_child_fork = 0;
-
return target_follow_fork (follow_child);
}
/* 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;
/* 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;
- pending_follow.fork_event.saw_child_fork = 1;
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));
+ 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_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
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. */
{
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. */
/* 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)
{