X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fremote-sim.c;h=4ec4cd392470f99b802cc0be19b612c8aee6cabd;hb=8387d6dfd396b90f8b3393488099b71622a8eaad;hp=1c2de529e4cf13ec7cccc8ba0e734a02b2d00dd6;hpb=8517f62b166073b871c896fdd642798fae4a08bd;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/remote-sim.c b/gdb/remote-sim.c index 1c2de529e4..4ec4cd3924 100644 --- a/gdb/remote-sim.c +++ b/gdb/remote-sim.c @@ -35,6 +35,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "callback.h" #include "remote-sim.h" #include "remote-utils.h" +#include "command.h" /* Prototypes */ @@ -161,8 +162,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 +242,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 */ @@ -358,18 +337,29 @@ gdb_os_error (p, va_alist) static void gdbsim_fetch_register (regno) -int regno; + int regno; { + static int warn_user = 1; if (regno == -1) { for (regno = 0; regno < NUM_REGS; regno++) gdbsim_fetch_register (regno); } - else + else if (reg_names[regno] != NULL && *reg_names[regno] != '\0') { char buf[MAX_REGISTER_RAW_SIZE]; - - sim_fetch_register (gdbsim_desc, regno, buf); + int nr_bytes = sim_fetch_register (gdbsim_desc, regno, buf, REGISTER_RAW_SIZE (regno)); + if (nr_bytes == 0) + /* register not applicable, supply zero's */ + memset (buf, 0, MAX_REGISTER_RAW_SIZE); + else if (nr_bytes > 0 && nr_bytes != REGISTER_RAW_SIZE (regno) + && warn_user) + { + printf_unfiltered ("Size of register %s (%d) incorrect (%d instead of %d))", + reg_names [regno], regno, + nr_bytes, REGISTER_RAW_SIZE (regno)); + warn_user = 0; + } supply_register (regno, buf); if (sr_get_debug ()) { @@ -383,19 +373,21 @@ int regno; static void gdbsim_store_register (regno) -int regno; + int regno; { if (regno == -1) { for (regno = 0; regno < NUM_REGS; regno++) gdbsim_store_register (regno); } - else + else if (reg_names[regno] != NULL && *reg_names[regno] != '\0') { - /* FIXME: Until read_register() returns LONGEST, we have this. */ char tmp[MAX_REGISTER_RAW_SIZE]; + int nr_bytes; read_register_gen (regno, tmp); - sim_store_register (gdbsim_desc, regno, tmp); + nr_bytes = sim_store_register (gdbsim_desc, regno, tmp, REGISTER_RAW_SIZE (regno)); + if (nr_bytes > 0 && nr_bytes != REGISTER_RAW_SIZE (regno)) + fatal ("Register size different to expected"); if (sr_get_debug ()) { printf_filtered ("gdbsim_store_register: %d", regno); @@ -414,7 +406,8 @@ gdbsim_kill () if (sr_get_debug ()) printf_filtered ("gdbsim_kill\n"); - sim_kill (gdbsim_desc); /* close fd's, remove mappings, etc. */ + /* There is no need to `kill' running simulator - the simulator is + not running */ inferior_pid = 0; } @@ -438,6 +431,9 @@ gdbsim_load (prog, fromtty) if (sim_load (gdbsim_desc, prog, NULL, fromtty) == SIM_RC_FAIL) error ("unable to load program"); + /* FIXME: If a load command should reset the targets registers then + a call to sim_create_inferior() should go here. */ + program_loaded = 1; } @@ -458,37 +454,43 @@ gdbsim_create_inferior (exec_file, args, env) { int len; char *arg_buf,**argv; - CORE_ADDR entry_pt; + if (exec_file == 0 || exec_bfd == 0) + warning ("No exec file specified."); if (! program_loaded) - error ("No program loaded."); + warning ("No program loaded."); if (sr_get_debug ()) printf_filtered ("gdbsim_create_inferior: exec_file \"%s\", args \"%s\"\n", - exec_file, args); - - if (exec_file == 0 || exec_bfd == 0) - error ("No exec file specified."); - - entry_pt = (CORE_ADDR) bfd_get_start_address (exec_bfd); + (exec_file ? exec_file: "(NULL)"), + args); gdbsim_kill (); remove_breakpoints (); init_wait_for_inferior (); - len = strlen (exec_file) + 1 + strlen (args) + 1 + /*slop*/ 10; - arg_buf = (char *) alloca (len); - arg_buf[0] = '\0'; - strcat (arg_buf, exec_file); - strcat (arg_buf, " "); - strcat (arg_buf, args); - argv = buildargv (arg_buf); - make_cleanup (freeargv, (char *) argv); - sim_create_inferior (gdbsim_desc, argv, env); + if (exec_file != NULL) + { + len = strlen (exec_file) + 1 + strlen (args) + 1 + /*slop*/ 10; + arg_buf = (char *) alloca (len); + arg_buf[0] = '\0'; + strcat (arg_buf, exec_file); + strcat (arg_buf, " "); + strcat (arg_buf, args); + argv = buildargv (arg_buf); + make_cleanup (freeargv, (char *) argv); + } + else + argv = NULL; + sim_create_inferior (gdbsim_desc, exec_bfd, argv, env); inferior_pid = 42; - insert_breakpoints (); /* Needed to get correct instruction in cache */ - proceed (entry_pt, TARGET_SIGNAL_DEFAULT, 0); + insert_breakpoints (); /* Needed to get correct instruction in cache */ + + clear_proceed_status (); + + /* NB: Entry point already set by sim_create_inferior. */ + proceed ((CORE_ADDR)-1, TARGET_SIGNAL_DEFAULT, 0); } /* The open routine takes the rest of the parameters from the command, @@ -517,19 +519,52 @@ gdbsim_open (args, from_tty) if (gdbsim_desc != NULL) unpush_target (&gdbsim_ops); - init_callbacks (); - - len = 7 + 1 + (args ? strlen (args) : 0) + 50; + len = (7 + 1 /* gdbsim */ + + strlen (" -E little") + + strlen (" --architecture=xxxxxxxxxx") + + (args ? strlen (args) : 0) + + 50) /* slack */; arg_buf = (char *) alloca (len); - sprintf (arg_buf, "gdbsim%s%s -E %s", - args ? " " : "", args ? args : "", - TARGET_BYTE_ORDER == BIG_ENDIAN ? "big" : "little"); + strcpy (arg_buf, "gdbsim"); /* 7 */ + /* Specify the byte order for the target when it is both selectable + and explicitly specified by the user (not auto detected). */ +#ifdef TARGET_BYTE_ORDER_SELECTABLE + if (!target_byte_order_auto) + { + switch (TARGET_BYTE_ORDER) + { + case BIG_ENDIAN: + strcat (arg_buf, " -E big"); + break; + case LITTLE_ENDIAN: + strcat (arg_buf, " -E little"); + break; + default: + fatal ("Value of TARGET_BYTE_ORDER unknown"); + } + } +#endif + /* Specify the architecture of the target when it has been + explicitly specified */ + if (!target_architecture_auto) + { + strcat (arg_buf, " --architecture="); + strcat (arg_buf, target_architecture->printable_name); + } + /* finally, any explicit args */ + if (args) + { + strcat (arg_buf, " "); /* 1 */ + strcat (arg_buf, args); + } 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, exec_bfd, argv); + if (gdbsim_desc == 0) error ("unable to create simulator instance"); @@ -610,27 +645,50 @@ 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) +gdbsim_cntrl_c (signo) + int signo; { gdbsim_stop (); } @@ -640,13 +698,25 @@ gdbsim_wait (pid, status) int pid; struct target_waitstatus *status; { + static RETSIGTYPE (*prev_sigint) (); int sigrc = 0; enum sim_stop reason = sim_running; if (sr_get_debug ()) printf_filtered ("gdbsim_wait\n"); +#if defined (HAVE_SIGACTION) && defined (SA_RESTART) + { + struct sigaction sa, osa; + sa.sa_handler = gdbsim_cntrl_c; + sigemptyset (&sa.sa_mask); + sa.sa_flags = 0; + sigaction (SIGINT, &sa, &osa); + prev_sigint = osa.sa_handler; + } +#else prev_sigint = signal (SIGINT, gdbsim_cntrl_c); +#endif sim_resume (gdbsim_desc, resume_step, target_signal_to_host (resume_siggnal)); signal (SIGINT, prev_sigint); @@ -682,6 +752,10 @@ gdbsim_wait (pid, status) should be fixed. */ status->value.sig = target_signal_from_host (sigrc); break; + case sim_running: + case sim_polling: + /* FIXME: Is this correct? */ + break; } return inferior_pid; @@ -763,6 +837,55 @@ gdbsim_mourn_inferior () generic_mourn_inferior (); } +static int +gdbsim_insert_breakpoint (addr, contents_cache) + CORE_ADDR addr; + char *contents_cache; +{ +#ifdef SIM_HAS_BREAKPOINTS + SIM_RC retcode; + + retcode = sim_set_breakpoint (gdbsim_desc, addr); + + switch (retcode) + { + case SIM_RC_OK: + return 0; + case SIM_RC_INSUFFICIENT_RESOURCES: + return ENOMEM; + default: + return EIO; + } +#else + return memory_insert_breakpoint (addr, contents_cache); +#endif +} + +static int +gdbsim_remove_breakpoint (addr, contents_cache) + CORE_ADDR addr; + char *contents_cache; +{ +#ifdef SIM_HAS_BREAKPOINTS + SIM_RC retcode; + + retcode = sim_clear_breakpoint (gdbsim_desc, addr); + + switch (retcode) + { + case SIM_RC_OK: + case SIM_RC_UNKNOWN_BREAKPOINT: + return 0; + case SIM_RC_INSUFFICIENT_RESOURCES: + return ENOMEM; + default: + return EIO; + } +#else + return memory_remove_breakpoint (addr, contents_cache); +#endif +} + /* Pass the command argument through to the simulator verbatim. The simulator must do any command interpretation work. */ @@ -771,15 +894,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); } @@ -800,8 +930,8 @@ struct target_ops gdbsim_ops = { gdbsim_prepare_to_store, /* to_prepare_to_store */ gdbsim_xfer_inferior_memory, /* to_xfer_memory */ gdbsim_files_info, /* to_files_info */ - memory_insert_breakpoint, /* to_insert_breakpoint */ - memory_remove_breakpoint, /* to_remove_breakpoint */ + gdbsim_insert_breakpoint, /* to_insert_breakpoint */ + gdbsim_remove_breakpoint, /* to_remove_breakpoint */ NULL, /* to_terminal_init */ NULL, /* to_terminal_inferior */ NULL, /* to_terminal_ours_for_output */