]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - gdb/gdbserver/server.c
Add selftests run filtering
[thirdparty/binutils-gdb.git] / gdb / gdbserver / server.c
index fd5f6dc7458750b55fd19c13dc00470b1741290c..99dedb2fed923f6be6eea3188f98e0e1c6b39928 100644 (file)
@@ -1,5 +1,5 @@
 /* Main code for remote server for GDB.
-   Copyright (C) 1989-2015 Free Software Foundation, Inc.
+   Copyright (C) 1989-2017 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -22,7 +22,7 @@
 #include "notif.h"
 #include "tdesc.h"
 #include "rsp-low.h"
-
+#include "signals-state-save-restore.h"
 #include <ctype.h>
 #include <unistd.h>
 #if HAVE_SIGNAL_H
 #include "tracepoint.h"
 #include "dll.h"
 #include "hostio.h"
+#include <vector>
+#include "common-inferior.h"
+#include "job-control.h"
+#include "environ.h"
+
+#include "common/selftest.h"
+
+#define require_running_or_return(BUF)         \
+  if (!target_running ())                      \
+    {                                          \
+      write_enn (BUF);                         \
+      return;                                  \
+    }
+
+#define require_running_or_break(BUF)          \
+  if (!target_running ())                      \
+    {                                          \
+      write_enn (BUF);                         \
+      break;                                   \
+    }
+
+/* The environment to pass to the inferior when creating it.  */
+
+static gdb_environ our_environ;
+
+/* Start the inferior using a shell.  */
+
+/* We always try to start the inferior using a shell.  */
+
+int startup_with_shell = 1;
 
 /* The thread set with an `Hc' packet.  `Hc' is deprecated in favor of
    `vCont'.  Note the multi-process extensions made `vCont' a
@@ -59,15 +89,28 @@ int run_once;
 int multi_process;
 int report_fork_events;
 int report_vfork_events;
+int report_exec_events;
+int report_thread_events;
+
+/* Whether to report TARGET_WAITKING_NO_RESUMED events.  */
+static int report_no_resumed;
+
 int non_stop;
 int swbreak_feature;
 int hwbreak_feature;
 
+/* True if the "vContSupported" feature is active.  In that case, GDB
+   wants us to report whether single step is supported in the reply to
+   "vCont?" packet.  */
+static int vCont_supported;
+
 /* Whether we should attempt to disable the operating system's address
    space randomization feature before starting an inferior.  */
 int disable_randomization = 1;
 
-static char **program_argv, **wrapper_argv;
+static char *program_name = NULL;
+static std::vector<char *> program_args;
+static std::string wrapper_argv;
 
 int pass_signals[GDB_SIGNAL_LAST];
 int program_signals[GDB_SIGNAL_LAST];
@@ -80,22 +123,6 @@ int program_signals_p;
 
 unsigned long signal_pid;
 
-#ifdef SIGTTOU
-/* A file descriptor for the controlling terminal.  */
-int terminal_fd;
-
-/* TERMINAL_FD's original foreground group.  */
-pid_t old_foreground_pgrp;
-
-/* Hand back terminal ownership to the original foreground group.  */
-
-static void
-restore_old_foreground_pgrp (void)
-{
-  tcsetpgrp (terminal_fd, old_foreground_pgrp);
-}
-#endif
-
 /* Set if you want to disable optional thread related packets support
    in gdbserver, for the sake of testing GDB against stubs that don't
    support them.  */
@@ -105,10 +132,10 @@ int disable_packet_qC;
 int disable_packet_qfThreadInfo;
 
 /* Last status reported to GDB.  */
-static struct target_waitstatus last_status;
-static ptid_t last_ptid;
+struct target_waitstatus last_status;
+ptid_t last_ptid;
 
-static char *own_buf;
+char *own_buf;
 static unsigned char *mem_buf;
 
 /* A sub-class of 'struct notif_event' for stop, holding information
@@ -137,7 +164,7 @@ DEFINE_QUEUE_P (notif_event_p);
 static void
 queue_stop_reply (ptid_t ptid, struct target_waitstatus *status)
 {
-  struct vstop_notif *new_notif = xmalloc (sizeof (*new_notif));
+  struct vstop_notif *new_notif = XNEW (struct vstop_notif);
 
   new_notif->ptid = ptid;
   new_notif->status = *status;
@@ -146,15 +173,15 @@ queue_stop_reply (ptid_t ptid, struct target_waitstatus *status)
 }
 
 static int
-remove_all_on_match_pid (QUEUE (notif_event_p) *q,
-                           QUEUE_ITER (notif_event_p) *iter,
-                           struct notif_event *event,
-                           void *data)
+remove_all_on_match_ptid (QUEUE (notif_event_p) *q,
+                         QUEUE_ITER (notif_event_p) *iter,
+                         struct notif_event *event,
+                         void *data)
 {
-  int *pid = data;
+  ptid_t filter_ptid = *(ptid_t *) data;
+  struct vstop_notif *vstop_event = (struct vstop_notif *) event;
 
-  if (*pid == -1
-      || ptid_get_pid (((struct vstop_notif *) event)->ptid) == *pid)
+  if (ptid_match (vstop_event->ptid, filter_ptid))
     {
       if (q->free_func != NULL)
        q->free_func (event);
@@ -165,14 +192,13 @@ remove_all_on_match_pid (QUEUE (notif_event_p) *q,
   return 1;
 }
 
-/* Get rid of the currently pending stop replies for PID.  If PID is
-   -1, then apply to all processes.  */
+/* See server.h.  */
 
-static void
-discard_queued_stop_replies (int pid)
+void
+discard_queued_stop_replies (ptid_t ptid)
 {
   QUEUE_iterate (notif_event_p, notif_stop.queue,
-                remove_all_on_match_pid, &pid);
+                remove_all_on_match_ptid, &ptid);
 }
 
 static void
@@ -183,113 +209,74 @@ vstop_notif_reply (struct notif_event *event, char *own_buf)
   prepare_resume_reply (own_buf, vstop->ptid, &vstop->status);
 }
 
-struct notif_server notif_stop =
-{
-  "vStopped", "Stop", NULL, vstop_notif_reply,
-};
+/* QUEUE_iterate callback helper for in_queued_stop_replies.  */
 
 static int
-target_running (void)
+in_queued_stop_replies_ptid (QUEUE (notif_event_p) *q,
+                            QUEUE_ITER (notif_event_p) *iter,
+                            struct notif_event *event,
+                            void *data)
 {
-  return get_first_thread () != NULL;
-}
-
-static int
-start_inferior (char **argv)
-{
-  char **new_argv = argv;
-
-  if (wrapper_argv != NULL)
-    {
-      int i, count = 1;
-
-      for (i = 0; wrapper_argv[i] != NULL; i++)
-       count++;
-      for (i = 0; argv[i] != NULL; i++)
-       count++;
-      new_argv = alloca (sizeof (char *) * count);
-      count = 0;
-      for (i = 0; wrapper_argv[i] != NULL; i++)
-       new_argv[count++] = wrapper_argv[i];
-      for (i = 0; argv[i] != NULL; i++)
-       new_argv[count++] = argv[i];
-      new_argv[count] = NULL;
-    }
-
-  if (debug_threads)
-    {
-      int i;
-      for (i = 0; new_argv[i]; ++i)
-       debug_printf ("new_argv[%d] = \"%s\"\n", i, new_argv[i]);
-      debug_flush ();
-    }
-
-#ifdef SIGTTOU
-  signal (SIGTTOU, SIG_DFL);
-  signal (SIGTTIN, SIG_DFL);
-#endif
+  ptid_t filter_ptid = *(ptid_t *) data;
+  struct vstop_notif *vstop_event = (struct vstop_notif *) event;
 
-  signal_pid = create_inferior (new_argv[0], new_argv);
+  if (ptid_match (vstop_event->ptid, filter_ptid))
+    return 0;
 
-  /* FIXME: we don't actually know at this point that the create
-     actually succeeded.  We won't know that until we wait.  */
-  fprintf (stderr, "Process %s created; pid = %ld\n", argv[0],
-          signal_pid);
-  fflush (stderr);
+  /* Don't resume fork children that GDB does not know about yet.  */
+  if ((vstop_event->status.kind == TARGET_WAITKIND_FORKED
+       || vstop_event->status.kind == TARGET_WAITKIND_VFORKED)
+      && ptid_match (vstop_event->status.value.related_pid, filter_ptid))
+    return 0;
 
-#ifdef SIGTTOU
-  signal (SIGTTOU, SIG_IGN);
-  signal (SIGTTIN, SIG_IGN);
-  terminal_fd = fileno (stderr);
-  old_foreground_pgrp = tcgetpgrp (terminal_fd);
-  tcsetpgrp (terminal_fd, signal_pid);
-  atexit (restore_old_foreground_pgrp);
-#endif
+  return 1;
+}
 
-  if (wrapper_argv != NULL)
-    {
-      struct thread_resume resume_info;
+/* See server.h.  */
 
-      memset (&resume_info, 0, sizeof (resume_info));
-      resume_info.thread = pid_to_ptid (signal_pid);
-      resume_info.kind = resume_continue;
-      resume_info.sig = 0;
+int
+in_queued_stop_replies (ptid_t ptid)
+{
+  return !QUEUE_iterate (notif_event_p, notif_stop.queue,
+                        in_queued_stop_replies_ptid, &ptid);
+}
 
-      last_ptid = mywait (pid_to_ptid (signal_pid), &last_status, 0, 0);
+struct notif_server notif_stop =
+{
+  "vStopped", "Stop", NULL, vstop_notif_reply,
+};
 
-      if (last_status.kind != TARGET_WAITKIND_STOPPED)
-       return signal_pid;
+static int
+target_running (void)
+{
+  return get_first_thread () != NULL;
+}
 
-      do
-       {
-         (*the_target->resume) (&resume_info, 1);
+/* See common/common-inferior.h.  */
 
-         last_ptid = mywait (pid_to_ptid (signal_pid), &last_status, 0, 0);
-         if (last_status.kind != TARGET_WAITKIND_STOPPED)
-           return signal_pid;
+const char *
+get_exec_wrapper ()
+{
+  return !wrapper_argv.empty () ? wrapper_argv.c_str () : NULL;
+}
 
-         current_thread->last_resume_kind = resume_stop;
-         current_thread->last_status = last_status;
-       }
-      while (last_status.value.sig != GDB_SIGNAL_TRAP);
+/* See common/common-inferior.h.  */
 
-      return signal_pid;
-    }
+char *
+get_exec_file (int err)
+{
+  if (err && program_name == NULL)
+    error (_("No executable file specified."));
 
-  /* Wait till we are at 1st instruction in program, return new pid
-     (assuming success).  */
-  last_ptid = mywait (pid_to_ptid (signal_pid), &last_status, 0, 0);
+  return program_name;
+}
 
