diff options
-rw-r--r-- | arch/arm/include/asm/kprobes.h | 2 | ||||
-rw-r--r-- | arch/arm/kernel/kprobes.c | 5 |
2 files changed, 7 insertions, 0 deletions
diff --git a/arch/arm/include/asm/kprobes.h b/arch/arm/include/asm/kprobes.h index 1e9ff56d40c7..feec86768f9c 100644 --- a/arch/arm/include/asm/kprobes.h +++ b/arch/arm/include/asm/kprobes.h | |||
@@ -34,6 +34,7 @@ struct kprobe; | |||
34 | typedef void (kprobe_insn_handler_t)(struct kprobe *, struct pt_regs *); | 34 | typedef void (kprobe_insn_handler_t)(struct kprobe *, struct pt_regs *); |
35 | typedef unsigned long (kprobe_check_cc)(unsigned long); | 35 | typedef unsigned long (kprobe_check_cc)(unsigned long); |
36 | typedef void (kprobe_insn_singlestep_t)(struct kprobe *, struct pt_regs *); | 36 | typedef void (kprobe_insn_singlestep_t)(struct kprobe *, struct pt_regs *); |
37 | typedef void (kprobe_insn_fn_t)(void); | ||
37 | 38 | ||
38 | /* Architecture specific copy of original instruction. */ | 39 | /* Architecture specific copy of original instruction. */ |
39 | struct arch_specific_insn { | 40 | struct arch_specific_insn { |
@@ -41,6 +42,7 @@ struct arch_specific_insn { | |||
41 | kprobe_insn_handler_t *insn_handler; | 42 | kprobe_insn_handler_t *insn_handler; |
42 | kprobe_check_cc *insn_check_cc; | 43 | kprobe_check_cc *insn_check_cc; |
43 | kprobe_insn_singlestep_t *insn_singlestep; | 44 | kprobe_insn_singlestep_t *insn_singlestep; |
45 | kprobe_insn_fn_t *insn_fn; | ||
44 | }; | 46 | }; |
45 | 47 | ||
46 | struct prev_kprobe { | 48 | struct prev_kprobe { |
diff --git a/arch/arm/kernel/kprobes.c b/arch/arm/kernel/kprobes.c index 77b7c6974802..129c1163248b 100644 --- a/arch/arm/kernel/kprobes.c +++ b/arch/arm/kernel/kprobes.c | |||
@@ -51,6 +51,7 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p) | |||
51 | kprobe_opcode_t insn; | 51 | kprobe_opcode_t insn; |
52 | kprobe_opcode_t tmp_insn[MAX_INSN_SIZE]; | 52 | kprobe_opcode_t tmp_insn[MAX_INSN_SIZE]; |
53 | unsigned long addr = (unsigned long)p->addr; | 53 | unsigned long addr = (unsigned long)p->addr; |
54 | bool thumb; | ||
54 | kprobe_decode_insn_t *decode_insn; | 55 | kprobe_decode_insn_t *decode_insn; |
55 | int is; | 56 | int is; |
56 | 57 | ||
@@ -58,6 +59,7 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p) | |||
58 | return -EINVAL; | 59 | return -EINVAL; |
59 | 60 | ||
60 | #ifdef CONFIG_THUMB2_KERNEL | 61 | #ifdef CONFIG_THUMB2_KERNEL |
62 | thumb = true; | ||
61 | addr &= ~1; /* Bit 0 would normally be set to indicate Thumb code */ | 63 | addr &= ~1; /* Bit 0 would normally be set to indicate Thumb code */ |
62 | insn = ((u16 *)addr)[0]; | 64 | insn = ((u16 *)addr)[0]; |
63 | if (is_wide_instruction(insn)) { | 65 | if (is_wide_instruction(insn)) { |
@@ -67,6 +69,7 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p) | |||
67 | } else | 69 | } else |
68 | decode_insn = thumb16_kprobe_decode_insn; | 70 | decode_insn = thumb16_kprobe_decode_insn; |
69 | #else /* !CONFIG_THUMB2_KERNEL */ | 71 | #else /* !CONFIG_THUMB2_KERNEL */ |
72 | thumb = false; | ||
70 | if (addr & 0x3) | 73 | if (addr & 0x3) |
71 | return -EINVAL; | 74 | return -EINVAL; |
72 | insn = *p->addr; | 75 | insn = *p->addr; |
@@ -88,6 +91,8 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p) | |||
88 | p->ainsn.insn[is] = tmp_insn[is]; | 91 | p->ainsn.insn[is] = tmp_insn[is]; |
89 | flush_insns(p->ainsn.insn, | 92 | flush_insns(p->ainsn.insn, |
90 | sizeof(p->ainsn.insn[0]) * MAX_INSN_SIZE); | 93 | sizeof(p->ainsn.insn[0]) * MAX_INSN_SIZE); |
94 | p->ainsn.insn_fn = (kprobe_insn_fn_t *) | ||
95 | ((uintptr_t)p->ainsn.insn | thumb); | ||
91 | break; | 96 | break; |
92 | 97 | ||
93 | case INSN_GOOD_NO_SLOT: /* instruction doesn't need insn slot */ | 98 | case INSN_GOOD_NO_SLOT: /* instruction doesn't need insn slot */ |