diff options
author | Ananth N Mavinakayanahalli <ananth@in.ibm.com> | 2006-04-28 08:08:42 -0400 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2006-05-03 09:06:41 -0400 |
commit | 0ccde0a290b44b8296b82a7683b4c299eb51ba6b (patch) | |
tree | cc586aa319da07dcda8f91e3ee03d9da960d5fac /arch/powerpc/kernel/kprobes.c | |
parent | 054d8ff37710efaebd1998ce94d366df315a354f (diff) |
[PATCH] powerpc/kprobes: fix singlestep out-of-line
We currently single-step inline if the instruction on which a kprobe is
inserted is a trap variant.
- variants (such as tdnei, used by BUG()) typically evaluate a condition
and cause a trap only if the condition is satisfied.
- kprobes uses the unconditional "trap" (0x7fe00008) and single-stepping
again on this instruction, resulting in another trap without
evaluating the condition is obviously incorrect.
Signed-off-by: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/kernel/kprobes.c')
-rw-r--r-- | arch/powerpc/kernel/kprobes.c | 14 |
1 files changed, 7 insertions, 7 deletions
diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c index 856ef1a832b9..f78866367b70 100644 --- a/arch/powerpc/kernel/kprobes.c +++ b/arch/powerpc/kernel/kprobes.c | |||
@@ -90,15 +90,15 @@ void __kprobes arch_remove_kprobe(struct kprobe *p) | |||
90 | 90 | ||
91 | static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs) | 91 | static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs) |
92 | { | 92 | { |
93 | kprobe_opcode_t insn = *p->ainsn.insn; | ||
94 | |||
95 | regs->msr |= MSR_SE; | 93 | regs->msr |= MSR_SE; |
96 | 94 | ||
97 | /* single step inline if it is a trap variant */ | 95 | /* |
98 | if (is_trap(insn)) | 96 | * On powerpc we should single step on the original |
99 | regs->nip = (unsigned long)p->addr; | 97 | * instruction even if the probed insn is a trap |
100 | else | 98 | * variant as values in regs could play a part in |
101 | regs->nip = (unsigned long)p->ainsn.insn; | 99 | * if the trap is taken or not |
100 | */ | ||
101 | regs->nip = (unsigned long)p->ainsn.insn; | ||
102 | } | 102 | } |
103 | 103 | ||
104 | static void __kprobes save_previous_kprobe(struct kprobe_ctlblk *kcb) | 104 | static void __kprobes save_previous_kprobe(struct kprobe_ctlblk *kcb) |