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: [gdbserver/RFA] decouple the target side from the remote protocol side.


On Monday 23 March 2009 03:54:35, Pedro Alves wrote:
> Hi,
> 
> This patch decouples the target implementation side from the remote
> procotol, mostly so that the target doesn't have to care as much
> about if multiprocess extensions are enabled.  As a bonus we get a bit
> of extra type safety (instead of passing strings around).
> 
> I've borrowed and adjusted several things from GDB.  Namely,
> target_waitkind, and target_waitstatus.  I'll then build on
> these to build an event queue in gdbserver common code for
> non-stop mode.  Future changes for multiprocess will further
> adjust the `target->wait' interface to return a ptid_t-like
> structure.
> 
> I've tested this on x86_64-linux.  I'll do some testing on cygwin
> as well, since I had to adjust all targets (linux, spu, win32) to
> the new interface.  Actually, win32-low.c was already using
> target_waitstatus internally, so the changes there were minimal, most
> related to dropping its private copy of target_waitstatus and friend.
> I adjusted spu-low.c as well, but unfortunately gets 0 testing from
> me :-/.  I hope I haven't messed it up too badly.

It required a couple of extra tweaks to build on Windows.  This version
now builds cleanly on Cygwin.  Here's the updated patch.

Note that this applies on top of these two patches, in this
order:

 http://sourceware.org/ml/gdb-patches/2009-03/msg00573.html
 http://sourceware.org/ml/gdb-patches/2009-03/msg00578.html

> 
> The changes to remote-utils.c are a bit hard to read due to indentation,
> so I've also appended a diff -upw of remote-utils.c below the patch.
> proper.  Look for the "SNIP" line.
> 
> Does it look OK?
> 

-- 
Pedro Alves

2009-03-25  Pedro Alves  <pedro@codesourcery.com>

	Decouple target code from remote protocol.

	* target.h (enum target_waitkind): New.
	(struct target_waitstatus): New.
	(struct target_ops) <wait>: Return an unsigned long.  Take a
	target_waitstatus pointer instead of a char pointer.
	(mywait): Likewise.
	* target.c (mywait): Change prototype to return an unsigned long.
	Take a target_waitstatus pointer instead of a char pointer.  Adjust.
	* server.h (thread_from_wait, old_thread_from_wait): Delete
	declarations.
	(prepare_resume_reply): Change prototype to take a
	target_waitstatus.
	* server.c (thread_from_wait, old_thread_from_wait): Delete.
	(last_status, last_ptid): New.
	(start_inferior): Remove "statusptr" argument.  Adjust.  Return a
	pid instead of a signal.
	(attach_inferior): Remove "status" and "signal" parameters.
	Adjust.
	(handle_query): For qGetTLSAddr, parse the thread id with strtol,
	not as an address.
	(handle_v_cont, handle_v_attach, handle_v_run, handle_v_kill)
	(handle_v_requests, myresume): Remove "status" and "signal"
	parameters.  Adjust.
	(handle_status): New.
	(main): Delete local `status'.  Adjust.
	* remote-utils.c: Include target.h.
	(prepare_resume_reply): Change prototype to take a
	target_waitstatus.  Adjust.

	* linux-low.c (linux_wait): Adjust to new target_ops->wait
	interface.
	* spu-low.c (spu_wait): Adjust.
	* win32-low.c (enum target_waitkind, struct target_waitstatus):
	Delete.
	(win32_wait): Adjust.

---
 gdb/gdbserver/linux-low.c    |   38 ++++++---
 gdb/gdbserver/remote-utils.c |  149 ++++++++++++++++++++-------------------
 gdb/gdbserver/server.c       |  164 ++++++++++++++++++++++++-------------------
 gdb/gdbserver/server.h       |    6 -
 gdb/gdbserver/spu-low.c      |   26 ++++--
 gdb/gdbserver/target.c       |    8 +-
 gdb/gdbserver/target.h       |   60 +++++++++++++--
 gdb/gdbserver/win32-low.c    |   69 +++---------------
 8 files changed, 289 insertions(+), 231 deletions(-)

Index: src/gdb/gdbserver/target.h
===================================================================
--- src.orig/gdb/gdbserver/target.h	2009-03-25 16:19:33.000000000 +0000
+++ src/gdb/gdbserver/target.h	2009-03-25 16:46:12.000000000 +0000
@@ -38,6 +38,53 @@ struct thread_resume
   int sig;
 };
 
