#include "gdbsupport/gdb_select.h"
#include <unordered_map>
#include "async-event.h"
+#include "gdbsupport/selftest.h"
+#include "scoped-mock-context.h"
+#include "test-target.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);
/* See infrun.h. */
+void
+infrun_debug_printf_1 (const char *func_name, const char *fmt, ...)
+{
+ va_list ap;
+ va_start (ap, fmt);
+ debug_prefixed_vprintf ("infrun", func_name, fmt, ap);
+ va_end (ap);
+}
+
+/* See infrun.h. */
+
void
infrun_async (int enable)
{
{
infrun_is_async = enable;
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog,
- "infrun: infrun_async(%d)\n",
- enable);
+ infrun_debug_printf ("enable=%d", enable);
if (enable)
mark_async_event_handler (infrun_async_inferior_event_token);
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().
&& !thread->stop_requested
&& thread->suspend.stop_signal == GDB_SIGNAL_0)
{
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog,
- "infrun: resuming vfork parent thread %s\n",
- target_pid_to_str (thread->ptid).c_str ());
+ infrun_debug_printf ("resuming vfork parent thread %s",
+ target_pid_to_str (thread->ptid).c_str ());
switch_to_thread (thread);
clear_proceed_status (0);
free now. */
scoped_restore_current_thread restore_thread;
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog,
- "infrun: resuming vfork parent process %d\n",
- resume_parent);
+ infrun_debug_printf ("resuming vfork parent process %d",
+ resume_parent);
iterate_over_threads (proceed_after_vfork_done, &resume_parent);
}
solib_create_inferior_hook (0);
- jit_inferior_created_hook ();
+ jit_inferior_created_hook (inf);
breakpoint_re_set ();
static void
clear_step_over_info (void)
{
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog,
- "infrun: clear_step_over_info\n");
+ infrun_debug_printf ("clearing step over info");
step_over_info.aspace = NULL;
step_over_info.address = 0;
step_over_info.nonsteppable_watchpoint_p = 0;
/* 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;
}
&& ex.error != NOT_SUPPORTED_ERROR)
throw;
- if (debug_infrun)
- {
- fprintf_unfiltered (gdb_stdlog,
- "infrun: disabling displaced stepping: %s\n",
- ex.what ());
- }
+ infrun_debug_printf ("caught exception, disabling displaced stepping: %s",
+ ex.what ());
/* Be verbose if "set displaced-stepping" is "on", silent if
"auto". */
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_queue_head == NULL)
- {
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog,
- "infrun: step-over queue now empty\n");
- }
+ infrun_debug_printf ("step-over queue now empty");
if (tp->control.trap_expected
|| tp->resumed
tp->executing);
}
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog,
- "infrun: resuming [%s] for step-over\n",
- target_pid_to_str (tp->ptid).c_str ());
+ infrun_debug_printf ("resuming [%s] for step-over",
+ target_pid_to_str (tp->ptid).c_str ());
/* keep_going_pass_signal skips the step-over if the breakpoint
is no longer inserted. In all-stop, we want to keep looking
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
holding OLD_PTID. */
static void
-infrun_thread_ptid_changed (ptid_t old_ptid, ptid_t new_ptid)
+infrun_thread_ptid_changed (process_stratum_target *target,
+ ptid_t old_ptid, ptid_t new_ptid)
{
- if (inferior_ptid == old_ptid)
+ if (inferior_ptid == old_ptid
+ && current_inferior ()->process_target () == target)
inferior_ptid = new_ptid;
}
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));
if (tp->suspend.waitstatus_pending_p)
{
- if (debug_infrun)
- {
- std::string 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).c_str (),
- statstr.c_str (),
- currently_stepping (tp));
- }
+ infrun_debug_printf
+ ("thread %s has pending wait "
+ "status %s (currently_stepping=%d).",
+ target_pid_to_str (tp->ptid).c_str (),
+ target_waitstatus_to_string (&tp->suspend.waitstatus).c_str (),
+ currently_stepping (tp));
tp->inf->process_target ()->threads_executing = true;
tp->resumed = true;
Eventually, we'll see a TARGET_WAITKIND_VFORK_DONE event for
the parent, and tell it to `keep_going', which automatically
re-sets it stepping. */
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog,
- "infrun: resume : clear step\n");
- step = 0;
+ infrun_debug_printf ("resume : clear step");
+ step = false;
}
CORE_ADDR pc = regcache_read_pc (regcache);
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog,
- "infrun: resume (step=%d, signal=%s), "
- "trap_expected=%d, current thread [%s] at %s\n",
- step, gdb_signal_to_symbol_string (sig),
- tp->control.trap_expected,
- target_pid_to_str (inferior_ptid).c_str (),
- paddress (gdbarch, pc));
+ infrun_debug_printf ("step=%d, signal=%s, trap_expected=%d, "
+ "current thread [%s] at %s",
+ step, gdb_signal_to_symbol_string (sig),
+ tp->control.trap_expected,
+ target_pid_to_str (inferior_ptid).c_str (),
+ paddress (gdbarch, pc));
/* Normally, by the time we reach `resume', the breakpoints are either
removed or inserted, as appropriate. The exception is if we're sitting
signal handler (or hit some other event). We'll delete
the step-resume breakpoint then. */
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog,
- "infrun: resume: skipping permanent breakpoint, "
- "deliver signal first\n");
+ infrun_debug_printf ("resume: skipping permanent breakpoint, "
+ "deliver signal first");
clear_step_over_info ();
tp->control.trap_expected = 0;
{
/* There's no signal to pass, we can go ahead and skip the
permanent breakpoint manually. */
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog,
- "infrun: resume: skipping permanent breakpoint\n");
+ infrun_debug_printf ("skipping permanent breakpoint");
gdbarch_skip_permanent_breakpoint (gdbarch, regcache);
/* Update pc to reflect the new address from which we will
execute instructions. */
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;
}
if (prepared == 0)
{
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog,
- "Got placed in step-over queue\n");
+ infrun_debug_printf ("Got placed in step-over queue");
tp->control.trap_expected = 0;
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);
}
}
gdb.threads/non-stop-fair-events.exp, on targets that don't
do displaced stepping. */
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog,
- "infrun: resume: [%s] stepped breakpoint\n",
- target_pid_to_str (tp->ptid).c_str ());
+ infrun_debug_printf ("resume: [%s] stepped breakpoint",
+ target_pid_to_str (tp->ptid).c_str ());
tp->stepped_breakpoint = 1;
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)
static void
clear_proceed_status_thread (struct thread_info *tp)
{
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog,
- "infrun: clear_proceed_status_thread (%s)\n",
- target_pid_to_str (tp->ptid).c_str ());
+ infrun_debug_printf ("%s", target_pid_to_str (tp->ptid).c_str ());
/* If we're starting a new sequence, then the previous finished
single-step is no longer relevant. */
{
if (tp->suspend.stop_reason == TARGET_STOPPED_BY_SINGLE_STEP)
{
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog,
- "infrun: clear_proceed_status: pending "
- "event of %s was a finished step. "
- "Discarding.\n",
- target_pid_to_str (tp->ptid).c_str ());
+ infrun_debug_printf ("pending event of %s was a finished step. "
+ "Discarding.",
+ target_pid_to_str (tp->ptid).c_str ());
tp->suspend.waitstatus_pending_p = 0;
tp->suspend.stop_reason = TARGET_STOPPED_BY_NO_REASON;
}
- else if (debug_infrun)
+ else
{
- std::string 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).c_str (),
- statstr.c_str (),
- currently_stepping (tp));
+ infrun_debug_printf
+ ("thread %s has pending wait status %s (currently_stepping=%d).",
+ target_pid_to_str (tp->ptid).c_str (),
+ target_waitstatus_to_string (&tp->suspend.waitstatus).c_str (),
+ currently_stepping (tp));
}
}
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
/* The target for some reason decided not to resume. */
normal_stop ();
if (target_can_async_p ())
- inferior_event_handler (INF_EXEC_COMPLETE, NULL);
+ inferior_event_handler (INF_EXEC_COMPLETE);
return;
}
if (!cur_thr->control.in_infcall)
set_running (resume_target, resume_ptid, true);
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog,
- "infrun: proceed (addr=%s, signal=%s)\n",
- paddress (gdbarch, addr),
- gdb_signal_to_symbol_string (siggnal));
+ infrun_debug_printf ("addr=%s, signal=%s", paddress (gdbarch, addr),
+ gdb_signal_to_symbol_string (siggnal));
annotate_starting ();
gdb_assert (!thread_is_in_step_over_chain (tp));
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog,
- "infrun: need to step-over [%s] first\n",
- target_pid_to_str (tp->ptid).c_str ());
+ infrun_debug_printf ("need to step-over [%s] first",
+ target_pid_to_str (tp->ptid).c_str ());
thread_step_over_chain_enqueue (tp);
}
if (!tp->inf->has_execution ())
{
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog,
- "infrun: proceed: [%s] target has "
- "no execution\n",
- target_pid_to_str (tp->ptid).c_str ());
+ infrun_debug_printf ("[%s] target has no execution",
+ target_pid_to_str (tp->ptid).c_str ());
continue;
}
if (tp->resumed)
{
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog,
- "infrun: proceed: [%s] resumed\n",
- target_pid_to_str (tp->ptid).c_str ());
+ infrun_debug_printf ("[%s] resumed",
+ target_pid_to_str (tp->ptid).c_str ());
gdb_assert (tp->executing || tp->suspend.waitstatus_pending_p);
continue;
}
if (thread_is_in_step_over_chain (tp))
{
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog,
- "infrun: proceed: [%s] needs step-over\n",
- target_pid_to_str (tp->ptid).c_str ());
+ infrun_debug_printf ("[%s] needs step-over",
+ target_pid_to_str (tp->ptid).c_str ());
continue;
}
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog,
- "infrun: proceed: resuming %s\n",
- target_pid_to_str (tp->ptid).c_str ());
+ infrun_debug_printf ("resuming %s",
+ target_pid_to_str (tp->ptid).c_str ());
reset_ecs (ecs, tp);
switch_to_thread (tp);
/* 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 ())
output as a unit; we want only one timestamp printed if debug_timestamp
is set. */
- stb.printf ("infrun: target_wait (%d.%ld.%ld",
+ stb.printf ("[infrun] target_wait (%d.%ld.%ld",
waiton_ptid.pid (),
waiton_ptid.lwp (),
waiton_ptid.tid ());
if (waiton_ptid.pid () != -1)
stb.printf (" [%s]", target_pid_to_str (waiton_ptid).c_str ());
stb.printf (", status) =\n");
- stb.printf ("infrun: %d.%ld.%ld [%s],\n",
+ stb.printf ("[infrun] %d.%ld.%ld [%s],\n",
result_ptid.pid (),
result_ptid.lwp (),
result_ptid.tid (),
target_pid_to_str (result_ptid).c_str ());
- stb.printf ("infrun: %s\n", status_string.c_str ());
+ 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. */
int random_selector = (int) ((num_events * (double) rand ())
/ (RAND_MAX + 1.0));
- if (debug_infrun && num_events > 1)
- fprintf_unfiltered (gdb_stdlog,
- "infrun: Found %d events, selecting #%d\n",
- num_events, random_selector);
+ if (num_events > 1)
+ infrun_debug_printf ("Found %d events, selecting #%d",
+ num_events, random_selector);
/* Select the Nth thread that has had an event. */
for (thread_info *tp : inf->non_exited_threads ())
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;
}
else
{
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog,
- "infrun: Waiting for specific thread %s.\n",
- target_pid_to_str (ptid).c_str ());
+ infrun_debug_printf ("Waiting for specific thread %s.",
+ target_pid_to_str (ptid).c_str ());
/* We have a specific thread to check. */
tp = find_thread_ptid (inf, ptid);
if (pc != tp->suspend.stop_pc)
{
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog,
- "infrun: PC of %s changed. was=%s, now=%s\n",
- target_pid_to_str (tp->ptid).c_str (),
- paddress (gdbarch, tp->suspend.stop_pc),
- paddress (gdbarch, pc));
+ infrun_debug_printf ("PC of %s changed. was=%s, now=%s",
+ target_pid_to_str (tp->ptid).c_str (),
+ paddress (gdbarch, tp->suspend.stop_pc),
+ paddress (gdbarch, pc));
discard = 1;
}
else if (!breakpoint_inserted_here_p (regcache->aspace (), pc))
{
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog,
- "infrun: previous breakpoint of %s, at %s gone\n",
- target_pid_to_str (tp->ptid).c_str (),
- paddress (gdbarch, pc));
+ infrun_debug_printf ("previous breakpoint of %s, at %s gone",
+ target_pid_to_str (tp->ptid).c_str (),
+ paddress (gdbarch, pc));
discard = 1;
}
if (discard)
{
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog,
- "infrun: pending event of %s cancelled.\n",
- target_pid_to_str (tp->ptid).c_str ());
+ infrun_debug_printf ("pending event of %s cancelled.",
+ target_pid_to_str (tp->ptid).c_str ());
tp->suspend.waitstatus.kind = TARGET_WAITKIND_SPURIOUS;
tp->suspend.stop_reason = TARGET_STOPPED_BY_NO_REASON;
if (tp != NULL)
{
- if (debug_infrun)
- {
- std::string statstr
- = target_waitstatus_to_string (&tp->suspend.waitstatus);
-
- fprintf_unfiltered (gdb_stdlog,
- "infrun: Using pending wait status %s for %s.\n",
- statstr.c_str (),
- target_pid_to_str (tp->ptid).c_str ());
- }
+ infrun_debug_printf ("Using pending wait status %s for %s.",
+ target_waitstatus_to_string
+ (&tp->suspend.waitstatus).c_str (),
+ target_pid_to_str (tp->ptid).c_str ());
/* Now that we've selected our final event LWP, un-adjust its PC
if it was a software breakpoint (and the target doesn't
/* 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
return event_ptid;
}
-/* Returns true if INF has any resumed thread with a status
- pending. */
-
-static bool
-threads_are_resumed_pending_p (inferior *inf)
-{
- for (thread_info *tp : inf->non_exited_threads ())
- if (tp->resumed
- && tp->suspend.waitstatus_pending_p)
- return true;
-
- return false;
-}
-
/* Wrapper for target_wait that first checks whether threads have
pending statuses to report before actually asking the target for
- more events. Polls for events from all inferiors/targets. */
+ 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;
- /* For fairness, we pick the first inferior/target to poll at
- random, and then continue polling the rest of the inferior list
- starting from that one in a circular fashion until the whole list
- is polled once. */
+ /* For fairness, we pick the first inferior/target to poll at random
+ out of all inferiors that may report events, and then continue
+ polling the rest of the inferior list starting from that one in a
+ circular fashion until the whole list is polled once. */
auto inferior_matches = [&wait_ptid] (inferior *inf)
{
return (inf->process_target () != NULL
- && (threads_are_executing (inf->process_target ())
- || threads_are_resumed_pending_p (inf))
&& ptid_t (inf->pid).matches (wait_ptid));
};
- /* First see how many resumed inferiors we have. */
+ /* First see how many matching inferiors we have. */
for (inferior *inf : all_inferiors ())
if (inferior_matches (inf))
num_inferiors++;
return false;
}
- /* Now randomly pick an inferior out of those that were resumed. */
+ /* Now randomly pick an inferior out of those that matched. */
random_selector = (int)
((num_inferiors * (double) rand ()) / (RAND_MAX + 1.0));
- if (debug_infrun && num_inferiors > 1)
- fprintf_unfiltered (gdb_stdlog,
- "infrun: Found %d inferiors, starting at #%d\n",
- num_inferiors, random_selector);
+ if (num_inferiors > 1)
+ infrun_debug_printf ("Found %d inferiors, starting at #%d",
+ num_inferiors, random_selector);
- /* Select the Nth inferior that was resumed. */
+ /* Select the Nth inferior that matched. */
inferior *selected = nullptr;
break;
}
- /* Now poll for events out of each of the resumed inferior's
+ /* Now poll for events out of each of the matching inferior's
targets, starting from the selected one. */
auto do_wait = [&] (inferior *inf)
return (ecs->ws.kind != TARGET_WAITKIND_IGNORE);
};
- /* Needed in all-stop+target-non-stop mode, because we end up here
- spuriously after the target is all stopped and we've already
+ /* Needed in 'all-stop + target-non-stop' mode, because we end up
+ here spuriously after the target is all stopped and we've already
reported the stop to the user, polling for events. */
scoped_restore_current_thread restore_thread;
if (displaced->step_thread == nullptr)
return;
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog,
- "displaced-stepping in-process while detaching");
+ infrun_debug_printf ("displaced-stepping in-process while detaching");
scoped_restore restore_detaching = make_scoped_restore (&inf->detaching, true);
static void
wait_for_inferior (inferior *inf)
{
- if (debug_infrun)
- fprintf_unfiltered
- (gdb_stdlog, "infrun: wait_for_inferior ()\n");
+ infrun_debug_printf ("wait_for_inferior ()");
SCOPE_EXIT { delete_just_stopped_threads_infrun_breakpoints (); };
necessary cleanups. */
void
-fetch_inferior_event (void *client_data)
+fetch_inferior_event ()
{
struct execution_control_state ecss;
struct execution_control_state *ecs = &ecss;
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 (); };
gdb_assert (ecs->ws.kind != TARGET_WAITKIND_IGNORE);
/* Switch to the target that generated the event, so we can do
- target calls. Any inferior bound to the target will do, so we
- just switch to the first we find. */
- for (inferior *inf : all_inferiors (ecs->target))
- {
- switch_to_inferior_no_thread (inf);
- break;
- }
+ target calls. */
+ switch_to_target_no_thread (ecs->target);
if (debug_infrun)
print_target_wait_results (minus_one_ptid, ecs->ptid, &ecs->ws);
if (!proceeded)
{
- inferior_event_handler (INF_EXEC_COMPLETE, NULL);
+ inferior_event_handler (INF_EXEC_COMPLETE);
cmd_done = 1;
}
static void
context_switch (execution_control_state *ecs)
{
- if (debug_infrun
- && ecs->ptid != inferior_ptid
+ if (ecs->ptid != inferior_ptid
&& (inferior_ptid == null_ptid
|| ecs->event_thread != inferior_thread ()))
{
- fprintf_unfiltered (gdb_stdlog, "infrun: Switching context from %s ",
- target_pid_to_str (inferior_ptid).c_str ());
- fprintf_unfiltered (gdb_stdlog, "to %s\n",
- target_pid_to_str (ecs->ptid).c_str ());
+ infrun_debug_printf ("Switching context from %s to %s",
+ target_pid_to_str (inferior_ptid).c_str (),
+ target_pid_to_str (ecs->ptid).c_str ());
}
switch_to_thread (ecs->event_thread);
}
}
-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;
if (catch_syscall_enabled () > 0
&& catching_syscall_number (syscall_number) > 0)
{
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog, "infrun: syscall number = '%d'\n",
- syscall_number);
+ infrun_debug_printf ("syscall number=%d", syscall_number);
ecs->event_thread->control.stop_bpstat
= bpstat_stop_status (regcache->aspace (),
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. */
if (!ecs->stop_func_filled_in)
{
const block *block;
+ const general_symbol_info *gsi;
/* Don't care about return value; stop_func_start and stop_func_name
will both be 0 if it doesn't work. */
- find_pc_partial_function (ecs->event_thread->suspend.stop_pc,
- &ecs->stop_func_name,
- &ecs->stop_func_start,
- &ecs->stop_func_end,
- &block);
+ find_pc_partial_function_sym (ecs->event_thread->suspend.stop_pc,
+ &gsi,
+ &ecs->stop_func_start,
+ &ecs->stop_func_end,
+ &block);
+ ecs->stop_func_name = gsi == nullptr ? nullptr : gsi->print_name ();
/* The call to find_pc_partial_function, above, will set
stop_func_start and stop_func_end to the start and end
static void
save_waitstatus (struct thread_info *tp, const target_waitstatus *ws)
{
- if (debug_infrun)
- {
- std::string statstr = target_waitstatus_to_string (ws);
-
- fprintf_unfiltered (gdb_stdlog,
- "infrun: saving status %s for %d.%ld.%ld\n",
- statstr.c_str (),
- tp->ptid.pid (),
- tp->ptid.lwp (),
- tp->ptid.tid ());
- }
+ infrun_debug_printf ("saving status %s for %d.%ld.%ld",
+ target_waitstatus_to_string (ws).c_str (),
+ tp->ptid.pid (),
+ tp->ptid.lwp (),
+ tp->ptid.tid ());
/* Record for later. */
tp->suspend.waitstatus = *ws;
gdb_assert (exists_non_stop_target ());
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog, "infrun: stop_all_threads\n");
+ infrun_debug_printf ("starting");
scoped_restore_current_thread restore_thread;
target_thread_events (false);
}
+ /* Use infrun_debug_printf_1 directly to get a meaningful function
+ name. */
if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog, "infrun: stop_all_threads done\n");
+ infrun_debug_printf_1 ("stop_all_threads", "done");
};
/* Request threads to stop, and then wait for the stops. Because
until two passes find no threads that need to be stopped. */
for (pass = 0; pass < 2; pass++, iterations++)
{
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog,
- "infrun: stop_all_threads, pass=%d, "
- "iterations=%d\n", pass, iterations);
+ infrun_debug_printf ("pass=%d, iterations=%d", pass, iterations);
while (1)
{
int waits_needed = 0;
We just haven't seen the notification yet. */
if (!t->stop_requested)
{
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog,
- "infrun: %s executing, "
- "need stop\n",
- target_pid_to_str (t->ptid).c_str ());
+ infrun_debug_printf (" %s executing, need stop",
+ target_pid_to_str (t->ptid).c_str ());
target_stop (t->ptid);
t->stop_requested = 1;
}
else
{
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog,
- "infrun: %s executing, "
- "already stopping\n",
- target_pid_to_str (t->ptid).c_str ());
+ infrun_debug_printf (" %s executing, already stopping",
+ target_pid_to_str (t->ptid).c_str ());
}
if (t->stop_requested)
}
else
{
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog,
- "infrun: %s not executing\n",
- target_pid_to_str (t->ptid).c_str ());
+ infrun_debug_printf (" %s not executing",
+ target_pid_to_str (t->ptid).c_str ());
/* The thread may be not executing, but still be
resumed with a pending status to process. */
{
wait_one_event event = wait_one ();
- if (debug_infrun)
- {
- fprintf_unfiltered (gdb_stdlog,
- "infrun: stop_all_threads %s %s\n",
- target_waitstatus_to_string (&event.ws).c_str (),
- target_pid_to_str (event.ptid).c_str ());
- }
+ infrun_debug_printf
+ ("%s %s", target_waitstatus_to_string (&event.ws).c_str (),
+ target_pid_to_str (event.ptid).c_str ());
if (event.ws.kind == TARGET_WAITKIND_NO_RESUMED)
{
of going into an infinite loop. */
gdb_assert (t != nullptr);
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog,
- "infrun: stop_all_threads, using %s\n",
- target_pid_to_str (t->ptid).c_str ());
+ infrun_debug_printf
+ ("using %s", target_pid_to_str (t->ptid).c_str ());
}
else
{
if (displaced_step_fixup (t, GDB_SIGNAL_0) < 0)
{
/* Add it back to the step-over queue. */
- if (debug_infrun)
- {
- fprintf_unfiltered (gdb_stdlog,
- "infrun: displaced-step of %s "
- "canceled: adding back to the "
- "step-over queue\n",
- target_pid_to_str (t->ptid).c_str ());
- }
+ infrun_debug_printf
+ ("displaced-step of %s canceled: adding back to "
+ "the step-over queue",
+ target_pid_to_str (t->ptid).c_str ());
+
t->control.trap_expected = 0;
thread_step_over_chain_enqueue (t);
}
enum gdb_signal sig;
struct regcache *regcache;
- if (debug_infrun)
- {
- std::string statstr = target_waitstatus_to_string (&event.ws);
-
- fprintf_unfiltered (gdb_stdlog,
- "infrun: target_wait %s, saving "
- "status for %d.%ld.%ld\n",
- statstr.c_str (),
- t->ptid.pid (),
- t->ptid.lwp (),
- t->ptid.tid ());
- }
+ infrun_debug_printf
+ ("target_wait %s, saving status for %d.%ld.%ld",
+ target_waitstatus_to_string (&event.ws).c_str (),
+ t->ptid.pid (), t->ptid.lwp (), t->ptid.tid ());
/* Record for later. */
save_waitstatus (t, &event.ws);
regcache = get_thread_regcache (t);
t->suspend.stop_pc = regcache_read_pc (regcache);
- if (debug_infrun)
- {
- fprintf_unfiltered (gdb_stdlog,
- "infrun: saved stop_pc=%s for %s "
- "(currently_stepping=%d)\n",
- paddress (target_gdbarch (),
- t->suspend.stop_pc),
- target_pid_to_str (t->ptid).c_str (),
- currently_stepping (t));
- }
+ infrun_debug_printf ("saved stop_pc=%s for %s "
+ "(currently_stepping=%d)",
+ paddress (target_gdbarch (),
+ t->suspend.stop_pc),
+ target_pid_to_str (t->ptid).c_str (),
+ currently_stepping (t));
}
}
}
/* 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;
}
}
we're not synchronously waiting for events either. Just
ignore. */
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog,
- "infrun: TARGET_WAITKIND_NO_RESUMED "
- "(ignoring: bg)\n");
+ infrun_debug_printf ("TARGET_WAITKIND_NO_RESUMED (ignoring: bg)");
prepare_to_wait (ecs);
- return 1;
+ return true;
}
}
have resumed threads _now_. In the example above, this removes
thread 3 from the thread list. If thread 2 was re-resumed, we
ignore this event. If we find no thread resumed, then we cancel
- the synchronous command show "no unwaited-for " to the user. */
- update_thread_list ();
+ the synchronous command and show "no unwaited-for " to the
+ user. */
+
+ inferior *curr_inf = current_inferior ();
+
+ scoped_restore_current_thread restore_thread;
- for (thread_info *thread : all_non_exited_threads (ecs->target))
+ for (auto *target : all_non_exited_process_targets ())
{
- if (thread->executing
- || thread->suspend.waitstatus_pending_p)
+ switch_to_target_no_thread (target);
+ update_thread_list ();
+ }
+
+ /* If:
+
+ - the current target has no thread executing, and
+ - the current inferior is native, and
+ - the current inferior is the one which has the terminal, and
+ - we did nothing,
+
+ then a Ctrl-C from this point on would remain stuck in the
+ kernel, until a thread resumes and dequeues it. That would
+ result in the GDB CLI not reacting to Ctrl-C, not able to
+ interrupt the program. To address this, if the current inferior
+ no longer has any thread executing, we give the terminal to some
+ other inferior that has at least one thread executing. */
+ bool swap_terminal = true;
+
+ /* Whether to ignore this TARGET_WAITKIND_NO_RESUMED event, or
+ whether to report it to the user. */
+ bool ignore_event = false;
+
+ for (thread_info *thread : all_non_exited_threads ())
+ {
+ if (swap_terminal && thread->executing)
{
- /* There were no unwaited-for children left in the target at
- some point, but there are now. Just ignore. */
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog,
- "infrun: TARGET_WAITKIND_NO_RESUMED "
- "(ignoring: found resumed)\n");
- prepare_to_wait (ecs);
- return 1;
+ if (thread->inf != curr_inf)
+ {
+ target_terminal::ours ();
+
+ switch_to_thread (thread);
+ target_terminal::inferior ();
+ }
+ swap_terminal = false;
+ }
+
+ if (!ignore_event
+ && (thread->executing
+ || thread->suspend.waitstatus_pending_p))
+ {
+ /* Either there were no unwaited-for children left in the
+ target at some point, but there are now, or some target
+ other than the eventing one has unwaited-for children
+ left. Just ignore. */
+ infrun_debug_printf ("TARGET_WAITKIND_NO_RESUMED "
+ "(ignoring: found resumed)");
+
+ ignore_event = true;
}
+
+ if (ignore_event && !swap_terminal)
+ break;
+ }
+
+ if (ignore_event)
+ {
+ switch_to_inferior_no_thread (curr_inf);
+ prepare_to_wait (ecs);
+ return true;
}
/* Go ahead and report the event. */
- return 0;
+ return false;
}
/* Given an execution control state that has been freshly filled in by
enum stop_kind stop_soon;
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog, "infrun: handle_inferior_event %s\n",
- target_waitstatus_to_string (&ecs->ws).c_str ());
+ infrun_debug_printf ("%s", target_waitstatus_to_string (&ecs->ws).c_str ());
if (ecs->ws.kind == TARGET_WAITKIND_IGNORE)
{
{
/* No unwaited-for children left. IOW, all resumed children
have exited. */
- stop_print_frame = 0;
+ stop_print_frame = false;
stop_waiting (ecs);
return;
}
if (breakpoint_inserted_here_p (regcache->aspace (),
regcache_read_pc (regcache)))
{
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog,
- "infrun: Treating signal as SIGTRAP\n");
+ infrun_debug_printf ("Treating signal as SIGTRAP");
ecs->ws.value.sig = GDB_SIGNAL_TRAP;
}
}
{
/* Make sure we print "Stopped due to solib-event" in
normal_stop. */
- stop_print_frame = 1;
+ stop_print_frame = true;
stop_waiting (ecs);
return;
if (stop_soon == STOP_QUIETLY_NO_SIGSTOP
|| stop_soon == STOP_QUIETLY_REMOTE)
{
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog, "infrun: quietly stopped\n");
+ infrun_debug_printf ("quietly stopped");
stop_waiting (ecs);
return;
}
information to the user. It's better to just warn
her about it (if infrun debugging is enabled), and
give up. */
- if (debug_infrun)
- fprintf_filtered (gdb_stdlog, _("\
-Cannot fill $_exitsignal with the correct signal number.\n"));
+ infrun_debug_printf ("Cannot fill $_exitsignal with the correct "
+ "signal number.");
}
gdb::observers::signal_exited.notify (ecs->ws.value.sig);
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);
}
/* Switch to the stopped thread. */
context_switch (ecs);
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog, "infrun: stopped\n");
+ infrun_debug_printf ("stopped");
delete_just_stopped_threads_single_step_breakpoints ();
ecs->event_thread->suspend.stop_pc
if (tp == event_thread)
{
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog,
- "infrun: restart threads: "
- "[%s] is event thread\n",
- target_pid_to_str (tp->ptid).c_str ());
+ infrun_debug_printf ("restart threads: [%s] is event thread",
+ target_pid_to_str (tp->ptid).c_str ());
continue;
}
if (!(tp->state == THREAD_RUNNING || tp->control.in_infcall))
{
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog,
- "infrun: restart threads: "
- "[%s] not meant to be running\n",
- target_pid_to_str (tp->ptid).c_str ());
+ infrun_debug_printf ("restart threads: [%s] not meant to be running",
+ target_pid_to_str (tp->ptid).c_str ());
continue;
}
if (tp->resumed)
{
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog,
- "infrun: restart threads: [%s] resumed\n",
- target_pid_to_str (tp->ptid).c_str ());
+ infrun_debug_printf ("restart threads: [%s] resumed",
+ target_pid_to_str (tp->ptid).c_str ());
gdb_assert (tp->executing || tp->suspend.waitstatus_pending_p);
continue;
}
if (thread_is_in_step_over_chain (tp))
{
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog,
- "infrun: restart threads: "
- "[%s] needs step-over\n",
- target_pid_to_str (tp->ptid).c_str ());
+ infrun_debug_printf ("restart threads: [%s] needs step-over",
+ target_pid_to_str (tp->ptid).c_str ());
gdb_assert (!tp->resumed);
continue;
}
if (tp->suspend.waitstatus_pending_p)
{
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog,
- "infrun: restart threads: "
- "[%s] has pending status\n",
- target_pid_to_str (tp->ptid).c_str ());
+ infrun_debug_printf ("restart threads: [%s] has pending status",
+ target_pid_to_str (tp->ptid).c_str ());
tp->resumed = true;
continue;
}
if (currently_stepping (tp))
{
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog,
- "infrun: restart threads: [%s] was stepping\n",
- target_pid_to_str (tp->ptid).c_str ());
+ infrun_debug_printf ("restart threads: [%s] was stepping",
+ target_pid_to_str (tp->ptid).c_str ());
keep_going_stepped_thread (tp);
}
else
struct execution_control_state ecss;
struct execution_control_state *ecs = &ecss;
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog,
- "infrun: restart threads: [%s] continuing\n",
- target_pid_to_str (tp->ptid).c_str ());
+ infrun_debug_printf ("restart threads: [%s] continuing",
+ target_pid_to_str (tp->ptid).c_str ());
reset_ecs (ecs, tp);
switch_to_thread (tp);
keep_going_pass_signal (ecs);
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)
{
struct thread_info *tp = ecs->event_thread;
struct regcache *regcache;
- if (debug_infrun)
- {
- fprintf_unfiltered (gdb_stdlog,
- "infrun: found resumed threads with "
- "pending events, saving status\n");
- }
+ infrun_debug_printf ("found resumed threads with "
+ "pending events, saving status");
gdb_assert (pending != tp);
regcache = get_thread_regcache (tp);
tp->suspend.stop_pc = regcache_read_pc (regcache);
- if (debug_infrun)
- {
- fprintf_unfiltered (gdb_stdlog,
- "infrun: saved stop_pc=%s for %s "
- "(currently_stepping=%d)\n",
- paddress (target_gdbarch (),
- tp->suspend.stop_pc),
- target_pid_to_str (tp->ptid).c_str (),
- currently_stepping (tp));
- }
+ infrun_debug_printf ("saved stop_pc=%s for %s "
+ "(currently_stepping=%d)",
+ paddress (target_gdbarch (),
+ tp->suspend.stop_pc),
+ target_pid_to_str (tp->ptid).c_str (),
+ currently_stepping (tp));
/* This in-line step-over finished; clear this so we won't
start a new one. This is what handle_signal_stop would
switch_to_thread (ecs->event_thread);
- fprintf_unfiltered (gdb_stdlog, "infrun: stop_pc = %s\n",
- paddress (reg_gdbarch,
- ecs->event_thread->suspend.stop_pc));
+ infrun_debug_printf ("stop_pc=%s",
+ paddress (reg_gdbarch,
+ ecs->event_thread->suspend.stop_pc));
if (target_stopped_by_watchpoint ())
{
CORE_ADDR addr;
- fprintf_unfiltered (gdb_stdlog, "infrun: stopped by watchpoint\n");
+ infrun_debug_printf ("stopped by watchpoint");
if (target_stopped_data_address (current_top_target (), &addr))
- fprintf_unfiltered (gdb_stdlog,
- "infrun: stopped data address = %s\n",
- paddress (reg_gdbarch, addr));
+ infrun_debug_printf ("stopped data address=%s",
+ paddress (reg_gdbarch, addr));
else
- fprintf_unfiltered (gdb_stdlog,
- "infrun: (no data address available)\n");
+ infrun_debug_printf ("(no data address available)");
}
}
if (stop_soon == STOP_QUIETLY || stop_soon == STOP_QUIETLY_REMOTE)
{
context_switch (ecs);
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog, "infrun: quietly stopped\n");
- stop_print_frame = 1;
+ infrun_debug_printf ("quietly stopped");
+ 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;
so, then switch to that thread. */
if (ecs->ptid != inferior_ptid)
{
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog, "infrun: context switch\n");
+ infrun_debug_printf ("context switch");
context_switch (ecs);
{
if (single_step_breakpoint_inserted_here_p (aspace, pc))
{
- if (debug_infrun)
- {
- fprintf_unfiltered (gdb_stdlog,
- "infrun: [%s] hit another thread's "
- "single-step breakpoint\n",
- target_pid_to_str (ecs->ptid).c_str ());
- }
+ infrun_debug_printf ("[%s] hit another thread's single-step "
+ "breakpoint",
+ target_pid_to_str (ecs->ptid).c_str ());
ecs->hit_singlestep_breakpoint = 1;
}
}
else
{
- if (debug_infrun)
- {
- fprintf_unfiltered (gdb_stdlog,
- "infrun: [%s] hit its "
- "single-step breakpoint\n",
- target_pid_to_str (ecs->ptid).c_str ());
- }
+ infrun_debug_printf ("[%s] hit its single-step breakpoint",
+ target_pid_to_str (ecs->ptid).c_str ());
}
}
delete_just_stopped_threads_single_step_breakpoints ();
/* 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;
int step_through_delay
= gdbarch_single_step_through_delay (gdbarch, frame);
- if (debug_infrun && step_through_delay)
- fprintf_unfiltered (gdb_stdlog, "infrun: step through delay\n");
+ if (step_through_delay)
+ infrun_debug_printf ("step through delay");
+
if (ecs->event_thread->control.step_range_end == 0
&& step_through_delay)
{
/* 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
simply make sure to ignore it if `stopped_by_watchpoint' is
set. */
- if (debug_infrun
- && ecs->event_thread->suspend.stop_signal == GDB_SIGNAL_TRAP
+ if (ecs->event_thread->suspend.stop_signal == GDB_SIGNAL_TRAP
&& !bpstat_explains_signal (ecs->event_thread->control.stop_bpstat,
GDB_SIGNAL_TRAP)
&& stopped_by_watchpoint)
- fprintf_unfiltered (gdb_stdlog,
- "infrun: no user watchpoint explains "
- "watchpoint SIGTRAP, ignoring\n");
+ {
+ infrun_debug_printf ("no user watchpoint explains watchpoint SIGTRAP, "
+ "ignoring");
+ }
/* NOTE: cagney/2003-03-29: These checks for a random signal
at one stage in the past included checks for an inferior
else
{
/* A delayed software breakpoint event. Ignore the trap. */
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog,
- "infrun: delayed software breakpoint "
- "trap, ignoring\n");
+ infrun_debug_printf ("delayed software breakpoint trap, ignoring");
random_signal = 0;
}
}
if (random_signal && target_stopped_by_hw_breakpoint ())
{
/* A delayed hardware breakpoint event. Ignore the trap. */
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog,
- "infrun: delayed hardware breakpoint/watchpoint "
- "trap, ignoring\n");
+ infrun_debug_printf ("delayed hardware breakpoint/watchpoint "
+ "trap, ignoring");
random_signal = 0;
}
if (ecs->event_thread->stop_requested)
{
random_signal = 1;
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog, "infrun: user-requested stop\n");
+ infrun_debug_printf ("user-requested stop");
}
/* For the program's own signals, act according to
struct inferior *inf = find_inferior_ptid (ecs->target, ecs->ptid);
enum gdb_signal stop_signal = ecs->event_thread->suspend.stop_signal;
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog, "infrun: random signal (%s)\n",
- gdb_signal_to_symbol_string (stop_signal));
+ infrun_debug_printf ("random signal (%s)",
+ gdb_signal_to_symbol_string (stop_signal));
stopped_by_random_signal = 1;
code paths as single-step - set a breakpoint at the
signal return address and then, once hit, step off that
breakpoint. */
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog,
- "infrun: signal arrived while stepping over "
- "breakpoint\n");
+ infrun_debug_printf ("signal arrived while stepping over breakpoint");
insert_hp_step_resume_breakpoint_at_frame (frame);
ecs->event_thread->step_after_step_resume_breakpoint = 1;
Note that this is only needed for a signal delivered
while in the single-step range. Nested signals aren't a
problem as they eventually all return. */
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog,
- "infrun: signal may take us out of "
- "single-step range\n");
+ infrun_debug_printf ("signal may take us out of single-step range");
clear_step_over_info ();
insert_hp_step_resume_breakpoint_at_frame (frame);
if (!switch_back_to_stepped_thread (ecs))
{
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog,
- "infrun: random signal, keep going\n");
+ infrun_debug_printf ("random signal, keep going");
keep_going (ecs);
}
install a momentary breakpoint at the target of the
jmp_buf. */
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog,
- "infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME\n");
+ infrun_debug_printf ("BPSTAT_WHAT_SET_LONGJMP_RESUME");
ecs->event_thread->stepping_over_breakpoint = 1;
|| !gdbarch_get_longjmp_target (gdbarch,
frame, &jmp_buf_pc))
{
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog,
- "infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME "
- "(!gdbarch_get_longjmp_target)\n");
+ infrun_debug_printf ("BPSTAT_WHAT_SET_LONGJMP_RESUME "
+ "(!gdbarch_get_longjmp_target)");
keep_going (ecs);
return;
}
against stale dummy frames and user is not interested in
stopping around longjmps. */
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog,
- "infrun: BPSTAT_WHAT_CLEAR_LONGJMP_RESUME\n");
+ infrun_debug_printf ("BPSTAT_WHAT_CLEAR_LONGJMP_RESUME");
gdb_assert (ecs->event_thread->control.exception_resume_breakpoint
!= NULL);
return;
case BPSTAT_WHAT_SINGLE:
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog, "infrun: BPSTAT_WHAT_SINGLE\n");
+ infrun_debug_printf ("BPSTAT_WHAT_SINGLE");
ecs->event_thread->stepping_over_breakpoint = 1;
/* Still need to check other stuff, at least the case where we
are stepping and step out of the right range. */
break;
case BPSTAT_WHAT_STEP_RESUME:
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog, "infrun: BPSTAT_WHAT_STEP_RESUME\n");
+ infrun_debug_printf ("BPSTAT_WHAT_STEP_RESUME");
delete_step_resume_breakpoint (ecs->event_thread);
if (ecs->event_thread->control.proceed_to_finish
break;
case BPSTAT_WHAT_STOP_NOISY:
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog, "infrun: BPSTAT_WHAT_STOP_NOISY\n");
- stop_print_frame = 1;
+ infrun_debug_printf ("BPSTAT_WHAT_STOP_NOISY");
+ stop_print_frame = true;
- /* Assume the thread stopped for a breapoint. We'll still check
+ /* Assume the thread stopped for a breakpoint. We'll still check
whether a/the breakpoint is there when the thread is next
resumed. */
ecs->event_thread->stepping_over_breakpoint = 1;
return;
case BPSTAT_WHAT_STOP_SILENT:
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog, "infrun: BPSTAT_WHAT_STOP_SILENT\n");
- stop_print_frame = 0;
+ infrun_debug_printf ("BPSTAT_WHAT_STOP_SILENT");
+ stop_print_frame = false;
- /* Assume the thread stopped for a breapoint. We'll still check
+ /* Assume the thread stopped for a breakpoint. We'll still check
whether a/the breakpoint is there when the thread is next
resumed. */
ecs->event_thread->stepping_over_breakpoint = 1;
return;
case BPSTAT_WHAT_HP_STEP_RESUME:
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog, "infrun: BPSTAT_WHAT_HP_STEP_RESUME\n");
+ infrun_debug_printf ("BPSTAT_WHAT_HP_STEP_RESUME");
delete_step_resume_breakpoint (ecs->event_thread);
if (ecs->event_thread->step_after_step_resume_breakpoint)
&& sr_bp->type == bp_hp_step_resume
&& sr_bp->loc->address == ecs->event_thread->prev_pc)
{
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog,
- "infrun: stepped permanent breakpoint, stopped in "
- "handler\n");
+ infrun_debug_printf ("stepped permanent breakpoint, stopped in handler");
delete_step_resume_breakpoint (ecs->event_thread);
ecs->event_thread->step_after_step_resume_breakpoint = 0;
}
if (ecs->event_thread->control.step_resume_breakpoint)
{
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog,
- "infrun: step-resume breakpoint is inserted\n");
+ infrun_debug_printf ("step-resume breakpoint is inserted");
/* Having a step-resume breakpoint overrides anything
else having to do with stepping commands until
if (ecs->event_thread->control.step_range_end == 0)
{
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog, "infrun: no stepping, continue\n");
+ infrun_debug_printf ("no stepping, continue");
/* Likewise if we aren't even stepping. */
keep_going (ecs);
return;
|| frame_id_eq (get_frame_id (frame),
ecs->event_thread->control.step_frame_id)))
{
- if (debug_infrun)
- fprintf_unfiltered
- (gdb_stdlog, "infrun: stepping inside range [%s-%s]\n",
- paddress (gdbarch, ecs->event_thread->control.step_range_start),
- paddress (gdbarch, ecs->event_thread->control.step_range_end));
+ infrun_debug_printf
+ ("stepping inside range [%s-%s]",
+ paddress (gdbarch, ecs->event_thread->control.step_range_start),
+ paddress (gdbarch, ecs->event_thread->control.step_range_end));
/* Tentatively re-enable range stepping; `resume' disables it if
necessary (e.g., if we're stepping over a breakpoint or we
gdbarch_skip_solib_resolver (gdbarch,
ecs->event_thread->suspend.stop_pc);
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog,
- "infrun: stepped into dynsym resolve code\n");
+ infrun_debug_printf ("stepped into dynsym resolve code");
if (pc_after_resolver)
{
&& gdbarch_in_indirect_branch_thunk (gdbarch,
ecs->event_thread->suspend.stop_pc))
{
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog,
- "infrun: stepped into indirect branch thunk\n");
+ infrun_debug_printf ("stepped into indirect branch thunk");
keep_going (ecs);
return;
}
|| ecs->event_thread->control.step_over_calls == STEP_OVER_ALL)
&& get_frame_type (frame) == SIGTRAMP_FRAME)
{
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog,
- "infrun: stepped into signal trampoline\n");
+ infrun_debug_printf ("stepped into signal trampoline");
/* The inferior, while doing a "step" or "next", has ended up in
a signal trampoline (either by a signal being delivered or by
the signal handler returning). Just single-step until the
CORE_ADDR real_stop_pc
= gdbarch_skip_trampoline_code (gdbarch, frame, stop_pc);
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog,
- "infrun: stepped into solib return tramp\n");
+ infrun_debug_printf ("stepped into solib return tramp");
/* Only proceed through if we know where it's going. */
if (real_stop_pc)
CORE_ADDR stop_pc = ecs->event_thread->suspend.stop_pc;
CORE_ADDR real_stop_pc;
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog, "infrun: stepped into subroutine\n");
+ infrun_debug_printf ("stepped into subroutine");
if (ecs->event_thread->control.step_over_calls == STEP_OVER_NONE)
{
&& ecs->stop_func_name == NULL
&& stop_pc_sal.line == 0)
{
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog,
- "infrun: stepped into undebuggable function\n");
+ infrun_debug_printf ("stepped into undebuggable function");
/* The inferior just stepped into, or returned to, an
undebuggable function (where there is no debugging information
{
/* It is stepi or nexti. We always want to stop stepping after
one instruction. */
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog, "infrun: stepi/nexti\n");
+ infrun_debug_printf ("stepi/nexti");
end_stepping_range (ecs);
return;
}
stepping (does this always happen right after one instruction,
when we do "s" in a function with no line numbers,
or can this happen as a result of a return or longjmp?). */
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog, "infrun: no line number info\n");
+ infrun_debug_printf ("line number info");
end_stepping_range (ecs);
return;
}
ecs->event_thread->control.step_frame_id)
&& inline_skipped_frames (ecs->event_thread))
{
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog,
- "infrun: stepped into inlined function\n");
+ infrun_debug_printf ("stepped into inlined function");
symtab_and_line call_sal = find_frame_sal (get_current_frame ());
&& stepped_in_from (get_current_frame (),
ecs->event_thread->control.step_frame_id))
{
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog,
- "infrun: stepping through inlined function\n");
+ infrun_debug_printf ("stepping through inlined function");
if (ecs->event_thread->control.step_over_calls == STEP_OVER_ALL
|| inline_frame_is_marked_for_skip (false, ecs->event_thread))
we don't stop if we step into the middle of a different line.
That is said to make things like for (;;) statements work
better. */
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog,
- "infrun: stepped to a different line\n");
+ infrun_debug_printf ("stepped to a different line");
end_stepping_range (ecs);
return;
}
ignore this line table entry, and continue stepping forward,
looking for a better place to stop. */
refresh_step_info = false;
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog,
- "infrun: stepped to a different line, but "
- "it's not the start of a statement\n");
+ infrun_debug_printf ("stepped to a different line, but "
+ "it's not the start of a statement");
}
}
if (refresh_step_info)
set_step_info (ecs->event_thread, frame, stop_pc_sal);
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog, "infrun: keep going\n");
+ infrun_debug_printf ("keep going");
keep_going (ecs);
}
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. */
if (ecs->event_thread->control.trap_expected
&& ecs->event_thread->suspend.stop_signal != GDB_SIGNAL_TRAP)
{
- if (debug_infrun)
- {
- fprintf_unfiltered (gdb_stdlog,
- "infrun: need to finish step-over of [%s]\n",
- target_pid_to_str (ecs->event_thread->ptid).c_str ());
- }
+ infrun_debug_printf
+ ("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
breakpoint of another thread. */
if (ecs->hit_singlestep_breakpoint)
{
- if (debug_infrun)
- {
- fprintf_unfiltered (gdb_stdlog,
- "infrun: need to step [%s] over single-step "
- "breakpoint\n",
- target_pid_to_str (ecs->ptid).c_str ());
- }
+ 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
another thread. */
if (thread_still_needs_step_over (ecs->event_thread))
{
- if (debug_infrun)
- {
- fprintf_unfiltered (gdb_stdlog,
- "infrun: thread [%s] still needs step-over\n",
- target_pid_to_str (ecs->event_thread->ptid).c_str ());
- }
+ infrun_debug_printf
+ ("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 (stepping_thread != NULL)
{
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog,
- "infrun: switching back to stepped thread\n");
+ infrun_debug_printf ("switching back to stepped 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;
if (tp->state == THREAD_EXITED || !target_thread_alive (tp->ptid))
{
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog,
- "infrun: not resuming previously "
- "stepped thread, it has vanished\n");
+ infrun_debug_printf ("not resuming previously stepped thread, it has "
+ "vanished");
delete_thread (tp);
- return 0;
+ return false;
}
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog,
- "infrun: resuming previously stepped thread\n");
+ infrun_debug_printf ("resuming previously stepped thread");
reset_ecs (ecs, tp);
switch_to_thread (tp);
{
ptid_t resume_ptid;
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog,
- "infrun: expected thread advanced also (%s -> %s)\n",
- paddress (target_gdbarch (), tp->prev_pc),
- paddress (target_gdbarch (), tp->suspend.stop_pc));
+ infrun_debug_printf ("expected thread advanced also (%s -> %s)",
+ paddress (target_gdbarch (), tp->prev_pc),
+ paddress (target_gdbarch (), tp->suspend.stop_pc));
/* Clear the info of the previous step-over, as it's no longer
valid (if the thread was trying to step over a breakpoint, it
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
{
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog,
- "infrun: expected thread still hasn't advanced\n");
+ infrun_debug_printf ("expected thread still hasn't advanced");
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
gdb_assert (inferior_thread ()->control.step_resume_breakpoint == NULL);
gdb_assert (sr_type == bp_step_resume || sr_type == bp_hp_step_resume);
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog,
- "infrun: inserting step-resume breakpoint at %s\n",
- paddress (gdbarch, sr_sal.pc));
+ infrun_debug_printf ("inserting step-resume breakpoint at %s",
+ paddress (gdbarch, sr_sal.pc));
inferior_thread ()->control.step_resume_breakpoint
= set_momentary_breakpoint (gdbarch, sr_sal, sr_id, sr_type).release ();
longjmp_resume_breakpoint when one is already active. */
gdb_assert (inferior_thread ()->control.exception_resume_breakpoint == NULL);
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog,
- "infrun: inserting longjmp-resume breakpoint at %s\n",
- paddress (gdbarch, pc));
+ infrun_debug_printf ("inserting longjmp-resume breakpoint at %s",
+ paddress (gdbarch, pc));
inferior_thread ()->control.exception_resume_breakpoint =
set_momentary_breakpoint_at_pc (gdbarch, pc, bp_longjmp_resume).release ();
{
handler = value_as_address (value);
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog,
- "infrun: exception resume at %lx\n",
- (unsigned long) handler);
+ infrun_debug_printf ("exception resume at %lx",
+ (unsigned long) handler);
bp = set_momentary_breakpoint_at_pc (get_frame_arch (frame),
handler,
handler = value_as_address (arg_value);
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog,
- "infrun: exception resume at %s\n",
- paddress (probe->objfile->arch (),
- handler));
+ infrun_debug_printf ("exception resume at %s",
+ paddress (probe->objfile->arch (), handler));
bp = set_momentary_breakpoint_at_pc (get_frame_arch (frame),
handler, bp_exception_resume).release ();
static void
stop_waiting (struct execution_control_state *ecs)
{
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog, "infrun: stop_waiting\n");
+ infrun_debug_printf ("stop_waiting");
/* Let callers know we don't want to wait for the inferior anymore. */
ecs->wait_some_more = 0;
{
struct thread_info *tp = ecs->event_thread;
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog,
- "infrun: %s has trap_expected set, "
- "resuming to collect trap\n",
- target_pid_to_str (tp->ptid).c_str ());
+ infrun_debug_printf ("%s has trap_expected set, "
+ "resuming to collect trap",
+ target_pid_to_str (tp->ptid).c_str ());
/* We haven't yet gotten our trap, and either: intercepted a
non-signal event (e.g., a fork); or took a signal which we
if (ecs->hit_singlestep_breakpoint
|| thread_still_needs_step_over (tp))
{
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog,
- "infrun: step-over already in progress: "
- "step-over for %s deferred\n",
- target_pid_to_str (tp->ptid).c_str ());
+ infrun_debug_printf ("step-over already in progress: "
+ "step-over for %s deferred",
+ target_pid_to_str (tp->ptid).c_str ());
thread_step_over_chain_enqueue (tp);
}
else
{
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog,
- "infrun: step-over in progress: "
- "resume of %s deferred\n",
- target_pid_to_str (tp->ptid).c_str ());
+ infrun_debug_printf ("step-over in progress: resume of %s deferred",
+ target_pid_to_str (tp->ptid).c_str ());
}
}
else
static void
prepare_to_wait (struct execution_control_state *ecs)
{
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog, "infrun: prepare_to_wait\n");
+ infrun_debug_printf ("prepare_to_wait");
ecs->wait_some_more = 1;
- if (!target_is_async_p ())
+ /* If the target can't async, emulate it by marking the infrun event
+ handler such that as soon as we get back to the event-loop, we
+ immediately end up in fetch_inferior_event again calling
+ target_wait. */
+ if (!target_can_async_p ())
mark_infrun_async_event_handler ();
}
}
}
-/* Some targets/architectures can do extra processing/display of
- segmentation faults. E.g., Intel MPX boundary faults.
- Call the architecture dependent function to handle the fault. */
-
-static void
-handle_segmentation_fault (struct ui_out *uiout)
-{
- struct regcache *regcache = get_current_regcache ();
- struct gdbarch *gdbarch = regcache->arch ();
-
- if (gdbarch_handle_segmentation_fault_p (gdbarch))
- gdbarch_handle_segmentation_fault (gdbarch, uiout);
-}
-
void
print_signal_received_reason (struct ui_out *uiout, enum gdb_signal siggnal)
{
annotate_signal_string ();
uiout->field_string ("signal-meaning", gdb_signal_to_string (siggnal));
- if (siggnal == GDB_SIGNAL_SEGV)
- handle_segmentation_fault (uiout);
+ struct regcache *regcache = get_current_regcache ();
+ struct gdbarch *gdbarch = regcache->arch ();
+ if (gdbarch_report_signal_info_p (gdbarch))
+ gdbarch_report_signal_info (gdbarch, uiout, siggnal);
annotate_signal_string_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;
static void
infrun_async_inferior_event_handler (gdb_client_data data)
{
- inferior_event_handler (INF_REG_EVENT, NULL);
+ inferior_event_handler (INF_REG_EVENT);
+}
+
+#if GDB_SELF_TEST
+namespace selftests
+{
+
+/* Verify that when two threads with the same ptid exist (from two different
+ targets) and one of them changes ptid, we only update inferior_ptid if
+ it is appropriate. */
+
+static void
+infrun_thread_ptid_changed ()
+{
+ gdbarch *arch = current_inferior ()->gdbarch;
+
+ /* The thread which inferior_ptid represents changes ptid. */
+ {
+ scoped_restore_current_pspace_and_thread restore;
+
+ scoped_mock_context<test_target_ops> target1 (arch);
+ scoped_mock_context<test_target_ops> target2 (arch);
+ target2.mock_inferior.next = &target1.mock_inferior;
+
+ ptid_t old_ptid (111, 222);
+ ptid_t new_ptid (111, 333);
+
+ target1.mock_inferior.pid = old_ptid.pid ();
+ target1.mock_thread.ptid = old_ptid;
+ target2.mock_inferior.pid = old_ptid.pid ();
+ target2.mock_thread.ptid = old_ptid;
+
+ auto restore_inferior_ptid = make_scoped_restore (&inferior_ptid, old_ptid);
+ set_current_inferior (&target1.mock_inferior);
+
+ thread_change_ptid (&target1.mock_target, old_ptid, new_ptid);
+
+ gdb_assert (inferior_ptid == new_ptid);
+ }
+
+ /* A thread with the same ptid as inferior_ptid, but from another target,
+ changes ptid. */
+ {
+ scoped_restore_current_pspace_and_thread restore;
+
+ scoped_mock_context<test_target_ops> target1 (arch);
+ scoped_mock_context<test_target_ops> target2 (arch);
+ target2.mock_inferior.next = &target1.mock_inferior;
+
+ ptid_t old_ptid (111, 222);
+ ptid_t new_ptid (111, 333);
+
+ target1.mock_inferior.pid = old_ptid.pid ();
+ target1.mock_thread.ptid = old_ptid;
+ target2.mock_inferior.pid = old_ptid.pid ();
+ target2.mock_thread.ptid = old_ptid;
+
+ auto restore_inferior_ptid = make_scoped_restore (&inferior_ptid, old_ptid);
+ set_current_inferior (&target2.mock_inferior);
+
+ thread_change_ptid (&target1.mock_target, old_ptid, new_ptid);
+
+ gdb_assert (inferior_ptid == old_ptid);
+ }
}
+} /* namespace selftests */
+
+#endif /* GDB_SELF_TEST */
+
void _initialize_infrun ();
void
_initialize_infrun ()
/* 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\
show_observer_mode,
&setlist,
&showlist);
+
+#if GDB_SELF_TEST
+ selftests::register_test ("infrun_thread_ptid_changed",
+ selftests::infrun_thread_ptid_changed);
+#endif
}