80 lines
2.3 KiB
Plaintext
80 lines
2.3 KiB
Plaintext
|
From: Andreas Schwab <schwab@suse.de>
|
||
|
Subject: Add compat handler for PTRACE_GETSIGINFO
|
||
|
Patch-mainline: not yet
|
||
|
|
||
|
Current versions of gdb require a working implementation of
|
||
|
PTRACE_GETSIGINFO for proper watchpoint support. Since struct siginfo
|
||
|
contains pointers it must be converted when passed to a 32-bit debugger.
|
||
|
|
||
|
Signed-off-by: Andreas Schwab <schwab@suse.de>
|
||
|
---
|
||
|
arch/powerpc/kernel/ppc32.h | 2 ++
|
||
|
arch/powerpc/kernel/ptrace32.c | 27 +++++++++++++++++++++++++++
|
||
|
2 files changed, 29 insertions(+)
|
||
|
|
||
|
--- a/arch/powerpc/kernel/ppc32.h
|
||
|
+++ b/arch/powerpc/kernel/ppc32.h
|
||
|
@@ -136,4 +136,6 @@ struct ucontext32 {
|
||
|
struct mcontext32 uc_mcontext;
|
||
|
};
|
||
|
|
||
|
+extern int copy_siginfo_to_user32(struct compat_siginfo __user *d, siginfo_t *s);
|
||
|
+
|
||
|
#endif /* _PPC64_PPC32_H */
|
||
|
--- a/arch/powerpc/kernel/ptrace32.c
|
||
|
+++ b/arch/powerpc/kernel/ptrace32.c
|
||
|
@@ -28,12 +28,15 @@
|
||
|
#include <linux/security.h>
|
||
|
#include <linux/signal.h>
|
||
|
#include <linux/compat.h>
|
||
|
+#include <linux/elf.h>
|
||
|
|
||
|
#include <asm/uaccess.h>
|
||
|
#include <asm/page.h>
|
||
|
#include <asm/pgtable.h>
|
||
|
#include <asm/system.h>
|
||
|
|
||
|
+#include "ppc32.h"
|
||
|
+
|
||
|
/*
|
||
|
* does not yet catch signals sent when the child dies.
|
||
|
* in exit.c or in signal.c.
|
||
|
@@ -69,6 +72,27 @@ static long compat_ptrace_old(struct tas
|
||
|
#define FPRINDEX(i) TS_FPRWIDTH * FPRNUMBER(i) * 2 + FPRHALF(i)
|
||
|
#define FPRINDEX_3264(i) (TS_FPRWIDTH * ((i) - PT_FPR0))
|
||
|
|
||
|
+static int compat_ptrace_getsiginfo(struct task_struct *child, compat_siginfo_t __user *data)
|
||
|
+{
|
||
|
+ siginfo_t lastinfo;
|
||
|
+ int error = -ESRCH;
|
||
|
+
|
||
|
+ read_lock(&tasklist_lock);
|
||
|
+ if (likely(child->sighand != NULL)) {
|
||
|
+ error = -EINVAL;
|
||
|
+ spin_lock_irq(&child->sighand->siglock);
|
||
|
+ if (likely(child->last_siginfo != NULL)) {
|
||
|
+ lastinfo = *child->last_siginfo;
|
||
|
+ error = 0;
|
||
|
+ }
|
||
|
+ spin_unlock_irq(&child->sighand->siglock);
|
||
|
+ }
|
||
|
+ read_unlock(&tasklist_lock);
|
||
|
+ if (!error)
|
||
|
+ return copy_siginfo_to_user32(data, &lastinfo);
|
||
|
+ return error;
|
||
|
+}
|
||
|
+
|
||
|
long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
|
||
|
compat_ulong_t caddr, compat_ulong_t cdata)
|
||
|
{
|
||
|
@@ -296,6 +320,9 @@ long compat_arch_ptrace(struct task_stru
|
||
|
0, PT_REGS_COUNT * sizeof(compat_long_t),
|
||
|
compat_ptr(data));
|
||
|
|
||
|
+ case PTRACE_GETSIGINFO:
|
||
|
+ return compat_ptrace_getsiginfo(child, compat_ptr(data));
|
||
|
+
|
||
|
case PTRACE_GETFPREGS:
|
||
|
case PTRACE_SETFPREGS:
|
||
|
case PTRACE_GETVRREGS:
|