+/* Generally, what has the program done?  */
+enum target_waitkind
+  {
+    /* The program has exited.  The exit status is in
+       value.integer.  */
+    TARGET_WAITKIND_EXITED,
+
+    /* The program has stopped with a signal.  Which signal is in
+       value.sig.  */
+    TARGET_WAITKIND_STOPPED,
+
+    /* The program has terminated with a signal.  Which signal is in
+       value.sig.  */
+    TARGET_WAITKIND_SIGNALLED,
+
+    /* The program is letting us know that it dynamically loaded
+       something.  */
+    TARGET_WAITKIND_LOADED,
+
+    /* The program has exec'ed a new executable file.  The new file's
+       pathname is pointed to by value.execd_pathname.  */
+    TARGET_WAITKIND_EXECD,
+
+    /* Nothing of interest to GDB happened, but we stopped anyway.  */
+    TARGET_WAITKIND_SPURIOUS,
+
+    /* An event has occurred, but we should wait again.  In this case,
+       we want to go back to the event loop and wait there for another
+       event from the inferior.  */
+    TARGET_WAITKIND_IGNORE
+  };
+
+struct target_waitstatus
+  {
+    enum target_waitkind kind;
+
+    /* Forked child pid, execd pathname, exit status or signal number.  */
+    union
+      {
+	int integer;
+	enum target_signal sig;
+	unsigned long related_pid;
+	char *execd_pathname;
+      }
+    value;
+  };
+
 struct target_ops
 {
   /* Start a new process.
@@ -82,15 +129,10 @@ struct target_ops
 
   void (*resume) (struct thread_resume *resume_info, size_t n);
 
-  /* Wait for the inferior process to change state.
-
-     STATUS will be filled in with a response code to send to GDB.
-
-     Returns the signal which caused the process to stop, in the
-     remote protocol numbering (e.g. TARGET_SIGNAL_STOP), or the
-     exit code as an integer if *STATUS is 'W'.  */
+  /* Wait for the inferior process or thread to change state.  Store
+     status through argument pointer STATUS.  */
 
-  unsigned char (*wait) (char *status);
+  unsigned long (*wait) (struct target_waitstatus *status);
 
   /* Fetch registers from the inferior process.
 
@@ -225,7 +267,7 @@ void set_target_ops (struct target_ops *
 #define join_inferior() \
   (*the_target->join) ()
 
-unsigned char mywait (char *statusp, int connected_wait);
+unsigned long mywait (struct target_waitstatus *ourstatus, int connected_wait);
 
 int read_inferior_memory (CORE_ADDR memaddr, unsigned char *myaddr, int len);
 
Index: src/gdb/gdbserver/target.c
===================================================================
--- src.orig/gdb/gdbserver/target.c	2009-03-25 16:13:54.000000000 +0000
+++ src/gdb/gdbserver/target.c	2009-03-25 16:45:52.000000000 +0000
@@ -88,15 +88,15 @@ write_inferior_memory (CORE_ADDR memaddr
   return res;
 }
 
-unsigned char
-mywait (char *statusp, int connected_wait)
+unsigned long
+mywait (struct target_waitstatus *ourstatus, int connected_wait)
 {
-  unsigned char ret;
+  unsigned long ret;
 
   if (connected_wait)
     server_waiting = 1;
 
-  ret = (*the_target->wait) (statusp);
+  ret = (*the_target->wait) (ourstatus);
 
   if (connected_wait)
     server_waiting = 0;
Index: src/gdb/gdbserver/server.h
===================================================================
--- src.orig/gdb/gdbserver/server.h	2009-03-25 16:13:54.000000000 +0000
+++ src/gdb/gdbserver/server.h	2009-03-25 16:45:52.000000000 +0000
@@ -160,8 +160,7 @@ void unloaded_dll (const char *name, COR
 extern unsigned long cont_thread;
 extern unsigned long general_thread;
 extern unsigned long step_thread;
-extern unsigned long thread_from_wait;
-extern unsigned long old_thread_from_wait;
+
 extern int server_waiting;
 extern int debug_threads;
 extern int pass_signals[];
@@ -201,7 +200,8 @@ void convert_ascii_to_int (char *from, u
 void convert_int_to_ascii (unsigned char *from, char *to, int n);
 void new_thread_notify (int id);
 void dead_thread_notify (int id);
-void prepare_resume_reply (char *buf, char status, unsigned char sig);
+void prepare_resume_reply (char *buf, unsigned long thread_id,
+			   struct target_waitstatus *status);
 
 const char *decode_address_to_semicolon (CORE_ADDR *addrp, const char *start);
 void decode_address (CORE_ADDR *addrp, const char *start, int len);
Index: src/gdb/gdbserver/server.c
===================================================================
--- src.orig/gdb/gdbserver/server.c	2009-03-25 16:19:33.000000000 +0000
+++ src/gdb/gdbserver/server.c	2009-03-25 16:45:52.000000000 +0000
@@ -35,8 +35,7 @@
 unsigned long cont_thread;
 unsigned long general_thread;
 unsigned long step_thread;
-unsigned long thread_from_wait;
-unsigned long old_thread_from_wait;
+
 int server_waiting;
 
 static int extended_protocol;
@@ -87,6 +86,10 @@ int disable_packet_Tthread;
 int disable_packet_qC;
 int disable_packet_qfThreadInfo;
 
+/* Last status reported to GDB.  */
+static struct target_waitstatus last_status;
+static unsigned long last_ptid;
+
 static int
 target_running (void)
 {
@@ -94,7 +97,7 @@ target_running (void)
 }
 
 static int
-start_inferior (char **argv, char *statusptr)
+start_inferior (char **argv)
 {
   char **new_argv = argv;
   attached = 0;
@@ -141,36 +144,38 @@ start_inferior (char **argv, char *statu
   if (wrapper_argv != NULL)
     {
       struct thread_resume resume_info;
-      int sig;
+      unsigned long ptid;
 
       resume_info.thread = -1;
       resume_info.step = 0;
       resume_info.sig = 0;
 
-      sig = mywait (statusptr, 0);
-      if (*statusptr != 'T')
-	return sig;
+      ptid = mywait (&last_status, 0);
+      if (last_status.kind != TARGET_WAITKIND_STOPPED)
+	return signal_pid;
 
       do
 	{
 	  (*the_target->resume) (&resume_info, 1);
 
-	  sig = mywait (statusptr, 0);
-	  if (*statusptr != 'T')
-	    return sig;
+ 	  mywait (&last_status, 0);
+	  if (last_status.kind != TARGET_WAITKIND_STOPPED)
+	    return signal_pid;
 	}
-      while (sig != TARGET_SIGNAL_TRAP);
+      while (last_status.value.sig != TARGET_SIGNAL_TRAP);
 
-      return sig;
+      return signal_pid;
     }
 
-  /* Wait till we are at 1st instruction in program, return signal
-     number (assuming success).  */
-  return mywait (statusptr, 0);
+  /* Wait till we are at 1st instruction in program, return new pid
+     (assuming success).  */
+  last_ptid = mywait (&last_status, 0);
+
+  return signal_pid;
 }
 
 static int
-attach_inferior (int pid, char *statusptr, int *sigptr)
+attach_inferior (int pid)
 {
   /* myattach should return -1 if attaching is unsupported,
      0 if it succeeded, and call error() otherwise.  */
@@ -188,13 +193,14 @@ attach_inferior (int pid, char *statuspt
      whichever we were told to attach to.  */
   signal_pid = pid;
 
-  *sigptr = mywait (statusptr, 0);
+  last_ptid = mywait (&last_status, 0);
 
   /* GDB knows to ignore the first SIGSTOP after attaching to a running
      process using the "attach" command, but this is different; it's
      just using "target remote".  Pretend it's just starting up.  */
-  if (*statusptr == 'T' && *sigptr == TARGET_SIGNAL_STOP)
-    *sigptr = TARGET_SIGNAL_TRAP;
+  if (last_status.kind == TARGET_WAITKIND_STOPPED
+      && last_status.value.sig == TARGET_SIGNAL_STOP)
+    last_status.value.sig = TARGET_SIGNAL_TRAP;
 
   return 0;
 }
@@ -917,8 +923,9 @@ handle_query (char *own_buf, int packet_
       && strncmp ("qGetTLSAddr:", own_buf, 12) == 0)
     {
       char *p = own_buf + 12;
-      CORE_ADDR parts[3], address = 0;
+      CORE_ADDR parts[2], address = 0;
       int i, err;
+      unsigned long ptid;
 
       require_running (own_buf);
 
@@ -942,7 +949,10 @@ handle_query (char *own_buf, int packet_
 	      p2 = NULL;
 	    }
 
-	  decode_address (&parts[i], p, len);
+	  if (i == 0)
+	    ptid = strtoul (p, NULL, 16);
+	  else
+	    decode_address (&parts[i - 1], p, len);
 	  p = p2;
 	}
 
@@ -950,12 +960,12 @@ handle_query (char *own_buf, int packet_
 	err = 1;
       else
 	{
-	  struct thread_info *thread = gdb_id_to_thread (parts[0]);
+	  struct thread_info *thread = gdb_id_to_thread (ptid);
 
 	  if (thread == NULL)
 	    err = 2;
 	  else
-	    err = the_target->get_tls_address (thread, parts[1], parts[2],
+	    err = the_target->get_tls_address (thread, parts[0], parts[1],
 					       &address);
 	}
 
@@ -1051,7 +1061,7 @@ handle_query (char *own_buf, int packet_
 
 /* Parse vCont packets.  */
 void
-handle_v_cont (char *own_buf, char *status, int *signal)
+handle_v_cont (char *own_buf)
 {
   char *p, *q;
   int n = 0, i = 0;
@@ -1145,8 +1155,8 @@ handle_v_cont (char *own_buf, char *stat
 
   free (resume_info);
 
-  *signal = mywait (status, 1);
-  prepare_resume_reply (own_buf, *status, *signal);
+  last_ptid = mywait (&last_status, 1);
+  prepare_resume_reply (own_buf, last_ptid, &last_status);
   disable_async_io ();
   return;
 
@@ -1158,19 +1168,19 @@ err:
 
 /* Attach to a new program.  Return 1 if successful, 0 if failure.  */
 int
-handle_v_attach (char *own_buf, char *status, int *signal)
+handle_v_attach (char *own_buf)
 {
   int pid;
 
   pid = strtol (own_buf + 8, NULL, 16);
-  if (pid != 0 && attach_inferior (pid, status, signal) == 0)
+  if (pid != 0 && attach_inferior (pid) == 0)
     {
       /* Don't report shared library events after attaching, even if
 	 some libraries are preloaded.  GDB will always poll the
 	 library list.  Avoids the "stopped by shared library event"
 	 notice on the GDB side.  */
       dlls_changed = 0;
-      prepare_resume_reply (own_buf, *status, *signal);
+      prepare_resume_reply (own_buf, last_ptid, &last_status);
       return 1;
     }
   else
@@ -1182,7 +1192,7 @@ handle_v_attach (char *own_buf, char *st
 
 /* Run a new program.  Return 1 if successful, 0 if failure.  */
 static int
-handle_v_run (char *own_buf, char *status, int *signal)
+handle_v_run (char *own_buf)
 {
   char *p, *next_p, **new_argv;
   int i, new_argc;
@@ -1249,10 +1259,10 @@ handle_v_run (char *own_buf, char *statu
   freeargv (program_argv);
   program_argv = new_argv;
 
-  *signal = start_inferior (program_argv, status);
-  if (*status == 'T')
+  start_inferior (program_argv);
+  if (last_status.kind == TARGET_WAITKIND_STOPPED)
     {
-      prepare_resume_reply (own_buf, *status, *signal);
+      prepare_resume_reply (own_buf, last_ptid, &last_status);
       return 1;
     }
   else
@@ -1264,15 +1274,14 @@ handle_v_run (char *own_buf, char *statu
 
 /* Handle all of the extended 'v' packets.  */
 void
-handle_v_requests (char *own_buf, char *status, int *signal,
-		   int packet_len, int *new_packet_len)
+handle_v_requests (char *own_buf, int packet_len, int *new_packet_len)
 {
   if (!disable_packet_vCont)
     {
       if (strncmp (own_buf, "vCont;", 6) == 0)
 	{
 	  require_running (own_buf);
-	  handle_v_cont (own_buf, status, signal);
+	  handle_v_cont (own_buf);
 	  return;
 	}
 
@@ -1295,7 +1304,7 @@ handle_v_requests (char *own_buf, char *
 	  write_enn (own_buf);
 	  return;
 	}
-      handle_v_attach (own_buf, status, signal);
+      handle_v_attach (own_buf);
       return;
     }
 
@@ -1307,7 +1316,7 @@ handle_v_requests (char *own_buf, char *
 	  write_enn (own_buf);
 	  return;
 	}
-      handle_v_run (own_buf, status, signal);
+      handle_v_run (own_buf);
       return;
     }
 
@@ -1318,11 +1327,10 @@ handle_v_requests (char *own_buf, char *
 }
 
 void
-myresume (char *own_buf, int step, int *signalp, char *statusp)
+myresume (char *own_buf, int step, int sig)
 {
   struct thread_resume resume_info[2];
   int n = 0;
-  int sig = *signalp;
   int valid_cont_thread;
 
   set_desired_inferior (0);
@@ -1348,11 +1356,23 @@ myresume (char *own_buf, int step, int *
 
   enable_async_io ();
   (*the_target->resume) (resume_info, n);
-  *signalp = mywait (statusp, 1);
-  prepare_resume_reply (own_buf, *statusp, *signalp);
+  last_ptid = mywait (&last_status, 1);
+  prepare_resume_reply (own_buf, last_ptid, &last_status);
   disable_async_io ();
 }
 
+/* Status handler for the '?' packet.  */
+
+static void
+handle_status (char *own_buf)
+{
+  if (all_threads.head)
+    prepare_resume_reply (own_buf,
+			  all_threads.head->id, &last_status);
+  else
+    strcpy (own_buf, "W00");
+}
+
 static void
 gdbserver_version (void)
 {
@@ -1405,7 +1425,7 @@ gdbserver_show_disableable (FILE *stream
 int
 main (int argc, char *argv[])
 {
-  char ch, status, *own_buf;
+  char ch, *own_buf;
   unsigned char *mem_buf;
   int i = 0;
   int signal;
@@ -1562,7 +1582,7 @@ main (int argc, char *argv[])
       program_argv[i] = NULL;
 
       /* Wait till we are at first instruction in program.  */
-      signal = start_inferior (program_argv, &status);
+      start_inferior (program_argv);
 
       /* We are now (hopefully) stopped at the first instruction of
 	 the target process.  This assumes that the target process was
@@ -1570,15 +1590,16 @@ main (int argc, char *argv[])
     }
   else if (pid != 0)
     {
-      if (attach_inferior (pid, &status, &signal) == -1)
+      if (attach_inferior (pid) == -1)
 	error ("Attaching not supported on this target");
 
       /* Otherwise succeeded.  */
     }
   else
     {
-      status = 'W';
-      signal = 0;
+      last_status.kind = TARGET_WAITKIND_EXITED;
+      last_status.value.integer = 0;
+      last_ptid = -1;
     }
 
   /* Don't report shared library events on the initial connection,
@@ -1593,7 +1614,8 @@ main (int argc, char *argv[])
       exit (1);
     }
 
-  if (status == 'W' || status == 'X')
+  if (last_status.kind == TARGET_WAITKIND_EXITED
+      || last_status.kind == TARGET_WAITKIND_SIGNALLED)
     was_running = 0;
   else
     was_running = 1;
@@ -1655,8 +1677,9 @@ main (int argc, char *argv[])
 		  if (extended_protocol)
 		    {
 		      /* Treat this like a normal program exit.  */
-		      signal = 0;
-		      status = 'W';
+		      last_status.kind = TARGET_WAITKIND_EXITED;
+		      last_status.value.integer = 0;
+		      last_ptid = signal_pid;
 		    }
 		  else
 		    {
@@ -1678,7 +1701,7 @@ main (int argc, char *argv[])
 	      write_ok (own_buf);
 	      break;
 	    case '?':
-	      prepare_resume_reply (own_buf, status, signal);
+	      handle_status (own_buf);
 	      break;
 	    case 'H':
 	      if (own_buf[1] == 'c' || own_buf[1] == 'g' || own_buf[1] == 's')
@@ -1761,7 +1784,7 @@ main (int argc, char *argv[])
 		signal = target_signal_to_host (sig);
 	      else
 		signal = 0;
-	      myresume (own_buf, 0, &signal, &status);
+	      myresume (own_buf, 0, signal);
 	      break;
 	    case 'S':
 	      require_running (own_buf);
@@ -1770,17 +1793,17 @@ main (int argc, char *argv[])
 		signal = target_signal_to_host (sig);
 	      else
 		signal = 0;
-	      myresume (own_buf, 1, &signal, &status);
+	      myresume (own_buf, 1, signal);
 	      break;
 	    case 'c':
 	      require_running (own_buf);
 	      signal = 0;
-	      myresume (own_buf, 0, &signal, &status);
+	      myresume (own_buf, 0, signal);
 	      break;
 	    case 's':
 	      require_running (own_buf);
 	      signal = 0;
-	      myresume (own_buf, 1, &signal, &status);
+	      myresume (own_buf, 1, signal);
 	      break;
 	    case 'Z':
 	      {
@@ -1859,8 +1882,8 @@ main (int argc, char *argv[])
 		 instead.  */
 	      if (extended_protocol)
 		{
-		  status = 'X';
-		  signal = TARGET_SIGNAL_KILL;
+		  last_status.kind = TARGET_WAITKIND_EXITED;
+		  last_status.value.sig = TARGET_SIGNAL_KILL;
 		  was_running = 0;
 		  goto restart;
 		}
@@ -1901,11 +1924,11 @@ main (int argc, char *argv[])
 
 		  /* Wait till we are at 1st instruction in prog.  */
 		  if (program_argv != NULL)
-		    signal = start_inferior (program_argv, &status);
+		    start_inferior (program_argv);
 		  else
 		    {
-		      status = 'X';
-		      signal = TARGET_SIGNAL_KILL;
+		      last_status.kind = TARGET_WAITKIND_EXITED;
+		      last_status.value.sig = TARGET_SIGNAL_KILL;
 		    }
 		  goto restart;
 		}
@@ -1919,8 +1942,7 @@ main (int argc, char *argv[])
 		}
 	    case 'v':
 	      /* Extended (long) request.  */
-	      handle_v_requests (own_buf, &status, &signal,
-				 packet_len, &new_packet_len);
+	      handle_v_requests (own_buf, packet_len, &new_packet_len);
 	      break;
 
 	    default:
@@ -1938,17 +1960,20 @@ main (int argc, char *argv[])
 
 	  response_needed = 0;
 
-	  if (was_running && (status == 'W' || status == 'X'))
+	  if (was_running
+	      && (last_status.kind == TARGET_WAITKIND_EXITED
+		  || last_status.kind == TARGET_WAITKIND_SIGNALLED))
 	    {
 	      was_running = 0;
 
-	      if (status == 'W')
+	      if (last_status.kind == TARGET_WAITKIND_EXITED)
 		fprintf (stderr,
-			 "\nChild exited with status %d\n", signal);
-	      if (status == 'X')
+			 "\nChild exited with status %d\n",
+			 last_status.value.integer);
+	      else if (last_status.kind == TARGET_WAITKIND_SIGNALLED)
 		fprintf (stderr, "\nChild terminated with signal = 0x%x (%s)\n",
-			 target_signal_to_host (signal),
-			 target_signal_to_name (signal));
+			 target_signal_to_host (last_status.value.sig),
+			 target_signal_to_name (last_status.value.sig));
 
 	      if (extended_protocol)
 		goto restart;
@@ -1959,7 +1984,8 @@ main (int argc, char *argv[])
 		}
 	    }
 
-	  if (status != 'W' && status != 'X')
+	  if (last_status.kind != TARGET_WAITKIND_EXITED
+	      && last_status.kind != TARGET_WAITKIND_SIGNALLED)
 	    was_running = 1;
 	}
 
Index: src/gdb/gdbserver/remote-utils.c
===================================================================
--- src.orig/gdb/gdbserver/remote-utils.c	2009-03-25 16:13:54.000000000 +0000
+++ src/gdb/gdbserver/remote-utils.c	2009-03-25 16:45:52.000000000 +0000
@@ -20,6 +20,7 @@
 
 #include "server.h"
 #include "terminal.h"
+#include "target.h"
 #include <stdio.h>
 #include <string.h>
 #if HAVE_SYS_IOCTL_H
@@ -933,88 +934,98 @@ dead_thread_notify (int id)
 }
 
 void
-prepare_resume_reply (char *buf, char status, unsigned char sig)
+prepare_resume_reply (char *buf, unsigned long ptid,
+		      struct target_waitstatus *status)
 {
-  int nib;
-
-  *buf++ = status;
+  if (debug_threads)
+    fprintf (stderr, "Writing resume reply for %lu:%d\n\n",
+	     ptid, status->kind);
 
-  nib = ((sig & 0xf0) >> 4);
-  *buf++ = tohex (nib);
-  nib = sig & 0x0f;
-  *buf++ = tohex (nib);
-
-  if (status == 'T')
+  switch (status->kind)
     {
-      const char **regp = gdbserver_expedite_regs;
+    case TARGET_WAITKIND_STOPPED:
+      {
+	struct thread_info *saved_inferior;
+	const char **regp;
 
-      if (the_target->stopped_by_watchpoint != NULL
-	  && (*the_target->stopped_by_watchpoint) ())
-	{
-	  CORE_ADDR addr;
-	  int i;
+	sprintf (buf, "T%02x", status->value.sig);
+	buf += strlen (buf);
 
-	  strncpy (buf, "watch:", 6);
-	  buf += 6;
+	regp = gdbserver_expedite_regs;
 
-	  addr = (*the_target->stopped_data_address) ();
+	saved_inferior = current_inferior;
 
-	  /* Convert each byte of the address into two hexadecimal chars.
-	     Note that we take sizeof (void *) instead of sizeof (addr);
-	     this is to avoid sending a 64-bit address to a 32-bit GDB.  */
-	  for (i = sizeof (void *) * 2; i > 0; i--)
-	    {
-	      *buf++ = tohex ((addr >> (i - 1) * 4) & 0xf);
-	    }
-	  *buf++ = ';';
-	}
+	current_inferior = gdb_id_to_thread (ptid);
 
-      while (*regp)
-	{
-	  buf = outreg (find_regno (*regp), buf);
-	  regp ++;
-	}
+	if (the_target->stopped_by_watchpoint != NULL
+	    && (*the_target->stopped_by_watchpoint) ())
+	  {
+	    CORE_ADDR addr;
+	    int i;
 
-      /* Formerly, if the debugger had not used any thread features we would not
-	 burden it with a thread status response.  This was for the benefit of
-	 GDB 4.13 and older.  However, in recent GDB versions the check
-	 (``if (cont_thread != 0)'') does not have the desired effect because of
-	 sillyness in the way that the remote protocol handles specifying a thread.
-	 Since thread support relies on qSymbol support anyway, assume GDB can handle
-	 threads.  */
+	    strncpy (buf, "watch:", 6);
+	    buf += 6;
 
-      if (using_threads && !disable_packet_Tthread)
-	{
-	  unsigned int gdb_id_from_wait;
+	    addr = (*the_target->stopped_data_address) ();
 
-	  /* FIXME right place to set this? */
-	  thread_from_wait = ((struct inferior_list_entry *)current_inferior)->id;
-	  gdb_id_from_wait = thread_to_gdb_id (current_inferior);
-
-	  if (debug_threads)
-	    fprintf (stderr, "Writing resume reply for %ld\n\n", thread_from_wait);
-	  /* This if (1) ought to be unnecessary.  But remote_wait in GDB
-	     will claim this event belongs to inferior_ptid if we do not
-	     specify a thread, and there's no way for gdbserver to know
-	     what inferior_ptid is.  */
-	  if (1 || old_thread_from_wait != thread_from_wait)
-	    {
-	      general_thread = thread_from_wait;
-	      sprintf (buf, "thread:%x;", gdb_id_from_wait);
-	      buf += strlen (buf);
-	      old_thread_from_wait = thread_from_wait;
-	    }
-	}
+	    /* Convert each byte of the address into two hexadecimal
+	       chars.  Note that we take sizeof (void *) instead of
+	       sizeof (addr); this is to avoid sending a 64-bit
+	       address to a 32-bit GDB.  */
+	    for (i = sizeof (void *) * 2; i > 0; i--)
+	      *buf++ = tohex ((addr >> (i - 1) * 4) & 0xf);
+	    *buf++ = ';';
+	  }
 
-      if (dlls_changed)
-	{
-	  strcpy (buf, "library:;");
-	  buf += strlen (buf);
-	  dlls_changed = 0;
-	}
+	while (*regp)
+	  {
+	    buf = outreg (find_regno (*regp), buf);
+	    regp ++;
+	  }
+
+	/* Formerly, if the debugger had not used any thread features
+	   we would not burden it with a thread status response.  This
+	   was for the benefit of GDB 4.13 and older.  However, in
+	   recent GDB versions the check (``if (cont_thread != 0)'')
+	   does not have the desired effect because of sillyness in
+	   the way that the remote protocol handles specifying a
+	   thread.  Since thread support relies on qSymbol support
+	   anyway, assume GDB can handle threads.  */
+
+	if (using_threads && !disable_packet_Tthread)
+	  {
+	    /* This if (1) ought to be unnecessary.  But remote_wait
+	       in GDB will claim this event belongs to inferior_ptid
+	       if we do not specify a thread, and there's no way for
+	       gdbserver to know what inferior_ptid is.  */
+	    if (1 || general_thread != ptid)
+	      {
+		general_thread = ptid;
+		sprintf (buf, "thread:%lx;", ptid);
+		buf += strlen (buf);
+	      }
+	  }
+
+	if (dlls_changed)
+	  {
+	    strcpy (buf, "library:;");
+	    buf += strlen (buf);
+	    dlls_changed = 0;
+	  }
+
+	current_inferior = saved_inferior;
+      }
+      break;
+    case TARGET_WAITKIND_EXITED:
+      sprintf (buf, "W%02x", status->value.integer);
+      break;
+    case TARGET_WAITKIND_SIGNALLED:
+      sprintf (buf, "X%02x", status->value.sig);
+      break;
+    default:
+      error ("unhandled waitkind");
+      break;
     }
-  /* For W and X, we're done.  */
-  *buf++ = 0;
 }
 
 void
Index: src/gdb/gdbserver/linux-low.c
===================================================================
--- src.orig/gdb/gdbserver/linux-low.c	2009-03-25 16:19:33.000000000 +0000
+++ src/gdb/gdbserver/linux-low.c	2009-03-25 16:45:52.000000000 +0000
@@ -929,11 +929,12 @@ linux_wait_for_event (struct thread_info
 
 /* Wait for process, returns status.  */
 
-static unsigned char
-linux_wait (char *status)
+static unsigned long
+linux_wait (struct target_waitstatus *ourstatus)
 {
   int w;
   struct thread_info *child = NULL;
+  struct lwp_info *lwp;
 
 retry:
   /* If we were only supposed to resume one thread, only wait for
@@ -966,6 +967,8 @@ retry:
       must_set_ptrace_flags = 0;
     }
 
+  lwp = get_thread_lwp (current_inferior);
+
   /* If we are waiting for a particular child, and it exited,
      linux_wait_for_event will return its exit status.  Similarly if
      the last child exited.  If this is not the last child, however,
@@ -980,25 +983,34 @@ retry:
 
   if (all_threads.head == all_threads.tail)
     {
+      int pid = pid_of (lwp);
       if (WIFEXITED (w))
 	{
-	  fprintf (stderr, "\nChild exited with retcode = %x \n",
-		   WEXITSTATUS (w));
-	  *status = 'W';
+	  if (debug_threads)
+	    fprintf (stderr, "\nChild exited with retcode = %x \n",
+		     WEXITSTATUS (w));
+
+	  ourstatus->kind = TARGET_WAITKIND_EXITED;
+	  ourstatus->value.integer = WEXITSTATUS (w);
 	  clear_inferiors ();
 	  free (all_lwps.head);
 	  all_lwps.head = all_lwps.tail = NULL;
-	  return WEXITSTATUS (w);
+
+	  return pid;
 	}
       else if (!WIFSTOPPED (w))
 	{
-	  fprintf (stderr, "\nChild terminated with signal = %x \n",
-		   WTERMSIG (w));
-	  *status = 'X';
+	  if (debug_threads)
+	    fprintf (stderr, "\nChild terminated with signal = %x \n",
+		     WTERMSIG (w));
+
+	  ourstatus->kind = TARGET_WAITKIND_SIGNALLED;
+	  ourstatus->value.sig = target_signal_from_host (WTERMSIG (w));
 	  clear_inferiors ();
 	  free (all_lwps.head);
 	  all_lwps.head = all_lwps.tail = NULL;
-	  return target_signal_from_host (WTERMSIG (w));
+
+	  return pid;
 	}
     }
   else
@@ -1007,8 +1019,10 @@ retry:
 	goto retry;
     }
 
-  *status = 'T';
-  return target_signal_from_host (WSTOPSIG (w));
+  ourstatus->kind = TARGET_WAITKIND_STOPPED;
+  ourstatus->value.sig = target_signal_from_host (WSTOPSIG (w));
+
+  return lwp->lwpid;
 }
 
 /* Send a signal to an LWP.  For LinuxThreads, kill is enough; however, if
Index: src/gdb/gdbserver/spu-low.c
===================================================================
--- src.orig/gdb/gdbserver/spu-low.c	2009-03-25 16:19:33.000000000 +0000
+++ src/gdb/gdbserver/spu-low.c	2009-03-25 16:21:18.000000000 +0000
@@ -371,8 +371,8 @@ spu_resume (struct thread_resume *resume
 }
 
 /* Wait for process, returns status.  */
-static unsigned char
-spu_wait (char *status)
+static unsigned long
+spu_wait (struct target_waitstatus *ourstatus)
 {
   int tid = current_tid;
   int w;
@@ -407,31 +407,37 @@ spu_wait (char *status)
 	}
     }
 
+  ret = current_tid;
+
   if (WIFEXITED (w))
     {
       fprintf (stderr, "\nChild exited with retcode = %x \n", WEXITSTATUS (w));
-      *status = 'W';
+      ourstatus->kind =  TARGET_WAITKIND_EXITED;
+      ourstatus->value.integer = WEXITSTATUS (w);
       clear_inferiors ();
-      return ((unsigned char) WEXITSTATUS (w));
+      return ret;
     }
   else if (!WIFSTOPPED (w))
     {
       fprintf (stderr, "\nChild terminated with signal = %x \n", WTERMSIG (w));
-      *status = 'X';
+      ourstatus->kind = TARGET_WAITKIND_SIGNALLED;
+      ourstatus->value.sig = target_signal_from_host (WTERMSIG (w));
       clear_inferiors ();
-      return ((unsigned char) WTERMSIG (w));
+      return ret;
     }
 
   /* After attach, we may have received a SIGSTOP.  Do not return this
      as signal to GDB, or else it will try to continue with SIGSTOP ...  */
   if (!server_waiting)
     {
-      *status = 'T';
-      return 0;
+      ourstatus->kind = TARGET_WAITKIND_STOPPED;
+      ourstatus->value.sig = TARGET_SIGNAL_0;
+      return ret;
     }
 
-  *status = 'T';
-  return ((unsigned char) WSTOPSIG (w));
+  ourstatus->kind = TARGET_WAITKIND_STOPPED;
+  ourstatus->value.sig = target_signal_from_host (WSTOPSIG (w));
+  return ret;
 }
 
 /* Fetch inferior registers.  */
Index: src/gdb/gdbserver/win32-low.c
===================================================================
--- src.orig/gdb/gdbserver/win32-low.c	2009-03-25 16:19:33.000000000 +0000
+++ src/gdb/gdbserver/win32-low.c	2009-03-25 16:46:12.000000000 +0000
@@ -241,45 +241,6 @@ child_xfer_memory (CORE_ADDR memaddr, ch
   return done;
 }
 
-/* Generally, what has the program done?  */
-enum target_waitkind
-{
-  /* The program has exited.  The exit status is in value.integer.  */
-  TARGET_WAITKIND_EXITED,
-
-  /* The program has stopped with a signal.  Which signal is in
-     value.sig.  */
-  TARGET_WAITKIND_STOPPED,
-
-  /* The program is letting us know that it dynamically loaded
-     or unloaded something.  */
-  TARGET_WAITKIND_LOADED,
-
-  /* The program has exec'ed a new executable file.  The new file's
-     pathname is pointed to by value.execd_pathname.  */
-  TARGET_WAITKIND_EXECD,
-
-  /* Nothing interesting happened, but we stopped anyway.  We take the
-     chance to check if GDB requested an interrupt.  */
-  TARGET_WAITKIND_SPURIOUS,
-};
-
-struct target_waitstatus
-{
-  enum target_waitkind kind;
-
-  /* Forked child pid, execd pathname, exit status or signal number.  */
-  union
-  {
-    int integer;
-    enum target_signal sig;
-    int related_pid;
-    char *execd_pathname;
-    int syscall_id;
-  }
-  value;
-};
-
 /* Clear out any old thread list and reinitialize it to a pristine
    state. */
 static void
@@ -1514,37 +1475,30 @@ get_child_debug_event (struct target_wai
 /* Wait for the inferior process to change state.
    STATUS will be filled in with a response code to send to GDB.
    Returns the signal which caused the process to stop. */
-static unsigned char
-win32_wait (char *status)
+static unsigned long
+win32_wait (struct target_waitstatus *ourstatus)
 {
-  struct target_waitstatus our_status;
-
-  *status = 'T';
-
   while (1)
     {
-      if (!get_child_debug_event (&our_status))
+      if (!get_child_debug_event (ourstatus))
 	continue;
 
-      switch (our_status.kind)
+      switch (ourstatus->kind)
 	{
 	case TARGET_WAITKIND_EXITED:
 	  OUTMSG2 (("Child exited with retcode = %x\n",
-		    our_status.value.integer));
+		    ourstatus->value.integer));
 
-	  *status = 'W';
 	  win32_clear_inferiors ();
-	  return our_status.value.integer;
+	  return current_event.dwProcessId;
 	case TARGET_WAITKIND_STOPPED:
 	case TARGET_WAITKIND_LOADED:
 	  OUTMSG2 (("Child Stopped with signal = %d \n",
 		    our_status.value.sig));
 
-	  *status = 'T';
-
 	  child_fetch_inferior_registers (-1);
 
-	  if (our_status.kind == TARGET_WAITKIND_LOADED
+	  if (ourstatus->kind == TARGET_WAITKIND_LOADED
 	      && !server_waiting)
 	    {
 	      /* When gdb connects, we want to be stopped at the
@@ -1553,9 +1507,14 @@ win32_wait (char *status)
 	      break;
 	    }
 
-	  return our_status.value.sig;
+	  /* We don't expose _LOADED events to gdbserver core.  See
+	     the `dlls_changed' global.  */
+	  if (ourstatus->kind == TARGET_WAITKIND_LOADED)
+	    ourstatus->kind = TARGET_WAITKIND_STOPPED;
+
+	  return current_event.dwThreadId;
 	default:
-	  OUTMSG (("Ignoring unknown internal event, %d\n", our_status.kind));
+	  OUTMSG (("Ignoring unknown internal event, %d\n", ourstatus->kind));
 	  /* fall-through */
 	case TARGET_WAITKIND_SPURIOUS:
 	case TARGET_WAITKIND_EXECD:


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