12437170710c4a3dee137a65623960aa7ac82a32eJon Medhurst/* 22437170710c4a3dee137a65623960aa7ac82a32eJon Medhurst * arch/arm/kernel/kprobes-thumb.c 32437170710c4a3dee137a65623960aa7ac82a32eJon Medhurst * 42437170710c4a3dee137a65623960aa7ac82a32eJon Medhurst * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>. 52437170710c4a3dee137a65623960aa7ac82a32eJon Medhurst * 62437170710c4a3dee137a65623960aa7ac82a32eJon Medhurst * This program is free software; you can redistribute it and/or modify 72437170710c4a3dee137a65623960aa7ac82a32eJon Medhurst * it under the terms of the GNU General Public License version 2 as 82437170710c4a3dee137a65623960aa7ac82a32eJon Medhurst * published by the Free Software Foundation. 92437170710c4a3dee137a65623960aa7ac82a32eJon Medhurst */ 102437170710c4a3dee137a65623960aa7ac82a32eJon Medhurst 1187abef63ead5ac9e2c67f0c07c461eda6be16aebDavid A. Long#include <linux/types.h> 122437170710c4a3dee137a65623960aa7ac82a32eJon Medhurst#include <linux/kernel.h> 1387abef63ead5ac9e2c67f0c07c461eda6be16aebDavid A. Long#include <linux/ptrace.h> 142437170710c4a3dee137a65623960aa7ac82a32eJon Medhurst#include <linux/kprobes.h> 152437170710c4a3dee137a65623960aa7ac82a32eJon Medhurst 162437170710c4a3dee137a65623960aa7ac82a32eJon Medhurst#include "kprobes.h" 1787abef63ead5ac9e2c67f0c07c461eda6be16aebDavid A. Long#include "probes-thumb.h" 18eaf4f33feca2704ad1d06f1ef6b427712c506cc0Jon Medhurst 193e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Long/* These emulation encodings are functionally equivalent... */ 203e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Long#define t32_emulate_rd8rn16rm0ra12_noflags \ 213e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Long t32_emulate_rdlo12rdhi8rn16rm0_noflags 223e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Long 2387abef63ead5ac9e2c67f0c07c461eda6be16aebDavid A. Long/* t32 thumb actions */ 2487abef63ead5ac9e2c67f0c07c461eda6be16aebDavid A. Long 253e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Longstatic void __kprobes 26f145d664df502585618b12ed68c681f82153e02aDavid A. Longt32_simulate_table_branch(probes_opcode_t insn, 27b4cd605ca92d9a8a2f71355cb45dd943ebcb0c97David A. Long struct arch_probes_insn *asi, struct pt_regs *regs) 28dd212bd3cbd337f8f3bd6b30929bef5a8c8ba81bJon Medhurst{ 297579f4b3764337b39087d10496af0e741cbfe570David A. Long unsigned long pc = regs->ARM_pc; 30dd212bd3cbd337f8f3bd6b30929bef5a8c8ba81bJon Medhurst int rn = (insn >> 16) & 0xf; 31dd212bd3cbd337f8f3bd6b30929bef5a8c8ba81bJon Medhurst int rm = insn & 0xf; 32dd212bd3cbd337f8f3bd6b30929bef5a8c8ba81bJon Medhurst 33dd212bd3cbd337f8f3bd6b30929bef5a8c8ba81bJon Medhurst unsigned long rnv = (rn == 15) ? pc : regs->uregs[rn]; 34dd212bd3cbd337f8f3bd6b30929bef5a8c8ba81bJon Medhurst unsigned long rmv = regs->uregs[rm]; 35dd212bd3cbd337f8f3bd6b30929bef5a8c8ba81bJon Medhurst unsigned int halfwords; 36dd212bd3cbd337f8f3bd6b30929bef5a8c8ba81bJon Medhurst 37ce715c772f0124f9d3f6f5cffcb85688c81d2c07Jon Medhurst if (insn & 0x10) /* TBH */ 38dd212bd3cbd337f8f3bd6b30929bef5a8c8ba81bJon Medhurst halfwords = ((u16 *)rnv)[rmv]; 39ce715c772f0124f9d3f6f5cffcb85688c81d2c07Jon Medhurst else /* TBB */ 40dd212bd3cbd337f8f3bd6b30929bef5a8c8ba81bJon Medhurst halfwords = ((u8 *)rnv)[rmv]; 41dd212bd3cbd337f8f3bd6b30929bef5a8c8ba81bJon Medhurst 42dd212bd3cbd337f8f3bd6b30929bef5a8c8ba81bJon Medhurst regs->ARM_pc = pc + 2 * halfwords; 43dd212bd3cbd337f8f3bd6b30929bef5a8c8ba81bJon Medhurst} 44dd212bd3cbd337f8f3bd6b30929bef5a8c8ba81bJon Medhurst 453e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Longstatic void __kprobes 46f145d664df502585618b12ed68c681f82153e02aDavid A. Longt32_simulate_mrs(probes_opcode_t insn, 47b4cd605ca92d9a8a2f71355cb45dd943ebcb0c97David A. Long struct arch_probes_insn *asi, struct pt_regs *regs) 48b06f3ee34d8b817d566d15d25a21f8320b3f7c57Jon Medhurst{ 49b06f3ee34d8b817d566d15d25a21f8320b3f7c57Jon Medhurst int rd = (insn >> 8) & 0xf; 50b06f3ee34d8b817d566d15d25a21f8320b3f7c57Jon Medhurst unsigned long mask = 0xf8ff03df; /* Mask out execution state */ 51b06f3ee34d8b817d566d15d25a21f8320b3f7c57Jon Medhurst regs->uregs[rd] = regs->ARM_cpsr & mask; 52b06f3ee34d8b817d566d15d25a21f8320b3f7c57Jon Medhurst} 53b06f3ee34d8b817d566d15d25a21f8320b3f7c57Jon Medhurst 543e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Longstatic void __kprobes 55f145d664df502585618b12ed68c681f82153e02aDavid A. Longt32_simulate_cond_branch(probes_opcode_t insn, 56b4cd605ca92d9a8a2f71355cb45dd943ebcb0c97David A. Long struct arch_probes_insn *asi, struct pt_regs *regs) 57ce715c772f0124f9d3f6f5cffcb85688c81d2c07Jon Medhurst{ 587579f4b3764337b39087d10496af0e741cbfe570David A. Long unsigned long pc = regs->ARM_pc; 59ce715c772f0124f9d3f6f5cffcb85688c81d2c07Jon Medhurst 60ce715c772f0124f9d3f6f5cffcb85688c81d2c07Jon Medhurst long offset = insn & 0x7ff; /* imm11 */ 61ce715c772f0124f9d3f6f5cffcb85688c81d2c07Jon Medhurst offset += (insn & 0x003f0000) >> 5; /* imm6 */ 62ce715c772f0124f9d3f6f5cffcb85688c81d2c07Jon Medhurst offset += (insn & 0x00002000) << 4; /* J1 */ 63ce715c772f0124f9d3f6f5cffcb85688c81d2c07Jon Medhurst offset += (insn & 0x00000800) << 7; /* J2 */ 64ce715c772f0124f9d3f6f5cffcb85688c81d2c07Jon Medhurst offset -= (insn & 0x04000000) >> 7; /* Apply sign bit */ 65ce715c772f0124f9d3f6f5cffcb85688c81d2c07Jon Medhurst 66ce715c772f0124f9d3f6f5cffcb85688c81d2c07Jon Medhurst regs->ARM_pc = pc + (offset * 2); 67ce715c772f0124f9d3f6f5cffcb85688c81d2c07Jon Medhurst} 68ce715c772f0124f9d3f6f5cffcb85688c81d2c07Jon Medhurst 6944a0a59c535004eac9f18210cb2ce10b23861630David A. Longstatic enum probes_insn __kprobes 70b4cd605ca92d9a8a2f71355cb45dd943ebcb0c97David A. Longt32_decode_cond_branch(probes_opcode_t insn, struct arch_probes_insn *asi, 713e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Long const struct decode_header *d) 72ce715c772f0124f9d3f6f5cffcb85688c81d2c07Jon Medhurst{ 73ce715c772f0124f9d3f6f5cffcb85688c81d2c07Jon Medhurst int cc = (insn >> 22) & 0xf; 74f145d664df502585618b12ed68c681f82153e02aDavid A. Long asi->insn_check_cc = probes_condition_checks[cc]; 75ce715c772f0124f9d3f6f5cffcb85688c81d2c07Jon Medhurst asi->insn_handler = t32_simulate_cond_branch; 76ce715c772f0124f9d3f6f5cffcb85688c81d2c07Jon Medhurst return INSN_GOOD_NO_SLOT; 77ce715c772f0124f9d3f6f5cffcb85688c81d2c07Jon Medhurst} 78ce715c772f0124f9d3f6f5cffcb85688c81d2c07Jon Medhurst 793e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Longstatic void __kprobes 80f145d664df502585618b12ed68c681f82153e02aDavid A. Longt32_simulate_branch(probes_opcode_t insn, 81b4cd605ca92d9a8a2f71355cb45dd943ebcb0c97David A. Long struct arch_probes_insn *asi, struct pt_regs *regs) 82ce715c772f0124f9d3f6f5cffcb85688c81d2c07Jon Medhurst{ 837579f4b3764337b39087d10496af0e741cbfe570David A. Long unsigned long pc = regs->ARM_pc; 84ce715c772f0124f9d3f6f5cffcb85688c81d2c07Jon Medhurst 85ce715c772f0124f9d3f6f5cffcb85688c81d2c07Jon Medhurst long offset = insn & 0x7ff; /* imm11 */ 86ce715c772f0124f9d3f6f5cffcb85688c81d2c07Jon Medhurst offset += (insn & 0x03ff0000) >> 5; /* imm10 */ 87ce715c772f0124f9d3f6f5cffcb85688c81d2c07Jon Medhurst offset += (insn & 0x00002000) << 9; /* J1 */ 88ce715c772f0124f9d3f6f5cffcb85688c81d2c07Jon Medhurst offset += (insn & 0x00000800) << 10; /* J2 */ 89ce715c772f0124f9d3f6f5cffcb85688c81d2c07Jon Medhurst if (insn & 0x04000000) 90ce715c772f0124f9d3f6f5cffcb85688c81d2c07Jon Medhurst offset -= 0x00800000; /* Apply sign bit */ 91ce715c772f0124f9d3f6f5cffcb85688c81d2c07Jon Medhurst else 92ce715c772f0124f9d3f6f5cffcb85688c81d2c07Jon Medhurst offset ^= 0x00600000; /* Invert J1 and J2 */ 93ce715c772f0124f9d3f6f5cffcb85688c81d2c07Jon Medhurst 94ce715c772f0124f9d3f6f5cffcb85688c81d2c07Jon Medhurst if (insn & (1 << 14)) { 95ce715c772f0124f9d3f6f5cffcb85688c81d2c07Jon Medhurst /* BL or BLX */ 967579f4b3764337b39087d10496af0e741cbfe570David A. Long regs->ARM_lr = regs->ARM_pc | 1; 97ce715c772f0124f9d3f6f5cffcb85688c81d2c07Jon Medhurst if (!(insn & (1 << 12))) { 98ce715c772f0124f9d3f6f5cffcb85688c81d2c07Jon Medhurst /* BLX so switch to ARM mode */ 99ce715c772f0124f9d3f6f5cffcb85688c81d2c07Jon Medhurst regs->ARM_cpsr &= ~PSR_T_BIT; 100ce715c772f0124f9d3f6f5cffcb85688c81d2c07Jon Medhurst pc &= ~3; 101ce715c772f0124f9d3f6f5cffcb85688c81d2c07Jon Medhurst } 102ce715c772f0124f9d3f6f5cffcb85688c81d2c07Jon Medhurst } 103ce715c772f0124f9d3f6f5cffcb85688c81d2c07Jon Medhurst 104ce715c772f0124f9d3f6f5cffcb85688c81d2c07Jon Medhurst regs->ARM_pc = pc + (offset * 2); 105ce715c772f0124f9d3f6f5cffcb85688c81d2c07Jon Medhurst} 106ce715c772f0124f9d3f6f5cffcb85688c81d2c07Jon Medhurst 1073e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Longstatic void __kprobes 108f145d664df502585618b12ed68c681f82153e02aDavid A. Longt32_simulate_ldr_literal(probes_opcode_t insn, 109b4cd605ca92d9a8a2f71355cb45dd943ebcb0c97David A. Long struct arch_probes_insn *asi, struct pt_regs *regs) 110d691023b62bdf33ed84023330f4d2c77d2325b01Jon Medhurst{ 1117579f4b3764337b39087d10496af0e741cbfe570David A. Long unsigned long addr = regs->ARM_pc & ~3; 112d691023b62bdf33ed84023330f4d2c77d2325b01Jon Medhurst int rt = (insn >> 12) & 0xf; 113d691023b62bdf33ed84023330f4d2c77d2325b01Jon Medhurst unsigned long rtv; 114d691023b62bdf33ed84023330f4d2c77d2325b01Jon Medhurst 115d691023b62bdf33ed84023330f4d2c77d2325b01Jon Medhurst long offset = insn & 0xfff; 116d691023b62bdf33ed84023330f4d2c77d2325b01Jon Medhurst if (insn & 0x00800000) 117d691023b62bdf33ed84023330f4d2c77d2325b01Jon Medhurst addr += offset; 118d691023b62bdf33ed84023330f4d2c77d2325b01Jon Medhurst else 119d691023b62bdf33ed84023330f4d2c77d2325b01Jon Medhurst addr -= offset; 120d691023b62bdf33ed84023330f4d2c77d2325b01Jon Medhurst 121d691023b62bdf33ed84023330f4d2c77d2325b01Jon Medhurst if (insn & 0x00400000) { 122d691023b62bdf33ed84023330f4d2c77d2325b01Jon Medhurst /* LDR */ 123d691023b62bdf33ed84023330f4d2c77d2325b01Jon Medhurst rtv = *(unsigned long *)addr; 124d691023b62bdf33ed84023330f4d2c77d2325b01Jon Medhurst if (rt == 15) { 125d691023b62bdf33ed84023330f4d2c77d2325b01Jon Medhurst bx_write_pc(rtv, regs); 126d691023b62bdf33ed84023330f4d2c77d2325b01Jon Medhurst return; 127d691023b62bdf33ed84023330f4d2c77d2325b01Jon Medhurst } 128d691023b62bdf33ed84023330f4d2c77d2325b01Jon Medhurst } else if (insn & 0x00200000) { 129d691023b62bdf33ed84023330f4d2c77d2325b01Jon Medhurst /* LDRH */ 130d691023b62bdf33ed84023330f4d2c77d2325b01Jon Medhurst if (insn & 0x01000000) 131d691023b62bdf33ed84023330f4d2c77d2325b01Jon Medhurst rtv = *(s16 *)addr; 132d691023b62bdf33ed84023330f4d2c77d2325b01Jon Medhurst else 133d691023b62bdf33ed84023330f4d2c77d2325b01Jon Medhurst rtv = *(u16 *)addr; 134d691023b62bdf33ed84023330f4d2c77d2325b01Jon Medhurst } else { 135d691023b62bdf33ed84023330f4d2c77d2325b01Jon Medhurst /* LDRB */ 136d691023b62bdf33ed84023330f4d2c77d2325b01Jon Medhurst if (insn & 0x01000000) 137d691023b62bdf33ed84023330f4d2c77d2325b01Jon Medhurst rtv = *(s8 *)addr; 138d691023b62bdf33ed84023330f4d2c77d2325b01Jon Medhurst else 139d691023b62bdf33ed84023330f4d2c77d2325b01Jon Medhurst rtv = *(u8 *)addr; 140d691023b62bdf33ed84023330f4d2c77d2325b01Jon Medhurst } 141d691023b62bdf33ed84023330f4d2c77d2325b01Jon Medhurst 142d691023b62bdf33ed84023330f4d2c77d2325b01Jon Medhurst regs->uregs[rt] = rtv; 143d691023b62bdf33ed84023330f4d2c77d2325b01Jon Medhurst} 144d691023b62bdf33ed84023330f4d2c77d2325b01Jon Medhurst 14544a0a59c535004eac9f18210cb2ce10b23861630David A. Longstatic enum probes_insn __kprobes 146b4cd605ca92d9a8a2f71355cb45dd943ebcb0c97David A. Longt32_decode_ldmstm(probes_opcode_t insn, struct arch_probes_insn *asi, 1473e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Long const struct decode_header *d) 148eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst{ 14944a0a59c535004eac9f18210cb2ce10b23861630David A. Long enum probes_insn ret = kprobe_decode_ldmstm(insn, asi, d); 150eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst 151eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst /* Fixup modified instruction to have halfwords in correct order...*/ 152888be25402021a425da3e85e2d5a954d7509286eBen Dooks insn = __mem_to_opcode_arm(asi->insn[0]); 153888be25402021a425da3e85e2d5a954d7509286eBen Dooks ((u16 *)asi->insn)[0] = __opcode_to_mem_thumb16(insn >> 16); 154888be25402021a425da3e85e2d5a954d7509286eBen Dooks ((u16 *)asi->insn)[1] = __opcode_to_mem_thumb16(insn & 0xffff); 155eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst 156eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst return ret; 157eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst} 158eaf1d06500c48109dcd37b7856773fdf608a8d21Jon Medhurst 1593e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Longstatic void __kprobes 160f145d664df502585618b12ed68c681f82153e02aDavid A. Longt32_emulate_ldrdstrd(probes_opcode_t insn, 161b4cd605ca92d9a8a2f71355cb45dd943ebcb0c97David A. Long struct arch_probes_insn *asi, struct pt_regs *regs) 162b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst{ 1637579f4b3764337b39087d10496af0e741cbfe570David A. Long unsigned long pc = regs->ARM_pc & ~3; 164b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst int rt1 = (insn >> 12) & 0xf; 165b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst int rt2 = (insn >> 8) & 0xf; 166b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst int rn = (insn >> 16) & 0xf; 167b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst 168b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst register unsigned long rt1v asm("r0") = regs->uregs[rt1]; 169b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst register unsigned long rt2v asm("r1") = regs->uregs[rt2]; 170b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst register unsigned long rnv asm("r2") = (rn == 15) ? pc 171b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst : regs->uregs[rn]; 172b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst 173b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst __asm__ __volatile__ ( 174b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst "blx %[fn]" 175b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst : "=r" (rt1v), "=r" (rt2v), "=r" (rnv) 1767579f4b3764337b39087d10496af0e741cbfe570David A. Long : "0" (rt1v), "1" (rt2v), "2" (rnv), [fn] "r" (asi->insn_fn) 177b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst : "lr", "memory", "cc" 178b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst ); 179b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst 180b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst if (rn != 15) 181b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst regs->uregs[rn] = rnv; /* Writeback base register */ 182b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst regs->uregs[rt1] = rt1v; 183b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst regs->uregs[rt2] = rt2v; 184b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst} 185b48354d3584e93284fba2ee99f6f9f44d18e4f83Jon Medhurst 1863e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Longstatic void __kprobes 187f145d664df502585618b12ed68c681f82153e02aDavid A. Longt32_emulate_ldrstr(probes_opcode_t insn, 188b4cd605ca92d9a8a2f71355cb45dd943ebcb0c97David A. Long struct arch_probes_insn *asi, struct pt_regs *regs) 189d691023b62bdf33ed84023330f4d2c77d2325b01Jon Medhurst{ 190d691023b62bdf33ed84023330f4d2c77d2325b01Jon Medhurst int rt = (insn >> 12) & 0xf; 191d691023b62bdf33ed84023330f4d2c77d2325b01Jon Medhurst int rn = (insn >> 16) & 0xf; 192d691023b62bdf33ed84023330f4d2c77d2325b01Jon Medhurst int rm = insn & 0xf; 193d691023b62bdf33ed84023330f4d2c77d2325b01Jon Medhurst 194d691023b62bdf33ed84023330f4d2c77d2325b01Jon Medhurst register unsigned long rtv asm("r0") = regs->uregs[rt]; 195d691023b62bdf33ed84023330f4d2c77d2325b01Jon Medhurst register unsigned long rnv asm("r2") = regs->uregs[rn]; 196d691023b62bdf33ed84023330f4d2c77d2325b01Jon Medhurst register unsigned long rmv asm("r3") = regs->uregs[rm]; 197d691023b62bdf33ed84023330f4d2c77d2325b01Jon Medhurst 198d691023b62bdf33ed84023330f4d2c77d2325b01Jon Medhurst __asm__ __volatile__ ( 199d691023b62bdf33ed84023330f4d2c77d2325b01Jon Medhurst "blx %[fn]" 200d691023b62bdf33ed84023330f4d2c77d2325b01Jon Medhurst : "=r" (rtv), "=r" (rnv) 2017579f4b3764337b39087d10496af0e741cbfe570David A. Long : "0" (rtv), "1" (rnv), "r" (rmv), [fn] "r" (asi->insn_fn) 202d691023b62bdf33ed84023330f4d2c77d2325b01Jon Medhurst : "lr", "memory", "cc" 203d691023b62bdf33ed84023330f4d2c77d2325b01Jon Medhurst ); 204d691023b62bdf33ed84023330f4d2c77d2325b01Jon Medhurst 205d691023b62bdf33ed84023330f4d2c77d2325b01Jon Medhurst regs->uregs[rn] = rnv; /* Writeback base register */ 206d691023b62bdf33ed84023330f4d2c77d2325b01Jon Medhurst if (rt == 15) /* Can't be true for a STR as they aren't allowed */ 207d691023b62bdf33ed84023330f4d2c77d2325b01Jon Medhurst bx_write_pc(rtv, regs); 208d691023b62bdf33ed84023330f4d2c77d2325b01Jon Medhurst else 209d691023b62bdf33ed84023330f4d2c77d2325b01Jon Medhurst regs->uregs[rt] = rtv; 210d691023b62bdf33ed84023330f4d2c77d2325b01Jon Medhurst} 211d691023b62bdf33ed84023330f4d2c77d2325b01Jon Medhurst 2123e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Longstatic void __kprobes 213f145d664df502585618b12ed68c681f82153e02aDavid A. Longt32_emulate_rd8rn16rm0_rwflags(probes_opcode_t insn, 214b4cd605ca92d9a8a2f71355cb45dd943ebcb0c97David A. Long struct arch_probes_insn *asi, struct pt_regs *regs) 215080e0013269e9fd428fd834e8a915a80fe6c8ae9Jon Medhurst{ 216080e0013269e9fd428fd834e8a915a80fe6c8ae9Jon Medhurst int rd = (insn >> 8) & 0xf; 217080e0013269e9fd428fd834e8a915a80fe6c8ae9Jon Medhurst int rn = (insn >> 16) & 0xf; 218080e0013269e9fd428fd834e8a915a80fe6c8ae9Jon Medhurst int rm = insn & 0xf; 219080e0013269e9fd428fd834e8a915a80fe6c8ae9Jon Medhurst 220080e0013269e9fd428fd834e8a915a80fe6c8ae9Jon Medhurst register unsigned long rdv asm("r1") = regs->uregs[rd]; 221080e0013269e9fd428fd834e8a915a80fe6c8ae9Jon Medhurst register unsigned long rnv asm("r2") = regs->uregs[rn]; 222080e0013269e9fd428fd834e8a915a80fe6c8ae9Jon Medhurst register unsigned long rmv asm("r3") = regs->uregs[rm]; 223080e0013269e9fd428fd834e8a915a80fe6c8ae9Jon Medhurst unsigned long cpsr = regs->ARM_cpsr; 224080e0013269e9fd428fd834e8a915a80fe6c8ae9Jon Medhurst 225080e0013269e9fd428fd834e8a915a80fe6c8ae9Jon Medhurst __asm__ __volatile__ ( 226080e0013269e9fd428fd834e8a915a80fe6c8ae9Jon Medhurst "msr cpsr_fs, %[cpsr] \n\t" 227080e0013269e9fd428fd834e8a915a80fe6c8ae9Jon Medhurst "blx %[fn] \n\t" 228080e0013269e9fd428fd834e8a915a80fe6c8ae9Jon Medhurst "mrs %[cpsr], cpsr \n\t" 229080e0013269e9fd428fd834e8a915a80fe6c8ae9Jon Medhurst : "=r" (rdv), [cpsr] "=r" (cpsr) 230080e0013269e9fd428fd834e8a915a80fe6c8ae9Jon Medhurst : "0" (rdv), "r" (rnv), "r" (rmv), 2317579f4b3764337b39087d10496af0e741cbfe570David A. Long "1" (cpsr), [fn] "r" (asi->insn_fn) 232080e0013269e9fd428fd834e8a915a80fe6c8ae9Jon Medhurst : "lr", "memory", "cc" 233080e0013269e9fd428fd834e8a915a80fe6c8ae9Jon Medhurst ); 234080e0013269e9fd428fd834e8a915a80fe6c8ae9Jon Medhurst 235080e0013269e9fd428fd834e8a915a80fe6c8ae9Jon Medhurst regs->uregs[rd] = rdv; 236080e0013269e9fd428fd834e8a915a80fe6c8ae9Jon Medhurst regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK); 237080e0013269e9fd428fd834e8a915a80fe6c8ae9Jon Medhurst} 238080e0013269e9fd428fd834e8a915a80fe6c8ae9Jon Medhurst 2393e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Longstatic void __kprobes 240f145d664df502585618b12ed68c681f82153e02aDavid A. Longt32_emulate_rd8pc16_noflags(probes_opcode_t insn, 241b4cd605ca92d9a8a2f71355cb45dd943ebcb0c97David A. Long struct arch_probes_insn *asi, struct pt_regs *regs) 2427848786a7a198dd5e097330ad0cbfdf155a25499Jon Medhurst{ 2437579f4b3764337b39087d10496af0e741cbfe570David A. Long unsigned long pc = regs->ARM_pc; 2447848786a7a198dd5e097330ad0cbfdf155a25499Jon Medhurst int rd = (insn >> 8) & 0xf; 2457848786a7a198dd5e097330ad0cbfdf155a25499Jon Medhurst 2467848786a7a198dd5e097330ad0cbfdf155a25499Jon Medhurst register unsigned long rdv asm("r1") = regs->uregs[rd]; 2477848786a7a198dd5e097330ad0cbfdf155a25499Jon Medhurst register unsigned long rnv asm("r2") = pc & ~3; 2487848786a7a198dd5e097330ad0cbfdf155a25499Jon Medhurst 2497848786a7a198dd5e097330ad0cbfdf155a25499Jon Medhurst __asm__ __volatile__ ( 2507848786a7a198dd5e097330ad0cbfdf155a25499Jon Medhurst "blx %[fn]" 2517848786a7a198dd5e097330ad0cbfdf155a25499Jon Medhurst : "=r" (rdv) 2527579f4b3764337b39087d10496af0e741cbfe570David A. Long : "0" (rdv), "r" (rnv), [fn] "r" (asi->insn_fn) 2537848786a7a198dd5e097330ad0cbfdf155a25499Jon Medhurst : "lr", "memory", "cc" 2547848786a7a198dd5e097330ad0cbfdf155a25499Jon Medhurst ); 2557848786a7a198dd5e097330ad0cbfdf155a25499Jon Medhurst 2567848786a7a198dd5e097330ad0cbfdf155a25499Jon Medhurst regs->uregs[rd] = rdv; 2577848786a7a198dd5e097330ad0cbfdf155a25499Jon Medhurst} 2587848786a7a198dd5e097330ad0cbfdf155a25499Jon Medhurst 2593e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Longstatic void __kprobes 260f145d664df502585618b12ed68c681f82153e02aDavid A. Longt32_emulate_rd8rn16_noflags(probes_opcode_t insn, 261b4cd605ca92d9a8a2f71355cb45dd943ebcb0c97David A. Long struct arch_probes_insn *asi, struct pt_regs *regs) 2627848786a7a198dd5e097330ad0cbfdf155a25499Jon Medhurst{ 2637848786a7a198dd5e097330ad0cbfdf155a25499Jon Medhurst int rd = (insn >> 8) & 0xf; 2647848786a7a198dd5e097330ad0cbfdf155a25499Jon Medhurst int rn = (insn >> 16) & 0xf; 2657848786a7a198dd5e097330ad0cbfdf155a25499Jon Medhurst 2667848786a7a198dd5e097330ad0cbfdf155a25499Jon Medhurst register unsigned long rdv asm("r1") = regs->uregs[rd]; 2677848786a7a198dd5e097330ad0cbfdf155a25499Jon Medhurst register unsigned long rnv asm("r2") = regs->uregs[rn]; 2687848786a7a198dd5e097330ad0cbfdf155a25499Jon Medhurst 2697848786a7a198dd5e097330ad0cbfdf155a25499Jon Medhurst __asm__ __volatile__ ( 2707848786a7a198dd5e097330ad0cbfdf155a25499Jon Medhurst "blx %[fn]" 2717848786a7a198dd5e097330ad0cbfdf155a25499Jon Medhurst : "=r" (rdv) 2727579f4b3764337b39087d10496af0e741cbfe570David A. Long : "0" (rdv), "r" (rnv), [fn] "r" (asi->insn_fn) 2737848786a7a198dd5e097330ad0cbfdf155a25499Jon Medhurst : "lr", "memory", "cc" 2747848786a7a198dd5e097330ad0cbfdf155a25499Jon Medhurst ); 2757848786a7a198dd5e097330ad0cbfdf155a25499Jon Medhurst 2767848786a7a198dd5e097330ad0cbfdf155a25499Jon Medhurst regs->uregs[rd] = rdv; 2777848786a7a198dd5e097330ad0cbfdf155a25499Jon Medhurst} 2787848786a7a198dd5e097330ad0cbfdf155a25499Jon Medhurst 2793e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Longstatic void __kprobes 280f145d664df502585618b12ed68c681f82153e02aDavid A. Longt32_emulate_rdlo12rdhi8rn16rm0_noflags(probes_opcode_t insn, 281b4cd605ca92d9a8a2f71355cb45dd943ebcb0c97David A. Long struct arch_probes_insn *asi, 2827579f4b3764337b39087d10496af0e741cbfe570David A. Long struct pt_regs *regs) 283231fb150c6f8a1f226380affc5498dd9abffc9d7Jon Medhurst{ 284231fb150c6f8a1f226380affc5498dd9abffc9d7Jon Medhurst int rdlo = (insn >> 12) & 0xf; 285231fb150c6f8a1f226380affc5498dd9abffc9d7Jon Medhurst int rdhi = (insn >> 8) & 0xf; 286231fb150c6f8a1f226380affc5498dd9abffc9d7Jon Medhurst int rn = (insn >> 16) & 0xf; 287231fb150c6f8a1f226380affc5498dd9abffc9d7Jon Medhurst int rm = insn & 0xf; 288231fb150c6f8a1f226380affc5498dd9abffc9d7Jon Medhurst 289231fb150c6f8a1f226380affc5498dd9abffc9d7Jon Medhurst register unsigned long rdlov asm("r0") = regs->uregs[rdlo]; 290231fb150c6f8a1f226380affc5498dd9abffc9d7Jon Medhurst register unsigned long rdhiv asm("r1") = regs->uregs[rdhi]; 291231fb150c6f8a1f226380affc5498dd9abffc9d7Jon Medhurst register unsigned long rnv asm("r2") = regs->uregs[rn]; 292231fb150c6f8a1f226380affc5498dd9abffc9d7Jon Medhurst register unsigned long rmv asm("r3") = regs->uregs[rm]; 293231fb150c6f8a1f226380affc5498dd9abffc9d7Jon Medhurst 294231fb150c6f8a1f226380affc5498dd9abffc9d7Jon Medhurst __asm__ __volatile__ ( 295231fb150c6f8a1f226380affc5498dd9abffc9d7Jon Medhurst "blx %[fn]" 296231fb150c6f8a1f226380affc5498dd9abffc9d7Jon Medhurst : "=r" (rdlov), "=r" (rdhiv) 297231fb150c6f8a1f226380affc5498dd9abffc9d7Jon Medhurst : "0" (rdlov), "1" (rdhiv), "r" (rnv), "r" (rmv), 2987579f4b3764337b39087d10496af0e741cbfe570David A. Long [fn] "r" (asi->insn_fn) 299231fb150c6f8a1f226380affc5498dd9abffc9d7Jon Medhurst : "lr", "memory", "cc" 300231fb150c6f8a1f226380affc5498dd9abffc9d7Jon Medhurst ); 301231fb150c6f8a1f226380affc5498dd9abffc9d7Jon Medhurst 302231fb150c6f8a1f226380affc5498dd9abffc9d7Jon Medhurst regs->uregs[rdlo] = rdlov; 303231fb150c6f8a1f226380affc5498dd9abffc9d7Jon Medhurst regs->uregs[rdhi] = rdhiv; 304231fb150c6f8a1f226380affc5498dd9abffc9d7Jon Medhurst} 30587abef63ead5ac9e2c67f0c07c461eda6be16aebDavid A. Long/* t16 thumb actions */ 306231fb150c6f8a1f226380affc5498dd9abffc9d7Jon Medhurst 3073e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Longstatic void __kprobes 308f145d664df502585618b12ed68c681f82153e02aDavid A. Longt16_simulate_bxblx(probes_opcode_t insn, 309b4cd605ca92d9a8a2f71355cb45dd943ebcb0c97David A. Long struct arch_probes_insn *asi, struct pt_regs *regs) 310a9c3c29e72cc459be0ecd597f0af11a67713175bJon Medhurst{ 3117579f4b3764337b39087d10496af0e741cbfe570David A. Long unsigned long pc = regs->ARM_pc + 2; 312a9c3c29e72cc459be0ecd597f0af11a67713175bJon Medhurst int rm = (insn >> 3) & 0xf; 313a9c3c29e72cc459be0ecd597f0af11a67713175bJon Medhurst unsigned long rmv = (rm == 15) ? pc : regs->uregs[rm]; 314a9c3c29e72cc459be0ecd597f0af11a67713175bJon Medhurst 315a9c3c29e72cc459be0ecd597f0af11a67713175bJon Medhurst if (insn & (1 << 7)) /* BLX ? */ 3167579f4b3764337b39087d10496af0e741cbfe570David A. Long regs->ARM_lr = regs->ARM_pc | 1; 317a9c3c29e72cc459be0ecd597f0af11a67713175bJon Medhurst 318a9c3c29e72cc459be0ecd597f0af11a67713175bJon Medhurst bx_write_pc(rmv, regs); 319a9c3c29e72cc459be0ecd597f0af11a67713175bJon Medhurst} 320a9c3c29e72cc459be0ecd597f0af11a67713175bJon Medhurst 3213e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Longstatic void __kprobes 322f145d664df502585618b12ed68c681f82153e02aDavid A. Longt16_simulate_ldr_literal(probes_opcode_t insn, 323b4cd605ca92d9a8a2f71355cb45dd943ebcb0c97David A. Long struct arch_probes_insn *asi, struct pt_regs *regs) 324f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst{ 3257579f4b3764337b39087d10496af0e741cbfe570David A. Long unsigned long *base = (unsigned long *)((regs->ARM_pc + 2) & ~3); 326f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst long index = insn & 0xff; 327f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst int rt = (insn >> 8) & 0x7; 328f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst regs->uregs[rt] = base[index]; 329f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst} 330f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst 3313e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Longstatic void __kprobes 332f145d664df502585618b12ed68c681f82153e02aDavid A. Longt16_simulate_ldrstr_sp_relative(probes_opcode_t insn, 333b4cd605ca92d9a8a2f71355cb45dd943ebcb0c97David A. Long struct arch_probes_insn *asi, struct pt_regs *regs) 334f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst{ 335f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst unsigned long* base = (unsigned long *)regs->ARM_sp; 336f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst long index = insn & 0xff; 337f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst int rt = (insn >> 8) & 0x7; 338f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst if (insn & 0x800) /* LDR */ 339f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst regs->uregs[rt] = base[index]; 340f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst else /* STR */ 341f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst base[index] = regs->uregs[rt]; 342f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst} 343f8695142820f3cb3bc97444a240eec5375a2b107Jon Medhurst 3443e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Longstatic void __kprobes 345f145d664df502585618b12ed68c681f82153e02aDavid A. Longt16_simulate_reladr(probes_opcode_t insn, 346b4cd605ca92d9a8a2f71355cb45dd943ebcb0c97David A. Long struct arch_probes_insn *asi, struct pt_regs *regs) 3472f335829040cb16d0640e87121bef208894d4934Jon Medhurst{ 3482f335829040cb16d0640e87121bef208894d4934Jon Medhurst unsigned long base = (insn & 0x800) ? regs->ARM_sp 3497579f4b3764337b39087d10496af0e741cbfe570David A. Long : ((regs->ARM_pc + 2) & ~3); 3502f335829040cb16d0640e87121bef208894d4934Jon Medhurst long offset = insn & 0xff; 3512f335829040cb16d0640e87121bef208894d4934Jon Medhurst int rt = (insn >> 8) & 0x7; 3522f335829040cb16d0640e87121bef208894d4934Jon Medhurst regs->uregs[rt] = base + offset * 4; 3532f335829040cb16d0640e87121bef208894d4934Jon Medhurst} 3542f335829040cb16d0640e87121bef208894d4934Jon Medhurst 3553e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Longstatic void __kprobes 356f145d664df502585618b12ed68c681f82153e02aDavid A. Longt16_simulate_add_sp_imm(probes_opcode_t insn, 357b4cd605ca92d9a8a2f71355cb45dd943ebcb0c97David A. Long struct arch_probes_insn *asi, struct pt_regs *regs) 3582f335829040cb16d0640e87121bef208894d4934Jon Medhurst{ 3592f335829040cb16d0640e87121bef208894d4934Jon Medhurst long imm = insn & 0x7f; 3602f335829040cb16d0640e87121bef208894d4934Jon Medhurst if (insn & 0x80) /* SUB */ 3612f335829040cb16d0640e87121bef208894d4934Jon Medhurst regs->ARM_sp -= imm * 4; 3622f335829040cb16d0640e87121bef208894d4934Jon Medhurst else /* ADD */ 3632f335829040cb16d0640e87121bef208894d4934Jon Medhurst regs->ARM_sp += imm * 4; 3642f335829040cb16d0640e87121bef208894d4934Jon Medhurst} 3652f335829040cb16d0640e87121bef208894d4934Jon Medhurst 3663e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Longstatic void __kprobes 367f145d664df502585618b12ed68c681f82153e02aDavid A. Longt16_simulate_cbz(probes_opcode_t insn, 368b4cd605ca92d9a8a2f71355cb45dd943ebcb0c97David A. Long struct arch_probes_insn *asi, struct pt_regs *regs) 36932818f31f8ed811ea7ef924f24642580a63a7c85Jon Medhurst{ 37032818f31f8ed811ea7ef924f24642580a63a7c85Jon Medhurst int rn = insn & 0x7; 371f145d664df502585618b12ed68c681f82153e02aDavid A. Long probes_opcode_t nonzero = regs->uregs[rn] ? insn : ~insn; 37232818f31f8ed811ea7ef924f24642580a63a7c85Jon Medhurst if (nonzero & 0x800) { 37332818f31f8ed811ea7ef924f24642580a63a7c85Jon Medhurst long i = insn & 0x200; 37432818f31f8ed811ea7ef924f24642580a63a7c85Jon Medhurst long imm5 = insn & 0xf8; 3757579f4b3764337b39087d10496af0e741cbfe570David A. Long unsigned long pc = regs->ARM_pc + 2; 37632818f31f8ed811ea7ef924f24642580a63a7c85Jon Medhurst regs->ARM_pc = pc + (i >> 3) + (imm5 >> 2); 37732818f31f8ed811ea7ef924f24642580a63a7c85Jon Medhurst } 37832818f31f8ed811ea7ef924f24642580a63a7c85Jon Medhurst} 37932818f31f8ed811ea7ef924f24642580a63a7c85Jon Medhurst 3803e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Longstatic void __kprobes 381f145d664df502585618b12ed68c681f82153e02aDavid A. Longt16_simulate_it(probes_opcode_t insn, 382b4cd605ca92d9a8a2f71355cb45dd943ebcb0c97David A. Long struct arch_probes_insn *asi, struct pt_regs *regs) 3835b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurst{ 3845b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurst /* 3855b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurst * The 8 IT state bits are split into two parts in CPSR: 3865b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurst * ITSTATE<1:0> are in CPSR<26:25> 3875b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurst * ITSTATE<7:2> are in CPSR<15:10> 3885b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurst * The new IT state is in the lower byte of insn. 3895b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurst */ 3905b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurst unsigned long cpsr = regs->ARM_cpsr; 3915b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurst cpsr &= ~PSR_IT_MASK; 3925b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurst cpsr |= (insn & 0xfc) << 8; 3935b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurst cpsr |= (insn & 0x03) << 25; 3945b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurst regs->ARM_cpsr = cpsr; 3955b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurst} 3965b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurst 3973e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Longstatic void __kprobes 398f145d664df502585618b12ed68c681f82153e02aDavid A. Longt16_singlestep_it(probes_opcode_t insn, 399b4cd605ca92d9a8a2f71355cb45dd943ebcb0c97David A. Long struct arch_probes_insn *asi, struct pt_regs *regs) 4005b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurst{ 4015b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurst regs->ARM_pc += 2; 4027579f4b3764337b39087d10496af0e741cbfe570David A. Long t16_simulate_it(insn, asi, regs); 4035b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurst} 4045b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurst 40544a0a59c535004eac9f18210cb2ce10b23861630David A. Longstatic enum probes_insn __kprobes 406b4cd605ca92d9a8a2f71355cb45dd943ebcb0c97David A. Longt16_decode_it(probes_opcode_t insn, struct arch_probes_insn *asi, 4073e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Long const struct decode_header *d) 4085b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurst{ 4095b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurst asi->insn_singlestep = t16_singlestep_it; 4105b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurst return INSN_GOOD_NO_SLOT; 4115b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurst} 4125b94faf8d76be2116223c2591b31ddae5eecac2bJon Medhurst 4133e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Longstatic void __kprobes 414f145d664df502585618b12ed68c681f82153e02aDavid A. Longt16_simulate_cond_branch(probes_opcode_t insn, 415b4cd605ca92d9a8a2f71355cb45dd943ebcb0c97David A. Long struct arch_probes_insn *asi, struct pt_regs *regs) 416396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurst{ 4177579f4b3764337b39087d10496af0e741cbfe570David A. Long unsigned long pc = regs->ARM_pc + 2; 418396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurst long offset = insn & 0x7f; 419396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurst offset -= insn & 0x80; /* Apply sign bit */ 420396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurst regs->ARM_pc = pc + (offset * 2); 421396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurst} 422396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurst 42344a0a59c535004eac9f18210cb2ce10b23861630David A. Longstatic enum probes_insn __kprobes 424b4cd605ca92d9a8a2f71355cb45dd943ebcb0c97David A. Longt16_decode_cond_branch(probes_opcode_t insn, struct arch_probes_insn *asi, 4253e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Long const struct decode_header *d) 426396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurst{ 427396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurst int cc = (insn >> 8) & 0xf; 428f145d664df502585618b12ed68c681f82153e02aDavid A. Long asi->insn_check_cc = probes_condition_checks[cc]; 429396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurst asi->insn_handler = t16_simulate_cond_branch; 430396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurst return INSN_GOOD_NO_SLOT; 431396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurst} 432396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurst 4333e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Longstatic void __kprobes 434f145d664df502585618b12ed68c681f82153e02aDavid A. Longt16_simulate_branch(probes_opcode_t insn, 435b4cd605ca92d9a8a2f71355cb45dd943ebcb0c97David A. Long struct arch_probes_insn *asi, struct pt_regs *regs) 436396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurst{ 4377579f4b3764337b39087d10496af0e741cbfe570David A. Long unsigned long pc = regs->ARM_pc + 2; 438396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurst long offset = insn & 0x3ff; 439396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurst offset -= insn & 0x400; /* Apply sign bit */ 440396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurst regs->ARM_pc = pc + (offset * 2); 441396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurst} 442396b41f68d937a0c48ba624186ed06288b35bb4eJon Medhurst 44302d194f64772aee91e7319ca033905b0bafee04cJon Medhurststatic unsigned long __kprobes 444f145d664df502585618b12ed68c681f82153e02aDavid A. Longt16_emulate_loregs(probes_opcode_t insn, 445b4cd605ca92d9a8a2f71355cb45dd943ebcb0c97David A. Long struct arch_probes_insn *asi, struct pt_regs *regs) 44602d194f64772aee91e7319ca033905b0bafee04cJon Medhurst{ 44702d194f64772aee91e7319ca033905b0bafee04cJon Medhurst unsigned long oldcpsr = regs->ARM_cpsr; 44802d194f64772aee91e7319ca033905b0bafee04cJon Medhurst unsigned long newcpsr; 44902d194f64772aee91e7319ca033905b0bafee04cJon Medhurst 45002d194f64772aee91e7319ca033905b0bafee04cJon Medhurst __asm__ __volatile__ ( 45102d194f64772aee91e7319ca033905b0bafee04cJon Medhurst "msr cpsr_fs, %[oldcpsr] \n\t" 45202d194f64772aee91e7319ca033905b0bafee04cJon Medhurst "ldmia %[regs], {r0-r7} \n\t" 45302d194f64772aee91e7319ca033905b0bafee04cJon Medhurst "blx %[fn] \n\t" 45402d194f64772aee91e7319ca033905b0bafee04cJon Medhurst "stmia %[regs], {r0-r7} \n\t" 45502d194f64772aee91e7319ca033905b0bafee04cJon Medhurst "mrs %[newcpsr], cpsr \n\t" 45602d194f64772aee91e7319ca033905b0bafee04cJon Medhurst : [newcpsr] "=r" (newcpsr) 45702d194f64772aee91e7319ca033905b0bafee04cJon Medhurst : [oldcpsr] "r" (oldcpsr), [regs] "r" (regs), 4587579f4b3764337b39087d10496af0e741cbfe570David A. Long [fn] "r" (asi->insn_fn) 45902d194f64772aee91e7319ca033905b0bafee04cJon Medhurst : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", 46002d194f64772aee91e7319ca033905b0bafee04cJon Medhurst "lr", "memory", "cc" 46102d194f64772aee91e7319ca033905b0bafee04cJon Medhurst ); 46202d194f64772aee91e7319ca033905b0bafee04cJon Medhurst 46302d194f64772aee91e7319ca033905b0bafee04cJon Medhurst return (oldcpsr & ~APSR_MASK) | (newcpsr & APSR_MASK); 46402d194f64772aee91e7319ca033905b0bafee04cJon Medhurst} 46502d194f64772aee91e7319ca033905b0bafee04cJon Medhurst 4663e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Longstatic void __kprobes 467f145d664df502585618b12ed68c681f82153e02aDavid A. Longt16_emulate_loregs_rwflags(probes_opcode_t insn, 468b4cd605ca92d9a8a2f71355cb45dd943ebcb0c97David A. Long struct arch_probes_insn *asi, struct pt_regs *regs) 46902d194f64772aee91e7319ca033905b0bafee04cJon Medhurst{ 4707579f4b3764337b39087d10496af0e741cbfe570David A. Long regs->ARM_cpsr = t16_emulate_loregs(insn, asi, regs); 47102d194f64772aee91e7319ca033905b0bafee04cJon Medhurst} 47202d194f64772aee91e7319ca033905b0bafee04cJon Medhurst 4733e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Longstatic void __kprobes 474f145d664df502585618b12ed68c681f82153e02aDavid A. Longt16_emulate_loregs_noitrwflags(probes_opcode_t insn, 475b4cd605ca92d9a8a2f71355cb45dd943ebcb0c97David A. Long struct arch_probes_insn *asi, struct pt_regs *regs) 47602d194f64772aee91e7319ca033905b0bafee04cJon Medhurst{ 4777579f4b3764337b39087d10496af0e741cbfe570David A. Long unsigned long cpsr = t16_emulate_loregs(insn, asi, regs); 47802d194f64772aee91e7319ca033905b0bafee04cJon Medhurst if (!in_it_block(cpsr)) 47902d194f64772aee91e7319ca033905b0bafee04cJon Medhurst regs->ARM_cpsr = cpsr; 48002d194f64772aee91e7319ca033905b0bafee04cJon Medhurst} 48102d194f64772aee91e7319ca033905b0bafee04cJon Medhurst 4823e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Longstatic void __kprobes 483f145d664df502585618b12ed68c681f82153e02aDavid A. Longt16_emulate_hiregs(probes_opcode_t insn, 484b4cd605ca92d9a8a2f71355cb45dd943ebcb0c97David A. Long struct arch_probes_insn *asi, struct pt_regs *regs) 4853b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst{ 4867579f4b3764337b39087d10496af0e741cbfe570David A. Long unsigned long pc = regs->ARM_pc + 2; 4873b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst int rdn = (insn & 0x7) | ((insn & 0x80) >> 4); 4883b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst int rm = (insn >> 3) & 0xf; 4893b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst 4903b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst register unsigned long rdnv asm("r1"); 4913b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst register unsigned long rmv asm("r0"); 4923b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst unsigned long cpsr = regs->ARM_cpsr; 4933b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst 4943b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst rdnv = (rdn == 15) ? pc : regs->uregs[rdn]; 4953b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst rmv = (rm == 15) ? pc : regs->uregs[rm]; 4963b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst 4973b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst __asm__ __volatile__ ( 4983b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst "msr cpsr_fs, %[cpsr] \n\t" 4993b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst "blx %[fn] \n\t" 5003b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst "mrs %[cpsr], cpsr \n\t" 5013b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst : "=r" (rdnv), [cpsr] "=r" (cpsr) 5027579f4b3764337b39087d10496af0e741cbfe570David A. Long : "0" (rdnv), "r" (rmv), "1" (cpsr), [fn] "r" (asi->insn_fn) 5033b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst : "lr", "memory", "cc" 5043b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst ); 5053b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst 5063b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst if (rdn == 15) 5073b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst rdnv &= ~1; 5083b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst 5093b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst regs->uregs[rdn] = rdnv; 5103b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK); 5113b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst} 5123b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst 51344a0a59c535004eac9f18210cb2ce10b23861630David A. Longstatic enum probes_insn __kprobes 514b4cd605ca92d9a8a2f71355cb45dd943ebcb0c97David A. Longt16_decode_hiregs(probes_opcode_t insn, struct arch_probes_insn *asi, 5153e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Long const struct decode_header *d) 5163b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst{ 5173b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst insn &= ~0x00ff; 5183b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst insn |= 0x001; /* Set Rdn = R1 and Rm = R0 */ 519888be25402021a425da3e85e2d5a954d7509286eBen Dooks ((u16 *)asi->insn)[0] = __opcode_to_mem_thumb16(insn); 5203b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst asi->insn_handler = t16_emulate_hiregs; 5213b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst return INSN_GOOD; 5223b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst} 5233b5940e81182ff26d539dcf0ee8b2310f6965833Jon Medhurst 5243e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Longstatic void __kprobes 525f145d664df502585618b12ed68c681f82153e02aDavid A. Longt16_emulate_push(probes_opcode_t insn, 526b4cd605ca92d9a8a2f71355cb45dd943ebcb0c97David A. Long struct arch_probes_insn *asi, struct pt_regs *regs) 527fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst{ 528fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst __asm__ __volatile__ ( 529fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst "ldr r9, [%[regs], #13*4] \n\t" 530fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst "ldr r8, [%[regs], #14*4] \n\t" 531fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst "ldmia %[regs], {r0-r7} \n\t" 532fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst "blx %[fn] \n\t" 533fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst "str r9, [%[regs], #13*4] \n\t" 534fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst : 5357579f4b3764337b39087d10496af0e741cbfe570David A. Long : [regs] "r" (regs), [fn] "r" (asi->insn_fn) 536fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", 537fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst "lr", "memory", "cc" 538fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst ); 539fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst} 540fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst 54144a0a59c535004eac9f18210cb2ce10b23861630David A. Longstatic enum probes_insn __kprobes 542b4cd605ca92d9a8a2f71355cb45dd943ebcb0c97David A. Longt16_decode_push(probes_opcode_t insn, struct arch_probes_insn *asi, 5433e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Long const struct decode_header *d) 544fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst{ 545fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst /* 546fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst * To simulate a PUSH we use a Thumb-2 "STMDB R9!, {registers}" 547fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst * and call it with R9=SP and LR in the register list represented 548fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst * by R8. 549fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst */ 550888be25402021a425da3e85e2d5a954d7509286eBen Dooks /* 1st half STMDB R9!,{} */ 551888be25402021a425da3e85e2d5a954d7509286eBen Dooks ((u16 *)asi->insn)[0] = __opcode_to_mem_thumb16(0xe929); 552888be25402021a425da3e85e2d5a954d7509286eBen Dooks /* 2nd half (register list) */ 553888be25402021a425da3e85e2d5a954d7509286eBen Dooks ((u16 *)asi->insn)[1] = __opcode_to_mem_thumb16(insn & 0x1ff); 554fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst asi->insn_handler = t16_emulate_push; 555fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst return INSN_GOOD; 556fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst} 557fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst 5583e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Longstatic void __kprobes 559f145d664df502585618b12ed68c681f82153e02aDavid A. Longt16_emulate_pop_nopc(probes_opcode_t insn, 560b4cd605ca92d9a8a2f71355cb45dd943ebcb0c97David A. Long struct arch_probes_insn *asi, struct pt_regs *regs) 561fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst{ 562fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst __asm__ __volatile__ ( 563fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst "ldr r9, [%[regs], #13*4] \n\t" 564fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst "ldmia %[regs], {r0-r7} \n\t" 565fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst "blx %[fn] \n\t" 566fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst "stmia %[regs], {r0-r7} \n\t" 567fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst "str r9, [%[regs], #13*4] \n\t" 568fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst : 5697579f4b3764337b39087d10496af0e741cbfe570David A. Long : [regs] "r" (regs), [fn] "r" (asi->insn_fn) 570fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r9", 571fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst "lr", "memory", "cc" 572fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst ); 573fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst} 574fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst 5753e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Longstatic void __kprobes 576f145d664df502585618b12ed68c681f82153e02aDavid A. Longt16_emulate_pop_pc(probes_opcode_t insn, 577b4cd605ca92d9a8a2f71355cb45dd943ebcb0c97David A. Long struct arch_probes_insn *asi, struct pt_regs *regs) 578fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst{ 579fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst register unsigned long pc asm("r8"); 580fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst 581fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst __asm__ __volatile__ ( 582fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst "ldr r9, [%[regs], #13*4] \n\t" 583fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst "ldmia %[regs], {r0-r7} \n\t" 584fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst "blx %[fn] \n\t" 585fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst "stmia %[regs], {r0-r7} \n\t" 586fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst "str r9, [%[regs], #13*4] \n\t" 587fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst : "=r" (pc) 5887579f4b3764337b39087d10496af0e741cbfe570David A. Long : [regs] "r" (regs), [fn] "r" (asi->insn_fn) 589fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r9", 590fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst "lr", "memory", "cc" 591fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst ); 592fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst 593fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst bx_write_pc(pc, regs); 594fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst} 595fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst 59644a0a59c535004eac9f18210cb2ce10b23861630David A. Longstatic enum probes_insn __kprobes 597b4cd605ca92d9a8a2f71355cb45dd943ebcb0c97David A. Longt16_decode_pop(probes_opcode_t insn, struct arch_probes_insn *asi, 5983e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Long const struct decode_header *d) 599fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst{ 600fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst /* 601fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst * To simulate a POP we use a Thumb-2 "LDMDB R9!, {registers}" 602fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst * and call it with R9=SP and PC in the register list represented 603fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst * by R8. 604fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst */ 605888be25402021a425da3e85e2d5a954d7509286eBen Dooks /* 1st half LDMIA R9!,{} */ 606888be25402021a425da3e85e2d5a954d7509286eBen Dooks ((u16 *)asi->insn)[0] = __opcode_to_mem_thumb16(0xe8b9); 607888be25402021a425da3e85e2d5a954d7509286eBen Dooks /* 2nd half (register list) */ 608888be25402021a425da3e85e2d5a954d7509286eBen Dooks ((u16 *)asi->insn)[1] = __opcode_to_mem_thumb16(insn & 0x1ff); 609fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst asi->insn_handler = insn & 0x100 ? t16_emulate_pop_pc 610fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst : t16_emulate_pop_nopc; 611fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst return INSN_GOOD; 612fd0c8d8a48c57cb8a3f1fbbe46a2b208b57ff477Jon Medhurst} 6133e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Long 6143e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Longconst union decode_action kprobes_t16_actions[NUM_PROBES_T16_ACTIONS] = { 6153e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Long [PROBES_T16_ADD_SP] = {.handler = t16_simulate_add_sp_imm}, 6163e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Long [PROBES_T16_CBZ] = {.handler = t16_simulate_cbz}, 6173e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Long [PROBES_T16_SIGN_EXTEND] = {.handler = t16_emulate_loregs_rwflags}, 6183e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Long [PROBES_T16_PUSH] = {.decoder = t16_decode_push}, 6193e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Long [PROBES_T16_POP] = {.decoder = t16_decode_pop}, 620eb73ea97e63bb06bf98ff052615ce181bc7f69ecDavid A. Long [PROBES_T16_SEV] = {.handler = probes_emulate_none}, 621eb73ea97e63bb06bf98ff052615ce181bc7f69ecDavid A. Long [PROBES_T16_WFE] = {.handler = probes_simulate_nop}, 6223e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Long [PROBES_T16_IT] = {.decoder = t16_decode_it}, 6233e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Long [PROBES_T16_CMP] = {.handler = t16_emulate_loregs_rwflags}, 6243e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Long [PROBES_T16_ADDSUB] = {.handler = t16_emulate_loregs_noitrwflags}, 6253e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Long [PROBES_T16_LOGICAL] = {.handler = t16_emulate_loregs_noitrwflags}, 6263e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Long [PROBES_T16_LDR_LIT] = {.handler = t16_simulate_ldr_literal}, 6273e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Long [PROBES_T16_BLX] = {.handler = t16_simulate_bxblx}, 6283e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Long [PROBES_T16_HIREGOPS] = {.decoder = t16_decode_hiregs}, 6293e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Long [PROBES_T16_LDRHSTRH] = {.handler = t16_emulate_loregs_rwflags}, 6303e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Long [PROBES_T16_LDRSTR] = {.handler = t16_simulate_ldrstr_sp_relative}, 6313e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Long [PROBES_T16_ADR] = {.handler = t16_simulate_reladr}, 6323e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Long [PROBES_T16_LDMSTM] = {.handler = t16_emulate_loregs_rwflags}, 6333e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Long [PROBES_T16_BRANCH_COND] = {.decoder = t16_decode_cond_branch}, 6343e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Long [PROBES_T16_BRANCH] = {.handler = t16_simulate_branch}, 6353e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Long}; 6363e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Long 6373e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Longconst union decode_action kprobes_t32_actions[NUM_PROBES_T32_ACTIONS] = { 6383e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Long [PROBES_T32_LDMSTM] = {.decoder = t32_decode_ldmstm}, 6393e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Long [PROBES_T32_LDRDSTRD] = {.handler = t32_emulate_ldrdstrd}, 6403e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Long [PROBES_T32_TABLE_BRANCH] = {.handler = t32_simulate_table_branch}, 6413e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Long [PROBES_T32_TST] = {.handler = t32_emulate_rd8rn16rm0_rwflags}, 6423e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Long [PROBES_T32_MOV] = {.handler = t32_emulate_rd8rn16rm0_rwflags}, 6433e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Long [PROBES_T32_ADDSUB] = {.handler = t32_emulate_rd8rn16rm0_rwflags}, 6443e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Long [PROBES_T32_LOGICAL] = {.handler = t32_emulate_rd8rn16rm0_rwflags}, 6453e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Long [PROBES_T32_CMP] = {.handler = t32_emulate_rd8rn16rm0_rwflags}, 6463e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Long [PROBES_T32_ADDWSUBW_PC] = {.handler = t32_emulate_rd8pc16_noflags,}, 6473e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Long [PROBES_T32_ADDWSUBW] = {.handler = t32_emulate_rd8rn16_noflags}, 6483e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Long [PROBES_T32_MOVW] = {.handler = t32_emulate_rd8rn16_noflags}, 6493e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Long [PROBES_T32_SAT] = {.handler = t32_emulate_rd8rn16rm0_rwflags}, 6503e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Long [PROBES_T32_BITFIELD] = {.handler = t32_emulate_rd8rn16_noflags}, 651eb73ea97e63bb06bf98ff052615ce181bc7f69ecDavid A. Long [PROBES_T32_SEV] = {.handler = probes_emulate_none}, 652eb73ea97e63bb06bf98ff052615ce181bc7f69ecDavid A. Long [PROBES_T32_WFE] = {.handler = probes_simulate_nop}, 6533e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Long [PROBES_T32_MRS] = {.handler = t32_simulate_mrs}, 6543e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Long [PROBES_T32_BRANCH_COND] = {.decoder = t32_decode_cond_branch}, 6553e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Long [PROBES_T32_BRANCH] = {.handler = t32_simulate_branch}, 656eb73ea97e63bb06bf98ff052615ce181bc7f69ecDavid A. Long [PROBES_T32_PLDI] = {.handler = probes_simulate_nop}, 6573e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Long [PROBES_T32_LDR_LIT] = {.handler = t32_simulate_ldr_literal}, 6583e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Long [PROBES_T32_LDRSTR] = {.handler = t32_emulate_ldrstr}, 6593e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Long [PROBES_T32_SIGN_EXTEND] = {.handler = t32_emulate_rd8rn16rm0_rwflags}, 6603e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Long [PROBES_T32_MEDIA] = {.handler = t32_emulate_rd8rn16rm0_rwflags}, 6613e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Long [PROBES_T32_REVERSE] = {.handler = t32_emulate_rd8rn16_noflags}, 6623e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Long [PROBES_T32_MUL_ADD] = {.handler = t32_emulate_rd8rn16rm0_rwflags}, 6633e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Long [PROBES_T32_MUL_ADD2] = {.handler = t32_emulate_rd8rn16rm0ra12_noflags}, 6643e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Long [PROBES_T32_MUL_ADD_LONG] = { 6653e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Long .handler = t32_emulate_rdlo12rdhi8rn16rm0_noflags}, 6663e6cd394bb10c2d65322e5f5d2ff0a9074d903a1David A. Long}; 667