]>
Commit | Line | Data |
---|---|---|
2cb7cef9 BS |
1 | From: Andreas Schwab <schwab@suse.de> |
2 | Subject: Add compat handler for PTRACE_GETSIGINFO | |
3 | ||
4 | Current versions of gdb require a working implementation of | |
5 | PTRACE_GETSIGINFO for proper watchpoint support. Since struct siginfo | |
6 | contains pointers it must be converted when passed to a 32-bit debugger. | |
7 | ||
8 | Signed-off-by: Andreas Schwab <schwab@suse.de> | |
9 | --- | |
10 | arch/powerpc/kernel/ppc32.h | 2 ++ | |
11 | arch/powerpc/kernel/ptrace32.c | 27 +++++++++++++++++++++++++++ | |
12 | 2 files changed, 29 insertions(+) | |
13 | ||
14 | --- a/arch/powerpc/kernel/ppc32.h | |
15 | +++ b/arch/powerpc/kernel/ppc32.h | |
16 | @@ -136,4 +136,6 @@ struct ucontext32 { | |
17 | struct mcontext32 uc_mcontext; | |
18 | }; | |
19 | ||
20 | +extern int copy_siginfo_to_user32(struct compat_siginfo __user *d, siginfo_t *s); | |
21 | + | |
22 | #endif /* _PPC64_PPC32_H */ | |
23 | --- a/arch/powerpc/kernel/ptrace32.c | |
24 | +++ b/arch/powerpc/kernel/ptrace32.c | |
25 | @@ -29,12 +29,15 @@ | |
26 | #include <linux/security.h> | |
27 | #include <linux/signal.h> | |
28 | #include <linux/compat.h> | |
29 | +#include <linux/elf.h> | |
30 | ||
31 | #include <asm/uaccess.h> | |
32 | #include <asm/page.h> | |
33 | #include <asm/pgtable.h> | |
34 | #include <asm/system.h> | |
35 | ||
36 | +#include "ppc32.h" | |
37 | + | |
38 | /* | |
39 | * does not yet catch signals sent when the child dies. | |
40 | * in exit.c or in signal.c. | |
41 | @@ -69,6 +72,27 @@ static long compat_ptrace_old(struct tas | |
42 | #define FPRHALF(i) (((i) - PT_FPR0) & 1) | |
43 | #define FPRINDEX(i) TS_FPRWIDTH * FPRNUMBER(i) + FPRHALF(i) | |
44 | ||
45 | +static int compat_ptrace_getsiginfo(struct task_struct *child, compat_siginfo_t __user *data) | |
46 | +{ | |
47 | + siginfo_t lastinfo; | |
48 | + int error = -ESRCH; | |
49 | + | |
50 | + read_lock(&tasklist_lock); | |
51 | + if (likely(child->sighand != NULL)) { | |
52 | + error = -EINVAL; | |
53 | + spin_lock_irq(&child->sighand->siglock); | |
54 | + if (likely(child->last_siginfo != NULL)) { | |
55 | + lastinfo = *child->last_siginfo; | |
56 | + error = 0; | |
57 | + } | |
58 | + spin_unlock_irq(&child->sighand->siglock); | |
59 | + } | |
60 | + read_unlock(&tasklist_lock); | |
61 | + if (!error) | |
62 | + return copy_siginfo_to_user32(data, &lastinfo); | |
63 | + return error; | |
64 | +} | |
65 | + | |
66 | long compat_arch_ptrace(struct task_struct *child, compat_long_t request, | |
67 | compat_ulong_t caddr, compat_ulong_t cdata) | |
68 | { | |
69 | @@ -290,6 +314,9 @@ long compat_arch_ptrace(struct task_stru | |
70 | 0, PT_REGS_COUNT * sizeof(compat_long_t), | |
71 | compat_ptr(data)); | |
72 | ||
73 | + case PTRACE_GETSIGINFO: | |
74 | + return compat_ptrace_getsiginfo(child, compat_ptr(data)); | |
75 | + | |
76 | case PTRACE_GETFPREGS: | |
77 | case PTRACE_SETFPREGS: | |
78 | case PTRACE_GETVRREGS: |