gdb/MAINTAINERS: add Luis Machado as global maintainer
[binutils-gdb.git] / gdb / remote-sim.c
index aed7a34b42c5498098869b2f7f266cdabf7119c2..518f7c9c5cde2a816718f4c0147e5cd2c3a8e508 100644 (file)
@@ -1,6 +1,6 @@
 /* Generic remote debugging interface for simulators.
 
-   Copyright (C) 1993-2018 Free Software Foundation, Inc.
+   Copyright (C) 1993-2023 Free Software Foundation, Inc.
 
    Contributed by Cygnus Support.
    Steve Chamberlain (sac@cygnus.com).
 #include <setjmp.h>
 #include "terminal.h"
 #include "target.h"
+#include "process-stratum-target.h"
 #include "gdbcore.h"
-#include "gdb/callback.h"
-#include "gdb/remote-sim.h"
+#include "sim/callback.h"
+#include "sim/sim.h"
 #include "command.h"
 #include "regcache.h"
 #include "sim-regno.h"
 #include "arch-utils.h"
 #include "readline/readline.h"
 #include "gdbthread.h"
-#include "common/byte-vector.h"
+#include "gdbsupport/byte-vector.h"
+#include "memory-map.h"
+#include "remote.h"
+#include "gdbsupport/buildargv.h"
 
 /* Prototypes */
 
@@ -58,7 +62,7 @@ static void gdb_os_flush_stderr (host_callback *);
 
 static int gdb_os_poll_quit (host_callback *);
 
-/* printf_filtered is depreciated.  */
+/* gdb_printf is depreciated.  */
 static void gdb_os_printf_filtered (host_callback *, const char *, ...);
 
 static void gdb_os_vprintf_filtered (host_callback *, const char *, va_list);
@@ -68,42 +72,31 @@ static void gdb_os_evprintf_filtered (host_callback *, const char *, va_list);
 static void gdb_os_error (host_callback *, const char *, ...)
      ATTRIBUTE_NORETURN;
 
-static void gdbsim_kill (struct target_ops *);
-
-static void gdbsim_load (struct target_ops *self, const char *prog,
-                        int fromtty);
-
-static void gdbsim_open (const char *args, int from_tty);
-
-static void gdbsim_close (struct target_ops *self);
-
-static void gdbsim_detach (struct target_ops *ops, inferior *inf, int from_tty);
-
-static void gdbsim_prepare_to_store (struct target_ops *self,
-                                    struct regcache *regcache);
-
-static void gdbsim_files_info (struct target_ops *target);
-
-static void gdbsim_mourn_inferior (struct target_ops *target);
-
-static void gdbsim_interrupt (struct target_ops *self, ptid_t ptid);
-
-void simulator_command (char *args, int from_tty);
-
 /* Naming convention:
 
    sim_* are the interface to the simulator (see remote-sim.h).
    gdbsim_* are stuff which is internal to gdb.  */
 
