aboutsummaryrefslogtreecommitdiff
path: root/gdb/remote-sim.c
diff options
context:
space:
mode:
authorAndrew Cagney <cagney@redhat.com>1997-04-18 12:24:52 +0000
committerAndrew Cagney <cagney@redhat.com>1997-04-18 12:24:52 +0000
commit8517f62b166073b871c896fdd642798fae4a08bd (patch)
tree805af7156e712458e58d2ebe21fc7b0b73dee681 /gdb/remote-sim.c
parent2d3588808f00aaa6784f004aa940b862a11be3a2 (diff)
downloadgdb-8517f62b166073b871c896fdd642798fae4a08bd.zip
gdb-8517f62b166073b871c896fdd642798fae4a08bd.tar.gz
gdb-8517f62b166073b871c896fdd642798fae4a08bd.tar.bz2
Ref gdb/11763 - can't stop a running simulator:
o Provide poll_quit callback to simulators so that they can poll for SIGINT on clueless OS's. o Add sim_stop to simulators so that clients can request a halt (eg gdbtk's STOP button) Works for PPC! o Re-arange remote-sim.c so that the hard work is moved from gdbsim_resume() to gdbsim_wait() (where it should be).
Diffstat (limited to 'gdb/remote-sim.c')
-rw-r--r--gdb/remote-sim.c88
1 files changed, 79 insertions, 9 deletions
diff --git a/gdb/remote-sim.c b/gdb/remote-sim.c
index 51cc66a..1c2de52 100644
--- a/gdb/remote-sim.c
+++ b/gdb/remote-sim.c
@@ -52,6 +52,8 @@ static int gdb_os_write_stderr PARAMS ((host_callback *, const char *, int));
static void gdb_os_flush_stderr PARAMS ((host_callback *));
+static int gdb_os_poll_quit PARAMS ((host_callback *));
+
/* printf_filtered is depreciated */
static void gdb_os_printf_filtered PARAMS ((host_callback *, const char *, ...));
@@ -92,6 +94,8 @@ static void gdbsim_files_info PARAMS ((struct target_ops *target));
static void gdbsim_mourn_inferior PARAMS ((void));
+static void gdbsim_stop PARAMS ((void));
+
static void simulator_command PARAMS ((char *args, int from_tty));
/* Naming convention:
@@ -155,7 +159,10 @@ init_callbacks ()
gdb_callback.vprintf_filtered = gdb_os_vprintf_filtered;
gdb_callback.evprintf_filtered = gdb_os_evprintf_filtered;
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;
}
}
@@ -236,6 +243,26 @@ 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 */
@@ -564,6 +591,9 @@ gdbsim_detach (args,from_tty)
or to run free; SIGGNAL is the signal value (e.g. SIGINT) to be given
to the target, or zero for no signal. */
+static enum target_signal resume_siggnal;
+static int resume_step;
+
static void
gdbsim_resume (pid, step, siggnal)
int pid, step;
@@ -575,25 +605,55 @@ gdbsim_resume (pid, step, siggnal)
if (sr_get_debug ())
printf_filtered ("gdbsim_resume: step %d, signal %d\n", step, siggnal);
- sim_resume (gdbsim_desc, step, target_signal_to_host (siggnal));
+ resume_siggnal = siggnal;
+ resume_step = step;
+}
+
+/* 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 */
+
+static void
+gdbsim_stop ()
+{
+ if (! sim_stop (gdbsim_desc))
+ {
+ error ("gdbsim_stop: simulator failed to stop!\n");
+ }
}
/* 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. */
+ just as `wait' would. */
+
+static void (*prev_sigint) ();
+
+static void
+gdbsim_cntrl_c (int signo)
+{
+ gdbsim_stop ();
+}
static int
gdbsim_wait (pid, status)
int pid;
struct target_waitstatus *status;
{
- int sigrc;
- enum sim_stop reason;
+ int sigrc = 0;
+ enum sim_stop reason = sim_running;
if (sr_get_debug ())
printf_filtered ("gdbsim_wait\n");
+ prev_sigint = signal (SIGINT, gdbsim_cntrl_c);
+ sim_resume (gdbsim_desc, resume_step,
+ target_signal_to_host (resume_siggnal));
+ signal (SIGINT, prev_sigint);
+ resume_step = 0;
+
sim_stop_reason (gdbsim_desc, &reason, &sigrc);
+
switch (reason)
{
case sim_exited:
@@ -601,10 +661,20 @@ gdbsim_wait (pid, status)
status->value.integer = sigrc;
break;
case sim_stopped:
- status->kind = TARGET_WAITKIND_STOPPED;
- /* The signal in sigrc is a host signal. That probably
- should be fixed. */
- status->value.sig = target_signal_from_host (sigrc);
+ switch (sigrc)
+ {
+ case SIGABRT:
+ quit ();
+ break;
+ case SIGINT:
+ case SIGTRAP:
+ default:
+ status->kind = TARGET_WAITKIND_STOPPED;
+ /* The signal in sigrc is a host signal. That probably
+ should be fixed. */
+ status->value.sig = target_signal_from_host (sigrc);
+ break;
+ }
break;
case sim_signalled:
status->kind = TARGET_WAITKIND_SIGNALLED;
@@ -745,7 +815,7 @@ struct target_ops gdbsim_ops = {
0, /* to_can_run */
0, /* to_notice_signals */
0, /* to_thread_alive */
- 0, /* to_stop */
+ gdbsim_stop, /* to_stop */
process_stratum, /* to_stratum */
NULL, /* to_next */
1, /* to_has_all_memory */