From feeed5fcece4ab4c4fc137ce78db8c8256111b39 Mon Sep 17 00:00:00 2001 From: Jon Medhurst Date: Thu, 9 Jun 2011 12:11:27 +0100 Subject: [PATCH] --- yaml --- r: 258336 b: refs/heads/master c: c6a7d97d57ef41477a85f4c0f48ea5243132ee1f h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/arch/arm/include/asm/kprobes.h | 9 +++++---- trunk/arch/arm/kernel/kprobes-arm.c | 7 +++++++ trunk/arch/arm/kernel/kprobes-thumb.c | 16 ++++++++++++++++ trunk/arch/arm/kernel/kprobes.c | 8 +++----- 5 files changed, 32 insertions(+), 10 deletions(-) diff --git a/[refs] b/[refs] index dff29ed3a01f..f8df4b4fd417 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 3b26945597d5eff5d428a268c9d109338fce801e +refs/heads/master: c6a7d97d57ef41477a85f4c0f48ea5243132ee1f diff --git a/trunk/arch/arm/include/asm/kprobes.h b/trunk/arch/arm/include/asm/kprobes.h index 57d37d52d71e..1e9ff56d40c7 100644 --- a/trunk/arch/arm/include/asm/kprobes.h +++ b/trunk/arch/arm/include/asm/kprobes.h @@ -32,14 +32,15 @@ typedef u32 kprobe_opcode_t; struct kprobe; typedef void (kprobe_insn_handler_t)(struct kprobe *, struct pt_regs *); - typedef unsigned long (kprobe_check_cc)(unsigned long); +typedef void (kprobe_insn_singlestep_t)(struct kprobe *, struct pt_regs *); /* Architecture specific copy of original instruction. */ struct arch_specific_insn { - kprobe_opcode_t *insn; - kprobe_insn_handler_t *insn_handler; - kprobe_check_cc *insn_check_cc; + kprobe_opcode_t *insn; + kprobe_insn_handler_t *insn_handler; + kprobe_check_cc *insn_check_cc; + kprobe_insn_singlestep_t *insn_singlestep; }; struct prev_kprobe { diff --git a/trunk/arch/arm/kernel/kprobes-arm.c b/trunk/arch/arm/kernel/kprobes-arm.c index 0262b29163d1..a1143e86a09a 100644 --- a/trunk/arch/arm/kernel/kprobes-arm.c +++ b/trunk/arch/arm/kernel/kprobes-arm.c @@ -1494,6 +1494,12 @@ space_cccc_11xx(kprobe_opcode_t insn, struct arch_specific_insn *asi) return INSN_REJECTED; } +static void __kprobes arm_singlestep(struct kprobe *p, struct pt_regs *regs) +{ + regs->ARM_pc += 4; + p->ainsn.insn_handler(p, regs); +} + /* Return: * INSN_REJECTED If instruction is one not allowed to kprobe, * INSN_GOOD If instruction is supported and uses instruction slot, @@ -1509,6 +1515,7 @@ space_cccc_11xx(kprobe_opcode_t insn, struct arch_specific_insn *asi) enum kprobe_insn __kprobes arm_kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi) { + asi->insn_singlestep = arm_singlestep; asi->insn_check_cc = kprobe_condition_checks[insn>>28]; asi->insn[1] = KPROBE_RETURN_INSTRUCTION; diff --git a/trunk/arch/arm/kernel/kprobes-thumb.c b/trunk/arch/arm/kernel/kprobes-thumb.c index 24a188b1601a..973c3eb1243a 100644 --- a/trunk/arch/arm/kernel/kprobes-thumb.c +++ b/trunk/arch/arm/kernel/kprobes-thumb.c @@ -33,9 +33,24 @@ static unsigned long __kprobes thumb_check_cc(unsigned long cpsr) return true; } +static void __kprobes thumb16_singlestep(struct kprobe *p, struct pt_regs *regs) +{ + regs->ARM_pc += 2; + p->ainsn.insn_handler(p, regs); + regs->ARM_cpsr = it_advance(regs->ARM_cpsr); +} + +static void __kprobes thumb32_singlestep(struct kprobe *p, struct pt_regs *regs) +{ + regs->ARM_pc += 4; + p->ainsn.insn_handler(p, regs); + regs->ARM_cpsr = it_advance(regs->ARM_cpsr); +} + enum kprobe_insn __kprobes thumb16_kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi) { + asi->insn_singlestep = thumb16_singlestep; asi->insn_check_cc = thumb_check_cc; return INSN_REJECTED; } @@ -43,6 +58,7 @@ thumb16_kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi) enum kprobe_insn __kprobes thumb32_kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi) { + asi->insn_singlestep = thumb32_singlestep; asi->insn_check_cc = thumb_check_cc; return INSN_REJECTED; } diff --git a/trunk/arch/arm/kernel/kprobes.c b/trunk/arch/arm/kernel/kprobes.c index 0003dfd3b854..77b7c6974802 100644 --- a/trunk/arch/arm/kernel/kprobes.c +++ b/trunk/arch/arm/kernel/kprobes.c @@ -227,12 +227,10 @@ singlestep_skip(struct kprobe *p, struct pt_regs *regs) #endif } -static void __kprobes singlestep(struct kprobe *p, struct pt_regs *regs, - struct kprobe_ctlblk *kcb) +static inline void __kprobes +singlestep(struct kprobe *p, struct pt_regs *regs, struct kprobe_ctlblk *kcb) { - regs->ARM_pc += 4; - if (p->ainsn.insn_check_cc(regs->ARM_cpsr)) - p->ainsn.insn_handler(p, regs); + p->ainsn.insn_singlestep(p, regs); } /*