discard_cleanups (back_to);
}
+/* We had just found out that the target was already attached to an
+ inferior. PTID points at a thread of this new inferior, that is
+ the most likely to be stopped right now, but not necessarily so.
+ The new inferior is assumed to be already added to the inferior
+ list at this point. If LEAVE_RUNNING, then leave the threads of
+ this inferior running, except those we've explicitly seen reported
+ as stopped. */
+
+void
+notice_new_inferior (ptid_t ptid, int leave_running, int from_tty)
+{
+ struct cleanup* old_chain;
+ int async_exec;
+
+ old_chain = make_cleanup (null_cleanup, NULL);
+
+ /* If in non-stop, leave threads as running as they were. If
+ they're stopped for some reason other than us telling it to, the
+ target reports a signal != TARGET_SIGNAL_0. We don't try to
+ resume threads with such a stop signal. */
+ async_exec = non_stop;
+
+ if (!ptid_equal (inferior_ptid, null_ptid))
+ make_cleanup_restore_current_thread ();
+
+ switch_to_thread (ptid);
+
+ /* When we "notice" a new inferior we need to do all the things we
+ would normally do if we had just attached to it. */
+
+ if (is_executing (inferior_ptid))
+ {
+ struct inferior *inferior = current_inferior ();
+
+ /* We're going to install breakpoints, and poke at memory,
+ ensure that the inferior is stopped for a moment while we do
+ that. */
+ target_stop (inferior_ptid);
+
+ inferior->stop_soon = STOP_QUIETLY_REMOTE;
+
+ /* Wait for stop before proceeding. */
+ if (target_can_async_p ())
+ {
+ struct attach_command_continuation_args *a;
+
+ a = xmalloc (sizeof (*a));
+ a->args = xstrdup ("");
+ a->from_tty = from_tty;
+ a->async_exec = async_exec;
+ add_inferior_continuation (attach_command_continuation, a,
+ attach_command_continuation_free_args);
+
+ do_cleanups (old_chain);
+ return;
+ }
+ else
+ wait_for_inferior (0);
+ }
+
+ async_exec = leave_running;
+ attach_command_post_wait ("" /* args */, from_tty, async_exec);
+
+ do_cleanups (old_chain);
+}
+
/*
* detach_command --
* takes a program previously attached to and detaches it.
static ptid_t general_thread;
static ptid_t continue_thread;
+/* Add PID to GDB's inferior table. Since we can be connected to a
+ remote system before before knowing about any inferior, mark the
+ target with execution when we find the first inferior. */
+
+static struct inferior *
+remote_add_inferior (int pid)
+{
+ struct remote_state *rs = get_remote_state ();
+ struct inferior *inf;
+
+ inf = add_inferior (pid);
+
+ /* This may be the first inferior we hear about. */
+ if (!target_has_execution)
+ {
+ if (rs->extended)
+ target_mark_running (&extended_remote_ops);
+ else
+ target_mark_running (&remote_ops);
+ }
+
+ return inf;
+}
+
+/* Add thread PTID to GDB's thread list. Tag it as executing/running
+ according to RUNNING. */
+
static void
-notice_new_inferiors (ptid_t currthread)
+remote_add_thread (ptid_t ptid, int running)
{
+ add_thread (ptid);
+
+ set_executing (ptid, running);
+ set_running (ptid, running);
+}
+
+/* Come here when we learn about a thread id from the remote target.
+ It may be the first time we hear about such thread, so take the
+ opportunity to add it to GDB's thread list. In case this is the
+ first time we're noticing its corresponding inferior, add it to
+ GDB's inferior list as well. */
+
+static void
+remote_notice_new_inferior (ptid_t currthread, int running)
+{
+ struct remote_state *rs = get_remote_state ();
+
/* If this is a new thread, add it to GDB's thread list.
If we leave it up to WFI to do this, bad things will happen. */
{
/* We're seeing an event on a thread id we knew had exited.
This has to be a new thread reusing the old id. Add it. */
- add_thread (currthread);
+ remote_add_thread (currthread, running);
return;
}
if (!in_thread_list (currthread))
{
+ struct inferior *inf = NULL;
+
if (ptid_equal (pid_to_ptid (ptid_get_pid (currthread)), inferior_ptid))
{
/* inferior_ptid has no thread member yet. This can happen
may not know about it yet. Add it before adding its child
thread, so notifications are emitted in a sensible order. */
if (!in_inferior_list (ptid_get_pid (currthread)))
- add_inferior (ptid_get_pid (currthread));
+ inf = remote_add_inferior (ptid_get_pid (currthread));
/* This is really a new thread. Add it. */
- add_thread (currthread);
+ remote_add_thread (currthread, running);
+
+ /* If we found a new inferior, let the common code do whatever
+ it needs to with it (e.g., read shared libraries, insert
+ breakpoints). */
+ if (inf != NULL)
+ notice_new_inferior (currthread, running, 0);
}
}
/* We're just invalidating the local thread mirror. */
return;
- notice_new_inferiors (currthread);
+ remote_notice_new_inferior (currthread, 0);
}
static char *last_pass_packet;
do
{
new_thread = read_ptid (bufp, &bufp);
- if (!ptid_equal (new_thread, null_ptid)
- && (!in_thread_list (new_thread)
- || is_exited (new_thread)))
+ if (!ptid_equal (new_thread, null_ptid))
{
- /* When connected to a multi-process aware stub,
- "info threads" may show up threads of
- inferiors we didn't know about yet. Add them
- now, and before adding any of its child
- threads, so notifications are emitted in a
- sensible order. */
- if (!in_inferior_list (ptid_get_pid (new_thread)))
- add_inferior (ptid_get_pid (new_thread));
-
- add_thread (new_thread);
-
/* In non-stop mode, we assume new found threads
- are running until we proven otherwise with a
+ are running until proven otherwise with a
stop reply. In all-stop, we can only get
here if all threads are stopped. */
- set_executing (new_thread, non_stop ? 1 : 0);
- set_running (new_thread, non_stop ? 1 : 0);
+ int running = non_stop ? 1 : 0;
+
+ remote_notice_new_inferior (new_thread, running);
}
}
while (*bufp++ == ','); /* comma-separated list */
}
else
{
- if (args->extended_p)
- target_mark_running (args->target);
-
/* Save the reply for later. */
wait_status = alloca (strlen (rs->buf) + 1);
strcpy (wait_status, rs->buf);
/* Now, if we have thread information, update inferior_ptid. */
inferior_ptid = remote_current_thread (inferior_ptid);
- add_inferior (ptid_get_pid (inferior_ptid));
+ remote_add_inferior (ptid_get_pid (inferior_ptid));
/* Always add the main thread. */
add_thread_silent (inferior_ptid);
error (_("Attaching to %s failed"),
target_pid_to_str (pid_to_ptid (pid)));
- target_mark_running (target);
inferior_ptid = pid_to_ptid (pid);
/* Now, if we have thread information, update inferior_ptid. */
inferior_ptid = remote_current_thread (inferior_ptid);
- inf = add_inferior (pid);
+ inf = remote_add_inferior (pid);
inf->attach_flag = 1;
if (non_stop)
if (status->kind != TARGET_WAITKIND_EXITED
&& status->kind != TARGET_WAITKIND_SIGNALLED)
{
- notice_new_inferiors (ptid);
-
/* Expedited registers. */
if (stop_reply->regcache)
{
remote_stopped_by_watchpoint_p = stop_reply->stopped_by_watchpoint_p;
remote_watch_data_address = stop_reply->watch_data_address;
+
+ remote_notice_new_inferior (ptid, 0);
}
stop_reply_xfree (stop_reply);
/* Now, if we have thread information, update inferior_ptid. */
inferior_ptid = remote_current_thread (inferior_ptid);
- add_inferior (ptid_get_pid (inferior_ptid));
+ remote_add_inferior (ptid_get_pid (inferior_ptid));
add_thread_silent (inferior_ptid);
- target_mark_running (&extended_remote_ops);
-
/* Get updated offsets, if the stub uses qOffsets. */
get_offsets ();
}