actions-thumb.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671
  1. /*
  2. * arch/arm/probes/kprobes/actions-thumb.c
  3. *
  4. * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>.
  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. #include <linux/types.h>
  11. #include <linux/kernel.h>
  12. #include <linux/ptrace.h>
  13. #include <linux/kprobes.h>
  14. #include "../decode-thumb.h"
  15. #include "core.h"
  16. #include "checkers.h"
  17. /* These emulation encodings are functionally equivalent... */
  18. #define t32_emulate_rd8rn16rm0ra12_noflags \
  19. t32_emulate_rdlo12rdhi8rn16rm0_noflags
  20. /* t32 thumb actions */
  21. static void __kprobes
  22. t32_simulate_table_branch(probes_opcode_t insn,
  23. struct arch_probes_insn *asi, struct pt_regs *regs)
  24. {
  25. unsigned long pc = regs->ARM_pc;
  26. int rn = (insn >> 16) & 0xf;
  27. int rm = insn & 0xf;
  28. unsigned long rnv = (rn == 15) ? pc : regs->uregs[rn];
  29. unsigned long rmv = regs->uregs[rm];
  30. unsigned int halfwords;
  31. if (insn & 0x10) /* TBH */
  32. halfwords = ((u16 *)rnv)[rmv];
  33. else /* TBB */
  34. halfwords = ((u8 *)rnv)[rmv];
  35. regs->ARM_pc = pc + 2 * halfwords;
  36. }
  37. static void __kprobes
  38. t32_simulate_mrs(probes_opcode_t insn,
  39. struct arch_probes_insn *asi, struct pt_regs *regs)
  40. {
  41. int rd = (insn >> 8) & 0xf;
  42. unsigned long mask = 0xf8ff03df; /* Mask out execution state */
  43. regs->uregs[rd] = regs->ARM_cpsr & mask;
  44. }
  45. static void __kprobes
  46. t32_simulate_cond_branch(probes_opcode_t insn,
  47. struct arch_probes_insn *asi, struct pt_regs *regs)
  48. {
  49. unsigned long pc = regs->ARM_pc;
  50. long offset = insn & 0x7ff; /* imm11 */
  51. offset += (insn & 0x003f0000) >> 5; /* imm6 */
  52. offset += (insn & 0x00002000) << 4; /* J1 */
  53. offset += (insn & 0x00000800) << 7; /* J2 */
  54. offset -= (insn & 0x04000000) >> 7; /* Apply sign bit */
  55. regs->ARM_pc = pc + (offset * 2);
  56. }
  57. static enum probes_insn __kprobes
  58. t32_decode_cond_branch(probes_opcode_t insn, struct arch_probes_insn *asi,
  59. const struct decode_header *d)
  60. {
  61. int cc = (insn >> 22) & 0xf;
  62. asi->insn_check_cc = probes_condition_checks[cc];
  63. asi->insn_handler = t32_simulate_cond_branch;
  64. return INSN_GOOD_NO_SLOT;
  65. }
  66. static void __kprobes
  67. t32_simulate_branch(probes_opcode_t insn,
  68. struct arch_probes_insn *asi, struct pt_regs *regs)
  69. {
  70. unsigned long pc = regs->ARM_pc;
  71. long offset = insn & 0x7ff; /* imm11 */
  72. offset += (insn & 0x03ff0000) >> 5; /* imm10 */
  73. offset += (insn & 0x00002000) << 9; /* J1 */
  74. offset += (insn & 0x00000800) << 10; /* J2 */
  75. if (insn & 0x04000000)
  76. offset -= 0x00800000; /* Apply sign bit */
  77. else
  78. offset ^= 0x00600000; /* Invert J1 and J2 */
  79. if (insn & (1 << 14)) {
  80. /* BL or BLX */
  81. regs->ARM_lr = regs->ARM_pc | 1;
  82. if (!(insn & (1 << 12))) {
  83. /* BLX so switch to ARM mode */
  84. regs->ARM_cpsr &= ~PSR_T_BIT;
  85. pc &= ~3;
  86. }
  87. }
  88. regs->ARM_pc = pc + (offset * 2);
  89. }
  90. static void __kprobes
  91. t32_simulate_ldr_literal(probes_opcode_t insn,
  92. struct arch_probes_insn *asi, struct pt_regs *regs)
  93. {
  94. unsigned long addr = regs->ARM_pc & ~3;
  95. int rt = (insn >> 12) & 0xf;
  96. unsigned long rtv;
  97. long offset = insn & 0xfff;
  98. if (insn & 0x00800000)
  99. addr += offset;
  100. else
  101. addr -= offset;
  102. if (insn & 0x00400000) {
  103. /* LDR */
  104. rtv = *(unsigned long *)addr;
  105. if (rt == 15) {
  106. bx_write_pc(rtv, regs);
  107. return;
  108. }
  109. } else if (insn & 0x00200000) {
  110. /* LDRH */
  111. if (insn & 0x01000000)
  112. rtv = *(s16 *)addr;
  113. else
  114. rtv = *(u16 *)addr;
  115. } else {
  116. /* LDRB */
  117. if (insn & 0x01000000)
  118. rtv = *(s8 *)addr;
  119. else
  120. rtv = *(u8 *)addr;
  121. }
  122. regs->uregs[rt] = rtv;
  123. }
  124. static enum probes_insn __kprobes
  125. t32_decode_ldmstm(probes_opcode_t insn, struct arch_probes_insn *asi,
  126. const struct decode_header *d)
  127. {
  128. enum probes_insn ret = kprobe_decode_ldmstm(insn, asi, d);
  129. /* Fixup modified instruction to have halfwords in correct order...*/
  130. insn = __mem_to_opcode_arm(asi->insn[0]);
  131. ((u16 *)asi->insn)[0] = __opcode_to_mem_thumb16(insn >> 16);
  132. ((u16 *)asi->insn)[1] = __opcode_to_mem_thumb16(insn & 0xffff);
  133. return ret;
  134. }
  135. static void __kprobes
  136. t32_emulate_ldrdstrd(probes_opcode_t insn,
  137. struct arch_probes_insn *asi, struct pt_regs *regs)
  138. {
  139. unsigned long pc = regs->ARM_pc & ~3;
  140. int rt1 = (insn >> 12) & 0xf;
  141. int rt2 = (insn >> 8) & 0xf;
  142. int rn = (insn >> 16) & 0xf;
  143. register unsigned long rt1v asm("r0") = regs->uregs[rt1];
  144. register unsigned long rt2v asm("r1") = regs->uregs[rt2];
  145. register unsigned long rnv asm("r2") = (rn == 15) ? pc
  146. : regs->uregs[rn];
  147. __asm__ __volatile__ (
  148. "blx %[fn]"
  149. : "=r" (rt1v), "=r" (rt2v), "=r" (rnv)
  150. : "0" (rt1v), "1" (rt2v), "2" (rnv), [fn] "r" (asi->insn_fn)
  151. : "lr", "memory", "cc"
  152. );
  153. if (rn != 15)
  154. regs->uregs[rn] = rnv; /* Writeback base register */
  155. regs->uregs[rt1] = rt1v;
  156. regs->uregs[rt2] = rt2v;
  157. }
  158. static void __kprobes
  159. t32_emulate_ldrstr(probes_opcode_t insn,
  160. struct arch_probes_insn *asi, struct pt_regs *regs)
  161. {
  162. int rt = (insn >> 12) & 0xf;
  163. int rn = (insn >> 16) & 0xf;
  164. int rm = insn & 0xf;
  165. register unsigned long rtv asm("r0") = regs->uregs[rt];
  166. register unsigned long rnv asm("r2") = regs->uregs[rn];
  167. register unsigned long rmv asm("r3") = regs->uregs[rm];
  168. __asm__ __volatile__ (
  169. "blx %[fn]"
  170. : "=r" (rtv), "=r" (rnv)
  171. : "0" (rtv), "1" (rnv), "r" (rmv), [fn] "r" (asi->insn_fn)
  172. : "lr", "memory", "cc"
  173. );
  174. regs->uregs[rn] = rnv; /* Writeback base register */
  175. if (rt == 15) /* Can't be true for a STR as they aren't allowed */
  176. bx_write_pc(rtv, regs);
  177. else
  178. regs->uregs[rt] = rtv;
  179. }
  180. static void __kprobes
  181. t32_emulate_rd8rn16rm0_rwflags(probes_opcode_t insn,
  182. struct arch_probes_insn *asi, struct pt_regs *regs)
  183. {
  184. int rd = (insn >> 8) & 0xf;
  185. int rn = (insn >> 16) & 0xf;
  186. int rm = insn & 0xf;
  187. register unsigned long rdv asm("r1") = regs->uregs[rd];
  188. register unsigned long rnv asm("r2") = regs->uregs[rn];
  189. register unsigned long rmv asm("r3") = regs->uregs[rm];
  190. unsigned long cpsr = regs->ARM_cpsr;
  191. __asm__ __volatile__ (
  192. "msr cpsr_fs, %[cpsr] \n\t"
  193. "blx %[fn] \n\t"
  194. "mrs %[cpsr], cpsr \n\t"
  195. : "=r" (rdv), [cpsr] "=r" (cpsr)
  196. : "0" (rdv), "r" (rnv), "r" (rmv),
  197. "1" (cpsr), [fn] "r" (asi->insn_fn)
  198. : "lr", "memory", "cc"
  199. );
  200. regs->uregs[rd] = rdv;
  201. regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK);
  202. }
  203. static void __kprobes
  204. t32_emulate_rd8pc16_noflags(probes_opcode_t insn,
  205. struct arch_probes_insn *asi, struct pt_regs *regs)
  206. {
  207. unsigned long pc = regs->ARM_pc;
  208. int rd = (insn >> 8) & 0xf;
  209. register unsigned long rdv asm("r1") = regs->uregs[rd];
  210. register unsigned long rnv asm("r2") = pc & ~3;
  211. __asm__ __volatile__ (
  212. "blx %[fn]"
  213. : "=r" (rdv)
  214. : "0" (rdv), "r" (rnv), [fn] "r" (asi->insn_fn)
  215. : "lr", "memory", "cc"
  216. );
  217. regs->uregs[rd] = rdv;
  218. }
  219. static void __kprobes
  220. t32_emulate_rd8rn16_noflags(probes_opcode_t insn,
  221. struct arch_probes_insn *asi, struct pt_regs *regs)
  222. {
  223. int rd = (insn >> 8) & 0xf;
  224. int rn = (insn >> 16) & 0xf;
  225. register unsigned long rdv asm("r1") = regs->uregs[rd];
  226. register unsigned long rnv asm("r2") = regs->uregs[rn];
  227. __asm__ __volatile__ (
  228. "blx %[fn]"
  229. : "=r" (rdv)
  230. : "0" (rdv), "r" (rnv), [fn] "r" (asi->insn_fn)
  231. : "lr", "memory", "cc"
  232. );
  233. regs->uregs[rd] = rdv;
  234. }
  235. static void __kprobes
  236. t32_emulate_rdlo12rdhi8rn16rm0_noflags(probes_opcode_t insn,
  237. struct arch_probes_insn *asi,
  238. struct pt_regs *regs)
  239. {
  240. int rdlo = (insn >> 12) & 0xf;
  241. int rdhi = (insn >> 8) & 0xf;
  242. int rn = (insn >> 16) & 0xf;
  243. int rm = insn & 0xf;
  244. register unsigned long rdlov asm("r0") = regs->uregs[rdlo];
  245. register unsigned long rdhiv asm("r1") = regs->uregs[rdhi];
  246. register unsigned long rnv asm("r2") = regs->uregs[rn];
  247. register unsigned long rmv asm("r3") = regs->uregs[rm];
  248. __asm__ __volatile__ (
  249. "blx %[fn]"
  250. : "=r" (rdlov), "=r" (rdhiv)
  251. : "0" (rdlov), "1" (rdhiv), "r" (rnv), "r" (rmv),
  252. [fn] "r" (asi->insn_fn)
  253. : "lr", "memory", "cc"
  254. );
  255. regs->uregs[rdlo] = rdlov;
  256. regs->uregs[rdhi] = rdhiv;
  257. }
  258. /* t16 thumb actions */
  259. static void __kprobes
  260. t16_simulate_bxblx(probes_opcode_t insn,
  261. struct arch_probes_insn *asi, struct pt_regs *regs)
  262. {
  263. unsigned long pc = regs->ARM_pc + 2;
  264. int rm = (insn >> 3) & 0xf;
  265. unsigned long rmv = (rm == 15) ? pc : regs->uregs[rm];
  266. if (insn & (1 << 7)) /* BLX ? */
  267. regs->ARM_lr = regs->ARM_pc | 1;
  268. bx_write_pc(rmv, regs);
  269. }
  270. static void __kprobes
  271. t16_simulate_ldr_literal(probes_opcode_t insn,
  272. struct arch_probes_insn *asi, struct pt_regs *regs)
  273. {
  274. unsigned long *base = (unsigned long *)((regs->ARM_pc + 2) & ~3);
  275. long index = insn & 0xff;
  276. int rt = (insn >> 8) & 0x7;
  277. regs->uregs[rt] = base[index];
  278. }
  279. static void __kprobes
  280. t16_simulate_ldrstr_sp_relative(probes_opcode_t insn,
  281. struct arch_probes_insn *asi, struct pt_regs *regs)
  282. {
  283. unsigned long* base = (unsigned long *)regs->ARM_sp;
  284. long index = insn & 0xff;
  285. int rt = (insn >> 8) & 0x7;
  286. if (insn & 0x800) /* LDR */
  287. regs->uregs[rt] = base[index];
  288. else /* STR */
  289. base[index] = regs->uregs[rt];
  290. }
  291. static void __kprobes
  292. t16_simulate_reladr(probes_opcode_t insn,
  293. struct arch_probes_insn *asi, struct pt_regs *regs)
  294. {
  295. unsigned long base = (insn & 0x800) ? regs->ARM_sp
  296. : ((regs->ARM_pc + 2) & ~3);
  297. long offset = insn & 0xff;
  298. int rt = (insn >> 8) & 0x7;
  299. regs->uregs[rt] = base + offset * 4;
  300. }
  301. static void __kprobes
  302. t16_simulate_add_sp_imm(probes_opcode_t insn,
  303. struct arch_probes_insn *asi, struct pt_regs *regs)
  304. {
  305. long imm = insn & 0x7f;
  306. if (insn & 0x80) /* SUB */
  307. regs->ARM_sp -= imm * 4;
  308. else /* ADD */
  309. regs->ARM_sp += imm * 4;
  310. }
  311. static void __kprobes
  312. t16_simulate_cbz(probes_opcode_t insn,
  313. struct arch_probes_insn *asi, struct pt_regs *regs)
  314. {
  315. int rn = insn & 0x7;
  316. probes_opcode_t nonzero = regs->uregs[rn] ? insn : ~insn;
  317. if (nonzero & 0x800) {
  318. long i = insn & 0x200;
  319. long imm5 = insn & 0xf8;
  320. unsigned long pc = regs->ARM_pc + 2;
  321. regs->ARM_pc = pc + (i >> 3) + (imm5 >> 2);
  322. }
  323. }
  324. static void __kprobes
  325. t16_simulate_it(probes_opcode_t insn,
  326. struct arch_probes_insn *asi, struct pt_regs *regs)
  327. {
  328. /*
  329. * The 8 IT state bits are split into two parts in CPSR:
  330. * ITSTATE<1:0> are in CPSR<26:25>
  331. * ITSTATE<7:2> are in CPSR<15:10>
  332. * The new IT state is in the lower byte of insn.
  333. */
  334. unsigned long cpsr = regs->ARM_cpsr;
  335. cpsr &= ~PSR_IT_MASK;
  336. cpsr |= (insn & 0xfc) << 8;
  337. cpsr |= (insn & 0x03) << 25;
  338. regs->ARM_cpsr = cpsr;
  339. }
  340. static void __kprobes
  341. t16_singlestep_it(probes_opcode_t insn,
  342. struct arch_probes_insn *asi, struct pt_regs *regs)
  343. {
  344. regs->ARM_pc += 2;
  345. t16_simulate_it(insn, asi, regs);
  346. }
  347. static enum probes_insn __kprobes
  348. t16_decode_it(probes_opcode_t insn, struct arch_probes_insn *asi,
  349. const struct decode_header *d)
  350. {
  351. asi->insn_singlestep = t16_singlestep_it;
  352. return INSN_GOOD_NO_SLOT;
  353. }
  354. static void __kprobes
  355. t16_simulate_cond_branch(probes_opcode_t insn,
  356. struct arch_probes_insn *asi, struct pt_regs *regs)
  357. {
  358. unsigned long pc = regs->ARM_pc + 2;
  359. long offset = insn & 0x7f;
  360. offset -= insn & 0x80; /* Apply sign bit */
  361. regs->ARM_pc = pc + (offset * 2);
  362. }
  363. static enum probes_insn __kprobes
  364. t16_decode_cond_branch(probes_opcode_t insn, struct arch_probes_insn *asi,
  365. const struct decode_header *d)
  366. {
  367. int cc = (insn >> 8) & 0xf;
  368. asi->insn_check_cc = probes_condition_checks[cc];
  369. asi->insn_handler = t16_simulate_cond_branch;
  370. return INSN_GOOD_NO_SLOT;
  371. }
  372. static void __kprobes
  373. t16_simulate_branch(probes_opcode_t insn,
  374. struct arch_probes_insn *asi, struct pt_regs *regs)
  375. {
  376. unsigned long pc = regs->ARM_pc + 2;
  377. long offset = insn & 0x3ff;
  378. offset -= insn & 0x400; /* Apply sign bit */
  379. regs->ARM_pc = pc + (offset * 2);
  380. }
  381. static unsigned long __kprobes
  382. t16_emulate_loregs(probes_opcode_t insn,
  383. struct arch_probes_insn *asi, struct pt_regs *regs)
  384. {
  385. unsigned long oldcpsr = regs->ARM_cpsr;
  386. unsigned long newcpsr;
  387. __asm__ __volatile__ (
  388. "msr cpsr_fs, %[oldcpsr] \n\t"
  389. "ldmia %[regs], {r0-r7} \n\t"
  390. "blx %[fn] \n\t"
  391. "stmia %[regs], {r0-r7} \n\t"
  392. "mrs %[newcpsr], cpsr \n\t"
  393. : [newcpsr] "=r" (newcpsr)
  394. : [oldcpsr] "r" (oldcpsr), [regs] "r" (regs),
  395. [fn] "r" (asi->insn_fn)
  396. : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
  397. "lr", "memory", "cc"
  398. );
  399. return (oldcpsr & ~APSR_MASK) | (newcpsr & APSR_MASK);
  400. }
  401. static void __kprobes
  402. t16_emulate_loregs_rwflags(probes_opcode_t insn,
  403. struct arch_probes_insn *asi, struct pt_regs *regs)
  404. {
  405. regs->ARM_cpsr = t16_emulate_loregs(insn, asi, regs);
  406. }
  407. static void __kprobes
  408. t16_emulate_loregs_noitrwflags(probes_opcode_t insn,
  409. struct arch_probes_insn *asi, struct pt_regs *regs)
  410. {
  411. unsigned long cpsr = t16_emulate_loregs(insn, asi, regs);
  412. if (!in_it_block(cpsr))
  413. regs->ARM_cpsr = cpsr;
  414. }
  415. static void __kprobes
  416. t16_emulate_hiregs(probes_opcode_t insn,
  417. struct arch_probes_insn *asi, struct pt_regs *regs)
  418. {
  419. unsigned long pc = regs->ARM_pc + 2;
  420. int rdn = (insn & 0x7) | ((insn & 0x80) >> 4);
  421. int rm = (insn >> 3) & 0xf;
  422. register unsigned long rdnv asm("r1");
  423. register unsigned long rmv asm("r0");
  424. unsigned long cpsr = regs->ARM_cpsr;
  425. rdnv = (rdn == 15) ? pc : regs->uregs[rdn];
  426. rmv = (rm == 15) ? pc : regs->uregs[rm];
  427. __asm__ __volatile__ (
  428. "msr cpsr_fs, %[cpsr] \n\t"
  429. "blx %[fn] \n\t"
  430. "mrs %[cpsr], cpsr \n\t"
  431. : "=r" (rdnv), [cpsr] "=r" (cpsr)
  432. : "0" (rdnv), "r" (rmv), "1" (cpsr), [fn] "r" (asi->insn_fn)
  433. : "lr", "memory", "cc"
  434. );
  435. if (rdn == 15)
  436. rdnv &= ~1;
  437. regs->uregs[rdn] = rdnv;
  438. regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK);
  439. }
  440. static enum probes_insn __kprobes
  441. t16_decode_hiregs(probes_opcode_t insn, struct arch_probes_insn *asi,
  442. const struct decode_header *d)
  443. {
  444. insn &= ~0x00ff;
  445. insn |= 0x001; /* Set Rdn = R1 and Rm = R0 */
  446. ((u16 *)asi->insn)[0] = __opcode_to_mem_thumb16(insn);
  447. asi->insn_handler = t16_emulate_hiregs;
  448. return INSN_GOOD;
  449. }
  450. static void __kprobes
  451. t16_emulate_push(probes_opcode_t insn,
  452. struct arch_probes_insn *asi, struct pt_regs *regs)
  453. {
  454. __asm__ __volatile__ (
  455. "ldr r9, [%[regs], #13*4] \n\t"
  456. "ldr r8, [%[regs], #14*4] \n\t"
  457. "ldmia %[regs], {r0-r7} \n\t"
  458. "blx %[fn] \n\t"
  459. "str r9, [%[regs], #13*4] \n\t"
  460. :
  461. : [regs] "r" (regs), [fn] "r" (asi->insn_fn)
  462. : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9",
  463. "lr", "memory", "cc"
  464. );
  465. }
  466. static enum probes_insn __kprobes
  467. t16_decode_push(probes_opcode_t insn, struct arch_probes_insn *asi,
  468. const struct decode_header *d)
  469. {
  470. /*
  471. * To simulate a PUSH we use a Thumb-2 "STMDB R9!, {registers}"
  472. * and call it with R9=SP and LR in the register list represented
  473. * by R8.
  474. */
  475. /* 1st half STMDB R9!,{} */
  476. ((u16 *)asi->insn)[0] = __opcode_to_mem_thumb16(0xe929);
  477. /* 2nd half (register list) */
  478. ((u16 *)asi->insn)[1] = __opcode_to_mem_thumb16(insn & 0x1ff);
  479. asi->insn_handler = t16_emulate_push;
  480. return INSN_GOOD;
  481. }
  482. static void __kprobes
  483. t16_emulate_pop_nopc(probes_opcode_t insn,
  484. struct arch_probes_insn *asi, struct pt_regs *regs)
  485. {
  486. __asm__ __volatile__ (
  487. "ldr r9, [%[regs], #13*4] \n\t"
  488. "ldmia %[regs], {r0-r7} \n\t"
  489. "blx %[fn] \n\t"
  490. "stmia %[regs], {r0-r7} \n\t"
  491. "str r9, [%[regs], #13*4] \n\t"
  492. :
  493. : [regs] "r" (regs), [fn] "r" (asi->insn_fn)
  494. : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r9",
  495. "lr", "memory", "cc"
  496. );
  497. }
  498. static void __kprobes
  499. t16_emulate_pop_pc(probes_opcode_t insn,
  500. struct arch_probes_insn *asi, struct pt_regs *regs)
  501. {
  502. register unsigned long pc asm("r8");
  503. __asm__ __volatile__ (
  504. "ldr r9, [%[regs], #13*4] \n\t"
  505. "ldmia %[regs], {r0-r7} \n\t"
  506. "blx %[fn] \n\t"
  507. "stmia %[regs], {r0-r7} \n\t"
  508. "str r9, [%[regs], #13*4] \n\t"
  509. : "=r" (pc)
  510. : [regs] "r" (regs), [fn] "r" (asi->insn_fn)
  511. : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r9",
  512. "lr", "memory", "cc"
  513. );
  514. bx_write_pc(pc, regs);
  515. }
  516. static enum probes_insn __kprobes
  517. t16_decode_pop(probes_opcode_t insn, struct arch_probes_insn *asi,
  518. const struct decode_header *d)
  519. {
  520. /*
  521. * To simulate a POP we use a Thumb-2 "LDMDB R9!, {registers}"
  522. * and call it with R9=SP and PC in the register list represented
  523. * by R8.
  524. */
  525. /* 1st half LDMIA R9!,{} */
  526. ((u16 *)asi->insn)[0] = __opcode_to_mem_thumb16(0xe8b9);
  527. /* 2nd half (register list) */
  528. ((u16 *)asi->insn)[1] = __opcode_to_mem_thumb16(insn & 0x1ff);
  529. asi->insn_handler = insn & 0x100 ? t16_emulate_pop_pc
  530. : t16_emulate_pop_nopc;
  531. return INSN_GOOD;
  532. }
  533. const union decode_action kprobes_t16_actions[NUM_PROBES_T16_ACTIONS] = {
  534. [PROBES_T16_ADD_SP] = {.handler = t16_simulate_add_sp_imm},
  535. [PROBES_T16_CBZ] = {.handler = t16_simulate_cbz},
  536. [PROBES_T16_SIGN_EXTEND] = {.handler = t16_emulate_loregs_rwflags},
  537. [PROBES_T16_PUSH] = {.decoder = t16_decode_push},
  538. [PROBES_T16_POP] = {.decoder = t16_decode_pop},
  539. [PROBES_T16_SEV] = {.handler = probes_emulate_none},
  540. [PROBES_T16_WFE] = {.handler = probes_simulate_nop},
  541. [PROBES_T16_IT] = {.decoder = t16_decode_it},
  542. [PROBES_T16_CMP] = {.handler = t16_emulate_loregs_rwflags},
  543. [PROBES_T16_ADDSUB] = {.handler = t16_emulate_loregs_noitrwflags},
  544. [PROBES_T16_LOGICAL] = {.handler = t16_emulate_loregs_noitrwflags},
  545. [PROBES_T16_LDR_LIT] = {.handler = t16_simulate_ldr_literal},
  546. [PROBES_T16_BLX] = {.handler = t16_simulate_bxblx},
  547. [PROBES_T16_HIREGOPS] = {.decoder = t16_decode_hiregs},
  548. [PROBES_T16_LDRHSTRH] = {.handler = t16_emulate_loregs_rwflags},
  549. [PROBES_T16_LDRSTR] = {.handler = t16_simulate_ldrstr_sp_relative},
  550. [PROBES_T16_ADR] = {.handler = t16_simulate_reladr},
  551. [PROBES_T16_LDMSTM] = {.handler = t16_emulate_loregs_rwflags},
  552. [PROBES_T16_BRANCH_COND] = {.decoder = t16_decode_cond_branch},
  553. [PROBES_T16_BRANCH] = {.handler = t16_simulate_branch},
  554. };
  555. const union decode_action kprobes_t32_actions[NUM_PROBES_T32_ACTIONS] = {
  556. [PROBES_T32_LDMSTM] = {.decoder = t32_decode_ldmstm},
  557. [PROBES_T32_LDRDSTRD] = {.handler = t32_emulate_ldrdstrd},
  558. [PROBES_T32_TABLE_BRANCH] = {.handler = t32_simulate_table_branch},
  559. [PROBES_T32_TST] = {.handler = t32_emulate_rd8rn16rm0_rwflags},
  560. [PROBES_T32_MOV] = {.handler = t32_emulate_rd8rn16rm0_rwflags},
  561. [PROBES_T32_ADDSUB] = {.handler = t32_emulate_rd8rn16rm0_rwflags},
  562. [PROBES_T32_LOGICAL] = {.handler = t32_emulate_rd8rn16rm0_rwflags},
  563. [PROBES_T32_CMP] = {.handler = t32_emulate_rd8rn16rm0_rwflags},
  564. [PROBES_T32_ADDWSUBW_PC] = {.handler = t32_emulate_rd8pc16_noflags,},
  565. [PROBES_T32_ADDWSUBW] = {.handler = t32_emulate_rd8rn16_noflags},
  566. [PROBES_T32_MOVW] = {.handler = t32_emulate_rd8rn16_noflags},
  567. [PROBES_T32_SAT] = {.handler = t32_emulate_rd8rn16rm0_rwflags},
  568. [PROBES_T32_BITFIELD] = {.handler = t32_emulate_rd8rn16_noflags},
  569. [PROBES_T32_SEV] = {.handler = probes_emulate_none},
  570. [PROBES_T32_WFE] = {.handler = probes_simulate_nop},
  571. [PROBES_T32_MRS] = {.handler = t32_simulate_mrs},
  572. [PROBES_T32_BRANCH_COND] = {.decoder = t32_decode_cond_branch},
  573. [PROBES_T32_BRANCH] = {.handler = t32_simulate_branch},
  574. [PROBES_T32_PLDI] = {.handler = probes_simulate_nop},
  575. [PROBES_T32_LDR_LIT] = {.handler = t32_simulate_ldr_literal},
  576. [PROBES_T32_LDRSTR] = {.handler = t32_emulate_ldrstr},
  577. [PROBES_T32_SIGN_EXTEND] = {.handler = t32_emulate_rd8rn16rm0_rwflags},
  578. [PROBES_T32_MEDIA] = {.handler = t32_emulate_rd8rn16rm0_rwflags},
  579. [PROBES_T32_REVERSE] = {.handler = t32_emulate_rd8rn16_noflags},
  580. [PROBES_T32_MUL_ADD] = {.handler = t32_emulate_rd8rn16rm0_rwflags},
  581. [PROBES_T32_MUL_ADD2] = {.handler = t32_emulate_rd8rn16rm0ra12_noflags},
  582. [PROBES_T32_MUL_ADD_LONG] = {
  583. .handler = t32_emulate_rdlo12rdhi8rn16rm0_noflags},
  584. };
  585. const struct decode_checker *kprobes_t32_checkers[] = {t32_stack_checker, NULL};
  586. const struct decode_checker *kprobes_t16_checkers[] = {t16_stack_checker, NULL};