-/* Forward data declarations */
-extern struct target_ops gdbsim_ops;
-
-static const struct inferior_data *sim_inferior_data_key;
+/* Value of the next pid to allocate for an inferior.  As indicated
+   elsewhere, its initial value is somewhat arbitrary; it's critical
+   though that it's not zero or negative.  */
+static int next_pid;
+#define INITIAL_PID 42000
 
 /* Simulator-specific, per-inferior state.  */
 struct sim_inferior_data {
+  explicit sim_inferior_data (SIM_DESC desc)
+    : gdbsim_desc (desc),
+      remote_sim_ptid (next_pid, 0, next_pid)
+  {
+    gdb_assert (remote_sim_ptid != null_ptid);
+    ++next_pid;
+  }
+
+  ~sim_inferior_data ();
+
   /* Flag which indicates whether or not the program has been loaded.  */
-  int program_loaded;
+  bool program_loaded = false;
 
   /* Simulator descriptor for this inferior.  */
   SIM_DESC gdbsim_desc;
@@ -116,21 +109,80 @@ struct sim_inferior_data {
   ptid_t remote_sim_ptid;
 
   /* Signal with which to resume.  */
-  enum gdb_signal resume_siggnal;
+  enum gdb_signal resume_siggnal = GDB_SIGNAL_0;
 
   /* Flag which indicates whether resume should step or not.  */
-  int resume_step;
+  bool resume_step = false;
 };
 
-/* Flag indicating the "open" status of this module.  It's set to 1
-   in gdbsim_open() and 0 in gdbsim_close().  */
-static int gdbsim_is_open = 0;
+static const target_info gdbsim_target_info = {
+  "sim",
+  N_("simulator"),
+  N_("Use the compiled-in simulator.")
+};
 
-/* Value of the next pid to allocate for an inferior.  As indicated
-   elsewhere, its initial value is somewhat arbitrary; it's critical
-   though that it's not zero or negative.  */
-static int next_pid;
-#define INITIAL_PID 42000
+struct gdbsim_target final
+  : public memory_breakpoint_target<process_stratum_target>
+{
+  gdbsim_target () = default;
+
+  const target_info &info () const override
+  { return gdbsim_target_info; }
+
+  void close () override;
+
+  void detach (inferior *inf, int) override;
+
+  void resume (ptid_t, int, enum gdb_signal) override;
+  ptid_t wait (ptid_t, struct target_waitstatus *, target_wait_flags) override;
+
+  void fetch_registers (struct regcache *, int) override;
+  void store_registers (struct regcache *, int) override;
+  void prepare_to_store (struct regcache *) override;
+
+  enum target_xfer_status xfer_partial (enum target_object object,
+                                       const char *annex,
+                                       gdb_byte *readbuf,
+                                       const gdb_byte *writebuf,
+                                       ULONGEST offset, ULONGEST len,
+                                       ULONGEST *xfered_len) override;
+
+  void files_info () override;
+
+  void kill () override;
+
+  void load (const char *, int) override;
+
+  bool can_create_inferior () override { return true; }
+  void create_inferior (const char *, const std::string &,
+                       char **, int) override;
+
+  void mourn_inferior () override;
+
+  void interrupt () override;
+
+  bool thread_alive (ptid_t ptid) override;
+
+  std::string pid_to_str (ptid_t) override;
+
+  bool has_all_memory ()  override;
+  bool has_memory ()  override;
+  std::vector<mem_region> memory_map () override;
+
+private:
+  sim_inferior_data *get_inferior_data_by_ptid (ptid_t ptid,
+                                               int sim_instance_needed);
+  void resume_one_inferior (inferior *inf, bool step, gdb_signal siggnal);
+  void close_one_inferior (inferior *inf);
+};
+
+static struct gdbsim_target gdbsim_ops;
+
+static const registry<inferior>::key<sim_inferior_data> sim_inferior_data_key;
+
+/* Flag indicating the "open" status of this module.  It's set true
+   in gdbsim_open() and false in gdbsim_close().  */
+static bool gdbsim_is_open = false;
 
 /* Argument list to pass to sim_open().  It is allocated in gdbsim_open()
    and deallocated in gdbsim_close().  The lifetime needs to extend beyond
@@ -142,22 +194,6 @@ static char **sim_argv = NULL;
 static host_callback gdb_callback;
 static int callbacks_initialized = 0;
 
-/* Callback for iterate_over_inferiors.  It checks to see if the sim
-   descriptor passed via ARG is the same as that for the inferior
-   designated by INF.  Return true if so; false otherwise.  */
-
-static int
-check_for_duplicate_sim_descriptor (struct inferior *inf, void *arg)
-{
-  struct sim_inferior_data *sim_data;
-  SIM_DESC new_sim_desc = (SIM_DESC) arg;
-
-  sim_data = ((struct sim_inferior_data *)
-             inferior_data (inf, sim_inferior_data_key));
-
-  return (sim_data != NULL && sim_data->gdbsim_desc == new_sim_desc);
-}
-
 /* Flags indicating whether or not a sim instance is needed.  One of these
    flags should be passed to get_sim_inferior_data().  */
 
@@ -170,8 +206,7 @@ static struct sim_inferior_data *
 get_sim_inferior_data (struct inferior *inf, int sim_instance_needed)
 {
   SIM_DESC sim_desc = NULL;
-  struct sim_inferior_data *sim_data
-    = (struct sim_inferior_data *) inferior_data (inf, sim_inferior_data_key);
+  struct sim_inferior_data *sim_data = sim_inferior_data_key.get (inf);
 
   /* Try to allocate a new sim instance, if needed.  We do this ahead of
      a potential allocation of a sim_inferior_data struct in order to
@@ -180,44 +215,40 @@ get_sim_inferior_data (struct inferior *inf, int sim_instance_needed)
   if (sim_instance_needed == SIM_INSTANCE_NEEDED
       && (sim_data == NULL || sim_data->gdbsim_desc == NULL))
     {
-      struct inferior *idup;
-      sim_desc = sim_open (SIM_OPEN_DEBUG, &gdb_callback, exec_bfd, sim_argv);
+      sim_desc = sim_open (SIM_OPEN_DEBUG, &gdb_callback,
+                          current_program_space->exec_bfd (), sim_argv);
       if (sim_desc == NULL)
        error (_("Unable to create simulator instance for inferior %d."),
               inf->num);
 
-      idup = iterate_over_inferiors (check_for_duplicate_sim_descriptor,
-                                    sim_desc);
-      if (idup != NULL)
+      /* Check if the sim descriptor is the same as that of another
+        inferior.  */
+      for (inferior *other_inf : all_inferiors ())
        {
-         /* We don't close the descriptor due to the fact that it's
-            shared with some other inferior.  If we were to close it,
-            that might needlessly muck up the other inferior.  Of
-            course, it's possible that the damage has already been
-            done...  Note that it *will* ultimately be closed during
-            cleanup of the other inferior.  */
-         sim_desc = NULL;
-         error (
- _("Inferior %d and inferior %d would have identical simulator state.\n"
-   "(This simulator does not support the running of more than one inferior.)"),
-                inf->num, idup->num);
+         sim_inferior_data *other_sim_data
+           = sim_inferior_data_key.get (other_inf);
+
+         if (other_sim_data != NULL
+             && other_sim_data->gdbsim_desc == sim_desc)
+           {
+             /* We don't close the descriptor due to the fact that it's
+                shared with some other inferior.  If we were to close it,
+                that might needlessly muck up the other inferior.  Of
+                course, it's possible that the damage has already been
+                done...  Note that it *will* ultimately be closed during
+                cleanup of the other inferior.  */
+             sim_desc = NULL;
+             error (
+_("Inferior %d and inferior %d would have identical simulator state.\n"
+ "(This simulator does not support the running of more than one inferior.)"),
+                    inf->num, other_inf->num);
+           }
        }
     }
 
   if (sim_data == NULL)
     {
-      sim_data = XCNEW(struct sim_inferior_data);
-      set_inferior_data (inf, sim_inferior_data_key, sim_data);
-
-      /* Allocate a ptid for this inferior.  */
-      sim_data->remote_sim_ptid = ptid_build (next_pid, 0, next_pid);
-      next_pid++;
-
-      /* Initialize the other instance variables.  */
-      sim_data->program_loaded = 0;
-      sim_data->gdbsim_desc = sim_desc;
-      sim_data->resume_siggnal = GDB_SIGNAL_0;
-      sim_data->resume_step = 0;
+      sim_data = sim_inferior_data_key.emplace (inf, sim_desc);
     }
   else if (sim_desc)
     {
@@ -234,16 +265,17 @@ get_sim_inferior_data (struct inferior *inf, int sim_instance_needed)
    inferior in question.  Return NULL when no inferior is found or
    when ptid has a zero or negative pid component.  */
 
-static struct sim_inferior_data *
-get_sim_inferior_data_by_ptid (ptid_t ptid, int sim_instance_needed)
+sim_inferior_data *
+gdbsim_target::get_inferior_data_by_ptid (ptid_t ptid,
+                                         int sim_instance_needed)
 {
   struct inferior *inf;
-  int pid = ptid_get_pid (ptid);
+  int pid = ptid.pid ();
 
   if (pid <= 0)
     return NULL;
 
-  inf = find_inferior_pid (pid);
+  inf = find_inferior_pid (this, pid);
 
   if (inf)
     return get_sim_inferior_data (inf, sim_instance_needed);
@@ -253,45 +285,35 @@ get_sim_inferior_data_by_ptid (ptid_t ptid, int sim_instance_needed)
 
 /* Free the per-inferior simulator data.  */
 
-static void
-sim_inferior_data_cleanup (struct inferior *inf, void *data)
+sim_inferior_data::~sim_inferior_data ()
 {
-  struct sim_inferior_data *sim_data = (struct sim_inferior_data *) data;
-
-  if (sim_data != NULL)
-    {
-      if (sim_data->gdbsim_desc)
-       {
-         sim_close (sim_data->gdbsim_desc, 0);
-         sim_data->gdbsim_desc = NULL;
-       }
-      xfree (sim_data);
-    }
+  if (gdbsim_desc)
+    sim_close (gdbsim_desc, 0);
 }
 
 static void
 dump_mem (const gdb_byte *buf, int len)
 {
-  fputs_unfiltered ("\t", gdb_stdlog);
+  gdb_puts ("\t", gdb_stdlog);
 
   if (len == 8 || len == 4)
     {
       uint32_t l[2];
 
       memcpy (l, buf, len);
-      fprintf_unfiltered (gdb_stdlog, "0x%08x", l[0]);
+      gdb_printf (gdb_stdlog, "0x%08x", l[0]);
       if (len == 8)
-       fprintf_unfiltered (gdb_stdlog, " 0x%08x", l[1]);
+       gdb_printf (gdb_stdlog, " 0x%08x", l[1]);
     }
   else
     {
       int i;
 
       for (i = 0; i < len; i++)
-       fprintf_unfiltered (gdb_stdlog, "0x%02x ", buf[i]);
+       gdb_printf (gdb_stdlog, "0x%02x ", buf[i]);
     }
 
-  fputs_unfiltered ("\n", gdb_stdlog);
+  gdb_puts ("\n", gdb_stdlog);
 }
 
 /* Initialize gdb_callback.  */
@@ -334,10 +356,7 @@ end_callbacks (void)
 static int
 gdb_os_write_stdout (host_callback *p, const char *buf, int len)
 {
-  int i;
-  char b[2];
-
-  ui_file_write (gdb_stdtarg, buf, len);
+  gdb_stdtarg->write (buf, len);
   return len;
 }
 
@@ -346,7 +365,7 @@ gdb_os_write_stdout (host_callback *p, const char *buf, int len)
 static void
 gdb_os_flush_stdout (host_callback *p)
 {
-  gdb_flush (gdb_stdtarg);
+  gdb_stdtarg->flush ();
 }
 
 /* GDB version of os_write_stderr callback.  */
@@ -361,7 +380,7 @@ gdb_os_write_stderr (host_callback *p, const char *buf, int len)
     {
       b[0] = buf[i];
       b[1] = 0;
-      fputs_unfiltered (b, gdb_stdtargerr);
+      gdb_stdtargerr->puts (b);
     }
   return len;
 }
@@ -371,40 +390,40 @@ gdb_os_write_stderr (host_callback *p, const char *buf, int len)
 static void
 gdb_os_flush_stderr (host_callback *p)
 {
-  gdb_flush (gdb_stdtargerr);
+  gdb_stdtargerr->flush ();
 }
 
-/* GDB version of printf_filtered callback.  */
+/* GDB version of gdb_printf callback.  */
 
-static void
-gdb_os_printf_filtered (host_callback * p, const char *format,...)
+static void ATTRIBUTE_PRINTF (2, 3)
+gdb_os_printf_filtered (host_callback * p, const char *format, ...)
 {
   va_list args;
 
   va_start (args, format);
-  vfprintf_filtered (gdb_stdout, format, args);
+  gdb_vprintf (gdb_stdout, format, args);
   va_end (args);
 }
 
-/* GDB version of error vprintf_filtered.  */
+/* GDB version of error gdb_vprintf.  */
 
-static void
+static void ATTRIBUTE_PRINTF (2, 0)
 gdb_os_vprintf_filtered (host_callback * p, const char *format, va_list ap)
 {
-  vfprintf_filtered (gdb_stdout, format, ap);
+  gdb_vprintf (gdb_stdout, format, ap);
 }
 
 /* GDB version of error evprintf_filtered.  */
 
-static void
+static void ATTRIBUTE_PRINTF (2, 0)
 gdb_os_evprintf_filtered (host_callback * p, const char *format, va_list ap)
 {
-  vfprintf_filtered (gdb_stderr, format, ap);
+  gdb_vprintf (gdb_stderr, format, ap);
 }
 
 /* GDB version of error callback.  */
 
-static void
+static void ATTRIBUTE_PRINTF (2, 3)
 gdb_os_error (host_callback * p, const char *format, ...)
 {
   va_list args;
@@ -422,19 +441,18 @@ one2one_register_sim_regno (struct gdbarch *gdbarch, int regnum)
   return regnum;
 }
 
-static void
-gdbsim_fetch_register (struct target_ops *ops,
-                      struct regcache *regcache, int regno)
+void
+gdbsim_target::fetch_registers (struct regcache *regcache, int regno)
 {
   struct gdbarch *gdbarch = regcache->arch ();
-  struct inferior *inf = find_inferior_ptid (regcache_get_ptid (regcache));
+  struct inferior *inf = find_inferior_ptid (this, regcache->ptid ());
   struct sim_inferior_data *sim_data
     = get_sim_inferior_data (inf, SIM_INSTANCE_NEEDED);
 
   if (regno == -1)
     {
       for (regno = 0; regno < gdbarch_num_regs (gdbarch); regno++)
-       gdbsim_fetch_register (ops, regcache, regno);
+       fetch_registers (regcache, regno);
       return;
     }
 
@@ -464,13 +482,13 @@ gdbsim_fetch_register (struct target_ops *ops,
                                       buf.data (), regsize);
        if (nr_bytes > 0 && nr_bytes != regsize && warn_user)
          {
-           fprintf_unfiltered (gdb_stderr,
-                               "Size of register %s (%d/%d) "
-                               "incorrect (%d instead of %d))",
-                               gdbarch_register_name (gdbarch, regno),
-                               regno,
-                               gdbarch_register_sim_regno (gdbarch, regno),
-                               nr_bytes, regsize);
+           gdb_printf (gdb_stderr,
+                       "Size of register %s (%d/%d) "
+                       "incorrect (%d instead of %d))",
+                       gdbarch_register_name (gdbarch, regno),
+                       regno,
+                       gdbarch_register_sim_regno (gdbarch, regno),
+                       nr_bytes, regsize);
            warn_user = 0;
          }
        /* FIXME: cagney/2002-05-27: Should check `nr_bytes == 0'
@@ -481,8 +499,8 @@ gdbsim_fetch_register (struct target_ops *ops,
        regcache->raw_supply (regno, buf.data ());
        if (remote_debug)
          {
-           fprintf_unfiltered (gdb_stdlog,
-                               "gdbsim_fetch_register: %d", regno);
+           gdb_printf (gdb_stdlog,
+                       "gdbsim_fetch_register: %d", regno);
            /* FIXME: We could print something more intelligible.  */
            dump_mem (buf.data (), regsize);
          }
@@ -492,19 +510,18 @@ gdbsim_fetch_register (struct target_ops *ops,
 }
 
 
-static void
-gdbsim_store_register (struct target_ops *ops,
-                      struct regcache *regcache, int regno)
+void
+gdbsim_target::store_registers (struct regcache *regcache, int regno)
 {
   struct gdbarch *gdbarch = regcache->arch ();
-  struct inferior *inf = find_inferior_ptid (regcache_get_ptid (regcache));
+  struct inferior *inf = find_inferior_ptid (this, regcache->ptid ());
   struct sim_inferior_data *sim_data
     = get_sim_inferior_data (inf, SIM_INSTANCE_NEEDED);
 
   if (regno == -1)
     {
       for (regno = 0; regno < gdbarch_num_regs (gdbarch); regno++)
-       gdbsim_store_register (ops, regcache, regno);
+       store_registers (regcache, regno);
       return;
     }
   else if (gdbarch_register_sim_regno (gdbarch, regno) >= 0)
@@ -520,18 +537,16 @@ gdbsim_store_register (struct target_ops *ops,
                                     tmp.data (), regsize);
 
       if (nr_bytes > 0 && nr_bytes != regsize)
-       internal_error (__FILE__, __LINE__,
-                       _("Register size different to expected"));
+       internal_error (_("Register size different to expected"));
       if (nr_bytes < 0)
-       internal_error (__FILE__, __LINE__,
-                       _("Register %d not updated"), regno);
+       internal_error (_("Register %d not updated"), regno);
       if (nr_bytes == 0)
        warning (_("Register %s not updated"),
                 gdbarch_register_name (gdbarch, regno));
 
       if (remote_debug)
        {
-         fprintf_unfiltered (gdb_stdlog, "gdbsim_store_register: %d", regno);
+         gdb_printf (gdb_stdlog, "gdbsim_store_register: %d", regno);
          /* FIXME: We could print something more intelligible.  */
          dump_mem (tmp.data (), regsize);
        }
@@ -541,11 +556,11 @@ gdbsim_store_register (struct target_ops *ops,
 /* Kill the running program.  This may involve closing any open files
    and releasing other resources acquired by the simulated program.  */
 
-static void
-gdbsim_kill (struct target_ops *ops)
+void
+gdbsim_target::kill ()
 {
   if (remote_debug)
-    fprintf_unfiltered (gdb_stdlog, "gdbsim_kill\n");
+    gdb_printf (gdb_stdlog, "gdbsim_kill\n");
 
   /* There is no need to `kill' running simulator - the simulator is
      not running.  Mourning it is enough.  */
@@ -556,8 +571,8 @@ gdbsim_kill (struct target_ops *ops)
    not only bring new code into the target process, but also to update
    GDB's symbol tables to match.  */
 
-static void
-gdbsim_load (struct target_ops *self, const char *args, int fromtty)
+void
+gdbsim_target::load (const char *args, int fromtty)
 {
   const char *prog;
   struct sim_inferior_data *sim_data
@@ -574,7 +589,7 @@ gdbsim_load (struct target_ops *self, const char *args, int fromtty)
     error (_("GDB sim does not yet support a load offset."));
 
   if (remote_debug)
-    fprintf_unfiltered (gdb_stdlog, "gdbsim_load: prog \"%s\"\n", prog);
+    gdb_printf (gdb_stdlog, "gdbsim_load: prog \"%s\"\n", prog);
 
   /* FIXME: We will print two messages on error.
      Need error to either not print anything if passed NULL or need
@@ -585,7 +600,7 @@ gdbsim_load (struct target_ops *self, const char *args, int fromtty)
   /* FIXME: If a load command should reset the targets registers then
      a call to sim_create_inferior() should go here.  */
 
-  sim_data->program_loaded = 1;
+  sim_data->program_loaded = true;
 }
 
 
@@ -597,9 +612,10 @@ gdbsim_load (struct target_ops *self, const char *args, int fromtty)
 /* This is called not only when we first attach, but also when the
    user types "run" after having attached.  */
 
-static void
-gdbsim_create_inferior (struct target_ops *target, const char *exec_file,
-                       const std::string &allargs, char **env, int from_tty)
+void
+gdbsim_target::create_inferior (const char *exec_file,
+                               const std::string &allargs,
+                               char **env, int from_tty)
 {
   struct sim_inferior_data *sim_data
     = get_sim_inferior_data (current_inferior (), SIM_INSTANCE_NEEDED);
@@ -607,19 +623,19 @@ gdbsim_create_inferior (struct target_ops *target, const char *exec_file,
   char *arg_buf;
   const char *args = allargs.c_str ();
 
-  if (exec_file == 0 || exec_bfd == 0)
+  if (exec_file == 0 || current_program_space->exec_bfd () == 0)
     warning (_("No executable file specified."));
   if (!sim_data->program_loaded)
     warning (_("No program loaded."));
 
   if (remote_debug)
-    fprintf_unfiltered (gdb_stdlog,
-                       "gdbsim_create_inferior: exec_file \"%s\", args \"%s\"\n",
-                       (exec_file ? exec_file : "(NULL)"),
-                       args);
+    gdb_printf (gdb_stdlog,
+               "gdbsim_create_inferior: exec_file \"%s\", args \"%s\"\n",
+               (exec_file ? exec_file : "(NULL)"),
+               args);
 
-  if (ptid_equal (inferior_ptid, sim_data->remote_sim_ptid))
-    gdbsim_kill (target);
+  if (inferior_ptid == sim_data->remote_sim_ptid)
+    kill ();
   remove_breakpoints ();
   init_wait_for_inferior ();
 
@@ -635,17 +651,16 @@ gdbsim_create_inferior (struct target_ops *target, const char *exec_file,
       built_argv.reset (arg_buf);
     }
 
-  if (!have_inferiors ())
-    init_thread_list ();
-
-  if (sim_create_inferior (sim_data->gdbsim_desc, exec_bfd,
+  if (sim_create_inferior (sim_data->gdbsim_desc,
+                          current_program_space->exec_bfd (),
                           built_argv.get (), env)
       != SIM_RC_OK)
     error (_("Unable to create sim inferior."));
 
-  inferior_ptid = sim_data->remote_sim_ptid;
-  inferior_appeared (current_inferior (), ptid_get_pid (inferior_ptid));
-  add_thread_silent (inferior_ptid);
+  inferior_appeared (current_inferior (),
+                    sim_data->remote_sim_ptid.pid ());
+  thread_info *thr = add_thread_silent (this, sim_data->remote_sim_ptid);
+  switch_to_thread (thr);
 
   insert_breakpoints ();       /* Needed to get correct instruction
                                   in cache.  */
@@ -659,21 +674,20 @@ gdbsim_create_inferior (struct target_ops *target, const char *exec_file,
 /* Called when selecting the simulator.  E.g. (gdb) target sim name.  */
 
 static void
-gdbsim_open (const char *args, int from_tty)
+gdbsim_target_open (const char *args, int from_tty)
 {
   int len;
   char *arg_buf;
   struct sim_inferior_data *sim_data;
-  const char *sysroot;
   SIM_DESC gdbsim_desc;
 
-  sysroot = gdb_sysroot;
+  const char *sysroot = gdb_sysroot.c_str ();
   if (is_target_filename (sysroot))
     sysroot += strlen (TARGET_SYSROOT_PREFIX);
 
   if (remote_debug)
-    fprintf_unfiltered (gdb_stdlog,
-                       "gdbsim_open: args \"%s\"\n", args ? args : "(null)");
+    gdb_printf (gdb_stdlog,
+               "gdbsim_open: args \"%s\"\n", args ? args : "(null)");
 
   /* Ensure that the sim target is not on the target stack.  This is
      necessary, because if it is on the target stack, the call to
@@ -683,7 +697,7 @@ gdbsim_open (const char *args, int from_tty)
      operation until after we complete those operations which could
      error out.  */
   if (gdbsim_is_open)
-    unpush_target (&gdbsim_ops);
+    current_inferior ()->unpush_target (&gdbsim_ops);
 
   len = (7 + 1                 /* gdbsim */
         + strlen (" -E little")
@@ -724,19 +738,19 @@ gdbsim_open (const char *args, int from_tty)
     }
 
   gdb_argv argv (arg_buf);
-  sim_argv = argv.get ();
+  sim_argv = argv.release ();
 
   init_callbacks ();
-  gdbsim_desc = sim_open (SIM_OPEN_DEBUG, &gdb_callback, exec_bfd, sim_argv);
+  gdbsim_desc = sim_open (SIM_OPEN_DEBUG, &gdb_callback,
+                         current_program_space->exec_bfd (), sim_argv);
 
   if (gdbsim_desc == 0)
     {
+      freeargv (sim_argv);
       sim_argv = NULL;
       error (_("unable to create simulator instance"));
     }
 
-  argv.release ();
-
   /* Reset the pid numberings for this batch of sim instances.  */
   next_pid = INITIAL_PID;
 
@@ -747,58 +761,51 @@ gdbsim_open (const char *args, int from_tty)
 
   sim_data->gdbsim_desc = gdbsim_desc;
 
-  push_target (&gdbsim_ops);
-  printf_filtered ("Connected to the simulator.\n");
+  current_inferior ()->push_target (&gdbsim_ops);
+  gdb_printf ("Connected to the simulator.\n");
 
   /* There's nothing running after "target sim" or "load"; not until
      "run".  */
-  inferior_ptid = null_ptid;
+  switch_to_no_thread ();
 
-  gdbsim_is_open = 1;
+  gdbsim_is_open = true;
 }
 
-/* Callback for iterate_over_inferiors.  Called (indirectly) by
-   gdbsim_close().  */
+/* Helper for gdbsim_target::close.  */
 
-static int
-gdbsim_close_inferior (struct inferior *inf, void *arg)
+void
+gdbsim_target::close_one_inferior (inferior *inf)
 {
-  struct sim_inferior_data *sim_data
-    = (struct sim_inferior_data *) inferior_data (inf, sim_inferior_data_key);
+  struct sim_inferior_data *sim_data = sim_inferior_data_key.get (inf);
   if (sim_data != NULL)
     {
       ptid_t ptid = sim_data->remote_sim_ptid;
 
-      sim_inferior_data_cleanup (inf, sim_data);
-      set_inferior_data (inf, sim_inferior_data_key, NULL);
+      sim_inferior_data_key.clear (inf);
 
       /* Having a ptid allocated and stored in remote_sim_ptid does
         not mean that a corresponding inferior was ever created.
         Thus we need to verify the existence of an inferior using the
         pid in question before setting inferior_ptid via
         switch_to_thread() or mourning the inferior.  */
-      if (find_inferior_ptid (ptid) != NULL)
+      if (find_inferior_ptid (this, ptid) != NULL)
        {
-         switch_to_thread (ptid);
+         switch_to_thread (this, ptid);
          generic_mourn_inferior ();
        }
     }
-
-  return 0;
 }
 
 /* Close out all files and local state before this target loses control.  */
 
-static void
-gdbsim_close (struct target_ops *self)
+void
+gdbsim_target::close ()
 {
-  struct sim_inferior_data *sim_data
-    = get_sim_inferior_data (current_inferior (), SIM_INSTANCE_NOT_NEEDED);
-
   if (remote_debug)
-    fprintf_unfiltered (gdb_stdlog, "gdbsim_close\n");
+    gdb_printf (gdb_stdlog, "gdbsim_close\n");
 
-  iterate_over_inferiors (gdbsim_close_inferior, NULL);
+  for (inferior *inf : all_inferiors (this))
+    close_one_inferior (inf);
 
   if (sim_argv != NULL)
     {
@@ -808,7 +815,7 @@ gdbsim_close (struct target_ops *self)
 
   end_callbacks ();
 
-  gdbsim_is_open = 0;
+  gdbsim_is_open = false;
 }
 
 /* Takes a program previously attached to and detaches it.
@@ -819,61 +826,45 @@ gdbsim_close (struct target_ops *self)
 /* Terminate the open connection to the remote debugger.
    Use this when you want to detach and do something else with your gdb.  */
 
-static void
-gdbsim_detach (struct target_ops *ops, inferior *inf, int from_tty)
+void
+gdbsim_target::detach (inferior *inf, int from_tty)
 {
   if (remote_debug)
-    fprintf_unfiltered (gdb_stdlog, "gdbsim_detach\n");
+    gdb_printf (gdb_stdlog, "gdbsim_detach\n");
 
-  unpush_target (ops);         /* calls gdbsim_close to do the real work */
+  inf->unpush_target (this);           /* calls gdbsim_close to do the real work */
   if (from_tty)
-    printf_filtered ("Ending simulator %s debugging\n", target_shortname);
+    gdb_printf ("Ending simulator %s debugging\n", target_shortname ());
 }
 
 /* Resume execution of the target process.  STEP says whether to single-step
    or to run free; SIGGNAL is the signal value (e.g. SIGINT) to be given
    to the target, or zero for no signal.  */
 
-struct resume_data
-{
-  enum gdb_signal siggnal;
-  int step;
-};
-
-static int
-gdbsim_resume_inferior (struct inferior *inf, void *arg)
+void
+gdbsim_target::resume_one_inferior (inferior *inf, bool step,
+                                   gdb_signal siggnal)
 {
   struct sim_inferior_data *sim_data
     = get_sim_inferior_data (inf, SIM_INSTANCE_NOT_NEEDED);
-  struct resume_data *rd = (struct resume_data *) arg;
 
   if (sim_data)
     {
-      sim_data->resume_siggnal = rd->siggnal;
-      sim_data->resume_step = rd->step;
+      sim_data->resume_siggnal = siggnal;
+      sim_data->resume_step = step;
 
       if (remote_debug)
-       fprintf_unfiltered (gdb_stdlog,
-                           _("gdbsim_resume: pid %d, step %d, signal %d\n"),
-                           inf->pid, rd->step, rd->siggnal);
+       gdb_printf (gdb_stdlog,
+                   _("gdbsim_resume: pid %d, step %d, signal %d\n"),
+                   inf->pid, step, siggnal);
     }
-
-  /* When called from iterate_over_inferiors, a zero return causes the
-     iteration process to proceed until there are no more inferiors to
-     consider.  */
-  return 0;
 }
 
-static void
-gdbsim_resume (struct target_ops *ops,
-              ptid_t ptid, int step, enum gdb_signal siggnal)
+void
+gdbsim_target::resume (ptid_t ptid, int step, enum gdb_signal siggnal)
 {
-  struct resume_data rd;
   struct sim_inferior_data *sim_data
-    = get_sim_inferior_data_by_ptid (ptid, SIM_INSTANCE_NOT_NEEDED);
-
-  rd.siggnal = siggnal;
-  rd.step = step;
+    = get_inferior_data_by_ptid (ptid, SIM_INSTANCE_NOT_NEEDED);
 
   /* We don't access any sim_data members within this function.
      What's of interest is whether or not the call to
@@ -883,9 +874,12 @@ gdbsim_resume (struct target_ops *ops,
      either have multiple inferiors to resume or an error condition.  */
 
   if (sim_data)
-    gdbsim_resume_inferior (find_inferior_ptid (ptid), &rd);
-  else if (ptid_equal (ptid, minus_one_ptid))
-    iterate_over_inferiors (gdbsim_resume_inferior, &rd);
+    resume_one_inferior (find_inferior_ptid (this, ptid), step, siggnal);
+  else if (ptid == minus_one_ptid)
+    {
+      for (inferior *inf : all_inferiors (this))
+       resume_one_inferior (inf, step, siggnal);
+    }
   else
     error (_("The program is not being run."));
 }
@@ -899,44 +893,16 @@ gdbsim_resume (struct target_ops *ops,
 
    For simulators that do not support this operation, just abort.  */
 
-static int
-gdbsim_interrupt_inferior (struct inferior *inf, void *arg)
-{
-  struct sim_inferior_data *sim_data
-    = get_sim_inferior_data (inf, SIM_INSTANCE_NEEDED);
-
-  if (sim_data)
-    {
-      if (!sim_stop (sim_data->gdbsim_desc))
-       {
-         quit ();
-       }
-    }
-
-  /* When called from iterate_over_inferiors, a zero return causes the
-     iteration process to proceed until there are no more inferiors to
-     consider.  */
-  return 0;
-}
-
-static void
-gdbsim_interrupt (struct target_ops *self, ptid_t ptid)
+void
+gdbsim_target::interrupt ()
 {
-  struct sim_inferior_data *sim_data;
-
-  if (ptid_equal (ptid, minus_one_ptid))
+  for (inferior *inf : all_inferiors ())
     {
-      iterate_over_inferiors (gdbsim_interrupt_inferior, NULL);
-    }
-  else
-    {
-      struct inferior *inf = find_inferior_ptid (ptid);
+      sim_inferior_data *sim_data
+       = get_sim_inferior_data (inf, SIM_INSTANCE_NEEDED);
 
-      if (inf == NULL)
-       error (_("Can't stop pid %d.  No inferior found."),
-              ptid_get_pid (ptid));
-
-      gdbsim_interrupt_inferior (inf, NULL);
+      if (sim_data != nullptr && !sim_stop (sim_data->gdbsim_desc))
+         quit ();
     }
 }
 
@@ -961,12 +927,12 @@ gdb_os_poll_quit (host_callback *p)
 static void
 gdbsim_cntrl_c (int signo)
 {
-  gdbsim_interrupt (NULL, minus_one_ptid);
+  gdbsim_ops.interrupt ();
 }
 
-static ptid_t
-gdbsim_wait (struct target_ops *ops,
-            ptid_t ptid, struct target_waitstatus *status, int options)
+ptid_t
+gdbsim_target::wait (ptid_t ptid, struct target_waitstatus *status,
+                    target_wait_flags options)
 {
   struct sim_inferior_data *sim_data;
   static sighandler_t prev_sigint;
@@ -976,20 +942,19 @@ gdbsim_wait (struct target_ops *ops,
   /* This target isn't able to (yet) resume more than one inferior at a time.
      When ptid is minus_one_ptid, just use the current inferior.  If we're
      given an explicit pid, we'll try to find it and use that instead.  */
-  if (ptid_equal (ptid, minus_one_ptid))
+  if (ptid == minus_one_ptid)
     sim_data = get_sim_inferior_data (current_inferior (),
                                      SIM_INSTANCE_NEEDED);
   else
     {
-      sim_data = get_sim_inferior_data_by_ptid (ptid, SIM_INSTANCE_NEEDED);
+      sim_data = get_inferior_data_by_ptid (ptid, SIM_INSTANCE_NEEDED);
       if (sim_data == NULL)
        error (_("Unable to wait for pid %d.  Inferior not found."),
-              ptid_get_pid (ptid));
-      inferior_ptid = ptid;
+              ptid.pid ());
     }
 
   if (remote_debug)
-    fprintf_unfiltered (gdb_stdlog, "gdbsim_wait\n");
+    gdb_printf (gdb_stdlog, "gdbsim_wait\n");
 
 #if defined (HAVE_SIGACTION) && defined (SA_RESTART)
   {
@@ -1003,19 +968,18 @@ gdbsim_wait (struct target_ops *ops,
 #else
   prev_sigint = signal (SIGINT, gdbsim_cntrl_c);
 #endif
-  sim_resume (sim_data->gdbsim_desc, sim_data->resume_step,
+  sim_resume (sim_data->gdbsim_desc, sim_data->resume_step ? 1 : 0,
              sim_data->resume_siggnal);
 
   signal (SIGINT, prev_sigint);
-  sim_data->resume_step = 0;
+  sim_data->resume_step = false;
 
   sim_stop_reason (sim_data->gdbsim_desc, &reason, &sigrc);
 
   switch (reason)
     {
     case sim_exited:
-      status->kind = TARGET_WAITKIND_EXITED;
-      status->value.integer = sigrc;
+      status->set_exited (sigrc);
       break;
     case sim_stopped:
       switch (sigrc)
@@ -1026,14 +990,12 @@ gdbsim_wait (struct target_ops *ops,
        case GDB_SIGNAL_INT:
        case GDB_SIGNAL_TRAP:
        default:
-         status->kind = TARGET_WAITKIND_STOPPED;
-         status->value.sig = (enum gdb_signal) sigrc;
+         status->set_stopped ((gdb_signal) sigrc);
          break;
        }
       break;
     case sim_signalled:
-      status->kind = TARGET_WAITKIND_SIGNALLED;
-      status->value.sig = (enum gdb_signal) sigrc;
+      status->set_signalled ((gdb_signal) sigrc);
       break;
     case sim_running:
     case sim_polling:
@@ -1041,7 +1003,7 @@ gdbsim_wait (struct target_ops *ops,
       break;
     }
 
-  return inferior_ptid;
+  return sim_data->remote_sim_ptid;
 }
 
 /* Get ready to modify the registers array.  On machines which store
@@ -1050,8 +1012,8 @@ gdbsim_wait (struct target_ops *ops,
    that registers contains all the registers from the program being
    debugged.  */
 
-static void
-gdbsim_prepare_to_store (struct target_ops *self, struct regcache *regcache)
+void
+gdbsim_target::prepare_to_store (struct regcache *regcache)
 {
   /* Do nothing, since we can store individual regs.  */
 }
@@ -1071,7 +1033,7 @@ gdbsim_xfer_memory (struct target_ops *target,
   /* If this target doesn't have memory yet, return 0 causing the
      request to be passed to a lower target, hopefully an exec
      file.  */
-  if (!target->to_has_memory (target))
+  if (!target->has_memory ())
     return TARGET_XFER_EOF;
 
   if (!sim_data->program_loaded)
@@ -1086,13 +1048,13 @@ gdbsim_xfer_memory (struct target_ops *target,
   gdb_assert (sim_data->gdbsim_desc != NULL);
 
   if (remote_debug)
-    fprintf_unfiltered (gdb_stdlog,
-                       "gdbsim_xfer_memory: readbuf %s, writebuf %s, "
-                       "memaddr %s, len %s\n",
-                       host_address_to_string (readbuf),
-                       host_address_to_string (writebuf),
-                       paddress (target_gdbarch (), memaddr),
-                       pulongest (len));
+    gdb_printf (gdb_stdlog,
+               "gdbsim_xfer_memory: readbuf %s, writebuf %s, "
+               "memaddr %s, len %s\n",
+               host_address_to_string (readbuf),
+               host_address_to_string (writebuf),
+               paddress (current_inferior ()->arch (), memaddr),
+               pulongest (len));
 
   if (writebuf)
     {
@@ -1119,16 +1081,16 @@ gdbsim_xfer_memory (struct target_ops *target,
 
 /* Target to_xfer_partial implementation.  */
 
-static enum target_xfer_status
-gdbsim_xfer_partial (struct target_ops *ops, enum target_object object,
-                    const char *annex, gdb_byte *readbuf,
-                    const gdb_byte *writebuf, ULONGEST offset, ULONGEST len,
-                    ULONGEST *xfered_len)
+enum target_xfer_status
+gdbsim_target::xfer_partial (enum target_object object,
+                            const char *annex, gdb_byte *readbuf,
+                            const gdb_byte *writebuf, ULONGEST offset, ULONGEST len,
+                            ULONGEST *xfered_len)
 {
   switch (object)
     {
     case TARGET_OBJECT_MEMORY:
-      return gdbsim_xfer_memory (ops, readbuf, writebuf, offset, len,
+      return gdbsim_xfer_memory (this, readbuf, writebuf, offset, len,
                                 xfered_len);
 
     default:
@@ -1136,47 +1098,43 @@ gdbsim_xfer_partial (struct target_ops *ops, enum target_object object,
     }
 }
 
-static void
-gdbsim_files_info (struct target_ops *target)
+void
+gdbsim_target::files_info ()
 {
   struct sim_inferior_data *sim_data
     = get_sim_inferior_data (current_inferior (), SIM_INSTANCE_NEEDED);
   const char *file = "nothing";
 
-  if (exec_bfd)
-    file = bfd_get_filename (exec_bfd);
+  if (current_program_space->exec_bfd ())
+    file = bfd_get_filename (current_program_space->exec_bfd ());
 
   if (remote_debug)
-    fprintf_unfiltered (gdb_stdlog, "gdbsim_files_info: file \"%s\"\n", file);
+    gdb_printf (gdb_stdlog, "gdbsim_files_info: file \"%s\"\n", file);
 
-  if (exec_bfd)
+  if (current_program_space->exec_bfd ())
     {
-      fprintf_unfiltered (gdb_stdlog, "\tAttached to %s running program %s\n",
-                         target_shortname, file);
+      gdb_printf ("\tAttached to %s running program %s\n",
+                 target_shortname (), file);
       sim_info (sim_data->gdbsim_desc, 0);
     }
 }
 
 /* Clear the simulator's notion of what the break points are.  */
 
-static void
-gdbsim_mourn_inferior (struct target_ops *target)
+void
+gdbsim_target::mourn_inferior ()
 {
-  struct sim_inferior_data *sim_data
-    = get_sim_inferior_data (current_inferior (), SIM_INSTANCE_NOT_NEEDED);
-
   if (remote_debug)
-    fprintf_unfiltered (gdb_stdlog, "gdbsim_mourn_inferior:\n");
+    gdb_printf (gdb_stdlog, "gdbsim_mourn_inferior:\n");
 
   remove_breakpoints ();
   generic_mourn_inferior ();
-  delete_thread_silent (sim_data->remote_sim_ptid);
 }
 
 /* Pass the command argument through to the simulator verbatim.  The
    simulator must do any command interpretation work.  */
 
-void
+static void
 simulator_command (const char *args, int from_tty)
 {
   struct sim_inferior_data *sim_data;
@@ -1191,8 +1149,7 @@ simulator_command (const char *args, int from_tty)
      thus allocating memory that would not be garbage collected until
      the ultimate destruction of the associated inferior.  */
 
-  sim_data  = ((struct sim_inferior_data *)
-              inferior_data (current_inferior (), sim_inferior_data_key));
+  sim_data  = sim_inferior_data_key.get (current_inferior ());
   if (sim_data == NULL || sim_data->gdbsim_desc == NULL)
     {
 
@@ -1223,8 +1180,7 @@ sim_command_completer (struct cmd_list_element *ignore,
 {
   struct sim_inferior_data *sim_data;
 
-  sim_data = ((struct sim_inferior_data *)
-             inferior_data (current_inferior (), sim_inferior_data_key));
+  sim_data = sim_inferior_data_key.get (current_inferior ());
   if (sim_data == NULL || sim_data->gdbsim_desc == NULL)
     return;
 
@@ -1262,107 +1218,81 @@ sim_command_completer (struct cmd_list_element *ignore,
 
 /* Check to see if a thread is still alive.  */
 
-static int
-gdbsim_thread_alive (struct target_ops *ops, ptid_t ptid)
+bool
+gdbsim_target::thread_alive (ptid_t ptid)
 {
   struct sim_inferior_data *sim_data
-    = get_sim_inferior_data_by_ptid (ptid, SIM_INSTANCE_NOT_NEEDED);
+    = get_inferior_data_by_ptid (ptid, SIM_INSTANCE_NOT_NEEDED);
 
   if (sim_data == NULL)
-    return 0;
+    return false;
 
-  if (ptid_equal (ptid, sim_data->remote_sim_ptid))
+  if (ptid == sim_data->remote_sim_ptid)
     /* The simulators' task is always alive.  */
-    return 1;
+    return true;
 
-  return 0;
+  return false;
 }
 
-/* Convert a thread ID to a string.  Returns the string in a static
-   buffer.  */
+/* Convert a thread ID to a string.  */
 
-static const char *
-gdbsim_pid_to_str (struct target_ops *ops, ptid_t ptid)
+std::string
+gdbsim_target::pid_to_str (ptid_t ptid)
 {
   return normal_pid_to_str (ptid);
 }
 
 /* Simulator memory may be accessed after the program has been loaded.  */
 
-static int
-gdbsim_has_all_memory (struct target_ops *ops)
+bool
+gdbsim_target::has_all_memory ()
 {
   struct sim_inferior_data *sim_data
     = get_sim_inferior_data (current_inferior (), SIM_INSTANCE_NOT_NEEDED);
 
   if (!sim_data->program_loaded)
-    return 0;
+    return false;
 
-  return 1;
+  return true;
 }
 
-static int
-gdbsim_has_memory (struct target_ops *ops)
+bool
+gdbsim_target::has_memory ()
 {
   struct sim_inferior_data *sim_data
     = get_sim_inferior_data (current_inferior (), SIM_INSTANCE_NOT_NEEDED);
 
   if (!sim_data->program_loaded)
-    return 0;
+    return false;
 
-  return 1;
+  return true;
 }
 
-/* Define the target subroutine names.  */
-
-struct target_ops gdbsim_ops;
+/* Get memory map from the simulator.  */
 
-static void
-init_gdbsim_ops (void)
+std::vector<mem_region>
+gdbsim_target::memory_map ()
 {
-  gdbsim_ops.to_shortname = "sim";
-  gdbsim_ops.to_longname = "simulator";
-  gdbsim_ops.to_doc = "Use the compiled-in simulator.";
-  gdbsim_ops.to_open = gdbsim_open;
-  gdbsim_ops.to_close = gdbsim_close;
-  gdbsim_ops.to_detach = gdbsim_detach;
-  gdbsim_ops.to_resume = gdbsim_resume;
-  gdbsim_ops.to_wait = gdbsim_wait;
-  gdbsim_ops.to_fetch_registers = gdbsim_fetch_register;
-  gdbsim_ops.to_store_registers = gdbsim_store_register;
-  gdbsim_ops.to_prepare_to_store = gdbsim_prepare_to_store;
-  gdbsim_ops.to_xfer_partial = gdbsim_xfer_partial;
-  gdbsim_ops.to_files_info = gdbsim_files_info;
-  gdbsim_ops.to_insert_breakpoint = memory_insert_breakpoint;
-  gdbsim_ops.to_remove_breakpoint = memory_remove_breakpoint;
-  gdbsim_ops.to_kill = gdbsim_kill;
-  gdbsim_ops.to_load = gdbsim_load;
-  gdbsim_ops.to_create_inferior = gdbsim_create_inferior;
-  gdbsim_ops.to_mourn_inferior = gdbsim_mourn_inferior;
-  gdbsim_ops.to_interrupt = gdbsim_interrupt;
-  gdbsim_ops.to_thread_alive = gdbsim_thread_alive;
-  gdbsim_ops.to_pid_to_str = gdbsim_pid_to_str;
-  gdbsim_ops.to_stratum = process_stratum;
-  gdbsim_ops.to_has_all_memory = gdbsim_has_all_memory;
-  gdbsim_ops.to_has_memory = gdbsim_has_memory;
-  gdbsim_ops.to_has_stack = default_child_has_stack;
-  gdbsim_ops.to_has_registers = default_child_has_registers;
-  gdbsim_ops.to_has_execution = default_child_has_execution;
-  gdbsim_ops.to_magic = OPS_MAGIC;
+  struct sim_inferior_data *sim_data
+    = get_sim_inferior_data (current_inferior (), SIM_INSTANCE_NEEDED);
+  std::vector<mem_region> result;
+  gdb::unique_xmalloc_ptr<char> text (sim_memory_map (sim_data->gdbsim_desc));
+
+  if (text != nullptr)
+    result = parse_memory_map (text.get ());
+
+  return result;
 }
 
+void _initialize_remote_sim ();
 void
-_initialize_remote_sim (void)
+_initialize_remote_sim ()
 {
   struct cmd_list_element *c;
 
-  init_gdbsim_ops ();
-  add_target (&gdbsim_ops);
+  add_target (gdbsim_target_info, gdbsim_target_open);
 
   c = add_com ("sim", class_obscure, simulator_command,
               _("Send a command to the simulator."));
   set_cmd_completer (c, sim_command_completer);
-
-  sim_inferior_data_key
-    = register_inferior_data_with_cleanup (NULL, sim_inferior_data_cleanup);
 }