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 union reg_pair fnr;
587 int rd = (insn >> 12) & 0xf;
588 int rn = (insn >> 16) & 0xf;
589 int rm = insn & 0xf;
590 long rdv;
591 long rnv = regs->uregs[rn];
592 long rmv = regs->uregs[rm];
593 long cpsr = regs->ARM_cpsr;
594
595 fnr.dr = insnslot_llret_3arg_rflags(rnv, 0, rmv, cpsr, i_fn);
596 regs->uregs[rn] = fnr.r0;
597 rdv = fnr.r1;
598
599 if (rd == 15) {
600#if __LINUX_ARM_ARCH__ >= 5
601 cpsr &= ~PSR_T_BIT;
602 if (rdv & 0x1)
603 cpsr |= PSR_T_BIT;
604 regs->ARM_cpsr = cpsr;
605 rdv &= ~0x1;
606#else
607 rdv &= ~0x2;
608#endif
609 }
610 regs->uregs[rd] = rdv;
611}
612
613static void __kprobes emulate_str(struct kprobe *p, struct pt_regs *regs)
614{
615 insn_3arg_fn_t *i_fn = (insn_3arg_fn_t *)&p->ainsn.insn[0];
616 kprobe_opcode_t insn = p->opcode;
617 long iaddr = (long)p->addr;
618 int rd = (insn >> 12) & 0xf;
619 int rn = (insn >> 16) & 0xf;
620 int rm = insn & 0xf;
621 long rdv = (rd == 15) ? iaddr + str_pc_offset : regs->uregs[rd];
622 long rnv = (rn == 15) ? iaddr + 8 : regs->uregs[rn];
623 long rmv = regs->uregs[rm];
624
625
626 regs->uregs[rn] =
627 insnslot_3arg_rflags(rnv, rdv, rmv, regs->ARM_cpsr, i_fn);
628}
629
630static void __kprobes emulate_mrrc(struct kprobe *p, struct pt_regs *regs)
631{
632 insn_llret_0arg_fn_t *i_fn = (insn_llret_0arg_fn_t *)&p->ainsn.insn[0];
633 kprobe_opcode_t insn = p->opcode;
634 union reg_pair fnr;
635 int rd = (insn >> 12) & 0xf;
636 int rn = (insn >> 16) & 0xf;
637
638 fnr.dr = insnslot_llret_0arg_rflags(regs->ARM_cpsr, i_fn);
639 regs->uregs[rn] = fnr.r0;
640 regs->uregs[rd] = fnr.r1;
641}
642
643static void __kprobes emulate_mcrr(struct kprobe *p, struct pt_regs *regs)
644{
645 insn_2arg_fn_t *i_fn = (insn_2arg_fn_t *)&p->ainsn.insn[0];
646 kprobe_opcode_t insn = p->opcode;
647 int rd = (insn >> 12) & 0xf;
648 int rn = (insn >> 16) & 0xf;
649 long rnv = regs->uregs[rn];
650 long rdv = regs->uregs[rd];
651
652 insnslot_2arg_rflags(rnv, rdv, regs->ARM_cpsr, i_fn);
653}
654
655static void __kprobes emulate_sat(struct kprobe *p, struct pt_regs *regs)
656{
657 insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
658 kprobe_opcode_t insn = p->opcode;
659 int rd = (insn >> 12) & 0xf;
660 int rm = insn & 0xf;
661 long rmv = regs->uregs[rm];
662
663
664 regs->uregs[rd] = insnslot_1arg_rwflags(rmv, ®s->ARM_cpsr, i_fn);
665}
666
667static void __kprobes emulate_sel(struct kprobe *p, struct pt_regs *regs)
668{
669 insn_2arg_fn_t *i_fn = (insn_2arg_fn_t *)&p->ainsn.insn[0];
670 kprobe_opcode_t insn = p->opcode;
671 int rd = (insn >> 12) & 0xf;
672 int rn = (insn >> 16) & 0xf;
673 int rm = insn & 0xf;
674 long rnv = regs->uregs[rn];
675 long rmv = regs->uregs[rm];
676
677
678 regs->uregs[rd] = insnslot_2arg_rflags(rnv, rmv, regs->ARM_cpsr, i_fn);
679}
680
681static void __kprobes emulate_none(struct kprobe *p, struct pt_regs *regs)
682{
683 insn_0arg_fn_t *i_fn = (insn_0arg_fn_t *)&p->ainsn.insn[0];
684
685 insnslot_0arg_rflags(regs->ARM_cpsr, i_fn);
686}
687
688static void __kprobes emulate_rd12(struct kprobe *p, struct pt_regs *regs)
689{
690 insn_0arg_fn_t *i_fn = (insn_0arg_fn_t *)&p->ainsn.insn[0];
691 kprobe_opcode_t insn = p->opcode;
692 int rd = (insn >> 12) & 0xf;
693
694 regs->uregs[rd] = insnslot_0arg_rflags(regs->ARM_cpsr, i_fn);
695}
696
697static void __kprobes emulate_ird12(struct kprobe *p, struct pt_regs *regs)
698{
699 insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
700 kprobe_opcode_t insn = p->opcode;
701 int ird = (insn >> 12) & 0xf;
702
703 insnslot_1arg_rflags(regs->uregs[ird], regs->ARM_cpsr, i_fn);
704}
705
706static void __kprobes emulate_rn16(struct kprobe *p, struct pt_regs *regs)
707{
708 insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
709 kprobe_opcode_t insn = p->opcode;
710 int rn = (insn >> 16) & 0xf;
711 long rnv = regs->uregs[rn];
712
713 insnslot_1arg_rflags(rnv, regs->ARM_cpsr, i_fn);
714}
715
716static void __kprobes emulate_rd12rm0(struct kprobe *p, struct pt_regs *regs)
717{
718 insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
719 kprobe_opcode_t insn = p->opcode;
720 int rd = (insn >> 12) & 0xf;
721 int rm = insn & 0xf;
722 long rmv = regs->uregs[rm];
723
724 regs->uregs[rd] = insnslot_1arg_rflags(rmv, regs->ARM_cpsr, i_fn);
725}
726
727static void __kprobes
728emulate_rd12rn16rm0_rwflags(struct kprobe *p, struct pt_regs *regs)
729{
730 insn_2arg_fn_t *i_fn = (insn_2arg_fn_t *)&p->ainsn.insn[0];
731 kprobe_opcode_t insn = p->opcode;
732 int rd = (insn >> 12) & 0xf;
733 int rn = (insn >> 16) & 0xf;
734 int rm = insn & 0xf;
735 long rnv = regs->uregs[rn];
736 long rmv = regs->uregs[rm];
737
738 regs->uregs[rd] =
739 insnslot_2arg_rwflags(rnv, rmv, ®s->ARM_cpsr, i_fn);
740}
741
742static void __kprobes
743emulate_rd16rn12rs8rm0_rwflags(struct kprobe *p, struct pt_regs *regs)
744{
745 insn_3arg_fn_t *i_fn = (insn_3arg_fn_t *)&p->ainsn.insn[0];
746 kprobe_opcode_t insn = p->opcode;
747 int rd = (insn >> 16) & 0xf;
748 int rn = (insn >> 12) & 0xf;
749 int rs = (insn >> 8) & 0xf;
750 int rm = insn & 0xf;
751 long rnv = regs->uregs[rn];
752 long rsv = regs->uregs[rs];
753 long rmv = regs->uregs[rm];
754
755 regs->uregs[rd] =
756 insnslot_3arg_rwflags(rnv, rsv, rmv, ®s->ARM_cpsr, i_fn);
757}
758
759static void __kprobes
760emulate_rd16rs8rm0_rwflags(struct kprobe *p, struct pt_regs *regs)
761{
762 insn_2arg_fn_t *i_fn = (insn_2arg_fn_t *)&p->ainsn.insn[0];
763 kprobe_opcode_t insn = p->opcode;
764 int rd = (insn >> 16) & 0xf;
765 int rs = (insn >> 8) & 0xf;
766 int rm = insn & 0xf;
767 long rsv = regs->uregs[rs];
768 long rmv = regs->uregs[rm];
769
770 regs->uregs[rd] =
771 insnslot_2arg_rwflags(rsv, rmv, ®s->ARM_cpsr, i_fn);
772}
773
774static void __kprobes
775emulate_rdhi16rdlo12rs8rm0_rwflags(struct kprobe *p, struct pt_regs *regs)
776{
777 insn_llret_4arg_fn_t *i_fn = (insn_llret_4arg_fn_t *)&p->ainsn.insn[0];
778 kprobe_opcode_t insn = p->opcode;
779 union reg_pair fnr;
780 int rdhi = (insn >> 16) & 0xf;
781 int rdlo = (insn >> 12) & 0xf;
782 int rs = (insn >> 8) & 0xf;
783 int rm = insn & 0xf;
784 long rsv = regs->uregs[rs];
785 long rmv = regs->uregs[rm];
786
787 fnr.dr = insnslot_llret_4arg_rwflags(regs->uregs[rdhi],
788 regs->uregs[rdlo], rsv, rmv,
789 ®s->ARM_cpsr, i_fn);
790 regs->uregs[rdhi] = fnr.r0;
791 regs->uregs[rdlo] = fnr.r1;
792}
793
794static void __kprobes
795emulate_alu_imm_rflags(struct kprobe *p, struct pt_regs *regs)
796{
797 insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
798 kprobe_opcode_t insn = p->opcode;
799 int rd = (insn >> 12) & 0xf;
800 int rn = (insn >> 16) & 0xf;
801 long rnv = (rn == 15) ? (long)p->addr + 8 : regs->uregs[rn];
802
803 regs->uregs[rd] = insnslot_1arg_rflags(rnv, regs->ARM_cpsr, i_fn);
804}
805
806static void __kprobes
807emulate_alu_imm_rwflags(struct kprobe *p, struct pt_regs *regs)
808{
809 insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
810 kprobe_opcode_t insn = p->opcode;
811 int rd = (insn >> 12) & 0xf;
812 int rn = (insn >> 16) & 0xf;
813 long rnv = (rn == 15) ? (long)p->addr + 8 : regs->uregs[rn];
814
815 regs->uregs[rd] = insnslot_1arg_rwflags(rnv, ®s->ARM_cpsr, i_fn);
816}
817
818static void __kprobes
819emulate_alu_rflags(struct kprobe *p, struct pt_regs *regs)
820{
821 insn_3arg_fn_t *i_fn = (insn_3arg_fn_t *)&p->ainsn.insn[0];
822 kprobe_opcode_t insn = p->opcode;
823 long ppc = (long)p->addr + 8;
824 int rd = (insn >> 12) & 0xf;
825 int rn = (insn >> 16) & 0xf;
826 int rs = (insn >> 8) & 0xf;
827 int rm = insn & 0xf;
828 long rnv = (rn == 15) ? ppc : regs->uregs[rn];
829 long rmv = (rm == 15) ? ppc : regs->uregs[rm];
830 long rsv = regs->uregs[rs];
831
832 regs->uregs[rd] =
833 insnslot_3arg_rflags(rnv, rmv, rsv, regs->ARM_cpsr, i_fn);
834}
835
836static void __kprobes
837emulate_alu_rwflags(struct kprobe *p, struct pt_regs *regs)
838{
839 insn_3arg_fn_t *i_fn = (insn_3arg_fn_t *)&p->ainsn.insn[0];
840 kprobe_opcode_t insn = p->opcode;
841 long ppc = (long)p->addr + 8;
842 int rd = (insn >> 12) & 0xf;
843 int rn = (insn >> 16) & 0xf;
844 int rs = (insn >> 8) & 0xf;
845 int rm = insn & 0xf;
846 long rnv = (rn == 15) ? ppc : regs->uregs[rn];
847 long rmv = (rm == 15) ? ppc : regs->uregs[rm];
848 long rsv = regs->uregs[rs];
849
850 regs->uregs[rd] =
851 insnslot_3arg_rwflags(rnv, rmv, rsv, ®s->ARM_cpsr, i_fn);
852}
853
854static enum kprobe_insn __kprobes
855prep_emulate_ldr_str(kprobe_opcode_t insn, struct arch_specific_insn *asi)
856{
857 int ibit = (insn & (1 << 26)) ? 25 : 22;
858
859 insn &= 0xfff00fff;
860 insn |= 0x00001000;
861 if (insn & (1 << ibit)) {
862 insn &= ~0xf;
863 insn |= 2;
864 }
865 asi->insn[0] = insn;
866 asi->insn_handler = (insn & (1 << 20)) ? emulate_ldr : emulate_str;
867 return INSN_GOOD;
868}
869
870static enum kprobe_insn __kprobes
871prep_emulate_rd12rm0(kprobe_opcode_t insn, struct arch_specific_insn *asi)
872{
873 insn &= 0xffff0ff0;
874 asi->insn[0] = insn;
875 asi->insn_handler = emulate_rd12rm0;
876 return INSN_GOOD;
877}
878
879static enum kprobe_insn __kprobes
880prep_emulate_rd12(kprobe_opcode_t insn, struct arch_specific_insn *asi)
881{
882 insn &= 0xffff0fff;
883 asi->insn[0] = insn;
884 asi->insn_handler = emulate_rd12;
885 return INSN_GOOD;
886}
887
888static enum kprobe_insn __kprobes
889prep_emulate_rd12rn16rm0_wflags(kprobe_opcode_t insn,
890 struct arch_specific_insn *asi)
891{
892 insn &= 0xfff00ff0;
893 insn |= 0x00000001;
894 asi->insn[0] = insn;
895 asi->insn_handler = emulate_rd12rn16rm0_rwflags;
896 return INSN_GOOD;
897}
898
899static enum kprobe_insn __kprobes
900prep_emulate_rd16rs8rm0_wflags(kprobe_opcode_t insn,
901 struct arch_specific_insn *asi)
902{
903 insn &= 0xfff0f0f0;
904 insn |= 0x00000001;
905 asi->insn[0] = insn;
906 asi->insn_handler = emulate_rd16rs8rm0_rwflags;
907 return INSN_GOOD;
908}
909
910static enum kprobe_insn __kprobes
911prep_emulate_rd16rn12rs8rm0_wflags(kprobe_opcode_t insn,
912 struct arch_specific_insn *asi)
913{
914 insn &= 0xfff000f0;
915 insn |= 0x00000102;
916 asi->insn[0] = insn;
917 asi->insn_handler = emulate_rd16rn12rs8rm0_rwflags;
918 return INSN_GOOD;
919}
920
921static enum kprobe_insn __kprobes
922prep_emulate_rdhi16rdlo12rs8rm0_wflags(kprobe_opcode_t insn,
923 struct arch_specific_insn *asi)
924{
925 insn &= 0xfff000f0;
926 insn |= 0x00001203;
927 asi->insn[0] = insn;
928 asi->insn_handler = emulate_rdhi16rdlo12rs8rm0_rwflags;
929 return INSN_GOOD;
930}
931
932
933
934
935
936
937
938
939
940
941
942static enum kprobe_insn __kprobes
943space_1111(kprobe_opcode_t insn, struct arch_specific_insn *asi)
944{
945
946
947
948 if ((insn & 0xfff30020) == 0xf1020000 ||
949 (insn & 0xfe500f00) == 0xf8100a00 ||
950 (insn & 0xfe5f0f00) == 0xf84d0500)
951 return INSN_REJECTED;
952
953
954 if ((insn & 0xfd700000) == 0xf4500000) {
955 insn &= 0xfff0ffff;
956 asi->insn[0] = insn;
957 asi->insn_handler = emulate_rn16;
958 return INSN_GOOD;
959 }
960
961
962 if ((insn & 0xfe000000) == 0xfa000000) {
963 asi->insn_handler = simulate_blx1;
964 return INSN_GOOD_NO_SLOT;
965 }
966
967
968
969 if ((insn & 0xffff00f0) == 0xf1010000 ||
970 (insn & 0xff000010) == 0xfe000000) {
971 asi->insn[0] = insn;
972 asi->insn_handler = emulate_none;
973 return INSN_GOOD;
974 }
975
976
977
978 if ((insn & 0xffe00000) == 0xfc400000) {
979 insn &= 0xfff00fff;
980 insn |= 0x00001000;
981 asi->insn[0] = insn;
982 asi->insn_handler =
983 (insn & (1 << 20)) ? emulate_mrrc : emulate_mcrr;
984 return INSN_GOOD;
985 }
986
987
988
989 if ((insn & 0xfe000000) == 0xfc000000) {
990 insn &= 0xfff0ffff;
991 asi->insn[0] = insn;
992 asi->insn_handler = emulate_ldcstc;
993 return INSN_GOOD;
994 }
995
996
997
998 insn &= 0xffff0fff;
999 asi->insn[0] = insn;
1000 asi->insn_handler = (insn & (1 << 20)) ? emulate_rd12 : emulate_ird12;
1001 return INSN_GOOD;
1002}
1003
1004static enum kprobe_insn __kprobes
1005space_cccc_000x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
1006{
1007
1008 if ((insn & 0x0f900010) == 0x01000000) {
1009
1010
1011
1012 if ((insn & 0x0ff000f0) == 0x01200020 ||
1013 (insn & 0x0fb000f0) == 0x01200000)
1014 return INSN_REJECTED;
1015
1016
1017 if ((insn & 0x0fb00010) == 0x01000000)
1018 return prep_emulate_rd12(insn, asi);
1019
1020
1021 if ((insn & 0x0ff00090) == 0x01400080)
1022 return prep_emulate_rdhi16rdlo12rs8rm0_wflags(insn, asi);
1023
1024
1025
1026 if ((insn & 0x0ff000b0) == 0x012000a0 ||
1027 (insn & 0x0ff00090) == 0x01600080)
1028 return prep_emulate_rd16rs8rm0_wflags(insn, asi);
1029
1030
1031
1032 return prep_emulate_rd16rn12rs8rm0_wflags(insn, asi);
1033
1034 }
1035
1036
1037 else if ((insn & 0x0f900090) == 0x01000010) {
1038
1039
1040 if ((insn & 0xfff000f0) == 0xe1200070)
1041 return INSN_REJECTED;
1042
1043
1044
1045 if ((insn & 0x0ff000d0) == 0x01200010) {
1046 asi->insn[0] = truecc_insn(insn);
1047 asi->insn_handler = simulate_blx2bx;
1048 return INSN_GOOD;
1049 }
1050
1051
1052 if ((insn & 0x0ff000f0) == 0x01600010)
1053 return prep_emulate_rd12rm0(insn, asi);
1054
1055
1056
1057
1058
1059 return prep_emulate_rd12rn16rm0_wflags(insn, asi);
1060 }
1061
1062
1063 else if ((insn & 0x0f000090) == 0x00000090) {
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078 if ((insn & 0x0fe000f0) == 0x00000090) {
1079 return prep_emulate_rd16rs8rm0_wflags(insn, asi);
1080 } else if ((insn & 0x0fe000f0) == 0x00200090) {
1081 return prep_emulate_rd16rn12rs8rm0_wflags(insn, asi);
1082 } else {
1083 return prep_emulate_rdhi16rdlo12rs8rm0_wflags(insn, asi);
1084 }
1085 }
1086
1087
1088 else if ((insn & 0x0e000090) == 0x00000090) {
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100 if ((insn & 0x0fb000f0) == 0x01000090) {
1101
1102 return prep_emulate_rd12rn16rm0_wflags(insn, asi);
1103 } else if ((insn & 0x0e1000d0) == 0x00000d0) {
1104
1105 insn &= 0xfff00fff;
1106 insn |= 0x00002000;
1107 if (insn & (1 << 22)) {
1108
1109 insn &= ~0xf;
1110 insn |= 1;
1111 }
1112 asi->insn[0] = insn;
1113 asi->insn_handler =
1114 (insn & (1 << 5)) ? emulate_strd : emulate_ldrd;
1115 return INSN_GOOD;
1116 }
1117
1118 return prep_emulate_ldr_str(insn, asi);
1119 }
1120
1121
1122
1123
1124
1125
1126
1127 if ((insn & 0x0e10f000) == 0x0010f000)
1128 return INSN_REJECTED;
1129
1130
1131
1132
1133
1134 if (insn == 0xe1a0c00d) {
1135 asi->insn_handler = simulate_mov_ipsp;
1136 return INSN_GOOD_NO_SLOT;
1137 }
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147 insn &= 0xfff00ff0;
1148 insn |= 0x00000001;
1149 if (insn & 0x010) {
1150 insn &= 0xfffff0ff;
1151 insn |= 0x00000200;
1152 }
1153 asi->insn[0] = insn;
1154 asi->insn_handler = (insn & (1 << 20)) ?
1155 emulate_alu_rwflags : emulate_alu_rflags;
1156 return INSN_GOOD;
1157}
1158
1159static enum kprobe_insn __kprobes
1160space_cccc_001x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
1161{
1162
1163
1164
1165
1166
1167
1168 if ((insn & 0x0f900000) == 0x03200000 ||
1169 (insn & 0x0e10f000) == 0x0210f000)
1170 return INSN_REJECTED;
1171
1172
1173
1174
1175
1176
1177
1178
1179 insn &= 0xfff00fff;
1180 asi->insn[0] = insn;
1181 asi->insn_handler = (insn & (1 << 20)) ?
1182 emulate_alu_imm_rwflags : emulate_alu_imm_rflags;
1183 return INSN_GOOD;
1184}
1185
1186static enum kprobe_insn __kprobes
1187space_cccc_0110__1(kprobe_opcode_t insn, struct arch_specific_insn *asi)
1188{
1189
1190 if ((insn & 0x0ff000f0) == 0x068000b0) {
1191 insn &= 0xfff00ff0;
1192 insn |= 0x00000001;
1193 asi->insn[0] = insn;
1194 asi->insn_handler = emulate_sel;
1195 return INSN_GOOD;
1196 }
1197
1198
1199
1200
1201
1202 if ((insn & 0x0fa00030) == 0x06a00010 ||
1203 (insn & 0x0fb000f0) == 0x06a00030) {
1204 insn &= 0xffff0ff0;
1205 asi->insn[0] = insn;
1206 asi->insn_handler = emulate_sat;
1207 return INSN_GOOD;
1208 }
1209
1210
1211
1212
1213 if ((insn & 0x0ff00070) == 0x06b00030 ||
1214 (insn & 0x0ff000f0) == 0x06f000b0)
1215 return prep_emulate_rd12rm0(insn, asi);
1216
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 return prep_emulate_rd12rn16rm0_wflags(insn, asi);
1263}
1264
1265static enum kprobe_insn __kprobes
1266space_cccc_0111__1(kprobe_opcode_t insn, struct arch_specific_insn *asi)
1267{
1268
1269 if ((insn & 0x0ff000f0) == 0x03f000f0)
1270 return INSN_REJECTED;
1271
1272
1273
1274 if ((insn & 0x0ff000f0) == 0x07800010)
1275 return prep_emulate_rd16rn12rs8rm0_wflags(insn, asi);
1276
1277
1278
1279 if ((insn & 0x0ff00090) == 0x07400010)
1280 return prep_emulate_rdhi16rdlo12rs8rm0_wflags(insn, asi);
1281
1282
1283
1284
1285
1286 if ((insn & 0x0ff00090) == 0x07000010 ||
1287 (insn & 0x0ff000d0) == 0x07500010 ||
1288 (insn & 0x0ff000d0) == 0x075000d0)
1289 return prep_emulate_rd16rn12rs8rm0_wflags(insn, asi);
1290
1291
1292
1293
1294 return prep_emulate_rd16rs8rm0_wflags(insn, asi);
1295}
1296
1297static enum kprobe_insn __kprobes
1298space_cccc_01xx(kprobe_opcode_t insn, struct arch_specific_insn *asi)
1299{
1300
1301
1302
1303
1304
1305
1306
1307
1308 return prep_emulate_ldr_str(insn, asi);
1309}
1310
1311static enum kprobe_insn __kprobes
1312space_cccc_100x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
1313{
1314
1315
1316 if ((insn & 0x0e708000) == 0x85000000 ||
1317 (insn & 0x0e508000) == 0x85010000)
1318 return INSN_REJECTED;
1319
1320
1321
1322 asi->insn[0] = truecc_insn(insn);
1323 asi->insn_handler = ((insn & 0x108000) == 0x008000) ?
1324 simulate_stm1_pc : simulate_ldm1stm1;
1325 return INSN_GOOD;
1326}
1327
1328static enum kprobe_insn __kprobes
1329space_cccc_101x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
1330{
1331
1332
1333 asi->insn[0] = truecc_insn(insn);
1334 asi->insn_handler = simulate_bbl;
1335 return INSN_GOOD;
1336}
1337
1338static enum kprobe_insn __kprobes
1339space_cccc_1100_010x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
1340{
1341
1342
1343 insn &= 0xfff00fff;
1344 insn |= 0x00001000;
1345 asi->insn[0] = insn;
1346 asi->insn_handler = (insn & (1 << 20)) ? emulate_mrrc : emulate_mcrr;
1347 return INSN_GOOD;
1348}
1349
1350static enum kprobe_insn __kprobes
1351space_cccc_110x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
1352{
1353
1354
1355 insn &= 0xfff0ffff;
1356 asi->insn[0] = insn;
1357 asi->insn_handler = emulate_ldcstc;
1358 return INSN_GOOD;
1359}
1360
1361static enum kprobe_insn __kprobes
1362space_cccc_111x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
1363{
1364
1365
1366 if ((insn & 0xfff000f0) == 0xe1200070 ||
1367 (insn & 0x0f000000) == 0x0f000000)
1368 return INSN_REJECTED;
1369
1370
1371 if ((insn & 0x0f000010) == 0x0e000000) {
1372 asi->insn[0] = insn;
1373 asi->insn_handler = emulate_none;
1374 return INSN_GOOD;
1375 }
1376
1377
1378
1379 insn &= 0xffff0fff;
1380 asi->insn[0] = insn;
1381 asi->insn_handler = (insn & (1 << 20)) ? emulate_rd12 : emulate_ird12;
1382 return INSN_GOOD;
1383}
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397enum kprobe_insn __kprobes
1398arm_kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi)
1399{
1400 asi->insn[1] = KPROBE_RETURN_INSTRUCTION;
1401
1402 if ((insn & 0xf0000000) == 0xf0000000) {
1403
1404 return space_1111(insn, asi);
1405
1406 } else if ((insn & 0x0e000000) == 0x00000000) {
1407
1408 return space_cccc_000x(insn, asi);
1409
1410 } else if ((insn & 0x0e000000) == 0x02000000) {
1411
1412 return space_cccc_001x(insn, asi);
1413
1414 } else if ((insn & 0x0f000010) == 0x06000010) {
1415
1416 return space_cccc_0110__1(insn, asi);
1417
1418 } else if ((insn & 0x0f000010) == 0x07000010) {
1419
1420 return space_cccc_0111__1(insn, asi);
1421
1422 } else if ((insn & 0x0c000000) == 0x04000000) {
1423
1424 return space_cccc_01xx(insn, asi);
1425
1426 } else if ((insn & 0x0e000000) == 0x08000000) {
1427
1428 return space_cccc_100x(insn, asi);
1429
1430 } else if ((insn & 0x0e000000) == 0x0a000000) {
1431
1432 return space_cccc_101x(insn, asi);
1433
1434 } else if ((insn & 0x0fe00000) == 0x0c400000) {
1435
1436 return space_cccc_1100_010x(insn, asi);
1437
1438 } else if ((insn & 0x0e000000) == 0x0c400000) {
1439
1440 return space_cccc_110x(insn, asi);
1441
1442 }
1443
1444 return space_cccc_111x(insn, asi);
1445}
1446
1447void __init arm_kprobe_decode_init(void)
1448{
1449 find_str_pc_offset();
1450}
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