gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / gdb / target.c
index a9255d7caf3a7dde2c27e0c739ebf829105f31fe..82c405a849172a08e678b6efdc2278028933d0e8 100644 (file)
@@ -1,6 +1,6 @@
 /* Select target systems and architectures at runtime for GDB.
 
-   Copyright (C) 1990-2014 Free Software Foundation, Inc.
+   Copyright (C) 1990-2020 Free Software Foundation, Inc.
 
    Contributed by Cygnus Support.
 
@@ -20,8 +20,6 @@
    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "defs.h"
-#include <errno.h>
-#include <string.h>
 #include "target.h"
 #include "target-dcache.h"
 #include "gdbcmd.h"
@@ -34,9 +32,7 @@
 #include "dcache.h"
 #include <signal.h>
 #include "regcache.h"
-#include "gdb_assert.h"
 #include "gdbcore.h"
-#include "exceptions.h"
 #include "target-descriptions.h"
 #include "gdbthread.h"
 #include "solib.h"
 #include "inline-frame.h"
 #include "tracepoint.h"
 #include "gdb/fileio.h"
-#include "agent.h"
+#include "gdbsupport/agent.h"
 #include "auxv.h"
+#include "target-debug.h"
+#include "top.h"
+#include "event-top.h"
+#include <algorithm>
+#include "gdbsupport/byte-vector.h"
+#include "terminal.h"
+#include <unordered_map>
+#include "target-connection.h"
 
-static void target_info (char *, int);
+static void generic_tls_error (void) ATTRIBUTE_NORETURN;
 
 static void default_terminal_info (struct target_ops *, const char *, int);
 
@@ -62,9 +66,6 @@ static void default_rcmd (struct target_ops *, const char *, struct ui_file *);
 static ptid_t default_get_ada_task_ptid (struct target_ops *self,
                                         long lwp, long tid);
 
-static int default_follow_fork (struct target_ops *self, int follow_child,
-                               int detach_fork);
-
 static void default_mourn_inferior (struct target_ops *self);
 
 static int default_search_memory (struct target_ops *ops,
@@ -78,21 +79,9 @@ static int default_verify_memory (struct target_ops *self,
                                  const gdb_byte *data,
                                  CORE_ADDR memaddr, ULONGEST size);
 
-static struct address_space *default_thread_address_space
-     (struct target_ops *self, ptid_t ptid);
-
 static void tcomplain (void) ATTRIBUTE_NORETURN;
 
-static int return_zero (struct target_ops *);
-
-static int return_zero_has_execution (struct target_ops *, ptid_t);
-
-static void target_command (char *, int);
-
-static struct target_ops *find_default_run_target (char *);
-
-static struct gdbarch *default_thread_architecture (struct target_ops *ops,
-                                                   ptid_t ptid);
+static struct target_ops *find_default_run_target (const char *);
 
 static int dummy_find_memory_regions (struct target_ops *self,
                                      find_memory_region_ftype ignore1,
@@ -101,110 +90,42 @@ static int dummy_find_memory_regions (struct target_ops *self,
 static char *dummy_make_corefile_notes (struct target_ops *self,
                                        bfd *ignore1, int *ignore2);
 
-static char *default_pid_to_str (struct target_ops *ops, ptid_t ptid);
+static std::string default_pid_to_str (struct target_ops *ops, ptid_t ptid);
 
 static enum exec_direction_kind default_execution_direction
     (struct target_ops *self);
 
-static CORE_ADDR default_target_decr_pc_after_break (struct target_ops *ops,
-                                                    struct gdbarch *gdbarch);
-
-#include "target-delegates.c"
-
-static void init_dummy_target (void);
-
-static struct target_ops debug_target;
-
-static void debug_to_open (char *, int);
-
-static void debug_to_prepare_to_store (struct target_ops *self,
-                                      struct regcache *);
-
-static void debug_to_files_info (struct target_ops *);
-
-static int debug_to_insert_breakpoint (struct target_ops *, struct gdbarch *,
-                                      struct bp_target_info *);
-
-static int debug_to_remove_breakpoint (struct target_ops *, struct gdbarch *,
-                                      struct bp_target_info *);
-
-static int debug_to_can_use_hw_breakpoint (struct target_ops *self,
-                                          int, int, int);
-
-static int debug_to_insert_hw_breakpoint (struct target_ops *self,
-                                         struct gdbarch *,
-                                         struct bp_target_info *);
-
-static int debug_to_remove_hw_breakpoint (struct target_ops *self,
-                                         struct gdbarch *,
-                                         struct bp_target_info *);
-
-static int debug_to_insert_watchpoint (struct target_ops *self,
-                                      CORE_ADDR, int, int,
-                                      struct expression *);
-
-static int debug_to_remove_watchpoint (struct target_ops *self,
-                                      CORE_ADDR, int, int,
-                                      struct expression *);
-
-static int debug_to_stopped_data_address (struct target_ops *, CORE_ADDR *);
-
-static int debug_to_watchpoint_addr_within_range (struct target_ops *,
-                                                 CORE_ADDR, CORE_ADDR, int);
-
-static int debug_to_region_ok_for_hw_watchpoint (struct target_ops *self,
-                                                CORE_ADDR, int);
-
-static int debug_to_can_accel_watchpoint_condition (struct target_ops *self,
-                                                   CORE_ADDR, int, int,
-                                                   struct expression *);
-
-static void debug_to_terminal_init (struct target_ops *self);
-
-static void debug_to_terminal_inferior (struct target_ops *self);
-
-static void debug_to_terminal_ours_for_output (struct target_ops *self);
-
-static void debug_to_terminal_save_ours (struct target_ops *self);
-
-static void debug_to_terminal_ours (struct target_ops *self);
-
-static void debug_to_load (struct target_ops *self, char *, int);
-
-static int debug_to_can_run (struct target_ops *self);
-
-static void debug_to_stop (struct target_ops *self, ptid_t);
+/* Mapping between target_info objects (which have address identity)
+   and corresponding open/factory function/callback.  Each add_target
+   call adds one entry to this map, and registers a "target
+   TARGET_NAME" command that when invoked calls the factory registered
+   here.  The target_info object is associated with the command via
+   the command's context.  */
+static std::unordered_map<const target_info *, target_open_ftype *>
+  target_factories;
 
-/* Pointer to array of target architecture structures; the size of the
-   array; the current index into the array; the allocated size of the
-   array.  */
-struct target_ops **target_structs;
-unsigned target_struct_size;
-unsigned target_struct_allocsize;
-#define        DEFAULT_ALLOCSIZE       10
+/* The singleton debug target.  */
 
-/* The initial current target, so that there is always a semi-valid
-   current target.  */
-
-static struct target_ops dummy_target;
+static struct target_ops *the_debug_target;
 
 /* Top of target stack.  */
-
-static struct target_ops *target_stack;
-
 /* The target structure we are currently using to talk to a process
    or file or whatever "inferior" we have.  */
 
-struct target_ops current_target;
+target_ops *
+current_top_target ()
+{
+  return current_inferior ()->top_target ();
+}
 
 /* Command list for target.  */
 
 static struct cmd_list_element *targetlist = NULL;
 
-/* Nonzero if we should trust readonly sections from the
+/* True if we should trust readonly sections from the
    executable when reading memory.  */
 
-static int trust_readonly = 0;
+static bool trust_readonly = false;
 
 /* Nonzero if we should show true memory content including
    memory breakpoint inserted by gdb.  */
@@ -213,102 +134,45 @@ static int show_memory_breakpoints = 0;
 
 /* These globals control whether GDB attempts to perform these
    operations; they are useful for targets that need to prevent
-   inadvertant disruption, such as in non-stop mode.  */
+   inadvertent disruption, such as in non-stop mode.  */
 
-int may_write_registers = 1;
+bool may_write_registers = true;
 
-int may_write_memory = 1;
+bool may_write_memory = true;
 
-int may_insert_breakpoints = 1;
+bool may_insert_breakpoints = true;
 
-int may_insert_tracepoints = 1;
+bool may_insert_tracepoints = true;
 
-int may_insert_fast_tracepoints = 1;
+bool may_insert_fast_tracepoints = true;
 
-int may_stop = 1;
+bool may_stop = true;
 
 /* Non-zero if we want to see trace of target level stuff.  */
 
 static unsigned int targetdebug = 0;
-static void
-show_targetdebug (struct ui_file *file, int from_tty,
-                 struct cmd_list_element *c, const char *value)
-{
-  fprintf_filtered (file, _("Target debugging is %s.\n"), value);
-}
-
-static void setup_target_debug (void);
-
-/* The user just typed 'target' without the name of a target.  */
 
 static void
-target_command (char *arg, int from_tty)
-{
-  fputs_filtered ("Argument required (target name).  Try `help target'\n",
-                 gdb_stdout);
-}
-
-/* Default target_has_* methods for process_stratum targets.  */
-
-int
-default_child_has_all_memory (struct target_ops *ops)
-{
-  /* If no inferior selected, then we can't read memory here.  */
-  if (ptid_equal (inferior_ptid, null_ptid))
-    return 0;
-
-  return 1;
-}
-
-int
-default_child_has_memory (struct target_ops *ops)
-{
-  /* If no inferior selected, then we can't read memory here.  */
-  if (ptid_equal (inferior_ptid, null_ptid))
-    return 0;
-
-  return 1;
-}
-
-int
-default_child_has_stack (struct target_ops *ops)
-{
-  /* If no inferior selected, there's no stack.  */
-  if (ptid_equal (inferior_ptid, null_ptid))
-    return 0;
-
-  return 1;
-}
-
-int
-default_child_has_registers (struct target_ops *ops)
+set_targetdebug  (const char *args, int from_tty, struct cmd_list_element *c)
 {
-  /* Can't read registers from no inferior.  */
-  if (ptid_equal (inferior_ptid, null_ptid))
-    return 0;
-
-  return 1;
+  if (targetdebug)
+    push_target (the_debug_target);
+  else
+    unpush_target (the_debug_target);
 }
 
-int
-default_child_has_execution (struct target_ops *ops, ptid_t the_ptid)
+static void
+show_targetdebug (struct ui_file *file, int from_tty,
+                 struct cmd_list_element *c, const char *value)
 {
-  /* If there's no thread selected, then we can't make it run through
-     hoops.  */
-  if (ptid_equal (the_ptid, null_ptid))
-    return 0;
-
-  return 1;
+  fprintf_filtered (file, _("Target debugging is %s.\n"), value);
 }
 
