}
static int
-pull_pid_from_list (struct simple_pid_list **listp, int pid, int *status)
+pull_pid_from_list (struct simple_pid_list **listp, int pid, int *statusp)
{
struct simple_pid_list **p;
{
struct simple_pid_list *next = (*p)->next;
- *status = (*p)->status;
+ *statusp = (*p)->status;
xfree (*p);
*p = next;
return 1;
/* Wrapper function for waitpid which handles EINTR. */
static int
-my_waitpid (int pid, int *status, int flags)
+my_waitpid (int pid, int *statusp, int flags)
{
int ret;
do
{
- ret = waitpid (pid, status, flags);
+ ret = waitpid (pid, statusp, flags);
}
while (ret == -1 && errno == EINTR);
static int stop_wait_callback (struct lwp_info *lp, void *data);
static int linux_thread_alive (ptid_t ptid);
static char *linux_child_pid_to_exec_file (int pid);
-static int cancel_breakpoint (struct lwp_info *lp);
\f
/* Convert wait status STATUS to a string. Used for printing debug
}
else if (WIFSIGNALED (status))
snprintf (buf, sizeof (buf), "%s (terminated)",
- strsignal (WSTOPSIG (status)));
+ strsignal (WTERMSIG (status)));
else
snprintf (buf, sizeof (buf), "%d (exited)", WEXITSTATUS (status));
}
else if (lp->stopped && lp->status == 0)
{
+ struct thread_info *tp = find_thread_ptid (lp->ptid);
+ /* lp->step may already contain a stale value. */
+ int step = tp ? currently_stepping (tp) : 0;
+
if (debug_linux_nat)
fprintf_unfiltered (gdb_stdlog,
- "RC: PTRACE_CONT %s, 0, 0 (resuming sibling)\n",
+ "RC: %s %s, 0, 0 (resuming sibling)\n",
+ step ? "PTRACE_SINGLESTEP" : "PTRACE_CONT",
target_pid_to_str (lp->ptid));
linux_ops->to_resume (linux_ops,
pid_to_ptid (GET_LWP (lp->ptid)),
- 0, TARGET_SIGNAL_0);
+ step, TARGET_SIGNAL_0);
if (debug_linux_nat)
fprintf_unfiltered (gdb_stdlog,
- "RC: PTRACE_CONT %s, 0, 0 (resume sibling)\n",
+ "RC: %s %s, 0, 0 (resume sibling)\n",
+ step ? "PTRACE_SINGLESTEP" : "PTRACE_CONT",
target_pid_to_str (lp->ptid));
lp->stopped = 0;
- lp->step = 0;
+ lp->step = step;
memset (&lp->siginfo, 0, sizeof (lp->siginfo));
lp->stopped_by_watchpoint = 0;
}
"LLR: Preparing to %s %s, %s, inferior_ptid %s\n",
step ? "step" : "resume",
target_pid_to_str (ptid),
- signo ? strsignal (signo) : "0",
+ (signo != TARGET_SIGNAL_0
+ ? strsignal (target_signal_to_host (signo)) : "0"),
target_pid_to_str (inferior_ptid));
block_child_signals (&prev_mask);
if (lp->status && WIFSTOPPED (lp->status))
{
- int saved_signo;
+ enum target_signal saved_signo;
struct inferior *inf;
inf = find_inferior_pid (ptid_get_pid (lp->ptid));
"LLR: %s %s, %s (resume event thread)\n",
step ? "PTRACE_SINGLESTEP" : "PTRACE_CONT",
target_pid_to_str (ptid),
- signo ? strsignal (signo) : "0");
+ (signo != TARGET_SIGNAL_0
+ ? strsignal (target_signal_to_host (signo)) : "0"));
restore_child_signals_mask (&prev_mask);
if (target_can_async_p ())
catchpoints. */
if (!stopping)
{
- int signo;
+ enum target_signal signo;
new_lp->stopped = 0;
new_lp->resumed = 1;
linux_ops->to_resume (linux_ops, pid_to_ptid (new_pid),
0, signo);
}
+ else
+ {
+ if (status != 0)
+ {
+ /* We created NEW_LP so it cannot yet contain STATUS. */
+ gdb_assert (new_lp->status == 0);
+
+ /* Save the wait status to report later. */
+ if (debug_linux_nat)
+ fprintf_unfiltered (gdb_stdlog,
+ "LHEW: waitpid of new LWP %ld, "
+ "saving status %s\n",
+ (long) GET_LWP (new_lp->ptid),
+ status_to_str (status));
+ new_lp->status = status;
+ }
+ }
if (debug_linux_nat)
fprintf_unfiltered (gdb_stdlog,
return lp->stopped_data_address_p;
}
+/* Commonly any breakpoint / watchpoint generate only SIGTRAP. */
+
+static int
+sigtrap_is_event (int status)
+{
+ 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. */
+
+void
+linux_nat_set_status_is_event (struct target_ops *t,
+ int (*status_is_event) (int status))
+{
+ linux_nat_status_is_event = status_is_event;
+}
+
/* Wait until LP is stopped. */
static int
if (WSTOPSIG (status) != SIGSTOP)
{
- if (WSTOPSIG (status) == SIGTRAP)
+ if (linux_nat_status_is_event (status))
{
/* If a LWP other than the LWP that we're reporting an
event for has hit a GDB breakpoint (as opposed to
gdb_assert (count != NULL);
/* Count only resumed LWPs that have a SIGTRAP event pending. */
- if (lp->status != 0 && lp->resumed
- && WIFSTOPPED (lp->status) && WSTOPSIG (lp->status) == SIGTRAP)
+ if (lp->resumed && linux_nat_lp_status_is_event (lp))
(*count)++;
return 0;
gdb_assert (selector != NULL);
/* Select only resumed LWPs that have a SIGTRAP event pending. */
- if (lp->status != 0 && lp->resumed
- && WIFSTOPPED (lp->status) && WSTOPSIG (lp->status) == SIGTRAP)
+ if (lp->resumed && linux_nat_lp_status_is_event (lp))
if ((*selector)-- == 0)
return 1;
delete or disable the breakpoint, but the LWP will have already
tripped on it. */
- if (lp->waitstatus.kind == TARGET_WAITKIND_IGNORE
- && lp->status != 0
- && WIFSTOPPED (lp->status) && WSTOPSIG (lp->status) == SIGTRAP
+ if (linux_nat_lp_status_is_event (lp)
&& cancel_breakpoint (lp))
/* Throw away the SIGTRAP. */
lp->status = 0;
return NULL;
}
- if (WIFSTOPPED (status) && WSTOPSIG (status) == SIGTRAP)
+ if (linux_nat_status_is_event (status))
{
/* Save the trap's siginfo in case we need it later. */
save_siginfo (lp);
lp = linux_nat_filter_event (lwpid, status, options);
+ /* STATUS is now no longer valid, use LP->STATUS instead. */
+ status = 0;
+
if (lp
&& ptid_is_pid (ptid)
&& ptid_get_pid (lp->ptid) != ptid_get_pid (ptid))
if (debug_linux_nat)
fprintf (stderr, "LWP %ld got an event %06x, leaving pending.\n",
- ptid_get_lwp (lp->ptid), status);
+ ptid_get_lwp (lp->ptid), lp->status);
if (WIFSTOPPED (lp->status))
{
always cancels breakpoint hits in all
threads. */
if (non_stop
- && lp->waitstatus.kind == TARGET_WAITKIND_IGNORE
- && WSTOPSIG (lp->status) == SIGTRAP
+ && linux_nat_lp_status_is_event (lp)
&& cancel_breakpoint (lp))
{
/* Throw away the SIGTRAP. */
lp->signalled = 0;
}
}
- else if (WIFEXITED (status) || WIFSIGNALED (status))
+ else if (WIFEXITED (lp->status) || WIFSIGNALED (lp->status))
{
if (debug_linux_nat)
fprintf (stderr, "Process %ld exited while stopping LWPs\n",
if (WIFSTOPPED (status))
{
- int signo = target_signal_from_host (WSTOPSIG (status));
+ enum target_signal signo = target_signal_from_host (WSTOPSIG (status));
struct inferior *inf;
inf = find_inferior_pid (ptid_get_pid (lp->ptid));
lp->step ?
"PTRACE_SINGLESTEP" : "PTRACE_CONT",
target_pid_to_str (lp->ptid),
- signo ? strsignal (signo) : "0");
+ (signo != TARGET_SIGNAL_0
+ ? strsignal (target_signal_to_host (signo))
+ : "0"));
lp->stopped = 0;
goto retry;
}
else
lp->resumed = 0;
- if (WIFSTOPPED (status) && WSTOPSIG (status) == SIGTRAP)
+ if (linux_nat_status_is_event (status))
{
if (debug_linux_nat)
fprintf_unfiltered (gdb_stdlog,
regions in the inferior for a corefile. */
static int
-linux_nat_find_memory_regions (int (*func) (CORE_ADDR,
- unsigned long,
- int, int, int, void *), void *obfd)
+linux_nat_find_memory_regions (find_memory_region_ftype func, void *obfd)
{
int pid = PIDGET (inferior_ptid);
char mapsfilename[MAXPATHLEN];
if (strcmp (sect_list->sect_name, ".reg") == 0)
note_data = (char *) elfcore_write_prstatus
(obfd, note_data, note_size,
- lwp, stop_signal, gdb_regset);
+ lwp, target_signal_to_host (stop_signal),
+ gdb_regset);
else
note_data = (char *) elfcore_write_register_note
(obfd, note_data, note_size,
else
fill_gregset (regcache, &gregs, -1);
- note_data = (char *) elfcore_write_prstatus (obfd,
- note_data,
- note_size,
- lwp,
- stop_signal, &gregs);
+ note_data = (char *) elfcore_write_prstatus
+ (obfd, note_data, note_size, lwp, target_signal_to_host (stop_signal),
+ &gregs);
if (core_regset_p
&& (regset = gdbarch_regset_from_core_section (gdbarch, ".reg2",