- 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;