gdb/linux-tdep.c: Add Perms to the 'info proc mappings' output
[binutils-gdb.git] / gdb / remote.c
index b4c6fc21083b5c82859170bbb733a1e5f78c6849..aa6a67a96e0a5be78243729611566358a20e96f4 100644 (file)
@@ -1,6 +1,6 @@
 /* Remote target communications for serial-line targets in custom GDB protocol
 
-   Copyright (C) 1988-2021 Free Software Foundation, Inc.
+   Copyright (C) 1988-2022 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -79,6 +79,7 @@
 #include <algorithm>
 #include <unordered_map>
 #include "async-event.h"
+#include "gdbsupport/selftest.h"
 
 /* The remote target.  */
 
@@ -87,6 +88,10 @@ Use a remote computer via a serial line, using a gdb-specific protocol.\n\
 Specify the serial device it is connected to\n\
 (e.g. /dev/ttyS0, /dev/ttya, COM1, etc.).");
 
+/* See remote.h  */
+
+bool remote_debug = false;
+
 #define OPAQUETHREADBYTES 8
 
 /* a 64 bit opaque identifier */
@@ -253,15 +258,6 @@ public: /* data */
      Otherwise zero, meaning to use the guessed size.  */
   long explicit_packet_size = 0;
 
-  /* remote_wait is normally called when the target is running and
-     waits for a stop reply packet.  But sometimes we need to call it
-     when the target is already stopped.  We can send a "?" packet
-     and have remote_wait read the response.  Or, if we already have
-     the response, we can stash it in BUF and tell remote_wait to
-     skip calling getpkt.  This flag is set when BUF contains a
-     stop reply packet and the target is not waiting.  */
-  int cached_wait_status = 0;
-
   /* True, if in no ack mode.  That is, neither GDB nor the stub will
      expect acks from each other.  The connection is assumed to be
      reliable.  */
@@ -395,7 +391,7 @@ private:
 
 static const target_info remote_target_info = {
   "remote",
-  N_("Remote serial target in gdb-specific protocol"),
+  N_("Remote target using gdb-specific protocol"),
   remote_doc
 };
 
@@ -421,16 +417,15 @@ public:
   void detach (inferior *, int) override;
   void disconnect (const char *, int) override;
 
-  void commit_resume () override;
+  void commit_resumed () override;
   void resume (ptid_t, int, enum gdb_signal) override;
   ptid_t wait (ptid_t, struct target_waitstatus *, target_wait_flags) override;
+  bool has_pending_events () override;
 
   void fetch_registers (struct regcache *, int) override;
   void store_registers (struct regcache *, int) override;
   void prepare_to_store (struct regcache *) override;
 
-  void files_info () override;
-
   int insert_breakpoint (struct gdbarch *, struct bp_target_info *) override;
 
   int remove_breakpoint (struct gdbarch *, struct bp_target_info *,
@@ -487,7 +482,7 @@ public:
 
   const char *extra_thread_info (struct thread_info *) override;
 
-  ptid_t get_ada_task_ptid (long lwp, long thread) override;
+  ptid_t get_ada_task_ptid (long lwp, ULONGEST thread) override;
 
   thread_info *thread_handle_to_thread_info (const gdb_byte *thread_handle,
                                             int handle_len,
@@ -663,8 +658,8 @@ public:
   bool use_agent (bool use) override;
   bool can_use_agent () override;
 
-  struct btrace_target_info *enable_btrace (ptid_t ptid,
-                                           const struct btrace_config *conf) override;
+  struct btrace_target_info *
+    enable_btrace (thread_info *tp, const struct btrace_config *conf) override;
 
   void disable_btrace (struct btrace_target_info *tinfo) override;
 
@@ -676,8 +671,8 @@ public:
 
   const struct btrace_config *btrace_conf (const struct btrace_target_info *) override;
   bool augmented_libraries_svr4_read () override;
-  bool follow_fork (bool, bool) override;
-  void follow_exec (struct inferior *, const char *) override;
+  void follow_fork (inferior *, ptid_t, target_waitkind, bool, bool) override;
+  void follow_exec (inferior *, ptid_t, const char *) override;
   int insert_fork_catchpoint (int) override;
   int remove_fork_catchpoint (int) override;
   int insert_vfork_catchpoint (int) override;
@@ -686,6 +681,14 @@ public:
   int remove_exec_catchpoint (int) override;
   enum exec_direction_kind execution_direction () override;
 
+  bool supports_memory_tagging () override;
+
+  bool fetch_memtags (CORE_ADDR address, size_t len,
+                     gdb::byte_vector &tags, int type) override;
+
+  bool store_memtags (CORE_ADDR address, size_t len,
+                     const gdb::byte_vector &tags, int type) override;
+
 public: /* Remote specific methods.  */
 
   void remote_download_command_source (int num, ULONGEST addr,
@@ -737,7 +740,7 @@ public: /* Remote specific methods.  */
   int remote_resume_with_vcont (ptid_t ptid, int step,
                                gdb_signal siggnal);
 
-  void add_current_inferior_and_thread (const char *wait_status);
+  thread_info *add_current_inferior_and_thread (const char *wait_status);
 
   ptid_t wait_ns (ptid_t ptid, struct target_waitstatus *status,
                  target_wait_flags options);
@@ -748,25 +751,27 @@ public: /* Remote specific methods.  */
                             target_waitstatus *status);
 
   ptid_t select_thread_for_ambiguous_stop_reply
-    (const struct target_waitstatus *status);
+    (const struct target_waitstatus &status);
 
-  void remote_notice_new_inferior (ptid_t currthread, int executing);
+  void remote_notice_new_inferior (ptid_t currthread, bool executing);
 
+  void print_one_stopped_thread (thread_info *thread);
   void process_initial_stop_replies (int from_tty);
 
-  thread_info *remote_add_thread (ptid_t ptid, bool running, bool executing);
+  thread_info *remote_add_thread (ptid_t ptid, bool running, bool executing,
+                                 bool silent_p);
 
   void btrace_sync_conf (const btrace_config *conf);
 
   void remote_btrace_maybe_reopen ();
 
   void remove_new_fork_children (threads_listing_context *context);
-  void kill_new_fork_children (int pid);
+  void kill_new_fork_children (inferior *inf);
   void discard_pending_stop_replies (struct inferior *inf);
   int stop_reply_queue_length ();
 
   void check_pending_events_prevent_wildcard_vcont
-    (int *may_global_wildcard_vcont);
+    (bool *may_global_wildcard_vcont);
 
   void discard_pending_stop_replies_in_queue ();
   struct stop_reply *remote_notif_remove_queued_reply (ptid_t ptid);
@@ -941,9 +946,9 @@ public: /* Remote specific methods.  */
 
   bool vcont_r_supported ();
 
-  void packet_command (const char *args, int from_tty);
+private:
 
-private: /* data fields */
+  bool start_remote_1 (int from_tty, int extended_p);
 
   /* The remote state.  Don't reference this directly.  Use the
      get_remote_state method instead.  */
@@ -952,7 +957,7 @@ private: /* data fields */
 
 static const target_info extended_remote_target_info = {
   "extended-remote",
-  N_("Extended remote serial target in gdb-specific protocol"),
+  N_("Extended remote target using gdb-specific protocol"),
   remote_doc
 };
 
@@ -981,6 +986,45 @@ public:
   bool supports_disable_randomization () override;
 };
 
+struct stop_reply : public notif_event
+{
+  ~stop_reply ();
+
+  /* The identifier of the thread about this event  */
+  ptid_t ptid;
+
+  /* The remote state this event is associated with.  When the remote
+     connection, represented by a remote_state object, is closed,
+     all the associated stop_reply events should be released.  */
+  struct remote_state *rs;
+
+  struct target_waitstatus ws;
+
+  /* The architecture associated with the expedited registers.  */
+  gdbarch *arch;
+
+  /* Expedited registers.  This makes remote debugging a bit more
+     efficient for those targets that provide critical registers as
+     part of their normal status mechanism (as another roundtrip to
+     fetch them is avoided).  */
+  std::vector<cached_reg_t> regcache;
+
+  enum target_stop_reason stop_reason;
+
+  CORE_ADDR watch_data_address;
+
+  int core;
+};
+
+/* See remote.h.  */
+
+bool
+is_remote_target (process_stratum_target *target)
+{
+  remote_target *rt = dynamic_cast<remote_target *> (target);
+  return rt != nullptr;
+}
+
 /* Per-program-space data key.  */
 static const struct program_space_key<char, gdb::xfree_deleter<char>>
   remote_pspace_data;
@@ -989,7 +1033,7 @@ static const struct program_space_key<char, gdb::xfree_deleter<char>>
    remote exec-file commands.  While the remote exec-file setting is
    per-program-space, the set/show machinery uses this as the 
    location of the remote exec-file value.  */
-static char *remote_exec_file_var;
+static std::string remote_exec_file_var;
 
 /* The size to align memory write packets, when practical.  The protocol
    does not guarantee any alignment, and gdb will generate short
@@ -1015,14 +1059,10 @@ static int hexnumnstr (char *, ULONGEST, int);
 
 static CORE_ADDR remote_address_masked (CORE_ADDR);
 
-static void print_packet (const char *);
-
 static int stub_unpack_int (const char *buff, int fieldlength);
 
 struct packet_config;
 
-static void show_packet_config_cmd (struct packet_config *config);
-
 static void show_remote_protocol_packet_cmd (struct ui_file *file,
                                             int from_tty,
                                             struct cmd_list_element *c,
@@ -1104,7 +1144,7 @@ struct remote_thread_info : public private_thread_info
   CORE_ADDR watch_data_address = 0;
 
   /* Get the thread's resume state.  */
-  enum resume_state resume_state () const
+  enum resume_state get_resume_state () const
   {
     return m_resume_state;
   }
@@ -1340,8 +1380,8 @@ static void
 set_remote_exec_file (const char *ignored, int from_tty,
                      struct cmd_list_element *c)
 {
-  gdb_assert (remote_exec_file_var != NULL);
-  set_pspace_remote_exec_file (current_program_space, remote_exec_file_var);
+  set_pspace_remote_exec_file (current_program_space,
+                              remote_exec_file_var.c_str ());
 }
 
 /* The "set/show remote exec-file" show command hook.  */
@@ -1858,6 +1898,9 @@ struct packet_config
        have an associated command always have this set to auto.  */
     enum auto_boolean detect;
 
+    /* The "show remote foo-packet" command created for this packet.  */
+    cmd_list_element *show_cmd;
+
     /* Does the target support this packet?  */
     enum packet_support support;
   };
@@ -1866,7 +1909,7 @@ static enum packet_support packet_config_support (struct packet_config *config);
 static enum packet_support packet_support (int packet);
 
 static void
-show_packet_config_cmd (struct packet_config *config)
+show_packet_config_cmd (ui_file *file, struct packet_config *config)
 {
   const char *support = "internal-error";
 
@@ -1885,14 +1928,16 @@ show_packet_config_cmd (struct packet_config *config)
   switch (config->detect)
     {
     case AUTO_BOOLEAN_AUTO:
-      printf_filtered (_("Support for the `%s' packet "
-                        "is auto-detected, currently %s.\n"),
-                      config->name, support);
+      fprintf_filtered (file,
+                       _("Support for the `%s' packet "
+                         "is auto-detected, currently %s.\n"),
+                       config->name, support);
       break;
     case AUTO_BOOLEAN_TRUE:
     case AUTO_BOOLEAN_FALSE:
-      printf_filtered (_("Support for the `%s' packet is currently %s.\n"),
-                      config->name, support);
+      fprintf_filtered (file,
+                       _("Support for the `%s' packet is currently %s.\n"),
+                       config->name, support);
       break;
     }
 }
@@ -1901,37 +1946,36 @@ static void
 add_packet_config_cmd (struct packet_config *config, const char *name,
                       const char *title, int legacy)
 {
-  char *set_doc;
-  char *show_doc;
-  char *cmd_name;
-
   config->name = name;
   config->title = title;
-  set_doc = xstrprintf ("Set use of remote protocol `%s' (%s) packet.",
-                       name, title);
-  show_doc = xstrprintf ("Show current use of remote "
-                        "protocol `%s' (%s) packet.",
-                        name, title);
+  gdb::unique_xmalloc_ptr<char> set_doc
+    = xstrprintf ("Set use of remote protocol `%s' (%s) packet.",
+                 name, title);
+  gdb::unique_xmalloc_ptr<char> show_doc
+    = xstrprintf ("Show current use of remote protocol `%s' (%s) packet.",
+                 name, title);
   /* set/show TITLE-packet {auto,on,off} */
-  cmd_name = xstrprintf ("%s-packet", title);
-  add_setshow_auto_boolean_cmd (cmd_name, class_obscure,
-                               &config->detect, set_doc,
-                               show_doc, NULL, /* help_doc */
-                               NULL,
-                               show_remote_protocol_packet_cmd,
-                               &remote_set_cmdlist, &remote_show_cmdlist);
-  /* The command code copies the documentation strings.  */
-  xfree (set_doc);
-  xfree (show_doc);
+  gdb::unique_xmalloc_ptr<char> cmd_name = xstrprintf ("%s-packet", title);
+  set_show_commands cmds
+    = add_setshow_auto_boolean_cmd (cmd_name.release (), class_obscure,
+                                   &config->detect, set_doc.get (),
+                                   show_doc.get (), NULL, /* help_doc */
+                                   NULL,
+                                   show_remote_protocol_packet_cmd,
+                                   &remote_set_cmdlist, &remote_show_cmdlist);
+  config->show_cmd = cmds.show;
+
   /* set/show remote NAME-packet {auto,on,off} -- legacy.  */
   if (legacy)
     {
-      char *legacy_name;
-
-      legacy_name = xstrprintf ("%s-packet", name);
-      add_alias_cmd (legacy_name, cmd_name, class_obscure, 0,
+      /* It's not clear who should take ownership of this string, so, for
+        now, make it static, and give copies to each of the add_alias_cmd
+        calls below.  */
+      static gdb::unique_xmalloc_ptr<char> legacy_name
+       = xstrprintf ("%s-packet", name);
+      add_alias_cmd (legacy_name.get (), cmds.set, class_obscure, 0,
                     &remote_set_cmdlist);
-      add_alias_cmd (legacy_name, cmd_name, class_obscure, 0,
+      add_alias_cmd (legacy_name.get (), cmds.show, class_obscure, 0,
                     &remote_show_cmdlist);
     }
 }
@@ -1986,10 +2030,8 @@ packet_ok (const char *buf, struct packet_config *config)
       /* The stub recognized the packet request.  */
       if (config->support == PACKET_SUPPORT_UNKNOWN)
        {
-         if (remote_debug)
-           fprintf_unfiltered (gdb_stdlog,
-                               "Packet %s (%s) is supported\n",
-                               config->name, config->title);
+         remote_debug_printf ("Packet %s (%s) is supported",
+                              config->name, config->title);
          config->support = PACKET_ENABLE;
        }
       break;
@@ -2010,10 +2052,8 @@ packet_ok (const char *buf, struct packet_config *config)
                 config->name, config->title);
        }
 
-      if (remote_debug)
-       fprintf_unfiltered (gdb_stdlog,
-                           "Packet %s (%s) is NOT supported\n",
-                           config->name, config->title);
+      remote_debug_printf ("Packet %s (%s) is NOT supported",
+                          config->name, config->title);
       config->support = PACKET_DISABLE;
       break;
     }
@@ -2167,6 +2207,10 @@ enum {
   /* Support TARGET_WAITKIND_NO_RESUMED.  */
   PACKET_no_resumed,
 
+  /* Support for memory tagging, allocation tag fetch/store
+     packets and the tag violation stop replies.  */
+  PACKET_memory_tagging_feature,
+
   PACKET_MAX
 };
 
@@ -2200,7 +2244,7 @@ packet_config_support (struct packet_config *config)
     case AUTO_BOOLEAN_AUTO:
       return config->support;
     default:
-      gdb_assert_not_reached (_("bad switch"));
+      gdb_assert_not_reached ("bad switch");
     }
 }
 
@@ -2221,14 +2265,15 @@ show_remote_protocol_packet_cmd (struct ui_file *file, int from_tty,
                                 const char *value)
 {
   struct packet_config *packet;
+  gdb_assert (c->var.has_value ());
 
   for (packet = remote_protocol_packets;
        packet < &remote_protocol_packets[PACKET_MAX];
        packet++)
     {
-      if (&packet->detect == c->var)
+      if (c == packet->show_cmd)
        {
-         show_packet_config_cmd (packet);
+         show_packet_config_cmd (file, packet);
          return;
        }
     }
@@ -2272,7 +2317,7 @@ show_remote_protocol_Z_packet_cmd (struct ui_file *file, int from_tty,
 
   for (i = 0; i < NR_Z_PACKET_TYPES; i++)
     {
-      show_packet_config_cmd (&remote_protocol_packets[PACKET_Z0 + i]);
+      show_packet_config_cmd (file, &remote_protocol_packets[PACKET_Z0 + i]);
     }
 }
 
@@ -2308,6 +2353,14 @@ remote_exec_event_p (struct remote_state *rs)
   return packet_support (PACKET_exec_event_feature) == PACKET_ENABLE;
 }
 
