diff options
author | Jon Medhurst <tixy@yxit.co.uk> | 2011-07-02 10:46:05 -0400 |
---|---|---|
committer | Tixy <tixy@medhuaa1.miniserver.com> | 2011-07-13 13:32:43 -0400 |
commit | 02d194f64772aee91e7319ca033905b0bafee04c (patch) | |
tree | 67071bb76ec91b1df072bc8eaa889f8c62cbb5d7 /arch | |
parent | 7460bce42323df6570c7ba5091cb5201c7af1944 (diff) |
ARM: kprobes: Decode 16-bit Thumb data-processing instructions
These instructions only operate on the low registers R0-R7, therefore
it is possible to emulate them by executing the original instruction
unaltered if we restore and save these registers. This is what
t16_emulate_loregs does.
Some of these instructions don't update the PSR when they execute in an
IT block, so there are two flavours of emulation functions:
t16_emulate_loregs_{noit}rwflags
Signed-off-by: Jon Medhurst <tixy@yxit.co.uk>
Acked-by: Nicolas Pitre <nicolas.pitre@linaro.org>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/kernel/kprobes-thumb.c | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/arch/arm/kernel/kprobes-thumb.c b/arch/arm/kernel/kprobes-thumb.c index 7dcf6df4a85c..e1cef8273126 100644 --- a/arch/arm/kernel/kprobes-thumb.c +++ b/arch/arm/kernel/kprobes-thumb.c | |||
@@ -26,6 +26,42 @@ | |||
26 | */ | 26 | */ |
27 | #define current_cond(cpsr) ((cpsr >> 12) & 0xf) | 27 | #define current_cond(cpsr) ((cpsr >> 12) & 0xf) |
28 | 28 | ||
29 | static unsigned long __kprobes | ||
30 | t16_emulate_loregs(struct kprobe *p, struct pt_regs *regs) | ||
31 | { | ||
32 | unsigned long oldcpsr = regs->ARM_cpsr; | ||
33 | unsigned long newcpsr; | ||
34 | |||
35 | __asm__ __volatile__ ( | ||
36 | "msr cpsr_fs, %[oldcpsr] \n\t" | ||
37 | "ldmia %[regs], {r0-r7} \n\t" | ||
38 | "blx %[fn] \n\t" | ||
39 | "stmia %[regs], {r0-r7} \n\t" | ||
40 | "mrs %[newcpsr], cpsr \n\t" | ||
41 | : [newcpsr] "=r" (newcpsr) | ||
42 | : [oldcpsr] "r" (oldcpsr), [regs] "r" (regs), | ||
43 | [fn] "r" (p->ainsn.insn_fn) | ||
44 | : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", | ||
45 | "lr", "memory", "cc" | ||
46 | ); | ||
47 | |||
48 | return (oldcpsr & ~APSR_MASK) | (newcpsr & APSR_MASK); | ||
49 | } | ||
50 | |||
51 | static void __kprobes | ||
52 | t16_emulate_loregs_rwflags(struct kprobe *p, struct pt_regs *regs) | ||
53 | { | ||
54 | regs->ARM_cpsr = t16_emulate_loregs(p, regs); | ||
55 | } | ||
56 | |||
57 | static void __kprobes | ||
58 | t16_emulate_loregs_noitrwflags(struct kprobe *p, struct pt_regs *regs) | ||
59 | { | ||
60 | unsigned long cpsr = t16_emulate_loregs(p, regs); | ||
61 | if (!in_it_block(cpsr)) | ||
62 | regs->ARM_cpsr = cpsr; | ||
63 | } | ||
64 | |||
29 | static const union decode_item t16_table_1011[] = { | 65 | static const union decode_item t16_table_1011[] = { |
30 | /* Miscellaneous 16-bit instructions */ | 66 | /* Miscellaneous 16-bit instructions */ |
31 | 67 | ||
@@ -51,6 +87,51 @@ static const union decode_item t16_table_1011[] = { | |||
51 | const union decode_item kprobe_decode_thumb16_table[] = { | 87 | const union decode_item kprobe_decode_thumb16_table[] = { |
52 | 88 | ||
53 | /* | 89 | /* |
90 | * Shift (immediate), add, subtract, move, and compare | ||
91 | * 00xx xxxx xxxx xxxx | ||
92 | */ | ||
93 | |||
94 | /* CMP (immediate) 0010 1xxx xxxx xxxx */ | ||
95 | DECODE_EMULATE (0xf800, 0x2800, t16_emulate_loregs_rwflags), | ||
96 | |||
97 | /* ADD (register) 0001 100x xxxx xxxx */ | ||
98 | /* SUB (register) 0001 101x xxxx xxxx */ | ||
99 | /* LSL (immediate) 0000 0xxx xxxx xxxx */ | ||
100 | /* LSR (immediate) 0000 1xxx xxxx xxxx */ | ||
101 | /* ASR (immediate) 0001 0xxx xxxx xxxx */ | ||
102 | /* ADD (immediate, Thumb) 0001 110x xxxx xxxx */ | ||
103 | /* SUB (immediate, Thumb) 0001 111x xxxx xxxx */ | ||
104 | /* MOV (immediate) 0010 0xxx xxxx xxxx */ | ||
105 | /* ADD (immediate, Thumb) 0011 0xxx xxxx xxxx */ | ||
106 | /* SUB (immediate, Thumb) 0011 1xxx xxxx xxxx */ | ||
107 | DECODE_EMULATE (0xc000, 0x0000, t16_emulate_loregs_noitrwflags), | ||
108 | |||
109 | /* | ||
110 | * 16-bit Thumb data-processing instructions | ||
111 | * 0100 00xx xxxx xxxx | ||
112 | */ | ||
113 | |||
114 | /* TST (register) 0100 0010 00xx xxxx */ | ||
115 | DECODE_EMULATE (0xffc0, 0x4200, t16_emulate_loregs_rwflags), | ||
116 | /* CMP (register) 0100 0010 10xx xxxx */ | ||
117 | /* CMN (register) 0100 0010 11xx xxxx */ | ||
118 | DECODE_EMULATE (0xff80, 0x4280, t16_emulate_loregs_rwflags), | ||
119 | /* AND (register) 0100 0000 00xx xxxx */ | ||
120 | /* EOR (register) 0100 0000 01xx xxxx */ | ||
121 | /* LSL (register) 0100 0000 10xx xxxx */ | ||
122 | /* LSR (register) 0100 0000 11xx xxxx */ | ||
123 | /* ASR (register) 0100 0001 00xx xxxx */ | ||
124 | /* ADC (register) 0100 0001 01xx xxxx */ | ||
125 | /* SBC (register) 0100 0001 10xx xxxx */ | ||
126 | /* ROR (register) 0100 0001 11xx xxxx */ | ||
127 | /* RSB (immediate) 0100 0010 01xx xxxx */ | ||
128 | /* ORR (register) 0100 0011 00xx xxxx */ | ||
129 | /* MUL 0100 0011 00xx xxxx */ | ||
130 | /* BIC (register) 0100 0011 10xx xxxx */ | ||
131 | /* MVN (register) 0100 0011 10xx xxxx */ | ||
132 | DECODE_EMULATE (0xfc00, 0x4000, t16_emulate_loregs_noitrwflags), | ||
133 | |||
134 | /* | ||
54 | * Miscellaneous 16-bit instructions | 135 | * Miscellaneous 16-bit instructions |
55 | * 1011 xxxx xxxx xxxx | 136 | * 1011 xxxx xxxx xxxx |
56 | */ | 137 | */ |