-  if (last_status.kind != TARGET_WAITKIND_EXITED
-      && last_status.kind != TARGET_WAITKIND_SIGNALLED)
-    {
-      current_thread->last_resume_kind = resume_stop;
-      current_thread->last_status = last_status;
-    }
-  else
-    mourn_inferior (find_process_pid (ptid_get_pid (last_ptid)));
+/* See server.h.  */
 
-  return signal_pid;
+gdb_environ *
+get_environ ()
+{
+  return &our_environ;
 }
 
 static int
@@ -378,7 +365,7 @@ decode_xfer (char *buf, char **object, char **rw, char **annex, char **offset)
    to as much of DATA/LEN as we could fit.  IS_MORE controls
    the first character of the response.  */
 static int
-write_qxfer_response (char *buf, const void *data, int len, int is_more)
+write_qxfer_response (char *buf, const gdb_byte *data, int len, int is_more)
 {
   int out_len;
 
@@ -408,7 +395,7 @@ handle_btrace_enable_bts (struct thread_info *thread)
   return NULL;
 }
 
-/* Handle btrace enabling in Intel(R) Processor Trace format.  */
+/* Handle btrace enabling in Intel Processor Trace format.  */
 
 static const char *
 handle_btrace_enable_pt (struct thread_info *thread)
@@ -612,12 +599,121 @@ handle_general_set (char *own_buf)
       return;
     }
 
+  if (startswith (own_buf, "QCatchSyscalls:"))
+    {
+      const char *p = own_buf + sizeof ("QCatchSyscalls:") - 1;
+      int enabled = -1;
+      CORE_ADDR sysno;
+      struct process_info *process;
+
+      if (!target_running () || !target_supports_catch_syscall ())
+       {
+         write_enn (own_buf);
+         return;
+       }
+
+      if (strcmp (p, "0") == 0)
+       enabled = 0;
+      else if (p[0] == '1' && (p[1] == ';' || p[1] == '\0'))
+       enabled = 1;
+      else
+       {
+         fprintf (stderr, "Unknown catch-syscalls mode requested: %s\n",
+                  own_buf);
+         write_enn (own_buf);
+         return;
+       }
+
+      process = current_process ();
+      VEC_truncate (int, process->syscalls_to_catch, 0);
+
+      if (enabled)
+       {
+         p += 1;
+         if (*p == ';')
+           {
+             p += 1;
+             while (*p != '\0')
+               {
+                 p = decode_address_to_semicolon (&sysno, p);
+                 VEC_safe_push (int, process->syscalls_to_catch, (int) sysno);
+               }
+           }
+         else
+           VEC_safe_push (int, process->syscalls_to_catch, ANY_SYSCALL);
+       }
+
+      write_ok (own_buf);
+      return;
+    }
+
+  if (strcmp (own_buf, "QEnvironmentReset") == 0)
+    {
+      our_environ = gdb_environ::from_host_environ ();
+
+      write_ok (own_buf);
+      return;
+    }
+
+  if (startswith (own_buf, "QEnvironmentHexEncoded:"))
+    {
+      const char *p = own_buf + sizeof ("QEnvironmentHexEncoded:") - 1;
+      /* The final form of the environment variable.  FINAL_VAR will
+        hold the 'VAR=VALUE' format.  */
+      std::string final_var = hex2str (p);
+      std::string var_name, var_value;
+
+      if (remote_debug)
+       {
+         debug_printf (_("[QEnvironmentHexEncoded received '%s']\n"), p);
+         debug_printf (_("[Environment variable to be set: '%s']\n"),
+                       final_var.c_str ());
+         debug_flush ();
+       }
+
+      size_t pos = final_var.find ('=');
+      if (pos == std::string::npos)
+       {
+         warning (_("Unexpected format for environment variable: '%s'"),
+                  final_var.c_str ());
+         write_enn (own_buf);
+         return;
+       }
+
+      var_name = final_var.substr (0, pos);
+      var_value = final_var.substr (pos + 1, std::string::npos);
+
+      our_environ.set (var_name.c_str (), var_value.c_str ());
+
+      write_ok (own_buf);
+      return;
+    }
+
+  if (startswith (own_buf, "QEnvironmentUnset:"))
+    {
+      const char *p = own_buf + sizeof ("QEnvironmentUnset:") - 1;
+      std::string varname = hex2str (p);
+
+      if (remote_debug)
+       {
+         debug_printf (_("[QEnvironmentUnset received '%s']\n"), p);
+         debug_printf (_("[Environment variable to be unset: '%s']\n"),
+                       varname.c_str ());
+         debug_flush ();
+       }
+
+      our_environ.unset (varname.c_str ());
+
+      write_ok (own_buf);
+      return;
+    }
+
   if (strcmp (own_buf, "QStartNoAckMode") == 0)
     {
       if (remote_debug)
        {
-         fprintf (stderr, "[noack mode enabled]\n");
-         fflush (stderr);
+         debug_printf ("[noack mode enabled]\n");
+         debug_flush ();
        }
 
       noack_mode = 1;
@@ -656,7 +752,7 @@ handle_general_set (char *own_buf)
       non_stop = req;
 
       if (remote_debug)
-       fprintf (stderr, "[%s mode enabled]\n", req_str);
+       debug_printf ("[%s mode enabled]\n", req_str);
 
       write_ok (own_buf);
       return;
@@ -672,10 +768,9 @@ handle_general_set (char *own_buf)
 
       if (remote_debug)
        {
-         if (disable_randomization)
-           fprintf (stderr, "[address space randomization disabled]\n");
-         else
-           fprintf (stderr, "[address space randomization enabled]\n");
+         debug_printf (disable_randomization
+                       ? "[address space randomization disabled]\n"
+                       : "[address space randomization enabled]\n");
        }
 
       write_ok (own_buf);
@@ -705,7 +800,7 @@ handle_general_set (char *own_buf)
       /* Update the flag.  */
       use_agent = req;
       if (remote_debug)
-       fprintf (stderr, "[%s agent]\n", req ? "Enable" : "Disable");
+       debug_printf ("[%s agent]\n", req ? "Enable" : "Disable");
       write_ok (own_buf);
       return;
     }
@@ -716,6 +811,64 @@ handle_general_set (char *own_buf)
   if (handle_btrace_conf_general_set (own_buf))
     return;
 
+  if (startswith (own_buf, "QThreadEvents:"))
+    {
+      char *mode = own_buf + strlen ("QThreadEvents:");
+      enum tribool req = TRIBOOL_UNKNOWN;
+
+      if (strcmp (mode, "0") == 0)
+       req = TRIBOOL_FALSE;
+      else if (strcmp (mode, "1") == 0)
+       req = TRIBOOL_TRUE;
+      else
+       {
+         char *mode_copy = xstrdup (mode);
+
+         /* We don't know what this mode is, so complain to GDB.  */
+         sprintf (own_buf, "E.Unknown thread-events mode requested: %s\n",
+                  mode_copy);
+         xfree (mode_copy);
+         return;
+       }
+
+      report_thread_events = (req == TRIBOOL_TRUE);
+
+      if (remote_debug)
+       {
+         const char *req_str = report_thread_events ? "enabled" : "disabled";
+
+         debug_printf ("[thread events are now %s]\n", req_str);
+       }
+
+      write_ok (own_buf);
+      return;
+    }
+
+  if (startswith (own_buf, "QStartupWithShell:"))
+    {
+      const char *value = own_buf + strlen ("QStartupWithShell:");
+
+      if (strcmp (value, "1") == 0)
+       startup_with_shell = true;
+      else if (strcmp (value, "0") == 0)
+       startup_with_shell = false;
+      else
+       {
+         /* Unknown value.  */
+         fprintf (stderr, "Unknown value to startup-with-shell: %s\n",
+                  own_buf);
+         write_enn (own_buf);
+         return;
+       }
+
+      if (remote_debug)
+       debug_printf (_("[Inferior will %s started with shell]"),
+                     startup_with_shell ? "be" : "not be");
+
+      write_ok (own_buf);
+      return;
+    }
+
   /* Otherwise we didn't know what packet it was.  Say we didn't
      understand it.  */
   own_buf[0] = 0;
@@ -734,12 +887,14 @@ get_features_xml (const char *annex)
      This variable is set up from the auto-generated
      init_registers_... routine for the current target.  */
 
-  if (desc->xmltarget != NULL && strcmp (annex, "target.xml") == 0)
+  if (strcmp (annex, "target.xml") == 0)
     {
-      if (*desc->xmltarget == '@')
-       return desc->xmltarget + 1;
+      const char *ret = tdesc_get_features_xml ((target_desc*) desc);
+
+      if (*ret == '@')
+       return ret + 1;
       else
-       annex = desc->xmltarget;
+       annex = ret;
     }
 
 #ifdef USE_XML
@@ -760,7 +915,7 @@ get_features_xml (const char *annex)
   return NULL;
 }
 
