X-Git-Url: http://drtracing.org/?a=blobdiff_plain;ds=sidebyside;f=gdb%2Fremote-sim.c;h=347dfd70131b03888bc9dd4faa6092063645d47e;hb=af0b2a3e85df9f49a3528e5b7578fcf9412f1acc;hp=29bfe1dc7e163d42312904db661ccf2e796725b4;hpb=b7a08269ca53323c5fe190370da281358dfee6b2;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/remote-sim.c b/gdb/remote-sim.c index 29bfe1dc7e..347dfd7013 100644 --- a/gdb/remote-sim.c +++ b/gdb/remote-sim.c @@ -1,6 +1,6 @@ /* Generic remote debugging interface for simulators. - Copyright (C) 1993-2018 Free Software Foundation, Inc. + Copyright (C) 1993-2020 Free Software Foundation, Inc. Contributed by Cygnus Support. Steve Chamberlain (sac@cygnus.com). @@ -31,6 +31,7 @@ #include #include "terminal.h" #include "target.h" +#include "process-stratum-target.h" #include "gdbcore.h" #include "gdb/callback.h" #include "gdb/remote-sim.h" @@ -40,7 +41,7 @@ #include "arch-utils.h" #include "readline/readline.h" #include "gdbthread.h" -#include "common/byte-vector.h" +#include "gdbsupport/byte-vector.h" /* Prototypes */ @@ -68,13 +69,49 @@ static void gdb_os_evprintf_filtered (host_callback *, const char *, va_list); static void gdb_os_error (host_callback *, const char *, ...) ATTRIBUTE_NORETURN; -void simulator_command (char *args, int from_tty); - /* Naming convention: sim_* are the interface to the simulator (see remote-sim.h). gdbsim_* are stuff which is internal to gdb. */ +/* Value of the next pid to allocate for an inferior. As indicated + elsewhere, its initial value is somewhat arbitrary; it's critical + though that it's not zero or negative. */ +static int next_pid; +#define INITIAL_PID 42000 + +/* Simulator-specific, per-inferior state. */ +struct sim_inferior_data { + explicit sim_inferior_data (SIM_DESC desc) + : gdbsim_desc (desc), + remote_sim_ptid (next_pid, 0, next_pid) + { + gdb_assert (remote_sim_ptid != null_ptid); + ++next_pid; + } + + ~sim_inferior_data (); + + /* Flag which indicates whether or not the program has been loaded. */ + int program_loaded = 0; + + /* Simulator descriptor for this inferior. */ + SIM_DESC gdbsim_desc; + + /* This is the ptid we use for this particular simulator instance. Its + value is somewhat arbitrary, as the simulator target don't have a + notion of tasks or threads, but we need something non-null to place + in inferior_ptid. For simulators which permit multiple instances, + we also need a unique identifier to use for each inferior. */ + ptid_t remote_sim_ptid; + + /* Signal with which to resume. */ + enum gdb_signal resume_siggnal = GDB_SIGNAL_0; + + /* Flag which indicates whether resume should step or not. */ + int resume_step = 0; +}; + static const target_info gdbsim_target_info = { "sim", N_("simulator"), @@ -82,10 +119,9 @@ static const target_info gdbsim_target_info = { }; struct gdbsim_target final - : public memory_breakpoint_target + : public memory_breakpoint_target { - gdbsim_target () - { to_stratum = process_stratum; } + gdbsim_target () = default; const target_info &info () const override { return gdbsim_target_info; } @@ -124,57 +160,26 @@ struct gdbsim_target final bool thread_alive (ptid_t ptid) override; - const char *pid_to_str (ptid_t) override; + std::string pid_to_str (ptid_t) override; bool has_all_memory () override; bool has_memory () override; - bool has_stack () override - { return default_child_has_stack (); } - - bool has_registers () override - { return default_child_has_registers (); } - - bool has_execution (ptid_t ptid) override - { return default_child_has_execution (ptid); } +private: + sim_inferior_data *get_inferior_data_by_ptid (ptid_t ptid, + int sim_instance_needed); + void resume_one_inferior (inferior *inf, bool step, gdb_signal siggnal); + void close_one_inferior (inferior *inf); }; static struct gdbsim_target gdbsim_ops; -static const struct inferior_data *sim_inferior_data_key; - -/* Simulator-specific, per-inferior state. */ -struct sim_inferior_data { - /* Flag which indicates whether or not the program has been loaded. */ - int program_loaded; - - /* Simulator descriptor for this inferior. */ - SIM_DESC gdbsim_desc; - - /* This is the ptid we use for this particular simulator instance. Its - value is somewhat arbitrary, as the simulator target don't have a - notion of tasks or threads, but we need something non-null to place - in inferior_ptid. For simulators which permit multiple instances, - we also need a unique identifier to use for each inferior. */ - ptid_t remote_sim_ptid; - - /* Signal with which to resume. */ - enum gdb_signal resume_siggnal; - - /* Flag which indicates whether resume should step or not. */ - int resume_step; -}; +static inferior_key sim_inferior_data_key; /* Flag indicating the "open" status of this module. It's set to 1 in gdbsim_open() and 0 in gdbsim_close(). */ static int gdbsim_is_open = 0; -/* Value of the next pid to allocate for an inferior. As indicated - elsewhere, its initial value is somewhat arbitrary; it's critical - though that it's not zero or negative. */ -static int next_pid; -#define INITIAL_PID 42000 - /* Argument list to pass to sim_open(). It is allocated in gdbsim_open() and deallocated in gdbsim_close(). The lifetime needs to extend beyond the call to gdbsim_open() due to the fact that other sim instances other @@ -185,22 +190,6 @@ static char **sim_argv = NULL; static host_callback gdb_callback; static int callbacks_initialized = 0; -/* Callback for iterate_over_inferiors. It checks to see if the sim - descriptor passed via ARG is the same as that for the inferior - designated by INF. Return true if so; false otherwise. */ - -static int -check_for_duplicate_sim_descriptor (struct inferior *inf, void *arg) -{ - struct sim_inferior_data *sim_data; - SIM_DESC new_sim_desc = (SIM_DESC) arg; - - sim_data = ((struct sim_inferior_data *) - inferior_data (inf, sim_inferior_data_key)); - - return (sim_data != NULL && sim_data->gdbsim_desc == new_sim_desc); -} - /* Flags indicating whether or not a sim instance is needed. One of these flags should be passed to get_sim_inferior_data(). */ @@ -213,8 +202,7 @@ static struct sim_inferior_data * get_sim_inferior_data (struct inferior *inf, int sim_instance_needed) { SIM_DESC sim_desc = NULL; - struct sim_inferior_data *sim_data - = (struct sim_inferior_data *) inferior_data (inf, sim_inferior_data_key); + struct sim_inferior_data *sim_data = sim_inferior_data_key.get (inf); /* Try to allocate a new sim instance, if needed. We do this ahead of a potential allocation of a sim_inferior_data struct in order to @@ -223,44 +211,39 @@ get_sim_inferior_data (struct inferior *inf, int sim_instance_needed) if (sim_instance_needed == SIM_INSTANCE_NEEDED && (sim_data == NULL || sim_data->gdbsim_desc == NULL)) { - struct inferior *idup; sim_desc = sim_open (SIM_OPEN_DEBUG, &gdb_callback, exec_bfd, sim_argv); if (sim_desc == NULL) error (_("Unable to create simulator instance for inferior %d."), inf->num); - idup = iterate_over_inferiors (check_for_duplicate_sim_descriptor, - sim_desc); - if (idup != NULL) + /* Check if the sim descriptor is the same as that of another + inferior. */ + for (inferior *other_inf : all_inferiors ()) { - /* We don't close the descriptor due to the fact that it's - shared with some other inferior. If we were to close it, - that might needlessly muck up the other inferior. Of - course, it's possible that the damage has already been - done... Note that it *will* ultimately be closed during - cleanup of the other inferior. */ - sim_desc = NULL; - error ( - _("Inferior %d and inferior %d would have identical simulator state.\n" - "(This simulator does not support the running of more than one inferior.)"), - inf->num, idup->num); + sim_inferior_data *other_sim_data + = sim_inferior_data_key.get (other_inf); + + if (other_sim_data != NULL + && other_sim_data->gdbsim_desc == sim_desc) + { + /* We don't close the descriptor due to the fact that it's + shared with some other inferior. If we were to close it, + that might needlessly muck up the other inferior. Of + course, it's possible that the damage has already been + done... Note that it *will* ultimately be closed during + cleanup of the other inferior. */ + sim_desc = NULL; + error ( +_("Inferior %d and inferior %d would have identical simulator state.\n" + "(This simulator does not support the running of more than one inferior.)"), + inf->num, other_inf->num); + } } } if (sim_data == NULL) { - sim_data = XCNEW(struct sim_inferior_data); - set_inferior_data (inf, sim_inferior_data_key, sim_data); - - /* Allocate a ptid for this inferior. */ - sim_data->remote_sim_ptid = ptid_build (next_pid, 0, next_pid); - next_pid++; - - /* Initialize the other instance variables. */ - sim_data->program_loaded = 0; - sim_data->gdbsim_desc = sim_desc; - sim_data->resume_siggnal = GDB_SIGNAL_0; - sim_data->resume_step = 0; + sim_data = sim_inferior_data_key.emplace (inf, sim_desc); } else if (sim_desc) { @@ -277,16 +260,17 @@ get_sim_inferior_data (struct inferior *inf, int sim_instance_needed) inferior in question. Return NULL when no inferior is found or when ptid has a zero or negative pid component. */ -static struct sim_inferior_data * -get_sim_inferior_data_by_ptid (ptid_t ptid, int sim_instance_needed) +sim_inferior_data * +gdbsim_target::get_inferior_data_by_ptid (ptid_t ptid, + int sim_instance_needed) { struct inferior *inf; - int pid = ptid_get_pid (ptid); + int pid = ptid.pid (); if (pid <= 0) return NULL; - inf = find_inferior_pid (pid); + inf = find_inferior_pid (this, pid); if (inf) return get_sim_inferior_data (inf, sim_instance_needed); @@ -296,20 +280,10 @@ get_sim_inferior_data_by_ptid (ptid_t ptid, int sim_instance_needed) /* Free the per-inferior simulator data. */ -static void -sim_inferior_data_cleanup (struct inferior *inf, void *data) +sim_inferior_data::~sim_inferior_data () { - struct sim_inferior_data *sim_data = (struct sim_inferior_data *) data; - - if (sim_data != NULL) - { - if (sim_data->gdbsim_desc) - { - sim_close (sim_data->gdbsim_desc, 0); - sim_data->gdbsim_desc = NULL; - } - xfree (sim_data); - } + if (gdbsim_desc) + sim_close (gdbsim_desc, 0); } static void @@ -377,10 +351,7 @@ end_callbacks (void) static int gdb_os_write_stdout (host_callback *p, const char *buf, int len) { - int i; - char b[2]; - - ui_file_write (gdb_stdtarg, buf, len); + gdb_stdtarg->write (buf, len); return len; } @@ -389,7 +360,7 @@ gdb_os_write_stdout (host_callback *p, const char *buf, int len) static void gdb_os_flush_stdout (host_callback *p) { - gdb_flush (gdb_stdtarg); + gdb_stdtarg->flush (); } /* GDB version of os_write_stderr callback. */ @@ -404,7 +375,7 @@ gdb_os_write_stderr (host_callback *p, const char *buf, int len) { b[0] = buf[i]; b[1] = 0; - fputs_unfiltered (b, gdb_stdtargerr); + gdb_stdtargerr->puts (b); } return len; } @@ -414,7 +385,7 @@ gdb_os_write_stderr (host_callback *p, const char *buf, int len) static void gdb_os_flush_stderr (host_callback *p) { - gdb_flush (gdb_stdtargerr); + gdb_stdtargerr->flush (); } /* GDB version of printf_filtered callback. */ @@ -469,7 +440,7 @@ void gdbsim_target::fetch_registers (struct regcache *regcache, int regno) { struct gdbarch *gdbarch = regcache->arch (); - struct inferior *inf = find_inferior_ptid (regcache->ptid ()); + struct inferior *inf = find_inferior_ptid (this, regcache->ptid ()); struct sim_inferior_data *sim_data = get_sim_inferior_data (inf, SIM_INSTANCE_NEEDED); @@ -538,7 +509,7 @@ void gdbsim_target::store_registers (struct regcache *regcache, int regno) { struct gdbarch *gdbarch = regcache->arch (); - struct inferior *inf = find_inferior_ptid (regcache->ptid ()); + struct inferior *inf = find_inferior_ptid (this, regcache->ptid ()); struct sim_inferior_data *sim_data = get_sim_inferior_data (inf, SIM_INSTANCE_NEEDED); @@ -660,7 +631,7 @@ gdbsim_target::create_inferior (const char *exec_file, (exec_file ? exec_file : "(NULL)"), args); - if (ptid_equal (inferior_ptid, sim_data->remote_sim_ptid)) + if (inferior_ptid == sim_data->remote_sim_ptid) kill (); remove_breakpoints (); init_wait_for_inferior (); @@ -677,17 +648,14 @@ gdbsim_target::create_inferior (const char *exec_file, built_argv.reset (arg_buf); } - if (!have_inferiors ()) - init_thread_list (); - if (sim_create_inferior (sim_data->gdbsim_desc, exec_bfd, built_argv.get (), env) != SIM_RC_OK) error (_("Unable to create sim inferior.")); inferior_ptid = sim_data->remote_sim_ptid; - inferior_appeared (current_inferior (), ptid_get_pid (inferior_ptid)); - add_thread_silent (inferior_ptid); + inferior_appeared (current_inferior (), inferior_ptid.pid ()); + add_thread_silent (this, inferior_ptid); insert_breakpoints (); /* Needed to get correct instruction in cache. */ @@ -766,19 +734,18 @@ gdbsim_target_open (const char *args, int from_tty) } gdb_argv argv (arg_buf); - sim_argv = argv.get (); + sim_argv = argv.release (); init_callbacks (); gdbsim_desc = sim_open (SIM_OPEN_DEBUG, &gdb_callback, exec_bfd, sim_argv); if (gdbsim_desc == 0) { + freeargv (sim_argv); sim_argv = NULL; error (_("unable to create simulator instance")); } - argv.release (); - /* Reset the pid numberings for this batch of sim instances. */ next_pid = INITIAL_PID; @@ -799,34 +766,29 @@ gdbsim_target_open (const char *args, int from_tty) gdbsim_is_open = 1; } -/* Callback for iterate_over_inferiors. Called (indirectly) by - gdbsim_close(). */ +/* Helper for gdbsim_target::close. */ -static int -gdbsim_close_inferior (struct inferior *inf, void *arg) +void +gdbsim_target::close_one_inferior (inferior *inf) { - struct sim_inferior_data *sim_data - = (struct sim_inferior_data *) inferior_data (inf, sim_inferior_data_key); + struct sim_inferior_data *sim_data = sim_inferior_data_key.get (inf); if (sim_data != NULL) { ptid_t ptid = sim_data->remote_sim_ptid; - sim_inferior_data_cleanup (inf, sim_data); - set_inferior_data (inf, sim_inferior_data_key, NULL); + sim_inferior_data_key.clear (inf); /* Having a ptid allocated and stored in remote_sim_ptid does not mean that a corresponding inferior was ever created. Thus we need to verify the existence of an inferior using the pid in question before setting inferior_ptid via switch_to_thread() or mourning the inferior. */ - if (find_inferior_ptid (ptid) != NULL) + if (find_inferior_ptid (this, ptid) != NULL) { - switch_to_thread (ptid); + switch_to_thread (this, ptid); generic_mourn_inferior (); } } - - return 0; } /* Close out all files and local state before this target loses control. */ @@ -834,13 +796,11 @@ gdbsim_close_inferior (struct inferior *inf, void *arg) void gdbsim_target::close () { - struct sim_inferior_data *sim_data - = get_sim_inferior_data (current_inferior (), SIM_INSTANCE_NOT_NEEDED); - if (remote_debug) fprintf_unfiltered (gdb_stdlog, "gdbsim_close\n"); - iterate_over_inferiors (gdbsim_close_inferior, NULL); + for (inferior *inf : all_inferiors (this)) + close_one_inferior (inf); if (sim_argv != NULL) { @@ -876,45 +836,30 @@ gdbsim_target::detach (inferior *inf, int 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. */ -struct resume_data -{ - enum gdb_signal siggnal; - int step; -}; - -static int -gdbsim_resume_inferior (struct inferior *inf, void *arg) +void +gdbsim_target::resume_one_inferior (inferior *inf, bool step, + gdb_signal siggnal) { struct sim_inferior_data *sim_data = get_sim_inferior_data (inf, SIM_INSTANCE_NOT_NEEDED); - struct resume_data *rd = (struct resume_data *) arg; if (sim_data) { - sim_data->resume_siggnal = rd->siggnal; - sim_data->resume_step = rd->step; + sim_data->resume_siggnal = siggnal; + sim_data->resume_step = step; if (remote_debug) fprintf_unfiltered (gdb_stdlog, _("gdbsim_resume: pid %d, step %d, signal %d\n"), - inf->pid, rd->step, rd->siggnal); + inf->pid, step, siggnal); } - - /* When called from iterate_over_inferiors, a zero return causes the - iteration process to proceed until there are no more inferiors to - consider. */ - return 0; } void gdbsim_target::resume (ptid_t ptid, int step, enum gdb_signal siggnal) { - struct resume_data rd; struct sim_inferior_data *sim_data - = get_sim_inferior_data_by_ptid (ptid, SIM_INSTANCE_NOT_NEEDED); - - rd.siggnal = siggnal; - rd.step = step; + = get_inferior_data_by_ptid (ptid, SIM_INSTANCE_NOT_NEEDED); /* We don't access any sim_data members within this function. What's of interest is whether or not the call to @@ -924,9 +869,12 @@ gdbsim_target::resume (ptid_t ptid, int step, enum gdb_signal siggnal) either have multiple inferiors to resume or an error condition. */ if (sim_data) - gdbsim_resume_inferior (find_inferior_ptid (ptid), &rd); - else if (ptid_equal (ptid, minus_one_ptid)) - iterate_over_inferiors (gdbsim_resume_inferior, &rd); + resume_one_inferior (find_inferior_ptid (this, ptid), step, siggnal); + else if (ptid == minus_one_ptid) + { + for (inferior *inf : all_inferiors (this)) + resume_one_inferior (inf, step, siggnal); + } else error (_("The program is not being run.")); } @@ -940,30 +888,17 @@ gdbsim_target::resume (ptid_t ptid, int step, enum gdb_signal siggnal) For simulators that do not support this operation, just abort. */ -static int -gdbsim_interrupt_inferior (struct inferior *inf, void *arg) +void +gdbsim_target::interrupt () { - struct sim_inferior_data *sim_data - = get_sim_inferior_data (inf, SIM_INSTANCE_NEEDED); - - if (sim_data) + for (inferior *inf : all_inferiors ()) { - if (!sim_stop (sim_data->gdbsim_desc)) - { + sim_inferior_data *sim_data + = get_sim_inferior_data (inf, SIM_INSTANCE_NEEDED); + + if (sim_data != nullptr && !sim_stop (sim_data->gdbsim_desc)) quit (); - } } - - /* When called from iterate_over_inferiors, a zero return causes the - iteration process to proceed until there are no more inferiors to - consider. */ - return 0; -} - -void -gdbsim_target::interrupt () -{ - iterate_over_inferiors (gdbsim_interrupt_inferior, NULL); } /* GDB version of os_poll_quit callback. @@ -1001,15 +936,15 @@ gdbsim_target::wait (ptid_t ptid, struct target_waitstatus *status, int options) /* This target isn't able to (yet) resume more than one inferior at a time. When ptid is minus_one_ptid, just use the current inferior. If we're given an explicit pid, we'll try to find it and use that instead. */ - if (ptid_equal (ptid, minus_one_ptid)) + if (ptid == minus_one_ptid) sim_data = get_sim_inferior_data (current_inferior (), SIM_INSTANCE_NEEDED); else { - sim_data = get_sim_inferior_data_by_ptid (ptid, SIM_INSTANCE_NEEDED); + sim_data = get_inferior_data_by_ptid (ptid, SIM_INSTANCE_NEEDED); if (sim_data == NULL) error (_("Unable to wait for pid %d. Inferior not found."), - ptid_get_pid (ptid)); + ptid.pid ()); inferior_ptid = ptid; } @@ -1066,7 +1001,7 @@ gdbsim_target::wait (ptid_t ptid, struct target_waitstatus *status, int options) break; } - return inferior_ptid; + return sim_data->remote_sim_ptid; } /* Get ready to modify the registers array. On machines which store @@ -1187,9 +1122,6 @@ gdbsim_target::files_info () void gdbsim_target::mourn_inferior () { - struct sim_inferior_data *sim_data - = get_sim_inferior_data (current_inferior (), SIM_INSTANCE_NOT_NEEDED); - if (remote_debug) fprintf_unfiltered (gdb_stdlog, "gdbsim_mourn_inferior:\n"); @@ -1200,7 +1132,7 @@ gdbsim_target::mourn_inferior () /* Pass the command argument through to the simulator verbatim. The simulator must do any command interpretation work. */ -void +static void simulator_command (const char *args, int from_tty) { struct sim_inferior_data *sim_data; @@ -1215,8 +1147,7 @@ simulator_command (const char *args, int from_tty) thus allocating memory that would not be garbage collected until the ultimate destruction of the associated inferior. */ - sim_data = ((struct sim_inferior_data *) - inferior_data (current_inferior (), sim_inferior_data_key)); + sim_data = sim_inferior_data_key.get (current_inferior ()); if (sim_data == NULL || sim_data->gdbsim_desc == NULL) { @@ -1247,8 +1178,7 @@ sim_command_completer (struct cmd_list_element *ignore, { struct sim_inferior_data *sim_data; - sim_data = ((struct sim_inferior_data *) - inferior_data (current_inferior (), sim_inferior_data_key)); + sim_data = sim_inferior_data_key.get (current_inferior ()); if (sim_data == NULL || sim_data->gdbsim_desc == NULL) return; @@ -1290,22 +1220,21 @@ bool gdbsim_target::thread_alive (ptid_t ptid) { struct sim_inferior_data *sim_data - = get_sim_inferior_data_by_ptid (ptid, SIM_INSTANCE_NOT_NEEDED); + = get_inferior_data_by_ptid (ptid, SIM_INSTANCE_NOT_NEEDED); if (sim_data == NULL) return false; - if (ptid_equal (ptid, sim_data->remote_sim_ptid)) + if (ptid == sim_data->remote_sim_ptid) /* The simulators' task is always alive. */ return true; return false; } -/* Convert a thread ID to a string. Returns the string in a static - buffer. */ +/* Convert a thread ID to a string. */ -const char * +std::string gdbsim_target::pid_to_str (ptid_t ptid) { return normal_pid_to_str (ptid); @@ -1337,8 +1266,9 @@ gdbsim_target::has_memory () return true; } +void _initialize_remote_sim (); void -_initialize_remote_sim (void) +_initialize_remote_sim () { struct cmd_list_element *c; @@ -1347,7 +1277,4 @@ _initialize_remote_sim (void) c = add_com ("sim", class_obscure, simulator_command, _("Send a command to the simulator.")); set_cmd_completer (c, sim_command_completer); - - sim_inferior_data_key - = register_inferior_data_with_cleanup (NULL, sim_inferior_data_cleanup); }