diff options
Diffstat (limited to 'gdb/remote-sp64sim.c')
-rw-r--r-- | gdb/remote-sp64sim.c | 317 |
1 files changed, 168 insertions, 149 deletions
diff --git a/gdb/remote-sp64sim.c b/gdb/remote-sp64sim.c index 7c222d7..e975c74 100644 --- a/gdb/remote-sp64sim.c +++ b/gdb/remote-sp64sim.c @@ -1,7 +1,7 @@ /* Generic remote debugging interface for simulators. Copyright 1993 Free Software Foundation, Inc. - Contributed by Cygnus Support. Hacked from Steve Chamberlain's Z8000 work - by Doug Evans. (dje@cygnus.com). + Contributed by Cygnus Support. + Steve Chamberlain (sac@cygnus.com) and Doug Evans (dje@cygnus.com). This file is part of GDB. @@ -32,70 +32,20 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "terminal.h" #include "target.h" #include "gdbcore.h" -#include "simif.h" +#include "remote-sim.h" /* Naming conventions: - sim_xxx are internal objects that describe top level interfaces to the - simulator. + simif_xxx are internal objects that describe top level interfaces to the + simulator (simif for SIMulator InterFace, duh...). - simif_xxx are external counterparts to the sim_xxx objects that must be - provided by the simulator (simif for SIMulator InterFace, duh...). + sim_xxx are external counterparts to the simif_xxx objects that must be + provided by the simulator. - A complete list of them is: - - --- Fetch one register and store the raw value in BUF. - -int simif_fetch_register (int regno, char *buf); - - --- Store VAL in one register. - -int simif_store_register (int regno, char *val); - - --- Complete terminate the simulator. This includes freeing all memory, - closing all open files, and releasing all mmap'd memory. - -int simif_kill (void); - - --- Load program PROG into the simulator. - -int simif_load (bfd *abfd, char *prog); - - --- Set the arguments and environment for the program loaded into the - simulator. ARGV and ENV are NULL terminated lists of pointers. - -int simif_set_args (char **argv, char **env); - - --- Initialize the simulator. This function is called when the simulator - is selected from the command line. ARGS is passed from the command line - and can be used to select whatever run time options the simulator provides. - ARGS is the raw character string and must be parsed by the simulator. - -int simif_open (char *args); - - --- Start running the program, or resume it after a breakpoint. - FIXME: What are A and B? - -int simif_resume (int a, int b); - - --- Fetch the reason why the program stopped running (breakpoint, signal, - etc.) - -WAITTYPE simif_stop_signal (void); - - --- Write some data into the program's memory. - Result is 0 for success, nonzero for failure. - -int simif_write (CORE_ADDR memaddr, char *myaddr, int len); - - --- Read some data from the program's memory. - Result is 0 for success, nonzero for failure. - -int simif_read (CORE_ADDR memaddr, char *myaddr, int len); -*/ + See simif.h for a description. */ /* Forward data declarations */ -extern struct target_ops sim_ops; +extern struct target_ops simif_ops; int sim_verbose = 0; /* available to the simulator to use */ @@ -104,81 +54,78 @@ static int program_loaded = 0; static void dump_mem (); static void -sim_fetch_register (regno) +simif_fetch_register (regno) int regno; { if (regno == -1) { - if (sim_verbose) - printf_filtered ("sim_fetch_register: %d\n", regno); - /* FIXME: Where did the 16 come from and what does it need to be? */ - for (regno = 0; regno < 16; regno++) - sim_fetch_register (regno); + for (regno = 0; regno < NUM_REGS; regno++) + simif_fetch_register (regno); } else { char buf[MAX_REGISTER_RAW_SIZE]; - simif_fetch_register (regno, buf); + sim_fetch_register (regno, buf); supply_register (regno, buf); if (sim_verbose) { - printf_filtered ("sim_fetch_register: %d", regno); - dump_mem (buf, sizeof (REGISTER_TYPE)); + printf_filtered ("simif_fetch_register: %d", regno); + /* FIXME: We could print something more intelligible. */ + dump_mem (buf, REGISTER_RAW_SIZE (regno)); } } } static void -sim_store_register (regno) +simif_store_register (regno) int regno; { if (regno == -1) { - if (sim_verbose) - printf_filtered ("sim_store_register: %d\n", regno); - /* FIXME: 16? */ - for (regno = 0; regno < 16; regno++) - sim_store_register (regno); + for (regno = 0; regno < NUM_REGS; regno++) + simif_store_register (regno); } else { - char value[sizeof (REGISTER_TYPE)]; + /* FIXME: Until read_register() returns LONGEST, we have this. */ + char value[MAX_REGISTER_RAW_SIZE]; read_register_gen (regno, value); - SWAP_TARGET_AND_HOST (value, sizeof (REGISTER_TYPE)); - simif_store_register (regno, value); + SWAP_TARGET_AND_HOST (value, REGISTER_RAW_SIZE (regno)); + sim_store_register (regno, value); if (sim_verbose) { - printf_filtered ("sim_store_register: %d", regno); - dump_mem (value, sizeof (REGISTER_TYPE)); + printf_filtered ("simif_store_register: %d", regno); + /* FIXME: We could print something more intelligible. */ + dump_mem (value, REGISTER_RAW_SIZE (regno)); } } } static void -sim_kill (arg,from_tty) -char *arg; -int from_tty; +simif_kill () { if (sim_verbose) - printf_filtered ("sim_kill: arg \"%s\"\n", arg); + printf_filtered ("simif_kill\n"); - simif_kill (); /* close fd's, remove mappings */ + sim_kill (); /* close fd's, remove mappings */ inferior_pid = 0; } -/* Load program PROG into the sim. */ +/* Load an executable file into the target process. This is expected to + not only bring new code into the target process, but also to update + GDB's symbol tables to match. */ static void -sim_load (prog, fromtty) +simif_load (prog, fromtty) char *prog; int fromtty; { bfd *abfd; if (sim_verbose) - printf_filtered ("sim_load: prog \"%s\"\n", prog); + printf_filtered ("simif_load: prog \"%s\"\n", prog); inferior_pid = 0; program_loaded = 0; @@ -187,22 +134,69 @@ sim_load (prog, fromtty) if (!abfd) error ("Unable to open file %s.", prog); - if (bfd_check_format (abfd, bfd_object) ==0) + if (bfd_check_format (abfd, bfd_object) == 0) error ("File is not an object file."); - if (simif_load (abfd, prog) != 0) + if (sim_load (abfd, prog) != 0) return; program_loaded = 1; - simif_set_pc (abfd->start_address); + sim_set_pc (abfd->start_address); +} + +/* + * This is a utility routine that sim_load() can call to do the work. + * The result is 0 for success, non-zero for failure. + * + * Eg: int sim_load (bfd *bfd, char *prog) { return sim_load_standard (bfd); } + */ + +sim_load_standard (abfd) + bfd *abfd; +{ + asection *s; + + s = abfd->sections; + while (s != (asection *)NULL) + { + if (s->flags & SEC_LOAD) + { + int i; + int delta = 4096; + char *buffer = xmalloc (delta); + printf_filtered ("%s\t: 0x%4x .. 0x%4x ", + s->name, s->vma, s->vma + s->_raw_size); + for (i = 0; i < s->_raw_size; i+= delta) + { + int sub_delta = delta; + if (sub_delta > s->_raw_size - i) + sub_delta = s->_raw_size - i ; + + bfd_get_section_contents (abfd, s, buffer, i, sub_delta); + sim_write (s->vma + i, buffer, sub_delta); + printf_filtered ("*"); + fflush (stdout); + } + printf_filtered ("\n"); + free (buffer); + } + s = s->next; + } + + return 0; } +/* Start an inferior process and set inferior_pid to its pid. + EXEC_FILE is the file to run. + ALLARGS is a string containing the arguments to the program. + ENV is the environment vector to pass. Errors reported with error(). + On VxWorks and various standalone systems, we ignore exec_file. */ /* This is called not only when we first attach, but also when the user types "run" after having attached. */ static void -sim_create_inferior (exec_file, args, env) +simif_create_inferior (exec_file, args, env) char *exec_file; char *args; char **env; @@ -214,7 +208,7 @@ sim_create_inferior (exec_file, args, env) error ("No program loaded."); if (sim_verbose) - printf_filtered ("sim_create_inferior: exec_file \"%s\", args \"%s\"\n", + printf_filtered ("simif_create_inferior: exec_file \"%s\", args \"%s\"\n", exec_file, args); if (exec_file == 0 || exec_bfd == 0) @@ -222,7 +216,7 @@ sim_create_inferior (exec_file, args, env) entry_pt = (int) bfd_get_start_address (exec_bfd); - sim_kill (NULL, NULL); + simif_kill (NULL, NULL); remove_breakpoints (); init_wait_for_inferior (); @@ -234,92 +228,112 @@ sim_create_inferior (exec_file, args, env) strcat (arg_buf, args); argv = buildargv (arg_buf); make_cleanup (freeargv, (char *) argv); - simif_set_args (argv, env); + if (sim_set_args (argv, env) != 0) + return; inferior_pid = 42; insert_breakpoints (); /* Needed to get correct instruction in cache */ proceed (entry_pt, -1, 0); } +/* The open routine takes the rest of the parameters from the command, + and (if successful) pushes a new target onto the stack. + Targets should supply this routine, if only to provide an error message. */ /* Called when selecting the simulator. EG: (gdb) target sim name. */ static void -sim_open (args, from_tty) +simif_open (args, from_tty) char *args; int from_tty; { if (sim_verbose) - printf_filtered ("sim_open: args \"%s\"\n", args); + printf_filtered ("simif_open: args \"%s\"\n", args); - if (simif_open (args) != 0) + if (sim_open (args) != 0) { error ("Unable to initialize simulator (insufficient memory?)."); return; } - push_target (&sim_ops); + push_target (&simif_ops); target_fetch_registers (-1); + /* FIXME: check from_tty here? */ printf_filtered ("Connected to the simulator.\n"); } +/* Does whatever cleanup is required for a target that we are no longer + going to be calling. Argument says whether we are quitting gdb and + should not get hung in case of errors, or whether we want a clean + termination even if it takes a while. This routine is automatically + always called just before a routine is popped off the target stack. + Closing file descriptors and freeing memory are typical things it should + do. */ /* Close out all files and local state before this target loses control. */ static void -sim_close (quitting) +simif_close (quitting) int quitting; { if (sim_verbose) - printf_filtered ("sim_close: quitting %d\n", quitting); + printf_filtered ("simif_close: quitting %d\n", quitting); program_loaded = 0; - /* FIXME: Need to call simif_close() to close all files and + /* FIXME: Need to call sim_close() to close all files and delete all mappings. */ } +/* Takes a program previously attached to and detaches it. + The program may resume execution (some targets do, some don't) and will + no longer stop on signals, etc. We better not have left any breakpoints + in the program or it'll die when it hits one. ARGS is arguments + typed by the user (e.g. a signal to send the process). FROM_TTY + says whether to be verbose or not. */ /* Terminate the open connection to the remote debugger. - Use this when you want to detach and do something else - with your gdb. */ + Use this when you want to detach and do something else with your gdb. */ static void -sim_detach (args,from_tty) +simif_detach (args,from_tty) char *args; int from_tty; { if (sim_verbose) - printf_filtered ("sim_detach: args \"%s\"\n", args); + printf_filtered ("simif_detach: args \"%s\"\n", args); - pop_target (); /* calls sim_close to do the real work */ + pop_target (); /* calls simif_close to do the real work */ if (from_tty) printf_filtered ("Ending simulator %s debugging\n", target_shortname); } -/* Tell the remote machine to resume. */ -/* FIXME: What are A and B? */ +/* Resume execution of the target process. STEP says whether to single-step + or to run free; SIGGNAL is the signal value (e.g. SIGINT) to be given + to the target, or zero for no signal. */ static void -sim_resume (a,b) +simif_resume (step, siggnal) + int step, siggnal; { if (sim_verbose) - printf_filtered ("sim_resume: %d/%d\n", a, b); + printf_filtered ("simif_resume: step %d, signal %d\n", step, siggnal); - simif_resume (a, b); + sim_resume (step, siggnal); } -/* Wait until the remote machine stops, then return, - storing status in STATUS just as `wait' would. */ +/* 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 int -sim_wait (status) +simif_wait (status) WAITTYPE *status; { if (sim_verbose) - printf_filtered ("sim_wait: "); + printf_filtered ("simif_wait: "); #if 1 - *status = simif_stop_signal (); + *status = sim_stop_signal (); #else - WSETSTOP (*status, simif_stop_signal ()); + WSETSTOP (*status, sim_stop_signal ()); #endif if (sim_verbose) printf_filtered ("status %d\n", *status); @@ -333,45 +347,46 @@ sim_wait (status) debugged. */ static void -sim_prepare_to_store () +simif_prepare_to_store () { /* Do nothing, since we can store individual regs */ } static int -sim_xfer_inferior_memory (memaddr, myaddr, len, write, target) +simif_xfer_inferior_memory (memaddr, myaddr, len, write, target) CORE_ADDR memaddr; char *myaddr; int len; int write; struct target_ops *target; /* ignored */ { + if (! program_loaded) + error ("No program loaded."); + if (sim_verbose) { - printf_filtered ("sim_xfer_inferior_memory: myaddr 0x%x, memaddr 0x%x, len %d, write %d\n", + printf_filtered ("simif_xfer_inferior_memory: myaddr 0x%x, memaddr 0x%x, len %d, write %d\n", myaddr, memaddr, len, write); if (sim_verbose && write) dump_mem(myaddr, len); } - if (! program_loaded) - error ("No program loaded."); - if (write) { - len = simif_write (memaddr, myaddr, len); + len = sim_write (memaddr, myaddr, len); } else { - len = simif_read (memaddr, myaddr, len); - if (sim_verbose && len > 0) + len = sim_read (memaddr, myaddr, len); + if (sim_verbose && len > 0) dump_mem(myaddr, len); } return len; } static void -sim_files_info () +simif_files_info (target) + struct target_ops *target; { char *file = "nothing"; @@ -379,19 +394,23 @@ sim_files_info () file = bfd_get_filename (exec_bfd); if (sim_verbose) - printf_filtered ("sim_files_info: file \"%s\"\n", file); + printf_filtered ("simif_files_info: file \"%s\"\n", file); if (exec_bfd) - printf_filtered ("\tAttached to %s running program %s\n", - target_shortname, file); + { + printf_filtered ("\tAttached to %s running program %s\n", + target_shortname, file); + sim_info (); + } } -/* Clear the sims notion of what the break points are */ +/* Clear the sims notion of what the break points are. */ + static void -sim_mourn () +simif_mourn_inferior () { if (sim_verbose) - printf_filtered ("sim_mourn:\n"); + printf_filtered ("simif_mourn_inferior:\n"); remove_breakpoints (); generic_mourn_inferior (); @@ -399,23 +418,23 @@ sim_mourn () /* Define the target subroutine names */ -struct target_ops sim_ops = +struct target_ops simif_ops = { - "sim", "Simulator", - "Use the Simulator", - sim_open, sim_close, - 0, sim_detach, sim_resume, sim_wait, /* attach */ - sim_fetch_register, sim_store_register, - sim_prepare_to_store, - sim_xfer_inferior_memory, - sim_files_info, + "sim", "simulator", + "Use the simulator", + simif_open, simif_close, + 0, simif_detach, simif_resume, simif_wait, /* attach */ + simif_fetch_register, simif_store_register, + simif_prepare_to_store, + simif_xfer_inferior_memory, + simif_files_info, 0, 0, /* Breakpoints */ 0, 0, 0, 0, 0, /* Terminal handling */ - sim_kill, /* FIXME, kill */ - sim_load, + simif_kill, /* FIXME, kill */ + simif_load, 0, /* lookup_symbol */ - sim_create_inferior, /* create_inferior */ - sim_mourn, /* mourn_inferior FIXME */ + simif_create_inferior, /* create_inferior */ + simif_mourn_inferior, /* mourn_inferior FIXME */ 0, /* can_run */ 0, /* notice_signals */ process_stratum, 0, /* next */ @@ -425,7 +444,7 @@ struct target_ops sim_ops = }; static void -sim_snoop () +simif_snoop () { sim_verbose = ! sim_verbose; if (sim_verbose) @@ -440,8 +459,8 @@ sim_snoop () void _initialize_remote_sim () { - add_target (&sim_ops); - add_com ("snoop", class_obscure, sim_snoop, + add_target (&simif_ops); + add_com ("snoop", class_obscure, simif_snoop, "Show what commands are going to the simulator"); } |