18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * arch/arm/probes/kprobes/actions-arm.c 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2006, 2007 Motorola Inc. 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci/* 98c2ecf20Sopenharmony_ci * We do not have hardware single-stepping on ARM, This 108c2ecf20Sopenharmony_ci * effort is further complicated by the ARM not having a 118c2ecf20Sopenharmony_ci * "next PC" register. Instructions that change the PC 128c2ecf20Sopenharmony_ci * can't be safely single-stepped in a MP environment, so 138c2ecf20Sopenharmony_ci * we have a lot of work to do: 148c2ecf20Sopenharmony_ci * 158c2ecf20Sopenharmony_ci * In the prepare phase: 168c2ecf20Sopenharmony_ci * *) If it is an instruction that does anything 178c2ecf20Sopenharmony_ci * with the CPU mode, we reject it for a kprobe. 188c2ecf20Sopenharmony_ci * (This is out of laziness rather than need. The 198c2ecf20Sopenharmony_ci * instructions could be simulated.) 208c2ecf20Sopenharmony_ci * 218c2ecf20Sopenharmony_ci * *) Otherwise, decode the instruction rewriting its 228c2ecf20Sopenharmony_ci * registers to take fixed, ordered registers and 238c2ecf20Sopenharmony_ci * setting a handler for it to run the instruction. 248c2ecf20Sopenharmony_ci * 258c2ecf20Sopenharmony_ci * In the execution phase by an instruction's handler: 268c2ecf20Sopenharmony_ci * 278c2ecf20Sopenharmony_ci * *) If the PC is written to by the instruction, the 288c2ecf20Sopenharmony_ci * instruction must be fully simulated in software. 298c2ecf20Sopenharmony_ci * 308c2ecf20Sopenharmony_ci * *) Otherwise, a modified form of the instruction is 318c2ecf20Sopenharmony_ci * directly executed. Its handler calls the 328c2ecf20Sopenharmony_ci * instruction in insn[0]. In insn[1] is a 338c2ecf20Sopenharmony_ci * "mov pc, lr" to return. 348c2ecf20Sopenharmony_ci * 358c2ecf20Sopenharmony_ci * Before calling, load up the reordered registers 368c2ecf20Sopenharmony_ci * from the original instruction's registers. If one 378c2ecf20Sopenharmony_ci * of the original input registers is the PC, compute 388c2ecf20Sopenharmony_ci * and adjust the appropriate input register. 398c2ecf20Sopenharmony_ci * 408c2ecf20Sopenharmony_ci * After call completes, copy the output registers to 418c2ecf20Sopenharmony_ci * the original instruction's original registers. 428c2ecf20Sopenharmony_ci * 438c2ecf20Sopenharmony_ci * We don't use a real breakpoint instruction since that 448c2ecf20Sopenharmony_ci * would have us in the kernel go from SVC mode to SVC 458c2ecf20Sopenharmony_ci * mode losing the link register. Instead we use an 468c2ecf20Sopenharmony_ci * undefined instruction. To simplify processing, the 478c2ecf20Sopenharmony_ci * undefined instruction used for kprobes must be reserved 488c2ecf20Sopenharmony_ci * exclusively for kprobes use. 498c2ecf20Sopenharmony_ci * 508c2ecf20Sopenharmony_ci * TODO: ifdef out some instruction decoding based on architecture. 518c2ecf20Sopenharmony_ci */ 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci#include <linux/kernel.h> 548c2ecf20Sopenharmony_ci#include <linux/kprobes.h> 558c2ecf20Sopenharmony_ci#include <linux/ptrace.h> 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ci#include "../decode-arm.h" 588c2ecf20Sopenharmony_ci#include "core.h" 598c2ecf20Sopenharmony_ci#include "checkers.h" 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci#if __LINUX_ARM_ARCH__ >= 6 628c2ecf20Sopenharmony_ci#define BLX(reg) "blx "reg" \n\t" 638c2ecf20Sopenharmony_ci#else 648c2ecf20Sopenharmony_ci#define BLX(reg) "mov lr, pc \n\t" \ 658c2ecf20Sopenharmony_ci "mov pc, "reg" \n\t" 668c2ecf20Sopenharmony_ci#endif 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_cistatic void __kprobes 698c2ecf20Sopenharmony_ciemulate_ldrdstrd(probes_opcode_t insn, 708c2ecf20Sopenharmony_ci struct arch_probes_insn *asi, struct pt_regs *regs) 718c2ecf20Sopenharmony_ci{ 728c2ecf20Sopenharmony_ci unsigned long pc = regs->ARM_pc + 4; 738c2ecf20Sopenharmony_ci int rt = (insn >> 12) & 0xf; 748c2ecf20Sopenharmony_ci int rn = (insn >> 16) & 0xf; 758c2ecf20Sopenharmony_ci int rm = insn & 0xf; 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci register unsigned long rtv asm("r0") = regs->uregs[rt]; 788c2ecf20Sopenharmony_ci register unsigned long rt2v asm("r1") = regs->uregs[rt+1]; 798c2ecf20Sopenharmony_ci register unsigned long rnv asm("r2") = (rn == 15) ? pc 808c2ecf20Sopenharmony_ci : regs->uregs[rn]; 818c2ecf20Sopenharmony_ci register unsigned long rmv asm("r3") = regs->uregs[rm]; 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci __asm__ __volatile__ ( 848c2ecf20Sopenharmony_ci BLX("%[fn]") 858c2ecf20Sopenharmony_ci : "=r" (rtv), "=r" (rt2v), "=r" (rnv) 868c2ecf20Sopenharmony_ci : "0" (rtv), "1" (rt2v), "2" (rnv), "r" (rmv), 878c2ecf20Sopenharmony_ci [fn] "r" (asi->insn_fn) 888c2ecf20Sopenharmony_ci : "lr", "memory", "cc" 898c2ecf20Sopenharmony_ci ); 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci regs->uregs[rt] = rtv; 928c2ecf20Sopenharmony_ci regs->uregs[rt+1] = rt2v; 938c2ecf20Sopenharmony_ci if (is_writeback(insn)) 948c2ecf20Sopenharmony_ci regs->uregs[rn] = rnv; 958c2ecf20Sopenharmony_ci} 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_cistatic void __kprobes 988c2ecf20Sopenharmony_ciemulate_ldr(probes_opcode_t insn, 998c2ecf20Sopenharmony_ci struct arch_probes_insn *asi, struct pt_regs *regs) 1008c2ecf20Sopenharmony_ci{ 1018c2ecf20Sopenharmony_ci unsigned long pc = regs->ARM_pc + 4; 1028c2ecf20Sopenharmony_ci int rt = (insn >> 12) & 0xf; 1038c2ecf20Sopenharmony_ci int rn = (insn >> 16) & 0xf; 1048c2ecf20Sopenharmony_ci int rm = insn & 0xf; 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci register unsigned long rtv asm("r0"); 1078c2ecf20Sopenharmony_ci register unsigned long rnv asm("r2") = (rn == 15) ? pc 1088c2ecf20Sopenharmony_ci : regs->uregs[rn]; 1098c2ecf20Sopenharmony_ci register unsigned long rmv asm("r3") = regs->uregs[rm]; 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ci __asm__ __volatile__ ( 1128c2ecf20Sopenharmony_ci BLX("%[fn]") 1138c2ecf20Sopenharmony_ci : "=r" (rtv), "=r" (rnv) 1148c2ecf20Sopenharmony_ci : "1" (rnv), "r" (rmv), [fn] "r" (asi->insn_fn) 1158c2ecf20Sopenharmony_ci : "lr", "memory", "cc" 1168c2ecf20Sopenharmony_ci ); 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci if (rt == 15) 1198c2ecf20Sopenharmony_ci load_write_pc(rtv, regs); 1208c2ecf20Sopenharmony_ci else 1218c2ecf20Sopenharmony_ci regs->uregs[rt] = rtv; 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ci if (is_writeback(insn)) 1248c2ecf20Sopenharmony_ci regs->uregs[rn] = rnv; 1258c2ecf20Sopenharmony_ci} 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_cistatic void __kprobes 1288c2ecf20Sopenharmony_ciemulate_str(probes_opcode_t insn, 1298c2ecf20Sopenharmony_ci struct arch_probes_insn *asi, struct pt_regs *regs) 1308c2ecf20Sopenharmony_ci{ 1318c2ecf20Sopenharmony_ci unsigned long rtpc = regs->ARM_pc - 4 + str_pc_offset; 1328c2ecf20Sopenharmony_ci unsigned long rnpc = regs->ARM_pc + 4; 1338c2ecf20Sopenharmony_ci int rt = (insn >> 12) & 0xf; 1348c2ecf20Sopenharmony_ci int rn = (insn >> 16) & 0xf; 1358c2ecf20Sopenharmony_ci int rm = insn & 0xf; 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci register unsigned long rtv asm("r0") = (rt == 15) ? rtpc 1388c2ecf20Sopenharmony_ci : regs->uregs[rt]; 1398c2ecf20Sopenharmony_ci register unsigned long rnv asm("r2") = (rn == 15) ? rnpc 1408c2ecf20Sopenharmony_ci : regs->uregs[rn]; 1418c2ecf20Sopenharmony_ci register unsigned long rmv asm("r3") = regs->uregs[rm]; 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci __asm__ __volatile__ ( 1448c2ecf20Sopenharmony_ci BLX("%[fn]") 1458c2ecf20Sopenharmony_ci : "=r" (rnv) 1468c2ecf20Sopenharmony_ci : "r" (rtv), "0" (rnv), "r" (rmv), [fn] "r" (asi->insn_fn) 1478c2ecf20Sopenharmony_ci : "lr", "memory", "cc" 1488c2ecf20Sopenharmony_ci ); 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci if (is_writeback(insn)) 1518c2ecf20Sopenharmony_ci regs->uregs[rn] = rnv; 1528c2ecf20Sopenharmony_ci} 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_cistatic void __kprobes 1558c2ecf20Sopenharmony_ciemulate_rd12rn16rm0rs8_rwflags(probes_opcode_t insn, 1568c2ecf20Sopenharmony_ci struct arch_probes_insn *asi, struct pt_regs *regs) 1578c2ecf20Sopenharmony_ci{ 1588c2ecf20Sopenharmony_ci unsigned long pc = regs->ARM_pc + 4; 1598c2ecf20Sopenharmony_ci int rd = (insn >> 12) & 0xf; 1608c2ecf20Sopenharmony_ci int rn = (insn >> 16) & 0xf; 1618c2ecf20Sopenharmony_ci int rm = insn & 0xf; 1628c2ecf20Sopenharmony_ci int rs = (insn >> 8) & 0xf; 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_ci register unsigned long rdv asm("r0") = regs->uregs[rd]; 1658c2ecf20Sopenharmony_ci register unsigned long rnv asm("r2") = (rn == 15) ? pc 1668c2ecf20Sopenharmony_ci : regs->uregs[rn]; 1678c2ecf20Sopenharmony_ci register unsigned long rmv asm("r3") = (rm == 15) ? pc 1688c2ecf20Sopenharmony_ci : regs->uregs[rm]; 1698c2ecf20Sopenharmony_ci register unsigned long rsv asm("r1") = regs->uregs[rs]; 1708c2ecf20Sopenharmony_ci unsigned long cpsr = regs->ARM_cpsr; 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_ci __asm__ __volatile__ ( 1738c2ecf20Sopenharmony_ci "msr cpsr_fs, %[cpsr] \n\t" 1748c2ecf20Sopenharmony_ci BLX("%[fn]") 1758c2ecf20Sopenharmony_ci "mrs %[cpsr], cpsr \n\t" 1768c2ecf20Sopenharmony_ci : "=r" (rdv), [cpsr] "=r" (cpsr) 1778c2ecf20Sopenharmony_ci : "0" (rdv), "r" (rnv), "r" (rmv), "r" (rsv), 1788c2ecf20Sopenharmony_ci "1" (cpsr), [fn] "r" (asi->insn_fn) 1798c2ecf20Sopenharmony_ci : "lr", "memory", "cc" 1808c2ecf20Sopenharmony_ci ); 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_ci if (rd == 15) 1838c2ecf20Sopenharmony_ci alu_write_pc(rdv, regs); 1848c2ecf20Sopenharmony_ci else 1858c2ecf20Sopenharmony_ci regs->uregs[rd] = rdv; 1868c2ecf20Sopenharmony_ci regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK); 1878c2ecf20Sopenharmony_ci} 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_cistatic void __kprobes 1908c2ecf20Sopenharmony_ciemulate_rd12rn16rm0_rwflags_nopc(probes_opcode_t insn, 1918c2ecf20Sopenharmony_ci struct arch_probes_insn *asi, struct pt_regs *regs) 1928c2ecf20Sopenharmony_ci{ 1938c2ecf20Sopenharmony_ci int rd = (insn >> 12) & 0xf; 1948c2ecf20Sopenharmony_ci int rn = (insn >> 16) & 0xf; 1958c2ecf20Sopenharmony_ci int rm = insn & 0xf; 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_ci register unsigned long rdv asm("r0") = regs->uregs[rd]; 1988c2ecf20Sopenharmony_ci register unsigned long rnv asm("r2") = regs->uregs[rn]; 1998c2ecf20Sopenharmony_ci register unsigned long rmv asm("r3") = regs->uregs[rm]; 2008c2ecf20Sopenharmony_ci unsigned long cpsr = regs->ARM_cpsr; 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_ci __asm__ __volatile__ ( 2038c2ecf20Sopenharmony_ci "msr cpsr_fs, %[cpsr] \n\t" 2048c2ecf20Sopenharmony_ci BLX("%[fn]") 2058c2ecf20Sopenharmony_ci "mrs %[cpsr], cpsr \n\t" 2068c2ecf20Sopenharmony_ci : "=r" (rdv), [cpsr] "=r" (cpsr) 2078c2ecf20Sopenharmony_ci : "0" (rdv), "r" (rnv), "r" (rmv), 2088c2ecf20Sopenharmony_ci "1" (cpsr), [fn] "r" (asi->insn_fn) 2098c2ecf20Sopenharmony_ci : "lr", "memory", "cc" 2108c2ecf20Sopenharmony_ci ); 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_ci regs->uregs[rd] = rdv; 2138c2ecf20Sopenharmony_ci regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK); 2148c2ecf20Sopenharmony_ci} 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_cistatic void __kprobes 2178c2ecf20Sopenharmony_ciemulate_rd16rn12rm0rs8_rwflags_nopc(probes_opcode_t insn, 2188c2ecf20Sopenharmony_ci struct arch_probes_insn *asi, 2198c2ecf20Sopenharmony_ci struct pt_regs *regs) 2208c2ecf20Sopenharmony_ci{ 2218c2ecf20Sopenharmony_ci int rd = (insn >> 16) & 0xf; 2228c2ecf20Sopenharmony_ci int rn = (insn >> 12) & 0xf; 2238c2ecf20Sopenharmony_ci int rm = insn & 0xf; 2248c2ecf20Sopenharmony_ci int rs = (insn >> 8) & 0xf; 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_ci register unsigned long rdv asm("r2") = regs->uregs[rd]; 2278c2ecf20Sopenharmony_ci register unsigned long rnv asm("r0") = regs->uregs[rn]; 2288c2ecf20Sopenharmony_ci register unsigned long rmv asm("r3") = regs->uregs[rm]; 2298c2ecf20Sopenharmony_ci register unsigned long rsv asm("r1") = regs->uregs[rs]; 2308c2ecf20Sopenharmony_ci unsigned long cpsr = regs->ARM_cpsr; 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_ci __asm__ __volatile__ ( 2338c2ecf20Sopenharmony_ci "msr cpsr_fs, %[cpsr] \n\t" 2348c2ecf20Sopenharmony_ci BLX("%[fn]") 2358c2ecf20Sopenharmony_ci "mrs %[cpsr], cpsr \n\t" 2368c2ecf20Sopenharmony_ci : "=r" (rdv), [cpsr] "=r" (cpsr) 2378c2ecf20Sopenharmony_ci : "0" (rdv), "r" (rnv), "r" (rmv), "r" (rsv), 2388c2ecf20Sopenharmony_ci "1" (cpsr), [fn] "r" (asi->insn_fn) 2398c2ecf20Sopenharmony_ci : "lr", "memory", "cc" 2408c2ecf20Sopenharmony_ci ); 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_ci regs->uregs[rd] = rdv; 2438c2ecf20Sopenharmony_ci regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK); 2448c2ecf20Sopenharmony_ci} 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_cistatic void __kprobes 2478c2ecf20Sopenharmony_ciemulate_rd12rm0_noflags_nopc(probes_opcode_t insn, 2488c2ecf20Sopenharmony_ci struct arch_probes_insn *asi, struct pt_regs *regs) 2498c2ecf20Sopenharmony_ci{ 2508c2ecf20Sopenharmony_ci int rd = (insn >> 12) & 0xf; 2518c2ecf20Sopenharmony_ci int rm = insn & 0xf; 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_ci register unsigned long rdv asm("r0") = regs->uregs[rd]; 2548c2ecf20Sopenharmony_ci register unsigned long rmv asm("r3") = regs->uregs[rm]; 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_ci __asm__ __volatile__ ( 2578c2ecf20Sopenharmony_ci BLX("%[fn]") 2588c2ecf20Sopenharmony_ci : "=r" (rdv) 2598c2ecf20Sopenharmony_ci : "0" (rdv), "r" (rmv), [fn] "r" (asi->insn_fn) 2608c2ecf20Sopenharmony_ci : "lr", "memory", "cc" 2618c2ecf20Sopenharmony_ci ); 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_ci regs->uregs[rd] = rdv; 2648c2ecf20Sopenharmony_ci} 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_cistatic void __kprobes 2678c2ecf20Sopenharmony_ciemulate_rdlo12rdhi16rn0rm8_rwflags_nopc(probes_opcode_t insn, 2688c2ecf20Sopenharmony_ci struct arch_probes_insn *asi, 2698c2ecf20Sopenharmony_ci struct pt_regs *regs) 2708c2ecf20Sopenharmony_ci{ 2718c2ecf20Sopenharmony_ci int rdlo = (insn >> 12) & 0xf; 2728c2ecf20Sopenharmony_ci int rdhi = (insn >> 16) & 0xf; 2738c2ecf20Sopenharmony_ci int rn = insn & 0xf; 2748c2ecf20Sopenharmony_ci int rm = (insn >> 8) & 0xf; 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_ci register unsigned long rdlov asm("r0") = regs->uregs[rdlo]; 2778c2ecf20Sopenharmony_ci register unsigned long rdhiv asm("r2") = regs->uregs[rdhi]; 2788c2ecf20Sopenharmony_ci register unsigned long rnv asm("r3") = regs->uregs[rn]; 2798c2ecf20Sopenharmony_ci register unsigned long rmv asm("r1") = regs->uregs[rm]; 2808c2ecf20Sopenharmony_ci unsigned long cpsr = regs->ARM_cpsr; 2818c2ecf20Sopenharmony_ci 2828c2ecf20Sopenharmony_ci __asm__ __volatile__ ( 2838c2ecf20Sopenharmony_ci "msr cpsr_fs, %[cpsr] \n\t" 2848c2ecf20Sopenharmony_ci BLX("%[fn]") 2858c2ecf20Sopenharmony_ci "mrs %[cpsr], cpsr \n\t" 2868c2ecf20Sopenharmony_ci : "=r" (rdlov), "=r" (rdhiv), [cpsr] "=r" (cpsr) 2878c2ecf20Sopenharmony_ci : "0" (rdlov), "1" (rdhiv), "r" (rnv), "r" (rmv), 2888c2ecf20Sopenharmony_ci "2" (cpsr), [fn] "r" (asi->insn_fn) 2898c2ecf20Sopenharmony_ci : "lr", "memory", "cc" 2908c2ecf20Sopenharmony_ci ); 2918c2ecf20Sopenharmony_ci 2928c2ecf20Sopenharmony_ci regs->uregs[rdlo] = rdlov; 2938c2ecf20Sopenharmony_ci regs->uregs[rdhi] = rdhiv; 2948c2ecf20Sopenharmony_ci regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK); 2958c2ecf20Sopenharmony_ci} 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_ciconst union decode_action kprobes_arm_actions[NUM_PROBES_ARM_ACTIONS] = { 2988c2ecf20Sopenharmony_ci [PROBES_PRELOAD_IMM] = {.handler = probes_simulate_nop}, 2998c2ecf20Sopenharmony_ci [PROBES_PRELOAD_REG] = {.handler = probes_simulate_nop}, 3008c2ecf20Sopenharmony_ci [PROBES_BRANCH_IMM] = {.handler = simulate_blx1}, 3018c2ecf20Sopenharmony_ci [PROBES_MRS] = {.handler = simulate_mrs}, 3028c2ecf20Sopenharmony_ci [PROBES_BRANCH_REG] = {.handler = simulate_blx2bx}, 3038c2ecf20Sopenharmony_ci [PROBES_CLZ] = {.handler = emulate_rd12rm0_noflags_nopc}, 3048c2ecf20Sopenharmony_ci [PROBES_SATURATING_ARITHMETIC] = { 3058c2ecf20Sopenharmony_ci .handler = emulate_rd12rn16rm0_rwflags_nopc}, 3068c2ecf20Sopenharmony_ci [PROBES_MUL1] = {.handler = emulate_rdlo12rdhi16rn0rm8_rwflags_nopc}, 3078c2ecf20Sopenharmony_ci [PROBES_MUL2] = {.handler = emulate_rd16rn12rm0rs8_rwflags_nopc}, 3088c2ecf20Sopenharmony_ci [PROBES_SWP] = {.handler = emulate_rd12rn16rm0_rwflags_nopc}, 3098c2ecf20Sopenharmony_ci [PROBES_LDRSTRD] = {.handler = emulate_ldrdstrd}, 3108c2ecf20Sopenharmony_ci [PROBES_LOAD_EXTRA] = {.handler = emulate_ldr}, 3118c2ecf20Sopenharmony_ci [PROBES_LOAD] = {.handler = emulate_ldr}, 3128c2ecf20Sopenharmony_ci [PROBES_STORE_EXTRA] = {.handler = emulate_str}, 3138c2ecf20Sopenharmony_ci [PROBES_STORE] = {.handler = emulate_str}, 3148c2ecf20Sopenharmony_ci [PROBES_MOV_IP_SP] = {.handler = simulate_mov_ipsp}, 3158c2ecf20Sopenharmony_ci [PROBES_DATA_PROCESSING_REG] = { 3168c2ecf20Sopenharmony_ci .handler = emulate_rd12rn16rm0rs8_rwflags}, 3178c2ecf20Sopenharmony_ci [PROBES_DATA_PROCESSING_IMM] = { 3188c2ecf20Sopenharmony_ci .handler = emulate_rd12rn16rm0rs8_rwflags}, 3198c2ecf20Sopenharmony_ci [PROBES_MOV_HALFWORD] = {.handler = emulate_rd12rm0_noflags_nopc}, 3208c2ecf20Sopenharmony_ci [PROBES_SEV] = {.handler = probes_emulate_none}, 3218c2ecf20Sopenharmony_ci [PROBES_WFE] = {.handler = probes_simulate_nop}, 3228c2ecf20Sopenharmony_ci [PROBES_SATURATE] = {.handler = emulate_rd12rn16rm0_rwflags_nopc}, 3238c2ecf20Sopenharmony_ci [PROBES_REV] = {.handler = emulate_rd12rm0_noflags_nopc}, 3248c2ecf20Sopenharmony_ci [PROBES_MMI] = {.handler = emulate_rd12rn16rm0_rwflags_nopc}, 3258c2ecf20Sopenharmony_ci [PROBES_PACK] = {.handler = emulate_rd12rn16rm0_rwflags_nopc}, 3268c2ecf20Sopenharmony_ci [PROBES_EXTEND] = {.handler = emulate_rd12rm0_noflags_nopc}, 3278c2ecf20Sopenharmony_ci [PROBES_EXTEND_ADD] = {.handler = emulate_rd12rn16rm0_rwflags_nopc}, 3288c2ecf20Sopenharmony_ci [PROBES_MUL_ADD_LONG] = { 3298c2ecf20Sopenharmony_ci .handler = emulate_rdlo12rdhi16rn0rm8_rwflags_nopc}, 3308c2ecf20Sopenharmony_ci [PROBES_MUL_ADD] = {.handler = emulate_rd16rn12rm0rs8_rwflags_nopc}, 3318c2ecf20Sopenharmony_ci [PROBES_BITFIELD] = {.handler = emulate_rd12rm0_noflags_nopc}, 3328c2ecf20Sopenharmony_ci [PROBES_BRANCH] = {.handler = simulate_bbl}, 3338c2ecf20Sopenharmony_ci [PROBES_LDMSTM] = {.decoder = kprobe_decode_ldmstm} 3348c2ecf20Sopenharmony_ci}; 3358c2ecf20Sopenharmony_ci 3368c2ecf20Sopenharmony_ciconst struct decode_checker *kprobes_arm_checkers[] = {arm_stack_checker, arm_regs_checker, NULL}; 337