diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2007-06-04 01:15:46 -0400 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2007-06-14 08:29:57 -0400 |
commit | 912000e73ee8fcb97831b123c9c3a7274b71cab7 (patch) | |
tree | a81fcda0f11cbb4c428ffae9f9f55f12677051fe /arch/powerpc/kernel/ptrace.c | |
parent | 1b6610d6fcb8dc23631cf48f09aa02e6649e379d (diff) |
[POWERPC] Allow ptrace write to pt_regs trap and orig_r3
This patch allows a ptracer to write to the "trap" and "orig_r3" words
of the pt_regs.
This, along with a subsequent patch to the signal restart code, should
enable gdb to properly handle syscall restarting after executing a separate
function (at least when there's no restart block).
This patch also removes ptrace32.c code toying directly with the registers
and makes it use the ptrace_get/put_reg() accessors for everything so that
the logic for checking what is permitted is in only one place.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/kernel/ptrace.c')
-rw-r--r-- | arch/powerpc/kernel/ptrace.c | 9 |
1 files changed, 6 insertions, 3 deletions
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c index c9c330d35c17..dd4837c4a68a 100644 --- a/arch/powerpc/kernel/ptrace.c +++ b/arch/powerpc/kernel/ptrace.c | |||
@@ -75,10 +75,15 @@ int ptrace_put_reg(struct task_struct *task, int regno, unsigned long data) | |||
75 | if (task->thread.regs == NULL) | 75 | if (task->thread.regs == NULL) |
76 | return -EIO; | 76 | return -EIO; |
77 | 77 | ||
78 | if (regno <= PT_MAX_PUT_REG) { | 78 | if (regno <= PT_MAX_PUT_REG || regno == PT_TRAP) { |
79 | if (regno == PT_MSR) | 79 | if (regno == PT_MSR) |
80 | data = (data & MSR_DEBUGCHANGE) | 80 | data = (data & MSR_DEBUGCHANGE) |
81 | | (task->thread.regs->msr & ~MSR_DEBUGCHANGE); | 81 | | (task->thread.regs->msr & ~MSR_DEBUGCHANGE); |
82 | /* We prevent mucking around with the reserved area of trap | ||
83 | * which are used internally by the kernel | ||
84 | */ | ||
85 | if (regno == PT_TRAP) | ||
86 | data &= 0xfff0; | ||
82 | ((unsigned long *)task->thread.regs)[regno] = data; | 87 | ((unsigned long *)task->thread.regs)[regno] = data; |
83 | return 0; | 88 | return 0; |
84 | } | 89 | } |
@@ -409,8 +414,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
409 | break; | 414 | break; |
410 | 415 | ||
411 | CHECK_FULL_REGS(child->thread.regs); | 416 | CHECK_FULL_REGS(child->thread.regs); |
412 | if (index == PT_ORIG_R3) | ||
413 | break; | ||
414 | if (index < PT_FPR0) { | 417 | if (index < PT_FPR0) { |
415 | ret = ptrace_put_reg(child, index, data); | 418 | ret = ptrace_put_reg(child, index, data); |
416 | } else { | 419 | } else { |