-
 int
 target_has_all_memory_1 (void)
 {
-  struct target_ops *t;
-
-  for (t = current_target.beneath; t != NULL; t = t->beneath)
-    if (t->to_has_all_memory (t))
+  for (target_ops *t = current_top_target (); t != NULL; t = t->beneath ())
+    if (t->has_all_memory ())
       return 1;
 
   return 0;
@@ -317,10 +181,8 @@ target_has_all_memory_1 (void)
 int
 target_has_memory_1 (void)
 {
-  struct target_ops *t;
-
-  for (t = current_target.beneath; t != NULL; t = t->beneath)
-    if (t->to_has_memory (t))
+  for (target_ops *t = current_top_target (); t != NULL; t = t->beneath ())
+    if (t->has_memory ())
       return 1;
 
   return 0;
@@ -329,10 +191,8 @@ target_has_memory_1 (void)
 int
 target_has_stack_1 (void)
 {
-  struct target_ops *t;
-
-  for (t = current_target.beneath; t != NULL; t = t->beneath)
-    if (t->to_has_stack (t))
+  for (target_ops *t = current_top_target (); t != NULL; t = t->beneath ())
+    if (t->has_stack ())
       return 1;
 
   return 0;
@@ -341,126 +201,93 @@ target_has_stack_1 (void)
 int
 target_has_registers_1 (void)
 {
-  struct target_ops *t;
-
-  for (t = current_target.beneath; t != NULL; t = t->beneath)
-    if (t->to_has_registers (t))
+  for (target_ops *t = current_top_target (); t != NULL; t = t->beneath ())
+    if (t->has_registers ())
       return 1;
 
   return 0;
 }
 
-int
-target_has_execution_1 (ptid_t the_ptid)
+bool
+target_has_execution_1 (inferior *inf)
 {
-  struct target_ops *t;
-
-  for (t = current_target.beneath; t != NULL; t = t->beneath)
-    if (t->to_has_execution (t, the_ptid))
-      return 1;
+  for (target_ops *t = inf->top_target ();
+       t != nullptr;
+       t = inf->find_target_beneath (t))
+    if (t->has_execution (inf))
+      return true;
 
-  return 0;
+  return false;
 }
 
 int
 target_has_execution_current (void)
 {
-  return target_has_execution_1 (inferior_ptid);
+  return target_has_execution_1 (current_inferior ());
 }
 
-/* Complete initialization of T.  This ensures that various fields in
-   T are set, if needed by the target implementation.  */
+/* This is used to implement the various target commands.  */
 
-void
-complete_target_initialization (struct target_ops *t)
+static void
+open_target (const char *args, int from_tty, struct cmd_list_element *command)
 {
-  /* Provide default values for all "must have" methods.  */
-
-  if (t->to_has_all_memory == NULL)
-    t->to_has_all_memory = return_zero;
-
-  if (t->to_has_memory == NULL)
-    t->to_has_memory = return_zero;
+  auto *ti = static_cast<target_info *> (get_cmd_context (command));
+  target_open_ftype *func = target_factories[ti];
 
-  if (t->to_has_stack == NULL)
-    t->to_has_stack = return_zero;
-
-  if (t->to_has_registers == NULL)
-    t->to_has_registers = return_zero;
-
-  if (t->to_has_execution == NULL)
-    t->to_has_execution = return_zero_has_execution;
+  if (targetdebug)
+    fprintf_unfiltered (gdb_stdlog, "-> %s->open (...)\n",
+                       ti->shortname);
 
-  /* These methods can be called on an unpushed target and so require
-     a default implementation if the target might plausibly be the
-     default run target.  */
-  gdb_assert (t->to_can_run == NULL || (t->to_can_async_p != NULL
-                                       && t->to_supports_non_stop != NULL));
+  func (args, from_tty);
 
-  install_delegators (t);
+  if (targetdebug)
+    fprintf_unfiltered (gdb_stdlog, "<- %s->open (%s, %d)\n",
+                       ti->shortname, args, from_tty);
 }
 
-/* Add possible target architecture T to the list and add a new
-   command 'target T->to_shortname'.  Set COMPLETER as the command's
-   completer if not NULL.  */
+/* See target.h.  */
 
 void
-add_target_with_completer (struct target_ops *t,
-                          completer_ftype *completer)
+add_target (const target_info &t, target_open_ftype *func,
+           completer_ftype *completer)
 {
   struct cmd_list_element *c;
 
-  complete_target_initialization (t);
-
-  if (!target_structs)
-    {
-      target_struct_allocsize = DEFAULT_ALLOCSIZE;
-      target_structs = (struct target_ops **) xmalloc
-       (target_struct_allocsize * sizeof (*target_structs));
-    }
-  if (target_struct_size >= target_struct_allocsize)
-    {
-      target_struct_allocsize *= 2;
-      target_structs = (struct target_ops **)
-       xrealloc ((char *) target_structs,
-                 target_struct_allocsize * sizeof (*target_structs));
-    }
-  target_structs[target_struct_size++] = t;
+  auto &func_slot = target_factories[&t];
+  if (func_slot != nullptr)
+    internal_error (__FILE__, __LINE__,
+                   _("target already added (\"%s\")."), t.shortname);
+  func_slot = func;
 
   if (targetlist == NULL)
-    add_prefix_cmd ("target", class_run, target_command, _("\
+    add_basic_prefix_cmd ("target", class_run, _("\
 Connect to a target machine or process.\n\
 The first argument is the type or protocol of the target machine.\n\
 Remaining arguments are interpreted by the target protocol.  For more\n\
 information on the arguments for a particular protocol, type\n\
 `help target ' followed by the protocol name."),
-                   &targetlist, "target ", 0, &cmdlist);
-  c = add_cmd (t->to_shortname, no_class, t->to_open, t->to_doc,
-              &targetlist);
+                         &targetlist, "target ", 0, &cmdlist);
+  c = add_cmd (t.shortname, no_class, t.doc, &targetlist);
+  set_cmd_context (c, (void *) &t);
+  set_cmd_sfunc (c, open_target);
   if (completer != NULL)
     set_cmd_completer (c, completer);
 }
 
-/* Add a possible target architecture to the list.  */
-
-void
-add_target (struct target_ops *t)
-{
-  add_target_with_completer (t, NULL);
-}
-
 /* See target.h.  */
 
 void
-add_deprecated_target_alias (struct target_ops *t, char *alias)
+add_deprecated_target_alias (const target_info &tinfo, const char *alias)
 {
   struct cmd_list_element *c;
   char *alt;
 
   /* If we use add_alias_cmd, here, we do not get the deprecated warning,
      see PR cli/15104.  */
-  c = add_cmd (alias, no_class, t->to_open, t->to_doc, &targetlist);
-  alt = xstrprintf ("target %s", t->to_shortname);
+  c = add_cmd (alias, no_class, tinfo.doc, &targetlist);
+  set_cmd_sfunc (c, open_target);
+  set_cmd_context (c, (void *) &tinfo);
+  alt = xstrprintf ("target %s", tinfo.shortname);
   deprecate_cmd (c, alt);
 }
 
@@ -469,39 +296,215 @@ add_deprecated_target_alias (struct target_ops *t, char *alias)
 void
 target_kill (void)
 {
-  if (targetdebug)
-    fprintf_unfiltered (gdb_stdlog, "target_kill ()\n");
-
-  current_target.to_kill (&current_target);
+  current_top_target ()->kill ();
 }
 
 void
-target_load (char *arg, int from_tty)
+target_load (const char *arg, int from_tty)
 {
   target_dcache_invalidate ();
-  (*current_target.to_load) (&current_target, arg, from_tty);
+  current_top_target ()->load (arg, from_tty);
+}
+
+/* Define it.  */
+
+target_terminal_state target_terminal::m_terminal_state
+  = target_terminal_state::is_ours;
+
+/* See target/target.h.  */
+
+void
+target_terminal::init (void)
+{
+  current_top_target ()->terminal_init ();
+
+  m_terminal_state = target_terminal_state::is_ours;
 }
 
+/* See target/target.h.  */
+
 void
-target_terminal_inferior (void)
+target_terminal::inferior (void)
 {
+  struct ui *ui = current_ui;
+
   /* A background resume (``run&'') should leave GDB in control of the
-     terminal.  Use target_can_async_p, not target_is_async_p, since at
-     this point the target is not async yet.  However, if sync_execution
-     is not set, we know it will become async prior to resume.  */
-  if (target_can_async_p () && !sync_execution)
+     terminal.  */
+  if (ui->prompt_state != PROMPT_BLOCKED)
+    return;
+
+  /* Since we always run the inferior in the main console (unless "set
+     inferior-tty" is in effect), when some UI other than the main one
+     calls target_terminal::inferior, then we leave the main UI's
+     terminal settings as is.  */
+  if (ui != main_ui)
     return;
 
   /* If GDB is resuming the inferior in the foreground, install
      inferior's terminal modes.  */
-  (*current_target.to_terminal_inferior) (&current_target);
+
+  struct inferior *inf = current_inferior ();
+
+  if (inf->terminal_state != target_terminal_state::is_inferior)
+    {
+      current_top_target ()->terminal_inferior ();
+      inf->terminal_state = target_terminal_state::is_inferior;
+    }
+
+  m_terminal_state = target_terminal_state::is_inferior;
+
+  /* If the user hit C-c before, pretend that it was hit right
+     here.  */
+  if (check_quit_flag ())
+    target_pass_ctrlc ();
+}
+
+/* See target/target.h.  */
+
+void
+target_terminal::restore_inferior (void)
+{
+  struct ui *ui = current_ui;
+
+  /* See target_terminal::inferior().  */
+  if (ui->prompt_state != PROMPT_BLOCKED || ui != main_ui)
+    return;
+
+  /* Restore the terminal settings of inferiors that were in the
+     foreground but are now ours_for_output due to a temporary
+     target_target::ours_for_output() call.  */
+
+  {
+    scoped_restore_current_inferior restore_inferior;
+
+    for (::inferior *inf : all_inferiors ())
+      {
+       if (inf->terminal_state == target_terminal_state::is_ours_for_output)
+         {
+           set_current_inferior (inf);
+           current_top_target ()->terminal_inferior ();
+           inf->terminal_state = target_terminal_state::is_inferior;
+         }
+      }
+  }
+
+  m_terminal_state = target_terminal_state::is_inferior;
+
+  /* If the user hit C-c before, pretend that it was hit right
+     here.  */
+  if (check_quit_flag ())
+    target_pass_ctrlc ();
+}
+
+/* Switch terminal state to DESIRED_STATE, either is_ours, or
+   is_ours_for_output.  */
+
+static void
+target_terminal_is_ours_kind (target_terminal_state desired_state)
+{
+  scoped_restore_current_inferior restore_inferior;
+
+  /* Must do this in two passes.  First, have all inferiors save the
+     current terminal settings.  Then, after all inferiors have add a
+     chance to safely save the terminal settings, restore GDB's
+     terminal settings.  */
+
+  for (inferior *inf : all_inferiors ())
+    {
+      if (inf->terminal_state == target_terminal_state::is_inferior)
+       {
+         set_current_inferior (inf);
+         current_top_target ()->terminal_save_inferior ();
+       }
+    }
+
+  for (inferior *inf : all_inferiors ())
+    {
+      /* Note we don't check is_inferior here like above because we
+        need to handle 'is_ours_for_output -> is_ours' too.  Careful
+        to never transition from 'is_ours' to 'is_ours_for_output',
+        though.  */
+      if (inf->terminal_state != target_terminal_state::is_ours
+         && inf->terminal_state != desired_state)
+       {
+         set_current_inferior (inf);
+         if (desired_state == target_terminal_state::is_ours)
+           current_top_target ()->terminal_ours ();
+         else if (desired_state == target_terminal_state::is_ours_for_output)
+           current_top_target ()->terminal_ours_for_output ();
+         else
+           gdb_assert_not_reached ("unhandled desired state");
+         inf->terminal_state = desired_state;
+       }
+    }
+}
+
+/* See target/target.h.  */
+
+void
+target_terminal::ours ()
+{
+  struct ui *ui = current_ui;
+
+  /* See target_terminal::inferior.  */
+  if (ui != main_ui)
+    return;
+
+  if (m_terminal_state == target_terminal_state::is_ours)
+    return;
+
+  target_terminal_is_ours_kind (target_terminal_state::is_ours);
+  m_terminal_state = target_terminal_state::is_ours;
+}
+
+/* See target/target.h.  */
+
+void
+target_terminal::ours_for_output ()
+{
+  struct ui *ui = current_ui;
+
+  /* See target_terminal::inferior.  */
+  if (ui != main_ui)
+    return;
+
+  if (!target_terminal::is_inferior ())
+    return;
+
+  target_terminal_is_ours_kind (target_terminal_state::is_ours_for_output);
+  target_terminal::m_terminal_state = target_terminal_state::is_ours_for_output;
+}
+
+/* See target/target.h.  */
+
+void
+target_terminal::info (const char *arg, int from_tty)
+{
+  current_top_target ()->terminal_info (arg, from_tty);
+}
+
+/* See target.h.  */
+
+bool
+target_supports_terminal_ours (void)
+{
+  /* The current top target is the target at the top of the target
+     stack of the current inferior.  While normally there's always an
+     inferior, we must check for nullptr here because we can get here
+     very early during startup, before the initial inferior is first
+     created.  */
+  inferior *inf = current_inferior ();
+
+  if (inf == nullptr)
+    return false;
+  return inf->top_target ()->supports_terminal_ours ();
 }
 
 static void
 tcomplain (void)
 {
   error (_("You can't do that when your target is `%s'"),
-        current_target.to_shortname);
+        current_top_target ()->shortname ());
 }
 
 void
@@ -525,7 +528,7 @@ default_terminal_info (struct target_ops *self, const char *args, int from_tty)
 static ptid_t
 default_get_ada_task_ptid (struct target_ops *self, long lwp, long tid)
 {
-  return ptid_build (ptid_get_pid (inferior_ptid), lwp, tid);
+  return ptid_t (inferior_ptid.pid (), lwp, tid);
 }
 
 static enum exec_direction_kind
@@ -540,196 +543,162 @@ default_execution_direction (struct target_ops *self)
 to_execution_direction must be implemented for reverse async");
 }
 
-/* Go through the target stack from top to bottom, copying over zero
-   entries in current_target, then filling in still empty entries.  In
-   effect, we are doing class inheritance through the pushed target
-   vectors.
-
-   NOTE: cagney/2003-10-17: The problem with this inheritance, as it
-   is currently implemented, is that it discards any knowledge of
-   which target an inherited method originally belonged to.
-   Consequently, new new target methods should instead explicitly and
-   locally search the target stack for the target that can handle the
-   request.  */
+/* See target.h.  */
 
-static void
-update_current_target (void)
+void
+decref_target (target_ops *t)
 {
-  struct target_ops *t;
+  t->decref ();
+  if (t->refcount () == 0)
+    {
+      if (t->stratum () == process_stratum)
+       connection_list_remove (as_process_stratum_target (t));
+      target_close (t);
+    }
+}
 
-  /* First, reset current's contents.  */
-  memset (&current_target, 0, sizeof (current_target));
+/* See target.h.  */
 
-  /* Install the delegators.  */
-  install_delegators (&current_target);
+void
+target_stack::push (target_ops *t)
+{
+  t->incref ();
 
-  current_target.to_stratum = target_stack->to_stratum;
+  strata stratum = t->stratum ();
 
-#define INHERIT(FIELD, TARGET) \
-      if (!current_target.FIELD) \
-       current_target.FIELD = (TARGET)->FIELD
+  if (stratum == process_stratum)
+    connection_list_add (as_process_stratum_target (t));
 
-  /* Do not add any new INHERITs here.  Instead, use the delegation
-     mechanism provided by make-target-delegates.  */
-  for (t = target_stack; t; t = t->beneath)
-    {
-      INHERIT (to_shortname, t);
-      INHERIT (to_longname, t);
-      INHERIT (to_attach_no_wait, t);
-      INHERIT (to_have_steppable_watchpoint, t);
-      INHERIT (to_have_continuable_watchpoint, t);
-      INHERIT (to_has_thread_control, t);
-    }
-#undef INHERIT
+  /* If there's already a target at this stratum, remove it.  */
 
-  /* Finally, position the target-stack beneath the squashed
-     "current_target".  That way code looking for a non-inherited
-     target method can quickly and simply find it.  */
-  current_target.beneath = target_stack;
+  if (m_stack[stratum] != NULL)
+    unpush (m_stack[stratum]);
 
-  if (targetdebug)
-    setup_target_debug ();
-}
+  /* Now add the new one.  */
+  m_stack[stratum] = t;
 
-/* Push a new target type into the stack of the existing target accessors,
-   possibly superseding some of the existing accessors.
+  if (m_top < stratum)
+    m_top = stratum;
+}
 
-   Rather than allow an empty stack, we always have the dummy target at
-   the bottom stratum, so we can call the function vectors without
-   checking them.  */
+/* See target.h.  */
 
 void
 push_target (struct target_ops *t)
 {
-  struct target_ops **cur;
-
-  /* Check magic number.  If wrong, it probably means someone changed
-     the struct definition, but not all the places that initialize one.  */
-  if (t->to_magic != OPS_MAGIC)
-    {
-      fprintf_unfiltered (gdb_stderr,
-                         "Magic number of %s target struct wrong\n",
-                         t->to_shortname);
-      internal_error (__FILE__, __LINE__,
-                     _("failed internal consistency check"));
-    }
-
-  /* Find the proper stratum to install this target in.  */
-  for (cur = &target_stack; (*cur) != NULL; cur = &(*cur)->beneath)
-    {
-      if ((int) (t->to_stratum) >= (int) (*cur)->to_stratum)
-       break;
-    }
-
-  /* If there's already targets at this stratum, remove them.  */
-  /* FIXME: cagney/2003-10-15: I think this should be popping all
-     targets to CUR, and not just those at this stratum level.  */
-  while ((*cur) != NULL && t->to_stratum == (*cur)->to_stratum)
-    {
-      /* There's already something at this stratum level.  Close it,
-         and un-hook it from the stack.  */
-      struct target_ops *tmp = (*cur);
-
-      (*cur) = (*cur)->beneath;
-      tmp->beneath = NULL;
-      target_close (tmp);
-    }
+  current_inferior ()->push_target (t);
+}
 
-  /* We have removed all targets in our stratum, now add the new one.  */
-  t->beneath = (*cur);
-  (*cur) = t;
+/* See target.h.  */
 
-  update_current_target ();
+void
+push_target (target_ops_up &&t)
+{
+  current_inferior ()->push_target (t.get ());
+  t.release ();
 }
 
-/* Remove a target_ops vector from the stack, wherever it may be.
-   Return how many times it was removed (0 or 1).  */
+/* See target.h.  */
 
 int
 unpush_target (struct target_ops *t)
 {
-  struct target_ops **cur;
-  struct target_ops *tmp;
+  return current_inferior ()->unpush_target (t);
+}
+
+/* See target.h.  */
+
+bool
+target_stack::unpush (target_ops *t)
+{
+  gdb_assert (t != NULL);
+
+  strata stratum = t->stratum ();
 
-  if (t->to_stratum == dummy_stratum)
+  if (stratum == dummy_stratum)
     internal_error (__FILE__, __LINE__,
                    _("Attempt to unpush the dummy target"));
 
-  /* Look for the specified target.  Note that we assume that a target
-     can only occur once in the target stack.  */
+  /* Look for the specified target.  Note that a target can only occur
+     once in the target stack.  */
 
-  for (cur = &target_stack; (*cur) != NULL; cur = &(*cur)->beneath)
+  if (m_stack[stratum] != t)
     {
-      if ((*cur) == t)
-       break;
+      /* If T wasn't pushed, quit.  Only open targets should be
+        closed.  */
+      return false;
     }
 
-  /* If we don't find target_ops, quit.  Only open targets should be
-     closed.  */
-  if ((*cur) == NULL)
-    return 0;                  
-
   /* Unchain the target.  */
-  tmp = (*cur);
-  (*cur) = (*cur)->beneath;
-  tmp->beneath = NULL;
+  m_stack[stratum] = NULL;
 
-  update_current_target ();
+  if (m_top == stratum)
+    m_top = t->beneath ()->stratum ();
 
-  /* Finally close the target.  Note we do this after unchaining, so
-     any target method calls from within the target_close
-     implementation don't end up in T anymore.  */
-  target_close (t);
+  /* Finally close the target, if there are no inferiors
+     referencing this target still.  Note we do this after unchaining,
+     so any target method calls from within the target_close
+     implementation don't end up in T anymore.  Do leave the target
+     open if we have are other inferiors referencing this target
+     still.  */
+  decref_target (t);
 
-  return 1;
+  return true;
 }
 
-void
-pop_all_targets_above (enum strata above_stratum)
+/* Unpush TARGET and assert that it worked.  */
+
+static void
+unpush_target_and_assert (struct target_ops *target)
 {
-  while ((int) (current_target.to_stratum) > (int) above_stratum)
+  if (!unpush_target (target))
     {
-      if (!unpush_target (target_stack))
-       {
-         fprintf_unfiltered (gdb_stderr,
-                             "pop_all_targets couldn't find target %s\n",
-                             target_stack->to_shortname);
-         internal_error (__FILE__, __LINE__,
-                         _("failed internal consistency check"));
-         break;
-       }
+      fprintf_unfiltered (gdb_stderr,
+                         "pop_all_targets couldn't find target %s\n",
+                         target->shortname ());
+      internal_error (__FILE__, __LINE__,
+                     _("failed internal consistency check"));
     }
 }
 
+void
+pop_all_targets_above (enum strata above_stratum)
+{
+  while ((int) (current_top_target ()->stratum ()) > (int) above_stratum)
+    unpush_target_and_assert (current_top_target ());
+}
+
+/* See target.h.  */
+
+void
+pop_all_targets_at_and_above (enum strata stratum)
+{
+  while ((int) (current_top_target ()->stratum ()) >= (int) stratum)
+    unpush_target_and_assert (current_top_target ());
+}
+
 void
 pop_all_targets (void)
 {
   pop_all_targets_above (dummy_stratum);
 }
 
-/* Return 1 if T is now pushed in the target stack.  Return 0 otherwise.  */
+/* Return true if T is now pushed in the current inferior's target
+   stack.  Return false otherwise.  */
 
-int
-target_is_pushed (struct target_ops *t)
+bool
+target_is_pushed (target_ops *t)
 {
-  struct target_ops **cur;
-
-  /* Check magic number.  If wrong, it probably means someone changed
-     the struct definition, but not all the places that initialize one.  */
-  if (t->to_magic != OPS_MAGIC)
-    {
-      fprintf_unfiltered (gdb_stderr,
-                         "Magic number of %s target struct wrong\n",
-                         t->to_shortname);
-      internal_error (__FILE__, __LINE__,
-                     _("failed internal consistency check"));
-    }
+  return current_inferior ()->target_is_pushed (t);
+}
 
-  for (cur = &target_stack; (*cur) != NULL; cur = &(*cur)->beneath)
-    if (*cur == t)
-      return 1;
+/* Default implementation of to_get_thread_local_address.  */
 
-  return 0;
+static void
+generic_tls_error (void)
+{
+  throw_error (TLS_GENERIC_ERROR,
+              _("Cannot find thread-local variables on this target"));
 }
 
 /* Using the objfile specified in OBJFILE, find the address for the
@@ -738,36 +707,30 @@ CORE_ADDR
 target_translate_tls_address (struct objfile *objfile, CORE_ADDR offset)
 {
   volatile CORE_ADDR addr = 0;
-  struct target_ops *target;
-
-  for (target = current_target.beneath;
-       target != NULL;
-       target = target->beneath)
-    {
-      if (target->to_get_thread_local_address != NULL)
-       break;
-    }
+  struct target_ops *target = current_top_target ();
+  struct gdbarch *gdbarch = target_gdbarch ();
 
-  if (target != NULL
-      && gdbarch_fetch_tls_load_module_address_p (target_gdbarch ()))
+  if (gdbarch_fetch_tls_load_module_address_p (gdbarch))
     {
       ptid_t ptid = inferior_ptid;
-      volatile struct gdb_exception ex;
 
-      TRY_CATCH (ex, RETURN_MASK_ALL)
+      try
        {
          CORE_ADDR lm_addr;
          
          /* Fetch the load module address for this objfile.  */
-         lm_addr = gdbarch_fetch_tls_load_module_address (target_gdbarch (),
+         lm_addr = gdbarch_fetch_tls_load_module_address (gdbarch,
                                                           objfile);
 
-         addr = target->to_get_thread_local_address (target, ptid,
-                                                     lm_addr, offset);
+         if (gdbarch_get_thread_local_address_p (gdbarch))
+           addr = gdbarch_get_thread_local_address (gdbarch, ptid, lm_addr,
+                                                    offset);
+         else
+           addr = target->get_thread_local_address (ptid, lm_addr, offset);
        }
       /* If an error occurred, print TLS related messages here.  Otherwise,
          throw the error to some higher catcher.  */
-      if (ex.reason < 0)
+      catch (const gdb_exception &ex)
        {
          int objfile_is_library = (objfile->flags & OBJF_SHARED);
 
@@ -791,34 +754,34 @@ target_translate_tls_address (struct objfile *objfile, CORE_ADDR offset)
                         " thread-local variables in\n"
                         "the shared library `%s'\n"
                         "for %s"),
-                      objfile_name (objfile), target_pid_to_str (ptid));
+                      objfile_name (objfile),
+                      target_pid_to_str (ptid).c_str ());
              else
                error (_("The inferior has not yet allocated storage for"
                         " thread-local variables in\n"
                         "the executable `%s'\n"
                         "for %s"),
-                      objfile_name (objfile), target_pid_to_str (ptid));
+                      objfile_name (objfile),
+                      target_pid_to_str (ptid).c_str ());
              break;
            case TLS_GENERIC_ERROR:
              if (objfile_is_library)
                error (_("Cannot find thread-local storage for %s, "
                         "shared library %s:\n%s"),
-                      target_pid_to_str (ptid),
-                      objfile_name (objfile), ex.message);
+                      target_pid_to_str (ptid).c_str (),
+                      objfile_name (objfile), ex.what ());
              else
                error (_("Cannot find thread-local storage for %s, "
                         "executable file %s:\n%s"),
-                      target_pid_to_str (ptid),
-                      objfile_name (objfile), ex.message);
+                      target_pid_to_str (ptid).c_str (),
+                      objfile_name (objfile), ex.what ());
              break;
            default:
-             throw_exception (ex);
+             throw;
              break;
            }
        }
     }
-  /* It wouldn't be wrong here to try a gdbarch method, too; finding
-     TLS is an ABI-specific thing.  But we don't do that yet.  */
   else
     error (_("Cannot find thread-local variables on this target"));
 
@@ -850,7 +813,8 @@ target_xfer_status_to_string (enum target_xfer_status status)
    read.  */
 
 int
-target_read_string (CORE_ADDR memaddr, char **string, int len, int *errnop)
+target_read_string (CORE_ADDR memaddr, gdb::unique_xmalloc_ptr<char> *string,
+                   int len, int *errnop)
 {
   int tlen, offset, i;
   gdb_byte buf[4];
@@ -864,7 +828,7 @@ target_read_string (CORE_ADDR memaddr, char **string, int len, int *errnop)
 
   /* Small for testing.  */
   buffer_allocated = 4;
-  buffer = xmalloc (buffer_allocated);
+  buffer = (char *) xmalloc (buffer_allocated);
   bufptr = buffer;
 
   while (len > 0)
@@ -891,7 +855,7 @@ target_read_string (CORE_ADDR memaddr, char **string, int len, int *errnop)
 
          bytes = bufptr - buffer;
          buffer_allocated *= 2;
-         buffer = xrealloc (buffer, buffer_allocated);
+         buffer = (char *) xrealloc (buffer, buffer_allocated);
          bufptr = buffer + bytes;
        }
 
@@ -910,7 +874,7 @@ target_read_string (CORE_ADDR memaddr, char **string, int len, int *errnop)
       nbytes_read += tlen;
     }
 done:
-  *string = buffer;
+  string->reset (buffer);
   if (errnop != NULL)
     *errnop = errcode;
   return nbytes_read;
@@ -919,10 +883,7 @@ done:
 struct target_section_table *
 target_get_section_table (struct target_ops *target)
 {
-  if (targetdebug)
-    fprintf_unfiltered (gdb_stdlog, "target_get_section_table ()\n");
-
-  return (*target->to_get_section_table) (target);
+  return target->get_section_table ();
 }
 
 /* Find a section containing ADDR.  */
@@ -944,11 +905,64 @@ target_section_by_addr (struct target_ops *target, CORE_ADDR addr)
   return NULL;
 }
 
+
+/* Helper for the memory xfer routines.  Checks the attributes of the
+   memory region of MEMADDR against the read or write being attempted.
+   If the access is permitted returns true, otherwise returns false.
+   REGION_P is an optional output parameter.  If not-NULL, it is
+   filled with a pointer to the memory region of MEMADDR.  REG_LEN
+   returns LEN trimmed to the end of the region.  This is how much the
+   caller can continue requesting, if the access is permitted.  A
+   single xfer request must not straddle memory region boundaries.  */
+
+static int
+memory_xfer_check_region (gdb_byte *readbuf, const gdb_byte *writebuf,
+                         ULONGEST memaddr, ULONGEST len, ULONGEST *reg_len,
+                         struct mem_region **region_p)
+{
+  struct mem_region *region;
+
+  region = lookup_mem_region (memaddr);
+
+  if (region_p != NULL)
+    *region_p = region;
+
+  switch (region->attrib.mode)
+    {
+    case MEM_RO:
+      if (writebuf != NULL)
+       return 0;
+      break;
+
+    case MEM_WO:
+      if (readbuf != NULL)
+       return 0;
+      break;
+
+    case MEM_FLASH:
+      /* We only support writing to flash during "load" for now.  */
+      if (writebuf != NULL)
+       error (_("Writing to flash memory forbidden in this context"));
+      break;
+
+    case MEM_NONE:
+      return 0;
+    }
+
+  /* region->hi == 0 means there's no upper bound.  */
+  if (memaddr + len < region->hi || region->hi == 0)
+    *reg_len = len;
+  else
+    *reg_len = region->hi - memaddr;
+
+  return 1;
+}
+
 /* Read memory from more than one valid target.  A core file, for
    instance, could have some of memory but delegate other bits to
    the target below it.  So, we must manually try all targets.  */
 
-static enum target_xfer_status
+enum target_xfer_status
 raw_memory_xfer_partial (struct target_ops *ops, gdb_byte *readbuf,
                         const gdb_byte *writebuf, ULONGEST memaddr, LONGEST len,
                         ULONGEST *xfered_len)
