aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/include/asm/kprobes.h9
-rw-r--r--arch/arm/kernel/kprobes-arm.c7
-rw-r--r--arch/arm/kernel/kprobes-thumb.c16
-rw-r--r--arch/arm/kernel/kprobes.c8
4 files changed, 31 insertions, 9 deletions
diff --git a/arch/arm/include/asm/kprobes.h b/arch/arm/include/asm/kprobes.h
index 57d37d52d71e..1e9ff56d40c7 100644
--- a/arch/arm/include/asm/kprobes.h
+++ b/arch/arm/include/asm/kprobes.h
@@ -32,14 +32,15 @@ typedef u32 kprobe_opcode_t;
32 32
33struct kprobe; 33struct kprobe;
34typedef void (kprobe_insn_handler_t)(struct kprobe *, struct pt_regs *); 34typedef void (kprobe_insn_handler_t)(struct kprobe *, struct pt_regs *);
35
36typedef unsigned long (kprobe_check_cc)(unsigned long); 35typedef unsigned long (kprobe_check_cc)(unsigned long);
36typedef void (kprobe_insn_singlestep_t)(struct kprobe *, struct pt_regs *);
37 37
38/* Architecture specific copy of original instruction. */ 38/* Architecture specific copy of original instruction. */
39struct arch_specific_insn { 39struct arch_specific_insn {
40 kprobe_opcode_t *insn; 40 kprobe_opcode_t *insn;
41 kprobe_insn_handler_t *insn_handler; 41 kprobe_insn_handler_t *insn_handler;
42 kprobe_check_cc *insn_check_cc; 42 kprobe_check_cc *insn_check_cc;
43 kprobe_insn_singlestep_t *insn_singlestep;
43}; 44};
44 45
45struct prev_kprobe { 46struct prev_kprobe {
diff --git a/arch/arm/kernel/kprobes-arm.c b/arch/arm/kernel/kprobes-arm.c
index 0262b29163d1..a1143e86a09a 100644
--- a/arch/arm/kernel/kprobes-arm.c
+++ b/arch/arm/kernel/kprobes-arm.c
@@ -1494,6 +1494,12 @@ space_cccc_11xx(kprobe_opcode_t insn, struct arch_specific_insn *asi)
1494 return INSN_REJECTED; 1494 return INSN_REJECTED;
1495} 1495}
1496 1496
1497static void __kprobes arm_singlestep(struct kprobe *p, struct pt_regs *regs)
1498{
1499 regs->ARM_pc += 4;
1500 p->ainsn.insn_handler(p, regs);
1501}
1502
1497/* Return: 1503/* Return:
1498 * INSN_REJECTED If instruction is one not allowed to kprobe, 1504 * INSN_REJECTED If instruction is one not allowed to kprobe,
1499 * INSN_GOOD If instruction is supported and uses instruction slot, 1505 * 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)
1509enum kprobe_insn __kprobes 1515enum kprobe_insn __kprobes
1510arm_kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi) 1516arm_kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi)
1511{ 1517{
1518 asi->insn_singlestep = arm_singlestep;
1512 asi->insn_check_cc = kprobe_condition_checks[insn>>28]; 1519 asi->insn_check_cc = kprobe_condition_checks[insn>>28];
1513 asi->insn[1] = KPROBE_RETURN_INSTRUCTION; 1520 asi->insn[1] = KPROBE_RETURN_INSTRUCTION;
1514 1521
diff --git a/arch/arm/kernel/kprobes-thumb.c b/arch/arm/kernel/kprobes-thumb.c
index 24a188b1601a..973c3eb1243a 100644
--- a/arch/arm/kernel/kprobes-thumb.c
+++ b/arch/arm/kernel/kprobes-thumb.c
@@ -33,9 +33,24 @@ static unsigned long __kprobes thumb_check_cc(unsigned long cpsr)
33 return true; 33 return true;
34} 34}
35 35
36static void __kprobes thumb16_singlestep(struct kprobe *p, struct pt_regs *regs)
37{
38 regs->ARM_pc += 2;
39 p->ainsn.insn_handler(p, regs);
40 regs->ARM_cpsr = it_advance(regs->ARM_cpsr);
41}
42
43static void __kprobes thumb32_singlestep(struct kprobe *p, struct pt_regs *regs)
44{
45 regs->ARM_pc += 4;
46 p->ainsn.insn_handler(p, regs);
47 regs->ARM_cpsr = it_advance(regs->ARM_cpsr);
48}
49
36enum kprobe_insn __kprobes 50enum kprobe_insn __kprobes
37thumb16_kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi) 51thumb16_kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi)
38{ 52{
53 asi->insn_singlestep = thumb16_singlestep;
39 asi->insn_check_cc = thumb_check_cc; 54 asi->insn_check_cc = thumb_check_cc;
40 return INSN_REJECTED; 55 return INSN_REJECTED;
41} 56}
@@ -43,6 +58,7 @@ thumb16_kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi)
43enum kprobe_insn __kprobes 58enum kprobe_insn __kprobes
44thumb32_kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi) 59thumb32_kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi)
45{ 60{
61 asi->insn_singlestep = thumb32_singlestep;
46 asi->insn_check_cc = thumb_check_cc; 62 asi->insn_check_cc = thumb_check_cc;
47 return INSN_REJECTED; 63 return INSN_REJECTED;
48} 64}
diff --git a/arch/arm/kernel/kprobes.c b/arch/arm/kernel/kprobes.c
index 0003dfd3b854..77b7c6974802 100644
--- a/arch/arm/kernel/kprobes.c
+++ b/arch/arm/kernel/kprobes.c
@@ -227,12 +227,10 @@ singlestep_skip(struct kprobe *p, struct pt_regs *regs)
227#endif 227#endif
228} 228}
229 229
230static void __kprobes singlestep(struct kprobe *p, struct pt_regs *regs, 230static inline void __kprobes
231 struct kprobe_ctlblk *kcb) 231singlestep(struct kprobe *p, struct pt_regs *regs, struct kprobe_ctlblk *kcb)
232{ 232{
233 regs->ARM_pc += 4; 233 p->ainsn.insn_singlestep(p, regs);
234 if (p->ainsn.insn_check_cc(regs->ARM_cpsr))
235 p->ainsn.insn_handler(p, regs);
236} 234}
237 235
238/* 236/*