/* Memory-access and commands for "inferior" process, for GDB.
- Copyright (C) 1986-2013 Free Software Foundation, Inc.
+ Copyright (C) 1986-2014 Free Software Foundation, Inc.
This file is part of GDB.
#include "defs.h"
#include "arch-utils.h"
#include <signal.h>
-#include "gdb_string.h"
#include "symtab.h"
#include "gdbtypes.h"
#include "frame.h"
#include "inferior.h"
+#include "infrun.h"
#include "environ.h"
#include "value.h"
#include "gdbcmd.h"
#include "gdbcore.h"
#include "target.h"
#include "language.h"
-#include "symfile.h"
#include "objfiles.h"
#include "completer.h"
#include "ui-out.h"
#include "block.h"
#include "solib.h"
#include <ctype.h>
-#include "gdb_assert.h"
#include "observer.h"
#include "target-descriptions.h"
#include "user-regs.h"
-#include "exceptions.h"
#include "cli/cli-decode.h"
#include "gdbthread.h"
#include "valprint.h"
static void go_command (char *line_no, int from_tty);
-static int strip_bg_char (char **);
-
void _initialize_infcmd (void);
#define ERROR_NO_INFERIOR \
int stopped_by_random_signal;
+/* See inferior.h. */
+
+int startup_with_shell = 1;
+
\f
/* Accessor routines. */
}
/* Notice when `set args' is run. */
+
static void
set_args_command (char *args, int from_tty, struct cmd_list_element *c)
{
}
/* 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)
\f
/* Compute command-line string given argument vector. This does the
same shell processing as fork_inferior. */
+
char *
construct_inferior_arguments (int argc, char **argv)
{
char *result;
- if (STARTUP_WITH_SHELL)
+ if (startup_with_shell)
{
#ifdef __MINGW32__
/* This holds all the characters considered special to the
}
\f
-/* This function detects whether or not a '&' character (indicating
- background execution) has been added as *the last* of the arguments ARGS
- of a command. If it has, it removes it and returns 1. Otherwise it
- does nothing and returns 0. */
-static int
-strip_bg_char (char **args)
+/* 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 char *
+strip_bg_char (const char *args, int *bg_char_p)
{
- char *p = NULL;
+ const char *p;
- p = strchr (*args, '&');
+ if (args == NULL || *args == '\0')
+ {
+ *bg_char_p = 0;
+ return NULL;
+ }
- if (p)
+ p = args + strlen (args);
+ if (p[-1] == '&')
{
- if (p == (*args + strlen (*args) - 1))
- {
- if (strlen (*args) > 1)
- {
- do
- p--;
- while (*p == ' ' || *p == '\t');
- *(p + 1) = '\0';
- }
- else
- *args = 0;
- return 1;
- }
+ p--;
+ while (p > args && isspace (p[-1]))
+ p--;
+
+ *bg_char_p = 1;
+ if (p != args)
+ return savestring (args, p - args);
+ else
+ return NULL;
}
- return 0;
+
+ *bg_char_p = 0;
+ return xstrdup (args);
}
/* Common actions to take after creating any sort of inferior, by any
}
}
+/* 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->to_can_async_p (target))
+ error (_("Asynchronous execution not supported on this target."));
+
+ /* If we don't get a request of running in the bg, then we need
+ to simulate synchronous (fg) execution. */
+ if (!background && target->to_can_async_p (target))
+ {
+ /* Simulate synchronous execution. Note no cleanup is necessary
+ for this. stdin is re-enabled whenever an error reaches the
+ top level. */
+ async_disable_stdin ();
+ }
+}
+
/* Implement the "run" command. If TBREAK_AT_MAIN is set, then insert
a temporary breakpoint at the begining of the main program before
running the program. */
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;
dont_repeat ();
reopen_exec_file ();
reread_symbols ();
+ args = strip_bg_char (args, &async_exec);
+ args_chain = make_cleanup (xfree, args);
+
+ /* 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->to_supports_non_stop (run_target))
+ error (_("The target does not support running in non-stop mode."));
+
+ /* Done. Can now set breakpoints, change inferior args, etc. */
+
/* Insert the temporary breakpoint if a location was specified. */
if (tbreak_at_main)
tbreak_command (main_name (), 0);
exec_file = (char *) get_exec_file (0);
- if (non_stop && !target_supports_non_stop ())
- error (_("The target does not support running in non-stop mode."));
-
/* 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
the user has to manually nuke all symbols between runs if they
want them to go away (PR 2207). This is probably reasonable. */
- if (!args)
- {
- if (target_can_async_p ())
- async_disable_stdin ();
- }
- else
- {
- int async_exec = strip_bg_char (&args);
-
- /* If we get a request for running in the bg but the target
- doesn't support it, error out. */
- if (async_exec && !target_can_async_p ())
- error (_("Asynchronous execution not supported on this target."));
-
- /* If we don't get a request of running in the bg, then we need
- to simulate synchronous (fg) execution. */
- if (!async_exec && target_can_async_p ())
- {
- /* Simulate synchronous execution. */
- async_disable_stdin ();
- }
-
- /* If there were other args, beside '&', process them. */
- if (args)
- set_inferior_args (args);
- }
+ /* If there were other args, beside '&', process them. */
+ if (args != NULL)
+ set_inferior_args (args);
if (from_tty)
{
ui_out_flush (uiout);
}
+ /* Done with ARGS. */
+ do_cleanups (args_chain);
+
/* We call get_inferior_args() because we might need to compute
the value now. */
- target_create_inferior (exec_file, get_inferior_args (),
- environ_vector (current_inferior ()->environment),
- from_tty);
+ run_target->to_create_inferior (run_target, exec_file, get_inferior_args (),
+ environ_vector (current_inferior ()->environment),
+ from_tty);
+ /* to_create_inferior should push the target, so after this point we
+ shouldn't refer to run_target again. */
+ run_target = NULL;
/* 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,
return 0;
switch_to_thread (thread->ptid);
- clear_proceed_status ();
+ clear_proceed_status (0);
proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT, 0);
return 0;
}
iterate_over_threads (proceed_thread_callback, NULL);
+ if (sync_execution)
+ {
+ /* 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 ();
+ }
+
/* Restore selected ptid. */
do_cleanups (old_chain);
}
{
ensure_valid_thread ();
ensure_not_running ();
- clear_proceed_status ();
+ clear_proceed_status (0);
proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT, 0);
}
}
/* continue [-a] [proceed-count] [&] */
+
static void
continue_command (char *args, int from_tty)
{
- int async_exec = 0;
+ int async_exec;
int all_threads = 0;
+ struct cleanup *args_chain;
+
ERROR_NO_INFERIOR;
/* Find out whether we must run in the background. */
- if (args != NULL)
- async_exec = strip_bg_char (&args);
+ args = strip_bg_char (args, &async_exec);
+ args_chain = make_cleanup (xfree, args);
- /* If we must run in the background, but the target can't do it,
- error out. */
- if (async_exec && !target_can_async_p ())
- error (_("Asynchronous execution not supported on this target."));
-
- /* If we are not asked to run in the bg, then prepare to run in the
- foreground, synchronously. */
- if (!async_exec && target_can_async_p ())
- {
- /* Simulate synchronous execution. */
- async_disable_stdin ();
- }
+ prepare_execution_command (¤t_target, async_exec);
if (args != NULL)
{
}
}
+ /* Done with ARGS. */
+ do_cleanups (args_chain);
+
if (from_tty)
printf_filtered (_("Continuing.\n"));
{
int count = 1;
struct cleanup *cleanups = make_cleanup (null_cleanup, NULL);
- int async_exec = 0;
+ int async_exec;
int thread = -1;
+ struct cleanup *args_chain;
ERROR_NO_INFERIOR;
ensure_not_tfind_mode ();
ensure_valid_thread ();
ensure_not_running ();
- if (count_string)
- async_exec = strip_bg_char (&count_string);
-
- /* If we get a request for running in the bg but the target
- doesn't support it, error out. */
- if (async_exec && !target_can_async_p ())
- error (_("Asynchronous execution not supported on this target."));
+ count_string = strip_bg_char (count_string, &async_exec);
+ args_chain = make_cleanup (xfree, count_string);
- /* If we don't get a request of running in the bg, then we need
- to simulate synchronous (fg) execution. */
- if (!async_exec && target_can_async_p ())
- {
- /* Simulate synchronous execution. */
- async_disable_stdin ();
- }
+ prepare_execution_command (¤t_target, async_exec);
count = count_string ? parse_and_eval_long (count_string) : 1;
+ /* Done with ARGS. */
+ do_cleanups (args_chain);
+
if (!single_inst || skip_subroutines) /* Leave si command alone. */
{
struct thread_info *tp = inferior_thread ();
to the user. If count is > 1, we will need to do one more call to
proceed(), via step_once(). Basically it is like step_once and
step_1_continuation are co-recursive. */
+
static void
step_1_continuation (void *args, int err)
{
THREAD is set. */
struct thread_info *tp = inferior_thread ();
- clear_proceed_status ();
+ clear_proceed_status (!skip_subroutines);
set_step_frame ();
if (!single_inst)
&tp->control.step_range_start,
&tp->control.step_range_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.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;
struct symtab_and_line sal;
struct symbol *fn;
struct symbol *sfn;
- int async_exec = 0;
+ 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. */
- if (arg != NULL)
- async_exec = strip_bg_char (&arg);
+ arg = strip_bg_char (arg, &async_exec);
+ args_chain = make_cleanup (xfree, arg);
- /* If we must run in the background, but the target can't do it,
- error out. */
- if (async_exec && !target_can_async_p ())
- error (_("Asynchronous execution not supported on this target."));
+ prepare_execution_command (¤t_target, async_exec);
if (!arg)
error_no_arg (_("starting address"));
sal = sals.sals[0];
xfree (sals.sals);
+ /* Done with ARGS. */
+ do_cleanups (args_chain);
+
if (sal.symtab == 0 && sal.pc == 0)
error (_("No source file has been specified."));
printf_filtered (".\n");
}
- /* If we are not asked to run in the bg, then prepare to run in the
- foreground, synchronously. */
- if (!async_exec && target_can_async_p ())
- {
- /* Simulate synchronous execution. */
- async_disable_stdin ();
- }
-
- clear_proceed_status ();
+ clear_proceed_status (0);
proceed (addr, GDB_SIGNAL_0, 0);
}
\f
/* Go to line or address in current procedure. */
+
static void
go_command (char *line_no, int from_tty)
{
signal_command (char *signum_exp, int from_tty)
{
enum gdb_signal oursig;
- int async_exec = 0;
+ 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. */
- if (signum_exp != NULL)
- async_exec = strip_bg_char (&signum_exp);
-
- /* If we must run in the background, but the target can't do it,
- error out. */
- if (async_exec && !target_can_async_p ())
- error (_("Asynchronous execution not supported on this target."));
+ signum_exp = strip_bg_char (signum_exp, &async_exec);
+ args_chain = make_cleanup (xfree, signum_exp);
- /* If we are not asked to run in the bg, then prepare to run in the
- foreground, synchronously. */
- if (!async_exec && target_can_async_p ())
- {
- /* Simulate synchronous execution. */
- async_disable_stdin ();
- }
+ prepare_execution_command (¤t_target, async_exec);
if (!signum_exp)
error_no_arg (_("signal number"));
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)
+ {
+ struct thread_info *tp;
+ ptid_t resume_ptid;
+ int must_confirm = 0;
+
+ /* This indicates what will be resumed. Either a single thread,
+ a whole process, or all threads of all processes. */
+ resume_ptid = user_visible_resume_ptid (0);
+
+ ALL_NON_EXITED_THREADS (tp)
+ {
+ if (ptid_equal (tp->ptid, inferior_ptid))
+ continue;
+ if (!ptid_match (tp->ptid, resume_ptid))
+ continue;
+
+ if (tp->suspend.stop_signal != GDB_SIGNAL_0
+ && signal_pass_state (tp->suspend.stop_signal))
+ {
+ if (!must_confirm)
+ printf_unfiltered (_("Note:\n"));
+ printf_unfiltered (_(" Thread %d previously stopped with signal %s, %s.\n"),
+ tp->num,
+ gdb_signal_to_name (tp->suspend.stop_signal),
+ gdb_signal_to_string (tp->suspend.stop_signal));
+ must_confirm = 1;
+ }
+ }
+
+ if (must_confirm
+ && !query (_("Continuing thread %d (the current thread) with specified signal will\n"
+ "still deliver the signals noted above to their respective threads.\n"
+ "Continue anyway? "),
+ inferior_thread ()->num))
+ error (_("Not confirmed."));
+ }
+
if (from_tty)
{
if (oursig == GDB_SIGNAL_0)
gdb_signal_to_name (oursig));
}
- clear_proceed_status ();
+ clear_proceed_status (0);
proceed ((CORE_ADDR) -1, oursig, 0);
}
+/* Queue a signal to be delivered to the current thread. */
+
+static void
+queue_signal_command (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 == NULL)
+ 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->suspend.stop_signal = oursig;
+}
+
/* Continuation args to be passed to the "until" command
continuation. */
struct until_next_continuation_args
int thread = tp->num;
struct cleanup *old_chain;
- clear_proceed_status ();
+ clear_proceed_status (0);
set_step_frame ();
frame = get_current_frame ();
if (msymbol.minsym == NULL)
error (_("Execution is not within a known function."));
- tp->control.step_range_start = SYMBOL_VALUE_ADDRESS (msymbol.minsym);
- tp->control.step_range_end = pc;
+ tp->control.step_range_start = BMSYMBOL_VALUE_ADDRESS (msymbol);
+ /* 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
{
tp->control.step_range_start = BLOCK_START (SYMBOL_BLOCK_VALUE (func));
tp->control.step_range_end = sal.end;
}
+ tp->control.may_range_step = 1;
tp->control.step_over_calls = STEP_OVER_ALL;
static void
until_command (char *arg, int from_tty)
{
- int async_exec = 0;
+ 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. */
- if (arg != NULL)
- async_exec = strip_bg_char (&arg);
+ arg = strip_bg_char (arg, &async_exec);
+ args_chain = make_cleanup (xfree, arg);
- /* If we must run in the background, but the target can't do it,
- error out. */
- if (async_exec && !target_can_async_p ())
- error (_("Asynchronous execution not supported on this target."));
-
- /* If we are not asked to run in the bg, then prepare to run in the
- foreground, synchronously. */
- if (!async_exec && target_can_async_p ())
- {
- /* Simulate synchronous execution. */
- async_disable_stdin ();
- }
+ prepare_execution_command (¤t_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)
{
- int async_exec = 0;
+ 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. */
- if (arg != NULL)
- async_exec = strip_bg_char (&arg);
+ arg = strip_bg_char (arg, &async_exec);
+ args_chain = make_cleanup (xfree, arg);
- /* If we must run in the background, but the target can't do it,
- error out. */
- if (async_exec && !target_can_async_p ())
- error (_("Asynchronous execution not supported on this target."));
-
- /* If we are not asked to run in the bg, then prepare to run in the
- foreground, synchronously. */
- if (!async_exec && target_can_async_p ())
- {
- /* Simulate synchronous execution. */
- async_disable_stdin ();
- }
+ prepare_execution_command (¤t_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'
ui_out_field_fmt (uiout, "gdb-result-var", "$%d",
record_latest_value (value));
ui_out_text (uiout, " = ");
- get_raw_print_options (&opts);
+ get_no_prettyformat_print_options (&opts);
value_print (value, stb, &opts);
ui_out_field_stream (uiout, "return-value", stb);
ui_out_text (uiout, "\n");
pc = get_frame_pc (get_current_frame ());
if (find_pc_partial_function (pc, NULL, &func_addr, NULL) == 0)
- internal_error (__FILE__, __LINE__,
- _("Finish: couldn't find function."));
+ error (_("Cannot find bounds of current function"));
sal = find_pc_line (func_addr, 0);
{
struct frame_info *frame;
struct symbol *function;
-
- int async_exec = 0;
+ 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. */
- if (arg != NULL)
- async_exec = strip_bg_char (&arg);
+ arg = strip_bg_char (arg, &async_exec);
+ args_chain = make_cleanup (xfree, arg);
- /* If we must run in the background, but the target can't do it,
- error out. */
- if (async_exec && !target_can_async_p ())
- error (_("Asynchronous execution not supported on this target."));
-
- /* If we are not asked to run in the bg, then prepare to run in the
- foreground, synchronously. */
- if (!async_exec && target_can_async_p ())
- {
- /* Simulate synchronous execution. */
- async_disable_stdin ();
- }
+ prepare_execution_command (¤t_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."));
- clear_proceed_status ();
+ clear_proceed_status (0);
/* Finishing from an inline frame is completely different. We don't
try to show the "return value" - no way to locate it. So we do
if (from_tty)
{
printf_filtered (_("Run till exit from "));
- print_stack_frame (get_selected_frame (NULL), 1, LOCATION);
+ print_stack_frame (get_selected_frame (NULL), 1, LOCATION, 0);
}
proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT, 1);
else
printf_filtered (_("Run till exit from "));
- print_stack_frame (get_selected_frame (NULL), 1, LOCATION);
+ print_stack_frame (get_selected_frame (NULL), 1, LOCATION, 0);
}
if (execution_direction == EXEC_REVERSE)
gdb_signal_to_string (tp->suspend.stop_signal));
}
- if (!from_tty)
+ if (from_tty)
{
printf_filtered (_("Type \"info stack\" or \"info "
"registers\" for more information.\n"));
struct value *val)
{
struct type *regtype = value_type (val);
+ int print_raw_format;
fputs_filtered (name, file);
print_spaces_filtered (15 - strlen (name), file);
- if (!value_entirely_available (val))
- {
- fprintf_filtered (file, "*value not available*\n");
- return;
- }
+ print_raw_format = (value_entirely_available (val)
+ && !value_optimized_out (val));
/* If virtual format is floating, print it that way, and in raw
hex. */
value_embedded_offset (val), 0,
file, 0, val, &opts, current_language);
- fprintf_filtered (file, "\t(raw 0x");
- for (j = 0; j < TYPE_LENGTH (regtype); j++)
+ if (print_raw_format)
{
- int idx;
-
- if (byte_order == BFD_ENDIAN_BIG)
- idx = j;
- else
- idx = TYPE_LENGTH (regtype) - 1 - j;
- fprintf_filtered (file, "%02x", (unsigned char) valaddr[idx]);
+ fprintf_filtered (file, "\t(raw ");
+ print_hex_chars (file, valaddr, TYPE_LENGTH (regtype), byte_order);
+ fprintf_filtered (file, ")");
}
- fprintf_filtered (file, ")");
}
else
{
file, 0, val, &opts, current_language);
/* If not a vector register, print it also according to its
natural format. */
- if (TYPE_VECTOR (regtype) == 0)
+ if (print_raw_format && TYPE_VECTOR (regtype) == 0)
{
get_user_print_options (&opts);
opts.deref_ref = 1;
for (i = 0; i < numregs; i++)
{
- struct type *regtype;
- struct value *val;
-
/* Decide between printing all regs, non-float / vector regs, or
specific reg. */
if (regnum == -1)
|| *(gdbarch_register_name (gdbarch, i)) == '\0')
continue;
- regtype = register_type (gdbarch, i);
- val = allocate_value (regtype);
-
- /* Get the data in raw format. */
- if (! deprecated_frame_register_read (frame, i, value_contents_raw (val)))
- mark_value_bytes_unavailable (val, 0, TYPE_LENGTH (value_type (val)));
-
default_print_one_register_info (file,
gdbarch_register_name (gdbarch, i),
- val);
+ value_of_register (i, frame));
}
}
if (target_has_stack)
{
printf_filtered (_("In %s,\n"), target_longname);
- print_stack_frame (get_selected_frame (NULL), 1, SRC_AND_LOC);
+ print_stack_frame (get_selected_frame (NULL), 1, SRC_AND_LOC, 1);
}
}
bfd_cache_close_all ();
&& thread->suspend.stop_signal == GDB_SIGNAL_0)
{
switch_to_thread (thread->ptid);
- clear_proceed_status ();
+ clear_proceed_status (0);
proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT, 0);
}
do_cleanups (old_chain);
}
-/*
- * TODO:
- * Should save/restore the tty state since it might be that the
- * program to be debugged was started on this tty and it wants
- * the tty in some state other than what we want. If it's running
- * on another terminal or without a terminal, then saving and
- * restoring the tty state is a harmless no-op.
- * This only needs to be done if we are attaching to a process.
- */
-
/* attach_command --
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.
exec_file = (char *) get_exec_file (0);
if (!exec_file)
{
- exec_file = target_pid_to_exec_file (PIDGET (inferior_ptid));
+ exec_file = target_pid_to_exec_file (ptid_get_pid (inferior_ptid));
if (exec_file)
{
/* It's possible we don't have a full path, but rather just a
}
/* Take any necessary post-attaching actions for this platform. */
- target_post_attach (PIDGET (inferior_ptid));
+ target_post_attach (ptid_get_pid (inferior_ptid));
post_create_inferior (¤t_target, from_tty);
- /* Install inferior's terminal modes. */
- target_terminal_inferior ();
-
if (async_exec)
{
/* The user requested an `attach&', so be sure to leave threads
{
if (inferior_thread ()->suspend.stop_signal == GDB_SIGNAL_0)
{
- clear_proceed_status ();
+ clear_proceed_status (0);
proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT, 0);
}
}
void
attach_command (char *args, int from_tty)
{
- int async_exec = 0;
- struct cleanup *back_to = make_cleanup (null_cleanup, NULL);
+ int async_exec;
+ struct cleanup *args_chain;
+ struct target_ops *attach_target;
dont_repeat (); /* Not for the faint of heart */
this function should probably be moved into target_pre_inferior. */
target_pre_inferior (from_tty);
- if (non_stop && !target_supports_non_stop ())
- error (_("Cannot attach to this target in non-stop mode"));
+ args = strip_bg_char (args, &async_exec);
+ args_chain = make_cleanup (xfree, args);
- if (args)
- {
- async_exec = strip_bg_char (&args);
+ attach_target = find_attach_target ();
- /* If we get a request for running in the bg but the target
- doesn't support it, error out. */
- if (async_exec && !target_can_async_p ())
- error (_("Asynchronous execution not supported on this target."));
- }
+ prepare_execution_command (attach_target, async_exec);
- /* If we don't get a request of running in the bg, then we need
- to simulate synchronous (fg) execution. */
- if (!async_exec && target_can_async_p ())
- {
- /* Simulate synchronous execution. */
- async_disable_stdin ();
- make_cleanup ((make_cleanup_ftype *)async_enable_stdin, NULL);
- }
+ if (non_stop && !attach_target->to_supports_non_stop (attach_target))
+ error (_("Cannot attach to this target in non-stop mode"));
+
+ attach_target->to_attach (attach_target, args, from_tty);
+ /* to_attach should push the target, so after this point we
+ shouldn't refer to attach_target again. */
+ attach_target = NULL;
- target_attach (args, from_tty);
+ /* Done with ARGS. */
+ do_cleanups (args_chain);
/* 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 ();
- clear_proceed_status ();
+ clear_proceed_status (0);
if (non_stop)
{
a->async_exec = async_exec;
add_inferior_continuation (attach_command_continuation, a,
attach_command_continuation_free_args);
- discard_cleanups (back_to);
return;
}
}
attach_command_post_wait (args, from_tty, async_exec);
- discard_cleanups (back_to);
}
/* We had just found out that the target was already attached to an
set_stop_requested (ptid, 1);
}
-/* Stop the execution of the target while running in async mode, in
+/* interrupt [-a]
+ Stop the execution of the target while running in async mode, in
the backgound. 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. */
-/* interrupt [-a] */
static void
-interrupt_target_command (char *args, int from_tty)
+interrupt_command (char *args, int from_tty)
{
if (target_can_async_p ())
{
{
printf_filtered (_("\"unset\" must be followed by the "
"name of an unset subcommand.\n"));
- help_list (unsetlist, "unset ", -1, gdb_stdout);
+ help_list (unsetlist, "unset ", all_commands, gdb_stdout);
}
/* Implement `info proc' family of commands. */
\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."));
+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);
add_com ("stepi", class_run, stepi_command, _("\
\"run\" command."));
set_cmd_completer (c, filename_completer);
- add_com ("interrupt", class_run, interrupt_target_command,
+ 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\