/* 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"
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
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)
{
}
}
+/* 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 = 0;
dont_repeat ();
reopen_exec_file ();
reread_symbols ();
+ if (args != NULL)
+ async_exec = strip_bg_char (&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)
{
/* 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;
}
{
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)
{
if (args != NULL)
async_exec = strip_bg_char (&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)
{
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."));
-
- /* 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;
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)
if (arg != NULL)
async_exec = strip_bg_char (&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"));
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)
{
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."));
-
- /* 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
{
if (arg != NULL)
async_exec = strip_bg_char (&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);
if (arg != NULL)
async_exec = strip_bg_char (&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);
}
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);
if (arg != NULL)
async_exec = strip_bg_char (&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."));
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
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 ");
- print_hex_chars (file, valaddr, TYPE_LENGTH (regtype), byte_order);
- fprintf_filtered (file, ")");
+ if (print_raw_format)
+ {
+ fprintf_filtered (file, "\t(raw ");
+ print_hex_chars (file, valaddr, TYPE_LENGTH (regtype), byte_order);
+ 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));
}
}
&& 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);
}
}
attach_command (char *args, int from_tty)
{
int async_exec = 0;
- struct cleanup *back_to = make_cleanup (null_cleanup, NULL);
+ 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"));
+ if (args != NULL)
+ async_exec = strip_bg_char (&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"));
- target_attach (args, from_tty);
+ 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;
/* 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\