#include "gdbsupport/selftest.h"
#include "scoped-mock-context.h"
#include "test-target.h"
-#include "debug.h"
+#include "gdbsupport/common-debug.h"
/* Prototypes for local functions */
static void follow_inferior_reset_breakpoints (void);
-static int currently_stepping (struct thread_info *tp);
+static bool currently_stepping (struct thread_info *tp);
static void insert_hp_step_resume_breakpoint_at_frame (struct frame_info *);
static void insert_longjmp_resume_breakpoint (struct gdbarch *, CORE_ADDR);
-static int maybe_software_singlestep (struct gdbarch *gdbarch, CORE_ADDR pc);
+static bool maybe_software_singlestep (struct gdbarch *gdbarch, CORE_ADDR pc);
static void resume (gdb_signal sig);
fprintf_filtered (file, _("Inferior debugging is %s.\n"), value);
}
+/* See infrun.h. */
+
+void
+displaced_debug_printf_1 (const char *func_name, const char *fmt, ...)
+{
+ va_list ap;
+ va_start (ap, fmt);
+ debug_prefixed_vprintf ("displaced", func_name, fmt, ap);
+ va_end (ap);
+}
/* Support for disabling address space randomization. */
set_non_stop (const char *args, int from_tty,
struct cmd_list_element *c)
{
- if (target_has_execution)
+ if (target_has_execution ())
{
non_stop_1 = non_stop;
error (_("Cannot change this setting while the inferior is running."));
set_observer_mode (const char *args, int from_tty,
struct cmd_list_element *c)
{
- if (target_has_execution)
+ if (target_has_execution ())
{
observer_mode_1 = observer_mode;
error (_("Cannot change this setting while the inferior is running."));
value);
}
-/* Nonzero after stop if current stack frame should be printed. */
+/* True after stop if current stack frame should be printed. */
-static int stop_print_frame;
+static bool stop_print_frame;
/* This is a cached copy of the target/ptid/waitstatus of the last
event returned by target_wait()/deprecated_target_wait_hook().
solib_create_inferior_hook (0);
- jit_inferior_created_hook ();
+ jit_inferior_created_hook (inf);
breakpoint_re_set ();
/* Returns true if step-over info is valid. */
-static int
+static bool
step_over_info_valid_p (void)
{
return (step_over_info.aspace != NULL
displaced_step_closure::~displaced_step_closure () = default;
-/* Get the displaced stepping state of process PID. */
+/* Get the displaced stepping state of inferior INF. */
static displaced_step_inferior_state *
get_displaced_stepping_state (inferior *inf)
return false;
}
-/* Return true if thread represented by PTID is doing a displaced
- step. */
+/* Return true if THREAD is doing a displaced step. */
-static int
+static bool
displaced_step_in_progress_thread (thread_info *thread)
{
gdb_assert (thread != NULL);
return get_displaced_stepping_state (thread->inf)->step_thread == thread;
}
-/* Return true if process PID has a thread doing a displaced step. */
+/* Return true if INF has a thread doing a displaced step. */
-static int
+static bool
displaced_step_in_progress (inferior *inf)
{
return get_displaced_stepping_state (inf)->step_thread != nullptr;
using displaced_step_reset_cleanup = FORWARD_SCOPE_EXIT (displaced_step_reset);
-/* Dump LEN bytes at BUF in hex to FILE, followed by a newline. */
-void
-displaced_step_dump_bytes (struct ui_file *file,
- const gdb_byte *buf,
- size_t len)
+/* See infrun.h. */
+
+std::string
+displaced_step_dump_bytes (const gdb_byte *buf, size_t len)
{
- int i;
+ std::string ret;
+
+ for (size_t i = 0; i < len; i++)
+ {
+ if (i == 0)
+ ret += string_printf ("%02x", buf[i]);
+ else
+ ret += string_printf (" %02x", buf[i]);
+ }
- for (i = 0; i < len; i++)
- fprintf_unfiltered (file, "%02x ", buf[i]);
- fputs_unfiltered ("\n", file);
+ return ret;
}
/* Prepare to single-step, using displaced stepping.
/* Already waiting for a displaced step to finish. Defer this
request and place in queue. */
- if (debug_displaced)
- fprintf_unfiltered (gdb_stdlog,
- "displaced: deferring step of %s\n",
- target_pid_to_str (tp->ptid).c_str ());
+ displaced_debug_printf ("deferring step of %s",
+ target_pid_to_str (tp->ptid).c_str ());
thread_step_over_chain_enqueue (tp);
return 0;
}
else
- {
- if (debug_displaced)
- fprintf_unfiltered (gdb_stdlog,
- "displaced: stepping %s now\n",
+ displaced_debug_printf ("stepping %s now",
target_pid_to_str (tp->ptid).c_str ());
- }
displaced_step_reset (displaced);
in the scratch pad range (after initial startup) anyway, but
the former is unacceptable. Simply punt and fallback to
stepping over this breakpoint in-line. */
- if (debug_displaced)
- {
- fprintf_unfiltered (gdb_stdlog,
- "displaced: breakpoint set in scratch pad. "
- "Stepping over breakpoint in-line instead.\n");
- }
+ displaced_debug_printf ("breakpoint set in scratch pad. "
+ "Stepping over breakpoint in-line instead.");
return -1;
}
_("Error accessing memory address %s (%s) for "
"displaced-stepping scratch space."),
paddress (gdbarch, copy), safe_strerror (status));
- if (debug_displaced)
- {
- fprintf_unfiltered (gdb_stdlog, "displaced: saved %s: ",
- paddress (gdbarch, copy));
- displaced_step_dump_bytes (gdb_stdlog,
- displaced->step_saved_copy.data (),
- len);
- };
+
+ displaced_debug_printf ("saved %s: %s",
+ paddress (gdbarch, copy),
+ displaced_step_dump_bytes
+ (displaced->step_saved_copy.data (), len).c_str ());
displaced->step_closure
= gdbarch_displaced_step_copy_insn (gdbarch, original, copy, regcache);
cleanup.release ();
}
- if (debug_displaced)
- fprintf_unfiltered (gdb_stdlog, "displaced: displaced pc to %s\n",
- paddress (gdbarch, copy));
+ displaced_debug_printf ("displaced pc to %s", paddress (gdbarch, copy));
return 1;
}
write_memory_ptid (ptid, displaced->step_copy,
displaced->step_saved_copy.data (), len);
- if (debug_displaced)
- fprintf_unfiltered (gdb_stdlog, "displaced: restored %s %s\n",
- target_pid_to_str (ptid).c_str (),
- paddress (displaced->step_gdbarch,
- displaced->step_copy));
+
+ displaced_debug_printf ("restored %s %s",
+ target_pid_to_str (ptid).c_str (),
+ paddress (displaced->step_gdbarch,
+ displaced->step_copy));
}
/* If we displaced stepped an instruction successfully, adjust
if (signal == GDB_SIGNAL_TRAP
&& !(target_stopped_by_watchpoint ()
&& (gdbarch_have_nonsteppable_watchpoint (displaced->step_gdbarch)
- || target_have_steppable_watchpoint)))
+ || target_have_steppable_watchpoint ())))
{
/* Fix up the resulting state. */
gdbarch_displaced_step_fixup (displaced->step_gdbarch,
static void keep_going_pass_signal (struct execution_control_state *ecs);
static void prepare_to_wait (struct execution_control_state *ecs);
-static int keep_going_stepped_thread (struct thread_info *tp);
+static bool keep_going_stepped_thread (struct thread_info *tp);
static step_over_what thread_still_needs_step_over (struct thread_info *tp);
/* Are there any pending step-over requests? If so, run all we can
now and return true. Otherwise, return false. */
-static int
+static bool
start_step_over (void)
{
struct thread_info *tp, *next;
/* Don't start a new step-over if we already have an in-line
step-over operation ongoing. */
if (step_over_info_valid_p ())
- return 0;
+ return false;
for (tp = step_over_queue_head; tp != NULL; tp = next)
{
in-line. If we need to start a new in-line step-over, let
any pending displaced steps finish first. */
if (must_be_in_line && displaced_step_in_progress_any_inferior ())
- return 0;
+ return false;
thread_step_over_chain_remove (tp);
if (step_over_info_valid_p ())
{
gdb_assert (tp->control.trap_expected);
- return 1;
+ return true;
}
if (!target_is_non_stop_p ())
/* With remote targets (at least), in all-stop, we can't
issue any further remote commands until the program stops
again. */
- return 1;
+ return true;
}
/* Either the thread no longer needed a step-over, or a new
displaced step on a thread of other process. */
}
- return 0;
+ return false;
}
/* Update global variables holding ptids to hold NEW_PTID if they were
static void
set_schedlock_func (const char *args, int from_tty, struct cmd_list_element *c)
{
- if (!target_can_lock_scheduler)
+ if (!target_can_lock_scheduler ())
{
scheduler_mode = schedlock_off;
error (_("Target '%s' cannot support this command."), target_shortname);
bool sched_multi = false;
/* Try to setup for software single stepping over the specified location.
- Return 1 if target_resume() should use hardware single step.
+ Return true if target_resume() should use hardware single step.
GDBARCH the current gdbarch.
PC the location to step over. */
-static int
+static bool
maybe_software_singlestep (struct gdbarch *gdbarch, CORE_ADDR pc)
{
- int hw_step = 1;
+ bool hw_step = true;
if (execution_direction == EXEC_FORWARD
&& gdbarch_software_single_step_p (gdbarch))
bookkeeping. */
static void
-do_target_resume (ptid_t resume_ptid, int step, enum gdb_signal sig)
+do_target_resume (ptid_t resume_ptid, bool step, enum gdb_signal sig)
{
struct thread_info *tp = inferior_thread ();
This can decay from a step to a continue, if e.g., we need to
implement single-stepping with breakpoints (software
single-step). */
- int step;
+ bool step;
gdb_assert (!tp->stop_requested);
gdb_assert (!thread_is_in_step_over_chain (tp));
the parent, and tell it to `keep_going', which automatically
re-sets it stepping. */
infrun_debug_printf ("resume : clear step");
- step = 0;
+ step = false;
}
CORE_ADDR pc = regcache_read_pc (regcache);
insert_breakpoints ();
resume_ptid = internal_resume_ptid (user_step);
- do_target_resume (resume_ptid, 0, GDB_SIGNAL_0);
+ do_target_resume (resume_ptid, false, GDB_SIGNAL_0);
tp->resumed = true;
return;
}
}
else if (prepared > 0)
{
- struct displaced_step_inferior_state *displaced;
-
/* Update pc to reflect the new address from which we will
execute instructions due to displaced stepping. */
pc = regcache_read_pc (get_thread_regcache (tp));
- displaced = get_displaced_stepping_state (tp->inf);
- step = gdbarch_displaced_step_hw_singlestep
- (gdbarch, displaced->step_closure.get ());
+ step = gdbarch_displaced_step_hw_singlestep (gdbarch);
}
}
executing it normally. But if this one cannot, just
continue and we will hit it anyway. */
if (gdbarch_cannot_step_breakpoint (gdbarch))
- step = 0;
+ step = false;
}
if (debug_displaced
CORE_ADDR actual_pc = regcache_read_pc (resume_regcache);
gdb_byte buf[4];
- fprintf_unfiltered (gdb_stdlog, "displaced: run %s: ",
- paddress (resume_gdbarch, actual_pc));
read_memory (actual_pc, buf, sizeof (buf));
- displaced_step_dump_bytes (gdb_stdlog, buf, sizeof (buf));
+ displaced_debug_printf ("run %s: %s",
+ paddress (resume_gdbarch, actual_pc),
+ displaced_step_dump_bytes
+ (buf, sizeof (buf)).c_str ());
}
if (tp->control.may_range_step)
stepping-over in order to make progress. If the breakpoint is gone
meanwhile, we can skip the whole step-over dance. */
-static int
+static bool
thread_still_needs_step_over_bp (struct thread_info *tp)
{
if (tp->stepping_over_breakpoint)
if (breakpoint_here_p (regcache->aspace (),
regcache_read_pc (regcache))
== ordinary_breakpoint_here)
- return 1;
+ return true;
tp->stepping_over_breakpoint = 0;
}
- return 0;
+ return false;
}
/* Check whether thread TP still needs to start a step-over in order
what |= STEP_OVER_BREAKPOINT;
if (tp->stepping_over_watchpoint
- && !target_have_steppable_watchpoint)
+ && !target_have_steppable_watchpoint ())
what |= STEP_OVER_WATCHPOINT;
return what;
/* Returns true if scheduler locking applies. STEP indicates whether
we're about to do a step/next-like command to a thread. */
-static int
+static bool
schedlock_applies (struct thread_info *tp)
{
return (scheduler_mode == schedlock_on
{
switch_to_inferior_no_thread (inf);
- if (!target_has_execution)
+ if (!target_has_execution ())
continue;
process_stratum_target *proc_target
CORE_ADDR pc;
struct execution_control_state ecss;
struct execution_control_state *ecs = &ecss;
- int started;
+ bool started;
/* If we're stopped at a fork/vfork, follow the branch set by the
"set follow-fork-mode" command; otherwise, we'll just proceed
/* Now that the inferior has stopped, do any bookkeeping like
loading shared libraries. We want to do this before normal_stop,
so that the displayed frame is up to date. */
- post_create_inferior (current_top_target (), from_tty);
+ post_create_inferior (from_tty);
normal_stop ();
}
static void stop_waiting (struct execution_control_state *ecs);
static void keep_going (struct execution_control_state *ecs);
static void process_event_stop_test (struct execution_control_state *ecs);
-static int switch_back_to_stepped_thread (struct execution_control_state *ecs);
+static bool switch_back_to_stepped_thread (struct execution_control_state *ecs);
/* This function is attached as a "thread_stop_requested" observer.
Cleanup local state that assumed the PTID was to be resumed, and
static void
for_each_just_stopped_thread (for_each_just_stopped_thread_callback_func func)
{
- if (!target_has_execution || inferior_ptid == null_ptid)
+ if (!target_has_execution () || inferior_ptid == null_ptid)
return;
if (target_is_non_stop_p ())
static ptid_t
do_target_wait_1 (inferior *inf, ptid_t ptid,
- target_waitstatus *status, int options)
+ target_waitstatus *status, target_wait_flags options)
{
ptid_t event_ptid;
struct thread_info *tp;
/* But if we don't find one, we'll have to wait. */
+ /* We can't ask a non-async target to do a non-blocking wait, so this will be
+ a blocking wait. */
+ if (!target_can_async_p ())
+ options &= ~TARGET_WNOHANG;
+
if (deprecated_target_wait_hook)
event_ptid = deprecated_target_wait_hook (ptid, status, options);
else
more events. Polls for events from all inferiors/targets. */
static bool
-do_target_wait (ptid_t wait_ptid, execution_control_state *ecs, int options)
+do_target_wait (ptid_t wait_ptid, execution_control_state *ecs,
+ target_wait_flags options)
{
int num_inferiors = 0;
int random_selector;
the main console. */
scoped_restore save_ui = make_scoped_restore (¤t_ui, main_ui);
+ /* Temporarily disable pagination. Otherwise, the user would be
+ given an option to press 'q' to quit, which would cause an early
+ exit and could leave GDB in a half-baked state. */
+ scoped_restore save_pagination
+ = make_scoped_restore (&pagination_enabled, false);
+
/* End up with readline processing input, if necessary. */
{
SCOPE_EXIT { reinstall_readline_callback_handler_cleanup (); };
}
}
-static int
+static bool
stepped_in_from (struct frame_info *frame, struct frame_id step_frame_id)
{
for (frame = get_prev_frame (frame);
frame = get_prev_frame (frame))
{
if (frame_id_eq (get_frame_id (frame), step_frame_id))
- return 1;
+ return true;
+
if (get_frame_type (frame) != INLINE_FRAME)
break;
}
- return 0;
+ return false;
}
/* Look for an inline frame that is marked for skip.
}
/* Auxiliary function that handles syscall entry/return events.
- It returns 1 if the inferior should keep going (and GDB
- should ignore the event), or 0 if the event deserves to be
+ It returns true if the inferior should keep going (and GDB
+ should ignore the event), or false if the event deserves to be
processed. */
-static int
+static bool
handle_syscall_event (struct execution_control_state *ecs)
{
struct regcache *regcache;
ecs->event_thread, &ecs->ws);
if (handle_stop_requested (ecs))
- return 0;
+ return false;
if (bpstat_causes_stop (ecs->event_thread->control.stop_bpstat))
{
/* Catchpoint hit. */
- return 0;
+ return false;
}
}
if (handle_stop_requested (ecs))
- return 0;
+ return false;
/* If no catchpoint triggered for this, then keep going. */
keep_going (ecs);
- return 1;
+
+ return true;
}
/* Lazily fill in the execution_control_state's stop_func_* fields. */
/* Handle a TARGET_WAITKIND_NO_RESUMED event. */
-static int
+static bool
handle_no_resumed (struct execution_control_state *ecs)
{
if (target_can_async_p ())
{
- int any_sync = 0;
+ bool any_sync = false;
for (ui *ui : all_uis ())
{
if (ui->prompt_state == PROMPT_BLOCKED)
{
- any_sync = 1;
+ any_sync = true;
break;
}
}
infrun_debug_printf ("TARGET_WAITKIND_NO_RESUMED (ignoring: bg)");
prepare_to_wait (ecs);
- return 1;
+ return true;
}
}
{
switch_to_inferior_no_thread (curr_inf);
prepare_to_wait (ecs);
- return 1;
+ return true;
}
/* Go ahead and report the event. */
- return 0;
+ return false;
}
/* Given an execution control state that has been freshly filled in by
{
/* No unwaited-for children left. IOW, all resumed children
have exited. */
- stop_print_frame = 0;
+ stop_print_frame = false;
stop_waiting (ecs);
return;
}
{
/* Make sure we print "Stopped due to solib-event" in
normal_stop. */
- stop_print_frame = 1;
+ stop_print_frame = true;
stop_waiting (ecs);
return;
gdb_flush (gdb_stdout);
target_mourn_inferior (inferior_ptid);
- stop_print_frame = 0;
+ stop_print_frame = false;
stop_waiting (ecs);
return;
/* Read PC value of parent process. */
parent_pc = regcache_read_pc (regcache);
- if (debug_displaced)
- fprintf_unfiltered (gdb_stdlog,
- "displaced: write child pc from %s to %s\n",
- paddress (gdbarch,
- regcache_read_pc (child_regcache)),
- paddress (gdbarch, parent_pc));
+ displaced_debug_printf ("write child pc from %s to %s",
+ paddress (gdbarch,
+ regcache_read_pc (child_regcache)),
+ paddress (gdbarch, parent_pc));
regcache_write_pc (child_regcache, parent_pc);
}
static int
finish_step_over (struct execution_control_state *ecs)
{
- int had_step_over_info;
-
displaced_step_fixup (ecs->event_thread,
ecs->event_thread->suspend.stop_signal);
- had_step_over_info = step_over_info_valid_p ();
+ bool had_step_over_info = step_over_info_valid_p ();
if (had_step_over_info)
{
{
context_switch (ecs);
infrun_debug_printf ("quietly stopped");
- stop_print_frame = 1;
+ stop_print_frame = true;
stop_waiting (ecs);
return;
}
|| ecs->event_thread->suspend.stop_signal == GDB_SIGNAL_TRAP
|| ecs->event_thread->suspend.stop_signal == GDB_SIGNAL_0))
{
- stop_print_frame = 1;
+ stop_print_frame = true;
stop_waiting (ecs);
ecs->event_thread->suspend.stop_signal = GDB_SIGNAL_0;
return;
/* If necessary, step over this watchpoint. We'll be back to display
it in a moment. */
if (stopped_by_watchpoint
- && (target_have_steppable_watchpoint
+ && (target_have_steppable_watchpoint ()
|| gdbarch_have_nonsteppable_watchpoint (gdbarch)))
{
/* At this point, we are stopped at an instruction which has
ecs->event_thread->stepping_over_watchpoint = 0;
bpstat_clear (&ecs->event_thread->control.stop_bpstat);
ecs->event_thread->control.stop_step = 0;
- stop_print_frame = 1;
+ stop_print_frame = true;
stopped_by_random_signal = 0;
bpstat stop_chain = NULL;
/* Following in case break condition called a
function. */
- stop_print_frame = 1;
+ stop_print_frame = true;
/* This is where we handle "moribund" watchpoints. Unlike
software breakpoints traps, hardware watchpoint traps are
case BPSTAT_WHAT_STOP_NOISY:
infrun_debug_printf ("BPSTAT_WHAT_STOP_NOISY");
- stop_print_frame = 1;
+ stop_print_frame = true;
/* Assume the thread stopped for a breakpoint. We'll still check
whether a/the breakpoint is there when the thread is next
case BPSTAT_WHAT_STOP_SILENT:
infrun_debug_printf ("BPSTAT_WHAT_STOP_SILENT");
- stop_print_frame = 0;
+ stop_print_frame = false;
/* Assume the thread stopped for a breakpoint. We'll still check
whether a/the breakpoint is there when the thread is next
thread. Returns true we set the inferior running, false if we left
it stopped (and the event needs further processing). */
-static int
+static bool
switch_back_to_stepped_thread (struct execution_control_state *ecs)
{
if (!target_is_non_stop_p ())
already. Let the caller check whether the step is finished,
etc., before deciding to move it past a breakpoint. */
if (ecs->event_thread->control.step_range_end != 0)
- return 0;
+ return false;
/* Check if the current thread is blocked on an incomplete
step-over, interrupted by a random signal. */
("need to finish step-over of [%s]",
target_pid_to_str (ecs->event_thread->ptid).c_str ());
keep_going (ecs);
- return 1;
+ return true;
}
/* Check if the current thread is blocked by a single-step
infrun_debug_printf ("need to step [%s] over single-step breakpoint",
target_pid_to_str (ecs->ptid).c_str ());
keep_going (ecs);
- return 1;
+ return true;
}
/* If this thread needs yet another step-over (e.g., stepping
("thread [%s] still needs step-over",
target_pid_to_str (ecs->event_thread->ptid).c_str ());
keep_going (ecs);
- return 1;
+ return true;
}
/* If scheduler locking applies even if not stepping, there's no
event thread is stepping, then it must be that scheduler
locking is not in effect. */
if (schedlock_applies (ecs->event_thread))
- return 0;
+ return false;
/* Otherwise, we no longer expect a trap in the current thread.
Clear the trap_expected flag before switching back -- this is
if (start_step_over ())
{
prepare_to_wait (ecs);
- return 1;
+ return true;
}
/* Look for the stepping/nexting thread. */
if (keep_going_stepped_thread (stepping_thread))
{
prepare_to_wait (ecs);
- return 1;
+ return true;
}
}
switch_to_thread (ecs->event_thread);
}
- return 0;
+ return false;
}
/* Set a previously stepped thread back to stepping. Returns true on
success, false if the resume is not possible (e.g., the thread
vanished). */
-static int
+static bool
keep_going_stepped_thread (struct thread_info *tp)
{
struct frame_info *frame;
"vanished");
delete_thread (tp);
- return 0;
+ return false;
}
infrun_debug_printf ("resuming previously stepped thread");
tp->resumed = true;
resume_ptid = internal_resume_ptid (tp->control.stepping_command);
- do_target_resume (resume_ptid, 0, GDB_SIGNAL_0);
+ do_target_resume (resume_ptid, false, GDB_SIGNAL_0);
}
else
{
keep_going_pass_signal (ecs);
}
- return 1;
+
+ return true;
}
/* Is thread TP in the middle of (software or hardware)
single-stepping? (Note the result of this function must never be
passed directly as target_resume's STEP parameter.) */
-static int
+static bool
currently_stepping (struct thread_info *tp)
{
return ((tp->control.step_range_end
void
maybe_remove_breakpoints (void)
{
- if (!breakpoints_should_be_inserted_now () && target_has_execution)
+ if (!breakpoints_should_be_inserted_now () && target_has_execution ())
{
if (remove_breakpoints ())
{
informing of a stop. */
if (!non_stop
&& previous_inferior_ptid != inferior_ptid
- && target_has_execution
+ && target_has_execution ()
&& last.kind != TARGET_WAITKIND_SIGNALLED
&& last.kind != TARGET_WAITKIND_EXITED
&& last.kind != TARGET_WAITKIND_NO_RESUMED)
annotate_stopped ();
- if (target_has_execution)
+ if (target_has_execution ())
{
if (last.kind != TARGET_WAITKIND_SIGNALLED
&& last.kind != TARGET_WAITKIND_EXITED
siginfo_make_value (struct gdbarch *gdbarch, struct internalvar *var,
void *ignore)
{
- if (target_has_stack
+ if (target_has_stack ()
&& inferior_ptid != null_ptid
&& gdbarch_get_siginfo_type_p (gdbarch))
{
/* The inferior can be gone if the user types "print exit(0)"
(and perhaps other times). */
- if (target_has_execution)
+ if (target_has_execution ())
/* NB: The register write goes through to the target. */
regcache->restore (registers ());
}
enum stop_stack_kind stop_stack_dummy = STOP_NONE;
int stopped_by_random_signal = 0;
- /* ID if the selected frame when the inferior function call was made. */
+ /* ID and level of the selected frame when the inferior function
+ call was made. */
struct frame_id selected_frame_id {};
+ int selected_frame_level = -1;
};
/* Save all of the information associated with the inferior<==>gdb
inf_status->stop_stack_dummy = stop_stack_dummy;
inf_status->stopped_by_random_signal = stopped_by_random_signal;
- inf_status->selected_frame_id = get_frame_id (get_selected_frame (NULL));
+ save_selected_frame (&inf_status->selected_frame_id,
+ &inf_status->selected_frame_level);
return inf_status;
}
-static void
-restore_selected_frame (const frame_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;
- }
-
- select_frame (frame);
-}
-
/* Restore inferior session state to INF_STATUS. */
void
stop_stack_dummy = inf_status->stop_stack_dummy;
stopped_by_random_signal = inf_status->stopped_by_random_signal;
- if (target_has_stack)
+ if (target_has_stack ())
{
- /* 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. */
- try
- {
- restore_selected_frame (inf_status->selected_frame_id);
- }
- catch (const gdb_exception_error &ex)
- {
- 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 ());
- }
+ restore_selected_frame (inf_status->selected_frame_id,
+ inf_status->selected_frame_level);
}
delete inf_status;
set_exec_direction_func (const char *args, int from_tty,
struct cmd_list_element *cmd)
{
- if (target_can_execute_reverse)
+ if (target_can_execute_reverse ())
{
if (!strcmp (exec_direction, exec_forward))
execution_direction = EXEC_FORWARD;
/* Register extra event sources in the event loop. */
infrun_async_inferior_event_token
- = create_async_event_handler (infrun_async_inferior_event_handler, NULL);
+ = create_async_event_handler (infrun_async_inferior_event_handler, NULL,
+ "infrun");
add_info ("signals", info_signals_command, _("\
What debugger does when program gets various signals.\n\