+/* Returns true if memory tagging is supported, false otherwise.  */
+
+static bool
+remote_memory_tagging_p ()
+{
+  return packet_support (PACKET_memory_tagging_feature) == PACKET_ENABLE;
+}
+
 /* Insert fork catchpoint target routine.  If fork events are enabled
    then return success, nothing more to do.  */
 
@@ -2474,7 +2527,7 @@ remote_target::remote_add_inferior (bool fake_pid_p, int pid, int attached,
          inf = add_inferior_with_spaces ();
        }
       switch_to_inferior_no_thread (inf);
-      push_target (this);
+      inf->push_target (this);
       inferior_appeared (inf, pid);
     }
 
@@ -2497,10 +2550,13 @@ static remote_thread_info *get_remote_thread_info (remote_target *target,
                                                   ptid_t ptid);
 
 /* Add thread PTID to GDB's thread list.  Tag it as executing/running
-   according to RUNNING.  */
+   according to EXECUTING and RUNNING respectively.  If SILENT_P (or the
+   remote_state::starting_up flag) is true then the new thread is added
+   silently, otherwise the new thread will be announced to the user.  */
 
 thread_info *
-remote_target::remote_add_thread (ptid_t ptid, bool running, bool executing)
+remote_target::remote_add_thread (ptid_t ptid, bool running, bool executing,
+                                 bool silent_p)
 {
   struct remote_state *rs = get_remote_state ();
   struct thread_info *thread;
@@ -2511,7 +2567,7 @@ remote_target::remote_add_thread (ptid_t ptid, bool running, bool executing)
      consider that a single-threaded target, mentioning a new thread
      might be confusing to the user.  Be silent then, preserving the
      age old behavior.  */
-  if (rs->starting_up)
+  if (rs->starting_up || silent_p)
     thread = add_thread_silent (this, ptid);
   else
     thread = add_thread (this, ptid);
@@ -2534,12 +2590,12 @@ remote_target::remote_add_thread (ptid_t ptid, bool running, bool executing)
    thread is (internally) executing or stopped.  */
 
 void
-remote_target::remote_notice_new_inferior (ptid_t currthread, int executing)
+remote_target::remote_notice_new_inferior (ptid_t currthread, bool executing)
 {
   /* In non-stop mode, we assume new found threads are (externally)
      running until proven otherwise with a stop reply.  In all-stop,
      we can only get here if all threads are stopped.  */
-  int running = target_is_non_stop_p () ? 1 : 0;
+  bool running = target_is_non_stop_p ();
 
   /* If this is a new thread, add it to GDB's thread list.
      If we leave it up to WFI to do this, bad things will happen.  */
@@ -2549,7 +2605,7 @@ remote_target::remote_notice_new_inferior (ptid_t currthread, int executing)
     {
       /* We're seeing an event on a thread id we knew had exited.
         This has to be a new thread reusing the old id.  Add it.  */
-      remote_add_thread (currthread, running, executing);
+      remote_add_thread (currthread, running, executing, false);
       return;
     }
 
@@ -2571,7 +2627,7 @@ remote_target::remote_notice_new_inferior (ptid_t currthread, int executing)
          else
            {
              thread_info *thr
-               = remote_add_thread (currthread, running, executing);
+               = remote_add_thread (currthread, running, executing, false);
              switch_to_thread (thr);
            }
          return;
@@ -2603,7 +2659,7 @@ remote_target::remote_notice_new_inferior (ptid_t currthread, int executing)
 
       /* This is really a new thread.  Add it.  */
       thread_info *new_thr
-       = remote_add_thread (currthread, running, executing);
+       = remote_add_thread (currthread, running, executing, false);
 
       /* If we found a new inferior, let the common code do whatever
         it needs to with it (e.g., read shared libraries, insert
@@ -2728,13 +2784,8 @@ remote_target::set_syscall_catchpoint (int pid, bool needed, int any_count,
        }
     }
 
-  if (remote_debug)
-    {
-      fprintf_unfiltered (gdb_stdlog,
-                         "remote_set_syscall_catchpoint "
-                         "pid %d needed %d any_count %d n_sysno %d\n",
-                         pid, needed, any_count, n_sysno);
-    }
+  remote_debug_printf ("pid %d needed %d any_count %d n_sysno %d",
+                      pid, needed, any_count, n_sysno);
 
   std::string built_packet;
   if (needed)
@@ -3080,7 +3131,7 @@ read_ptid (const char *buf, const char **obuf)
       pp = unpack_varlen_hex (p + 1, &tid);
       if (obuf)
        *obuf = pp;
-      return ptid_t (pid, tid, 0);
+      return ptid_t (pid, tid);
     }
 
   /* No multi-process.  Just a tid.  */
@@ -3105,7 +3156,7 @@ read_ptid (const char *buf, const char **obuf)
 
   if (obuf)
     *obuf = pp;
-  return ptid_t (pid, tid, 0);
+  return ptid_t (pid, tid);
 }
 
 static int
@@ -3705,9 +3756,8 @@ remote_target::remote_current_thread (ptid_t oldpid)
       ptid_t result;
 
       result = read_ptid (&rs->buf[2], &obuf);
-      if (*obuf != '\0' && remote_debug)
-       fprintf_unfiltered (gdb_stdlog,
-                           "warning: garbage in qC reply\n");
+      if (*obuf != '\0')
+       remote_debug_printf ("warning: garbage in qC reply");
 
       return result;
     }
@@ -3939,7 +3989,7 @@ remote_target::update_thread_list ()
                 executing until proven otherwise with a stop reply.
                 In all-stop, we can only get here if all threads are
                 stopped.  */
-             int executing = target_is_non_stop_p () ? 1 : 0;
+             bool executing = target_is_non_stop_p ();
 
              remote_notice_new_inferior (item.ptid, executing);
 
@@ -4116,9 +4166,9 @@ remote_target::static_tracepoint_markers_by_strid (const char *strid)
 /* Implement the to_get_ada_task_ptid function for the remote targets.  */
 
 ptid_t
-remote_target::get_ada_task_ptid (long lwp, long thread)
+remote_target::get_ada_task_ptid (long lwp, ULONGEST thread)
 {
-  return ptid_t (inferior_ptid.pid (), lwp, 0);
+  return ptid_t (inferior_ptid.pid (), lwp);
 }
 \f
 
@@ -4415,9 +4465,11 @@ remote_target::get_current_thread (const char *wait_status)
    whose response is a stop reply from which we can also try
    extracting the thread.  If the target doesn't support the explicit
    qC query, we infer the current thread from that stop reply, passed
-   in in WAIT_STATUS, which may be NULL.  */
+   in in WAIT_STATUS, which may be NULL.
 
-void
+   The function returns pointer to the main thread of the inferior. */
+
+thread_info *
 remote_target::add_current_inferior_and_thread (const char *wait_status)
 {
   struct remote_state *rs = get_remote_state ();
@@ -4451,25 +4503,42 @@ remote_target::add_current_inferior_and_thread (const char *wait_status)
      yet.  */
   thread_info *tp = add_thread_silent (this, curr_ptid);
   switch_to_thread_no_regs (tp);
+
+  return tp;
 }
 
 /* Print info about a thread that was found already stopped on
    connection.  */
 
-static void
-print_one_stopped_thread (struct thread_info *thread)
+void
+remote_target::print_one_stopped_thread (thread_info *thread)
 {
-  struct target_waitstatus *ws = &thread->suspend.waitstatus;
+  target_waitstatus ws;
+
+  /* If there is a pending waitstatus, use it.  If there isn't it's because
+     the thread's stop was reported with TARGET_WAITKIND_STOPPED / GDB_SIGNAL_0
+     and process_initial_stop_replies decided it wasn't interesting to save
+     and report to the core.  */
+  if (thread->has_pending_waitstatus ())
+    {
+      ws = thread->pending_waitstatus ();
+      thread->clear_pending_waitstatus ();
+    }
+  else
+    {
+      ws.set_stopped (GDB_SIGNAL_0);
+    }
 
   switch_to_thread (thread);
-  thread->suspend.stop_pc = get_frame_pc (get_current_frame ());
+  thread->set_stop_pc (get_frame_pc (get_current_frame ()));
   set_current_sal_from_frame (get_current_frame ());
 
-  thread->suspend.waitstatus_pending_p = 0;
+  /* For "info program".  */
+  set_last_target_status (this, thread->ptid, ws);
 
-  if (ws->kind == TARGET_WAITKIND_STOPPED)
+  if (ws.kind () == TARGET_WAITKIND_STOPPED)
     {
-      enum gdb_signal sig = ws->value.sig;
+      enum gdb_signal sig = ws.sig ();
 
       if (signal_print_state (sig))
        gdb::observers::signal_received.notify (sig);
@@ -4490,6 +4559,9 @@ remote_target::process_initial_stop_replies (int from_tty)
   struct thread_info *lowest_stopped = NULL;
   struct thread_info *first = NULL;
 
+  /* This is only used when the target is non-stop.  */
+  gdb_assert (target_is_non_stop_p ());
+
   /* Consume the initial pending events.  */
   while (pending_stop_replies-- > 0)
     {
@@ -4498,26 +4570,21 @@ remote_target::process_initial_stop_replies (int from_tty)
       struct target_waitstatus ws;
       int ignore_event = 0;
 
-      memset (&ws, 0, sizeof (ws));
       event_ptid = target_wait (waiton_ptid, &ws, TARGET_WNOHANG);
       if (remote_debug)
-       print_target_wait_results (waiton_ptid, event_ptid, &ws);
+       print_target_wait_results (waiton_ptid, event_ptid, ws);
 
-      switch (ws.kind)
+      switch (ws.kind ())
        {
        case TARGET_WAITKIND_IGNORE:
        case TARGET_WAITKIND_NO_RESUMED:
        case TARGET_WAITKIND_SIGNALLED:
        case TARGET_WAITKIND_EXITED:
          /* We shouldn't see these, but if we do, just ignore.  */
-         if (remote_debug)
-           fprintf_unfiltered (gdb_stdlog, "remote: event ignored\n");
+         remote_debug_printf ("event ignored");
          ignore_event = 1;
          break;
 
-       case TARGET_WAITKIND_EXECD:
-         xfree (ws.value.execd_pathname);
-         break;
        default:
          break;
        }
@@ -4527,23 +4594,21 @@ remote_target::process_initial_stop_replies (int from_tty)
 
       thread_info *evthread = find_thread_ptid (this, event_ptid);
 
-      if (ws.kind == TARGET_WAITKIND_STOPPED)
+      if (ws.kind () == TARGET_WAITKIND_STOPPED)
        {
-         enum gdb_signal sig = ws.value.sig;
+         enum gdb_signal sig = ws.sig ();
 
          /* Stubs traditionally report SIGTRAP as initial signal,
             instead of signal 0.  Suppress it.  */
          if (sig == GDB_SIGNAL_TRAP)
            sig = GDB_SIGNAL_0;
-         evthread->suspend.stop_signal = sig;
-         ws.value.sig = sig;
+         evthread->set_stop_signal (sig);
+         ws.set_stopped (sig);
        }
 
-      evthread->suspend.waitstatus = ws;
-
-      if (ws.kind != TARGET_WAITKIND_STOPPED
-         || ws.value.sig != GDB_SIGNAL_0)
-       evthread->suspend.waitstatus_pending_p = 1;
+      if (ws.kind () != TARGET_WAITKIND_STOPPED
+         || ws.sig () != GDB_SIGNAL_0)
+       evthread->set_pending_waitstatus (ws);
 
       set_executing (this, event_ptid, false);
       set_running (this, event_ptid, false);
@@ -4569,7 +4634,15 @@ remote_target::process_initial_stop_replies (int from_tty)
      the inferiors.  */
   if (!non_stop)
     {
-      stop_all_threads ();
+      {
+       /* At this point, the remote target is not async.  It needs to be for
+          the poll in stop_all_threads to consider events from it, so enable
+          it temporarily.  */
+       gdb_assert (!this->is_async_p ());
+       SCOPE_EXIT { target_async (0); };
+       target_async (1);
+       stop_all_threads ();
+      }
 
       /* If all threads of an inferior were already stopped, we
         haven't setup the inferior yet.  */
@@ -4597,8 +4670,7 @@ remote_target::process_initial_stop_replies (int from_tty)
       else if (thread->state != THREAD_STOPPED)
        continue;
 
-      if (selected == NULL
-         && thread->suspend.waitstatus_pending_p)
+      if (selected == nullptr && thread->has_pending_waitstatus ())
        selected = thread;
 
       if (lowest_stopped == NULL
@@ -4622,18 +4694,50 @@ remote_target::process_initial_stop_replies (int from_tty)
 
       print_one_stopped_thread (thread);
     }
-
-  /* For "info program".  */
-  thread_info *thread = inferior_thread ();
-  if (thread->state == THREAD_STOPPED)
-    set_last_target_status (this, inferior_ptid, thread->suspend.waitstatus);
 }
 
-/* Start the remote connection and sync state.  */
+/* Mark a remote_target as marking (by setting the starting_up flag within
+   its remote_state) for the lifetime of this object.  The reference count
+   on the remote target is temporarily incremented, to prevent the target
+   being deleted under our feet.  */
 
-void
-remote_target::start_remote (int from_tty, int extended_p)
+struct scoped_mark_target_starting
+{
+  /* Constructor, TARGET is the target to be marked as starting, its
+     reference count will be incremented.  */
+  scoped_mark_target_starting (remote_target *target)
+    : m_remote_target (target)
+  {
+    m_remote_target->incref ();
+    remote_state *rs = m_remote_target->get_remote_state ();
+    rs->starting_up = true;
+  }
+
+  /* Destructor, mark the target being worked on as no longer starting, and
+     decrement the reference count.  */
+  ~scoped_mark_target_starting ()
+  {
+    remote_state *rs = m_remote_target->get_remote_state ();
+    rs->starting_up = false;
+    decref_target (m_remote_target);
+  }
+
+private:
+
+  /* The target on which we are operating.  */
+  remote_target *m_remote_target;
+};
+
+/* Helper for remote_target::start_remote, start the remote connection and
+   sync state.  Return true if everything goes OK, otherwise, return false.
+   This function exists so that the scoped_restore created within it will
+   expire before we return to remote_target::start_remote.  */
+
+bool
+remote_target::start_remote_1 (int from_tty, int extended_p)
 {
+  REMOTE_SCOPED_DEBUG_ENTER_EXIT;
+
   struct remote_state *rs = get_remote_state ();
   struct packet_config *noack_config;
 
@@ -4643,7 +4747,7 @@ remote_target::start_remote (int from_tty, int extended_p)
      Ctrl-C before we're connected and synced up can't interrupt the
      target.  Instead, it offers to drop the (potentially wedged)
      connection.  */
-  rs->starting_up = 1;
+  scoped_mark_target_starting target_is_starting (this);
 
   QUIT;
 
@@ -4781,11 +4885,7 @@ remote_target::start_remote (int from_tty, int extended_p)
        {
          if (!extended_p)
            error (_("The target is not running (try extended-remote?)"));
-
-         /* We're connected, but not running.  Drop out before we
-            call start_remote.  */
-         rs->starting_up = 0;
-         return;
+         return false;
        }
       else
        {
@@ -4805,7 +4905,8 @@ remote_target::start_remote (int from_tty, int extended_p)
          /* Target has no concept of threads at all.  GDB treats
             non-threaded target as single-threaded; add a main
             thread.  */
-         add_current_inferior_and_thread (wait_status);
+         thread_info *tp = add_current_inferior_and_thread (wait_status);
+         get_remote_thread_info (tp)->set_resumed ();
        }
       else
        {
@@ -4820,11 +4921,9 @@ remote_target::start_remote (int from_tty, int extended_p)
                 tell us which thread was current (no "thread"
                 register in T stop reply?).  Just pick the first
                 thread in the thread list then.  */
-             
-             if (remote_debug)
-               fprintf_unfiltered (gdb_stdlog,
-                                   "warning: couldn't determine remote "
-                                   "current thread; picking first in list.\n");
+
+             remote_debug_printf ("warning: couldn't determine remote "
+                                  "current thread; picking first in list.");
 
              for (thread_info *tp : all_non_exited_threads (this,
                                                             minus_one_ptid))
@@ -4863,8 +4962,9 @@ remote_target::start_remote (int from_tty, int extended_p)
 
       /* Use the previously fetched status.  */
       gdb_assert (wait_status != NULL);
-      strcpy (rs->buf.data (), wait_status);
-      rs->cached_wait_status = 1;
+      struct notif_event *reply
+       = remote_notif_parse (this, &notif_client_stop, wait_status);
+      push_stop_reply ((struct stop_reply *) reply);
 
       ::start_remote (from_tty); /* Initialize gdb process mechanisms.  */
     }
@@ -4897,11 +4997,7 @@ remote_target::start_remote (int from_tty, int extended_p)
        {
          if (!extended_p)
            error (_("The target is not running (try extended-remote?)"));
-
-         /* We're connected, but not running.  Drop out before we
-            call start_remote.  */
-         rs->starting_up = 0;
-         return;
+         return false;
        }
 
       /* Report all signals during attach/startup.  */
@@ -4941,14 +5037,16 @@ remote_target::start_remote (int from_tty, int extended_p)
      previously; find out where things are at.  */
   remote_btrace_maybe_reopen ();
 
-  /* The thread and inferior lists are now synchronized with the
-     target, our symbols have been relocated, and we're merged the
-     target's tracepoints with ours.  We're done with basic start
-     up.  */
-  rs->starting_up = 0;
+  return true;
+}
 
-  /* Maybe breakpoints are global and need to be inserted now.  */
-  if (breakpoints_should_be_inserted_now ())
+/* Start the remote connection and sync state.  */
+
+void
+remote_target::start_remote (int from_tty, int extended_p)
+{
+  if (start_remote_1 (from_tty, extended_p)
+      && breakpoints_should_be_inserted_now ())
     insert_breakpoints ();
 }
 
@@ -5060,9 +5158,8 @@ remote_target::remote_check_symbols ()
 
          /* If this is a function address, return the start of code
             instead of any data function descriptor.  */
-         sym_addr = gdbarch_convert_from_func_ptr_addr (target_gdbarch (),
-                                                        sym_addr,
-                                                        current_top_target ());
+         sym_addr = gdbarch_convert_from_func_ptr_addr
+           (target_gdbarch (), sym_addr, current_inferior ()->top_target ());
 
          xsnprintf (msg.data (), get_remote_packet_size (), "qSymbol:%s:%s",
                     phex_nz (sym_addr, addr_size), &reply[8]);
@@ -5309,6 +5406,8 @@ static const struct protocol_feature remote_protocol_features[] = {
   { "vContSupported", PACKET_DISABLE, remote_supported_packet, PACKET_vContSupported },
   { "QThreadEvents", PACKET_DISABLE, remote_supported_packet, PACKET_QThreadEvents },
   { "no-resumed", PACKET_DISABLE, remote_supported_packet, PACKET_no_resumed },
+  { "memory-tagging", PACKET_DISABLE, remote_supported_packet,
+    PACKET_memory_tagging_feature },
 };
 
 static char *remote_support_xml;
@@ -5403,6 +5502,10 @@ remote_target::remote_query_supported ()
       if (packet_set_cmd_state (PACKET_no_resumed) != AUTO_BOOLEAN_FALSE)
        remote_query_supported_append (&q, "no-resumed+");
 
+      if (packet_set_cmd_state (PACKET_memory_tagging_feature)
+         != AUTO_BOOLEAN_FALSE)
+       remote_query_supported_append (&q, "memory-tagging+");
+
       /* Keep this one last to work around a gdbserver <= 7.10 bug in
         the qSupported:xmlRegisters=i386 handling.  */
       if (remote_support_xml != NULL
@@ -5596,6 +5699,15 @@ remote_unpush_target (remote_target *target)
       pop_all_targets_at_and_above (process_stratum);
       generic_mourn_inferior ();
     }
+
+  /* Don't rely on target_close doing this when the target is popped
+     from the last remote inferior above, because something may be
+     holding a reference to the target higher up on the stack, meaning
+     target_close won't be called yet.  We lost the connection to the
+     target, so clear these now, otherwise we may later throw
+     TARGET_CLOSE_ERROR while trying to tell the remote target to
+     close the file.  */
+  fileio_handles_invalidate_target (target);
 }
 
 static void
@@ -5630,7 +5742,7 @@ remote_target::open_1 (const char *name, int from_tty, int extended_p)
 
   remote_fileio_reset ();
   reopen_exec_file ();
-  reread_symbols ();
+  reread_symbols (from_tty);
 
   remote_target *remote
     = (extended_p ? new extended_remote_target () : new remote_target ());
@@ -5675,18 +5787,17 @@ remote_target::open_1 (const char *name, int from_tty, int extended_p)
     }
 
   /* Switch to using the remote target now.  */
-  push_target (std::move (target_holder));
+  current_inferior ()->push_target (std::move (target_holder));
 
   /* Register extra event sources in the event loop.  */
   rs->remote_async_inferior_event_token
-    = create_async_event_handler (remote_async_inferior_event_handler, remote,
+    = create_async_event_handler (remote_async_inferior_event_handler, nullptr,
                                  "remote");
   rs->notif_state = remote_notif_state_allocate (remote);
 
   /* Reset the target state; these things will be queried either by
      remote_query_supported or as they are needed.  */
   reset_all_packet_configs_support ();
-  rs->cached_wait_status = 0;
   rs->explicit_packet_size = 0;
   rs->noack_mode = 0;
   rs->extended = extended_p;
@@ -5758,6 +5869,32 @@ remote_target::open_1 (const char *name, int from_tty, int extended_p)
     rs->wait_forever_enabled_p = 1;
 }
 
+/* Determine if WS represents a fork status.  */
+
+static bool
+is_fork_status (target_waitkind kind)
+{
+  return (kind == TARGET_WAITKIND_FORKED
+         || kind == TARGET_WAITKIND_VFORKED);
+}
+
+/* Return THREAD's pending status if it is a pending fork parent, else
+   return nullptr.  */
+
+static const target_waitstatus *
+thread_pending_fork_status (struct thread_info *thread)
+{
+  const target_waitstatus &ws
+    = (thread->has_pending_waitstatus ()
+       ? thread->pending_waitstatus ()
+       : thread->pending_follow);
+
+  if (!is_fork_status (ws.kind ()))
+    return nullptr;
+
+  return &ws;
+}
+
 /* Detach the specified process.  */
 
 void
@@ -5807,6 +5944,16 @@ remote_target::remote_detach_1 (inferior *inf, int from_tty)
 
   target_announce_detach (from_tty);
 
+  if (!gdbarch_has_global_breakpoints (target_gdbarch ()))
+    {
+      /* If we're in breakpoints-always-inserted mode, or the inferior
+        is running, we have to remove breakpoints before detaching.
+        We don't do this in common code instead because not all
+        targets support removing breakpoints while the target is
+        running.  The remote target / gdbserver does, though.  */
+      remove_breakpoints_inf (current_inferior ());
+    }
+
   /* Tell the remote target to detach.  */
   remote_detach_pid (pid);
 
@@ -5814,12 +5961,38 @@ remote_target::remote_detach_1 (inferior *inf, int from_tty)
   if (from_tty && !rs->extended && number_of_live_inferiors (this) == 1)
     puts_filtered (_("Ending remote debugging.\n"));
 
+  /* See if any thread of the inferior we are detaching has a pending fork
+     status.  In that case, we must detach from the child resulting from
+     that fork.  */
+  for (thread_info *thread : inf->non_exited_threads ())
+    {
+      const target_waitstatus *ws = thread_pending_fork_status (thread);
+
+      if (ws == nullptr)
+       continue;
+
+      remote_detach_pid (ws->child_ptid ().pid ());
+    }
+
+  /* Check also for any pending fork events in the stop reply queue.  */
+  remote_notif_get_pending_events (&notif_client_stop);
+  for (stop_reply_up &reply : rs->stop_reply_queue)
+    {
+      if (reply->ptid.pid () != pid)
+       continue;
+
+      if (!is_fork_status (reply->ws.kind ()))
+       continue;
+
+      remote_detach_pid (reply->ws.child_ptid ().pid ());
+    }
+
   thread_info *tp = find_thread_ptid (this, inferior_ptid);
 
   /* Check to see if we are detaching a fork parent.  Note that if we
      are detaching a fork child, tp == NULL.  */
   is_fork_parent = (tp != NULL
-                   && tp->pending_follow.kind == TARGET_WAITKIND_FORKED);
+                   && tp->pending_follow.kind () == TARGET_WAITKIND_FORKED);
 
   /* If doing detach-on-fork, we don't mourn, because that will delete
      breakpoints that should be available for the followed inferior.  */
