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