• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * arch/arm/kernel/kprobes-decode.c
3  *
4  * Copyright (C) 2006, 2007 Motorola Inc.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License for more details.
14  */
15 
16 /*
17  * We do not have hardware single-stepping on ARM, This
18  * effort is further complicated by the ARM not having a
19  * "next PC" register.  Instructions that change the PC
20  * can't be safely single-stepped in a MP environment, so
21  * we have a lot of work to do:
22  *
23  * In the prepare phase:
24  *   *) If it is an instruction that does anything
25  *      with the CPU mode, we reject it for a kprobe.
26  *      (This is out of laziness rather than need.  The
27  *      instructions could be simulated.)
28  *
29  *   *) Otherwise, decode the instruction rewriting its
30  *      registers to take fixed, ordered registers and
31  *      setting a handler for it to run the instruction.
32  *
33  * In the execution phase by an instruction's handler:
34  *
35  *   *) If the PC is written to by the instruction, the
36  *      instruction must be fully simulated in software.
37  *
38  *   *) Otherwise, a modified form of the instruction is
39  *      directly executed.  Its handler calls the
40  *      instruction in insn[0].  In insn[1] is a
41  *      "mov pc, lr" to return.
42  *
43  *      Before calling, load up the reordered registers
44  *      from the original instruction's registers.  If one
45  *      of the original input registers is the PC, compute
46  *      and adjust the appropriate input register.
47  *
48  *	After call completes, copy the output registers to
49  *      the original instruction's original registers.
50  *
51  * We don't use a real breakpoint instruction since that
52  * would have us in the kernel go from SVC mode to SVC
53  * mode losing the link register.  Instead we use an
54  * undefined instruction.  To simplify processing, the
55  * undefined instruction used for kprobes must be reserved
56  * exclusively for kprobes use.
57  *
58  * TODO: ifdef out some instruction decoding based on architecture.
59  */
60 
61 #include <linux/kernel.h>
62 #include <linux/kprobes.h>
63 #include <linux/ptrace.h>
64 
65 #include "kprobes.h"
66 #include "probes-arm.h"
67 
68 #if  __LINUX_ARM_ARCH__ >= 6
69 #define BLX(reg)	"blx	"reg"		\n\t"
70 #else
71 #define BLX(reg)	"mov	lr, pc		\n\t"	\
72 			"mov	pc, "reg"	\n\t"
73 #endif
74 
75 static void __kprobes
emulate_ldrdstrd(probes_opcode_t insn,struct arch_probes_insn * asi,struct pt_regs * regs)76 emulate_ldrdstrd(probes_opcode_t insn,
77 	struct arch_probes_insn *asi, struct pt_regs *regs)
78 {
79 	unsigned long pc = regs->ARM_pc + 4;
80 	int rt = (insn >> 12) & 0xf;
81 	int rn = (insn >> 16) & 0xf;
82 	int rm = insn & 0xf;
83 
84 	register unsigned long rtv asm("r0") = regs->uregs[rt];
85 	register unsigned long rt2v asm("r1") = regs->uregs[rt+1];
86 	register unsigned long rnv asm("r2") = (rn == 15) ? pc
87 							  : regs->uregs[rn];
88 	register unsigned long rmv asm("r3") = regs->uregs[rm];
89 
90 	__asm__ __volatile__ (
91 		BLX("%[fn]")
92 		: "=r" (rtv), "=r" (rt2v), "=r" (rnv)
93 		: "0" (rtv), "1" (rt2v), "2" (rnv), "r" (rmv),
94 		  [fn] "r" (asi->insn_fn)
95 		: "lr", "memory", "cc"
96 	);
97 
98 	regs->uregs[rt] = rtv;
99 	regs->uregs[rt+1] = rt2v;
100 	if (is_writeback(insn))
101 		regs->uregs[rn] = rnv;
102 }
103 
104 static void __kprobes
emulate_ldr(probes_opcode_t insn,struct arch_probes_insn * asi,struct pt_regs * regs)105 emulate_ldr(probes_opcode_t insn,
106 	struct arch_probes_insn *asi, struct pt_regs *regs)
107 {
108 	unsigned long pc = regs->ARM_pc + 4;
109 	int rt = (insn >> 12) & 0xf;
110 	int rn = (insn >> 16) & 0xf;
111 	int rm = insn & 0xf;
112 
113 	register unsigned long rtv asm("r0");
114 	register unsigned long rnv asm("r2") = (rn == 15) ? pc
115 							  : regs->uregs[rn];
116 	register unsigned long rmv asm("r3") = regs->uregs[rm];
117 
118 	__asm__ __volatile__ (
119 		BLX("%[fn]")
120 		: "=r" (rtv), "=r" (rnv)
121 		: "1" (rnv), "r" (rmv), [fn] "r" (asi->insn_fn)
122 		: "lr", "memory", "cc"
123 	);
124 
125 	if (rt == 15)
126 		load_write_pc(rtv, regs);
127 	else
128 		regs->uregs[rt] = rtv;
129 
130 	if (is_writeback(insn))
131 		regs->uregs[rn] = rnv;
132 }
133 
134 static void __kprobes
emulate_str(probes_opcode_t insn,struct arch_probes_insn * asi,struct pt_regs * regs)135 emulate_str(probes_opcode_t insn,
136 	struct arch_probes_insn *asi, struct pt_regs *regs)
137 {
138 	unsigned long rtpc = regs->ARM_pc - 4 + str_pc_offset;
139 	unsigned long rnpc = regs->ARM_pc + 4;
140 	int rt = (insn >> 12) & 0xf;
141 	int rn = (insn >> 16) & 0xf;
142 	int rm = insn & 0xf;
143 
144 	register unsigned long rtv asm("r0") = (rt == 15) ? rtpc
145 							  : regs->uregs[rt];
146 	register unsigned long rnv asm("r2") = (rn == 15) ? rnpc
147 							  : regs->uregs[rn];
148 	register unsigned long rmv asm("r3") = regs->uregs[rm];
149 
150 	__asm__ __volatile__ (
151 		BLX("%[fn]")
152 		: "=r" (rnv)
153 		: "r" (rtv), "0" (rnv), "r" (rmv), [fn] "r" (asi->insn_fn)
154 		: "lr", "memory", "cc"
155 	);
156 
157 	if (is_writeback(insn))
158 		regs->uregs[rn] = rnv;
159 }
160 
161 static void __kprobes
emulate_rd12rn16rm0rs8_rwflags(probes_opcode_t insn,struct arch_probes_insn * asi,struct pt_regs * regs)162 emulate_rd12rn16rm0rs8_rwflags(probes_opcode_t insn,
163 	struct arch_probes_insn *asi, struct pt_regs *regs)
164 {
165 	unsigned long pc = regs->ARM_pc + 4;
166 	int rd = (insn >> 12) & 0xf;
167 	int rn = (insn >> 16) & 0xf;
168 	int rm = insn & 0xf;
169 	int rs = (insn >> 8) & 0xf;
170 
171 	register unsigned long rdv asm("r0") = regs->uregs[rd];
172 	register unsigned long rnv asm("r2") = (rn == 15) ? pc
173 							  : regs->uregs[rn];
174 	register unsigned long rmv asm("r3") = (rm == 15) ? pc
175 							  : regs->uregs[rm];
176 	register unsigned long rsv asm("r1") = regs->uregs[rs];
177 	unsigned long cpsr = regs->ARM_cpsr;
178 
179 	__asm__ __volatile__ (
180 		"msr	cpsr_fs, %[cpsr]	\n\t"
181 		BLX("%[fn]")
182 		"mrs	%[cpsr], cpsr		\n\t"
183 		: "=r" (rdv), [cpsr] "=r" (cpsr)
184 		: "0" (rdv), "r" (rnv), "r" (rmv), "r" (rsv),
185 		  "1" (cpsr), [fn] "r" (asi->insn_fn)
186 		: "lr", "memory", "cc"
187 	);
188 
189 	if (rd == 15)
190 		alu_write_pc(rdv, regs);
191 	else
192 		regs->uregs[rd] = rdv;
193 	regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK);
194 }
195 
196 static void __kprobes
emulate_rd12rn16rm0_rwflags_nopc(probes_opcode_t insn,struct arch_probes_insn * asi,struct pt_regs * regs)197 emulate_rd12rn16rm0_rwflags_nopc(probes_opcode_t insn,
198 	struct arch_probes_insn *asi, struct pt_regs *regs)
199 {
200 	int rd = (insn >> 12) & 0xf;
201 	int rn = (insn >> 16) & 0xf;
202 	int rm = insn & 0xf;
203 
204 	register unsigned long rdv asm("r0") = regs->uregs[rd];
205 	register unsigned long rnv asm("r2") = regs->uregs[rn];
206 	register unsigned long rmv asm("r3") = regs->uregs[rm];
207 	unsigned long cpsr = regs->ARM_cpsr;
208 
209 	__asm__ __volatile__ (
210 		"msr	cpsr_fs, %[cpsr]	\n\t"
211 		BLX("%[fn]")
212 		"mrs	%[cpsr], cpsr		\n\t"
213 		: "=r" (rdv), [cpsr] "=r" (cpsr)
214 		: "0" (rdv), "r" (rnv), "r" (rmv),
215 		  "1" (cpsr), [fn] "r" (asi->insn_fn)
216 		: "lr", "memory", "cc"
217 	);
218 
219 	regs->uregs[rd] = rdv;
220 	regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK);
221 }
222 
223 static void __kprobes
emulate_rd16rn12rm0rs8_rwflags_nopc(probes_opcode_t insn,struct arch_probes_insn * asi,struct pt_regs * regs)224 emulate_rd16rn12rm0rs8_rwflags_nopc(probes_opcode_t insn,
225 	struct arch_probes_insn *asi,
226 	struct pt_regs *regs)
227 {
228 	int rd = (insn >> 16) & 0xf;
229 	int rn = (insn >> 12) & 0xf;
230 	int rm = insn & 0xf;
231 	int rs = (insn >> 8) & 0xf;
232 
233 	register unsigned long rdv asm("r2") = regs->uregs[rd];
234 	register unsigned long rnv asm("r0") = regs->uregs[rn];
235 	register unsigned long rmv asm("r3") = regs->uregs[rm];
236 	register unsigned long rsv asm("r1") = regs->uregs[rs];
237 	unsigned long cpsr = regs->ARM_cpsr;
238 
239 	__asm__ __volatile__ (
240 		"msr	cpsr_fs, %[cpsr]	\n\t"
241 		BLX("%[fn]")
242 		"mrs	%[cpsr], cpsr		\n\t"
243 		: "=r" (rdv), [cpsr] "=r" (cpsr)
244 		: "0" (rdv), "r" (rnv), "r" (rmv), "r" (rsv),
245 		  "1" (cpsr), [fn] "r" (asi->insn_fn)
246 		: "lr", "memory", "cc"
247 	);
248 
249 	regs->uregs[rd] = rdv;
250 	regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK);
251 }
252 
253 static void __kprobes
emulate_rd12rm0_noflags_nopc(probes_opcode_t insn,struct arch_probes_insn * asi,struct pt_regs * regs)254 emulate_rd12rm0_noflags_nopc(probes_opcode_t insn,
255 	struct arch_probes_insn *asi, struct pt_regs *regs)
256 {
257 	int rd = (insn >> 12) & 0xf;
258 	int rm = insn & 0xf;
259 
260 	register unsigned long rdv asm("r0") = regs->uregs[rd];
261 	register unsigned long rmv asm("r3") = regs->uregs[rm];
262 
263 	__asm__ __volatile__ (
264 		BLX("%[fn]")
265 		: "=r" (rdv)
266 		: "0" (rdv), "r" (rmv), [fn] "r" (asi->insn_fn)
267 		: "lr", "memory", "cc"
268 	);
269 
270 	regs->uregs[rd] = rdv;
271 }
272 
273 static void __kprobes
emulate_rdlo12rdhi16rn0rm8_rwflags_nopc(probes_opcode_t insn,struct arch_probes_insn * asi,struct pt_regs * regs)274 emulate_rdlo12rdhi16rn0rm8_rwflags_nopc(probes_opcode_t insn,
275 	struct arch_probes_insn *asi,
276 	struct pt_regs *regs)
277 {
278 	int rdlo = (insn >> 12) & 0xf;
279 	int rdhi = (insn >> 16) & 0xf;
280 	int rn = insn & 0xf;
281 	int rm = (insn >> 8) & 0xf;
282 
283 	register unsigned long rdlov asm("r0") = regs->uregs[rdlo];
284 	register unsigned long rdhiv asm("r2") = regs->uregs[rdhi];
285 	register unsigned long rnv asm("r3") = regs->uregs[rn];
286 	register unsigned long rmv asm("r1") = regs->uregs[rm];
287 	unsigned long cpsr = regs->ARM_cpsr;
288 
289 	__asm__ __volatile__ (
290 		"msr	cpsr_fs, %[cpsr]	\n\t"
291 		BLX("%[fn]")
292 		"mrs	%[cpsr], cpsr		\n\t"
293 		: "=r" (rdlov), "=r" (rdhiv), [cpsr] "=r" (cpsr)
294 		: "0" (rdlov), "1" (rdhiv), "r" (rnv), "r" (rmv),
295 		  "2" (cpsr), [fn] "r" (asi->insn_fn)
296 		: "lr", "memory", "cc"
297 	);
298 
299 	regs->uregs[rdlo] = rdlov;
300 	regs->uregs[rdhi] = rdhiv;
301 	regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK);
302 }
303 
304 const union decode_action kprobes_arm_actions[NUM_PROBES_ARM_ACTIONS] = {
305 	[PROBES_EMULATE_NONE] = {.handler = probes_emulate_none},
306 	[PROBES_SIMULATE_NOP] = {.handler = probes_simulate_nop},
307 	[PROBES_PRELOAD_IMM] = {.handler = probes_simulate_nop},
308 	[PROBES_PRELOAD_REG] = {.handler = probes_simulate_nop},
309 	[PROBES_BRANCH_IMM] = {.handler = simulate_blx1},
310 	[PROBES_MRS] = {.handler = simulate_mrs},
311 	[PROBES_BRANCH_REG] = {.handler = simulate_blx2bx},
312 	[PROBES_CLZ] = {.handler = emulate_rd12rm0_noflags_nopc},
313 	[PROBES_SATURATING_ARITHMETIC] = {
314 		.handler = emulate_rd12rn16rm0_rwflags_nopc},
315 	[PROBES_MUL1] = {.handler = emulate_rdlo12rdhi16rn0rm8_rwflags_nopc},
316 	[PROBES_MUL2] = {.handler = emulate_rd16rn12rm0rs8_rwflags_nopc},
317 	[PROBES_SWP] = {.handler = emulate_rd12rn16rm0_rwflags_nopc},
318 	[PROBES_LDRSTRD] = {.handler = emulate_ldrdstrd},
319 	[PROBES_LOAD_EXTRA] = {.handler = emulate_ldr},
320 	[PROBES_LOAD] = {.handler = emulate_ldr},
321 	[PROBES_STORE_EXTRA] = {.handler = emulate_str},
322 	[PROBES_STORE] = {.handler = emulate_str},
323 	[PROBES_MOV_IP_SP] = {.handler = simulate_mov_ipsp},
324 	[PROBES_DATA_PROCESSING_REG] = {
325 		.handler = emulate_rd12rn16rm0rs8_rwflags},
326 	[PROBES_DATA_PROCESSING_IMM] = {
327 		.handler = emulate_rd12rn16rm0rs8_rwflags},
328 	[PROBES_MOV_HALFWORD] = {.handler = emulate_rd12rm0_noflags_nopc},
329 	[PROBES_SEV] = {.handler = probes_emulate_none},
330 	[PROBES_WFE] = {.handler = probes_simulate_nop},
331 	[PROBES_SATURATE] = {.handler = emulate_rd12rn16rm0_rwflags_nopc},
332 	[PROBES_REV] = {.handler = emulate_rd12rm0_noflags_nopc},
333 	[PROBES_MMI] = {.handler = emulate_rd12rn16rm0_rwflags_nopc},
334 	[PROBES_PACK] = {.handler = emulate_rd12rn16rm0_rwflags_nopc},
335 	[PROBES_EXTEND] = {.handler = emulate_rd12rm0_noflags_nopc},
336 	[PROBES_EXTEND_ADD] = {.handler = emulate_rd12rn16rm0_rwflags_nopc},
337 	[PROBES_MUL_ADD_LONG] = {
338 		.handler = emulate_rdlo12rdhi16rn0rm8_rwflags_nopc},
339 	[PROBES_MUL_ADD] = {.handler = emulate_rd16rn12rm0rs8_rwflags_nopc},
340 	[PROBES_BITFIELD] = {.handler = emulate_rd12rm0_noflags_nopc},
341 	[PROBES_BRANCH] = {.handler = simulate_bbl},
342 	[PROBES_LDMSTM] = {.decoder = kprobe_decode_ldmstm}
343 };
344