@@ -5860,14 +6033,18 @@ extended_remote_target::detach (inferior *inf, int from_tty)
    it is named remote_follow_fork in anticipation of using it for the
    remote target as well.  */
 
-bool
-remote_target::follow_fork (bool follow_child, bool detach_fork)
+void
+remote_target::follow_fork (inferior *child_inf, ptid_t child_ptid,
+                           target_waitkind fork_kind, bool follow_child,
+                           bool detach_fork)
 {
+  process_stratum_target::follow_fork (child_inf, child_ptid,
+                                      fork_kind, follow_child, detach_fork);
+
   struct remote_state *rs = get_remote_state ();
-  enum target_waitkind kind = inferior_thread ()->pending_follow.kind;
 
-  if ((kind == TARGET_WAITKIND_FORKED && remote_fork_event_p (rs))
-      || (kind == TARGET_WAITKIND_VFORKED && remote_vfork_event_p (rs)))
+  if ((fork_kind == TARGET_WAITKIND_FORKED && remote_fork_event_p (rs))
+      || (fork_kind == TARGET_WAITKIND_VFORKED && remote_vfork_event_p (rs)))
     {
       /* When following the parent and detaching the child, we detach
         the child here.  For the case of following the child and
@@ -5878,34 +6055,26 @@ remote_target::follow_fork (bool follow_child, bool detach_fork)
       if (detach_fork && !follow_child)
        {
          /* Detach the fork child.  */
-         ptid_t child_ptid;
-         pid_t child_pid;
-
-         child_ptid = inferior_thread ()->pending_follow.value.related_pid;
-         child_pid = child_ptid.pid ();
-
-         remote_detach_pid (child_pid);
+         remote_detach_pid (child_ptid.pid ());
        }
     }
-
-  return false;
 }
 
 /* Target follow-exec function for remote targets.  Save EXECD_PATHNAME
-   in the program space of the new inferior.  On entry and at return the
-   current inferior is the exec'ing inferior.  INF is the new exec'd
-   inferior, which may be the same as the exec'ing inferior unless
-   follow-exec-mode is "new".  */
+   in the program space of the new inferior.  */
 
 void
-remote_target::follow_exec (struct inferior *inf, const char *execd_pathname)
+remote_target::follow_exec (inferior *follow_inf, ptid_t ptid,
+                           const char *execd_pathname)
 {
+  process_stratum_target::follow_exec (follow_inf, ptid, execd_pathname);
+
   /* We know that this is a target file name, so if it has the "target:"
      prefix we strip it off before saving it in the program space.  */
   if (is_target_filename (execd_pathname))
     execd_pathname += strlen (TARGET_SYSROOT_PREFIX);
 
-  set_pspace_remote_exec_file (inf->pspace, execd_pathname);
+  set_pspace_remote_exec_file (follow_inf->pspace, execd_pathname);
 }
 
 /* Same as remote_detach, but don't send the "D" packet; just disconnect.  */
@@ -5944,17 +6113,7 @@ extended_remote_target::attach (const char *args, int from_tty)
   if (packet_support (PACKET_vAttach) == PACKET_DISABLE)
     error (_("This target does not support attaching to a process"));
 
-  if (from_tty)
-    {
-      const char *exec_file = get_exec_file (0);
-
-      if (exec_file)
-       printf_unfiltered (_("Attaching to program: %s, %s\n"), exec_file,
-                          target_pid_to_str (ptid_t (pid)).c_str ());
-      else
-       printf_unfiltered (_("Attaching to %s\n"),
-                          target_pid_to_str (ptid_t (pid)).c_str ());
-    }
+  target_announce_attach (from_tty, pid);
 
   xsnprintf (rs->buf.data (), get_remote_packet_size (), "vAttach;%x", pid);
   putpkt (rs->buf);
@@ -6004,14 +6163,11 @@ extended_remote_target::attach (const char *args, int from_tty)
         ptid.  */
       ptid_t curr_ptid = remote_current_thread (ptid_t (pid));
 
-      /* Add the main thread to the thread list.  */
-      thread_info *thr = add_thread_silent (this, curr_ptid);
+      /* Add the main thread to the thread list.  We add the thread
+        silently in this case (the final true parameter).  */
+      thread_info *thr = remote_add_thread (curr_ptid, true, true, true);
 
       switch_to_thread (thr);
-
-      /* Don't consider the thread stopped until we've processed the
-        saved stop reply.  */
-      set_executing (this, thr->ptid, true);
     }
 
   /* Next, if the target can specify a description, read it.  We do
@@ -6023,24 +6179,17 @@ extended_remote_target::attach (const char *args, int from_tty)
       /* Use the previously fetched status.  */
       gdb_assert (wait_status != NULL);
 
-      if (target_can_async_p ())
-       {
-         struct notif_event *reply
-           =  remote_notif_parse (this, &notif_client_stop, wait_status);
-
-         push_stop_reply ((struct stop_reply *) reply);
+      struct notif_event *reply
+       =  remote_notif_parse (this, &notif_client_stop, wait_status);
 
-         target_async (1);
-       }
-      else
-       {
-         gdb_assert (wait_status != NULL);
-         strcpy (rs->buf.data (), wait_status);
-         rs->cached_wait_status = 1;
-       }
+      push_stop_reply ((struct stop_reply *) reply);
     }
   else
-    gdb_assert (wait_status == NULL);
+    {
+      gdb_assert (wait_status == NULL);
+
+      gdb_assert (target_can_async_p ());
+    }
 }
 
 /* Implementation of the to_post_attach method.  */
