* 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.
This commit is contained in:
Daniel Jacobowitz 2006-09-28 22:46:29 +00:00
parent ef05d49568
commit 32ca6d6157
3 changed files with 55 additions and 9 deletions

View File

@ -1,3 +1,14 @@
2006-09-28 Daniel Jacobowitz <dan@codesourcery.com>
* 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 <dan@codesourcery.com> 2006-09-21 Daniel Jacobowitz <dan@codesourcery.com>
* remote-utils.c (try_rle): New function. * remote-utils.c (try_rle): New function.

View File

@ -38,6 +38,11 @@
#include <errno.h> #include <errno.h>
#include <sys/syscall.h> #include <sys/syscall.h>
#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, /* ``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 however. This requires changing the ID in place when we go from !using_threads
to using_threads, immediately. to using_threads, immediately.
@ -54,7 +59,7 @@ int stopping_threads;
int using_threads; int using_threads;
static void linux_resume_one_process (struct inferior_list_entry *entry, 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 linux_resume (struct thread_resume *resume_info);
static void stop_all_processes (void); static void stop_all_processes (void);
static int linux_wait_for_event (struct thread_info *child); 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 struct pending_signals
{ {
int signal; int signal;
siginfo_t info;
struct pending_signals *prev; 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 So instead of reporting the old SIGTRAP, pretend we got to
the breakpoint just after it was removed instead of just the breakpoint just after it was removed instead of just
before; resume the process. */ before; resume the process. */
linux_resume_one_process (&process->head, 0, 0); linux_resume_one_process (&process->head, 0, 0, NULL);
return 0; return 0;
} }
@ -419,6 +425,8 @@ linux_wait_for_process (struct process_info **childp, int *wstatp)
(*childp)->stopped = 1; (*childp)->stopped = 1;
(*childp)->pending_is_breakpoint = 0; (*childp)->pending_is_breakpoint = 0;
(*childp)->last_status = *wstatp;
if (debug_threads if (debug_threads
&& WIFSTOPPED (*wstatp)) && WIFSTOPPED (*wstatp))
{ {
@ -527,7 +535,7 @@ linux_wait_for_event (struct thread_info *child)
fprintf (stderr, "Expected stop.\n"); fprintf (stderr, "Expected stop.\n");
event_child->stop_expected = 0; event_child->stop_expected = 0;
linux_resume_one_process (&event_child->head, linux_resume_one_process (&event_child->head,
event_child->stepping, 0); event_child->stepping, 0, NULL);
continue; continue;
} }
@ -537,13 +545,20 @@ linux_wait_for_event (struct thread_info *child)
&& (WSTOPSIG (wstat) == __SIGRTMIN && (WSTOPSIG (wstat) == __SIGRTMIN
|| WSTOPSIG (wstat) == __SIGRTMIN + 1)) || WSTOPSIG (wstat) == __SIGRTMIN + 1))
{ {
siginfo_t info, *info_p;
if (debug_threads) if (debug_threads)
fprintf (stderr, "Ignored signal %d for %ld (LWP %ld).\n", fprintf (stderr, "Ignored signal %d for %ld (LWP %ld).\n",
WSTOPSIG (wstat), event_child->tid, WSTOPSIG (wstat), event_child->tid,
event_child->head.id); 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, linux_resume_one_process (&event_child->head,
event_child->stepping, event_child->stepping,
WSTOPSIG (wstat)); WSTOPSIG (wstat), info_p);
continue; continue;
} }
} }
@ -572,7 +587,7 @@ linux_wait_for_event (struct thread_info *child)
event_child->bp_reinsert = 0; event_child->bp_reinsert = 0;
/* Clear the single-stepping flag and SIGTRAP as we resume. */ /* 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; continue;
} }
@ -609,13 +624,13 @@ linux_wait_for_event (struct thread_info *child)
{ {
event_child->bp_reinsert = stop_pc; event_child->bp_reinsert = stop_pc;
uninsert_breakpoint (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 else
{ {
reinsert_breakpoint_by_bp reinsert_breakpoint_by_bp
(stop_pc, (*the_low_target.breakpoint_reinsert_addr) ()); (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; continue;
@ -840,7 +855,7 @@ stop_all_processes (void)
static void static void
linux_resume_one_process (struct inferior_list_entry *entry, 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 process_info *process = (struct process_info *) entry;
struct thread_info *saved_inferior; 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 = malloc (sizeof (*p_sig));
p_sig->prev = process->pending_signals; p_sig->prev = process->pending_signals;
p_sig->signal = signal; 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; process->pending_signals = p_sig;
} }
@ -914,6 +933,9 @@ linux_resume_one_process (struct inferior_list_entry *entry,
p_sig = &(*p_sig)->prev; p_sig = &(*p_sig)->prev;
signal = (*p_sig)->signal; signal = (*p_sig)->signal;
if ((*p_sig)->info.si_signo != 0)
ptrace (PTRACE_SETSIGINFO, process->lwpid, 0, &(*p_sig)->info);
free (*p_sig); free (*p_sig);
*p_sig = NULL; *p_sig = NULL;
} }
@ -980,7 +1002,7 @@ linux_continue_one_thread (struct inferior_list_entry *entry)
else else
step = process->resume->step; 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; process->resume = NULL;
} }
@ -1011,6 +1033,16 @@ linux_queue_one_thread (struct inferior_list_entry *entry)
p_sig = malloc (sizeof (*p_sig)); p_sig = malloc (sizeof (*p_sig));
p_sig->prev = process->pending_signals; p_sig->prev = process->pending_signals;
p_sig->signal = process->resume->sig; 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; process->pending_signals = p_sig;
} }

View File

@ -92,6 +92,9 @@ struct process_info
event already received in a wait()). */ event already received in a wait()). */
int stopped; 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 /* If this flag is set, we have sent a SIGSTOP to this process and are
waiting for it to stop. */ waiting for it to stop. */
int sigstop_sent; int sigstop_sent;