1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64#include <linux/kernel.h>
65#include <linux/kprobes.h>
66
67#define sign_extend(x, signbit) ((x) | (0 - ((x) & (1 << (signbit)))))
68
69#define branch_displacement(insn) sign_extend(((insn) & 0xffffff) << 2, 25)
70
71#define PSR_fs (PSR_f|PSR_s)
72
73#define KPROBE_RETURN_INSTRUCTION 0xe1a0f00e
74#define SET_R0_TRUE_INSTRUCTION 0xe3a00001
75
76#define truecc_insn(insn) (((insn) & 0xf0000000) | \
77 (SET_R0_TRUE_INSTRUCTION & 0x0fffffff))
78
79typedef long (insn_0arg_fn_t)(void);
80typedef long (insn_1arg_fn_t)(long);
81typedef long (insn_2arg_fn_t)(long, long);
82typedef long (insn_3arg_fn_t)(long, long, long);
83typedef long (insn_4arg_fn_t)(long, long, long, long);
84typedef long long (insn_llret_0arg_fn_t)(void);
85typedef long long (insn_llret_3arg_fn_t)(long, long, long);
86typedef long long (insn_llret_4arg_fn_t)(long, long, long, long);
87
88union reg_pair {
89 long long dr;
90#ifdef __LITTLE_ENDIAN
91 struct { long r0, r1; };
92#else
93 struct { long r1, r0; };
94#endif
95};
96
97
98
99
100
101
102
103
104static int str_pc_offset;
105
106static void __init find_str_pc_offset(void)
107{
108 int addr, scratch, ret;
109
110 __asm__ (
111 "sub %[ret], pc, #4 \n\t"
112 "str pc, %[addr] \n\t"
113 "ldr %[scr], %[addr] \n\t"
114 "sub %[ret], %[scr], %[ret] \n\t"
115 : [ret] "=r" (ret), [scr] "=r" (scratch), [addr] "+m" (addr));
116
117 str_pc_offset = ret;
118}
119
120
121
122
123
124
125
126
127static inline long __kprobes
128insnslot_0arg_rflags(long cpsr, insn_0arg_fn_t *fn)
129{
130 register long ret asm("r0");
131
132 __asm__ __volatile__ (
133 "msr cpsr_fs, %[cpsr] \n\t"
134 "mov lr, pc \n\t"
135 "mov pc, %[fn] \n\t"
136 : "=r" (ret)
137 : [cpsr] "r" (cpsr), [fn] "r" (fn)
138 : "lr", "cc"
139 );
140 return ret;
141}
142
143static inline long long __kprobes
144insnslot_llret_0arg_rflags(long cpsr, insn_llret_0arg_fn_t *fn)
145{
146 register long ret0 asm("r0");
147 register long ret1 asm("r1");
148 union reg_pair fnr;
149
150 __asm__ __volatile__ (
151 "msr cpsr_fs, %[cpsr] \n\t"
152 "mov lr, pc \n\t"
153 "mov pc, %[fn] \n\t"
154 : "=r" (ret0), "=r" (ret1)
155 : [cpsr] "r" (cpsr), [fn] "r" (fn)
156 : "lr", "cc"
157 );
158 fnr.r0 = ret0;
159 fnr.r1 = ret1;
160 return fnr.dr;
161}
162
163static inline long __kprobes
164insnslot_1arg_rflags(long r0, long cpsr, insn_1arg_fn_t *fn)
165{
166 register long rr0 asm("r0") = r0;
167 register long ret asm("r0");
168
169 __asm__ __volatile__ (
170 "msr cpsr_fs, %[cpsr] \n\t"
171 "mov lr, pc \n\t"
172 "mov pc, %[fn] \n\t"
173 : "=r" (ret)
174 : "0" (rr0), [cpsr] "r" (cpsr), [fn] "r" (fn)
175 : "lr", "cc"
176 );
177 return ret;
178}
179
180static inline long __kprobes
181insnslot_2arg_rflags(long r0, long r1, long cpsr, insn_2arg_fn_t *fn)
182{
183 register long rr0 asm("r0") = r0;
184 register long rr1 asm("r1") = r1;
185 register long ret asm("r0");
186
187 __asm__ __volatile__ (
188 "msr cpsr_fs, %[cpsr] \n\t"
189 "mov lr, pc \n\t"
190 "mov pc, %[fn] \n\t"
191 : "=r" (ret)
192 : "0" (rr0), "r" (rr1),
193 [cpsr] "r" (cpsr), [fn] "r" (fn)
194 : "lr", "cc"
195 );
196 return ret;
197}
198
199static inline long __kprobes
200insnslot_3arg_rflags(long r0, long r1, long r2, long cpsr, insn_3arg_fn_t *fn)
201{
202 register long rr0 asm("r0") = r0;
203 register long rr1 asm("r1") = r1;
204 register long rr2 asm("r2") = r2;
205 register long ret asm("r0");
206
207 __asm__ __volatile__ (
208 "msr cpsr_fs, %[cpsr] \n\t"
209 "mov lr, pc \n\t"
210 "mov pc, %[fn] \n\t"
211 : "=r" (ret)
212 : "0" (rr0), "r" (rr1), "r" (rr2),
213 [cpsr] "r" (cpsr), [fn] "r" (fn)
214 : "lr", "cc"
215 );
216 return ret;
217}
218
219static inline long long __kprobes
220insnslot_llret_3arg_rflags(long r0, long r1, long r2, long cpsr,
221 insn_llret_3arg_fn_t *fn)
222{
223 register long rr0 asm("r0") = r0;
224 register long rr1 asm("r1") = r1;
225 register long rr2 asm("r2") = r2;
226 register long ret0 asm("r0");
227 register long ret1 asm("r1");
228 union reg_pair fnr;
229
230 __asm__ __volatile__ (
231 "msr cpsr_fs, %[cpsr] \n\t"
232 "mov lr, pc \n\t"
233 "mov pc, %[fn] \n\t"
234 : "=r" (ret0), "=r" (ret1)
235 : "0" (rr0), "r" (rr1), "r" (rr2),
236 [cpsr] "r" (cpsr), [fn] "r" (fn)
237 : "lr", "cc"
238 );
239 fnr.r0 = ret0;
240 fnr.r1 = ret1;
241 return fnr.dr;
242}
243
244static inline long __kprobes
245insnslot_4arg_rflags(long r0, long r1, long r2, long r3, long cpsr,
246 insn_4arg_fn_t *fn)
247{
248 register long rr0 asm("r0") = r0;
249 register long rr1 asm("r1") = r1;
250 register long rr2 asm("r2") = r2;
251 register long rr3 asm("r3") = r3;
252 register long ret asm("r0");
253
254 __asm__ __volatile__ (
255 "msr cpsr_fs, %[cpsr] \n\t"
256 "mov lr, pc \n\t"
257 "mov pc, %[fn] \n\t"
258 : "=r" (ret)
259 : "0" (rr0), "r" (rr1), "r" (rr2), "r" (rr3),
260 [cpsr] "r" (cpsr), [fn] "r" (fn)
261 : "lr", "cc"
262 );
263 return ret;
264}
265
266static inline long __kprobes
267insnslot_1arg_rwflags(long r0, long *cpsr, insn_1arg_fn_t *fn)
268{
269 register long rr0 asm("r0") = r0;
270 register long ret asm("r0");
271 long oldcpsr = *cpsr;
272 long newcpsr;
273
274 __asm__ __volatile__ (
275 "msr cpsr_fs, %[oldcpsr] \n\t"
276 "mov lr, pc \n\t"
277 "mov pc, %[fn] \n\t"
278 "mrs %[newcpsr], cpsr \n\t"
279 : "=r" (ret), [newcpsr] "=r" (newcpsr)
280 : "0" (rr0), [oldcpsr] "r" (oldcpsr), [fn] "r" (fn)
281 : "lr", "cc"
282 );
283 *cpsr = (oldcpsr & ~PSR_fs) | (newcpsr & PSR_fs);
284 return ret;
285}
286
287static inline long __kprobes
288insnslot_2arg_rwflags(long r0, long r1, long *cpsr, insn_2arg_fn_t *fn)
289{
290 register long rr0 asm("r0") = r0;
291 register long rr1 asm("r1") = r1;
292 register long ret asm("r0");
293 long oldcpsr = *cpsr;
294 long newcpsr;
295
296 __asm__ __volatile__ (
297 "msr cpsr_fs, %[oldcpsr] \n\t"
298 "mov lr, pc \n\t"
299 "mov pc, %[fn] \n\t"
300 "mrs %[newcpsr], cpsr \n\t"
301 : "=r" (ret), [newcpsr] "=r" (newcpsr)
302 : "0" (rr0), "r" (rr1), [oldcpsr] "r" (oldcpsr), [fn] "r" (fn)
303 : "lr", "cc"
304 );
305 *cpsr = (oldcpsr & ~PSR_fs) | (newcpsr & PSR_fs);
306 return ret;
307}
308
309static inline long __kprobes
310insnslot_3arg_rwflags(long r0, long r1, long r2, long *cpsr,
311 insn_3arg_fn_t *fn)
312{
313 register long rr0 asm("r0") = r0;
314 register long rr1 asm("r1") = r1;
315 register long rr2 asm("r2") = r2;
316 register long ret asm("r0");
317 long oldcpsr = *cpsr;
318 long newcpsr;
319
320 __asm__ __volatile__ (
321 "msr cpsr_fs, %[oldcpsr] \n\t"
322 "mov lr, pc \n\t"
323 "mov pc, %[fn] \n\t"
324 "mrs %[newcpsr], cpsr \n\t"
325 : "=r" (ret), [newcpsr] "=r" (newcpsr)
326 : "0" (rr0), "r" (rr1), "r" (rr2),
327 [oldcpsr] "r" (oldcpsr), [fn] "r" (fn)
328 : "lr", "cc"
329 );
330 *cpsr = (oldcpsr & ~PSR_fs) | (newcpsr & PSR_fs);
331 return ret;
332}
333
334static inline long __kprobes
335insnslot_4arg_rwflags(long r0, long r1, long r2, long r3, long *cpsr,
336 insn_4arg_fn_t *fn)
337{
338 register long rr0 asm("r0") = r0;
339 register long rr1 asm("r1") = r1;
340 register long rr2 asm("r2") = r2;
341 register long rr3 asm("r3") = r3;
342 register long ret asm("r0");
343 long oldcpsr = *cpsr;
344 long newcpsr;
345
346 __asm__ __volatile__ (
347 "msr cpsr_fs, %[oldcpsr] \n\t"
348 "mov lr, pc \n\t"
349 "mov pc, %[fn] \n\t"
350 "mrs %[newcpsr], cpsr \n\t"
351 : "=r" (ret), [newcpsr] "=r" (newcpsr)
352 : "0" (rr0), "r" (rr1), "r" (rr2), "r" (rr3),
353 [oldcpsr] "r" (oldcpsr), [fn] "r" (fn)
354 : "lr", "cc"
355 );
356 *cpsr = (oldcpsr & ~PSR_fs) | (newcpsr & PSR_fs);
357 return ret;
358}
359
360static inline long long __kprobes
361insnslot_llret_4arg_rwflags(long r0, long r1, long r2, long r3, long *cpsr,
362 insn_llret_4arg_fn_t *fn)
363{
364 register long rr0 asm("r0") = r0;
365 register long rr1 asm("r1") = r1;
366 register long rr2 asm("r2") = r2;
367 register long rr3 asm("r3") = r3;
368 register long ret0 asm("r0");
369 register long ret1 asm("r1");
370 long oldcpsr = *cpsr;
371 long newcpsr;
372 union reg_pair fnr;
373
374 __asm__ __volatile__ (
375 "msr cpsr_fs, %[oldcpsr] \n\t"
376 "mov lr, pc \n\t"
377 "mov pc, %[fn] \n\t"
378 "mrs %[newcpsr], cpsr \n\t"
379 : "=r" (ret0), "=r" (ret1), [newcpsr] "=r" (newcpsr)
380 : "0" (rr0), "r" (rr1), "r" (rr2), "r" (rr3),
381 [oldcpsr] "r" (oldcpsr), [fn] "r" (fn)
382 : "lr", "cc"
383 );
384 *cpsr = (oldcpsr & ~PSR_fs) | (newcpsr & PSR_fs);
385 fnr.r0 = ret0;
386 fnr.r1 = ret1;
387 return fnr.dr;
388}
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420static void __kprobes simulate_bbl(struct kprobe *p, struct pt_regs *regs)
421{
422 insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
423 kprobe_opcode_t insn = p->opcode;
424 long iaddr = (long)p->addr;
425 int disp = branch_displacement(insn);
426
427 if (!insnslot_1arg_rflags(0, regs->ARM_cpsr, i_fn))
428 return;
429
430 if (insn & (1 << 24))
431 regs->ARM_lr = iaddr + 4;
432
433 regs->ARM_pc = iaddr + 8 + disp;
434}
435
436static void __kprobes simulate_blx1(struct kprobe *p, struct pt_regs *regs)
437{
438 kprobe_opcode_t insn = p->opcode;
439 long iaddr = (long)p->addr;
440 int disp = branch_displacement(insn);
441
442 regs->ARM_lr = iaddr + 4;
443 regs->ARM_pc = iaddr + 8 + disp + ((insn >> 23) & 0x2);
444 regs->ARM_cpsr |= PSR_T_BIT;
445}
446
447static void __kprobes simulate_blx2bx(struct kprobe *p, struct pt_regs *regs)
448{
449 insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
450 kprobe_opcode_t insn = p->opcode;
451 int rm = insn & 0xf;
452 long rmv = regs->uregs[rm];
453
454 if (!insnslot_1arg_rflags(0, regs->ARM_cpsr, i_fn))
455 return;
456
457 if (insn & (1 << 5))
458 regs->ARM_lr = (long)p->addr + 4;
459
460 regs->ARM_pc = rmv & ~0x1;
461 regs->ARM_cpsr &= ~PSR_T_BIT;
462 if (rmv & 0x1)
463 regs->ARM_cpsr |= PSR_T_BIT;
464}
465
466static void __kprobes simulate_ldm1stm1(struct kprobe *p, struct pt_regs *regs)
467{
468 insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
469 kprobe_opcode_t insn = p->opcode;
470 int rn = (insn >> 16) & 0xf;
471 int lbit = insn & (1 << 20);
472 int wbit = insn & (1 << 21);
473 int ubit = insn & (1 << 23);
474 int pbit = insn & (1 << 24);
475 long *addr = (long *)regs->uregs[rn];
476 int reg_bit_vector;
477 int reg_count;
478
479 if (!insnslot_1arg_rflags(0, regs->ARM_cpsr, i_fn))
480 return;
481
482 reg_count = 0;
483 reg_bit_vector = insn & 0xffff;
484 while (reg_bit_vector) {
485 reg_bit_vector &= (reg_bit_vector - 1);
486 ++reg_count;
487 }
488
489 if (!ubit)
490 addr -= reg_count;
491 addr += (!pbit == !ubit);
492
493 reg_bit_vector = insn & 0xffff;
494 while (reg_bit_vector) {
495 int reg = __ffs(reg_bit_vector);
496 reg_bit_vector &= (reg_bit_vector - 1);
497 if (lbit)
498 regs->uregs[reg] = *addr++;
499 else
500 *addr++ = regs->uregs[reg];
501 }
502
503 if (wbit) {
504 if (!ubit)
505 addr -= reg_count;
506 addr -= (!pbit == !ubit);
507 regs->uregs[rn] = (long)addr;
508 }
509}
510
511static void __kprobes simulate_stm1_pc(struct kprobe *p, struct pt_regs *regs)
512{
513 insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
514
515 if (!insnslot_1arg_rflags(0, regs->ARM_cpsr, i_fn))
516 return;
517
518 regs->ARM_pc = (long)p->addr + str_pc_offset;
519 simulate_ldm1stm1(p, regs);
520 regs->ARM_pc = (long)p->addr + 4;
521}
522
523static void __kprobes simulate_mov_ipsp(struct kprobe *p, struct pt_regs *regs)
524{
525 regs->uregs[12] = regs->uregs[13];
526}
527
528static void __kprobes emulate_ldcstc(struct kprobe *p, struct pt_regs *regs)
529{
530 insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
531 kprobe_opcode_t insn = p->opcode;
532 int rn = (insn >> 16) & 0xf;
533 long rnv = regs->uregs[rn];
534
535
536 regs->uregs[rn] = insnslot_1arg_rflags(rnv, regs->ARM_cpsr, i_fn);
537}
538
539static void __kprobes emulate_ldrd(struct kprobe *p, struct pt_regs *regs)
540{
541 insn_2arg_fn_t *i_fn = (insn_2arg_fn_t *)&p->ainsn.insn[0];
542 kprobe_opcode_t insn = p->opcode;
543 int rd = (insn >> 12) & 0xf;
544 int rn = (insn >> 16) & 0xf;
545 int rm = insn & 0xf;
546
547
548 __asm__ __volatile__ (
549 "ldr r0, %[rn] \n\t"
550 "ldr r1, %[rm] \n\t"
551 "msr cpsr_fs, %[cpsr]\n\t"
552 "mov lr, pc \n\t"
553 "mov pc, %[i_fn] \n\t"
554 "str r0, %[rn] \n\t"
555 "str r2, %[rd0] \n\t"
556 "str r3, %[rd1] \n\t"
557 : [rn] "+m" (regs->uregs[rn]),
558 [rd0] "=m" (regs->uregs[rd]),
559 [rd1] "=m" (regs->uregs[rd+1])
560 : [rm] "m" (regs->uregs[rm]),
561 [cpsr] "r" (regs->ARM_cpsr),
562 [i_fn] "r" (i_fn)
563 : "r0", "r1", "r2", "r3", "lr", "cc"
564 );
565}
566
567static void __kprobes emulate_strd(struct kprobe *p, struct pt_regs *regs)
568{
569 insn_4arg_fn_t *i_fn = (insn_4arg_fn_t *)&p->ainsn.insn[0];
570 kprobe_opcode_t insn = p->opcode;
571 int rd = (insn >> 12) & 0xf;
572 int rn = (insn >> 16) & 0xf;
573 int rm = insn & 0xf;
574 long rnv = regs->uregs[rn];
575 long rmv = regs->uregs[rm];
576
577 regs->uregs[rn] = insnslot_4arg_rflags(rnv, rmv, regs->uregs[rd],
578 regs->uregs[rd+1],
579 regs->ARM_cpsr, i_fn);
580}
581
582static void __kprobes emulate_ldr(struct kprobe *p, struct pt_regs *regs)
583{
584 insn_llret_3arg_fn_t *i_fn = (insn_llret_3arg_fn_t *)&p->ainsn.insn[0];
585 kprobe_opcode_t insn = p->opcode;
586 long ppc = (long)p->addr + 8;
587 union reg_pair fnr;
588 int rd = (insn >> 12) & 0xf;
589 int rn = (insn >> 16) & 0xf;
590 int rm = insn & 0xf;
591 long rdv;
592 long rnv = (rn == 15) ? ppc : regs->uregs[rn];
593 long rmv = (rm == 15) ? ppc : regs->uregs[rm];
594 long cpsr = regs->ARM_cpsr;
595
596 fnr.dr = insnslot_llret_3arg_rflags(rnv, 0, rmv, cpsr, i_fn);
597 regs->uregs[rn] = fnr.r0;
598 rdv = fnr.r1;
599
600 if (rd == 15) {
601#if __LINUX_ARM_ARCH__ >= 5
602 cpsr &= ~PSR_T_BIT;
603 if (rdv & 0x1)
604 cpsr |= PSR_T_BIT;
605 regs->ARM_cpsr = cpsr;
606 rdv &= ~0x1;
607#else
608 rdv &= ~0x2;
609#endif
610 }
611 regs->uregs[rd] = rdv;
612}
613
614static void __kprobes emulate_str(struct kprobe *p, struct pt_regs *regs)
615{
616 insn_3arg_fn_t *i_fn = (insn_3arg_fn_t *)&p->ainsn.insn[0];
617 kprobe_opcode_t insn = p->opcode;
618 long iaddr = (long)p->addr;
619 int rd = (insn >> 12) & 0xf;
620 int rn = (insn >> 16) & 0xf;
621 int rm = insn & 0xf;
622 long rdv = (rd == 15) ? iaddr + str_pc_offset : regs->uregs[rd];
623 long rnv = (rn == 15) ? iaddr + 8 : regs->uregs[rn];
624 long rmv = regs->uregs[rm];
625
626
627 regs->uregs[rn] =
628 insnslot_3arg_rflags(rnv, rdv, rmv, regs->ARM_cpsr, i_fn);
629}
630
631static void __kprobes emulate_mrrc(struct kprobe *p, struct pt_regs *regs)
632{
633 insn_llret_0arg_fn_t *i_fn = (insn_llret_0arg_fn_t *)&p->ainsn.insn[0];
634 kprobe_opcode_t insn = p->opcode;
635 union reg_pair fnr;
636 int rd = (insn >> 12) & 0xf;
637 int rn = (insn >> 16) & 0xf;
638
639 fnr.dr = insnslot_llret_0arg_rflags(regs->ARM_cpsr, i_fn);
640 regs->uregs[rn] = fnr.r0;
641 regs->uregs[rd] = fnr.r1;
642}
643
644static void __kprobes emulate_mcrr(struct kprobe *p, struct pt_regs *regs)
645{
646 insn_2arg_fn_t *i_fn = (insn_2arg_fn_t *)&p->ainsn.insn[0];
647 kprobe_opcode_t insn = p->opcode;
648 int rd = (insn >> 12) & 0xf;
649 int rn = (insn >> 16) & 0xf;
650 long rnv = regs->uregs[rn];
651 long rdv = regs->uregs[rd];
652
653 insnslot_2arg_rflags(rnv, rdv, regs->ARM_cpsr, i_fn);
654}
655
656static void __kprobes emulate_sat(struct kprobe *p, struct pt_regs *regs)
657{
658 insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
659 kprobe_opcode_t insn = p->opcode;
660 int rd = (insn >> 12) & 0xf;
661 int rm = insn & 0xf;
662 long rmv = regs->uregs[rm];
663
664
665 regs->uregs[rd] = insnslot_1arg_rwflags(rmv, ®s->ARM_cpsr, i_fn);
666}
667
668static void __kprobes emulate_sel(struct kprobe *p, struct pt_regs *regs)
669{
670 insn_2arg_fn_t *i_fn = (insn_2arg_fn_t *)&p->ainsn.insn[0];
671 kprobe_opcode_t insn = p->opcode;
672 int rd = (insn >> 12) & 0xf;
673 int rn = (insn >> 16) & 0xf;
674 int rm = insn & 0xf;
675 long rnv = regs->uregs[rn];
676 long rmv = regs->uregs[rm];
677
678
679 regs->uregs[rd] = insnslot_2arg_rflags(rnv, rmv, regs->ARM_cpsr, i_fn);
680}
681
682static void __kprobes emulate_none(struct kprobe *p, struct pt_regs *regs)
683{
684 insn_0arg_fn_t *i_fn = (insn_0arg_fn_t *)&p->ainsn.insn[0];
685
686 insnslot_0arg_rflags(regs->ARM_cpsr, i_fn);
687}
688
689static void __kprobes emulate_rd12(struct kprobe *p, struct pt_regs *regs)
690{
691 insn_0arg_fn_t *i_fn = (insn_0arg_fn_t *)&p->ainsn.insn[0];
692 kprobe_opcode_t insn = p->opcode;
693 int rd = (insn >> 12) & 0xf;
694
695 regs->uregs[rd] = insnslot_0arg_rflags(regs->ARM_cpsr, i_fn);
696}
697
698static void __kprobes emulate_ird12(struct kprobe *p, struct pt_regs *regs)
699{
700 insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
701 kprobe_opcode_t insn = p->opcode;
702 int ird = (insn >> 12) & 0xf;
703
704 insnslot_1arg_rflags(regs->uregs[ird], regs->ARM_cpsr, i_fn);
705}
706
707static void __kprobes emulate_rn16(struct kprobe *p, struct pt_regs *regs)
708{
709 insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
710 kprobe_opcode_t insn = p->opcode;
711 int rn = (insn >> 16) & 0xf;
712 long rnv = regs->uregs[rn];
713
714 insnslot_1arg_rflags(rnv, regs->ARM_cpsr, i_fn);
715}
716
717static void __kprobes emulate_rd12rm0(struct kprobe *p, struct pt_regs *regs)
718{
719 insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
720 kprobe_opcode_t insn = p->opcode;
721 int rd = (insn >> 12) & 0xf;
722 int rm = insn & 0xf;
723 long rmv = regs->uregs[rm];
724
725 regs->uregs[rd] = insnslot_1arg_rflags(rmv, regs->ARM_cpsr, i_fn);
726}
727
728static void __kprobes
729emulate_rd12rn16rm0_rwflags(struct kprobe *p, struct pt_regs *regs)
730{
731 insn_2arg_fn_t *i_fn = (insn_2arg_fn_t *)&p->ainsn.insn[0];
732 kprobe_opcode_t insn = p->opcode;
733 int rd = (insn >> 12) & 0xf;
734 int rn = (insn >> 16) & 0xf;
735 int rm = insn & 0xf;
736 long rnv = regs->uregs[rn];
737 long rmv = regs->uregs[rm];
738
739 regs->uregs[rd] =
740 insnslot_2arg_rwflags(rnv, rmv, ®s->ARM_cpsr, i_fn);
741}
742
743static void __kprobes
744emulate_rd16rn12rs8rm0_rwflags(struct kprobe *p, struct pt_regs *regs)
745{
746 insn_3arg_fn_t *i_fn = (insn_3arg_fn_t *)&p->ainsn.insn[0];
747 kprobe_opcode_t insn = p->opcode;
748 int rd = (insn >> 16) & 0xf;
749 int rn = (insn >> 12) & 0xf;
750 int rs = (insn >> 8) & 0xf;
751 int rm = insn & 0xf;
752 long rnv = regs->uregs[rn];
753 long rsv = regs->uregs[rs];
754 long rmv = regs->uregs[rm];
755
756 regs->uregs[rd] =
757 insnslot_3arg_rwflags(rnv, rsv, rmv, ®s->ARM_cpsr, i_fn);
758}
759
760static void __kprobes
761emulate_rd16rs8rm0_rwflags(struct kprobe *p, struct pt_regs *regs)
762{
763 insn_2arg_fn_t *i_fn = (insn_2arg_fn_t *)&p->ainsn.insn[0];
764 kprobe_opcode_t insn = p->opcode;
765 int rd = (insn >> 16) & 0xf;
766 int rs = (insn >> 8) & 0xf;
767 int rm = insn & 0xf;
768 long rsv = regs->uregs[rs];
769 long rmv = regs->uregs[rm];
770
771 regs->uregs[rd] =
772 insnslot_2arg_rwflags(rsv, rmv, ®s->ARM_cpsr, i_fn);
773}
774
775static void __kprobes
776emulate_rdhi16rdlo12rs8rm0_rwflags(struct kprobe *p, struct pt_regs *regs)
777{
778 insn_llret_4arg_fn_t *i_fn = (insn_llret_4arg_fn_t *)&p->ainsn.insn[0];
779 kprobe_opcode_t insn = p->opcode;
780 union reg_pair fnr;
781 int rdhi = (insn >> 16) & 0xf;
782 int rdlo = (insn >> 12) & 0xf;
783 int rs = (insn >> 8) & 0xf;
784 int rm = insn & 0xf;
785 long rsv = regs->uregs[rs];
786 long rmv = regs->uregs[rm];
787
788 fnr.dr = insnslot_llret_4arg_rwflags(regs->uregs[rdhi],
789 regs->uregs[rdlo], rsv, rmv,
790 ®s->ARM_cpsr, i_fn);
791 regs->uregs[rdhi] = fnr.r0;
792 regs->uregs[rdlo] = fnr.r1;
793}
794
795static void __kprobes
796emulate_alu_imm_rflags(struct kprobe *p, struct pt_regs *regs)
797{
798 insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
799 kprobe_opcode_t insn = p->opcode;
800 int rd = (insn >> 12) & 0xf;
801 int rn = (insn >> 16) & 0xf;
802 long rnv = (rn == 15) ? (long)p->addr + 8 : regs->uregs[rn];
803
804 regs->uregs[rd] = insnslot_1arg_rflags(rnv, regs->ARM_cpsr, i_fn);
805}
806
807static void __kprobes
808emulate_alu_imm_rwflags(struct kprobe *p, struct pt_regs *regs)
809{
810 insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
811 kprobe_opcode_t insn = p->opcode;
812 int rd = (insn >> 12) & 0xf;
813 int rn = (insn >> 16) & 0xf;
814 long rnv = (rn == 15) ? (long)p->addr + 8 : regs->uregs[rn];
815
816 regs->uregs[rd] = insnslot_1arg_rwflags(rnv, ®s->ARM_cpsr, i_fn);
817}
818
819static void __kprobes
820emulate_alu_rflags(struct kprobe *p, struct pt_regs *regs)
821{
822 insn_3arg_fn_t *i_fn = (insn_3arg_fn_t *)&p->ainsn.insn[0];
823 kprobe_opcode_t insn = p->opcode;
824 long ppc = (long)p->addr + 8;
825 int rd = (insn >> 12) & 0xf;
826 int rn = (insn >> 16) & 0xf;
827 int rs = (insn >> 8) & 0xf;
828 int rm = insn & 0xf;
829 long rnv = (rn == 15) ? ppc : regs->uregs[rn];
830 long rmv = (rm == 15) ? ppc : regs->uregs[rm];
831 long rsv = regs->uregs[rs];
832
833 regs->uregs[rd] =
834 insnslot_3arg_rflags(rnv, rmv, rsv, regs->ARM_cpsr, i_fn);
835}
836
837static void __kprobes
838emulate_alu_rwflags(struct kprobe *p, struct pt_regs *regs)
839{
840 insn_3arg_fn_t *i_fn = (insn_3arg_fn_t *)&p->ainsn.insn[0];
841 kprobe_opcode_t insn = p->opcode;
842 long ppc = (long)p->addr + 8;
843 int rd = (insn >> 12) & 0xf;
844 int rn = (insn >> 16) & 0xf;
845 int rs = (insn >> 8) & 0xf;
846 int rm = insn & 0xf;
847 long rnv = (rn == 15) ? ppc : regs->uregs[rn];
848 long rmv = (rm == 15) ? ppc : regs->uregs[rm];
849 long rsv = regs->uregs[rs];
850
851 regs->uregs[rd] =
852 insnslot_3arg_rwflags(rnv, rmv, rsv, ®s->ARM_cpsr, i_fn);
853}
854
855static enum kprobe_insn __kprobes
856prep_emulate_ldr_str(kprobe_opcode_t insn, struct arch_specific_insn *asi)
857{
858 int ibit = (insn & (1 << 26)) ? 25 : 22;
859
860 insn &= 0xfff00fff;
861 insn |= 0x00001000;
862 if (insn & (1 << ibit)) {
863 insn &= ~0xf;
864 insn |= 2;
865 }
866 asi->insn[0] = insn;
867 asi->insn_handler = (insn & (1 << 20)) ? emulate_ldr : emulate_str;
868 return INSN_GOOD;
869}
870
871static enum kprobe_insn __kprobes
872prep_emulate_rd12rm0(kprobe_opcode_t insn, struct arch_specific_insn *asi)
873{
874 insn &= 0xffff0ff0;
875 asi->insn[0] = insn;
876 asi->insn_handler = emulate_rd12rm0;
877 return INSN_GOOD;
878}
879
880static enum kprobe_insn __kprobes
881prep_emulate_rd12(kprobe_opcode_t insn, struct arch_specific_insn *asi)
882{
883 insn &= 0xffff0fff;
884 asi->insn[0] = insn;
885 asi->insn_handler = emulate_rd12;
886 return INSN_GOOD;
887}
888
889static enum kprobe_insn __kprobes
890prep_emulate_rd12rn16rm0_wflags(kprobe_opcode_t insn,
891 struct arch_specific_insn *asi)
892{
893 insn &= 0xfff00ff0;
894 insn |= 0x00000001;
895 asi->insn[0] = insn;
896 asi->insn_handler = emulate_rd12rn16rm0_rwflags;
897 return INSN_GOOD;
898}
899
900static enum kprobe_insn __kprobes
901prep_emulate_rd16rs8rm0_wflags(kprobe_opcode_t insn,
902 struct arch_specific_insn *asi)
903{
904 insn &= 0xfff0f0f0;
905 insn |= 0x00000001;
906 asi->insn[0] = insn;
907 asi->insn_handler = emulate_rd16rs8rm0_rwflags;
908 return INSN_GOOD;
909}
910
911static enum kprobe_insn __kprobes
912prep_emulate_rd16rn12rs8rm0_wflags(kprobe_opcode_t insn,
913 struct arch_specific_insn *asi)
914{
915 insn &= 0xfff000f0;
916 insn |= 0x00000102;
917 asi->insn[0] = insn;
918 asi->insn_handler = emulate_rd16rn12rs8rm0_rwflags;
919 return INSN_GOOD;
920}
921
922static enum kprobe_insn __kprobes
923prep_emulate_rdhi16rdlo12rs8rm0_wflags(kprobe_opcode_t insn,
924 struct arch_specific_insn *asi)
925{
926 insn &= 0xfff000f0;
927 insn |= 0x00001203;
928 asi->insn[0] = insn;
929 asi->insn_handler = emulate_rdhi16rdlo12rs8rm0_rwflags;
930 return INSN_GOOD;
931}
932
933
934
935
936
937
938
939
940
941
942
943static enum kprobe_insn __kprobes
944space_1111(kprobe_opcode_t insn, struct arch_specific_insn *asi)
945{
946
947
948
949 if ((insn & 0xfff30020) == 0xf1020000 ||
950 (insn & 0xfe500f00) == 0xf8100a00 ||
951 (insn & 0xfe5f0f00) == 0xf84d0500)
952 return INSN_REJECTED;
953
954
955 if ((insn & 0xfd700000) == 0xf4500000) {
956 insn &= 0xfff0ffff;
957 asi->insn[0] = insn;
958 asi->insn_handler = emulate_rn16;
959 return INSN_GOOD;
960 }
961
962
963 if ((insn & 0xfe000000) == 0xfa000000) {
964 asi->insn_handler = simulate_blx1;
965 return INSN_GOOD_NO_SLOT;
966 }
967
968
969
970 if ((insn & 0xffff00f0) == 0xf1010000 ||
971 (insn & 0xff000010) == 0xfe000000) {
972 asi->insn[0] = insn;
973 asi->insn_handler = emulate_none;
974 return INSN_GOOD;
975 }
976
977
978
979 if ((insn & 0xffe00000) == 0xfc400000) {
980 insn &= 0xfff00fff;
981 insn |= 0x00001000;
982 asi->insn[0] = insn;
983 asi->insn_handler =
984 (insn & (1 << 20)) ? emulate_mrrc : emulate_mcrr;
985 return INSN_GOOD;
986 }
987
988
989
990 if ((insn & 0xfe000000) == 0xfc000000) {
991 insn &= 0xfff0ffff;
992 asi->insn[0] = insn;
993 asi->insn_handler = emulate_ldcstc;
994 return INSN_GOOD;
995 }
996
997
998
999 insn &= 0xffff0fff;
1000 asi->insn[0] = insn;
1001 asi->insn_handler = (insn & (1 << 20)) ? emulate_rd12 : emulate_ird12;
1002 return INSN_GOOD;
1003}
1004
1005static enum kprobe_insn __kprobes
1006space_cccc_000x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
1007{
1008
1009 if ((insn & 0x0f900010) == 0x01000000) {
1010
1011
1012
1013 if ((insn & 0x0ff000f0) == 0x01200020 ||
1014 (insn & 0x0fb000f0) == 0x01200000)
1015 return INSN_REJECTED;
1016
1017
1018 if ((insn & 0x0fb00010) == 0x01000000)
1019 return prep_emulate_rd12(insn, asi);
1020
1021
1022 if ((insn & 0x0ff00090) == 0x01400080)
1023 return prep_emulate_rdhi16rdlo12rs8rm0_wflags(insn, asi);
1024
1025
1026
1027 if ((insn & 0x0ff000b0) == 0x012000a0 ||
1028 (insn & 0x0ff00090) == 0x01600080)
1029 return prep_emulate_rd16rs8rm0_wflags(insn, asi);
1030
1031
1032
1033 return prep_emulate_rd16rn12rs8rm0_wflags(insn, asi);
1034
1035 }
1036
1037
1038 else if ((insn & 0x0f900090) == 0x01000010) {
1039
1040
1041 if ((insn & 0xfff000f0) == 0xe1200070)
1042 return INSN_REJECTED;
1043
1044
1045
1046 if ((insn & 0x0ff000d0) == 0x01200010) {
1047 asi->insn[0] = truecc_insn(insn);
1048 asi->insn_handler = simulate_blx2bx;
1049 return INSN_GOOD;
1050 }
1051
1052
1053 if ((insn & 0x0ff000f0) == 0x01600010)
1054 return prep_emulate_rd12rm0(insn, asi);
1055
1056
1057
1058
1059
1060 return prep_emulate_rd12rn16rm0_wflags(insn, asi);
1061 }
1062
1063
1064 else if ((insn & 0x0f000090) == 0x00000090) {
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079 if ((insn & 0x0fe000f0) == 0x00000090) {
1080 return prep_emulate_rd16rs8rm0_wflags(insn, asi);
1081 } else if ((insn & 0x0fe000f0) == 0x00200090) {
1082 return prep_emulate_rd16rn12rs8rm0_wflags(insn, asi);
1083 } else {
1084 return prep_emulate_rdhi16rdlo12rs8rm0_wflags(insn, asi);
1085 }
1086 }
1087
1088
1089 else if ((insn & 0x0e000090) == 0x00000090) {
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101 if ((insn & 0x0fb000f0) == 0x01000090) {
1102
1103 return prep_emulate_rd12rn16rm0_wflags(insn, asi);
1104 } else if ((insn & 0x0e1000d0) == 0x00000d0) {
1105
1106 insn &= 0xfff00fff;
1107 insn |= 0x00002000;
1108 if (insn & (1 << 22)) {
1109
1110 insn &= ~0xf;
1111 insn |= 1;
1112 }
1113 asi->insn[0] = insn;
1114 asi->insn_handler =
1115 (insn & (1 << 5)) ? emulate_strd : emulate_ldrd;
1116 return INSN_GOOD;
1117 }
1118
1119 return prep_emulate_ldr_str(insn, asi);
1120 }
1121
1122
1123
1124
1125
1126
1127
1128 if ((insn & 0x0e10f000) == 0x0010f000)
1129 return INSN_REJECTED;
1130
1131
1132
1133
1134
1135 if (insn == 0xe1a0c00d) {
1136 asi->insn_handler = simulate_mov_ipsp;
1137 return INSN_GOOD_NO_SLOT;
1138 }
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148 insn &= 0xfff00ff0;
1149 insn |= 0x00000001;
1150 if (insn & 0x010) {
1151 insn &= 0xfffff0ff;
1152 insn |= 0x00000200;
1153 }
1154 asi->insn[0] = insn;
1155 asi->insn_handler = (insn & (1 << 20)) ?
1156 emulate_alu_rwflags : emulate_alu_rflags;
1157 return INSN_GOOD;
1158}
1159
1160static enum kprobe_insn __kprobes
1161space_cccc_001x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
1162{
1163
1164
1165
1166
1167
1168
1169 if ((insn & 0x0f900000) == 0x03200000 ||
1170 (insn & 0x0e10f000) == 0x0210f000)
1171 return INSN_REJECTED;
1172
1173
1174
1175
1176
1177
1178
1179
1180 insn &= 0xfff00fff;
1181 asi->insn[0] = insn;
1182 asi->insn_handler = (insn & (1 << 20)) ?
1183 emulate_alu_imm_rwflags : emulate_alu_imm_rflags;
1184 return INSN_GOOD;
1185}
1186
1187static enum kprobe_insn __kprobes
1188space_cccc_0110__1(kprobe_opcode_t insn, struct arch_specific_insn *asi)
1189{
1190
1191 if ((insn & 0x0ff000f0) == 0x068000b0) {
1192 insn &= 0xfff00ff0;
1193 insn |= 0x00000001;
1194 asi->insn[0] = insn;
1195 asi->insn_handler = emulate_sel;
1196 return INSN_GOOD;
1197 }
1198
1199
1200
1201
1202
1203 if ((insn & 0x0fa00030) == 0x06a00010 ||
1204 (insn & 0x0fb000f0) == 0x06a00030) {
1205 insn &= 0xffff0ff0;
1206 asi->insn[0] = insn;
1207 asi->insn_handler = emulate_sat;
1208 return INSN_GOOD;
1209 }
1210
1211
1212
1213
1214 if ((insn & 0x0ff00070) == 0x06b00030 ||
1215 (insn & 0x0ff000f0) == 0x06f000b0)
1216 return prep_emulate_rd12rm0(insn, asi);
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263 return prep_emulate_rd12rn16rm0_wflags(insn, asi);
1264}
1265
1266static enum kprobe_insn __kprobes
1267space_cccc_0111__1(kprobe_opcode_t insn, struct arch_specific_insn *asi)
1268{
1269
1270 if ((insn & 0x0ff000f0) == 0x03f000f0)
1271 return INSN_REJECTED;
1272
1273
1274
1275 if ((insn & 0x0ff000f0) == 0x07800010)
1276 return prep_emulate_rd16rn12rs8rm0_wflags(insn, asi);
1277
1278
1279
1280 if ((insn & 0x0ff00090) == 0x07400010)
1281 return prep_emulate_rdhi16rdlo12rs8rm0_wflags(insn, asi);
1282
1283
1284
1285
1286
1287 if ((insn & 0x0ff00090) == 0x07000010 ||
1288 (insn & 0x0ff000d0) == 0x07500010 ||
1289 (insn & 0x0ff000d0) == 0x075000d0)
1290 return prep_emulate_rd16rn12rs8rm0_wflags(insn, asi);
1291
1292
1293
1294
1295 return prep_emulate_rd16rs8rm0_wflags(insn, asi);
1296}
1297
1298static enum kprobe_insn __kprobes
1299space_cccc_01xx(kprobe_opcode_t insn, struct arch_specific_insn *asi)
1300{
1301
1302
1303
1304
1305
1306
1307
1308
1309 return prep_emulate_ldr_str(insn, asi);
1310}
1311
1312static enum kprobe_insn __kprobes
1313space_cccc_100x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
1314{
1315
1316
1317 if ((insn & 0x0e708000) == 0x85000000 ||
1318 (insn & 0x0e508000) == 0x85010000)
1319 return INSN_REJECTED;
1320
1321
1322
1323 asi->insn[0] = truecc_insn(insn);
1324 asi->insn_handler = ((insn & 0x108000) == 0x008000) ?
1325 simulate_stm1_pc : simulate_ldm1stm1;
1326 return INSN_GOOD;
1327}
1328
1329static enum kprobe_insn __kprobes
1330space_cccc_101x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
1331{
1332
1333
1334 asi->insn[0] = truecc_insn(insn);
1335 asi->insn_handler = simulate_bbl;
1336 return INSN_GOOD;
1337}
1338
1339static enum kprobe_insn __kprobes
1340space_cccc_1100_010x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
1341{
1342
1343
1344 insn &= 0xfff00fff;
1345 insn |= 0x00001000;
1346 asi->insn[0] = insn;
1347 asi->insn_handler = (insn & (1 << 20)) ? emulate_mrrc : emulate_mcrr;
1348 return INSN_GOOD;
1349}
1350
1351static enum kprobe_insn __kprobes
1352space_cccc_110x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
1353{
1354
1355
1356 insn &= 0xfff0ffff;
1357 asi->insn[0] = insn;
1358 asi->insn_handler = emulate_ldcstc;
1359 return INSN_GOOD;
1360}
1361
1362static enum kprobe_insn __kprobes
1363space_cccc_111x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
1364{
1365
1366
1367 if ((insn & 0xfff000f0) == 0xe1200070 ||
1368 (insn & 0x0f000000) == 0x0f000000)
1369 return INSN_REJECTED;
1370
1371
1372 if ((insn & 0x0f000010) == 0x0e000000) {
1373 asi->insn[0] = insn;
1374 asi->insn_handler = emulate_none;
1375 return INSN_GOOD;
1376 }
1377
1378
1379
1380 insn &= 0xffff0fff;
1381 asi->insn[0] = insn;
1382 asi->insn_handler = (insn & (1 << 20)) ? emulate_rd12 : emulate_ird12;
1383 return INSN_GOOD;
1384}
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398enum kprobe_insn __kprobes
1399arm_kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi)
1400{
1401 asi->insn[1] = KPROBE_RETURN_INSTRUCTION;
1402
1403 if ((insn & 0xf0000000) == 0xf0000000) {
1404
1405 return space_1111(insn, asi);
1406
1407 } else if ((insn & 0x0e000000) == 0x00000000) {
1408
1409 return space_cccc_000x(insn, asi);
1410
1411 } else if ((insn & 0x0e000000) == 0x02000000) {
1412
1413 return space_cccc_001x(insn, asi);
1414
1415 } else if ((insn & 0x0f000010) == 0x06000010) {
1416
1417 return space_cccc_0110__1(insn, asi);
1418
1419 } else if ((insn & 0x0f000010) == 0x07000010) {
1420
1421 return space_cccc_0111__1(insn, asi);
1422
1423 } else if ((insn & 0x0c000000) == 0x04000000) {
1424
1425 return space_cccc_01xx(insn, asi);
1426
1427 } else if ((insn & 0x0e000000) == 0x08000000) {
1428
1429 return space_cccc_100x(insn, asi);
1430
1431 } else if ((insn & 0x0e000000) == 0x0a000000) {
1432
1433 return space_cccc_101x(insn, asi);
1434
1435 } else if ((insn & 0x0fe00000) == 0x0c400000) {
1436
1437 return space_cccc_1100_010x(insn, asi);
1438
1439 } else if ((insn & 0x0e000000) == 0x0c400000) {
1440
1441 return space_cccc_110x(insn, asi);
1442
1443 }
1444
1445 return space_cccc_111x(insn, asi);
1446}
1447
1448void __init arm_kprobe_decode_init(void)
1449{
1450 find_str_pc_offset();
1451}
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531