@@ -6182,7 +6331,7 @@ remote_target::append_resumption (char *p, char *endp,
       ptid_t nptid;
 
       /* All (-1) threads of process.  */
-      nptid = ptid_t (ptid.pid (), -1, 0);
+      nptid = ptid_t (ptid.pid (), -1);
 
       p += xsnprintf (p, endp - p, ":");
       p = write_ptid (p, endp, nptid);
@@ -6219,11 +6368,11 @@ remote_target::append_pending_thread_resumptions (char *p, char *endp,
 {
   for (thread_info *thread : all_non_exited_threads (this, ptid))
     if (inferior_ptid != thread->ptid
-       && thread->suspend.stop_signal != GDB_SIGNAL_0)
+       && thread->stop_signal () != GDB_SIGNAL_0)
       {
        p = append_resumption (p, endp, thread->ptid,
-                              0, thread->suspend.stop_signal);
-       thread->suspend.stop_signal = GDB_SIGNAL_0;
+                              0, thread->stop_signal ());
+       thread->set_stop_signal (GDB_SIGNAL_0);
        resume_clear_thread_private_info (thread);
       }
 
@@ -6393,7 +6542,7 @@ remote_target::resume (ptid_t ptid, int step, enum gdb_signal siggnal)
 
       /* We don't expect the core to ask to resume an already resumed (from
          its point of view) thread.  */
-      gdb_assert (remote_thr->resume_state () == resume_state::NOT_RESUMED);
+      gdb_assert (remote_thr->get_resume_state () == resume_state::NOT_RESUMED);
 
       remote_thr->set_resumed_pending_vcont (step, siggnal);
       return;
@@ -6418,16 +6567,6 @@ remote_target::resume (ptid_t ptid, int step, enum gdb_signal siggnal)
   for (thread_info *tp : all_non_exited_threads (this, ptid))
     get_remote_thread_info (tp)->set_resumed ();
 
-  /* We are about to start executing the inferior, let's register it
-     with the event loop.  NOTE: this is the one place where all the
-     execution commands end up.  We could alternatively do this in each
-     of the execution commands in infcmd.c.  */
-  /* FIXME: ezannoni 1999-09-28: We may need to move this out of here
-     into infcmd.c in order to allow inferior function calls to work
-     NOT asynchronously.  */
-  if (target_can_async_p ())
-    target_async (1);
-
   /* We've just told the target to resume.  The remote server will
      wait for the inferior to stop, and then send a stop reply.  In
      the mean time, we can't start another command/query ourselves
@@ -6439,8 +6578,6 @@ remote_target::resume (ptid_t ptid, int step, enum gdb_signal siggnal)
     rs->waiting_for_stop_reply = 1;
 }
 
-static int is_pending_fork_parent_thread (struct thread_info *thread);
-
 /* Private per-inferior info for target remote processes.  */
 
 struct remote_inferior : public private_inferior
@@ -6564,11 +6701,8 @@ vcont_builder::push_action (ptid_t ptid, bool step, gdb_signal siggnal)
 /* to_commit_resume implementation.  */
 
 void
-remote_target::commit_resume ()
+remote_target::commit_resumed ()
 {
-  int any_process_wildcard;
-  int may_global_wildcard_vcont;
-
   /* If connected in all-stop mode, we'd send the remote resume
      request directly from remote_resume.  Likewise if
      reverse-debugging, as there are no defined vCont actions for
@@ -6625,7 +6759,7 @@ remote_target::commit_resume ()
      (vCont;c).  We can still send process-wide wildcards though.  */
 
   /* Start by assuming a global wildcard (vCont;c) is possible.  */
-  may_global_wildcard_vcont = 1;
+  bool may_global_wildcard_vcont = true;
 
   /* And assume every process is individually wildcard-able too.  */
   for (inferior *inf : all_non_exited_inferiors (this))
@@ -6639,29 +6773,39 @@ remote_target::commit_resume ()
      disable process and global wildcard resumes appropriately.  */
   check_pending_events_prevent_wildcard_vcont (&may_global_wildcard_vcont);
 
+  bool any_pending_vcont_resume = false;
+
   for (thread_info *tp : all_non_exited_threads (this))
     {
       remote_thread_info *priv = get_remote_thread_info (tp);
 
       /* If a thread of a process is not meant to be resumed, then we
         can't wildcard that process.  */
-      if (priv->resume_state () == resume_state::NOT_RESUMED)
+      if (priv->get_resume_state () == resume_state::NOT_RESUMED)
        {
          get_remote_inferior (tp->inf)->may_wildcard_vcont = false;
 
          /* And if we can't wildcard a process, we can't wildcard
             everything either.  */
-         may_global_wildcard_vcont = 0;
+         may_global_wildcard_vcont = false;
          continue;
        }
 
+      if (priv->get_resume_state () == resume_state::RESUMED_PENDING_VCONT)
+       any_pending_vcont_resume = true;
+
       /* If a thread is the parent of an unfollowed fork, then we
         can't do a global wildcard, as that would resume the fork
         child.  */
-      if (is_pending_fork_parent_thread (tp))
-       may_global_wildcard_vcont = 0;
+      if (thread_pending_fork_status (tp) != nullptr)
+       may_global_wildcard_vcont = false;
     }
 
+  /* We didn't have any resumed thread pending a vCont resume, so nothing to
+     do.  */
+  if (!any_pending_vcont_resume)
+    return;
+
   /* Now let's build the vCont packet(s).  Actions must be appended
      from narrower to wider scopes (thread -> process -> global).  If
      we end up with too many actions for a single packet vcont_builder
@@ -6677,11 +6821,18 @@ remote_target::commit_resume ()
       /* If the thread was previously vCont-resumed, no need to send a specific
         action for it.  If we didn't receive a resume request for it, don't
         send an action for it either.  */
-      if (remote_thr->resume_state () != resume_state::RESUMED_PENDING_VCONT)
+      if (remote_thr->get_resume_state () != resume_state::RESUMED_PENDING_VCONT)
        continue;
 
       gdb_assert (!thread_is_in_step_over_chain (tp));
 
+      /* We should never be commit-resuming a thread that has a stop reply.
+         Otherwise, we would end up reporting a stop event for a thread while
+        it is running on the remote target.  */
+      remote_state *rs = get_remote_state ();
+      for (const auto &stop_reply : rs->stop_reply_queue)
+       gdb_assert (stop_reply->ptid != tp->ptid);
+
       const resumed_pending_vcont_info &info
        = remote_thr->resumed_pending_vcont_info ();
 
@@ -6697,13 +6848,13 @@ remote_target::commit_resume ()
   /* Now check whether we can send any process-wide wildcard.  This is
      to avoid sending a global wildcard in the case nothing is
      supposed to be resumed.  */
-  any_process_wildcard = 0;
+  bool any_process_wildcard = false;
 
   for (inferior *inf : all_non_exited_inferiors (this))
     {
       if (get_remote_inferior (inf)->may_wildcard_vcont)
        {
-         any_process_wildcard = 1;
+         any_process_wildcard = true;
          break;
        }
     }
@@ -6734,6 +6885,26 @@ remote_target::commit_resume ()
   vcont_builder.flush ();
 }
 
+/* Implementation of target_has_pending_events.  */
+
+bool
+remote_target::has_pending_events ()
+{
+  if (target_can_async_p ())
+    {
+      remote_state *rs = get_remote_state ();
+
+      if (async_event_handler_marked (rs->remote_async_inferior_event_token))
+       return true;
+
+      /* Note that BUFCNT can be negative, indicating sticky
+        error.  */
+      if (rs->remote_desc->bufcnt != 0)
+       return true;
+    }
+  return false;
+}
+
 \f
 
 /* Non-stop version of target_stop.  Uses `vCont;t' to stop a remote
@@ -6747,6 +6918,74 @@ remote_target::remote_stop_ns (ptid_t ptid)
   char *p = rs->buf.data ();
   char *endp = p + get_remote_packet_size ();
 
+  /* If any thread that needs to stop was resumed but pending a vCont
+     resume, generate a phony stop_reply.  However, first check
+     whether the thread wasn't resumed with a signal.  Generating a
+     phony stop in that case would result in losing the signal.  */
+  bool needs_commit = false;
+  for (thread_info *tp : all_non_exited_threads (this, ptid))
+    {
+      remote_thread_info *remote_thr = get_remote_thread_info (tp);
+
+      if (remote_thr->get_resume_state ()
+         == resume_state::RESUMED_PENDING_VCONT)
+       {
+         const resumed_pending_vcont_info &info
+           = remote_thr->resumed_pending_vcont_info ();
+         if (info.sig != GDB_SIGNAL_0)
+           {
+             /* This signal must be forwarded to the inferior.  We
+                could commit-resume just this thread, but its simpler
+                to just commit-resume everything.  */
+             needs_commit = true;
+             break;
+           }
+       }
+    }
+
+  if (needs_commit)
+    commit_resumed ();
+  else
+    for (thread_info *tp : all_non_exited_threads (this, ptid))
+      {
+       remote_thread_info *remote_thr = get_remote_thread_info (tp);
+
+       if (remote_thr->get_resume_state ()
+           == resume_state::RESUMED_PENDING_VCONT)
+         {
+           remote_debug_printf ("Enqueueing phony stop reply for thread pending "
+                                "vCont-resume (%d, %ld, %s)", tp->ptid.pid(),
+                                tp->ptid.lwp (),
+                                pulongest (tp->ptid.tid ()));
+
+           /* Check that the thread wasn't resumed with a signal.
+              Generating a phony stop would result in losing the
+              signal.  */
+           const resumed_pending_vcont_info &info
+             = remote_thr->resumed_pending_vcont_info ();
+           gdb_assert (info.sig == GDB_SIGNAL_0);
+
+           stop_reply *sr = new stop_reply ();
+           sr->ptid = tp->ptid;
+           sr->rs = rs;
+           sr->ws.set_stopped (GDB_SIGNAL_0);
+           sr->arch = tp->inf->gdbarch;
+           sr->stop_reason = TARGET_STOPPED_BY_NO_REASON;
+           sr->watch_data_address = 0;
+           sr->core = 0;
+           this->push_stop_reply (sr);
+
+           /* Pretend that this thread was actually resumed on the
+              remote target, then stopped.  If we leave it in the
+              RESUMED_PENDING_VCONT state and the commit_resumed
+              method is called while the stop reply is still in the
+              queue, we'll end up reporting a stop event to the core
+              for that thread while it is running on the remote
+              target... that would be bad.  */
+           remote_thr->set_resumed ();
+         }
+      }
+
   /* FIXME: This supports_vCont_probed check is a workaround until
      packet_support is per-connection.  */
   if (packet_support (PACKET_vCont) == PACKET_SUPPORT_UNKNOWN
@@ -6767,7 +7006,7 @@ remote_target::remote_stop_ns (ptid_t ptid)
 
       if (ptid.is_pid ())
          /* All (-1) threads of process.  */
-       nptid = ptid_t (ptid.pid (), -1, 0);
+       nptid = ptid_t (ptid.pid (), -1);
       else
        {
          /* Small optimization: if we already have a stop reply for
@@ -6803,9 +7042,9 @@ remote_target::remote_interrupt_as ()
   rs->ctrlc_pending_p = 1;
 
   /* If the inferior is stopped already, but the core didn't know
-     about it yet, just ignore the request.  The cached wait status
+     about it yet, just ignore the request.  The pending stop events
      will be collected in remote_wait.  */
-  if (rs->cached_wait_status)
+  if (stop_reply_queue_length () > 0)
     return;
 
   /* Send interrupt_sequence to remote target.  */
@@ -6847,8 +7086,7 @@ remote_target::remote_interrupt_ns ()
 void
 remote_target::stop (ptid_t ptid)
 {
-  if (remote_debug)
-    fprintf_unfiltered (gdb_stdlog, "remote_stop called\n");
+  REMOTE_SCOPED_DEBUG_ENTER_EXIT;
 
   if (target_is_non_stop_p ())
     remote_stop_ns (ptid);
@@ -6865,8 +7103,7 @@ remote_target::stop (ptid_t ptid)
 void
 remote_target::interrupt ()
 {
-  if (remote_debug)
-    fprintf_unfiltered (gdb_stdlog, "remote_interrupt called\n");
+  REMOTE_SCOPED_DEBUG_ENTER_EXIT;
 
   if (target_is_non_stop_p ())
     remote_interrupt_ns ();
@@ -6879,10 +7116,9 @@ remote_target::interrupt ()
 void
 remote_target::pass_ctrlc ()
 {
-  struct remote_state *rs = get_remote_state ();
+  REMOTE_SCOPED_DEBUG_ENTER_EXIT;
 
-  if (remote_debug)
-    fprintf_unfiltered (gdb_stdlog, "remote_pass_ctrlc called\n");
+  struct remote_state *rs = get_remote_state ();
 
   /* If we're starting up, we're not fully synced yet.  Quit
      immediately.  */
@@ -6954,36 +7190,6 @@ remote_console_output (const char *msg)
   gdb_stdtarg->flush ();
 }
 
-struct stop_reply : public notif_event
-{
-  ~stop_reply ();
-
-  /* The identifier of the thread about this event  */
-  ptid_t ptid;
-
-  /* The remote state this event is associated with.  When the remote
-     connection, represented by a remote_state object, is closed,
-     all the associated stop_reply events should be released.  */
-  struct remote_state *rs;
-
-  struct target_waitstatus ws;
-
-  /* The architecture associated with the expedited registers.  */
-  gdbarch *arch;
-
-  /* Expedited registers.  This makes remote debugging a bit more
-     efficient for those targets that provide critical registers as
-     part of their normal status mechanism (as another roundtrip to
-     fetch them is avoided).  */
-  std::vector<cached_reg_t> regcache;
-
-  enum target_stop_reason stop_reason;
-
-  CORE_ADDR watch_data_address;
-
-  int core;
-};
-
 /* Return the length of the stop reply queue.  */
 
 int
@@ -7011,13 +7217,11 @@ remote_notif_stop_ack (remote_target *remote,
   /* acknowledge */
   putpkt (remote, self->ack_command);
 
-  if (stop_reply->ws.kind == TARGET_WAITKIND_IGNORE)
-    {
-      /* We got an unknown stop reply.  */
-      error (_("Unknown stop reply"));
-    }
-
-  remote->push_stop_reply (stop_reply);
+  /* Kind can be TARGET_WAITKIND_IGNORE if we have meanwhile discarded
+     the notification.  It was left in the queue because we need to
+     acknowledge it and pull the rest of the notifications out.  */
+  if (stop_reply->ws.kind () != TARGET_WAITKIND_IGNORE)
+    remote->push_stop_reply (stop_reply);
 }
 
 static int
@@ -7059,47 +7263,6 @@ struct notif_client notif_client_stop =
   REMOTE_NOTIF_STOP,
 };
 
-/* Determine if THREAD_PTID is a pending fork parent thread.  ARG contains
-   the pid of the process that owns the threads we want to check, or
-   -1 if we want to check all threads.  */
-
-static int
-is_pending_fork_parent (struct target_waitstatus *ws, int event_pid,
-                       ptid_t thread_ptid)
-{
-  if (ws->kind == TARGET_WAITKIND_FORKED
-      || ws->kind == TARGET_WAITKIND_VFORKED)
-    {
-      if (event_pid == -1 || event_pid == thread_ptid.pid ())
-       return 1;
-    }
-
-  return 0;
-}
-
-/* Return the thread's pending status used to determine whether the
-   thread is a fork parent stopped at a fork event.  */
-
-static struct target_waitstatus *
-thread_pending_fork_status (struct thread_info *thread)
-{
-  if (thread->suspend.waitstatus_pending_p)
-    return &thread->suspend.waitstatus;
-  else
-    return &thread->pending_follow;
-}
-
-/* Determine if THREAD is a pending fork parent thread.  */
-
-static int
-is_pending_fork_parent_thread (struct thread_info *thread)
-{
-  struct target_waitstatus *ws = thread_pending_fork_status (thread);
-  int pid = -1;
-
-  return is_pending_fork_parent (ws, pid, thread->ptid);
-}
-
 /* If CONTEXT contains any fork child threads that have not been
    reported yet, remove them from the CONTEXT list.  If such a
    thread exists it is because we are stopped at a fork catchpoint
@@ -7109,17 +7272,18 @@ is_pending_fork_parent_thread (struct thread_info *thread)
 void
 remote_target::remove_new_fork_children (threads_listing_context *context)
 {
-  int pid = -1;
   struct notif_client *notif = &notif_client_stop;
 
   /* For any threads stopped at a fork event, remove the corresponding
      fork child threads from the CONTEXT list.  */
   for (thread_info *thread : all_non_exited_threads (this))
     {
-      struct target_waitstatus *ws = thread_pending_fork_status (thread);
+      const target_waitstatus *ws = thread_pending_fork_status (thread);
 
-      if (is_pending_fork_parent (ws, pid, thread->ptid))
-       context->remove_thread (ws->value.related_pid);
+      if (ws == nullptr)
+       continue;
+
+      context->remove_thread (ws->child_ptid ());
     }
 
   /* Check for any pending fork events (not reported or processed yet)
@@ -7127,43 +7291,45 @@ remote_target::remove_new_fork_children (threads_listing_context *context)
      CONTEXT list as well.  */
   remote_notif_get_pending_events (notif);
   for (auto &event : get_remote_state ()->stop_reply_queue)
-    if (event->ws.kind == TARGET_WAITKIND_FORKED
-       || event->ws.kind == TARGET_WAITKIND_VFORKED
-       || event->ws.kind == TARGET_WAITKIND_THREAD_EXITED)
-      context->remove_thread (event->ws.value.related_pid);
+    if (event->ws.kind () == TARGET_WAITKIND_FORKED
+       || event->ws.kind () == TARGET_WAITKIND_VFORKED
+       || event->ws.kind () == TARGET_WAITKIND_THREAD_EXITED)
+      context->remove_thread (event->ws.child_ptid ());
 }
 
-/* Check whether any event pending in the vStopped queue would prevent
-   a global or process wildcard vCont action.  Clear
-   *may_global_wildcard if we can't do a global wildcard (vCont;c),
-   and clear the event inferior's may_wildcard_vcont flag if we can't
-   do a process-wide wildcard resume (vCont;c:pPID.-1).  */
+/* Check whether any event pending in the vStopped queue would prevent a
+   global or process wildcard vCont action.  Set *may_global_wildcard to
+   false if we can't do a global wildcard (vCont;c), and clear the event
+   inferior's may_wildcard_vcont flag if we can't do a process-wide
+   wildcard resume (vCont;c:pPID.-1).  */
 
 void
 remote_target::check_pending_events_prevent_wildcard_vcont
-  (int *may_global_wildcard)
+  (bool *may_global_wildcard)
 {
   struct notif_client *notif = &notif_client_stop;
 
   remote_notif_get_pending_events (notif);
   for (auto &event : get_remote_state ()->stop_reply_queue)
     {
-      if (event->ws.kind == TARGET_WAITKIND_NO_RESUMED
-         || event->ws.kind == TARGET_WAITKIND_NO_HISTORY)
+      if (event->ws.kind () == TARGET_WAITKIND_NO_RESUMED
+         || event->ws.kind () == TARGET_WAITKIND_NO_HISTORY)
        continue;
 
-      if (event->ws.kind == TARGET_WAITKIND_FORKED
-         || event->ws.kind == TARGET_WAITKIND_VFORKED)
-       *may_global_wildcard = 0;
-
-      struct inferior *inf = find_inferior_ptid (this, event->ptid);
+      if (event->ws.kind () == TARGET_WAITKIND_FORKED
+         || event->ws.kind () == TARGET_WAITKIND_VFORKED)
+       *may_global_wildcard = false;
 
       /* This may be the first time we heard about this process.
         Regardless, we must not do a global wildcard resume, otherwise
         we'd resume this process too.  */
-      *may_global_wildcard = 0;
-      if (inf != NULL)
-       get_remote_inferior (inf)->may_wildcard_vcont = false;
+      *may_global_wildcard = false;
+      if (event->ptid != null_ptid)
+       {
+         inferior *inf = find_inferior_ptid (this, event->ptid);
+         if (inf != NULL)
+           get_remote_inferior (inf)->may_wildcard_vcont = false;
+       }
     }
 }
 
@@ -7186,8 +7352,14 @@ remote_target::discard_pending_stop_replies (struct inferior *inf)
   /* Discard the in-flight notification.  */
   if (reply != NULL && reply->ptid.pid () == inf->pid)
     {
-      delete reply;
-      rns->pending_event[notif_client_stop.id] = NULL;
+      /* Leave the notification pending, since the server expects that
+        we acknowledge it with vStopped.  But clear its contents, so
+        that later on when we acknowledge it, we also discard it.  */
+      remote_debug_printf
+       ("discarding in-flight notification: ptid: %s, ws: %s\n",
+        reply->ptid.to_string().c_str(),
+        reply->ws.to_string ().c_str ());
+      reply->ws.set_ignore ();
     }
 
   /* Discard the stop replies we have already pulled with
@@ -7198,6 +7370,11 @@ remote_target::discard_pending_stop_replies (struct inferior *inf)
                              {
                                return event->ptid.pid () == inf->pid;
                              });
+  for (auto it = iter; it != rs->stop_reply_queue.end (); ++it)
+    remote_debug_printf
+      ("discarding queued stop reply: ptid: %s, ws: %s\n",
+       reply->ptid.to_string().c_str(),
+       reply->ws.to_string ().c_str ());
   rs->stop_reply_queue.erase (iter, rs->stop_reply_queue.end ());
 }
 
@@ -7245,7 +7422,7 @@ remote_target::remote_notif_remove_queued_reply (ptid_t ptid)
   if (notif_debug)
     fprintf_unfiltered (gdb_stdlog,
                        "notif: discard queued event: 'Stop' in %s\n",
-                       target_pid_to_str (ptid).c_str ());
+                       ptid.to_string ().c_str ());
 
   return result;
 }
@@ -7261,7 +7438,7 @@ remote_target::queued_stop_reply (ptid_t ptid)
   remote_state *rs = get_remote_state ();
   struct stop_reply *r = remote_notif_remove_queued_reply (ptid);
 
-  if (!rs->stop_reply_queue.empty ())
+  if (!rs->stop_reply_queue.empty () && target_can_async_p ())
     {
       /* There's still at least an event left.  */
       mark_async_event_handler (rs->remote_async_inferior_event_token);
@@ -7283,10 +7460,15 @@ remote_target::push_stop_reply (struct stop_reply *new_event)
   if (notif_debug)
     fprintf_unfiltered (gdb_stdlog,
                        "notif: push 'Stop' %s to queue %d\n",
-                       target_pid_to_str (new_event->ptid).c_str (),
+                       new_event->ptid.to_string ().c_str (),
                        int (rs->stop_reply_queue.size ()));
 
-  mark_async_event_handler (rs->remote_async_inferior_event_token);
+  /* Mark the pending event queue only if async mode is currently enabled.
+     If async mode is not currently enabled, then, if it later becomes
+     enabled, and there are events in this queue, we will mark the event
+     token at that point, see remote_target::async.  */
+  if (target_is_async_p ())
+    mark_async_event_handler (rs->remote_async_inferior_event_token);
 }
 
 /* Returns true if we have a stop reply for PTID.  */
@@ -7297,7 +7479,7 @@ remote_target::peek_stop_reply (ptid_t ptid)
   remote_state *rs = get_remote_state ();
   for (auto &event : rs->stop_reply_queue)
     if (ptid == event->ptid
-       && event->ws.kind == TARGET_WAITKIND_STOPPED)
+       && event->ws.kind () == TARGET_WAITKIND_STOPPED)
       return 1;
   return 0;
 }