@@ -957,9 +971,9 @@ raw_memory_xfer_partial (struct target_ops *ops, gdb_byte *readbuf,
 
   do
     {
-      res = ops->to_xfer_partial (ops, TARGET_OBJECT_MEMORY, NULL,
-                                 readbuf, writebuf, memaddr, len,
-                                 xfered_len);
+      res = ops->xfer_partial (TARGET_OBJECT_MEMORY, NULL,
+                              readbuf, writebuf, memaddr, len,
+                              xfered_len);
       if (res == TARGET_XFER_OK)
        break;
 
@@ -969,10 +983,10 @@ raw_memory_xfer_partial (struct target_ops *ops, gdb_byte *readbuf,
 
       /* We want to continue past core files to executables, but not
         past a running target's memory.  */
-      if (ops->to_has_all_memory (ops))
+      if (ops->has_all_memory ())
        break;
 
-      ops = ops->beneath;
+      ops = ops->beneath ();
     }
   while (ops != NULL);
 
@@ -982,7 +996,7 @@ raw_memory_xfer_partial (struct target_ops *ops, gdb_byte *readbuf,
      first, so that if it fails, we don't write to the cache contents
      that never made it to the target.  */
   if (writebuf != NULL
-      && !ptid_equal (inferior_ptid, null_ptid)
+      && inferior_ptid != null_ptid
       && target_dcache_init_p ()
       && (stack_cache_enabled_p () || code_cache_enabled_p ()))
     {
@@ -1005,7 +1019,7 @@ memory_xfer_partial_1 (struct target_ops *ops, enum target_object object,
                       ULONGEST len, ULONGEST *xfered_len)
 {
   enum target_xfer_status res;
-  int reg_len;
+  ULONGEST reg_len;
   struct mem_region *region;
   struct inferior *inf;
 
@@ -1038,9 +1052,7 @@ memory_xfer_partial_1 (struct target_ops *ops, enum target_object object,
 
       secp = target_section_by_addr (ops, memaddr);
       if (secp != NULL
-         && (bfd_get_section_flags (secp->the_bfd_section->owner,
-                                    secp->the_bfd_section)
-             & SEC_READONLY))
+         && (bfd_section_flags (secp->the_bfd_section) & SEC_READONLY))
        {
          table = target_get_section_table (ops);
          return section_table_xfer_memory_partial (readbuf, writebuf,
@@ -1052,37 +1064,13 @@ memory_xfer_partial_1 (struct target_ops *ops, enum target_object object,
     }
 
   /* Try GDB's internal data cache.  */
-  region = lookup_mem_region (memaddr);
-  /* region->hi == 0 means there's no upper bound.  */
-  if (memaddr + len < region->hi || region->hi == 0)
-    reg_len = len;
-  else
-    reg_len = region->hi - memaddr;
-
-  switch (region->attrib.mode)
-    {
-    case MEM_RO:
-      if (writebuf != NULL)
-       return TARGET_XFER_E_IO;
-      break;
 
-    case MEM_WO:
-      if (readbuf != NULL)
-       return TARGET_XFER_E_IO;
-      break;
-
-    case MEM_FLASH:
-      /* We only support writing to flash during "load" for now.  */
-      if (writebuf != NULL)
-       error (_("Writing to flash memory forbidden in this context"));
-      break;
-
-    case MEM_NONE:
-      return TARGET_XFER_E_IO;
-    }
+  if (!memory_xfer_check_region (readbuf, writebuf, memaddr, len, &reg_len,
+                                &region))
+    return TARGET_XFER_E_IO;
 
-  if (!ptid_equal (inferior_ptid, null_ptid))
-    inf = find_inferior_pid (ptid_get_pid (inferior_ptid));
+  if (inferior_ptid != null_ptid)
+    inf = current_inferior ();
   else
     inf = NULL;
 
@@ -1134,6 +1122,8 @@ memory_xfer_partial (struct target_ops *ops, enum target_object object,
   if (len == 0)
     return TARGET_XFER_EOF;
 
+  memaddr = address_significant (target_gdbarch (), memaddr);
+
   /* Fill in READBUF with breakpoint shadows, or WRITEBUF with
      breakpoint insns, thus hiding out from higher layers whether
      there are software breakpoints inserted in the code stream.  */
@@ -1147,44 +1137,27 @@ memory_xfer_partial (struct target_ops *ops, enum target_object object,
     }
   else
     {
-      void *buf;
-      struct cleanup *old_chain;
-
       /* A large write request is likely to be partially satisfied
         by memory_xfer_partial_1.  We will continually malloc
         and free a copy of the entire write request for breakpoint
         shadow handling even though we only end up writing a small
-        subset of it.  Cap writes to 4KB to mitigate this.  */
-      len = min (4096, len);
+        subset of it.  Cap writes to a limit specified by the target
+        to mitigate this.  */
+      len = std::min (ops->get_memory_xfer_limit (), len);
 
-      buf = xmalloc (len);
-      old_chain = make_cleanup (xfree, buf);
-      memcpy (buf, writebuf, len);
-
-      breakpoint_xfer_memory (NULL, buf, writebuf, memaddr, len);
-      res = memory_xfer_partial_1 (ops, object, NULL, buf, memaddr, len,
+      gdb::byte_vector buf (writebuf, writebuf + len);
+      breakpoint_xfer_memory (NULL, buf.data (), writebuf, memaddr, len);
+      res = memory_xfer_partial_1 (ops, object, NULL, buf.data (), memaddr, len,
                                   xfered_len);
-
-      do_cleanups (old_chain);
     }
 
   return res;
 }
 
-static void
-restore_show_memory_breakpoints (void *arg)
-{
-  show_memory_breakpoints = (uintptr_t) arg;
-}
-
-struct cleanup *
-make_show_memory_breakpoints_cleanup (int show)
+scoped_restore_tmpl<int>
+make_scoped_restore_show_memory_breakpoints (int show)
 {
-  int current = show_memory_breakpoints;
-
-  show_memory_breakpoints = show;
-  return make_cleanup (restore_show_memory_breakpoints,
-                      (void *) (uintptr_t) current);
+  return make_scoped_restore (&show_memory_breakpoints, show);
 }
 
 /* For docs see target.h, to_xfer_partial.  */
@@ -1198,8 +1171,6 @@ target_xfer_partial (struct target_ops *ops,
 {
   enum target_xfer_status retval;
 
-  gdb_assert (ops->to_xfer_partial != NULL);
-
   /* Transfer is done when LEN is zero.  */
   if (len == 0)
     return TARGET_XFER_EOF;
@@ -1219,13 +1190,23 @@ target_xfer_partial (struct target_ops *ops,
                                  writebuf, offset, len, xfered_len);
   else if (object == TARGET_OBJECT_RAW_MEMORY)
     {
+      /* Skip/avoid accessing the target if the memory region
+        attributes block the access.  Check this here instead of in
+        raw_memory_xfer_partial as otherwise we'd end up checking
+        this twice in the case of the memory_xfer_partial path is
+        taken; once before checking the dcache, and another in the
+        tail call to raw_memory_xfer_partial.  */
+      if (!memory_xfer_check_region (readbuf, writebuf, offset, len, &len,
+                                    NULL))
+       return TARGET_XFER_E_IO;
+
       /* Request the normal memory object from other layers.  */
       retval = raw_memory_xfer_partial (ops, readbuf, writebuf, offset, len,
                                        xfered_len);
     }
   else
-    retval = ops->to_xfer_partial (ops, object, annex, readbuf,
-                                  writebuf, offset, len, xfered_len);
+    retval = ops->xfer_partial (object, annex, readbuf,
+                               writebuf, offset, len, xfered_len);
 
   if (targetdebug)
     {
@@ -1234,7 +1215,7 @@ target_xfer_partial (struct target_ops *ops,
       fprintf_unfiltered (gdb_stdlog,
                          "%s:target_xfer_partial "
                          "(%d, %s, %s, %s, %s, %s) = %d, %s",
-                         ops->to_shortname,
+                         ops->shortname (),
                          (int) object,
                          (annex ? annex : "(null)"),
                          host_address_to_string (readbuf),
@@ -1282,7 +1263,7 @@ target_xfer_partial (struct target_ops *ops,
 
 /* Read LEN bytes of target memory at address MEMADDR, placing the
    results in GDB's memory at MYADDR.  Returns either 0 for success or
-   TARGET_XFER_E_IO if any error occurs.
+   -1 if any error occurs.
 
    If an error occurs, no guarantee is made about the contents of the data at
    MYADDR.  In particular, the caller should not depend upon partial reads
@@ -1294,14 +1275,27 @@ target_xfer_partial (struct target_ops *ops,
 int
 target_read_memory (CORE_ADDR memaddr, gdb_byte *myaddr, ssize_t len)
 {
-  /* Dispatch to the topmost target, not the flattened current_target.
-     Memory accesses check target->to_has_(all_)memory, and the
-     flattened target doesn't inherit those.  */
-  if (target_read (current_target.beneath, TARGET_OBJECT_MEMORY, NULL,
+  if (target_read (current_top_target (), TARGET_OBJECT_MEMORY, NULL,
                   myaddr, memaddr, len) == len)
     return 0;
   else
-    return TARGET_XFER_E_IO;
+    return -1;
+}
+
+/* See target/target.h.  */
+
+int
+target_read_uint32 (CORE_ADDR memaddr, uint32_t *result)
+{
+  gdb_byte buf[4];
+  int r;
+
+  r = target_read_memory (memaddr, buf, sizeof buf);
+  if (r != 0)
+    return r;
+  *result = extract_unsigned_integer (buf, sizeof buf,
+                                     gdbarch_byte_order (target_gdbarch ()));
+  return 0;
 }
 
 /* Like target_read_memory, but specify explicitly that this is a read
@@ -1311,13 +1305,11 @@ target_read_memory (CORE_ADDR memaddr, gdb_byte *myaddr, ssize_t len)
 int
 target_read_raw_memory (CORE_ADDR memaddr, gdb_byte *myaddr, ssize_t len)
 {
-  /* See comment in target_read_memory about why the request starts at
-     current_target.beneath.  */
-  if (target_read (current_target.beneath, TARGET_OBJECT_RAW_MEMORY, NULL,
+  if (target_read (current_top_target (), TARGET_OBJECT_RAW_MEMORY, NULL,
                   myaddr, memaddr, len) == len)
     return 0;
   else
-    return TARGET_XFER_E_IO;
+    return -1;
 }
 
 /* Like target_read_memory, but specify explicitly that this is a read from
@@ -1326,13 +1318,11 @@ target_read_raw_memory (CORE_ADDR memaddr, gdb_byte *myaddr, ssize_t len)
 int
 target_read_stack (CORE_ADDR memaddr, gdb_byte *myaddr, ssize_t len)
 {
-  /* See comment in target_read_memory about why the request starts at
-     current_target.beneath.  */
-  if (target_read (current_target.beneath, TARGET_OBJECT_STACK_MEMORY, NULL,
+  if (target_read (current_top_target (), TARGET_OBJECT_STACK_MEMORY, NULL,
                   myaddr, memaddr, len) == len)
     return 0;
   else
-    return TARGET_XFER_E_IO;
+    return -1;
 }
 
 /* Like target_read_memory, but specify explicitly that this is a read from
@@ -1341,86 +1331,71 @@ target_read_stack (CORE_ADDR memaddr, gdb_byte *myaddr, ssize_t len)
 int
 target_read_code (CORE_ADDR memaddr, gdb_byte *myaddr, ssize_t len)
 {
-  /* See comment in target_read_memory about why the request starts at
-     current_target.beneath.  */
-  if (target_read (current_target.beneath, TARGET_OBJECT_CODE_MEMORY, NULL,
+  if (target_read (current_top_target (), TARGET_OBJECT_CODE_MEMORY, NULL,
                   myaddr, memaddr, len) == len)
     return 0;
   else
-    return TARGET_XFER_E_IO;
+    return -1;
 }
 
 /* Write LEN bytes from MYADDR to target memory at address MEMADDR.
-   Returns either 0 for success or TARGET_XFER_E_IO if any
-   error occurs.  If an error occurs, no guarantee is made about how
-   much data got written.  Callers that can deal with partial writes
-   should call target_write.  */
+   Returns either 0 for success or -1 if any error occurs.  If an
+   error occurs, no guarantee is made about how much data got written.
+   Callers that can deal with partial writes should call
+   target_write.  */
 
 int
 target_write_memory (CORE_ADDR memaddr, const gdb_byte *myaddr, ssize_t len)
 {
-  /* See comment in target_read_memory about why the request starts at
-     current_target.beneath.  */
-  if (target_write (current_target.beneath, TARGET_OBJECT_MEMORY, NULL,
+  if (target_write (current_top_target (), TARGET_OBJECT_MEMORY, NULL,
                    myaddr, memaddr, len) == len)
     return 0;
   else
-    return TARGET_XFER_E_IO;
+    return -1;
 }
 
 /* Write LEN bytes from MYADDR to target raw memory at address
-   MEMADDR.  Returns either 0 for success or TARGET_XFER_E_IO
-   if any error occurs.  If an error occurs, no guarantee is made
-   about how much data got written.  Callers that can deal with
-   partial writes should call target_write.  */
+   MEMADDR.  Returns either 0 for success or -1 if any error occurs.
+   If an error occurs, no guarantee is made about how much data got
+   written.  Callers that can deal with partial writes should call
+   target_write.  */
 
 int
 target_write_raw_memory (CORE_ADDR memaddr, const gdb_byte *myaddr, ssize_t len)
 {
-  /* See comment in target_read_memory about why the request starts at
-     current_target.beneath.  */
-  if (target_write (current_target.beneath, TARGET_OBJECT_RAW_MEMORY, NULL,
+  if (target_write (current_top_target (), TARGET_OBJECT_RAW_MEMORY, NULL,
                    myaddr, memaddr, len) == len)
     return 0;
   else
-    return TARGET_XFER_E_IO;
+    return -1;
 }
 
 /* Fetch the target's memory map.  */
 
-VEC(mem_region_s) *
+std::vector<mem_region>
 target_memory_map (void)
 {
-  VEC(mem_region_s) *result;
-  struct mem_region *last_one, *this_one;
-  int ix;
-  struct target_ops *t;
-
-  if (targetdebug)
-    fprintf_unfiltered (gdb_stdlog, "target_memory_map ()\n");
-
-  result = current_target.to_memory_map (&current_target);
-  if (result == NULL)
-    return NULL;
+  std::vector<mem_region> result = current_top_target ()->memory_map ();
+  if (result.empty ())
+    return result;
 
-  qsort (VEC_address (mem_region_s, result),
-        VEC_length (mem_region_s, result),
-        sizeof (struct mem_region), mem_region_cmp);
+  std::sort (result.begin (), result.end ());
 
   /* Check that regions do not overlap.  Simultaneously assign
      a numbering for the "mem" commands to use to refer to
      each region.  */
-  last_one = NULL;
-  for (ix = 0; VEC_iterate (mem_region_s, result, ix, this_one); ix++)
+  mem_region *last_one = NULL;
+  for (size_t ix = 0; ix < result.size (); ix++)
     {
+      mem_region *this_one = &result[ix];
       this_one->number = ix;
 
-      if (last_one && last_one->hi > this_one->lo)
+      if (last_one != NULL && last_one->hi > this_one->lo)
        {
          warning (_("Overlapping regions in memory map: ignoring"));
-         VEC_free (mem_region_s, result);
-         return NULL;
+         return std::vector<mem_region> ();
        }
+
       last_one = this_one;
     }
 
@@ -1430,18 +1405,13 @@ target_memory_map (void)
 void
 target_flash_erase (ULONGEST address, LONGEST length)
 {
-  if (targetdebug)
-    fprintf_unfiltered (gdb_stdlog, "target_flash_erase (%s, %s)\n",
-                       hex_string (address), phex (length, 0));
-  current_target.to_flash_erase (&current_target, address, length);
+  current_top_target ()->flash_erase (address, length);
 }
 
 void
 target_flash_done (void)
 {
-  if (targetdebug)
-    fprintf_unfiltered (gdb_stdlog, "target_flash_done\n");
-  current_target.to_flash_done (&current_target);
+  current_top_target ()->flash_done ();
 }
 
 static void
@@ -1486,28 +1456,37 @@ target_read (struct target_ops *ops,
             const char *annex, gdb_byte *buf,
             ULONGEST offset, LONGEST len)
 {
-  LONGEST xfered = 0;
+  LONGEST xfered_total = 0;
+  int unit_size = 1;
 
-  while (xfered < len)
+  /* If we are reading from a memory object, find the length of an addressable
+     unit for that architecture.  */
+  if (object == TARGET_OBJECT_MEMORY
+      || object == TARGET_OBJECT_STACK_MEMORY
+      || object == TARGET_OBJECT_CODE_MEMORY
+      || object == TARGET_OBJECT_RAW_MEMORY)
+    unit_size = gdbarch_addressable_memory_unit_size (target_gdbarch ());
+
+  while (xfered_total < len)
     {
-      ULONGEST xfered_len;
+      ULONGEST xfered_partial;
       enum target_xfer_status status;
 
       status = target_read_partial (ops, object, annex,
-                                   (gdb_byte *) buf + xfered,
-                                   offset + xfered, len - xfered,
-                                   &xfered_len);
+                                   buf + xfered_total * unit_size,
+                                   offset + xfered_total, len - xfered_total,
+                                   &xfered_partial);
 
       /* Call an observer, notifying them of the xfer progress?  */
       if (status == TARGET_XFER_EOF)
-       return xfered;
+       return xfered_total;
       else if (status == TARGET_XFER_OK)
        {
-         xfered += xfered_len;
+         xfered_total += xfered_partial;
          QUIT;
        }
       else
-       return -1;
+       return TARGET_XFER_E_IO;
 
     }
   return len;
@@ -1536,44 +1515,39 @@ target_read (struct target_ops *ops,
 
 static void
 read_whatever_is_readable (struct target_ops *ops,
-                          ULONGEST begin, ULONGEST end,
-                          VEC(memory_read_result_s) **result)
+                          const ULONGEST begin, const ULONGEST end,
+                          int unit_size,
+                          std::vector<memory_read_result> *result)
 {
-  gdb_byte *buf = xmalloc (end - begin);
   ULONGEST current_begin = begin;
   ULONGEST current_end = end;
   int forward;
-  memory_read_result_s r;
   ULONGEST xfered_len;
 
   /* If we previously failed to read 1 byte, nothing can be done here.  */
   if (end - begin <= 1)
-    {
-      xfree (buf);
-      return;
-    }
+    return;
+
+  gdb::unique_xmalloc_ptr<gdb_byte> buf ((gdb_byte *) xmalloc (end - begin));
 
   /* Check that either first or the last byte is readable, and give up
      if not.  This heuristic is meant to permit reading accessible memory
      at the boundary of accessible region.  */
   if (target_read_partial (ops, TARGET_OBJECT_MEMORY, NULL,
-                          buf, begin, 1, &xfered_len) == TARGET_XFER_OK)
+                          buf.get (), begin, 1, &xfered_len) == TARGET_XFER_OK)
     {
       forward = 1;
       ++current_begin;
     }
   else if (target_read_partial (ops, TARGET_OBJECT_MEMORY, NULL,
-                               buf + (end-begin) - 1, end - 1, 1,
+                               buf.get () + (end - begin) - 1, end - 1, 1,
                                &xfered_len) == TARGET_XFER_OK)
     {
       forward = 0;
       --current_end;
     }
   else
-    {
-      xfree (buf);
-      return;
-    }
+    return;
 
   /* Loop invariant is that the [current_begin, current_end) was previously
      found to be not readable as a whole.
@@ -1585,7 +1559,7 @@ read_whatever_is_readable (struct target_ops *ops,
       ULONGEST first_half_begin, first_half_end;
       ULONGEST second_half_begin, second_half_end;
       LONGEST xfer;
-      ULONGEST middle = current_begin + (current_end - current_begin)/2;
+      ULONGEST middle = current_begin + (current_end - current_begin) / 2;
 
       if (forward)
        {
@@ -1603,7 +1577,7 @@ read_whatever_is_readable (struct target_ops *ops,
        }
 
       xfer = target_read (ops, TARGET_OBJECT_MEMORY, NULL,
-                         buf + (first_half_begin - begin),
+                         buf.get () + (first_half_begin - begin) * unit_size,
                          first_half_begin,
                          first_half_end - first_half_begin);
 
@@ -1617,7 +1591,7 @@ read_whatever_is_readable (struct target_ops *ops,
       else
        {
          /* This half is not readable.  Because we've tried one byte, we
-            know some part of this half if actually redable.  Go to the next
+            know some part of this half if actually readable.  Go to the next
             iteration to divide again and try to read.
 
             We don't handle the other half, because this function only tries
@@ -1630,94 +1604,79 @@ read_whatever_is_readable (struct target_ops *ops,
   if (forward)
     {
       /* The [begin, current_begin) range has been read.  */
-      r.begin = begin;
-      r.end = current_begin;
-      r.data = buf;
+      result->emplace_back (begin, current_end, std::move (buf));
     }
   else
     {
       /* The [current_end, end) range has been read.  */
-      LONGEST rlen = end - current_end;
-
-      r.data = xmalloc (rlen);
-      memcpy (r.data, buf + current_end - begin, rlen);
-      r.begin = current_end;
-      r.end = end;
-      xfree (buf);
-    }
-  VEC_safe_push(memory_read_result_s, (*result), &r);
-}
-
-void
-free_memory_read_result_vector (void *x)
-{
-  VEC(memory_read_result_s) *v = x;
-  memory_read_result_s *current;
-  int ix;
+      LONGEST region_len = end - current_end;
 
-  for (ix = 0; VEC_iterate (memory_read_result_s, v, ix, current); ++ix)
-    {
-      xfree (current->data);
+      gdb::unique_xmalloc_ptr<gdb_byte> data
+       ((gdb_byte *) xmalloc (region_len * unit_size));
+      memcpy (data.get (), buf.get () + (current_end - begin) * unit_size,
+             region_len * unit_size);
+      result->emplace_back (current_end, end, std::move (data));
     }
-  VEC_free (memory_read_result_s, v);
 }
 
-VEC(memory_read_result_s) *
-read_memory_robust (struct target_ops *ops, ULONGEST offset, LONGEST len)
+std::vector<memory_read_result>
+read_memory_robust (struct target_ops *ops,
+                   const ULONGEST offset, const LONGEST len)
 {
-  VEC(memory_read_result_s) *result = 0;
+  std::vector<memory_read_result> result;
+  int unit_size = gdbarch_addressable_memory_unit_size (target_gdbarch ());
 
-  LONGEST xfered = 0;
-  while (xfered < len)
+  LONGEST xfered_total = 0;
+  while (xfered_total < len)
     {
-      struct mem_region *region = lookup_mem_region (offset + xfered);
-      LONGEST rlen;
+      struct mem_region *region = lookup_mem_region (offset + xfered_total);
+      LONGEST region_len;
 
       /* If there is no explicit region, a fake one should be created.  */
       gdb_assert (region);
 
       if (region->hi == 0)
-       rlen = len - xfered;
+       region_len = len - xfered_total;
       else
-       rlen = region->hi - offset;
+       region_len = region->hi - offset;
 
       if (region->attrib.mode == MEM_NONE || region->attrib.mode == MEM_WO)
        {
          /* Cannot read this region.  Note that we can end up here only
             if the region is explicitly marked inaccessible, or
             'inaccessible-by-default' is in effect.  */
-         xfered += rlen;
+         xfered_total += region_len;
        }
       else
        {
-         LONGEST to_read = min (len - xfered, rlen);
-         gdb_byte *buffer = (gdb_byte *)xmalloc (to_read);
+         LONGEST to_read = std::min (len - xfered_total, region_len);
+         gdb::unique_xmalloc_ptr<gdb_byte> buffer
+           ((gdb_byte *) xmalloc (to_read * unit_size));
 
-         LONGEST xfer = target_read (ops, TARGET_OBJECT_MEMORY, NULL,
-                                     (gdb_byte *) buffer,
-                                     offset + xfered, to_read);
+         LONGEST xfered_partial =
+             target_read (ops, TARGET_OBJECT_MEMORY, NULL, buffer.get (),
+                          offset + xfered_total, to_read);
          /* Call an observer, notifying them of the xfer progress?  */
-         if (xfer <= 0)
+         if (xfered_partial <= 0)
            {
              /* Got an error reading full chunk.  See if maybe we can read
                 some subrange.  */
-             xfree (buffer);
-             read_whatever_is_readable (ops, offset + xfered,
-                                        offset + xfered + to_read, &result);
-             xfered += to_read;
+             read_whatever_is_readable (ops, offset + xfered_total,
+                                        offset + xfered_total + to_read,
+                                        unit_size, &result);
+             xfered_total += to_read;
            }
          else
            {
-             struct memory_read_result r;
-             r.data = buffer;
-             r.begin = offset + xfered;
-             r.end = r.begin + xfer;
-             VEC_safe_push (memory_read_result_s, result, &r);
-             xfered += xfer;
+             result.emplace_back (offset + xfered_total,
+                                  offset + xfered_total + xfered_partial,
+                                  std::move (buffer));
+             xfered_total += xfered_partial;
            }
          QUIT;
        }
     }
+
   return result;
 }
 
@@ -1731,29 +1690,38 @@ target_write_with_progress (struct target_ops *ops,
                            ULONGEST offset, LONGEST len,
                            void (*progress) (ULONGEST, void *), void *baton)
 {
-  LONGEST xfered = 0;
+  LONGEST xfered_total = 0;
+  int unit_size = 1;
+
+  /* If we are writing to a memory object, find the length of an addressable
+     unit for that architecture.  */
+  if (object == TARGET_OBJECT_MEMORY
+      || object == TARGET_OBJECT_STACK_MEMORY
+      || object == TARGET_OBJECT_CODE_MEMORY
+      || object == TARGET_OBJECT_RAW_MEMORY)
+    unit_size = gdbarch_addressable_memory_unit_size (target_gdbarch ());
 
   /* Give the progress callback a chance to set up.  */
   if (progress)
     (*progress) (0, baton);
 
-  while (xfered < len)
+  while (xfered_total < len)
     {
-      ULONGEST xfered_len;
+      ULONGEST xfered_partial;
       enum target_xfer_status status;
 
       status = target_write_partial (ops, object, annex,
-                                    (gdb_byte *) buf + xfered,
-                                    offset + xfered, len - xfered,
-                                    &xfered_len);
+                                    buf + xfered_total * unit_size,
+                                    offset + xfered_total, len - xfered_total,
+                                    &xfered_partial);
 
       if (status != TARGET_XFER_OK)
-       return status == TARGET_XFER_EOF ? xfered : -1;
+       return status == TARGET_XFER_EOF ? xfered_total : TARGET_XFER_E_IO;
 
       if (progress)
-       (*progress) (xfered_len, baton);
+       (*progress) (xfered_partial, baton);
 
-      xfered += xfered_len;
+      xfered_total += xfered_partial;
       QUIT;
     }
   return len;
@@ -1771,18 +1739,17 @@ target_write (struct target_ops *ops,
                                     NULL, NULL);
 }
 
-/* Read OBJECT/ANNEX using OPS.  Store the result in *BUF_P and return
-   the size of the transferred data.  PADDING additional bytes are
-   available in *BUF_P.  This is a helper function for
-   target_read_alloc; see the declaration of that function for more
-   information.  */
+/* Help for target_read_alloc and target_read_stralloc.  See their comments
+   for details.  */
 
-static LONGEST
+template <typename T>
+gdb::optional<gdb::def_vector<T>>
 target_read_alloc_1 (struct target_ops *ops, enum target_object object,
-                    const char *annex, gdb_byte **buf_p, int padding)
+                    const char *annex)
 {
-  size_t buf_alloc, buf_pos;
-  gdb_byte *buf;
+  gdb::def_vector<T> buf;
+  size_t buf_pos = 0;
+  const int chunk = 4096;
 
   /* This function does not have a length parameter; it reads the
      entire OBJECT).  Also, it doesn't support objects fetched partly
@@ -1793,86 +1760,64 @@ target_read_alloc_1 (struct target_ops *ops, enum target_object object,
 
   /* Start by reading up to 4K at a time.  The target will throttle
      this number down if necessary.  */
-  buf_alloc = 4096;
-  buf = xmalloc (buf_alloc);
-  buf_pos = 0;
   while (1)
     {
       ULONGEST xfered_len;
       enum target_xfer_status status;
 
-      status = target_read_partial (ops, object, annex, &buf[buf_pos],
-                                   buf_pos, buf_alloc - buf_pos - padding,
+      buf.resize (buf_pos + chunk);
+
+      status = target_read_partial (ops, object, annex,
+                                   (gdb_byte *) &buf[buf_pos],
+                                   buf_pos, chunk,
                                    &xfered_len);
 
       if (status == TARGET_XFER_EOF)
        {
          /* Read all there was.  */
-         if (buf_pos == 0)
-           xfree (buf);
-         else
-           *buf_p = buf;
-         return buf_pos;
+         buf.resize (buf_pos);
+         return buf;
        }
       else if (status != TARGET_XFER_OK)
        {
          /* An error occurred.  */
-         xfree (buf);
-         return TARGET_XFER_E_IO;
+         return {};
        }
 
       buf_pos += xfered_len;
 
-      /* If the buffer is filling up, expand it.  */
-      if (buf_alloc < buf_pos * 2)
-       {
-         buf_alloc *= 2;
-         buf = xrealloc (buf, buf_alloc);
-       }
-
       QUIT;
     }
 }
 
-/* Read OBJECT/ANNEX using OPS.  Store the result in *BUF_P and return
-   the size of the transferred data.  See the declaration in "target.h"
-   function for more information about the return value.  */
+/* See target.h  */
 
-LONGEST
+gdb::optional<gdb::byte_vector>
 target_read_alloc (struct target_ops *ops, enum target_object object,
-                  const char *annex, gdb_byte **buf_p)
+                  const char *annex)
 {
-  return target_read_alloc_1 (ops, object, annex, buf_p, 0);
+  return target_read_alloc_1<gdb_byte> (ops, object, annex);
 }
 
-/* Read OBJECT/ANNEX using OPS.  The result is NUL-terminated and
-   returned as a string, allocated using xmalloc.  If an error occurs
-   or the transfer is unsupported, NULL is returned.  Empty objects
-   are returned as allocated but empty strings.  A warning is issued
-   if the result contains any embedded NUL bytes.  */
+/* See target.h.  */
 
-char *
+gdb::optional<gdb::char_vector>
 target_read_stralloc (struct target_ops *ops, enum target_object object,
                      const char *annex)
 {
-  gdb_byte *buffer;
-  char *bufstr;
-  LONGEST i, transferred;
-
-  transferred = target_read_alloc_1 (ops, object, annex, &buffer, 1);
-  bufstr = (char *) buffer;
-
-  if (transferred < 0)
-    return NULL;
+  gdb::optional<gdb::char_vector> buf
+    = target_read_alloc_1<char> (ops, object, annex);
 
-  if (transferred == 0)
-    return xstrdup ("");
+  if (!buf)
+    return {};
 
-  bufstr[transferred] = 0;
+  if (buf->empty () || buf->back () != '\0')
+    buf->push_back ('\0');
 
   /* Check for embedded NUL bytes; but allow trailing NULs.  */
-  for (i = strlen (bufstr); i < transferred; i++)
-    if (bufstr[i] != 0)
+  for (auto it = std::find (buf->begin (), buf->end (), '\0');
+       it != buf->end (); it++)
+    if (*it != '\0')
       {
        warning (_("target object %d, annex %s, "
                   "contained unexpected null characters"),
@@ -1880,7 +1825,7 @@ target_read_stralloc (struct target_ops *ops, enum target_object object,
        break;
       }
 
-  return bufstr;
+  return buf;
 }
 
 /* Memory transfer methods.  */
@@ -1921,15 +1866,15 @@ target_insert_breakpoint (struct gdbarch *gdbarch,
       return 1;
     }
 
-  return current_target.to_insert_breakpoint (&current_target,
-                                             gdbarch, bp_tgt);
+  return current_top_target ()->insert_breakpoint (gdbarch, bp_tgt);
 }
 
 /* See target.h.  */
 
 int
 target_remove_breakpoint (struct gdbarch *gdbarch,
-                         struct bp_target_info *bp_tgt)
+                         struct bp_target_info *bp_tgt,
+                         enum remove_bp_reason reason)
 {
   /* This is kind of a weird case to handle, but the permission might
      have been changed after breakpoints were inserted - in which case
@@ -1941,33 +1886,31 @@ target_remove_breakpoint (struct gdbarch *gdbarch,
       return 1;
     }
 
-  return current_target.to_remove_breakpoint (&current_target,
-                                             gdbarch, bp_tgt);
+  return current_top_target ()->remove_breakpoint (gdbarch, bp_tgt, reason);
 }
 
 static void
-target_info (char *args, int from_tty)
+info_target_command (const char *args, int from_tty)
 {
-  struct target_ops *t;
   int has_all_mem = 0;
 
   if (symfile_objfile != NULL)
     printf_unfiltered (_("Symbols from \"%s\".\n"),
                       objfile_name (symfile_objfile));
 
-  for (t = target_stack; t != NULL; t = t->beneath)
+  for (target_ops *t = current_top_target (); t != NULL; t = t->beneath ())
     {
-      if (!(*t->to_has_memory) (t))
+      if (!t->has_memory ())
        continue;
 
-      if ((int) (t->to_stratum) <= (int) dummy_stratum)
+      if ((int) (t->stratum ()) <= (int) dummy_stratum)
        continue;
       if (has_all_mem)
        printf_unfiltered (_("\tWhile running this, "
                             "GDB does not access memory from...\n"));
-      printf_unfiltered ("%s:\n", t->to_longname);
-      (t->to_files_info) (t);
-      has_all_mem = (*t->to_has_all_memory) (t);
+      printf_unfiltered ("%s:\n", t->longname ());
+      t->files_info ();
+      has_all_mem = t->has_all_memory ();
     }
 }
 
@@ -2009,30 +1952,13 @@ target_pre_inferior (int from_tty)
       target_clear_description ();
     }
 
-  agent_capability_invalidate ();
-}
-
-/* Callback for iterate_over_inferiors.  Gets rid of the given
-   inferior.  */
-
-static int
-dispose_inferior (struct inferior *inf, void *args)
-{
-  struct thread_info *thread;
-
-  thread = any_thread_of_process (inf->pid);
-  if (thread)
-    {
-      switch_to_thread (thread->ptid);
+  /* attach_flag may be set if the previous process associated with
+     the inferior was attached to.  */
+  current_inferior ()->attach_flag = 0;
 
-      /* Core inferiors actually should be detached, not killed.  */
-      if (target_has_execution)
-       target_kill ();
-      else
-       target_detach (NULL, 0);
-    }
+  current_inferior ()->highest_thread_num = 0;
 
-  return 0;
+  agent_capability_invalidate ();
 }
 
 /* This is to be called by the open routine before it does
@@ -2043,12 +1969,19 @@ target_preopen (int from_tty)
 {
   dont_repeat ();
 
-  if (have_inferiors ())
+  if (current_inferior ()->pid != 0)
     {
       if (!from_tty
-         || !have_live_inferiors ()
+         || !target_has_execution
          || query (_("A program is being debugged already.  Kill it? ")))
-       iterate_over_inferiors (dispose_inferior, NULL);
+       {
+         /* Core inferiors actually should be detached, not
+            killed.  */
+         if (target_has_execution)
+           target_kill ();
+         else
+           target_detach (current_inferior (), 0);
+       }
       else
        error (_("Program not killed."));
     }
@@ -2062,149 +1995,167 @@ target_preopen (int from_tty)
   target_pre_inferior (from_tty);
 }
 
-/* Detach a target after doing deferred register stores.  */
+/* See target.h.  */
 
 void
-target_detach (const char *args, int from_tty)
+target_detach (inferior *inf, int from_tty)
 {
-  struct target_ops* t;
-  
+  /* After we have detached, we will clear the register cache for this inferior
+     by calling registers_changed_ptid.  We must save the pid_ptid before
+     detaching, as the target detach method will clear inf->pid.  */
+  ptid_t save_pid_ptid = ptid_t (inf->pid);
+
+  /* As long as some to_detach implementations rely on the current_inferior
+     (either directly, or indirectly, like through target_gdbarch or by
+     reading memory), INF needs to be the current inferior.  When that
+     requirement will become no longer true, then we can remove this
+     assertion.  */
+  gdb_assert (inf == current_inferior ());
+
   if (gdbarch_has_global_breakpoints (target_gdbarch ()))
     /* Don't remove global breakpoints here.  They're removed on
        disconnection from the target.  */
     ;
   else
     /* If we're in breakpoints-always-inserted mode, have to remove
-       them before detaching.  */
-    remove_breakpoints_pid (ptid_get_pid (inferior_ptid));
+       breakpoints before detaching.  */
+    remove_breakpoints_inf (current_inferior ());
 
   prepare_for_detach ();
 
-  current_target.to_detach (&current_target, args, from_tty);
-  if (targetdebug)
-    fprintf_unfiltered (gdb_stdlog, "target_detach (%s, %d)\n",
-                       args, from_tty);
+  /* Hold a strong reference because detaching may unpush the
+     target.  */
+  auto proc_target_ref = target_ops_ref::new_reference (inf->process_target ());
+
+  current_top_target ()->detach (inf, from_tty);
+
+  process_stratum_target *proc_target
+    = as_process_stratum_target (proc_target_ref.get ());
+
+  registers_changed_ptid (proc_target, save_pid_ptid);
+
+  /* We have to ensure we have no frame cache left.  Normally,
+     registers_changed_ptid (save_pid_ptid) calls reinit_frame_cache when
+     inferior_ptid matches save_pid_ptid, but in our case, it does not
+     call it, as inferior_ptid has been reset.  */
+  reinit_frame_cache ();
 }
 
 void
-target_disconnect (char *args, int from_tty)
+target_disconnect (const char *args, int from_tty)
 {
   /* If we're in breakpoints-always-inserted mode or if breakpoints
      are global across processes, we have to remove them before
      disconnecting.  */
   remove_breakpoints ();
 
-  if (targetdebug)
-    fprintf_unfiltered (gdb_stdlog, "target_disconnect (%s, %d)\n",
-                       args, from_tty);
-  current_target.to_disconnect (&current_target, args, from_tty);
+  current_top_target ()->disconnect (args, from_tty);
 }
 
+/* See target/target.h.  */
+
 ptid_t
 target_wait (ptid_t ptid, struct target_waitstatus *status, int options)
 {
-  struct target_ops *t;
-  ptid_t retval = (current_target.to_wait) (&current_target, ptid,
-                                           status, options);
-
-  if (targetdebug)
-    {
-      char *status_string;
-      char *options_string;
+  return current_top_target ()->wait (ptid, status, options);
+}
 
-      status_string = target_waitstatus_to_string (status);
-      options_string = target_options_to_string (options);
-      fprintf_unfiltered (gdb_stdlog,
-                         "target_wait (%d, status, options={%s})"
-                         " = %d,   %s\n",
-                         ptid_get_pid (ptid), options_string,
-                         ptid_get_pid (retval), status_string);
-      xfree (status_string);
-      xfree (options_string);
-    }
+/* See target.h.  */
 
-  return retval;
+ptid_t
+default_target_wait (struct target_ops *ops,
+                    ptid_t ptid, struct target_waitstatus *status,
+                    int options)
+{
+  status->kind = TARGET_WAITKIND_IGNORE;
+  return minus_one_ptid;
 }
 
-char *
+std::string
 target_pid_to_str (ptid_t ptid)
 {
-  return (*current_target.to_pid_to_str) (&current_target, ptid);
+  return current_top_target ()->pid_to_str (ptid);
 }
 
-char *
+const char *
 target_thread_name (struct thread_info *info)
 {
-  return current_target.to_thread_name (&current_target, info);
+  gdb_assert (info->inf == current_inferior ());
+
+  return current_top_target ()->thread_name (info);
+}
+
+struct thread_info *
+target_thread_handle_to_thread_info (const gdb_byte *thread_handle,
+                                    int handle_len,
+                                    struct inferior *inf)
+{
+  return current_top_target ()->thread_handle_to_thread_info (thread_handle,
+                                                    handle_len, inf);
+}
+
+/* See target.h.  */
+
+gdb::byte_vector
+target_thread_info_to_thread_handle (struct thread_info *tip)
+{
+  return current_top_target ()->thread_info_to_thread_handle (tip);
 }
 
 void
 target_resume (ptid_t ptid, int step, enum gdb_signal signal)
 {
-  struct target_ops *t;
+  process_stratum_target *curr_target = current_inferior ()->process_target ();
 
   target_dcache_invalidate ();
 
-  current_target.to_resume (&current_target, ptid, step, signal);
-  if (targetdebug)
-    fprintf_unfiltered (gdb_stdlog, "target_resume (%d, %s, %s)\n",
-                       ptid_get_pid (ptid),
-                       step ? "step" : "continue",
-                       gdb_signal_to_name (signal));
+  current_top_target ()->resume (ptid, step, signal);
 
-  registers_changed_ptid (ptid);
+  registers_changed_ptid (curr_target, ptid);
   /* We only set the internal executing state here.  The user/frontend
-     running state is set at a higher level.  */
-  set_executing (ptid, 1);
-  clear_inline_frame_state (ptid);
+     running state is set at a higher level.  This also clears the
+     thread's stop_pc as side effect.  */
+  set_executing (curr_target, ptid, true);
+  clear_inline_frame_state (curr_target, ptid);
 }
 
+/* If true, target_commit_resume is a nop.  */
+static int defer_target_commit_resume;
+
+/* See target.h.  */
+
 void
-target_pass_signals (int numsigs, unsigned char *pass_signals)
+target_commit_resume (void)
 {
-  if (targetdebug)
-    {
-      int i;
+  if (defer_target_commit_resume)
+    return;
 
-      fprintf_unfiltered (gdb_stdlog, "target_pass_signals (%d, {",
-                         numsigs);
+  current_top_target ()->commit_resume ();
+}
 
-      for (i = 0; i < numsigs; i++)
-       if (pass_signals[i])
-         fprintf_unfiltered (gdb_stdlog, " %s",
-                             gdb_signal_to_name (i));
+/* See target.h.  */
 
-      fprintf_unfiltered (gdb_stdlog, " })\n");
-    }
+scoped_restore_tmpl<int>
+make_scoped_defer_target_commit_resume ()
+{
+  return make_scoped_restore (&defer_target_commit_resume, 1);
+}
 
-  (*current_target.to_pass_signals) (&current_target, numsigs, pass_signals);
+void
+target_pass_signals (gdb::array_view<const unsigned char> pass_signals)
+{
+  current_top_target ()->pass_signals (pass_signals);
 }
 
 void
-target_program_signals (int numsigs, unsigned char *program_signals)
+target_program_signals (gdb::array_view<const unsigned char> program_signals)
 {
-  if (targetdebug)
-    {
-      int i;
-
-      fprintf_unfiltered (gdb_stdlog, "target_program_signals (%d, {",
-                         numsigs);
-
-      for (i = 0; i < numsigs; i++)
-       if (program_signals[i])
-         fprintf_unfiltered (gdb_stdlog, " %s",
-                             gdb_signal_to_name (i));
-
-      fprintf_unfiltered (gdb_stdlog, " })\n");
-    }
-
-  (*current_target.to_program_signals) (&current_target,
-                                       numsigs, program_signals);
+  current_top_target ()->program_signals (program_signals);
 }
 
-static int
-default_follow_fork (struct target_ops *self, int follow_child,
-                    int detach_fork)
+static bool
+default_follow_fork (struct target_ops *self, bool follow_child,
+                    bool detach_fork)
 {
   /* Some target returned a fork event, but did not know how to follow it.  */
   internal_error (__FILE__, __LINE__,
@@ -2214,17 +2165,18 @@ default_follow_fork (struct target_ops *self, int follow_child,
 /* Look through the list of possible targets for a target that can
    follow forks.  */
 
-int
-target_follow_fork (int follow_child, int detach_fork)
+bool
+target_follow_fork (bool follow_child, bool detach_fork)
 {
-  int retval = current_target.to_follow_fork (&current_target,
-                                             follow_child, detach_fork);
+  return current_top_target ()->follow_fork (follow_child, detach_fork);
+}
 
-  if (targetdebug)
-    fprintf_unfiltered (gdb_stdlog,
-                       "target_follow_fork (%d, %d) = %d\n",
-                       follow_child, detach_fork, retval);
-  return retval;
+/* Target wrapper for follow exec hook.  */
+
+void
+target_follow_exec (struct inferior *inf, const char *execd_pathname)
+{
+  current_top_target ()->follow_exec (inf, execd_pathname);
 }
 
 static void
@@ -2235,11 +2187,10 @@ default_mourn_inferior (struct target_ops *self)
 }
 
 void
-target_mourn_inferior (void)
+target_mourn_inferior (ptid_t ptid)
 {
-  current_target.to_mourn_inferior (&current_target);
-  if (targetdebug)
-    fprintf_unfiltered (gdb_stdlog, "target_mourn_inferior ()\n");
+  gdb_assert (ptid == inferior_ptid);
+  current_top_target ()->mourn_inferior ();
 
   /* We no longer need to keep handles on any of the object files.
      Make sure to release them to avoid unnecessarily locking any
@@ -2253,7 +2204,7 @@ target_mourn_inferior (void)
 const struct target_desc *
 target_read_description (struct target_ops *target)
 {
-  return target->to_read_description (target);
+  return target->read_description ();
 }
 
 /* This implements a basic search of memory, reading target memory and
@@ -2270,9 +2221,7 @@ simple_search_memory (struct target_ops *ops,
 #define SEARCH_CHUNK_SIZE 16000
   const unsigned chunk_size = SEARCH_CHUNK_SIZE;
   /* Buffer to hold memory contents for searching.  */
-  gdb_byte *search_buf;
   unsigned search_buf_size;
-  struct cleanup *old_cleanups;
 
   search_buf_size = chunk_size + pattern_len - 1;
 
@@ -2280,20 +2229,17 @@ simple_search_memory (struct target_ops *ops,
   if (search_space_len < search_buf_size)
     search_buf_size = search_space_len;
 
-  search_buf = malloc (search_buf_size);
-  if (search_buf == NULL)
-    error (_("Unable to allocate memory to perform the search."));
-  old_cleanups = make_cleanup (free_current_contents, &search_buf);
+  gdb::byte_vector search_buf (search_buf_size);
 
   /* Prime the search buffer.  */
 
   if (target_read (ops, TARGET_OBJECT_MEMORY, NULL,
-                  search_buf, start_addr, search_buf_size) != search_buf_size)
+                  search_buf.data (), start_addr, search_buf_size)
+      != search_buf_size)
     {
       warning (_("Unable to access %s bytes of target "
                 "memory at %s, halting search."),
               pulongest (search_buf_size), hex_string (start_addr));
-      do_cleanups (old_cleanups);
       return -1;
     }
 
@@ -2306,17 +2252,17 @@ simple_search_memory (struct target_ops *ops,
   while (search_space_len >= pattern_len)
     {
       gdb_byte *found_ptr;
-      unsigned nr_search_bytes = min (search_space_len, search_buf_size);
+      unsigned nr_search_bytes
+       = std::min (search_space_len, (ULONGEST) search_buf_size);
 
-      found_ptr = memmem (search_buf, nr_search_bytes,
-                         pattern, pattern_len);
+      found_ptr = (gdb_byte *) memmem (search_buf.data (), nr_search_bytes,
+                                      pattern, pattern_len);
 
       if (found_ptr != NULL)
        {
-         CORE_ADDR found_addr = start_addr + (found_ptr - search_buf);
+         CORE_ADDR found_addr = start_addr + (found_ptr - search_buf.data ());
 
          *found_addrp = found_addr;
-         do_cleanups (old_cleanups);
          return 1;
        }
 
@@ -2337,19 +2283,19 @@ simple_search_memory (struct target_ops *ops,
          /* Copy the trailing part of the previous iteration to the front
             of the buffer for the next iteration.  */
          gdb_assert (keep_len == pattern_len - 1);
-         memcpy (search_buf, search_buf + chunk_size, keep_len);
+         memcpy (&search_buf[0], &search_buf[chunk_size], keep_len);
 
-         nr_to_read = min (search_space_len - keep_len, chunk_size);
+         nr_to_read = std::min (search_space_len - keep_len,
+                                (ULONGEST) chunk_size);
 
          if (target_read (ops, TARGET_OBJECT_MEMORY, NULL,
-                          search_buf + keep_len, read_addr,
+                          &search_buf[keep_len], read_addr,
                           nr_to_read) != nr_to_read)
            {
              warning (_("Unable to access %s bytes of target "
                         "memory at %s, halting search."),
                       plongest (nr_to_read),
                       hex_string (read_addr));
-             do_cleanups (old_cleanups);
              return -1;
            }
 
@@ -2359,7 +2305,6 @@ simple_search_memory (struct target_ops *ops,
 
   /* Not found.  */
 
-  do_cleanups (old_cleanups);
   return 0;
 }
 
@@ -2372,7 +2317,7 @@ default_search_memory (struct target_ops *self,
                       CORE_ADDR *found_addrp)
 {
   /* Start over from the top of the target stack.  */
-  return simple_search_memory (current_target.beneath,
+  return simple_search_memory (current_top_target (),
                               start_addr, search_space_len,
                               pattern, pattern_len, found_addrp);
 }
@@ -2389,20 +2334,8 @@ target_search_memory (CORE_ADDR start_addr, ULONGEST search_space_len,
                      const gdb_byte *pattern, ULONGEST pattern_len,
                      CORE_ADDR *found_addrp)
 {
-  int found;
-
-  if (targetdebug)
-    fprintf_unfiltered (gdb_stdlog, "target_search_memory (%s, ...)\n",
-                       hex_string (start_addr));
-
-  found = current_target.to_search_memory (&current_target, start_addr,
-                                          search_space_len,
-                                          pattern, pattern_len, found_addrp);
-
-  if (targetdebug)
-    fprintf_unfiltered (gdb_stdlog, "  = %d\n", found);
-
-  return found;
+  return current_top_target ()->search_memory (start_addr, search_space_len,
+                                     pattern, pattern_len, found_addrp);
 }
 
 /* Look through the currently pushed targets.  If none of them will
@@ -2412,27 +2345,24 @@ target_search_memory (CORE_ADDR start_addr, ULONGEST search_space_len,
 void
 target_require_runnable (void)
 {
-  struct target_ops *t;
-
-  for (t = target_stack; t != NULL; t = t->beneath)
+  for (target_ops *t = current_top_target (); t != NULL; t = t->beneath ())
     {
       /* If this target knows how to create a new program, then
         assume we will still be able to after killing the current
         one.  Either killing and mourning will not pop T, or else
         find_default_run_target will find it again.  */
-      if (t->to_create_inferior != NULL)
+      if (t->can_create_inferior ())
        return;
 
-      /* Do not worry about thread_stratum targets that can not
+      /* Do not worry about targets at certain strata that can not
         create inferiors.  Assume they will be pushed again if
         necessary, and continue to the process_stratum.  */
-      if (t->to_stratum == thread_stratum
-         || t->to_stratum == arch_stratum)
+      if (t->stratum () > process_stratum)
        continue;
 
       error (_("The \"%s\" target does not support \"run\".  "
               "Try \"help target\" or \"continue\"."),
-            t->to_shortname);
+            t->shortname ());
     }
 
   /* This function is only called if the target is running.  In that
@@ -2443,7 +2373,7 @@ target_require_runnable (void)
 
 /* Whether GDB is allowed to fall back to the default run target for
    "run", "attach", etc. when no target is connected yet.  */
-static int auto_connect_native_target = 1;
+static bool auto_connect_native_target = true;
 
 static void
 show_auto_connect_native_target (struct ui_file *file, int from_tty,
@@ -2455,6 +2385,32 @@ show_auto_connect_native_target (struct ui_file *file, int from_tty,
                    value);
 }
 
+/* A pointer to the target that can respond to "run" or "attach".
+   Native targets are always singletons and instantiated early at GDB
+   startup.  */
+static target_ops *the_native_target;
+
+/* See target.h.  */
+
+void
+set_native_target (target_ops *target)
+{
+  if (the_native_target != NULL)
+    internal_error (__FILE__, __LINE__,
+                   _("native target already set (\"%s\")."),
+                   the_native_target->longname ());
+
+  the_native_target = target;
+}
+
+/* See target.h.  */
+
+target_ops *
+get_native_target ()
+{
+  return the_native_target;
+}
+
 /* Look through the list of possible targets for a target that can
    execute a run or attach command without any other data.  This is
    used to locate the default process stratum.
@@ -2463,38 +2419,14 @@ show_auto_connect_native_target (struct ui_file *file, int from_tty,
    called for errors); else, return NULL on error.  */
 
 static struct target_ops *
-find_default_run_target (char *do_mesg)
+find_default_run_target (const char *do_mesg)
 {
-  struct target_ops *runable = NULL;
-
-  if (auto_connect_native_target)
-    {
-      struct target_ops **t;
-      int count = 0;
-
-      for (t = target_structs; t < target_structs + target_struct_size;
-          ++t)
-       {
-         if ((*t)->to_can_run != delegate_can_run && target_can_run (*t))
-           {
-             runable = *t;
-             ++count;
-           }
-       }
-
-      if (count != 1)
-       runable = NULL;
-    }
+  if (auto_connect_native_target && the_native_target != NULL)
+    return the_native_target;
 
-  if (runable == NULL)
-    {
-      if (do_mesg)
-       error (_("Don't know how to %s.  Try \"help target\"."), do_mesg);
-      else
-       return NULL;
-    }
-
-  return runable;
+  if (do_mesg != NULL)
+    error (_("Don't know how to %s.  Try \"help target\"."), do_mesg);
+  return NULL;
 }
 
 /* See target.h.  */
@@ -2502,20 +2434,15 @@ find_default_run_target (char *do_mesg)
 struct target_ops *
 find_attach_target (void)
 {
-  struct target_ops *t;
-
   /* If a target on the current stack can attach, use it.  */
-  for (t = current_target.beneath; t != NULL; t = t->beneath)
+  for (target_ops *t = current_top_target (); t != NULL; t = t->beneath ())
     {
-      if (t->to_attach != NULL)
-       break;
+      if (t->can_attach ())
+       return t;
     }
 
   /* Otherwise, use the default run target for attaching.  */
-  if (t == NULL)
-    t = find_default_run_target ("attach");
-
-  return t;
+  return find_default_run_target ("attach");
 }
 
 /* See target.h.  */
@@ -2523,43 +2450,41 @@ find_attach_target (void)
 struct target_ops *
 find_run_target (void)
 {
-  struct target_ops *t;
-
-  /* If a target on the current stack can attach, use it.  */
-  for (t = current_target.beneath; t != NULL; t = t->beneath)
+  /* If a target on the current stack can run, use it.  */
+  for (target_ops *t = current_top_target (); t != NULL; t = t->beneath ())
     {
-      if (t->to_create_inferior != NULL)
-       break;
+      if (t->can_create_inferior ())
+       return t;
     }
 
   /* Otherwise, use the default run target.  */
-  if (t == NULL)
-    t = find_default_run_target ("run");
+  return find_default_run_target ("run");
+}
 
-  return t;
+bool
+target_ops::info_proc (const char *args, enum info_proc_what what)
+{
+  return false;
 }
 
 /* Implement the "info proc" command.  */
 
 int
-target_info_proc (char *args, enum info_proc_what what)
+target_info_proc (const char *args, enum info_proc_what what)
 {
   struct target_ops *t;
 
   /* If we're already connected to something that can get us OS
      related data, use it.  Otherwise, try using the native
      target.  */
-  if (current_target.to_stratum >= process_stratum)
-    t = current_target.beneath;
-  else
+  t = find_target_at (process_stratum);
+  if (t == NULL)
     t = find_default_run_target (NULL);
 
-  for (; t != NULL; t = t->beneath)
+  for (; t != NULL; t = t->beneath ())
     {
-      if (t->to_info_proc != NULL)
+      if (t->info_proc (args, what))
        {
-         t->to_info_proc (t, args, what);
-
          if (targetdebug)
            fprintf_unfiltered (gdb_stdlog,
                                "target_info_proc (\"%s\", %d)\n", args, what);
@@ -2577,24 +2502,28 @@ find_default_supports_disable_randomization (struct target_ops *self)
   struct target_ops *t;
 
   t = find_default_run_target (NULL);
-  if (t && t->to_supports_disable_randomization)
-    return (t->to_supports_disable_randomization) (t);
+  if (t != NULL)
+    return t->supports_disable_randomization ();
   return 0;
 }
 
 int
 target_supports_disable_randomization (void)
 {
-  struct target_ops *t;
+  return current_top_target ()->supports_disable_randomization ();
+}
 
-  for (t = &current_target; t != NULL; t = t->beneath)
-    if (t->to_supports_disable_randomization)
-      return t->to_supports_disable_randomization (t);
+/* See target/target.h.  */
 
-  return 0;
+int
+target_supports_multi_process (void)
+{
+  return current_top_target ()->supports_multi_process ();
 }
 
-char *
+/* See target.h.  */
+
+gdb::optional<gdb::char_vector>
 target_get_osdata (const char *type)
 {
   struct target_ops *t;
@@ -2602,285 +2531,511 @@ target_get_osdata (const char *type)
   /* If we're already connected to something that can get us OS
      related data, use it.  Otherwise, try using the native
      target.  */
-  if (current_target.to_stratum >= process_stratum)
-    t = current_target.beneath;
-  else
+  t = find_target_at (process_stratum);
+  if (t == NULL)
     t = find_default_run_target ("get OS data");
 
   if (!t)
-    return NULL;
+    return {};
 
   return target_read_stralloc (t, TARGET_OBJECT_OSDATA, type);
 }
 
-static struct address_space *
-default_thread_address_space (struct target_ops *self, ptid_t ptid)
+/* Determine the current address space of thread PTID.  */
+
+struct address_space *
+target_thread_address_space (ptid_t ptid)
 {
-  struct inferior *inf;
+  struct address_space *aspace;
 
-  /* Fall-back to the "main" address space of the inferior.  */
-  inf = find_inferior_pid (ptid_get_pid (ptid));
+  aspace = current_top_target ()->thread_address_space (ptid);
+  gdb_assert (aspace != NULL);
 
-  if (inf == NULL || inf->aspace == NULL)
-    internal_error (__FILE__, __LINE__,
-                   _("Can't determine the current "
-                     "address space of thread %s\n"),
-                   target_pid_to_str (ptid));
+  return aspace;
+}
 
-  return inf->aspace;
+/* See target.h.  */
+
+target_ops *
+target_ops::beneath () const
+{
+  return current_inferior ()->find_target_beneath (this);
 }
 
-/* Determine the current address space of thread PTID.  */
+void
+target_ops::close ()
+{
+}
 
-struct address_space *
-target_thread_address_space (ptid_t ptid)
+bool
+target_ops::can_attach ()
 {
-  struct address_space *aspace;
+  return 0;
+}
 
-  aspace = current_target.to_thread_address_space (&current_target, ptid);
-  gdb_assert (aspace != NULL);
+void
+target_ops::attach (const char *, int)
+{
+  gdb_assert_not_reached ("target_ops::attach called");
+}
 
-  if (targetdebug)
-    fprintf_unfiltered (gdb_stdlog,
-                       "target_thread_address_space (%s) = %d\n",
-                       target_pid_to_str (ptid),
-                       address_space_num (aspace));
+bool
+target_ops::can_create_inferior ()
+{
+  return 0;
+}
 
-  return aspace;
+void
+target_ops::create_inferior (const char *, const std::string &,
+                            char **, int)
+{
+  gdb_assert_not_reached ("target_ops::create_inferior called");
 }
 
+bool
+target_ops::can_run ()
+{
+  return false;
+}
+
+int
+target_can_run ()
+{
+  for (target_ops *t = current_top_target (); t != NULL; t = t->beneath ())
+    {
+      if (t->can_run ())
+       return 1;
+    }
+
+  return 0;
+}
 
 /* Target file operations.  */
 
 static struct target_ops *
 default_fileio_target (void)
 {
+  struct target_ops *t;
+
   /* If we're already connected to something that can perform
      file I/O, use it. Otherwise, try using the native target.  */
-  if (current_target.to_stratum >= process_stratum)
-    return current_target.beneath;
-  else
-    return find_default_run_target ("file I/O");
+  t = find_target_at (process_stratum);
+  if (t != NULL)
+    return t;
+  return find_default_run_target ("file I/O");
 }
 
-/* Open FILENAME on the target, using FLAGS and MODE.  Return a
-   target file descriptor, or -1 if an error occurs (and set
-   *TARGET_ERRNO).  */
-int
-target_fileio_open (const char *filename, int flags, int mode,
-                   int *target_errno)
+/* File handle for target file operations.  */
+
+struct fileio_fh_t
 {
-  struct target_ops *t;
+  /* The target on which this file is open.  NULL if the target is
+     meanwhile closed while the handle is open.  */
+  target_ops *target;
 
-  for (t = default_fileio_target (); t != NULL; t = t->beneath)
-    {
-      if (t->to_fileio_open != NULL)
-       {
-         int fd = t->to_fileio_open (t, filename, flags, mode, target_errno);
+  /* The file descriptor on the target.  */
+  int target_fd;
 
-         if (targetdebug)
-           fprintf_unfiltered (gdb_stdlog,
-                               "target_fileio_open (%s,0x%x,0%o) = %d (%d)\n",
-                               filename, flags, mode,
-                               fd, fd != -1 ? 0 : *target_errno);
-         return fd;
-       }
-    }
+  /* Check whether this fileio_fh_t represents a closed file.  */
+  bool is_closed ()
+  {
+    return target_fd < 0;
+  }
+};
 
-  *target_errno = FILEIO_ENOSYS;
-  return -1;
-}
+/* Vector of currently open file handles.  The value returned by
+   target_fileio_open and passed as the FD argument to other
+   target_fileio_* functions is an index into this vector.  This
+   vector's entries are never freed; instead, files are marked as
+   closed, and the handle becomes available for reuse.  */
+static std::vector<fileio_fh_t> fileio_fhandles;
 
-/* Write up to LEN bytes from WRITE_BUF to FD on the target.
-   Return the number of bytes written, or -1 if an error occurs
-   (and set *TARGET_ERRNO).  */
-int
-target_fileio_pwrite (int fd, const gdb_byte *write_buf, int len,
-                     ULONGEST offset, int *target_errno)
+/* Index into fileio_fhandles of the lowest handle that might be
+   closed.  This permits handle reuse without searching the whole
+   list each time a new file is opened.  */
+static int lowest_closed_fd;
+
+/* Invalidate the target associated with open handles that were open
+   on target TARG, since we're about to close (and maybe destroy) the
+   target.  The handles remain open from the client's perspective, but
+   trying to do anything with them other than closing them will fail
+   with EIO.  */
+
+static void
+fileio_handles_invalidate_target (target_ops *targ)
 {
-  struct target_ops *t;
+  for (fileio_fh_t &fh : fileio_fhandles)
+    if (fh.target == targ)
+      fh.target = NULL;
+}
+
+/* Acquire a target fileio file descriptor.  */
 
-  for (t = default_fileio_target (); t != NULL; t = t->beneath)
+static int
+acquire_fileio_fd (target_ops *target, int target_fd)
+{
+  /* Search for closed handles to reuse.  */
+  for (; lowest_closed_fd < fileio_fhandles.size (); lowest_closed_fd++)
     {
-      if (t->to_fileio_pwrite != NULL)
-       {
-         int ret = t->to_fileio_pwrite (t, fd, write_buf, len, offset,
-                                        target_errno);
+      fileio_fh_t &fh = fileio_fhandles[lowest_closed_fd];
 
-         if (targetdebug)
-           fprintf_unfiltered (gdb_stdlog,
-                               "target_fileio_pwrite (%d,...,%d,%s) "
-                               "= %d (%d)\n",
-                               fd, len, pulongest (offset),
-                               ret, ret != -1 ? 0 : *target_errno);
-         return ret;
-       }
+      if (fh.is_closed ())
+       break;
     }
 
-  *target_errno = FILEIO_ENOSYS;
-  return -1;
+  /* Push a new handle if no closed handles were found.  */
+  if (lowest_closed_fd == fileio_fhandles.size ())
+    fileio_fhandles.push_back (fileio_fh_t {target, target_fd});
+  else
+    fileio_fhandles[lowest_closed_fd] = {target, target_fd};
+
+  /* Should no longer be marked closed.  */
+  gdb_assert (!fileio_fhandles[lowest_closed_fd].is_closed ());
+
+  /* Return its index, and start the next lookup at
+     the next index.  */
+  return lowest_closed_fd++;
 }
 
-/* Read up to LEN bytes FD on the target into READ_BUF.
-   Return the number of bytes read, or -1 if an error occurs
-   (and set *TARGET_ERRNO).  */
-int
-target_fileio_pread (int fd, gdb_byte *read_buf, int len,
-                    ULONGEST offset, int *target_errno)
+/* Release a target fileio file descriptor.  */
+
+static void
+release_fileio_fd (int fd, fileio_fh_t *fh)
 {
-  struct target_ops *t;
+  fh->target_fd = -1;
+  lowest_closed_fd = std::min (lowest_closed_fd, fd);
+}
 
-  for (t = default_fileio_target (); t != NULL; t = t->beneath)
-    {
-      if (t->to_fileio_pread != NULL)
-       {
-         int ret = t->to_fileio_pread (t, fd, read_buf, len, offset,
-                                       target_errno);
+/* Return a pointer to the fileio_fhandle_t corresponding to FD.  */
 
-         if (targetdebug)
-           fprintf_unfiltered (gdb_stdlog,
-                               "target_fileio_pread (%d,...,%d,%s) "
-                               "= %d (%d)\n",
-                               fd, len, pulongest (offset),
-                               ret, ret != -1 ? 0 : *target_errno);
-         return ret;
-       }
-    }
+static fileio_fh_t *
+fileio_fd_to_fh (int fd)
+{
+  return &fileio_fhandles[fd];
+}
 
+
+/* Default implementations of file i/o methods.  We don't want these
+   to delegate automatically, because we need to know which target
+   supported the method, in order to call it directly from within
+   pread/pwrite, etc.  */
+
+int
+target_ops::fileio_open (struct inferior *inf, const char *filename,
+                        int flags, int mode, int warn_if_slow,
+                        int *target_errno)
+{
   *target_errno = FILEIO_ENOSYS;
   return -1;
 }
 
-/* Close FD on the target.  Return 0, or -1 if an error occurs
-   (and set *TARGET_ERRNO).  */
 int
-target_fileio_close (int fd, int *target_errno)
+target_ops::fileio_pwrite (int fd, const gdb_byte *write_buf, int len,
+                          ULONGEST offset, int *target_errno)
 {
-  struct target_ops *t;
-
-  for (t = default_fileio_target (); t != NULL; t = t->beneath)
-    {
-      if (t->to_fileio_close != NULL)
-       {
-         int ret = t->to_fileio_close (t, fd, target_errno);
-
-         if (targetdebug)
-           fprintf_unfiltered (gdb_stdlog,
-                               "target_fileio_close (%d) = %d (%d)\n",
-                               fd, ret, ret != -1 ? 0 : *target_errno);
-         return ret;
-       }
-    }
-
   *target_errno = FILEIO_ENOSYS;
   return -1;
 }
 
-/* Unlink FILENAME on the target.  Return 0, or -1 if an error
-   occurs (and set *TARGET_ERRNO).  */
 int
-target_fileio_unlink (const char *filename, int *target_errno)
+target_ops::fileio_pread (int fd, gdb_byte *read_buf, int len,
+                         ULONGEST offset, int *target_errno)
 {
-  struct target_ops *t;
+  *target_errno = FILEIO_ENOSYS;
+  return -1;
+}
 
-  for (t = default_fileio_target (); t != NULL; t = t->beneath)
-    {
-      if (t->to_fileio_unlink != NULL)
-       {
-         int ret = t->to_fileio_unlink (t, filename, target_errno);
+int
+target_ops::fileio_fstat (int fd, struct stat *sb, int *target_errno)
+{
+  *target_errno = FILEIO_ENOSYS;
+  return -1;
+}
 
-         if (targetdebug)
-           fprintf_unfiltered (gdb_stdlog,
-                               "target_fileio_unlink (%s) = %d (%d)\n",
-                               filename, ret, ret != -1 ? 0 : *target_errno);
-         return ret;
-       }
-    }
+int
+target_ops::fileio_close (int fd, int *target_errno)
+{
+  *target_errno = FILEIO_ENOSYS;
+  return -1;
+}
 
+int
+target_ops::fileio_unlink (struct inferior *inf, const char *filename,
+                          int *target_errno)
+{
   *target_errno = FILEIO_ENOSYS;
   return -1;
 }
 
-/* Read value of symbolic link FILENAME on the target.  Return a
-   null-terminated string allocated via xmalloc, or NULL if an error
-   occurs (and set *TARGET_ERRNO).  */
-char *
-target_fileio_readlink (const char *filename, int *target_errno)
+gdb::optional<std::string>
+target_ops::fileio_readlink (struct inferior *inf, const char *filename,
+                            int *target_errno)
 {
-  struct target_ops *t;
+  *target_errno = FILEIO_ENOSYS;
+  return {};
+}
 
-  for (t = default_fileio_target (); t != NULL; t = t->beneath)
+/* See target.h.  */
+
+int
+target_fileio_open (struct inferior *inf, const char *filename,
+                   int flags, int mode, bool warn_if_slow, int *target_errno)
+{
+  for (target_ops *t = default_fileio_target (); t != NULL; t = t->beneath ())
     {
-      if (t->to_fileio_readlink != NULL)
-       {
-         char *ret = t->to_fileio_readlink (t, filename, target_errno);
+      int fd = t->fileio_open (inf, filename, flags, mode,
+                              warn_if_slow, target_errno);
 
-         if (targetdebug)
-           fprintf_unfiltered (gdb_stdlog,
-                               "target_fileio_readlink (%s) = %s (%d)\n",
-                               filename, ret? ret : "(nil)",
-                               ret? 0 : *target_errno);
-         return ret;
-       }
+      if (fd == -1 && *target_errno == FILEIO_ENOSYS)
+       continue;
+
+      if (fd < 0)
+       fd = -1;
+      else
+       fd = acquire_fileio_fd (t, fd);
+
+      if (targetdebug)
+       fprintf_unfiltered (gdb_stdlog,
+                               "target_fileio_open (%d,%s,0x%x,0%o,%d)"
+                               " = %d (%d)\n",
+                               inf == NULL ? 0 : inf->num,
+                               filename, flags, mode,
+                               warn_if_slow, fd,
+                               fd != -1 ? 0 : *target_errno);
+      return fd;
     }
 
   *target_errno = FILEIO_ENOSYS;
-  return NULL;
+  return -1;
 }
 
-static void
-target_fileio_close_cleanup (void *opaque)
+/* See target.h.  */
+
+int
+target_fileio_pwrite (int fd, const gdb_byte *write_buf, int len,
+                     ULONGEST offset, int *target_errno)
 {
-  int fd = *(int *) opaque;
-  int target_errno;
+  fileio_fh_t *fh = fileio_fd_to_fh (fd);
+  int ret = -1;
+
+  if (fh->is_closed ())
+    *target_errno = EBADF;
+  else if (fh->target == NULL)
+    *target_errno = EIO;
+  else
+    ret = fh->target->fileio_pwrite (fh->target_fd, write_buf,
+                                    len, offset, target_errno);
 
-  target_fileio_close (fd, &target_errno);
+  if (targetdebug)
+    fprintf_unfiltered (gdb_stdlog,
+                       "target_fileio_pwrite (%d,...,%d,%s) "
+                       "= %d (%d)\n",
+                       fd, len, pulongest (offset),
+                       ret, ret != -1 ? 0 : *target_errno);
+  return ret;
 }
 
-/* Read target file FILENAME.  Store the result in *BUF_P and
-   return the size of the transferred data.  PADDING additional bytes are
-   available in *BUF_P.  This is a helper function for
-   target_fileio_read_alloc; see the declaration of that function for more
-   information.  */
+/* See target.h.  */
 
-static LONGEST
-target_fileio_read_alloc_1 (const char *filename,
-                           gdb_byte **buf_p, int padding)
+int
+target_fileio_pread (int fd, gdb_byte *read_buf, int len,
+                    ULONGEST offset, int *target_errno)
 {
-  struct cleanup *close_cleanup;
-  size_t buf_alloc, buf_pos;
-  gdb_byte *buf;
-  LONGEST n;
-  int fd;
-  int target_errno;
-
-  fd = target_fileio_open (filename, FILEIO_O_RDONLY, 0700, &target_errno);
-  if (fd == -1)
-    return -1;
+  fileio_fh_t *fh = fileio_fd_to_fh (fd);
+  int ret = -1;
 
-  close_cleanup = make_cleanup (target_fileio_close_cleanup, &fd);
+  if (fh->is_closed ())
+    *target_errno = EBADF;
+  else if (fh->target == NULL)
+    *target_errno = EIO;
+  else
+    ret = fh->target->fileio_pread (fh->target_fd, read_buf,
+                                   len, offset, target_errno);
+
+  if (targetdebug)
+    fprintf_unfiltered (gdb_stdlog,
+                       "target_fileio_pread (%d,...,%d,%s) "
+                       "= %d (%d)\n",
+                       fd, len, pulongest (offset),
+                       ret, ret != -1 ? 0 : *target_errno);
+  return ret;
+}
+
+/* See target.h.  */
+
+int
+target_fileio_fstat (int fd, struct stat *sb, int *target_errno)
+{
+  fileio_fh_t *fh = fileio_fd_to_fh (fd);
+  int ret = -1;
+
+  if (fh->is_closed ())
+    *target_errno = EBADF;
+  else if (fh->target == NULL)
+    *target_errno = EIO;
+  else
+    ret = fh->target->fileio_fstat (fh->target_fd, sb, target_errno);
+
+  if (targetdebug)
+    fprintf_unfiltered (gdb_stdlog,
+                       "target_fileio_fstat (%d) = %d (%d)\n",
+                       fd, ret, ret != -1 ? 0 : *target_errno);
+  return ret;
+}
+
+/* See target.h.  */
+
+int
+target_fileio_close (int fd, int *target_errno)
+{
+  fileio_fh_t *fh = fileio_fd_to_fh (fd);
+  int ret = -1;
+
+  if (fh->is_closed ())
+    *target_errno = EBADF;
+  else
+    {
+      if (fh->target != NULL)
+       ret = fh->target->fileio_close (fh->target_fd,
+                                       target_errno);
+      else
+       ret = 0;
+      release_fileio_fd (fd, fh);
+    }
+
+  if (targetdebug)
+    fprintf_unfiltered (gdb_stdlog,
+                       "target_fileio_close (%d) = %d (%d)\n",
+                       fd, ret, ret != -1 ? 0 : *target_errno);
+  return ret;
+}
+
+/* See target.h.  */
+
+int
+target_fileio_unlink (struct inferior *inf, const char *filename,
+                     int *target_errno)
+{
+  for (target_ops *t = default_fileio_target (); t != NULL; t = t->beneath ())
+    {
+      int ret = t->fileio_unlink (inf, filename, target_errno);
+
+      if (ret == -1 && *target_errno == FILEIO_ENOSYS)
+       continue;
+
+      if (targetdebug)
+       fprintf_unfiltered (gdb_stdlog,
+                           "target_fileio_unlink (%d,%s)"
+                           " = %d (%d)\n",
+                           inf == NULL ? 0 : inf->num, filename,
+                           ret, ret != -1 ? 0 : *target_errno);
+      return ret;
+    }
+
+  *target_errno = FILEIO_ENOSYS;
+  return -1;
+}
+
+/* See target.h.  */
+
+gdb::optional<std::string>
+target_fileio_readlink (struct inferior *inf, const char *filename,
+                       int *target_errno)
+{
+  for (target_ops *t = default_fileio_target (); t != NULL; t = t->beneath ())
+    {
+      gdb::optional<std::string> ret
+       = t->fileio_readlink (inf, filename, target_errno);
+
+      if (!ret.has_value () && *target_errno == FILEIO_ENOSYS)
+       continue;
+
+      if (targetdebug)
+       fprintf_unfiltered (gdb_stdlog,
+                           "target_fileio_readlink (%d,%s)"
+                           " = %s (%d)\n",
+                           inf == NULL ? 0 : inf->num,
+                           filename, ret ? ret->c_str () : "(nil)",
+                           ret ? 0 : *target_errno);
+      return ret;
+    }
+
+  *target_errno = FILEIO_ENOSYS;
+  return {};
+}
+
+/* Like scoped_fd, but specific to target fileio.  */
+
+class scoped_target_fd
+{
+public:
+  explicit scoped_target_fd (int fd) noexcept
+    : m_fd (fd)
+  {
+  }
+
+  ~scoped_target_fd ()
+  {
+    if (m_fd >= 0)
+      {
+       int target_errno;
+
+       target_fileio_close (m_fd, &target_errno);
+      }
+  }
+
+  DISABLE_COPY_AND_ASSIGN (scoped_target_fd);
+
+  int get () const noexcept
+  {
+    return m_fd;
+  }
+
+private:
+  int m_fd;
+};
+
+/* Read target file FILENAME, in the filesystem as seen by INF.  If
+   INF is NULL, use the filesystem seen by the debugger (GDB or, for
+   remote targets, the remote stub).  Store the result in *BUF_P and
+   return the size of the transferred data.  PADDING additional bytes
+   are available in *BUF_P.  This is a helper function for
+   target_fileio_read_alloc; see the declaration of that function for
+   more information.  */
+
+static LONGEST
+target_fileio_read_alloc_1 (struct inferior *inf, const char *filename,
+                           gdb_byte **buf_p, int padding)
+{
+  size_t buf_alloc, buf_pos;
+  gdb_byte *buf;
+  LONGEST n;
+  int target_errno;
+
+  scoped_target_fd fd (target_fileio_open (inf, filename, FILEIO_O_RDONLY,
+                                          0700, false, &target_errno));
+  if (fd.get () == -1)
+    return -1;
 
   /* Start by reading up to 4K at a time.  The target will throttle
      this number down if necessary.  */
   buf_alloc = 4096;
-  buf = xmalloc (buf_alloc);
+  buf = (gdb_byte *) xmalloc (buf_alloc);
   buf_pos = 0;
   while (1)
     {
-      n = target_fileio_pread (fd, &buf[buf_pos],
+      n = target_fileio_pread (fd.get (), &buf[buf_pos],
                               buf_alloc - buf_pos - padding, buf_pos,
                               &target_errno);
       if (n < 0)
        {
          /* An error occurred.  */
-         do_cleanups (close_cleanup);
          xfree (buf);
          return -1;
        }
       else if (n == 0)
        {
          /* Read all there was.  */
-         do_cleanups (close_cleanup);
          if (buf_pos == 0)
            xfree (buf);
          else
@@ -2894,44 +3049,39 @@ target_fileio_read_alloc_1 (const char *filename,
       if (buf_alloc < buf_pos * 2)
        {
          buf_alloc *= 2;
-         buf = xrealloc (buf, buf_alloc);
+         buf = (gdb_byte *) xrealloc (buf, buf_alloc);
        }
 
       QUIT;
     }
 }
 
-/* Read target file FILENAME.  Store the result in *BUF_P and return
-   the size of the transferred data.  See the declaration in "target.h"
-   function for more information about the return value.  */
+/* See target.h.  */
 
 LONGEST
-target_fileio_read_alloc (const char *filename, gdb_byte **buf_p)
+target_fileio_read_alloc (struct inferior *inf, const char *filename,
+                         gdb_byte **buf_p)
 {
-  return target_fileio_read_alloc_1 (filename, buf_p, 0);
+  return target_fileio_read_alloc_1 (inf, filename, buf_p, 0);
 }
 
-/* Read target file FILENAME.  The result is NUL-terminated and
-   returned as a string, allocated using xmalloc.  If an error occurs
-   or the transfer is unsupported, NULL is returned.  Empty objects
-   are returned as allocated but empty strings.  A warning is issued
-   if the result contains any embedded NUL bytes.  */
+/* See target.h.  */
 
-char *
-target_fileio_read_stralloc (const char *filename)
+gdb::unique_xmalloc_ptr<char> 
+target_fileio_read_stralloc (struct inferior *inf, const char *filename)
 {
   gdb_byte *buffer;
   char *bufstr;
   LONGEST i, transferred;
 
-  transferred = target_fileio_read_alloc_1 (filename, &buffer, 1);
+  transferred = target_fileio_read_alloc_1 (inf, filename, &buffer, 1);
   bufstr = (char *) buffer;
 
   if (transferred < 0)
-    return NULL;
+    return gdb::unique_xmalloc_ptr<char> (nullptr);
 
   if (transferred == 0)
-    return xstrdup ("");
+    return make_unique_xstrdup ("");
 
   bufstr[transferred] = 0;
 
@@ -2945,7 +3095,7 @@ target_fileio_read_stralloc (const char *filename)
        break;
       }
 
-  return bufstr;
+  return gdb::unique_xmalloc_ptr<char> (bufstr);
 }
 
 
@@ -2964,57 +3114,56 @@ default_watchpoint_addr_within_range (struct target_ops *target,
   return addr >= start && addr < start + length;
 }
 
-static struct gdbarch *
-default_thread_architecture (struct target_ops *ops, ptid_t ptid)
-{
-  return target_gdbarch ();
-}
+/* See target.h.  */
 
-static int
-return_zero (struct target_ops *ignore)
+target_ops *
+target_stack::find_beneath (const target_ops *t) const
 {
-  return 0;
-}
+  /* Look for a non-empty slot at stratum levels beneath T's.  */
+  for (int stratum = t->stratum () - 1; stratum >= 0; --stratum)
+    if (m_stack[stratum] != NULL)
+      return m_stack[stratum];
 
-static int
-return_zero_has_execution (struct target_ops *ignore, ptid_t ignore2)
-{
-  return 0;
+  return NULL;
 }
 
-/*
- * Find the next target down the stack from the specified target.
- */
+/* See target.h.  */
 
 struct target_ops *
-find_target_beneath (struct target_ops *t)
+find_target_at (enum strata stratum)
 {
-  return t->beneath;
+  return current_inferior ()->target_at (stratum);
 }
 
-/* See target.h.  */
+\f
 
-struct target_ops *
-find_target_at (enum strata stratum)
+/* See target.h  */
+
+void
+target_announce_detach (int from_tty)
 {
-  struct target_ops *t;
+  pid_t pid;
+  const char *exec_file;
 
-  for (t = current_target.beneath; t != NULL; t = t->beneath)
-    if (t->to_stratum == stratum)
-      return t;
+  if (!from_tty)
+    return;
 
-  return NULL;
+  exec_file = get_exec_file (0);
+  if (exec_file == NULL)
+    exec_file = "";
+
+  pid = inferior_ptid.pid ();
+  printf_unfiltered (_("Detaching from program: %s, %s\n"), exec_file,
+                    target_pid_to_str (ptid_t (pid)).c_str ());
 }
 
-\f
 /* The inferior process has died.  Long live the inferior!  */
 
 void
 generic_mourn_inferior (void)
 {
-  ptid_t ptid;
+  inferior *inf = current_inferior ();
 
-  ptid = inferior_ptid;
   inferior_ptid = null_ptid;
 
   /* Mark breakpoints uninserted in case something tries to delete a
@@ -3022,11 +3171,8 @@ generic_mourn_inferior (void)
      fail, since the inferior is long gone).  */
   mark_breakpoints_out ();
 
-  if (!ptid_equal (ptid, null_ptid))
-    {
-      int pid = ptid_get_pid (ptid);
-      exit_inferior (pid);
-    }
+  if (inf->pid != 0)
+    exit_inferior (inf);
 
   /* Note this wipes step-resume breakpoints, so needs to be done
      after exit_inferior, which ends up referencing the step-resume
@@ -3045,16 +3191,13 @@ generic_mourn_inferior (void)
 /* Convert a normal process ID to a string.  Returns the string in a
    static buffer.  */
 
-char *
+std::string
 normal_pid_to_str (ptid_t ptid)
 {
-  static char buf[32];
-
-  xsnprintf (buf, sizeof buf, "process %d", ptid_get_pid (ptid));
-  return buf;
+  return string_printf ("process %d", ptid.pid ());
 }
 
-static char *
+static std::string
 default_pid_to_str (struct target_ops *ops, ptid_t ptid)
 {
   return normal_pid_to_str (ptid);
@@ -3078,1000 +3221,543 @@ dummy_make_corefile_notes (struct target_ops *self,
   return NULL;
 }
 
-/* Set up the handful of non-empty slots needed by the dummy target
-   vector.  */
-
-static void
-init_dummy_target (void)
-{
-  dummy_target.to_shortname = "None";
-  dummy_target.to_longname = "None";
-  dummy_target.to_doc = "";
-  dummy_target.to_supports_disable_randomization
-    = find_default_supports_disable_randomization;
-  dummy_target.to_stratum = dummy_stratum;
-  dummy_target.to_has_all_memory = return_zero;
-  dummy_target.to_has_memory = return_zero;
-  dummy_target.to_has_stack = return_zero;
-  dummy_target.to_has_registers = return_zero;
-  dummy_target.to_has_execution = return_zero_has_execution;
-  dummy_target.to_magic = OPS_MAGIC;
-
-  install_dummy_methods (&dummy_target);
-}
-\f
-static void
-debug_to_open (char *args, int from_tty)
-{
-  debug_target.to_open (args, from_tty);
-
-  fprintf_unfiltered (gdb_stdlog, "target_open (%s, %d)\n", args, from_tty);
-}
-
-void
-target_close (struct target_ops *targ)
-{
-  gdb_assert (!target_is_pushed (targ));
-
-  if (targ->to_xclose != NULL)
-    targ->to_xclose (targ);
-  else if (targ->to_close != NULL)
-    targ->to_close (targ);
-
-  if (targetdebug)
-    fprintf_unfiltered (gdb_stdlog, "target_close ()\n");
-}
-
-int
-target_thread_alive (ptid_t ptid)
-{
-  int retval;
-
-  retval = current_target.to_thread_alive (&current_target, ptid);
-  if (targetdebug)
-    fprintf_unfiltered (gdb_stdlog, "target_thread_alive (%d) = %d\n",
-                       ptid_get_pid (ptid), retval);
-
-  return retval;
-}
+#include "target-delegates.c"
 
-void
-target_find_new_threads (void)
-{
-  current_target.to_find_new_threads (&current_target);
-  if (targetdebug)
-    fprintf_unfiltered (gdb_stdlog, "target_find_new_threads ()\n");
-}
+/* The initial current target, so that there is always a semi-valid
+   current target.  */
 
-void
-target_stop (ptid_t ptid)
-{
-  if (!may_stop)
-    {
-      warning (_("May not interrupt or stop the target, ignoring attempt"));
-      return;
-    }
+static dummy_target the_dummy_target;
 
-  (*current_target.to_stop) (&current_target, ptid);
-}
+/* See target.h.  */
 
-static void
-debug_to_post_attach (struct target_ops *self, int pid)
+target_ops *
+get_dummy_target ()
 {
-  debug_target.to_post_attach (&debug_target, pid);
-
-  fprintf_unfiltered (gdb_stdlog, "target_post_attach (%d)\n", pid);
+  return &the_dummy_target;
 }
 
-/* Concatenate ELEM to LIST, a comma separate list, and return the
-   result.  The LIST incoming argument is released.  */
+static const target_info dummy_target_info = {
+  "None",
+  N_("None"),
+  ""
+};
 
-static char *
-str_comma_list_concat_elem (char *list, const char *elem)
+strata
+dummy_target::stratum () const
 {
-  if (list == NULL)
-    return xstrdup (elem);
-  else
-    return reconcat (list, list, ", ", elem, (char *) NULL);
+  return dummy_stratum;
 }
 
-/* Helper for target_options_to_string.  If OPT is present in
-   TARGET_OPTIONS, append the OPT_STR (string version of OPT) in RET.
-   Returns the new resulting string.  OPT is removed from
-   TARGET_OPTIONS.  */
-
-static char *
-do_option (int *target_options, char *ret,
-          int opt, char *opt_str)
+strata
+debug_target::stratum () const
 {
-  if ((*target_options & opt) != 0)
-    {
-      ret = str_comma_list_concat_elem (ret, opt_str);
-      *target_options &= ~opt;
-    }
-
-  return ret;
+  return debug_stratum;
 }
 
-char *
-target_options_to_string (int target_options)
+const target_info &
+dummy_target::info () const
 {
-  char *ret = NULL;
-
-#define DO_TARG_OPTION(OPT) \
-  ret = do_option (&target_options, ret, OPT, #OPT)
-
-  DO_TARG_OPTION (TARGET_WNOHANG);
-
-  if (target_options != 0)
-    ret = str_comma_list_concat_elem (ret, "unknown???");
-
-  if (ret == NULL)
-    ret = xstrdup ("");
-  return ret;
+  return dummy_target_info;
 }
 
-static void
-debug_print_register (const char * func,
-                     struct regcache *regcache, int regno)
+const target_info &
+debug_target::info () const
 {
-  struct gdbarch *gdbarch = get_regcache_arch (regcache);
-
-  fprintf_unfiltered (gdb_stdlog, "%s ", func);
-  if (regno >= 0 && regno < gdbarch_num_regs (gdbarch)
-      && gdbarch_register_name (gdbarch, regno) != NULL
-      && gdbarch_register_name (gdbarch, regno)[0] != '\0')
-    fprintf_unfiltered (gdb_stdlog, "(%s)",
-                       gdbarch_register_name (gdbarch, regno));
-  else
-    fprintf_unfiltered (gdb_stdlog, "(%d)", regno);
-  if (regno >= 0 && regno < gdbarch_num_regs (gdbarch))
-    {
-      enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
-      int i, size = register_size (gdbarch, regno);
-      gdb_byte buf[MAX_REGISTER_SIZE];
-
-      regcache_raw_collect (regcache, regno, buf);
-      fprintf_unfiltered (gdb_stdlog, " = ");
-      for (i = 0; i < size; i++)
-       {
-         fprintf_unfiltered (gdb_stdlog, "%02x", buf[i]);
-       }
-      if (size <= sizeof (LONGEST))
-       {
-         ULONGEST val = extract_unsigned_integer (buf, size, byte_order);
-
-         fprintf_unfiltered (gdb_stdlog, " %s %s",
-                             core_addr_to_string_nz (val), plongest (val));
-       }
-    }
-  fprintf_unfiltered (gdb_stdlog, "\n");
+  return beneath ()->info ();
 }
 
-void
-target_fetch_registers (struct regcache *regcache, int regno)
-{
-  current_target.to_fetch_registers (&current_target, regcache, regno);
-  if (targetdebug)
-    debug_print_register ("target_fetch_registers", regcache, regno);
-}
+\f
 
 void
-target_store_registers (struct regcache *regcache, int regno)
-{
-  struct target_ops *t;
-
-  if (!may_write_registers)
-    error (_("Writing to registers is not allowed (regno %d)"), regno);
-
-  current_target.to_store_registers (&current_target, regcache, regno);
-  if (targetdebug)
-    {
-      debug_print_register ("target_store_registers", regcache, regno);
-    }
-}
-
-int
-target_core_of_thread (ptid_t ptid)
-{
-  int retval = current_target.to_core_of_thread (&current_target, ptid);
-
-  if (targetdebug)
-    fprintf_unfiltered (gdb_stdlog,
-                       "target_core_of_thread (%d) = %d\n",
-                       ptid_get_pid (ptid), retval);
-  return retval;
-}
-
-int
-simple_verify_memory (struct target_ops *ops,
-                     const gdb_byte *data, CORE_ADDR lma, ULONGEST size)
-{
-  LONGEST total_xfered = 0;
-
-  while (total_xfered < size)
-    {
-      ULONGEST xfered_len;
-      enum target_xfer_status status;
-      gdb_byte buf[1024];
-      ULONGEST howmuch = min (sizeof (buf), size - total_xfered);
-
-      status = target_xfer_partial (ops, TARGET_OBJECT_MEMORY, NULL,
-                                   buf, NULL, lma + total_xfered, howmuch,
-                                   &xfered_len);
-      if (status == TARGET_XFER_OK
-         && memcmp (data + total_xfered, buf, xfered_len) == 0)
-       {
-         total_xfered += xfered_len;
-         QUIT;
-       }
-      else
-       return 0;
-    }
-  return 1;
-}
-
-/* Default implementation of memory verification.  */
-
-static int
-default_verify_memory (struct target_ops *self,
-                      const gdb_byte *data, CORE_ADDR memaddr, ULONGEST size)
-{
-  /* Start over from the top of the target stack.  */
-  return simple_verify_memory (current_target.beneath,
-                              data, memaddr, size);
-}
-
-int
-target_verify_memory (const gdb_byte *data, CORE_ADDR memaddr, ULONGEST size)
-{
-  int retval = current_target.to_verify_memory (&current_target,
-                                               data, memaddr, size);
-
-  if (targetdebug)
-    fprintf_unfiltered (gdb_stdlog,
-                       "target_verify_memory (%s, %s) = %d\n",
-                       paddress (target_gdbarch (), memaddr),
-                       pulongest (size),
-                       retval);
-  return retval;
-}
-
-/* The documentation for this function is in its prototype declaration in
-   target.h.  */
-
-int
-target_insert_mask_watchpoint (CORE_ADDR addr, CORE_ADDR mask, int rw)
+target_close (struct target_ops *targ)
 {
-  int ret;
-
-  ret = current_target.to_insert_mask_watchpoint (&current_target,
-                                                 addr, mask, rw);
-
-  if (targetdebug)
-    fprintf_unfiltered (gdb_stdlog, "\
-target_insert_mask_watchpoint (%s, %s, %d) = %d\n",
-                       core_addr_to_string (addr),
-                       core_addr_to_string (mask), rw, ret);
-  
-  return ret;
-}
-
-/* The documentation for this function is in its prototype declaration in
-   target.h.  */
+  gdb_assert (!target_is_pushed (targ));
 
-int
-target_remove_mask_watchpoint (CORE_ADDR addr, CORE_ADDR mask, int rw)
-{
-  int ret;
+  fileio_handles_invalidate_target (targ);
 
-  ret = current_target.to_remove_mask_watchpoint (&current_target,
-                                                 addr, mask, rw);
+  targ->close ();
 
   if (targetdebug)
-    fprintf_unfiltered (gdb_stdlog, "\
-target_remove_mask_watchpoint (%s, %s, %d) = %d\n",
-                       core_addr_to_string (addr),
-                       core_addr_to_string (mask), rw, ret);
-
-  return ret;
-}
-
-/* The documentation for this function is in its prototype declaration
-   in target.h.  */
-
-int
-target_masked_watch_num_registers (CORE_ADDR addr, CORE_ADDR mask)
-{
-  return current_target.to_masked_watch_num_registers (&current_target,
-                                                      addr, mask);
+    fprintf_unfiltered (gdb_stdlog, "target_close ()\n");
 }
 
-/* The documentation for this function is in its prototype declaration
-   in target.h.  */
-
 int
-target_ranged_break_num_registers (void)
-{
-  return current_target.to_ranged_break_num_registers (&current_target);
-}
-
-/* See target.h.  */
-
-struct btrace_target_info *
-target_enable_btrace (ptid_t ptid)
-{
-  return current_target.to_enable_btrace (&current_target, ptid);
-}
-
-/* See target.h.  */
-
-void
-target_disable_btrace (struct btrace_target_info *btinfo)
-{
-  current_target.to_disable_btrace (&current_target, btinfo);
-}
-
-/* See target.h.  */
-
-void
-target_teardown_btrace (struct btrace_target_info *btinfo)
-{
-  current_target.to_teardown_btrace (&current_target, btinfo);
-}
-
-/* See target.h.  */
-
-enum btrace_error
-target_read_btrace (VEC (btrace_block_s) **btrace,
-                   struct btrace_target_info *btinfo,
-                   enum btrace_read_type type)
-{
-  return current_target.to_read_btrace (&current_target, btrace, btinfo, type);
-}
-
-/* See target.h.  */
-
-void
-target_stop_recording (void)
+target_thread_alive (ptid_t ptid)
 {
-  current_target.to_stop_recording (&current_target);
+  return current_top_target ()->thread_alive (ptid);
 }
 
-/* See target.h.  */
-
 void
-target_info_record (void)
+target_update_thread_list (void)
 {
-  struct target_ops *t;
-
-  for (t = current_target.beneath; t != NULL; t = t->beneath)
-    if (t->to_info_record != NULL)
-      {
-       t->to_info_record (t);
-       return;
-      }
-
-  tcomplain ();
+  current_top_target ()->update_thread_list ();
 }
 
-/* See target.h.  */
-
 void
-target_save_record (const char *filename)
-{
-  current_target.to_save_record (&current_target, filename);
-}
-
-/* See target.h.  */
-
-int
-target_supports_delete_record (void)
+target_stop (ptid_t ptid)
 {
-  struct target_ops *t;
-
-  for (t = current_target.beneath; t != NULL; t = t->beneath)
-    if (t->to_delete_record != NULL)
-      return 1;
+  if (!may_stop)
+    {
+      warning (_("May not interrupt or stop the target, ignoring attempt"));
+      return;
+    }
 
-  return 0;
+  current_top_target ()->stop (ptid);
 }
 
-/* See target.h.  */
-
 void
-target_delete_record (void)
+target_interrupt ()
 {
-  current_target.to_delete_record (&current_target);
-}
-
-/* See target.h.  */
+  if (!may_stop)
+    {
+      warning (_("May not interrupt or stop the target, ignoring attempt"));
+      return;
+    }
 
-int
-target_record_is_replaying (void)
-{
-  return current_target.to_record_is_replaying (&current_target);
+  current_top_target ()->interrupt ();
 }
 
 /* See target.h.  */
 
 void
-target_goto_record_begin (void)
+target_pass_ctrlc (void)
 {
-  current_target.to_goto_record_begin (&current_target);
-}
-
-/* See target.h.  */
+  /* Pass the Ctrl-C to the first target that has a thread
+     running.  */
+  for (inferior *inf : all_inferiors ())
+    {
+      target_ops *proc_target = inf->process_target ();
+      if (proc_target == NULL)
+       continue;
 
-void
-target_goto_record_end (void)
-{
-  current_target.to_goto_record_end (&current_target);
+      for (thread_info *thr : inf->threads ())
+       {
+         /* A thread can be THREAD_STOPPED and executing, while
+            running an infcall.  */
+         if (thr->state == THREAD_RUNNING || thr->executing)
+           {
+             /* We can get here quite deep in target layers.  Avoid
+                switching thread context or anything that would
+                communicate with the target (e.g., to fetch
+                registers), or flushing e.g., the frame cache.  We
+                just switch inferior in order to be able to call
+                through the target_stack.  */
+             scoped_restore_current_inferior restore_inferior;
+             set_current_inferior (inf);
+             current_top_target ()->pass_ctrlc ();
+             return;
+           }
+       }
+    }
 }
 
 /* See target.h.  */
 
 void
-target_goto_record (ULONGEST insn)
+default_target_pass_ctrlc (struct target_ops *ops)
 {
-  current_target.to_goto_record (&current_target, insn);
+  target_interrupt ();
 }
 
-/* See target.h.  */
+/* See target/target.h.  */
 
 void
-target_insn_history (int size, int flags)
+target_stop_and_wait (ptid_t ptid)
 {
-  current_target.to_insn_history (&current_target, size, flags);
-}
-
-/* See target.h.  */
+  struct target_waitstatus status;
+  bool was_non_stop = non_stop;
 
-void
-target_insn_history_from (ULONGEST from, int size, int flags)
-{
-  current_target.to_insn_history_from (&current_target, from, size, flags);
-}
+  non_stop = true;
+  target_stop (ptid);
 
-/* See target.h.  */
+  memset (&status, 0, sizeof (status));
+  target_wait (ptid, &status, 0);
 
-void
-target_insn_history_range (ULONGEST begin, ULONGEST end, int flags)
-{
-  current_target.to_insn_history_range (&current_target, begin, end, flags);
+  non_stop = was_non_stop;
 }
 
-/* See target.h.  */
+/* See target/target.h.  */
 
 void
-target_call_history (int size, int flags)
+target_continue_no_signal (ptid_t ptid)
 {
-  current_target.to_call_history (&current_target, size, flags);
+  target_resume (ptid, 0, GDB_SIGNAL_0);
 }
 
-/* See target.h.  */
+/* See target/target.h.  */
 
 void
-target_call_history_from (ULONGEST begin, int size, int flags)
+target_continue (ptid_t ptid, enum gdb_signal signal)
 {
-  current_target.to_call_history_from (&current_target, begin, size, flags);
+  target_resume (ptid, 0, signal);
 }
 
-/* See target.h.  */
-
-void
-target_call_history_range (ULONGEST begin, ULONGEST end, int flags)
-{
-  current_target.to_call_history_range (&current_target, begin, end, flags);
-}
+/* Concatenate ELEM to LIST, a comma-separated list.  */
 
 static void
-debug_to_prepare_to_store (struct target_ops *self, struct regcache *regcache)
-{
-  debug_target.to_prepare_to_store (&debug_target, regcache);
-
-  fprintf_unfiltered (gdb_stdlog, "target_prepare_to_store ()\n");
-}
-
-/* See target.h.  */
-
-const struct frame_unwind *
-target_get_unwinder (void)
-{
-  return current_target.to_get_unwinder (&current_target);
-}
-
-/* See target.h.  */
-
-const struct frame_unwind *
-target_get_tailcall_unwinder (void)
+str_comma_list_concat_elem (std::string *list, const char *elem)
 {
-  return current_target.to_get_tailcall_unwinder (&current_target);
-}
-
-/* Default implementation of to_decr_pc_after_break.  */
+  if (!list->empty ())
+    list->append (", ");
 
-static CORE_ADDR
-default_target_decr_pc_after_break (struct target_ops *ops,
-                                   struct gdbarch *gdbarch)
-{
-  return gdbarch_decr_pc_after_break (gdbarch);
+  list->append (elem);
 }
 
-/* See target.h.  */
-
-CORE_ADDR
-target_decr_pc_after_break (struct gdbarch *gdbarch)
-{
-  return current_target.to_decr_pc_after_break (&current_target, gdbarch);
-}
+/* Helper for target_options_to_string.  If OPT is present in
+   TARGET_OPTIONS, append the OPT_STR (string version of OPT) in RET.
+   OPT is removed from TARGET_OPTIONS.  */
 
 static void
-debug_to_files_info (struct target_ops *target)
-{
-  debug_target.to_files_info (target);
-
-  fprintf_unfiltered (gdb_stdlog, "target_files_info (xxx)\n");
-}
-
-static int
-debug_to_insert_breakpoint (struct target_ops *ops, struct gdbarch *gdbarch,
-                           struct bp_target_info *bp_tgt)
-{
-  int retval;
-
-  retval = debug_target.to_insert_breakpoint (&debug_target, gdbarch, bp_tgt);
-
-  fprintf_unfiltered (gdb_stdlog,
-                     "target_insert_breakpoint (%s, xxx) = %ld\n",
-                     core_addr_to_string (bp_tgt->placed_address),
-                     (unsigned long) retval);
-  return retval;
-}
-
-static int
-debug_to_remove_breakpoint (struct target_ops *ops, struct gdbarch *gdbarch,
-                           struct bp_target_info *bp_tgt)
+do_option (int *target_options, std::string *ret,
+          int opt, const char *opt_str)
 {
-  int retval;
-
-  retval = debug_target.to_remove_breakpoint (&debug_target, gdbarch, bp_tgt);
-
-  fprintf_unfiltered (gdb_stdlog,
-                     "target_remove_breakpoint (%s, xxx) = %ld\n",
-                     core_addr_to_string (bp_tgt->placed_address),
-                     (unsigned long) retval);
-  return retval;
+  if ((*target_options & opt) != 0)
+    {
+      str_comma_list_concat_elem (ret, opt_str);
+      *target_options &= ~opt;
+    }
 }
 
-static int
-debug_to_can_use_hw_breakpoint (struct target_ops *self,
-                               int type, int cnt, int from_tty)
-{
-  int retval;
-
-  retval = debug_target.to_can_use_hw_breakpoint (&debug_target,
-                                                 type, cnt, from_tty);
-
-  fprintf_unfiltered (gdb_stdlog,
-                     "target_can_use_hw_breakpoint (%ld, %ld, %ld) = %ld\n",
-                     (unsigned long) type,
-                     (unsigned long) cnt,
-                     (unsigned long) from_tty,
-                     (unsigned long) retval);
-  return retval;
-}
+/* See target.h.  */
 
-static int
-debug_to_region_ok_for_hw_watchpoint (struct target_ops *self,
-                                     CORE_ADDR addr, int len)
+std::string
+target_options_to_string (int target_options)
 {
-  CORE_ADDR retval;
+  std::string ret;
 
-  retval = debug_target.to_region_ok_for_hw_watchpoint (&debug_target,
-                                                       addr, len);
-
-  fprintf_unfiltered (gdb_stdlog,
-                     "target_region_ok_for_hw_watchpoint (%s, %ld) = %s\n",
-                     core_addr_to_string (addr), (unsigned long) len,
-                     core_addr_to_string (retval));
-  return retval;
-}
+#define DO_TARG_OPTION(OPT) \
+  do_option (&target_options, &ret, OPT, #OPT)
 
-static int
-debug_to_can_accel_watchpoint_condition (struct target_ops *self,
-                                        CORE_ADDR addr, int len, int rw,
-                                        struct expression *cond)
-{
-  int retval;
+  DO_TARG_OPTION (TARGET_WNOHANG);
 
-  retval = debug_target.to_can_accel_watchpoint_condition (&debug_target,
-                                                          addr, len,
-                                                          rw, cond);
+  if (target_options != 0)
+    str_comma_list_concat_elem (&ret, "unknown???");
 
-  fprintf_unfiltered (gdb_stdlog,
-                     "target_can_accel_watchpoint_condition "
-                     "(%s, %d, %d, %s) = %ld\n",
-                     core_addr_to_string (addr), len, rw,
-                     host_address_to_string (cond), (unsigned long) retval);
-  return retval;
+  return ret;
 }
 
-static int
-debug_to_stopped_by_watchpoint (struct target_ops *ops)
+void
+target_fetch_registers (struct regcache *regcache, int regno)
 {
-  int retval;
-
-  retval = debug_target.to_stopped_by_watchpoint (&debug_target);
-
-  fprintf_unfiltered (gdb_stdlog,
-                     "target_stopped_by_watchpoint () = %ld\n",
-                     (unsigned long) retval);
-  return retval;
+  current_top_target ()->fetch_registers (regcache, regno);
+  if (targetdebug)
+    regcache->debug_print_register ("target_fetch_registers", regno);
 }
 
-static int
-debug_to_stopped_data_address (struct target_ops *target, CORE_ADDR *addr)
+void
+target_store_registers (struct regcache *regcache, int regno)
 {
-  int retval;
-
-  retval = debug_target.to_stopped_data_address (target, addr);
+  if (!may_write_registers)
+    error (_("Writing to registers is not allowed (regno %d)"), regno);
 
-  fprintf_unfiltered (gdb_stdlog,
-                     "target_stopped_data_address ([%s]) = %ld\n",
-                     core_addr_to_string (*addr),
-                     (unsigned long)retval);
-  return retval;
+  current_top_target ()->store_registers (regcache, regno);
+  if (targetdebug)
+    {
+      regcache->debug_print_register ("target_store_registers", regno);
+    }
 }
 
-static int
-debug_to_watchpoint_addr_within_range (struct target_ops *target,
-                                      CORE_ADDR addr,
-                                      CORE_ADDR start, int length)
+int
+target_core_of_thread (ptid_t ptid)
 {
-  int retval;
-
-  retval = debug_target.to_watchpoint_addr_within_range (target, addr,
-                                                        start, length);
-
-  fprintf_filtered (gdb_stdlog,
-                   "target_watchpoint_addr_within_range (%s, %s, %d) = %d\n",
-                   core_addr_to_string (addr), core_addr_to_string (start),
-                   length, retval);
-  return retval;
+  return current_top_target ()->core_of_thread (ptid);
 }
 
-static int
-debug_to_insert_hw_breakpoint (struct target_ops *self,
-                              struct gdbarch *gdbarch,
-                              struct bp_target_info *bp_tgt)
+int
+simple_verify_memory (struct target_ops *ops,
+                     const gdb_byte *data, CORE_ADDR lma, ULONGEST size)
 {
-  int retval;
+  LONGEST total_xfered = 0;
 
-  retval = debug_target.to_insert_hw_breakpoint (&debug_target,
-                                                gdbarch, bp_tgt);
+  while (total_xfered < size)
+    {
+      ULONGEST xfered_len;
+      enum target_xfer_status status;
+      gdb_byte buf[1024];
+      ULONGEST howmuch = std::min<ULONGEST> (sizeof (buf), size - total_xfered);
 
-  fprintf_unfiltered (gdb_stdlog,
-                     "target_insert_hw_breakpoint (%s, xxx) = %ld\n",
-                     core_addr_to_string (bp_tgt->placed_address),
-                     (unsigned long) retval);
-  return retval;
+      status = target_xfer_partial (ops, TARGET_OBJECT_MEMORY, NULL,
+                                   buf, NULL, lma + total_xfered, howmuch,
+                                   &xfered_len);
+      if (status == TARGET_XFER_OK
+         && memcmp (data + total_xfered, buf, xfered_len) == 0)
+       {
+         total_xfered += xfered_len;
+         QUIT;
+       }
+      else
+       return 0;
+    }
+  return 1;
 }
 
-static int
-debug_to_remove_hw_breakpoint (struct target_ops *self,
-                              struct gdbarch *gdbarch,
-                              struct bp_target_info *bp_tgt)
-{
-  int retval;
-
-  retval = debug_target.to_remove_hw_breakpoint (&debug_target,
-                                                gdbarch, bp_tgt);
-
-  fprintf_unfiltered (gdb_stdlog,
-                     "target_remove_hw_breakpoint (%s, xxx) = %ld\n",
-                     core_addr_to_string (bp_tgt->placed_address),
-                     (unsigned long) retval);
-  return retval;
-}
+/* Default implementation of memory verification.  */
 
 static int
-debug_to_insert_watchpoint (struct target_ops *self,
-                           CORE_ADDR addr, int len, int type,
-                           struct expression *cond)
+default_verify_memory (struct target_ops *self,
+                      const gdb_byte *data, CORE_ADDR memaddr, ULONGEST size)
 {
-  int retval;
-
-  retval = debug_target.to_insert_watchpoint (&debug_target,
-                                             addr, len, type, cond);
-
-  fprintf_unfiltered (gdb_stdlog,
-                     "target_insert_watchpoint (%s, %d, %d, %s) = %ld\n",
-                     core_addr_to_string (addr), len, type,
-                     host_address_to_string (cond), (unsigned long) retval);
-  return retval;
+  /* Start over from the top of the target stack.  */
+  return simple_verify_memory (current_top_target (),
+                              data, memaddr, size);
 }
 
-static int
-debug_to_remove_watchpoint (struct target_ops *self,
-                           CORE_ADDR addr, int len, int type,
-                           struct expression *cond)
+int
+target_verify_memory (const gdb_byte *data, CORE_ADDR memaddr, ULONGEST size)
 {
-  int retval;
-
-  retval = debug_target.to_remove_watchpoint (&debug_target,
-                                             addr, len, type, cond);
-
-  fprintf_unfiltered (gdb_stdlog,
-                     "target_remove_watchpoint (%s, %d, %d, %s) = %ld\n",
-                     core_addr_to_string (addr), len, type,
-                     host_address_to_string (cond), (unsigned long) retval);
-  return retval;
+  return current_top_target ()->verify_memory (data, memaddr, size);
 }
 
-static void
-debug_to_terminal_init (struct target_ops *self)
-{
-  debug_target.to_terminal_init (&debug_target);
+/* The documentation for this function is in its prototype declaration in
+   target.h.  */
 
-  fprintf_unfiltered (gdb_stdlog, "target_terminal_init ()\n");
+int
+target_insert_mask_watchpoint (CORE_ADDR addr, CORE_ADDR mask,
+                              enum target_hw_bp_type rw)
+{
+  return current_top_target ()->insert_mask_watchpoint (addr, mask, rw);
 }
 
-static void
-debug_to_terminal_inferior (struct target_ops *self)
-{
-  debug_target.to_terminal_inferior (&debug_target);
+/* The documentation for this function is in its prototype declaration in
+   target.h.  */
 
-  fprintf_unfiltered (gdb_stdlog, "target_terminal_inferior ()\n");
+int
+target_remove_mask_watchpoint (CORE_ADDR addr, CORE_ADDR mask,
+                              enum target_hw_bp_type rw)
+{
+  return current_top_target ()->remove_mask_watchpoint (addr, mask, rw);
 }
 
-static void
-debug_to_terminal_ours_for_output (struct target_ops *self)
-{
-  debug_target.to_terminal_ours_for_output (&debug_target);
+/* The documentation for this function is in its prototype declaration
+   in target.h.  */
 
-  fprintf_unfiltered (gdb_stdlog, "target_terminal_ours_for_output ()\n");
+int
+target_masked_watch_num_registers (CORE_ADDR addr, CORE_ADDR mask)
+{
+  return current_top_target ()->masked_watch_num_registers (addr, mask);
 }
 
-static void
-debug_to_terminal_ours (struct target_ops *self)
-{
-  debug_target.to_terminal_ours (&debug_target);
+/* The documentation for this function is in its prototype declaration
+   in target.h.  */
 
-  fprintf_unfiltered (gdb_stdlog, "target_terminal_ours ()\n");
+int
+target_ranged_break_num_registers (void)
+{
+  return current_top_target ()->ranged_break_num_registers ();
 }
 
-static void
-debug_to_terminal_save_ours (struct target_ops *self)
-{
-  debug_target.to_terminal_save_ours (&debug_target);
+/* See target.h.  */
 
-  fprintf_unfiltered (gdb_stdlog, "target_terminal_save_ours ()\n");
+struct btrace_target_info *
+target_enable_btrace (ptid_t ptid, const struct btrace_config *conf)
+{
+  return current_top_target ()->enable_btrace (ptid, conf);
 }
 
-static void
-debug_to_terminal_info (struct target_ops *self,
-                       const char *arg, int from_tty)
-{
-  debug_target.to_terminal_info (&debug_target, arg, from_tty);
+/* See target.h.  */
 
-  fprintf_unfiltered (gdb_stdlog, "target_terminal_info (%s, %d)\n", arg,
-                     from_tty);
+void
+target_disable_btrace (struct btrace_target_info *btinfo)
+{
+  current_top_target ()->disable_btrace (btinfo);
 }
 
-static void
-debug_to_load (struct target_ops *self, char *args, int from_tty)
-{
-  debug_target.to_load (&debug_target, args, from_tty);
+/* See target.h.  */
 
-  fprintf_unfiltered (gdb_stdlog, "target_load (%s, %d)\n", args, from_tty);
+void
+target_teardown_btrace (struct btrace_target_info *btinfo)
+{
+  current_top_target ()->teardown_btrace (btinfo);
 }
 
-static void
-debug_to_post_startup_inferior (struct target_ops *self, ptid_t ptid)
-{
-  debug_target.to_post_startup_inferior (&debug_target, ptid);
+/* See target.h.  */
 
-  fprintf_unfiltered (gdb_stdlog, "target_post_startup_inferior (%d)\n",
-                     ptid_get_pid (ptid));
+enum btrace_error
+target_read_btrace (struct btrace_data *btrace,
+                   struct btrace_target_info *btinfo,
+                   enum btrace_read_type type)
+{
+  return current_top_target ()->read_btrace (btrace, btinfo, type);
 }
 
-static int
-debug_to_insert_fork_catchpoint (struct target_ops *self, int pid)
-{
-  int retval;
+/* See target.h.  */
 
-  retval = debug_target.to_insert_fork_catchpoint (&debug_target, pid);
+const struct btrace_config *
+target_btrace_conf (const struct btrace_target_info *btinfo)
+{
+  return current_top_target ()->btrace_conf (btinfo);
+}
 
-  fprintf_unfiltered (gdb_stdlog, "target_insert_fork_catchpoint (%d) = %d\n",
-                     pid, retval);
+/* See target.h.  */
 
-  return retval;
+void
+target_stop_recording (void)
+{
+  current_top_target ()->stop_recording ();
 }
 
-static int
-debug_to_remove_fork_catchpoint (struct target_ops *self, int pid)
-{
-  int retval;
+/* See target.h.  */
 
-  retval = debug_target.to_remove_fork_catchpoint (&debug_target, pid);
+void
+target_save_record (const char *filename)
+{
+  current_top_target ()->save_record (filename);
+}
 
-  fprintf_unfiltered (gdb_stdlog, "target_remove_fork_catchpoint (%d) = %d\n",
-                     pid, retval);
+/* See target.h.  */
 
-  return retval;
+int
+target_supports_delete_record ()
+{
+  return current_top_target ()->supports_delete_record ();
 }
 
-static int
-debug_to_insert_vfork_catchpoint (struct target_ops *self, int pid)
-{
-  int retval;
+/* See target.h.  */
 
-  retval = debug_target.to_insert_vfork_catchpoint (&debug_target, pid);
+void
+target_delete_record (void)
+{
+  current_top_target ()->delete_record ();
+}
 
-  fprintf_unfiltered (gdb_stdlog, "target_insert_vfork_catchpoint (%d) = %d\n",
-                     pid, retval);
+/* See target.h.  */
 
-  return retval;
+enum record_method
+target_record_method (ptid_t ptid)
+{
+  return current_top_target ()->record_method (ptid);
 }
 
-static int
-debug_to_remove_vfork_catchpoint (struct target_ops *self, int pid)
-{
-  int retval;
+/* See target.h.  */
 
-  retval = debug_target.to_remove_vfork_catchpoint (&debug_target, pid);
+int
+target_record_is_replaying (ptid_t ptid)
+{
+  return current_top_target ()->record_is_replaying (ptid);
+}
 
-  fprintf_unfiltered (gdb_stdlog, "target_remove_vfork_catchpoint (%d) = %d\n",
-                     pid, retval);
+/* See target.h.  */
 
-  return retval;
+int
+target_record_will_replay (ptid_t ptid, int dir)
+{
+  return current_top_target ()->record_will_replay (ptid, dir);
 }
 
-static int
-debug_to_insert_exec_catchpoint (struct target_ops *self, int pid)
-{
-  int retval;
+/* See target.h.  */
 
-  retval = debug_target.to_insert_exec_catchpoint (&debug_target, pid);
+void
+target_record_stop_replaying (void)
+{
+  current_top_target ()->record_stop_replaying ();
+}
 
-  fprintf_unfiltered (gdb_stdlog, "target_insert_exec_catchpoint (%d) = %d\n",
-                     pid, retval);
+/* See target.h.  */
 
-  return retval;
+void
+target_goto_record_begin (void)
+{
+  current_top_target ()->goto_record_begin ();
 }
 
-static int
-debug_to_remove_exec_catchpoint (struct target_ops *self, int pid)
-{
-  int retval;
+/* See target.h.  */
 
-  retval = debug_target.to_remove_exec_catchpoint (&debug_target, pid);
+void
+target_goto_record_end (void)
+{
+  current_top_target ()->goto_record_end ();
+}
 
-  fprintf_unfiltered (gdb_stdlog, "target_remove_exec_catchpoint (%d) = %d\n",
-                     pid, retval);
+/* See target.h.  */
 
-  return retval;
+void
+target_goto_record (ULONGEST insn)
+{
+  current_top_target ()->goto_record (insn);
 }
 
-static int
-debug_to_has_exited (struct target_ops *self,
-                    int pid, int wait_status, int *exit_status)
-{
-  int has_exited;
+/* See target.h.  */
 
-  has_exited = debug_target.to_has_exited (&debug_target,
-                                          pid, wait_status, exit_status);
+void
+target_insn_history (int size, gdb_disassembly_flags flags)
+{
+  current_top_target ()->insn_history (size, flags);
+}
 
-  fprintf_unfiltered (gdb_stdlog, "target_has_exited (%d, %d, %d) = %d\n",
-                     pid, wait_status, *exit_status, has_exited);
+/* See target.h.  */
 
-  return has_exited;
+void
+target_insn_history_from (ULONGEST from, int size,
+                         gdb_disassembly_flags flags)
+{
+  current_top_target ()->insn_history_from (from, size, flags);
 }
 
-static int
-debug_to_can_run (struct target_ops *self)
-{
-  int retval;
+/* See target.h.  */
 
-  retval = debug_target.to_can_run (&debug_target);
+void
+target_insn_history_range (ULONGEST begin, ULONGEST end,
+                          gdb_disassembly_flags flags)
+{
+  current_top_target ()->insn_history_range (begin, end, flags);
+}
 
-  fprintf_unfiltered (gdb_stdlog, "target_can_run () = %d\n", retval);
+/* See target.h.  */
 
-  return retval;
+void
+target_call_history (int size, record_print_flags flags)
+{
+  current_top_target ()->call_history (size, flags);
 }
 
-static struct gdbarch *
-debug_to_thread_architecture (struct target_ops *ops, ptid_t ptid)
+/* See target.h.  */
+
+void
+target_call_history_from (ULONGEST begin, int size, record_print_flags flags)
 {
-  struct gdbarch *retval;
+  current_top_target ()->call_history_from (begin, size, flags);
+}
 
-  retval = debug_target.to_thread_architecture (ops, ptid);
+/* See target.h.  */
 
-  fprintf_unfiltered (gdb_stdlog, 
-                     "target_thread_architecture (%s) = %s [%s]\n",
-                     target_pid_to_str (ptid),
-                     host_address_to_string (retval),
-                     gdbarch_bfd_arch_info (retval)->printable_name);
-  return retval;
+void
+target_call_history_range (ULONGEST begin, ULONGEST end, record_print_flags flags)
+{
+  current_top_target ()->call_history_range (begin, end, flags);
 }
 
-static void
-debug_to_stop (struct target_ops *self, ptid_t ptid)
-{
-  debug_target.to_stop (&debug_target, ptid);
+/* See target.h.  */
 
-  fprintf_unfiltered (gdb_stdlog, "target_stop (%s)\n",
-                     target_pid_to_str (ptid));
+const struct frame_unwind *
+target_get_unwinder (void)
+{
+  return current_top_target ()->get_unwinder ();
 }
 
-static void
-debug_to_rcmd (struct target_ops *self, const char *command,
-              struct ui_file *outbuf)
+/* See target.h.  */
+
+const struct frame_unwind *
+target_get_tailcall_unwinder (void)
 {
-  debug_target.to_rcmd (&debug_target, command, outbuf);
-  fprintf_unfiltered (gdb_stdlog, "target_rcmd (%s, ...)\n", command);
+  return current_top_target ()->get_tailcall_unwinder ();
 }
 
-static char *
-debug_to_pid_to_exec_file (struct target_ops *self, int pid)
-{
-  char *exec_file;
+/* See target.h.  */
 
-  exec_file = debug_target.to_pid_to_exec_file (&debug_target, pid);
+void
+target_prepare_to_generate_core (void)
+{
+  current_top_target ()->prepare_to_generate_core ();
+}
 
-  fprintf_unfiltered (gdb_stdlog, "target_pid_to_exec_file (%d) = %s\n",
-                     pid, exec_file);
+/* See target.h.  */
 
-  return exec_file;
+void
+target_done_generating_core (void)
+{
+  current_top_target ()->done_generating_core ();
 }
 
-static void
-setup_target_debug (void)
-{
-  memcpy (&debug_target, &current_target, sizeof debug_target);
-
-  current_target.to_open = debug_to_open;
-  current_target.to_post_attach = debug_to_post_attach;
-  current_target.to_prepare_to_store = debug_to_prepare_to_store;
-  current_target.to_files_info = debug_to_files_info;
-  current_target.to_insert_breakpoint = debug_to_insert_breakpoint;
-  current_target.to_remove_breakpoint = debug_to_remove_breakpoint;
-  current_target.to_can_use_hw_breakpoint = debug_to_can_use_hw_breakpoint;
-  current_target.to_insert_hw_breakpoint = debug_to_insert_hw_breakpoint;
-  current_target.to_remove_hw_breakpoint = debug_to_remove_hw_breakpoint;
-  current_target.to_insert_watchpoint = debug_to_insert_watchpoint;
-  current_target.to_remove_watchpoint = debug_to_remove_watchpoint;
-  current_target.to_stopped_by_watchpoint = debug_to_stopped_by_watchpoint;
-  current_target.to_stopped_data_address = debug_to_stopped_data_address;
-  current_target.to_watchpoint_addr_within_range
-    = debug_to_watchpoint_addr_within_range;
-  current_target.to_region_ok_for_hw_watchpoint
-    = debug_to_region_ok_for_hw_watchpoint;
-  current_target.to_can_accel_watchpoint_condition
-    = debug_to_can_accel_watchpoint_condition;
-  current_target.to_terminal_init = debug_to_terminal_init;
-  current_target.to_terminal_inferior = debug_to_terminal_inferior;
-  current_target.to_terminal_ours_for_output
-    = debug_to_terminal_ours_for_output;
-  current_target.to_terminal_ours = debug_to_terminal_ours;
-  current_target.to_terminal_save_ours = debug_to_terminal_save_ours;
-  current_target.to_terminal_info = debug_to_terminal_info;
-  current_target.to_load = debug_to_load;
-  current_target.to_post_startup_inferior = debug_to_post_startup_inferior;
-  current_target.to_insert_fork_catchpoint = debug_to_insert_fork_catchpoint;
-  current_target.to_remove_fork_catchpoint = debug_to_remove_fork_catchpoint;
-  current_target.to_insert_vfork_catchpoint = debug_to_insert_vfork_catchpoint;
-  current_target.to_remove_vfork_catchpoint = debug_to_remove_vfork_catchpoint;
-  current_target.to_insert_exec_catchpoint = debug_to_insert_exec_catchpoint;
-  current_target.to_remove_exec_catchpoint = debug_to_remove_exec_catchpoint;
-  current_target.to_has_exited = debug_to_has_exited;
-  current_target.to_can_run = debug_to_can_run;
-  current_target.to_stop = debug_to_stop;
-  current_target.to_rcmd = debug_to_rcmd;
-  current_target.to_pid_to_exec_file = debug_to_pid_to_exec_file;
-  current_target.to_thread_architecture = debug_to_thread_architecture;
-}
 \f
 
 static char targ_desc[] =
@@ -4087,37 +3773,91 @@ default_rcmd (struct target_ops *self, const char *command,
 }
 
 static void
-do_monitor_command (char *cmd,
-                int from_tty)
+do_monitor_command (const char *cmd, int from_tty)
 {
   target_rcmd (cmd, gdb_stdtarg);
 }
 
+/* Erases all the memory regions marked as flash.  CMD and FROM_TTY are
+   ignored.  */
+
+void
+flash_erase_command (const char *cmd, int from_tty)
+{
+  /* Used to communicate termination of flash operations to the target.  */
+  bool found_flash_region = false;
+  struct gdbarch *gdbarch = target_gdbarch ();
+
+  std::vector<mem_region> mem_regions = target_memory_map ();
+
+  /* Iterate over all memory regions.  */
+  for (const mem_region &m : mem_regions)
+    {
+      /* Is this a flash memory region?  */
+      if (m.attrib.mode == MEM_FLASH)
+        {
+          found_flash_region = true;
+          target_flash_erase (m.lo, m.hi - m.lo);
+
+         ui_out_emit_tuple tuple_emitter (current_uiout, "erased-regions");
+
+          current_uiout->message (_("Erasing flash memory region at address "));
+          current_uiout->field_core_addr ("address", gdbarch, m.lo);
+          current_uiout->message (", size = ");
+          current_uiout->field_string ("size", hex_string (m.hi - m.lo));
+          current_uiout->message ("\n");
+        }
+    }
+
+  /* Did we do any flash operations?  If so, we need to finalize them.  */
+  if (found_flash_region)
+    target_flash_done ();
+  else
+    current_uiout->message (_("No flash memory regions found.\n"));
+}
+
 /* Print the name of each layers of our target stack.  */
 
 static void
-maintenance_print_target_stack (char *cmd, int from_tty)
+maintenance_print_target_stack (const char *cmd, int from_tty)
 {
-  struct target_ops *t;
-
   printf_filtered (_("The current target stack is:\n"));
 
-  for (t = target_stack; t != NULL; t = t->beneath)
+  for (target_ops *t = current_top_target (); t != NULL; t = t->beneath ())
     {
-      printf_filtered ("  - %s (%s)\n", t->to_shortname, t->to_longname);
+      if (t->stratum () == debug_stratum)
+       continue;
+      printf_filtered ("  - %s (%s)\n", t->shortname (), t->longname ());
     }
 }
 
+/* See target.h.  */
+
+void
+target_async (int enable)
+{
+  infrun_async (enable);
+  current_top_target ()->async (enable);
+}
+
+/* See target.h.  */
+
+void
+target_thread_events (int enable)
+{
+  current_top_target ()->thread_events (enable);
+}
+
 /* Controls if targets can report that they can/are async.  This is
    just for maintainers to use when debugging gdb.  */
-int target_async_permitted = 1;
+bool target_async_permitted = true;
 
 /* The set command writes to this variable.  If the inferior is
    executing, target_async_permitted is *not* updated.  */
-static int target_async_permitted_1 = 1;
+static bool target_async_permitted_1 = true;
 
 static void
-maint_set_target_async_command (char *args, int from_tty,
+maint_set_target_async_command (const char *args, int from_tty,
                                struct cmd_list_element *c)
 {
   if (have_live_inferiors ())
@@ -4139,14 +3879,95 @@ maint_show_target_async_command (struct ui_file *file, int from_tty,
                      "asynchronous mode is %s.\n"), value);
 }
 
+/* Return true if the target operates in non-stop mode even with "set
+   non-stop off".  */
+
+static int
+target_always_non_stop_p (void)
+{
+  return current_top_target ()->always_non_stop_p ();
+}
+
+/* See target.h.  */
+
+int
+target_is_non_stop_p (void)
+{
+  return (non_stop
+         || target_non_stop_enabled == AUTO_BOOLEAN_TRUE
+         || (target_non_stop_enabled == AUTO_BOOLEAN_AUTO
+             && target_always_non_stop_p ()));
+}
+
+/* See target.h.  */
+
+bool
+exists_non_stop_target ()
+{
+  if (target_is_non_stop_p ())
+    return true;
+
+  scoped_restore_current_thread restore_thread;
+
+  for (inferior *inf : all_inferiors ())
+    {
+      switch_to_inferior_no_thread (inf);
+      if (target_is_non_stop_p ())
+       return true;
+    }
+
+  return false;
+}
+
+/* Controls if targets can report that they always run in non-stop
+   mode.  This is just for maintainers to use when debugging gdb.  */
+enum auto_boolean target_non_stop_enabled = AUTO_BOOLEAN_AUTO;
+
+/* The set command writes to this variable.  If the inferior is
+   executing, target_non_stop_enabled is *not* updated.  */
+static enum auto_boolean target_non_stop_enabled_1 = AUTO_BOOLEAN_AUTO;
+
+/* Implementation of "maint set target-non-stop".  */
+
+static void
+maint_set_target_non_stop_command (const char *args, int from_tty,
+                                  struct cmd_list_element *c)
+{
+  if (have_live_inferiors ())
+    {
+      target_non_stop_enabled_1 = target_non_stop_enabled;
+      error (_("Cannot change this setting while the inferior is running."));
+    }
+
+  target_non_stop_enabled = target_non_stop_enabled_1;
+}
+
+/* Implementation of "maint show target-non-stop".  */
+
+static void
+maint_show_target_non_stop_command (struct ui_file *file, int from_tty,
+                                   struct cmd_list_element *c,
+                                   const char *value)
+{
+  if (target_non_stop_enabled == AUTO_BOOLEAN_AUTO)
+    fprintf_filtered (file,
+                     _("Whether the target is always in non-stop mode "
+                       "is %s (currently %s).\n"), value,
+                     target_always_non_stop_p () ? "on" : "off");
+  else
+    fprintf_filtered (file,
+                     _("Whether the target is always in non-stop mode "
+                       "is %s.\n"), value);
+}
+
 /* Temporary copies of permission settings.  */
 
-static int may_write_registers_1 = 1;
-static int may_write_memory_1 = 1;
-static int may_insert_breakpoints_1 = 1;
-static int may_insert_tracepoints_1 = 1;
-static int may_insert_fast_tracepoints_1 = 1;
-static int may_stop_1 = 1;
+static bool may_write_registers_1 = true;
+static bool may_write_memory_1 = true;
+static bool may_insert_breakpoints_1 = true;
+static bool may_insert_tracepoints_1 = true;
+static bool may_insert_fast_tracepoints_1 = true;
+static bool may_stop_1 = true;
 
 /* Make the user-set values match the real values again.  */
 
@@ -4165,7 +3986,7 @@ update_target_permissions (void)
    way.  */
 
 static void
-set_target_permissions (char *args, int from_tty,
+set_target_permissions (const char *args, int from_tty,
                        struct cmd_list_element *c)
 {
   if (target_has_execution)
@@ -4186,7 +4007,7 @@ set_target_permissions (char *args, int from_tty,
 /* Set memory write permission independently of observer mode.  */
 
 static void
-set_write_memory_permission (char *args, int from_tty,
+set_write_memory_permission (const char *args, int from_tty,
                        struct cmd_list_element *c)
 {
   /* Make the real values match the user-changed values.  */
@@ -4194,23 +4015,22 @@ set_write_memory_permission (char *args, int from_tty,
   update_observer_mode ();
 }
 
+void _initialize_target ();
 
 void
-initialize_targets (void)
+_initialize_target ()
 {
-  init_dummy_target ();
-  push_target (&dummy_target);
+  the_debug_target = new debug_target ();
 
-  add_info ("target", target_info, targ_desc);
-  add_info ("files", target_info, targ_desc);
+  add_info ("target", info_target_command, targ_desc);
+  add_info ("files", info_target_command, targ_desc);
 
   add_setshow_zuinteger_cmd ("target", class_maintenance, &targetdebug, _("\
 Set target debugging."), _("\
 Show target debugging."), _("\
 When non-zero, target debugging is enabled.  Higher numbers are more\n\
-verbose.  Changes do not take effect until the next \"run\" or \"target\"\n\
-command."),
-                            NULL,
+verbose."),
+                            set_targetdebug,
                             show_targetdebug,
                             &setdebuglist, &showdebuglist);
 
@@ -4242,6 +4062,16 @@ Tells gdb whether to control the inferior in asynchronous mode."),
                           &maintenance_set_cmdlist,
                           &maintenance_show_cmdlist);
 
+  add_setshow_auto_boolean_cmd ("target-non-stop", no_class,
+                               &target_non_stop_enabled_1, _("\
+Set whether gdb always controls the inferior in non-stop mode."), _("\
+Show whether gdb always controls the inferior in non-stop mode."), _("\
+Tells gdb whether to control the inferior in non-stop mode."),
+                          maint_set_target_non_stop_command,
+                          maint_show_target_non_stop_command,
+                          &maintenance_set_cmdlist,
+                          &maintenance_show_cmdlist);
+
   add_setshow_boolean_cmd ("may-write-registers", class_support,
                           &may_write_registers_1, _("\
 Set permission to write into registers."), _("\
@@ -4296,6 +4126,9 @@ Otherwise, any attempt to interrupt or stop will be ignored."),
                           set_target_permissions, NULL,
                           &setlist, &showlist);
 
+  add_com ("flash-erase", no_class, flash_erase_command,
+           _("Erase all flash memory regions."));
+
   add_setshow_boolean_cmd ("auto-connect-native-target", class_support,
                           &auto_connect_native_target, _("\
 Set whether GDB may automatically connect to the native target."), _("\
This page took 0.088818 seconds and 4 git commands to generate.