diff options
author | Russell King <rmk@dyn-67.arm.linux.org.uk> | 2007-03-04 04:50:28 -0500 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2007-04-21 15:34:58 -0400 |
commit | b2a0d36fde90fa9dd20b7dde21dbcff09b130b38 (patch) | |
tree | 354fe85244f011e17e1c96243f5f7925ba16b6b6 | |
parent | 0f0a00beb80624a446ba7c0152cd171008eeab2e (diff) |
[ARM] ptrace: clean up single stepping support
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
-rw-r--r-- | arch/arm/kernel/ptrace.c | 15 | ||||
-rw-r--r-- | arch/arm/kernel/ptrace.h | 39 | ||||
-rw-r--r-- | arch/arm/kernel/signal.c | 22 |
3 files changed, 48 insertions, 28 deletions
diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c index 9254ba2f46fc..e594b84cca83 100644 --- a/arch/arm/kernel/ptrace.c +++ b/arch/arm/kernel/ptrace.c | |||
@@ -457,13 +457,10 @@ void ptrace_cancel_bpt(struct task_struct *child) | |||
457 | 457 | ||
458 | /* | 458 | /* |
459 | * Called by kernel/ptrace.c when detaching.. | 459 | * Called by kernel/ptrace.c when detaching.. |
460 | * | ||
461 | * Make sure the single step bit is not set. | ||
462 | */ | 460 | */ |
463 | void ptrace_disable(struct task_struct *child) | 461 | void ptrace_disable(struct task_struct *child) |
464 | { | 462 | { |
465 | child->ptrace &= ~PT_SINGLESTEP; | 463 | single_step_disable(child); |
466 | ptrace_cancel_bpt(child); | ||
467 | } | 464 | } |
468 | 465 | ||
469 | /* | 466 | /* |
@@ -712,9 +709,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
712 | else | 709 | else |
713 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | 710 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); |
714 | child->exit_code = data; | 711 | child->exit_code = data; |
715 | /* make sure single-step breakpoint is gone. */ | 712 | single_step_disable(child); |
716 | child->ptrace &= ~PT_SINGLESTEP; | ||
717 | ptrace_cancel_bpt(child); | ||
718 | wake_up_process(child); | 713 | wake_up_process(child); |
719 | ret = 0; | 714 | ret = 0; |
720 | break; | 715 | break; |
@@ -725,9 +720,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
725 | * exit. | 720 | * exit. |
726 | */ | 721 | */ |
727 | case PTRACE_KILL: | 722 | case PTRACE_KILL: |
728 | /* make sure single-step breakpoint is gone. */ | 723 | single_step_disable(child); |
729 | child->ptrace &= ~PT_SINGLESTEP; | ||
730 | ptrace_cancel_bpt(child); | ||
731 | if (child->exit_state != EXIT_ZOMBIE) { | 724 | if (child->exit_state != EXIT_ZOMBIE) { |
732 | child->exit_code = SIGKILL; | 725 | child->exit_code = SIGKILL; |
733 | wake_up_process(child); | 726 | wake_up_process(child); |
@@ -742,7 +735,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
742 | ret = -EIO; | 735 | ret = -EIO; |
743 | if (!valid_signal(data)) | 736 | if (!valid_signal(data)) |
744 | break; | 737 | break; |
745 | child->ptrace |= PT_SINGLESTEP; | 738 | single_step_enable(child); |
746 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | 739 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); |
747 | child->exit_code = data; | 740 | child->exit_code = data; |
748 | /* give it a chance to run. */ | 741 | /* give it a chance to run. */ |
diff --git a/arch/arm/kernel/ptrace.h b/arch/arm/kernel/ptrace.h index f7cad13a22e9..def3b6184a79 100644 --- a/arch/arm/kernel/ptrace.h +++ b/arch/arm/kernel/ptrace.h | |||
@@ -7,6 +7,45 @@ | |||
7 | * it under the terms of the GNU General Public License version 2 as | 7 | * it under the terms of the GNU General Public License version 2 as |
8 | * published by the Free Software Foundation. | 8 | * published by the Free Software Foundation. |
9 | */ | 9 | */ |
10 | #include <linux/ptrace.h> | ||
11 | |||
10 | extern void ptrace_cancel_bpt(struct task_struct *); | 12 | extern void ptrace_cancel_bpt(struct task_struct *); |
11 | extern void ptrace_set_bpt(struct task_struct *); | 13 | extern void ptrace_set_bpt(struct task_struct *); |
12 | extern void ptrace_break(struct task_struct *, struct pt_regs *); | 14 | extern void ptrace_break(struct task_struct *, struct pt_regs *); |
15 | |||
16 | /* | ||
17 | * make sure single-step breakpoint is gone. | ||
18 | */ | ||
19 | static inline void single_step_disable(struct task_struct *task) | ||
20 | { | ||
21 | task->ptrace &= ~PT_SINGLESTEP; | ||
22 | ptrace_cancel_bpt(task); | ||
23 | } | ||
24 | |||
25 | static inline void single_step_enable(struct task_struct *task) | ||
26 | { | ||
27 | task->ptrace |= PT_SINGLESTEP; | ||
28 | } | ||
29 | |||
30 | /* | ||
31 | * Send SIGTRAP if we're single-stepping | ||
32 | */ | ||
33 | static inline void single_step_trap(struct task_struct *task) | ||
34 | { | ||
35 | if (task->ptrace & PT_SINGLESTEP) { | ||
36 | ptrace_cancel_bpt(task); | ||
37 | send_sig(SIGTRAP, task, 1); | ||
38 | } | ||
39 | } | ||
40 | |||
41 | static inline void single_step_clear(struct task_struct *task) | ||
42 | { | ||
43 | if (task->ptrace & PT_SINGLESTEP) | ||
44 | ptrace_cancel_bpt(task); | ||
45 | } | ||
46 | |||
47 | static inline void single_step_set(struct task_struct *task) | ||
48 | { | ||
49 | if (task->ptrace & PT_SINGLESTEP) | ||
50 | ptrace_set_bpt(task); | ||
51 | } | ||
diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c index 3843d3bab2dd..54cdf1aeefc3 100644 --- a/arch/arm/kernel/signal.c +++ b/arch/arm/kernel/signal.c | |||
@@ -9,7 +9,6 @@ | |||
9 | */ | 9 | */ |
10 | #include <linux/errno.h> | 10 | #include <linux/errno.h> |
11 | #include <linux/signal.h> | 11 | #include <linux/signal.h> |
12 | #include <linux/ptrace.h> | ||
13 | #include <linux/personality.h> | 12 | #include <linux/personality.h> |
14 | #include <linux/freezer.h> | 13 | #include <linux/freezer.h> |
15 | 14 | ||
@@ -285,11 +284,7 @@ asmlinkage int sys_sigreturn(struct pt_regs *regs) | |||
285 | if (restore_sigframe(regs, frame)) | 284 | if (restore_sigframe(regs, frame)) |
286 | goto badframe; | 285 | goto badframe; |
287 | 286 | ||
288 | /* Send SIGTRAP if we're single-stepping */ | 287 | single_step_trap(current); |
289 | if (current->ptrace & PT_SINGLESTEP) { | ||
290 | ptrace_cancel_bpt(current); | ||
291 | send_sig(SIGTRAP, current, 1); | ||
292 | } | ||
293 | 288 | ||
294 | return regs->ARM_r0; | 289 | return regs->ARM_r0; |
295 | 290 | ||
@@ -324,11 +319,7 @@ asmlinkage int sys_rt_sigreturn(struct pt_regs *regs) | |||
324 | if (do_sigaltstack(&frame->sig.uc.uc_stack, NULL, regs->ARM_sp) == -EFAULT) | 319 | if (do_sigaltstack(&frame->sig.uc.uc_stack, NULL, regs->ARM_sp) == -EFAULT) |
325 | goto badframe; | 320 | goto badframe; |
326 | 321 | ||
327 | /* Send SIGTRAP if we're single-stepping */ | 322 | single_step_trap(current); |
328 | if (current->ptrace & PT_SINGLESTEP) { | ||
329 | ptrace_cancel_bpt(current); | ||
330 | send_sig(SIGTRAP, current, 1); | ||
331 | } | ||
332 | 323 | ||
333 | return regs->ARM_r0; | 324 | return regs->ARM_r0; |
334 | 325 | ||
@@ -644,14 +635,12 @@ static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall) | |||
644 | if (try_to_freeze()) | 635 | if (try_to_freeze()) |
645 | goto no_signal; | 636 | goto no_signal; |
646 | 637 | ||
647 | if (current->ptrace & PT_SINGLESTEP) | 638 | single_step_clear(current); |
648 | ptrace_cancel_bpt(current); | ||
649 | 639 | ||
650 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); | 640 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); |
651 | if (signr > 0) { | 641 | if (signr > 0) { |
652 | handle_signal(signr, &ka, &info, oldset, regs, syscall); | 642 | handle_signal(signr, &ka, &info, oldset, regs, syscall); |
653 | if (current->ptrace & PT_SINGLESTEP) | 643 | single_step_set(current); |
654 | ptrace_set_bpt(current); | ||
655 | return 1; | 644 | return 1; |
656 | } | 645 | } |
657 | 646 | ||
@@ -705,8 +694,7 @@ static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall) | |||
705 | restart_syscall(regs); | 694 | restart_syscall(regs); |
706 | } | 695 | } |
707 | } | 696 | } |
708 | if (current->ptrace & PT_SINGLESTEP) | 697 | single_step_set(current); |
709 | ptrace_set_bpt(current); | ||
710 | return 0; | 698 | return 0; |
711 | } | 699 | } |
712 | 700 | ||