aboutsummaryrefslogtreecommitdiff
path: root/gdb/infrun.c
diff options
context:
space:
mode:
authorDaniel Jacobowitz <drow@false.org>2002-12-11 02:04:45 +0000
committerDaniel Jacobowitz <drow@false.org>2002-12-11 02:04:45 +0000
commit6604731ba7c2a5b3bffcf6ff2831b77ff09a92aa (patch)
treec31e75c7f0d42f7934d4e1d18553146ca71cbc2e /gdb/infrun.c
parent7d2830a309f131b09372007cdff1f277a76b2458 (diff)
downloadgdb-6604731ba7c2a5b3bffcf6ff2831b77ff09a92aa.zip
gdb-6604731ba7c2a5b3bffcf6ff2831b77ff09a92aa.tar.gz
gdb-6604731ba7c2a5b3bffcf6ff2831b77ff09a92aa.tar.bz2
* 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.
Diffstat (limited to 'gdb/infrun.c')
-rw-r--r--gdb/infrun.c196
1 files changed, 33 insertions, 163 deletions
diff --git a/gdb/infrun.c b/gdb/infrun.c
index b96e1c7..0bb2e75 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);
@@ -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: