From 32ca6d6157b3c1d65205631f7598f7dc3853935c Mon Sep 17 00:00:00 2001 From: Daniel Jacobowitz Date: Thu, 28 Sep 2006 22:46:29 +0000 Subject: [PATCH] * linux-low.c (PTRACE_GETSIGINFO, PTRACE_SETSIGINFO): Define. (linux_resume_one_process): Take a siginfo_t *. Update all callers. Queue it if necessary. Use PTRACE_SETSIGINFO. (struct pending_signals): Add a siginfo_t. (linux_wait_for_process): Always set last_status. (linux_wait_for_event): Use PTRACE_GETSIGINFO. (linux_queue_one_thread): Use PTRACE_GETSIGINFO. * linux-low.h (struct process_info): Add last_status. --- gdb/gdbserver/ChangeLog | 11 +++++++++ gdb/gdbserver/linux-low.c | 50 ++++++++++++++++++++++++++++++++------- gdb/gdbserver/linux-low.h | 3 +++ 3 files changed, 55 insertions(+), 9 deletions(-) diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog index 737f9cd0040..18427bf3138 100644 --- a/gdb/gdbserver/ChangeLog +++ b/gdb/gdbserver/ChangeLog @@ -1,3 +1,14 @@ +2006-09-28 Daniel Jacobowitz + + * linux-low.c (PTRACE_GETSIGINFO, PTRACE_SETSIGINFO): Define. + (linux_resume_one_process): Take a siginfo_t *. Update all + callers. Queue it if necessary. Use PTRACE_SETSIGINFO. + (struct pending_signals): Add a siginfo_t. + (linux_wait_for_process): Always set last_status. + (linux_wait_for_event): Use PTRACE_GETSIGINFO. + (linux_queue_one_thread): Use PTRACE_GETSIGINFO. + * linux-low.h (struct process_info): Add last_status. + 2006-09-21 Daniel Jacobowitz * remote-utils.c (try_rle): New function. diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c index b0f0b6096e9..d4839a4c2cc 100644 --- a/gdb/gdbserver/linux-low.c +++ b/gdb/gdbserver/linux-low.c @@ -38,6 +38,11 @@ #include #include +#ifndef PTRACE_GETSIGINFO +# define PTRACE_GETSIGINFO 0x4202 +# define PTRACE_SETSIGINFO 0x4203 +#endif + /* ``all_threads'' is keyed by the LWP ID - it should be the thread ID instead, however. This requires changing the ID in place when we go from !using_threads to using_threads, immediately. @@ -54,7 +59,7 @@ int stopping_threads; int using_threads; static void linux_resume_one_process (struct inferior_list_entry *entry, - int step, int signal); + int step, int signal, siginfo_t *info); static void linux_resume (struct thread_resume *resume_info); static void stop_all_processes (void); static int linux_wait_for_event (struct thread_info *child); @@ -62,6 +67,7 @@ static int linux_wait_for_event (struct thread_info *child); struct pending_signals { int signal; + siginfo_t info; struct pending_signals *prev; }; @@ -366,7 +372,7 @@ status_pending_p (struct inferior_list_entry *entry, void *dummy) So instead of reporting the old SIGTRAP, pretend we got to the breakpoint just after it was removed instead of just before; resume the process. */ - linux_resume_one_process (&process->head, 0, 0); + linux_resume_one_process (&process->head, 0, 0, NULL); return 0; } @@ -419,6 +425,8 @@ linux_wait_for_process (struct process_info **childp, int *wstatp) (*childp)->stopped = 1; (*childp)->pending_is_breakpoint = 0; + (*childp)->last_status = *wstatp; + if (debug_threads && WIFSTOPPED (*wstatp)) { @@ -527,7 +535,7 @@ linux_wait_for_event (struct thread_info *child) fprintf (stderr, "Expected stop.\n"); event_child->stop_expected = 0; linux_resume_one_process (&event_child->head, - event_child->stepping, 0); + event_child->stepping, 0, NULL); continue; } @@ -537,13 +545,20 @@ linux_wait_for_event (struct thread_info *child) && (WSTOPSIG (wstat) == __SIGRTMIN || WSTOPSIG (wstat) == __SIGRTMIN + 1)) { + siginfo_t info, *info_p; + if (debug_threads) fprintf (stderr, "Ignored signal %d for %ld (LWP %ld).\n", WSTOPSIG (wstat), event_child->tid, event_child->head.id); + + if (ptrace (PTRACE_GETSIGINFO, event_child->lwpid, 0, &info) == 0) + info_p = &info; + else + info_p = NULL; linux_resume_one_process (&event_child->head, event_child->stepping, - WSTOPSIG (wstat)); + WSTOPSIG (wstat), info_p); continue; } } @@ -572,7 +587,7 @@ linux_wait_for_event (struct thread_info *child) event_child->bp_reinsert = 0; /* Clear the single-stepping flag and SIGTRAP as we resume. */ - linux_resume_one_process (&event_child->head, 0, 0); + linux_resume_one_process (&event_child->head, 0, 0, NULL); continue; } @@ -609,13 +624,13 @@ linux_wait_for_event (struct thread_info *child) { event_child->bp_reinsert = stop_pc; uninsert_breakpoint (stop_pc); - linux_resume_one_process (&event_child->head, 1, 0); + linux_resume_one_process (&event_child->head, 1, 0, NULL); } else { reinsert_breakpoint_by_bp (stop_pc, (*the_low_target.breakpoint_reinsert_addr) ()); - linux_resume_one_process (&event_child->head, 0, 0); + linux_resume_one_process (&event_child->head, 0, 0, NULL); } continue; @@ -840,7 +855,7 @@ stop_all_processes (void) static void linux_resume_one_process (struct inferior_list_entry *entry, - int step, int signal) + int step, int signal, siginfo_t *info) { struct process_info *process = (struct process_info *) entry; struct thread_info *saved_inferior; @@ -859,6 +874,10 @@ linux_resume_one_process (struct inferior_list_entry *entry, p_sig = malloc (sizeof (*p_sig)); p_sig->prev = process->pending_signals; p_sig->signal = signal; + if (info == NULL) + memset (&p_sig->info, 0, sizeof (siginfo_t)); + else + memcpy (&p_sig->info, info, sizeof (siginfo_t)); process->pending_signals = p_sig; } @@ -914,6 +933,9 @@ linux_resume_one_process (struct inferior_list_entry *entry, p_sig = &(*p_sig)->prev; signal = (*p_sig)->signal; + if ((*p_sig)->info.si_signo != 0) + ptrace (PTRACE_SETSIGINFO, process->lwpid, 0, &(*p_sig)->info); + free (*p_sig); *p_sig = NULL; } @@ -980,7 +1002,7 @@ linux_continue_one_thread (struct inferior_list_entry *entry) else step = process->resume->step; - linux_resume_one_process (&process->head, step, process->resume->sig); + linux_resume_one_process (&process->head, step, process->resume->sig, NULL); process->resume = NULL; } @@ -1011,6 +1033,16 @@ linux_queue_one_thread (struct inferior_list_entry *entry) p_sig = malloc (sizeof (*p_sig)); p_sig->prev = process->pending_signals; p_sig->signal = process->resume->sig; + memset (&p_sig->info, 0, sizeof (siginfo_t)); + + /* If this is the same signal we were previously stopped by, + make sure to queue its siginfo. We can ignore the return + value of ptrace; if it fails, we'll skip + PTRACE_SETSIGINFO. */ + if (WIFSTOPPED (process->last_status) + && WSTOPSIG (process->last_status) == process->resume->sig) + ptrace (PTRACE_GETSIGINFO, process->lwpid, 0, &p_sig->info); + process->pending_signals = p_sig; } diff --git a/gdb/gdbserver/linux-low.h b/gdb/gdbserver/linux-low.h index 516b40d8717..d090b31a235 100644 --- a/gdb/gdbserver/linux-low.h +++ b/gdb/gdbserver/linux-low.h @@ -92,6 +92,9 @@ struct process_info event already received in a wait()). */ int stopped; + /* When stopped is set, the last wait status recorded for this process. */ + int last_status; + /* If this flag is set, we have sent a SIGSTOP to this process and are waiting for it to stop. */ int sigstop_sent; -- 2.30.2