diff options
Diffstat (limited to 'arch/arm/kernel/kprobes.c')
-rw-r--r-- | arch/arm/kernel/kprobes.c | 25 |
1 files changed, 17 insertions, 8 deletions
diff --git a/arch/arm/kernel/kprobes.c b/arch/arm/kernel/kprobes.c index a7b621ece23d..8795f9f819d5 100644 --- a/arch/arm/kernel/kprobes.c +++ b/arch/arm/kernel/kprobes.c | |||
@@ -27,8 +27,12 @@ | |||
27 | #include <linux/stringify.h> | 27 | #include <linux/stringify.h> |
28 | #include <asm/traps.h> | 28 | #include <asm/traps.h> |
29 | #include <asm/cacheflush.h> | 29 | #include <asm/cacheflush.h> |
30 | #include <linux/percpu.h> | ||
31 | #include <linux/bug.h> | ||
30 | 32 | ||
31 | #include "kprobes.h" | 33 | #include "kprobes.h" |
34 | #include "probes-arm.h" | ||
35 | #include "probes-thumb.h" | ||
32 | #include "patch.h" | 36 | #include "patch.h" |
33 | 37 | ||
34 | #define MIN_STACK_SIZE(addr) \ | 38 | #define MIN_STACK_SIZE(addr) \ |
@@ -54,6 +58,7 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p) | |||
54 | unsigned long addr = (unsigned long)p->addr; | 58 | unsigned long addr = (unsigned long)p->addr; |
55 | bool thumb; | 59 | bool thumb; |
56 | kprobe_decode_insn_t *decode_insn; | 60 | kprobe_decode_insn_t *decode_insn; |
61 | const union decode_action *actions; | ||
57 | int is; | 62 | int is; |
58 | 63 | ||
59 | if (in_exception_text(addr)) | 64 | if (in_exception_text(addr)) |
@@ -66,21 +71,25 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p) | |||
66 | if (is_wide_instruction(insn)) { | 71 | if (is_wide_instruction(insn)) { |
67 | insn <<= 16; | 72 | insn <<= 16; |
68 | insn |= ((u16 *)addr)[1]; | 73 | insn |= ((u16 *)addr)[1]; |
69 | decode_insn = thumb32_kprobe_decode_insn; | 74 | decode_insn = thumb32_probes_decode_insn; |
70 | } else | 75 | actions = kprobes_t32_actions; |
71 | decode_insn = thumb16_kprobe_decode_insn; | 76 | } else { |
77 | decode_insn = thumb16_probes_decode_insn; | ||
78 | actions = kprobes_t16_actions; | ||
79 | } | ||
72 | #else /* !CONFIG_THUMB2_KERNEL */ | 80 | #else /* !CONFIG_THUMB2_KERNEL */ |
73 | thumb = false; | 81 | thumb = false; |
74 | if (addr & 0x3) | 82 | if (addr & 0x3) |
75 | return -EINVAL; | 83 | return -EINVAL; |
76 | insn = *p->addr; | 84 | insn = *p->addr; |
77 | decode_insn = arm_kprobe_decode_insn; | 85 | decode_insn = arm_probes_decode_insn; |
86 | actions = kprobes_arm_actions; | ||
78 | #endif | 87 | #endif |
79 | 88 | ||
80 | p->opcode = insn; | 89 | p->opcode = insn; |
81 | p->ainsn.insn = tmp_insn; | 90 | p->ainsn.insn = tmp_insn; |
82 | 91 | ||
83 | switch ((*decode_insn)(insn, &p->ainsn)) { | 92 | switch ((*decode_insn)(insn, &p->ainsn, true, actions)) { |
84 | case INSN_REJECTED: /* not supported */ | 93 | case INSN_REJECTED: /* not supported */ |
85 | return -EINVAL; | 94 | return -EINVAL; |
86 | 95 | ||
@@ -92,7 +101,7 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p) | |||
92 | p->ainsn.insn[is] = tmp_insn[is]; | 101 | p->ainsn.insn[is] = tmp_insn[is]; |
93 | flush_insns(p->ainsn.insn, | 102 | flush_insns(p->ainsn.insn, |
94 | sizeof(p->ainsn.insn[0]) * MAX_INSN_SIZE); | 103 | sizeof(p->ainsn.insn[0]) * MAX_INSN_SIZE); |
95 | p->ainsn.insn_fn = (kprobe_insn_fn_t *) | 104 | p->ainsn.insn_fn = (probes_insn_fn_t *) |
96 | ((uintptr_t)p->ainsn.insn | thumb); | 105 | ((uintptr_t)p->ainsn.insn | thumb); |
97 | break; | 106 | break; |
98 | 107 | ||
@@ -197,7 +206,7 @@ singlestep_skip(struct kprobe *p, struct pt_regs *regs) | |||
197 | static inline void __kprobes | 206 | static inline void __kprobes |
198 | singlestep(struct kprobe *p, struct pt_regs *regs, struct kprobe_ctlblk *kcb) | 207 | singlestep(struct kprobe *p, struct pt_regs *regs, struct kprobe_ctlblk *kcb) |
199 | { | 208 | { |
200 | p->ainsn.insn_singlestep(p, regs); | 209 | p->ainsn.insn_singlestep(p->opcode, &p->ainsn, regs); |
201 | } | 210 | } |
202 | 211 | ||
203 | /* | 212 | /* |
@@ -607,7 +616,7 @@ static struct undef_hook kprobes_arm_break_hook = { | |||
607 | 616 | ||
608 | int __init arch_init_kprobes() | 617 | int __init arch_init_kprobes() |
609 | { | 618 | { |
610 | arm_kprobe_decode_init(); | 619 | arm_probes_decode_init(); |
611 | #ifdef CONFIG_THUMB2_KERNEL | 620 | #ifdef CONFIG_THUMB2_KERNEL |
612 | register_undef_hook(&kprobes_thumb16_break_hook); | 621 | register_undef_hook(&kprobes_thumb16_break_hook); |
613 | register_undef_hook(&kprobes_thumb32_break_hook); | 622 | register_undef_hook(&kprobes_thumb32_break_hook); |