diff options
author | Jon Medhurst <tixy@yxit.co.uk> | 2011-07-03 09:26:16 -0400 |
---|---|---|
committer | Tixy <tixy@medhuaa1.miniserver.com> | 2011-07-13 13:32:46 -0400 |
commit | dd212bd3cbd337f8f3bd6b30929bef5a8c8ba81b (patch) | |
tree | fea20f88c887778bf0738b00ea3da09adb86a46d /arch/arm/kernel/kprobes-thumb.c | |
parent | b48354d3584e93284fba2ee99f6f9f44d18e4f83 (diff) |
ARM: kprobes: Decode 32-bit Thumb table branch instructions
Signed-off-by: Jon Medhurst <tixy@yxit.co.uk>
Acked-by: Nicolas Pitre <nicolas.pitre@linaro.org>
Diffstat (limited to 'arch/arm/kernel/kprobes-thumb.c')
-rw-r--r-- | arch/arm/kernel/kprobes-thumb.c | 25 |
1 files changed, 25 insertions, 0 deletions
diff --git a/arch/arm/kernel/kprobes-thumb.c b/arch/arm/kernel/kprobes-thumb.c index 299dc3a33ad2..dfaea25c6069 100644 --- a/arch/arm/kernel/kprobes-thumb.c +++ b/arch/arm/kernel/kprobes-thumb.c | |||
@@ -37,6 +37,26 @@ static inline unsigned long __kprobes thumb_probe_pc(struct kprobe *p) | |||
37 | return (unsigned long)p->addr - 1 + 4; | 37 | return (unsigned long)p->addr - 1 + 4; |
38 | } | 38 | } |
39 | 39 | ||
40 | static void __kprobes | ||
41 | t32_simulate_table_branch(struct kprobe *p, struct pt_regs *regs) | ||
42 | { | ||
43 | kprobe_opcode_t insn = p->opcode; | ||
44 | unsigned long pc = thumb_probe_pc(p); | ||
45 | int rn = (insn >> 16) & 0xf; | ||
46 | int rm = insn & 0xf; | ||
47 | |||
48 | unsigned long rnv = (rn == 15) ? pc : regs->uregs[rn]; | ||
49 | unsigned long rmv = regs->uregs[rm]; | ||
50 | unsigned int halfwords; | ||
51 | |||
52 | if (insn & 0x10) | ||
53 | halfwords = ((u16 *)rnv)[rmv]; | ||
54 | else | ||
55 | halfwords = ((u8 *)rnv)[rmv]; | ||
56 | |||
57 | regs->ARM_pc = pc + 2 * halfwords; | ||
58 | } | ||
59 | |||
40 | static enum kprobe_insn __kprobes | 60 | static enum kprobe_insn __kprobes |
41 | t32_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi) | 61 | t32_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi) |
42 | { | 62 | { |
@@ -117,6 +137,11 @@ static const union decode_item t32_table_1110_100x_x1xx[] = { | |||
117 | DECODE_EMULATEX (0xff400000, 0xe9400000, t32_emulate_ldrdstrd, | 137 | DECODE_EMULATEX (0xff400000, 0xe9400000, t32_emulate_ldrdstrd, |
118 | REGS(NOPCWB, NOSPPC, NOSPPC, 0, 0)), | 138 | REGS(NOPCWB, NOSPPC, NOSPPC, 0, 0)), |
119 | 139 | ||
140 | /* TBB 1110 1000 1101 xxxx xxxx xxxx 0000 xxxx */ | ||
141 | /* TBH 1110 1000 1101 xxxx xxxx xxxx 0001 xxxx */ | ||
142 | DECODE_SIMULATEX(0xfff000e0, 0xe8d00000, t32_simulate_table_branch, | ||
143 | REGS(NOSP, 0, 0, 0, NOSPPC)), | ||
144 | |||
120 | /* STREX 1110 1000 0100 xxxx xxxx xxxx xxxx xxxx */ | 145 | /* STREX 1110 1000 0100 xxxx xxxx xxxx xxxx xxxx */ |
121 | /* LDREX 1110 1000 0101 xxxx xxxx xxxx xxxx xxxx */ | 146 | /* LDREX 1110 1000 0101 xxxx xxxx xxxx xxxx xxxx */ |
122 | /* STREXB 1110 1000 1100 xxxx xxxx xxxx 0100 xxxx */ | 147 | /* STREXB 1110 1000 1100 xxxx xxxx xxxx 0100 xxxx */ |