diff options
author | Andrew Cagney <cagney@redhat.com> | 1997-04-18 12:24:52 +0000 |
---|---|---|
committer | Andrew Cagney <cagney@redhat.com> | 1997-04-18 12:24:52 +0000 |
commit | 8517f62b166073b871c896fdd642798fae4a08bd (patch) | |
tree | 805af7156e712458e58d2ebe21fc7b0b73dee681 /gdb/remote-sim.c | |
parent | 2d3588808f00aaa6784f004aa940b862a11be3a2 (diff) | |
download | gdb-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.c | 88 |
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 */ |