Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995,
1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
- 2008 Free Software Foundation, Inc.
+ 2008, 2009 Free Software Foundation, Inc.
This file is part of GDB.
static int currently_stepping (struct thread_info *tp);
+static int currently_stepping_callback (struct thread_info *tp, void *data);
+
static void xdb_handle_command (char *args, int from_tty);
static int prepare_to_proceed (int);
int stop_after_trap;
-/* Save register contents here when about to pop a stack dummy frame,
- if-and-only-if proceed_to_finish is set.
+/* Save register contents here when executing a "finish" command or are
+ about to pop a stack dummy frame, if-and-only-if proceed_to_finish is set.
Thus this contains the return value from the called function (assuming
values are returned in a register). */
{
int should_resume = 1;
struct cleanup *old_cleanups = make_cleanup (resume_cleanups, 0);
+
+ /* Note that these must be reset if we follow a fork below. */
struct regcache *regcache = get_current_regcache ();
struct gdbarch *gdbarch = get_regcache_arch (regcache);
struct thread_info *tp = inferior_thread ();
CORE_ADDR pc = regcache_read_pc (regcache);
+
QUIT;
if (debug_infrun)
pending_follow.kind = TARGET_WAITKIND_SPURIOUS;
if (follow_fork ())
should_resume = 0;
+
+ /* Following a child fork will change our notion of current
+ thread. */
+ tp = inferior_thread ();
+ regcache = get_current_regcache ();
+ gdbarch = get_regcache_arch (regcache);
+ pc = regcache_read_pc (regcache);
break;
case TARGET_WAITKIND_EXECD:
displaced_step_dump_bytes (gdb_stdlog, buf, sizeof (buf));
}
- target_resume (resume_ptid, step, sig);
-
/* Avoid confusing the next resume, if the next stop/resume
happens to apply to another thread. */
tp->stop_signal = TARGET_SIGNAL_0;
+
+ target_resume (resume_ptid, step, sig);
}
discard_cleanups (old_cleanups);
/* Clear out all variables saying what to do when inferior is continued.
First do this, then set the ones you want, then call `proceed'. */
-void
-clear_proceed_status (void)
+static void
+clear_proceed_status_thread (struct thread_info *tp)
{
- if (!ptid_equal (inferior_ptid, null_ptid))
- {
- struct thread_info *tp;
- struct inferior *inferior;
+ if (debug_infrun)
+ fprintf_unfiltered (gdb_stdlog,
+ "infrun: clear_proceed_status_thread (%s)\n",
+ target_pid_to_str (tp->ptid));
- tp = inferior_thread ();
+ tp->trap_expected = 0;
+ tp->step_range_start = 0;
+ tp->step_range_end = 0;
+ tp->step_frame_id = null_frame_id;
+ tp->step_over_calls = STEP_OVER_UNDEBUGGABLE;
+ tp->stop_requested = 0;
- tp->trap_expected = 0;
- tp->step_range_start = 0;
- tp->step_range_end = 0;
- tp->step_frame_id = null_frame_id;
- tp->step_over_calls = STEP_OVER_UNDEBUGGABLE;
- tp->stop_requested = 0;
+ tp->stop_step = 0;
- tp->stop_step = 0;
+ tp->proceed_to_finish = 0;
- tp->proceed_to_finish = 0;
+ /* Discard any remaining commands or status from previous stop. */
+ bpstat_clear (&tp->stop_bpstat);
+}
- /* Discard any remaining commands or status from previous
- stop. */
- bpstat_clear (&tp->stop_bpstat);
+static int
+clear_proceed_status_callback (struct thread_info *tp, void *data)
+{
+ if (is_exited (tp->ptid))
+ return 0;
+ clear_proceed_status_thread (tp);
+ return 0;
+}
+
+void
+clear_proceed_status (void)
+{
+ if (!ptid_equal (inferior_ptid, null_ptid))
+ {
+ struct inferior *inferior;
+
+ if (non_stop)
+ {
+ /* If in non-stop mode, only delete the per-thread status
+ of the current thread. */
+ clear_proceed_status_thread (inferior_thread ());
+ }
+ else
+ {
+ /* In all-stop mode, delete the per-thread status of
+ *all* threads. */
+ iterate_over_threads (clear_proceed_status_callback, NULL);
+ }
+
inferior = current_inferior ();
inferior->stop_soon = NO_STOP_QUIETLY;
}
struct thread_info *tp;
CORE_ADDR pc = regcache_read_pc (regcache);
int oneproc = 0;
- enum target_signal stop_signal;
if (step > 0)
step_start_function = find_pc_function (pc);
{
breakpoint_retire_moribund ();
- /* Mark the non-executing threads accordingly. */
- if (!non_stop
- || ecs->ws.kind == TARGET_WAITKIND_EXITED
- || ecs->ws.kind == TARGET_WAITKIND_SIGNALLED)
- set_executing (pid_to_ptid (-1), 0);
- else
- set_executing (ecs->ptid, 0);
+ /* Mark the non-executing threads accordingly. In all-stop, all
+ threads of all processes are stopped when we get any event
+ reported. In non-stop mode, only the event thread stops. If
+ we're handling a process exit in non-stop mode, there's
+ nothing to do, as threads of the dead process are gone, and
+ threads of any other process were left running. */
+ if (!non_stop)
+ set_executing (minus_one_ptid, 0);
+ else if (ecs->ws.kind != TARGET_WAITKIND_SIGNALLED
+ && ecs->ws.kind != TARGET_WAITKIND_EXITED)
+ set_executing (inferior_ptid, 0);
}
switch (infwait_state)
case TARGET_WAITKIND_EXITED:
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_EXITED\n");
+ inferior_ptid = ecs->ptid;
target_terminal_ours (); /* Must do this before mourn anyway */
print_stop_reason (EXITED, ecs->ws.value.integer);
case TARGET_WAITKIND_SIGNALLED:
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_SIGNALLED\n");
+ inferior_ptid = ecs->ptid;
stop_print_frame = 0;
target_terminal_ours (); /* Must do this before mourn anyway */
}
}
- stepping_past_singlestep_breakpoint = 0;
-
if (!ptid_equal (deferred_step_ptid, null_ptid))
{
/* In non-stop mode, there's never a deferred_step_ptid set. */
the fact that we were supposed to switch back. */
if (ecs->event_thread->stop_signal == TARGET_SIGNAL_TRAP)
{
- struct thread_info *tp;
-
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog,
"infrun: handling deferred step\n");
break;
case BPSTAT_WHAT_CHECK_SHLIBS:
- case BPSTAT_WHAT_CHECK_SHLIBS_RESUME_FROM_HOOK:
{
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, "infrun: BPSTAT_WHAT_CHECK_SHLIBS\n");
test for stepping. But, if not stepping,
do not stop. */
+ /* In all-stop mode, if we're currently stepping but have stopped in
+ some other thread, we need to switch back to the stepped thread. */
+ if (!non_stop)
+ {
+ struct thread_info *tp;
+ tp = iterate_over_threads (currently_stepping_callback,
+ ecs->event_thread);
+ if (tp)
+ {
+ /* However, if the current thread is blocked on some internal
+ breakpoint, and we simply need to step over that breakpoint
+ to get it going again, do that first. */
+ if ((ecs->event_thread->trap_expected
+ && ecs->event_thread->stop_signal != TARGET_SIGNAL_TRAP)
+ || ecs->event_thread->stepping_over_breakpoint)
+ {
+ keep_going (ecs);
+ return;
+ }
+
+ /* Otherwise, we no longer expect a trap in the current thread.
+ Clear the trap_expected flag before switching back -- this is
+ what keep_going would do as well, if we called it. */
+ ecs->event_thread->trap_expected = 0;
+
+ if (debug_infrun)
+ fprintf_unfiltered (gdb_stdlog,
+ "infrun: switching back to stepped thread\n");
+
+ ecs->event_thread = tp;
+ ecs->ptid = tp->ptid;
+ context_switch (ecs->ptid);
+ keep_going (ecs);
+ return;
+ }
+ }
+
/* Are we stepping to get the inferior out of the dynamic linker's
hook (and possibly the dld itself) after catching a shlib
event? */
/* Are we in the middle of stepping? */
+static int
+currently_stepping_thread (struct thread_info *tp)
+{
+ return (tp->step_range_end && tp->step_resume_breakpoint == NULL)
+ || tp->trap_expected
+ || tp->stepping_through_solib_after_catch;
+}
+
+static int
+currently_stepping_callback (struct thread_info *tp, void *data)
+{
+ /* Return true if any thread *but* the one passed in "data" is
+ in the middle of stepping. */
+ return tp != data && currently_stepping_thread (tp);
+}
+
static int
currently_stepping (struct thread_info *tp)
{
- return (((tp->step_range_end && tp->step_resume_breakpoint == NULL)
- || tp->trap_expected)
- || tp->stepping_through_solib_after_catch
- || bpstat_should_step ());
+ return currently_stepping_thread (tp) || bpstat_should_step ();
}
/* Inferior has stepped into a subroutine call with source code that
else
observer_notify_normal_stop (NULL);
}
- if (target_has_execution
- && last.kind != TARGET_WAITKIND_SIGNALLED
- && last.kind != TARGET_WAITKIND_EXITED)
- {
- /* Delete the breakpoint we stopped at, if it wants to be deleted.
- Delete any breakpoint that is to be deleted at the next stop. */
- breakpoint_auto_delete (inferior_thread ()->stop_bpstat);
+ if (target_has_execution)
+ {
+ if (last.kind != TARGET_WAITKIND_SIGNALLED
+ && last.kind != TARGET_WAITKIND_EXITED)
+ /* Delete the breakpoint we stopped at, if it wants to be deleted.
+ Delete any breakpoint that is to be deleted at the next stop. */
+ breakpoint_auto_delete (inferior_thread ()->stop_bpstat);
+
+ /* Mark the stopped threads accordingly. In all-stop, all
+ threads of all processes are stopped when we get any event
+ reported. In non-stop mode, only the event thread stops. If
+ we're handling a process exit in non-stop mode, there's
+ nothing to do, as threads of the dead process are gone, and
+ threads of any other process were left running. */
if (!non_stop)
- set_running (pid_to_ptid (-1), 0);
- else
+ set_running (minus_one_ptid, 0);
+ else if (last.kind != TARGET_WAITKIND_SIGNALLED
+ && last.kind != TARGET_WAITKIND_EXITED)
set_running (inferior_ptid, 0);
}
argv++;
}
- target_notice_signals (inferior_ptid);
+ for (signum = 0; signum < nsigs; signum++)
+ if (sigs[signum])
+ {
+ target_notice_signals (inferior_ptid);
- if (from_tty)
- {
- /* Show the results. */
- sig_print_header ();
- for (signum = 0; signum < nsigs; signum++)
- {
- if (sigs[signum])
- {
- sig_print_info (signum);
- }
- }
- }
+ if (from_tty)
+ {
+ /* Show the results. */
+ sig_print_header ();
+ for (; signum < nsigs; signum++)
+ if (sigs[signum])
+ sig_print_info (signum);
+ }
+
+ break;
+ }
do_cleanups (old_chain);
}