mirror of
https://github.com/bminor/binutils-gdb.git
synced 2025-12-26 17:18:55 +00:00
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).
This commit is contained in:
@@ -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 */
|
||||
|
||||
Reference in New Issue
Block a user