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/ptrace32.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/ptrace32.c')
-rw-r--r-- | arch/powerpc/kernel/ptrace32.c | 27 |
1 files changed, 14 insertions, 13 deletions
diff --git a/arch/powerpc/kernel/ptrace32.c b/arch/powerpc/kernel/ptrace32.c index 4511b422992f..aae6a988e183 100644 --- a/arch/powerpc/kernel/ptrace32.c +++ b/arch/powerpc/kernel/ptrace32.c | |||
@@ -206,7 +206,9 @@ long compat_sys_ptrace(int request, int pid, unsigned long addr, | |||
206 | else | 206 | else |
207 | part = 0; /* want the 1st half of the register (left-most). */ | 207 | part = 0; /* want the 1st half of the register (left-most). */ |
208 | 208 | ||
209 | /* Validate the input - check to see if address is on the wrong boundary or beyond the end of the user area */ | 209 | /* Validate the input - check to see if address is on the wrong boundary |
210 | * or beyond the end of the user area | ||
211 | */ | ||
210 | if ((addr & 3) || numReg > PT_FPSCR) | 212 | if ((addr & 3) || numReg > PT_FPSCR) |
211 | break; | 213 | break; |
212 | 214 | ||
@@ -270,8 +272,6 @@ long compat_sys_ptrace(int request, int pid, unsigned long addr, | |||
270 | if ((addr & 3) || (index > PT_FPSCR32)) | 272 | if ((addr & 3) || (index > PT_FPSCR32)) |
271 | break; | 273 | break; |
272 | 274 | ||
273 | if (index == PT_ORIG_R3) | ||
274 | break; | ||
275 | if (index < PT_FPR0) { | 275 | if (index < PT_FPR0) { |
276 | ret = ptrace_put_reg(child, index, data); | 276 | ret = ptrace_put_reg(child, index, data); |
277 | } else { | 277 | } else { |
@@ -302,24 +302,25 @@ long compat_sys_ptrace(int request, int pid, unsigned long addr, | |||
302 | /* Determine which register the user wants */ | 302 | /* Determine which register the user wants */ |
303 | index = (u64)addr >> 2; | 303 | index = (u64)addr >> 2; |
304 | numReg = index / 2; | 304 | numReg = index / 2; |
305 | |||
305 | /* | 306 | /* |
306 | * Validate the input - check to see if address is on the | 307 | * Validate the input - check to see if address is on the |
307 | * wrong boundary or beyond the end of the user area | 308 | * wrong boundary or beyond the end of the user area |
308 | */ | 309 | */ |
309 | if ((addr & 3) || (numReg > PT_FPSCR)) | 310 | if ((addr & 3) || (numReg > PT_FPSCR)) |
310 | break; | 311 | break; |
311 | /* Insure it is a register we let them change */ | 312 | if (numReg < PT_FPR0) { |
312 | if ((numReg == PT_ORIG_R3) | 313 | unsigned long freg = ptrace_get_reg(child, numReg); |
313 | || ((numReg > PT_CCR) && (numReg < PT_FPR0))) | 314 | if (index % 2) |
314 | break; | 315 | freg = (freg & ~0xfffffffful) | (data & 0xfffffffful); |
315 | if (numReg >= PT_FPR0) { | 316 | else |
317 | freg = (freg & 0xfffffffful) | (data << 32); | ||
318 | ret = ptrace_put_reg(child, numReg, freg); | ||
319 | } else { | ||
316 | flush_fp_to_thread(child); | 320 | flush_fp_to_thread(child); |
321 | ((unsigned int *)child->thread.regs)[index] = data; | ||
322 | ret = 0; | ||
317 | } | 323 | } |
318 | if (numReg == PT_MSR) | ||
319 | data = (data & MSR_DEBUGCHANGE) | ||
320 | | (child->thread.regs->msr & ~MSR_DEBUGCHANGE); | ||
321 | ((u32*)child->thread.regs)[index] = data; | ||
322 | ret = 0; | ||
323 | break; | 324 | break; |
324 | } | 325 | } |
325 | 326 | ||