static int lwp_status_pending_p (struct lwp_info *lp);
+static int check_stopped_by_breakpoint (struct lwp_info *lp);
+static int sigtrap_is_event (int status);
+static int (*linux_nat_status_is_event) (int status) = sigtrap_is_event;
+
\f
/* Trivial list manipulation functions to keep track of a list of
new stopped processes. */
ptid_t ptid;
lp->step = step;
+
+ /* stop_pc doubles as the PC the LWP had when it was last resumed.
+ We only presently need that if the LWP is stepped though (to
+ handle the case of stepping a breakpoint instruction). */
+ if (step)
+ {
+ struct regcache *regcache = get_thread_regcache (lp->ptid);
+
+ lp->stop_pc = regcache_read_pc (regcache);
+ }
+ else
+ lp->stop_pc = 0;
+
if (linux_nat_prepare_to_resume != NULL)
linux_nat_prepare_to_resume (lp);
/* Convert to something the lower layer understands. */
ptid = pid_to_ptid (ptid_get_lwp (lp->ptid));
linux_ops->to_resume (linux_ops, ptid, step, signo);
- lp->stopped_by_watchpoint = 0;
+ lp->stop_reason = LWP_STOPPED_BY_NO_REASON;
lp->stopped = 0;
registers_changed_ptid (lp->ptid);
}
soon as we see LP stop with a SIGTRAP. If GDB changes the debug
registers meanwhile, we have the cached data we can rely on. */
-static void
-save_sigtrap (struct lwp_info *lp)
+static int
+check_stopped_by_watchpoint (struct lwp_info *lp)
{
struct cleanup *old_chain;
if (linux_ops->to_stopped_by_watchpoint == NULL)
- {
- lp->stopped_by_watchpoint = 0;
- return;
- }
+ return 0;
old_chain = save_inferior_ptid ();
inferior_ptid = lp->ptid;
- lp->stopped_by_watchpoint = linux_ops->to_stopped_by_watchpoint (linux_ops);
-
- if (lp->stopped_by_watchpoint)
+ if (linux_ops->to_stopped_by_watchpoint (linux_ops))
{
+ lp->stop_reason = LWP_STOPPED_BY_WATCHPOINT;
+
if (linux_ops->to_stopped_data_address != NULL)
lp->stopped_data_address_p =
linux_ops->to_stopped_data_address (¤t_target,
}
do_cleanups (old_chain);
+
+ return lp->stop_reason == LWP_STOPPED_BY_WATCHPOINT;
}
-/* See save_sigtrap. */
+/* Called when the LWP stopped for a trap that could be explained by a
+ watchpoint or a breakpoint. */
+
+static void
+save_sigtrap (struct lwp_info *lp)
+{
+ gdb_assert (lp->stop_reason == LWP_STOPPED_BY_NO_REASON);
+ gdb_assert (lp->status != 0);
+
+ if (check_stopped_by_watchpoint (lp))
+ return;
+
+ if (linux_nat_status_is_event (lp->status))
+ check_stopped_by_breakpoint (lp);
+}
+
+/* Returns true if the LWP had stopped for a watchpoint. */
static int
linux_nat_stopped_by_watchpoint (struct target_ops *ops)
gdb_assert (lp != NULL);
- return lp->stopped_by_watchpoint;
+ return lp->stop_reason == LWP_STOPPED_BY_WATCHPOINT;
}
static int
return WIFSTOPPED (status) && WSTOPSIG (status) == SIGTRAP;
}
-/* SIGTRAP-like events recognizer. */
-
-static int (*linux_nat_status_is_event) (int status) = sigtrap_is_event;
-
-/* Check for SIGTRAP-like events in LP. */
-
-static int
-linux_nat_lp_status_is_event (struct lwp_info *lp)
-{
- /* We check for lp->waitstatus in addition to lp->status, because we can
- have pending process exits recorded in lp->status
- and W_EXITCODE(0,0) == 0. We should probably have an additional
- lp->status_p flag. */
-
- return (lp->waitstatus.kind == TARGET_WAITKIND_IGNORE
- && linux_nat_status_is_event (lp->status));
-}
-
/* Set alternative SIGTRAP-like events recognizer. If
breakpoint_inserted_here_p there then gdbarch_decr_pc_after_break will be
applied. */
{
/* The thread was stopped with a signal other than SIGSTOP. */
- save_sigtrap (lp);
-
if (debug_linux_nat)
fprintf_unfiltered (gdb_stdlog,
"SWC: Pending event %s in %s\n",
/* Save the sigtrap event. */
lp->status = status;
gdb_assert (lp->signalled);
+ save_sigtrap (lp);
}
else
{
return 0;
}
-/* Return non-zero if LP has a wait status pending. */
+/* Return non-zero if LP has a wait status pending. Discard the
+ pending event and resume the LWP if the event that originally
+ caused the stop became uninteresting. */
static int
status_callback (struct lwp_info *lp, void *data)
if (!lp->resumed)
return 0;
+ if (lp->stop_reason == LWP_STOPPED_BY_SW_BREAKPOINT
+ || lp->stop_reason == LWP_STOPPED_BY_HW_BREAKPOINT)
+ {
+ struct regcache *regcache = get_thread_regcache (lp->ptid);
+ struct gdbarch *gdbarch = get_regcache_arch (regcache);
+ CORE_ADDR pc;
+ int discard = 0;
+
+ gdb_assert (lp->status != 0);
+
+ pc = regcache_read_pc (regcache);
+
+ if (pc != lp->stop_pc)
+ {
+ if (debug_linux_nat)
+ fprintf_unfiltered (gdb_stdlog,
+ "SC: PC of %s changed. was=%s, now=%s\n",
+ target_pid_to_str (lp->ptid),
+ paddress (target_gdbarch (), lp->stop_pc),
+ paddress (target_gdbarch (), pc));
+ discard = 1;
+ }
+ else if (!breakpoint_inserted_here_p (get_regcache_aspace (regcache), pc))
+ {
+ if (debug_linux_nat)
+ fprintf_unfiltered (gdb_stdlog,
+ "SC: previous breakpoint of %s, at %s gone\n",
+ target_pid_to_str (lp->ptid),
+ paddress (target_gdbarch (), lp->stop_pc));
+
+ discard = 1;
+ }
+
+ if (discard)
+ {
+ if (debug_linux_nat)
+ fprintf_unfiltered (gdb_stdlog,
+ "SC: pending event of %s cancelled.\n",
+ target_pid_to_str (lp->ptid));
+
+ lp->status = 0;
+ linux_resume_one_lwp (lp, lp->step, GDB_SIGNAL_0);
+ return 0;
+ }
+ return 1;
+ }
+
return lwp_status_pending_p (lp);
}
gdb_assert (count != NULL);
- /* Count only resumed LWPs that have a SIGTRAP event pending. */
- if (lp->resumed && linux_nat_lp_status_is_event (lp))
+ /* Select only resumed LWPs that have an event pending. */
+ if (lp->resumed && lwp_status_pending_p (lp))
(*count)++;
return 0;
gdb_assert (selector != NULL);
- /* Select only resumed LWPs that have a SIGTRAP event pending. */
- if (lp->resumed && linux_nat_lp_status_is_event (lp))
+ /* Select only resumed LWPs that have an event pending. */
+ if (lp->resumed && lwp_status_pending_p (lp))
if ((*selector)-- == 0)
return 1;
return 0;
}
+/* Called when the LWP got a signal/trap that could be explained by a
+ software or hardware breakpoint. */
+
static int
-cancel_breakpoint (struct lwp_info *lp)
+check_stopped_by_breakpoint (struct lwp_info *lp)
{
/* Arrange for a breakpoint to be hit again later. We don't keep
the SIGTRAP status and don't forward the SIGTRAP signal to the
struct regcache *regcache = get_thread_regcache (lp->ptid);
struct gdbarch *gdbarch = get_regcache_arch (regcache);
CORE_ADDR pc;
+ CORE_ADDR sw_bp_pc;
+
+ pc = regcache_read_pc (regcache);
+ sw_bp_pc = pc - target_decr_pc_after_break (gdbarch);
- pc = regcache_read_pc (regcache) - target_decr_pc_after_break (gdbarch);
- if (breakpoint_inserted_here_p (get_regcache_aspace (regcache), pc))
+ if ((!lp->step || lp->stop_pc == sw_bp_pc)
+ && software_breakpoint_inserted_here_p (get_regcache_aspace (regcache),
+ sw_bp_pc))
{
+ /* The LWP was either continued, or stepped a software
+ breakpoint instruction. */
if (debug_linux_nat)
fprintf_unfiltered (gdb_stdlog,
- "CB: Push back breakpoint for %s\n",
+ "CB: Push back software breakpoint for %s\n",
target_pid_to_str (lp->ptid));
/* Back up the PC if necessary. */
- if (target_decr_pc_after_break (gdbarch))
- regcache_write_pc (regcache, pc);
+ if (pc != sw_bp_pc)
+ regcache_write_pc (regcache, sw_bp_pc);
+ lp->stop_pc = sw_bp_pc;
+ lp->stop_reason = LWP_STOPPED_BY_SW_BREAKPOINT;
return 1;
}
- return 0;
-}
-static int
-cancel_breakpoints_callback (struct lwp_info *lp, void *data)
-{
- struct lwp_info *event_lp = data;
-
- /* Leave the LWP that has been elected to receive a SIGTRAP alone. */
- if (lp == event_lp)
- return 0;
-
- /* If a LWP other than the LWP that we're reporting an event for has
- hit a GDB breakpoint (as opposed to some random trap signal),
- then just arrange for it to hit it again later. We don't keep
- the SIGTRAP status and don't forward the SIGTRAP signal to the
- LWP. We will handle the current event, eventually we will resume
- all LWPs, and this one will get its breakpoint trap again.
-
- If we do not do this, then we run the risk that the user will
- delete or disable the breakpoint, but the LWP will have already
- tripped on it. */
+ if (hardware_breakpoint_inserted_here_p (get_regcache_aspace (regcache), pc))
+ {
+ if (debug_linux_nat)
+ fprintf_unfiltered (gdb_stdlog,
+ "CB: Push back hardware breakpoint for %s\n",
+ target_pid_to_str (lp->ptid));
- if (linux_nat_lp_status_is_event (lp)
- && cancel_breakpoint (lp))
- /* Throw away the SIGTRAP. */
- lp->status = 0;
+ lp->stop_pc = pc;
+ lp->stop_reason = LWP_STOPPED_BY_HW_BREAKPOINT;
+ return 1;
+ }
return 0;
}
{
int num_events = 0;
int random_selector;
- struct lwp_info *event_lp;
+ struct lwp_info *event_lp = NULL;
/* Record the wait status for the original LWP. */
(*orig_lp)->status = *status;
- /* Give preference to any LWP that is being single-stepped. */
- event_lp = iterate_over_lwps (filter,
- select_singlestep_lwp_callback, NULL);
- if (event_lp != NULL)
+ /* In all-stop, give preference to the LWP that is being
+ single-stepped. There will be at most one, and it will be the
+ LWP that the core is most interested in. If we didn't do this,
+ then we'd have to handle pending step SIGTRAPs somehow in case
+ the core later continues the previously-stepped thread, as
+ otherwise we'd report the pending SIGTRAP then, and the core, not
+ having stepped the thread, wouldn't understand what the trap was
+ for, and therefore would report it to the user as a random
+ signal. */
+ if (!non_stop)
{
- if (debug_linux_nat)
- fprintf_unfiltered (gdb_stdlog,
- "SEL: Select single-step %s\n",
- target_pid_to_str (event_lp->ptid));
+ event_lp = iterate_over_lwps (filter,
+ select_singlestep_lwp_callback, NULL);
+ if (event_lp != NULL)
+ {
+ if (debug_linux_nat)
+ fprintf_unfiltered (gdb_stdlog,
+ "SEL: Select single-step %s\n",
+ target_pid_to_str (event_lp->ptid));
+ }
}
- else
+
+ if (event_lp == NULL)
{
- /* No single-stepping LWP. Select one at random, out of those
- which have had SIGTRAP events. */
+ /* Pick one at random, out of those which have had events. */
- /* First see how many SIGTRAP events we have. */
+ /* First see how many events we have. */
iterate_over_lwps (filter, count_events_callback, &num_events);
- /* Now randomly pick a LWP out of those that have had a SIGTRAP. */
+ /* Now randomly pick a LWP out of those that have had
+ events. */
random_selector = (int)
((num_events * (double) rand ()) / (RAND_MAX + 1.0));
if (debug_linux_nat && num_events > 1)
fprintf_unfiltered (gdb_stdlog,
- "SEL: Found %d SIGTRAP events, selecting #%d\n",
+ "SEL: Found %d events, selecting #%d\n",
num_events, random_selector);
event_lp = iterate_over_lwps (filter,
static int
stop_and_resume_callback (struct lwp_info *lp, void *data)
{
- int *new_pending_p = data;
-
if (!lp->stopped)
{
ptid_t ptid = lp->ptid;
"SARC: not re-resuming LWP %ld "
"(has pending)\n",
ptid_get_lwp (lp->ptid));
- if (new_pending_p)
- *new_pending_p = 1;
}
}
}
}
/* Check if we should go on and pass this event to common code.
- Return the affected lwp if we are, or NULL otherwise. If we stop
- all lwps temporarily, we may end up with new pending events in some
- other lwp. In that case set *NEW_PENDING_P to true. */
+ Return the affected lwp if we are, or NULL otherwise. */
static struct lwp_info *
-linux_nat_filter_event (int lwpid, int status, int *new_pending_p)
+linux_nat_filter_event (int lwpid, int status)
{
struct lwp_info *lp;
int event = linux_ptrace_get_extended_event (status);
- *new_pending_p = 0;
-
lp = find_lwp_pid (pid_to_ptid (lwpid));
/* Check for stop events reported by a process we didn't already
return NULL;
}
- if (linux_nat_status_is_event (status))
- save_sigtrap (lp);
-
/* Check if the thread has exited. */
- if ((WIFEXITED (status) || WIFSIGNALED (status))
- && num_lwps (ptid_get_pid (lp->ptid)) > 1)
+ if (WIFEXITED (status) || WIFSIGNALED (status))
{
- /* If this is the main thread, we must stop all threads and verify
- if they are still alive. This is because in the nptl thread model
- on Linux 2.4, there is no signal issued for exiting LWPs
- other than the main thread. We only get the main thread exit
- signal once all child threads have already exited. If we
- stop all the threads and use the stop_wait_callback to check
- if they have exited we can determine whether this signal
- should be ignored or whether it means the end of the debugged
- application, regardless of which threading model is being
- used. */
- if (ptid_get_pid (lp->ptid) == ptid_get_lwp (lp->ptid))
+ if (num_lwps (ptid_get_pid (lp->ptid)) > 1)
{
- iterate_over_lwps (pid_to_ptid (ptid_get_pid (lp->ptid)),
- stop_and_resume_callback, new_pending_p);
+ /* If this is the main thread, we must stop all threads and
+ verify if they are still alive. This is because in the
+ nptl thread model on Linux 2.4, there is no signal issued
+ for exiting LWPs other than the main thread. We only get
+ the main thread exit signal once all child threads have
+ already exited. If we stop all the threads and use the
+ stop_wait_callback to check if they have exited we can
+ determine whether this signal should be ignored or
+ whether it means the end of the debugged application,
+ regardless of which threading model is being used. */
+ if (ptid_get_pid (lp->ptid) == ptid_get_lwp (lp->ptid))
+ {
+ iterate_over_lwps (pid_to_ptid (ptid_get_pid (lp->ptid)),
+ stop_and_resume_callback, NULL);
+ }
+
+ if (debug_linux_nat)
+ fprintf_unfiltered (gdb_stdlog,
+ "LLW: %s exited.\n",
+ target_pid_to_str (lp->ptid));
+
+ if (num_lwps (ptid_get_pid (lp->ptid)) > 1)
+ {
+ /* If there is at least one more LWP, then the exit signal
+ was not the end of the debugged application and should be
+ ignored. */
+ exit_lwp (lp);
+ return NULL;
+ }
}
+ gdb_assert (lp->resumed);
+
if (debug_linux_nat)
fprintf_unfiltered (gdb_stdlog,
- "LLW: %s exited.\n",
- target_pid_to_str (lp->ptid));
+ "Process %ld exited\n",
+ ptid_get_lwp (lp->ptid));
- if (num_lwps (ptid_get_pid (lp->ptid)) > 1)
- {
- /* If there is at least one more LWP, then the exit signal
- was not the end of the debugged application and should be
- ignored. */
- exit_lwp (lp);
- return NULL;
- }
+ /* This was the last lwp in the process. Since events are
+ serialized to GDB core, we may not be able report this one
+ right now, but GDB core and the other target layers will want
+ to be notified about the exit code/signal, leave the status
+ pending for the next time we're able to report it. */
+
+ /* Dead LWP's aren't expected to reported a pending sigstop. */
+ lp->signalled = 0;
+
+ /* Store the pending event in the waitstatus, because
+ W_EXITCODE(0,0) == 0. */
+ store_waitstatus (&lp->waitstatus, status);
+ return lp;
}
/* Check if the current LWP has previously exited. In the nptl
return NULL;
}
+ /* Don't report signals that GDB isn't interested in, such as
+ signals that are neither printed nor stopped upon. Stopping all
+ threads can be a bit time-consuming so if we want decent
+ performance with heavily multi-threaded programs, especially when
+ they're using a high frequency timer, we'd better avoid it if we
+ can. */
+ if (WIFSTOPPED (status))
+ {
+ enum gdb_signal signo = gdb_signal_from_host (WSTOPSIG (status));
+
+ if (!non_stop)
+ {
+ /* Only do the below in all-stop, as we currently use SIGSTOP
+ to implement target_stop (see linux_nat_stop) in
+ non-stop. */
+ if (signo == GDB_SIGNAL_INT && signal_pass_state (signo) == 0)
+ {
+ /* If ^C/BREAK is typed at the tty/console, SIGINT gets
+ forwarded to the entire process group, that is, all LWPs
+ will receive it - unless they're using CLONE_THREAD to
+ share signals. Since we only want to report it once, we
+ mark it as ignored for all LWPs except this one. */
+ iterate_over_lwps (pid_to_ptid (ptid_get_pid (lp->ptid)),
+ set_ignore_sigint, NULL);
+ lp->ignore_sigint = 0;
+ }
+ else
+ maybe_clear_ignore_sigint (lp);
+ }
+
+ /* When using hardware single-step, we need to report every signal.
+ Otherwise, signals in pass_mask may be short-circuited. */
+ if (!lp->step
+ && WSTOPSIG (status) && sigismember (&pass_mask, WSTOPSIG (status)))
+ {
+ linux_resume_one_lwp (lp, lp->step, signo);
+ if (debug_linux_nat)
+ fprintf_unfiltered (gdb_stdlog,
+ "LLW: %s %s, %s (preempt 'handle')\n",
+ lp->step ?
+ "PTRACE_SINGLESTEP" : "PTRACE_CONT",
+ target_pid_to_str (lp->ptid),
+ (signo != GDB_SIGNAL_0
+ ? strsignal (gdb_signal_to_host (signo))
+ : "0"));
+ return NULL;
+ }
+ }
+
/* An interesting event. */
gdb_assert (lp);
lp->status = status;
+ save_sigtrap (lp);
return lp;
}
/* Make sure SIGCHLD is blocked until the sigsuspend below. */
block_child_signals (&prev_mask);
-retry:
- status = 0;
-
/* First check if there is a LWP with a wait status pending. */
lp = iterate_over_lwps (ptid, status_callback, NULL);
if (lp != NULL)
set_sigint_trap ();
}
- /* But if we don't find a pending event, we'll have to wait. */
+ /* But if we don't find a pending event, we'll have to wait. Always
+ pull all events out of the kernel. We'll randomly select an
+ event LWP out of all that have events, to prevent starvation. */
while (lp == NULL)
{
if (lwpid > 0)
{
- /* If this is true, then we paused LWPs momentarily, and may
- now have pending events to handle. */
- int new_pending;
-
if (debug_linux_nat)
{
fprintf_unfiltered (gdb_stdlog,
(long) lwpid, status_to_str (status));
}
- lp = linux_nat_filter_event (lwpid, status, &new_pending);
-
- /* STATUS is now no longer valid, use LP->STATUS instead. */
- status = 0;
-
- if (lp && !ptid_match (lp->ptid, ptid))
- {
- gdb_assert (lp->resumed);
-
- if (debug_linux_nat)
- fprintf_unfiltered (gdb_stdlog,
- "LWP %ld got an event %06x, "
- "leaving pending.\n",
- ptid_get_lwp (lp->ptid), lp->status);
-
- if (WIFSTOPPED (lp->status))
- {
- if (WSTOPSIG (lp->status) != SIGSTOP)
- {
- /* Cancel breakpoint hits. The breakpoint may
- be removed before we fetch events from this
- process to report to the core. It is best
- not to assume the moribund breakpoints
- heuristic always handles these cases --- it
- could be too many events go through to the
- core before this one is handled. All-stop
- always cancels breakpoint hits in all
- threads. */
- if (non_stop
- && linux_nat_lp_status_is_event (lp)
- && cancel_breakpoint (lp))
- {
- /* Throw away the SIGTRAP. */
- lp->status = 0;
-
- if (debug_linux_nat)
- fprintf_unfiltered (gdb_stdlog,
- "LLW: LWP %ld hit a "
- "breakpoint while "
- "waiting for another "
- "process; "
- "cancelled it\n",
- ptid_get_lwp (lp->ptid));
- }
- }
- else
- lp->signalled = 0;
- }
- else if (WIFEXITED (lp->status) || WIFSIGNALED (lp->status))
- {
- if (debug_linux_nat)
- fprintf_unfiltered (gdb_stdlog,
- "Process %ld exited while stopping "
- "LWPs\n",
- ptid_get_lwp (lp->ptid));
-
- /* This was the last lwp in the process. Since
- events are serialized to GDB core, and we can't
- report this one right now, but GDB core and the
- other target layers will want to be notified
- about the exit code/signal, leave the status
- pending for the next time we're able to report
- it. */
-
- /* Dead LWP's aren't expected to reported a pending
- sigstop. */
- lp->signalled = 0;
-
- /* Store the pending event in the waitstatus as
- well, because W_EXITCODE(0,0) == 0. */
- store_waitstatus (&lp->waitstatus, lp->status);
- }
-
- /* Keep looking. */
- lp = NULL;
- }
-
- if (new_pending)
- {
- /* Some LWP now has a pending event. Go all the way
- back to check it. */
- goto retry;
- }
-
- if (lp)
- {
- /* We got an event to report to the core. */
- break;
- }
-
+ linux_nat_filter_event (lwpid, status);
/* Retry until nothing comes out of waitpid. A single
SIGCHLD can indicate more than one child stopped. */
continue;
}
+ /* Now that we've pulled all events out of the kernel, check if
+ there's any LWP with a status to report to the core. */
+ lp = iterate_over_lwps (ptid, status_callback, NULL);
+ if (lp != NULL)
+ break;
+
/* Check for zombie thread group leaders. Those can't be reaped
until all other threads in the thread group are. */
check_zombie_leaders ();
status = lp->status;
lp->status = 0;
- /* Don't report signals that GDB isn't interested in, such as
- signals that are neither printed nor stopped upon. Stopping all
- threads can be a bit time-consuming so if we want decent
- performance with heavily multi-threaded programs, especially when
- they're using a high frequency timer, we'd better avoid it if we
- can. */
-
- if (WIFSTOPPED (status))
- {
- enum gdb_signal signo = gdb_signal_from_host (WSTOPSIG (status));
-
- /* When using hardware single-step, we need to report every signal.
- Otherwise, signals in pass_mask may be short-circuited. */
- if (!lp->step
- && WSTOPSIG (status) && sigismember (&pass_mask, WSTOPSIG (status)))
- {
- /* FIMXE: kettenis/2001-06-06: Should we resume all threads
- here? It is not clear we should. GDB may not expect
- other threads to run. On the other hand, not resuming
- newly attached threads may cause an unwanted delay in
- getting them running. */
- linux_resume_one_lwp (lp, lp->step, signo);
- if (debug_linux_nat)
- fprintf_unfiltered (gdb_stdlog,
- "LLW: %s %s, %s (preempt 'handle')\n",
- lp->step ?
- "PTRACE_SINGLESTEP" : "PTRACE_CONT",
- target_pid_to_str (lp->ptid),
- (signo != GDB_SIGNAL_0
- ? strsignal (gdb_signal_to_host (signo))
- : "0"));
- goto retry;
- }
-
- if (!non_stop)
- {
- /* Only do the below in all-stop, as we currently use SIGINT
- to implement target_stop (see linux_nat_stop) in
- non-stop. */
- if (signo == GDB_SIGNAL_INT && signal_pass_state (signo) == 0)
- {
- /* If ^C/BREAK is typed at the tty/console, SIGINT gets
- forwarded to the entire process group, that is, all LWPs
- will receive it - unless they're using CLONE_THREAD to
- share signals. Since we only want to report it once, we
- mark it as ignored for all LWPs except this one. */
- iterate_over_lwps (pid_to_ptid (ptid_get_pid (ptid)),
- set_ignore_sigint, NULL);
- lp->ignore_sigint = 0;
- }
- else
- maybe_clear_ignore_sigint (lp);
- }
- }
-
- /* This LWP is stopped now. */
- lp->stopped = 1;
-
- if (debug_linux_nat)
- fprintf_unfiltered (gdb_stdlog, "LLW: Candidate event %s in %s.\n",
- status_to_str (status), target_pid_to_str (lp->ptid));
-
if (!non_stop)
{
/* Now stop all other LWP's ... */
/* ... and wait until all of them have reported back that
they're no longer running. */
iterate_over_lwps (minus_one_ptid, stop_wait_callback, NULL);
+ }
+
+ /* If we're not waiting for a specific LWP, choose an event LWP from
+ among those that have had events. Giving equal priority to all
+ LWPs that have had events helps prevent starvation. */
+ if (ptid_equal (ptid, minus_one_ptid) || ptid_is_pid (ptid))
+ select_event_lwp (ptid, &lp, &status);
+
+ gdb_assert (lp != NULL);
+
+ /* Now that we've selected our final event LWP, un-adjust its PC if
+ it was a software breakpoint. */
+ if (lp->stop_reason == LWP_STOPPED_BY_SW_BREAKPOINT)
+ {
+ struct regcache *regcache = get_thread_regcache (lp->ptid);
+ struct gdbarch *gdbarch = get_regcache_arch (regcache);
+ int decr_pc = target_decr_pc_after_break (gdbarch);
- /* If we're not waiting for a specific LWP, choose an event LWP
- from among those that have had events. Giving equal priority
- to all LWPs that have had events helps prevent
- starvation. */
- if (ptid_equal (ptid, minus_one_ptid) || ptid_is_pid (ptid))
- select_event_lwp (ptid, &lp, &status);
+ if (decr_pc != 0)
+ {
+ CORE_ADDR pc;
- /* Now that we've selected our final event LWP, cancel any
- breakpoints in other LWPs that have hit a GDB breakpoint.
- See the comment in cancel_breakpoints_callback to find out
- why. */
- iterate_over_lwps (minus_one_ptid, cancel_breakpoints_callback, lp);
+ pc = regcache_read_pc (regcache);
+ regcache_write_pc (regcache, pc + decr_pc);
+ }
+ }
- /* We'll need this to determine whether to report a SIGSTOP as
- TARGET_WAITKIND_0. Need to take a copy because
- resume_clear_callback clears it. */
- last_resume_kind = lp->last_resume_kind;
+ /* We'll need this to determine whether to report a SIGSTOP as
+ GDB_SIGNAL_0. Need to take a copy because resume_clear_callback
+ clears it. */
+ last_resume_kind = lp->last_resume_kind;
+ if (!non_stop)
+ {
/* In all-stop, from the core's perspective, all LWPs are now
stopped until a new resume action is sent over. */
iterate_over_lwps (minus_one_ptid, resume_clear_callback, NULL);
}
else
{
- /* See above. */
- last_resume_kind = lp->last_resume_kind;
resume_clear_callback (lp, NULL);
}