/* Memory-access and commands for "inferior" process, for GDB.
- Copyright (C) 1986-2022 Free Software Foundation, Inc.
+ Copyright (C) 1986-2024 Free Software Foundation, Inc.
This file is part of GDB.
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 "infrun.h"
#include "gdbsupport/environ.h"
#include "value.h"
-#include "gdbcmd.h"
+#include "cli/cli-cmds.h"
#include "symfile.h"
#include "gdbcore.h"
#include "target.h"
#include "inf-loop.h"
#include "linespec.h"
#include "thread-fsm.h"
-#include "top.h"
+#include "ui.h"
#include "interps.h"
#include "skip.h"
-#include "gdbsupport/gdb_optional.h"
+#include <optional>
#include "source.h"
#include "cli/cli-style.h"
#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
int stopped_by_random_signal;
+
+/* Whether "finish" should print the value. */
+
+static bool finish_print = true;
+
\f
+/* Store the new value passed to 'set inferior-tty'. */
+
static void
-set_inferior_tty_command (const char *args, int from_tty,
- struct cmd_list_element *c)
+set_tty_value (const std::string &tty)
{
- /* 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);
+ current_inferior ()->set_tty (tty);
}
+/* Get the current 'inferior-tty' value. */
+
+static const std::string &
+get_tty_value ()
+{
+ return current_inferior ()->tty ();
+}
+
+/* Implement 'show inferior-tty' command. */
+
static void
show_inferior_tty_command (struct ui_file *file, int from_tty,
struct cmd_list_element *c, const char *value)
directly. */
const std::string &inferior_tty = current_inferior ()->tty ();
- fprintf_filtered (file,
- _("Terminal for future runs of program being debugged "
- "is \"%s\".\n"), inferior_tty.c_str ());
+ 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)
+/* Store the new value passed to 'set args'. */
+
+static void
+set_args_value (const std::string &args)
{
- gdb::array_view<char * const> args (argv, argc);
- std::string n = construct_inferior_arguments (args);
- current_inferior ()->set_args (std::move (n));
+ current_inferior ()->set_args (args);
}
-/* Notice when `set args' is run. */
+/* Return the value for 'show args' to display. */
-static void
-set_args_command (const char *args, int from_tty, struct cmd_list_element *c)
+static const std::string &
+get_args_value ()
{
- /* CLI has assigned the user-provided value to inferior_args_scratch.
- Now route it to current inferior. */
- current_inferior ()->set_args (inferior_args_scratch);
+ return current_inferior ()->args ();
}
-/* Notice when `show args' is run. */
+/* Callback to implement 'show args' command. */
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 ());
+ /* Ignore the passed in value, pull the argument directly from the
+ inferior. However, these should always be the same. */
+ gdb_printf (file, _("\
+Argument list to give program being debugged when it is started is \"%s\".\n"),
+ current_inferior ()->args ().c_str ());
}
/* See gdbsupport/common-inferior.h. */
return current_inferior ()->cwd ();
}
-/* Handle the 'set cwd' command. */
+/* Store the new value passed to 'set cwd'. */
static void
-set_cwd_command (const char *args, int from_tty, struct cmd_list_element *c)
+set_cwd_value (const std::string &args)
{
- current_inferior ()->set_cwd (inferior_cwd_scratch);
+ current_inferior ()->set_cwd (args);
}
/* Handle the 'show cwd' command. */
const std::string &cwd = current_inferior ()->cwd ();
if (cwd.empty ())
- fprintf_filtered (file,
- _("\
+ 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
- fprintf_filtered (file,
- _("Current working directory that will be used "
- "when starting the inferior is \"%s\".\n"),
- cwd.c_str ());
+ gdb_printf (file,
+ _("Current working directory that will be used "
+ "when starting the inferior is \"%s\".\n"),
+ cwd.c_str ());
}
{
const char *p;
- if (args == NULL || *args == '\0')
+ if (args == nullptr || *args == '\0')
{
*bg_char_p = 0;
- return NULL;
+ return nullptr;
}
p = args + strlen (args);
/* 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
/* If the solist is global across processes, there's no need to
refetch it here. */
- if (!gdbarch_has_global_solist (target_gdbarch ()))
- solib_add (NULL, 0, auto_solib_add);
+ if (!gdbarch_has_global_solist (current_inferior ()->arch ()))
+ solib_add (nullptr, 0, auto_solib_add);
}
}
/* Insert temporary breakpoint in main function if requested. */
if (run_how == RUN_STOP_AT_MAIN)
{
- std::string arg = string_printf ("-qualified %s", main_name ());
+ /* To avoid other inferiors hitting this breakpoint, make it
+ inferior-specific. */
+ std::string arg = string_printf ("-qualified %s inferior %d",
+ main_name (),
+ current_inferior ()->num);
tbreak_command (arg.c_str (), 0);
}
want them to go away (PR 2207). This is probably reasonable. */
/* If there were other args, beside '&', process them. */
- if (args != NULL)
+ if (args != nullptr)
current_inferior ()->set_args (args);
if (from_tty)
{
- uiout->field_string (NULL, "Starting program");
+ uiout->field_string (nullptr, "Starting program");
uiout->text (": ");
if (exec_file)
- uiout->field_string ("execfile", 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");
from_tty);
/* to_create_inferior should push the target, so after this point we
shouldn't refer to run_target again. */
- run_target = NULL;
+ 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,
/* 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);
+ proceed (regcache_read_pc (get_thread_regcache (inferior_thread ())),
+ GDB_SIGNAL_0);
/* Since there was no error, there's no need to finish the thread
states here. */
scoped_disable_commit_resumed disable_commit_resumed
("continue all threads in non-stop");
- iterate_over_threads (proceed_thread_callback, NULL);
+ iterate_over_threads (proceed_thread_callback, nullptr);
if (current_ui->prompt_state == PROMPT_BLOCKED)
{
gdb::unique_xmalloc_ptr<char> stripped = strip_bg_char (args, &async_exec);
args = stripped.get ();
- if (args != NULL)
+ if (args != nullptr)
{
if (startswith (args, "-a"))
{
all_threads_p = true;
args += sizeof ("-a") - 1;
if (*args == '\0')
- args = NULL;
+ args = nullptr;
}
}
if (!non_stop && all_threads_p)
error (_("`-a' is meaningless in all-stop mode."));
- if (args != NULL && all_threads_p)
+ 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 != NULL)
+ if (args != nullptr)
{
bpstat *bs = nullptr;
int num, stat;
ptid_t last_ptid;
get_last_target_status (&last_target, &last_ptid, nullptr);
- tp = find_thread_ptid (last_target, last_ptid);
+ tp = last_target->find_thread (last_ptid);
}
- if (tp != NULL)
+ if (tp != nullptr)
bs = tp->control.stop_bpstat;
while ((stat = bpstat_num (&bs, &num)) != 0)
/* set_ignore_count prints a message ending with a period.
So print two spaces before "Continuing.". */
if (from_tty)
- printf_filtered (" ");
+ gdb_printf (" ");
stopped = 1;
}
if (!stopped && from_tty)
{
- printf_filtered
+ gdb_printf
("Not stopped at any breakpoint; argument ignored.\n");
}
}
- ERROR_NO_INFERIOR;
ensure_not_tfind_mode ();
if (!non_stop || !all_threads_p)
prepare_execution_command (current_inferior ()->top_target (), async_exec);
if (from_tty)
- printf_filtered (_("Continuing.\n"));
+ gdb_printf (_("Continuing.\n"));
continue_1 (all_threads_p);
}
inferior_ptid value. */
gdb_assert (inferior_ptid == tp->ptid);
- frame_info *frame = get_current_frame ();
+ frame_info_ptr frame = get_current_frame ();
symtab_and_line sal = find_frame_sal (frame);
set_step_info (tp, frame, sal);
steps. */
thr = inferior_thread ();
step_sm = new step_command_fsm (command_interp ());
- thr->thread_fsm = step_sm;
+ thr->set_thread_fsm (std::unique_ptr<thread_fsm> (step_sm));
step_command_fsm_prepare (step_sm, skip_subroutines,
single_inst, count, thr);
proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
else
{
- int proceeded;
-
/* Stepped into an inline frame. Pretend that we've
stopped. */
- thr->thread_fsm->clean_up (thr);
- proceeded = normal_stop ();
+ thr->thread_fsm ()->clean_up (thr);
+ bool proceeded = normal_stop ();
if (!proceeded)
inferior_event_handler (INF_EXEC_COMPLETE);
all_uis_check_sync_execution_done ();
if (sm->count > 0)
{
- struct frame_info *frame = get_current_frame ();
+ frame_info_ptr frame = get_current_frame ();
set_step_frame (tp);
&& inline_skipped_frames (tp))
{
ptid_t resume_ptid;
- const char *fn = NULL;
+ const char *fn = nullptr;
symtab_and_line sal;
struct symbol *sym;
sal = find_frame_sal (frame);
sym = get_frame_function (frame);
- if (sym != NULL)
+ if (sym != nullptr)
fn = sym->print_name ();
if (sal.line == 0
&tp->control.step_range_start,
&tp->control.step_range_end);
+ if (execution_direction == EXEC_REVERSE)
+ {
+ symtab_and_line sal = find_pc_line (pc, 0);
+ symtab_and_line sal_start
+ = find_pc_line (tp->control.step_range_start, 0);
+
+ if (sal.line == sal_start.line)
+ /* Executing in reverse, the step_range_start address is in
+ the same line. We want to stop in the previous line so
+ move step_range_start before the current line. */
+ tp->control.step_range_start--;
+ }
+
/* 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. */
symbol *sym = inline_skipped_symbol (tp);
if (sym->aclass () == LOC_BLOCK)
{
- const block *block = SYMBOL_BLOCK_VALUE (sym);
- if (BLOCK_END (block) < tp->control.step_range_end)
- tp->control.step_range_end = BLOCK_END (block);
+ const block *block = sym->value_block ();
+ if (block->end () < tp->control.step_range_end)
+ tp->control.step_range_end = block->end ();
}
}
error (_("Cannot find bounds of current function"));
target_terminal::ours_for_output ();
- printf_filtered (_("Single stepping until exit from function %s,"
- "\nwhich has no line number information.\n"),
- name);
+ gdb_printf (_("Single stepping until exit from function %s,"
+ "\nwhich has no line number information.\n"),
+ name);
}
}
else
error_no_arg (_("starting address"));
std::vector<symtab_and_line> sals
- = decode_line_with_last_displayed (arg, DECODE_LINE_FUNFIRSTLINE);
+ = decode_line_with_current_source (arg, DECODE_LINE_FUNFIRSTLINE);
if (sals.size () != 1)
- error (_("Unreasonable jump request"));
+ {
+ /* If multiple sal-objects were found, try dropping those that aren't
+ from the current symtab. */
+ struct symtab_and_line cursal = get_current_source_symtab_and_line ();
+ sals.erase (std::remove_if (sals.begin (), sals.end (),
+ [&] (const symtab_and_line &sal)
+ {
+ return sal.symtab != cursal.symtab;
+ }), sals.end ());
+ if (sals.size () != 1)
+ error (_("Jump request is ambiguous: "
+ "does not resolve to a single address"));
+ }
symtab_and_line &sal = sals[0];
/* 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 != NULL && sfn != fn)
+ sfn = find_pc_sect_containing_function (sal.pc,
+ find_pc_mapped_section (sal.pc));
+ if (fn != nullptr && sfn != fn)
{
if (!query (_("Line %d is not in `%s'. Jump anyway? "), sal.line,
fn->print_name ()))
}
}
- if (sfn != NULL)
+ if (sfn != nullptr)
{
struct obj_section *section;
- fixup_symbol_section (sfn, 0);
- section = sfn->obj_section (symbol_objfile (sfn));
+ section = sfn->obj_section (sfn->objfile ());
if (section_is_overlay (section)
&& !section_is_mapped (section))
{
if (from_tty)
{
- printf_filtered (_("Continuing at "));
- puts_filtered (paddress (gdbarch, addr));
- printf_filtered (".\n");
+ gdb_printf (_("Continuing at "));
+ gdb_puts (paddress (gdbarch, addr));
+ gdb_printf (".\n");
}
clear_proceed_status (0);
&& signal_pass_state (tp->stop_signal ()))
{
if (!must_confirm)
- printf_unfiltered (_("Note:\n"));
- printf_unfiltered (_(" 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 ()));
+ 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 (from_tty)
{
if (oursig == GDB_SIGNAL_0)
- printf_filtered (_("Continuing with no signal.\n"));
+ gdb_printf (_("Continuing with no signal.\n"));
else
- printf_filtered (_("Continuing with signal %s.\n"),
- gdb_signal_to_name (oursig));
+ gdb_printf (_("Continuing with signal %s.\n"),
+ gdb_signal_to_name (oursig));
}
clear_proceed_status (0);
ensure_valid_thread ();
ensure_not_running ();
- if (signum_exp == NULL)
+ if (signum_exp == nullptr)
error_no_arg (_("signal number"));
/* It would be even slicker to make signal names be valid expressions,
static void
until_next_command (int from_tty)
{
- struct frame_info *frame;
+ frame_info_ptr frame;
CORE_ADDR pc;
struct symbol *func;
struct symtab_and_line sal;
{
struct bound_minimal_symbol msymbol = lookup_minimal_symbol_by_pc (pc);
- if (msymbol.minsym == NULL)
+ if (msymbol.minsym == nullptr)
error (_("Execution is not within a known function."));
- tp->control.step_range_start = BMSYMBOL_VALUE_ADDRESS (msymbol);
+ 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;
{
sal = find_pc_line (pc, 0);
- tp->control.step_range_start = BLOCK_ENTRY_PC (SYMBOL_BLOCK_VALUE (func));
+ tp->control.step_range_start = func->value_block ()->entry_pc ();
tp->control.step_range_end = sal.end;
}
tp->control.may_range_step = 1;
delete_longjmp_breakpoint_cleanup lj_deleter (thread);
sm = new until_next_fsm (command_interp (), tp->global_num);
- tp->thread_fsm = sm;
+ tp->set_thread_fsm (std::unique_ptr<thread_fsm> (sm));
lj_deleter.release ();
proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
ensure_valid_thread ();
ensure_not_running ();
- if (arg == NULL)
+ if (arg == nullptr)
error_no_arg (_("a location"));
/* Find out whether we must run in the background. */
until_break_command (arg, from_tty, 1);
}
\f
-/* Return the value of the result of a function at the end of a 'finish'
- command/BP. DTOR_DATA (if not NULL) can represent inferior registers
- right after an inferior call has finished. */
+/* See inferior.h. */
struct value *
-get_return_value (struct value *function, struct type *value_type)
+get_return_value (struct symbol *func_symbol, struct value *function)
{
- regcache *stop_regs = get_current_regcache ();
+ regcache *stop_regs = get_thread_regcache (inferior_thread ());
struct gdbarch *gdbarch = stop_regs->arch ();
struct value *value;
- value_type = check_typedef (value_type);
+ 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 (function->type ())))
+ {
+ 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
inferior function call code. In fact, when inferior function
calls are made async, this will likely be made the norm. */
- switch (gdbarch_return_value (gdbarch, function, value_type,
- NULL, NULL, NULL))
+ 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:
- value = allocate_value (value_type);
- gdbarch_return_value (gdbarch, function, value_type, stop_regs,
- value_contents_raw (value).data (), NULL);
+ gdbarch_return_value_as_value (gdbarch, function, value_type, stop_regs,
+ &value, nullptr);
break;
case RETURN_VALUE_STRUCT_CONVENTION:
- value = NULL;
+ value = nullptr;
break;
default:
- internal_error (__FILE__, __LINE__, _("bad switch"));
+ 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 != NULL)
+ if (rv->value != nullptr)
{
- struct value_print_options opts;
-
/* Print it. */
uiout->text ("Value returned is ");
uiout->field_fmt ("gdb-result-var", "$%d",
rv->value_history_index);
uiout->text (" = ");
- get_user_print_options (&opts);
- if (opts.finish_print)
+ 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);
void
print_return_value (struct ui_out *uiout, struct return_value_info *rv)
{
- if (rv->type == NULL
+ if (rv->type == nullptr
|| check_typedef (rv->type)->code () == TYPE_CODE_VOID)
return;
delete the breakpoint. */
print_return_value_1 (uiout, rv);
}
- catch (const gdb_exception &ex)
+ catch (const gdb_exception_error &ex)
{
exception_print (gdb_stdout, ex);
}
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)
{
{
struct return_value_info *rv = &return_value_info;
- if (function != NULL
+ if (function != nullptr
&& bpstat_find_breakpoint (tp->control.stop_bpstat,
- breakpoint.get ()) != NULL)
+ breakpoint.get ()) != nullptr)
{
/* We're done. */
set_finished ();
- rv->type = TYPE_TARGET_TYPE (function->type ());
- if (rv->type == NULL)
- internal_error (__FILE__, __LINE__,
- _("finish_command: function has no target type"));
+ 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, NULL, get_current_frame ());
- rv->value = get_return_value (func, rv->type);
- if (rv->value != NULL)
- rv->value_history_index = record_latest_value (rv->value);
+ 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 = rv->value->record_latest ();
}
}
else if (tp->control.stop_step)
struct thread_info *tp = inferior_thread ();
CORE_ADDR pc;
CORE_ADDR func_addr;
+ CORE_ADDR alt_entry_point;
+ CORE_ADDR entry_point;
+ frame_info_ptr frame = get_selected_frame (nullptr);
+ struct gdbarch *gdbarch = get_frame_arch (frame);
pc = get_frame_pc (get_current_frame ());
- if (find_pc_partial_function (pc, NULL, &func_addr, NULL) == 0)
+ 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);
+ alt_entry_point = sal.pc;
+ entry_point = alt_entry_point;
+
+ if (gdbarch_skip_entrypoint_p (gdbarch))
+ /* Some architectures, like PowerPC use local and global entry points.
+ There is only one Entry Point (GEP = LEP) for other architectures.
+ The GEP is an alternate entry point. The LEP is the normal entry point.
+ The value of entry_point was initialized to the alternate entry point
+ (GEP). It will be adjusted to the normal entry point if the function
+ has two entry points. */
+ entry_point = gdbarch_skip_entrypoint (gdbarch, sal.pc);
tp->control.proceed_to_finish = 1;
/* Special case: if we're sitting at the function entry point,
no way that a function up the stack can have a return address
that's equal to its entry point. */
- if (sal.pc != pc)
+ if ((pc < alt_entry_point) || (pc > entry_point))
{
- struct frame_info *frame = get_selected_frame (NULL);
- 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. */
+ /* We are in the body of the function. Set a breakpoint to go back to
+ the normal entry point. */
symtab_and_line sr_sal;
- sr_sal.pc = sal.pc;
+ sr_sal.pc = entry_point;
sr_sal.pspace = get_frame_program_space (frame);
insert_step_resume_breakpoint_at_sal (gdbarch,
sr_sal, null_frame_id);
}
else
{
- /* We're almost there -- we just need to back up by one more
- single-step. */
+ /* We are either at one of the entry points or between the entry points.
+ If we are not at the alt_entry point, go back to the alt_entry_point
+ If we at the normal entry point step back one instruction, when we
+ stop we will determine if we entered via the entry point or the
+ alternate entry point. If we are at the alternate entry point,
+ single step back to the function call. */
tp->control.step_range_start = tp->control.step_range_end = 1;
proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
}
frame that called the function we're about to step out of. */
static void
-finish_forward (struct finish_command_fsm *sm, struct frame_info *frame)
+finish_forward (struct finish_command_fsm *sm, const frame_info_ptr &frame)
{
struct frame_id frame_id = get_frame_id (frame);
struct gdbarch *gdbarch = get_frame_arch (frame);
get_stack_frame_id (frame),
bp_finish);
- /* set_momentary_breakpoint invalidates FRAME. */
- frame = NULL;
-
set_longjmp_breakpoint (tp, frame_id);
/* We want to print return value, please... */
/* Skip frames for "finish". */
-static struct frame_info *
-skip_finish_frames (struct frame_info *frame)
+static frame_info_ptr
+skip_finish_frames (const frame_info_ptr &initial_frame)
{
- struct frame_info *start;
+ frame_info_ptr start;
+ frame_info_ptr frame = initial_frame;
do
{
start = frame;
frame = skip_tailcall_frames (frame);
- if (frame == NULL)
+ if (frame == nullptr)
break;
frame = skip_unwritable_frames (frame);
- if (frame == NULL)
+ if (frame == nullptr)
break;
}
while (start != frame);
static void
finish_command (const char *arg, int from_tty)
{
- struct frame_info *frame;
+ frame_info_ptr frame;
int async_exec;
struct finish_command_fsm *sm;
struct thread_info *tp;
sm = new finish_command_fsm (command_interp ());
- tp->thread_fsm = sm;
+ 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. */
source. */
if (from_tty)
{
- printf_filtered (_("Run till exit from "));
- print_stack_frame (get_selected_frame (NULL), 1, LOCATION, 0);
+ gdb_printf (_("Run till exit from "));
+ print_stack_frame (get_selected_frame (nullptr), 1, LOCATION, 0);
}
proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
}
/* 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. */
- sm->function = find_pc_function (get_frame_pc (get_selected_frame (NULL)));
+ /* 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)
- printf_filtered (_("Run back to call of "));
+ gdb_printf (_("Run back to call of "));
else
{
- if (sm->function != NULL && TYPE_NO_RETURN (sm->function->type ())
+ 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."));
- printf_filtered (_("Run till exit from "));
+ gdb_printf (_("Run till exit from "));
}
- print_stack_frame (get_selected_frame (NULL), 1, LOCATION, 0);
+ print_stack_frame (callee_frame, 1, LOCATION, 0);
}
if (execution_direction == EXEC_REVERSE)
{
frame = skip_finish_frames (frame);
- if (frame == NULL)
+ 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;
+ scoped_restore_current_thread restore_thread;
- if (!target_has_execution ())
- {
- printf_filtered (_("The program being debugged is not being run.\n"));
- return;
- }
+ thread_info *tp;
+
+ /* In non-stop, since every thread is controlled individually, we'll
+ show execution info about the current thread. In all-stop, we'll
+ show execution info about the last stop. */
if (non_stop)
{
- ptid = inferior_ptid;
- proc_target = current_inferior ()->process_target ();
+ if (!target_has_execution ())
+ {
+ gdb_printf (_("The program being debugged is not being run.\n"));
+ return;
+ }
+
+ if (inferior_ptid == null_ptid)
+ error (_("No selected thread."));
+
+ tp = inferior_thread ();
+
+ gdb_printf (_("Selected thread %s (%s).\n"),
+ print_thread_id (tp),
+ target_pid_to_str (tp->ptid).c_str ());
+
+ if (tp->state == THREAD_EXITED)
+ {
+ gdb_printf (_("Selected thread has exited.\n"));
+ return;
+ }
+ else if (tp->state == THREAD_RUNNING)
+ {
+ gdb_printf (_("Selected thread is running.\n"));
+ return;
+ }
}
else
- get_last_target_status (&proc_target, &ptid, nullptr);
+ {
+ tp = get_previous_thread ();
+
+ if (tp == nullptr)
+ {
+ gdb_printf (_("The program being debugged is not being run.\n"));
+ return;
+ }
+
+ switch_to_thread (tp);
- if (ptid == null_ptid || ptid == minus_one_ptid)
- error (_("No selected thread."));
+ gdb_printf (_("Last stopped for thread %s (%s).\n"),
+ print_thread_id (tp),
+ target_pid_to_str (tp->ptid).c_str ());
- thread_info *tp = find_thread_ptid (proc_target, ptid);
+ if (tp->state == THREAD_EXITED)
+ {
+ gdb_printf (_("Thread has since exited.\n"));
+ return;
+ }
- if (tp->state == THREAD_EXITED)
- error (_("Invalid selected thread."));
- else if (tp->state == THREAD_RUNNING)
- error (_("Selected thread is running."));
+ if (tp->state == THREAD_RUNNING)
+ {
+ gdb_printf (_("Thread is now running.\n"));
+ return;
+ }
+ }
- bs = tp->control.stop_bpstat;
- stat = bpstat_num (&bs, &num);
+ int num;
+ bpstat *bs = tp->control.stop_bpstat;
+ int stat = bpstat_num (&bs, &num);
target_files_info ();
- printf_filtered (_("Program stopped at %s.\n"),
- paddress (target_gdbarch (), tp->stop_pc ()));
+ gdb_printf (_("Program stopped at %s.\n"),
+ paddress (current_inferior ()->arch (), tp->stop_pc ()));
if (tp->control.stop_step)
- printf_filtered (_("It stopped after being stepped.\n"));
+ gdb_printf (_("It stopped after being stepped.\n"));
else if (stat != 0)
{
/* There may be several breakpoints in the same place, so this
{
if (stat < 0)
{
- printf_filtered (_("It stopped at a breakpoint "
- "that has since been deleted.\n"));
+ gdb_printf (_("It stopped at a breakpoint "
+ "that has since been deleted.\n"));
}
else
- printf_filtered (_("It stopped at breakpoint %d.\n"), num);
+ gdb_printf (_("It stopped at breakpoint %d.\n"), num);
stat = bpstat_num (&bs, &num);
}
}
else if (tp->stop_signal () != GDB_SIGNAL_0)
{
- printf_filtered (_("It stopped with signal %s, %s.\n"),
- gdb_signal_to_name (tp->stop_signal ()),
- gdb_signal_to_string (tp->stop_signal ()));
+ 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)
{
- printf_filtered (_("Type \"info stack\" or \"info "
- "registers\" for more information.\n"));
+ gdb_printf (_("Type \"info stack\" or \"info "
+ "registers\" for more information.\n"));
}
}
\f
if (val)
{
- puts_filtered (var);
- puts_filtered (" = ");
- puts_filtered (val);
- puts_filtered ("\n");
+ gdb_puts (var);
+ gdb_puts (" = ");
+ gdb_puts (val);
+ gdb_puts ("\n");
}
else
{
- puts_filtered ("Environment variable \"");
- puts_filtered (var);
- puts_filtered ("\" not defined.\n");
+ 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] != NULL; ++idx)
+ for (int idx = 0; envp[idx] != nullptr; ++idx)
{
- puts_filtered (envp[idx]);
- puts_filtered ("\n");
+ gdb_puts (envp[idx]);
+ gdb_puts ("\n");
}
}
}
std::string var (arg, p - arg);
if (nullset)
{
- printf_filtered (_("Setting environment variable "
- "\"%s\" to null value.\n"),
- var.c_str ());
+ gdb_printf (_("Setting environment variable "
+ "\"%s\" to null value.\n"),
+ var.c_str ());
current_inferior ()->environment.set (var.c_str (), "");
}
else
static void
path_info (const char *args, int from_tty)
{
- puts_filtered ("Executable and object file path: ");
- puts_filtered (current_inferior ()->environment.get (path_var_name));
- puts_filtered ("\n");
+ 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. */
mod_path (dirname, exec_path);
current_inferior ()->environment.set (path_var_name, exec_path.c_str ());
if (from_tty)
- path_info (NULL, from_tty);
+ path_info (nullptr, from_tty);
}
\f
const char *name,
struct value *val)
{
- struct type *regtype = value_type (val);
+ struct type *regtype = val->type ();
int print_raw_format;
string_file format_stream;
enum tab_stops
format_stream.puts (name);
pad_to_column (format_stream, value_column_1);
- print_raw_format = (value_entirely_available (val)
- && !value_optimized_out (val));
+ print_raw_format = (val->entirely_available ()
+ && !val->optimized_out ());
/* If virtual format is floating, print it that way, and in raw
hex. */
|| regtype->code () == TYPE_CODE_DECFLOAT)
{
struct value_print_options opts;
- const gdb_byte *valaddr = value_contents_for_printing (val).data ();
+ const gdb_byte *valaddr = val->contents_for_printing ().data ();
enum bfd_endian byte_order = type_byte_order (regtype);
get_user_print_options (&opts);
- opts.deref_ref = 1;
+ opts.deref_ref = true;
common_val_print (val, &format_stream, 0, &opts, current_language);
{
pad_to_column (format_stream, value_column_2);
format_stream.puts ("(raw ");
- print_hex_chars (&format_stream, valaddr, TYPE_LENGTH (regtype),
+ print_hex_chars (&format_stream, valaddr, regtype->length (),
byte_order, true);
format_stream.putc (')');
}
/* Print the register in hex. */
get_formatted_print_options (&opts, 'x');
- opts.deref_ref = 1;
+ 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. */
{
pad_to_column (format_stream, value_column_2);
get_user_print_options (&opts);
- opts.deref_ref = 1;
+ opts.deref_ref = true;
common_val_print (val, &format_stream, 0, &opts, current_language);
}
}
- fputs_filtered (format_stream.c_str (), file);
- fprintf_filtered (file, "\n");
+ gdb_puts (format_stream.c_str (), file);
+ gdb_printf (file, "\n");
}
/* Print out the machine register regnum. If regnum is -1, print all
void
default_print_registers_info (struct gdbarch *gdbarch,
struct ui_file *file,
- struct frame_info *frame,
+ const frame_info_ptr &frame,
int regnum, int print_all)
{
int i;
/* If the register name is empty, it is undefined for this
processor, so don't display anything. */
- if (gdbarch_register_name (gdbarch, i) == NULL
- || *(gdbarch_register_name (gdbarch, i)) == '\0')
+ if (*(gdbarch_register_name (gdbarch, i)) == '\0')
continue;
- default_print_one_register_info (file,
- gdbarch_register_name (gdbarch, i),
- value_of_register (i, frame));
+ default_print_one_register_info
+ (file, gdbarch_register_name (gdbarch, i),
+ value_of_register (i, get_next_frame_sentinel_okay (frame)));
}
}
void
registers_info (const char *addr_exp, int fpregs)
{
- struct frame_info *frame;
+ frame_info_ptr frame;
struct gdbarch *gdbarch;
if (!target_has_registers ())
error (_("The program has no registers now."));
- frame = get_selected_frame (NULL);
+ frame = get_selected_frame (nullptr);
gdbarch = get_frame_arch (frame);
if (!addr_exp)
/* A register group? */
{
- struct reggroup *group;
-
- for (group = reggroup_next (gdbarch, NULL);
- group != NULL;
- group = reggroup_next (gdbarch, 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, reggroup_name (group), end - start) == 0)
- break;
+ if (strncmp (start, g->name (), end - start) == 0)
+ {
+ group = g;
+ break;
+ }
}
- if (group != NULL)
+ if (group != nullptr)
{
int regnum;
static void
print_vector_info (struct ui_file *file,
- struct frame_info *frame, const char *args)
+ const frame_info_ptr &frame, const char *args)
{
struct gdbarch *gdbarch = get_frame_arch (frame);
}
}
if (!printed_something)
- fprintf_filtered (file, "No vector information\n");
+ gdb_printf (file, "No vector information\n");
}
}
if (!target_has_registers ())
error (_("The program has no registers now."));
- print_vector_info (gdb_stdout, get_selected_frame (NULL), args);
+ print_vector_info (gdb_stdout, get_selected_frame (nullptr), args);
}
\f
/* Kill the inferior process. Make us have no inferior. */
int infnum = current_inferior ()->num;
target_kill ();
- bfd_cache_close_all ();
+
+ update_previous_thread ();
if (print_inferior_events)
- printf_filtered (_("[Inferior %d (%s) killed]\n"),
- infnum, pid_str.c_str ());
+ gdb_printf (_("[Inferior %d (%s) killed]\n"),
+ infnum, pid_str.c_str ());
}
/* Used in `attach&' command. Proceed threads of inferior INF iff
struct inferior *inferior;
inferior = current_inferior ();
- inferior->needs_setup = 0;
+ inferior->needs_setup = false;
/* If no exec file is yet known, try to determine it from the
process itself. */
- if (get_exec_file (0) == NULL)
+ if (get_exec_file (0) == nullptr)
exec_file_locate_attach (inferior_ptid.pid (), 1, from_tty);
else
{
{
struct thread_info *lowest = inferior_thread ();
- stop_all_threads ();
+ stop_all_threads ("attaching");
/* It's not defined which thread will report the attach
stop. For consistency, always select the thread with
scoped_disable_commit_resumed disable_commit_resumed ("attaching");
- if (gdbarch_has_global_solist (target_gdbarch ()))
+ if (gdbarch_has_global_solist (current_inferior ()->arch ()))
/* Don't complain if all processes share the same symbol
space. */
;
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 = NULL;
+ attach_target = nullptr;
- if (debug_infrun)
- {
- infrun_debug_printf ("immediately after attach:");
- for (thread_info *thread : inferior->non_exited_threads ())
- infrun_debug_printf (" thread %s, executing = %d, resumed = %d, "
- "state = %s",
- thread->ptid.to_string ().c_str (),
- thread->executing (),
- thread->resumed (),
- thread_state_string (thread->state));
- }
+ 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. */
wait_for_inferior as soon as the target reports a stop. */
init_wait_for_inferior ();
- inferior->needs_setup = 1;
+ inferior->needs_setup = true;
if (target_is_non_stop_p ())
{
enum attach_post_wait_mode mode
= leave_running ? ATTACH_POST_WAIT_RESUME : ATTACH_POST_WAIT_NOTHING;
- gdb::optional<scoped_restore_current_thread> restore_thread;
+ std::optional<scoped_restore_current_thread> restore_thread;
if (inferior_ptid != null_ptid)
restore_thread.emplace ();
/* 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 ());
+ inferior *inf = current_inferior ();
+ auto target_ref = target_ops_ref::new_reference (inf->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);
+ target_detach (inf, from_tty);
+
+ update_previous_thread ();
/* 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);
+ breakpoint_init_inferior (inf, 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 (NULL, from_tty);
+ if (!gdbarch_has_global_solist (inf->arch ()))
+ no_shared_libraries (nullptr, from_tty);
if (deprecated_detach_hook)
deprecated_detach_hook ();
query_if_trace_running (from_tty);
disconnect_tracing ();
target_disconnect (args, from_tty);
- no_shared_libraries (NULL, from_tty);
+ no_shared_libraries (nullptr, from_tty);
init_thread_list ();
+ update_previous_thread ();
if (deprecated_detach_hook)
deprecated_detach_hook ();
}
dont_repeat (); /* Not for the faint of heart. */
- if (args != NULL
+ if (args != nullptr
&& startswith (args, "-a"))
all_threads = 1;
- if (!non_stop && all_threads)
- error (_("-a is meaningless in all-stop mode."));
-
interrupt_target_1 (all_threads);
}
}
void
default_print_float_info (struct gdbarch *gdbarch, struct ui_file *file,
- struct frame_info *frame, const char *args)
+ const frame_info_ptr &frame, const char *args)
{
int regnum;
int printed_something = 0;
}
}
if (!printed_something)
- fprintf_filtered (file, "No floating-point info "
- "available for this processor.\n");
+ gdb_printf (file, "No floating-point info "
+ "available for this processor.\n");
}
static void
info_float_command (const char *args, int from_tty)
{
- struct frame_info *frame;
+ frame_info_ptr frame;
if (!target_has_registers ())
error (_("The program has no registers now."));
- frame = get_selected_frame (NULL);
+ frame = get_selected_frame (nullptr);
gdbarch_print_float_info (get_frame_arch (frame), gdb_stdout, frame, args);
}
\f
struct cmd_list_element *c,
const char *value)
{
- fprintf_filtered (file, _("\
+ gdb_printf (file, _("\
Printing of return value after `finish' is %s.\n"),
- value);
+ value);
}
variable). Input and output redirection with \">\", \"<\", or \">>\"\n\
are also allowed.\n\
\n\
-With no arguments, uses arguments last specified (with \"run\" or \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\
_initialize_infcmd ()
{
static struct cmd_list_element *info_proc_cmdlist;
- struct cmd_list_element *c = NULL;
- const char *cmd_name;
+ struct cmd_list_element *c = nullptr;
/* Add the filename of the terminal connected to inferior I/O. */
- add_setshow_optional_filename_cmd ("inferior-tty", class_run,
- &inferior_io_terminal_scratch, _("\
+ auto tty_set_show
+ = add_setshow_optional_filename_cmd ("inferior-tty", class_run, _("\
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, "", NULL, -1, 1);
- gdb_assert (c != NULL);
- 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_tty_value,
+ get_tty_value,
+ show_inferior_tty_command,
+ &setlist, &showlist);
+ add_alias_cmd ("tty", tty_set_show.set, class_run, 0, &cmdlist);
+
+ auto args_set_show
+ = add_setshow_string_noescape_cmd ("args", class_run, _("\
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, "", NULL, -1, 1);
- gdb_assert (c != NULL);
- set_cmd_completer (c, filename_completer);
-
- cmd_name = "cwd";
- add_setshow_string_noescape_cmd (cmd_name, class_run,
- &inferior_cwd_scratch, _("\
+ set_args_value,
+ get_args_value,
+ show_args_command,
+ &setlist, &showlist);
+ set_cmd_completer (args_set_show.set, filename_completer);
+
+ auto cwd_set_show
+ = add_setshow_string_noescape_cmd ("cwd", class_run, _("\
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, "", NULL, -1, 1);
- gdb_assert (c != NULL);
- set_cmd_completer (c, filename_completer);
+ set_cwd_value, get_inferior_cwd,
+ show_cwd_command,
+ &setlist, &showlist);
+ set_cmd_completer (cwd_set_show.set, filename_completer);
c = add_cmd ("environment", no_class, environment_info, _("\
The environment to give the program, or one variable's value.\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\
+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 ("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\
+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
&info_proc_cmdlist);
add_setshow_boolean_cmd ("finish", class_support,
- &user_print_options.finish_print, _("\
+ &finish_print, _("\
Set whether `finish' prints the return value."), _("\
-Show whether `finish' prints the return value."), NULL,
- NULL,
+Show whether `finish' prints the return value."), nullptr,
+ nullptr,
show_print_finish,
&setprintlist, &showprintlist);
}