@@ -7327,8 +7509,7 @@ remote_target::remote_parse_stop_reply (const char *buf, stop_reply *event)
 
   event->ptid = null_ptid;
   event->rs = get_remote_state ();
-  event->ws.kind = TARGET_WAITKIND_IGNORE;
-  event->ws.value.integer = 0;
+  event->ws.set_ignore ();
   event->stop_reason = TARGET_STOPPED_BY_NO_REASON;
   event->regcache.clear ();
   event->core = -1;
@@ -7372,17 +7553,15 @@ Packet: '%s'\n"),
            {
              ULONGEST sysno;
 
-             event->ws.kind = TARGET_WAITKIND_SYSCALL_ENTRY;
              p = unpack_varlen_hex (++p1, &sysno);
-             event->ws.value.syscall_number = (int) sysno;
+             event->ws.set_syscall_entry ((int) sysno);
            }
          else if (strprefix (p, p1, "syscall_return"))
            {
              ULONGEST sysno;
 
-             event->ws.kind = TARGET_WAITKIND_SYSCALL_RETURN;
              p = unpack_varlen_hex (++p1, &sysno);
-             event->ws.value.syscall_number = (int) sysno;
+             event->ws.set_syscall_return ((int) sysno);
            }
          else if (strprefix (p, p1, "watch")
                   || strprefix (p, p1, "rwatch")
@@ -7420,12 +7599,12 @@ Packet: '%s'\n"),
            }
          else if (strprefix (p, p1, "library"))
            {
-             event->ws.kind = TARGET_WAITKIND_LOADED;
+             event->ws.set_loaded ();
              p = strchrnul (p1 + 1, ';');
            }
          else if (strprefix (p, p1, "replaylog"))
            {
-             event->ws.kind = TARGET_WAITKIND_NO_HISTORY;
+             event->ws.set_no_history ();
              /* p1 will indicate "begin" or "end", but it makes
                 no difference for now, so ignore it.  */
              p = strchrnul (p1 + 1, ';');
@@ -7438,18 +7617,12 @@ Packet: '%s'\n"),
              event->core = c;
            }
          else if (strprefix (p, p1, "fork"))
-           {
-             event->ws.value.related_pid = read_ptid (++p1, &p);
-             event->ws.kind = TARGET_WAITKIND_FORKED;
-           }
+           event->ws.set_forked (read_ptid (++p1, &p));
          else if (strprefix (p, p1, "vfork"))
-           {
-             event->ws.value.related_pid = read_ptid (++p1, &p);
-             event->ws.kind = TARGET_WAITKIND_VFORKED;
-           }
+           event->ws.set_vforked (read_ptid (++p1, &p));
          else if (strprefix (p, p1, "vforkdone"))
            {
-             event->ws.kind = TARGET_WAITKIND_VFORK_DONE;
+             event->ws.set_vfork_done ();
              p = strchrnul (p1 + 1, ';');
            }
          else if (strprefix (p, p1, "exec"))
@@ -7463,14 +7636,13 @@ Packet: '%s'\n"),
 
              /* Save the pathname for event reporting and for
                 the next run command.  */
-             gdb::unique_xmalloc_ptr<char[]> pathname
+             gdb::unique_xmalloc_ptr<char> pathname
                ((char *) xmalloc (pathlen + 1));
              hex2bin (p1, (gdb_byte *) pathname.get (), pathlen);
-             pathname[pathlen] = '\0';
+             pathname.get ()[pathlen] = '\0';
 
              /* This is freed during event handling.  */
-             event->ws.value.execd_pathname = pathname.release ();
-             event->ws.kind = TARGET_WAITKIND_EXECD;
+             event->ws.set_execd (std::move (pathname));
 
              /* Skip the registers included in this packet, since
                 they may be for an architecture different from the
@@ -7479,7 +7651,7 @@ Packet: '%s'\n"),
            }
          else if (strprefix (p, p1, "create"))
            {
-             event->ws.kind = TARGET_WAITKIND_THREAD_CREATED;
+             event->ws.set_thread_created ();
              p = strchrnul (p1 + 1, ';');
            }
          else
@@ -7578,7 +7750,7 @@ Packet: '%s'\n"),
          ++p;
        }
 
-      if (event->ws.kind != TARGET_WAITKIND_IGNORE)
+      if (event->ws.kind () != TARGET_WAITKIND_IGNORE)
        break;
 
       /* fall through */
