#include "inf-loop.h"
#include "regcache.h"
#include "value.h"
-#include "observer.h"
+#include "observable.h"
#include "language.h"
#include "solib.h"
#include "main.h"
static ptid_t target_last_wait_ptid;
static struct target_waitstatus target_last_waitstatus;
-static void context_switch (ptid_t ptid);
-
void init_thread_stepping_state (struct thread_info *tss);
static const char follow_fork_mode_child[] = "child";
if (has_vforked)
{
/* Keep breakpoints list in sync. */
- remove_breakpoints_pid (ptid_get_pid (inferior_ptid));
+ remove_breakpoints_inf (current_inferior ());
}
- if (info_verbose || debug_infrun)
+ if (print_inferior_events)
{
/* Ensure that we have a process ptid. */
ptid_t process_ptid = pid_to_ptid (ptid_get_pid (child_ptid));
target_terminal::ours_for_output ();
fprintf_filtered (gdb_stdlog,
- _("Detaching after %s from child %s.\n"),
+ _("[Detaching after %s from child %s]\n"),
has_vforked ? "vfork" : "fork",
target_pid_to_str (process_ptid));
}
scoped_restore_current_pspace_and_thread restore_pspace_thread;
inferior_ptid = child_ptid;
- add_thread (inferior_ptid);
+ add_thread_silent (inferior_ptid);
set_current_inferior (child_inf);
child_inf->symfile_flags = SYMFILE_NO_READ;
struct inferior *parent_inf, *child_inf;
struct program_space *parent_pspace;
- if (info_verbose || debug_infrun)
+ if (print_inferior_events)
{
+ std::string parent_pid = target_pid_to_str (parent_ptid);
+ std::string child_pid = target_pid_to_str (child_ptid);
+
target_terminal::ours_for_output ();
fprintf_filtered (gdb_stdlog,
- _("Attaching after %s %s to child %s.\n"),
- target_pid_to_str (parent_ptid),
+ _("[Attaching after %s %s to child %s]\n"),
+ parent_pid.c_str (),
has_vforked ? "vfork" : "fork",
- target_pid_to_str (child_ptid));
+ child_pid.c_str ());
}
/* Add the new inferior first, so that the target_detach below
}
else if (detach_fork)
{
- if (info_verbose || debug_infrun)
+ if (print_inferior_events)
{
/* Ensure that we have a process ptid. */
- ptid_t process_ptid = pid_to_ptid (ptid_get_pid (child_ptid));
+ ptid_t process_ptid = pid_to_ptid (ptid_get_pid (parent_ptid));
target_terminal::ours_for_output ();
fprintf_filtered (gdb_stdlog,
- _("Detaching after fork from "
- "child %s.\n"),
+ _("[Detaching after fork from "
+ "parent %s]\n"),
target_pid_to_str (process_ptid));
}
informing the solib layer about this new process. */
inferior_ptid = child_ptid;
- add_thread (inferior_ptid);
+ add_thread_silent (inferior_ptid);
set_current_inferior (child_inf);
/* If this is a vfork child, then the address-space is shared
/* Check if we switched over from WAIT_PTID, since the event was
reported. */
- if (!ptid_equal (wait_ptid, minus_one_ptid)
- && !ptid_equal (inferior_ptid, wait_ptid))
+ if (wait_ptid != minus_one_ptid
+ && inferior_ptid != wait_ptid)
{
/* We did. Switch back to WAIT_PTID thread, to tell the
target to follow it (in either direction). We'll
afterwards refuse to resume, and inform the user what
happened. */
- switch_to_thread (wait_ptid);
+ thread_info *wait_thread
+ = find_thread_ptid (wait_ptid);
+ switch_to_thread (wait_thread);
should_resume = 0;
}
}
/* If we followed the child, switch to it... */
if (follow_child)
{
- switch_to_thread (child);
+ thread_info *child_thr = find_thread_ptid (child);
+ switch_to_thread (child_thr);
/* ... and preserve the stepping state, in case the
user was stepping over the fork call. */
/* Reset breakpoints in the child as appropriate. */
follow_inferior_reset_breakpoints ();
}
- else
- switch_to_thread (parent);
}
}
break;
{
int pid = * (int *) arg;
- if (ptid_get_pid (thread->ptid) == pid
- && is_running (thread->ptid)
- && !is_executing (thread->ptid)
+ if (thread->ptid.pid () == pid
+ && thread->state == THREAD_RUNNING
+ && !thread->executing
&& !thread->stop_requested
&& thread->suspend.stop_signal == GDB_SIGNAL_0)
{
"infrun: resuming vfork parent thread %s\n",
target_pid_to_str (thread->ptid));
- switch_to_thread (thread->ptid);
+ switch_to_thread (thread);
clear_proceed_status (0);
proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
}
maybe_restore_thread.emplace ();
/* We're letting loose of the parent. */
- tp = any_live_thread_of_process (inf->vfork_parent->pid);
- switch_to_thread (tp->ptid);
+ tp = any_live_thread_of_inferior (inf->vfork_parent);
+ switch_to_thread (tp);
/* We're about to detach from the parent, which implicitly
removes breakpoints from its address space. There's a
inf->aspace = NULL;
inf->pspace = NULL;
- if (debug_infrun || info_verbose)
+ if (print_inferior_events)
{
+ const char *pidstr
+ = target_pid_to_str (pid_to_ptid (inf->vfork_parent->pid));
+
target_terminal::ours_for_output ();
if (exec)
{
fprintf_filtered (gdb_stdlog,
- _("Detaching vfork parent process "
- "%d after child exec.\n"),
- inf->vfork_parent->pid);
+ _("[Detaching vfork parent %s "
+ "after child exec]\n"), pidstr);
}
else
{
fprintf_filtered (gdb_stdlog,
- _("Detaching vfork parent process "
- "%d after child exit.\n"),
- inf->vfork_parent->pid);
+ _("[Detaching vfork parent %s "
+ "after child exit]\n"), pidstr);
}
}
notifications. */
ALL_THREADS_SAFE (th, tmp)
if (ptid_get_pid (th->ptid) == pid && !ptid_equal (th->ptid, ptid))
- delete_thread (th->ptid);
+ delete_thread (th);
/* We also need to clear any left over stale state for the
leader/event thread. E.g., if there was any step-resume
struct displaced_step_inferior_state *next;
/* The process this displaced step state refers to. */
- int pid;
+ inferior *inf;
/* True if preparing a displaced step ever failed. If so, we won't
try displaced stepping for this inferior again. */
int failed_before;
- /* If this is not null_ptid, this is the thread carrying out a
+ /* If this is not nullptr, this is the thread carrying out a
displaced single-step in process PID. This thread's state will
require fixing up once it has completed its step. */
- ptid_t step_ptid;
+ thread_info *step_thread;
/* The architecture the thread had when we stepped it. */
struct gdbarch *step_gdbarch;
/* Get the displaced stepping state of process PID. */
static struct displaced_step_inferior_state *
-get_displaced_stepping_state (int pid)
+get_displaced_stepping_state (inferior *inf)
{
struct displaced_step_inferior_state *state;
for (state = displaced_step_inferior_states;
state != NULL;
state = state->next)
- if (state->pid == pid)
+ if (state->inf == inf)
return state;
return NULL;
for (state = displaced_step_inferior_states;
state != NULL;
state = state->next)
- if (!ptid_equal (state->step_ptid, null_ptid))
+ if (state->step_thread != nullptr)
return 1;
return 0;
step. */
static int
-displaced_step_in_progress_thread (ptid_t ptid)
+displaced_step_in_progress_thread (thread_info *thread)
{
struct displaced_step_inferior_state *displaced;
- gdb_assert (!ptid_equal (ptid, null_ptid));
+ gdb_assert (thread != NULL);
- displaced = get_displaced_stepping_state (ptid_get_pid (ptid));
+ displaced = get_displaced_stepping_state (thread->inf);
- return (displaced != NULL && ptid_equal (displaced->step_ptid, ptid));
+ return (displaced != NULL && displaced->step_thread == thread);
}
/* Return true if process PID has a thread doing a displaced step. */
static int
-displaced_step_in_progress (int pid)
+displaced_step_in_progress (inferior *inf)
{
struct displaced_step_inferior_state *displaced;
- displaced = get_displaced_stepping_state (pid);
- if (displaced != NULL && !ptid_equal (displaced->step_ptid, null_ptid))
+ displaced = get_displaced_stepping_state (inf);
+ if (displaced != NULL && displaced->step_thread != nullptr)
return 1;
return 0;
entry, if it already exists. Never returns NULL. */
static struct displaced_step_inferior_state *
-add_displaced_stepping_state (int pid)
+add_displaced_stepping_state (inferior *inf)
{
struct displaced_step_inferior_state *state;
for (state = displaced_step_inferior_states;
state != NULL;
state = state->next)
- if (state->pid == pid)
+ if (state->inf == inf)
return state;
state = XCNEW (struct displaced_step_inferior_state);
- state->pid = pid;
+ state->inf = inf;
state->next = displaced_step_inferior_states;
displaced_step_inferior_states = state;
get_displaced_step_closure_by_addr (CORE_ADDR addr)
{
struct displaced_step_inferior_state *displaced
- = get_displaced_stepping_state (ptid_get_pid (inferior_ptid));
+ = get_displaced_stepping_state (current_inferior ());
/* If checking the mode of displaced instruction in copy area. */
- if (displaced && !ptid_equal (displaced->step_ptid, null_ptid)
- && (displaced->step_copy == addr))
+ if (displaced != NULL
+ && displaced->step_thread != nullptr
+ && displaced->step_copy == addr)
return displaced->step_closure;
return NULL;
/* Remove the displaced stepping state of process PID. */
static void
-remove_displaced_stepping_state (int pid)
+remove_displaced_stepping_state (inferior *inf)
{
struct displaced_step_inferior_state *it, **prev_next_p;
- gdb_assert (pid != 0);
+ gdb_assert (inf != nullptr);
it = displaced_step_inferior_states;
prev_next_p = &displaced_step_inferior_states;
while (it)
{
- if (it->pid == pid)
+ if (it->inf == inf)
{
*prev_next_p = it->next;
xfree (it);
static void
infrun_inferior_exit (struct inferior *inf)
{
- remove_displaced_stepping_state (inf->pid);
+ remove_displaced_stepping_state (inf);
}
/* If ON, and the architecture supports it, GDB will use displaced
static int
use_displaced_stepping (struct thread_info *tp)
{
- struct regcache *regcache = get_thread_regcache (tp->ptid);
+ struct regcache *regcache = get_thread_regcache (tp);
struct gdbarch *gdbarch = regcache->arch ();
struct displaced_step_inferior_state *displaced_state;
- displaced_state = get_displaced_stepping_state (ptid_get_pid (tp->ptid));
+ displaced_state = get_displaced_stepping_state (tp->inf);
return (((can_use_displaced_stepping == AUTO_BOOLEAN_AUTO
&& target_is_non_stop_p ())
displaced_step_clear (struct displaced_step_inferior_state *displaced)
{
/* Indicate that there is no cleanup pending. */
- displaced->step_ptid = null_ptid;
+ displaced->step_thread = nullptr;
delete displaced->step_closure;
displaced->step_closure = NULL;
if this instruction can't be displaced stepped. */
static int
-displaced_step_prepare_throw (ptid_t ptid)
+displaced_step_prepare_throw (thread_info *tp)
{
struct cleanup *ignore_cleanups;
- struct thread_info *tp = find_thread_ptid (ptid);
- struct regcache *regcache = get_thread_regcache (ptid);
+ regcache *regcache = get_thread_regcache (tp);
struct gdbarch *gdbarch = regcache->arch ();
const address_space *aspace = regcache->aspace ();
CORE_ADDR original, copy;
/* We have to displaced step one thread at a time, as we only have
access to a single scratch space per inferior. */
- displaced = add_displaced_stepping_state (ptid_get_pid (ptid));
+ displaced = add_displaced_stepping_state (tp->inf);
- if (!ptid_equal (displaced->step_ptid, null_ptid))
+ if (displaced->step_thread != nullptr)
{
/* 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 (ptid));
+ target_pid_to_str (tp->ptid));
thread_step_over_chain_enqueue (tp);
return 0;
if (debug_displaced)
fprintf_unfiltered (gdb_stdlog,
"displaced: stepping %s now\n",
- target_pid_to_str (ptid));
+ target_pid_to_str (tp->ptid));
}
displaced_step_clear (displaced);
- scoped_restore save_inferior_ptid = make_scoped_restore (&inferior_ptid);
- inferior_ptid = ptid;
+ scoped_restore_current_thread restore_thread;
+
+ switch_to_thread (tp);
original = regcache_read_pc (regcache);
/* Save the information we need to fix things up if the step
succeeds. */
- displaced->step_ptid = ptid;
+ displaced->step_thread = tp;
displaced->step_gdbarch = gdbarch;
displaced->step_closure = closure;
displaced->step_original = original;
attempts at displaced stepping if we get a memory error. */
static int
-displaced_step_prepare (ptid_t ptid)
+displaced_step_prepare (thread_info *thread)
{
int prepared = -1;
TRY
{
- prepared = displaced_step_prepare_throw (ptid);
+ prepared = displaced_step_prepare_throw (thread);
}
CATCH (ex, RETURN_MASK_ERROR)
{
/* Disable further displaced stepping attempts. */
displaced_state
- = get_displaced_stepping_state (ptid_get_pid (ptid));
+ = get_displaced_stepping_state (thread->inf);
displaced_state->failed_before = 1;
}
END_CATCH
-1. If the thread wasn't displaced stepping, return 0. */
static int
-displaced_step_fixup (ptid_t event_ptid, enum gdb_signal signal)
+displaced_step_fixup (thread_info *event_thread, enum gdb_signal signal)
{
struct cleanup *old_cleanups;
struct displaced_step_inferior_state *displaced
- = get_displaced_stepping_state (ptid_get_pid (event_ptid));
+ = get_displaced_stepping_state (event_thread->inf);
int ret;
/* Was any thread of this process doing a displaced step? */
if (displaced == NULL)
return 0;
- /* Was this event for the pid we displaced? */
- if (ptid_equal (displaced->step_ptid, null_ptid)
- || ! ptid_equal (displaced->step_ptid, event_ptid))
+ /* Was this event for the thread we displaced? */
+ if (displaced->step_thread != event_thread)
return 0;
old_cleanups = make_cleanup (displaced_step_clear_cleanup, displaced);
- displaced_step_restore (displaced, displaced->step_ptid);
+ displaced_step_restore (displaced, displaced->step_thread->ptid);
/* Fixup may need to read memory/registers. Switch to the thread
that we're fixing up. Also, target_stopped_by_watchpoint checks
the current thread. */
- switch_to_thread (event_ptid);
+ switch_to_thread (event_thread);
/* Did the instruction complete successfully? */
if (signal == GDB_SIGNAL_TRAP
displaced->step_closure,
displaced->step_original,
displaced->step_copy,
- get_thread_regcache (displaced->step_ptid));
+ get_thread_regcache (displaced->step_thread));
ret = 1;
}
else
{
/* Since the instruction didn't complete, all we can do is
relocate the PC. */
- struct regcache *regcache = get_thread_regcache (event_ptid);
+ struct regcache *regcache = get_thread_regcache (event_thread);
CORE_ADDR pc = regcache_read_pc (regcache);
pc = displaced->step_original + (pc - displaced->step_copy);
do_cleanups (old_cleanups);
- displaced->step_ptid = null_ptid;
+ displaced->step_thread = nullptr;
return ret;
}
/* If this inferior already has a displaced step in process,
don't start a new one. */
- if (displaced_step_in_progress (ptid_get_pid (tp->ptid)))
+ if (displaced_step_in_progress (tp->inf))
continue;
step_what = thread_still_needs_step_over (tp);
if (!target_is_non_stop_p () && !step_what)
continue;
- switch_to_thread (tp->ptid);
+ switch_to_thread (tp);
reset_ecs (ecs, tp);
keep_going_pass_signal (ecs);
if (ptid_equal (inferior_ptid, old_ptid))
inferior_ptid = new_ptid;
-
- for (displaced = displaced_step_inferior_states;
- displaced;
- displaced = displaced->next)
- {
- if (ptid_equal (displaced->step_ptid, old_ptid))
- displaced->step_ptid = new_ptid;
- }
}
\f
return to the scratch pad area, which would no longer be
valid. */
if (step_over_info_valid_p ()
- || displaced_step_in_progress (ptid_get_pid (tp->ptid)))
+ || displaced_step_in_progress (tp->inf))
target_pass_signals (0, NULL);
else
target_pass_signals ((int) GDB_SIGNAL_LAST, signal_pass);
tp->suspend.stop_signal = GDB_SIGNAL_0;
if (target_can_async_p ())
- target_async (1);
+ {
+ target_async (1);
+ /* Tell the event loop we have an event to process. */
+ mark_async_event_handler (infrun_async_inferior_event_token);
+ }
return;
}
&& sig == GDB_SIGNAL_0
&& !current_inferior ()->waiting_for_vfork_done)
{
- int prepared = displaced_step_prepare (inferior_ptid);
+ int prepared = displaced_step_prepare (tp);
if (prepared == 0)
{
/* Update pc to reflect the new address from which we will
execute instructions due to displaced stepping. */
- pc = regcache_read_pc (get_thread_regcache (inferior_ptid));
+ pc = regcache_read_pc (get_thread_regcache (tp));
- displaced = get_displaced_stepping_state (ptid_get_pid (inferior_ptid));
+ displaced = get_displaced_stepping_state (tp->inf);
step = gdbarch_displaced_step_hw_singlestep (gdbarch,
displaced->step_closure);
}
&& use_displaced_stepping (tp)
&& !step_over_info_valid_p ())
{
- struct regcache *resume_regcache = get_thread_regcache (tp->ptid);
+ struct regcache *resume_regcache = get_thread_regcache (tp);
struct gdbarch *resume_gdbarch = resume_regcache->arch ();
CORE_ADDR actual_pc = regcache_read_pc (resume_regcache);
gdb_byte buf[4];
inferior->control.stop_soon = NO_STOP_QUIETLY;
}
- observer_notify_about_to_proceed ();
+ gdb::observers::about_to_proceed.notify ();
}
/* Returns true if TP is still stopped at a breakpoint that needs
{
if (tp->stepping_over_breakpoint)
{
- struct regcache *regcache = get_thread_regcache (tp->ptid);
+ struct regcache *regcache = get_thread_regcache (tp);
if (breakpoint_here_p (regcache->aspace (),
regcache_read_pc (regcache))
ptid_t resume_ptid;
struct execution_control_state ecss;
struct execution_control_state *ecs = &ecss;
- struct cleanup *old_chain;
int started;
/* If we're stopped at a fork/vfork, follow the branch set by the
if (addr == (CORE_ADDR) -1)
{
- if (pc == stop_pc
+ if (pc == tp->suspend.stop_pc
&& breakpoint_here_p (aspace, pc) == ordinary_breakpoint_here
&& execution_direction != EXEC_REVERSE)
/* There is a breakpoint at the address we will resume at,
/* If an exception is thrown from this point on, make sure to
propagate GDB's knowledge of the executing state to the
frontend/user running state. */
- old_chain = make_cleanup (finish_thread_state_cleanup, &resume_ptid);
+ scoped_finish_thread_state finish_state (resume_ptid);
/* Even if RESUME_PTID is a wildcard, and we end up resuming fewer
threads (e.g., we might need to set threads stepping over
target_pid_to_str (tp->ptid));
reset_ecs (ecs, tp);
- switch_to_thread (tp->ptid);
+ switch_to_thread (tp);
keep_going_pass_signal (ecs);
if (!ecs->wait_some_more)
error (_("Command aborted."));
{
/* The thread wasn't started, and isn't queued, run it now. */
reset_ecs (ecs, tp);
- switch_to_thread (tp->ptid);
+ switch_to_thread (tp);
keep_going_pass_signal (ecs);
if (!ecs->wait_some_more)
error (_("Command aborted."));
target_commit_resume ();
- discard_cleanups (old_chain);
+ finish_state.release ();
/* Tell the event loop to wait for it to stop. If the target
supports asynchronous execution, it'll do this from within
/* 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 (¤t_target, from_tty);
+ post_create_inferior (current_top_target (), from_tty);
normal_stop ();
}
&& (tp->suspend.stop_reason == TARGET_STOPPED_BY_SW_BREAKPOINT
|| tp->suspend.stop_reason == TARGET_STOPPED_BY_HW_BREAKPOINT))
{
- struct regcache *regcache = get_thread_regcache (tp->ptid);
+ struct regcache *regcache = get_thread_regcache (tp);
struct gdbarch *gdbarch = regcache->arch ();
CORE_ADDR pc;
int discard = 0;
fprintf_unfiltered (gdb_stdlog,
"infrun: PC of %s changed. was=%s, now=%s\n",
target_pid_to_str (tp->ptid),
- paddress (gdbarch, tp->prev_pc),
+ paddress (gdbarch, tp->suspend.stop_pc),
paddress (gdbarch, pc));
discard = 1;
}
struct gdbarch *gdbarch;
int decr_pc;
- regcache = get_thread_regcache (tp->ptid);
+ regcache = get_thread_regcache (tp);
gdbarch = regcache->arch ();
decr_pc = gdbarch_decr_pc_after_break (gdbarch);
{
struct inferior *inf = current_inferior ();
ptid_t pid_ptid = pid_to_ptid (inf->pid);
- struct displaced_step_inferior_state *displaced;
- displaced = get_displaced_stepping_state (inf->pid);
+ displaced_step_inferior_state *displaced = get_displaced_stepping_state (inf);
/* Is any thread of this process displaced stepping? If not,
there's nothing else to do. */
- if (displaced == NULL || ptid_equal (displaced->step_ptid, null_ptid))
+ if (displaced == NULL || displaced->step_thread == nullptr)
return;
if (debug_infrun)
scoped_restore restore_detaching = make_scoped_restore (&inf->detaching, true);
- while (!ptid_equal (displaced->step_ptid, null_ptid))
+ while (displaced->step_thread != nullptr)
{
- struct cleanup *old_chain_2;
struct execution_control_state ecss;
struct execution_control_state *ecs;
/* If an error happens while handling the event, propagate GDB's
knowledge of the executing state to the frontend/user running
state. */
- old_chain_2 = make_cleanup (finish_thread_state_cleanup,
- &minus_one_ptid);
+ scoped_finish_thread_state finish_state (minus_one_ptid);
/* Now figure out what to do with the result of the result. */
handle_inferior_event (ecs);
/* No error, don't finish the state yet. */
- discard_cleanups (old_chain_2);
+ finish_state.release ();
/* Breakpoints and watchpoints are not installed on the target
at this point, and signals are passed directly to the
wait_for_inferior (void)
{
struct cleanup *old_cleanups;
- struct cleanup *thread_state_chain;
if (debug_infrun)
fprintf_unfiltered
/* If an error happens while handling the event, propagate GDB's
knowledge of the executing state to the frontend/user running
state. */
- thread_state_chain = make_cleanup (finish_thread_state_cleanup, &minus_one_ptid);
+ scoped_finish_thread_state finish_state (minus_one_ptid);
while (1)
{
}
/* No error, don't finish the state yet. */
- discard_cleanups (thread_state_chain);
+ finish_state.release ();
do_cleanups (old_cleanups);
}
if (thr == ecs->event_thread)
continue;
- switch_to_thread (thr->ptid);
+ switch_to_thread (thr);
thread_fsm_clean_up (thr->thread_fsm, thr);
}
if (ecs->event_thread != NULL)
- switch_to_thread (ecs->event_thread->ptid);
+ switch_to_thread (ecs->event_thread);
}
}
&& !gdb_in_secondary_prompt_p (ui))
{
target_terminal::ours ();
- observer_notify_sync_execution_done ();
+ gdb::observers::sync_execution_done.notify ();
ui_register_input_event_handler (ui);
}
}
struct execution_control_state ecss;
struct execution_control_state *ecs = &ecss;
struct cleanup *old_chain = make_cleanup (null_cleanup, NULL);
- struct cleanup *ts_old_chain;
int cmd_done = 0;
ptid_t waiton_ptid = minus_one_ptid;
debugging. If we're looking at traceframes while the target is
running, we're going to need to get back to that mode after
handling the event. */
+ gdb::optional<scoped_restore_current_traceframe> maybe_restore_traceframe;
if (non_stop)
{
- make_cleanup_restore_current_traceframe ();
+ maybe_restore_traceframe.emplace ();
set_current_traceframe (-1);
}
/* If an error happens while handling the event, propagate GDB's
knowledge of the executing state to the frontend/user running
state. */
- if (!target_is_non_stop_p ())
- ts_old_chain = make_cleanup (finish_thread_state_cleanup, &minus_one_ptid);
- else
- ts_old_chain = make_cleanup (finish_thread_state_cleanup, &ecs->ptid);
+ ptid_t finish_ptid = !target_is_non_stop_p () ? minus_one_ptid : ecs->ptid;
+ scoped_finish_thread_state finish_state (finish_ptid);
/* Get executed before make_cleanup_restore_current_thread above to apply
still for the thread which has thrown the exception. */
- make_bpstat_clear_actions_cleanup ();
+ struct cleanup *ts_old_chain = make_bpstat_clear_actions_cleanup ();
make_cleanup (delete_just_stopped_threads_infrun_breakpoints_cleanup, NULL);
struct inferior *inf = find_inferior_ptid (ecs->ptid);
int should_stop = 1;
struct thread_info *thr = ecs->event_thread;
- int should_notify_stop = 1;
delete_just_stopped_threads_infrun_breakpoints ();
}
else
{
+ int should_notify_stop = 1;
+ int proceeded = 0;
+
clean_up_just_stopped_threads_fsms (ecs);
if (thr != NULL && thr->thread_fsm != NULL)
if (should_notify_stop)
{
- int proceeded = 0;
-
/* We may not find an inferior if this was a process exit. */
if (inf == NULL || inf->control.stop_soon == NO_STOP_QUIETLY)
proceeded = normal_stop ();
+ }
- if (!proceeded)
- {
- inferior_event_handler (INF_EXEC_COMPLETE, NULL);
- cmd_done = 1;
- }
+ if (!proceeded)
+ {
+ inferior_event_handler (INF_EXEC_COMPLETE, NULL);
+ cmd_done = 1;
}
}
}
- /* No error, don't finish the thread states yet. */
discard_cleanups (ts_old_chain);
+ /* No error, don't finish the thread states yet. */
+ finish_state.release ();
+
/* Revert thread and frame. */
do_cleanups (old_chain);
if (cmd_done
&& exec_done_display_p
- && (ptid_equal (inferior_ptid, null_ptid)
- || !is_running (inferior_ptid)))
+ && (inferior_ptid == null_ptid
+ || inferior_thread ()->state != THREAD_RUNNING))
printf_unfiltered (_("completed.\n"));
}
/* Switch thread contexts. */
static void
-context_switch (ptid_t ptid)
+context_switch (execution_control_state *ecs)
{
- if (debug_infrun && !ptid_equal (ptid, inferior_ptid))
+ if (debug_infrun
+ && ecs->ptid != inferior_ptid
+ && ecs->event_thread != inferior_thread ())
{
fprintf_unfiltered (gdb_stdlog, "infrun: Switching context from %s ",
target_pid_to_str (inferior_ptid));
fprintf_unfiltered (gdb_stdlog, "to %s\n",
- target_pid_to_str (ptid));
+ target_pid_to_str (ecs->ptid));
}
- switch_to_thread (ptid);
+ switch_to_thread (ecs->event_thread);
}
/* If the target can't tell whether we've hit breakpoints
/* If this target does not decrement the PC after breakpoints, then
we have nothing to do. */
- regcache = get_thread_regcache (thread->ptid);
+ regcache = get_thread_regcache (thread);
gdbarch = regcache->arch ();
decr_pc = gdbarch_decr_pc_after_break (gdbarch);
struct regcache *regcache;
int syscall_number;
- if (!ptid_equal (ecs->ptid, inferior_ptid))
- context_switch (ecs->ptid);
+ context_switch (ecs);
- regcache = get_thread_regcache (ecs->ptid);
+ regcache = get_thread_regcache (ecs->event_thread);
syscall_number = ecs->ws.value.syscall_number;
- stop_pc = regcache_read_pc (regcache);
+ ecs->event_thread->suspend.stop_pc = regcache_read_pc (regcache);
if (catch_syscall_enabled () > 0
&& catching_syscall_number (syscall_number) > 0)
ecs->event_thread->control.stop_bpstat
= bpstat_stop_status (regcache->aspace (),
- stop_pc, ecs->ptid, &ecs->ws);
+ ecs->event_thread->suspend.stop_pc,
+ ecs->event_thread, &ecs->ws);
if (handle_stop_requested (ecs))
return 0;
{
/* 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 (stop_pc, &ecs->stop_func_name,
+ find_pc_partial_function (ecs->event_thread->suspend.stop_pc,
+ &ecs->stop_func_name,
&ecs->stop_func_start, &ecs->stop_func_end);
ecs->stop_func_start
+= gdbarch_deprecated_function_start_offset (gdbarch);
}
-/* Return the STOP_SOON field of the inferior pointed at by PTID. */
+/* Return the STOP_SOON field of the inferior pointed at by ECS. */
static enum stop_kind
-get_inferior_stop_soon (ptid_t ptid)
+get_inferior_stop_soon (execution_control_state *ecs)
{
- struct inferior *inf = find_inferior_ptid (ptid);
+ struct inferior *inf = find_inferior_ptid (ecs->ptid);
gdb_assert (inf != NULL);
return inf->control.stop_soon;
/* Generate thread_stopped_by_hw_breakpoint. */
THREAD_STOPPED_BY (hw_breakpoint)
-/* Cleanups that switches to the PTID pointed at by PTID_P. */
-
-static void
-switch_to_thread_cleanup (void *ptid_p)
-{
- ptid_t ptid = *(ptid_t *) ptid_p;
-
- switch_to_thread (ptid);
-}
-
/* Save the thread's event and stop reason to process it later. */
static void
save_waitstatus (struct thread_info *tp, struct target_waitstatus *ws)
{
- struct regcache *regcache;
-
if (debug_infrun)
{
std::string statstr = target_waitstatus_to_string (ws);
tp->suspend.waitstatus = *ws;
tp->suspend.waitstatus_pending_p = 1;
- regcache = get_thread_regcache (tp->ptid);
+ struct regcache *regcache = get_thread_regcache (tp);
const address_space *aspace = regcache->aspace ();
if (ws->kind == TARGET_WAITKIND_STOPPED
/* We may need multiple passes to discover all threads. */
int pass;
int iterations = 0;
- ptid_t entry_ptid;
struct cleanup *old_chain;
gdb_assert (target_is_non_stop_p ());
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, "infrun: stop_all_threads\n");
- entry_ptid = inferior_ptid;
- old_chain = make_cleanup (switch_to_thread_cleanup, &entry_ptid);
+ scoped_restore_current_thread restore_thread;
target_thread_events (1);
- make_cleanup (disable_thread_events, NULL);
+ old_chain = make_cleanup (disable_thread_events, NULL);
/* Request threads to stop, and then wait for the stops. Because
threads we already know about can spawn more threads while we're
pass = -1;
event_ptid = wait_one (&ws);
+
if (ws.kind == TARGET_WAITKIND_NO_RESUMED)
{
/* All resumed threads exited. */
}
else
{
- struct inferior *inf;
+ inferior *inf;
t = find_thread_ptid (event_ptid);
if (t == NULL)
t->suspend.waitstatus.kind = TARGET_WAITKIND_IGNORE;
t->suspend.waitstatus_pending_p = 0;
- if (displaced_step_fixup (t->ptid, GDB_SIGNAL_0) < 0)
+ if (displaced_step_fixup (t, GDB_SIGNAL_0) < 0)
{
/* Add it back to the step-over queue. */
if (debug_infrun)
sig = (ws.kind == TARGET_WAITKIND_STOPPED
? ws.value.sig : GDB_SIGNAL_0);
- if (displaced_step_fixup (t->ptid, sig) < 0)
+ if (displaced_step_fixup (t, sig) < 0)
{
/* Add it back to the step-over queue. */
t->control.trap_expected = 0;
thread_step_over_chain_enqueue (t);
}
- regcache = get_thread_regcache (t->ptid);
+ regcache = get_thread_regcache (t);
t->suspend.stop_pc = regcache_read_pc (regcache);
if (debug_infrun)
if (inf->pid == 0)
continue;
- thread = any_live_thread_of_process (inf->pid);
+ thread_info *thread = any_live_thread_of_inferior (inf);
if (thread == NULL)
{
if (debug_infrun)
|| ecs->ws.value.sig == GDB_SIGNAL_SEGV
|| ecs->ws.value.sig == GDB_SIGNAL_EMT))
{
- struct regcache *regcache = get_thread_regcache (ecs->ptid);
+ struct regcache *regcache = get_thread_regcache (ecs->event_thread);
if (breakpoint_inserted_here_p (regcache->aspace (),
regcache_read_pc (regcache)))
case TARGET_WAITKIND_LOADED:
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_LOADED\n");
- if (!ptid_equal (ecs->ptid, inferior_ptid))
- context_switch (ecs->ptid);
+ context_switch (ecs);
/* Ignore gracefully during startup of the inferior, as it might
be the shell which has just loaded some objects, otherwise
add the symbols for the newly loaded objects. Also ignore at
the full list of libraries once the connection is
established. */
- stop_soon = get_inferior_stop_soon (ecs->ptid);
+ stop_soon = get_inferior_stop_soon (ecs);
if (stop_soon == NO_STOP_QUIETLY)
{
struct regcache *regcache;
- regcache = get_thread_regcache (ecs->ptid);
+ regcache = get_thread_regcache (ecs->event_thread);
handle_solib_event ();
ecs->event_thread->control.stop_bpstat
= bpstat_stop_status (regcache->aspace (),
- stop_pc, ecs->ptid, &ecs->ws);
+ ecs->event_thread->suspend.stop_pc,
+ ecs->event_thread, &ecs->ws);
if (handle_stop_requested (ecs))
return;
fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_SPURIOUS\n");
if (handle_stop_requested (ecs))
return;
- if (!ptid_equal (ecs->ptid, inferior_ptid))
- context_switch (ecs->ptid);
+ context_switch (ecs);
resume (GDB_SIGNAL_0);
prepare_to_wait (ecs);
return;
fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_THREAD_CREATED\n");
if (handle_stop_requested (ecs))
return;
- if (!ptid_equal (ecs->ptid, inferior_ptid))
- context_switch (ecs->ptid);
+ context_switch (ecs);
if (!switch_back_to_stepped_thread (ecs))
keep_going (ecs);
return;
/* Support the --return-child-result option. */
return_child_result_value = ecs->ws.value.integer;
- observer_notify_exited (ecs->ws.value.integer);
+ gdb::observers::exited.notify (ecs->ws.value.integer);
}
else
{
- struct regcache *regcache = get_thread_regcache (ecs->ptid);
- struct gdbarch *gdbarch = regcache->arch ();
+ struct gdbarch *gdbarch = current_inferior ()->gdbarch;
if (gdbarch_gdb_signal_to_target_p (gdbarch))
{
Cannot fill $_exitsignal with the correct signal number.\n"));
}
- observer_notify_signal_exited (ecs->ws.value.sig);
+ gdb::observers::signal_exited.notify (ecs->ws.value.sig);
}
gdb_flush (gdb_stdout);
/* Check whether the inferior is displaced stepping. */
{
- struct regcache *regcache = get_thread_regcache (ecs->ptid);
+ struct regcache *regcache = get_thread_regcache (ecs->event_thread);
struct gdbarch *gdbarch = regcache->arch ();
/* If checking displaced stepping is supported, and thread
ecs->ptid is displaced stepping. */
- if (displaced_step_in_progress_thread (ecs->ptid))
+ if (displaced_step_in_progress_thread (ecs->event_thread))
{
struct inferior *parent_inf
= find_inferior_ptid (ecs->ptid);
has been done. Perform cleanup for parent process here. Note
that this operation also cleans up the child process for vfork,
because their pages are shared. */
- displaced_step_fixup (ecs->ptid, GDB_SIGNAL_TRAP);
+ displaced_step_fixup (ecs->event_thread, GDB_SIGNAL_TRAP);
/* Start a new step-over in another thread if there's one
that needs it. */
start_step_over ();
if (ecs->ws.kind == TARGET_WAITKIND_FORKED)
{
struct displaced_step_inferior_state *displaced
- = get_displaced_stepping_state (ptid_get_pid (ecs->ptid));
+ = get_displaced_stepping_state (parent_inf);
/* Restore scratch pad for child process. */
displaced_step_restore (displaced, ecs->ws.value.related_pid);
}
}
- if (!ptid_equal (ecs->ptid, inferior_ptid))
- context_switch (ecs->ptid);
+ context_switch (ecs);
/* Immediately detach breakpoints from the child before there's
any chance of letting the user delete breakpoints from the
and not immediately. */
ecs->event_thread->pending_follow = ecs->ws;
- stop_pc = regcache_read_pc (get_thread_regcache (ecs->ptid));
+ ecs->event_thread->suspend.stop_pc
+ = regcache_read_pc (get_thread_regcache (ecs->event_thread));
ecs->event_thread->control.stop_bpstat
= bpstat_stop_status (get_current_regcache ()->aspace (),
- stop_pc, ecs->ptid, &ecs->ws);
+ ecs->event_thread->suspend.stop_pc,
+ ecs->event_thread, &ecs->ws);
if (handle_stop_requested (ecs))
return;
watchpoints, for example, always appear in the bpstat. */
if (!bpstat_causes_stop (ecs->event_thread->control.stop_bpstat))
{
- ptid_t parent;
- ptid_t child;
int should_resume;
int follow_child
= (follow_fork_mode_string == follow_fork_mode_child);
should_resume = follow_fork ();
- parent = ecs->ptid;
- child = ecs->ws.value.related_pid;
+ thread_info *parent = ecs->event_thread;
+ thread_info *child = find_thread_ptid (ecs->ws.value.related_pid);
/* At this point, the parent is marked running, and the
child is marked stopped. */
/* If not resuming the parent, mark it stopped. */
if (follow_child && !detach_fork && !non_stop && !sched_multi)
- set_running (parent, 0);
+ parent->set_running (false);
/* If resuming the child, mark it running. */
if (follow_child || (!detach_fork && (non_stop || sched_multi)))
- set_running (child, 1);
+ child->set_running (true);
/* In non-stop mode, also resume the other branch. */
if (!detach_fork && (non_stop
fprintf_unfiltered (gdb_stdlog,
"infrun: TARGET_WAITKIND_VFORK_DONE\n");
- if (!ptid_equal (ecs->ptid, inferior_ptid))
- context_switch (ecs->ptid);
+ context_switch (ecs);
current_inferior ()->waiting_for_vfork_done = 0;
current_inferior ()->pspace->breakpoints_not_allowed = 0;
/* Note we can't read registers yet (the stop_pc), because we
don't yet know the inferior's post-exec architecture.
'stop_pc' is explicitly read below instead. */
- if (!ptid_equal (ecs->ptid, inferior_ptid))
- switch_to_thread_no_regs (ecs->event_thread);
+ switch_to_thread_no_regs (ecs->event_thread);
/* Do whatever is necessary to the parent branch of the vfork. */
handle_vfork_child_exec_or_exit (1);
stop. */
follow_exec (inferior_ptid, ecs->ws.value.execd_pathname);
- stop_pc = regcache_read_pc (get_thread_regcache (ecs->ptid));
-
/* In follow_exec we may have deleted the original thread and
created a new one. Make sure that the event thread is the
execd thread for that case (this is a nop otherwise). */
ecs->event_thread = inferior_thread ();
+ ecs->event_thread->suspend.stop_pc
+ = regcache_read_pc (get_thread_regcache (ecs->event_thread));
+
ecs->event_thread->control.stop_bpstat
= bpstat_stop_status (get_current_regcache ()->aspace (),
- stop_pc, ecs->ptid, &ecs->ws);
+ ecs->event_thread->suspend.stop_pc,
+ ecs->event_thread, &ecs->ws);
/* Note that this may be referenced from inside
bpstat_stop_status above, through inferior_has_execd. */
/* Reverse execution: target ran out of history info. */
/* Switch to the stopped thread. */
- if (!ptid_equal (ecs->ptid, inferior_ptid))
- context_switch (ecs->ptid);
+ context_switch (ecs);
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, "infrun: stopped\n");
delete_just_stopped_threads_single_step_breakpoints ();
- stop_pc = regcache_read_pc (get_thread_regcache (inferior_ptid));
+ ecs->event_thread->suspend.stop_pc
+ = regcache_read_pc (get_thread_regcache (inferior_thread ()));
if (handle_stop_requested (ecs))
return;
- observer_notify_no_history ();
+ gdb::observers::no_history.notify ();
stop_waiting (ecs);
return;
}
"infrun: restart threads: [%s] continuing\n",
target_pid_to_str (tp->ptid));
reset_ecs (ecs, tp);
- switch_to_thread (tp->ptid);
+ switch_to_thread (tp);
keep_going_pass_signal (ecs);
}
}
{
int had_step_over_info;
- displaced_step_fixup (ecs->ptid,
+ displaced_step_fixup (ecs->event_thread,
ecs->event_thread->suspend.stop_signal);
had_step_over_info = step_over_info_valid_p ();
another thread has a pending event for this breakpoint too,
we'd discard its event (because the breakpoint that
originally caused the event was no longer inserted). */
- context_switch (ecs->ptid);
+ context_switch (ecs);
insert_breakpoints ();
restart_threads (ecs->event_thread);
gdb_assert (!tp->executing);
- regcache = get_thread_regcache (tp->ptid);
+ regcache = get_thread_regcache (tp);
tp->suspend.stop_pc = regcache_read_pc (regcache);
if (debug_infrun)
&& ecs->event_thread->suspend.stop_signal == GDB_SIGNAL_TRAP)
ecs->event_thread->suspend.stop_signal = GDB_SIGNAL_0;
- stop_pc = regcache_read_pc (get_thread_regcache (ecs->ptid));
+ ecs->event_thread->suspend.stop_pc
+ = regcache_read_pc (get_thread_regcache (ecs->event_thread));
if (debug_infrun)
{
- struct regcache *regcache = get_thread_regcache (ecs->ptid);
+ struct regcache *regcache = get_thread_regcache (ecs->event_thread);
struct gdbarch *gdbarch = regcache->arch ();
scoped_restore save_inferior_ptid = make_scoped_restore (&inferior_ptid);
inferior_ptid = ecs->ptid;
fprintf_unfiltered (gdb_stdlog, "infrun: stop_pc = %s\n",
- paddress (gdbarch, stop_pc));
+ paddress (gdbarch,
+ ecs->event_thread->suspend.stop_pc));
if (target_stopped_by_watchpoint ())
{
CORE_ADDR addr;
fprintf_unfiltered (gdb_stdlog, "infrun: stopped by watchpoint\n");
- if (target_stopped_data_address (¤t_target, &addr))
+ if (target_stopped_data_address (current_top_target (), &addr))
fprintf_unfiltered (gdb_stdlog,
"infrun: stopped data address = %s\n",
paddress (gdbarch, addr));
/* This is originated from start_remote(), start_inferior() and
shared libraries hook functions. */
- stop_soon = get_inferior_stop_soon (ecs->ptid);
+ stop_soon = get_inferior_stop_soon (ecs);
if (stop_soon == STOP_QUIETLY || stop_soon == STOP_QUIETLY_REMOTE)
{
- if (!ptid_equal (ecs->ptid, inferior_ptid))
- context_switch (ecs->ptid);
+ context_switch (ecs);
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, "infrun: quietly stopped\n");
stop_print_frame = 1;
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, "infrun: context switch\n");
- context_switch (ecs->ptid);
+ context_switch (ecs);
if (deprecated_context_hook)
- deprecated_context_hook (ptid_to_global_thread_id (ecs->ptid));
+ deprecated_context_hook (ecs->event_thread->global_num);
}
/* At this point, get hold of the now-current thread's frame. */
struct regcache *regcache;
CORE_ADDR pc;
- regcache = get_thread_regcache (ecs->ptid);
+ regcache = get_thread_regcache (ecs->event_thread);
const address_space *aspace = regcache->aspace ();
pc = regcache_read_pc (regcache);
ecs->event_thread->control.stop_step = 0;
stop_print_frame = 1;
stopped_by_random_signal = 0;
+ bpstat stop_chain = NULL;
/* Hide inlined functions starting here, unless we just performed stepi or
nexti. After stepi and nexti, always show the innermost frame (not any
inline function call sites). */
if (ecs->event_thread->control.step_range_end != 1)
{
- const address_space *aspace =
- get_thread_regcache (ecs->ptid)->aspace ();
+ const address_space *aspace
+ = get_thread_regcache (ecs->event_thread)->aspace ();
/* skip_inline_frames is expensive, so we avoid it if we can
determine that the address is one where functions cannot have
user had set a breakpoint on that inlined code, the missing
skip_inline_frames call would break things. Fortunately
that's an extremely unlikely scenario. */
- if (!pc_at_non_inline_function (aspace, stop_pc, &ecs->ws)
+ if (!pc_at_non_inline_function (aspace,
+ ecs->event_thread->suspend.stop_pc,
+ &ecs->ws)
&& !(ecs->event_thread->suspend.stop_signal == GDB_SIGNAL_TRAP
&& ecs->event_thread->control.trap_expected
&& pc_at_non_inline_function (aspace,
ecs->event_thread->prev_pc,
&ecs->ws)))
{
- skip_inline_frames (ecs->ptid);
+ stop_chain = build_bpstat_chain (aspace,
+ ecs->event_thread->suspend.stop_pc,
+ &ecs->ws);
+ skip_inline_frames (ecs->event_thread, stop_chain);
/* Re-fetch current thread's frame in case that invalidated
the frame cache. */
handles this event. */
ecs->event_thread->control.stop_bpstat
= bpstat_stop_status (get_current_regcache ()->aspace (),
- stop_pc, ecs->ptid, &ecs->ws);
+ ecs->event_thread->suspend.stop_pc,
+ ecs->event_thread, &ecs->ws, stop_chain);
/* Following in case break condition called a
function. */
been removed. */
if (random_signal && target_stopped_by_sw_breakpoint ())
{
- if (program_breakpoint_here_p (gdbarch, stop_pc))
+ if (program_breakpoint_here_p (gdbarch,
+ ecs->event_thread->suspend.stop_pc))
{
struct regcache *regcache;
int decr_pc;
/* Re-adjust PC to what the program would see if GDB was not
debugging it. */
- regcache = get_thread_regcache (ecs->event_thread->ptid);
+ regcache = get_thread_regcache (ecs->event_thread);
decr_pc = gdbarch_decr_pc_after_break (gdbarch);
if (decr_pc != 0)
{
restore_operation_disable.emplace
(record_full_gdb_operation_disable_set ());
- regcache_write_pc (regcache, stop_pc + decr_pc);
+ regcache_write_pc (regcache,
+ ecs->event_thread->suspend.stop_pc + decr_pc);
}
}
else
{
/* The signal table tells us to print about this signal. */
target_terminal::ours_for_output ();
- observer_notify_signal_received (ecs->event_thread->suspend.stop_signal);
+ gdb::observers::signal_received.notify (ecs->event_thread->suspend.stop_signal);
target_terminal::inferior ();
}
if (signal_program[ecs->event_thread->suspend.stop_signal] == 0)
ecs->event_thread->suspend.stop_signal = GDB_SIGNAL_0;
- if (ecs->event_thread->prev_pc == stop_pc
+ if (ecs->event_thread->prev_pc == ecs->event_thread->suspend.stop_pc
&& ecs->event_thread->control.trap_expected
&& ecs->event_thread->control.step_resume_breakpoint == NULL)
{
}
if (ecs->event_thread->suspend.stop_signal != GDB_SIGNAL_0
- && (pc_in_thread_step_range (stop_pc, ecs->event_thread)
+ && (pc_in_thread_step_range (ecs->event_thread->suspend.stop_pc,
+ ecs->event_thread)
|| ecs->event_thread->control.step_range_end == 1)
&& frame_id_eq (get_stack_frame_id (frame),
ecs->event_thread->control.step_stack_frame_id)
return;
}
fill_in_stop_func (gdbarch, ecs);
- if (stop_pc == ecs->stop_func_start
+ if (ecs->event_thread->suspend.stop_pc == ecs->stop_func_start
&& execution_direction == EXEC_REVERSE)
{
/* We are stepping over a function call in reverse, and just
through a function epilogue and therefore must detect when
the current-frame changes in the middle of a line. */
- if (pc_in_thread_step_range (stop_pc, ecs->event_thread)
+ if (pc_in_thread_step_range (ecs->event_thread->suspend.stop_pc,
+ ecs->event_thread)
&& (execution_direction != EXEC_REVERSE
|| frame_id_eq (get_frame_id (frame),
ecs->event_thread->control.step_frame_id)))
/* When stepping backward, stop at beginning of line range
(unless it's the function entry point, in which case
keep going back to the call point). */
+ CORE_ADDR stop_pc = ecs->event_thread->suspend.stop_pc;
if (stop_pc == ecs->event_thread->control.step_range_start
&& stop_pc != ecs->stop_func_start
&& execution_direction == EXEC_REVERSE)
if (execution_direction != EXEC_REVERSE
&& ecs->event_thread->control.step_over_calls == STEP_OVER_UNDEBUGGABLE
- && in_solib_dynsym_resolve_code (stop_pc))
+ && in_solib_dynsym_resolve_code (ecs->event_thread->suspend.stop_pc))
{
CORE_ADDR pc_after_resolver =
- gdbarch_skip_solib_resolver (gdbarch, stop_pc);
+ gdbarch_skip_solib_resolver (gdbarch,
+ ecs->event_thread->suspend.stop_pc);
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog,
return;
}
+ /* Step through an indirect branch thunk. */
+ if (ecs->event_thread->control.step_over_calls != STEP_OVER_NONE
+ && 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");
+ keep_going (ecs);
+ return;
+ }
+
if (ecs->event_thread->control.step_range_end != 1
&& (ecs->event_thread->control.step_over_calls == STEP_OVER_UNDEBUGGABLE
|| ecs->event_thread->control.step_over_calls == STEP_OVER_ALL)
call check below as on some targets return trampolines look
like subroutine calls (MIPS16 return thunks). */
if (gdbarch_in_solib_return_trampoline (gdbarch,
- stop_pc, ecs->stop_func_name)
+ ecs->event_thread->suspend.stop_pc,
+ ecs->stop_func_name)
&& ecs->event_thread->control.step_over_calls != STEP_OVER_NONE)
{
/* Determine where this trampoline returns. */
- CORE_ADDR real_stop_pc;
-
- real_stop_pc = gdbarch_skip_trampoline_code (gdbarch, frame, stop_pc);
+ CORE_ADDR stop_pc = ecs->event_thread->suspend.stop_pc;
+ CORE_ADDR real_stop_pc
+ = gdbarch_skip_trampoline_code (gdbarch, frame, stop_pc);
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog,
&& (!frame_id_eq (ecs->event_thread->control.step_stack_frame_id,
outer_frame_id)
|| (ecs->event_thread->control.step_start_function
- != find_pc_function (stop_pc)))))
+ != find_pc_function (ecs->event_thread->suspend.stop_pc)))))
{
+ CORE_ADDR stop_pc = ecs->event_thread->suspend.stop_pc;
CORE_ADDR real_stop_pc;
if (debug_infrun)
if (execution_direction == EXEC_REVERSE
&& ecs->event_thread->control.step_over_calls != STEP_OVER_NONE)
{
+ CORE_ADDR stop_pc = ecs->event_thread->suspend.stop_pc;
+
if (gdbarch_skip_trampoline_code (gdbarch, frame, stop_pc)
|| (ecs->stop_func_start == 0
&& in_solib_dynsym_resolve_code (stop_pc)))
}
}
- stop_pc_sal = find_pc_line (stop_pc, 0);
+ stop_pc_sal = find_pc_line (ecs->event_thread->suspend.stop_pc, 0);
/* NOTE: tausq/2004-05-24: This if block used to be done before all
the trampoline processing logic, however, there are some trampolines
if (frame_id_eq (get_frame_id (get_current_frame ()),
ecs->event_thread->control.step_frame_id)
- && inline_skipped_frames (ecs->ptid))
+ && inline_skipped_frames (ecs->event_thread))
{
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog,
if (call_sal.line == ecs->event_thread->current_line
&& call_sal.symtab == ecs->event_thread->current_symtab)
- step_into_inline_frame (ecs->ptid);
+ step_into_inline_frame (ecs->event_thread);
end_stepping_range (ecs);
return;
return;
}
- if ((stop_pc == stop_pc_sal.pc)
+ if ((ecs->event_thread->suspend.stop_pc == stop_pc_sal.pc)
&& (ecs->event_thread->current_line != stop_pc_sal.line
|| ecs->event_thread->current_symtab != stop_pc_sal.symtab))
{
stepping thread is still alive. For that reason, we need to
synchronously query the target now. */
- if (is_exited (tp->ptid)
- || !target_thread_alive (tp->ptid))
+ 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");
- delete_thread (tp->ptid);
+ delete_thread (tp);
return 0;
}
"infrun: resuming previously stepped thread\n");
reset_ecs (ecs, tp);
- switch_to_thread (tp->ptid);
+ switch_to_thread (tp);
- stop_pc = regcache_read_pc (get_thread_regcache (tp->ptid));
+ tp->suspend.stop_pc = regcache_read_pc (get_thread_regcache (tp));
frame = get_current_frame ();
/* If the PC of the thread we were trying to single-step has
This prevents us continuously moving the single-step breakpoint
forward, one instruction at a time, overstepping. */
- if (stop_pc != tp->prev_pc)
+ if (tp->suspend.stop_pc != tp->prev_pc)
{
ptid_t resume_ptid;
fprintf_unfiltered (gdb_stdlog,
"infrun: expected thread advanced also (%s -> %s)\n",
paddress (target_gdbarch (), tp->prev_pc),
- paddress (target_gdbarch (), stop_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
insert_single_step_breakpoint (get_frame_arch (frame),
get_frame_address_space (frame),
- stop_pc);
+ tp->suspend.stop_pc);
tp->resumed = 1;
resume_ptid = internal_resume_ptid (tp->control.stepping_command);
{
fill_in_stop_func (gdbarch, ecs);
- compunit_symtab *cust = find_pc_compunit_symtab (stop_pc);
+ compunit_symtab *cust
+ = find_pc_compunit_symtab (ecs->event_thread->suspend.stop_pc);
if (cust != NULL && compunit_language (cust) != language_asm)
ecs->stop_func_start
= gdbarch_skip_prologue_noexcept (gdbarch, ecs->stop_func_start);
ecs->stop_func_start);
}
- if (ecs->stop_func_start == stop_pc)
+ if (ecs->stop_func_start == ecs->event_thread->suspend.stop_pc)
{
/* We are already there: stop now. */
end_stepping_range (ecs);
fill_in_stop_func (gdbarch, ecs);
- cust = find_pc_compunit_symtab (stop_pc);
+ cust = find_pc_compunit_symtab (ecs->event_thread->suspend.stop_pc);
if (cust != NULL && compunit_language (cust) != language_asm)
ecs->stop_func_start
= gdbarch_skip_prologue_noexcept (gdbarch, ecs->stop_func_start);
- stop_func_sal = find_pc_line (stop_pc, 0);
+ stop_func_sal = find_pc_line (ecs->event_thread->suspend.stop_pc, 0);
/* OK, we're just going to keep stepping here. */
- if (stop_func_sal.pc == stop_pc)
+ if (stop_func_sal.pc == ecs->event_thread->suspend.stop_pc)
{
/* We're there already. Just stop stepping now. */
end_stepping_range (ecs);
/* Save the pc before execution, to compare with pc after stop. */
ecs->event_thread->prev_pc
- = regcache_read_pc (get_thread_regcache (ecs->ptid));
+ = regcache_read_pc (get_thread_regcache (ecs->event_thread));
if (ecs->event_thread->control.trap_expected)
{
if (tp->control.stop_step
&& frame_id_eq (tp->control.step_frame_id,
get_frame_id (get_current_frame ()))
- && tp->control.step_start_function == find_pc_function (stop_pc))
+ && (tp->control.step_start_function
+ == find_pc_function (tp->suspend.stop_pc)))
{
/* Finished step, just print source line. */
source_flag = SRC_LINE;
{
struct target_waitstatus last;
ptid_t last_ptid;
- struct cleanup *old_chain = make_cleanup (null_cleanup, NULL);
- ptid_t pid_ptid;
get_last_target_status (&last_ptid, &last);
propagate GDB's knowledge of the executing state to the
frontend/user running state. A QUIT is an easy exception to see
here, so do this before any filtered output. */
+
+ gdb::optional<scoped_finish_thread_state> maybe_finish_thread_state;
+
if (!non_stop)
- make_cleanup (finish_thread_state_cleanup, &minus_one_ptid);
+ maybe_finish_thread_state.emplace (minus_one_ptid);
else if (last.kind == TARGET_WAITKIND_SIGNALLED
|| last.kind == TARGET_WAITKIND_EXITED)
{
"checkpoint", when the current checkpoint/fork exits,
linux-fork.c automatically switches to another fork from
within target_mourn_inferior. */
- if (!ptid_equal (inferior_ptid, null_ptid))
- {
- pid_ptid = pid_to_ptid (ptid_get_pid (inferior_ptid));
- make_cleanup (finish_thread_state_cleanup, &pid_ptid);
- }
+ if (inferior_ptid != null_ptid)
+ maybe_finish_thread_state.emplace (ptid_t (inferior_ptid.pid ()));
}
else if (last.kind != TARGET_WAITKIND_NO_RESUMED)
- make_cleanup (finish_thread_state_cleanup, &inferior_ptid);
+ maybe_finish_thread_state.emplace (inferior_ptid);
/* As we're presenting a stop, and potentially removing breakpoints,
update the thread list so we can tell whether there are threads
update_thread_list ();
if (last.kind == TARGET_WAITKIND_STOPPED && stopped_by_random_signal)
- observer_notify_signal_received (inferior_thread ()->suspend.stop_signal);
+ gdb::observers::signal_received.notify (inferior_thread ()->suspend.stop_signal);
/* As with the notification of thread events, we want to delay
notifying the user that we've switched thread context until
after this event is handled, so we're not really switching, only
informing of a stop. */
if (!non_stop
- && !ptid_equal (previous_inferior_ptid, inferior_ptid)
+ && previous_inferior_ptid != inferior_ptid
&& target_has_execution
&& last.kind != TARGET_WAITKIND_SIGNALLED
&& last.kind != TARGET_WAITKIND_EXITED
}
/* Let the user/frontend see the threads as stopped. */
- do_cleanups (old_chain);
+ maybe_finish_thread_state.reset ();
/* Select innermost stack frame - i.e., current frame is frame 0,
and current location is based on that. Handle the case where the
/* Notify observers about the stop. This is where the interpreters
print the stop event. */
if (!ptid_equal (inferior_ptid, null_ptid))
- observer_notify_normal_stop (inferior_thread ()->control.stop_bpstat,
+ gdb::observers::normal_stop.notify (inferior_thread ()->control.stop_bpstat,
stop_print_frame);
else
- observer_notify_normal_stop (NULL, stop_print_frame);
+ gdb::observers::normal_stop.notify (NULL, stop_print_frame);
annotate_stopped ();
validate_registers_access ();
transferred =
- target_read (¤t_target, TARGET_OBJECT_SIGNAL_INFO,
+ target_read (current_top_target (), TARGET_OBJECT_SIGNAL_INFO,
NULL,
value_contents_all_raw (v),
value_offset (v),
vice versa. */
validate_registers_access ();
- transferred = target_write (¤t_target,
+ transferred = target_write (current_top_target (),
TARGET_OBJECT_SIGNAL_INFO,
NULL,
value_contents_all_raw (fromval),
struct thread_suspend_state thread_suspend;
/* Other fields: */
- CORE_ADDR stop_pc;
readonly_detached_regcache *registers;
/* Format of SIGINFO_DATA or NULL if it is not present. */
siginfo_data = (gdb_byte *) xmalloc (len);
back_to = make_cleanup (xfree, siginfo_data);
- if (target_read (¤t_target, TARGET_OBJECT_SIGNAL_INFO, NULL,
+ if (target_read (current_top_target (), TARGET_OBJECT_SIGNAL_INFO, NULL,
siginfo_data, 0, len) == len)
discard_cleanups (back_to);
else
GDB_SIGNAL_0 anyway. */
tp->suspend.stop_signal = GDB_SIGNAL_0;
- inf_state->stop_pc = stop_pc;
-
inf_state->registers = new readonly_detached_regcache (*regcache);
return inf_state;
tp->suspend = inf_state->thread_suspend;
- stop_pc = inf_state->stop_pc;
-
if (inf_state->siginfo_gdbarch == gdbarch)
{
struct type *type = gdbarch_get_siginfo_type (gdbarch);
/* Errors ignored. */
- target_write (¤t_target, TARGET_OBJECT_SIGNAL_INFO, NULL,
+ target_write (current_top_target (), TARGET_OBJECT_SIGNAL_INFO, NULL,
inf_state->siginfo_data, 0, TYPE_LENGTH (type));
}
inferior_ptid = null_ptid;
target_last_wait_ptid = minus_one_ptid;
- observer_attach_thread_ptid_changed (infrun_thread_ptid_changed);
- observer_attach_thread_stop_requested (infrun_thread_stop_requested);
- observer_attach_thread_exit (infrun_thread_thread_exit);
- observer_attach_inferior_exit (infrun_inferior_exit);
+ gdb::observers::thread_ptid_changed.attach (infrun_thread_ptid_changed);
+ gdb::observers::thread_stop_requested.attach (infrun_thread_stop_requested);
+ gdb::observers::thread_exit.attach (infrun_thread_thread_exit);
+ gdb::observers::inferior_exit.attach (infrun_inferior_exit);
/* Explicitly create without lookup, since that tries to create a
value with a void typed value, and when we get here, gdbarch