aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/ptrace32.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/kernel/ptrace32.c')
-rw-r--r--arch/powerpc/kernel/ptrace32.c204
1 files changed, 87 insertions, 117 deletions
diff --git a/arch/powerpc/kernel/ptrace32.c b/arch/powerpc/kernel/ptrace32.c
index 1bf1f450e1ab..98b1580a2bc2 100644
--- a/arch/powerpc/kernel/ptrace32.c
+++ b/arch/powerpc/kernel/ptrace32.c
@@ -41,6 +41,50 @@
41 * in exit.c or in signal.c. 41 * in exit.c or in signal.c.
42 */ 42 */
43 43
44/*
45 * Here are the old "legacy" powerpc specific getregs/setregs ptrace calls,
46 * we mark them as obsolete now, they will be removed in a future version
47 */
48static long compat_ptrace_old(struct task_struct *child, long request,
49 long addr, long data)
50{
51 int ret = -EPERM;
52
53 switch(request) {
54 case PPC_PTRACE_GETREGS: { /* Get GPRs 0 - 31. */
55 int i;
56 unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
57 unsigned int __user *tmp = (unsigned int __user *)addr;
58
59 for (i = 0; i < 32; i++) {
60 ret = put_user(*reg, tmp);
61 if (ret)
62 break;
63 reg++;
64 tmp++;
65 }
66 break;
67 }
68
69 case PPC_PTRACE_SETREGS: { /* Set GPRs 0 - 31. */
70 int i;
71 unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
72 unsigned int __user *tmp = (unsigned int __user *)addr;
73
74 for (i = 0; i < 32; i++) {
75 ret = get_user(*reg, tmp);
76 if (ret)
77 break;
78 reg++;
79 tmp++;
80 }
81 break;
82 }
83
84 }
85 return ret;
86}
87
44long compat_sys_ptrace(int request, int pid, unsigned long addr, 88long compat_sys_ptrace(int request, int pid, unsigned long addr,
45 unsigned long data) 89 unsigned long data)
46{ 90{
@@ -280,52 +324,6 @@ long compat_sys_ptrace(int request, int pid, unsigned long addr,
280 break; 324 break;
281 } 325 }
282 326
283 case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
284 case PTRACE_CONT: { /* restart after signal. */
285 ret = -EIO;
286 if (!valid_signal(data))
287 break;
288 if (request == PTRACE_SYSCALL)
289 set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
290 else
291 clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
292 child->exit_code = data;
293 /* make sure the single step bit is not set. */
294 clear_single_step(child);
295 wake_up_process(child);
296 ret = 0;
297 break;
298 }
299
300 /*
301 * make the child exit. Best I can do is send it a sigkill.
302 * perhaps it should be put in the status that it wants to
303 * exit.
304 */
305 case PTRACE_KILL: {
306 ret = 0;
307 if (child->exit_state == EXIT_ZOMBIE) /* already dead */
308 break;
309 child->exit_code = SIGKILL;
310 /* make sure the single step bit is not set. */
311 clear_single_step(child);
312 wake_up_process(child);
313 break;
314 }
315
316 case PTRACE_SINGLESTEP: { /* set the trap flag. */
317 ret = -EIO;
318 if (!valid_signal(data))
319 break;
320 clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
321 set_single_step(child);
322 child->exit_code = data;
323 /* give it a chance to run. */
324 wake_up_process(child);
325 ret = 0;
326 break;
327 }
328
329 case PTRACE_GET_DEBUGREG: { 327 case PTRACE_GET_DEBUGREG: {
330 ret = -EINVAL; 328 ret = -EINVAL;
331 /* We only support one DABR and no IABRS at the moment */ 329 /* We only support one DABR and no IABRS at the moment */
@@ -335,95 +333,67 @@ long compat_sys_ptrace(int request, int pid, unsigned long addr,
335 break; 333 break;
336 } 334 }
337 335
338 case PTRACE_SET_DEBUGREG: 336 case PTRACE_GETEVENTMSG:
339 ret = ptrace_set_debugreg(child, addr, data); 337 ret = put_user(child->ptrace_message, (unsigned int __user *) data);
340 break;
341
342 case PTRACE_DETACH:
343 ret = ptrace_detach(child, data);
344 break; 338 break;
345 339
346 case PPC_PTRACE_GETREGS: { /* Get GPRs 0 - 31. */ 340 case PTRACE_GETREGS: { /* Get all pt_regs from the child. */
347 int i; 341 int ui;
348 unsigned long *reg = &((unsigned long *)child->thread.regs)[0]; 342 if (!access_ok(VERIFY_WRITE, (void __user *)data,
349 unsigned int __user *tmp = (unsigned int __user *)addr; 343 PT_REGS_COUNT * sizeof(int))) {
350 344 ret = -EIO;
351 for (i = 0; i < 32; i++) { 345 break;
352 ret = put_user(*reg, tmp);
353 if (ret)
354 break;
355 reg++;
356 tmp++;
357 } 346 }
358 break; 347 ret = 0;
359 } 348 for (ui = 0; ui < PT_REGS_COUNT; ui ++) {
360 349 ret |= __put_user(get_reg(child, ui),
361 case PPC_PTRACE_SETREGS: { /* Set GPRs 0 - 31. */ 350 (unsigned int __user *) data);
362 int i; 351 data += sizeof(int);
363 unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
364 unsigned int __user *tmp = (unsigned int __user *)addr;
365
366 for (i = 0; i < 32; i++) {
367 ret = get_user(*reg, tmp);
368 if (ret)
369 break;
370 reg++;
371 tmp++;
372 } 352 }
373 break; 353 break;
374 } 354 }
375 355
376 case PPC_PTRACE_GETFPREGS: { /* Get FPRs 0 - 31. */ 356 case PTRACE_SETREGS: { /* Set all gp regs in the child. */
377 int i; 357 unsigned long tmp;
378 unsigned long *reg = &((unsigned long *)child->thread.fpr)[0]; 358 int ui;
379 unsigned int __user *tmp = (unsigned int __user *)addr; 359 if (!access_ok(VERIFY_READ, (void __user *)data,
380 360 PT_REGS_COUNT * sizeof(int))) {
381 flush_fp_to_thread(child); 361 ret = -EIO;
382 362 break;
383 for (i = 0; i < 32; i++) {
384 ret = put_user(*reg, tmp);
385 if (ret)
386 break;
387 reg++;
388 tmp++;
389 } 363 }
390 break; 364 ret = 0;
391 } 365 for (ui = 0; ui < PT_REGS_COUNT; ui ++) {
392 366 ret = __get_user(tmp, (unsigned int __user *) data);
393 case PPC_PTRACE_SETFPREGS: { /* Get FPRs 0 - 31. */
394 int i;
395 unsigned long *reg = &((unsigned long *)child->thread.fpr)[0];
396 unsigned int __user *tmp = (unsigned int __user *)addr;
397
398 flush_fp_to_thread(child);
399
400 for (i = 0; i < 32; i++) {
401 ret = get_user(*reg, tmp);
402 if (ret) 367 if (ret)
403 break; 368 break;
404 reg++; 369 put_reg(child, ui, tmp);
405 tmp++; 370 data += sizeof(int);
406 } 371 }
407 break; 372 break;
408 } 373 }
409 374
410 case PTRACE_GETEVENTMSG: 375 case PTRACE_GETFPREGS:
411 ret = put_user(child->ptrace_message, (unsigned int __user *) data); 376 case PTRACE_SETFPREGS:
412 break;
413
414#ifdef CONFIG_ALTIVEC
415 case PTRACE_GETVRREGS: 377 case PTRACE_GETVRREGS:
416 /* Get the child altivec register state. */ 378 case PTRACE_SETVRREGS:
417 flush_altivec_to_thread(child); 379 case PTRACE_GETREGS64:
418 ret = get_vrregs((unsigned long __user *)data, child); 380 case PTRACE_SETREGS64:
381 case PPC_PTRACE_GETFPREGS:
382 case PPC_PTRACE_SETFPREGS:
383 case PTRACE_KILL:
384 case PTRACE_SINGLESTEP:
385 case PTRACE_DETACH:
386 case PTRACE_SET_DEBUGREG:
387 case PTRACE_SYSCALL:
388 case PTRACE_CONT:
389 ret = arch_ptrace(child, request, addr, data);
419 break; 390 break;
420 391
421 case PTRACE_SETVRREGS: 392 /* Old reverse args ptrace callss */
422 /* Set the child altivec register state. */ 393 case PPC_PTRACE_GETREGS: /* Get GPRs 0 - 31. */
423 flush_altivec_to_thread(child); 394 case PPC_PTRACE_SETREGS: /* Set GPRs 0 - 31. */
424 ret = set_vrregs(child, (unsigned long __user *)data); 395 ret = compat_ptrace_old(child, request, addr, data);
425 break; 396 break;
426#endif
427 397
428 default: 398 default:
429 ret = ptrace_request(child, request, addr, data); 399 ret = ptrace_request(child, request, addr, data);