/* Memory-access and commands for "inferior" process, for GDB.
- Copyright (C) 1986-2017 Free Software Foundation, Inc.
+ Copyright (C) 1986-2018 Free Software Foundation, Inc.
This file is part of GDB.
#include "block.h"
#include "solib.h"
#include <ctype.h>
-#include "observer.h"
+#include "observable.h"
#include "target-descriptions.h"
#include "user-regs.h"
#include "cli/cli-decode.h"
#include "top.h"
#include "interps.h"
#include "common/gdb_optional.h"
+#include "source.h"
/* Local functions: */
-static void info_registers_command (char *, int);
-
static void until_next_command (int);
-static void until_command (char *, int);
-
-static void path_command (char *, int);
-
-static void info_float_command (char *, int);
-
-static void disconnect_command (char *, int);
-
-static void info_program_command (char *, int);
-
-static void finish_command (char *, int);
-
-static void signal_command (char *, int);
-
-static void jump_command (char *, int);
-
-static void step_1 (int, int, char *);
-
-static void next_command (char *, int);
-
-static void step_command (char *, int);
-
-static void run_command (char *, int);
+static void step_1 (int, int, const char *);
#define ERROR_NO_INFERIOR \
if (!target_has_execution) error (_("The program is not being run."));
}
static void
-set_inferior_tty_command (char *args, int from_tty,
+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.
NEWARGS is not transferred. */
void
-set_inferior_args (char *newargs)
+set_inferior_args (const char *newargs)
{
xfree (current_inferior ()->args);
current_inferior ()->args = newargs ? xstrdup (newargs) : NULL;
/* Notice when `set args' is run. */
static void
-set_args_command (char *args, int from_tty, struct cmd_list_element *c)
+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. */
/* Handle the 'set cwd' command. */
static void
-set_cwd_command (char *args, int from_tty, struct cmd_list_element *c)
+set_cwd_command (const char *args, int from_tty, struct cmd_list_element *c)
{
if (*inferior_cwd_scratch == '\0')
set_inferior_cwd (NULL);
NULL is returned. *BG_CHAR_P is an output boolean that indicates
whether the '&' character was found. */
-static char *
+static gdb::unique_xmalloc_ptr<char>
strip_bg_char (const char *args, int *bg_char_p)
{
const char *p;
*bg_char_p = 1;
if (p != args)
- return savestring (args, p - args);
+ return gdb::unique_xmalloc_ptr<char>
+ (savestring (args, p - args));
else
- return NULL;
+ return gdb::unique_xmalloc_ptr<char> (nullptr);
}
*bg_char_p = 0;
- return xstrdup (args);
+ return gdb::unique_xmalloc_ptr<char> (xstrdup (args));
}
/* Common actions to take after creating any sort of inferior, by any
if the now pushed target supports hardware watchpoints. */
breakpoint_re_set ();
- observer_notify_inferior_created (target, from_tty);
+ gdb::observers::inferior_created.notify (target, from_tty);
}
/* Kill the inferior if already running. This function is designed
{
/* If we get a request for running in the bg but the target
doesn't support it, error out. */
- if (background && !target->to_can_async_p (target))
+ if (background && !target->can_async_p ())
error (_("Asynchronous execution not supported on this target."));
if (!background)
requested by RUN_HOW. */
static void
-run_command_1 (char *args, int from_tty, enum run_how run_how)
+run_command_1 (const char *args, int from_tty, enum run_how run_how)
{
const char *exec_file;
- struct cleanup *old_chain;
- ptid_t ptid;
struct ui_out *uiout = current_uiout;
struct target_ops *run_target;
int async_exec;
- struct cleanup *args_chain;
- CORE_ADDR pc;
dont_repeat ();
reopen_exec_file ();
reread_symbols ();
- args = strip_bg_char (args, &async_exec);
- args_chain = make_cleanup (xfree, args);
+ 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. */
prepare_execution_command (run_target, async_exec);
- if (non_stop && !run_target->to_supports_non_stop (run_target))
+ 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. */
uiout->flush ();
}
- /* Done with ARGS. */
- do_cleanups (args_chain);
-
/* We call get_inferior_args() because we might need to compute
the value now. */
- run_target->to_create_inferior (run_target, exec_file,
- std::string (get_inferior_args ()),
- current_inferior ()->environment.envp (),
- from_tty);
+ run_target->create_inferior (exec_file,
+ std::string (get_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 = NULL;
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. */
- if (non_stop)
- ptid = pid_to_ptid (ptid_get_pid (inferior_ptid));
- else
- ptid = minus_one_ptid;
- old_chain = make_cleanup (finish_thread_state_cleanup, &ptid);
+ ptid_t finish_ptid = (non_stop
+ ? ptid_t (current_inferior ()->pid)
+ : minus_one_ptid);
+ scoped_finish_thread_state finish_state (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 (¤t_target, 0);
+ post_create_inferior (current_top_target (), 0);
/* Queue a pending event so that the program stops immediately. */
if (run_how == RUN_STOP_AT_FIRST_INSN)
/* Since there was no error, there's no need to finish the thread
states here. */
- discard_cleanups (old_chain);
+ finish_state.release ();
}
static void
-run_command (char *args, int from_tty)
+run_command (const char *args, int from_tty)
{
run_command_1 (args, from_tty, RUN_NORMAL);
}
program. */
static void
-start_command (char *args, int from_tty)
+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
instruction. */
static void
-starti_command (char *args, int from_tty)
+starti_command (const char *args, int from_tty)
{
run_command_1 (args, from_tty, RUN_STOP_AT_FIRST_INSN);
}
/* continue [-a] [proceed-count] [&] */
static void
-continue_command (char *args, int from_tty)
+continue_command (const char *args, int from_tty)
{
int async_exec;
int all_threads = 0;
- struct cleanup *args_chain;
ERROR_NO_INFERIOR;
/* Find out whether we must run in the background. */
- args = strip_bg_char (args, &async_exec);
- args_chain = make_cleanup (xfree, args);
+ gdb::unique_xmalloc_ptr<char> stripped = strip_bg_char (args, &async_exec);
+ args = stripped.get ();
if (args != NULL)
{
}
}
- /* Done with ARGS. */
- do_cleanups (args_chain);
-
ERROR_NO_INFERIOR;
ensure_not_tfind_mode ();
ensure_not_running ();
}
- prepare_execution_command (¤t_target, async_exec);
+ prepare_execution_command (current_top_target (), async_exec);
if (from_tty)
printf_filtered (_("Continuing.\n"));
/* Step until outside of current statement. */
static void
-step_command (char *count_string, int from_tty)
+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 (char *count_string, int from_tty)
+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 (char *count_string, int from_tty)
+stepi_command (const char *count_string, int from_tty)
{
step_1 (0, 1, count_string);
}
static void
-nexti_command (char *count_string, int from_tty)
+nexti_command (const char *count_string, int from_tty)
{
step_1 (1, 1, count_string);
}
static int prepare_one_step (struct step_command_fsm *sm);
static void
-step_1 (int skip_subroutines, int single_inst, char *count_string)
+step_1 (int skip_subroutines, int single_inst, const char *count_string)
{
int count;
int async_exec;
- struct cleanup *args_chain;
struct thread_info *thr;
struct step_command_fsm *step_sm;
ensure_valid_thread ();
ensure_not_running ();
- count_string = strip_bg_char (count_string, &async_exec);
- args_chain = make_cleanup (xfree, count_string);
+ gdb::unique_xmalloc_ptr<char> stripped
+ = strip_bg_char (count_string, &async_exec);
+ count_string = stripped.get ();
- prepare_execution_command (¤t_target, async_exec);
+ prepare_execution_command (current_top_target (), async_exec);
count = count_string ? parse_and_eval_long (count_string) : 1;
- /* Done with ARGS. */
- do_cleanups (args_chain);
-
clear_proceed_status (1);
/* Setup the execution command state machine to handle all the COUNT
/* Continue program at specified address. */
static void
-jump_command (char *arg, int from_tty)
+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;
- struct cleanup *args_chain;
ERROR_NO_INFERIOR;
ensure_not_tfind_mode ();
ensure_not_running ();
/* Find out whether we must run in the background. */
- arg = strip_bg_char (arg, &async_exec);
- args_chain = make_cleanup (xfree, arg);
+ gdb::unique_xmalloc_ptr<char> stripped = strip_bg_char (arg, &async_exec);
+ arg = stripped.get ();
- prepare_execution_command (¤t_target, async_exec);
+ prepare_execution_command (current_top_target (), async_exec);
if (!arg)
error_no_arg (_("starting address"));
if (sals.size () != 1)
error (_("Unreasonable jump request"));
- /* Done with ARGS. */
- do_cleanups (args_chain);
-
symtab_and_line &sal = sals[0];
if (sal.symtab == 0 && sal.pc == 0)
/* Continue program giving it specified signal. */
static void
-signal_command (char *signum_exp, int from_tty)
+signal_command (const char *signum_exp, int from_tty)
{
enum gdb_signal oursig;
int async_exec;
- struct cleanup *args_chain;
dont_repeat (); /* Too dangerous. */
ERROR_NO_INFERIOR;
ensure_not_running ();
/* Find out whether we must run in the background. */
- signum_exp = strip_bg_char (signum_exp, &async_exec);
- args_chain = make_cleanup (xfree, signum_exp);
+ gdb::unique_xmalloc_ptr<char> stripped
+ = strip_bg_char (signum_exp, &async_exec);
+ signum_exp = stripped.get ();
- prepare_execution_command (¤t_target, async_exec);
+ prepare_execution_command (current_top_target (), async_exec);
if (!signum_exp)
error_no_arg (_("signal number"));
oursig = gdb_signal_from_command (num);
}
- do_cleanups (args_chain);
-
/* 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
/* Queue a signal to be delivered to the current thread. */
static void
-queue_signal_command (char *signum_exp, int from_tty)
+queue_signal_command (const char *signum_exp, int from_tty)
{
enum gdb_signal oursig;
struct thread_info *tp;
static void
until_next_fsm_clean_up (struct thread_fsm *self, struct thread_info *thread)
{
- struct until_next_fsm *sm = (struct until_next_fsm *) self;
-
delete_longjmp_breakpoint (thread->global_num);
}
}
static void
-until_command (char *arg, int from_tty)
+until_command (const char *arg, int from_tty)
{
int async_exec;
- struct cleanup *args_chain;
ERROR_NO_INFERIOR;
ensure_not_tfind_mode ();
ensure_not_running ();
/* Find out whether we must run in the background. */
- arg = strip_bg_char (arg, &async_exec);
- args_chain = make_cleanup (xfree, arg);
+ gdb::unique_xmalloc_ptr<char> stripped = strip_bg_char (arg, &async_exec);
+ arg = stripped.get ();
- prepare_execution_command (¤t_target, async_exec);
+ prepare_execution_command (current_top_target (), async_exec);
if (arg)
until_break_command (arg, from_tty, 0);
else
until_next_command (from_tty);
-
- /* Done with ARGS. */
- do_cleanups (args_chain);
}
static void
-advance_command (char *arg, int from_tty)
+advance_command (const char *arg, int from_tty)
{
int async_exec;
- struct cleanup *args_chain;
ERROR_NO_INFERIOR;
ensure_not_tfind_mode ();
error_no_arg (_("a location"));
/* Find out whether we must run in the background. */
- arg = strip_bg_char (arg, &async_exec);
- args_chain = make_cleanup (xfree, arg);
+ gdb::unique_xmalloc_ptr<char> stripped = strip_bg_char (arg, &async_exec);
+ arg = stripped.get ();
- prepare_execution_command (¤t_target, async_exec);
+ prepare_execution_command (current_top_target (), async_exec);
until_break_command (arg, from_tty, 1);
-
- /* Done with ARGS. */
- do_cleanups (args_chain);
}
\f
/* Return the value of the result of a function at the end of a 'finish'
struct value *
get_return_value (struct value *function, struct type *value_type)
{
- regcache stop_regs (regcache::readonly, *get_current_regcache ());
- struct gdbarch *gdbarch = stop_regs.arch ();
+ regcache *stop_regs = get_current_regcache ();
+ struct gdbarch *gdbarch = stop_regs->arch ();
struct value *value;
value_type = check_typedef (value_type);
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,
+ gdbarch_return_value (gdbarch, function, value_type, stop_regs,
value_contents_raw (value), NULL);
break;
case RETURN_VALUE_STRUCT_CONVENTION:
sm->breakpoint = set_momentary_breakpoint (gdbarch, sal,
get_stack_frame_id (frame),
- bp_finish);
+ bp_finish).release ();
/* set_momentary_breakpoint invalidates FRAME. */
frame = NULL;
frame will return to, then continue. */
static void
-finish_command (char *arg, int from_tty)
+finish_command (const char *arg, int from_tty)
{
struct frame_info *frame;
int async_exec;
- struct cleanup *args_chain;
struct finish_command_fsm *sm;
struct thread_info *tp;
ensure_not_running ();
/* Find out whether we must run in the background. */
- arg = strip_bg_char (arg, &async_exec);
- args_chain = make_cleanup (xfree, arg);
+ gdb::unique_xmalloc_ptr<char> stripped = strip_bg_char (arg, &async_exec);
+ arg = stripped.get ();
- prepare_execution_command (¤t_target, async_exec);
+ prepare_execution_command (current_top_target (), async_exec);
if (arg)
error (_("The \"finish\" command does not take any arguments."));
- /* Done with ARGS. */
- do_cleanups (args_chain);
-
frame = get_prev_frame (get_selected_frame (_("No selected frame.")));
if (frame == 0)
error (_("\"finish\" not meaningful in the outermost frame."));
\f
static void
-info_program_command (char *args, int from_tty)
+info_program_command (const char *args, int from_tty)
{
bpstat bs;
int num, stat;
/* Add zero or more directories to the front of the execution path. */
static void
-path_command (char *dirname, int from_tty)
+path_command (const char *dirname, int from_tty)
{
char *exec_path;
const char *env;
}
\f
+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. */
{
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,
+ };
- fputs_filtered (name, file);
- print_spaces_filtered (15 - strlen (name), file);
+ format_stream.puts (name);
+ pad_to_column (format_stream, value_column_1);
print_raw_format = (value_entirely_available (val)
&& !value_optimized_out (val));
val_print (regtype,
value_embedded_offset (val), 0,
- file, 0, val, &opts, current_language);
+ &format_stream, 0, val, &opts, current_language);
if (print_raw_format)
{
- fprintf_filtered (file, "\t(raw ");
- print_hex_chars (file, valaddr, TYPE_LENGTH (regtype), byte_order,
- true);
- fprintf_filtered (file, ")");
+ pad_to_column (format_stream, value_column_2);
+ format_stream.puts ("(raw ");
+ print_hex_chars (&format_stream, valaddr, TYPE_LENGTH (regtype),
+ byte_order, true);
+ format_stream.putc (')');
}
}
else
opts.deref_ref = 1;
val_print (regtype,
value_embedded_offset (val), 0,
- file, 0, val, &opts, current_language);
+ &format_stream, 0, val, &opts, current_language);
/* If not a vector register, print it also according to its
natural format. */
if (print_raw_format && TYPE_VECTOR (regtype) == 0)
{
+ pad_to_column (format_stream, value_column_2);
get_user_print_options (&opts);
opts.deref_ref = 1;
- fprintf_filtered (file, "\t");
val_print (regtype,
value_embedded_offset (val), 0,
- file, 0, val, &opts, current_language);
+ &format_stream, 0, val, &opts, current_language);
}
}
+ fputs_filtered (format_stream.c_str (), file);
fprintf_filtered (file, "\n");
}
}
void
-registers_info (char *addr_exp, int fpregs)
+registers_info (const char *addr_exp, int fpregs)
{
struct frame_info *frame;
struct gdbarch *gdbarch;
while (*addr_exp != '\0')
{
- char *start;
+ const char *start;
const char *end;
/* Skip leading white space. */
}
static void
-info_all_registers_command (char *addr_exp, int from_tty)
+info_all_registers_command (const char *addr_exp, int from_tty)
{
registers_info (addr_exp, 1);
}
static void
-info_registers_command (char *addr_exp, int from_tty)
+info_registers_command (const char *addr_exp, int from_tty)
{
registers_info (addr_exp, 0);
}
}
static void
-info_vector_command (char *args, int from_tty)
+info_vector_command (const char *args, int from_tty)
{
if (!target_has_registers)
error (_("The program has no registers now."));
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 (pid_to_ptid (pid));
+ int infnum = current_inferior ()->num;
+
target_kill ();
+ if (print_inferior_events)
+ printf_unfiltered (_("[Inferior %d (%s) killed]\n"),
+ infnum, pid_str.c_str ());
+
/* If we still have other inferiors to debug, then don't mess with
with their threads. */
if (!have_inferiors ())
/* Take any necessary post-attaching actions for this platform. */
target_post_attach (ptid_get_pid (inferior_ptid));
- post_create_inferior (¤t_target, from_tty);
+ post_create_inferior (current_top_target (), from_tty);
}
/* What to do after the first program stops after attaching. */
and allows us to start debugging it. */
void
-attach_command (char *args, int from_tty)
+attach_command (const char *args, int from_tty)
{
int async_exec;
- struct cleanup *args_chain;
struct target_ops *attach_target;
struct inferior *inferior = current_inferior ();
enum attach_post_wait_mode mode;
this function should probably be moved into target_pre_inferior. */
target_pre_inferior (from_tty);
- args = strip_bg_char (args, &async_exec);
- args_chain = make_cleanup (xfree, args);
+ 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->to_supports_non_stop (attach_target))
+ if (non_stop && !attach_target->supports_non_stop ())
error (_("Cannot attach to this target in non-stop mode"));
- attach_target->to_attach (attach_target, args, from_tty);
+ 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;
/* Some system don't generate traps when attaching to inferior.
E.g. Mach 3 or GNU hurd. */
- if (!target_attach_no_wait)
+ if (!target_attach_no_wait ())
{
struct attach_command_continuation_args *a;
a->mode = mode;
add_inferior_continuation (attach_command_continuation, a,
attach_command_continuation_free_args);
- /* Done with ARGS. */
- do_cleanups (args_chain);
if (!target_is_async_p ())
mark_infrun_async_event_handler ();
return;
}
- /* Done with ARGS. */
- do_cleanups (args_chain);
-
attach_post_wait (args, from_tty, mode);
}
disconnect_tracing ();
- target_detach (args, from_tty);
+ 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
stopped processes on some native platforms (e.g. GNU/Linux). */
static void
-disconnect_command (char *args, int from_tty)
+disconnect_command (const char *args, int from_tty)
{
dont_repeat (); /* Not for the faint of heart. */
query_if_trace_running (from_tty);
if (non_stop)
target_stop (ptid);
else
- target_interrupt (ptid);
+ target_interrupt ();
/* Tag the thread as having been explicitly requested to stop, so
other parts of gdb know not to resume this thread automatically,
if the `-a' switch is used. */
static void
-interrupt_command (char *args, int from_tty)
+interrupt_command (const char *args, int from_tty)
{
if (target_can_async_p ())
{
}
static void
-info_float_command (char *args, int from_tty)
+info_float_command (const char *args, int from_tty)
{
struct frame_info *frame;
c = add_com ("jump", class_run, jump_command, _("\
Continue program being debugged at specified line or address.\n\
-Usage: jump <location>\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 (c, location_completer);
c = add_info ("registers", info_registers_command, _("\
List of integer registers and their contents, for selected stack frame.\n\
-Register name as argument means describe only that register."));
+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", "registers", 1);
set_cmd_completer (c, 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\
-Register name as argument means describe only that register."));
+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,