/* Target-struct-independent code to start (run) and stop an inferior
process.
- Copyright (C) 1986-2017 Free Software Foundation, Inc.
+ Copyright (C) 1986-2018 Free Software Foundation, Inc.
This file is part of GDB.
#include "inf-loop.h"
#include "regcache.h"
#include "value.h"
-#include "observer.h"
+#include "observable.h"
#include "language.h"
#include "solib.h"
#include "main.h"
/* Prototypes for local functions */
-static void signals_info (char *, int);
-
-static void handle_command (char *, int);
-
static void sig_print_info (enum gdb_signal);
static void sig_print_header (void);
-static void resume_cleanups (void *);
-
-static int hook_stop_stub (void *);
-
-static int restore_selected_frame (void *);
-
static int follow_fork (void);
static int follow_fork_inferior (int follow_child, int detach_fork);
static void follow_inferior_reset_breakpoints (void);
-static void set_schedlock_func (char *args, int from_tty,
- struct cmd_list_element *c);
-
static int currently_stepping (struct thread_info *tp);
-void _initialize_infrun (void);
-
void nullify_last_target_wait_ptid (void);
static void insert_hp_step_resume_breakpoint_at_frame (struct frame_info *);
}
static void
-set_disable_randomization (char *args, int from_tty,
+set_disable_randomization (const char *args, int from_tty,
struct cmd_list_element *c)
{
if (!target_supports_disable_randomization ())
static int non_stop_1 = 0;
static void
-set_non_stop (char *args, int from_tty,
+set_non_stop (const char *args, int from_tty,
struct cmd_list_element *c)
{
if (target_has_execution)
static int observer_mode_1 = 0;
static void
-set_observer_mode (char *args, int from_tty,
+set_observer_mode (const char *args, int from_tty,
struct cmd_list_element *c)
{
if (target_has_execution)
as appropriate when the above flag is changed. */
static void
-set_stop_on_solib_events (char *args, int from_tty, struct cmd_list_element *c)
+set_stop_on_solib_events (const char *args,
+ int from_tty, struct cmd_list_element *c)
{
update_solib_breakpoints ();
}
/* Ensure that we have a process ptid. */
ptid_t process_ptid = pid_to_ptid (ptid_get_pid (child_ptid));
- target_terminal_ours_for_output ();
+ target_terminal::ours_for_output ();
fprintf_filtered (gdb_stdlog,
_("Detaching after %s from child %s.\n"),
has_vforked ? "vfork" : "fork",
else
{
child_inf->aspace = new_address_space ();
- child_inf->pspace = add_program_space (child_inf->aspace);
+ child_inf->pspace = new program_space (child_inf->aspace);
child_inf->removable = 1;
set_current_program_space (child_inf->pspace);
clone_program_space (child_inf->pspace, parent_inf->pspace);
if (info_verbose || debug_infrun)
{
- target_terminal_ours_for_output ();
+ target_terminal::ours_for_output ();
fprintf_filtered (gdb_stdlog,
_("Attaching after %s %s to child %s.\n"),
target_pid_to_str (parent_ptid),
/* Ensure that we have a process ptid. */
ptid_t process_ptid = pid_to_ptid (ptid_get_pid (child_ptid));
- target_terminal_ours_for_output ();
+ target_terminal::ours_for_output ();
fprintf_filtered (gdb_stdlog,
_("Detaching after fork from "
"child %s.\n"),
target_pid_to_str (process_ptid));
}
- target_detach (NULL, 0);
+ target_detach (parent_inf, 0);
}
/* Note that the detach above makes PARENT_INF dangling. */
else
{
child_inf->aspace = new_address_space ();
- child_inf->pspace = add_program_space (child_inf->aspace);
+ child_inf->pspace = new program_space (child_inf->aspace);
child_inf->removable = 1;
child_inf->symfile_flags = SYMFILE_NO_READ;
set_current_program_space (child_inf->pspace);
if (debug_infrun || info_verbose)
{
- target_terminal_ours_for_output ();
+ target_terminal::ours_for_output ();
if (exec)
{
}
}
- target_detach (NULL, 0);
+ target_detach (inf->vfork_parent, 0);
/* Put it back. */
inf->pspace = pspace;
{
/* We're staying attached to the parent, so, really give the
child a new address space. */
- inf->pspace = add_program_space (maybe_new_address_space ());
+ inf->pspace = new program_space (maybe_new_address_space ());
inf->aspace = inf->pspace->aspace;
inf->removable = 1;
set_current_program_space (inf->pspace);
program space resets breakpoints). */
inf->aspace = NULL;
inf->pspace = NULL;
- pspace = add_program_space (maybe_new_address_space ());
+ pspace = new program_space (maybe_new_address_space ());
set_current_program_space (pspace);
inf->removable = 1;
inf->symfile_flags = SYMFILE_NO_READ;
struct inferior *inf = current_inferior ();
int pid = ptid_get_pid (ptid);
ptid_t process_ptid;
- char *exec_file_host;
- struct cleanup *old_chain;
/* This is an exec event that we actually wish to pay attention to.
Refresh our symbol table to the newly exec'd program, remove any
breakpoint_init_inferior (inf_execd);
- exec_file_host = exec_file_find (exec_file_target, NULL);
- old_chain = make_cleanup (xfree, exec_file_host);
+ gdb::unique_xmalloc_ptr<char> exec_file_host
+ = exec_file_find (exec_file_target, NULL);
/* If we were unable to map the executable target pathname onto a host
pathname, tell the user that. Otherwise GDB's subsequent behavior
set_current_inferior (inf);
set_current_program_space (inf->pspace);
- add_thread (ptid);
}
else
{
Executable) main symbol file will only be computed by
solib_create_inferior_hook below. breakpoint_re_set would fail
to insert the breakpoints with the zero displacement. */
- try_open_exec_file (exec_file_host, inf, SYMFILE_DEFER_BP_RESET);
-
- do_cleanups (old_chain);
+ try_open_exec_file (exec_file_host.get (), inf, SYMFILE_DEFER_BP_RESET);
/* If the target can specify a description, read it. Must do this
after flipping to the new executable (because the target supplied
registers. */
target_find_description ();
+ /* The add_thread call ends up reading registers, so do it after updating the
+ target description. */
+ if (follow_exec_mode_string == follow_exec_mode_new)
+ add_thread (ptid);
+
solib_create_inferior_hook (0);
jit_inferior_created_hook ();
and address of the instruction the breakpoint is set at. We'll
skip inserting all breakpoints here. Valid iff ASPACE is
non-NULL. */
- struct address_space *aspace;
+ const address_space *aspace;
CORE_ADDR address;
/* The instruction being stepped over triggers a nonsteppable
because when we need the info later the thread may be running. */
static void
-set_step_over_info (struct address_space *aspace, CORE_ADDR address,
+set_step_over_info (const address_space *aspace, CORE_ADDR address,
int nonsteppable_watchpoint_p,
int thread)
{
same effect the instruction would have had if we had executed it
at its original address. We use this in step n3.
- - gdbarch_displaced_step_free_closure provides cleanup.
-
The gdbarch_displaced_step_copy_insn and
gdbarch_displaced_step_fixup functions must be written so that
copying an instruction with gdbarch_displaced_step_copy_insn,
displaced step operation on it. See displaced_step_prepare and
displaced_step_fixup for details. */
+/* Default destructor for displaced_step_closure. */
+
+displaced_step_closure::~displaced_step_closure () = default;
+
/* Per-inferior displaced stepping state. */
struct displaced_step_inferior_state
{
use_displaced_stepping (struct thread_info *tp)
{
struct regcache *regcache = get_thread_regcache (tp->ptid);
- struct gdbarch *gdbarch = get_regcache_arch (regcache);
+ struct gdbarch *gdbarch = regcache->arch ();
struct displaced_step_inferior_state *displaced_state;
displaced_state = get_displaced_stepping_state (ptid_get_pid (tp->ptid));
/* Indicate that there is no cleanup pending. */
displaced->step_ptid = null_ptid;
- xfree (displaced->step_closure);
+ delete displaced->step_closure;
displaced->step_closure = NULL;
}
static int
displaced_step_prepare_throw (ptid_t ptid)
{
- struct cleanup *old_cleanups, *ignore_cleanups;
+ struct cleanup *ignore_cleanups;
struct thread_info *tp = find_thread_ptid (ptid);
struct regcache *regcache = get_thread_regcache (ptid);
- struct gdbarch *gdbarch = get_regcache_arch (regcache);
- struct address_space *aspace = get_regcache_aspace (regcache);
+ struct gdbarch *gdbarch = regcache->arch ();
+ const address_space *aspace = regcache->aspace ();
CORE_ADDR original, copy;
ULONGEST len;
struct displaced_step_closure *closure;
displaced_step_clear (displaced);
- old_cleanups = save_inferior_ptid ();
+ scoped_restore save_inferior_ptid = make_scoped_restore (&inferior_ptid);
inferior_ptid = ptid;
original = regcache_read_pc (regcache);
"Stepping over breakpoint in-line instead.\n");
}
- do_cleanups (old_cleanups);
return -1;
}
/* The architecture doesn't know how or want to displaced step
this instruction or instruction sequence. Fallback to
stepping over the breakpoint in-line. */
- do_cleanups (old_cleanups);
+ do_cleanups (ignore_cleanups);
return -1;
}
discard_cleanups (ignore_cleanups);
- do_cleanups (old_cleanups);
-
if (debug_displaced)
fprintf_unfiltered (gdb_stdlog, "displaced: displaced pc to %s\n",
paddress (gdbarch, copy));
write_memory_ptid (ptid_t ptid, CORE_ADDR memaddr,
const gdb_byte *myaddr, int len)
{
- struct cleanup *ptid_cleanup = save_inferior_ptid ();
+ scoped_restore save_inferior_ptid = make_scoped_restore (&inferior_ptid);
inferior_ptid = ptid;
write_memory (memaddr, myaddr, len);
- do_cleanups (ptid_cleanup);
}
/* Restore the contents of the copy area for thread PTID. */
}
\f
-/* Resuming. */
-
-/* Things to clean up if we QUIT out of resume (). */
-static void
-resume_cleanups (void *ignore)
-{
- if (!ptid_equal (inferior_ptid, null_ptid))
- delete_single_step_breakpoints (inferior_thread ());
-
- normal_stop ();
-}
static const char schedlock_off[] = "off";
static const char schedlock_on[] = "on";
}
static void
-set_schedlock_func (char *args, int from_tty, struct cmd_list_element *c)
+set_schedlock_func (const char *args, int from_tty, struct cmd_list_element *c)
{
if (!target_can_lock_scheduler)
{
gdb_assert (!tp->stop_requested);
/* Install inferior's terminal modes. */
- target_terminal_inferior ();
+ target_terminal::inferior ();
/* Avoid confusing the next resume, if the next stop/resume
happens to apply to another thread. */
target_commit_resume ();
}
-/* Resume the inferior, but allow a QUIT. This is useful if the user
- wants to interrupt some lengthy single-stepping operation
- (for child processes, the SIGINT goes to the inferior, and so
- we get a SIGINT random_signal, but for remote debugging and perhaps
- other targets, that's not true).
+/* Resume the inferior. SIG is the signal to give the inferior
+ (GDB_SIGNAL_0 for none). Note: don't call this directly; instead
+ call 'resume', which handles exceptions. */
- SIG is the signal to give the inferior (zero for none). */
-void
-resume (enum gdb_signal sig)
+static void
+resume_1 (enum gdb_signal sig)
{
- struct cleanup *old_cleanups = make_cleanup (resume_cleanups, 0);
struct regcache *regcache = get_current_regcache ();
- struct gdbarch *gdbarch = get_regcache_arch (regcache);
+ struct gdbarch *gdbarch = regcache->arch ();
struct thread_info *tp = inferior_thread ();
CORE_ADDR pc = regcache_read_pc (regcache);
- struct address_space *aspace = get_regcache_aspace (regcache);
+ const address_space *aspace = regcache->aspace ();
ptid_t resume_ptid;
/* This represents the user's step vs continue request. When
deciding whether "set scheduler-locking step" applies, it's the
gdb_assert (!tp->stop_requested);
gdb_assert (!thread_is_in_step_over_chain (tp));
- QUIT;
-
if (tp->suspend.waitstatus_pending_p)
{
if (debug_infrun)
{
- char *statstr;
+ std::string statstr
+ = target_waitstatus_to_string (&tp->suspend.waitstatus);
- statstr = target_waitstatus_to_string (&tp->suspend.waitstatus);
fprintf_unfiltered (gdb_stdlog,
- "infrun: resume: thread %s has pending wait status %s "
- "(currently_stepping=%d).\n",
- target_pid_to_str (tp->ptid), statstr,
+ "infrun: resume: thread %s has pending wait "
+ "status %s (currently_stepping=%d).\n",
+ target_pid_to_str (tp->ptid), statstr.c_str (),
currently_stepping (tp));
- xfree (statstr);
}
tp->resumed = 1;
}
tp->suspend.stop_signal = GDB_SIGNAL_0;
- discard_cleanups (old_cleanups);
if (target_can_async_p ())
target_async (1);
resume_ptid = internal_resume_ptid (user_step);
do_target_resume (resume_ptid, 0, GDB_SIGNAL_0);
- discard_cleanups (old_cleanups);
tp->resumed = 1;
return;
}
"Got placed in step-over queue\n");
tp->control.trap_expected = 0;
- discard_cleanups (old_cleanups);
return;
}
else if (prepared < 0)
if (target_is_non_stop_p ())
stop_all_threads ();
- set_step_over_info (get_regcache_aspace (regcache),
+ set_step_over_info (regcache->aspace (),
regcache_read_pc (regcache), 0, tp->global_num);
step = maybe_software_singlestep (gdbarch, pc);
&& !step_over_info_valid_p ())
{
struct regcache *resume_regcache = get_thread_regcache (tp->ptid);
- struct gdbarch *resume_gdbarch = get_regcache_arch (resume_regcache);
+ struct gdbarch *resume_gdbarch = resume_regcache->arch ();
CORE_ADDR actual_pc = regcache_read_pc (resume_regcache);
gdb_byte buf[4];
do_target_resume (resume_ptid, step, sig);
tp->resumed = 1;
- discard_cleanups (old_cleanups);
}
+
+/* Resume the inferior. SIG is the signal to give the inferior
+ (GDB_SIGNAL_0 for none). This is a wrapper around 'resume_1' that
+ rolls back state on error. */
+
+void
+resume (gdb_signal sig)
+{
+ TRY
+ {
+ resume_1 (sig);
+ }
+ CATCH (ex, RETURN_MASK_ALL)
+ {
+ /* If resuming is being aborted for any reason, delete any
+ single-step breakpoint resume_1 may have created, to avoid
+ confusing the following resumption, and to avoid leaving
+ single-step breakpoints perturbing other threads, in case
+ we're running in non-stop mode. */
+ if (inferior_ptid != null_ptid)
+ delete_single_step_breakpoints (inferior_thread ());
+ throw_exception (ex);
+ }
+ END_CATCH
+}
+
\f
/* Proceeding. */
}
else if (debug_infrun)
{
- char *statstr;
+ std::string statstr
+ = target_waitstatus_to_string (&tp->suspend.waitstatus);
- statstr = target_waitstatus_to_string (&tp->suspend.waitstatus);
fprintf_unfiltered (gdb_stdlog,
"infrun: clear_proceed_status_thread: thread %s "
"has pending wait status %s "
"(currently_stepping=%d).\n",
- target_pid_to_str (tp->ptid), statstr,
+ target_pid_to_str (tp->ptid), statstr.c_str (),
currently_stepping (tp));
- xfree (statstr);
}
}
inferior->control.stop_soon = NO_STOP_QUIETLY;
}
- observer_notify_about_to_proceed ();
+ gdb::observers::about_to_proceed.notify ();
}
/* Returns true if TP is still stopped at a breakpoint that needs
{
struct regcache *regcache = get_thread_regcache (tp->ptid);
- if (breakpoint_here_p (get_regcache_aspace (regcache),
+ if (breakpoint_here_p (regcache->aspace (),
regcache_read_pc (regcache))
== ordinary_breakpoint_here)
return 1;
struct gdbarch *gdbarch;
struct thread_info *tp;
CORE_ADDR pc;
- struct address_space *aspace;
ptid_t resume_ptid;
struct execution_control_state ecss;
struct execution_control_state *ecs = &ecss;
struct cleanup *old_chain;
- struct cleanup *defer_resume_cleanup;
int started;
/* If we're stopped at a fork/vfork, follow the branch set by the
previous_inferior_ptid = inferior_ptid;
regcache = get_current_regcache ();
- gdbarch = get_regcache_arch (regcache);
- aspace = get_regcache_aspace (regcache);
+ gdbarch = regcache->arch ();
+ const address_space *aspace = regcache->aspace ();
+
pc = regcache_read_pc (regcache);
tp = inferior_thread ();
inferior. */
gdb_flush (gdb_stdout);
+ /* Since we've marked the inferior running, give it the terminal. A
+ QUIT/Ctrl-C from here on is forwarded to the target (which can
+ still detect attempts to unblock a stuck connection with repeated
+ Ctrl-C from within target_pass_ctrlc). */
+ target_terminal::inferior ();
+
/* In a multi-threaded task we may select another thread and
then continue or step.
until the target stops again. */
tp->prev_pc = regcache_read_pc (regcache);
- defer_resume_cleanup = make_cleanup_defer_target_commit_resume ();
+ {
+ scoped_restore save_defer_tc = make_scoped_defer_target_commit_resume ();
- started = start_step_over ();
+ started = start_step_over ();
- if (step_over_info_valid_p ())
- {
- /* Either this thread started a new in-line step over, or some
- other thread was already doing one. In either case, don't
- resume anything else until the step-over is finished. */
- }
- else if (started && !target_is_non_stop_p ())
- {
- /* A new displaced stepping sequence was started. In all-stop,
- we can't talk to the target anymore until it next stops. */
- }
- else if (!non_stop && target_is_non_stop_p ())
- {
- /* In all-stop, but the target is always in non-stop mode.
- Start all other threads that are implicitly resumed too. */
- ALL_NON_EXITED_THREADS (tp)
+ if (step_over_info_valid_p ())
+ {
+ /* Either this thread started a new in-line step over, or some
+ other thread was already doing one. In either case, don't
+ resume anything else until the step-over is finished. */
+ }
+ else if (started && !target_is_non_stop_p ())
+ {
+ /* A new displaced stepping sequence was started. In all-stop,
+ we can't talk to the target anymore until it next stops. */
+ }
+ else if (!non_stop && target_is_non_stop_p ())
+ {
+ /* In all-stop, but the target is always in non-stop mode.
+ Start all other threads that are implicitly resumed too. */
+ ALL_NON_EXITED_THREADS (tp)
{
/* Ignore threads of processes we're not resuming. */
if (!ptid_match (tp->ptid, resume_ptid))
if (!ecs->wait_some_more)
error (_("Command aborted."));
}
- }
- else if (!tp->resumed && !thread_is_in_step_over_chain (tp))
- {
- /* The thread wasn't started, and isn't queued, run it now. */
- reset_ecs (ecs, tp);
- switch_to_thread (tp->ptid);
- keep_going_pass_signal (ecs);
- if (!ecs->wait_some_more)
- error (_("Command aborted."));
- }
+ }
+ else if (!tp->resumed && !thread_is_in_step_over_chain (tp))
+ {
+ /* The thread wasn't started, and isn't queued, run it now. */
+ reset_ecs (ecs, tp);
+ switch_to_thread (tp->ptid);
+ keep_going_pass_signal (ecs);
+ if (!ecs->wait_some_more)
+ error (_("Command aborted."));
+ }
+ }
- do_cleanups (defer_resume_cleanup);
target_commit_resume ();
discard_cleanups (old_chain);
print_target_wait_results (ptid_t waiton_ptid, ptid_t result_ptid,
const struct target_waitstatus *ws)
{
- char *status_string = target_waitstatus_to_string (ws);
+ std::string status_string = target_waitstatus_to_string (ws);
string_file stb;
/* The text is split over several lines because it was getting too long.
ptid_get_lwp (result_ptid),
ptid_get_tid (result_ptid),
target_pid_to_str (result_ptid));
- stb.printf ("infrun: %s\n", status_string);
+ stb.printf ("infrun: %s\n", status_string.c_str ());
/* This uses %s in part to handle %'s in the text, but also to avoid
a gcc error: the format attribute requires a string literal. */
fprintf_unfiltered (gdb_stdlog, "%s", stb.c_str ());
-
- xfree (status_string);
}
/* Select a thread at random, out of those which are resumed and have
|| tp->suspend.stop_reason == TARGET_STOPPED_BY_HW_BREAKPOINT))
{
struct regcache *regcache = get_thread_regcache (tp->ptid);
- struct gdbarch *gdbarch = get_regcache_arch (regcache);
+ struct gdbarch *gdbarch = regcache->arch ();
CORE_ADDR pc;
int discard = 0;
paddress (gdbarch, pc));
discard = 1;
}
- else if (!breakpoint_inserted_here_p (get_regcache_aspace (regcache), pc))
+ else if (!breakpoint_inserted_here_p (regcache->aspace (), pc))
{
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog,
{
if (debug_infrun)
{
- char *statstr;
+ std::string statstr
+ = target_waitstatus_to_string (&tp->suspend.waitstatus);
- statstr = target_waitstatus_to_string (&tp->suspend.waitstatus);
fprintf_unfiltered (gdb_stdlog,
"infrun: Using pending wait status %s for %s.\n",
- statstr,
+ statstr.c_str (),
target_pid_to_str (tp->ptid));
- xfree (statstr);
}
/* Now that we've selected our final event LWP, un-adjust its PC
int decr_pc;
regcache = get_thread_regcache (tp->ptid);
- gdbarch = get_regcache_arch (regcache);
+ gdbarch = regcache->arch ();
decr_pc = gdbarch_decr_pc_after_break (gdbarch);
if (decr_pc != 0)
&& ui->async
&& !gdb_in_secondary_prompt_p (ui))
{
- target_terminal_ours ();
- observer_notify_sync_execution_done ();
+ target_terminal::ours ();
+ gdb::observers::sync_execution_done.notify ();
ui_register_input_event_handler (ui);
}
}
{
struct regcache *regcache;
struct gdbarch *gdbarch;
- struct address_space *aspace;
CORE_ADDR breakpoint_pc, decr_pc;
/* If we've hit a breakpoint, we'll normally be stopped with SIGTRAP. If
/* If this target does not decrement the PC after breakpoints, then
we have nothing to do. */
regcache = get_thread_regcache (thread->ptid);
- gdbarch = get_regcache_arch (regcache);
+ gdbarch = regcache->arch ();
decr_pc = gdbarch_decr_pc_after_break (gdbarch);
if (decr_pc == 0)
return;
- aspace = get_regcache_aspace (regcache);
+ const address_space *aspace = regcache->aspace ();
/* Find the location where (if we've hit a breakpoint) the
breakpoint would be. */
|| (target_is_non_stop_p ()
&& moribund_breakpoint_here_p (aspace, breakpoint_pc)))
{
- struct cleanup *old_cleanups = make_cleanup (null_cleanup, NULL);
+ gdb::optional<scoped_restore_tmpl<int>> restore_operation_disable;
if (record_full_is_used ())
- record_full_gdb_operation_disable_set ();
+ restore_operation_disable.emplace
+ (record_full_gdb_operation_disable_set ());
/* When using hardware single-step, a SIGTRAP is reported for both
a completed single-step and a software breakpoint. Need to
|| (thread->stepped_breakpoint
&& thread->prev_pc == breakpoint_pc))
regcache_write_pc (regcache, breakpoint_pc);
-
- do_cleanups (old_cleanups);
}
}
syscall_number);
ecs->event_thread->control.stop_bpstat
- = bpstat_stop_status (get_regcache_aspace (regcache),
+ = bpstat_stop_status (regcache->aspace (),
stop_pc, ecs->ptid, &ecs->ws);
if (handle_stop_requested (ecs))
static int \
thread_stopped_by_ ## REASON (ptid_t ptid) \
{ \
- struct cleanup *old_chain; \
- int res; \
- \
- old_chain = save_inferior_ptid (); \
+ scoped_restore save_inferior_ptid = make_scoped_restore (&inferior_ptid); \
inferior_ptid = ptid; \
\
- res = target_stopped_by_ ## REASON (); \
- \
- do_cleanups (old_chain); \
- \
- return res; \
+ return target_stopped_by_ ## REASON (); \
}
/* Generate thread_stopped_by_watchpoint. */
save_waitstatus (struct thread_info *tp, struct target_waitstatus *ws)
{
struct regcache *regcache;
- struct address_space *aspace;
if (debug_infrun)
{
- char *statstr;
+ std::string statstr = target_waitstatus_to_string (ws);
- statstr = target_waitstatus_to_string (ws);
fprintf_unfiltered (gdb_stdlog,
"infrun: saving status %s for %d.%ld.%ld\n",
- statstr,
+ statstr.c_str (),
ptid_get_pid (tp->ptid),
ptid_get_lwp (tp->ptid),
ptid_get_tid (tp->ptid));
- xfree (statstr);
}
/* Record for later. */
tp->suspend.waitstatus_pending_p = 1;
regcache = get_thread_regcache (tp->ptid);
- aspace = get_regcache_aspace (regcache);
+ const address_space *aspace = regcache->aspace ();
if (ws->kind == TARGET_WAITKIND_STOPPED
&& ws->value.sig == GDB_SIGNAL_TRAP)
if (debug_infrun)
{
- char *statstr;
+ std::string statstr = target_waitstatus_to_string (&ws);
- statstr = target_waitstatus_to_string (&ws);
fprintf_unfiltered (gdb_stdlog,
"infrun: target_wait %s, saving "
"status for %d.%ld.%ld\n",
- statstr,
+ statstr.c_str (),
ptid_get_pid (t->ptid),
ptid_get_lwp (t->ptid),
ptid_get_tid (t->ptid));
- xfree (statstr);
}
/* Record for later. */
{
struct regcache *regcache = get_thread_regcache (ecs->ptid);
- if (breakpoint_inserted_here_p (get_regcache_aspace (regcache),
+ if (breakpoint_inserted_here_p (regcache->aspace (),
regcache_read_pc (regcache)))
{
if (debug_infrun)
handle_solib_event ();
ecs->event_thread->control.stop_bpstat
- = bpstat_stop_status (get_regcache_aspace (regcache),
+ = bpstat_stop_status (regcache->aspace (),
stop_pc, ecs->ptid, &ecs->ws);
if (handle_stop_requested (ecs))
set_current_inferior (find_inferior_ptid (ecs->ptid));
set_current_program_space (current_inferior ()->pspace);
handle_vfork_child_exec_or_exit (0);
- target_terminal_ours (); /* Must do this before mourn anyway. */
+ target_terminal::ours (); /* Must do this before mourn anyway. */
/* Clearing any previous state of convenience variables. */
clear_exit_convenience_vars ();
/* Support the --return-child-result option. */
return_child_result_value = ecs->ws.value.integer;
- observer_notify_exited (ecs->ws.value.integer);
+ gdb::observers::exited.notify (ecs->ws.value.integer);
}
else
{
struct regcache *regcache = get_thread_regcache (ecs->ptid);
- struct gdbarch *gdbarch = get_regcache_arch (regcache);
+ struct gdbarch *gdbarch = regcache->arch ();
if (gdbarch_gdb_signal_to_target_p (gdbarch))
{
Cannot fill $_exitsignal with the correct signal number.\n"));
}
- observer_notify_signal_exited (ecs->ws.value.sig);
+ gdb::observers::signal_exited.notify (ecs->ws.value.sig);
}
gdb_flush (gdb_stdout);
/* Check whether the inferior is displaced stepping. */
{
struct regcache *regcache = get_thread_regcache (ecs->ptid);
- struct gdbarch *gdbarch = get_regcache_arch (regcache);
+ struct gdbarch *gdbarch = regcache->arch ();
/* If checking displaced stepping is supported, and thread
ecs->ptid is displaced stepping. */
stop_pc = regcache_read_pc (get_thread_regcache (ecs->ptid));
ecs->event_thread->control.stop_bpstat
- = bpstat_stop_status (get_regcache_aspace (get_current_regcache ()),
+ = bpstat_stop_status (get_current_regcache ()->aspace (),
stop_pc, ecs->ptid, &ecs->ws);
if (handle_stop_requested (ecs))
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_EXECD\n");
+ /* Note we can't read registers yet (the stop_pc), because we
+ don't yet know the inferior's post-exec architecture.
+ 'stop_pc' is explicitly read below instead. */
if (!ptid_equal (ecs->ptid, inferior_ptid))
- context_switch (ecs->ptid);
-
- stop_pc = regcache_read_pc (get_thread_regcache (ecs->ptid));
+ switch_to_thread_no_regs (ecs->event_thread);
/* Do whatever is necessary to the parent branch of the vfork. */
handle_vfork_child_exec_or_exit (1);
stop. */
follow_exec (inferior_ptid, ecs->ws.value.execd_pathname);
+ stop_pc = regcache_read_pc (get_thread_regcache (ecs->ptid));
+
/* In follow_exec we may have deleted the original thread and
created a new one. Make sure that the event thread is the
execd thread for that case (this is a nop otherwise). */
ecs->event_thread = inferior_thread ();
ecs->event_thread->control.stop_bpstat
- = bpstat_stop_status (get_regcache_aspace (get_current_regcache ()),
+ = bpstat_stop_status (get_current_regcache ()->aspace (),
stop_pc, ecs->ptid, &ecs->ws);
/* Note that this may be referenced from inside
if (handle_stop_requested (ecs))
return;
- observer_notify_no_history ();
+ gdb::observers::no_history.notify ();
stop_waiting (ecs);
return;
}
if (debug_infrun)
{
struct regcache *regcache = get_thread_regcache (ecs->ptid);
- struct gdbarch *gdbarch = get_regcache_arch (regcache);
- struct cleanup *old_chain = save_inferior_ptid ();
+ struct gdbarch *gdbarch = regcache->arch ();
+ scoped_restore save_inferior_ptid = make_scoped_restore (&inferior_ptid);
inferior_ptid = ecs->ptid;
fprintf_unfiltered (gdb_stdlog,
"infrun: (no data address available)\n");
}
-
- do_cleanups (old_chain);
}
/* This is originated from start_remote(), start_inferior() and
if (ecs->event_thread->suspend.stop_signal == GDB_SIGNAL_TRAP)
{
struct regcache *regcache;
- struct address_space *aspace;
CORE_ADDR pc;
regcache = get_thread_regcache (ecs->ptid);
- aspace = get_regcache_aspace (regcache);
+ const address_space *aspace = regcache->aspace ();
+
pc = regcache_read_pc (regcache);
/* However, before doing so, if this single-step breakpoint was
inline function call sites). */
if (ecs->event_thread->control.step_range_end != 1)
{
- struct address_space *aspace =
- get_regcache_aspace (get_thread_regcache (ecs->ptid));
+ const address_space *aspace =
+ get_thread_regcache (ecs->ptid)->aspace ();
/* skip_inline_frames is expensive, so we avoid it if we can
determine that the address is one where functions cannot have
/* See if there is a breakpoint/watchpoint/catchpoint/etc. that
handles this event. */
ecs->event_thread->control.stop_bpstat
- = bpstat_stop_status (get_regcache_aspace (get_current_regcache ()),
+ = bpstat_stop_status (get_current_regcache ()->aspace (),
stop_pc, ecs->ptid, &ecs->ws);
/* Following in case break condition called a
decr_pc = gdbarch_decr_pc_after_break (gdbarch);
if (decr_pc != 0)
{
- struct cleanup *old_cleanups = make_cleanup (null_cleanup, NULL);
+ gdb::optional<scoped_restore_tmpl<int>>
+ restore_operation_disable;
if (record_full_is_used ())
- record_full_gdb_operation_disable_set ();
+ restore_operation_disable.emplace
+ (record_full_gdb_operation_disable_set ());
regcache_write_pc (regcache, stop_pc + decr_pc);
-
- do_cleanups (old_cleanups);
}
}
else
if (signal_print[ecs->event_thread->suspend.stop_signal])
{
/* The signal table tells us to print about this signal. */
- target_terminal_ours_for_output ();
- observer_notify_signal_received (ecs->event_thread->suspend.stop_signal);
- target_terminal_inferior ();
+ target_terminal::ours_for_output ();
+ gdb::observers::signal_received.notify (ecs->event_thread->suspend.stop_signal);
+ target_terminal::inferior ();
}
/* Clear the signal if it should not be passed. */
{
/* Set up a step-resume breakpoint at the address
indicated by SKIP_SOLIB_RESOLVER. */
- struct symtab_and_line sr_sal;
-
- init_sal (&sr_sal);
+ symtab_and_line sr_sal;
sr_sal.pc = pc_after_resolver;
sr_sal.pspace = get_frame_program_space (frame);
if (real_stop_pc)
{
/* And put the step-breakpoint there and go until there. */
- struct symtab_and_line sr_sal;
-
- init_sal (&sr_sal); /* initialize to zeroes */
+ symtab_and_line sr_sal;
sr_sal.pc = real_stop_pc;
sr_sal.section = find_pc_overlay (sr_sal.pc);
sr_sal.pspace = get_frame_program_space (frame);
to the caller. */
if (ecs->stop_func_start != stop_pc && ecs->stop_func_start != 0)
{
- struct symtab_and_line sr_sal;
-
/* Normal function call return (static or dynamic). */
- init_sal (&sr_sal);
+ symtab_and_line sr_sal;
sr_sal.pc = ecs->stop_func_start;
sr_sal.pspace = get_frame_program_space (frame);
insert_step_resume_breakpoint_at_sal (gdbarch,
if (real_stop_pc != 0 && in_solib_dynsym_resolve_code (real_stop_pc))
{
- struct symtab_and_line sr_sal;
-
- init_sal (&sr_sal);
+ symtab_and_line sr_sal;
sr_sal.pc = ecs->stop_func_start;
sr_sal.pspace = get_frame_program_space (frame);
tmp_sal = find_pc_line (ecs->stop_func_start, 0);
if (tmp_sal.line != 0
&& !function_name_is_marked_for_skip (ecs->stop_func_name,
- &tmp_sal))
+ tmp_sal))
{
if (execution_direction == EXEC_REVERSE)
handle_step_into_function_backward (gdbarch, ecs);
{
/* Set a breakpoint at callee's start address.
From there we can step once and be back in the caller. */
- struct symtab_and_line sr_sal;
-
- init_sal (&sr_sal);
+ symtab_and_line sr_sal;
sr_sal.pc = ecs->stop_func_start;
sr_sal.pspace = get_frame_program_space (frame);
insert_step_resume_breakpoint_at_sal (gdbarch,
/* Stepped backward into the solib dynsym resolver.
Set a breakpoint at its start and continue, then
one more step will take us out. */
- struct symtab_and_line sr_sal;
-
- init_sal (&sr_sal);
+ symtab_and_line sr_sal;
sr_sal.pc = ecs->stop_func_start;
sr_sal.pspace = get_frame_program_space (frame);
insert_step_resume_breakpoint_at_sal (gdbarch,
ecs->event_thread->control.step_frame_id)
&& inline_skipped_frames (ecs->ptid))
{
- struct symtab_and_line call_sal;
-
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog,
"infrun: stepped into inlined function\n");
- find_frame_sal (get_current_frame (), &call_sal);
+ symtab_and_line call_sal = find_frame_sal (get_current_frame ());
if (ecs->event_thread->control.step_over_calls != STEP_OVER_ALL)
{
handle_step_into_function (struct gdbarch *gdbarch,
struct execution_control_state *ecs)
{
- struct compunit_symtab *cust;
- struct symtab_and_line stop_func_sal, sr_sal;
-
fill_in_stop_func (gdbarch, ecs);
- cust = find_pc_compunit_symtab (stop_pc);
+ compunit_symtab *cust = find_pc_compunit_symtab (stop_pc);
if (cust != NULL && compunit_language (cust) != language_asm)
ecs->stop_func_start
= gdbarch_skip_prologue_noexcept (gdbarch, ecs->stop_func_start);
- stop_func_sal = find_pc_line (ecs->stop_func_start, 0);
+ symtab_and_line stop_func_sal = find_pc_line (ecs->stop_func_start, 0);
/* Use the step_resume_break to step until the end of the prologue,
even if that involves jumps (as it seems to on the vax under
4.2). */
else
{
/* Put the step-breakpoint there and go until there. */
- init_sal (&sr_sal); /* initialize to zeroes */
+ symtab_and_line sr_sal;
sr_sal.pc = ecs->stop_func_start;
sr_sal.section = find_pc_overlay (ecs->stop_func_start);
sr_sal.pspace = get_frame_program_space (get_current_frame ());
paddress (gdbarch, sr_sal.pc));
inferior_thread ()->control.step_resume_breakpoint
- = set_momentary_breakpoint (gdbarch, sr_sal, sr_id, sr_type);
+ = set_momentary_breakpoint (gdbarch, sr_sal, sr_id, sr_type).release ();
}
void
static void
insert_hp_step_resume_breakpoint_at_frame (struct frame_info *return_frame)
{
- struct symtab_and_line sr_sal;
- struct gdbarch *gdbarch;
-
gdb_assert (return_frame != NULL);
- init_sal (&sr_sal); /* initialize to zeros */
- gdbarch = get_frame_arch (return_frame);
+ struct gdbarch *gdbarch = get_frame_arch (return_frame);
+
+ symtab_and_line sr_sal;
sr_sal.pc = gdbarch_addr_bits_remove (gdbarch, get_frame_pc (return_frame));
sr_sal.section = find_pc_overlay (sr_sal.pc);
sr_sal.pspace = get_frame_program_space (return_frame);
static void
insert_step_resume_breakpoint_at_caller (struct frame_info *next_frame)
{
- struct symtab_and_line sr_sal;
- struct gdbarch *gdbarch;
-
/* We shouldn't have gotten here if we don't know where the call site
is. */
gdb_assert (frame_id_p (frame_unwind_caller_id (next_frame)));
- init_sal (&sr_sal); /* initialize to zeros */
+ struct gdbarch *gdbarch = frame_unwind_caller_arch (next_frame);
- gdbarch = frame_unwind_caller_arch (next_frame);
+ symtab_and_line sr_sal;
sr_sal.pc = gdbarch_addr_bits_remove (gdbarch,
frame_unwind_caller_pc (next_frame));
sr_sal.section = find_pc_overlay (sr_sal.pc);
paddress (gdbarch, pc));
inferior_thread ()->control.exception_resume_breakpoint =
- set_momentary_breakpoint_at_pc (gdbarch, pc, bp_longjmp_resume);
+ set_momentary_breakpoint_at_pc (gdbarch, pc, bp_longjmp_resume).release ();
}
/* Insert an exception resume breakpoint. TP is the thread throwing
CORE_ADDR handler;
struct breakpoint *bp;
- vsym = lookup_symbol (SYMBOL_LINKAGE_NAME (sym), b, VAR_DOMAIN, NULL);
+ vsym = lookup_symbol_search_name (SYMBOL_SEARCH_NAME (sym),
+ b, VAR_DOMAIN);
value = read_var_value (vsym.symbol, vsym.block, frame);
/* If the value was optimized out, revert to the old behavior. */
if (! value_optimized_out (value))
(unsigned long) handler);
bp = set_momentary_breakpoint_at_pc (get_frame_arch (frame),
- handler, bp_exception_resume);
+ handler,
+ bp_exception_resume).release ();
/* set_momentary_breakpoint_at_pc invalidates FRAME. */
frame = NULL;
handler));
bp = set_momentary_breakpoint_at_pc (get_frame_arch (frame),
- handler, bp_exception_resume);
+ handler, bp_exception_resume).release ();
bp->thread = tp->global_num;
inferior_thread ()->control.exception_resume_breakpoint = bp;
}
CFA and the HANDLER. We ignore the CFA, extract the handler, and
set a breakpoint there. */
probe = find_probe_by_pc (get_frame_pc (frame));
- if (probe.probe)
+ if (probe.prob)
{
insert_exception_resume_from_probe (ecs->event_thread, &probe, frame);
return;
static void
keep_going_pass_signal (struct execution_control_state *ecs)
{
- /* Make sure normal_stop is called if we get a QUIT handled before
- reaching resume. */
- struct cleanup *old_cleanups = make_cleanup (resume_cleanups, 0);
-
gdb_assert (ptid_equal (ecs->event_thread->ptid, inferior_ptid));
gdb_assert (!ecs->event_thread->resumed);
non-signal event (e.g., a fork); or took a signal which we
are supposed to pass through to the inferior. Simply
continue. */
- discard_cleanups (old_cleanups);
resume (ecs->event_thread->suspend.stop_signal);
}
else if (step_over_info_valid_p ())
"resume of %s deferred\n",
target_pid_to_str (tp->ptid));
}
-
- discard_cleanups (old_cleanups);
}
else
{
if (remove_bp
&& (remove_wps || !use_displaced_stepping (ecs->event_thread)))
{
- set_step_over_info (get_regcache_aspace (regcache),
+ set_step_over_info (regcache->aspace (),
regcache_read_pc (regcache), remove_wps,
ecs->event_thread->global_num);
}
{
exception_print (gdb_stderr, e);
stop_waiting (ecs);
- discard_cleanups (old_cleanups);
+ clear_step_over_info ();
return;
}
END_CATCH
ecs->event_thread->control.trap_expected = (remove_bp || remove_wps);
- discard_cleanups (old_cleanups);
resume (ecs->event_thread->suspend.stop_signal);
}
handle_segmentation_fault (struct ui_out *uiout)
{
struct regcache *regcache = get_current_regcache ();
- struct gdbarch *gdbarch = get_regcache_arch (regcache);
+ struct gdbarch *gdbarch = regcache->arch ();
if (gdbarch_handle_segmentation_fault_p (gdbarch))
gdbarch_handle_segmentation_fault (gdbarch, uiout);
{
if (remove_breakpoints ())
{
- target_terminal_ours_for_output ();
+ target_terminal::ours_for_output ();
printf_filtered (_("Cannot remove breakpoints because "
"program is no longer writable.\nFurther "
"execution is probably impossible.\n"));
update_thread_list ();
if (last.kind == TARGET_WAITKIND_STOPPED && stopped_by_random_signal)
- observer_notify_signal_received (inferior_thread ()->suspend.stop_signal);
+ gdb::observers::signal_received.notify (inferior_thread ()->suspend.stop_signal);
/* As with the notification of thread events, we want to delay
notifying the user that we've switched thread context until
{
SWITCH_THRU_ALL_UIS ()
{
- target_terminal_ours_for_output ();
+ target_terminal::ours_for_output ();
printf_filtered (_("[Switching to %s]\n"),
target_pid_to_str (inferior_ptid));
annotate_thread_changed ();
SWITCH_THRU_ALL_UIS ()
if (current_ui->prompt_state == PROMPT_BLOCKED)
{
- target_terminal_ours_for_output ();
+ target_terminal::ours_for_output ();
printf_filtered (_("No unwaited-for children left.\n"));
}
}
struct cleanup *old_chain
= make_cleanup (release_stop_context_cleanup, saved_context);
- catch_errors (hook_stop_stub, stop_command,
- "Error while running hook_stop:\n", RETURN_MASK_ALL);
+ TRY
+ {
+ execute_cmd_pre_hook (stop_command);
+ }
+ CATCH (ex, RETURN_MASK_ALL)
+ {
+ exception_fprintf (gdb_stderr, ex,
+ "Error while running hook_stop:\n");
+ }
+ END_CATCH
/* If the stop hook resumes the target, then there's no point in
trying to notify about the previous stop; its context is
/* Notify observers about the stop. This is where the interpreters
print the stop event. */
if (!ptid_equal (inferior_ptid, null_ptid))
- observer_notify_normal_stop (inferior_thread ()->control.stop_bpstat,
+ gdb::observers::normal_stop.notify (inferior_thread ()->control.stop_bpstat,
stop_print_frame);
else
- observer_notify_normal_stop (NULL, stop_print_frame);
+ gdb::observers::normal_stop.notify (NULL, stop_print_frame);
annotate_stopped ();
return 0;
}
-
-static int
-hook_stop_stub (void *cmd)
-{
- execute_cmd_pre_hook ((struct cmd_list_element *) cmd);
- return (0);
-}
\f
int
signal_stop_state (int signo)
/* Specify how various signals in the inferior should be handled. */
static void
-handle_command (char *args, int from_tty)
+handle_command (const char *args, int from_tty)
{
- char **argv;
int digits, wordlen;
int sigfirst, signum, siglast;
enum gdb_signal oursig;
int allsigs;
int nsigs;
unsigned char *sigs;
- struct cleanup *old_chain;
if (args == NULL)
{
/* Break the command line up into args. */
- argv = gdb_buildargv (args);
- old_chain = make_cleanup_freeargv (argv);
+ gdb_argv built_argv (args);
/* Walk through the args, looking for signal oursigs, signal names, and
actions. Signal numbers and signal names may be interspersed with
actions, with the actions being performed for all signals cumulatively
specified. Signal ranges can be specified as <LOW>-<HIGH>. */
- while (*argv != NULL)
+ for (char *arg : built_argv)
{
- wordlen = strlen (*argv);
- for (digits = 0; isdigit ((*argv)[digits]); digits++)
+ wordlen = strlen (arg);
+ for (digits = 0; isdigit (arg[digits]); digits++)
{;
}
allsigs = 0;
sigfirst = siglast = -1;
- if (wordlen >= 1 && !strncmp (*argv, "all", wordlen))
+ if (wordlen >= 1 && !strncmp (arg, "all", wordlen))
{
/* Apply action to all signals except those used by the
debugger. Silently skip those. */
sigfirst = 0;
siglast = nsigs - 1;
}
- else if (wordlen >= 1 && !strncmp (*argv, "stop", wordlen))
+ else if (wordlen >= 1 && !strncmp (arg, "stop", wordlen))
{
SET_SIGS (nsigs, sigs, signal_stop);
SET_SIGS (nsigs, sigs, signal_print);
}
- else if (wordlen >= 1 && !strncmp (*argv, "ignore", wordlen))
+ else if (wordlen >= 1 && !strncmp (arg, "ignore", wordlen))
{
UNSET_SIGS (nsigs, sigs, signal_program);
}
- else if (wordlen >= 2 && !strncmp (*argv, "print", wordlen))
+ else if (wordlen >= 2 && !strncmp (arg, "print", wordlen))
{
SET_SIGS (nsigs, sigs, signal_print);
}
- else if (wordlen >= 2 && !strncmp (*argv, "pass", wordlen))
+ else if (wordlen >= 2 && !strncmp (arg, "pass", wordlen))
{
SET_SIGS (nsigs, sigs, signal_program);
}
- else if (wordlen >= 3 && !strncmp (*argv, "nostop", wordlen))
+ else if (wordlen >= 3 && !strncmp (arg, "nostop", wordlen))
{
UNSET_SIGS (nsigs, sigs, signal_stop);
}
- else if (wordlen >= 3 && !strncmp (*argv, "noignore", wordlen))
+ else if (wordlen >= 3 && !strncmp (arg, "noignore", wordlen))
{
SET_SIGS (nsigs, sigs, signal_program);
}
- else if (wordlen >= 4 && !strncmp (*argv, "noprint", wordlen))
+ else if (wordlen >= 4 && !strncmp (arg, "noprint", wordlen))
{
UNSET_SIGS (nsigs, sigs, signal_print);
UNSET_SIGS (nsigs, sigs, signal_stop);
}
- else if (wordlen >= 4 && !strncmp (*argv, "nopass", wordlen))
+ else if (wordlen >= 4 && !strncmp (arg, "nopass", wordlen))
{
UNSET_SIGS (nsigs, sigs, signal_program);
}
SIGHUP, SIGINT, SIGALRM, etc. will work right anyway. */
sigfirst = siglast = (int)
- gdb_signal_from_command (atoi (*argv));
- if ((*argv)[digits] == '-')
+ gdb_signal_from_command (atoi (arg));
+ if (arg[digits] == '-')
{
siglast = (int)
- gdb_signal_from_command (atoi ((*argv) + digits + 1));
+ gdb_signal_from_command (atoi (arg + digits + 1));
}
if (sigfirst > siglast)
{
}
else
{
- oursig = gdb_signal_from_name (*argv);
+ oursig = gdb_signal_from_name (arg);
if (oursig != GDB_SIGNAL_UNKNOWN)
{
sigfirst = siglast = (int) oursig;
else
{
/* Not a number and not a recognized flag word => complain. */
- error (_("Unrecognized or ambiguous flag word: \"%s\"."), *argv);
+ error (_("Unrecognized or ambiguous flag word: \"%s\"."), arg);
}
}
break;
}
}
-
- argv++;
}
for (signum = 0; signum < nsigs; signum++)
break;
}
-
- do_cleanups (old_chain);
}
/* Complete the "handle" command. */
targets, all signals should be in the signal tables). */
static void
-signals_info (char *signum_exp, int from_tty)
+info_signals_command (const char *signum_exp, int from_tty)
{
enum gdb_signal oursig;
/* Other fields: */
CORE_ADDR stop_pc;
- struct regcache *registers;
+ readonly_detached_regcache *registers;
/* Format of SIGINFO_DATA or NULL if it is not present. */
struct gdbarch *siginfo_gdbarch;
struct infcall_suspend_state *inf_state;
struct thread_info *tp = inferior_thread ();
struct regcache *regcache = get_current_regcache ();
- struct gdbarch *gdbarch = get_regcache_arch (regcache);
+ struct gdbarch *gdbarch = regcache->arch ();
gdb_byte *siginfo_data = NULL;
if (gdbarch_get_siginfo_type_p (gdbarch))
inf_state->stop_pc = stop_pc;
- inf_state->registers = regcache_dup (regcache);
+ inf_state->registers = new readonly_detached_regcache (*regcache);
return inf_state;
}
{
struct thread_info *tp = inferior_thread ();
struct regcache *regcache = get_current_regcache ();
- struct gdbarch *gdbarch = get_regcache_arch (regcache);
+ struct gdbarch *gdbarch = regcache->arch ();
tp->suspend = inf_state->thread_suspend;
(and perhaps other times). */
if (target_has_execution)
/* NB: The register write goes through to the target. */
- regcache_cpy (regcache, inf_state->registers);
+ regcache->restore (inf_state->registers);
discard_infcall_suspend_state (inf_state);
}
void
discard_infcall_suspend_state (struct infcall_suspend_state *inf_state)
{
- regcache_xfree (inf_state->registers);
+ delete inf_state->registers;
xfree (inf_state->siginfo_data);
xfree (inf_state);
}
-struct regcache *
+readonly_detached_regcache *
get_infcall_suspend_state_regcache (struct infcall_suspend_state *inf_state)
{
return inf_state->registers;
return inf_status;
}
-static int
-restore_selected_frame (void *args)
+static void
+restore_selected_frame (const frame_id &fid)
{
- struct frame_id *fid = (struct frame_id *) args;
- struct frame_info *frame;
-
- frame = frame_find_by_id (*fid);
+ frame_info *frame = frame_find_by_id (fid);
/* If inf_status->selected_frame_id is NULL, there was no previously
selected frame. */
if (frame == NULL)
{
warning (_("Unable to restore previously selected frame."));
- return 0;
+ return;
}
select_frame (frame);
-
- return (1);
}
/* Restore inferior session state to INF_STATUS. */
if (target_has_stack)
{
- /* The point of catch_errors is that if the stack is clobbered,
+ /* The point of the try/catch is that if the stack is clobbered,
walking the stack might encounter a garbage pointer and
error() trying to dereference it. */
- if (catch_errors
- (restore_selected_frame, &inf_status->selected_frame_id,
- "Unable to restore previously selected frame:\n",
- RETURN_MASK_ERROR) == 0)
- /* Error in restoring the selected frame. Select the innermost
- frame. */
- select_frame (get_current_frame ());
+ TRY
+ {
+ restore_selected_frame (inf_status->selected_frame_id);
+ }
+ CATCH (ex, RETURN_MASK_ERROR)
+ {
+ exception_fprintf (gdb_stderr, ex,
+ "Unable to restore previously selected frame:\n");
+ /* Error in restoring the selected frame. Select the
+ innermost frame. */
+ select_frame (get_current_frame ());
+ }
+ END_CATCH
}
xfree (inf_status);
xfree (inf_status);
}
\f
-/* restore_inferior_ptid() will be used by the cleanup machinery
- to restore the inferior_ptid value saved in a call to
- save_inferior_ptid(). */
-
-static void
-restore_inferior_ptid (void *arg)
-{
- ptid_t *saved_ptid_ptr = (ptid_t *) arg;
-
- inferior_ptid = *saved_ptid_ptr;
- xfree (arg);
-}
-
-/* Save the value of inferior_ptid so that it may be restored by a
- later call to do_cleanups(). Returns the struct cleanup pointer
- needed for later doing the cleanup. */
-
-struct cleanup *
-save_inferior_ptid (void)
-{
- ptid_t *saved_ptid_ptr = XNEW (ptid_t);
-
- *saved_ptid_ptr = inferior_ptid;
- return make_cleanup (restore_inferior_ptid, saved_ptid_ptr);
-}
-
/* See infrun.h. */
void
};
static void
-set_exec_direction_func (char *args, int from_tty,
+set_exec_direction_func (const char *args, int from_tty,
struct cmd_list_element *cmd)
{
if (target_can_execute_reverse)
infrun_async_inferior_event_token
= create_async_event_handler (infrun_async_inferior_event_handler, NULL);
- add_info ("signals", signals_info, _("\
+ add_info ("signals", info_signals_command, _("\
What debugger does when program gets various signals.\n\
Specify a signal as argument to print info on that signal only."));
add_info_alias ("handle", "signals", 0);
inferior_ptid = null_ptid;
target_last_wait_ptid = minus_one_ptid;
- observer_attach_thread_ptid_changed (infrun_thread_ptid_changed);
- observer_attach_thread_stop_requested (infrun_thread_stop_requested);
- observer_attach_thread_exit (infrun_thread_thread_exit);
- observer_attach_inferior_exit (infrun_inferior_exit);
+ gdb::observers::thread_ptid_changed.attach (infrun_thread_ptid_changed);
+ gdb::observers::thread_stop_requested.attach (infrun_thread_stop_requested);
+ gdb::observers::thread_exit.attach (infrun_thread_thread_exit);
+ gdb::observers::inferior_exit.attach (infrun_inferior_exit);
/* Explicitly create without lookup, since that tries to create a
value with a void typed value, and when we get here, gdbarch