]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - gdb/remote-sim.c
[binutils, ARM, 4/16] BF insns infrastructure with array of relocs in struct arm_it
[thirdparty/binutils-gdb.git] / gdb / remote-sim.c
index edc70d5b3ed8eb4f2531a95d18351bab07779c65..8a6cb6b18e3fe0cb7e2c9e9a83e5da4408f1dc8b 100644 (file)
@@ -1,6 +1,6 @@
 /* Generic remote debugging interface for simulators.
 
-   Copyright (C) 1993-2018 Free Software Foundation, Inc.
+   Copyright (C) 1993-2019 Free Software Foundation, Inc.
 
    Contributed by Cygnus Support.
    Steve Chamberlain (sac@cygnus.com).
@@ -31,6 +31,7 @@
 #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"
@@ -68,35 +69,68 @@ 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 *);
+void simulator_command (char *args, int from_tty);
 
-static void gdbsim_load (struct target_ops *self, const char *prog,
-                        int fromtty);
+/* Naming convention:
 
-static void gdbsim_open (const char *args, int from_tty);
+   sim_* are the interface to the simulator (see remote-sim.h).
+   gdbsim_* are stuff which is internal to gdb.  */
 
-static void gdbsim_close (struct target_ops *self);
+static const target_info gdbsim_target_info = {
+  "sim",
+  N_("simulator"),
+  N_("Use the compiled-in simulator.")
+};
 
-static void gdbsim_detach (struct target_ops *ops, int from_tty);
+struct gdbsim_target final
+  : public memory_breakpoint_target<process_stratum_target>
+{
+  gdbsim_target () = default;
 
-static void gdbsim_prepare_to_store (struct target_ops *self,
-                                    struct regcache *regcache);
+  const target_info &info () const override
+  { return gdbsim_target_info; }
 
-static void gdbsim_files_info (struct target_ops *target);
+  void close () override;
 
-static void gdbsim_mourn_inferior (struct target_ops *target);
+  void detach (inferior *inf, int) override;
 
-static void gdbsim_interrupt (struct target_ops *self, ptid_t ptid);
+  void resume (ptid_t, int, enum gdb_signal) override;
+  ptid_t wait (ptid_t, struct target_waitstatus *, int) override;
 
-void simulator_command (char *args, int from_tty);
+  void fetch_registers (struct regcache *, int) override;
+  void store_registers (struct regcache *, int) override;
+  void prepare_to_store (struct regcache *) override;
 
-/* Naming convention:
+  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;
 
-   sim_* are the interface to the simulator (see remote-sim.h).
-   gdbsim_* are stuff which is internal to gdb.  */
+  void files_info () override;
 
-/* Forward data declarations */
-extern struct target_ops gdbsim_ops;
+  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;
+};
+
+static struct gdbsim_target gdbsim_ops;
 
 static const struct inferior_data *sim_inferior_data_key;
 
@@ -210,7 +244,7 @@ get_sim_inferior_data (struct inferior *inf, int sim_instance_needed)
       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);
+      sim_data->remote_sim_ptid = ptid_t (next_pid, 0, next_pid);
       next_pid++;
 
       /* Initialize the other instance variables.  */
@@ -238,7 +272,7 @@ static struct sim_inferior_data *
 get_sim_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;
@@ -334,9 +368,6 @@ 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);
   return len;
 }
@@ -376,8 +407,8 @@ gdb_os_flush_stderr (host_callback *p)
 
 /* GDB version of printf_filtered 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;
 
@@ -388,7 +419,7 @@ gdb_os_printf_filtered (host_callback * p, const char *format,...)
 
 /* GDB version of error vprintf_filtered.  */
 
-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);
@@ -396,7 +427,7 @@ gdb_os_vprintf_filtered (host_callback * p, const char *format, va_list 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);
@@ -404,7 +435,7 @@ gdb_os_evprintf_filtered (host_callback * p, const char *format, va_list 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 +453,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 (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;
     }
 
@@ -492,19 +522,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 (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)
@@ -541,8 +570,8 @@ 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");
@@ -556,8 +585,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
@@ -597,9 +626,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);
@@ -618,8 +648,8 @@ gdbsim_create_inferior (struct target_ops *target, const char *exec_file,
                        (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,16 +665,13 @@ 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,
                           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));
+  inferior_appeared (current_inferior (), inferior_ptid.pid ());
   add_thread_silent (inferior_ptid);
 
   insert_breakpoints ();       /* Needed to get correct instruction
@@ -659,7 +686,7 @@ 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;
@@ -724,19 +751,18 @@ 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);
 
   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;
 
@@ -789,12 +815,9 @@ gdbsim_close_inferior (struct inferior *inf, void *arg)
 
 /* 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");
 
@@ -819,13 +842,13 @@ 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, int from_tty)
+void
+gdbsim_target::detach (inferior *inf, int from_tty)
 {
   if (remote_debug)
     fprintf_unfiltered (gdb_stdlog, "gdbsim_detach\n");
 
-  unpush_target (ops);         /* calls gdbsim_close to do the real work */
+  unpush_target (this);                /* calls gdbsim_close to do the real work */
   if (from_tty)
     printf_filtered ("Ending simulator %s debugging\n", target_shortname);
 }
@@ -864,9 +887,8 @@ gdbsim_resume_inferior (struct inferior *inf, void *arg)
   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
@@ -884,7 +906,7 @@ gdbsim_resume (struct target_ops *ops,
 
   if (sim_data)
     gdbsim_resume_inferior (find_inferior_ptid (ptid), &rd);
-  else if (ptid_equal (ptid, minus_one_ptid))
+  else if (ptid == minus_one_ptid)
     iterate_over_inferiors (gdbsim_resume_inferior, &rd);
   else
     error (_("The program is not being run."));
@@ -919,25 +941,10 @@ gdbsim_interrupt_inferior (struct inferior *inf, void *arg)
   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))
-    {
-      iterate_over_inferiors (gdbsim_interrupt_inferior, NULL);
-    }
-  else
-    {
-      struct inferior *inf = find_inferior_ptid (ptid);
-
-      if (inf == NULL)
-       error (_("Can't stop pid %d.  No inferior found."),
-              ptid_get_pid (ptid));
-
-      gdbsim_interrupt_inferior (inf, NULL);
-    }
+  iterate_over_inferiors (gdbsim_interrupt_inferior, NULL);
 }
 
 /* GDB version of os_poll_quit callback.
@@ -961,12 +968,11 @@ 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, int options)
 {
   struct sim_inferior_data *sim_data;
   static sighandler_t prev_sigint;
@@ -976,7 +982,7 @@ 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
@@ -984,7 +990,7 @@ gdbsim_wait (struct target_ops *ops,
       sim_data = get_sim_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));
+              ptid.pid ());
       inferior_ptid = ptid;
     }
 
@@ -1050,8 +1056,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 +1077,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)
@@ -1119,16 +1125,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,8 +1142,8 @@ 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);
@@ -1159,18 +1165,14 @@ gdbsim_files_info (struct target_ops *target)
 
 /* 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");
 
   remove_breakpoints ();
   generic_mourn_inferior ();
-  delete_thread_silent (sim_data->remote_sim_ptid);
 }
 
 /* Pass the command argument through to the simulator verbatim.  The
@@ -1262,93 +1264,54 @@ 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);
 
   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 1;
-}
-
-/* Define the target subroutine names.  */
-
-struct target_ops gdbsim_ops;
+    return false;
 
-static void
-init_gdbsim_ops (void)
-{
-  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;
+  return true;
 }
 
 void
@@ -1356,8 +1319,7 @@ _initialize_remote_sim (void)
 {
   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."));