@@ -7586,21 +7758,19 @@ Packet: '%s'\n"),
       {
        int sig;
 
-       event->ws.kind = TARGET_WAITKIND_STOPPED;
        sig = (fromhex (buf[1]) << 4) + fromhex (buf[2]);
        if (GDB_SIGNAL_FIRST <= sig && sig < GDB_SIGNAL_LAST)
-         event->ws.value.sig = (enum gdb_signal) sig;
+         event->ws.set_stopped ((enum gdb_signal) sig);
        else
-         event->ws.value.sig = GDB_SIGNAL_UNKNOWN;
+         event->ws.set_stopped (GDB_SIGNAL_UNKNOWN);
       }
       break;
     case 'w':          /* Thread exited.  */
       {
        ULONGEST value;
 
-       event->ws.kind = TARGET_WAITKIND_THREAD_EXITED;
        p = unpack_varlen_hex (&buf[1], &value);
-       event->ws.value.integer = value;
+       event->ws.set_thread_exited (value);
        if (*p != ';')
          error (_("stop reply packet badly formatted: %s"), buf);
        event->ptid = read_ptid (++p, NULL);
@@ -7619,17 +7789,15 @@ Packet: '%s'\n"),
        if (buf[0] == 'W')
          {
            /* The remote process exited.  */
-           event->ws.kind = TARGET_WAITKIND_EXITED;
-           event->ws.value.integer = value;
+           event->ws.set_exited (value);
          }
        else
          {
            /* The remote process exited with a signal.  */
-           event->ws.kind = TARGET_WAITKIND_SIGNALLED;
            if (GDB_SIGNAL_FIRST <= value && value < GDB_SIGNAL_LAST)
-             event->ws.value.sig = (enum gdb_signal) value;
+             event->ws.set_signalled ((enum gdb_signal) value);
            else
-             event->ws.value.sig = GDB_SIGNAL_UNKNOWN;
+             event->ws.set_signalled (GDB_SIGNAL_UNKNOWN);
          }
 
        /* If no process is specified, return null_ptid, and let the
@@ -7660,7 +7828,7 @@ Packet: '%s'\n"),
       }
       break;
     case 'N':
-      event->ws.kind = TARGET_WAITKIND_NO_RESUMED;
+      event->ws.set_no_resumed ();
       event->ptid = minus_one_ptid;
       break;
     }
@@ -7786,13 +7954,17 @@ remote_notif_get_pending_events (remote_target *remote, notif_client *nc)
 
 ptid_t
 remote_target::select_thread_for_ambiguous_stop_reply
-  (const struct target_waitstatus *status)
+  (const target_waitstatus &status)
 {
+  REMOTE_SCOPED_DEBUG_ENTER_EXIT;
+
   /* Some stop events apply to all threads in an inferior, while others
      only apply to a single thread.  */
   bool process_wide_stop
-    = (status->kind == TARGET_WAITKIND_EXITED
-       || status->kind == TARGET_WAITKIND_SIGNALLED);
+    = (status.kind () == TARGET_WAITKIND_EXITED
+       || status.kind () == TARGET_WAITKIND_SIGNALLED);
+
+  remote_debug_printf ("process_wide_stop = %d", process_wide_stop);
 
   thread_info *first_resumed_thread = nullptr;
   bool ambiguous = false;
@@ -7803,7 +7975,7 @@ remote_target::select_thread_for_ambiguous_stop_reply
     {
       remote_thread_info *remote_thr = get_remote_thread_info (thr);
 
-      if (remote_thr->resume_state () != resume_state::RESUMED)
+      if (remote_thr->get_resume_state () != resume_state::RESUMED)
        continue;
 
       if (first_resumed_thread == nullptr)
@@ -7815,6 +7987,10 @@ remote_target::select_thread_for_ambiguous_stop_reply
 
   gdb_assert (first_resumed_thread != nullptr);
 
+  remote_debug_printf ("first resumed thread is %s",
+                      pid_to_str (first_resumed_thread->ptid).c_str ());
+  remote_debug_printf ("is this guess ambiguous? = %d", ambiguous);
+
   /* Warn if the remote target is sending ambiguous stop replies.  */
   if (ambiguous)
     {
@@ -7868,12 +8044,12 @@ remote_target::process_stop_reply (struct stop_reply *stop_reply,
   /* If no thread/process was reported by the stub then select a suitable
      thread/process.  */
   if (ptid == null_ptid)
-    ptid = select_thread_for_ambiguous_stop_reply (status);
+    ptid = select_thread_for_ambiguous_stop_reply (*status);
   gdb_assert (ptid != null_ptid);
 
-  if (status->kind != TARGET_WAITKIND_EXITED
-      && status->kind != TARGET_WAITKIND_SIGNALLED
-      && status->kind != TARGET_WAITKIND_NO_RESUMED)
+  if (status->kind () != TARGET_WAITKIND_EXITED
+      && status->kind () != TARGET_WAITKIND_SIGNALLED
+      && status->kind () != TARGET_WAITKIND_NO_RESUMED)
     {
       /* Expedited registers.  */
       if (!stop_reply->regcache.empty ())
@@ -7890,7 +8066,7 @@ remote_target::process_stop_reply (struct stop_reply *stop_reply,
          stop_reply->regcache.clear ();
        }
 
-      remote_notice_new_inferior (ptid, 0);
+      remote_notice_new_inferior (ptid, false);
       remote_thread_info *remote_thr = get_remote_thread_info (this, ptid);
       remote_thr->core = stop_reply->core;
       remote_thr->stop_reason = stop_reply->stop_reason;
@@ -7963,7 +8139,7 @@ remote_target::wait_ns (ptid_t ptid, struct target_waitstatus *status,
         return to the event loop.  */
       if (options & TARGET_WNOHANG)
        {
-         status->kind = TARGET_WAITKIND_IGNORE;
+         status->set_ignore ();
          return minus_one_ptid;
        }
 
@@ -7978,7 +8154,7 @@ static ptid_t
 first_remote_resumed_thread (remote_target *target)
 {
   for (thread_info *tp : all_non_exited_threads (target, minus_one_ptid))
-    if (tp->resumed)
+    if (tp->resumed ())
       return tp->ptid;
   return null_ptid;
 }
@@ -7997,26 +8173,24 @@ remote_target::wait_as (ptid_t ptid, target_waitstatus *status,
 
  again:
 
-  status->kind = TARGET_WAITKIND_IGNORE;
-  status->value.integer = 0;
+  status->set_ignore ();
 
   stop_reply = queued_stop_reply (ptid);
   if (stop_reply != NULL)
-    return process_stop_reply (stop_reply, status);
-
-  if (rs->cached_wait_status)
-    /* Use the cached wait status, but only once.  */
-    rs->cached_wait_status = 0;
+    {
+      /* None of the paths that push a stop reply onto the queue should
+        have set the waiting_for_stop_reply flag.  */
+      gdb_assert (!rs->waiting_for_stop_reply);
+      event_ptid = process_stop_reply (stop_reply, status);
+    }
   else
     {
-      int ret;
-      int is_notif;
       int forever = ((options & TARGET_WNOHANG) == 0
                     && rs->wait_forever_enabled_p);
 
       if (!rs->waiting_for_stop_reply)
        {
-         status->kind = TARGET_WAITKIND_NO_RESUMED;
+         status->set_no_resumed ();
          return minus_one_ptid;
        }
 
@@ -8024,7 +8198,8 @@ remote_target::wait_as (ptid_t ptid, target_waitstatus *status,
         _never_ wait for ever -> test on target_is_async_p().
         However, before we do that we need to ensure that the caller
         knows how to take the target into/out of async mode.  */
-      ret = getpkt_or_notif_sane (&rs->buf, forever, &is_notif);
+      int is_notif;
+      int ret = getpkt_or_notif_sane (&rs->buf, forever, &is_notif);
 
       /* GDB gets a notification.  Return to core as this event is
         not interesting.  */
@@ -8033,79 +8208,78 @@ remote_target::wait_as (ptid_t ptid, target_waitstatus *status,
 
       if (ret == -1 && (options & TARGET_WNOHANG) != 0)
        return minus_one_ptid;
-    }
-
-  buf = rs->buf.data ();
 
-  /* Assume that the target has acknowledged Ctrl-C unless we receive
-     an 'F' or 'O' packet.  */
-  if (buf[0] != 'F' && buf[0] != 'O')
-    rs->ctrlc_pending_p = 0;
+      buf = rs->buf.data ();
 
-  switch (buf[0])
-    {
-    case 'E':          /* Error of some sort.  */
-      /* We're out of sync with the target now.  Did it continue or
-        not?  Not is more likely, so report a stop.  */
-      rs->waiting_for_stop_reply = 0;
+      /* Assume that the target has acknowledged Ctrl-C unless we receive
+        an 'F' or 'O' packet.  */
+      if (buf[0] != 'F' && buf[0] != 'O')
+       rs->ctrlc_pending_p = 0;
 
-      warning (_("Remote failure reply: %s"), buf);
-      status->kind = TARGET_WAITKIND_STOPPED;
-      status->value.sig = GDB_SIGNAL_0;
-      break;
-    case 'F':          /* File-I/O request.  */
-      /* GDB may access the inferior memory while handling the File-I/O
-        request, but we don't want GDB accessing memory while waiting
-        for a stop reply.  See the comments in putpkt_binary.  Set
-        waiting_for_stop_reply to 0 temporarily.  */
-      rs->waiting_for_stop_reply = 0;
-      remote_fileio_request (this, buf, rs->ctrlc_pending_p);
-      rs->ctrlc_pending_p = 0;
-      /* GDB handled the File-I/O request, and the target is running
-        again.  Keep waiting for events.  */
-      rs->waiting_for_stop_reply = 1;
-      break;
-    case 'N': case 'T': case 'S': case 'X': case 'W':
-      {
-       /* There is a stop reply to handle.  */
-       rs->waiting_for_stop_reply = 0;
+      switch (buf[0])
+       {
+       case 'E':               /* Error of some sort.  */
+         /* We're out of sync with the target now.  Did it continue or
+            not?  Not is more likely, so report a stop.  */
+         rs->waiting_for_stop_reply = 0;
 
-       stop_reply
-         = (struct stop_reply *) remote_notif_parse (this,
-                                                     &notif_client_stop,
-                                                     rs->buf.data ());
+         warning (_("Remote failure reply: %s"), buf);
+         status->set_stopped (GDB_SIGNAL_0);
+         break;
+       case 'F':               /* File-I/O request.  */
+         /* GDB may access the inferior memory while handling the File-I/O
+            request, but we don't want GDB accessing memory while waiting
+            for a stop reply.  See the comments in putpkt_binary.  Set
+            waiting_for_stop_reply to 0 temporarily.  */
+         rs->waiting_for_stop_reply = 0;
+         remote_fileio_request (this, buf, rs->ctrlc_pending_p);
+         rs->ctrlc_pending_p = 0;
+         /* GDB handled the File-I/O request, and the target is running
+            again.  Keep waiting for events.  */
+         rs->waiting_for_stop_reply = 1;
+         break;
+       case 'N': case 'T': case 'S': case 'X': case 'W':
+         {
+           /* There is a stop reply to handle.  */
+           rs->waiting_for_stop_reply = 0;
 
-       event_ptid = process_stop_reply (stop_reply, status);
-       break;
-      }
-    case 'O':          /* Console output.  */
-      remote_console_output (buf + 1);
-      break;
-    case '\0':
-      if (rs->last_sent_signal != GDB_SIGNAL_0)
-       {
-         /* Zero length reply means that we tried 'S' or 'C' and the
-            remote system doesn't support it.  */
-         target_terminal::ours_for_output ();
-         printf_filtered
-           ("Can't send signals to this remote system.  %s not sent.\n",
-            gdb_signal_to_name (rs->last_sent_signal));
-         rs->last_sent_signal = GDB_SIGNAL_0;
-         target_terminal::inferior ();
-
-         strcpy (buf, rs->last_sent_step ? "s" : "c");
-         putpkt (buf);
+           stop_reply
+             = (struct stop_reply *) remote_notif_parse (this,
+                                                         &notif_client_stop,
+                                                         rs->buf.data ());
+
+           event_ptid = process_stop_reply (stop_reply, status);
+           break;
+         }
+       case 'O':               /* Console output.  */
+         remote_console_output (buf + 1);
+         break;
+       case '\0':
+         if (rs->last_sent_signal != GDB_SIGNAL_0)
+           {
+             /* Zero length reply means that we tried 'S' or 'C' and the
+                remote system doesn't support it.  */
+             target_terminal::ours_for_output ();
+             printf_filtered
+               ("Can't send signals to this remote system.  %s not sent.\n",
+                gdb_signal_to_name (rs->last_sent_signal));
+             rs->last_sent_signal = GDB_SIGNAL_0;
+             target_terminal::inferior ();
+
+             strcpy (buf, rs->last_sent_step ? "s" : "c");
+             putpkt (buf);
+             break;
+           }
+         /* fallthrough */
+       default:
+         warning (_("Invalid remote reply: %s"), buf);
          break;
        }
-      /* fallthrough */
-    default:
-      warning (_("Invalid remote reply: %s"), buf);
-      break;
     }
 
-  if (status->kind == TARGET_WAITKIND_NO_RESUMED)
+  if (status->kind () == TARGET_WAITKIND_NO_RESUMED)
     return minus_one_ptid;
-  else if (status->kind == TARGET_WAITKIND_IGNORE)
+  else if (status->kind () == TARGET_WAITKIND_IGNORE)
     {
       /* Nothing interesting happened.  If we're doing a non-blocking
         poll, we're done.  Otherwise, go back to waiting.  */
@@ -8114,8 +8288,8 @@ remote_target::wait_as (ptid_t ptid, target_waitstatus *status,
       else
        goto again;
     }
-  else if (status->kind != TARGET_WAITKIND_EXITED
-          && status->kind != TARGET_WAITKIND_SIGNALLED)
+  else if (status->kind () != TARGET_WAITKIND_EXITED
+          && status->kind () != TARGET_WAITKIND_SIGNALLED)
     {
       if (event_ptid != null_ptid)
        record_currthread (rs, event_ptid);
@@ -8144,6 +8318,19 @@ ptid_t
 remote_target::wait (ptid_t ptid, struct target_waitstatus *status,
                     target_wait_flags options)
 {
+  REMOTE_SCOPED_DEBUG_ENTER_EXIT;
+
+  remote_state *rs = get_remote_state ();
+
+  /* Start by clearing the flag that asks for our wait method to be called,
+     we'll mark it again at the end if needed.  If the target is not in
+     async mode then the async token should not be marked.  */
+  if (target_is_async_p ())
+    clear_async_event_handler (rs->remote_async_inferior_event_token);
+  else
+    gdb_assert (!async_event_handler_marked
+               (rs->remote_async_inferior_event_token));
+
   ptid_t event_ptid;
 
   if (target_is_non_stop_p ())
@@ -8153,11 +8340,10 @@ remote_target::wait (ptid_t ptid, struct target_waitstatus *status,
 
   if (target_is_async_p ())
     {
-      remote_state *rs = get_remote_state ();
-
-      /* If there are are events left in the queue tell the event loop
-        to return here.  */
-      if (!rs->stop_reply_queue.empty ())
+      /* If there are events left in the queue, or unacknowledged
+        notifications, then tell the event loop to call us again.  */
+      if (!rs->stop_reply_queue.empty ()
+         || rs->notif_state->pending_event[notif_client_stop.id] != nullptr)
        mark_async_event_handler (rs->remote_async_inferior_event_token);
     }
 
@@ -8249,9 +8435,7 @@ remote_target::send_g_packet ()
         && (rs->buf[0] < 'a' || rs->buf[0] > 'f')
         && rs->buf[0] != 'x')  /* New: unavailable register value.  */
     {
-      if (remote_debug)
-       fprintf_unfiltered (gdb_stdlog,
-                           "Bad register packet; fetching a new packet\n");
+      remote_debug_printf ("Bad register packet; fetching a new packet");
       getpkt (&rs->buf, 0);
     }
 
@@ -8707,17 +8891,12 @@ remote_target::check_binary_download (CORE_ADDR addr)
 
        if (rs->buf[0] == '\0')
          {
-           if (remote_debug)
-             fprintf_unfiltered (gdb_stdlog,
-                                 "binary downloading NOT "
-                                 "supported by target\n");
+           remote_debug_printf ("binary downloading NOT supported by target");
            remote_protocol_packets[PACKET_X].support = PACKET_DISABLE;
          }
        else
          {
-           if (remote_debug)
-             fprintf_unfiltered (gdb_stdlog,
-                                 "binary downloading supported by target\n");
+           remote_debug_printf ("binary downloading supported by target");
            remote_protocol_packets[PACKET_X].support = PACKET_ENABLE;
          }
        break;
@@ -9034,7 +9213,7 @@ remote_target::remote_xfer_live_readonly_partial (gdb_byte *readbuf,
                                                  int unit_size,
                                                  ULONGEST *xfered_len)
 {
-  struct target_section *secp;
+  const struct target_section *secp;
 
   secp = target_section_by_addr (this, memaddr);
   if (secp != NULL
@@ -9042,8 +9221,8 @@ remote_target::remote_xfer_live_readonly_partial (gdb_byte *readbuf,
     {
       ULONGEST memend = memaddr + len;
 
-      target_section_table *table = target_get_section_table (this);
-      for (target_section &p : *table)
+      const target_section_table *table = target_get_section_table (this);
+      for (const target_section &p : *table)
        {
          if (memaddr >= p.addr)
            {
@@ -9225,11 +9404,6 @@ remote_target::flash_done ()
     }
 }
 
-void
-remote_target::files_info ()
-{
-  puts_filtered ("Debugging a target over a serial line.\n");
-}
 \f
 /* Stuff for dealing with the packets which are part of this protocol.
    See comment at top of file for details.  */
@@ -9331,18 +9505,7 @@ escape_buffer (const char *buf, int n)
   string_file stb;
 
   stb.putstrn (buf, n, '\\');
-  return std::move (stb.string ());
-}
-
-/* Display a null-terminated packet on stdout, for debugging, using C
-   string notation.  */
-
-static void
-print_packet (const char *buf)
-{
-  puts_filtered ("\"");
-  fputstr_filtered (buf, '"', gdb_stdout);
-  puts_filtered ("\"");
+  return stb.release ();
 }
 
 int
@@ -9395,10 +9558,6 @@ remote_target::putpkt_binary (const char *buf, int cnt)
               "and then try again."));
     }
 
-  /* We're sending out a new packet.  Make sure we don't look at a
-     stale cached response.  */
-  rs->cached_wait_status = 0;
-
   /* Copy the packet into buffer BUF2, encapsulating it
      and giving it a checksum.  */
 
@@ -9418,8 +9577,6 @@ remote_target::putpkt_binary (const char *buf, int cnt)
 
   while (1)
     {
-      int started_error_output = 0;
-
       if (remote_debug)
        {
          *p = '\0';
@@ -9435,15 +9592,12 @@ remote_target::putpkt_binary (const char *buf, int cnt)
          std::string str
            = escape_buffer (buf2, std::min (len, max_chars));
 
-         fprintf_unfiltered (gdb_stdlog, "Sending packet: %s", str.c_str ());
-
          if (len > max_chars)
-           fprintf_unfiltered (gdb_stdlog, "[%d bytes omitted]",
-                               len - max_chars);
-
-         fprintf_unfiltered (gdb_stdlog, "...");
-
-         gdb_flush (gdb_stdlog);
+           remote_debug_printf_nofunc
+             ("Sending packet: %s [%d bytes omitted]", str.c_str (),
+              len - max_chars);
+         else
+           remote_debug_printf_nofunc ("Sending packet: %s", str.c_str ());
        }
       remote_serial_write (buf2, p - buf2);
 
@@ -9458,32 +9612,13 @@ remote_target::putpkt_binary (const char *buf, int cnt)
        {
          ch = readchar (remote_timeout);
 
-         if (remote_debug)
-           {
-             switch (ch)
-               {
-               case '+':
-               case '-':
-               case SERIAL_TIMEOUT:
-               case '$':
-               case '%':
-                 if (started_error_output)
-                   {
-                     putchar_unfiltered ('\n');
-                     started_error_output = 0;
-                   }
-               }
-           }
-
          switch (ch)
            {
            case '+':
-             if (remote_debug)
-               fprintf_unfiltered (gdb_stdlog, "Ack\n");
+             remote_debug_printf_nofunc ("Received Ack");
              return 1;
            case '-':
-             if (remote_debug)
-               fprintf_unfiltered (gdb_stdlog, "Nak\n");
+             remote_debug_printf_nofunc ("Received Nak");
              /* FALLTHROUGH */
            case SERIAL_TIMEOUT:
              tcount++;
@@ -9492,9 +9627,7 @@ remote_target::putpkt_binary (const char *buf, int cnt)
              break;            /* Retransmit buffer.  */
            case '$':
              {
-               if (remote_debug)
-                 fprintf_unfiltered (gdb_stdlog,
-                                     "Packet instead of Ack, ignoring it\n");
+               remote_debug_printf ("Packet instead of Ack, ignoring it");
                /* It's probably an old response sent because an ACK
                   was lost.  Gobble up the packet and ack it so it
                   doesn't get retransmitted when we resend this
@@ -9515,44 +9648,23 @@ remote_target::putpkt_binary (const char *buf, int cnt)
                val = read_frame (&rs->buf);
                if (val >= 0)
                  {
-                   if (remote_debug)
-                     {
-                       std::string str = escape_buffer (rs->buf.data (), val);
+                   remote_debug_printf_nofunc
+                     ("  Notification received: %s",
+                      escape_buffer (rs->buf.data (), val).c_str ());
 
-                       fprintf_unfiltered (gdb_stdlog,
-                                           "  Notification received: %s\n",
-                                           str.c_str ());
-                     }
                    handle_notification (rs->notif_state, rs->buf.data ());
                    /* We're in sync now, rewait for the ack.  */
                    tcount = 0;
                  }
                else
-                 {
-                   if (remote_debug)
-                     {
-                       if (!started_error_output)
-                         {
-                           started_error_output = 1;
-                           fprintf_unfiltered (gdb_stdlog, "putpkt: Junk: ");
-                         }
-                       fputc_unfiltered (ch & 0177, gdb_stdlog);
-                       fprintf_unfiltered (gdb_stdlog, "%s", rs->buf.data ());
-                     }
-                 }
+                 remote_debug_printf_nofunc ("Junk: %c%s", ch & 0177,
+                                             rs->buf.data ());
                continue;
              }
              /* fall-through */
            default:
-             if (remote_debug)
-               {
-                 if (!started_error_output)
-                   {
-                     started_error_output = 1;
-                     fprintf_unfiltered (gdb_stdlog, "putpkt: Junk: ");
-                   }
-                 fputc_unfiltered (ch & 0177, gdb_stdlog);
-               }
+             remote_debug_printf_nofunc ("Junk: %c%s", ch & 0177,
+                                         rs->buf.data ());
              continue;
            }
          break;                /* Here to retransmit.  */
@@ -9638,14 +9750,13 @@ remote_target::read_frame (gdb::char_vector *buf_p)
       switch (c)
        {
        case SERIAL_TIMEOUT:
-         if (remote_debug)
-           fputs_filtered ("Timeout in mid-packet, retrying\n", gdb_stdlog);
+         remote_debug_printf ("Timeout in mid-packet, retrying");
          return -1;
+
        case '$':
-         if (remote_debug)
-           fputs_filtered ("Saw new packet start in middle of old one\n",
-                           gdb_stdlog);
+         remote_debug_printf ("Saw new packet start in middle of old one");
          return -1;            /* Start a new packet, count retries.  */
+
        case '#':
          {
            unsigned char pktcsum;
@@ -9660,16 +9771,12 @@ remote_target::read_frame (gdb::char_vector *buf_p)
 
            if (check_0 == SERIAL_TIMEOUT || check_1 == SERIAL_TIMEOUT)
              {
-               if (remote_debug)
-                 fputs_filtered ("Timeout in checksum, retrying\n",
-                                 gdb_stdlog);
+               remote_debug_printf ("Timeout in checksum, retrying");
                return -1;
              }
            else if (check_0 < 0 || check_1 < 0)
              {
-               if (remote_debug)
-                 fputs_filtered ("Communication error in checksum\n",
-                                 gdb_stdlog);
+               remote_debug_printf ("Communication error in checksum");
                return -1;
              }
 
@@ -9683,15 +9790,10 @@ remote_target::read_frame (gdb::char_vector *buf_p)
            if (csum == pktcsum)
              return bc;
 
-           if (remote_debug)
-             {
-               std::string str = escape_buffer (buf, bc);
+           remote_debug_printf
+             ("Bad checksum, sentsum=0x%x, csum=0x%x, buf=%s",
+              pktcsum, csum, escape_buffer (buf, bc).c_str ());
 
-               fprintf_unfiltered (gdb_stdlog,
-                                   "Bad checksum, sentsum=0x%x, "
-                                   "csum=0x%x, buf=%s\n",
-                                   pktcsum, csum, str.c_str ());
-             }
            /* Number of characters in buffer ignoring trailing
               NULL.  */
            return -1;
@@ -9700,7 +9802,7 @@ remote_target::read_frame (gdb::char_vector *buf_p)
          {
            int repeat;
 
-           csum += c;
+           csum += c;
            c = readchar (remote_timeout);
            csum += c;
            repeat = c - ' ' + 3;       /* Compute repeat count.  */
@@ -9793,10 +9895,6 @@ remote_target::getpkt_or_notif_sane_1 (gdb::char_vector *buf,
   int timeout;
   int val = -1;
 
-  /* We're reading a new response.  Make sure we don't look at a
-     previously cached response.  */
-  rs->cached_wait_status = 0;
-
   strcpy (buf->data (), "timeout");
 
   if (forever)
@@ -9843,8 +9941,8 @@ remote_target::getpkt_or_notif_sane_1 (gdb::char_vector *buf,
                               _("Watchdog timeout has expired.  "
                                 "Target detached."));
                }
-             if (remote_debug)
-               fputs_filtered ("Timed out.\n", gdb_stdlog);
+
+             remote_debug_printf ("Timed out.");
            }
          else
            {
@@ -9886,14 +9984,13 @@ remote_target::getpkt_or_notif_sane_1 (gdb::char_vector *buf,
                = escape_buffer (buf->data (),
                                 std::min (val, max_chars));
 
-             fprintf_unfiltered (gdb_stdlog, "Packet received: %s",
-                                 str.c_str ());
-
              if (val > max_chars)
-               fprintf_unfiltered (gdb_stdlog, "[%d bytes omitted]",
-                                   val - max_chars);
-
-             fprintf_unfiltered (gdb_stdlog, "\n");
+               remote_debug_printf_nofunc
+                 ("Packet received: %s [%d bytes omitted]", str.c_str (),
+                  val - max_chars);
+             else
+               remote_debug_printf_nofunc ("Packet received: %s",
+                                           str.c_str ());
            }
 
          /* Skip the ack char if we're in no-ack mode.  */
@@ -9910,14 +10007,10 @@ remote_target::getpkt_or_notif_sane_1 (gdb::char_vector *buf,
        {
          gdb_assert (c == '%');
 
-         if (remote_debug)
-           {
-             std::string str = escape_buffer (buf->data (), val);
+         remote_debug_printf_nofunc
+           ("  Notification received: %s",
+            escape_buffer (buf->data (), val).c_str ());
 
-             fprintf_unfiltered (gdb_stdlog,
-                                 "  Notification received: %s\n",
-                                 str.c_str ());
-           }
          if (is_notif != NULL)
            *is_notif = 1;
 
@@ -9944,45 +10037,48 @@ remote_target::getpkt_or_notif_sane (gdb::char_vector *buf, int forever,
   return getpkt_or_notif_sane_1 (buf, forever, 1, is_notif);
 }
 
-/* Kill any new fork children of process PID that haven't been
+/* Kill any new fork children of inferior INF that haven't been
    processed by follow_fork.  */
 
 void
-remote_target::kill_new_fork_children (int pid)
+remote_target::kill_new_fork_children (inferior *inf)
 {
   remote_state *rs = get_remote_state ();
   struct notif_client *notif = &notif_client_stop;
 
-  /* Kill the fork child threads of any threads in process PID
-     that are stopped at a fork event.  */
-  for (thread_info *thread : all_non_exited_threads (this))
+  /* Kill the fork child threads of any threads in inferior INF that are stopped
+     at a fork event.  */
+  for (thread_info *thread : inf->non_exited_threads ())
     {
-      struct target_waitstatus *ws = &thread->pending_follow;
+      const target_waitstatus *ws = thread_pending_fork_status (thread);
 
-      if (is_pending_fork_parent (ws, pid, thread->ptid))
-       {
-         int child_pid = ws->value.related_pid.pid ();
-         int res;
+      if (ws == nullptr)
+       continue;
 
-         res = remote_vkill (child_pid);
-         if (res != 0)
-           error (_("Can't kill fork child process %d"), child_pid);
-       }
+      int child_pid = ws->child_ptid ().pid ();
+      int res = remote_vkill (child_pid);
+
+      if (res != 0)
+       error (_("Can't kill fork child process %d"), child_pid);
     }
 
   /* Check for any pending fork events (not reported or processed yet)
-     in process PID and kill those fork child threads as well.  */
+     in inferior INF and kill those fork child threads as well.  */
   remote_notif_get_pending_events (notif);
   for (auto &event : rs->stop_reply_queue)
-    if (is_pending_fork_parent (&event->ws, pid, event->ptid))
-      {
-       int child_pid = event->ws.value.related_pid.pid ();
-       int res;
+    {
+      if (event->ptid.pid () != inf->pid)
+       continue;
 
-       res = remote_vkill (child_pid);
-       if (res != 0)
-         error (_("Can't kill fork child process %d"), child_pid);
-      }
+      if (!is_fork_status (event->ws.kind ()))
+       continue;
+
+      int child_pid = event->ws.child_ptid ().pid ();
+      int res = remote_vkill (child_pid);
+
+      if (res != 0)
+       error (_("Can't kill fork child process %d"), child_pid);
+    }
 }
 
 \f
@@ -9992,18 +10088,20 @@ void
 remote_target::kill ()
 {
   int res = -1;
-  int pid = inferior_ptid.pid ();
+  inferior *inf = find_inferior_pid (this, inferior_ptid.pid ());
   struct remote_state *rs = get_remote_state ();
 
+  gdb_assert (inf != nullptr);
+
   if (packet_support (PACKET_vKill) != PACKET_DISABLE)
     {
       /* If we're stopped while forking and we haven't followed yet,
         kill the child task.  We need to do this before killing the
         parent task because if this is a vfork then the parent will
         be sleeping.  */
-      kill_new_fork_children (pid);
+      kill_new_fork_children (inf);
 
-      res = remote_vkill (pid);
+      res = remote_vkill (inf->pid);
       if (res == 0)
        {
          target_mourn_inferior (inferior_ptid);
@@ -10217,7 +10315,7 @@ remote_target::extended_remote_run (const std::string &args)
        error (_("Running \"%s\" on the remote target failed"),
               remote_exec_file);
     default:
-      gdb_assert_not_reached (_("bad switch"));
+      gdb_assert_not_reached ("bad switch");
     }
 }
 
@@ -10283,13 +10381,14 @@ remote_target::extended_remote_set_inferior_cwd ()
 {
   if (packet_support (PACKET_QSetWorkingDir) != PACKET_DISABLE)
     {
-      const char *inferior_cwd = get_inferior_cwd ();
+      const std::string &inferior_cwd = current_inferior ()->cwd ();
       remote_state *rs = get_remote_state ();
 
-      if (inferior_cwd != NULL)
+      if (!inferior_cwd.empty ())
        {
-         std::string hexpath = bin2hex ((const gdb_byte *) inferior_cwd,
-                                        strlen (inferior_cwd));
+         std::string hexpath
+           = bin2hex ((const gdb_byte *) inferior_cwd.data (),
+                      inferior_cwd.size ());
 
          xsnprintf (rs->buf.data (), get_remote_packet_size (),
                     "QSetWorkingDir:%s", hexpath.c_str ());
@@ -11483,7 +11582,8 @@ remote_target::memory_map ()
 {
   std::vector<mem_region> result;
   gdb::optional<gdb::char_vector> text
-    = target_read_stralloc (current_top_target (), TARGET_OBJECT_MEMORY_MAP, NULL);
+    = target_read_stralloc (current_inferior ()->top_target (),
+                           TARGET_OBJECT_MEMORY_MAP, NULL);
 
   if (text)
     result = parse_memory_map (text->data ());
@@ -11491,34 +11591,87 @@ remote_target::memory_map ()
   return result;
 }
 
-static void
-packet_command (const char *args, int from_tty)
+/* Set of callbacks used to implement the 'maint packet' command.  */
+
+struct cli_packet_command_callbacks : public send_remote_packet_callbacks
 {
-  remote_target *remote = get_current_remote_target ();
+  /* Called before the packet is sent.  BUF is the packet content before
+     the protocol specific prefix, suffix, and escaping is added.  */
 
-  if (remote == nullptr)
-    error (_("command can only be used with remote target"));
+  void sending (gdb::array_view<const char> &buf) override
+  {
+    puts_filtered ("sending: ");
+    print_packet (buf);
+    puts_filtered ("\n");
+  }
 
-  remote->packet_command (args, from_tty);
-}
+  /* Called with BUF, the reply from the remote target.  */
+
+  void received (gdb::array_view<const char> &buf) override
+  {
+    puts_filtered ("received: \"");
+    print_packet (buf);
+    puts_filtered ("\"\n");
+  }
+
+private:
+
+  /* Print BUF o gdb_stdout.  Any non-printable bytes in BUF are printed as
+     '\x??' with '??' replaced by the hexadecimal value of the byte.  */
+
+  static void
+  print_packet (gdb::array_view<const char> &buf)
+  {
+    string_file stb;
+
+    for (int i = 0; i < buf.size (); ++i)
+      {
+       gdb_byte c = buf[i];
+       if (isprint (c))
+         fputc_unfiltered (c, &stb);
+       else
+         fprintf_unfiltered (&stb, "\\x%02x", (unsigned char) c);
+      }
+
+    puts_filtered (stb.string ().c_str ());
+  }
+};
+
+/* See remote.h.  */
 
 void
-remote_target::packet_command (const char *args, int from_tty)
+send_remote_packet (gdb::array_view<const char> &buf,
+                   send_remote_packet_callbacks *callbacks)
 {
-  if (!args)
-    error (_("remote-packet command requires packet text as argument"));
+  if (buf.size () == 0 || buf.data ()[0] == '\0')
+    error (_("a remote packet must not be empty"));
 
-  puts_filtered ("sending: ");
-  print_packet (args);
-  puts_filtered ("\n");
-  putpkt (args);
+  remote_target *remote = get_current_remote_target ();
+  if (remote == nullptr)
+    error (_("packets can only be sent to a remote target"));
 
-  remote_state *rs = get_remote_state ();
+  callbacks->sending (buf);
 
-  getpkt (&rs->buf, 0);
-  puts_filtered ("received: ");
-  print_packet (rs->buf.data ());
-  puts_filtered ("\n");
+  remote->putpkt_binary (buf.data (), buf.size ());
+  remote_state *rs = remote->get_remote_state ();
+  int bytes = remote->getpkt_sane (&rs->buf, 0);
+
+  if (bytes < 0)
+    error (_("error while fetching packet from remote target"));
+
+  gdb::array_view<const char> view (&rs->buf[0], bytes);
+  callbacks->received (view);
+}
+
+/* Entry point for the 'maint packet' command.  */
+
+static void
+cli_packet_command (const char *args, int from_tty)
+{
+  cli_packet_command_callbacks cb;
+  gdb::array_view<const char> view
+    = gdb::make_array_view (args, args == nullptr ? 0 : strlen (args));
+  send_remote_packet (view, &cb);
 }
 
 #if 0
@@ -12309,16 +12462,15 @@ remote_target::remote_hostio_pread (int fd, gdb_byte *read_buf, int len,
     {
       cache->hit_count++;
 
-      if (remote_debug)
-       fprintf_unfiltered (gdb_stdlog, "readahead cache hit %s\n",
-                           pulongest (cache->hit_count));
+      remote_debug_printf ("readahead cache hit %s",
+                          pulongest (cache->hit_count));
       return ret;
     }
 
   cache->miss_count++;
-  if (remote_debug)
-    fprintf_unfiltered (gdb_stdlog, "readahead cache miss %s\n",
-                       pulongest (cache->miss_count));
+
+  remote_debug_printf ("readahead cache miss %s",
+                      pulongest (cache->miss_count));
 
   cache->fd = fd;
   cache->offset = offset;
@@ -12505,7 +12657,7 @@ remote_target::filesystem_is_local ()
      this case we treat the remote filesystem as local if the
      sysroot is exactly TARGET_SYSROOT_PREFIX and if the stub
      does not support vFile:open.  */
-  if (strcmp (gdb_sysroot, TARGET_SYSROOT_PREFIX) == 0)
+  if (gdb_sysroot == TARGET_SYSROOT_PREFIX)
     {
       enum packet_support ps = packet_support (PACKET_vFile_open);
 
@@ -13133,7 +13285,7 @@ remote_target::download_tracepoint (struct bp_location *loc)
                   "ignoring tp %d cond"), b->number);
     }
 
-  if (b->commands || *default_collect)
+  if (b->commands || !default_collect.empty ())
     {
       size_left = buf.size () - strlen (buf.data ());
 
@@ -13221,7 +13373,7 @@ remote_target::download_tracepoint (struct bp_location *loc)
            error ("%s", err_msg);
 
          encode_source_string (b->number, loc->address,
-                               "cond", b->cond_string,
+                               "cond", b->cond_string.get (),
                                buf.data () + strlen (buf.data ()),
                                buf.size () - strlen (buf.data ()));
          putpkt (buf.data ());
@@ -13436,7 +13588,6 @@ remote_target::get_tracepoint_status (struct breakpoint *bp,
 {
   struct remote_state *rs = get_remote_state ();
   char *reply;
-  struct bp_location *loc;
   struct tracepoint *tp = (struct tracepoint *) bp;
   size_t size = get_remote_packet_size ();
 
@@ -13444,7 +13595,7 @@ remote_target::get_tracepoint_status (struct breakpoint *bp,
     {
       tp->hit_count = 0;
       tp->traceframe_usage = 0;
-      for (loc = tp->loc; loc; loc = loc->next)
+      for (bp_location *loc : tp->locations ())
        {
          /* If the tracepoint was never downloaded, don't go asking for
             any status.  */
@@ -13715,7 +13866,8 @@ traceframe_info_up
 remote_target::traceframe_info ()
 {
   gdb::optional<gdb::char_vector> text
-    = target_read_stralloc (current_top_target (), TARGET_OBJECT_TRACEFRAME_INFO,
+    = target_read_stralloc (current_inferior ()->top_target (),
+                           TARGET_OBJECT_TRACEFRAME_INFO,
                            NULL);
   if (text)
     return parse_traceframe_info (text->data ());
@@ -13937,14 +14089,18 @@ remote_target::btrace_sync_conf (const btrace_config *conf)
     }
 }
 
-/* Read the current thread's btrace configuration from the target and
-   store it into CONF.  */
+/* Read TP's btrace configuration from the target and store it into CONF.  */
 
 static void
-btrace_read_config (struct btrace_config *conf)
+btrace_read_config (thread_info *tp, struct btrace_config *conf)
 {
+  /* target_read_stralloc relies on INFERIOR_PTID.  */
+  scoped_restore_current_thread restore_thread;
+  switch_to_thread (tp);
+
   gdb::optional<gdb::char_vector> xml
-    = target_read_stralloc (current_top_target (), TARGET_OBJECT_BTRACE_CONF, "");
+    = target_read_stralloc (current_inferior ()->top_target (),
+                           TARGET_OBJECT_BTRACE_CONF, "");
   if (xml)
     parse_xml_btrace_conf (conf, xml->data ());
 }
@@ -13965,14 +14121,10 @@ remote_target::remote_btrace_maybe_reopen ()
   if (packet_support (PACKET_qXfer_btrace_conf) != PACKET_ENABLE)
     return;
 
-  scoped_restore_current_thread restore_thread;
-
   for (thread_info *tp : all_non_exited_threads (this))
     {
-      set_general_thread (tp->ptid);
-
       memset (&rs->btrace_config, 0x00, sizeof (struct btrace_config));
-      btrace_read_config (&rs->btrace_config);
+      btrace_read_config (tp, &rs->btrace_config);
 
       if (rs->btrace_config.format == BTRACE_FORMAT_NONE)
        continue;
@@ -14011,7 +14163,8 @@ remote_target::remote_btrace_maybe_reopen ()
 /* Enable branch tracing.  */
 
 struct btrace_target_info *
-remote_target::enable_btrace (ptid_t ptid, const struct btrace_config *conf)
+remote_target::enable_btrace (thread_info *tp,
+                             const struct btrace_config *conf)
 {
   struct btrace_target_info *tinfo = NULL;
   struct packet_config *packet = NULL;
@@ -14035,6 +14188,7 @@ remote_target::enable_btrace (ptid_t ptid, const struct btrace_config *conf)
 
   btrace_sync_conf (conf);
 
+  ptid_t ptid = tp->ptid;
   set_general_thread (ptid);
 
   buf += xsnprintf (buf, endbuf - buf, "%s", packet->name);
@@ -14058,7 +14212,7 @@ remote_target::enable_btrace (ptid_t ptid, const struct btrace_config *conf)
      tracing itself is not impacted.  */
   try
     {
-      btrace_read_config (&tinfo->conf);
+      btrace_read_config (tp, &tinfo->conf);
     }
   catch (const gdb_exception_error &err)
     {
@@ -14145,7 +14299,8 @@ remote_target::read_btrace (struct btrace_data *btrace,
     }
 
   gdb::optional<gdb::char_vector> xml
-    = target_read_stralloc (current_top_target (), TARGET_OBJECT_BTRACE, annex);
+    = target_read_stralloc (current_inferior ()->top_target (),
+                           TARGET_OBJECT_BTRACE, annex);
   if (!xml)
     return BTRACE_ERR_UNKNOWN;
 
@@ -14201,7 +14356,7 @@ remote_target::pid_to_exec_file (int pid)
       xsnprintf (annex, annex_size, "%x", pid);
     }
 
-  filename = target_read_stralloc (current_top_target (),
+  filename = target_read_stralloc (current_inferior ()->top_target (),
                                   TARGET_OBJECT_EXEC_FILE, annex);
 
   return filename ? filename->data () : nullptr;
@@ -14277,27 +14432,19 @@ remote_target::thread_info_to_thread_handle (struct thread_info *tp)
 bool
 remote_target::can_async_p ()
 {
-  struct remote_state *rs = get_remote_state ();
+  /* This flag should be checked in the common target.c code.  */
+  gdb_assert (target_async_permitted);
 
-  /* We don't go async if the user has explicitly prevented it with the
-     "maint set target-async" command.  */
-  if (!target_async_permitted)
-    return false;
-
-  /* We're async whenever the serial device is.  */
+  /* We're async whenever the serial device can.  */
+  struct remote_state *rs = get_remote_state ();
   return serial_can_async_p (rs->remote_desc);
 }
 
 bool
 remote_target::is_async_p ()
 {
-  struct remote_state *rs = get_remote_state ();
-
-  if (!target_async_permitted)
-    /* We only enable async when the user specifically asks for it.  */
-    return false;
-
   /* We're async whenever the serial device is.  */
+  struct remote_state *rs = get_remote_state ();
   return serial_is_async_p (rs->remote_desc);
 }
 
@@ -14319,19 +14466,6 @@ static void
 remote_async_inferior_event_handler (gdb_client_data data)
 {
   inferior_event_handler (INF_REG_EVENT);
-
-  remote_target *remote = (remote_target *) data;
-  remote_state *rs = remote->get_remote_state ();
-
-  /* inferior_event_handler may have consumed an event pending on the
-     infrun side without calling target_wait on the REMOTE target, or
-     may have pulled an event out of a different target.  Keep trying
-     for this remote target as long it still has either pending events
-     or unacknowledged notifications.  */
-
-  if (rs->notif_state->pending_event[notif_client_stop.id] != NULL
-      || !rs->stop_reply_queue.empty ())
-    mark_async_event_handler (rs->remote_async_inferior_event_token);
 }
 
 int
@@ -14440,8 +14574,26 @@ remote_new_objfile (struct objfile *objfile)
 {
   remote_target *remote = get_current_remote_target ();
 
-  if (remote != NULL)                  /* Have a remote connection.  */
-    remote->remote_check_symbols ();
+  /* First, check whether the current inferior's process target is a remote
+     target.  */
+  if (remote == nullptr)
+    return;
+
+  /* When we are attaching or handling a fork child and the shared library
+     subsystem reads the list of loaded libraries, we receive new objfile
+     events in between each found library.  The libraries are read in an
+     undefined order, so if we gave the remote side a chance to look up
+     symbols between each objfile, we might give it an inconsistent picture
+     of the inferior.  It could appear that a library A appears loaded but
+     a library B does not, even though library A requires library B.  That
+     would present a state that couldn't normally exist in the inferior.
+
+     So, skip these events, we'll give the remote a chance to look up symbols
+     once all the loaded libraries and their symbols are known to GDB.  */
+  if (current_inferior ()->in_initial_library_scan)
+    return;
+
+  remote->remote_check_symbols ();
 }
 
 /* Pull all the tracepoints defined on the target and create local
@@ -14533,13 +14685,229 @@ set_range_stepping (const char *ignore_args, int from_tty,
     }
 }
 
+static void
+show_remote_debug (struct ui_file *file, int from_tty,
+                  struct cmd_list_element *c, const char *value)
+{
+  fprintf_filtered (file, _("Debugging of remote protocol is %s.\n"),
+                   value);
+}
+
+static void
+show_remote_timeout (struct ui_file *file, int from_tty,
+                    struct cmd_list_element *c, const char *value)
+{
+  fprintf_filtered (file,
+                   _("Timeout limit to wait for target to respond is %s.\n"),
+                   value);
+}
+
+/* Implement the "supports_memory_tagging" target_ops method.  */
+
+bool
+remote_target::supports_memory_tagging ()
+{
+  return remote_memory_tagging_p ();
+}
+
+/* Create the qMemTags packet given ADDRESS, LEN and TYPE.  */
+
+static void
+create_fetch_memtags_request (gdb::char_vector &packet, CORE_ADDR address,
+                             size_t len, int type)
+{
+  int addr_size = gdbarch_addr_bit (target_gdbarch ()) / 8;
+
+  std::string request = string_printf ("qMemTags:%s,%s:%s",
+                                      phex_nz (address, addr_size),
+                                      phex_nz (len, sizeof (len)),
+                                      phex_nz (type, sizeof (type)));
+
+  strcpy (packet.data (), request.c_str ());
+}
+
+/* Parse the qMemTags packet reply into TAGS.
+
+   Return true if successful, false otherwise.  */
+
+static bool
+parse_fetch_memtags_reply (const gdb::char_vector &reply,
+                          gdb::byte_vector &tags)
+{
+  if (reply.empty () || reply[0] == 'E' || reply[0] != 'm')
+    return false;
+
+  /* Copy the tag data.  */
+  tags = hex2bin (reply.data () + 1);
+
+  return true;
+}
+
+/* Create the QMemTags packet given ADDRESS, LEN, TYPE and TAGS.  */
+
+static void
+create_store_memtags_request (gdb::char_vector &packet, CORE_ADDR address,
+                             size_t len, int type,
+                             const gdb::byte_vector &tags)
+{
+  int addr_size = gdbarch_addr_bit (target_gdbarch ()) / 8;
+
+  /* Put together the main packet, address and length.  */
+  std::string request = string_printf ("QMemTags:%s,%s:%s:",
+                                      phex_nz (address, addr_size),
+                                      phex_nz (len, sizeof (len)),
+                                      phex_nz (type, sizeof (type)));
+  request += bin2hex (tags.data (), tags.size ());
+
+  /* Check if we have exceeded the maximum packet size.  */
+  if (packet.size () < request.length ())
+    error (_("Contents too big for packet QMemTags."));
+
+  strcpy (packet.data (), request.c_str ());
+}
+
+/* Implement the "fetch_memtags" target_ops method.  */
+
+bool
+remote_target::fetch_memtags (CORE_ADDR address, size_t len,
+                             gdb::byte_vector &tags, int type)
+{
+  /* Make sure the qMemTags packet is supported.  */
+  if (!remote_memory_tagging_p ())
+    gdb_assert_not_reached ("remote fetch_memtags called with packet disabled");
+
+  struct remote_state *rs = get_remote_state ();
+
+  create_fetch_memtags_request (rs->buf, address, len, type);
+
+  putpkt (rs->buf);
+  getpkt (&rs->buf, 0);
+
+  return parse_fetch_memtags_reply (rs->buf, tags);
+}
+
+/* Implement the "store_memtags" target_ops method.  */
+
+bool
+remote_target::store_memtags (CORE_ADDR address, size_t len,
+                             const gdb::byte_vector &tags, int type)
+{
+  /* Make sure the QMemTags packet is supported.  */
+  if (!remote_memory_tagging_p ())
+    gdb_assert_not_reached ("remote store_memtags called with packet disabled");
+
+  struct remote_state *rs = get_remote_state ();
+
+  create_store_memtags_request (rs->buf, address, len, type, tags);
+
+  putpkt (rs->buf);
+  getpkt (&rs->buf, 0);
+
+  /* Verify if the request was successful.  */
+  return packet_check_result (rs->buf.data ()) == PACKET_OK;
+}
+
+/* Return true if remote target T is non-stop.  */
+
+bool
+remote_target_is_non_stop_p (remote_target *t)
+{
+  scoped_restore_current_thread restore_thread;
+  switch_to_target_no_thread (t);
+
+  return target_is_non_stop_p ();
+}
+
+#if GDB_SELF_TEST
+
+namespace selftests {
+
+static void
+test_memory_tagging_functions ()
+{
+  remote_target remote;
+
+  struct packet_config *config
+    = &remote_protocol_packets[PACKET_memory_tagging_feature];
+
+  scoped_restore restore_memtag_support_
+    = make_scoped_restore (&config->support);
+
+  /* Test memory tagging packet support.  */
+  config->support = PACKET_SUPPORT_UNKNOWN;
+  SELF_CHECK (remote.supports_memory_tagging () == false);
+  config->support = PACKET_DISABLE;
+  SELF_CHECK (remote.supports_memory_tagging () == false);
+  config->support = PACKET_ENABLE;
+  SELF_CHECK (remote.supports_memory_tagging () == true);
+
+  /* Setup testing.  */
+  gdb::char_vector packet;
+  gdb::byte_vector tags, bv;
+  std::string expected, reply;
+  packet.resize (32000);
+
+  /* Test creating a qMemTags request.  */
+
+  expected = "qMemTags:0,0:0";
+  create_fetch_memtags_request (packet, 0x0, 0x0, 0);
+  SELF_CHECK (strcmp (packet.data (), expected.c_str ()) == 0);
+
+  expected = "qMemTags:deadbeef,10:1";
+  create_fetch_memtags_request (packet, 0xdeadbeef, 16, 1);
+  SELF_CHECK (strcmp (packet.data (), expected.c_str ()) == 0);
+
+  /* Test parsing a qMemTags reply.  */
+
+  /* Error reply, tags vector unmodified.  */
+  reply = "E00";
+  strcpy (packet.data (), reply.c_str ());
+  tags.resize (0);
+  SELF_CHECK (parse_fetch_memtags_reply (packet, tags) == false);
+  SELF_CHECK (tags.size () == 0);
+
+  /* Valid reply, tags vector updated.  */
+  tags.resize (0);
+  bv.resize (0);
+
+  for (int i = 0; i < 5; i++)
+    bv.push_back (i);
+
+  reply = "m" + bin2hex (bv.data (), bv.size ());
+  strcpy (packet.data (), reply.c_str ());
+
+  SELF_CHECK (parse_fetch_memtags_reply (packet, tags) == true);
+  SELF_CHECK (tags.size () == 5);
+
+  for (int i = 0; i < 5; i++)
+    SELF_CHECK (tags[i] == i);
+
+  /* Test creating a QMemTags request.  */
+
+  /* Empty tag data.  */
+  tags.resize (0);
+  expected = "QMemTags:0,0:0:";
+  create_store_memtags_request (packet, 0x0, 0x0, 0, tags);
+  SELF_CHECK (memcmp (packet.data (), expected.c_str (),
+                     expected.length ()) == 0);
+
+  /* Non-empty tag data.  */
+  tags.resize (0);
+  for (int i = 0; i < 5; i++)
+    tags.push_back (i);
+  expected = "QMemTags:deadbeef,ff:1:0001020304";
+  create_store_memtags_request (packet, 0xdeadbeef, 255, 1, tags);
+  SELF_CHECK (memcmp (packet.data (), expected.c_str (),
+                     expected.length ()) == 0);
+}
+
+} // namespace selftests
+#endif /* GDB_SELF_TEST */
+
 void _initialize_remote ();
 void
 _initialize_remote ()
 {
-  struct cmd_list_element *cmd;
-  const char *cmd_name;
-
   /* architecture specific data */
   remote_g_packet_data_handle =
     gdbarch_data_register_pre_init (remote_g_packet_data_init);
@@ -14548,7 +14916,7 @@ _initialize_remote ()
   add_target (extended_remote_target_info, extended_remote_target::open);
 
   /* Hook into new objfile notification.  */
-  gdb::observers::new_objfile.attach (remote_new_objfile);
+  gdb::observers::new_objfile.attach (remote_new_objfile, "remote");
 
 #if 0
   init_remote_threadtests ();
@@ -14560,13 +14928,13 @@ _initialize_remote ()
 Remote protocol specific variables.\n\
 Configure various remote-protocol specific variables such as\n\
 the packets being used."),
-                       &remote_set_cmdlist, "set remote ",
+                       &remote_set_cmdlist,
                        0 /* allow-unknown */, &setlist);
   add_prefix_cmd ("remote", class_maintenance, show_remote_cmd, _("\
 Remote protocol specific variables.\n\
 Configure various remote-protocol specific variables such as\n\
 the packets being used."),
-                 &remote_show_cmdlist, "show remote ",
+                 &remote_show_cmdlist,
                  0 /* allow-unknown */, &showlist);
 
   add_cmd ("compare-sections", class_obscure, compare_sections_command, _("\
@@ -14575,7 +14943,7 @@ Argument is a single section name (default: all loaded sections).\n\
 To compare only read-only loaded sections, specify the -r option."),
           &cmdlist);
 
-  add_cmd ("packet", class_maintenance, packet_command, _("\
+  add_cmd ("packet", class_maintenance, cli_packet_command, _("\
 Send an arbitrary packet to a remote target.\n\
    maintenance packet TEXT\n\
 If GDB is talking to an inferior via the GDB serial protocol, then\n\
@@ -14584,18 +14952,15 @@ response packet.  GDB supplies the initial `$' character, and the\n\
 terminating `#' character and checksum."),
           &maintenancelist);
 
-  add_setshow_boolean_cmd ("remotebreak", no_class, &remote_break, _("\
+  set_show_commands remotebreak_cmds
+    = add_setshow_boolean_cmd ("remotebreak", no_class, &remote_break, _("\
 Set whether to send break if interrupted."), _("\
 Show whether to send break if interrupted."), _("\
 If set, a break, instead of a cntrl-c, is sent to the remote target."),
-                          set_remotebreak, show_remotebreak,
-                          &setlist, &showlist);
-  cmd_name = "remotebreak";
-  cmd = lookup_cmd (&cmd_name, setlist, "", NULL, -1, 1);
-  deprecate_cmd (cmd, "set remote interrupt-sequence");
-  cmd_name = "remotebreak"; /* needed because lookup_cmd updates the pointer */
-  cmd = lookup_cmd (&cmd_name, showlist, "", NULL, -1, 1);
-  deprecate_cmd (cmd, "show remote interrupt-sequence");
+                              set_remotebreak, show_remotebreak,
+                              &setlist, &showlist);
+  deprecate_cmd (remotebreak_cmds.set, "set remote interrupt-sequence");
+  deprecate_cmd (remotebreak_cmds.show, "show remote interrupt-sequence");
 
   add_setshow_enum_cmd ("interrupt-sequence", class_support,
                        interrupt_sequence_modes, &interrupt_sequence_mode,
@@ -14932,6 +15297,9 @@ Show the maximum size of the address (in bits) in a memory packet."), NULL,
   add_packet_config_cmd (&remote_protocol_packets[PACKET_no_resumed],
                         "N stop reply", "no-resumed-stop-reply", 0);
 
+  add_packet_config_cmd (&remote_protocol_packets[PACKET_memory_tagging_feature],
+                        "memory-tagging-feature", "memory-tagging-feature", 0);
+
   /* Assert that we've registered "set remote foo-packet" commands
      for all packet configs.  */
   {
@@ -14985,7 +15353,7 @@ packets."),
   add_basic_prefix_cmd ("remote", class_files, _("\
 Manipulate files on the remote system.\n\
 Transfer files to and from the remote target system."),
-                       &remote_cmdlist, "remote ",
+                       &remote_cmdlist,
                        0 /* allow-unknown */, &cmdlist);
 
   add_cmd ("put", class_files, remote_put_command,
@@ -15041,6 +15409,31 @@ Specify \"unlimited\" to display all the characters."),
                                       NULL, show_remote_packet_max_chars,
                                       &setdebuglist, &showdebuglist);
 
+  add_setshow_boolean_cmd ("remote", no_class, &remote_debug,
+                          _("Set debugging of remote protocol."),
+                          _("Show debugging of remote protocol."),
+                          _("\
+When enabled, each packet sent or received with the remote target\n\
+is displayed."),
+                          NULL,
+                          show_remote_debug,
+                          &setdebuglist, &showdebuglist);
+
+  add_setshow_zuinteger_unlimited_cmd ("remotetimeout", no_class,
+                                      &remote_timeout, _("\
+Set timeout limit to wait for target to respond."), _("\
+Show timeout limit to wait for target to respond."), _("\
+This value is used to set the time limit for gdb to wait for a response\n\
+from the target."),
+                                      NULL,
+                                      show_remote_timeout,
+                                      &setlist, &showlist);
+
   /* Eventually initialize fileio.  See fileio.c */
   initialize_remote_fileio (&remote_set_cmdlist, &remote_show_cmdlist);
+
+#if GDB_SELF_TEST
+  selftests::register_test ("remote_memory_tagging",
+                           selftests::test_memory_tagging_functions);
+#endif
 }