aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/ptrace32.c
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2007-06-04 01:15:46 -0400
committerPaul Mackerras <paulus@samba.org>2007-06-14 08:29:57 -0400
commit912000e73ee8fcb97831b123c9c3a7274b71cab7 (patch)
treea81fcda0f11cbb4c428ffae9f9f55f12677051fe /arch/powerpc/kernel/ptrace32.c
parent1b6610d6fcb8dc23631cf48f09aa02e6649e379d (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.c27
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