Restrict simulator commands to an enabled simulator.
[binutils-gdb.git] / gdb / remote-sim.c
index 1c2de529e4cf13ec7cccc8ba0e734a02b2d00dd6..7574cbe76685935b94680369cc7ac548edc52a44 100644 (file)
@@ -161,8 +161,6 @@ init_callbacks ()
       gdb_callback.error = gdb_os_error;
       gdb_callback.poll_quit = gdb_os_poll_quit;
       gdb_callback.magic = HOST_CALLBACK_MAGIC;
-      sim_set_callbacks (gdbsim_desc, &gdb_callback);
-      
       callbacks_initialized = 1;
     }
 }
@@ -243,26 +241,6 @@ gdb_os_flush_stderr (p)
   gdb_flush (gdb_stderr);
 }
 
-/* GDB version of os_poll_quit callback.
-   Taken from gdb/util.c - should be in a library */
-
-static int
-gdb_os_poll_quit (p)
-     host_callback *p;
-{
-  notice_quit ();
-  if (quit_flag)
-    {
-      quit_flag = 0; /* we've stolen it */
-      return 1;
-    }
-  else if (immediate_quit)
-    {
-      return 1;
-    }
-  return 0;
-}
-
 /* GDB version of printf_filtered callback.  */
 
 /* VARARGS */
@@ -517,19 +495,26 @@ gdbsim_open (args, from_tty)
   if (gdbsim_desc != NULL)
     unpush_target (&gdbsim_ops);
 
-  init_callbacks ();
-
   len = 7 + 1 + (args ? strlen (args) : 0) + 50;
   arg_buf = (char *) alloca (len);
-  sprintf (arg_buf, "gdbsim%s%s -E %s",
-          args ? " " : "", args ? args : "",
-          TARGET_BYTE_ORDER == BIG_ENDIAN ? "big" : "little");
+  sprintf (arg_buf, "gdbsim%s%s",
+          args ? " " : "", args ? args : "");
+#ifdef TARGET_BYTE_ORDER_SELECTABLE
+  /* Since GDB always closes the target and updates byte-order when
+     opening a new file, TARGET_BYTE_ORDER is normally correct. */
+  if (TARGET_BYTE_ORDER == BIG_ENDIAN)
+    strcat (arg_buf, " -E big");
+  else
+    strcat (arg_buf, " -E little");
+#endif
   argv = buildargv (arg_buf);
   if (argv == NULL)
     error ("Insufficient memory available to allocate simulator arg list.");
   make_cleanup (freeargv, (char *) argv);
 
-  gdbsim_desc = sim_open (SIM_OPEN_DEBUG, argv);
+  init_callbacks ();
+  gdbsim_desc = sim_open (SIM_OPEN_DEBUG, &gdb_callback, argv);
+
   if (gdbsim_desc == 0)
     error ("unable to create simulator instance");
 
@@ -610,25 +595,47 @@ gdbsim_resume (pid, step, siggnal)
 }
 
 /* Notify the simulator of an asynchronous request to stop.
-   Since some simulators can not stop, help them out.
-   When stepping, need to also notify the client that it
-   too should quit */
+   
+   The simulator shall ensure that the stop request is eventually
+   delivered to the simulator.  If the call is made while the
+   simulator is not running then the stop request is processed when
+   the simulator is next resumed.
+
+   For simulators that do not support this operation, just abort */
 
 static void
 gdbsim_stop ()
 {
   if (! sim_stop (gdbsim_desc))
     {
-      error ("gdbsim_stop: simulator failed to stop!\n");
+      quit ();
     }
 }
 
+/* GDB version of os_poll_quit callback.
+   Taken from gdb/util.c - should be in a library */
+
+static int
+gdb_os_poll_quit (p)
+     host_callback *p;
+{
+  notice_quit ();
+  if (quit_flag) /* gdb's idea of quit */
+    {
+      quit_flag = 0; /* we've stolen it */
+      return 1;
+    }
+  else if (immediate_quit)
+    {
+      return 1;
+    }
+  return 0;
+}
+
 /* Wait for inferior process to do something.  Return pid of child,
    or -1 in case of error; store status through argument pointer STATUS,
    just as `wait' would. */
 
-static void (*prev_sigint) ();
-
 static void
 gdbsim_cntrl_c (int signo)
 {
@@ -640,6 +647,7 @@ gdbsim_wait (pid, status)
      int pid;
      struct target_waitstatus *status;
 {
+  static RETSIGTYPE (*prev_sigint) ();
   int sigrc = 0;
   enum sim_stop reason = sim_running;
 
@@ -771,15 +779,22 @@ simulator_command (args, from_tty)
      char *args;
      int from_tty;
 {
-  /* The user may give a command before the simulator is opened, so
-     ensure that the callbacks have been set up.  */
-  init_callbacks ();
+  if (gdbsim_desc == NULL)
+    {
+
+      /* PREVIOUSLY: The user may give a command before the simulator
+         is opened. [...] (??? assuming of course one wishes to
+         continue to allow commands to be sent to unopened simulators,
+         which isn't entirely unreasonable). */
+
+      /* The simulator is a builtin abstraction of a remote target.
+         Consistent with that model, access to the simulator, via sim
+         commands, is restricted to the period when the channel to the
+         simulator is open. */
+
+      error ("Not connected to the simulator target");
+    }
 
-  /* Note that if the simulator hasn't been opened, gdbsim_desc == NULL
-     which is correct (??? assuming of course one wishes to continue to
-     allow commands to be sent to unopened simulators, which isn't entirely
-     unreasonable).  Simulators should be prepared to deal with any
-     combination of NULL or empty args. */
   sim_do_command (gdbsim_desc, args);
 }