aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/kernel/kprobes.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/kernel/kprobes.c')
-rw-r--r--arch/arm/kernel/kprobes.c25
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)
197static inline void __kprobes 206static inline void __kprobes
198singlestep(struct kprobe *p, struct pt_regs *regs, struct kprobe_ctlblk *kcb) 207singlestep(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
608int __init arch_init_kprobes() 617int __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);