diff options
| -rw-r--r-- | arch/m32r/include/asm/ptrace.h | 2 | ||||
| -rw-r--r-- | arch/m32r/kernel/ptrace.c | 97 |
2 files changed, 31 insertions, 68 deletions
diff --git a/arch/m32r/include/asm/ptrace.h b/arch/m32r/include/asm/ptrace.h index a0755b982028..840a1231edeb 100644 --- a/arch/m32r/include/asm/ptrace.h +++ b/arch/m32r/include/asm/ptrace.h | |||
| @@ -120,6 +120,8 @@ struct pt_regs { | |||
| 120 | 120 | ||
| 121 | #include <asm/m32r.h> /* M32R_PSW_BSM, M32R_PSW_BPM */ | 121 | #include <asm/m32r.h> /* M32R_PSW_BSM, M32R_PSW_BPM */ |
| 122 | 122 | ||
| 123 | #define arch_has_single_step() (1) | ||
| 124 | |||
| 123 | struct task_struct; | 125 | struct task_struct; |
| 124 | extern void init_debug_traps(struct task_struct *); | 126 | extern void init_debug_traps(struct task_struct *); |
| 125 | #define arch_ptrace_attach(child) \ | 127 | #define arch_ptrace_attach(child) \ |
diff --git a/arch/m32r/kernel/ptrace.c b/arch/m32r/kernel/ptrace.c index 98682bba0ed9..e555091eb97c 100644 --- a/arch/m32r/kernel/ptrace.c +++ b/arch/m32r/kernel/ptrace.c | |||
| @@ -580,6 +580,35 @@ init_debug_traps(struct task_struct *child) | |||
| 580 | } | 580 | } |
| 581 | } | 581 | } |
| 582 | 582 | ||
| 583 | void user_enable_single_step(struct task_struct *child) | ||
| 584 | { | ||
| 585 | unsigned long next_pc; | ||
| 586 | unsigned long pc, insn; | ||
| 587 | |||
| 588 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||
| 589 | |||
| 590 | /* Compute next pc. */ | ||
| 591 | pc = get_stack_long(child, PT_BPC); | ||
| 592 | |||
| 593 | if (access_process_vm(child, pc&~3, &insn, sizeof(insn), 0) | ||
| 594 | != sizeof(insn)) | ||
| 595 | break; | ||
| 596 | |||
| 597 | compute_next_pc(insn, pc, &next_pc, child); | ||
| 598 | if (next_pc & 0x80000000) | ||
| 599 | break; | ||
| 600 | |||
| 601 | if (embed_debug_trap(child, next_pc)) | ||
| 602 | break; | ||
| 603 | |||
| 604 | invalidate_cache(); | ||
| 605 | } | ||
| 606 | |||
| 607 | void user_disable_single_step(struct task_struct *child) | ||
| 608 | { | ||
| 609 | unregister_all_debug_traps(child); | ||
| 610 | invalidate_cache(); | ||
| 611 | } | ||
| 583 | 612 | ||
| 584 | /* | 613 | /* |
| 585 | * Called by kernel/ptrace.c when detaching.. | 614 | * Called by kernel/ptrace.c when detaching.. |
| @@ -630,74 +659,6 @@ arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
| 630 | ret = ptrace_write_user(child, addr, data); | 659 | ret = ptrace_write_user(child, addr, data); |
| 631 | break; | 660 | break; |
| 632 | 661 | ||
| 633 | /* | ||
| 634 | * continue/restart and stop at next (return from) syscall | ||
| 635 | */ | ||
| 636 | case PTRACE_SYSCALL: | ||
| 637 | case PTRACE_CONT: | ||
| 638 | ret = -EIO; | ||
| 639 | if (!valid_signal(data)) | ||
| 640 | break; | ||
| 641 | if (request == PTRACE_SYSCALL) | ||
| 642 | set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||
| 643 | else | ||
| 644 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||
| 645 | child->exit_code = data; | ||
| 646 | wake_up_process(child); | ||
| 647 | ret = 0; | ||
| 648 | break; | ||
| 649 | |||
| 650 | /* | ||
| 651 | * make the child exit. Best I can do is send it a sigkill. | ||
| 652 | * perhaps it should be put in the status that it wants to | ||
| 653 | * exit. | ||
| 654 | */ | ||
| 655 | case PTRACE_KILL: { | ||
| 656 | ret = 0; | ||
| 657 | unregister_all_debug_traps(child); | ||
| 658 | invalidate_cache(); | ||
| 659 | if (child->exit_state == EXIT_ZOMBIE) /* already dead */ | ||
| 660 | break; | ||
| 661 | child->exit_code = SIGKILL; | ||
| 662 | wake_up_process(child); | ||
| 663 | break; | ||
| 664 | } | ||
| 665 | |||
| 666 | /* | ||
| 667 | * execute single instruction. | ||
| 668 | */ | ||
| 669 | case PTRACE_SINGLESTEP: { | ||
| 670 | unsigned long next_pc; | ||
| 671 | unsigned long pc, insn; | ||
| 672 | |||
| 673 | ret = -EIO; | ||
| 674 | if (!valid_signal(data)) | ||
| 675 | break; | ||
| 676 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||
| 677 | |||
| 678 | /* Compute next pc. */ | ||
| 679 | pc = get_stack_long(child, PT_BPC); | ||
| 680 | |||
| 681 | if (access_process_vm(child, pc&~3, &insn, sizeof(insn), 0) | ||
| 682 | != sizeof(insn)) | ||
| 683 | break; | ||
| 684 | |||
| 685 | compute_next_pc(insn, pc, &next_pc, child); | ||
| 686 | if (next_pc & 0x80000000) | ||
| 687 | break; | ||
| 688 | |||
| 689 | if (embed_debug_trap(child, next_pc)) | ||
| 690 | break; | ||
| 691 | |||
| 692 | invalidate_cache(); | ||
| 693 | child->exit_code = data; | ||
| 694 | |||
| 695 | /* give it a chance to run. */ | ||
| 696 | wake_up_process(child); | ||
| 697 | ret = 0; | ||
| 698 | break; | ||
| 699 | } | ||
| 700 | |||
| 701 | case PTRACE_GETREGS: | 662 | case PTRACE_GETREGS: |
| 702 | ret = ptrace_getregs(child, (void __user *)data); | 663 | ret = ptrace_getregs(child, (void __user *)data); |
| 703 | break; | 664 | break; |
