This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
Re: [RFA 03/08] multi-process support: remote multi-process extensions
- From: Pedro Alves <pedro at codesourcery dot com>
- To: gdb-patches at sourceware dot org, Eli Zaretskii <eliz at gnu dot org>
- Date: Fri, 12 Sep 2008 17:51:30 +0100
- Subject: Re: [RFA 03/08] multi-process support: remote multi-process extensions
- References: <200809121638.59063.pedro@codesourcery.com> <ufxo5pcqx.fsf@gnu.org>
On Friday 12 September 2008 17:09:26, Eli Zaretskii wrote:
> > From: Pedro Alves <pedro@codesourcery.com>
> > Date: Fri, 12 Sep 2008 16:38:58 +0100
> >
> > - if (extended)
> > - puts_filtered ("Detached from remote process.\n");
> > + if (rs->multi_process_aware)
> > + printf_filtered ("Detached from %s.\n",
> > + target_pid_to_str (pid_to_ptid (pid)));
> > else
> > - puts_filtered ("Ending remote debugging.\n");
> > + {
> > + /* Unregister the file descriptor from the event loop. */
> > + if (target_is_async_p ())
> > + serial_async (remote_desc, NULL, 0);
> > +
> > + if (extended)
> > + puts_filtered ("Detached from remote process.\n");
> > + else
> > + puts_filtered ("Ending remote debugging.\n");
> > + }
>
> Please put all user-visible messages inside _().
Ah, good catch. While we're at it, let's fix those. Done. Thanks.
--
Pedro Alves
2008-09-12 Pedro Alves <pedro@codesourcery.com>
Implement multi-process extensions.
* remote.c (struct remote_state): Add multi_process_aware field.
(PACKET_vKill): New.
(record_currthread): Use thread_change_ptid. Notice new
inferiors.
(set_thread, remote_thread_alive): Use write_ptid.
(write_ptid, read_ptid): New.
(remote_current_thread, remote_threads_info)
(remote_threads_extra_info): Use them.
(remote_start_remote): Add inferior to inferior list.
(remote_multi_process_feature): New.
(remote_protocol_features): Add "multiprocess" feature.
(remote_query_supported): Pass "multiprocess+" as supported
features.
(remote_open_1): Clear multi_process_aware.
(remote_detach_1): Detach current process. Use extended packet
format for multi-process. Detach process from the inferior list.
Only mourn after printing output.
(extended_remote_attach_1): Add process to the inferior list.
(remote_vcont_resume): Use write_ptid to pass the thread ids.
(remote_wait): Use read_ptid. Implement the extended
multi-process extension format of the 'W' and 'X' reply packets.
Remove exited inferiors from inferior list.
(remote_xfer_memory): Set general thread.
(remote_vkill): New.
(extended_remote_kill): New.
(select_new_thread_callback): New.
(extended_remote_mourn_1): If there are more processes to debug,
switch to a thread in another process, and don't pop the target.
(extended_remote_create_inferior_1): Add the new process to the
inferior list.
(remote_stopped_by_watchpoint): Indenting.
(remote_xfer_partial): Set the general thread.
(remote_pid_to_str): If the remote is multi-process aware, print
the process id as well as the thread id.
(remote_get_thread_local_address): Use write_ptid.
(init_extended_remote_ops): Register extended_remote_kill.
(_initialize_remote): Register new packets. Change
magic_null_ptid's, not_sent_ptid's and any_thread_ptid's pid
member to 42000.
* thread.c (thread_change_ptid): Also account for the inferior pid
changing.
---
gdb/remote.c | 517 +++++++++++++++++++++++++++++++++++++++++++++--------------
gdb/thread.c | 11 +
2 files changed, 407 insertions(+), 121 deletions(-)
Index: src/gdb/remote.c
===================================================================
--- src.orig/gdb/remote.c 2008-09-12 16:34:09.000000000 +0100
+++ src/gdb/remote.c 2008-09-12 17:43:37.000000000 +0100
@@ -208,6 +208,9 @@ static void show_remote_protocol_packet_
struct cmd_list_element *c,
const char *value);
+static char *write_ptid (char *buf, const char *endbuf, ptid_t ptid);
+static ptid_t read_ptid (char *buf, char **obuf);
+
void _initialize_remote (void);
/* For "remote". */
@@ -253,6 +256,9 @@ struct remote_state
expect acks from each other. The connection is assumed to be
reliable. */
int noack_mode;
+
+ /* The stub reported support for multi-process extensions. */
+ int multi_process_aware;
};
/* This data could be associated with a target, but we do not always
@@ -940,6 +946,7 @@ enum {
PACKET_vAttach,
PACKET_vRun,
PACKET_QStartNoAckMode,
+ PACKET_vKill,
PACKET_MAX
};
@@ -1068,6 +1075,15 @@ record_currthread (ptid_t currthread)
/* 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. */
+
+ if (in_thread_list (currthread) && is_exited (currthread))
+ {
+ /* 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);
+ return;
+ }
+
if (!in_thread_list (currthread))
{
if (ptid_equal (pid_to_ptid (ptid_get_pid (currthread)), inferior_ptid))
@@ -1077,23 +1093,30 @@ record_currthread (ptid_t currthread)
stub doesn't support qC. This is the first stop reported
after an attach, so this is the main thread. Update the
ptid in the thread list. */
- struct thread_info *th = find_thread_pid (inferior_ptid);
- inferior_ptid = th->ptid = currthread;
+ thread_change_ptid (inferior_ptid, currthread);
+ return;
}
- else if (ptid_equal (magic_null_ptid, inferior_ptid))
+
+ if (ptid_equal (magic_null_ptid, inferior_ptid))
{
/* inferior_ptid is not set yet. This can happen with the
vRun -> remote_wait,"TAAthread:" path if the stub
doesn't support qC. This is the first stop reported
after an attach, so this is the main thread. Update the
ptid in the thread list. */
- struct thread_info *th = find_thread_pid (inferior_ptid);
- inferior_ptid = th->ptid = currthread;
+ thread_change_ptid (inferior_ptid, currthread);
+ return;
}
- else
- /* This is really a new thread. Add it. */
- add_thread (currthread);
+
+ /* This is really a new thread. Add it. */
+ add_thread (currthread);
}
+
+ if (!in_inferior_list (ptid_get_pid (currthread)))
+ /* When connecting to a target remote, or to a target
+ extended-remote which already was debugging an inferior, we may
+ not know about it yet --- add it. */
+ add_inferior (ptid_get_pid (currthread));
}
static char *last_pass_packet;
@@ -1179,13 +1202,7 @@ set_thread (struct ptid ptid, int gen)
else if (ptid_equal (ptid, minus_one_ptid))
xsnprintf (buf, endbuf - buf, "-1");
else
- {
- int tid = ptid_get_tid (ptid);
- if (tid < 0)
- xsnprintf (buf, endbuf - buf, "-%x", -tid);
- else
- xsnprintf (buf, endbuf - buf, "%x", tid);
- }
+ write_ptid (buf, endbuf, ptid);
putpkt (rs->buf);
getpkt (&rs->buf, &rs->buf_size, 0);
if (gen)
@@ -1215,6 +1232,7 @@ remote_thread_alive (ptid_t ptid)
{
struct remote_state *rs = get_remote_state ();
int tid = ptid_get_tid (ptid);
+ char *p, *endp;
if (ptid_equal (ptid, magic_null_ptid))
/* The main thread is always alive. */
@@ -1226,10 +1244,12 @@ remote_thread_alive (ptid_t ptid)
multi-threading. */
return 1;
- if (tid < 0)
- xsnprintf (rs->buf, get_remote_packet_size (), "T-%08x", -tid);
- else
- xsnprintf (rs->buf, get_remote_packet_size (), "T%08x", tid);
+ p = rs->buf;
+ endp = rs->buf + get_remote_packet_size ();
+
+ *p++ = 'T';
+ write_ptid (p, endp, ptid);
+
putpkt (rs->buf);
getpkt (&rs->buf, &rs->buf_size, 0);
return (rs->buf[0] == 'O' && rs->buf[1] == 'K');
@@ -1350,6 +1370,71 @@ static int remote_threadlist_iterator (r
static int remote_newthread_step (threadref *ref, void *context);
+
+/* Write a PTID to BUF. ENDBUF points to one-passed-the-end of the
+ buffer we're allowed to write to. Returns
+ BUF+CHARACTERS_WRITTEN. */
+
+static char *
+write_ptid (char *buf, const char *endbuf, ptid_t ptid)
+{
+ int pid, tid;
+ struct remote_state *rs = get_remote_state ();
+
+ if (rs->multi_process_aware)
+ {
+ pid = ptid_get_pid (ptid);
+ if (pid < 0)
+ buf += xsnprintf (buf, endbuf - buf, "p-%x.", -pid);
+ else
+ buf += xsnprintf (buf, endbuf - buf, "p%x.", pid);
+ }
+ tid = ptid_get_tid (ptid);
+ if (tid < 0)
+ buf += xsnprintf (buf, endbuf - buf, "-%x", -tid);
+ else
+ buf += xsnprintf (buf, endbuf - buf, "%x", tid);
+
+ return buf;
+}
+
+/* Extract a PTID from BUF. If non-null, OBUF is set to the to one
+ passed the last parsed char. Returns null_ptid on error. */
+
+static ptid_t
+read_ptid (char *buf, char **obuf)
+{
+ char *p = buf;
+ char *pp;
+ ULONGEST pid = 0, tid = 0;
+ ptid_t ptid;
+
+ if (*p == 'p')
+ {
+ /* Multi-process ptid. */
+ pp = unpack_varlen_hex (p + 1, &pid);
+ if (*pp != '.')
+ error (_("invalid remote ptid: %s\n"), p);
+
+ p = pp;
+ pp = unpack_varlen_hex (p + 1, &tid);
+ if (obuf)
+ *obuf = pp;
+ return ptid_build (pid, 0, tid);
+ }
+
+ /* No multi-process. Just a tid. */
+ pp = unpack_varlen_hex (p, &tid);
+
+ /* Since the stub is not sending a process id, then default to
+ what's in inferior_ptid. */
+ pid = ptid_get_pid (inferior_ptid);
+
+ if (obuf)
+ *obuf = pp;
+ return ptid_build (pid, 0, tid);
+}
+
/* Encode 64 bits in 16 chars of hex. */
static const char hexchars[] = "0123456789abcdef";
@@ -1916,16 +2001,7 @@ remote_current_thread (ptid_t oldpid)
putpkt ("qC");
getpkt (&rs->buf, &rs->buf_size, 0);
if (rs->buf[0] == 'Q' && rs->buf[1] == 'C')
- {
- /* Use strtoul here, so we'll correctly parse values whose
- highest bit is set. The protocol carries them as a simple
- series of hex digits; in the absence of a sign, strtol will
- see such values as positive numbers out of range for signed
- 'long', and return LONG_MAX to indicate an overflow. */
- tid = strtoul (&rs->buf[2], NULL, 16);
- pid = ptid_get_pid (oldpid);
- return ptid_build (pid, 0, tid);
- }
+ return read_ptid (&rs->buf[2], NULL);
else
return oldpid;
}
@@ -1953,8 +2029,6 @@ remote_threads_info (void)
{
struct remote_state *rs = get_remote_state ();
char *bufp;
- int tid;
- int pid;
ptid_t new_thread;
if (remote_desc == 0) /* paranoia */
@@ -1971,16 +2045,9 @@ remote_threads_info (void)
{
do
{
- /* Use strtoul here, so we'll correctly parse values
- whose highest bit is set. The protocol carries
- them as a simple series of hex digits; in the
- absence of a sign, strtol will see such values as
- positive numbers out of range for signed 'long',
- and return LONG_MAX to indicate an overflow. */
- tid = strtoul (bufp, &bufp, 16);
- pid = ptid_get_pid (inferior_ptid);
- new_thread = ptid_build (pid, 0, tid);
- if (tid != 0 && !in_thread_list (new_thread))
+ new_thread = read_ptid (bufp, &bufp);
+ if (!ptid_equal (new_thread, null_ptid)
+ && !in_thread_list (new_thread))
add_thread (new_thread);
}
while (*bufp++ == ','); /* comma-separated list */
@@ -2030,8 +2097,13 @@ remote_threads_extra_info (struct thread
if (use_threadextra_query)
{
- xsnprintf (rs->buf, get_remote_packet_size (), "qThreadExtraInfo,%lx",
- ptid_get_tid (tp->ptid));
+ char *b = rs->buf;
+ char *endb = rs->buf + get_remote_packet_size ();
+
+ xsnprintf (b, endb - b, "qThreadExtraInfo,");
+ b += strlen (b);
+ write_ptid (b, endb, tp->ptid);
+
putpkt (rs->buf);
getpkt (&rs->buf, &rs->buf_size, 0);
if (rs->buf[0] != 0)
@@ -2321,6 +2393,8 @@ remote_start_remote (struct ui_out *uiou
/* Now, if we have thread information, update inferior_ptid. */
inferior_ptid = remote_current_thread (inferior_ptid);
+ add_inferior (ptid_get_pid (inferior_ptid));
+
/* Always add the main thread. */
add_thread_silent (inferior_ptid);
@@ -2518,6 +2592,14 @@ remote_packet_size (const struct protoco
rs->explicit_packet_size = packet_size;
}
+static void
+remote_multi_process_feature (const struct protocol_feature *feature,
+ enum packet_support support, const char *value)
+{
+ struct remote_state *rs = get_remote_state ();
+ rs->multi_process_aware = (support == PACKET_ENABLE);
+}
+
static struct protocol_feature remote_protocol_features[] = {
{ "PacketSize", PACKET_DISABLE, remote_packet_size, -1 },
{ "qXfer:auxv:read", PACKET_DISABLE, remote_supported_packet,
@@ -2536,6 +2618,7 @@ static struct protocol_feature remote_pr
PACKET_QPassSignals },
{ "QStartNoAckMode", PACKET_DISABLE, remote_supported_packet,
PACKET_QStartNoAckMode },
+ { "multiprocess", PACKET_DISABLE, remote_multi_process_feature, -1 },
};
static void
@@ -2556,7 +2639,7 @@ remote_query_supported (void)
rs->buf[0] = 0;
if (remote_protocol_packets[PACKET_qSupported].support != PACKET_DISABLE)
{
- putpkt ("qSupported");
+ putpkt ("qSupported:multiprocess+");
getpkt (&rs->buf, &rs->buf_size, 0);
/* If an error occured, warn, but do not return - just reset the
@@ -2753,6 +2836,7 @@ remote_open_1 (char *name, int from_tty,
init_all_packet_configs ();
rs->explicit_packet_size = 0;
rs->noack_mode = 0;
+ rs->multi_process_aware = 0;
general_thread = not_sent_ptid;
continue_thread = not_sent_ptid;
@@ -2875,6 +2959,7 @@ remote_open_1 (char *name, int from_tty,
static void
remote_detach_1 (char *args, int from_tty, int extended)
{
+ int pid = ptid_get_pid (inferior_ptid);
struct remote_state *rs = get_remote_state ();
if (args)
@@ -2884,25 +2969,41 @@ remote_detach_1 (char *args, int from_tt
error (_("No process to detach from."));
/* Tell the remote target to detach. */
- strcpy (rs->buf, "D");
+ if (rs->multi_process_aware)
+ sprintf (rs->buf, "D;%x", pid);
+ else
+ strcpy (rs->buf, "D");
+
putpkt (rs->buf);
getpkt (&rs->buf, &rs->buf_size, 0);
- if (rs->buf[0] == 'E')
+ if (rs->buf[0] == 'O' && rs->buf[1] == 'K')
+ ;
+ else if (rs->buf[0] == '\0')
+ error (_("Remote doesn't know how to detach"));
+ else
error (_("Can't detach process."));
- /* Unregister the file descriptor from the event loop. */
- if (target_is_async_p ())
- serial_async (remote_desc, NULL, 0);
-
- target_mourn_inferior ();
if (from_tty)
{
- if (extended)
- puts_filtered ("Detached from remote process.\n");
+ if (rs->multi_process_aware)
+ printf_filtered (_("Detached from remote %s.\n"),
+ target_pid_to_str (pid_to_ptid (pid)));
else
- puts_filtered ("Ending remote debugging.\n");
+ {
+ /* Unregister the file descriptor from the event loop. */
+ if (target_is_async_p ())
+ serial_async (remote_desc, NULL, 0);
+
+ if (extended)
+ puts_filtered (_("Detached from remote process.\n"));
+ else
+ puts_filtered (_("Ending remote debugging.\n"));
+ }
}
+
+ detach_inferior (pid);
+ target_mourn_inferior ();
}
static void
@@ -2987,6 +3088,8 @@ extended_remote_attach_1 (struct target_
/* Now, if we have thread information, update inferior_ptid. */
inferior_ptid = remote_current_thread (inferior_ptid);
+ add_inferior (pid);
+
/* Now, add the main thread to the thread list. */
add_thread_silent (inferior_ptid);
@@ -3131,8 +3234,8 @@ static int
remote_vcont_resume (ptid_t ptid, int step, enum target_signal siggnal)
{
struct remote_state *rs = get_remote_state ();
- char *outbuf;
- struct cleanup *old_cleanup;
+ char *p;
+ char *endp;
if (remote_protocol_packets[PACKET_vCont].support == PACKET_SUPPORT_UNKNOWN)
remote_vcont_probe (rs);
@@ -3140,6 +3243,9 @@ remote_vcont_resume (ptid_t ptid, int st
if (remote_protocol_packets[PACKET_vCont].support == PACKET_DISABLE)
return 0;
+ p = rs->buf;
+ endp = rs->buf + get_remote_packet_size ();
+
/* If we could generate a wider range of packets, we'd have to worry
about overflowing BUF. Should there be a generic
"multi-part-packet" packet? */
@@ -3151,47 +3257,75 @@ remote_vcont_resume (ptid_t ptid, int st
understand. Make sure to only send forms that do not specify
a TID. */
if (step && siggnal != TARGET_SIGNAL_0)
- outbuf = xstrprintf ("vCont;S%02x", siggnal);
+ xsnprintf (p, endp - p, "vCont;S%02x", siggnal);
else if (step)
- outbuf = xstrprintf ("vCont;s");
+ xsnprintf (p, endp - p, "vCont;s");
else if (siggnal != TARGET_SIGNAL_0)
- outbuf = xstrprintf ("vCont;C%02x", siggnal);
+ xsnprintf (p, endp - p, "vCont;C%02x", siggnal);
else
- outbuf = xstrprintf ("vCont;c");
+ xsnprintf (p, endp - p, "vCont;c");
}
else if (ptid_equal (ptid, minus_one_ptid))
{
/* Resume all threads, with preference for INFERIOR_PTID. */
- int tid = ptid_get_tid (inferior_ptid);
if (step && siggnal != TARGET_SIGNAL_0)
- outbuf = xstrprintf ("vCont;S%02x:%x;c", siggnal, tid);
+ {
+ /* Step inferior_ptid with signal. */
+ p += xsnprintf (p, endp - p, "vCont;S%02x:", siggnal);
+ p = write_ptid (p, endp, inferior_ptid);
+ /* And continue others. */
+ p += xsnprintf (p, endp - p, ";c");
+ }
else if (step)
- outbuf = xstrprintf ("vCont;s:%x;c", tid);
+ {
+ /* Step inferior_ptid. */
+ p += xsnprintf (p, endp - p, "vCont;s:");
+ p = write_ptid (p, endp, inferior_ptid);
+ /* And continue others. */
+ p += xsnprintf (p, endp - p, ";c");
+ }
else if (siggnal != TARGET_SIGNAL_0)
- outbuf = xstrprintf ("vCont;C%02x:%x;c", siggnal, tid);
+ {
+ /* Continue inferior_ptid with signal. */
+ p += xsnprintf (p, endp - p, "vCont;C%02x:", siggnal);
+ p = write_ptid (p, endp, inferior_ptid);
+ /* And continue others. */
+ p += xsnprintf (p, endp - p, ";c");
+ }
else
- outbuf = xstrprintf ("vCont;c");
+ xsnprintf (p, endp - p, "vCont;c");
}
else
{
/* Scheduler locking; resume only PTID. */
- int tid = ptid_get_tid (ptid);
if (step && siggnal != TARGET_SIGNAL_0)
- outbuf = xstrprintf ("vCont;S%02x:%x", siggnal, tid);
+ {
+ /* Step ptid with signal. */
+ p += xsnprintf (p, endp - p, "vCont;S%02x:", siggnal);
+ p = write_ptid (p, endp, ptid);
+ }
else if (step)
- outbuf = xstrprintf ("vCont;s:%x", tid);
+ {
+ /* Step ptid. */
+ p += xsnprintf (p, endp - p, "vCont;s:");
+ p = write_ptid (p, endp, ptid);
+ }
else if (siggnal != TARGET_SIGNAL_0)
- outbuf = xstrprintf ("vCont;C%02x:%x", siggnal, tid);
+ {
+ /* Continue ptid with signal. */
+ p += xsnprintf (p, endp - p, "vCont;C%02x:", siggnal);
+ p = write_ptid (p, endp, ptid);
+ }
else
- outbuf = xstrprintf ("vCont;c:%x", tid);
+ {
+ /* Continue ptid. */
+ p += xsnprintf (p, endp - p, "vCont;c:");
+ p = write_ptid (p, endp, ptid);
+ }
}
- gdb_assert (outbuf && strlen (outbuf) < get_remote_packet_size ());
- old_cleanup = make_cleanup (xfree, outbuf);
-
- putpkt (outbuf);
-
- do_cleanups (old_cleanup);
+ gdb_assert (strlen (rs->buf) < get_remote_packet_size ());
+ putpkt (rs->buf);
return 1;
}
@@ -3446,8 +3580,7 @@ remote_wait (ptid_t ptid, struct target_
{
struct remote_state *rs = get_remote_state ();
struct remote_arch_state *rsa = get_remote_arch_state ();
- ULONGEST thread_num = -1;
- ULONGEST process_num = -1;
+ ptid_t event_ptid = null_ptid;
ULONGEST addr;
int solibs_changed = 0;
@@ -3542,10 +3675,7 @@ remote_wait (ptid_t ptid, struct target_
Packet: '%s'\n"),
p, buf);
if (strncmp (p, "thread", p1 - p) == 0)
- {
- p_temp = unpack_varlen_hex (++p1, &thread_num);
- p = p_temp;
- }
+ event_ptid = read_ptid (++p1, &p);
else if ((strncmp (p, "watch", p1 - p) == 0)
|| (strncmp (p, "rwatch", p1 - p) == 0)
|| (strncmp (p, "awatch", p1 - p) == 0))
@@ -3617,18 +3747,56 @@ Packet: '%s'\n"),
}
goto got_status;
case 'W': /* Target exited. */
+ case 'X':
{
- /* The remote process exited. */
- status->kind = TARGET_WAITKIND_EXITED;
- status->value.integer = (fromhex (buf[1]) << 4) + fromhex (buf[2]);
+ char *p;
+ int pid;
+ ULONGEST value;
+
+ /* GDB used to accept only 2 hex chars here. Stubs should
+ only send more if they detect GDB supports
+ multi-process support. */
+ p = unpack_varlen_hex (&buf[1], &value);
+
+ if (buf[0] == 'W')
+ {
+ /* The remote process exited. */
+ status->kind = TARGET_WAITKIND_EXITED;
+ status->value.integer = value;
+ }
+ else
+ {
+ /* The remote process exited with a signal. */
+ status->kind = TARGET_WAITKIND_SIGNALLED;
+ status->value.sig = (enum target_signal) value;
+ }
+
+ /* If no process is specified, assume inferior_ptid. */
+ pid = ptid_get_pid (inferior_ptid);
+ if (*p == '\0')
+ ;
+ else if (*p == ';')
+ {
+ p++;
+
+ if (p == '\0')
+ ;
+ else if (strncmp (p,
+ "process:", sizeof ("process:") - 1) == 0)
+ {
+ ULONGEST upid;
+ p += sizeof ("process:") - 1;
+ unpack_varlen_hex (p, &upid);
+ pid = upid;
+ }
+ else
+ error (_("unknown stop reply packet: %s"), buf);
+ }
+ else
+ error (_("unknown stop reply packet: %s"), buf);
+ event_ptid = ptid_build (pid, 0, 0);
goto got_status;
}
- case 'X':
- status->kind = TARGET_WAITKIND_SIGNALLED;
- status->value.sig = (enum target_signal)
- (((fromhex (buf[1])) << 4) + (fromhex (buf[2])));
-
- goto got_status;
case 'O': /* Console output. */
remote_console_output (buf + 1);
if (target_can_async_p ())
@@ -3663,15 +3831,21 @@ Packet: '%s'\n"),
}
}
got_status:
- if (thread_num != -1)
+ if (status->kind == TARGET_WAITKIND_EXITED
+ || status->kind == TARGET_WAITKIND_SIGNALLED)
{
- ptid_t ptid;
- ptid = ptid_build (ptid_get_pid (inferior_ptid), 0, thread_num);
- record_currthread (ptid);
- return ptid;
+ int pid = ptid_get_pid (event_ptid);
+ delete_inferior (pid);
+ }
+ else
+ {
+ if (!ptid_equal (event_ptid, null_ptid))
+ record_currthread (event_ptid);
+ else
+ event_ptid = inferior_ptid;
}
- return inferior_ptid;
+ return event_ptid;
}
/* Fetch a single register using a 'p' packet. */
@@ -4563,6 +4737,8 @@ remote_xfer_memory (CORE_ADDR mem_addr,
{
int res;
+ set_general_thread (inferior_ptid);
+
if (should_write)
res = remote_write_bytes (mem_addr, buffer, mem_len);
else
@@ -5187,6 +5363,58 @@ remote_kill (void)
target_mourn_inferior ();
}
+static int
+remote_vkill (int pid, struct remote_state *rs)
+{
+ if (remote_protocol_packets[PACKET_vKill].support == PACKET_DISABLE)
+ return -1;
+
+ /* Tell the remote target to detach. */
+ sprintf (rs->buf, "vKill;%x", pid);
+ putpkt (rs->buf);
+ getpkt (&rs->buf, &rs->buf_size, 0);
+
+ if (packet_ok (rs->buf,
+ &remote_protocol_packets[PACKET_vKill]) == PACKET_OK)
+ return 0;
+ else if (remote_protocol_packets[PACKET_vKill].support == PACKET_DISABLE)
+ return -1;
+ else
+ return 1;
+}
+
+static void
+extended_remote_kill (void)
+{
+ int res;
+ int pid = ptid_get_pid (inferior_ptid);
+ struct remote_state *rs = get_remote_state ();
+
+ res = remote_vkill (pid, rs);
+ if (res == -1 && !rs->multi_process_aware)
+ {
+ /* Don't try 'k' on a multi-process aware stub -- it has no way
+ to specify the pid. */
+
+ putpkt ("k");
+#if 0
+ getpkt (&rs->buf, &rs->buf_size, 0);
+ if (rs->buf[0] != 'O' || rs->buf[0] != 'K')
+ res = 1;
+#else
+ /* Don't wait for it to die. I'm not really sure it matters whether
+ we do or not. For the existing stubs, kill is a noop. */
+ res = 0;
+#endif
+ }
+
+ if (res != 0)
+ error (_("Can't kill process"));
+
+ delete_inferior (pid);
+ target_mourn_inferior ();
+}
+
static void
remote_mourn (void)
{
@@ -5201,6 +5429,19 @@ remote_mourn_1 (struct target_ops *targe
generic_mourn_inferior ();
}
+static int
+select_new_thread_callback (struct thread_info *th, void* data)
+{
+ if (!ptid_equal (th->ptid, minus_one_ptid))
+ {
+ switch_to_thread (th->ptid);
+ printf_filtered (_("[Switching to %s]\n"),
+ target_pid_to_str (inferior_ptid));
+ return 1;
+ }
+ return 0;
+}
+
static void
extended_remote_mourn_1 (struct target_ops *target)
{
@@ -5209,27 +5450,45 @@ extended_remote_mourn_1 (struct target_o
/* Unlike "target remote", we do not want to unpush the target; then
the next time the user says "run", we won't be connected. */
- /* Call common code to mark the inferior as not running. */
- generic_mourn_inferior ();
-
- /* Check whether the target is running now - some remote stubs
- automatically restart after kill. */
- putpkt ("?");
- getpkt (&rs->buf, &rs->buf_size, 0);
-
- if (rs->buf[0] == 'S' || rs->buf[0] == 'T')
+ if (have_inferiors ())
{
- /* Assume that the target has been restarted. Set inferior_ptid
- so that bits of core GDB realizes there's something here, e.g.,
- so that the user can say "kill" again. */
- inferior_ptid = remote_current_thread (magic_null_ptid);
- add_thread_silent (inferior_ptid);
+ extern void nullify_last_target_wait_ptid ();
+ /* Multi-process case. The current process has exited, but
+ there are other processes to debug. Switch to the first
+ available. */
+ iterate_over_threads (select_new_thread_callback, NULL);
+ nullify_last_target_wait_ptid ();
}
else
{
- /* Mark this (still pushed) target as not executable until we
- restart it. */
- target_mark_exited (target);
+ struct remote_state *rs = get_remote_state ();
+
+ /* Call common code to mark the inferior as not running. */
+ generic_mourn_inferior ();
+ if (!rs->multi_process_aware)
+ {
+ /* Check whether the target is running now - some remote stubs
+ automatically restart after kill. */
+ putpkt ("?");
+ getpkt (&rs->buf, &rs->buf_size, 0);
+
+ if (rs->buf[0] == 'S' || rs->buf[0] == 'T')
+ {
+ /* Assume that the target has been restarted. Set inferior_ptid
+ so that bits of core GDB realizes there's something here, e.g.,
+ so that the user can say "kill" again. */
+ inferior_ptid = magic_null_ptid;
+ }
+ else
+ {
+ /* Mark this (still pushed) target as not executable until we
+ restart it. */
+ target_mark_exited (target);
+ }
+ }
+ else
+ /* Always remove execution if this was the last process. */
+ target_mark_exited (target);
}
}
@@ -5339,6 +5598,7 @@ extended_remote_create_inferior_1 (char
attach_flag = 0;
inferior_ptid = magic_null_ptid;
+ add_inferior (ptid_get_pid (inferior_ptid));
add_thread_silent (inferior_ptid);
target_mark_running (&extended_remote_ops);
@@ -5548,7 +5808,7 @@ remote_check_watch_resources (int type,
static int
remote_stopped_by_watchpoint (void)
{
- return remote_stopped_by_watchpoint_p;
+ return remote_stopped_by_watchpoint_p;
}
static int
@@ -5906,11 +6166,15 @@ remote_xfer_partial (struct target_ops *
const char *annex, gdb_byte *readbuf,
const gdb_byte *writebuf, ULONGEST offset, LONGEST len)
{
- struct remote_state *rs = get_remote_state ();
+ struct remote_state *rs;
int i;
char *p2;
char query_type;
+ set_general_thread (inferior_ptid);
+
+ rs = get_remote_state ();
+
/* Handle memory using the standard memory routines. */
if (object == TARGET_OBJECT_MEMORY)
{
@@ -6389,12 +6653,20 @@ static char *
remote_pid_to_str (ptid_t ptid)
{
static char buf[64];
+ struct remote_state *rs = get_remote_state ();
if (ptid_equal (magic_null_ptid, ptid))
{
xsnprintf (buf, sizeof buf, "Thread <main>");
return buf;
}
+ else if (rs->multi_process_aware
+ && ptid_get_tid (ptid) != 0 && ptid_get_pid (ptid) != 0)
+ {
+ xsnprintf (buf, sizeof buf, "Thread %d.%ld",
+ ptid_get_pid (ptid), ptid_get_tid (ptid));
+ return buf;
+ }
else if (ptid_get_tid (ptid) != 0)
{
xsnprintf (buf, sizeof buf, "Thread %ld",
@@ -6415,11 +6687,12 @@ remote_get_thread_local_address (ptid_t
{
struct remote_state *rs = get_remote_state ();
char *p = rs->buf;
+ char *endp = rs->buf + get_remote_packet_size ();
enum packet_result result;
strcpy (p, "qGetTLSAddr:");
p += strlen (p);
- p += hexnumstr (p, ptid_get_tid (ptid));
+ p = write_ptid (p, endp, ptid);
*p++ = ',';
p += hexnumstr (p, offset);
*p++ = ',';
@@ -7325,6 +7598,7 @@ Specify the serial device it is connecte
extended_remote_ops.to_mourn_inferior = extended_remote_mourn;
extended_remote_ops.to_detach = extended_remote_detach;
extended_remote_ops.to_attach = extended_remote_attach;
+ extended_remote_ops.to_kill = extended_remote_kill;
}
static int
@@ -7656,6 +7930,9 @@ Show the maximum size of the address (in
add_packet_config_cmd (&remote_protocol_packets[PACKET_QStartNoAckMode],
"QStartNoAckMode", "noack", 0);
+ add_packet_config_cmd (&remote_protocol_packets[PACKET_vKill],
+ "vKill", "kill", 0);
+
/* Keep the old ``set remote Z-packet ...'' working. Each individual
Z sub-packet has its own set and show commands, but users may
have sets to this variable in their .gdbinit files (or in their
@@ -7700,7 +7977,7 @@ Show the remote pathname for \"run\""),
/* Take advantage of the fact that the LWP field is not used, to tag
special ptids with it set to != 0. */
- magic_null_ptid = ptid_build (0, 1, -1);
- not_sent_ptid = ptid_build (0, 1, -2);
- any_thread_ptid = ptid_build (0, 1, 0);
+ magic_null_ptid = ptid_build (42000, 1, -1);
+ not_sent_ptid = ptid_build (42000, 1, -2);
+ any_thread_ptid = ptid_build (42000, 1, 0);
}
Index: src/gdb/thread.c
===================================================================
--- src.orig/gdb/thread.c 2008-09-12 16:34:09.000000000 +0100
+++ src/gdb/thread.c 2008-09-12 17:31:27.000000000 +0100
@@ -466,7 +466,16 @@ prune_threads (void)
void
thread_change_ptid (ptid_t old_ptid, ptid_t new_ptid)
{
- struct thread_info * tp = find_thread_pid (old_ptid);
+ struct inferior *inf;
+ struct thread_info *tp;
+
+ /* It can happen that what we knew as the target inferior id
+ changes. E.g, target remote may only discover the remote process
+ pid after adding the inferior to GDB's list. */
+ inf = find_inferior_pid (ptid_get_pid (old_ptid));
+ inf->pid = ptid_get_pid (new_ptid);
+
+ tp = find_thread_pid (old_ptid);
tp->ptid = new_ptid;
observer_notify_thread_ptid_changed (old_ptid, new_ptid);