aboutsummaryrefslogtreecommitdiff
path: root/gdb/infrun.c
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/infrun.c')
-rw-r--r--gdb/infrun.c170
1 files changed, 74 insertions, 96 deletions
diff --git a/gdb/infrun.c b/gdb/infrun.c
index 815ebf4..6c42c48 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -428,7 +428,8 @@ holding the child stopped. Try \"set detach-on-fork\" or \
return true;
}
- thread_info *child_thr = nullptr;
+ inferior *parent_inf = current_inferior ();
+ inferior *child_inf = nullptr;
if (!follow_child)
{
@@ -462,25 +463,15 @@ holding the child stopped. Try \"set detach-on-fork\" or \
}
else
{
- struct inferior *parent_inf, *child_inf;
-
/* Add process to GDB's tables. */
child_inf = add_inferior (child_ptid.pid ());
- parent_inf = current_inferior ();
child_inf->attach_flag = parent_inf->attach_flag;
copy_terminal_info (child_inf, parent_inf);
child_inf->gdbarch = parent_inf->gdbarch;
copy_inferior_target_desc_info (child_inf, parent_inf);
- scoped_restore_current_pspace_and_thread restore_pspace_thread;
-
- set_current_inferior (child_inf);
- switch_to_no_thread ();
child_inf->symfile_flags = SYMFILE_NO_READ;
- child_inf->push_target (parent_inf->process_target ());
- child_thr = add_thread_silent (child_inf->process_target (),
- child_ptid);
/* If this is a vfork child, then the address-space is
shared with the parent. */
@@ -489,7 +480,7 @@ holding the child stopped. Try \"set detach-on-fork\" or \
child_inf->pspace = parent_inf->pspace;
child_inf->aspace = parent_inf->aspace;
- exec_on_vfork ();
+ exec_on_vfork (child_inf);
/* The parent will be frozen until the child is done
with the shared region. Keep track of the
@@ -498,32 +489,18 @@ holding the child stopped. Try \"set detach-on-fork\" or \
child_inf->pending_detach = 0;
parent_inf->vfork_child = child_inf;
parent_inf->pending_detach = 0;
-
- /* Now that the inferiors and program spaces are all
- wired up, we can switch to the child thread (which
- switches inferior and program space too). */
- switch_to_thread (child_thr);
}
else
{
child_inf->aspace = new_address_space ();
child_inf->pspace = new program_space (child_inf->aspace);
child_inf->removable = 1;
- set_current_program_space (child_inf->pspace);
clone_program_space (child_inf->pspace, parent_inf->pspace);
-
- /* solib_create_inferior_hook relies on the current
- thread. */
- switch_to_thread (child_thr);
}
}
if (has_vforked)
{
- struct inferior *parent_inf;
-
- parent_inf = current_inferior ();
-
/* If we detached from the child, then we have to be careful
to not insert breakpoints in the parent until the child
is done with the shared memory region. However, if we're
@@ -538,8 +515,6 @@ holding the child stopped. Try \"set detach-on-fork\" or \
else
{
/* Follow the child. */
- struct inferior *parent_inf, *child_inf;
- struct program_space *parent_pspace;
if (print_inferior_events)
{
@@ -559,71 +534,12 @@ holding the child stopped. Try \"set detach-on-fork\" or \
child_inf = add_inferior (child_ptid.pid ());
- parent_inf = current_inferior ();
child_inf->attach_flag = parent_inf->attach_flag;
copy_terminal_info (child_inf, parent_inf);
child_inf->gdbarch = parent_inf->gdbarch;
copy_inferior_target_desc_info (child_inf, parent_inf);
- parent_pspace = parent_inf->pspace;
-
- process_stratum_target *target = parent_inf->process_target ();
-
- {
- /* Hold a strong reference to the target while (maybe)
- detaching the parent. Otherwise detaching could close the
- target. */
- auto target_ref = target_ops_ref::new_reference (target);
-
- /* If we're vforking, we want to hold on to the parent until
- the child exits or execs. At child exec or exit time we
- can remove the old breakpoints from the parent and detach
- or resume debugging it. Otherwise, detach the parent now;
- we'll want to reuse it's program/address spaces, but we
- can't set them to the child before removing breakpoints
- from the parent, otherwise, the breakpoints module could
- decide to remove breakpoints from the wrong process (since
- they'd be assigned to the same address space). */
-
- if (has_vforked)
- {
- gdb_assert (child_inf->vfork_parent == NULL);
- gdb_assert (parent_inf->vfork_child == NULL);
- child_inf->vfork_parent = parent_inf;
- child_inf->pending_detach = 0;
- parent_inf->vfork_child = child_inf;
- parent_inf->pending_detach = detach_fork;
- parent_inf->waiting_for_vfork_done = 0;
- }
- else if (detach_fork)
- {
- if (print_inferior_events)
- {
- /* Ensure that we have a process ptid. */
- ptid_t process_ptid = ptid_t (parent_ptid.pid ());
-
- target_terminal::ours_for_output ();
- fprintf_filtered (gdb_stdlog,
- _("[Detaching after fork from "
- "parent %s]\n"),
- target_pid_to_str (process_ptid).c_str ());
- }
-
- target_detach (parent_inf, 0);
- parent_inf = NULL;
- }
-
- /* Note that the detach above makes PARENT_INF dangling. */
-
- /* Add the child thread to the appropriate lists, and switch
- to this new thread, before cloning the program space, and
- informing the solib layer about this new process. */
-
- set_current_inferior (child_inf);
- child_inf->push_target (target);
- }
-
- child_thr = add_thread_silent (target, child_ptid);
+ program_space *parent_pspace = parent_inf->pspace;
/* If this is a vfork child, then the address-space is shared
with the parent. If we detached from the parent, then we can
@@ -633,7 +549,7 @@ holding the child stopped. Try \"set detach-on-fork\" or \
child_inf->pspace = parent_pspace;
child_inf->aspace = child_inf->pspace->aspace;
- exec_on_vfork ();
+ exec_on_vfork (child_inf);
}
else
{
@@ -641,22 +557,84 @@ holding the child stopped. Try \"set detach-on-fork\" or \
child_inf->pspace = new program_space (child_inf->aspace);
child_inf->removable = 1;
child_inf->symfile_flags = SYMFILE_NO_READ;
- set_current_program_space (child_inf->pspace);
clone_program_space (child_inf->pspace, parent_pspace);
}
-
- switch_to_thread (child_thr);
}
- target_follow_fork (child_ptid, fork_kind, follow_child, detach_fork);
+ gdb_assert (current_inferior () == parent_inf);
+
+ /* If we are setting up an inferior for the child, target_follow_fork is
+ responsible for pushing the appropriate targets on the new inferior's
+ target stack and adding the initial thread (with ptid CHILD_PTID).
+
+ If we are not setting up an inferior for the child (because following
+ the parent and detach_fork is true), it is responsible for detaching
+ from CHILD_PTID. */
+ target_follow_fork (child_inf, child_ptid, fork_kind, follow_child,
+ detach_fork);
+
+ /* target_follow_fork must leave the parent as the current inferior. If we
+ want to follow the child, we make it the current one below. */
+ gdb_assert (current_inferior () == parent_inf);
+
+ /* If there is a child inferior, target_follow_fork must have created a thread
+ for it. */
+ if (child_inf != nullptr)
+ gdb_assert (!child_inf->thread_list.empty ());
+
+ /* Detach the parent if needed. */
+ if (follow_child)
+ {
+ /* If we're vforking, we want to hold on to the parent until
+ the child exits or execs. At child exec or exit time we
+ can remove the old breakpoints from the parent and detach
+ or resume debugging it. Otherwise, detach the parent now;
+ we'll want to reuse it's program/address spaces, but we
+ can't set them to the child before removing breakpoints
+ from the parent, otherwise, the breakpoints module could
+ decide to remove breakpoints from the wrong process (since
+ they'd be assigned to the same address space). */
+
+ if (has_vforked)
+ {
+ gdb_assert (child_inf->vfork_parent == NULL);
+ gdb_assert (parent_inf->vfork_child == NULL);
+ child_inf->vfork_parent = parent_inf;
+ child_inf->pending_detach = 0;
+ parent_inf->vfork_child = child_inf;
+ parent_inf->pending_detach = detach_fork;
+ parent_inf->waiting_for_vfork_done = 0;
+ }
+ else if (detach_fork)
+ {
+ if (print_inferior_events)
+ {
+ /* Ensure that we have a process ptid. */
+ ptid_t process_ptid = ptid_t (parent_ptid.pid ());
+
+ target_terminal::ours_for_output ();
+ fprintf_filtered (gdb_stdlog,
+ _("[Detaching after fork from "
+ "parent %s]\n"),
+ target_pid_to_str (process_ptid).c_str ());
+ }
+
+ target_detach (parent_inf, 0);
+ }
+ }
/* If we ended up creating a new inferior, call post_create_inferior to inform
the various subcomponents. */
- if (child_thr != nullptr)
+ if (child_inf != nullptr)
{
- scoped_restore_current_thread restore;
- switch_to_thread (child_thr);
+ /* If FOLLOW_CHILD, we leave CHILD_INF as the current inferior
+ (do not restore the parent as the current inferior). */
+ gdb::optional<scoped_restore_current_thread> maybe_restore;
+
+ if (!follow_child)
+ maybe_restore.emplace ();
+ switch_to_thread (*child_inf->threads ().begin ());
post_create_inferior (0);
}