aboutsummaryrefslogtreecommitdiff
path: root/gdb
diff options
context:
space:
mode:
Diffstat (limited to 'gdb')
-rw-r--r--gdb/gdbserver/ChangeLog11
-rw-r--r--gdb/gdbserver/linux-low.c50
-rw-r--r--gdb/gdbserver/linux-low.h3
3 files changed, 55 insertions, 9 deletions
diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog
index 737f9cd..18427bf 100644
--- a/gdb/gdbserver/ChangeLog
+++ b/gdb/gdbserver/ChangeLog
@@ -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>
* remote-utils.c (try_rle): New function.
diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c
index b0f0b60..d4839a4 100644
--- a/gdb/gdbserver/linux-low.c
+++ b/gdb/gdbserver/linux-low.c
@@ -38,6 +38,11 @@
#include <errno.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,
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 516b40d..d090b31 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;