|  | /* Memory-access and commands for "inferior" process, for GDB. | 
|  |  | 
|  | Copyright (C) 1986-2023 Free Software Foundation, Inc. | 
|  |  | 
|  | This file is part of GDB. | 
|  |  | 
|  | This program is free software; you can redistribute it and/or modify | 
|  | it under the terms of the GNU General Public License as published by | 
|  | the Free Software Foundation; either version 3 of the License, or | 
|  | (at your option) any later version. | 
|  |  | 
|  | This program is distributed in the hope that it will be useful, | 
|  | but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
|  | GNU General Public License for more details. | 
|  |  | 
|  | You should have received a copy of the GNU General Public License | 
|  | along with this program.  If not, see <http://www.gnu.org/licenses/>.  */ | 
|  |  | 
|  | #include "defs.h" | 
|  | #include "arch-utils.h" | 
|  | #include "symtab.h" | 
|  | #include "gdbtypes.h" | 
|  | #include "frame.h" | 
|  | #include "inferior.h" | 
|  | #include "infrun.h" | 
|  | #include "gdbsupport/environ.h" | 
|  | #include "value.h" | 
|  | #include "gdbcmd.h" | 
|  | #include "symfile.h" | 
|  | #include "gdbcore.h" | 
|  | #include "target.h" | 
|  | #include "language.h" | 
|  | #include "objfiles.h" | 
|  | #include "completer.h" | 
|  | #include "ui-out.h" | 
|  | #include "regcache.h" | 
|  | #include "reggroups.h" | 
|  | #include "block.h" | 
|  | #include "solib.h" | 
|  | #include <ctype.h> | 
|  | #include "observable.h" | 
|  | #include "target-descriptions.h" | 
|  | #include "user-regs.h" | 
|  | #include "gdbthread.h" | 
|  | #include "valprint.h" | 
|  | #include "inline-frame.h" | 
|  | #include "tracepoint.h" | 
|  | #include "inf-loop.h" | 
|  | #include "linespec.h" | 
|  | #include "thread-fsm.h" | 
|  | #include "top.h" | 
|  | #include "interps.h" | 
|  | #include "skip.h" | 
|  | #include "gdbsupport/gdb_optional.h" | 
|  | #include "source.h" | 
|  | #include "cli/cli-style.h" | 
|  | #include "dwarf2/loc.h" | 
|  |  | 
|  | /* Local functions: */ | 
|  |  | 
|  | static void until_next_command (int); | 
|  |  | 
|  | static void step_1 (int, int, const char *); | 
|  |  | 
|  | #define ERROR_NO_INFERIOR \ | 
|  | if (!target_has_execution ()) error (_("The program is not being run.")); | 
|  |  | 
|  | /* Scratch area where string containing arguments to give to the | 
|  | program will be stored by 'set args'.  As soon as anything is | 
|  | stored, notice_args_set will move it into per-inferior storage. | 
|  | Arguments are separated by spaces.  Empty string (pointer to '\0') | 
|  | means no args.  */ | 
|  |  | 
|  | static std::string inferior_args_scratch; | 
|  |  | 
|  | /* Scratch area where the new cwd will be stored by 'set cwd'.  */ | 
|  |  | 
|  | static std::string inferior_cwd_scratch; | 
|  |  | 
|  | /* Scratch area where 'set inferior-tty' will store user-provided value. | 
|  | We'll immediate copy it into per-inferior storage.  */ | 
|  |  | 
|  | static std::string inferior_io_terminal_scratch; | 
|  |  | 
|  | /* Pid of our debugged inferior, or 0 if no inferior now. | 
|  | Since various parts of infrun.c test this to see whether there is a program | 
|  | being debugged it should be nonzero (currently 3 is used) for remote | 
|  | debugging.  */ | 
|  |  | 
|  | ptid_t inferior_ptid; | 
|  |  | 
|  | /* Nonzero if stopped due to completion of a stack dummy routine.  */ | 
|  |  | 
|  | enum stop_stack_kind stop_stack_dummy; | 
|  |  | 
|  | /* Nonzero if stopped due to a random (unexpected) signal in inferior | 
|  | process.  */ | 
|  |  | 
|  | int stopped_by_random_signal; | 
|  |  | 
|  |  | 
|  | /* Whether "finish" should print the value.  */ | 
|  |  | 
|  | static bool finish_print = true; | 
|  |  | 
|  |  | 
|  |  | 
|  | static void | 
|  | set_inferior_tty_command (const char *args, int from_tty, | 
|  | struct cmd_list_element *c) | 
|  | { | 
|  | /* CLI has assigned the user-provided value to inferior_io_terminal_scratch. | 
|  | Now route it to current inferior.  */ | 
|  | current_inferior ()->set_tty (inferior_io_terminal_scratch); | 
|  | } | 
|  |  | 
|  | static void | 
|  | show_inferior_tty_command (struct ui_file *file, int from_tty, | 
|  | struct cmd_list_element *c, const char *value) | 
|  | { | 
|  | /* Note that we ignore the passed-in value in favor of computing it | 
|  | directly.  */ | 
|  | const std::string &inferior_tty = current_inferior ()->tty (); | 
|  |  | 
|  | gdb_printf (file, | 
|  | _("Terminal for future runs of program being debugged " | 
|  | "is \"%s\".\n"), inferior_tty.c_str ()); | 
|  | } | 
|  |  | 
|  | void | 
|  | set_inferior_args_vector (int argc, char **argv) | 
|  | { | 
|  | gdb::array_view<char * const> args (argv, argc); | 
|  | std::string n = construct_inferior_arguments (args); | 
|  | current_inferior ()->set_args (std::move (n)); | 
|  | } | 
|  |  | 
|  | /* Notice when `set args' is run.  */ | 
|  |  | 
|  | static void | 
|  | set_args_command (const char *args, int from_tty, struct cmd_list_element *c) | 
|  | { | 
|  | /* CLI has assigned the user-provided value to inferior_args_scratch. | 
|  | Now route it to current inferior.  */ | 
|  | current_inferior ()->set_args (inferior_args_scratch); | 
|  | } | 
|  |  | 
|  | /* Notice when `show args' is run.  */ | 
|  |  | 
|  | static void | 
|  | show_args_command (struct ui_file *file, int from_tty, | 
|  | struct cmd_list_element *c, const char *value) | 
|  | { | 
|  | /* Note that we ignore the passed-in value in favor of computing it | 
|  | directly.  */ | 
|  | deprecated_show_value_hack (file, from_tty, c, | 
|  | current_inferior ()->args ().c_str ()); | 
|  | } | 
|  |  | 
|  | /* See gdbsupport/common-inferior.h.  */ | 
|  |  | 
|  | const std::string & | 
|  | get_inferior_cwd () | 
|  | { | 
|  | return current_inferior ()->cwd (); | 
|  | } | 
|  |  | 
|  | /* Handle the 'set cwd' command.  */ | 
|  |  | 
|  | static void | 
|  | set_cwd_command (const char *args, int from_tty, struct cmd_list_element *c) | 
|  | { | 
|  | current_inferior ()->set_cwd (inferior_cwd_scratch); | 
|  | } | 
|  |  | 
|  | /* Handle the 'show cwd' command.  */ | 
|  |  | 
|  | static void | 
|  | show_cwd_command (struct ui_file *file, int from_tty, | 
|  | struct cmd_list_element *c, const char *value) | 
|  | { | 
|  | const std::string &cwd = current_inferior ()->cwd (); | 
|  |  | 
|  | if (cwd.empty ()) | 
|  | gdb_printf (file, | 
|  | _("\ | 
|  | You have not set the inferior's current working directory.\n\ | 
|  | The inferior will inherit GDB's cwd if native debugging, or the remote\n\ | 
|  | server's cwd if remote debugging.\n")); | 
|  | else | 
|  | gdb_printf (file, | 
|  | _("Current working directory that will be used " | 
|  | "when starting the inferior is \"%s\".\n"), | 
|  | cwd.c_str ()); | 
|  | } | 
|  |  | 
|  |  | 
|  | /* This function strips the '&' character (indicating background | 
|  | execution) that is added as *the last* of the arguments ARGS of a | 
|  | command.  A copy of the incoming ARGS without the '&' is returned, | 
|  | unless the resulting string after stripping is empty, in which case | 
|  | NULL is returned.  *BG_CHAR_P is an output boolean that indicates | 
|  | whether the '&' character was found.  */ | 
|  |  | 
|  | static gdb::unique_xmalloc_ptr<char> | 
|  | strip_bg_char (const char *args, int *bg_char_p) | 
|  | { | 
|  | const char *p; | 
|  |  | 
|  | if (args == nullptr || *args == '\0') | 
|  | { | 
|  | *bg_char_p = 0; | 
|  | return nullptr; | 
|  | } | 
|  |  | 
|  | p = args + strlen (args); | 
|  | if (p[-1] == '&') | 
|  | { | 
|  | p--; | 
|  | while (p > args && isspace (p[-1])) | 
|  | p--; | 
|  |  | 
|  | *bg_char_p = 1; | 
|  | if (p != args) | 
|  | return gdb::unique_xmalloc_ptr<char> | 
|  | (savestring (args, p - args)); | 
|  | else | 
|  | return gdb::unique_xmalloc_ptr<char> (nullptr); | 
|  | } | 
|  |  | 
|  | *bg_char_p = 0; | 
|  | return make_unique_xstrdup (args); | 
|  | } | 
|  |  | 
|  | /* Common actions to take after creating any sort of inferior, by any | 
|  | means (running, attaching, connecting, et cetera).  The target | 
|  | should be stopped.  */ | 
|  |  | 
|  | void | 
|  | post_create_inferior (int from_tty) | 
|  | { | 
|  |  | 
|  | /* Be sure we own the terminal in case write operations are performed.  */ | 
|  | target_terminal::ours_for_output (); | 
|  |  | 
|  | infrun_debug_show_threads ("threads in the newly created inferior", | 
|  | current_inferior ()->non_exited_threads ()); | 
|  |  | 
|  | /* If the target hasn't taken care of this already, do it now. | 
|  | Targets which need to access registers during to_open, | 
|  | to_create_inferior, or to_attach should do it earlier; but many | 
|  | don't need to.  */ | 
|  | target_find_description (); | 
|  |  | 
|  | /* Now that we know the register layout, retrieve current PC.  But | 
|  | if the PC is unavailable (e.g., we're opening a core file with | 
|  | missing registers info), ignore it.  */ | 
|  | thread_info *thr = inferior_thread (); | 
|  |  | 
|  | thr->clear_stop_pc (); | 
|  | try | 
|  | { | 
|  | regcache *rc = get_thread_regcache (thr); | 
|  | thr->set_stop_pc (regcache_read_pc (rc)); | 
|  | } | 
|  | catch (const gdb_exception_error &ex) | 
|  | { | 
|  | if (ex.error != NOT_AVAILABLE_ERROR) | 
|  | throw; | 
|  | } | 
|  |  | 
|  | if (current_program_space->exec_bfd ()) | 
|  | { | 
|  | const unsigned solib_add_generation | 
|  | = current_program_space->solib_add_generation; | 
|  |  | 
|  | scoped_restore restore_in_initial_library_scan | 
|  | = make_scoped_restore (¤t_inferior ()->in_initial_library_scan, | 
|  | true); | 
|  |  | 
|  | /* Create the hooks to handle shared library load and unload | 
|  | events.  */ | 
|  | solib_create_inferior_hook (from_tty); | 
|  |  | 
|  | if (current_program_space->solib_add_generation == solib_add_generation) | 
|  | { | 
|  | /* The platform-specific hook should load initial shared libraries, | 
|  | but didn't.  FROM_TTY will be incorrectly 0 but such solib | 
|  | targets should be fixed anyway.  Call it only after the solib | 
|  | target has been initialized by solib_create_inferior_hook.  */ | 
|  |  | 
|  | if (info_verbose) | 
|  | warning (_("platform-specific solib_create_inferior_hook did " | 
|  | "not load initial shared libraries.")); | 
|  |  | 
|  | /* If the solist is global across processes, there's no need to | 
|  | refetch it here.  */ | 
|  | if (!gdbarch_has_global_solist (target_gdbarch ())) | 
|  | solib_add (nullptr, 0, auto_solib_add); | 
|  | } | 
|  | } | 
|  |  | 
|  | /* If the user sets watchpoints before execution having started, | 
|  | then she gets software watchpoints, because GDB can't know which | 
|  | target will end up being pushed, or if it supports hardware | 
|  | watchpoints or not.  breakpoint_re_set takes care of promoting | 
|  | watchpoints to hardware watchpoints if possible, however, if this | 
|  | new inferior doesn't load shared libraries or we don't pull in | 
|  | symbols from any other source on this target/arch, | 
|  | breakpoint_re_set is never called.  Call it now so that software | 
|  | watchpoints get a chance to be promoted to hardware watchpoints | 
|  | if the now pushed target supports hardware watchpoints.  */ | 
|  | breakpoint_re_set (); | 
|  |  | 
|  | gdb::observers::inferior_created.notify (current_inferior ()); | 
|  | } | 
|  |  | 
|  | /* Kill the inferior if already running.  This function is designed | 
|  | to be called when we are about to start the execution of the program | 
|  | from the beginning.  Ask the user to confirm that he wants to restart | 
|  | the program being debugged when FROM_TTY is non-null.  */ | 
|  |  | 
|  | static void | 
|  | kill_if_already_running (int from_tty) | 
|  | { | 
|  | if (inferior_ptid != null_ptid && target_has_execution ()) | 
|  | { | 
|  | /* Bail out before killing the program if we will not be able to | 
|  | restart it.  */ | 
|  | target_require_runnable (); | 
|  |  | 
|  | if (from_tty | 
|  | && !query (_("The program being debugged has been started already.\n\ | 
|  | Start it from the beginning? "))) | 
|  | error (_("Program not restarted.")); | 
|  | target_kill (); | 
|  | } | 
|  | } | 
|  |  | 
|  | /* See inferior.h.  */ | 
|  |  | 
|  | void | 
|  | prepare_execution_command (struct target_ops *target, int background) | 
|  | { | 
|  | /* If we get a request for running in the bg but the target | 
|  | doesn't support it, error out.  */ | 
|  | if (background && !target_can_async_p (target)) | 
|  | error (_("Asynchronous execution not supported on this target.")); | 
|  |  | 
|  | if (!background) | 
|  | { | 
|  | /* If we get a request for running in the fg, then we need to | 
|  | simulate synchronous (fg) execution.  Note no cleanup is | 
|  | necessary for this.  stdin is re-enabled whenever an error | 
|  | reaches the top level.  */ | 
|  | all_uis_on_sync_execution_starting (); | 
|  | } | 
|  | } | 
|  |  | 
|  | /* Determine how the new inferior will behave.  */ | 
|  |  | 
|  | enum run_how | 
|  | { | 
|  | /* Run program without any explicit stop during startup.  */ | 
|  | RUN_NORMAL, | 
|  |  | 
|  | /* Stop at the beginning of the program's main function.  */ | 
|  | RUN_STOP_AT_MAIN, | 
|  |  | 
|  | /* Stop at the first instruction of the program.  */ | 
|  | RUN_STOP_AT_FIRST_INSN | 
|  | }; | 
|  |  | 
|  | /* Implement the "run" command.  Force a stop during program start if | 
|  | requested by RUN_HOW.  */ | 
|  |  | 
|  | static void | 
|  | run_command_1 (const char *args, int from_tty, enum run_how run_how) | 
|  | { | 
|  | const char *exec_file; | 
|  | struct ui_out *uiout = current_uiout; | 
|  | struct target_ops *run_target; | 
|  | int async_exec; | 
|  |  | 
|  | dont_repeat (); | 
|  |  | 
|  | scoped_disable_commit_resumed disable_commit_resumed ("running"); | 
|  |  | 
|  | kill_if_already_running (from_tty); | 
|  |  | 
|  | init_wait_for_inferior (); | 
|  | clear_breakpoint_hit_counts (); | 
|  |  | 
|  | /* Clean up any leftovers from other runs.  Some other things from | 
|  | this function should probably be moved into target_pre_inferior.  */ | 
|  | target_pre_inferior (from_tty); | 
|  |  | 
|  | /* The comment here used to read, "The exec file is re-read every | 
|  | time we do a generic_mourn_inferior, so we just have to worry | 
|  | about the symbol file."  The `generic_mourn_inferior' function | 
|  | gets called whenever the program exits.  However, suppose the | 
|  | program exits, and *then* the executable file changes?  We need | 
|  | to check again here.  Since reopen_exec_file doesn't do anything | 
|  | if the timestamp hasn't changed, I don't see the harm.  */ | 
|  | reopen_exec_file (); | 
|  | reread_symbols (from_tty); | 
|  |  | 
|  | gdb::unique_xmalloc_ptr<char> stripped = strip_bg_char (args, &async_exec); | 
|  | args = stripped.get (); | 
|  |  | 
|  | /* Do validation and preparation before possibly changing anything | 
|  | in the inferior.  */ | 
|  |  | 
|  | run_target = find_run_target (); | 
|  |  | 
|  | prepare_execution_command (run_target, async_exec); | 
|  |  | 
|  | if (non_stop && !run_target->supports_non_stop ()) | 
|  | error (_("The target does not support running in non-stop mode.")); | 
|  |  | 
|  | /* Done.  Can now set breakpoints, change inferior args, etc.  */ | 
|  |  | 
|  | /* Insert temporary breakpoint in main function if requested.  */ | 
|  | if (run_how == RUN_STOP_AT_MAIN) | 
|  | { | 
|  | /* To avoid other inferiors hitting this breakpoint, make it | 
|  | inferior-specific using a condition.  A better solution would be to | 
|  | have proper inferior-specific breakpoint support, in the breakpoint | 
|  | machinery.  We could then avoid inserting a breakpoint in the program | 
|  | spaces unrelated to this inferior.  */ | 
|  | const char *op | 
|  | = ((current_language->la_language == language_ada | 
|  | || current_language->la_language == language_pascal | 
|  | || current_language->la_language == language_m2) ? "=" : "=="); | 
|  | std::string arg = string_printf | 
|  | ("-qualified %s if $_inferior %s %d", main_name (), op, | 
|  | current_inferior ()->num); | 
|  | tbreak_command (arg.c_str (), 0); | 
|  | } | 
|  |  | 
|  | exec_file = get_exec_file (0); | 
|  |  | 
|  | /* We keep symbols from add-symbol-file, on the grounds that the | 
|  | user might want to add some symbols before running the program | 
|  | (right?).  But sometimes (dynamic loading where the user manually | 
|  | introduces the new symbols with add-symbol-file), the code which | 
|  | the symbols describe does not persist between runs.  Currently | 
|  | the user has to manually nuke all symbols between runs if they | 
|  | want them to go away (PR 2207).  This is probably reasonable.  */ | 
|  |  | 
|  | /* If there were other args, beside '&', process them.  */ | 
|  | if (args != nullptr) | 
|  | current_inferior ()->set_args (args); | 
|  |  | 
|  | if (from_tty) | 
|  | { | 
|  | uiout->field_string (nullptr, "Starting program"); | 
|  | uiout->text (": "); | 
|  | if (exec_file) | 
|  | uiout->field_string ("execfile", exec_file, | 
|  | file_name_style.style ()); | 
|  | uiout->spaces (1); | 
|  | uiout->field_string ("infargs", current_inferior ()->args ()); | 
|  | uiout->text ("\n"); | 
|  | uiout->flush (); | 
|  | } | 
|  |  | 
|  | run_target->create_inferior (exec_file, | 
|  | current_inferior ()->args (), | 
|  | current_inferior ()->environment.envp (), | 
|  | from_tty); | 
|  | /* to_create_inferior should push the target, so after this point we | 
|  | shouldn't refer to run_target again.  */ | 
|  | run_target = nullptr; | 
|  |  | 
|  | infrun_debug_show_threads ("immediately after create_process", | 
|  | current_inferior ()->non_exited_threads ()); | 
|  |  | 
|  | /* We're starting off a new process.  When we get out of here, in | 
|  | non-stop mode, finish the state of all threads of that process, | 
|  | but leave other threads alone, as they may be stopped in internal | 
|  | events --- the frontend shouldn't see them as stopped.  In | 
|  | all-stop, always finish the state of all threads, as we may be | 
|  | resuming more than just the new process.  */ | 
|  | process_stratum_target *finish_target; | 
|  | ptid_t finish_ptid; | 
|  | if (non_stop) | 
|  | { | 
|  | finish_target = current_inferior ()->process_target (); | 
|  | finish_ptid = ptid_t (current_inferior ()->pid); | 
|  | } | 
|  | else | 
|  | { | 
|  | finish_target = nullptr; | 
|  | finish_ptid = minus_one_ptid; | 
|  | } | 
|  | scoped_finish_thread_state finish_state (finish_target, finish_ptid); | 
|  |  | 
|  | /* Pass zero for FROM_TTY, because at this point the "run" command | 
|  | has done its thing; now we are setting up the running program.  */ | 
|  | post_create_inferior (0); | 
|  |  | 
|  | /* Queue a pending event so that the program stops immediately.  */ | 
|  | if (run_how == RUN_STOP_AT_FIRST_INSN) | 
|  | { | 
|  | thread_info *thr = inferior_thread (); | 
|  | target_waitstatus ws; | 
|  | ws.set_stopped (GDB_SIGNAL_0); | 
|  | thr->set_pending_waitstatus (ws); | 
|  | } | 
|  |  | 
|  | /* Start the target running.  Do not use -1 continuation as it would skip | 
|  | breakpoint right at the entry point.  */ | 
|  | proceed (regcache_read_pc (get_current_regcache ()), GDB_SIGNAL_0); | 
|  |  | 
|  | /* Since there was no error, there's no need to finish the thread | 
|  | states here.  */ | 
|  | finish_state.release (); | 
|  |  | 
|  | disable_commit_resumed.reset_and_commit (); | 
|  | } | 
|  |  | 
|  | static void | 
|  | run_command (const char *args, int from_tty) | 
|  | { | 
|  | run_command_1 (args, from_tty, RUN_NORMAL); | 
|  | } | 
|  |  | 
|  | /* Start the execution of the program up until the beginning of the main | 
|  | program.  */ | 
|  |  | 
|  | static void | 
|  | start_command (const char *args, int from_tty) | 
|  | { | 
|  | /* Some languages such as Ada need to search inside the program | 
|  | minimal symbols for the location where to put the temporary | 
|  | breakpoint before starting.  */ | 
|  | if (!have_minimal_symbols ()) | 
|  | error (_("No symbol table loaded.  Use the \"file\" command.")); | 
|  |  | 
|  | /* Run the program until reaching the main procedure...  */ | 
|  | run_command_1 (args, from_tty, RUN_STOP_AT_MAIN); | 
|  | } | 
|  |  | 
|  | /* Start the execution of the program stopping at the first | 
|  | instruction.  */ | 
|  |  | 
|  | static void | 
|  | starti_command (const char *args, int from_tty) | 
|  | { | 
|  | run_command_1 (args, from_tty, RUN_STOP_AT_FIRST_INSN); | 
|  | } | 
|  |  | 
|  | static int | 
|  | proceed_thread_callback (struct thread_info *thread, void *arg) | 
|  | { | 
|  | /* We go through all threads individually instead of compressing | 
|  | into a single target `resume_all' request, because some threads | 
|  | may be stopped in internal breakpoints/events, or stopped waiting | 
|  | for its turn in the displaced stepping queue (that is, they are | 
|  | running && !executing).  The target side has no idea about why | 
|  | the thread is stopped, so a `resume_all' command would resume too | 
|  | much.  If/when GDB gains a way to tell the target `hold this | 
|  | thread stopped until I say otherwise', then we can optimize | 
|  | this.  */ | 
|  | if (thread->state != THREAD_STOPPED) | 
|  | return 0; | 
|  |  | 
|  | if (!thread->inf->has_execution ()) | 
|  | return 0; | 
|  |  | 
|  | switch_to_thread (thread); | 
|  | clear_proceed_status (0); | 
|  | proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT); | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | static void | 
|  | ensure_valid_thread (void) | 
|  | { | 
|  | if (inferior_ptid == null_ptid | 
|  | || inferior_thread ()->state == THREAD_EXITED) | 
|  | error (_("Cannot execute this command without a live selected thread.")); | 
|  | } | 
|  |  | 
|  | /* If the user is looking at trace frames, any resumption of execution | 
|  | is likely to mix up recorded and live target data.  So simply | 
|  | disallow those commands.  */ | 
|  |  | 
|  | static void | 
|  | ensure_not_tfind_mode (void) | 
|  | { | 
|  | if (get_traceframe_number () >= 0) | 
|  | error (_("Cannot execute this command while looking at trace frames.")); | 
|  | } | 
|  |  | 
|  | /* Throw an error indicating the current thread is running.  */ | 
|  |  | 
|  | static void | 
|  | error_is_running (void) | 
|  | { | 
|  | error (_("Cannot execute this command while " | 
|  | "the selected thread is running.")); | 
|  | } | 
|  |  | 
|  | /* Calls error_is_running if the current thread is running.  */ | 
|  |  | 
|  | static void | 
|  | ensure_not_running (void) | 
|  | { | 
|  | if (inferior_thread ()->state == THREAD_RUNNING) | 
|  | error_is_running (); | 
|  | } | 
|  |  | 
|  | void | 
|  | continue_1 (int all_threads) | 
|  | { | 
|  | ERROR_NO_INFERIOR; | 
|  | ensure_not_tfind_mode (); | 
|  |  | 
|  | if (non_stop && all_threads) | 
|  | { | 
|  | /* Don't error out if the current thread is running, because | 
|  | there may be other stopped threads.  */ | 
|  |  | 
|  | /* Backup current thread and selected frame and restore on scope | 
|  | exit.  */ | 
|  | scoped_restore_current_thread restore_thread; | 
|  | scoped_disable_commit_resumed disable_commit_resumed | 
|  | ("continue all threads in non-stop"); | 
|  |  | 
|  | iterate_over_threads (proceed_thread_callback, nullptr); | 
|  |  | 
|  | if (current_ui->prompt_state == PROMPT_BLOCKED) | 
|  | { | 
|  | /* If all threads in the target were already running, | 
|  | proceed_thread_callback ends up never calling proceed, | 
|  | and so nothing calls this to put the inferior's terminal | 
|  | settings in effect and remove stdin from the event loop, | 
|  | which we must when running a foreground command.  E.g.: | 
|  |  | 
|  | (gdb) c -a& | 
|  | Continuing. | 
|  | <all threads are running now> | 
|  | (gdb) c -a | 
|  | Continuing. | 
|  | <no thread was resumed, but the inferior now owns the terminal> | 
|  | */ | 
|  | target_terminal::inferior (); | 
|  | } | 
|  |  | 
|  | disable_commit_resumed.reset_and_commit (); | 
|  | } | 
|  | else | 
|  | { | 
|  | ensure_valid_thread (); | 
|  | ensure_not_running (); | 
|  | clear_proceed_status (0); | 
|  | proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT); | 
|  | } | 
|  | } | 
|  |  | 
|  | /* continue [-a] [proceed-count] [&]  */ | 
|  |  | 
|  | static void | 
|  | continue_command (const char *args, int from_tty) | 
|  | { | 
|  | int async_exec; | 
|  | bool all_threads_p = false; | 
|  |  | 
|  | ERROR_NO_INFERIOR; | 
|  |  | 
|  | /* Find out whether we must run in the background.  */ | 
|  | gdb::unique_xmalloc_ptr<char> stripped = strip_bg_char (args, &async_exec); | 
|  | args = stripped.get (); | 
|  |  | 
|  | if (args != nullptr) | 
|  | { | 
|  | if (startswith (args, "-a")) | 
|  | { | 
|  | all_threads_p = true; | 
|  | args += sizeof ("-a") - 1; | 
|  | if (*args == '\0') | 
|  | args = nullptr; | 
|  | } | 
|  | } | 
|  |  | 
|  | if (!non_stop && all_threads_p) | 
|  | error (_("`-a' is meaningless in all-stop mode.")); | 
|  |  | 
|  | if (args != nullptr && all_threads_p) | 
|  | error (_("Can't resume all threads and specify " | 
|  | "proceed count simultaneously.")); | 
|  |  | 
|  | /* If we have an argument left, set proceed count of breakpoint we | 
|  | stopped at.  */ | 
|  | if (args != nullptr) | 
|  | { | 
|  | bpstat *bs = nullptr; | 
|  | int num, stat; | 
|  | int stopped = 0; | 
|  | struct thread_info *tp; | 
|  |  | 
|  | if (non_stop) | 
|  | tp = inferior_thread (); | 
|  | else | 
|  | { | 
|  | process_stratum_target *last_target; | 
|  | ptid_t last_ptid; | 
|  |  | 
|  | get_last_target_status (&last_target, &last_ptid, nullptr); | 
|  | tp = find_thread_ptid (last_target, last_ptid); | 
|  | } | 
|  | if (tp != nullptr) | 
|  | bs = tp->control.stop_bpstat; | 
|  |  | 
|  | while ((stat = bpstat_num (&bs, &num)) != 0) | 
|  | if (stat > 0) | 
|  | { | 
|  | set_ignore_count (num, | 
|  | parse_and_eval_long (args) - 1, | 
|  | from_tty); | 
|  | /* set_ignore_count prints a message ending with a period. | 
|  | So print two spaces before "Continuing.".  */ | 
|  | if (from_tty) | 
|  | gdb_printf ("  "); | 
|  | stopped = 1; | 
|  | } | 
|  |  | 
|  | if (!stopped && from_tty) | 
|  | { | 
|  | gdb_printf | 
|  | ("Not stopped at any breakpoint; argument ignored.\n"); | 
|  | } | 
|  | } | 
|  |  | 
|  | ERROR_NO_INFERIOR; | 
|  | ensure_not_tfind_mode (); | 
|  |  | 
|  | if (!non_stop || !all_threads_p) | 
|  | { | 
|  | ensure_valid_thread (); | 
|  | ensure_not_running (); | 
|  | } | 
|  |  | 
|  | prepare_execution_command (current_inferior ()->top_target (), async_exec); | 
|  |  | 
|  | if (from_tty) | 
|  | gdb_printf (_("Continuing.\n")); | 
|  |  | 
|  | continue_1 (all_threads_p); | 
|  | } | 
|  |  | 
|  | /* Record in TP the starting point of a "step" or "next" command.  */ | 
|  |  | 
|  | static void | 
|  | set_step_frame (thread_info *tp) | 
|  | { | 
|  | /* This can be removed once this function no longer implicitly relies on the | 
|  | inferior_ptid value.  */ | 
|  | gdb_assert (inferior_ptid == tp->ptid); | 
|  |  | 
|  | frame_info_ptr frame = get_current_frame (); | 
|  |  | 
|  | symtab_and_line sal = find_frame_sal (frame); | 
|  | set_step_info (tp, frame, sal); | 
|  |  | 
|  | CORE_ADDR pc = get_frame_pc (frame); | 
|  | tp->control.step_start_function = find_pc_function (pc); | 
|  | } | 
|  |  | 
|  | /* Step until outside of current statement.  */ | 
|  |  | 
|  | static void | 
|  | step_command (const char *count_string, int from_tty) | 
|  | { | 
|  | step_1 (0, 0, count_string); | 
|  | } | 
|  |  | 
|  | /* Likewise, but skip over subroutine calls as if single instructions.  */ | 
|  |  | 
|  | static void | 
|  | next_command (const char *count_string, int from_tty) | 
|  | { | 
|  | step_1 (1, 0, count_string); | 
|  | } | 
|  |  | 
|  | /* Likewise, but step only one instruction.  */ | 
|  |  | 
|  | static void | 
|  | stepi_command (const char *count_string, int from_tty) | 
|  | { | 
|  | step_1 (0, 1, count_string); | 
|  | } | 
|  |  | 
|  | static void | 
|  | nexti_command (const char *count_string, int from_tty) | 
|  | { | 
|  | step_1 (1, 1, count_string); | 
|  | } | 
|  |  | 
|  | /* Data for the FSM that manages the step/next/stepi/nexti | 
|  | commands.  */ | 
|  |  | 
|  | struct step_command_fsm : public thread_fsm | 
|  | { | 
|  | /* How many steps left in a "step N"-like command.  */ | 
|  | int count; | 
|  |  | 
|  | /* If true, this is a next/nexti, otherwise a step/stepi.  */ | 
|  | int skip_subroutines; | 
|  |  | 
|  | /* If true, this is a stepi/nexti, otherwise a step/step.  */ | 
|  | int single_inst; | 
|  |  | 
|  | explicit step_command_fsm (struct interp *cmd_interp) | 
|  | : thread_fsm (cmd_interp) | 
|  | { | 
|  | } | 
|  |  | 
|  | void clean_up (struct thread_info *thread) override; | 
|  | bool should_stop (struct thread_info *thread) override; | 
|  | enum async_reply_reason do_async_reply_reason () override; | 
|  | }; | 
|  |  | 
|  | /* Prepare for a step/next/etc. command.  Any target resource | 
|  | allocated here is undone in the FSM's clean_up method.  */ | 
|  |  | 
|  | static void | 
|  | step_command_fsm_prepare (struct step_command_fsm *sm, | 
|  | int skip_subroutines, int single_inst, | 
|  | int count, struct thread_info *thread) | 
|  | { | 
|  | sm->skip_subroutines = skip_subroutines; | 
|  | sm->single_inst = single_inst; | 
|  | sm->count = count; | 
|  |  | 
|  | /* Leave the si command alone.  */ | 
|  | if (!sm->single_inst || sm->skip_subroutines) | 
|  | set_longjmp_breakpoint (thread, get_frame_id (get_current_frame ())); | 
|  |  | 
|  | thread->control.stepping_command = 1; | 
|  | } | 
|  |  | 
|  | static int prepare_one_step (thread_info *, struct step_command_fsm *sm); | 
|  |  | 
|  | static void | 
|  | step_1 (int skip_subroutines, int single_inst, const char *count_string) | 
|  | { | 
|  | int count; | 
|  | int async_exec; | 
|  | struct thread_info *thr; | 
|  | struct step_command_fsm *step_sm; | 
|  |  | 
|  | ERROR_NO_INFERIOR; | 
|  | ensure_not_tfind_mode (); | 
|  | ensure_valid_thread (); | 
|  | ensure_not_running (); | 
|  |  | 
|  | gdb::unique_xmalloc_ptr<char> stripped | 
|  | = strip_bg_char (count_string, &async_exec); | 
|  | count_string = stripped.get (); | 
|  |  | 
|  | prepare_execution_command (current_inferior ()->top_target (), async_exec); | 
|  |  | 
|  | count = count_string ? parse_and_eval_long (count_string) : 1; | 
|  |  | 
|  | clear_proceed_status (1); | 
|  |  | 
|  | /* Setup the execution command state machine to handle all the COUNT | 
|  | steps.  */ | 
|  | thr = inferior_thread (); | 
|  | step_sm = new step_command_fsm (command_interp ()); | 
|  | thr->set_thread_fsm (std::unique_ptr<thread_fsm> (step_sm)); | 
|  |  | 
|  | step_command_fsm_prepare (step_sm, skip_subroutines, | 
|  | single_inst, count, thr); | 
|  |  | 
|  | /* Do only one step for now, before returning control to the event | 
|  | loop.  Let the continuation figure out how many other steps we | 
|  | need to do, and handle them one at the time, through | 
|  | step_once.  */ | 
|  | if (!prepare_one_step (thr, step_sm)) | 
|  | proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT); | 
|  | else | 
|  | { | 
|  | /* Stepped into an inline frame.  Pretend that we've | 
|  | stopped.  */ | 
|  | thr->thread_fsm ()->clean_up (thr); | 
|  | bool proceeded = normal_stop (); | 
|  | if (!proceeded) | 
|  | inferior_event_handler (INF_EXEC_COMPLETE); | 
|  | all_uis_check_sync_execution_done (); | 
|  | } | 
|  | } | 
|  |  | 
|  | /* Implementation of the 'should_stop' FSM method for stepping | 
|  | commands.  Called after we are done with one step operation, to | 
|  | check whether we need to step again, before we print the prompt and | 
|  | return control to the user.  If count is > 1, returns false, as we | 
|  | will need to keep going.  */ | 
|  |  | 
|  | bool | 
|  | step_command_fsm::should_stop (struct thread_info *tp) | 
|  | { | 
|  | if (tp->control.stop_step) | 
|  | { | 
|  | /* There are more steps to make, and we did stop due to | 
|  | ending a stepping range.  Do another step.  */ | 
|  | if (--count > 0) | 
|  | return prepare_one_step (tp, this); | 
|  |  | 
|  | set_finished (); | 
|  | } | 
|  |  | 
|  | return true; | 
|  | } | 
|  |  | 
|  | /* Implementation of the 'clean_up' FSM method for stepping commands.  */ | 
|  |  | 
|  | void | 
|  | step_command_fsm::clean_up (struct thread_info *thread) | 
|  | { | 
|  | if (!single_inst || skip_subroutines) | 
|  | delete_longjmp_breakpoint (thread->global_num); | 
|  | } | 
|  |  | 
|  | /* Implementation of the 'async_reply_reason' FSM method for stepping | 
|  | commands.  */ | 
|  |  | 
|  | enum async_reply_reason | 
|  | step_command_fsm::do_async_reply_reason () | 
|  | { | 
|  | return EXEC_ASYNC_END_STEPPING_RANGE; | 
|  | } | 
|  |  | 
|  | /* Prepare for one step in "step N".  The actual target resumption is | 
|  | done by the caller.  Return true if we're done and should thus | 
|  | report a stop to the user.  Returns false if the target needs to be | 
|  | resumed.  */ | 
|  |  | 
|  | static int | 
|  | prepare_one_step (thread_info *tp, struct step_command_fsm *sm) | 
|  | { | 
|  | /* This can be removed once this function no longer implicitly relies on the | 
|  | inferior_ptid value.  */ | 
|  | gdb_assert (inferior_ptid == tp->ptid); | 
|  |  | 
|  | if (sm->count > 0) | 
|  | { | 
|  | frame_info_ptr frame = get_current_frame (); | 
|  |  | 
|  | set_step_frame (tp); | 
|  |  | 
|  | if (!sm->single_inst) | 
|  | { | 
|  | CORE_ADDR pc; | 
|  |  | 
|  | /* Step at an inlined function behaves like "down".  */ | 
|  | if (!sm->skip_subroutines | 
|  | && inline_skipped_frames (tp)) | 
|  | { | 
|  | ptid_t resume_ptid; | 
|  | const char *fn = nullptr; | 
|  | symtab_and_line sal; | 
|  | struct symbol *sym; | 
|  |  | 
|  | /* Pretend that we've ran.  */ | 
|  | resume_ptid = user_visible_resume_ptid (1); | 
|  | set_running (tp->inf->process_target (), resume_ptid, true); | 
|  |  | 
|  | step_into_inline_frame (tp); | 
|  |  | 
|  | frame = get_current_frame (); | 
|  | sal = find_frame_sal (frame); | 
|  | sym = get_frame_function (frame); | 
|  |  | 
|  | if (sym != nullptr) | 
|  | fn = sym->print_name (); | 
|  |  | 
|  | if (sal.line == 0 | 
|  | || !function_name_is_marked_for_skip (fn, sal)) | 
|  | { | 
|  | sm->count--; | 
|  | return prepare_one_step (tp, sm); | 
|  | } | 
|  | } | 
|  |  | 
|  | pc = get_frame_pc (frame); | 
|  | find_pc_line_pc_range (pc, | 
|  | &tp->control.step_range_start, | 
|  | &tp->control.step_range_end); | 
|  |  | 
|  | /* There's a problem in gcc (PR gcc/98780) that causes missing line | 
|  | table entries, which results in a too large stepping range. | 
|  | Use inlined_subroutine info to make the range more narrow.  */ | 
|  | if (inline_skipped_frames (tp) > 0) | 
|  | { | 
|  | symbol *sym = inline_skipped_symbol (tp); | 
|  | if (sym->aclass () == LOC_BLOCK) | 
|  | { | 
|  | const block *block = sym->value_block (); | 
|  | if (block->end () < tp->control.step_range_end) | 
|  | tp->control.step_range_end = block->end (); | 
|  | } | 
|  | } | 
|  |  | 
|  | tp->control.may_range_step = 1; | 
|  |  | 
|  | /* If we have no line info, switch to stepi mode.  */ | 
|  | if (tp->control.step_range_end == 0 && step_stop_if_no_debug) | 
|  | { | 
|  | tp->control.step_range_start = tp->control.step_range_end = 1; | 
|  | tp->control.may_range_step = 0; | 
|  | } | 
|  | else if (tp->control.step_range_end == 0) | 
|  | { | 
|  | const char *name; | 
|  |  | 
|  | if (find_pc_partial_function (pc, &name, | 
|  | &tp->control.step_range_start, | 
|  | &tp->control.step_range_end) == 0) | 
|  | error (_("Cannot find bounds of current function")); | 
|  |  | 
|  | target_terminal::ours_for_output (); | 
|  | gdb_printf (_("Single stepping until exit from function %s," | 
|  | "\nwhich has no line number information.\n"), | 
|  | name); | 
|  | } | 
|  | } | 
|  | else | 
|  | { | 
|  | /* Say we are stepping, but stop after one insn whatever it does.  */ | 
|  | tp->control.step_range_start = tp->control.step_range_end = 1; | 
|  | if (!sm->skip_subroutines) | 
|  | /* It is stepi. | 
|  | Don't step over function calls, not even to functions lacking | 
|  | line numbers.  */ | 
|  | tp->control.step_over_calls = STEP_OVER_NONE; | 
|  | } | 
|  |  | 
|  | if (sm->skip_subroutines) | 
|  | tp->control.step_over_calls = STEP_OVER_ALL; | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | /* Done.  */ | 
|  | sm->set_finished (); | 
|  | return 1; | 
|  | } | 
|  |  | 
|  |  | 
|  | /* Continue program at specified address.  */ | 
|  |  | 
|  | static void | 
|  | jump_command (const char *arg, int from_tty) | 
|  | { | 
|  | struct gdbarch *gdbarch = get_current_arch (); | 
|  | CORE_ADDR addr; | 
|  | struct symbol *fn; | 
|  | struct symbol *sfn; | 
|  | int async_exec; | 
|  |  | 
|  | ERROR_NO_INFERIOR; | 
|  | ensure_not_tfind_mode (); | 
|  | ensure_valid_thread (); | 
|  | ensure_not_running (); | 
|  |  | 
|  | /* Find out whether we must run in the background.  */ | 
|  | gdb::unique_xmalloc_ptr<char> stripped = strip_bg_char (arg, &async_exec); | 
|  | arg = stripped.get (); | 
|  |  | 
|  | prepare_execution_command (current_inferior ()->top_target (), async_exec); | 
|  |  | 
|  | if (!arg) | 
|  | error_no_arg (_("starting address")); | 
|  |  | 
|  | std::vector<symtab_and_line> sals | 
|  | = decode_line_with_last_displayed (arg, DECODE_LINE_FUNFIRSTLINE); | 
|  | if (sals.size () != 1) | 
|  | error (_("Unreasonable jump request")); | 
|  |  | 
|  | symtab_and_line &sal = sals[0]; | 
|  |  | 
|  | if (sal.symtab == 0 && sal.pc == 0) | 
|  | error (_("No source file has been specified.")); | 
|  |  | 
|  | resolve_sal_pc (&sal);	/* May error out.  */ | 
|  |  | 
|  | /* See if we are trying to jump to another function.  */ | 
|  | fn = get_frame_function (get_current_frame ()); | 
|  | sfn = find_pc_function (sal.pc); | 
|  | if (fn != nullptr && sfn != fn) | 
|  | { | 
|  | if (!query (_("Line %d is not in `%s'.  Jump anyway? "), sal.line, | 
|  | fn->print_name ())) | 
|  | { | 
|  | error (_("Not confirmed.")); | 
|  | /* NOTREACHED */ | 
|  | } | 
|  | } | 
|  |  | 
|  | if (sfn != nullptr) | 
|  | { | 
|  | struct obj_section *section; | 
|  |  | 
|  | fixup_symbol_section (sfn, 0); | 
|  | section = sfn->obj_section (sfn->objfile ()); | 
|  | if (section_is_overlay (section) | 
|  | && !section_is_mapped (section)) | 
|  | { | 
|  | if (!query (_("WARNING!!!  Destination is in " | 
|  | "unmapped overlay!  Jump anyway? "))) | 
|  | { | 
|  | error (_("Not confirmed.")); | 
|  | /* NOTREACHED */ | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | addr = sal.pc; | 
|  |  | 
|  | if (from_tty) | 
|  | { | 
|  | gdb_printf (_("Continuing at ")); | 
|  | gdb_puts (paddress (gdbarch, addr)); | 
|  | gdb_printf (".\n"); | 
|  | } | 
|  |  | 
|  | clear_proceed_status (0); | 
|  | proceed (addr, GDB_SIGNAL_0); | 
|  | } | 
|  |  | 
|  | /* Continue program giving it specified signal.  */ | 
|  |  | 
|  | static void | 
|  | signal_command (const char *signum_exp, int from_tty) | 
|  | { | 
|  | enum gdb_signal oursig; | 
|  | int async_exec; | 
|  |  | 
|  | dont_repeat ();		/* Too dangerous.  */ | 
|  | ERROR_NO_INFERIOR; | 
|  | ensure_not_tfind_mode (); | 
|  | ensure_valid_thread (); | 
|  | ensure_not_running (); | 
|  |  | 
|  | /* Find out whether we must run in the background.  */ | 
|  | gdb::unique_xmalloc_ptr<char> stripped | 
|  | = strip_bg_char (signum_exp, &async_exec); | 
|  | signum_exp = stripped.get (); | 
|  |  | 
|  | prepare_execution_command (current_inferior ()->top_target (), async_exec); | 
|  |  | 
|  | if (!signum_exp) | 
|  | error_no_arg (_("signal number")); | 
|  |  | 
|  | /* It would be even slicker to make signal names be valid expressions, | 
|  | (the type could be "enum $signal" or some such), then the user could | 
|  | assign them to convenience variables.  */ | 
|  | oursig = gdb_signal_from_name (signum_exp); | 
|  |  | 
|  | if (oursig == GDB_SIGNAL_UNKNOWN) | 
|  | { | 
|  | /* No, try numeric.  */ | 
|  | int num = parse_and_eval_long (signum_exp); | 
|  |  | 
|  | if (num == 0) | 
|  | oursig = GDB_SIGNAL_0; | 
|  | else | 
|  | oursig = gdb_signal_from_command (num); | 
|  | } | 
|  |  | 
|  | /* Look for threads other than the current that this command ends up | 
|  | resuming too (due to schedlock off), and warn if they'll get a | 
|  | signal delivered.  "signal 0" is used to suppress a previous | 
|  | signal, but if the current thread is no longer the one that got | 
|  | the signal, then the user is potentially suppressing the signal | 
|  | of the wrong thread.  */ | 
|  | if (!non_stop) | 
|  | { | 
|  | int must_confirm = 0; | 
|  |  | 
|  | /* This indicates what will be resumed.  Either a single thread, | 
|  | a whole process, or all threads of all processes.  */ | 
|  | ptid_t resume_ptid = user_visible_resume_ptid (0); | 
|  | process_stratum_target *resume_target | 
|  | = user_visible_resume_target (resume_ptid); | 
|  |  | 
|  | thread_info *current = inferior_thread (); | 
|  |  | 
|  | for (thread_info *tp : all_non_exited_threads (resume_target, resume_ptid)) | 
|  | { | 
|  | if (tp == current) | 
|  | continue; | 
|  |  | 
|  | if (tp->stop_signal () != GDB_SIGNAL_0 | 
|  | && signal_pass_state (tp->stop_signal ())) | 
|  | { | 
|  | if (!must_confirm) | 
|  | gdb_printf (_("Note:\n")); | 
|  | gdb_printf (_("  Thread %s previously stopped with signal %s, %s.\n"), | 
|  | print_thread_id (tp), | 
|  | gdb_signal_to_name (tp->stop_signal ()), | 
|  | gdb_signal_to_string (tp->stop_signal ())); | 
|  | must_confirm = 1; | 
|  | } | 
|  | } | 
|  |  | 
|  | if (must_confirm | 
|  | && !query (_("Continuing thread %s (the current thread) with specified signal will\n" | 
|  | "still deliver the signals noted above to their respective threads.\n" | 
|  | "Continue anyway? "), | 
|  | print_thread_id (inferior_thread ()))) | 
|  | error (_("Not confirmed.")); | 
|  | } | 
|  |  | 
|  | if (from_tty) | 
|  | { | 
|  | if (oursig == GDB_SIGNAL_0) | 
|  | gdb_printf (_("Continuing with no signal.\n")); | 
|  | else | 
|  | gdb_printf (_("Continuing with signal %s.\n"), | 
|  | gdb_signal_to_name (oursig)); | 
|  | } | 
|  |  | 
|  | clear_proceed_status (0); | 
|  | proceed ((CORE_ADDR) -1, oursig); | 
|  | } | 
|  |  | 
|  | /* Queue a signal to be delivered to the current thread.  */ | 
|  |  | 
|  | static void | 
|  | queue_signal_command (const char *signum_exp, int from_tty) | 
|  | { | 
|  | enum gdb_signal oursig; | 
|  | struct thread_info *tp; | 
|  |  | 
|  | ERROR_NO_INFERIOR; | 
|  | ensure_not_tfind_mode (); | 
|  | ensure_valid_thread (); | 
|  | ensure_not_running (); | 
|  |  | 
|  | if (signum_exp == nullptr) | 
|  | error_no_arg (_("signal number")); | 
|  |  | 
|  | /* It would be even slicker to make signal names be valid expressions, | 
|  | (the type could be "enum $signal" or some such), then the user could | 
|  | assign them to convenience variables.  */ | 
|  | oursig = gdb_signal_from_name (signum_exp); | 
|  |  | 
|  | if (oursig == GDB_SIGNAL_UNKNOWN) | 
|  | { | 
|  | /* No, try numeric.  */ | 
|  | int num = parse_and_eval_long (signum_exp); | 
|  |  | 
|  | if (num == 0) | 
|  | oursig = GDB_SIGNAL_0; | 
|  | else | 
|  | oursig = gdb_signal_from_command (num); | 
|  | } | 
|  |  | 
|  | if (oursig != GDB_SIGNAL_0 | 
|  | && !signal_pass_state (oursig)) | 
|  | error (_("Signal handling set to not pass this signal to the program.")); | 
|  |  | 
|  | tp = inferior_thread (); | 
|  | tp->set_stop_signal (oursig); | 
|  | } | 
|  |  | 
|  | /* Data for the FSM that manages the until (with no argument) | 
|  | command.  */ | 
|  |  | 
|  | struct until_next_fsm : public thread_fsm | 
|  | { | 
|  | /* The thread that as current when the command was executed.  */ | 
|  | int thread; | 
|  |  | 
|  | until_next_fsm (struct interp *cmd_interp, int thread) | 
|  | : thread_fsm (cmd_interp), | 
|  | thread (thread) | 
|  | { | 
|  | } | 
|  |  | 
|  | bool should_stop (struct thread_info *thread) override; | 
|  | void clean_up (struct thread_info *thread) override; | 
|  | enum async_reply_reason do_async_reply_reason () override; | 
|  | }; | 
|  |  | 
|  | /* Implementation of the 'should_stop' FSM method for the until (with | 
|  | no arg) command.  */ | 
|  |  | 
|  | bool | 
|  | until_next_fsm::should_stop (struct thread_info *tp) | 
|  | { | 
|  | if (tp->control.stop_step) | 
|  | set_finished (); | 
|  |  | 
|  | return true; | 
|  | } | 
|  |  | 
|  | /* Implementation of the 'clean_up' FSM method for the until (with no | 
|  | arg) command.  */ | 
|  |  | 
|  | void | 
|  | until_next_fsm::clean_up (struct thread_info *thread) | 
|  | { | 
|  | delete_longjmp_breakpoint (thread->global_num); | 
|  | } | 
|  |  | 
|  | /* Implementation of the 'async_reply_reason' FSM method for the until | 
|  | (with no arg) command.  */ | 
|  |  | 
|  | enum async_reply_reason | 
|  | until_next_fsm::do_async_reply_reason () | 
|  | { | 
|  | return EXEC_ASYNC_END_STEPPING_RANGE; | 
|  | } | 
|  |  | 
|  | /* Proceed until we reach a different source line with pc greater than | 
|  | our current one or exit the function.  We skip calls in both cases. | 
|  |  | 
|  | Note that eventually this command should probably be changed so | 
|  | that only source lines are printed out when we hit the breakpoint | 
|  | we set.  This may involve changes to wait_for_inferior and the | 
|  | proceed status code.  */ | 
|  |  | 
|  | static void | 
|  | until_next_command (int from_tty) | 
|  | { | 
|  | frame_info_ptr frame; | 
|  | CORE_ADDR pc; | 
|  | struct symbol *func; | 
|  | struct symtab_and_line sal; | 
|  | struct thread_info *tp = inferior_thread (); | 
|  | int thread = tp->global_num; | 
|  | struct until_next_fsm *sm; | 
|  |  | 
|  | clear_proceed_status (0); | 
|  | set_step_frame (tp); | 
|  |  | 
|  | frame = get_current_frame (); | 
|  |  | 
|  | /* Step until either exited from this function or greater | 
|  | than the current line (if in symbolic section) or pc (if | 
|  | not).  */ | 
|  |  | 
|  | pc = get_frame_pc (frame); | 
|  | func = find_pc_function (pc); | 
|  |  | 
|  | if (!func) | 
|  | { | 
|  | struct bound_minimal_symbol msymbol = lookup_minimal_symbol_by_pc (pc); | 
|  |  | 
|  | if (msymbol.minsym == nullptr) | 
|  | error (_("Execution is not within a known function.")); | 
|  |  | 
|  | tp->control.step_range_start = msymbol.value_address (); | 
|  | /* The upper-bound of step_range is exclusive.  In order to make PC | 
|  | within the range, set the step_range_end with PC + 1.  */ | 
|  | tp->control.step_range_end = pc + 1; | 
|  | } | 
|  | else | 
|  | { | 
|  | sal = find_pc_line (pc, 0); | 
|  |  | 
|  | tp->control.step_range_start = func->value_block ()->entry_pc (); | 
|  | tp->control.step_range_end = sal.end; | 
|  |  | 
|  | /* By setting the step_range_end based on the current pc, we are | 
|  | assuming that the last line table entry for any given source line | 
|  | will have is_stmt set to true.  This is not necessarily the case, | 
|  | there may be additional entries for the same source line with | 
|  | is_stmt set false.  Consider the following code: | 
|  |  | 
|  | for (int i = 0; i < 10; i++) | 
|  | loop_body (); | 
|  |  | 
|  | Clang-13, will generate multiple line table entries at the end of | 
|  | the loop all associated with the 'for' line.  The first of these | 
|  | entries is marked is_stmt true, but the other entries are is_stmt | 
|  | false. | 
|  |  | 
|  | If we only use the values in SAL, then our stepping range may not | 
|  | extend to the end of the loop. The until command will reach the | 
|  | end of the range, find a non is_stmt instruction, and step to the | 
|  | next is_stmt instruction. This stopping point, however, will be | 
|  | inside the loop, which is not what we wanted. | 
|  |  | 
|  | Instead, we now check any subsequent line table entries to see if | 
|  | they are for the same line.  If they are, and they are marked | 
|  | is_stmt false, then we extend the end of our stepping range. | 
|  |  | 
|  | When we finish this process the end of the stepping range will | 
|  | point either to a line with a different line number, or, will | 
|  | point at an address for the same line number that is marked as a | 
|  | statement.  */ | 
|  |  | 
|  | struct symtab_and_line final_sal | 
|  | = find_pc_line (tp->control.step_range_end, 0); | 
|  |  | 
|  | while (final_sal.line == sal.line && final_sal.symtab == sal.symtab | 
|  | && !final_sal.is_stmt) | 
|  | { | 
|  | tp->control.step_range_end = final_sal.end; | 
|  | final_sal = find_pc_line (final_sal.end, 0); | 
|  | } | 
|  | } | 
|  | tp->control.may_range_step = 1; | 
|  |  | 
|  | tp->control.step_over_calls = STEP_OVER_ALL; | 
|  |  | 
|  | set_longjmp_breakpoint (tp, get_frame_id (frame)); | 
|  | delete_longjmp_breakpoint_cleanup lj_deleter (thread); | 
|  |  | 
|  | sm = new until_next_fsm (command_interp (), tp->global_num); | 
|  | tp->set_thread_fsm (std::unique_ptr<thread_fsm> (sm)); | 
|  | lj_deleter.release (); | 
|  |  | 
|  | proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT); | 
|  | } | 
|  |  | 
|  | static void | 
|  | until_command (const char *arg, int from_tty) | 
|  | { | 
|  | int async_exec; | 
|  |  | 
|  | ERROR_NO_INFERIOR; | 
|  | ensure_not_tfind_mode (); | 
|  | ensure_valid_thread (); | 
|  | ensure_not_running (); | 
|  |  | 
|  | /* Find out whether we must run in the background.  */ | 
|  | gdb::unique_xmalloc_ptr<char> stripped = strip_bg_char (arg, &async_exec); | 
|  | arg = stripped.get (); | 
|  |  | 
|  | prepare_execution_command (current_inferior ()->top_target (), async_exec); | 
|  |  | 
|  | if (arg) | 
|  | until_break_command (arg, from_tty, 0); | 
|  | else | 
|  | until_next_command (from_tty); | 
|  | } | 
|  |  | 
|  | static void | 
|  | advance_command (const char *arg, int from_tty) | 
|  | { | 
|  | int async_exec; | 
|  |  | 
|  | ERROR_NO_INFERIOR; | 
|  | ensure_not_tfind_mode (); | 
|  | ensure_valid_thread (); | 
|  | ensure_not_running (); | 
|  |  | 
|  | if (arg == nullptr) | 
|  | error_no_arg (_("a location")); | 
|  |  | 
|  | /* Find out whether we must run in the background.  */ | 
|  | gdb::unique_xmalloc_ptr<char> stripped = strip_bg_char (arg, &async_exec); | 
|  | arg = stripped.get (); | 
|  |  | 
|  | prepare_execution_command (current_inferior ()->top_target (), async_exec); | 
|  |  | 
|  | until_break_command (arg, from_tty, 1); | 
|  | } | 
|  |  | 
|  | /* See inferior.h.  */ | 
|  |  | 
|  | struct value * | 
|  | get_return_value (struct symbol *func_symbol, struct value *function) | 
|  | { | 
|  | regcache *stop_regs = get_current_regcache (); | 
|  | struct gdbarch *gdbarch = stop_regs->arch (); | 
|  | struct value *value; | 
|  |  | 
|  | struct type *value_type | 
|  | = check_typedef (func_symbol->type ()->target_type ()); | 
|  | gdb_assert (value_type->code () != TYPE_CODE_VOID); | 
|  |  | 
|  | if (is_nocall_function (check_typedef (::value_type (function)))) | 
|  | { | 
|  | warning (_("Function '%s' does not follow the target calling " | 
|  | "convention, cannot determine its returned value."), | 
|  | func_symbol->print_name ()); | 
|  |  | 
|  | return nullptr; | 
|  | } | 
|  |  | 
|  | /* FIXME: 2003-09-27: When returning from a nested inferior function | 
|  | call, it's possible (with no help from the architecture vector) | 
|  | to locate and return/print a "struct return" value.  This is just | 
|  | a more complicated case of what is already being done in the | 
|  | inferior function call code.  In fact, when inferior function | 
|  | calls are made async, this will likely be made the norm.  */ | 
|  |  | 
|  | switch (gdbarch_return_value_as_value (gdbarch, function, value_type, | 
|  | nullptr, nullptr, nullptr)) | 
|  | { | 
|  | case RETURN_VALUE_REGISTER_CONVENTION: | 
|  | case RETURN_VALUE_ABI_RETURNS_ADDRESS: | 
|  | case RETURN_VALUE_ABI_PRESERVES_ADDRESS: | 
|  | gdbarch_return_value_as_value (gdbarch, function, value_type, stop_regs, | 
|  | &value, nullptr); | 
|  | break; | 
|  | case RETURN_VALUE_STRUCT_CONVENTION: | 
|  | value = nullptr; | 
|  | break; | 
|  | default: | 
|  | internal_error (_("bad switch")); | 
|  | } | 
|  |  | 
|  | return value; | 
|  | } | 
|  |  | 
|  | /* The captured function return value/type and its position in the | 
|  | value history.  */ | 
|  |  | 
|  | struct return_value_info | 
|  | { | 
|  | /* The captured return value.  May be NULL if we weren't able to | 
|  | retrieve it.  See get_return_value.  */ | 
|  | struct value *value; | 
|  |  | 
|  | /* The return type.  In some cases, we'll not be able extract the | 
|  | return value, but we always know the type.  */ | 
|  | struct type *type; | 
|  |  | 
|  | /* If we captured a value, this is the value history index.  */ | 
|  | int value_history_index; | 
|  | }; | 
|  |  | 
|  | /* Helper for print_return_value.  */ | 
|  |  | 
|  | static void | 
|  | print_return_value_1 (struct ui_out *uiout, struct return_value_info *rv) | 
|  | { | 
|  | if (rv->value != nullptr) | 
|  | { | 
|  | /* Print it.  */ | 
|  | uiout->text ("Value returned is "); | 
|  | uiout->field_fmt ("gdb-result-var", "$%d", | 
|  | rv->value_history_index); | 
|  | uiout->text (" = "); | 
|  |  | 
|  | if (finish_print) | 
|  | { | 
|  | struct value_print_options opts; | 
|  | get_user_print_options (&opts); | 
|  |  | 
|  | string_file stb; | 
|  | value_print (rv->value, &stb, &opts); | 
|  | uiout->field_stream ("return-value", stb); | 
|  | } | 
|  | else | 
|  | uiout->field_string ("return-value", _("<not displayed>"), | 
|  | metadata_style.style ()); | 
|  | uiout->text ("\n"); | 
|  | } | 
|  | else | 
|  | { | 
|  | std::string type_name = type_to_string (rv->type); | 
|  | uiout->text ("Value returned has type: "); | 
|  | uiout->field_string ("return-type", type_name); | 
|  | uiout->text ("."); | 
|  | uiout->text (" Cannot determine contents\n"); | 
|  | } | 
|  | } | 
|  |  | 
|  | /* Print the result of a function at the end of a 'finish' command. | 
|  | RV points at an object representing the captured return value/type | 
|  | and its position in the value history.  */ | 
|  |  | 
|  | void | 
|  | print_return_value (struct ui_out *uiout, struct return_value_info *rv) | 
|  | { | 
|  | if (rv->type == nullptr | 
|  | || check_typedef (rv->type)->code () == TYPE_CODE_VOID) | 
|  | return; | 
|  |  | 
|  | try | 
|  | { | 
|  | /* print_return_value_1 can throw an exception in some | 
|  | circumstances.  We need to catch this so that we still | 
|  | delete the breakpoint.  */ | 
|  | print_return_value_1 (uiout, rv); | 
|  | } | 
|  | catch (const gdb_exception &ex) | 
|  | { | 
|  | exception_print (gdb_stdout, ex); | 
|  | } | 
|  | } | 
|  |  | 
|  | /* Data for the FSM that manages the finish command.  */ | 
|  |  | 
|  | struct finish_command_fsm : public thread_fsm | 
|  | { | 
|  | /* The momentary breakpoint set at the function's return address in | 
|  | the caller.  */ | 
|  | breakpoint_up breakpoint; | 
|  |  | 
|  | /* The function that we're stepping out of.  */ | 
|  | struct symbol *function = nullptr; | 
|  |  | 
|  | /* If the FSM finishes successfully, this stores the function's | 
|  | return value.  */ | 
|  | struct return_value_info return_value_info {}; | 
|  |  | 
|  | /* If the current function uses the "struct return convention", | 
|  | this holds the address at which the value being returned will | 
|  | be stored, or zero if that address could not be determined or | 
|  | the "struct return convention" is not being used.  */ | 
|  | CORE_ADDR return_buf; | 
|  |  | 
|  | explicit finish_command_fsm (struct interp *cmd_interp) | 
|  | : thread_fsm (cmd_interp) | 
|  | { | 
|  | } | 
|  |  | 
|  | bool should_stop (struct thread_info *thread) override; | 
|  | void clean_up (struct thread_info *thread) override; | 
|  | struct return_value_info *return_value () override; | 
|  | enum async_reply_reason do_async_reply_reason () override; | 
|  | }; | 
|  |  | 
|  | /* Implementation of the 'should_stop' FSM method for the finish | 
|  | commands.  Detects whether the thread stepped out of the function | 
|  | successfully, and if so, captures the function's return value and | 
|  | marks the FSM finished.  */ | 
|  |  | 
|  | bool | 
|  | finish_command_fsm::should_stop (struct thread_info *tp) | 
|  | { | 
|  | struct return_value_info *rv = &return_value_info; | 
|  |  | 
|  | if (function != nullptr | 
|  | && bpstat_find_breakpoint (tp->control.stop_bpstat, | 
|  | breakpoint.get ()) != nullptr) | 
|  | { | 
|  | /* We're done.  */ | 
|  | set_finished (); | 
|  |  | 
|  | rv->type = function->type ()->target_type (); | 
|  | if (rv->type == nullptr) | 
|  | internal_error (_("finish_command: function has no target type")); | 
|  |  | 
|  | if (check_typedef (rv->type)->code () != TYPE_CODE_VOID) | 
|  | { | 
|  | struct value *func; | 
|  |  | 
|  | func = read_var_value (function, nullptr, get_current_frame ()); | 
|  |  | 
|  | if (return_buf != 0) | 
|  | /* Retrieve return value from the buffer where it was saved.  */ | 
|  | rv->value = value_at (rv->type, return_buf); | 
|  | else | 
|  | rv->value = get_return_value (function, func); | 
|  |  | 
|  | if (rv->value != nullptr) | 
|  | rv->value_history_index = record_latest_value (rv->value); | 
|  | } | 
|  | } | 
|  | else if (tp->control.stop_step) | 
|  | { | 
|  | /* Finishing from an inline frame, or reverse finishing.  In | 
|  | either case, there's no way to retrieve the return value.  */ | 
|  | set_finished (); | 
|  | } | 
|  |  | 
|  | return true; | 
|  | } | 
|  |  | 
|  | /* Implementation of the 'clean_up' FSM method for the finish | 
|  | commands.  */ | 
|  |  | 
|  | void | 
|  | finish_command_fsm::clean_up (struct thread_info *thread) | 
|  | { | 
|  | breakpoint.reset (); | 
|  | delete_longjmp_breakpoint (thread->global_num); | 
|  | } | 
|  |  | 
|  | /* Implementation of the 'return_value' FSM method for the finish | 
|  | commands.  */ | 
|  |  | 
|  | struct return_value_info * | 
|  | finish_command_fsm::return_value () | 
|  | { | 
|  | return &return_value_info; | 
|  | } | 
|  |  | 
|  | /* Implementation of the 'async_reply_reason' FSM method for the | 
|  | finish commands.  */ | 
|  |  | 
|  | enum async_reply_reason | 
|  | finish_command_fsm::do_async_reply_reason () | 
|  | { | 
|  | if (execution_direction == EXEC_REVERSE) | 
|  | return EXEC_ASYNC_END_STEPPING_RANGE; | 
|  | else | 
|  | return EXEC_ASYNC_FUNCTION_FINISHED; | 
|  | } | 
|  |  | 
|  | /* finish_backward -- helper function for finish_command.  */ | 
|  |  | 
|  | static void | 
|  | finish_backward (struct finish_command_fsm *sm) | 
|  | { | 
|  | struct symtab_and_line sal; | 
|  | struct thread_info *tp = inferior_thread (); | 
|  | CORE_ADDR pc; | 
|  | CORE_ADDR func_addr; | 
|  |  | 
|  | pc = get_frame_pc (get_current_frame ()); | 
|  |  | 
|  | if (find_pc_partial_function (pc, nullptr, &func_addr, nullptr) == 0) | 
|  | error (_("Cannot find bounds of current function")); | 
|  |  | 
|  | sal = find_pc_line (func_addr, 0); | 
|  |  | 
|  | tp->control.proceed_to_finish = 1; | 
|  | /* Special case: if we're sitting at the function entry point, | 
|  | then all we need to do is take a reverse singlestep.  We | 
|  | don't need to set a breakpoint, and indeed it would do us | 
|  | no good to do so. | 
|  |  | 
|  | Note that this can only happen at frame #0, since there's | 
|  | no way that a function up the stack can have a return address | 
|  | that's equal to its entry point.  */ | 
|  |  | 
|  | if (sal.pc != pc) | 
|  | { | 
|  | frame_info_ptr frame = get_selected_frame (nullptr); | 
|  | struct gdbarch *gdbarch = get_frame_arch (frame); | 
|  |  | 
|  | /* Set a step-resume at the function's entry point.  Once that's | 
|  | hit, we'll do one more step backwards.  */ | 
|  | symtab_and_line sr_sal; | 
|  | sr_sal.pc = sal.pc; | 
|  | sr_sal.pspace = get_frame_program_space (frame); | 
|  | insert_step_resume_breakpoint_at_sal (gdbarch, | 
|  | sr_sal, null_frame_id); | 
|  |  | 
|  | proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT); | 
|  | } | 
|  | else | 
|  | { | 
|  | /* We're almost there -- we just need to back up by one more | 
|  | single-step.  */ | 
|  | tp->control.step_range_start = tp->control.step_range_end = 1; | 
|  | proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT); | 
|  | } | 
|  | } | 
|  |  | 
|  | /* finish_forward -- helper function for finish_command.  FRAME is the | 
|  | frame that called the function we're about to step out of.  */ | 
|  |  | 
|  | static void | 
|  | finish_forward (struct finish_command_fsm *sm, frame_info_ptr frame) | 
|  | { | 
|  | struct frame_id frame_id = get_frame_id (frame); | 
|  | struct gdbarch *gdbarch = get_frame_arch (frame); | 
|  | struct symtab_and_line sal; | 
|  | struct thread_info *tp = inferior_thread (); | 
|  |  | 
|  | sal = find_pc_line (get_frame_pc (frame), 0); | 
|  | sal.pc = get_frame_pc (frame); | 
|  |  | 
|  | sm->breakpoint = set_momentary_breakpoint (gdbarch, sal, | 
|  | get_stack_frame_id (frame), | 
|  | bp_finish); | 
|  |  | 
|  | /* set_momentary_breakpoint invalidates FRAME.  */ | 
|  | frame = nullptr; | 
|  |  | 
|  | set_longjmp_breakpoint (tp, frame_id); | 
|  |  | 
|  | /* We want to print return value, please...  */ | 
|  | tp->control.proceed_to_finish = 1; | 
|  |  | 
|  | proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT); | 
|  | } | 
|  |  | 
|  | /* Skip frames for "finish".  */ | 
|  |  | 
|  | static frame_info_ptr | 
|  | skip_finish_frames (frame_info_ptr frame) | 
|  | { | 
|  | frame_info_ptr start; | 
|  |  | 
|  | do | 
|  | { | 
|  | start = frame; | 
|  |  | 
|  | frame = skip_tailcall_frames (frame); | 
|  | if (frame == nullptr) | 
|  | break; | 
|  |  | 
|  | frame = skip_unwritable_frames (frame); | 
|  | if (frame == nullptr) | 
|  | break; | 
|  | } | 
|  | while (start != frame); | 
|  |  | 
|  | return frame; | 
|  | } | 
|  |  | 
|  | /* "finish": Set a temporary breakpoint at the place the selected | 
|  | frame will return to, then continue.  */ | 
|  |  | 
|  | static void | 
|  | finish_command (const char *arg, int from_tty) | 
|  | { | 
|  | frame_info_ptr frame; | 
|  | int async_exec; | 
|  | struct finish_command_fsm *sm; | 
|  | struct thread_info *tp; | 
|  |  | 
|  | ERROR_NO_INFERIOR; | 
|  | ensure_not_tfind_mode (); | 
|  | ensure_valid_thread (); | 
|  | ensure_not_running (); | 
|  |  | 
|  | /* Find out whether we must run in the background.  */ | 
|  | gdb::unique_xmalloc_ptr<char> stripped = strip_bg_char (arg, &async_exec); | 
|  | arg = stripped.get (); | 
|  |  | 
|  | prepare_execution_command (current_inferior ()->top_target (), async_exec); | 
|  |  | 
|  | if (arg) | 
|  | error (_("The \"finish\" command does not take any arguments.")); | 
|  |  | 
|  | frame = get_prev_frame (get_selected_frame (_("No selected frame."))); | 
|  | if (frame == 0) | 
|  | error (_("\"finish\" not meaningful in the outermost frame.")); | 
|  |  | 
|  | clear_proceed_status (0); | 
|  |  | 
|  | tp = inferior_thread (); | 
|  |  | 
|  | sm = new finish_command_fsm (command_interp ()); | 
|  |  | 
|  | tp->set_thread_fsm (std::unique_ptr<thread_fsm> (sm)); | 
|  |  | 
|  | /* Finishing from an inline frame is completely different.  We don't | 
|  | try to show the "return value" - no way to locate it.  */ | 
|  | if (get_frame_type (get_selected_frame (_("No selected frame."))) | 
|  | == INLINE_FRAME) | 
|  | { | 
|  | /* Claim we are stepping in the calling frame.  An empty step | 
|  | range means that we will stop once we aren't in a function | 
|  | called by that frame.  We don't use the magic "1" value for | 
|  | step_range_end, because then infrun will think this is nexti, | 
|  | and not step over the rest of this inlined function call.  */ | 
|  | set_step_info (tp, frame, {}); | 
|  | tp->control.step_range_start = get_frame_pc (frame); | 
|  | tp->control.step_range_end = tp->control.step_range_start; | 
|  | tp->control.step_over_calls = STEP_OVER_ALL; | 
|  |  | 
|  | /* Print info on the selected frame, including level number but not | 
|  | source.  */ | 
|  | if (from_tty) | 
|  | { | 
|  | gdb_printf (_("Run till exit from ")); | 
|  | print_stack_frame (get_selected_frame (nullptr), 1, LOCATION, 0); | 
|  | } | 
|  |  | 
|  | proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT); | 
|  | return; | 
|  | } | 
|  |  | 
|  | /* Find the function we will return from.  */ | 
|  | frame_info_ptr callee_frame = get_selected_frame (nullptr); | 
|  | sm->function = find_pc_function (get_frame_pc (callee_frame)); | 
|  | sm->return_buf = 0;    /* Initialize buffer address is not available.  */ | 
|  |  | 
|  | /* Determine the return convention.  If it is RETURN_VALUE_STRUCT_CONVENTION, | 
|  | attempt to determine the address of the return buffer.  */ | 
|  | if (sm->function != nullptr) | 
|  | { | 
|  | enum return_value_convention return_value; | 
|  | struct gdbarch *gdbarch = get_frame_arch (callee_frame); | 
|  |  | 
|  | struct type * val_type | 
|  | = check_typedef (sm->function->type ()->target_type ()); | 
|  |  | 
|  | return_value | 
|  | = gdbarch_return_value_as_value (gdbarch, | 
|  | read_var_value (sm->function, nullptr, | 
|  | callee_frame), | 
|  | val_type, nullptr, nullptr, nullptr); | 
|  |  | 
|  | if (return_value == RETURN_VALUE_STRUCT_CONVENTION | 
|  | && val_type->code () != TYPE_CODE_VOID) | 
|  | sm->return_buf = gdbarch_get_return_buf_addr (gdbarch, val_type, | 
|  | callee_frame); | 
|  | } | 
|  |  | 
|  | /* Print info on the selected frame, including level number but not | 
|  | source.  */ | 
|  | if (from_tty) | 
|  | { | 
|  | if (execution_direction == EXEC_REVERSE) | 
|  | gdb_printf (_("Run back to call of ")); | 
|  | else | 
|  | { | 
|  | if (sm->function != nullptr && TYPE_NO_RETURN (sm->function->type ()) | 
|  | && !query (_("warning: Function %s does not return normally.\n" | 
|  | "Try to finish anyway? "), | 
|  | sm->function->print_name ())) | 
|  | error (_("Not confirmed.")); | 
|  | gdb_printf (_("Run till exit from ")); | 
|  | } | 
|  |  | 
|  | print_stack_frame (callee_frame, 1, LOCATION, 0); | 
|  | } | 
|  |  | 
|  | if (execution_direction == EXEC_REVERSE) | 
|  | finish_backward (sm); | 
|  | else | 
|  | { | 
|  | frame = skip_finish_frames (frame); | 
|  |  | 
|  | if (frame == nullptr) | 
|  | error (_("Cannot find the caller frame.")); | 
|  |  | 
|  | finish_forward (sm, frame); | 
|  | } | 
|  | } | 
|  |  | 
|  |  | 
|  | static void | 
|  | info_program_command (const char *args, int from_tty) | 
|  | { | 
|  | bpstat *bs; | 
|  | int num, stat; | 
|  | ptid_t ptid; | 
|  | process_stratum_target *proc_target; | 
|  |  | 
|  | if (!target_has_execution ()) | 
|  | { | 
|  | gdb_printf (_("The program being debugged is not being run.\n")); | 
|  | return; | 
|  | } | 
|  |  | 
|  | if (non_stop) | 
|  | { | 
|  | ptid = inferior_ptid; | 
|  | proc_target = current_inferior ()->process_target (); | 
|  | } | 
|  | else | 
|  | get_last_target_status (&proc_target, &ptid, nullptr); | 
|  |  | 
|  | if (ptid == null_ptid || ptid == minus_one_ptid) | 
|  | error (_("No selected thread.")); | 
|  |  | 
|  | thread_info *tp = find_thread_ptid (proc_target, ptid); | 
|  |  | 
|  | if (tp->state == THREAD_EXITED) | 
|  | error (_("Invalid selected thread.")); | 
|  | else if (tp->state == THREAD_RUNNING) | 
|  | error (_("Selected thread is running.")); | 
|  |  | 
|  | bs = tp->control.stop_bpstat; | 
|  | stat = bpstat_num (&bs, &num); | 
|  |  | 
|  | target_files_info (); | 
|  | gdb_printf (_("Program stopped at %s.\n"), | 
|  | paddress (target_gdbarch (), tp->stop_pc ())); | 
|  | if (tp->control.stop_step) | 
|  | gdb_printf (_("It stopped after being stepped.\n")); | 
|  | else if (stat != 0) | 
|  | { | 
|  | /* There may be several breakpoints in the same place, so this | 
|  | isn't as strange as it seems.  */ | 
|  | while (stat != 0) | 
|  | { | 
|  | if (stat < 0) | 
|  | { | 
|  | gdb_printf (_("It stopped at a breakpoint " | 
|  | "that has since been deleted.\n")); | 
|  | } | 
|  | else | 
|  | gdb_printf (_("It stopped at breakpoint %d.\n"), num); | 
|  | stat = bpstat_num (&bs, &num); | 
|  | } | 
|  | } | 
|  | else if (tp->stop_signal () != GDB_SIGNAL_0) | 
|  | { | 
|  | gdb_printf (_("It stopped with signal %s, %s.\n"), | 
|  | gdb_signal_to_name (tp->stop_signal ()), | 
|  | gdb_signal_to_string (tp->stop_signal ())); | 
|  | } | 
|  |  | 
|  | if (from_tty) | 
|  | { | 
|  | gdb_printf (_("Type \"info stack\" or \"info " | 
|  | "registers\" for more information.\n")); | 
|  | } | 
|  | } | 
|  |  | 
|  | static void | 
|  | environment_info (const char *var, int from_tty) | 
|  | { | 
|  | if (var) | 
|  | { | 
|  | const char *val = current_inferior ()->environment.get (var); | 
|  |  | 
|  | if (val) | 
|  | { | 
|  | gdb_puts (var); | 
|  | gdb_puts (" = "); | 
|  | gdb_puts (val); | 
|  | gdb_puts ("\n"); | 
|  | } | 
|  | else | 
|  | { | 
|  | gdb_puts ("Environment variable \""); | 
|  | gdb_puts (var); | 
|  | gdb_puts ("\" not defined.\n"); | 
|  | } | 
|  | } | 
|  | else | 
|  | { | 
|  | char **envp = current_inferior ()->environment.envp (); | 
|  |  | 
|  | for (int idx = 0; envp[idx] != nullptr; ++idx) | 
|  | { | 
|  | gdb_puts (envp[idx]); | 
|  | gdb_puts ("\n"); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | static void | 
|  | set_environment_command (const char *arg, int from_tty) | 
|  | { | 
|  | const char *p, *val; | 
|  | int nullset = 0; | 
|  |  | 
|  | if (arg == 0) | 
|  | error_no_arg (_("environment variable and value")); | 
|  |  | 
|  | /* Find separation between variable name and value.  */ | 
|  | p = (char *) strchr (arg, '='); | 
|  | val = (char *) strchr (arg, ' '); | 
|  |  | 
|  | if (p != 0 && val != 0) | 
|  | { | 
|  | /* We have both a space and an equals.  If the space is before the | 
|  | equals, walk forward over the spaces til we see a nonspace | 
|  | (possibly the equals).  */ | 
|  | if (p > val) | 
|  | while (*val == ' ') | 
|  | val++; | 
|  |  | 
|  | /* Now if the = is after the char following the spaces, | 
|  | take the char following the spaces.  */ | 
|  | if (p > val) | 
|  | p = val - 1; | 
|  | } | 
|  | else if (val != 0 && p == 0) | 
|  | p = val; | 
|  |  | 
|  | if (p == arg) | 
|  | error_no_arg (_("environment variable to set")); | 
|  |  | 
|  | if (p == 0 || p[1] == 0) | 
|  | { | 
|  | nullset = 1; | 
|  | if (p == 0) | 
|  | p = arg + strlen (arg);	/* So that savestring below will work.  */ | 
|  | } | 
|  | else | 
|  | { | 
|  | /* Not setting variable value to null.  */ | 
|  | val = p + 1; | 
|  | while (*val == ' ' || *val == '\t') | 
|  | val++; | 
|  | } | 
|  |  | 
|  | while (p != arg && (p[-1] == ' ' || p[-1] == '\t')) | 
|  | p--; | 
|  |  | 
|  | std::string var (arg, p - arg); | 
|  | if (nullset) | 
|  | { | 
|  | gdb_printf (_("Setting environment variable " | 
|  | "\"%s\" to null value.\n"), | 
|  | var.c_str ()); | 
|  | current_inferior ()->environment.set (var.c_str (), ""); | 
|  | } | 
|  | else | 
|  | current_inferior ()->environment.set (var.c_str (), val); | 
|  | } | 
|  |  | 
|  | static void | 
|  | unset_environment_command (const char *var, int from_tty) | 
|  | { | 
|  | if (var == 0) | 
|  | { | 
|  | /* If there is no argument, delete all environment variables. | 
|  | Ask for confirmation if reading from the terminal.  */ | 
|  | if (!from_tty || query (_("Delete all environment variables? "))) | 
|  | current_inferior ()->environment.clear (); | 
|  | } | 
|  | else | 
|  | current_inferior ()->environment.unset (var); | 
|  | } | 
|  |  | 
|  | /* Handle the execution path (PATH variable).  */ | 
|  |  | 
|  | static const char path_var_name[] = "PATH"; | 
|  |  | 
|  | static void | 
|  | path_info (const char *args, int from_tty) | 
|  | { | 
|  | gdb_puts ("Executable and object file path: "); | 
|  | gdb_puts (current_inferior ()->environment.get (path_var_name)); | 
|  | gdb_puts ("\n"); | 
|  | } | 
|  |  | 
|  | /* Add zero or more directories to the front of the execution path.  */ | 
|  |  | 
|  | static void | 
|  | path_command (const char *dirname, int from_tty) | 
|  | { | 
|  | const char *env; | 
|  |  | 
|  | dont_repeat (); | 
|  | env = current_inferior ()->environment.get (path_var_name); | 
|  | /* Can be null if path is not set.  */ | 
|  | if (!env) | 
|  | env = ""; | 
|  | std::string exec_path = env; | 
|  | mod_path (dirname, exec_path); | 
|  | current_inferior ()->environment.set (path_var_name, exec_path.c_str ()); | 
|  | if (from_tty) | 
|  | path_info (nullptr, from_tty); | 
|  | } | 
|  |  | 
|  |  | 
|  | static void | 
|  | pad_to_column (string_file &stream, int col) | 
|  | { | 
|  | /* At least one space must be printed to separate columns.  */ | 
|  | stream.putc (' '); | 
|  | const int size = stream.size (); | 
|  | if (size < col) | 
|  | stream.puts (n_spaces (col - size)); | 
|  | } | 
|  |  | 
|  | /* Print out the register NAME with value VAL, to FILE, in the default | 
|  | fashion.  */ | 
|  |  | 
|  | static void | 
|  | default_print_one_register_info (struct ui_file *file, | 
|  | const char *name, | 
|  | struct value *val) | 
|  | { | 
|  | struct type *regtype = value_type (val); | 
|  | int print_raw_format; | 
|  | string_file format_stream; | 
|  | enum tab_stops | 
|  | { | 
|  | value_column_1 = 15, | 
|  | /* Give enough room for "0x", 16 hex digits and two spaces in | 
|  | preceding column.  */ | 
|  | value_column_2 = value_column_1 + 2 + 16 + 2, | 
|  | }; | 
|  |  | 
|  | format_stream.puts (name); | 
|  | pad_to_column (format_stream, value_column_1); | 
|  |  | 
|  | print_raw_format = (value_entirely_available (val) | 
|  | && !value_optimized_out (val)); | 
|  |  | 
|  | /* If virtual format is floating, print it that way, and in raw | 
|  | hex.  */ | 
|  | if (regtype->code () == TYPE_CODE_FLT | 
|  | || regtype->code () == TYPE_CODE_DECFLOAT) | 
|  | { | 
|  | struct value_print_options opts; | 
|  | const gdb_byte *valaddr = value_contents_for_printing (val).data (); | 
|  | enum bfd_endian byte_order = type_byte_order (regtype); | 
|  |  | 
|  | get_user_print_options (&opts); | 
|  | opts.deref_ref = true; | 
|  |  | 
|  | common_val_print (val, &format_stream, 0, &opts, current_language); | 
|  |  | 
|  | if (print_raw_format) | 
|  | { | 
|  | pad_to_column (format_stream, value_column_2); | 
|  | format_stream.puts ("(raw "); | 
|  | print_hex_chars (&format_stream, valaddr, regtype->length (), | 
|  | byte_order, true); | 
|  | format_stream.putc (')'); | 
|  | } | 
|  | } | 
|  | else | 
|  | { | 
|  | struct value_print_options opts; | 
|  |  | 
|  | /* Print the register in hex.  */ | 
|  | get_formatted_print_options (&opts, 'x'); | 
|  | opts.deref_ref = true; | 
|  | common_val_print (val, &format_stream, 0, &opts, current_language); | 
|  | /* If not a vector register, print it also according to its | 
|  | natural format.  */ | 
|  | if (print_raw_format && regtype->is_vector () == 0) | 
|  | { | 
|  | pad_to_column (format_stream, value_column_2); | 
|  | get_user_print_options (&opts); | 
|  | opts.deref_ref = true; | 
|  | common_val_print (val, &format_stream, 0, &opts, current_language); | 
|  | } | 
|  | } | 
|  |  | 
|  | gdb_puts (format_stream.c_str (), file); | 
|  | gdb_printf (file, "\n"); | 
|  | } | 
|  |  | 
|  | /* Print out the machine register regnum.  If regnum is -1, print all | 
|  | registers (print_all == 1) or all non-float and non-vector | 
|  | registers (print_all == 0). | 
|  |  | 
|  | For most machines, having all_registers_info() print the | 
|  | register(s) one per line is good enough.  If a different format is | 
|  | required, (eg, for MIPS or Pyramid 90x, which both have lots of | 
|  | regs), or there is an existing convention for showing all the | 
|  | registers, define the architecture method PRINT_REGISTERS_INFO to | 
|  | provide that format.  */ | 
|  |  | 
|  | void | 
|  | default_print_registers_info (struct gdbarch *gdbarch, | 
|  | struct ui_file *file, | 
|  | frame_info_ptr frame, | 
|  | int regnum, int print_all) | 
|  | { | 
|  | int i; | 
|  | const int numregs = gdbarch_num_cooked_regs (gdbarch); | 
|  |  | 
|  | for (i = 0; i < numregs; i++) | 
|  | { | 
|  | /* Decide between printing all regs, non-float / vector regs, or | 
|  | specific reg.  */ | 
|  | if (regnum == -1) | 
|  | { | 
|  | if (print_all) | 
|  | { | 
|  | if (!gdbarch_register_reggroup_p (gdbarch, i, all_reggroup)) | 
|  | continue; | 
|  | } | 
|  | else | 
|  | { | 
|  | if (!gdbarch_register_reggroup_p (gdbarch, i, general_reggroup)) | 
|  | continue; | 
|  | } | 
|  | } | 
|  | else | 
|  | { | 
|  | if (i != regnum) | 
|  | continue; | 
|  | } | 
|  |  | 
|  | /* If the register name is empty, it is undefined for this | 
|  | processor, so don't display anything.  */ | 
|  | if (*(gdbarch_register_name (gdbarch, i)) == '\0') | 
|  | continue; | 
|  |  | 
|  | default_print_one_register_info (file, | 
|  | gdbarch_register_name (gdbarch, i), | 
|  | value_of_register (i, frame)); | 
|  | } | 
|  | } | 
|  |  | 
|  | void | 
|  | registers_info (const char *addr_exp, int fpregs) | 
|  | { | 
|  | frame_info_ptr frame; | 
|  | struct gdbarch *gdbarch; | 
|  |  | 
|  | if (!target_has_registers ()) | 
|  | error (_("The program has no registers now.")); | 
|  | frame = get_selected_frame (nullptr); | 
|  | gdbarch = get_frame_arch (frame); | 
|  |  | 
|  | if (!addr_exp) | 
|  | { | 
|  | gdbarch_print_registers_info (gdbarch, gdb_stdout, | 
|  | frame, -1, fpregs); | 
|  | return; | 
|  | } | 
|  |  | 
|  | while (*addr_exp != '\0') | 
|  | { | 
|  | const char *start; | 
|  | const char *end; | 
|  |  | 
|  | /* Skip leading white space.  */ | 
|  | addr_exp = skip_spaces (addr_exp); | 
|  |  | 
|  | /* Discard any leading ``$''.  Check that there is something | 
|  | resembling a register following it.  */ | 
|  | if (addr_exp[0] == '$') | 
|  | addr_exp++; | 
|  | if (isspace ((*addr_exp)) || (*addr_exp) == '\0') | 
|  | error (_("Missing register name")); | 
|  |  | 
|  | /* Find the start/end of this register name/num/group.  */ | 
|  | start = addr_exp; | 
|  | while ((*addr_exp) != '\0' && !isspace ((*addr_exp))) | 
|  | addr_exp++; | 
|  | end = addr_exp; | 
|  |  | 
|  | /* Figure out what we've found and display it.  */ | 
|  |  | 
|  | /* A register name?  */ | 
|  | { | 
|  | int regnum = user_reg_map_name_to_regnum (gdbarch, start, end - start); | 
|  |  | 
|  | if (regnum >= 0) | 
|  | { | 
|  | /* User registers lie completely outside of the range of | 
|  | normal registers.  Catch them early so that the target | 
|  | never sees them.  */ | 
|  | if (regnum >= gdbarch_num_cooked_regs (gdbarch)) | 
|  | { | 
|  | struct value *regval = value_of_user_reg (regnum, frame); | 
|  | const char *regname = user_reg_map_regnum_to_name (gdbarch, | 
|  | regnum); | 
|  |  | 
|  | /* Print in the same fashion | 
|  | gdbarch_print_registers_info's default | 
|  | implementation prints.  */ | 
|  | default_print_one_register_info (gdb_stdout, | 
|  | regname, | 
|  | regval); | 
|  | } | 
|  | else | 
|  | gdbarch_print_registers_info (gdbarch, gdb_stdout, | 
|  | frame, regnum, fpregs); | 
|  | continue; | 
|  | } | 
|  | } | 
|  |  | 
|  | /* A register group?  */ | 
|  | { | 
|  | const struct reggroup *group = nullptr; | 
|  | for (const struct reggroup *g : gdbarch_reggroups (gdbarch)) | 
|  | { | 
|  | /* Don't bother with a length check.  Should the user | 
|  | enter a short register group name, go with the first | 
|  | group that matches.  */ | 
|  | if (strncmp (start, g->name (), end - start) == 0) | 
|  | { | 
|  | group = g; | 
|  | break; | 
|  | } | 
|  | } | 
|  | if (group != nullptr) | 
|  | { | 
|  | int regnum; | 
|  |  | 
|  | for (regnum = 0; | 
|  | regnum < gdbarch_num_cooked_regs (gdbarch); | 
|  | regnum++) | 
|  | { | 
|  | if (gdbarch_register_reggroup_p (gdbarch, regnum, group)) | 
|  | gdbarch_print_registers_info (gdbarch, | 
|  | gdb_stdout, frame, | 
|  | regnum, fpregs); | 
|  | } | 
|  | continue; | 
|  | } | 
|  | } | 
|  |  | 
|  | /* Nothing matched.  */ | 
|  | error (_("Invalid register `%.*s'"), (int) (end - start), start); | 
|  | } | 
|  | } | 
|  |  | 
|  | static void | 
|  | info_all_registers_command (const char *addr_exp, int from_tty) | 
|  | { | 
|  | registers_info (addr_exp, 1); | 
|  | } | 
|  |  | 
|  | static void | 
|  | info_registers_command (const char *addr_exp, int from_tty) | 
|  | { | 
|  | registers_info (addr_exp, 0); | 
|  | } | 
|  |  | 
|  | static void | 
|  | print_vector_info (struct ui_file *file, | 
|  | frame_info_ptr frame, const char *args) | 
|  | { | 
|  | struct gdbarch *gdbarch = get_frame_arch (frame); | 
|  |  | 
|  | if (gdbarch_print_vector_info_p (gdbarch)) | 
|  | gdbarch_print_vector_info (gdbarch, file, frame, args); | 
|  | else | 
|  | { | 
|  | int regnum; | 
|  | int printed_something = 0; | 
|  |  | 
|  | for (regnum = 0; regnum < gdbarch_num_cooked_regs (gdbarch); regnum++) | 
|  | { | 
|  | if (gdbarch_register_reggroup_p (gdbarch, regnum, vector_reggroup)) | 
|  | { | 
|  | printed_something = 1; | 
|  | gdbarch_print_registers_info (gdbarch, file, frame, regnum, 1); | 
|  | } | 
|  | } | 
|  | if (!printed_something) | 
|  | gdb_printf (file, "No vector information\n"); | 
|  | } | 
|  | } | 
|  |  | 
|  | static void | 
|  | info_vector_command (const char *args, int from_tty) | 
|  | { | 
|  | if (!target_has_registers ()) | 
|  | error (_("The program has no registers now.")); | 
|  |  | 
|  | print_vector_info (gdb_stdout, get_selected_frame (nullptr), args); | 
|  | } | 
|  |  | 
|  | /* Kill the inferior process.  Make us have no inferior.  */ | 
|  |  | 
|  | static void | 
|  | kill_command (const char *arg, int from_tty) | 
|  | { | 
|  | /* FIXME:  This should not really be inferior_ptid (or target_has_execution). | 
|  | It should be a distinct flag that indicates that a target is active, cuz | 
|  | some targets don't have processes!  */ | 
|  |  | 
|  | if (inferior_ptid == null_ptid) | 
|  | error (_("The program is not being run.")); | 
|  | if (!query (_("Kill the program being debugged? "))) | 
|  | error (_("Not confirmed.")); | 
|  |  | 
|  | int pid = current_inferior ()->pid; | 
|  | /* Save the pid as a string before killing the inferior, since that | 
|  | may unpush the current target, and we need the string after.  */ | 
|  | std::string pid_str = target_pid_to_str (ptid_t (pid)); | 
|  | int infnum = current_inferior ()->num; | 
|  |  | 
|  | target_kill (); | 
|  | bfd_cache_close_all (); | 
|  |  | 
|  | if (print_inferior_events) | 
|  | gdb_printf (_("[Inferior %d (%s) killed]\n"), | 
|  | infnum, pid_str.c_str ()); | 
|  | } | 
|  |  | 
|  | /* Used in `attach&' command.  Proceed threads of inferior INF iff | 
|  | they stopped due to debugger request, and when they did, they | 
|  | reported a clean stop (GDB_SIGNAL_0).  Do not proceed threads that | 
|  | have been explicitly been told to stop.  */ | 
|  |  | 
|  | static void | 
|  | proceed_after_attach (inferior *inf) | 
|  | { | 
|  | /* Don't error out if the current thread is running, because | 
|  | there may be other stopped threads.  */ | 
|  |  | 
|  | /* Backup current thread and selected frame.  */ | 
|  | scoped_restore_current_thread restore_thread; | 
|  |  | 
|  | for (thread_info *thread : inf->non_exited_threads ()) | 
|  | if (!thread->executing () | 
|  | && !thread->stop_requested | 
|  | && thread->stop_signal () == GDB_SIGNAL_0) | 
|  | { | 
|  | switch_to_thread (thread); | 
|  | clear_proceed_status (0); | 
|  | proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT); | 
|  | } | 
|  | } | 
|  |  | 
|  | /* See inferior.h.  */ | 
|  |  | 
|  | void | 
|  | setup_inferior (int from_tty) | 
|  | { | 
|  | struct inferior *inferior; | 
|  |  | 
|  | inferior = current_inferior (); | 
|  | inferior->needs_setup = false; | 
|  |  | 
|  | /* If no exec file is yet known, try to determine it from the | 
|  | process itself.  */ | 
|  | if (get_exec_file (0) == nullptr) | 
|  | exec_file_locate_attach (inferior_ptid.pid (), 1, from_tty); | 
|  | else | 
|  | { | 
|  | reopen_exec_file (); | 
|  | reread_symbols (from_tty); | 
|  | } | 
|  |  | 
|  | /* Take any necessary post-attaching actions for this platform.  */ | 
|  | target_post_attach (inferior_ptid.pid ()); | 
|  |  | 
|  | post_create_inferior (from_tty); | 
|  | } | 
|  |  | 
|  | /* What to do after the first program stops after attaching.  */ | 
|  | enum attach_post_wait_mode | 
|  | { | 
|  | /* Do nothing.  Leaves threads as they are.  */ | 
|  | ATTACH_POST_WAIT_NOTHING, | 
|  |  | 
|  | /* Re-resume threads that are marked running.  */ | 
|  | ATTACH_POST_WAIT_RESUME, | 
|  |  | 
|  | /* Stop all threads.  */ | 
|  | ATTACH_POST_WAIT_STOP, | 
|  | }; | 
|  |  | 
|  | /* Called after we've attached to a process and we've seen it stop for | 
|  | the first time.  Resume, stop, or don't touch the threads according | 
|  | to MODE.  */ | 
|  |  | 
|  | static void | 
|  | attach_post_wait (int from_tty, enum attach_post_wait_mode mode) | 
|  | { | 
|  | struct inferior *inferior; | 
|  |  | 
|  | inferior = current_inferior (); | 
|  | inferior->control.stop_soon = NO_STOP_QUIETLY; | 
|  |  | 
|  | if (inferior->needs_setup) | 
|  | setup_inferior (from_tty); | 
|  |  | 
|  | if (mode == ATTACH_POST_WAIT_RESUME) | 
|  | { | 
|  | /* The user requested an `attach&', so be sure to leave threads | 
|  | that didn't get a signal running.  */ | 
|  |  | 
|  | /* Immediately resume all suspended threads of this inferior, | 
|  | and this inferior only.  This should have no effect on | 
|  | already running threads.  If a thread has been stopped with a | 
|  | signal, leave it be.  */ | 
|  | if (non_stop) | 
|  | proceed_after_attach (inferior); | 
|  | else | 
|  | { | 
|  | if (inferior_thread ()->stop_signal () == GDB_SIGNAL_0) | 
|  | { | 
|  | clear_proceed_status (0); | 
|  | proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT); | 
|  | } | 
|  | } | 
|  | } | 
|  | else if (mode == ATTACH_POST_WAIT_STOP) | 
|  | { | 
|  | /* The user requested a plain `attach', so be sure to leave | 
|  | the inferior stopped.  */ | 
|  |  | 
|  | /* At least the current thread is already stopped.  */ | 
|  |  | 
|  | /* In all-stop, by definition, all threads have to be already | 
|  | stopped at this point.  In non-stop, however, although the | 
|  | selected thread is stopped, others may still be executing. | 
|  | Be sure to explicitly stop all threads of the process.  This | 
|  | should have no effect on already stopped threads.  */ | 
|  | if (non_stop) | 
|  | target_stop (ptid_t (inferior->pid)); | 
|  | else if (target_is_non_stop_p ()) | 
|  | { | 
|  | struct thread_info *lowest = inferior_thread (); | 
|  |  | 
|  | stop_all_threads ("attaching"); | 
|  |  | 
|  | /* It's not defined which thread will report the attach | 
|  | stop.  For consistency, always select the thread with | 
|  | lowest GDB number, which should be the main thread, if it | 
|  | still exists.  */ | 
|  | for (thread_info *thread : current_inferior ()->non_exited_threads ()) | 
|  | if (thread->inf->num < lowest->inf->num | 
|  | || thread->per_inf_num < lowest->per_inf_num) | 
|  | lowest = thread; | 
|  |  | 
|  | switch_to_thread (lowest); | 
|  | } | 
|  |  | 
|  | /* Tell the user/frontend where we're stopped.  */ | 
|  | normal_stop (); | 
|  | if (deprecated_attach_hook) | 
|  | deprecated_attach_hook (); | 
|  | } | 
|  | } | 
|  |  | 
|  | /* "attach" command entry point.  Takes a program started up outside | 
|  | of gdb and ``attaches'' to it.  This stops it cold in its tracks | 
|  | and allows us to start debugging it.  */ | 
|  |  | 
|  | void | 
|  | attach_command (const char *args, int from_tty) | 
|  | { | 
|  | int async_exec; | 
|  | struct target_ops *attach_target; | 
|  | struct inferior *inferior = current_inferior (); | 
|  | enum attach_post_wait_mode mode; | 
|  |  | 
|  | dont_repeat ();		/* Not for the faint of heart */ | 
|  |  | 
|  | scoped_disable_commit_resumed disable_commit_resumed ("attaching"); | 
|  |  | 
|  | if (gdbarch_has_global_solist (target_gdbarch ())) | 
|  | /* Don't complain if all processes share the same symbol | 
|  | space.  */ | 
|  | ; | 
|  | else if (target_has_execution ()) | 
|  | { | 
|  | if (query (_("A program is being debugged already.  Kill it? "))) | 
|  | target_kill (); | 
|  | else | 
|  | error (_("Not killed.")); | 
|  | } | 
|  |  | 
|  | /* Clean up any leftovers from other runs.  Some other things from | 
|  | this function should probably be moved into target_pre_inferior.  */ | 
|  | target_pre_inferior (from_tty); | 
|  |  | 
|  | gdb::unique_xmalloc_ptr<char> stripped = strip_bg_char (args, &async_exec); | 
|  | args = stripped.get (); | 
|  |  | 
|  | attach_target = find_attach_target (); | 
|  |  | 
|  | prepare_execution_command (attach_target, async_exec); | 
|  |  | 
|  | if (non_stop && !attach_target->supports_non_stop ()) | 
|  | error (_("Cannot attach to this target in non-stop mode")); | 
|  |  | 
|  | attach_target->attach (args, from_tty); | 
|  | /* to_attach should push the target, so after this point we | 
|  | shouldn't refer to attach_target again.  */ | 
|  | attach_target = nullptr; | 
|  |  | 
|  | infrun_debug_show_threads ("immediately after attach", | 
|  | current_inferior ()->non_exited_threads ()); | 
|  |  | 
|  | /* Enable async mode if it is supported by the target.  */ | 
|  | if (target_can_async_p ()) | 
|  | target_async (true); | 
|  |  | 
|  | /* Set up the "saved terminal modes" of the inferior | 
|  | based on what modes we are starting it with.  */ | 
|  | target_terminal::init (); | 
|  |  | 
|  | /* Install inferior's terminal modes.  This may look like a no-op, | 
|  | as we've just saved them above, however, this does more than | 
|  | restore terminal settings: | 
|  |  | 
|  | - installs a SIGINT handler that forwards SIGINT to the inferior. | 
|  | Otherwise a Ctrl-C pressed just while waiting for the initial | 
|  | stop would end up as a spurious Quit. | 
|  |  | 
|  | - removes stdin from the event loop, which we need if attaching | 
|  | in the foreground, otherwise on targets that report an initial | 
|  | stop on attach (which are most) we'd process input/commands | 
|  | while we're in the event loop waiting for that stop.  That is, | 
|  | before the attach continuation runs and the command is really | 
|  | finished.  */ | 
|  | target_terminal::inferior (); | 
|  |  | 
|  | /* Set up execution context to know that we should return from | 
|  | wait_for_inferior as soon as the target reports a stop.  */ | 
|  | init_wait_for_inferior (); | 
|  |  | 
|  | inferior->needs_setup = true; | 
|  |  | 
|  | if (target_is_non_stop_p ()) | 
|  | { | 
|  | /* If we find that the current thread isn't stopped, explicitly | 
|  | do so now, because we're going to install breakpoints and | 
|  | poke at memory.  */ | 
|  |  | 
|  | if (async_exec) | 
|  | /* The user requested an `attach&'; stop just one thread.  */ | 
|  | target_stop (inferior_ptid); | 
|  | else | 
|  | /* The user requested an `attach', so stop all threads of this | 
|  | inferior.  */ | 
|  | target_stop (ptid_t (inferior_ptid.pid ())); | 
|  | } | 
|  |  | 
|  | /* Check for exec file mismatch, and let the user solve it.  */ | 
|  | validate_exec_file (from_tty); | 
|  |  | 
|  | mode = async_exec ? ATTACH_POST_WAIT_RESUME : ATTACH_POST_WAIT_STOP; | 
|  |  | 
|  | /* Some system don't generate traps when attaching to inferior. | 
|  | E.g. Mach 3 or GNU hurd.  */ | 
|  | if (!target_attach_no_wait ()) | 
|  | { | 
|  | /* Careful here.  See comments in inferior.h.  Basically some | 
|  | OSes don't ignore SIGSTOPs on continue requests anymore.  We | 
|  | need a way for handle_inferior_event to reset the stop_signal | 
|  | variable after an attach, and this is what | 
|  | STOP_QUIETLY_NO_SIGSTOP is for.  */ | 
|  | inferior->control.stop_soon = STOP_QUIETLY_NO_SIGSTOP; | 
|  |  | 
|  | /* Wait for stop.  */ | 
|  | inferior->add_continuation ([=] () | 
|  | { | 
|  | attach_post_wait (from_tty, mode); | 
|  | }); | 
|  |  | 
|  | /* Let infrun consider waiting for events out of this | 
|  | target.  */ | 
|  | inferior->process_target ()->threads_executing = true; | 
|  |  | 
|  | if (!target_is_async_p ()) | 
|  | mark_infrun_async_event_handler (); | 
|  | return; | 
|  | } | 
|  | else | 
|  | attach_post_wait (from_tty, mode); | 
|  |  | 
|  | disable_commit_resumed.reset_and_commit (); | 
|  | } | 
|  |  | 
|  | /* We had just found out that the target was already attached to an | 
|  | inferior.  PTID points at a thread of this new inferior, that is | 
|  | the most likely to be stopped right now, but not necessarily so. | 
|  | The new inferior is assumed to be already added to the inferior | 
|  | list at this point.  If LEAVE_RUNNING, then leave the threads of | 
|  | this inferior running, except those we've explicitly seen reported | 
|  | as stopped.  */ | 
|  |  | 
|  | void | 
|  | notice_new_inferior (thread_info *thr, bool leave_running, int from_tty) | 
|  | { | 
|  | enum attach_post_wait_mode mode | 
|  | = leave_running ? ATTACH_POST_WAIT_RESUME : ATTACH_POST_WAIT_NOTHING; | 
|  |  | 
|  | gdb::optional<scoped_restore_current_thread> restore_thread; | 
|  |  | 
|  | if (inferior_ptid != null_ptid) | 
|  | restore_thread.emplace (); | 
|  |  | 
|  | /* Avoid reading registers -- we haven't fetched the target | 
|  | description yet.  */ | 
|  | switch_to_thread_no_regs (thr); | 
|  |  | 
|  | /* When we "notice" a new inferior we need to do all the things we | 
|  | would normally do if we had just attached to it.  */ | 
|  |  | 
|  | if (thr->executing ()) | 
|  | { | 
|  | struct inferior *inferior = current_inferior (); | 
|  |  | 
|  | /* We're going to install breakpoints, and poke at memory, | 
|  | ensure that the inferior is stopped for a moment while we do | 
|  | that.  */ | 
|  | target_stop (inferior_ptid); | 
|  |  | 
|  | inferior->control.stop_soon = STOP_QUIETLY_REMOTE; | 
|  |  | 
|  | /* Wait for stop before proceeding.  */ | 
|  | inferior->add_continuation ([=] () | 
|  | { | 
|  | attach_post_wait (from_tty, mode); | 
|  | }); | 
|  |  | 
|  | return; | 
|  | } | 
|  |  | 
|  | attach_post_wait (from_tty, mode); | 
|  | } | 
|  |  | 
|  | /* | 
|  | * detach_command -- | 
|  | * takes a program previously attached to and detaches it. | 
|  | * The program resumes execution 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.  For this | 
|  | * to work, it may be necessary for the process to have been | 
|  | * previously attached.  It *might* work if the program was | 
|  | * started via the normal ptrace (PTRACE_TRACEME). | 
|  | */ | 
|  |  | 
|  | void | 
|  | detach_command (const char *args, int from_tty) | 
|  | { | 
|  | dont_repeat ();		/* Not for the faint of heart.  */ | 
|  |  | 
|  | if (inferior_ptid == null_ptid) | 
|  | error (_("The program is not being run.")); | 
|  |  | 
|  | scoped_disable_commit_resumed disable_commit_resumed ("detaching"); | 
|  |  | 
|  | query_if_trace_running (from_tty); | 
|  |  | 
|  | disconnect_tracing (); | 
|  |  | 
|  | /* Hold a strong reference to the target while (maybe) | 
|  | detaching the parent.  Otherwise detaching could close the | 
|  | target.  */ | 
|  | auto target_ref | 
|  | = target_ops_ref::new_reference (current_inferior ()->process_target ()); | 
|  |  | 
|  | /* Save this before detaching, since detaching may unpush the | 
|  | process_stratum target.  */ | 
|  | bool was_non_stop_p = target_is_non_stop_p (); | 
|  |  | 
|  | target_detach (current_inferior (), from_tty); | 
|  |  | 
|  | /* The current inferior process was just detached successfully.  Get | 
|  | rid of breakpoints that no longer make sense.  Note we don't do | 
|  | this within target_detach because that is also used when | 
|  | following child forks, and in that case we will want to transfer | 
|  | breakpoints to the child, not delete them.  */ | 
|  | breakpoint_init_inferior (inf_exited); | 
|  |  | 
|  | /* If the solist is global across inferiors, don't clear it when we | 
|  | detach from a single inferior.  */ | 
|  | if (!gdbarch_has_global_solist (target_gdbarch ())) | 
|  | no_shared_libraries (nullptr, from_tty); | 
|  |  | 
|  | if (deprecated_detach_hook) | 
|  | deprecated_detach_hook (); | 
|  |  | 
|  | if (!was_non_stop_p) | 
|  | restart_after_all_stop_detach (as_process_stratum_target (target_ref.get ())); | 
|  |  | 
|  | disable_commit_resumed.reset_and_commit (); | 
|  | } | 
|  |  | 
|  | /* Disconnect from the current target without resuming it (leaving it | 
|  | waiting for a debugger). | 
|  |  | 
|  | We'd better not have left any breakpoints in the program or the | 
|  | next debugger will get confused.  Currently only supported for some | 
|  | remote targets, since the normal attach mechanisms don't work on | 
|  | stopped processes on some native platforms (e.g. GNU/Linux).  */ | 
|  |  | 
|  | static void | 
|  | disconnect_command (const char *args, int from_tty) | 
|  | { | 
|  | dont_repeat ();		/* Not for the faint of heart.  */ | 
|  | query_if_trace_running (from_tty); | 
|  | disconnect_tracing (); | 
|  | target_disconnect (args, from_tty); | 
|  | no_shared_libraries (nullptr, from_tty); | 
|  | init_thread_list (); | 
|  | if (deprecated_detach_hook) | 
|  | deprecated_detach_hook (); | 
|  | } | 
|  |  | 
|  | /* Stop PTID in the current target, and tag the PTID threads as having | 
|  | been explicitly requested to stop.  PTID can be a thread, a | 
|  | process, or minus_one_ptid, meaning all threads of all inferiors of | 
|  | the current target.  */ | 
|  |  | 
|  | static void | 
|  | stop_current_target_threads_ns (ptid_t ptid) | 
|  | { | 
|  | target_stop (ptid); | 
|  |  | 
|  | /* Tag the thread as having been explicitly requested to stop, so | 
|  | other parts of gdb know not to resume this thread automatically, | 
|  | if it was stopped due to an internal event.  Limit this to | 
|  | non-stop mode, as when debugging a multi-threaded application in | 
|  | all-stop mode, we will only get one stop event --- it's undefined | 
|  | which thread will report the event.  */ | 
|  | set_stop_requested (current_inferior ()->process_target (), | 
|  | ptid, 1); | 
|  | } | 
|  |  | 
|  | /* See inferior.h.  */ | 
|  |  | 
|  | void | 
|  | interrupt_target_1 (bool all_threads) | 
|  | { | 
|  | scoped_disable_commit_resumed disable_commit_resumed ("interrupting"); | 
|  |  | 
|  | if (non_stop) | 
|  | { | 
|  | if (all_threads) | 
|  | { | 
|  | scoped_restore_current_thread restore_thread; | 
|  |  | 
|  | for (inferior *inf : all_inferiors ()) | 
|  | { | 
|  | switch_to_inferior_no_thread (inf); | 
|  | stop_current_target_threads_ns (minus_one_ptid); | 
|  | } | 
|  | } | 
|  | else | 
|  | stop_current_target_threads_ns (inferior_ptid); | 
|  | } | 
|  | else | 
|  | target_interrupt (); | 
|  |  | 
|  | disable_commit_resumed.reset_and_commit (); | 
|  | } | 
|  |  | 
|  | /* interrupt [-a] | 
|  | Stop the execution of the target while running in async mode, in | 
|  | the background.  In all-stop, stop the whole process.  In non-stop | 
|  | mode, stop the current thread only by default, or stop all threads | 
|  | if the `-a' switch is used.  */ | 
|  |  | 
|  | static void | 
|  | interrupt_command (const char *args, int from_tty) | 
|  | { | 
|  | if (target_can_async_p ()) | 
|  | { | 
|  | int all_threads = 0; | 
|  |  | 
|  | dont_repeat ();		/* Not for the faint of heart.  */ | 
|  |  | 
|  | if (args != nullptr | 
|  | && startswith (args, "-a")) | 
|  | all_threads = 1; | 
|  |  | 
|  | interrupt_target_1 (all_threads); | 
|  | } | 
|  | } | 
|  |  | 
|  | /* See inferior.h.  */ | 
|  |  | 
|  | void | 
|  | default_print_float_info (struct gdbarch *gdbarch, struct ui_file *file, | 
|  | frame_info_ptr frame, const char *args) | 
|  | { | 
|  | int regnum; | 
|  | int printed_something = 0; | 
|  |  | 
|  | for (regnum = 0; regnum < gdbarch_num_cooked_regs (gdbarch); regnum++) | 
|  | { | 
|  | if (gdbarch_register_reggroup_p (gdbarch, regnum, float_reggroup)) | 
|  | { | 
|  | printed_something = 1; | 
|  | gdbarch_print_registers_info (gdbarch, file, frame, regnum, 1); | 
|  | } | 
|  | } | 
|  | if (!printed_something) | 
|  | gdb_printf (file, "No floating-point info " | 
|  | "available for this processor.\n"); | 
|  | } | 
|  |  | 
|  | static void | 
|  | info_float_command (const char *args, int from_tty) | 
|  | { | 
|  | frame_info_ptr frame; | 
|  |  | 
|  | if (!target_has_registers ()) | 
|  | error (_("The program has no registers now.")); | 
|  |  | 
|  | frame = get_selected_frame (nullptr); | 
|  | gdbarch_print_float_info (get_frame_arch (frame), gdb_stdout, frame, args); | 
|  | } | 
|  |  | 
|  | /* Implement `info proc' family of commands.  */ | 
|  |  | 
|  | static void | 
|  | info_proc_cmd_1 (const char *args, enum info_proc_what what, int from_tty) | 
|  | { | 
|  | struct gdbarch *gdbarch = get_current_arch (); | 
|  |  | 
|  | if (!target_info_proc (args, what)) | 
|  | { | 
|  | if (gdbarch_info_proc_p (gdbarch)) | 
|  | gdbarch_info_proc (gdbarch, args, what); | 
|  | else | 
|  | error (_("Not supported on this target.")); | 
|  | } | 
|  | } | 
|  |  | 
|  | /* Implement `info proc' when given without any further parameters.  */ | 
|  |  | 
|  | static void | 
|  | info_proc_cmd (const char *args, int from_tty) | 
|  | { | 
|  | info_proc_cmd_1 (args, IP_MINIMAL, from_tty); | 
|  | } | 
|  |  | 
|  | /* Implement `info proc mappings'.  */ | 
|  |  | 
|  | static void | 
|  | info_proc_cmd_mappings (const char *args, int from_tty) | 
|  | { | 
|  | info_proc_cmd_1 (args, IP_MAPPINGS, from_tty); | 
|  | } | 
|  |  | 
|  | /* Implement `info proc stat'.  */ | 
|  |  | 
|  | static void | 
|  | info_proc_cmd_stat (const char *args, int from_tty) | 
|  | { | 
|  | info_proc_cmd_1 (args, IP_STAT, from_tty); | 
|  | } | 
|  |  | 
|  | /* Implement `info proc status'.  */ | 
|  |  | 
|  | static void | 
|  | info_proc_cmd_status (const char *args, int from_tty) | 
|  | { | 
|  | info_proc_cmd_1 (args, IP_STATUS, from_tty); | 
|  | } | 
|  |  | 
|  | /* Implement `info proc cwd'.  */ | 
|  |  | 
|  | static void | 
|  | info_proc_cmd_cwd (const char *args, int from_tty) | 
|  | { | 
|  | info_proc_cmd_1 (args, IP_CWD, from_tty); | 
|  | } | 
|  |  | 
|  | /* Implement `info proc cmdline'.  */ | 
|  |  | 
|  | static void | 
|  | info_proc_cmd_cmdline (const char *args, int from_tty) | 
|  | { | 
|  | info_proc_cmd_1 (args, IP_CMDLINE, from_tty); | 
|  | } | 
|  |  | 
|  | /* Implement `info proc exe'.  */ | 
|  |  | 
|  | static void | 
|  | info_proc_cmd_exe (const char *args, int from_tty) | 
|  | { | 
|  | info_proc_cmd_1 (args, IP_EXE, from_tty); | 
|  | } | 
|  |  | 
|  | /* Implement `info proc files'.  */ | 
|  |  | 
|  | static void | 
|  | info_proc_cmd_files (const char *args, int from_tty) | 
|  | { | 
|  | info_proc_cmd_1 (args, IP_FILES, from_tty); | 
|  | } | 
|  |  | 
|  | /* Implement `info proc all'.  */ | 
|  |  | 
|  | static void | 
|  | info_proc_cmd_all (const char *args, int from_tty) | 
|  | { | 
|  | info_proc_cmd_1 (args, IP_ALL, from_tty); | 
|  | } | 
|  |  | 
|  | /* Implement `show print finish'.  */ | 
|  |  | 
|  | static void | 
|  | show_print_finish (struct ui_file *file, int from_tty, | 
|  | struct cmd_list_element *c, | 
|  | const char *value) | 
|  | { | 
|  | gdb_printf (file, _("\ | 
|  | Printing of return value after `finish' is %s.\n"), | 
|  | value); | 
|  | } | 
|  |  | 
|  |  | 
|  | /* This help string is used for the run, start, and starti commands. | 
|  | It is defined as a macro to prevent duplication.  */ | 
|  |  | 
|  | #define RUN_ARGS_HELP \ | 
|  | "You may specify arguments to give it.\n\ | 
|  | Args may include \"*\", or \"[...]\"; they are expanded using the\n\ | 
|  | shell that will start the program (specified by the \"$SHELL\" environment\n\ | 
|  | variable).  Input and output redirection with \">\", \"<\", or \">>\"\n\ | 
|  | are also allowed.\n\ | 
|  | \n\ | 
|  | With no arguments, uses arguments last specified (with \"run\" or \n\ | 
|  | \"set args\").  To cancel previous arguments and run with no arguments,\n\ | 
|  | use \"set args\" without arguments.\n\ | 
|  | \n\ | 
|  | To start the inferior without using a shell, use \"set startup-with-shell off\"." | 
|  |  | 
|  | void _initialize_infcmd (); | 
|  | void | 
|  | _initialize_infcmd () | 
|  | { | 
|  | static struct cmd_list_element *info_proc_cmdlist; | 
|  | struct cmd_list_element *c = nullptr; | 
|  | const char *cmd_name; | 
|  |  | 
|  | /* Add the filename of the terminal connected to inferior I/O.  */ | 
|  | add_setshow_optional_filename_cmd ("inferior-tty", class_run, | 
|  | &inferior_io_terminal_scratch, _("\ | 
|  | Set terminal for future runs of program being debugged."), _("\ | 
|  | Show terminal for future runs of program being debugged."), _("\ | 
|  | Usage: set inferior-tty [TTY]\n\n\ | 
|  | If TTY is omitted, the default behavior of using the same terminal as GDB\n\ | 
|  | is restored."), | 
|  | set_inferior_tty_command, | 
|  | show_inferior_tty_command, | 
|  | &setlist, &showlist); | 
|  | cmd_name = "inferior-tty"; | 
|  | c = lookup_cmd (&cmd_name, setlist, "", nullptr, -1, 1); | 
|  | gdb_assert (c != nullptr); | 
|  | add_alias_cmd ("tty", c, class_run, 0, &cmdlist); | 
|  |  | 
|  | cmd_name = "args"; | 
|  | add_setshow_string_noescape_cmd (cmd_name, class_run, | 
|  | &inferior_args_scratch, _("\ | 
|  | Set argument list to give program being debugged when it is started."), _("\ | 
|  | Show argument list to give program being debugged when it is started."), _("\ | 
|  | Follow this command with any number of args, to be passed to the program."), | 
|  | set_args_command, | 
|  | show_args_command, | 
|  | &setlist, &showlist); | 
|  | c = lookup_cmd (&cmd_name, setlist, "", nullptr, -1, 1); | 
|  | gdb_assert (c != nullptr); | 
|  | set_cmd_completer (c, filename_completer); | 
|  |  | 
|  | cmd_name = "cwd"; | 
|  | add_setshow_string_noescape_cmd (cmd_name, class_run, | 
|  | &inferior_cwd_scratch, _("\ | 
|  | Set the current working directory to be used when the inferior is started.\n\ | 
|  | Changing this setting does not have any effect on inferiors that are\n\ | 
|  | already running."), | 
|  | _("\ | 
|  | Show the current working directory that is used when the inferior is started."), | 
|  | _("\ | 
|  | Use this command to change the current working directory that will be used\n\ | 
|  | when the inferior is started.  This setting does not affect GDB's current\n\ | 
|  | working directory."), | 
|  | set_cwd_command, | 
|  | show_cwd_command, | 
|  | &setlist, &showlist); | 
|  | c = lookup_cmd (&cmd_name, setlist, "", nullptr, -1, 1); | 
|  | gdb_assert (c != nullptr); | 
|  | set_cmd_completer (c, filename_completer); | 
|  |  | 
|  | c = add_cmd ("environment", no_class, environment_info, _("\ | 
|  | The environment to give the program, or one variable's value.\n\ | 
|  | With an argument VAR, prints the value of environment variable VAR to\n\ | 
|  | give the program being debugged.  With no arguments, prints the entire\n\ | 
|  | environment to be given to the program."), &showlist); | 
|  | set_cmd_completer (c, noop_completer); | 
|  |  | 
|  | add_basic_prefix_cmd ("unset", no_class, | 
|  | _("Complement to certain \"set\" commands."), | 
|  | &unsetlist, 0, &cmdlist); | 
|  |  | 
|  | c = add_cmd ("environment", class_run, unset_environment_command, _("\ | 
|  | Cancel environment variable VAR for the program.\n\ | 
|  | This does not affect the program until the next \"run\" command."), | 
|  | &unsetlist); | 
|  | set_cmd_completer (c, noop_completer); | 
|  |  | 
|  | c = add_cmd ("environment", class_run, set_environment_command, _("\ | 
|  | Set environment variable value to give the program.\n\ | 
|  | Arguments are VAR VALUE where VAR is variable name and VALUE is value.\n\ | 
|  | VALUES of environment variables are uninterpreted strings.\n\ | 
|  | This does not affect the program until the next \"run\" command."), | 
|  | &setlist); | 
|  | set_cmd_completer (c, noop_completer); | 
|  |  | 
|  | c = add_com ("path", class_files, path_command, _("\ | 
|  | Add directory DIR(s) to beginning of search path for object files.\n\ | 
|  | $cwd in the path means the current working directory.\n\ | 
|  | This path is equivalent to the $PATH shell variable.  It is a list of\n\ | 
|  | directories, separated by colons.  These directories are searched to find\n\ | 
|  | fully linked executable files and separately compiled object files as \ | 
|  | needed.")); | 
|  | set_cmd_completer (c, filename_completer); | 
|  |  | 
|  | c = add_cmd ("paths", no_class, path_info, _("\ | 
|  | Current search path for finding object files.\n\ | 
|  | $cwd in the path means the current working directory.\n\ | 
|  | This path is equivalent to the $PATH shell variable.  It is a list of\n\ | 
|  | directories, separated by colons.  These directories are searched to find\n\ | 
|  | fully linked executable files and separately compiled object files as \ | 
|  | needed."), | 
|  | &showlist); | 
|  | set_cmd_completer (c, noop_completer); | 
|  |  | 
|  | add_prefix_cmd ("kill", class_run, kill_command, | 
|  | _("Kill execution of program being debugged."), | 
|  | &killlist, 0, &cmdlist); | 
|  |  | 
|  | add_com ("attach", class_run, attach_command, _("\ | 
|  | Attach to a process or file outside of GDB.\n\ | 
|  | This command attaches to another target, of the same type as your last\n\ | 
|  | \"target\" command (\"info files\" will show your target stack).\n\ | 
|  | The command may take as argument a process id or a device file.\n\ | 
|  | For a process id, you must have permission to send the process a signal,\n\ | 
|  | and it must have the same effective uid as the debugger.\n\ | 
|  | When using \"attach\" with a process id, the debugger finds the\n\ | 
|  | program running in the process, looking first in the current working\n\ | 
|  | directory, or (if not found there) using the source file search path\n\ | 
|  | (see the \"directory\" command).  You can also use the \"file\" command\n\ | 
|  | to specify the program, and to load its symbol table.")); | 
|  |  | 
|  | add_prefix_cmd ("detach", class_run, detach_command, _("\ | 
|  | Detach a process or file previously attached.\n\ | 
|  | If a process, it is no longer traced, and it continues its execution.  If\n\ | 
|  | you were debugging a file, the file is closed and gdb no longer accesses it."), | 
|  | &detachlist, 0, &cmdlist); | 
|  |  | 
|  | add_com ("disconnect", class_run, disconnect_command, _("\ | 
|  | Disconnect from a target.\n\ | 
|  | The target will wait for another debugger to connect.  Not available for\n\ | 
|  | all targets.")); | 
|  |  | 
|  | c = add_com ("signal", class_run, signal_command, _("\ | 
|  | Continue program with the specified signal.\n\ | 
|  | Usage: signal SIGNAL\n\ | 
|  | The SIGNAL argument is processed the same as the handle command.\n\ | 
|  | \n\ | 
|  | An argument of \"0\" means continue the program without sending it a signal.\n\ | 
|  | This is useful in cases where the program stopped because of a signal,\n\ | 
|  | and you want to resume the program while discarding the signal.\n\ | 
|  | \n\ | 
|  | In a multi-threaded program the signal is delivered to, or discarded from,\n\ | 
|  | the current thread only.")); | 
|  | set_cmd_completer (c, signal_completer); | 
|  |  | 
|  | c = add_com ("queue-signal", class_run, queue_signal_command, _("\ | 
|  | Queue a signal to be delivered to the current thread when it is resumed.\n\ | 
|  | Usage: queue-signal SIGNAL\n\ | 
|  | The SIGNAL argument is processed the same as the handle command.\n\ | 
|  | It is an error if the handling state of SIGNAL is \"nopass\".\n\ | 
|  | \n\ | 
|  | An argument of \"0\" means remove any currently queued signal from\n\ | 
|  | the current thread.  This is useful in cases where the program stopped\n\ | 
|  | because of a signal, and you want to resume it while discarding the signal.\n\ | 
|  | \n\ | 
|  | In a multi-threaded program the signal is queued with, or discarded from,\n\ | 
|  | the current thread only.")); | 
|  | set_cmd_completer (c, signal_completer); | 
|  |  | 
|  | cmd_list_element *stepi_cmd | 
|  | = add_com ("stepi", class_run, stepi_command, _("\ | 
|  | Step one instruction exactly.\n\ | 
|  | Usage: stepi [N]\n\ | 
|  | Argument N means step N times (or till program stops for another \ | 
|  | reason).")); | 
|  | add_com_alias ("si", stepi_cmd, class_run, 0); | 
|  |  | 
|  | cmd_list_element *nexti_cmd | 
|  | = add_com ("nexti", class_run, nexti_command, _("\ | 
|  | Step one instruction, but proceed through subroutine calls.\n\ | 
|  | Usage: nexti [N]\n\ | 
|  | Argument N means step N times (or till program stops for another \ | 
|  | reason).")); | 
|  | add_com_alias ("ni", nexti_cmd, class_run, 0); | 
|  |  | 
|  | cmd_list_element *finish_cmd | 
|  | = add_com ("finish", class_run, finish_command, _("\ | 
|  | Execute until selected stack frame returns.\n\ | 
|  | Usage: finish\n\ | 
|  | Upon return, the value returned is printed and put in the value history.")); | 
|  | add_com_alias ("fin", finish_cmd, class_run, 1); | 
|  |  | 
|  | cmd_list_element *next_cmd | 
|  | = add_com ("next", class_run, next_command, _("\ | 
|  | Step program, proceeding through subroutine calls.\n\ | 
|  | Usage: next [N]\n\ | 
|  | Unlike \"step\", if the current source line calls a subroutine,\n\ | 
|  | this command does not enter the subroutine, but instead steps over\n\ | 
|  | the call, in effect treating it as a single source line.")); | 
|  | add_com_alias ("n", next_cmd, class_run, 1); | 
|  |  | 
|  | cmd_list_element *step_cmd | 
|  | = add_com ("step", class_run, step_command, _("\ | 
|  | Step program until it reaches a different source line.\n\ | 
|  | Usage: step [N]\n\ | 
|  | Argument N means step N times (or till program stops for another \ | 
|  | reason).")); | 
|  | add_com_alias ("s", step_cmd, class_run, 1); | 
|  |  | 
|  | cmd_list_element *until_cmd | 
|  | = add_com ("until", class_run, until_command, _("\ | 
|  | Execute until past the current line or past a LOCATION.\n\ | 
|  | Execute until the program reaches a source line greater than the current\n\ | 
|  | or a specified location (same args as break command) within the current \ | 
|  | frame.")); | 
|  | set_cmd_completer (until_cmd, location_completer); | 
|  | add_com_alias ("u", until_cmd, class_run, 1); | 
|  |  | 
|  | c = add_com ("advance", class_run, advance_command, _("\ | 
|  | Continue the program up to the given location (same form as args for break \ | 
|  | command).\n\ | 
|  | Execution will also stop upon exit from the current stack frame.")); | 
|  | set_cmd_completer (c, location_completer); | 
|  |  | 
|  | cmd_list_element *jump_cmd | 
|  | = add_com ("jump", class_run, jump_command, _("\ | 
|  | Continue program being debugged at specified line or address.\n\ | 
|  | Usage: jump LOCATION\n\ | 
|  | Give as argument either LINENUM or *ADDR, where ADDR is an expression\n\ | 
|  | for an address to start at.")); | 
|  | set_cmd_completer (jump_cmd, location_completer); | 
|  | add_com_alias ("j", jump_cmd, class_run, 1); | 
|  |  | 
|  | cmd_list_element *continue_cmd | 
|  | = add_com ("continue", class_run, continue_command, _("\ | 
|  | Continue program being debugged, after signal or breakpoint.\n\ | 
|  | Usage: continue [N]\n\ | 
|  | If proceeding from breakpoint, a number N may be used as an argument,\n\ | 
|  | which means to set the ignore count of that breakpoint to N - 1 (so that\n\ | 
|  | the breakpoint won't break until the Nth time it is reached).\n\ | 
|  | \n\ | 
|  | If non-stop mode is enabled, continue only the current thread,\n\ | 
|  | otherwise all the threads in the program are continued.  To \n\ | 
|  | continue all stopped threads in non-stop mode, use the -a option.\n\ | 
|  | Specifying -a and an ignore count simultaneously is an error.")); | 
|  | add_com_alias ("c", continue_cmd, class_run, 1); | 
|  | add_com_alias ("fg", continue_cmd, class_run, 1); | 
|  |  | 
|  | cmd_list_element *run_cmd | 
|  | = add_com ("run", class_run, run_command, _("\ | 
|  | Start debugged program.\n" | 
|  | RUN_ARGS_HELP)); | 
|  | set_cmd_completer (run_cmd, filename_completer); | 
|  | add_com_alias ("r", run_cmd, class_run, 1); | 
|  |  | 
|  | c = add_com ("start", class_run, start_command, _("\ | 
|  | Start the debugged program stopping at the beginning of the main procedure.\n" | 
|  | RUN_ARGS_HELP)); | 
|  | set_cmd_completer (c, filename_completer); | 
|  |  | 
|  | c = add_com ("starti", class_run, starti_command, _("\ | 
|  | Start the debugged program stopping at the first instruction.\n" | 
|  | RUN_ARGS_HELP)); | 
|  | set_cmd_completer (c, filename_completer); | 
|  |  | 
|  | add_com ("interrupt", class_run, interrupt_command, | 
|  | _("Interrupt the execution of the debugged program.\n\ | 
|  | If non-stop mode is enabled, interrupt only the current thread,\n\ | 
|  | otherwise all the threads in the program are stopped.  To \n\ | 
|  | interrupt all running threads in non-stop mode, use the -a option.")); | 
|  |  | 
|  | cmd_list_element *info_registers_cmd | 
|  | = add_info ("registers", info_registers_command, _("\ | 
|  | List of integer registers and their contents, for selected stack frame.\n\ | 
|  | One or more register names as argument means describe the given registers.\n\ | 
|  | One or more register group names as argument means describe the registers\n\ | 
|  | in the named register groups.")); | 
|  | add_info_alias ("r", info_registers_cmd, 1); | 
|  | set_cmd_completer (info_registers_cmd, reg_or_group_completer); | 
|  |  | 
|  | c = add_info ("all-registers", info_all_registers_command, _("\ | 
|  | List of all registers and their contents, for selected stack frame.\n\ | 
|  | One or more register names as argument means describe the given registers.\n\ | 
|  | One or more register group names as argument means describe the registers\n\ | 
|  | in the named register groups.")); | 
|  | set_cmd_completer (c, reg_or_group_completer); | 
|  |  | 
|  | add_info ("program", info_program_command, | 
|  | _("Execution status of the program.")); | 
|  |  | 
|  | add_info ("float", info_float_command, | 
|  | _("Print the status of the floating point unit.")); | 
|  |  | 
|  | add_info ("vector", info_vector_command, | 
|  | _("Print the status of the vector unit.")); | 
|  |  | 
|  | add_prefix_cmd ("proc", class_info, info_proc_cmd, | 
|  | _("\ | 
|  | Show additional information about a process.\n\ | 
|  | Specify any process id, or use the program being debugged by default."), | 
|  | &info_proc_cmdlist, | 
|  | 1/*allow-unknown*/, &infolist); | 
|  |  | 
|  | add_cmd ("mappings", class_info, info_proc_cmd_mappings, _("\ | 
|  | List memory regions mapped by the specified process."), | 
|  | &info_proc_cmdlist); | 
|  |  | 
|  | add_cmd ("stat", class_info, info_proc_cmd_stat, _("\ | 
|  | List process info from /proc/PID/stat."), | 
|  | &info_proc_cmdlist); | 
|  |  | 
|  | add_cmd ("status", class_info, info_proc_cmd_status, _("\ | 
|  | List process info from /proc/PID/status."), | 
|  | &info_proc_cmdlist); | 
|  |  | 
|  | add_cmd ("cwd", class_info, info_proc_cmd_cwd, _("\ | 
|  | List current working directory of the specified process."), | 
|  | &info_proc_cmdlist); | 
|  |  | 
|  | add_cmd ("cmdline", class_info, info_proc_cmd_cmdline, _("\ | 
|  | List command line arguments of the specified process."), | 
|  | &info_proc_cmdlist); | 
|  |  | 
|  | add_cmd ("exe", class_info, info_proc_cmd_exe, _("\ | 
|  | List absolute filename for executable of the specified process."), | 
|  | &info_proc_cmdlist); | 
|  |  | 
|  | add_cmd ("files", class_info, info_proc_cmd_files, _("\ | 
|  | List files opened by the specified process."), | 
|  | &info_proc_cmdlist); | 
|  |  | 
|  | add_cmd ("all", class_info, info_proc_cmd_all, _("\ | 
|  | List all available info about the specified process."), | 
|  | &info_proc_cmdlist); | 
|  |  | 
|  | add_setshow_boolean_cmd ("finish", class_support, | 
|  | &finish_print, _("\ | 
|  | Set whether `finish' prints the return value."), _("\ | 
|  | Show whether `finish' prints the return value."), nullptr, | 
|  | nullptr, | 
|  | show_print_finish, | 
|  | &setprintlist, &showprintlist); | 
|  | } |