162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * arch/arm/probes/kprobes/actions-arm.c 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2006, 2007 Motorola Inc. 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci/* 962306a36Sopenharmony_ci * We do not have hardware single-stepping on ARM, This 1062306a36Sopenharmony_ci * effort is further complicated by the ARM not having a 1162306a36Sopenharmony_ci * "next PC" register. Instructions that change the PC 1262306a36Sopenharmony_ci * can't be safely single-stepped in a MP environment, so 1362306a36Sopenharmony_ci * we have a lot of work to do: 1462306a36Sopenharmony_ci * 1562306a36Sopenharmony_ci * In the prepare phase: 1662306a36Sopenharmony_ci * *) If it is an instruction that does anything 1762306a36Sopenharmony_ci * with the CPU mode, we reject it for a kprobe. 1862306a36Sopenharmony_ci * (This is out of laziness rather than need. The 1962306a36Sopenharmony_ci * instructions could be simulated.) 2062306a36Sopenharmony_ci * 2162306a36Sopenharmony_ci * *) Otherwise, decode the instruction rewriting its 2262306a36Sopenharmony_ci * registers to take fixed, ordered registers and 2362306a36Sopenharmony_ci * setting a handler for it to run the instruction. 2462306a36Sopenharmony_ci * 2562306a36Sopenharmony_ci * In the execution phase by an instruction's handler: 2662306a36Sopenharmony_ci * 2762306a36Sopenharmony_ci * *) If the PC is written to by the instruction, the 2862306a36Sopenharmony_ci * instruction must be fully simulated in software. 2962306a36Sopenharmony_ci * 3062306a36Sopenharmony_ci * *) Otherwise, a modified form of the instruction is 3162306a36Sopenharmony_ci * directly executed. Its handler calls the 3262306a36Sopenharmony_ci * instruction in insn[0]. In insn[1] is a 3362306a36Sopenharmony_ci * "mov pc, lr" to return. 3462306a36Sopenharmony_ci * 3562306a36Sopenharmony_ci * Before calling, load up the reordered registers 3662306a36Sopenharmony_ci * from the original instruction's registers. If one 3762306a36Sopenharmony_ci * of the original input registers is the PC, compute 3862306a36Sopenharmony_ci * and adjust the appropriate input register. 3962306a36Sopenharmony_ci * 4062306a36Sopenharmony_ci * After call completes, copy the output registers to 4162306a36Sopenharmony_ci * the original instruction's original registers. 4262306a36Sopenharmony_ci * 4362306a36Sopenharmony_ci * We don't use a real breakpoint instruction since that 4462306a36Sopenharmony_ci * would have us in the kernel go from SVC mode to SVC 4562306a36Sopenharmony_ci * mode losing the link register. Instead we use an 4662306a36Sopenharmony_ci * undefined instruction. To simplify processing, the 4762306a36Sopenharmony_ci * undefined instruction used for kprobes must be reserved 4862306a36Sopenharmony_ci * exclusively for kprobes use. 4962306a36Sopenharmony_ci * 5062306a36Sopenharmony_ci * TODO: ifdef out some instruction decoding based on architecture. 5162306a36Sopenharmony_ci */ 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci#include <linux/kernel.h> 5462306a36Sopenharmony_ci#include <linux/kprobes.h> 5562306a36Sopenharmony_ci#include <linux/ptrace.h> 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci#include "../decode-arm.h" 5862306a36Sopenharmony_ci#include "core.h" 5962306a36Sopenharmony_ci#include "checkers.h" 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci#if __LINUX_ARM_ARCH__ >= 6 6262306a36Sopenharmony_ci#define BLX(reg) "blx "reg" \n\t" 6362306a36Sopenharmony_ci#else 6462306a36Sopenharmony_ci#define BLX(reg) "mov lr, pc \n\t" \ 6562306a36Sopenharmony_ci "mov pc, "reg" \n\t" 6662306a36Sopenharmony_ci#endif 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_cistatic void __kprobes 6962306a36Sopenharmony_ciemulate_ldrdstrd(probes_opcode_t insn, 7062306a36Sopenharmony_ci struct arch_probes_insn *asi, struct pt_regs *regs) 7162306a36Sopenharmony_ci{ 7262306a36Sopenharmony_ci unsigned long pc = regs->ARM_pc + 4; 7362306a36Sopenharmony_ci int rt = (insn >> 12) & 0xf; 7462306a36Sopenharmony_ci int rn = (insn >> 16) & 0xf; 7562306a36Sopenharmony_ci int rm = insn & 0xf; 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci register unsigned long rtv asm("r0") = regs->uregs[rt]; 7862306a36Sopenharmony_ci register unsigned long rt2v asm("r1") = regs->uregs[rt+1]; 7962306a36Sopenharmony_ci register unsigned long rnv asm("r2") = (rn == 15) ? pc 8062306a36Sopenharmony_ci : regs->uregs[rn]; 8162306a36Sopenharmony_ci register unsigned long rmv asm("r3") = regs->uregs[rm]; 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci __asm__ __volatile__ ( 8462306a36Sopenharmony_ci BLX("%[fn]") 8562306a36Sopenharmony_ci : "=r" (rtv), "=r" (rt2v), "=r" (rnv) 8662306a36Sopenharmony_ci : "0" (rtv), "1" (rt2v), "2" (rnv), "r" (rmv), 8762306a36Sopenharmony_ci [fn] "r" (asi->insn_fn) 8862306a36Sopenharmony_ci : "lr", "memory", "cc" 8962306a36Sopenharmony_ci ); 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci regs->uregs[rt] = rtv; 9262306a36Sopenharmony_ci regs->uregs[rt+1] = rt2v; 9362306a36Sopenharmony_ci if (is_writeback(insn)) 9462306a36Sopenharmony_ci regs->uregs[rn] = rnv; 9562306a36Sopenharmony_ci} 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_cistatic void __kprobes 9862306a36Sopenharmony_ciemulate_ldr(probes_opcode_t insn, 9962306a36Sopenharmony_ci struct arch_probes_insn *asi, struct pt_regs *regs) 10062306a36Sopenharmony_ci{ 10162306a36Sopenharmony_ci unsigned long pc = regs->ARM_pc + 4; 10262306a36Sopenharmony_ci int rt = (insn >> 12) & 0xf; 10362306a36Sopenharmony_ci int rn = (insn >> 16) & 0xf; 10462306a36Sopenharmony_ci int rm = insn & 0xf; 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci register unsigned long rtv asm("r0"); 10762306a36Sopenharmony_ci register unsigned long rnv asm("r2") = (rn == 15) ? pc 10862306a36Sopenharmony_ci : regs->uregs[rn]; 10962306a36Sopenharmony_ci register unsigned long rmv asm("r3") = regs->uregs[rm]; 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci __asm__ __volatile__ ( 11262306a36Sopenharmony_ci BLX("%[fn]") 11362306a36Sopenharmony_ci : "=r" (rtv), "=r" (rnv) 11462306a36Sopenharmony_ci : "1" (rnv), "r" (rmv), [fn] "r" (asi->insn_fn) 11562306a36Sopenharmony_ci : "lr", "memory", "cc" 11662306a36Sopenharmony_ci ); 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci if (rt == 15) 11962306a36Sopenharmony_ci load_write_pc(rtv, regs); 12062306a36Sopenharmony_ci else 12162306a36Sopenharmony_ci regs->uregs[rt] = rtv; 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ci if (is_writeback(insn)) 12462306a36Sopenharmony_ci regs->uregs[rn] = rnv; 12562306a36Sopenharmony_ci} 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_cistatic void __kprobes 12862306a36Sopenharmony_ciemulate_str(probes_opcode_t insn, 12962306a36Sopenharmony_ci struct arch_probes_insn *asi, struct pt_regs *regs) 13062306a36Sopenharmony_ci{ 13162306a36Sopenharmony_ci unsigned long rtpc = regs->ARM_pc - 4 + str_pc_offset; 13262306a36Sopenharmony_ci unsigned long rnpc = regs->ARM_pc + 4; 13362306a36Sopenharmony_ci int rt = (insn >> 12) & 0xf; 13462306a36Sopenharmony_ci int rn = (insn >> 16) & 0xf; 13562306a36Sopenharmony_ci int rm = insn & 0xf; 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci register unsigned long rtv asm("r0") = (rt == 15) ? rtpc 13862306a36Sopenharmony_ci : regs->uregs[rt]; 13962306a36Sopenharmony_ci register unsigned long rnv asm("r2") = (rn == 15) ? rnpc 14062306a36Sopenharmony_ci : regs->uregs[rn]; 14162306a36Sopenharmony_ci register unsigned long rmv asm("r3") = regs->uregs[rm]; 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci __asm__ __volatile__ ( 14462306a36Sopenharmony_ci BLX("%[fn]") 14562306a36Sopenharmony_ci : "=r" (rnv) 14662306a36Sopenharmony_ci : "r" (rtv), "0" (rnv), "r" (rmv), [fn] "r" (asi->insn_fn) 14762306a36Sopenharmony_ci : "lr", "memory", "cc" 14862306a36Sopenharmony_ci ); 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_ci if (is_writeback(insn)) 15162306a36Sopenharmony_ci regs->uregs[rn] = rnv; 15262306a36Sopenharmony_ci} 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_cistatic void __kprobes 15562306a36Sopenharmony_ciemulate_rd12rn16rm0rs8_rwflags(probes_opcode_t insn, 15662306a36Sopenharmony_ci struct arch_probes_insn *asi, struct pt_regs *regs) 15762306a36Sopenharmony_ci{ 15862306a36Sopenharmony_ci unsigned long pc = regs->ARM_pc + 4; 15962306a36Sopenharmony_ci int rd = (insn >> 12) & 0xf; 16062306a36Sopenharmony_ci int rn = (insn >> 16) & 0xf; 16162306a36Sopenharmony_ci int rm = insn & 0xf; 16262306a36Sopenharmony_ci int rs = (insn >> 8) & 0xf; 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ci register unsigned long rdv asm("r0") = regs->uregs[rd]; 16562306a36Sopenharmony_ci register unsigned long rnv asm("r2") = (rn == 15) ? pc 16662306a36Sopenharmony_ci : regs->uregs[rn]; 16762306a36Sopenharmony_ci register unsigned long rmv asm("r3") = (rm == 15) ? pc 16862306a36Sopenharmony_ci : regs->uregs[rm]; 16962306a36Sopenharmony_ci register unsigned long rsv asm("r1") = regs->uregs[rs]; 17062306a36Sopenharmony_ci unsigned long cpsr = regs->ARM_cpsr; 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ci __asm__ __volatile__ ( 17362306a36Sopenharmony_ci "msr cpsr_fs, %[cpsr] \n\t" 17462306a36Sopenharmony_ci BLX("%[fn]") 17562306a36Sopenharmony_ci "mrs %[cpsr], cpsr \n\t" 17662306a36Sopenharmony_ci : "=r" (rdv), [cpsr] "=r" (cpsr) 17762306a36Sopenharmony_ci : "0" (rdv), "r" (rnv), "r" (rmv), "r" (rsv), 17862306a36Sopenharmony_ci "1" (cpsr), [fn] "r" (asi->insn_fn) 17962306a36Sopenharmony_ci : "lr", "memory", "cc" 18062306a36Sopenharmony_ci ); 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_ci if (rd == 15) 18362306a36Sopenharmony_ci alu_write_pc(rdv, regs); 18462306a36Sopenharmony_ci else 18562306a36Sopenharmony_ci regs->uregs[rd] = rdv; 18662306a36Sopenharmony_ci regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK); 18762306a36Sopenharmony_ci} 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_cistatic void __kprobes 19062306a36Sopenharmony_ciemulate_rd12rn16rm0_rwflags_nopc(probes_opcode_t insn, 19162306a36Sopenharmony_ci struct arch_probes_insn *asi, struct pt_regs *regs) 19262306a36Sopenharmony_ci{ 19362306a36Sopenharmony_ci int rd = (insn >> 12) & 0xf; 19462306a36Sopenharmony_ci int rn = (insn >> 16) & 0xf; 19562306a36Sopenharmony_ci int rm = insn & 0xf; 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci register unsigned long rdv asm("r0") = regs->uregs[rd]; 19862306a36Sopenharmony_ci register unsigned long rnv asm("r2") = regs->uregs[rn]; 19962306a36Sopenharmony_ci register unsigned long rmv asm("r3") = regs->uregs[rm]; 20062306a36Sopenharmony_ci unsigned long cpsr = regs->ARM_cpsr; 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ci __asm__ __volatile__ ( 20362306a36Sopenharmony_ci "msr cpsr_fs, %[cpsr] \n\t" 20462306a36Sopenharmony_ci BLX("%[fn]") 20562306a36Sopenharmony_ci "mrs %[cpsr], cpsr \n\t" 20662306a36Sopenharmony_ci : "=r" (rdv), [cpsr] "=r" (cpsr) 20762306a36Sopenharmony_ci : "0" (rdv), "r" (rnv), "r" (rmv), 20862306a36Sopenharmony_ci "1" (cpsr), [fn] "r" (asi->insn_fn) 20962306a36Sopenharmony_ci : "lr", "memory", "cc" 21062306a36Sopenharmony_ci ); 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_ci regs->uregs[rd] = rdv; 21362306a36Sopenharmony_ci regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK); 21462306a36Sopenharmony_ci} 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_cistatic void __kprobes 21762306a36Sopenharmony_ciemulate_rd16rn12rm0rs8_rwflags_nopc(probes_opcode_t insn, 21862306a36Sopenharmony_ci struct arch_probes_insn *asi, 21962306a36Sopenharmony_ci struct pt_regs *regs) 22062306a36Sopenharmony_ci{ 22162306a36Sopenharmony_ci int rd = (insn >> 16) & 0xf; 22262306a36Sopenharmony_ci int rn = (insn >> 12) & 0xf; 22362306a36Sopenharmony_ci int rm = insn & 0xf; 22462306a36Sopenharmony_ci int rs = (insn >> 8) & 0xf; 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_ci register unsigned long rdv asm("r2") = regs->uregs[rd]; 22762306a36Sopenharmony_ci register unsigned long rnv asm("r0") = regs->uregs[rn]; 22862306a36Sopenharmony_ci register unsigned long rmv asm("r3") = regs->uregs[rm]; 22962306a36Sopenharmony_ci register unsigned long rsv asm("r1") = regs->uregs[rs]; 23062306a36Sopenharmony_ci unsigned long cpsr = regs->ARM_cpsr; 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_ci __asm__ __volatile__ ( 23362306a36Sopenharmony_ci "msr cpsr_fs, %[cpsr] \n\t" 23462306a36Sopenharmony_ci BLX("%[fn]") 23562306a36Sopenharmony_ci "mrs %[cpsr], cpsr \n\t" 23662306a36Sopenharmony_ci : "=r" (rdv), [cpsr] "=r" (cpsr) 23762306a36Sopenharmony_ci : "0" (rdv), "r" (rnv), "r" (rmv), "r" (rsv), 23862306a36Sopenharmony_ci "1" (cpsr), [fn] "r" (asi->insn_fn) 23962306a36Sopenharmony_ci : "lr", "memory", "cc" 24062306a36Sopenharmony_ci ); 24162306a36Sopenharmony_ci 24262306a36Sopenharmony_ci regs->uregs[rd] = rdv; 24362306a36Sopenharmony_ci regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK); 24462306a36Sopenharmony_ci} 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_cistatic void __kprobes 24762306a36Sopenharmony_ciemulate_rd12rm0_noflags_nopc(probes_opcode_t insn, 24862306a36Sopenharmony_ci struct arch_probes_insn *asi, struct pt_regs *regs) 24962306a36Sopenharmony_ci{ 25062306a36Sopenharmony_ci int rd = (insn >> 12) & 0xf; 25162306a36Sopenharmony_ci int rm = insn & 0xf; 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_ci register unsigned long rdv asm("r0") = regs->uregs[rd]; 25462306a36Sopenharmony_ci register unsigned long rmv asm("r3") = regs->uregs[rm]; 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci __asm__ __volatile__ ( 25762306a36Sopenharmony_ci BLX("%[fn]") 25862306a36Sopenharmony_ci : "=r" (rdv) 25962306a36Sopenharmony_ci : "0" (rdv), "r" (rmv), [fn] "r" (asi->insn_fn) 26062306a36Sopenharmony_ci : "lr", "memory", "cc" 26162306a36Sopenharmony_ci ); 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ci regs->uregs[rd] = rdv; 26462306a36Sopenharmony_ci} 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_cistatic void __kprobes 26762306a36Sopenharmony_ciemulate_rdlo12rdhi16rn0rm8_rwflags_nopc(probes_opcode_t insn, 26862306a36Sopenharmony_ci struct arch_probes_insn *asi, 26962306a36Sopenharmony_ci struct pt_regs *regs) 27062306a36Sopenharmony_ci{ 27162306a36Sopenharmony_ci int rdlo = (insn >> 12) & 0xf; 27262306a36Sopenharmony_ci int rdhi = (insn >> 16) & 0xf; 27362306a36Sopenharmony_ci int rn = insn & 0xf; 27462306a36Sopenharmony_ci int rm = (insn >> 8) & 0xf; 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_ci register unsigned long rdlov asm("r0") = regs->uregs[rdlo]; 27762306a36Sopenharmony_ci register unsigned long rdhiv asm("r2") = regs->uregs[rdhi]; 27862306a36Sopenharmony_ci register unsigned long rnv asm("r3") = regs->uregs[rn]; 27962306a36Sopenharmony_ci register unsigned long rmv asm("r1") = regs->uregs[rm]; 28062306a36Sopenharmony_ci unsigned long cpsr = regs->ARM_cpsr; 28162306a36Sopenharmony_ci 28262306a36Sopenharmony_ci __asm__ __volatile__ ( 28362306a36Sopenharmony_ci "msr cpsr_fs, %[cpsr] \n\t" 28462306a36Sopenharmony_ci BLX("%[fn]") 28562306a36Sopenharmony_ci "mrs %[cpsr], cpsr \n\t" 28662306a36Sopenharmony_ci : "=r" (rdlov), "=r" (rdhiv), [cpsr] "=r" (cpsr) 28762306a36Sopenharmony_ci : "0" (rdlov), "1" (rdhiv), "r" (rnv), "r" (rmv), 28862306a36Sopenharmony_ci "2" (cpsr), [fn] "r" (asi->insn_fn) 28962306a36Sopenharmony_ci : "lr", "memory", "cc" 29062306a36Sopenharmony_ci ); 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_ci regs->uregs[rdlo] = rdlov; 29362306a36Sopenharmony_ci regs->uregs[rdhi] = rdhiv; 29462306a36Sopenharmony_ci regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK); 29562306a36Sopenharmony_ci} 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_ciconst union decode_action kprobes_arm_actions[NUM_PROBES_ARM_ACTIONS] = { 29862306a36Sopenharmony_ci [PROBES_PRELOAD_IMM] = {.handler = probes_simulate_nop}, 29962306a36Sopenharmony_ci [PROBES_PRELOAD_REG] = {.handler = probes_simulate_nop}, 30062306a36Sopenharmony_ci [PROBES_BRANCH_IMM] = {.handler = simulate_blx1}, 30162306a36Sopenharmony_ci [PROBES_MRS] = {.handler = simulate_mrs}, 30262306a36Sopenharmony_ci [PROBES_BRANCH_REG] = {.handler = simulate_blx2bx}, 30362306a36Sopenharmony_ci [PROBES_CLZ] = {.handler = emulate_rd12rm0_noflags_nopc}, 30462306a36Sopenharmony_ci [PROBES_SATURATING_ARITHMETIC] = { 30562306a36Sopenharmony_ci .handler = emulate_rd12rn16rm0_rwflags_nopc}, 30662306a36Sopenharmony_ci [PROBES_MUL1] = {.handler = emulate_rdlo12rdhi16rn0rm8_rwflags_nopc}, 30762306a36Sopenharmony_ci [PROBES_MUL2] = {.handler = emulate_rd16rn12rm0rs8_rwflags_nopc}, 30862306a36Sopenharmony_ci [PROBES_SWP] = {.handler = emulate_rd12rn16rm0_rwflags_nopc}, 30962306a36Sopenharmony_ci [PROBES_LDRSTRD] = {.handler = emulate_ldrdstrd}, 31062306a36Sopenharmony_ci [PROBES_LOAD_EXTRA] = {.handler = emulate_ldr}, 31162306a36Sopenharmony_ci [PROBES_LOAD] = {.handler = emulate_ldr}, 31262306a36Sopenharmony_ci [PROBES_STORE_EXTRA] = {.handler = emulate_str}, 31362306a36Sopenharmony_ci [PROBES_STORE] = {.handler = emulate_str}, 31462306a36Sopenharmony_ci [PROBES_MOV_IP_SP] = {.handler = simulate_mov_ipsp}, 31562306a36Sopenharmony_ci [PROBES_DATA_PROCESSING_REG] = { 31662306a36Sopenharmony_ci .handler = emulate_rd12rn16rm0rs8_rwflags}, 31762306a36Sopenharmony_ci [PROBES_DATA_PROCESSING_IMM] = { 31862306a36Sopenharmony_ci .handler = emulate_rd12rn16rm0rs8_rwflags}, 31962306a36Sopenharmony_ci [PROBES_MOV_HALFWORD] = {.handler = emulate_rd12rm0_noflags_nopc}, 32062306a36Sopenharmony_ci [PROBES_SEV] = {.handler = probes_emulate_none}, 32162306a36Sopenharmony_ci [PROBES_WFE] = {.handler = probes_simulate_nop}, 32262306a36Sopenharmony_ci [PROBES_SATURATE] = {.handler = emulate_rd12rn16rm0_rwflags_nopc}, 32362306a36Sopenharmony_ci [PROBES_REV] = {.handler = emulate_rd12rm0_noflags_nopc}, 32462306a36Sopenharmony_ci [PROBES_MMI] = {.handler = emulate_rd12rn16rm0_rwflags_nopc}, 32562306a36Sopenharmony_ci [PROBES_PACK] = {.handler = emulate_rd12rn16rm0_rwflags_nopc}, 32662306a36Sopenharmony_ci [PROBES_EXTEND] = {.handler = emulate_rd12rm0_noflags_nopc}, 32762306a36Sopenharmony_ci [PROBES_EXTEND_ADD] = {.handler = emulate_rd12rn16rm0_rwflags_nopc}, 32862306a36Sopenharmony_ci [PROBES_MUL_ADD_LONG] = { 32962306a36Sopenharmony_ci .handler = emulate_rdlo12rdhi16rn0rm8_rwflags_nopc}, 33062306a36Sopenharmony_ci [PROBES_MUL_ADD] = {.handler = emulate_rd16rn12rm0rs8_rwflags_nopc}, 33162306a36Sopenharmony_ci [PROBES_BITFIELD] = {.handler = emulate_rd12rm0_noflags_nopc}, 33262306a36Sopenharmony_ci [PROBES_BRANCH] = {.handler = simulate_bbl}, 33362306a36Sopenharmony_ci [PROBES_LDMSTM] = {.decoder = kprobe_decode_ldmstm} 33462306a36Sopenharmony_ci}; 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_ciconst struct decode_checker *kprobes_arm_checkers[] = {arm_stack_checker, arm_regs_checker, NULL}; 337