This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [RFA 03/08] multi-process support: remote multi-process extensions


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

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]