/* Memory-access and commands for "inferior" process, for GDB.
- Copyright (C) 1986-2019 Free Software Foundation, Inc.
+ Copyright (C) 1986-2020 Free Software Foundation, Inc.
This file is part of GDB.
#include "defs.h"
#include "arch-utils.h"
-#include <signal.h>
#include "symtab.h"
#include "gdbtypes.h"
#include "frame.h"
#include "objfiles.h"
#include "completer.h"
#include "ui-out.h"
-#include "event-top.h"
-#include "parser-defs.h"
#include "regcache.h"
#include "reggroups.h"
#include "block.h"
#include "observable.h"
#include "target-descriptions.h"
#include "user-regs.h"
-#include "cli/cli-decode.h"
#include "gdbthread.h"
#include "valprint.h"
#include "inline-frame.h"
#include "inf-loop.h"
#include "continuations.h"
#include "linespec.h"
-#include "cli/cli-utils.h"
-#include "infcall.h"
#include "thread-fsm.h"
#include "top.h"
#include "interps.h"
+#include "skip.h"
#include "gdbsupport/gdb_optional.h"
#include "source.h"
+#include "cli/cli-style.h"
/* Local functions: */
int stopped_by_random_signal;
-/* See inferior.h. */
-
-int startup_with_shell = 1;
-
\f
/* Accessor routines. */
"when starting the inferior is \"%s\".\n"), cwd);
}
-\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)
- {
-#ifdef __MINGW32__
- /* This holds all the characters considered special to the
- Windows shells. */
- static const char special[] = "\"!&*|[]{}<>?`~^=;, \t\n";
- static const char quote = '"';
-#else
- /* This holds all the characters considered special to the
- typical Unix shells. We include `^' because the SunOS
- /bin/sh treats it as a synonym for `|'. */
- static const char special[] = "\"!#$&*()\\|[]{}<>?'`~^; \t\n";
- static const char quote = '\'';
-#endif
- int i;
- int length = 0;
- char *out, *cp;
-
- /* We over-compute the size. It shouldn't matter. */
- for (i = 0; i < argc; ++i)
- length += 3 * strlen (argv[i]) + 1 + 2 * (argv[i][0] == '\0');
-
- result = (char *) xmalloc (length);
- out = result;
-
- for (i = 0; i < argc; ++i)
- {
- if (i > 0)
- *out++ = ' ';
-
- /* Need to handle empty arguments specially. */
- if (argv[i][0] == '\0')
- {
- *out++ = quote;
- *out++ = quote;
- }
- else
- {
-#ifdef __MINGW32__
- int quoted = 0;
-
- if (strpbrk (argv[i], special))
- {
- quoted = 1;
- *out++ = quote;
- }
-#endif
- for (cp = argv[i]; *cp; ++cp)
- {
- if (*cp == '\n')
- {
- /* A newline cannot be quoted with a backslash (it
- just disappears), only by putting it inside
- quotes. */
- *out++ = quote;
- *out++ = '\n';
- *out++ = quote;
- }
- else
- {
-#ifdef __MINGW32__
- if (*cp == quote)
-#else
- if (strchr (special, *cp) != NULL)
-#endif
- *out++ = '\\';
- *out++ = *cp;
- }
- }
-#ifdef __MINGW32__
- if (quoted)
- *out++ = quote;
-#endif
- }
- }
- *out = '\0';
- }
- else
- {
- /* In this case we can't handle arguments that contain spaces,
- tabs, or newlines -- see breakup_args(). */
- int i;
- int length = 0;
-
- for (i = 0; i < argc; ++i)
- {
- char *cp = strchr (argv[i], ' ');
- if (cp == NULL)
- cp = strchr (argv[i], '\t');
- if (cp == NULL)
- cp = strchr (argv[i], '\n');
- if (cp != NULL)
- error (_("can't handle command-line "
- "argument containing whitespace"));
- length += strlen (argv[i]) + 1;
- }
-
- result = (char *) xmalloc (length);
- result[0] = '\0';
- for (i = 0; i < argc; ++i)
- {
- if (i > 0)
- strcat (result, " ");
- strcat (result, argv[i]);
- }
- }
-
- return result;
-}
-\f
/* This function strips the '&' character (indicating background
execution) that is added as *the last* of the arguments ARGS of a
thr->suspend.stop_pc = 0;
try
{
- thr->suspend.stop_pc = regcache_read_pc (get_current_regcache ());
+ regcache *rc = get_thread_regcache (thr);
+ thr->suspend.stop_pc = regcache_read_pc (rc);
}
catch (const gdb_exception_error &ex)
{
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. */
- ptid_t finish_ptid = (non_stop
- ? ptid_t (current_inferior ()->pid)
- : minus_one_ptid);
- scoped_finish_thread_state finish_state (finish_ptid);
+ process_stratum_target *finish_target;
+ ptid_t finish_ptid;
+ if (non_stop)
+ {
+ finish_target = current_inferior ()->process_target ();
+ finish_ptid = ptid_t (current_inferior ()->pid);
+ }
+ else
+ {
+ finish_target = nullptr;
+ finish_ptid = minus_one_ptid;
+ }
+ scoped_finish_thread_state finish_state (finish_target, finish_ptid);
/* Pass zero for FROM_TTY, because at this point the "run" command
has done its thing; now we are setting up the running program. */
if (thread->state != THREAD_STOPPED)
return 0;
+ if (!thread->inf->has_execution ())
+ return 0;
+
switch_to_thread (thread);
clear_proceed_status (0);
proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
continue_command (const char *args, int from_tty)
{
int async_exec;
- int all_threads = 0;
+ bool all_threads_p = false;
ERROR_NO_INFERIOR;
{
if (startswith (args, "-a"))
{
- all_threads = 1;
+ all_threads_p = true;
args += sizeof ("-a") - 1;
if (*args == '\0')
args = NULL;
}
}
- if (!non_stop && all_threads)
+ if (!non_stop && all_threads_p)
error (_("`-a' is meaningless in all-stop mode."));
- if (args != NULL && all_threads)
+ if (args != NULL && all_threads_p)
error (_("Can't resume all threads and specify "
"proceed count simultaneously."));
tp = inferior_thread ();
else
{
+ process_stratum_target *last_target;
ptid_t last_ptid;
- struct target_waitstatus ws;
- get_last_target_status (&last_ptid, &ws);
- tp = find_thread_ptid (last_ptid);
+ get_last_target_status (&last_target, &last_ptid, nullptr);
+ tp = find_thread_ptid (last_target, last_ptid);
}
if (tp != NULL)
bs = tp->control.stop_bpstat;
ERROR_NO_INFERIOR;
ensure_not_tfind_mode ();
- if (!non_stop || !all_threads)
+ if (!non_stop || !all_threads_p)
{
ensure_valid_thread ();
ensure_not_running ();
if (from_tty)
printf_filtered (_("Continuing.\n"));
- continue_1 (all_threads);
+ continue_1 (all_threads_p);
}
\f
-/* Record the starting point of a "step" or "next" command. */
+/* Record in TP the starting point of a "step" or "next" command. */
static void
-set_step_frame (void)
+set_step_frame (thread_info *tp)
{
+ /* This can be removed once this function no longer implicitly relies on the
+ inferior_ptid value. */
+ gdb_assert (inferior_ptid == tp->ptid);
+
frame_info *frame = get_current_frame ();
symtab_and_line sal = find_frame_sal (frame);
- set_step_info (frame, sal);
+ set_step_info (tp, frame, sal);
CORE_ADDR pc = get_frame_pc (frame);
- thread_info *tp = inferior_thread ();
tp->control.step_start_function = find_pc_function (pc);
}
thread->control.stepping_command = 1;
}
-static int prepare_one_step (struct step_command_fsm *sm);
+static int prepare_one_step (thread_info *, struct step_command_fsm *sm);
static void
step_1 (int skip_subroutines, int single_inst, const char *count_string)
loop. Let the continuation figure out how many other steps we
need to do, and handle them one at the time, through
step_once. */
- if (!prepare_one_step (step_sm))
+ if (!prepare_one_step (thr, step_sm))
proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
else
{
/* There are more steps to make, and we did stop due to
ending a stepping range. Do another step. */
if (--count > 0)
- return prepare_one_step (this);
+ return prepare_one_step (tp, this);
set_finished ();
}
resumed. */
static int
-prepare_one_step (struct step_command_fsm *sm)
+prepare_one_step (thread_info *tp, struct step_command_fsm *sm)
{
+ /* This can be removed once this function no longer implicitly relies on the
+ inferior_ptid value. */
+ gdb_assert (inferior_ptid == tp->ptid);
+
if (sm->count > 0)
{
struct frame_info *frame = get_current_frame ();
- /* Don't assume THREAD is a valid thread id. It is set to -1 if
- the longjmp breakpoint was not required. Use the
- INFERIOR_PTID thread instead, which is the same thread when
- THREAD is set. */
- struct thread_info *tp = inferior_thread ();
-
- set_step_frame ();
+ set_step_frame (tp);
if (!sm->single_inst)
{
&& inline_skipped_frames (tp))
{
ptid_t resume_ptid;
+ const char *fn = NULL;
+ symtab_and_line sal;
+ struct symbol *sym;
/* Pretend that we've ran. */
resume_ptid = user_visible_resume_ptid (1);
- set_running (resume_ptid, 1);
+ set_running (tp->inf->process_target (), resume_ptid, true);
step_into_inline_frame (tp);
- sm->count--;
- return prepare_one_step (sm);
+
+ frame = get_current_frame ();
+ sal = find_frame_sal (frame);
+ sym = get_frame_function (frame);
+
+ if (sym != NULL)
+ fn = sym->print_name ();
+
+ if (sal.line == 0
+ || !function_name_is_marked_for_skip (fn, sal))
+ {
+ sm->count--;
+ return prepare_one_step (tp, sm);
+ }
}
pc = get_frame_pc (frame);
if (fn != NULL && sfn != fn)
{
if (!query (_("Line %d is not in `%s'. Jump anyway? "), sal.line,
- SYMBOL_PRINT_NAME (fn)))
+ fn->print_name ()))
{
error (_("Not confirmed."));
/* NOTREACHED */
/* This indicates what will be resumed. Either a single thread,
a whole process, or all threads of all processes. */
ptid_t resume_ptid = user_visible_resume_ptid (0);
+ process_stratum_target *resume_target
+ = user_visible_resume_target (resume_ptid);
+
+ thread_info *current = inferior_thread ();
- for (thread_info *tp : all_non_exited_threads (resume_ptid))
+ for (thread_info *tp : all_non_exited_threads (resume_target, resume_ptid))
{
- if (tp->ptid == inferior_ptid)
+ if (tp == current)
continue;
if (tp->suspend.stop_signal != GDB_SIGNAL_0
struct until_next_fsm *sm;
clear_proceed_status (0);
- set_step_frame ();
+ set_step_frame (tp);
frame = get_current_frame ();
struct value *value;
value_type = check_typedef (value_type);
- gdb_assert (TYPE_CODE (value_type) != TYPE_CODE_VOID);
+ gdb_assert (value_type->code () != TYPE_CODE_VOID);
/* FIXME: 2003-09-27: When returning from a nested inferior function
call, it's possible (with no help from the architecture vector)
uiout->field_stream ("return-value", stb);
}
else
- uiout->field_string ("return-value", _("<not displayed>"));
+ uiout->field_string ("return-value", _("<not displayed>"),
+ metadata_style.style ());
uiout->text ("\n");
}
else
print_return_value (struct ui_out *uiout, struct return_value_info *rv)
{
if (rv->type == NULL
- || TYPE_CODE (check_typedef (rv->type)) == TYPE_CODE_VOID)
+ || check_typedef (rv->type)->code () == TYPE_CODE_VOID)
return;
try
internal_error (__FILE__, __LINE__,
_("finish_command: function has no target type"));
- if (TYPE_CODE (check_typedef (rv->type)) != TYPE_CODE_VOID)
+ if (check_typedef (rv->type)->code () != TYPE_CODE_VOID)
{
struct value *func;
called by that frame. We don't use the magic "1" value for
step_range_end, because then infrun will think this is nexti,
and not step over the rest of this inlined function call. */
- set_step_info (frame, {});
+ set_step_info (tp, frame, {});
tp->control.step_range_start = get_frame_pc (frame);
tp->control.step_range_end = tp->control.step_range_start;
tp->control.step_over_calls = STEP_OVER_ALL;
if (sm->function != NULL && TYPE_NO_RETURN (sm->function->type)
&& !query (_("warning: Function %s does not return normally.\n"
"Try to finish anyway? "),
- SYMBOL_PRINT_NAME (sm->function)))
+ sm->function->print_name ()))
error (_("Not confirmed."));
printf_filtered (_("Run till exit from "));
}
bpstat bs;
int num, stat;
ptid_t ptid;
+ process_stratum_target *proc_target;
if (!target_has_execution)
{
}
if (non_stop)
- ptid = inferior_ptid;
- else
{
- struct target_waitstatus ws;
-
- get_last_target_status (&ptid, &ws);
+ ptid = inferior_ptid;
+ proc_target = current_inferior ()->process_target ();
}
+ else
+ get_last_target_status (&proc_target, &ptid, nullptr);
if (ptid == null_ptid || ptid == minus_one_ptid)
error (_("No selected thread."));
- thread_info *tp = find_thread_ptid (ptid);
+ thread_info *tp = find_thread_ptid (proc_target, ptid);
if (tp->state == THREAD_EXITED)
error (_("Invalid selected thread."));
if (arg == 0)
error_no_arg (_("environment variable and value"));
- /* Find seperation between variable name and value. */
+ /* Find separation between variable name and value. */
p = (char *) strchr (arg, '=');
val = (char *) strchr (arg, ' ');
/* If virtual format is floating, print it that way, and in raw
hex. */
- if (TYPE_CODE (regtype) == TYPE_CODE_FLT
- || TYPE_CODE (regtype) == TYPE_CODE_DECFLOAT)
+ if (regtype->code () == TYPE_CODE_FLT
+ || regtype->code () == TYPE_CODE_DECFLOAT)
{
struct value_print_options opts;
const gdb_byte *valaddr = value_contents_for_printing (val);
- enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (regtype));
+ enum bfd_endian byte_order = type_byte_order (regtype);
get_user_print_options (&opts);
opts.deref_ref = 1;
- val_print (regtype,
- value_embedded_offset (val), 0,
- &format_stream, 0, val, &opts, current_language);
+ common_val_print (val, &format_stream, 0, &opts, current_language);
if (print_raw_format)
{
/* Print the register in hex. */
get_formatted_print_options (&opts, 'x');
opts.deref_ref = 1;
- val_print (regtype,
- value_embedded_offset (val), 0,
- &format_stream, 0, val, &opts, current_language);
+ common_val_print (val, &format_stream, 0, &opts, current_language);
/* If not a vector register, print it also according to its
natural format. */
if (print_raw_format && TYPE_VECTOR (regtype) == 0)
pad_to_column (format_stream, value_column_2);
get_user_print_options (&opts);
opts.deref_ref = 1;
- val_print (regtype,
- value_embedded_offset (val), 0,
- &format_stream, 0, val, &opts, current_language);
+ common_val_print (val, &format_stream, 0, &opts, current_language);
}
}
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 ())
- {
- init_thread_list (); /* Destroy thread info. */
-
- /* Killing off the inferior can leave us with a core file. If
- so, print the state we are left in. */
- if (target_has_stack)
- {
- printf_filtered (_("In %s,\n"), target_longname);
- print_stack_frame (get_selected_frame (NULL), 1, SRC_AND_LOC, 1);
- }
- }
bfd_cache_close_all ();
}
target_stop (ptid_t (inferior_ptid.pid ()));
}
+ /* Check for exec file mismatch, and let the user solve it. */
+ validate_exec_file (from_tty);
+
mode = async_exec ? ATTACH_POST_WAIT_RESUME : ATTACH_POST_WAIT_STOP;
/* Some system don't generate traps when attaching to inferior.
add_inferior_continuation (attach_command_continuation, a,
attach_command_continuation_free_args);
+ /* Let infrun consider waiting for events out of this
+ target. */
+ inferior->process_target ()->threads_executing = true;
+
if (!target_is_async_p ())
mark_infrun_async_event_handler ();
return;
}
-
- attach_post_wait (args, from_tty, mode);
+ else
+ attach_post_wait (args, from_tty, mode);
}
/* We had just found out that the target was already attached to an
deprecated_detach_hook ();
}
-void
-interrupt_target_1 (int all_threads)
-{
- ptid_t ptid;
+/* Stop PTID in the current target, and tag the PTID threads as having
+ been explicitly requested to stop. PTID can be a thread, a
+ process, or minus_one_ptid, meaning all threads of all inferiors of
+ the current target. */
- if (all_threads)
- ptid = minus_one_ptid;
- else
- ptid = inferior_ptid;
-
- if (non_stop)
- target_stop (ptid);
- else
- target_interrupt ();
+static void
+stop_current_target_threads_ns (ptid_t ptid)
+{
+ target_stop (ptid);
/* Tag the thread as having been explicitly requested to stop, so
other parts of gdb know not to resume this thread automatically,
non-stop mode, as when debugging a multi-threaded application in
all-stop mode, we will only get one stop event --- it's undefined
which thread will report the event. */
+ set_stop_requested (current_inferior ()->process_target (),
+ ptid, 1);
+}
+
+/* See inferior.h. */
+
+void
+interrupt_target_1 (bool all_threads)
+{
if (non_stop)
- set_stop_requested (ptid, 1);
+ {
+ if (all_threads)
+ {
+ scoped_restore_current_thread restore_thread;
+
+ for (inferior *inf : all_inferiors ())
+ {
+ switch_to_inferior_no_thread (inf);
+ stop_current_target_threads_ns (minus_one_ptid);
+ }
+ }
+ else
+ stop_current_target_threads_ns (inferior_ptid);
+ }
+ else
+ target_interrupt ();
}
/* interrupt [-a]
gdbarch_print_float_info (get_frame_arch (frame), gdb_stdout, frame, args);
}
\f
-static void
-unset_command (const char *args, int from_tty)
-{
- printf_filtered (_("\"unset\" must be followed by the "
- "name of an unset subcommand.\n"));
- help_list (unsetlist, "unset ", all_commands, gdb_stdout);
-}
-
/* Implement `info proc' family of commands. */
static void
}
}
-/* Implement `info proc' when given without any futher parameters. */
+/* Implement `info proc' when given without any further parameters. */
static void
info_proc_cmd (const char *args, int from_tty)
\n\
To start the inferior without using a shell, use \"set startup-with-shell off\"."
+void _initialize_infcmd ();
void
-_initialize_infcmd (void)
+_initialize_infcmd ()
{
static struct cmd_list_element *info_proc_cmdlist;
struct cmd_list_element *c = NULL;
cmd_name = "inferior-tty";
c = lookup_cmd (&cmd_name, setlist, "", -1, 1);
gdb_assert (c != NULL);
- add_alias_cmd ("tty", c, class_alias, 0, &cmdlist);
+ add_alias_cmd ("tty", c, class_run, 0, &cmdlist);
cmd_name = "args";
add_setshow_string_noescape_cmd (cmd_name, class_run,
environment to be given to the program."), &showlist);
set_cmd_completer (c, noop_completer);
- add_prefix_cmd ("unset", no_class, unset_command,
- _("Complement to certain \"set\" commands."),
- &unsetlist, "unset ", 0, &cmdlist);
+ add_basic_prefix_cmd ("unset", no_class,
+ _("Complement to certain \"set\" commands."),
+ &unsetlist, "unset ", 0, &cmdlist);
c = add_cmd ("environment", class_run, unset_environment_command, _("\
Cancel environment variable VAR for the program.\n\
Usage: stepi [N]\n\
Argument N means step N times (or till program stops for another \
reason)."));
- add_com_alias ("si", "stepi", class_alias, 0);
+ add_com_alias ("si", "stepi", class_run, 0);
add_com ("nexti", class_run, nexti_command, _("\
Step one instruction, but proceed through subroutine calls.\n\
Usage: nexti [N]\n\
Argument N means step N times (or till program stops for another \
reason)."));
- add_com_alias ("ni", "nexti", class_alias, 0);
+ add_com_alias ("ni", "nexti", class_run, 0);
add_com ("finish", class_run, finish_command, _("\
Execute until selected stack frame returns.\n\