static void set_schedlock_func (char *args, int from_tty,
struct cmd_list_element *c);
-struct execution_control_state;
+struct thread_stepping_state;
-static int currently_stepping (struct execution_control_state *ecs);
+static int currently_stepping (struct thread_stepping_state *tss);
static void xdb_handle_command (char *args, int from_tty);
static ptid_t target_last_wait_ptid;
static struct target_waitstatus target_last_waitstatus;
-struct execution_control_state ecss;
+/* Context-switchable data. */
+struct thread_stepping_state
+{
+ /* Should we step over breakpoint next time keep_going
+ is called? */
+ int stepping_over_breakpoint;
+ struct symtab_and_line sal;
+ int current_line;
+ struct symtab *current_symtab;
+ int step_after_step_resume_breakpoint;
+ int stepping_through_solib_after_catch;
+ bpstat stepping_through_solib_catchpoints;
+};
+
+struct thread_stepping_state gtss;
+struct thread_stepping_state *tss = >ss;
+
+static void context_switch (ptid_t ptid);
+
+void init_thread_stepping_state (struct thread_stepping_state *tss);
+
+void init_infwait_state (void);
/* This is used to remember when a fork, vfork or exec event
was caught by a catchpoint, and thus the event is to be
target_last_wait_ptid = minus_one_ptid;
+ init_thread_stepping_state (tss);
+ previous_inferior_ptid = null_ptid;
+ init_infwait_state ();
+
displaced_step_clear ();
}
SIGNAL_RECEIVED
};
-/* This structure contains what used to be local variables in
- wait_for_inferior. Probably many of them can return to being
- locals in handle_inferior_event. */
+/* The PTID we'll do a target_wait on.*/
+ptid_t waiton_ptid;
+
+/* Current inferior wait state. */
+enum infwait_states infwait_state;
+/* Data to be passed around while handling an event. This data is
+ discarded between events. */
struct execution_control_state
{
+ ptid_t ptid;
struct target_waitstatus ws;
- struct target_waitstatus *wp;
- /* Should we step over breakpoint next time keep_going
- is called? */
- int stepping_over_breakpoint;
int random_signal;
CORE_ADDR stop_func_start;
CORE_ADDR stop_func_end;
char *stop_func_name;
- struct symtab_and_line sal;
- int current_line;
- struct symtab *current_symtab;
- ptid_t ptid;
- ptid_t saved_inferior_ptid;
- int step_after_step_resume_breakpoint;
- int stepping_through_solib_after_catch;
- bpstat stepping_through_solib_catchpoints;
int new_thread_event;
- struct target_waitstatus tmpstatus;
- enum infwait_states infwait_state;
- ptid_t waiton_ptid;
int wait_some_more;
};
wait_for_inferior (int treat_exec_as_sigtrap)
{
struct cleanup *old_cleanups;
+ struct execution_control_state ecss;
struct execution_control_state *ecs;
if (debug_infrun)
&step_resume_breakpoint);
ecs = &ecss;
+ memset (ecs, 0, sizeof (*ecs));
+
+ /* Fill in with reasonable starting values. */
+ init_thread_stepping_state (tss);
- /* Fill in with reasonable starting values. */
- init_execution_control_state (ecs);
+ /* Reset to normal state. */
+ init_infwait_state ();
/* We'll update this if & when we switch to a new thread. */
previous_inferior_ptid = inferior_ptid;
while (1)
{
if (deprecated_target_wait_hook)
- ecs->ptid = deprecated_target_wait_hook (ecs->waiton_ptid, ecs->wp);
+ ecs->ptid = deprecated_target_wait_hook (waiton_ptid, &ecs->ws);
else
- ecs->ptid = target_wait (ecs->waiton_ptid, ecs->wp);
+ ecs->ptid = target_wait (waiton_ptid, &ecs->ws);
if (treat_exec_as_sigtrap && ecs->ws.kind == TARGET_WAITKIND_EXECD)
{
void
fetch_inferior_event (void *client_data)
{
+ struct execution_control_state ecss;
struct execution_control_state *ecs = &ecss;
+ memset (ecs, 0, sizeof (*ecs));
+
if (!ecs->wait_some_more)
{
/* Fill in with reasonable starting values. */
- init_execution_control_state (ecs);
+ init_thread_stepping_state (tcs);
+
+ init_infwait_state ();
/* We'll update this if & when we switch to a new thread. */
previous_inferior_ptid = inferior_ptid;
if (deprecated_target_wait_hook)
ecs->ptid =
- deprecated_target_wait_hook (ecs->waiton_ptid, ecs->wp);
+ deprecated_target_wait_hook (waiton_ptid, &ecs->ws);
else
- ecs->ptid = target_wait (ecs->waiton_ptid, ecs->wp);
+ ecs->ptid = target_wait (waiton_ptid, &ecs->ws);
/* Now figure out what to do with the result of the result. */
handle_inferior_event (ecs);
void
init_execution_control_state (struct execution_control_state *ecs)
{
- ecs->stepping_over_breakpoint = 0;
ecs->random_signal = 0;
- ecs->step_after_step_resume_breakpoint = 0;
- ecs->stepping_through_solib_after_catch = 0;
- ecs->stepping_through_solib_catchpoints = NULL;
- ecs->sal = find_pc_line (prev_pc, 0);
- ecs->current_line = ecs->sal.line;
- ecs->current_symtab = ecs->sal.symtab;
- ecs->infwait_state = infwait_normal_state;
- ecs->waiton_ptid = pid_to_ptid (-1);
- ecs->wp = &(ecs->ws);
+}
+
+/* Clear context switchable stepping state. */
+
+void
+init_thread_stepping_state (struct thread_stepping_state *tss)
+{
+ tss->stepping_over_breakpoint = 0;
+ tss->step_after_step_resume_breakpoint = 0;
+ tss->stepping_through_solib_after_catch = 0;
+ tss->stepping_through_solib_catchpoints = NULL;
+ tss->sal = find_pc_line (prev_pc, 0);
+ tss->current_line = tss->sal.line;
+ tss->current_symtab = tss->sal.symtab;
}
/* Return the cached copy of the last pid/waitstatus returned by
/* Switch thread contexts, maintaining "infrun state". */
static void
-context_switch (struct execution_control_state *ecs)
+context_switch (ptid_t ptid)
{
/* Caution: it may happen that the new thread (or the old one!)
is not in the thread list. In this case we must not attempt
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 (ecs->ptid));
+ target_pid_to_str (ptid));
}
- if (in_thread_list (inferior_ptid) && in_thread_list (ecs->ptid))
+ if (in_thread_list (inferior_ptid) && in_thread_list (ptid))
{ /* Perform infrun state context switch: */
/* Save infrun state for the old thread. */
save_infrun_state (inferior_ptid, prev_pc,
stepping_over_breakpoint, step_resume_breakpoint,
step_range_start,
step_range_end, &step_frame_id,
- ecs->stepping_over_breakpoint,
- ecs->stepping_through_solib_after_catch,
- ecs->stepping_through_solib_catchpoints,
- ecs->current_line, ecs->current_symtab,
+ tss->stepping_over_breakpoint,
+ tss->stepping_through_solib_after_catch,
+ tss->stepping_through_solib_catchpoints,
+ tss->current_line, tss->current_symtab,
cmd_continuation, intermediate_continuation,
proceed_to_finish,
step_over_calls,
stop_bpstat);
/* Load infrun state for the new thread. */
- load_infrun_state (ecs->ptid, &prev_pc,
+ load_infrun_state (ptid, &prev_pc,
&stepping_over_breakpoint, &step_resume_breakpoint,
&step_range_start,
&step_range_end, &step_frame_id,
- &ecs->stepping_over_breakpoint,
- &ecs->stepping_through_solib_after_catch,
- &ecs->stepping_through_solib_catchpoints,
- &ecs->current_line, &ecs->current_symtab,
+ &tss->stepping_over_breakpoint,
+ &tss->stepping_through_solib_after_catch,
+ &tss->stepping_through_solib_catchpoints,
+ &tss->current_line, &tss->current_symtab,
&cmd_continuation, &intermediate_continuation,
&proceed_to_finish,
&step_over_calls,
&stop_bpstat);
}
- switch_to_thread (ecs->ptid);
+ switch_to_thread (ptid);
}
/* Context switch to thread PTID. */
/* Context switch to the new thread. */
if (!ptid_equal (ptid, inferior_ptid))
{
- ecss.ptid = ptid;
- context_switch (&ecss);
+ context_switch (ptid);
}
return current_ptid;
}
if (singlestep_breakpoints_inserted_p
|| !ptid_equal (ecs->ptid, inferior_ptid)
- || !currently_stepping (ecs)
+ || !currently_stepping (tss)
|| prev_pc == breakpoint_pc)
regcache_write_pc (regcache, breakpoint_pc);
}
}
+void
+init_infwait_state (void)
+{
+ waiton_ptid = pid_to_ptid (-1);
+ infwait_state = infwait_normal_state;
+}
+
/* Given an execution control state that has been freshly filled in
by an event from the inferior, figure out what it means and take
appropriate action. */
/* Cache the last pid/waitstatus. */
target_last_wait_ptid = ecs->ptid;
- target_last_waitstatus = *ecs->wp;
+ target_last_waitstatus = ecs->ws;
/* Always clear state belonging to the previous time we stopped. */
stop_stack_dummy = 0;
adjust_pc_after_break (ecs);
- switch (ecs->infwait_state)
+ switch (infwait_state)
{
case infwait_thread_hop_state:
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, "infrun: infwait_thread_hop_state\n");
/* Cancel the waiton_ptid. */
- ecs->waiton_ptid = pid_to_ptid (-1);
+ waiton_ptid = pid_to_ptid (-1);
break;
case infwait_normal_state:
default:
internal_error (__FILE__, __LINE__, _("bad switch"));
}
- ecs->infwait_state = infwait_normal_state;
+ infwait_state = infwait_normal_state;
reinit_frame_cache ();
if (!ptid_equal (ecs->ptid, inferior_ptid))
{
- context_switch (ecs);
+ context_switch (ecs->ptid);
reinit_frame_cache ();
}
xfree (pending_follow.execd_pathname);
stop_pc = regcache_read_pc (get_thread_regcache (ecs->ptid));
- ecs->saved_inferior_ptid = inferior_ptid;
- inferior_ptid = ecs->ptid;
- stop_bpstat = bpstat_stop_status (stop_pc, ecs->ptid);
+ {
+ /* The breakpoints module may need to touch the inferior's
+ memory. Switch to the (stopped) event ptid
+ momentarily. */
+ ptid_t saved_inferior_ptid = inferior_ptid;
+ inferior_ptid = ecs->ptid;
- ecs->random_signal = !bpstat_explains_signal (stop_bpstat);
- inferior_ptid = ecs->saved_inferior_ptid;
+ stop_bpstat = bpstat_stop_status (stop_pc, ecs->ptid);
+
+ ecs->random_signal = !bpstat_explains_signal (stop_bpstat);
+ inferior_ptid = saved_inferior_ptid;
+ }
if (!ptid_equal (ecs->ptid, inferior_ptid))
{
- context_switch (ecs);
+ context_switch (ecs->ptid);
reinit_frame_cache ();
}
ecs->random_signal = 0;
- ecs->ptid = saved_singlestep_ptid;
- context_switch (ecs);
+ context_switch (saved_singlestep_ptid);
if (deprecated_context_hook)
deprecated_context_hook (pid_to_thread_id (ecs->ptid));
else
{ /* Single step */
if (!ptid_equal (inferior_ptid, ecs->ptid))
- context_switch (ecs);
- ecs->waiton_ptid = ecs->ptid;
- ecs->wp = &(ecs->ws);
- ecs->stepping_over_breakpoint = 1;
+ context_switch (ecs->ptid);
+
+ waiton_ptid = ecs->ptid;
+ infwait_state = infwait_thread_hop_state;
- ecs->infwait_state = infwait_thread_hop_state;
+ tss->stepping_over_breakpoint = 1;
keep_going (ecs);
registers_changed ();
return;
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, "infrun: context switch\n");
- context_switch (ecs);
+ context_switch (ecs->ptid);
if (deprecated_context_hook)
deprecated_context_hook (pid_to_thread_id (ecs->ptid));
remove_breakpoints ();
registers_changed ();
target_resume (ecs->ptid, 1, TARGET_SIGNAL_0); /* Single step */
- ecs->waiton_ptid = ecs->ptid;
+ waiton_ptid = ecs->ptid;
if (HAVE_STEPPABLE_WATCHPOINT)
- ecs->infwait_state = infwait_step_watch_state;
+ infwait_state = infwait_step_watch_state;
else
- ecs->infwait_state = infwait_nonstep_watch_state;
+ infwait_state = infwait_nonstep_watch_state;
prepare_to_wait (ecs);
return;
}
&ecs->stop_func_start, &ecs->stop_func_end);
ecs->stop_func_start
+= gdbarch_deprecated_function_start_offset (current_gdbarch);
- ecs->stepping_over_breakpoint = 0;
+ tss->stepping_over_breakpoint = 0;
bpstat_clear (&stop_bpstat);
stop_step = 0;
stop_print_frame = 1;
if (stop_signal == TARGET_SIGNAL_TRAP
&& stepping_over_breakpoint
&& gdbarch_single_step_through_delay_p (current_gdbarch)
- && currently_stepping (ecs))
+ && currently_stepping (tss))
{
/* We're trying to step off a breakpoint. Turns out that we're
also on an instruction that needs to be stepped multiple
{
/* The user issued a continue when stopped at a breakpoint.
Set up for another trap and get out of here. */
- ecs->stepping_over_breakpoint = 1;
+ tss->stepping_over_breakpoint = 1;
keep_going (ecs);
return;
}
case, don't decide that here, just set
ecs->stepping_over_breakpoint, making sure we
single-step again before breakpoints are re-inserted. */
- ecs->stepping_over_breakpoint = 1;
+ tss->stepping_over_breakpoint = 1;
}
}
/* Look at the cause of the stop, and decide what to do.
The alternatives are:
- 1) break; to really stop and return to the debugger,
- 2) drop through to start up again
- (set ecs->stepping_over_breakpoint to 1 to single step once)
+ 1) stop_stepping and return; to really stop and return to the debugger,
+ 2) keep_going and return to start up again
+ (set tss->stepping_over_breakpoint to 1 to single step once)
3) set ecs->random_signal to 1, and the decision between 1 and 2
will be made according to the signal handling tables. */
"breakpoint\n");
insert_step_resume_breakpoint_at_frame (get_current_frame ());
- ecs->step_after_step_resume_breakpoint = 1;
+ tss->step_after_step_resume_breakpoint = 1;
keep_going (ecs);
return;
}
fprintf_unfiltered (gdb_stdlog,
"infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME\n");
- ecs->stepping_over_breakpoint = 1;
+ tss->stepping_over_breakpoint = 1;
if (!gdbarch_get_longjmp_target_p (current_gdbarch)
|| !gdbarch_get_longjmp_target (current_gdbarch,
case BPSTAT_WHAT_SINGLE:
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, "infrun: BPSTAT_WHAT_SINGLE\n");
- ecs->stepping_over_breakpoint = 1;
+ tss->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;
bpstat_find_step_resume_breakpoint (stop_bpstat);
}
delete_step_resume_breakpoint (&step_resume_breakpoint);
- if (ecs->step_after_step_resume_breakpoint)
+ if (tss->step_after_step_resume_breakpoint)
{
/* Back when the step-resume breakpoint was inserted, we
were trying to single-step off a breakpoint. Go back
to doing that. */
- ecs->step_after_step_resume_breakpoint = 0;
- ecs->stepping_over_breakpoint = 1;
+ tss->step_after_step_resume_breakpoint = 0;
+ tss->stepping_over_breakpoint = 1;
keep_going (ecs);
return;
}
friends) until we reach non-dld code. At that point,
we can stop stepping. */
bpstat_get_triggered_catchpoints (stop_bpstat,
- &ecs->
+ &tss->
stepping_through_solib_catchpoints);
- ecs->stepping_through_solib_after_catch = 1;
+ tss->stepping_through_solib_after_catch = 1;
/* Be sure to lift all breakpoints, so the inferior does
actually step past this point... */
- ecs->stepping_over_breakpoint = 1;
+ tss->stepping_over_breakpoint = 1;
break;
}
else
{
/* We want to step over this breakpoint, then keep going. */
- ecs->stepping_over_breakpoint = 1;
+ tss->stepping_over_breakpoint = 1;
break;
}
}
/* Are we stepping to get the inferior out of the dynamic linker's
hook (and possibly the dld itself) after catching a shlib
event? */
- if (ecs->stepping_through_solib_after_catch)
+ if (tss->stepping_through_solib_after_catch)
{
#if defined(SOLIB_ADD)
/* Have we reached our destination? If not, keep going. */
{
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, "infrun: stepping in dynamic linker\n");
- ecs->stepping_over_breakpoint = 1;
+ tss->stepping_over_breakpoint = 1;
keep_going (ecs);
return;
}
fprintf_unfiltered (gdb_stdlog, "infrun: step past dynamic linker\n");
/* Else, stop and report the catchpoint(s) whose triggering
caused us to begin stepping. */
- ecs->stepping_through_solib_after_catch = 0;
+ tss->stepping_through_solib_after_catch = 0;
bpstat_clear (&stop_bpstat);
- stop_bpstat = bpstat_copy (ecs->stepping_through_solib_catchpoints);
- bpstat_clear (&ecs->stepping_through_solib_catchpoints);
+ stop_bpstat = bpstat_copy (tss->stepping_through_solib_catchpoints);
+ bpstat_clear (&tss->stepping_through_solib_catchpoints);
stop_print_frame = 1;
stop_stepping (ecs);
return;
}
}
- ecs->sal = find_pc_line (stop_pc, 0);
+ tss->sal = find_pc_line (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
that have no names, so we should do trampoline handling first. */
if (step_over_calls == STEP_OVER_UNDEBUGGABLE
&& ecs->stop_func_name == NULL
- && ecs->sal.line == 0)
+ && tss->sal.line == 0)
{
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, "infrun: stepped into undebuggable function\n");
return;
}
- if (ecs->sal.line == 0)
+ if (tss->sal.line == 0)
{
/* We have no line number information. That means to stop
stepping (does this always happen right after one instruction,
return;
}
- if ((stop_pc == ecs->sal.pc)
- && (ecs->current_line != ecs->sal.line
- || ecs->current_symtab != ecs->sal.symtab))
+ if ((stop_pc == tss->sal.pc)
+ && (tss->current_line != tss->sal.line
+ || tss->current_symtab != tss->sal.symtab))
{
/* We are at the start of a different line. So stop. Note that
we don't stop if we step into the middle of a different line.
new line in mid-statement, we continue stepping. This makes
things like for(;;) statements work better.) */
- step_range_start = ecs->sal.pc;
- step_range_end = ecs->sal.end;
+ step_range_start = tss->sal.pc;
+ step_range_end = tss->sal.end;
step_frame_id = get_frame_id (get_current_frame ());
- ecs->current_line = ecs->sal.line;
- ecs->current_symtab = ecs->sal.symtab;
+ tss->current_line = tss->sal.line;
+ tss->current_symtab = tss->sal.symtab;
/* In the case where we just stepped out of a function into the
middle of a line of the caller, continue stepping, but
/* Are we in the middle of stepping? */
static int
-currently_stepping (struct execution_control_state *ecs)
+currently_stepping (struct thread_stepping_state *tss)
{
return (((step_range_end && step_resume_breakpoint == NULL)
|| stepping_over_breakpoint)
- || ecs->stepping_through_solib_after_catch
+ || tss->stepping_through_solib_after_catch
|| bpstat_should_step ());
}
ecs->stop_func_start = gdbarch_skip_prologue
(current_gdbarch, ecs->stop_func_start);
- ecs->sal = find_pc_line (ecs->stop_func_start, 0);
+ tss->sal = find_pc_line (ecs->stop_func_start, 0);
/* Use the step_resume_break to step until the end of the prologue,
even if that involves jumps (as it seems to on the vax under
4.2). */
/* If the prologue ends in the middle of a source line, continue to
the end of that source line (if it is still within the function).
Otherwise, just go to end of prologue. */
- if (ecs->sal.end
- && ecs->sal.pc != ecs->stop_func_start
- && ecs->sal.end < ecs->stop_func_end)
- ecs->stop_func_start = ecs->sal.end;
+ if (tss->sal.end
+ && tss->sal.pc != ecs->stop_func_start
+ && tss->sal.end < ecs->stop_func_end)
+ ecs->stop_func_start = tss->sal.end;
/* Architectures which require breakpoint adjustment might not be able
to place a breakpoint at the computed address. If so, the test
/* We took a signal (which we are supposed to pass through to
the inferior, else we'd have done a break above) and we
haven't yet gotten our trap. Simply continue. */
- resume (currently_stepping (ecs), stop_signal);
+ resume (currently_stepping (tss), stop_signal);
}
else
{
already inserted breakpoints. Therefore, we don't
care if breakpoints were already inserted, or not. */
- if (ecs->stepping_over_breakpoint)
+ if (tss->stepping_over_breakpoint)
{
if (! use_displaced_stepping (current_gdbarch))
/* Since we can't do a displaced step, we have to remove
}
}
- stepping_over_breakpoint = ecs->stepping_over_breakpoint;
+ stepping_over_breakpoint = tss->stepping_over_breakpoint;
/* Do not deliver SIGNAL_TRAP (except when the user explicitly
specifies that such a signal should be delivered to the
stop_signal = TARGET_SIGNAL_0;
- resume (currently_stepping (ecs), stop_signal);
+ resume (currently_stepping (tss), stop_signal);
}
prepare_to_wait (ecs);
{
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, "infrun: prepare_to_wait\n");
- if (ecs->infwait_state == infwait_normal_state)
+ if (infwait_state == infwait_normal_state)
{
overlay_cache_invalid = 1;
as part of their normal status mechanism. */
registers_changed ();
- ecs->waiton_ptid = pid_to_ptid (-1);
- ecs->wp = &(ecs->ws);
+ waiton_ptid = pid_to_ptid (-1);
}
/* This is the old end of the while loop. Let everybody know we
want to wait for the inferior some more and get called again