-void
+static void
 monitor_show_help (void)
 {
   monitor_output ("The following monitor commands are supported:\n");
@@ -814,7 +969,10 @@ gdb_read_memory (CORE_ADDR memaddr, unsigned char *myaddr, int len)
   res = prepare_to_access_memory ();
   if (res == 0)
     {
-      res = read_inferior_memory (memaddr, myaddr, len);
+      if (set_desired_thread (1))
+       res = read_inferior_memory (memaddr, myaddr, len);
+      else
+       res = 1;
       done_accessing_memory ();
 
       return res == 0 ? len : -1;
@@ -838,7 +996,10 @@ gdb_write_memory (CORE_ADDR memaddr, const unsigned char *myaddr, int len)
       ret = prepare_to_access_memory ();
       if (ret == 0)
        {
-         ret = write_inferior_memory (memaddr, myaddr, len);
+         if (set_desired_thread (1))
+           ret = write_inferior_memory (memaddr, myaddr, len);
+         else
+           ret = EIO;
          done_accessing_memory ();
        }
       return ret;
@@ -878,7 +1039,8 @@ handle_search_memory_1 (CORE_ADDR start_addr, CORE_ADDR search_space_len,
                                  ? search_space_len
                                  : search_buf_size);
 
-      found_ptr = memmem (search_buf, nr_search_bytes, pattern, pattern_len);
+      found_ptr = (gdb_byte *) memmem (search_buf, nr_search_bytes, pattern,
+                                      pattern_len);
 
       if (found_ptr != NULL)
        {
@@ -946,7 +1108,7 @@ handle_search_memory (char *own_buf, int packet_len)
   CORE_ADDR found_addr;
   int cmd_name_len = sizeof ("qSearch:memory:") - 1;
 
-  pattern = malloc (packet_len);
+  pattern = (gdb_byte *) malloc (packet_len);
   if (pattern == NULL)
     {
       error ("Unable to allocate memory to perform the search");
@@ -970,7 +1132,7 @@ handle_search_memory (char *own_buf, int packet_len)
   if (search_space_len < search_buf_size)
     search_buf_size = search_space_len;
 
-  search_buf = malloc (search_buf_size);
+  search_buf = (gdb_byte *) malloc (search_buf_size);
   if (search_buf == NULL)
     {
       free (pattern);
@@ -995,12 +1157,99 @@ handle_search_memory (char *own_buf, int packet_len)
   free (pattern);
 }
 
-#define require_running(BUF)                   \
-  if (!target_running ())                      \
-    {                                          \
-      write_enn (BUF);                         \
-      return;                                  \
+/* Handle the "D" packet.  */
+
+static void
+handle_detach (char *own_buf)
+{
+  require_running_or_return (own_buf);
+
+  int pid;
+
+  if (multi_process)
+    {
+      /* skip 'D;' */
+      pid = strtol (&own_buf[2], NULL, 16);
     }
+  else
+    pid = ptid_get_pid (current_ptid);
+
+  if ((tracing && disconnected_tracing) || any_persistent_commands ())
+    {
+      struct process_info *process = find_process_pid (pid);
+
+      if (process == NULL)
+       {
+         write_enn (own_buf);
+         return;
+       }
+
+      if (tracing && disconnected_tracing)
+       fprintf (stderr,
+                "Disconnected tracing in effect, "
+                "leaving gdbserver attached to the process\n");
+
+      if (any_persistent_commands ())
+       fprintf (stderr,
+                "Persistent commands are present, "
+                "leaving gdbserver attached to the process\n");
+
+      /* Make sure we're in non-stop/async mode, so we we can both
+        wait for an async socket accept, and handle async target
+        events simultaneously.  There's also no point either in
+        having the target stop all threads, when we're going to
+        pass signals down without informing GDB.  */
+      if (!non_stop)
+       {
+         if (debug_threads)
+           debug_printf ("Forcing non-stop mode\n");
+
+         non_stop = 1;
+         start_non_stop (1);
+       }
+
+      process->gdb_detached = 1;
+
+      /* Detaching implicitly resumes all threads.  */
+      target_continue_no_signal (minus_one_ptid);
+
+      write_ok (own_buf);
+      return;
+    }
+
+  fprintf (stderr, "Detaching from process %d\n", pid);
+  stop_tracing ();
+  if (detach_inferior (pid) != 0)
+    write_enn (own_buf);
+  else
+    {
+      discard_queued_stop_replies (pid_to_ptid (pid));
+      write_ok (own_buf);
+
+      if (extended_protocol || target_running ())
+       {
+         /* There is still at least one inferior remaining or
+            we are in extended mode, so don't terminate gdbserver,
+            and instead treat this like a normal program exit.  */
+         last_status.kind = TARGET_WAITKIND_EXITED;
+         last_status.value.integer = 0;
+         last_ptid = pid_to_ptid (pid);
+
+         current_thread = NULL;
+       }
+      else
+       {
+         putpkt (own_buf);
+         remote_close ();
+
+         /* If we are attached, then we can exit.  Otherwise, we
+            need to hang around doing nothing, until the child is
+            gone.  */
+         join_inferior (pid);
+         exit (0);
+       }
+    }
+}
 
 /* Parse options to --debug-format= and "monitor set debug-format".
    ARG is the text after "--debug-format=" or "monitor set debug-format".
@@ -1169,7 +1418,7 @@ handle_qxfer_auxv (const char *annex,
   if (the_target->read_auxv == NULL || writebuf != NULL)
     return -2;
 
-  if (annex[0] != '\0' || !target_running ())
+  if (annex[0] != '\0' || current_thread == NULL)
     return -1;
 
   return (*the_target->read_auxv) (offset, readbuf, len);
@@ -1198,7 +1447,7 @@ handle_qxfer_exec_file (const char *const_annex,
     }
   else
     {
-      char *annex = alloca (strlen (const_annex) + 1);
+      char *annex = (char *) alloca (strlen (const_annex) + 1);
 
       strcpy (annex, const_annex);
       annex = unpack_varlen_hex (annex, &pid);
@@ -1267,7 +1516,7 @@ static void
 accumulate_file_name_length (struct inferior_list_entry *inf, void *arg)
 {
   struct dll_info *dll = (struct dll_info *) inf;
-  unsigned int *total_len = arg;
+  unsigned int *total_len = (unsigned int *) arg;
 
   /* Over-estimate the necessary memory.  Assume that every character
      in the library name must be escaped.  */
@@ -1281,7 +1530,7 @@ static void
 emit_dll_description (struct inferior_list_entry *inf, void *arg)
 {
   struct dll_info *dll = (struct dll_info *) inf;
-  char **p_ptr = arg;
+  char **p_ptr = (char **) arg;
   char *p = *p_ptr;
   char *name;
 
@@ -1314,14 +1563,14 @@ handle_qxfer_libraries (const char *annex,
   if (writebuf != NULL)
     return -2;
 
-  if (annex[0] != '\0' || !target_running ())
+  if (annex[0] != '\0' || current_thread == NULL)
     return -1;
 
   total_len = 64;
   for_each_inferior_with_data (&all_dlls, accumulate_file_name_length,
                               &total_len);
 
-  document = malloc (total_len);
+  document = (char *) malloc (total_len);
   if (document == NULL)
     return -1;
 
@@ -1358,7 +1607,7 @@ handle_qxfer_libraries_svr4 (const char *annex,
   if (writebuf != NULL)
     return -2;
 
-  if (!target_running () || the_target->qxfer_libraries_svr4 == NULL)
+  if (current_thread == NULL || the_target->qxfer_libraries_svr4 == NULL)
     return -1;
 
   return the_target->qxfer_libraries_svr4 (annex, readbuf, writebuf, offset, len);
@@ -1387,7 +1636,7 @@ handle_qxfer_siginfo (const char *annex,
   if (the_target->qxfer_siginfo == NULL)
     return -2;
 
-  if (annex[0] != '\0' || !target_running ())
+  if (annex[0] != '\0' || current_thread == NULL)
     return -1;
 
   return (*the_target->qxfer_siginfo) (annex, readbuf, writebuf, offset, len);
@@ -1403,7 +1652,7 @@ handle_qxfer_spu (const char *annex,
   if (the_target->qxfer_spu == NULL)
     return -2;
 
-  if (!target_running ())
+  if (current_thread == NULL)
     return -1;
 
   return (*the_target->qxfer_spu) (annex, readbuf, writebuf, offset, len);
@@ -1421,7 +1670,7 @@ handle_qxfer_statictrace (const char *annex,
   if (writebuf != NULL)
     return -2;
 
-  if (annex[0] != '\0' || !target_running () || current_traceframe == -1)
+  if (annex[0] != '\0' || current_thread == NULL || current_traceframe == -1)
     return -1;
 
   if (traceframe_read_sdata (current_traceframe, offset,
@@ -1437,25 +1686,27 @@ static void
 handle_qxfer_threads_worker (struct inferior_list_entry *inf, void *arg)
 {
   struct thread_info *thread = (struct thread_info *) inf;
-  struct buffer *buffer = arg;
-  ptid_t ptid = thread_to_gdb_id (thread);
+  struct buffer *buffer = (struct buffer *) arg;
+  ptid_t ptid = ptid_of (thread);
   char ptid_s[100];
   int core = target_core_of_thread (ptid);
   char core_s[21];
+  const char *name = target_thread_name (ptid);
 
   write_ptid (ptid_s, ptid);
 
+  buffer_xml_printf (buffer, "<thread id=\"%s\"", ptid_s);
+
   if (core != -1)
     {
       sprintf (core_s, "%d", core);
-      buffer_xml_printf (buffer, "<thread id=\"%s\" core=\"%s\"/>\n",
-                        ptid_s, core_s);
-    }
-  else
-    {
-      buffer_xml_printf (buffer, "<thread id=\"%s\"/>\n",
-                        ptid_s);
+      buffer_xml_printf (buffer, " core=\"%s\"", core_s);
     }
+
+  if (name != NULL)
+    buffer_xml_printf (buffer, " name=\"%s\"", name);
+
+  buffer_xml_printf (buffer, "/>\n");
 }
 
 /* Helper for handle_qxfer_threads.  */
@@ -1484,7 +1735,7 @@ handle_qxfer_threads (const char *annex,
   if (writebuf != NULL)
     return -2;
 
-  if (!target_running () || annex[0] != '\0')
+  if (annex[0] != '\0')
     return -1;
 
   if (offset == 0)
@@ -1580,7 +1831,7 @@ handle_qxfer_fdpic (const char *annex, gdb_byte *readbuf,
   if (the_target->read_loadmap == NULL)
     return -2;
 
-  if (!target_running ())
+  if (current_thread == NULL)
     return -1;
 
   return (*the_target->read_loadmap) (annex, offset, readbuf, len);
@@ -1595,14 +1846,12 @@ handle_qxfer_btrace (const char *annex,
 {
   static struct buffer cache;
   struct thread_info *thread;
-  int type, result;
+  enum btrace_read_type type;
+  int result;
 
   if (the_target->read_btrace == NULL || writebuf != NULL)
     return -2;
 
-  if (!target_running ())
-    return -1;
-
   if (ptid_equal (general_thread, null_ptid)
       || ptid_equal (general_thread, minus_one_ptid))
     {
@@ -1674,7 +1923,7 @@ handle_qxfer_btrace_conf (const char *annex,
   if (the_target->read_btrace_conf == NULL || writebuf != NULL)
     return -2;
 
-  if (annex[0] != '\0' || !target_running ())
+  if (annex[0] != '\0')
     return -1;
 
   if (ptid_equal (general_thread, null_ptid)
@@ -1785,7 +2034,7 @@ handle_qxfer (char *own_buf, int packet_len, int *new_packet_len_p)
                 more.  */
              if (len > PBUFSIZ - 2)
                len = PBUFSIZ - 2;
-             data = malloc (len + 1);
+             data = (unsigned char *) malloc (len + 1);
              if (data == NULL)
                {
                  write_enn (own_buf);
@@ -1819,7 +2068,7 @@ handle_qxfer (char *own_buf, int packet_len, int *new_packet_len_p)
              unsigned char *data;
 
              strcpy (own_buf, "E00");
-             data = malloc (packet_len - (offset - own_buf));
+             data = (unsigned char *) malloc (packet_len - (offset - own_buf));
              if (data == NULL)
                {
                  write_enn (own_buf);
@@ -1859,11 +2108,6 @@ handle_qxfer (char *own_buf, int packet_len, int *new_packet_len_p)
   return 0;
 }
 
-/* Table used by the crc32 function to calcuate the checksum.  */
-
-static unsigned int crc32_table[256] =
-{0, 0};
-
 /* Compute 32 bit CRC from inferior memory.
 
    On success, return 32 bit CRC.
@@ -1872,20 +2116,6 @@ static unsigned int crc32_table[256] =
 static unsigned long long
 crc32 (CORE_ADDR base, int len, unsigned int crc)
 {
-  if (!crc32_table[1])
-    {
-      /* Initialize the CRC table and the decoding table.  */
-      int i, j;
-      unsigned int c;
-
-      for (i = 0; i < 256; i++)
-       {
-         for (c = i << 24, j = 8; j > 0; --j)
-           c = c & 0x80000000 ? (c << 1) ^ 0x04c11db7 : (c << 1);
-         crc32_table[i] = c;
-       }
-    }
-
   while (len--)
     {
       unsigned char byte = 0;
@@ -1894,7 +2124,7 @@ crc32 (CORE_ADDR base, int len, unsigned int crc)
       if (read_inferior_memory (base, &byte, 1) != 0)
        return (unsigned long long) -1;
 
-      crc = (crc << 8) ^ crc32_table[((crc >> 24) ^ byte) & 255];
+      crc = xcrc32 (&byte, 1, crc);
       base++;
     }
   return (unsigned long long) crc;
@@ -1933,7 +2163,7 @@ supported_btrace_packets (char *buf)
 
 /* Handle all of the extended 'q' packets.  */
 
-void
+static void
 handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
 {
   static struct inferior_list_entry *thread_ptr;
@@ -1941,26 +2171,47 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
   /* Reply the current thread id.  */
   if (strcmp ("qC", own_buf) == 0 && !disable_packet_qC)
     {
-      ptid_t gdb_id;
-      require_running (own_buf);
+      ptid_t ptid;
+      require_running_or_return (own_buf);
 
-      if (!ptid_equal (general_thread, null_ptid)
-         && !ptid_equal (general_thread, minus_one_ptid))
-       gdb_id = general_thread;
+      if (general_thread != null_ptid && general_thread != minus_one_ptid)
+       ptid = general_thread;
       else
        {
          thread_ptr = get_first_inferior (&all_threads);
-         gdb_id = thread_to_gdb_id ((struct thread_info *)thread_ptr);
+         ptid = thread_ptr->id;
        }
 
       sprintf (own_buf, "QC");
       own_buf += 2;
-      write_ptid (own_buf, gdb_id);
+      write_ptid (own_buf, ptid);
       return;
     }
 
   if (strcmp ("qSymbol::", own_buf) == 0)
     {
+      struct thread_info *save_thread = current_thread;
+
+      /* For qSymbol, GDB only changes the current thread if the
+        previous current thread was of a different process.  So if
+        the previous thread is gone, we need to pick another one of
+        the same process.  This can happen e.g., if we followed an
+        exec in a non-leader thread.  */
+      if (current_thread == NULL)
+       {
+         current_thread
+           = find_any_thread_of_pid (ptid_get_pid (general_thread));
+
+         /* Just in case, if we didn't find a thread, then bail out
+            instead of crashing.  */
+         if (current_thread == NULL)
+           {
+             write_enn (own_buf);
+             current_thread = save_thread;
+             return;
+           }
+       }
+
       /* GDB is suggesting new symbols have been loaded.  This may
         mean a new shared library has been detected as loaded, so
         take the opportunity to check if breakpoints we think are
@@ -1976,9 +2227,11 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
       if (target_supports_tracepoints ())
        tracepoint_look_up_symbols ();
 
-      if (target_running () && the_target->look_up_symbols != NULL)
+      if (current_thread != NULL && the_target->look_up_symbols != NULL)
        (*the_target->look_up_symbols) ();
 
+      current_thread = save_thread;
+
       strcpy (own_buf, "OK");
       return;
     }
@@ -1987,28 +2240,22 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
     {
       if (strcmp ("qfThreadInfo", own_buf) == 0)
        {
-         ptid_t gdb_id;
-
-         require_running (own_buf);
+         require_running_or_return (own_buf);
          thread_ptr = get_first_inferior (&all_threads);
 
          *own_buf++ = 'm';
-         gdb_id = thread_to_gdb_id ((struct thread_info *)thread_ptr);
-         write_ptid (own_buf, gdb_id);
+         write_ptid (own_buf, thread_ptr->id);
          thread_ptr = thread_ptr->next;
          return;
        }
 
       if (strcmp ("qsThreadInfo", own_buf) == 0)
        {
-         ptid_t gdb_id;
-
-         require_running (own_buf);
+         require_running_or_return (own_buf);
          if (thread_ptr != NULL)
            {
              *own_buf++ = 'm';
-             gdb_id = thread_to_gdb_id ((struct thread_info *)thread_ptr);
-             write_ptid (own_buf, gdb_id);
+             write_ptid (own_buf, thread_ptr->id);
              thread_ptr = thread_ptr->next;
              return;
            }
@@ -2025,7 +2272,7 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
     {
       CORE_ADDR text, data;
 
-      require_running (own_buf);
+      require_running_or_return (own_buf);
       if (the_target->read_offsets (&text, &data))
        sprintf (own_buf, "Text=%lX;Data=%lX;Bss=%lX",
                 (long)text, (long)data, (long)data);
@@ -2042,9 +2289,6 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
       char *p = &own_buf[10];
       int gdb_supports_qRelocInsn = 0;
 
-      /* Start processing qSupported packet.  */
-      target_process_qsupported (NULL);
-
       /* Process each feature being provided by GDB.  The first
         feature will follow a ':', and latter features will follow
         ';'.  */
@@ -2052,6 +2296,7 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
        {
          char **qsupported = NULL;
          int count = 0;
+         int unknown = 0;
          int i;
 
          /* Two passes, to avoid nested strtok calls in
@@ -2061,7 +2306,7 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
               p = strtok (NULL, ";"))
            {
              count++;
-             qsupported = xrealloc (qsupported, count * sizeof (char *));
+             qsupported = XRESIZEVEC (char *, qsupported, count);
              qsupported[count - 1] = xstrdup (p);
            }
 
@@ -2107,19 +2352,49 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
                  if (target_supports_vfork_events ())
                    report_vfork_events = 1;
                }
+             else if (strcmp (p, "exec-events+") == 0)
+               {
+                 /* GDB supports and wants exec events if possible.  */
+                 if (target_supports_exec_events ())
+                   report_exec_events = 1;
+               }
+             else if (strcmp (p, "vContSupported+") == 0)
+               vCont_supported = 1;
+             else if (strcmp (p, "QThreadEvents+") == 0)
+               ;
+             else if (strcmp (p, "no-resumed+") == 0)
+               {
+                 /* GDB supports and wants TARGET_WAITKIND_NO_RESUMED
+                    events.  */
+                 report_no_resumed = 1;
+               }
              else
-               target_process_qsupported (p);
-
-             free (p);
+               {
+                 /* Move the unknown features all together.  */
+                 qsupported[i] = NULL;
+                 qsupported[unknown] = p;
+                 unknown++;
+               }
            }
 
+         /* Give the target backend a chance to process the unknown
+            features.  */
+         target_process_qsupported (qsupported, unknown);
+
+         for (i = 0; i < count; i++)
+           free (qsupported[i]);
          free (qsupported);
        }
 
       sprintf (own_buf,
-              "PacketSize=%x;QPassSignals+;QProgramSignals+",
+              "PacketSize=%x;QPassSignals+;QProgramSignals+;"
+              "QStartupWithShell+;QEnvironmentHexEncoded+;"
+              "QEnvironmentReset+;QEnvironmentUnset+",
               PBUFSIZ - 1);
 
+      if (target_supports_catch_syscall ())
+       strcat (own_buf, ";QCatchSyscalls+");
+
       if (the_target->qxfer_libraries_svr4 != NULL)
        strcat (own_buf, ";qXfer:libraries-svr4:read+"
                ";augmented-libraries-svr4-read+");
@@ -2163,6 +2438,9 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
       if (target_supports_vfork_events ())
        strcat (own_buf, ";vfork-events+");
 
+      if (target_supports_exec_events ())
+       strcat (own_buf, ";exec-events+");
+
       if (target_supports_non_stop ())
        strcat (own_buf, ";QNonStop+");
 
@@ -2188,9 +2466,11 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
          strcat (own_buf, ";tracenz+");
        }
 
-      /* Support target-side breakpoint conditions and commands.  */
-      if (target_supports_conditional_breakpoints ())
-       strcat (own_buf, ";ConditionalBreakpoints+");
+      if (target_supports_hardware_single_step ()
+         || target_supports_software_single_step () )
+       {
+         strcat (own_buf, ";ConditionalBreakpoints+");
+       }
       strcat (own_buf, ";BreakpointCommands+");
 
       if (target_supports_agent ())
@@ -2207,6 +2487,12 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
       if (the_target->pid_to_exec_file != NULL)
        strcat (own_buf, ";qXfer:exec-file:read+");
 
+      strcat (own_buf, ";vContSupported+");
+
+      strcat (own_buf, ";QThreadEvents+");
+
+      strcat (own_buf, ";no-resumed+");
+
       /* Reinitialize components as needed for the new connection.  */
       hostio_handle_new_gdb_connection ();
       target_handle_new_gdb_connection ();
@@ -2223,7 +2509,7 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
       int i, err;
       ptid_t ptid = null_ptid;
 
-      require_running (own_buf);
+      require_running_or_return (own_buf);
 
       for (i = 0; i < 3; i++)
        {
@@ -2305,7 +2591,7 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
   /* Handle "monitor" commands.  */
   if (startswith (own_buf, "qRcmd,"))
     {
-      char *mon = malloc (PBUFSIZ);
+      char *mon = (char *) malloc (PBUFSIZ);
       int len = strlen (own_buf + 6);
 
       if (mon == NULL)
@@ -2336,7 +2622,7 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
 
   if (startswith (own_buf, "qSearch:memory:"))
     {
-      require_running (own_buf);
+      require_running_or_return (own_buf);
       handle_search_memory (own_buf, packet_len);
       return;
     }
@@ -2354,7 +2640,7 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
        }
       else
        {
-         require_running (own_buf);
+         require_running_or_return (own_buf);
          process = current_process ();
        }
 
@@ -2376,7 +2662,7 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
       int len;
       unsigned long long crc;
 
-      require_running (own_buf);
+      require_running_or_return (own_buf);
       comma = unpack_varlen_hex (own_buf + 5, &base);
       if (*comma++ != ',')
        {
@@ -2430,7 +2716,8 @@ struct visit_actioned_threads_data
 static int
 visit_actioned_threads (struct inferior_list_entry *entry, void *datap)
 {
-  struct visit_actioned_threads_data *data = datap;
+  struct visit_actioned_threads_data *data
+    = (struct visit_actioned_threads_data *) datap;
   const struct thread_resume *actions = data->actions;
   size_t num_actions = data->num_actions;
   visit_actioned_threads_callback_ftype *callback = data->callback;
@@ -2476,13 +2763,13 @@ handle_pending_status (const struct thread_resume *resumption,
 }
 
 /* Parse vCont packets.  */
-void
+static void
 handle_v_cont (char *own_buf)
 {
   char *p, *q;
   int n = 0, i = 0;
   struct thread_resume *resume_info;
-  struct thread_resume default_action = {{0}};
+  struct thread_resume default_action { null_ptid };
 
   /* Count the number of semicolons in the packet.  There should be one
      for every action.  */
@@ -2494,7 +2781,7 @@ handle_v_cont (char *own_buf)
       p = strchr (p, ';');
     }
 
-  resume_info = malloc (n * sizeof (resume_info[0]));
+  resume_info = (struct thread_resume *) malloc (n * sizeof (resume_info[0]));
   if (resume_info == NULL)
     goto err;
 
@@ -2524,9 +2811,9 @@ handle_v_cont (char *own_buf)
            goto err;
          p = q;
 
-         if (!gdb_signal_to_host_p (sig))
+         if (!gdb_signal_to_host_p ((enum gdb_signal) sig))
            goto err;
-         resume_info[i].sig = gdb_signal_to_host (sig);
+         resume_info[i].sig = gdb_signal_to_host ((enum gdb_signal) sig);
        }
       else if (p[0] == 'r')
        {
@@ -2573,8 +2860,6 @@ handle_v_cont (char *own_buf)
   if (i < n)
     resume_info[i] = default_action;
 
-  set_desired_thread (0);
-
   resume (resume_info, n);
   free (resume_info);
   return;
@@ -2615,10 +2900,11 @@ resume (struct thread_resume *actions, size_t num_actions)
     {
       last_ptid = mywait (minus_one_ptid, &last_status, 0, 1);
 
-      if (last_status.kind == TARGET_WAITKIND_NO_RESUMED)
+      if (last_status.kind == TARGET_WAITKIND_NO_RESUMED
+         && !report_no_resumed)
        {
-         /* No proper RSP support for this yet.  At least return
-            error.  */
+         /* The client does not support this stop reply.  At least
+            return error.  */
          sprintf (own_buf, "E.No unwaited-for children left.");
          disable_async_io ();
          return;
@@ -2639,12 +2925,12 @@ resume (struct thread_resume *actions, size_t num_actions)
 
       if (last_status.kind == TARGET_WAITKIND_EXITED
           || last_status.kind == TARGET_WAITKIND_SIGNALLED)
-        mourn_inferior (find_process_pid (ptid_get_pid (last_ptid)));
+        target_mourn_inferior (last_ptid);
     }
 }
 
 /* Attach to a new program.  Return 1 if successful, 0 if failure.  */
-int
+static int
 handle_v_attach (char *own_buf)
 {
   int pid;
@@ -2681,7 +2967,9 @@ handle_v_attach (char *own_buf)
 static int
 handle_v_run (char *own_buf)
 {
-  char *p, *next_p, **new_argv;
+  char *p, *next_p;
+  std::vector<char *> new_argv;
+  char *new_program_name = NULL;
   int i, new_argc;
 
   new_argc = 0;
@@ -2691,62 +2979,103 @@ handle_v_run (char *own_buf)
       new_argc++;
     }
 
-  new_argv = calloc (new_argc + 2, sizeof (char *));
-  if (new_argv == NULL)
-    {
-      write_enn (own_buf);
-      return 0;
-    }
-
-  i = 0;
-  for (p = own_buf + strlen ("vRun;"); *p; p = next_p)
+  for (i = 0, p = own_buf + strlen ("vRun;"); *p; p = next_p, ++i)
     {
       next_p = strchr (p, ';');
       if (next_p == NULL)
        next_p = p + strlen (p);
 
       if (i == 0 && p == next_p)
-       new_argv[i] = NULL;
-      else
        {
-         /* FIXME: Fail request if out of memory instead of dying.  */
-         new_argv[i] = xmalloc (1 + (next_p - p) / 2);
-         hex2bin (p, (gdb_byte *) new_argv[i], (next_p - p) / 2);
-         new_argv[i][(next_p - p) / 2] = '\0';
+         /* No program specified.  */
+         new_program_name = NULL;
+       }
+      else if (p == next_p)
+       {
+         /* Empty argument.  */
+         new_argv.push_back (xstrdup ("''"));
        }
+      else
+       {
+         size_t len = (next_p - p) / 2;
+         /* ARG is the unquoted argument received via the RSP.  */
+         char *arg = (char *) xmalloc (len + 1);
+         /* FULL_ARGS will contain the quoted version of ARG.  */
+         char *full_arg = (char *) xmalloc ((len + 1) * 2);
+         /* These are pointers used to navigate the strings above.  */
+         char *tmp_arg = arg;
+         char *tmp_full_arg = full_arg;
+         int need_quote = 0;
+
+         hex2bin (p, (gdb_byte *) arg, len);
+         arg[len] = '\0';
+
+         while (*tmp_arg != '\0')
+           {
+             switch (*tmp_arg)
+               {
+               case '\n':
+                 /* Quote \n.  */
+                 *tmp_full_arg = '\'';
+                 ++tmp_full_arg;
+                 need_quote = 1;
+                 break;
+
+               case '\'':
+                 /* Quote single quote.  */
+                 *tmp_full_arg = '\\';
+                 ++tmp_full_arg;
+                 break;
 
+               default:
+                 break;
+               }
+
+             *tmp_full_arg = *tmp_arg;
+             ++tmp_full_arg;
+             ++tmp_arg;
+           }
+
+         if (need_quote)
+           *tmp_full_arg++ = '\'';
+
+         /* Finish FULL_ARG and push it into the vector containing
+            the argv.  */
+         *tmp_full_arg = '\0';
+         if (i == 0)
+           new_program_name = full_arg;
+         else
+           new_argv.push_back (full_arg);
+         xfree (arg);
+       }
       if (*next_p)
        next_p++;
-      i++;
     }
-  new_argv[i] = NULL;
+  new_argv.push_back (NULL);
 
-  if (new_argv[0] == NULL)
+  if (new_program_name == NULL)
     {
       /* GDB didn't specify a program to run.  Use the program from the
         last run with the new argument list.  */
-
-      if (program_argv == NULL)
-       {
-         write_enn (own_buf);
-         freeargv (new_argv);
-         return 0;
-       }
-
-      new_argv[0] = strdup (program_argv[0]);
-      if (new_argv[0] == NULL)
+      if (program_name == NULL)
        {
          write_enn (own_buf);
-         freeargv (new_argv);
+         free_vector_argv (new_argv);
          return 0;
        }
     }
+  else
+    {
+      xfree (program_name);
+      program_name = new_program_name;
+    }
 
   /* Free the old argv and install the new one.  */
-  freeargv (program_argv);
-  program_argv = new_argv;
+  free_vector_argv (program_args);
+  program_args = new_argv;
+
+  create_inferior (program_name, program_args);
 
-  start_inferior (program_argv);
   if (last_status.kind == TARGET_WAITKIND_STOPPED)
     {
       prepare_resume_reply (own_buf, last_ptid, &last_status);
@@ -2767,7 +3096,7 @@ handle_v_run (char *own_buf)
 }
 
 /* Kill process.  Return 1 if successful, 0 if failure.  */
-int
+static int
 handle_v_kill (char *own_buf)
 {
   int pid;
@@ -2781,7 +3110,7 @@ handle_v_kill (char *own_buf)
       last_status.kind = TARGET_WAITKIND_SIGNALLED;
       last_status.value.sig = GDB_SIGNAL_KILL;
       last_ptid = pid_to_ptid (pid);
-      discard_queued_stop_replies (pid);
+      discard_queued_stop_replies (last_ptid);
       write_ok (own_buf);
       return 1;
     }
@@ -2798,16 +3127,36 @@ handle_v_requests (char *own_buf, int packet_len, int *new_packet_len)
 {
   if (!disable_packet_vCont)
     {
+      if (strcmp (own_buf, "vCtrlC") == 0)
+       {
+         (*the_target->request_interrupt) ();
+         write_ok (own_buf);
+         return;
+       }
+
       if (startswith (own_buf, "vCont;"))
        {
-         require_running (own_buf);
          handle_v_cont (own_buf);
          return;
        }
 
       if (startswith (own_buf, "vCont?"))
        {
-         strcpy (own_buf, "vCont;c;C;s;S;t");
+         strcpy (own_buf, "vCont;c;C;t");
+
+         if (target_supports_hardware_single_step ()
+             || target_supports_software_single_step ()
+             || !vCont_supported)
+           {
+             /* If target supports single step either by hardware or by
+                software, add actions s and S to the list of supported
+                actions.  On the other hand, if GDB doesn't request the
+                supported vCont actions in qSupported packet, add s and
+                S to the list too.  */
+             own_buf = own_buf + strlen (own_buf);
+             strcpy (own_buf, ";s;S");
+           }
+
          if (target_supports_range_stepping ())
            {
              own_buf = own_buf + strlen (own_buf);
@@ -2876,8 +3225,6 @@ myresume (char *own_buf, int step, int sig)
   int n = 0;
   int valid_cont_thread;
 
-  set_desired_thread (0);
-
   valid_cont_thread = (!ptid_equal (cont_thread, null_ptid)
                         && !ptid_equal (cont_thread, minus_one_ptid));
 
@@ -2915,7 +3262,7 @@ queue_stop_reply_callback (struct inferior_list_entry *entry, void *arg)
      manage the thread's last_status field.  */
   if (the_target->thread_stopped == NULL)
     {
-      struct vstop_notif *new_notif = xmalloc (sizeof (*new_notif));
+      struct vstop_notif *new_notif = XNEW (struct vstop_notif);
 
       new_notif->ptid = entry->id;
       new_notif->status = thread->last_status;
@@ -2930,14 +3277,12 @@ queue_stop_reply_callback (struct inferior_list_entry *entry, void *arg)
        {
          if (debug_threads)
            {
-             char *status_string
+             std::string status_string
                = target_waitstatus_to_string (&thread->last_status);
 
              debug_printf ("Reporting thread %s as already stopped with %s\n",
                            target_pid_to_str (entry->id),
-                           status_string);
-
-             xfree (status_string);
+                           status_string.c_str ());
            }
 
          gdb_assert (thread->last_status.kind != TARGET_WAITKIND_IGNORE);
@@ -3111,7 +3456,7 @@ static void
 gdbserver_version (void)
 {
   printf ("GNU gdbserver %s%s\n"
-         "Copyright (C) 2015 Free Software Foundation, Inc.\n"
+         "Copyright (C) 2017 Free Software Foundation, Inc.\n"
          "gdbserver is free software, covered by the "
          "GNU General Public License.\n"
          "This gdbserver was configured as \"%s\"\n",
@@ -3148,6 +3493,13 @@ gdbserver_usage (FILE *stream)
           "  --no-disable-randomization\n"
           "                        Don't disable address space randomization when\n"
           "                        starting PROG.\n"
+          "  --startup-with-shell\n"
+          "                        Start PROG using a shell.  I.e., execs a shell that\n"
+          "                        then execs PROG.  (default)\n"
+          "  --no-startup-with-shell\n"
+          "                        Exec PROG directly instead of using a shell.\n"
+          "                        Disables argument globbing and variable substitution\n"
+          "                        on UNIX-like systems.\n"
           "\n"
           "Debug options:\n"
           "\n"
@@ -3183,26 +3535,6 @@ gdbserver_show_disableable (FILE *stream)
           "  threads     \tAll of the above\n");
 }
 
-
-#undef require_running
-#define require_running(BUF)                   \
-  if (!target_running ())                      \
-    {                                          \
-      write_enn (BUF);                         \
-      break;                                   \
-    }
-
-static int
-first_thread_of (struct inferior_list_entry *entry, void *args)
-{
-  int pid = * (int *) args;
-
-  if (ptid_get_pid (entry->id) == pid)
-    return 1;
-
-  return 0;
-}
-
 static void
 kill_inferior_callback (struct inferior_list_entry *entry)
 {
@@ -3210,7 +3542,7 @@ kill_inferior_callback (struct inferior_list_entry *entry)
   int pid = ptid_get_pid (process->entry.id);
 
   kill_inferior (pid);
-  discard_queued_stop_replies (pid);
+  discard_queued_stop_replies (pid_to_ptid (pid));
 }
 
 /* Callback for for_each_inferior to detach or kill the inferior,
@@ -3229,7 +3561,7 @@ detach_or_kill_inferior_callback (struct inferior_list_entry *entry)
   else
     kill_inferior (pid);
 
-  discard_queued_stop_replies (pid);
+  discard_queued_stop_replies (pid_to_ptid (pid));
 }
 
 /* for_each_inferior callback for detach_or_kill_for_exit to print
@@ -3322,11 +3654,14 @@ captured_main (int argc, char *argv[])
 {
   int bad_attach;
   int pid;
-  char *arg_end, *port;
+  char *arg_end;
+  const char *port = NULL;
   char **next_arg = &argv[1];
   volatile int multi_mode = 0;
   volatile int attach = 0;
   int was_running;
+  bool selftest = false;
+  const char *selftest_filter = NULL;
 
   while (*next_arg != NULL && **next_arg == '-')
     {
@@ -3346,13 +3681,25 @@ captured_main (int argc, char *argv[])
        multi_mode = 1;
       else if (strcmp (*next_arg, "--wrapper") == 0)
        {
+         char **tmp;
+
          next_arg++;
 
-         wrapper_argv = next_arg;
+         tmp = next_arg;
          while (*next_arg != NULL && strcmp (*next_arg, "--") != 0)
-           next_arg++;
+           {
+             wrapper_argv += *next_arg;
+             wrapper_argv += ' ';
+             next_arg++;
+           }
 
-         if (next_arg == wrapper_argv || *next_arg == NULL)
+         if (!wrapper_argv.empty ())
+           {
+             /* Erase the last whitespace.  */
+             wrapper_argv.erase (wrapper_argv.end () - 1);
+           }
+
+         if (next_arg == tmp || *next_arg == NULL)
            {
              gdbserver_usage (stderr);
              exit (1);
@@ -3419,15 +3766,27 @@ captured_main (int argc, char *argv[])
        {
          /* "-" specifies a stdio connection and is a form of port
             specification.  */
-         *next_arg = STDIO_CONNECTION_NAME;
+         port = STDIO_CONNECTION_NAME;
+         next_arg++;
          break;
        }
       else if (strcmp (*next_arg, "--disable-randomization") == 0)
        disable_randomization = 1;
       else if (strcmp (*next_arg, "--no-disable-randomization") == 0)
        disable_randomization = 0;
+      else if (strcmp (*next_arg, "--startup-with-shell") == 0)
+       startup_with_shell = true;
+      else if (strcmp (*next_arg, "--no-startup-with-shell") == 0)
+       startup_with_shell = false;
       else if (strcmp (*next_arg, "--once") == 0)
        run_once = 1;
+      else if (strcmp (*next_arg, "--selftest") == 0)
+       selftest = true;
+      else if (startswith (*next_arg, "--selftest="))
+       {
+         selftest = true;
+         selftest_filter = *next_arg + strlen ("--selftest=");
+       }
       else
        {
          fprintf (stderr, "Unknown argument: %s\n", *next_arg);
@@ -3438,9 +3797,13 @@ captured_main (int argc, char *argv[])
       continue;
     }
 
-  port = *next_arg;
-  next_arg++;
-  if (port == NULL || (!attach && !multi_mode && *next_arg == NULL))
+  if (port == NULL)
+    {
+      port = *next_arg;
+      next_arg++;
+    }
+  if ((port == NULL || (!attach && !multi_mode && *next_arg == NULL))
+       && !selftest)
     {
       gdbserver_usage (stderr);
       exit (1);
@@ -3450,11 +3813,14 @@ captured_main (int argc, char *argv[])
      opened by remote_prepare.  */
   notice_open_fds ();
 
+  save_original_signals_state ();
+
   /* We need to know whether the remote connection is stdio before
      starting the inferior.  Inferiors created in this scenario have
      stdin,stdout redirected.  So do this here before we call
      start_inferior.  */
-  remote_prepare (port);
+  if (port != NULL)
+    remote_prepare (port);
 
   bad_attach = 0;
   pid = 0;
@@ -3481,27 +3847,38 @@ captured_main (int argc, char *argv[])
       exit (1);
     }
 
+  /* Gather information about the environment.  */
+  our_environ = gdb_environ::from_host_environ ();
+
   initialize_async_io ();
   initialize_low ();
+  have_job_control ();
   initialize_event_loop ();
   if (target_supports_tracepoints ())
     initialize_tracepoint ();
+  initialize_notif ();
+
+  own_buf = (char *) xmalloc (PBUFSIZ + 1);
+  mem_buf = (unsigned char *) xmalloc (PBUFSIZ);
 
-  own_buf = xmalloc (PBUFSIZ + 1);
-  mem_buf = xmalloc (PBUFSIZ);
+  if (selftest)
+    {
+      selftests::run_tests (selftest_filter);
+      throw_quit ("Quit");
+    }
 
   if (pid == 0 && *next_arg != NULL)
     {
       int i, n;
 
       n = argc - (next_arg - argv);
-      program_argv = xmalloc (sizeof (char *) * (n + 1));
-      for (i = 0; i < n; i++)
-       program_argv[i] = xstrdup (next_arg[i]);
-      program_argv[i] = NULL;
+      program_name = xstrdup (next_arg[0]);
+      for (i = 1; i < n; i++)
+       program_args.push_back (xstrdup (next_arg[i]));
+      program_args.push_back (NULL);
 
       /* Wait till we are at first instruction in program.  */
-      start_inferior (program_argv);
+      create_inferior (program_name, program_args);
 
       /* We are now (hopefully) stopped at the first instruction of
         the target process.  This assumes that the target process was
@@ -3522,8 +3899,6 @@ captured_main (int argc, char *argv[])
     }
   make_cleanup (detach_or_kill_for_exit_cleanup, NULL);
 
-  initialize_notif ();
-
   /* Don't report shared library events on the initial connection,
      even if some libraries are preloaded.  Avoids the "stopped by
      shared library event" notice on gdb side.  */
@@ -3545,11 +3920,13 @@ captured_main (int argc, char *argv[])
       multi_process = 0;
       report_fork_events = 0;
       report_vfork_events = 0;
+      report_exec_events = 0;
       /* Be sure we're out of tfind mode.  */
       current_traceframe = -1;
       cont_thread = null_ptid;
       swbreak_feature = 0;
       hwbreak_feature = 0;
+      vCont_supported = 0;
 
       remote_open (port);
 
@@ -3560,11 +3937,21 @@ captured_main (int argc, char *argv[])
          start_event_loop ();
 
          /* If an exit was requested (using the "monitor exit"
-            command), terminate now.  The only other way to get
-            here is for getpkt to fail; close the connection
-            and reopen it at the top of the loop.  */
+            command), terminate now.  */
+         if (exit_requested)
+           throw_quit ("Quit");
+
+         /* The only other way to get here is for getpkt to fail:
+
+             - If --once was specified, we're done.
+
+             - If not in extended-remote mode, and we're no longer
+               debugging anything, simply exit: GDB has disconnected
+               after processing the last process exit.
 
-         if (exit_requested || run_once)
+             - Otherwise, close the connection and reopen it at the
+               top of the loop.  */
+         if (run_once || (!extended_protocol && !target_running ()))
            throw_quit ("Quit");
 
          fprintf (stderr,
@@ -3574,7 +3961,7 @@ captured_main (int argc, char *argv[])
          /* Get rid of any pending statuses.  An eventual reconnection
             (by the same GDB instance or another) will refresh all its
             state from scratch.  */
-         discard_queued_stop_replies (-1);
+         discard_queued_stop_replies (minus_one_ptid);
          for_each_inferior (&all_threads,
                             clear_pending_status_callback);
 
@@ -3608,11 +3995,17 @@ captured_main (int argc, char *argv[])
        }
       CATCH (exception, RETURN_MASK_ERROR)
        {
+         fflush (stdout);
+         fprintf (stderr, "gdbserver: %s\n", exception.message);
+
          if (response_needed)
            {
              write_enn (own_buf);
              putpkt (own_buf);
            }
+
+         if (run_once)
+           throw_quit ("Quit");
        }
       END_CATCH
     }
@@ -3645,21 +4038,12 @@ main (int argc, char *argv[])
   gdb_assert_not_reached ("captured_main should never return");
 }
 
-/* Skip PACKET until the next semi-colon (or end of string).  */
-
-static void
-skip_to_semicolon (char **packet)
-{
-  while (**packet != '\0' && **packet != ';')
-    (*packet)++;
-}
-
 /* Process options coming from Z packets for a breakpoint.  PACKET is
    the packet buffer.  *PACKET is updated to point to the first char
    after the last processed option.  */
 
 static void
-process_point_options (struct breakpoint *bp, char **packet)
+process_point_options (struct gdb_breakpoint *bp, char **packet)
 {
   char *dataptr = *packet;
   int persist;
@@ -3681,7 +4065,7 @@ process_point_options (struct breakpoint *bp, char **packet)
          if (debug_threads)
            debug_printf ("Found breakpoint condition.\n");
          if (!add_breakpoint_condition (bp, &dataptr))
-           skip_to_semicolon (&dataptr);
+           dataptr = strchrnul (dataptr, ';');
        }
       else if (startswith (dataptr, "cmds:"))
        {
@@ -3691,14 +4075,14 @@ process_point_options (struct breakpoint *bp, char **packet)
          persist = (*dataptr == '1');
          dataptr += 2;
          if (add_breakpoint_commands (bp, &dataptr, persist))
-           skip_to_semicolon (&dataptr);
+           dataptr = strchrnul (dataptr, ';');
        }
       else
        {
          fprintf (stderr, "Unknown token %c, ignoring.\n",
                   *dataptr);
          /* Skip tokens until we find one that we recognize.  */
-         skip_to_semicolon (&dataptr);
+         dataptr = strchrnul (dataptr, ';');
        }
     }
   *packet = dataptr;
@@ -3712,24 +4096,14 @@ process_point_options (struct breakpoint *bp, char **packet)
 static int
 process_serial_event (void)
 {
-  char ch;
-  int i = 0;
   int signal;
   unsigned int len;
   int res;
   CORE_ADDR mem_addr;
-  int pid;
   unsigned char sig;
   int packet_len;
   int new_packet_len = -1;
 
-  /* Used to decide when gdbserver should exit in
-     multi-mode/remote.  */
-  static int have_ran = 0;
-
-  if (!have_ran)
-    have_ran = target_running ();
-
   disable_async_io ();
 
   response_needed = 0;
@@ -3742,8 +4116,7 @@ process_serial_event (void)
     }
   response_needed = 1;
 
-  i = 0;
-  ch = own_buf[i++];
+  char ch = own_buf[0];
   switch (ch)
     {
     case 'q':
@@ -3753,93 +4126,7 @@ process_serial_event (void)
       handle_general_set (own_buf);
       break;
     case 'D':
-      require_running (own_buf);
-
-      if (multi_process)
-       {
-         i++; /* skip ';' */
-         pid = strtol (&own_buf[i], NULL, 16);
-       }
-      else
-       pid = ptid_get_pid (current_ptid);
-
-      if ((tracing && disconnected_tracing) || any_persistent_commands ())
-       {
-         struct thread_resume resume_info;
-         struct process_info *process = find_process_pid (pid);
-
-         if (process == NULL)
-           {
-             write_enn (own_buf);
-             break;
-           }
-
-         if (tracing && disconnected_tracing)
-           fprintf (stderr,
-                    "Disconnected tracing in effect, "
-                    "leaving gdbserver attached to the process\n");
-
-         if (any_persistent_commands ())
-           fprintf (stderr,
-                    "Persistent commands are present, "
-                    "leaving gdbserver attached to the process\n");
-
-         /* Make sure we're in non-stop/async mode, so we we can both
-            wait for an async socket accept, and handle async target
-            events simultaneously.  There's also no point either in
-            having the target stop all threads, when we're going to
-            pass signals down without informing GDB.  */
-         if (!non_stop)
-           {
-             if (debug_threads)
-               debug_printf ("Forcing non-stop mode\n");
-
-             non_stop = 1;
-             start_non_stop (1);
-           }
-
-         process->gdb_detached = 1;
-
-         /* Detaching implicitly resumes all threads.  */
-         resume_info.thread = minus_one_ptid;
-         resume_info.kind = resume_continue;
-         resume_info.sig = 0;
-         (*the_target->resume) (&resume_info, 1);
-
-         write_ok (own_buf);
-         break; /* from switch/case */
-       }
-
-      fprintf (stderr, "Detaching from process %d\n", pid);
-      stop_tracing ();
-      if (detach_inferior (pid) != 0)
-       write_enn (own_buf);
-      else
-       {
-         discard_queued_stop_replies (pid);
-         write_ok (own_buf);
-
-         if (extended_protocol)
-           {
-             /* Treat this like a normal program exit.  */
-             last_status.kind = TARGET_WAITKIND_EXITED;
-             last_status.value.integer = 0;
-             last_ptid = pid_to_ptid (pid);
-
-             current_thread = NULL;
-           }
-         else
-           {
-             putpkt (own_buf);
-             remote_close ();
-
-             /* If we are attached, then we can exit.  Otherwise, we
-                need to hang around doing nothing, until the child is
-                gone.  */
-             join_inferior (pid);
-             exit (0);
-           }
-       }
+      handle_detach (own_buf);
       break;
     case '!':
       extended_protocol = 1;
@@ -3851,27 +4138,18 @@ process_serial_event (void)
     case 'H':
       if (own_buf[1] == 'c' || own_buf[1] == 'g' || own_buf[1] == 's')
        {
-         ptid_t gdb_id, thread_id;
-         int pid;
-
-         require_running (own_buf);
-
-         gdb_id = read_ptid (&own_buf[2], NULL);
+         require_running_or_break (own_buf);
 
-         pid = ptid_get_pid (gdb_id);
+         ptid_t thread_id = read_ptid (&own_buf[2], NULL);
 
-         if (ptid_equal (gdb_id, null_ptid)
-             || ptid_equal (gdb_id, minus_one_ptid))
+         if (thread_id == null_ptid || thread_id == minus_one_ptid)
            thread_id = null_ptid;
-         else if (pid != 0
-                  && ptid_equal (pid_to_ptid (pid),
-                                 gdb_id))
+         else if (thread_id.is_pid ())
            {
-             struct thread_info *thread =
-               (struct thread_info *) find_inferior (&all_threads,
-                                                     first_thread_of,
-                                                     &pid);
-             if (!thread)
+             /* The ptid represents a pid.  */
+             thread_info *thread = find_any_thread_of_pid (thread_id.pid ());
+
+             if (thread == NULL)
                {
                  write_enn (own_buf);
                  break;
@@ -3881,8 +4159,8 @@ process_serial_event (void)
            }
          else
            {
-             thread_id = gdb_id_to_thread_id (gdb_id);
-             if (ptid_equal (thread_id, null_ptid))
+             /* The ptid represents a lwp/tid.  */
+             if (find_thread_ptid (thread_id) == NULL)
                {
                  write_enn (own_buf);
                  break;
@@ -3900,14 +4178,13 @@ process_serial_event (void)
                    (struct thread_info *) find_inferior_id (&all_threads,
                                                             general_thread);
                  if (thread == NULL)
-                   {
-                     thread = get_first_thread ();
-                     thread_id = thread->entry.id;
-                   }
+                   thread = get_first_thread ();
+                 thread_id = thread->entry.id;
                }
 
              general_thread = thread_id;
              set_desired_thread (1);
+             gdb_assert (current_thread != NULL);
            }
          else if (own_buf[1] == 'c')
            cont_thread = thread_id;
@@ -3922,7 +4199,7 @@ process_serial_event (void)
        }
       break;
     case 'g':
-      require_running (own_buf);
+      require_running_or_break (own_buf);
       if (current_traceframe >= 0)
        {
          struct regcache *regcache
@@ -3939,27 +4216,35 @@ process_serial_event (void)
        {
          struct regcache *regcache;
 
-         set_desired_thread (1);
-         regcache = get_thread_regcache (current_thread, 1);
-         registers_to_string (regcache, own_buf);
+         if (!set_desired_thread (1))
+           write_enn (own_buf);
+         else
+           {
+             regcache = get_thread_regcache (current_thread, 1);
+             registers_to_string (regcache, own_buf);
+           }
        }
       break;
     case 'G':
-      require_running (own_buf);
+      require_running_or_break (own_buf);
       if (current_traceframe >= 0)
        write_enn (own_buf);
       else
        {
          struct regcache *regcache;
 
-         set_desired_thread (1);
-         regcache = get_thread_regcache (current_thread, 1);
-         registers_from_string (regcache, &own_buf[1]);
-         write_ok (own_buf);
+         if (!set_desired_thread (1))
+           write_enn (own_buf);
+         else
+           {
+             regcache = get_thread_regcache (current_thread, 1);
+             registers_from_string (regcache, &own_buf[1]);
+             write_ok (own_buf);
+           }
        }
       break;
     case 'm':
-      require_running (own_buf);
+      require_running_or_break (own_buf);
       decode_m_packet (&own_buf[1], &mem_addr, &len);
       res = gdb_read_memory (mem_addr, mem_buf, len);
       if (res < 0)
@@ -3968,7 +4253,7 @@ process_serial_event (void)
        bin2hex (mem_buf, own_buf, res);
       break;
     case 'M':
-      require_running (own_buf);
+      require_running_or_break (own_buf);
       decode_M_packet (&own_buf[1], &mem_addr, &len, &mem_buf);
       if (gdb_write_memory (mem_addr, mem_buf, len) == 0)
        write_ok (own_buf);
@@ -3976,7 +4261,7 @@ process_serial_event (void)
        write_enn (own_buf);
       break;
     case 'X':
-      require_running (own_buf);
+      require_running_or_break (own_buf);
       if (decode_X_packet (&own_buf[1], packet_len - 1,
                           &mem_addr, &len, &mem_buf) < 0
          || gdb_write_memory (mem_addr, mem_buf, len) != 0)
@@ -3985,30 +4270,30 @@ process_serial_event (void)
        write_ok (own_buf);
       break;
     case 'C':
-      require_running (own_buf);
+      require_running_or_break (own_buf);
       hex2bin (own_buf + 1, &sig, 1);
-      if (gdb_signal_to_host_p (sig))
-       signal = gdb_signal_to_host (sig);
+      if (gdb_signal_to_host_p ((enum gdb_signal) sig))
+       signal = gdb_signal_to_host ((enum gdb_signal) sig);
       else
        signal = 0;
       myresume (own_buf, 0, signal);
       break;
     case 'S':
-      require_running (own_buf);
+      require_running_or_break (own_buf);
       hex2bin (own_buf + 1, &sig, 1);
-      if (gdb_signal_to_host_p (sig))
-       signal = gdb_signal_to_host (sig);
+      if (gdb_signal_to_host_p ((enum gdb_signal) sig))
+       signal = gdb_signal_to_host ((enum gdb_signal) sig);
       else
        signal = 0;
       myresume (own_buf, 1, signal);
       break;
     case 'c':
-      require_running (own_buf);
+      require_running_or_break (own_buf);
       signal = 0;
       myresume (own_buf, 0, signal);
       break;
     case 's':
-      require_running (own_buf);
+      require_running_or_break (own_buf);
       signal = 0;
       myresume (own_buf, 1, signal);
       break;
@@ -4018,20 +4303,20 @@ process_serial_event (void)
       {
        char *dataptr;
        ULONGEST addr;
-       int len;
+       int kind;
        char type = own_buf[1];
        int res;
        const int insert = ch == 'Z';
        char *p = &own_buf[3];
 
        p = unpack_varlen_hex (p, &addr);
-       len = strtol (p + 1, &dataptr, 16);
+       kind = strtol (p + 1, &dataptr, 16);
 
        if (insert)
          {
-           struct breakpoint *bp;
+           struct gdb_breakpoint *bp;
 
-           bp = set_gdb_breakpoint (type, addr, len, &res);
+           bp = set_gdb_breakpoint (type, addr, kind, &res);
            if (bp != NULL)
              {
                res = 0;
@@ -4046,7 +4331,7 @@ process_serial_event (void)
              }
          }
        else
-         res = delete_gdb_breakpoint (type, addr, len);
+         res = delete_gdb_breakpoint (type, addr, kind);
 
        if (res == 0)
          write_ok (own_buf);
@@ -4080,13 +4365,10 @@ process_serial_event (void)
 
     case 'T':
       {
-       ptid_t gdb_id, thread_id;
+       require_running_or_break (own_buf);
 
-       require_running (own_buf);
-
-       gdb_id = read_ptid (&own_buf[1], NULL);
-       thread_id = gdb_id_to_thread_id (gdb_id);
-       if (ptid_equal (thread_id, null_ptid))
+       ptid_t thread_id = read_ptid (&own_buf[1], NULL);
+       if (find_thread_ptid (thread_id) == NULL)
          {
            write_enn (own_buf);
            break;
@@ -4111,9 +4393,10 @@ process_serial_event (void)
          fprintf (stderr, "GDBserver restarting\n");
 
          /* Wait till we are at 1st instruction in prog.  */
-         if (program_argv != NULL)
+         if (program_name != NULL)
            {
-             start_inferior (program_argv);
+             create_inferior (program_name, program_args);
+
              if (last_status.kind == TARGET_WAITKIND_STOPPED)
                {
                  /* Stopped at the first instruction of the target
@@ -4161,21 +4444,6 @@ process_serial_event (void)
 
   response_needed = 0;
 
-  if (!extended_protocol && have_ran && !target_running ())
-    {
-      /* In non-stop, defer exiting until GDB had a chance to query
-        the whole vStopped list (until it gets an OK).  */
-      if (QUEUE_is_empty (notif_event_p, notif_stop.queue))
-       {
-         /* Be transparent when GDB is connected through stdio -- no
-            need to spam GDB's console.  */
-         if (!remote_connection_is_stdio ())
-           fprintf (stderr, "GDBserver exiting\n");
-         remote_close ();
-         exit (0);
-       }
-    }
-
   if (exit_requested)
     return -1;
 
@@ -4201,6 +4469,19 @@ handle_serial_event (int err, gdb_client_data client_data)
   return 0;
 }
 
+/* Push a stop notification on the notification queue.  */
+
+static void
+push_stop_notification (ptid_t ptid, struct target_waitstatus *status)
+{
+  struct vstop_notif *vstop_notif = XNEW (struct vstop_notif);
+
+  vstop_notif->status = *status;
+  vstop_notif->ptid = ptid;
+  /* Push Stop notification.  */
+  notif_push (&notif_stop, (struct notif_event *) vstop_notif);
+}
+
 /* Event-loop callback for target events.  */
 
 int
@@ -4214,7 +4495,8 @@ handle_target_event (int err, gdb_client_data client_data)
 
   if (last_status.kind == TARGET_WAITKIND_NO_RESUMED)
     {
-      /* No RSP support for this yet.  */
+      if (gdb_connected () && report_no_resumed)
+       push_stop_notification (null_ptid, &last_status);
     }
   else if (last_status.kind != TARGET_WAITKIND_IGNORE)
     {
@@ -4226,8 +4508,10 @@ handle_target_event (int err, gdb_client_data client_data)
          || last_status.kind == TARGET_WAITKIND_SIGNALLED)
        {
          mark_breakpoints_out (process);
-         mourn_inferior (process);
+         target_mourn_inferior (last_ptid);
        }
+      else if (last_status.kind == TARGET_WAITKIND_THREAD_EXITED)
+       ;
       else
        {
          /* We're reporting this thread as stopped.  Update its
@@ -4245,12 +4529,16 @@ handle_target_event (int err, gdb_client_data client_data)
              exit (0);
            }
 
-         if (last_status.kind == TARGET_WAITKIND_STOPPED)
+         if (last_status.kind == TARGET_WAITKIND_EXITED
+             || last_status.kind == TARGET_WAITKIND_SIGNALLED
+             || last_status.kind == TARGET_WAITKIND_THREAD_EXITED)
+           ;
+         else
            {
              /* A thread stopped with a signal, but gdb isn't
                 connected to handle it.  Pass it down to the
                 inferior, as if it wasn't being traced.  */
-             struct thread_resume resume_info;
+             enum gdb_signal signal;
 
              if (debug_threads)
                debug_printf ("GDB not connected; forwarding event %d for"
@@ -4258,27 +4546,15 @@ handle_target_event (int err, gdb_client_data client_data)
                              (int) last_status.kind,
                              target_pid_to_str (last_ptid));
 
-             resume_info.thread = last_ptid;
-             resume_info.kind = resume_continue;
-             resume_info.sig = gdb_signal_to_host (last_status.value.sig);
-             (*the_target->resume) (&resume_info, 1);
+             if (last_status.kind == TARGET_WAITKIND_STOPPED)
+               signal = last_status.value.sig;
+             else
+               signal = GDB_SIGNAL_0;
+             target_continue (last_ptid, signal);
            }
-         else if (debug_threads)
-           debug_printf ("GDB not connected; ignoring event %d for [%s]\n",
-                         (int) last_status.kind,
-                         target_pid_to_str (last_ptid));
        }
       else
-       {
-         struct vstop_notif *vstop_notif
-           = xmalloc (sizeof (struct vstop_notif));
-
-         vstop_notif->status = last_status;
-         vstop_notif->ptid = last_ptid;
-         /* Push Stop notification.  */
-         notif_push (&notif_stop,
-                     (struct notif_event *) vstop_notif);
-       }
+       push_stop_notification (last_ptid, &last_status);
     }
 
   /* Be sure to not change the selected thread behind GDB's back.
@@ -4287,3 +4563,14 @@ handle_target_event (int err, gdb_client_data client_data)
 
   return 0;
 }
+
+#if GDB_SELF_TEST
+namespace selftests
+{
+
+void
+reset ()
+{}
+
+} // namespace selftests
+#endif /* GDB_SELF_TEST */