diff --git a/arch/arm/kernel/kprobes-arm.c b/arch/arm/kernel/kprobes-arm.c index a1d0a8f00f9e..8ebd84c48867 100644 --- a/arch/arm/kernel/kprobes-arm.c +++ b/arch/arm/kernel/kprobes-arm.c @@ -73,7 +73,7 @@ #endif -void __kprobes +static void __kprobes emulate_ldrdstrd(struct kprobe *p, struct pt_regs *regs) { kprobe_opcode_t insn = p->opcode; @@ -102,7 +102,7 @@ emulate_ldrdstrd(struct kprobe *p, struct pt_regs *regs) regs->uregs[rn] = rnv; } -void __kprobes +static void __kprobes emulate_ldr(struct kprobe *p, struct pt_regs *regs) { kprobe_opcode_t insn = p->opcode; @@ -132,7 +132,7 @@ emulate_ldr(struct kprobe *p, struct pt_regs *regs) regs->uregs[rn] = rnv; } -void __kprobes +static void __kprobes emulate_str(struct kprobe *p, struct pt_regs *regs) { kprobe_opcode_t insn = p->opcode; @@ -159,7 +159,7 @@ emulate_str(struct kprobe *p, struct pt_regs *regs) regs->uregs[rn] = rnv; } -void __kprobes +static void __kprobes emulate_rd12rn16rm0rs8_rwflags(struct kprobe *p, struct pt_regs *regs) { kprobe_opcode_t insn = p->opcode; @@ -194,7 +194,7 @@ emulate_rd12rn16rm0rs8_rwflags(struct kprobe *p, struct pt_regs *regs) regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK); } -void __kprobes +static void __kprobes emulate_rd12rn16rm0_rwflags_nopc(struct kprobe *p, struct pt_regs *regs) { kprobe_opcode_t insn = p->opcode; @@ -221,7 +221,7 @@ emulate_rd12rn16rm0_rwflags_nopc(struct kprobe *p, struct pt_regs *regs) regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK); } -void __kprobes +static void __kprobes emulate_rd16rn12rm0rs8_rwflags_nopc(struct kprobe *p, struct pt_regs *regs) { kprobe_opcode_t insn = p->opcode; @@ -250,7 +250,7 @@ emulate_rd16rn12rm0rs8_rwflags_nopc(struct kprobe *p, struct pt_regs *regs) regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK); } -void __kprobes +static void __kprobes emulate_rd12rm0_noflags_nopc(struct kprobe *p, struct pt_regs *regs) { kprobe_opcode_t insn = p->opcode; @@ -270,7 +270,7 @@ emulate_rd12rm0_noflags_nopc(struct kprobe *p, struct pt_regs *regs) regs->uregs[rd] = rdv; } -void __kprobes +static void __kprobes emulate_rdlo12rdhi16rn0rm8_rwflags_nopc(struct kprobe *p, struct pt_regs *regs) { kprobe_opcode_t insn = p->opcode; @@ -299,3 +299,44 @@ emulate_rdlo12rdhi16rn0rm8_rwflags_nopc(struct kprobe *p, struct pt_regs *regs) regs->uregs[rdhi] = rdhiv; regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK); } + +const union decode_action kprobes_arm_actions[NUM_PROBES_ARM_ACTIONS] = { + [PROBES_EMULATE_NONE] = {.handler = kprobe_emulate_none}, + [PROBES_SIMULATE_NOP] = {.handler = kprobe_simulate_nop}, + [PROBES_PRELOAD_IMM] = {.handler = kprobe_simulate_nop}, + [PROBES_PRELOAD_REG] = {.handler = kprobe_simulate_nop}, + [PROBES_BRANCH_IMM] = {.handler = simulate_blx1}, + [PROBES_MRS] = {.handler = simulate_mrs}, + [PROBES_BRANCH_REG] = {.handler = simulate_blx2bx}, + [PROBES_CLZ] = {.handler = emulate_rd12rm0_noflags_nopc}, + [PROBES_SATURATING_ARITHMETIC] = { + .handler = emulate_rd12rn16rm0_rwflags_nopc}, + [PROBES_MUL1] = {.handler = emulate_rdlo12rdhi16rn0rm8_rwflags_nopc}, + [PROBES_MUL2] = {.handler = emulate_rd16rn12rm0rs8_rwflags_nopc}, + [PROBES_SWP] = {.handler = emulate_rd12rn16rm0_rwflags_nopc}, + [PROBES_LDRSTRD] = {.handler = emulate_ldrdstrd}, + [PROBES_LOAD_EXTRA] = {.handler = emulate_ldr}, + [PROBES_LOAD] = {.handler = emulate_ldr}, + [PROBES_STORE_EXTRA] = {.handler = emulate_str}, + [PROBES_STORE] = {.handler = emulate_str}, + [PROBES_MOV_IP_SP] = {.handler = simulate_mov_ipsp}, + [PROBES_DATA_PROCESSING_REG] = { + .handler = emulate_rd12rn16rm0rs8_rwflags}, + [PROBES_DATA_PROCESSING_IMM] = { + .handler = emulate_rd12rn16rm0rs8_rwflags}, + [PROBES_MOV_HALFWORD] = {.handler = emulate_rd12rm0_noflags_nopc}, + [PROBES_SEV] = {.handler = kprobe_emulate_none}, + [PROBES_WFE] = {.handler = kprobe_simulate_nop}, + [PROBES_SATURATE] = {.handler = emulate_rd12rn16rm0_rwflags_nopc}, + [PROBES_REV] = {.handler = emulate_rd12rm0_noflags_nopc}, + [PROBES_MMI] = {.handler = emulate_rd12rn16rm0_rwflags_nopc}, + [PROBES_PACK] = {.handler = emulate_rd12rn16rm0_rwflags_nopc}, + [PROBES_EXTEND] = {.handler = emulate_rd12rm0_noflags_nopc}, + [PROBES_EXTEND_ADD] = {.handler = emulate_rd12rn16rm0_rwflags_nopc}, + [PROBES_MUL_ADD_LONG] = { + .handler = emulate_rdlo12rdhi16rn0rm8_rwflags_nopc}, + [PROBES_MUL_ADD] = {.handler = emulate_rd16rn12rm0rs8_rwflags_nopc}, + [PROBES_BITFIELD] = {.handler = emulate_rd12rm0_noflags_nopc}, + [PROBES_BRANCH] = {.handler = simulate_bbl}, + [PROBES_LDMSTM] = {.decoder = kprobe_decode_ldmstm} +}; diff --git a/arch/arm/kernel/kprobes-common.c b/arch/arm/kernel/kprobes-common.c index f02c038059c3..029b79c6face 100644 --- a/arch/arm/kernel/kprobes-common.c +++ b/arch/arm/kernel/kprobes-common.c @@ -112,7 +112,8 @@ emulate_ldm_r3_15(struct kprobe *p, struct pt_regs *regs) } enum kprobe_insn __kprobes -kprobe_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi) +kprobe_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi, + const struct decode_header *h) { kprobe_insn_handler_t *handler = 0; unsigned reglist = insn & 0xffff; diff --git a/arch/arm/kernel/kprobes-thumb.c b/arch/arm/kernel/kprobes-thumb.c index 977f21723a9c..d83f6092920a 100644 --- a/arch/arm/kernel/kprobes-thumb.c +++ b/arch/arm/kernel/kprobes-thumb.c @@ -16,6 +16,10 @@ #include "kprobes.h" #include "probes-thumb.h" +/* These emulation encodings are functionally equivalent... */ +#define t32_emulate_rd8rn16rm0ra12_noflags \ + t32_emulate_rdlo12rdhi8rn16rm0_noflags + /* * Return the PC value for a probe in thumb code. * This is the address of the probed instruction plus 4. @@ -29,7 +33,7 @@ static inline unsigned long __kprobes thumb_probe_pc(struct kprobe *p) /* t32 thumb actions */ -void __kprobes +static void __kprobes t32_simulate_table_branch(struct kprobe *p, struct pt_regs *regs) { kprobe_opcode_t insn = p->opcode; @@ -49,7 +53,7 @@ t32_simulate_table_branch(struct kprobe *p, struct pt_regs *regs) regs->ARM_pc = pc + 2 * halfwords; } -void __kprobes +static void __kprobes t32_simulate_mrs(struct kprobe *p, struct pt_regs *regs) { kprobe_opcode_t insn = p->opcode; @@ -58,7 +62,7 @@ t32_simulate_mrs(struct kprobe *p, struct pt_regs *regs) regs->uregs[rd] = regs->ARM_cpsr & mask; } -void __kprobes +static void __kprobes t32_simulate_cond_branch(struct kprobe *p, struct pt_regs *regs) { kprobe_opcode_t insn = p->opcode; @@ -73,8 +77,9 @@ t32_simulate_cond_branch(struct kprobe *p, struct pt_regs *regs) regs->ARM_pc = pc + (offset * 2); } -enum kprobe_insn __kprobes -t32_decode_cond_branch(kprobe_opcode_t insn, struct arch_specific_insn *asi) +static enum kprobe_insn __kprobes +t32_decode_cond_branch(kprobe_opcode_t insn, struct arch_specific_insn *asi, + const struct decode_header *d) { int cc = (insn >> 22) & 0xf; asi->insn_check_cc = kprobe_condition_checks[cc]; @@ -82,7 +87,7 @@ t32_decode_cond_branch(kprobe_opcode_t insn, struct arch_specific_insn *asi) return INSN_GOOD_NO_SLOT; } -void __kprobes +static void __kprobes t32_simulate_branch(struct kprobe *p, struct pt_regs *regs) { kprobe_opcode_t insn = p->opcode; @@ -110,7 +115,7 @@ t32_simulate_branch(struct kprobe *p, struct pt_regs *regs) regs->ARM_pc = pc + (offset * 2); } -void __kprobes +static void __kprobes t32_simulate_ldr_literal(struct kprobe *p, struct pt_regs *regs) { kprobe_opcode_t insn = p->opcode; @@ -148,10 +153,11 @@ t32_simulate_ldr_literal(struct kprobe *p, struct pt_regs *regs) regs->uregs[rt] = rtv; } -enum kprobe_insn __kprobes -t32_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi) +static enum kprobe_insn __kprobes +t32_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi, + const struct decode_header *d) { - enum kprobe_insn ret = kprobe_decode_ldmstm(insn, asi); + enum kprobe_insn ret = kprobe_decode_ldmstm(insn, asi, d); /* Fixup modified instruction to have halfwords in correct order...*/ insn = asi->insn[0]; @@ -161,7 +167,7 @@ t32_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi) return ret; } -void __kprobes +static void __kprobes t32_emulate_ldrdstrd(struct kprobe *p, struct pt_regs *regs) { kprobe_opcode_t insn = p->opcode; @@ -188,7 +194,7 @@ t32_emulate_ldrdstrd(struct kprobe *p, struct pt_regs *regs) regs->uregs[rt2] = rt2v; } -void __kprobes +static void __kprobes t32_emulate_ldrstr(struct kprobe *p, struct pt_regs *regs) { kprobe_opcode_t insn = p->opcode; @@ -214,7 +220,7 @@ t32_emulate_ldrstr(struct kprobe *p, struct pt_regs *regs) regs->uregs[rt] = rtv; } -void __kprobes +static void __kprobes t32_emulate_rd8rn16rm0_rwflags(struct kprobe *p, struct pt_regs *regs) { kprobe_opcode_t insn = p->opcode; @@ -241,7 +247,7 @@ t32_emulate_rd8rn16rm0_rwflags(struct kprobe *p, struct pt_regs *regs) regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK); } -void __kprobes +static void __kprobes t32_emulate_rd8pc16_noflags(struct kprobe *p, struct pt_regs *regs) { kprobe_opcode_t insn = p->opcode; @@ -261,7 +267,7 @@ t32_emulate_rd8pc16_noflags(struct kprobe *p, struct pt_regs *regs) regs->uregs[rd] = rdv; } -void __kprobes +static void __kprobes t32_emulate_rd8rn16_noflags(struct kprobe *p, struct pt_regs *regs) { kprobe_opcode_t insn = p->opcode; @@ -281,7 +287,7 @@ t32_emulate_rd8rn16_noflags(struct kprobe *p, struct pt_regs *regs) regs->uregs[rd] = rdv; } -void __kprobes +static void __kprobes t32_emulate_rdlo12rdhi8rn16rm0_noflags(struct kprobe *p, struct pt_regs *regs) { kprobe_opcode_t insn = p->opcode; @@ -308,7 +314,7 @@ t32_emulate_rdlo12rdhi8rn16rm0_noflags(struct kprobe *p, struct pt_regs *regs) } /* t16 thumb actions */ -void __kprobes +static void __kprobes t16_simulate_bxblx(struct kprobe *p, struct pt_regs *regs) { kprobe_opcode_t insn = p->opcode; @@ -322,7 +328,7 @@ t16_simulate_bxblx(struct kprobe *p, struct pt_regs *regs) bx_write_pc(rmv, regs); } -void __kprobes +static void __kprobes t16_simulate_ldr_literal(struct kprobe *p, struct pt_regs *regs) { kprobe_opcode_t insn = p->opcode; @@ -332,7 +338,7 @@ t16_simulate_ldr_literal(struct kprobe *p, struct pt_regs *regs) regs->uregs[rt] = base[index]; } -void __kprobes +static void __kprobes t16_simulate_ldrstr_sp_relative(struct kprobe *p, struct pt_regs *regs) { kprobe_opcode_t insn = p->opcode; @@ -345,7 +351,7 @@ t16_simulate_ldrstr_sp_relative(struct kprobe *p, struct pt_regs *regs) base[index] = regs->uregs[rt]; } -void __kprobes +static void __kprobes t16_simulate_reladr(struct kprobe *p, struct pt_regs *regs) { kprobe_opcode_t insn = p->opcode; @@ -356,7 +362,7 @@ t16_simulate_reladr(struct kprobe *p, struct pt_regs *regs) regs->uregs[rt] = base + offset * 4; } -void __kprobes +static void __kprobes t16_simulate_add_sp_imm(struct kprobe *p, struct pt_regs *regs) { kprobe_opcode_t insn = p->opcode; @@ -367,7 +373,7 @@ t16_simulate_add_sp_imm(struct kprobe *p, struct pt_regs *regs) regs->ARM_sp += imm * 4; } -void __kprobes +static void __kprobes t16_simulate_cbz(struct kprobe *p, struct pt_regs *regs) { kprobe_opcode_t insn = p->opcode; @@ -381,7 +387,7 @@ t16_simulate_cbz(struct kprobe *p, struct pt_regs *regs) } } -void __kprobes +static void __kprobes t16_simulate_it(struct kprobe *p, struct pt_regs *regs) { /* @@ -398,21 +404,22 @@ t16_simulate_it(struct kprobe *p, struct pt_regs *regs) regs->ARM_cpsr = cpsr; } -void __kprobes +static void __kprobes t16_singlestep_it(struct kprobe *p, struct pt_regs *regs) { regs->ARM_pc += 2; t16_simulate_it(p, regs); } -enum kprobe_insn __kprobes -t16_decode_it(kprobe_opcode_t insn, struct arch_specific_insn *asi) +static enum kprobe_insn __kprobes +t16_decode_it(kprobe_opcode_t insn, struct arch_specific_insn *asi, + const struct decode_header *d) { asi->insn_singlestep = t16_singlestep_it; return INSN_GOOD_NO_SLOT; } -void __kprobes +static void __kprobes t16_simulate_cond_branch(struct kprobe *p, struct pt_regs *regs) { kprobe_opcode_t insn = p->opcode; @@ -422,8 +429,9 @@ t16_simulate_cond_branch(struct kprobe *p, struct pt_regs *regs) regs->ARM_pc = pc + (offset * 2); } -enum kprobe_insn __kprobes -t16_decode_cond_branch(kprobe_opcode_t insn, struct arch_specific_insn *asi) +static enum kprobe_insn __kprobes +t16_decode_cond_branch(kprobe_opcode_t insn, struct arch_specific_insn *asi, + const struct decode_header *d) { int cc = (insn >> 8) & 0xf; asi->insn_check_cc = kprobe_condition_checks[cc]; @@ -431,7 +439,7 @@ t16_decode_cond_branch(kprobe_opcode_t insn, struct arch_specific_insn *asi) return INSN_GOOD_NO_SLOT; } -void __kprobes +static void __kprobes t16_simulate_branch(struct kprobe *p, struct pt_regs *regs) { kprobe_opcode_t insn = p->opcode; @@ -463,13 +471,13 @@ t16_emulate_loregs(struct kprobe *p, struct pt_regs *regs) return (oldcpsr & ~APSR_MASK) | (newcpsr & APSR_MASK); } -void __kprobes +static void __kprobes t16_emulate_loregs_rwflags(struct kprobe *p, struct pt_regs *regs) { regs->ARM_cpsr = t16_emulate_loregs(p, regs); } -void __kprobes +static void __kprobes t16_emulate_loregs_noitrwflags(struct kprobe *p, struct pt_regs *regs) { unsigned long cpsr = t16_emulate_loregs(p, regs); @@ -477,7 +485,7 @@ t16_emulate_loregs_noitrwflags(struct kprobe *p, struct pt_regs *regs) regs->ARM_cpsr = cpsr; } -void __kprobes +static void __kprobes t16_emulate_hiregs(struct kprobe *p, struct pt_regs *regs) { kprobe_opcode_t insn = p->opcode; @@ -508,8 +516,9 @@ t16_emulate_hiregs(struct kprobe *p, struct pt_regs *regs) regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK); } -enum kprobe_insn __kprobes -t16_decode_hiregs(kprobe_opcode_t insn, struct arch_specific_insn *asi) +static enum kprobe_insn __kprobes +t16_decode_hiregs(kprobe_opcode_t insn, struct arch_specific_insn *asi, + const struct decode_header *d) { insn &= ~0x00ff; insn |= 0x001; /* Set Rdn = R1 and Rm = R0 */ @@ -518,7 +527,7 @@ t16_decode_hiregs(kprobe_opcode_t insn, struct arch_specific_insn *asi) return INSN_GOOD; } -void __kprobes +static void __kprobes t16_emulate_push(struct kprobe *p, struct pt_regs *regs) { __asm__ __volatile__ ( @@ -534,8 +543,9 @@ t16_emulate_push(struct kprobe *p, struct pt_regs *regs) ); } -enum kprobe_insn __kprobes -t16_decode_push(kprobe_opcode_t insn, struct arch_specific_insn *asi) +static enum kprobe_insn __kprobes +t16_decode_push(kprobe_opcode_t insn, struct arch_specific_insn *asi, + const struct decode_header *d) { /* * To simulate a PUSH we use a Thumb-2 "STMDB R9!, {registers}" @@ -548,7 +558,7 @@ t16_decode_push(kprobe_opcode_t insn, struct arch_specific_insn *asi) return INSN_GOOD; } -void __kprobes +static void __kprobes t16_emulate_pop_nopc(struct kprobe *p, struct pt_regs *regs) { __asm__ __volatile__ ( @@ -564,7 +574,7 @@ t16_emulate_pop_nopc(struct kprobe *p, struct pt_regs *regs) ); } -void __kprobes +static void __kprobes t16_emulate_pop_pc(struct kprobe *p, struct pt_regs *regs) { register unsigned long pc asm("r8"); @@ -584,8 +594,9 @@ t16_emulate_pop_pc(struct kprobe *p, struct pt_regs *regs) bx_write_pc(pc, regs); } -enum kprobe_insn __kprobes -t16_decode_pop(kprobe_opcode_t insn, struct arch_specific_insn *asi) +static enum kprobe_insn __kprobes +t16_decode_pop(kprobe_opcode_t insn, struct arch_specific_insn *asi, + const struct decode_header *d) { /* * To simulate a POP we use a Thumb-2 "LDMDB R9!, {registers}" @@ -598,3 +609,57 @@ t16_decode_pop(kprobe_opcode_t insn, struct arch_specific_insn *asi) : t16_emulate_pop_nopc; return INSN_GOOD; } + +const union decode_action kprobes_t16_actions[NUM_PROBES_T16_ACTIONS] = { + [PROBES_T16_ADD_SP] = {.handler = t16_simulate_add_sp_imm}, + [PROBES_T16_CBZ] = {.handler = t16_simulate_cbz}, + [PROBES_T16_SIGN_EXTEND] = {.handler = t16_emulate_loregs_rwflags}, + [PROBES_T16_PUSH] = {.decoder = t16_decode_push}, + [PROBES_T16_POP] = {.decoder = t16_decode_pop}, + [PROBES_T16_SEV] = {.handler = kprobe_emulate_none}, + [PROBES_T16_WFE] = {.handler = kprobe_simulate_nop}, + [PROBES_T16_IT] = {.decoder = t16_decode_it}, + [PROBES_T16_CMP] = {.handler = t16_emulate_loregs_rwflags}, + [PROBES_T16_ADDSUB] = {.handler = t16_emulate_loregs_noitrwflags}, + [PROBES_T16_LOGICAL] = {.handler = t16_emulate_loregs_noitrwflags}, + [PROBES_T16_LDR_LIT] = {.handler = t16_simulate_ldr_literal}, + [PROBES_T16_BLX] = {.handler = t16_simulate_bxblx}, + [PROBES_T16_HIREGOPS] = {.decoder = t16_decode_hiregs}, + [PROBES_T16_LDRHSTRH] = {.handler = t16_emulate_loregs_rwflags}, + [PROBES_T16_LDRSTR] = {.handler = t16_simulate_ldrstr_sp_relative}, + [PROBES_T16_ADR] = {.handler = t16_simulate_reladr}, + [PROBES_T16_LDMSTM] = {.handler = t16_emulate_loregs_rwflags}, + [PROBES_T16_BRANCH_COND] = {.decoder = t16_decode_cond_branch}, + [PROBES_T16_BRANCH] = {.handler = t16_simulate_branch}, +}; + +const union decode_action kprobes_t32_actions[NUM_PROBES_T32_ACTIONS] = { + [PROBES_T32_LDMSTM] = {.decoder = t32_decode_ldmstm}, + [PROBES_T32_LDRDSTRD] = {.handler = t32_emulate_ldrdstrd}, + [PROBES_T32_TABLE_BRANCH] = {.handler = t32_simulate_table_branch}, + [PROBES_T32_TST] = {.handler = t32_emulate_rd8rn16rm0_rwflags}, + [PROBES_T32_MOV] = {.handler = t32_emulate_rd8rn16rm0_rwflags}, + [PROBES_T32_ADDSUB] = {.handler = t32_emulate_rd8rn16rm0_rwflags}, + [PROBES_T32_LOGICAL] = {.handler = t32_emulate_rd8rn16rm0_rwflags}, + [PROBES_T32_CMP] = {.handler = t32_emulate_rd8rn16rm0_rwflags}, + [PROBES_T32_ADDWSUBW_PC] = {.handler = t32_emulate_rd8pc16_noflags,}, + [PROBES_T32_ADDWSUBW] = {.handler = t32_emulate_rd8rn16_noflags}, + [PROBES_T32_MOVW] = {.handler = t32_emulate_rd8rn16_noflags}, + [PROBES_T32_SAT] = {.handler = t32_emulate_rd8rn16rm0_rwflags}, + [PROBES_T32_BITFIELD] = {.handler = t32_emulate_rd8rn16_noflags}, + [PROBES_T32_SEV] = {.handler = kprobe_emulate_none}, + [PROBES_T32_WFE] = {.handler = kprobe_simulate_nop}, + [PROBES_T32_MRS] = {.handler = t32_simulate_mrs}, + [PROBES_T32_BRANCH_COND] = {.decoder = t32_decode_cond_branch}, + [PROBES_T32_BRANCH] = {.handler = t32_simulate_branch}, + [PROBES_T32_PLDI] = {.handler = kprobe_simulate_nop}, + [PROBES_T32_LDR_LIT] = {.handler = t32_simulate_ldr_literal}, + [PROBES_T32_LDRSTR] = {.handler = t32_emulate_ldrstr}, + [PROBES_T32_SIGN_EXTEND] = {.handler = t32_emulate_rd8rn16rm0_rwflags}, + [PROBES_T32_MEDIA] = {.handler = t32_emulate_rd8rn16rm0_rwflags}, + [PROBES_T32_REVERSE] = {.handler = t32_emulate_rd8rn16_noflags}, + [PROBES_T32_MUL_ADD] = {.handler = t32_emulate_rd8rn16rm0_rwflags}, + [PROBES_T32_MUL_ADD2] = {.handler = t32_emulate_rd8rn16rm0ra12_noflags}, + [PROBES_T32_MUL_ADD_LONG] = { + .handler = t32_emulate_rdlo12rdhi8rn16rm0_noflags}, +}; diff --git a/arch/arm/kernel/kprobes.c b/arch/arm/kernel/kprobes.c index 54e7b46a3295..a757c3c22381 100644 --- a/arch/arm/kernel/kprobes.c +++ b/arch/arm/kernel/kprobes.c @@ -56,6 +56,7 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p) unsigned long addr = (unsigned long)p->addr; bool thumb; kprobe_decode_insn_t *decode_insn; + const union decode_action *actions; int is; if (in_exception_text(addr)) @@ -69,20 +70,24 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p) insn <<= 16; insn |= ((u16 *)addr)[1]; decode_insn = thumb32_kprobe_decode_insn; - } else + actions = kprobes_t32_actions; + } else { decode_insn = thumb16_kprobe_decode_insn; + actions = kprobes_t16_actions; + } #else /* !CONFIG_THUMB2_KERNEL */ thumb = false; if (addr & 0x3) return -EINVAL; insn = *p->addr; decode_insn = arm_kprobe_decode_insn; + actions = kprobes_arm_actions; #endif p->opcode = insn; p->ainsn.insn = tmp_insn; - switch ((*decode_insn)(insn, &p->ainsn)) { + switch ((*decode_insn)(insn, &p->ainsn, actions)) { case INSN_REJECTED: /* not supported */ return -EINVAL; diff --git a/arch/arm/kernel/kprobes.h b/arch/arm/kernel/kprobes.h index aa68c0ea1a0b..7798035d6003 100644 --- a/arch/arm/kernel/kprobes.h +++ b/arch/arm/kernel/kprobes.h @@ -27,6 +27,8 @@ #define KPROBE_THUMB16_BREAKPOINT_INSTRUCTION 0xde18 #define KPROBE_THUMB32_BREAKPOINT_INSTRUCTION 0xf7f0a018 +struct decode_header; +union decode_action; enum kprobe_insn { INSN_REJECTED, @@ -35,19 +37,24 @@ enum kprobe_insn { }; typedef enum kprobe_insn (kprobe_decode_insn_t)(kprobe_opcode_t, - struct arch_specific_insn *); + struct arch_specific_insn *, + const union decode_action *); #ifdef CONFIG_THUMB2_KERNEL enum kprobe_insn thumb16_kprobe_decode_insn(kprobe_opcode_t, - struct arch_specific_insn *); + struct arch_specific_insn *, + const union decode_action *); enum kprobe_insn thumb32_kprobe_decode_insn(kprobe_opcode_t, - struct arch_specific_insn *); + struct arch_specific_insn *, + const union decode_action *); #else /* !CONFIG_THUMB2_KERNEL */ enum kprobe_insn arm_kprobe_decode_insn(kprobe_opcode_t, - struct arch_specific_insn *); + struct arch_specific_insn *, + const union decode_action *); + #endif void __init arm_kprobe_decode_init(void); diff --git a/arch/arm/kernel/probes-arm.c b/arch/arm/kernel/probes-arm.c index 57e08b28e87f..496e0e913fa6 100644 --- a/arch/arm/kernel/probes-arm.c +++ b/arch/arm/kernel/probes-arm.c @@ -126,16 +126,16 @@ static const union decode_item arm_1111_table[] = { /* PLDI (immediate) 1111 0100 x101 xxxx xxxx xxxx xxxx xxxx */ /* PLDW (immediate) 1111 0101 x001 xxxx xxxx xxxx xxxx xxxx */ /* PLD (immediate) 1111 0101 x101 xxxx xxxx xxxx xxxx xxxx */ - DECODE_SIMULATE (0xfe300000, 0xf4100000, kprobe_simulate_nop), + DECODE_SIMULATE (0xfe300000, 0xf4100000, PROBES_PRELOAD_IMM), /* memory hint 1111 0110 x001 xxxx xxxx xxxx xxx0 xxxx */ /* PLDI (register) 1111 0110 x101 xxxx xxxx xxxx xxx0 xxxx */ /* PLDW (register) 1111 0111 x001 xxxx xxxx xxxx xxx0 xxxx */ /* PLD (register) 1111 0111 x101 xxxx xxxx xxxx xxx0 xxxx */ - DECODE_SIMULATE (0xfe300010, 0xf6100000, kprobe_simulate_nop), + DECODE_SIMULATE (0xfe300010, 0xf6100000, PROBES_PRELOAD_REG), /* BLX (immediate) 1111 101x xxxx xxxx xxxx xxxx xxxx xxxx */ - DECODE_SIMULATE (0xfe000000, 0xfa000000, simulate_blx1), + DECODE_SIMULATE (0xfe000000, 0xfa000000, PROBES_BRANCH_IMM), /* CPS 1111 0001 0000 xxx0 xxxx xxxx xx0x xxxx */ /* SETEND 1111 0001 0000 0001 xxxx xxxx 0000 xxxx */ @@ -159,25 +159,25 @@ static const union decode_item arm_cccc_0001_0xx0____0xxx_table[] = { /* Miscellaneous instructions */ /* MRS cpsr cccc 0001 0000 xxxx xxxx xxxx 0000 xxxx */ - DECODE_SIMULATEX(0x0ff000f0, 0x01000000, simulate_mrs, + DECODE_SIMULATEX(0x0ff000f0, 0x01000000, PROBES_MRS, REGS(0, NOPC, 0, 0, 0)), /* BX cccc 0001 0010 xxxx xxxx xxxx 0001 xxxx */ - DECODE_SIMULATE (0x0ff000f0, 0x01200010, simulate_blx2bx), + DECODE_SIMULATE (0x0ff000f0, 0x01200010, PROBES_BRANCH_REG), /* BLX (register) cccc 0001 0010 xxxx xxxx xxxx 0011 xxxx */ - DECODE_SIMULATEX(0x0ff000f0, 0x01200030, simulate_blx2bx, + DECODE_SIMULATEX(0x0ff000f0, 0x01200030, PROBES_BRANCH_REG, REGS(0, 0, 0, 0, NOPC)), /* CLZ cccc 0001 0110 xxxx xxxx xxxx 0001 xxxx */ - DECODE_EMULATEX (0x0ff000f0, 0x01600010, emulate_rd12rm0_noflags_nopc, + DECODE_EMULATEX (0x0ff000f0, 0x01600010, PROBES_CLZ, REGS(0, NOPC, 0, 0, NOPC)), /* QADD cccc 0001 0000 xxxx xxxx xxxx 0101 xxxx */ /* QSUB cccc 0001 0010 xxxx xxxx xxxx 0101 xxxx */ /* QDADD cccc 0001 0100 xxxx xxxx xxxx 0101 xxxx */ /* QDSUB cccc 0001 0110 xxxx xxxx xxxx 0101 xxxx */ - DECODE_EMULATEX (0x0f9000f0, 0x01000050, emulate_rd12rn16rm0_rwflags_nopc, + DECODE_EMULATEX (0x0f9000f0, 0x01000050, PROBES_SATURATING_ARITHMETIC, REGS(NOPC, NOPC, 0, 0, NOPC)), /* BXJ cccc 0001 0010 xxxx xxxx xxxx 0010 xxxx */ @@ -193,19 +193,19 @@ static const union decode_item arm_cccc_0001_0xx0____1xx0_table[] = { /* Halfword multiply and multiply-accumulate */ /* SMLALxy cccc 0001 0100 xxxx xxxx xxxx 1xx0 xxxx */ - DECODE_EMULATEX (0x0ff00090, 0x01400080, emulate_rdlo12rdhi16rn0rm8_rwflags_nopc, + DECODE_EMULATEX (0x0ff00090, 0x01400080, PROBES_MUL1, REGS(NOPC, NOPC, NOPC, 0, NOPC)), /* SMULWy cccc 0001 0010 xxxx xxxx xxxx 1x10 xxxx */ DECODE_OR (0x0ff000b0, 0x012000a0), /* SMULxy cccc 0001 0110 xxxx xxxx xxxx 1xx0 xxxx */ - DECODE_EMULATEX (0x0ff00090, 0x01600080, emulate_rd16rn12rm0rs8_rwflags_nopc, + DECODE_EMULATEX (0x0ff00090, 0x01600080, PROBES_MUL2, REGS(NOPC, 0, NOPC, 0, NOPC)), /* SMLAxy cccc 0001 0000 xxxx xxxx xxxx 1xx0 xxxx */ DECODE_OR (0x0ff00090, 0x01000080), /* SMLAWy cccc 0001 0010 xxxx xxxx xxxx 1x00 xxxx */ - DECODE_EMULATEX (0x0ff000b0, 0x01200080, emulate_rd16rn12rm0rs8_rwflags_nopc, + DECODE_EMULATEX (0x0ff000b0, 0x01200080, PROBES_MUL2, REGS(NOPC, NOPC, NOPC, 0, NOPC)), DECODE_END @@ -216,14 +216,14 @@ static const union decode_item arm_cccc_0000_____1001_table[] = { /* MUL cccc 0000 0000 xxxx xxxx xxxx 1001 xxxx */ /* MULS cccc 0000 0001 xxxx xxxx xxxx 1001 xxxx */ - DECODE_EMULATEX (0x0fe000f0, 0x00000090, emulate_rd16rn12rm0rs8_rwflags_nopc, + DECODE_EMULATEX (0x0fe000f0, 0x00000090, PROBES_MUL2, REGS(NOPC, 0, NOPC, 0, NOPC)), /* MLA cccc 0000 0010 xxxx xxxx xxxx 1001 xxxx */ /* MLAS cccc 0000 0011 xxxx xxxx xxxx 1001 xxxx */ DECODE_OR (0x0fe000f0, 0x00200090), /* MLS cccc 0000 0110 xxxx xxxx xxxx 1001 xxxx */ - DECODE_EMULATEX (0x0ff000f0, 0x00600090, emulate_rd16rn12rm0rs8_rwflags_nopc, + DECODE_EMULATEX (0x0ff000f0, 0x00600090, PROBES_MUL2, REGS(NOPC, NOPC, NOPC, 0, NOPC)), /* UMAAL cccc 0000 0100 xxxx xxxx xxxx 1001 xxxx */ @@ -236,7 +236,7 @@ static const union decode_item arm_cccc_0000_____1001_table[] = { /* SMULLS cccc 0000 1101 xxxx xxxx xxxx 1001 xxxx */ /* SMLAL cccc 0000 1110 xxxx xxxx xxxx 1001 xxxx */ /* SMLALS cccc 0000 1111 xxxx xxxx xxxx 1001 xxxx */ - DECODE_EMULATEX (0x0f8000f0, 0x00800090, emulate_rdlo12rdhi16rn0rm8_rwflags_nopc, + DECODE_EMULATEX (0x0f8000f0, 0x00800090, PROBES_MUL1, REGS(NOPC, NOPC, NOPC, 0, NOPC)), DECODE_END @@ -248,7 +248,7 @@ static const union decode_item arm_cccc_0001_____1001_table[] = { #if __LINUX_ARM_ARCH__ < 6 /* Deprecated on ARMv6 and may be UNDEFINED on v7 */ /* SMP/SWPB cccc 0001 0x00 xxxx xxxx xxxx 1001 xxxx */ - DECODE_EMULATEX (0x0fb000f0, 0x01000090, emulate_rd12rn16rm0_rwflags_nopc, + DECODE_EMULATEX (0x0fb000f0, 0x01000090, PROBES_SWP, REGS(NOPC, NOPC, 0, 0, NOPC)), #endif /* LDREX/STREX{,D,B,H} cccc 0001 1xxx xxxx xxxx xxxx 1001 xxxx */ @@ -271,32 +271,32 @@ static const union decode_item arm_cccc_000x_____1xx1_table[] = { /* LDRD (register) cccc 000x x0x0 xxxx xxxx xxxx 1101 xxxx */ /* STRD (register) cccc 000x x0x0 xxxx xxxx xxxx 1111 xxxx */ - DECODE_EMULATEX (0x0e5000d0, 0x000000d0, emulate_ldrdstrd, + DECODE_EMULATEX (0x0e5000d0, 0x000000d0, PROBES_LDRSTRD, REGS(NOPCWB, NOPCX, 0, 0, NOPC)), /* LDRD (immediate) cccc 000x x1x0 xxxx xxxx xxxx 1101 xxxx */ /* STRD (immediate) cccc 000x x1x0 xxxx xxxx xxxx 1111 xxxx */ - DECODE_EMULATEX (0x0e5000d0, 0x004000d0, emulate_ldrdstrd, + DECODE_EMULATEX (0x0e5000d0, 0x004000d0, PROBES_LDRSTRD, REGS(NOPCWB, NOPCX, 0, 0, 0)), /* STRH (register) cccc 000x x0x0 xxxx xxxx xxxx 1011 xxxx */ - DECODE_EMULATEX (0x0e5000f0, 0x000000b0, emulate_str, + DECODE_EMULATEX (0x0e5000f0, 0x000000b0, PROBES_STORE_EXTRA, REGS(NOPCWB, NOPC, 0, 0, NOPC)), /* LDRH (register) cccc 000x x0x1 xxxx xxxx xxxx 1011 xxxx */ /* LDRSB (register) cccc 000x x0x1 xxxx xxxx xxxx 1101 xxxx */ /* LDRSH (register) cccc 000x x0x1 xxxx xxxx xxxx 1111 xxxx */ - DECODE_EMULATEX (0x0e500090, 0x00100090, emulate_ldr, + DECODE_EMULATEX (0x0e500090, 0x00100090, PROBES_LOAD_EXTRA, REGS(NOPCWB, NOPC, 0, 0, NOPC)), /* STRH (immediate) cccc 000x x1x0 xxxx xxxx xxxx 1011 xxxx */ - DECODE_EMULATEX (0x0e5000f0, 0x004000b0, emulate_str, + DECODE_EMULATEX (0x0e5000f0, 0x004000b0, PROBES_STORE_EXTRA, REGS(NOPCWB, NOPC, 0, 0, 0)), /* LDRH (immediate) cccc 000x x1x1 xxxx xxxx xxxx 1011 xxxx */ /* LDRSB (immediate) cccc 000x x1x1 xxxx xxxx xxxx 1101 xxxx */ /* LDRSH (immediate) cccc 000x x1x1 xxxx xxxx xxxx 1111 xxxx */ - DECODE_EMULATEX (0x0e500090, 0x00500090, emulate_ldr, + DECODE_EMULATEX (0x0e500090, 0x00500090, PROBES_LOAD_EXTRA, REGS(NOPCWB, NOPC, 0, 0, 0)), DECODE_END @@ -309,18 +309,18 @@ static const union decode_item arm_cccc_000x_table[] = { DECODE_REJECT (0x0e10f000, 0x0010f000), /* MOV IP, SP 1110 0001 1010 0000 1100 0000 0000 1101 */ - DECODE_SIMULATE (0xffffffff, 0xe1a0c00d, simulate_mov_ipsp), + DECODE_SIMULATE (0xffffffff, 0xe1a0c00d, PROBES_MOV_IP_SP), /* TST (register) cccc 0001 0001 xxxx xxxx xxxx xxx0 xxxx */ /* TEQ (register) cccc 0001 0011 xxxx xxxx xxxx xxx0 xxxx */ /* CMP (register) cccc 0001 0101 xxxx xxxx xxxx xxx0 xxxx */ /* CMN (register) cccc 0001 0111 xxxx xxxx xxxx xxx0 xxxx */ - DECODE_EMULATEX (0x0f900010, 0x01100000, emulate_rd12rn16rm0rs8_rwflags, + DECODE_EMULATEX (0x0f900010, 0x01100000, PROBES_DATA_PROCESSING_REG, REGS(ANY, 0, 0, 0, ANY)), /* MOV (register) cccc 0001 101x xxxx xxxx xxxx xxx0 xxxx */ /* MVN (register) cccc 0001 111x xxxx xxxx xxxx xxx0 xxxx */ - DECODE_EMULATEX (0x0fa00010, 0x01a00000, emulate_rd12rn16rm0rs8_rwflags, + DECODE_EMULATEX (0x0fa00010, 0x01a00000, PROBES_DATA_PROCESSING_REG, REGS(0, ANY, 0, 0, ANY)), /* AND (register) cccc 0000 000x xxxx xxxx xxxx xxx0 xxxx */ @@ -333,19 +333,19 @@ static const union decode_item arm_cccc_000x_table[] = { /* RSC (register) cccc 0000 111x xxxx xxxx xxxx xxx0 xxxx */ /* ORR (register) cccc 0001 100x xxxx xxxx xxxx xxx0 xxxx */ /* BIC (register) cccc 0001 110x xxxx xxxx xxxx xxx0 xxxx */ - DECODE_EMULATEX (0x0e000010, 0x00000000, emulate_rd12rn16rm0rs8_rwflags, + DECODE_EMULATEX (0x0e000010, 0x00000000, PROBES_DATA_PROCESSING_REG, REGS(ANY, ANY, 0, 0, ANY)), /* TST (reg-shift reg) cccc 0001 0001 xxxx xxxx xxxx 0xx1 xxxx */ /* TEQ (reg-shift reg) cccc 0001 0011 xxxx xxxx xxxx 0xx1 xxxx */ /* CMP (reg-shift reg) cccc 0001 0101 xxxx xxxx xxxx 0xx1 xxxx */ /* CMN (reg-shift reg) cccc 0001 0111 xxxx xxxx xxxx 0xx1 xxxx */ - DECODE_EMULATEX (0x0f900090, 0x01100010, emulate_rd12rn16rm0rs8_rwflags, + DECODE_EMULATEX (0x0f900090, 0x01100010, PROBES_DATA_PROCESSING_REG, REGS(ANY, 0, NOPC, 0, ANY)), /* MOV (reg-shift reg) cccc 0001 101x xxxx xxxx xxxx 0xx1 xxxx */ /* MVN (reg-shift reg) cccc 0001 111x xxxx xxxx xxxx 0xx1 xxxx */ - DECODE_EMULATEX (0x0fa00090, 0x01a00010, emulate_rd12rn16rm0rs8_rwflags, + DECODE_EMULATEX (0x0fa00090, 0x01a00010, PROBES_DATA_PROCESSING_REG, REGS(0, ANY, NOPC, 0, ANY)), /* AND (reg-shift reg) cccc 0000 000x xxxx xxxx xxxx 0xx1 xxxx */ @@ -358,7 +358,7 @@ static const union decode_item arm_cccc_000x_table[] = { /* RSC (reg-shift reg) cccc 0000 111x xxxx xxxx xxxx 0xx1 xxxx */ /* ORR (reg-shift reg) cccc 0001 100x xxxx xxxx xxxx 0xx1 xxxx */ /* BIC (reg-shift reg) cccc 0001 110x xxxx xxxx xxxx 0xx1 xxxx */ - DECODE_EMULATEX (0x0e000090, 0x00000010, emulate_rd12rn16rm0rs8_rwflags, + DECODE_EMULATEX (0x0e000090, 0x00000010, PROBES_DATA_PROCESSING_REG, REGS(ANY, ANY, NOPC, 0, ANY)), DECODE_END @@ -369,17 +369,17 @@ static const union decode_item arm_cccc_001x_table[] = { /* MOVW cccc 0011 0000 xxxx xxxx xxxx xxxx xxxx */ /* MOVT cccc 0011 0100 xxxx xxxx xxxx xxxx xxxx */ - DECODE_EMULATEX (0x0fb00000, 0x03000000, emulate_rd12rm0_noflags_nopc, + DECODE_EMULATEX (0x0fb00000, 0x03000000, PROBES_DATA_PROCESSING_IMM, REGS(0, NOPC, 0, 0, 0)), /* YIELD cccc 0011 0010 0000 xxxx xxxx 0000 0001 */ DECODE_OR (0x0fff00ff, 0x03200001), /* SEV cccc 0011 0010 0000 xxxx xxxx 0000 0100 */ - DECODE_EMULATE (0x0fff00ff, 0x03200004, kprobe_emulate_none), + DECODE_EMULATE (0x0fff00ff, 0x03200004, PROBES_EMULATE_NONE), /* NOP cccc 0011 0010 0000 xxxx xxxx 0000 0000 */ /* WFE cccc 0011 0010 0000 xxxx xxxx 0000 0010 */ /* WFI cccc 0011 0010 0000 xxxx xxxx 0000 0011 */ - DECODE_SIMULATE (0x0fff00fc, 0x03200000, kprobe_simulate_nop), + DECODE_SIMULATE (0x0fff00fc, 0x03200000, PROBES_SIMULATE_NOP), /* DBG cccc 0011 0010 0000 xxxx xxxx ffff xxxx */ /* unallocated hints cccc 0011 0010 0000 xxxx xxxx xxxx xxxx */ /* MSR (immediate) cccc 0011 0x10 xxxx xxxx xxxx xxxx xxxx */ @@ -392,12 +392,12 @@ static const union decode_item arm_cccc_001x_table[] = { /* TEQ (immediate) cccc 0011 0011 xxxx xxxx xxxx xxxx xxxx */ /* CMP (immediate) cccc 0011 0101 xxxx xxxx xxxx xxxx xxxx */ /* CMN (immediate) cccc 0011 0111 xxxx xxxx xxxx xxxx xxxx */ - DECODE_EMULATEX (0x0f900000, 0x03100000, emulate_rd12rn16rm0rs8_rwflags, + DECODE_EMULATEX (0x0f900000, 0x03100000, PROBES_DATA_PROCESSING_IMM, REGS(ANY, 0, 0, 0, 0)), /* MOV (immediate) cccc 0011 101x xxxx xxxx xxxx xxxx xxxx */ /* MVN (immediate) cccc 0011 111x xxxx xxxx xxxx xxxx xxxx */ - DECODE_EMULATEX (0x0fa00000, 0x03a00000, emulate_rd12rn16rm0rs8_rwflags, + DECODE_EMULATEX (0x0fa00000, 0x03a00000, PROBES_DATA_PROCESSING_IMM, REGS(0, ANY, 0, 0, 0)), /* AND (immediate) cccc 0010 000x xxxx xxxx xxxx xxxx xxxx */ @@ -410,7 +410,7 @@ static const union decode_item arm_cccc_001x_table[] = { /* RSC (immediate) cccc 0010 111x xxxx xxxx xxxx xxxx xxxx */ /* ORR (immediate) cccc 0011 100x xxxx xxxx xxxx xxxx xxxx */ /* BIC (immediate) cccc 0011 110x xxxx xxxx xxxx xxxx xxxx */ - DECODE_EMULATEX (0x0e000000, 0x02000000, emulate_rd12rn16rm0rs8_rwflags, + DECODE_EMULATEX (0x0e000000, 0x02000000, PROBES_DATA_PROCESSING_IMM, REGS(ANY, ANY, 0, 0, 0)), DECODE_END @@ -420,7 +420,7 @@ static const union decode_item arm_cccc_0110_____xxx1_table[] = { /* Media instructions */ /* SEL cccc 0110 1000 xxxx xxxx xxxx 1011 xxxx */ - DECODE_EMULATEX (0x0ff000f0, 0x068000b0, emulate_rd12rn16rm0_rwflags_nopc, + DECODE_EMULATEX (0x0ff000f0, 0x068000b0, PROBES_SATURATE, REGS(NOPC, NOPC, 0, 0, NOPC)), /* SSAT cccc 0110 101x xxxx xxxx xxxx xx01 xxxx */ @@ -428,14 +428,14 @@ static const union decode_item arm_cccc_0110_____xxx1_table[] = { DECODE_OR(0x0fa00030, 0x06a00010), /* SSAT16 cccc 0110 1010 xxxx xxxx xxxx 0011 xxxx */ /* USAT16 cccc 0110 1110 xxxx xxxx xxxx 0011 xxxx */ - DECODE_EMULATEX (0x0fb000f0, 0x06a00030, emulate_rd12rn16rm0_rwflags_nopc, + DECODE_EMULATEX (0x0fb000f0, 0x06a00030, PROBES_SATURATE, REGS(0, NOPC, 0, 0, NOPC)), /* REV cccc 0110 1011 xxxx xxxx xxxx 0011 xxxx */ /* REV16 cccc 0110 1011 xxxx xxxx xxxx 1011 xxxx */ /* RBIT cccc 0110 1111 xxxx xxxx xxxx 0011 xxxx */ /* REVSH cccc 0110 1111 xxxx xxxx xxxx 1011 xxxx */ - DECODE_EMULATEX (0x0fb00070, 0x06b00030, emulate_rd12rm0_noflags_nopc, + DECODE_EMULATEX (0x0fb00070, 0x06b00030, PROBES_REV, REGS(0, NOPC, 0, 0, NOPC)), /* ??? cccc 0110 0x00 xxxx xxxx xxxx xxx1 xxxx */ @@ -480,12 +480,12 @@ static const union decode_item arm_cccc_0110_____xxx1_table[] = { /* UHSUB16 cccc 0110 0111 xxxx xxxx xxxx 0111 xxxx */ /* UHADD8 cccc 0110 0111 xxxx xxxx xxxx 1001 xxxx */ /* UHSUB8 cccc 0110 0111 xxxx xxxx xxxx 1111 xxxx */ - DECODE_EMULATEX (0x0f800010, 0x06000010, emulate_rd12rn16rm0_rwflags_nopc, + DECODE_EMULATEX (0x0f800010, 0x06000010, PROBES_MMI, REGS(NOPC, NOPC, 0, 0, NOPC)), /* PKHBT cccc 0110 1000 xxxx xxxx xxxx x001 xxxx */ /* PKHTB cccc 0110 1000 xxxx xxxx xxxx x101 xxxx */ - DECODE_EMULATEX (0x0ff00030, 0x06800010, emulate_rd12rn16rm0_rwflags_nopc, + DECODE_EMULATEX (0x0ff00030, 0x06800010, PROBES_PACK, REGS(NOPC, NOPC, 0, 0, NOPC)), /* ??? cccc 0110 1001 xxxx xxxx xxxx 0111 xxxx */ @@ -498,7 +498,7 @@ static const union decode_item arm_cccc_0110_____xxx1_table[] = { /* UXTB16 cccc 0110 1100 1111 xxxx xxxx 0111 xxxx */ /* UXTB cccc 0110 1110 1111 xxxx xxxx 0111 xxxx */ /* UXTH cccc 0110 1111 1111 xxxx xxxx 0111 xxxx */ - DECODE_EMULATEX (0x0f8f00f0, 0x068f0070, emulate_rd12rm0_noflags_nopc, + DECODE_EMULATEX (0x0f8f00f0, 0x068f0070, PROBES_EXTEND, REGS(0, NOPC, 0, 0, NOPC)), /* SXTAB16 cccc 0110 1000 xxxx xxxx xxxx 0111 xxxx */ @@ -507,7 +507,7 @@ static const union decode_item arm_cccc_0110_____xxx1_table[] = { /* UXTAB16 cccc 0110 1100 xxxx xxxx xxxx 0111 xxxx */ /* UXTAB cccc 0110 1110 xxxx xxxx xxxx 0111 xxxx */ /* UXTAH cccc 0110 1111 xxxx xxxx xxxx 0111 xxxx */ - DECODE_EMULATEX (0x0f8000f0, 0x06800070, emulate_rd12rn16rm0_rwflags_nopc, + DECODE_EMULATEX (0x0f8000f0, 0x06800070, PROBES_EXTEND_ADD, REGS(NOPCX, NOPC, 0, 0, NOPC)), DECODE_END @@ -521,7 +521,7 @@ static const union decode_item arm_cccc_0111_____xxx1_table[] = { /* SMLALD cccc 0111 0100 xxxx xxxx xxxx 00x1 xxxx */ /* SMLSLD cccc 0111 0100 xxxx xxxx xxxx 01x1 xxxx */ - DECODE_EMULATEX (0x0ff00090, 0x07400010, emulate_rdlo12rdhi16rn0rm8_rwflags_nopc, + DECODE_EMULATEX (0x0ff00090, 0x07400010, PROBES_MUL_ADD_LONG, REGS(NOPC, NOPC, NOPC, 0, NOPC)), /* SMUAD cccc 0111 0000 xxxx 1111 xxxx 00x1 xxxx */ @@ -530,7 +530,7 @@ static const union decode_item arm_cccc_0111_____xxx1_table[] = { /* SMMUL cccc 0111 0101 xxxx 1111 xxxx 00x1 xxxx */ DECODE_OR (0x0ff0f0d0, 0x0750f010), /* USAD8 cccc 0111 1000 xxxx 1111 xxxx 0001 xxxx */ - DECODE_EMULATEX (0x0ff0f0f0, 0x0780f010, emulate_rd16rn12rm0rs8_rwflags_nopc, + DECODE_EMULATEX (0x0ff0f0f0, 0x0780f010, PROBES_MUL_ADD, REGS(NOPC, 0, NOPC, 0, NOPC)), /* SMLAD cccc 0111 0000 xxxx xxxx xxxx 00x1 xxxx */ @@ -539,24 +539,24 @@ static const union decode_item arm_cccc_0111_____xxx1_table[] = { /* SMMLA cccc 0111 0101 xxxx xxxx xxxx 00x1 xxxx */ DECODE_OR (0x0ff000d0, 0x07500010), /* USADA8 cccc 0111 1000 xxxx xxxx xxxx 0001 xxxx */ - DECODE_EMULATEX (0x0ff000f0, 0x07800010, emulate_rd16rn12rm0rs8_rwflags_nopc, + DECODE_EMULATEX (0x0ff000f0, 0x07800010, PROBES_MUL_ADD, REGS(NOPC, NOPCX, NOPC, 0, NOPC)), /* SMMLS cccc 0111 0101 xxxx xxxx xxxx 11x1 xxxx */ - DECODE_EMULATEX (0x0ff000d0, 0x075000d0, emulate_rd16rn12rm0rs8_rwflags_nopc, + DECODE_EMULATEX (0x0ff000d0, 0x075000d0, PROBES_MUL_ADD, REGS(NOPC, NOPC, NOPC, 0, NOPC)), /* SBFX cccc 0111 101x xxxx xxxx xxxx x101 xxxx */ /* UBFX cccc 0111 111x xxxx xxxx xxxx x101 xxxx */ - DECODE_EMULATEX (0x0fa00070, 0x07a00050, emulate_rd12rm0_noflags_nopc, + DECODE_EMULATEX (0x0fa00070, 0x07a00050, PROBES_BITFIELD, REGS(0, NOPC, 0, 0, NOPC)), /* BFC cccc 0111 110x xxxx xxxx xxxx x001 1111 */ - DECODE_EMULATEX (0x0fe0007f, 0x07c0001f, emulate_rd12rm0_noflags_nopc, + DECODE_EMULATEX (0x0fe0007f, 0x07c0001f, PROBES_BITFIELD, REGS(0, NOPC, 0, 0, 0)), /* BFI cccc 0111 110x xxxx xxxx xxxx x001 xxxx */ - DECODE_EMULATEX (0x0fe00070, 0x07c00010, emulate_rd12rm0_noflags_nopc, + DECODE_EMULATEX (0x0fe00070, 0x07c00010, PROBES_BITFIELD, REGS(0, NOPC, 0, 0, NOPCX)), DECODE_END @@ -576,22 +576,22 @@ static const union decode_item arm_cccc_01xx_table[] = { /* STR (immediate) cccc 010x x0x0 xxxx xxxx xxxx xxxx xxxx */ /* STRB (immediate) cccc 010x x1x0 xxxx xxxx xxxx xxxx xxxx */ - DECODE_EMULATEX (0x0e100000, 0x04000000, emulate_str, + DECODE_EMULATEX (0x0e100000, 0x04000000, PROBES_STORE, REGS(NOPCWB, ANY, 0, 0, 0)), /* LDR (immediate) cccc 010x x0x1 xxxx xxxx xxxx xxxx xxxx */ /* LDRB (immediate) cccc 010x x1x1 xxxx xxxx xxxx xxxx xxxx */ - DECODE_EMULATEX (0x0e100000, 0x04100000, emulate_ldr, + DECODE_EMULATEX (0x0e100000, 0x04100000, PROBES_LOAD, REGS(NOPCWB, ANY, 0, 0, 0)), /* STR (register) cccc 011x x0x0 xxxx xxxx xxxx xxxx xxxx */ /* STRB (register) cccc 011x x1x0 xxxx xxxx xxxx xxxx xxxx */ - DECODE_EMULATEX (0x0e100000, 0x06000000, emulate_str, + DECODE_EMULATEX (0x0e100000, 0x06000000, PROBES_STORE, REGS(NOPCWB, ANY, 0, 0, NOPC)), /* LDR (register) cccc 011x x0x1 xxxx xxxx xxxx xxxx xxxx */ /* LDRB (register) cccc 011x x1x1 xxxx xxxx xxxx xxxx xxxx */ - DECODE_EMULATEX (0x0e100000, 0x06100000, emulate_ldr, + DECODE_EMULATEX (0x0e100000, 0x06100000, PROBES_LOAD, REGS(NOPCWB, ANY, 0, 0, NOPC)), DECODE_END @@ -602,7 +602,7 @@ static const union decode_item arm_cccc_100x_table[] = { /* LDM cccc 100x x0x1 xxxx xxxx xxxx xxxx xxxx */ /* STM cccc 100x x0x0 xxxx xxxx xxxx xxxx xxxx */ - DECODE_CUSTOM (0x0e400000, 0x08000000, kprobe_decode_ldmstm), + DECODE_CUSTOM (0x0e400000, 0x08000000, PROBES_LDMSTM), /* STM (user registers) cccc 100x x1x0 xxxx xxxx xxxx xxxx xxxx */ /* LDM (user registers) cccc 100x x1x1 xxxx 0xxx xxxx xxxx xxxx */ @@ -682,7 +682,7 @@ const union decode_item kprobe_decode_arm_table[] = { /* B cccc 1010 xxxx xxxx xxxx xxxx xxxx xxxx */ /* BL cccc 1011 xxxx xxxx xxxx xxxx xxxx xxxx */ - DECODE_SIMULATE (0x0e000000, 0x0a000000, simulate_bbl), + DECODE_SIMULATE (0x0e000000, 0x0a000000, PROBES_BRANCH), /* * Supervisor Call, and coprocessor instructions @@ -723,9 +723,11 @@ static void __kprobes arm_singlestep(struct kprobe *p, struct pt_regs *regs) * should also be very rare. */ enum kprobe_insn __kprobes -arm_kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi) +arm_kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi, + const union decode_action *actions) { asi->insn_singlestep = arm_singlestep; asi->insn_check_cc = kprobe_condition_checks[insn>>28]; - return kprobe_decode_insn(insn, asi, kprobe_decode_arm_table, false); + return kprobe_decode_insn(insn, asi, kprobe_decode_arm_table, false, + actions); } diff --git a/arch/arm/kernel/probes-arm.h b/arch/arm/kernel/probes-arm.h index 86084727d36d..ef3089419a0b 100644 --- a/arch/arm/kernel/probes-arm.h +++ b/arch/arm/kernel/probes-arm.h @@ -15,24 +15,48 @@ #ifndef _ARM_KERNEL_PROBES_ARM_H #define _ARM_KERNEL_PROBES_ARM_H +enum probes_arm_action { + PROBES_EMULATE_NONE, + PROBES_SIMULATE_NOP, + PROBES_PRELOAD_IMM, + PROBES_PRELOAD_REG, + PROBES_BRANCH_IMM, + PROBES_BRANCH_REG, + PROBES_MRS, + PROBES_CLZ, + PROBES_SATURATING_ARITHMETIC, + PROBES_MUL1, + PROBES_MUL2, + PROBES_SWP, + PROBES_LDRSTRD, + PROBES_LOAD, + PROBES_STORE, + PROBES_LOAD_EXTRA, + PROBES_STORE_EXTRA, + PROBES_MOV_IP_SP, + PROBES_DATA_PROCESSING_REG, + PROBES_DATA_PROCESSING_IMM, + PROBES_MOV_HALFWORD, + PROBES_SEV, + PROBES_WFE, + PROBES_SATURATE, + PROBES_REV, + PROBES_MMI, + PROBES_PACK, + PROBES_EXTEND, + PROBES_EXTEND_ADD, + PROBES_MUL_ADD_LONG, + PROBES_MUL_ADD, + PROBES_BITFIELD, + PROBES_BRANCH, + PROBES_LDMSTM, + NUM_PROBES_ARM_ACTIONS +}; + void __kprobes simulate_bbl(struct kprobe *p, struct pt_regs *regs); void __kprobes simulate_blx1(struct kprobe *p, struct pt_regs *regs); void __kprobes simulate_blx2bx(struct kprobe *p, struct pt_regs *regs); void __kprobes simulate_mrs(struct kprobe *p, struct pt_regs *regs); void __kprobes simulate_mov_ipsp(struct kprobe *p, struct pt_regs *regs); -void __kprobes emulate_ldrdstrd(struct kprobe *p, struct pt_regs *regs); -void __kprobes emulate_ldr(struct kprobe *p, struct pt_regs *regs); -void __kprobes emulate_str(struct kprobe *p, struct pt_regs *regs); -void __kprobes emulate_rd12rn16rm0rs8_rwflags(struct kprobe *p, - struct pt_regs *regs); -void __kprobes emulate_rd12rn16rm0_rwflags_nopc(struct kprobe *p, - struct pt_regs *regs); -void __kprobes emulate_rd16rn12rm0rs8_rwflags_nopc(struct kprobe *p, - struct pt_regs *regs); -void __kprobes emulate_rd12rm0_noflags_nopc(struct kprobe *p, - struct pt_regs *regs); -void __kprobes emulate_rdlo12rdhi16rn0rm8_rwflags_nopc(struct kprobe *p, - struct pt_regs *regs); - #endif diff --git a/arch/arm/kernel/probes-thumb.c b/arch/arm/kernel/probes-thumb.c index a1f24777a41a..2abe8ceeb670 100644 --- a/arch/arm/kernel/probes-thumb.c +++ b/arch/arm/kernel/probes-thumb.c @@ -16,9 +16,6 @@ #include "kprobes.h" #include "probes-thumb.h" -/* These emulation encodings are functionally equivalent... */ -#define t32_emulate_rd8rn16rm0ra12_noflags \ - t32_emulate_rdlo12rdhi8rn16rm0_noflags static const union decode_item t32_table_1110_100x_x0xx[] = { /* Load/store multiple instructions */ @@ -44,7 +41,7 @@ static const union decode_item t32_table_1110_100x_x0xx[] = { /* LDMIA 1110 1000 10x1 xxxx xxxx xxxx xxxx xxxx */ /* STMDB 1110 1001 00x0 xxxx xxxx xxxx xxxx xxxx */ /* LDMDB 1110 1001 00x1 xxxx xxxx xxxx xxxx xxxx */ - DECODE_CUSTOM (0xfe400000, 0xe8000000, t32_decode_ldmstm), + DECODE_CUSTOM (0xfe400000, 0xe8000000, PROBES_T32_LDMSTM), DECODE_END }; @@ -57,12 +54,12 @@ static const union decode_item t32_table_1110_100x_x1xx[] = { DECODE_OR (0xff600000, 0xe8600000), /* STRD (immediate) 1110 1001 x1x0 xxxx xxxx xxxx xxxx xxxx */ /* LDRD (immediate) 1110 1001 x1x1 xxxx xxxx xxxx xxxx xxxx */ - DECODE_EMULATEX (0xff400000, 0xe9400000, t32_emulate_ldrdstrd, + DECODE_EMULATEX (0xff400000, 0xe9400000, PROBES_T32_LDRDSTRD, REGS(NOPCWB, NOSPPC, NOSPPC, 0, 0)), /* TBB 1110 1000 1101 xxxx xxxx xxxx 0000 xxxx */ /* TBH 1110 1000 1101 xxxx xxxx xxxx 0001 xxxx */ - DECODE_SIMULATEX(0xfff000e0, 0xe8d00000, t32_simulate_table_branch, + DECODE_SIMULATEX(0xfff000e0, 0xe8d00000, PROBES_T32_TABLE_BRANCH, REGS(NOSP, 0, 0, 0, NOSPPC)), /* STREX 1110 1000 0100 xxxx xxxx xxxx xxxx xxxx */ @@ -82,18 +79,18 @@ static const union decode_item t32_table_1110_101x[] = { /* TST 1110 1010 0001 xxxx xxxx 1111 xxxx xxxx */ /* TEQ 1110 1010 1001 xxxx xxxx 1111 xxxx xxxx */ - DECODE_EMULATEX (0xff700f00, 0xea100f00, t32_emulate_rd8rn16rm0_rwflags, + DECODE_EMULATEX (0xff700f00, 0xea100f00, PROBES_T32_TST, REGS(NOSPPC, 0, 0, 0, NOSPPC)), /* CMN 1110 1011 0001 xxxx xxxx 1111 xxxx xxxx */ DECODE_OR (0xfff00f00, 0xeb100f00), /* CMP 1110 1011 1011 xxxx xxxx 1111 xxxx xxxx */ - DECODE_EMULATEX (0xfff00f00, 0xebb00f00, t32_emulate_rd8rn16rm0_rwflags, + DECODE_EMULATEX (0xfff00f00, 0xebb00f00, PROBES_T32_TST, REGS(NOPC, 0, 0, 0, NOSPPC)), /* MOV 1110 1010 010x 1111 xxxx xxxx xxxx xxxx */ /* MVN 1110 1010 011x 1111 xxxx xxxx xxxx xxxx */ - DECODE_EMULATEX (0xffcf0000, 0xea4f0000, t32_emulate_rd8rn16rm0_rwflags, + DECODE_EMULATEX (0xffcf0000, 0xea4f0000, PROBES_T32_MOV, REGS(0, 0, NOSPPC, 0, NOSPPC)), /* ??? 1110 1010 101x xxxx xxxx xxxx xxxx xxxx */ @@ -108,7 +105,7 @@ static const union decode_item t32_table_1110_101x[] = { /* ADD/SUB SP, SP, Rm, LSL #0..3 */ /* 1110 1011 x0xx 1101 x000 1101 xx00 xxxx */ - DECODE_EMULATEX (0xff4f7f30, 0xeb0d0d00, t32_emulate_rd8rn16rm0_rwflags, + DECODE_EMULATEX (0xff4f7f30, 0xeb0d0d00, PROBES_T32_ADDSUB, REGS(SP, 0, SP, 0, NOSPPC)), /* ADD/SUB SP, SP, Rm, shift */ @@ -117,7 +114,7 @@ static const union decode_item t32_table_1110_101x[] = { /* ADD/SUB Rd, SP, Rm, shift */ /* 1110 1011 x0xx 1101 xxxx xxxx xxxx xxxx */ - DECODE_EMULATEX (0xff4f0000, 0xeb0d0000, t32_emulate_rd8rn16rm0_rwflags, + DECODE_EMULATEX (0xff4f0000, 0xeb0d0000, PROBES_T32_ADDSUB, REGS(SP, 0, NOPC, 0, NOSPPC)), /* AND 1110 1010 000x xxxx xxxx xxxx xxxx xxxx */ @@ -131,7 +128,7 @@ static const union decode_item t32_table_1110_101x[] = { /* SBC 1110 1011 011x xxxx xxxx xxxx xxxx xxxx */ /* SUB 1110 1011 101x xxxx xxxx xxxx xxxx xxxx */ /* RSB 1110 1011 110x xxxx xxxx xxxx xxxx xxxx */ - DECODE_EMULATEX (0xfe000000, 0xea000000, t32_emulate_rd8rn16rm0_rwflags, + DECODE_EMULATEX (0xfe000000, 0xea000000, PROBES_T32_LOGICAL, REGS(NOSPPC, 0, NOSPPC, 0, NOSPPC)), DECODE_END @@ -142,18 +139,18 @@ static const union decode_item t32_table_1111_0x0x___0[] = { /* TST 1111 0x00 0001 xxxx 0xxx 1111 xxxx xxxx */ /* TEQ 1111 0x00 1001 xxxx 0xxx 1111 xxxx xxxx */ - DECODE_EMULATEX (0xfb708f00, 0xf0100f00, t32_emulate_rd8rn16rm0_rwflags, + DECODE_EMULATEX (0xfb708f00, 0xf0100f00, PROBES_T32_TST, REGS(NOSPPC, 0, 0, 0, 0)), /* CMN 1111 0x01 0001 xxxx 0xxx 1111 xxxx xxxx */ DECODE_OR (0xfbf08f00, 0xf1100f00), /* CMP 1111 0x01 1011 xxxx 0xxx 1111 xxxx xxxx */ - DECODE_EMULATEX (0xfbf08f00, 0xf1b00f00, t32_emulate_rd8rn16rm0_rwflags, + DECODE_EMULATEX (0xfbf08f00, 0xf1b00f00, PROBES_T32_CMP, REGS(NOPC, 0, 0, 0, 0)), /* MOV 1111 0x00 010x 1111 0xxx xxxx xxxx xxxx */ /* MVN 1111 0x00 011x 1111 0xxx xxxx xxxx xxxx */ - DECODE_EMULATEX (0xfbcf8000, 0xf04f0000, t32_emulate_rd8rn16rm0_rwflags, + DECODE_EMULATEX (0xfbcf8000, 0xf04f0000, PROBES_T32_MOV, REGS(0, 0, NOSPPC, 0, 0)), /* ??? 1111 0x00 101x xxxx 0xxx xxxx xxxx xxxx */ @@ -170,7 +167,7 @@ static const union decode_item t32_table_1111_0x0x___0[] = { /* ADD Rd, SP, #imm 1111 0x01 000x 1101 0xxx xxxx xxxx xxxx */ /* SUB Rd, SP, #imm 1111 0x01 101x 1101 0xxx xxxx xxxx xxxx */ - DECODE_EMULATEX (0xfb4f8000, 0xf10d0000, t32_emulate_rd8rn16rm0_rwflags, + DECODE_EMULATEX (0xfb4f8000, 0xf10d0000, PROBES_T32_ADDSUB, REGS(SP, 0, NOPC, 0, 0)), /* AND 1111 0x00 000x xxxx 0xxx xxxx xxxx xxxx */ @@ -183,7 +180,7 @@ static const union decode_item t32_table_1111_0x0x___0[] = { /* SBC 1111 0x01 011x xxxx 0xxx xxxx xxxx xxxx */ /* SUB 1111 0x01 101x xxxx 0xxx xxxx xxxx xxxx */ /* RSB 1111 0x01 110x xxxx 0xxx xxxx xxxx xxxx */ - DECODE_EMULATEX (0xfa008000, 0xf0000000, t32_emulate_rd8rn16rm0_rwflags, + DECODE_EMULATEX (0xfa008000, 0xf0000000, PROBES_T32_LOGICAL, REGS(NOSPPC, 0, NOSPPC, 0, 0)), DECODE_END @@ -195,44 +192,44 @@ static const union decode_item t32_table_1111_0x1x___0[] = { /* ADDW Rd, PC, #imm 1111 0x10 0000 1111 0xxx xxxx xxxx xxxx */ DECODE_OR (0xfbff8000, 0xf20f0000), /* SUBW Rd, PC, #imm 1111 0x10 1010 1111 0xxx xxxx xxxx xxxx */ - DECODE_EMULATEX (0xfbff8000, 0xf2af0000, t32_emulate_rd8pc16_noflags, + DECODE_EMULATEX (0xfbff8000, 0xf2af0000, PROBES_T32_ADDWSUBW_PC, REGS(PC, 0, NOSPPC, 0, 0)), /* ADDW SP, SP, #imm 1111 0x10 0000 1101 0xxx 1101 xxxx xxxx */ DECODE_OR (0xfbff8f00, 0xf20d0d00), /* SUBW SP, SP, #imm 1111 0x10 1010 1101 0xxx 1101 xxxx xxxx */ - DECODE_EMULATEX (0xfbff8f00, 0xf2ad0d00, t32_emulate_rd8rn16_noflags, + DECODE_EMULATEX (0xfbff8f00, 0xf2ad0d00, PROBES_T32_ADDWSUBW, REGS(SP, 0, SP, 0, 0)), /* ADDW 1111 0x10 0000 xxxx 0xxx xxxx xxxx xxxx */ DECODE_OR (0xfbf08000, 0xf2000000), /* SUBW 1111 0x10 1010 xxxx 0xxx xxxx xxxx xxxx */ - DECODE_EMULATEX (0xfbf08000, 0xf2a00000, t32_emulate_rd8rn16_noflags, + DECODE_EMULATEX (0xfbf08000, 0xf2a00000, PROBES_T32_ADDWSUBW, REGS(NOPCX, 0, NOSPPC, 0, 0)), /* MOVW 1111 0x10 0100 xxxx 0xxx xxxx xxxx xxxx */ /* MOVT 1111 0x10 1100 xxxx 0xxx xxxx xxxx xxxx */ - DECODE_EMULATEX (0xfb708000, 0xf2400000, t32_emulate_rd8rn16_noflags, + DECODE_EMULATEX (0xfb708000, 0xf2400000, PROBES_T32_MOVW, REGS(0, 0, NOSPPC, 0, 0)), /* SSAT16 1111 0x11 0010 xxxx 0000 xxxx 00xx xxxx */ /* SSAT 1111 0x11 00x0 xxxx 0xxx xxxx xxxx xxxx */ /* USAT16 1111 0x11 1010 xxxx 0000 xxxx 00xx xxxx */ /* USAT 1111 0x11 10x0 xxxx 0xxx xxxx xxxx xxxx */ - DECODE_EMULATEX (0xfb508000, 0xf3000000, t32_emulate_rd8rn16rm0_rwflags, + DECODE_EMULATEX (0xfb508000, 0xf3000000, PROBES_T32_SAT, REGS(NOSPPC, 0, NOSPPC, 0, 0)), /* SFBX 1111 0x11 0100 xxxx 0xxx xxxx xxxx xxxx */ /* UFBX 1111 0x11 1100 xxxx 0xxx xxxx xxxx xxxx */ - DECODE_EMULATEX (0xfb708000, 0xf3400000, t32_emulate_rd8rn16_noflags, + DECODE_EMULATEX (0xfb708000, 0xf3400000, PROBES_T32_BITFIELD, REGS(NOSPPC, 0, NOSPPC, 0, 0)), /* BFC 1111 0x11 0110 1111 0xxx xxxx xxxx xxxx */ - DECODE_EMULATEX (0xfbff8000, 0xf36f0000, t32_emulate_rd8rn16_noflags, + DECODE_EMULATEX (0xfbff8000, 0xf36f0000, PROBES_T32_BITFIELD, REGS(0, 0, NOSPPC, 0, 0)), /* BFI 1111 0x11 0110 xxxx 0xxx xxxx xxxx xxxx */ - DECODE_EMULATEX (0xfbf08000, 0xf3600000, t32_emulate_rd8rn16_noflags, + DECODE_EMULATEX (0xfbf08000, 0xf3600000, PROBES_T32_BITFIELD, REGS(NOSPPCX, 0, NOSPPC, 0, 0)), DECODE_END @@ -244,14 +241,14 @@ static const union decode_item t32_table_1111_0xxx___1[] = { /* YIELD 1111 0011 1010 xxxx 10x0 x000 0000 0001 */ DECODE_OR (0xfff0d7ff, 0xf3a08001), /* SEV 1111 0011 1010 xxxx 10x0 x000 0000 0100 */ - DECODE_EMULATE (0xfff0d7ff, 0xf3a08004, kprobe_emulate_none), + DECODE_EMULATE (0xfff0d7ff, 0xf3a08004, PROBES_T32_SEV), /* NOP 1111 0011 1010 xxxx 10x0 x000 0000 0000 */ /* WFE 1111 0011 1010 xxxx 10x0 x000 0000 0010 */ /* WFI 1111 0011 1010 xxxx 10x0 x000 0000 0011 */ - DECODE_SIMULATE (0xfff0d7fc, 0xf3a08000, kprobe_simulate_nop), + DECODE_SIMULATE (0xfff0d7fc, 0xf3a08000, PROBES_T32_WFE), /* MRS Rd, CPSR 1111 0011 1110 xxxx 10x0 xxxx xxxx xxxx */ - DECODE_SIMULATEX(0xfff0d000, 0xf3e08000, t32_simulate_mrs, + DECODE_SIMULATEX(0xfff0d000, 0xf3e08000, PROBES_T32_MRS, REGS(0, 0, NOSPPC, 0, 0)), /* @@ -273,13 +270,13 @@ static const union decode_item t32_table_1111_0xxx___1[] = { DECODE_REJECT (0xfb80d000, 0xf3808000), /* Bcc 1111 0xxx xxxx xxxx 10x0 xxxx xxxx xxxx */ - DECODE_CUSTOM (0xf800d000, 0xf0008000, t32_decode_cond_branch), + DECODE_CUSTOM (0xf800d000, 0xf0008000, PROBES_T32_BRANCH_COND), /* BLX 1111 0xxx xxxx xxxx 11x0 xxxx xxxx xxx0 */ DECODE_OR (0xf800d001, 0xf000c000), /* B 1111 0xxx xxxx xxxx 10x1 xxxx xxxx xxxx */ /* BL 1111 0xxx xxxx xxxx 11x1 xxxx xxxx xxxx */ - DECODE_SIMULATE (0xf8009000, 0xf0009000, t32_simulate_branch), + DECODE_SIMULATE (0xf8009000, 0xf0009000, PROBES_T32_BRANCH), DECODE_END }; @@ -289,7 +286,7 @@ static const union decode_item t32_table_1111_100x_x0x1__1111[] = { /* PLD (literal) 1111 1000 x001 1111 1111 xxxx xxxx xxxx */ /* PLI (literal) 1111 1001 x001 1111 1111 xxxx xxxx xxxx */ - DECODE_SIMULATE (0xfe7ff000, 0xf81ff000, kprobe_simulate_nop), + DECODE_SIMULATE (0xfe7ff000, 0xf81ff000, PROBES_T32_PLDI), /* PLD{W} (immediate) 1111 1000 10x1 xxxx 1111 xxxx xxxx xxxx */ DECODE_OR (0xffd0f000, 0xf890f000), @@ -298,13 +295,13 @@ static const union decode_item t32_table_1111_100x_x0x1__1111[] = { /* PLI (immediate) 1111 1001 1001 xxxx 1111 xxxx xxxx xxxx */ DECODE_OR (0xfff0f000, 0xf990f000), /* PLI (immediate) 1111 1001 0001 xxxx 1111 1100 xxxx xxxx */ - DECODE_SIMULATEX(0xfff0ff00, 0xf910fc00, kprobe_simulate_nop, + DECODE_SIMULATEX(0xfff0ff00, 0xf910fc00, PROBES_T32_PLDI, REGS(NOPCX, 0, 0, 0, 0)), /* PLD{W} (register) 1111 1000 00x1 xxxx 1111 0000 00xx xxxx */ DECODE_OR (0xffd0ffc0, 0xf810f000), /* PLI (register) 1111 1001 0001 xxxx 1111 0000 00xx xxxx */ - DECODE_SIMULATEX(0xfff0ffc0, 0xf910f000, kprobe_simulate_nop, + DECODE_SIMULATEX(0xfff0ffc0, 0xf910f000, PROBES_T32_PLDI, REGS(NOPCX, 0, 0, 0, NOSPPC)), /* Other unallocated instructions... */ @@ -340,7 +337,7 @@ static const union decode_item t32_table_1111_100x[] = { DECODE_REJECT (0xff10f000, 0xf800f000), /* LDR (literal) 1111 1000 x101 1111 xxxx xxxx xxxx xxxx */ - DECODE_SIMULATEX(0xff7f0000, 0xf85f0000, t32_simulate_ldr_literal, + DECODE_SIMULATEX(0xff7f0000, 0xf85f0000, PROBES_T32_LDR_LIT, REGS(PC, ANY, 0, 0, 0)), /* STR (immediate) 1111 1000 0100 xxxx xxxx 1xxx xxxx xxxx */ @@ -348,19 +345,19 @@ static const union decode_item t32_table_1111_100x[] = { DECODE_OR (0xffe00800, 0xf8400800), /* STR (immediate) 1111 1000 1100 xxxx xxxx xxxx xxxx xxxx */ /* LDR (immediate) 1111 1000 1101 xxxx xxxx xxxx xxxx xxxx */ - DECODE_EMULATEX (0xffe00000, 0xf8c00000, t32_emulate_ldrstr, + DECODE_EMULATEX (0xffe00000, 0xf8c00000, PROBES_T32_LDRSTR, REGS(NOPCX, ANY, 0, 0, 0)), /* STR (register) 1111 1000 0100 xxxx xxxx 0000 00xx xxxx */ /* LDR (register) 1111 1000 0101 xxxx xxxx 0000 00xx xxxx */ - DECODE_EMULATEX (0xffe00fc0, 0xf8400000, t32_emulate_ldrstr, + DECODE_EMULATEX (0xffe00fc0, 0xf8400000, PROBES_T32_LDRSTR, REGS(NOPCX, ANY, 0, 0, NOSPPC)), /* LDRB (literal) 1111 1000 x001 1111 xxxx xxxx xxxx xxxx */ /* LDRSB (literal) 1111 1001 x001 1111 xxxx xxxx xxxx xxxx */ /* LDRH (literal) 1111 1000 x011 1111 xxxx xxxx xxxx xxxx */ /* LDRSH (literal) 1111 1001 x011 1111 xxxx xxxx xxxx xxxx */ - DECODE_SIMULATEX(0xfe5f0000, 0xf81f0000, t32_simulate_ldr_literal, + DECODE_SIMULATEX(0xfe5f0000, 0xf81f0000, PROBES_T32_LDR_LIT, REGS(PC, NOSPPCX, 0, 0, 0)), /* STRB (immediate) 1111 1000 0000 xxxx xxxx 1xxx xxxx xxxx */ @@ -376,7 +373,7 @@ static const union decode_item t32_table_1111_100x[] = { /* LDRSB (immediate) 1111 1001 1001 xxxx xxxx xxxx xxxx xxxx */ /* LDRH (immediate) 1111 1000 1011 xxxx xxxx xxxx xxxx xxxx */ /* LDRSH (immediate) 1111 1001 1011 xxxx xxxx xxxx xxxx xxxx */ - DECODE_EMULATEX (0xfec00000, 0xf8800000, t32_emulate_ldrstr, + DECODE_EMULATEX (0xfec00000, 0xf8800000, PROBES_T32_LDRSTR, REGS(NOPCX, NOSPPCX, 0, 0, 0)), /* STRB (register) 1111 1000 0000 xxxx xxxx 0000 00xx xxxx */ @@ -385,7 +382,7 @@ static const union decode_item t32_table_1111_100x[] = { /* LDRSB (register) 1111 1001 0001 xxxx xxxx 0000 00xx xxxx */ /* LDRH (register) 1111 1000 0011 xxxx xxxx 0000 00xx xxxx */ /* LDRSH (register) 1111 1001 0011 xxxx xxxx 0000 00xx xxxx */ - DECODE_EMULATEX (0xfe800fc0, 0xf8000000, t32_emulate_ldrstr, + DECODE_EMULATEX (0xfe800fc0, 0xf8000000, PROBES_T32_LDRSTR, REGS(NOPCX, NOSPPCX, 0, 0, NOSPPC)), /* Other unallocated instructions... */ @@ -404,7 +401,7 @@ static const union decode_item t32_table_1111_1010___1111[] = { /* UXTB16 1111 1010 0011 1111 1111 xxxx 1xxx xxxx */ /* SXTB 1111 1010 0100 1111 1111 xxxx 1xxx xxxx */ /* UXTB 1111 1010 0101 1111 1111 xxxx 1xxx xxxx */ - DECODE_EMULATEX (0xff8ff080, 0xfa0ff080, t32_emulate_rd8rn16rm0_rwflags, + DECODE_EMULATEX (0xff8ff080, 0xfa0ff080, PROBES_T32_SIGN_EXTEND, REGS(0, 0, NOSPPC, 0, NOSPPC)), @@ -477,7 +474,7 @@ static const union decode_item t32_table_1111_1010___1111[] = { /* LSR 1111 1010 001x xxxx 1111 xxxx 0000 xxxx */ /* ASR 1111 1010 010x xxxx 1111 xxxx 0000 xxxx */ /* ROR 1111 1010 011x xxxx 1111 xxxx 0000 xxxx */ - DECODE_EMULATEX (0xff80f0f0, 0xfa00f000, t32_emulate_rd8rn16rm0_rwflags, + DECODE_EMULATEX (0xff80f0f0, 0xfa00f000, PROBES_T32_MEDIA, REGS(NOSPPC, 0, NOSPPC, 0, NOSPPC)), /* CLZ 1111 1010 1010 xxxx 1111 xxxx 1000 xxxx */ @@ -487,7 +484,7 @@ static const union decode_item t32_table_1111_1010___1111[] = { /* REV16 1111 1010 1001 xxxx 1111 xxxx 1001 xxxx */ /* RBIT 1111 1010 1001 xxxx 1111 xxxx 1010 xxxx */ /* REVSH 1111 1010 1001 xxxx 1111 xxxx 1011 xxxx */ - DECODE_EMULATEX (0xfff0f0c0, 0xfa90f080, t32_emulate_rd8rn16_noflags, + DECODE_EMULATEX (0xfff0f0c0, 0xfa90f080, PROBES_T32_REVERSE, REGS(NOSPPC, 0, NOSPPC, 0, SAMEAS16)), /* Other unallocated instructions... */ @@ -510,7 +507,7 @@ static const union decode_item t32_table_1111_1011_0[] = { /* SMUSD{X} 1111 1011 0100 xxxx 1111 xxxx 000x xxxx */ /* SMMUL{R} 1111 1011 0101 xxxx 1111 xxxx 000x xxxx */ /* USAD8 1111 1011 0111 xxxx 1111 xxxx 0000 xxxx */ - DECODE_EMULATEX (0xff80f0e0, 0xfb00f000, t32_emulate_rd8rn16rm0_rwflags, + DECODE_EMULATEX (0xff80f0e0, 0xfb00f000, PROBES_T32_MUL_ADD, REGS(NOSPPC, 0, NOSPPC, 0, NOSPPC)), /* ??? 1111 1011 0111 xxxx xxxx xxxx 0001 xxxx */ @@ -526,7 +523,7 @@ static const union decode_item t32_table_1111_1011_0[] = { /* SMMLA{R} 1111 1011 0101 xxxx xxxx xxxx 000x xxxx */ /* SMMLS{R} 1111 1011 0110 xxxx xxxx xxxx 000x xxxx */ /* USADA8 1111 1011 0111 xxxx xxxx xxxx 0000 xxxx */ - DECODE_EMULATEX (0xff8000c0, 0xfb000000, t32_emulate_rd8rn16rm0ra12_noflags, + DECODE_EMULATEX (0xff8000c0, 0xfb000000, PROBES_T32_MUL_ADD2, REGS(NOSPPC, NOSPPCX, NOSPPC, 0, NOSPPC)), /* Other unallocated instructions... */ @@ -547,7 +544,7 @@ static const union decode_item t32_table_1111_1011_1[] = { /* UMULL 1111 1011 1010 xxxx xxxx xxxx 0000 xxxx */ /* SMLAL 1111 1011 1100 xxxx xxxx xxxx 0000 xxxx */ /* UMLAL 1111 1011 1110 xxxx xxxx xxxx 0000 xxxx */ - DECODE_EMULATEX (0xff9000f0, 0xfb800000, t32_emulate_rdlo12rdhi8rn16rm0_noflags, + DECODE_EMULATEX (0xff9000f0, 0xfb800000, PROBES_T32_MUL_ADD_LONG, REGS(NOSPPC, NOSPPC, NOSPPC, 0, NOSPPC)), /* SDIV 1111 1011 1001 xxxx xxxx xxxx 1111 xxxx */ @@ -653,11 +650,11 @@ static const union decode_item t16_table_1011[] = { /* ADD (SP plus immediate) 1011 0000 0xxx xxxx */ /* SUB (SP minus immediate) 1011 0000 1xxx xxxx */ - DECODE_SIMULATE (0xff00, 0xb000, t16_simulate_add_sp_imm), + DECODE_SIMULATE (0xff00, 0xb000, PROBES_T16_ADD_SP), /* CBZ 1011 00x1 xxxx xxxx */ /* CBNZ 1011 10x1 xxxx xxxx */ - DECODE_SIMULATE (0xf500, 0xb100, t16_simulate_cbz), + DECODE_SIMULATE (0xf500, 0xb100, PROBES_T16_CBZ), /* SXTH 1011 0010 00xx xxxx */ /* SXTB 1011 0010 01xx xxxx */ @@ -668,12 +665,12 @@ static const union decode_item t16_table_1011[] = { /* ??? 1011 1010 10xx xxxx */ /* REVSH 1011 1010 11xx xxxx */ DECODE_REJECT (0xffc0, 0xba80), - DECODE_EMULATE (0xf500, 0xb000, t16_emulate_loregs_rwflags), + DECODE_EMULATE (0xf500, 0xb000, PROBES_T16_SIGN_EXTEND), /* PUSH 1011 010x xxxx xxxx */ - DECODE_CUSTOM (0xfe00, 0xb400, t16_decode_push), + DECODE_CUSTOM (0xfe00, 0xb400, PROBES_T16_PUSH), /* POP 1011 110x xxxx xxxx */ - DECODE_CUSTOM (0xfe00, 0xbc00, t16_decode_pop), + DECODE_CUSTOM (0xfe00, 0xbc00, PROBES_T16_POP), /* * If-Then, and hints @@ -683,15 +680,15 @@ static const union decode_item t16_table_1011[] = { /* YIELD 1011 1111 0001 0000 */ DECODE_OR (0xffff, 0xbf10), /* SEV 1011 1111 0100 0000 */ - DECODE_EMULATE (0xffff, 0xbf40, kprobe_emulate_none), + DECODE_EMULATE (0xffff, 0xbf40, PROBES_T16_SEV), /* NOP 1011 1111 0000 0000 */ /* WFE 1011 1111 0010 0000 */ /* WFI 1011 1111 0011 0000 */ - DECODE_SIMULATE (0xffcf, 0xbf00, kprobe_simulate_nop), + DECODE_SIMULATE (0xffcf, 0xbf00, PROBES_T16_WFE), /* Unassigned hints 1011 1111 xxxx 0000 */ DECODE_REJECT (0xff0f, 0xbf00), /* IT 1011 1111 xxxx xxxx */ - DECODE_CUSTOM (0xff00, 0xbf00, t16_decode_it), + DECODE_CUSTOM (0xff00, 0xbf00, PROBES_T16_IT), /* SETEND 1011 0110 010x xxxx */ /* CPS 1011 0110 011x xxxx */ @@ -708,7 +705,7 @@ const union decode_item kprobe_decode_thumb16_table[] = { */ /* CMP (immediate) 0010 1xxx xxxx xxxx */ - DECODE_EMULATE (0xf800, 0x2800, t16_emulate_loregs_rwflags), + DECODE_EMULATE (0xf800, 0x2800, PROBES_T16_CMP), /* ADD (register) 0001 100x xxxx xxxx */ /* SUB (register) 0001 101x xxxx xxxx */ @@ -720,7 +717,7 @@ const union decode_item kprobe_decode_thumb16_table[] = { /* MOV (immediate) 0010 0xxx xxxx xxxx */ /* ADD (immediate, Thumb) 0011 0xxx xxxx xxxx */ /* SUB (immediate, Thumb) 0011 1xxx xxxx xxxx */ - DECODE_EMULATE (0xc000, 0x0000, t16_emulate_loregs_noitrwflags), + DECODE_EMULATE (0xc000, 0x0000, PROBES_T16_ADDSUB), /* * 16-bit Thumb data-processing instructions @@ -728,10 +725,10 @@ const union decode_item kprobe_decode_thumb16_table[] = { */ /* TST (register) 0100 0010 00xx xxxx */ - DECODE_EMULATE (0xffc0, 0x4200, t16_emulate_loregs_rwflags), + DECODE_EMULATE (0xffc0, 0x4200, PROBES_T16_CMP), /* CMP (register) 0100 0010 10xx xxxx */ /* CMN (register) 0100 0010 11xx xxxx */ - DECODE_EMULATE (0xff80, 0x4280, t16_emulate_loregs_rwflags), + DECODE_EMULATE (0xff80, 0x4280, PROBES_T16_CMP), /* AND (register) 0100 0000 00xx xxxx */ /* EOR (register) 0100 0000 01xx xxxx */ /* LSL (register) 0100 0000 10xx xxxx */ @@ -745,7 +742,7 @@ const union decode_item kprobe_decode_thumb16_table[] = { /* MUL 0100 0011 00xx xxxx */ /* BIC (register) 0100 0011 10xx xxxx */ /* MVN (register) 0100 0011 10xx xxxx */ - DECODE_EMULATE (0xfc00, 0x4000, t16_emulate_loregs_noitrwflags), + DECODE_EMULATE (0xfc00, 0x4000, PROBES_T16_LOGICAL), /* * Special data instructions and branch and exchange @@ -757,7 +754,7 @@ const union decode_item kprobe_decode_thumb16_table[] = { /* BX (register) 0100 0111 0xxx xxxx */ /* BLX (register) 0100 0111 1xxx xxxx */ - DECODE_SIMULATE (0xff00, 0x4700, t16_simulate_bxblx), + DECODE_SIMULATE (0xff00, 0x4700, PROBES_T16_BLX), /* ADD pc, pc 0100 0100 1111 1111 */ DECODE_REJECT (0xffff, 0x44ff), @@ -765,13 +762,13 @@ const union decode_item kprobe_decode_thumb16_table[] = { /* ADD (register) 0100 0100 xxxx xxxx */ /* CMP (register) 0100 0101 xxxx xxxx */ /* MOV (register) 0100 0110 xxxx xxxx */ - DECODE_CUSTOM (0xfc00, 0x4400, t16_decode_hiregs), + DECODE_CUSTOM (0xfc00, 0x4400, PROBES_T16_HIREGOPS), /* * Load from Literal Pool * LDR (literal) 0100 1xxx xxxx xxxx */ - DECODE_SIMULATE (0xf800, 0x4800, t16_simulate_ldr_literal), + DECODE_SIMULATE (0xf800, 0x4800, PROBES_T16_LDR_LIT), /* * 16-bit Thumb Load/store instructions @@ -792,20 +789,20 @@ const union decode_item kprobe_decode_thumb16_table[] = { /* LDR (immediate, Thumb) 0110 1xxx xxxx xxxx */ /* STRB (immediate, Thumb) 0111 0xxx xxxx xxxx */ /* LDRB (immediate, Thumb) 0111 1xxx xxxx xxxx */ - DECODE_EMULATE (0xc000, 0x4000, t16_emulate_loregs_rwflags), + DECODE_EMULATE (0xc000, 0x4000, PROBES_T16_LDRHSTRH), /* STRH (immediate, Thumb) 1000 0xxx xxxx xxxx */ /* LDRH (immediate, Thumb) 1000 1xxx xxxx xxxx */ - DECODE_EMULATE (0xf000, 0x8000, t16_emulate_loregs_rwflags), + DECODE_EMULATE (0xf000, 0x8000, PROBES_T16_LDRHSTRH), /* STR (immediate, Thumb) 1001 0xxx xxxx xxxx */ /* LDR (immediate, Thumb) 1001 1xxx xxxx xxxx */ - DECODE_SIMULATE (0xf000, 0x9000, t16_simulate_ldrstr_sp_relative), + DECODE_SIMULATE (0xf000, 0x9000, PROBES_T16_LDRSTR), /* * Generate PC-/SP-relative address * ADR (literal) 1010 0xxx xxxx xxxx * ADD (SP plus immediate) 1010 1xxx xxxx xxxx */ - DECODE_SIMULATE (0xf000, 0xa000, t16_simulate_reladr), + DECODE_SIMULATE (0xf000, 0xa000, PROBES_T16_ADR), /* * Miscellaneous 16-bit instructions @@ -815,7 +812,7 @@ const union decode_item kprobe_decode_thumb16_table[] = { /* STM 1100 0xxx xxxx xxxx */ /* LDM 1100 1xxx xxxx xxxx */ - DECODE_EMULATE (0xf000, 0xc000, t16_emulate_loregs_rwflags), + DECODE_EMULATE (0xf000, 0xc000, PROBES_T16_LDMSTM), /* * Conditional branch, and Supervisor Call @@ -826,13 +823,13 @@ const union decode_item kprobe_decode_thumb16_table[] = { DECODE_REJECT (0xfe00, 0xde00), /* Conditional branch 1101 xxxx xxxx xxxx */ - DECODE_CUSTOM (0xf000, 0xd000, t16_decode_cond_branch), + DECODE_CUSTOM (0xf000, 0xd000, PROBES_T16_BRANCH_COND), /* * Unconditional branch * B 1110 0xxx xxxx xxxx */ - DECODE_SIMULATE (0xf800, 0xe000, t16_simulate_branch), + DECODE_SIMULATE (0xf800, 0xe000, PROBES_T16_BRANCH), DECODE_END }; @@ -862,17 +859,21 @@ static void __kprobes thumb32_singlestep(struct kprobe *p, struct pt_regs *regs) } enum kprobe_insn __kprobes -thumb16_kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi) +thumb16_kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi, + const union decode_action *actions) { asi->insn_singlestep = thumb16_singlestep; asi->insn_check_cc = thumb_check_cc; - return kprobe_decode_insn(insn, asi, kprobe_decode_thumb16_table, true); + return kprobe_decode_insn(insn, asi, kprobe_decode_thumb16_table, true, + actions); } enum kprobe_insn __kprobes -thumb32_kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi) +thumb32_kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi, + const union decode_action *actions) { asi->insn_singlestep = thumb32_singlestep; asi->insn_check_cc = thumb_check_cc; - return kprobe_decode_insn(insn, asi, kprobe_decode_thumb32_table, true); + return kprobe_decode_insn(insn, asi, kprobe_decode_thumb32_table, true, + actions); } diff --git a/arch/arm/kernel/probes-thumb.h b/arch/arm/kernel/probes-thumb.h index 98709c40b659..8d6b4eefa706 100644 --- a/arch/arm/kernel/probes-thumb.h +++ b/arch/arm/kernel/probes-thumb.h @@ -27,55 +27,61 @@ */ #define current_cond(cpsr) ((cpsr >> 12) & 0xf) -void __kprobes t16_simulate_bxblx(struct kprobe *p, struct pt_regs *regs); -void __kprobes t16_simulate_ldr_literal(struct kprobe *p, struct pt_regs *regs); -void __kprobes t16_simulate_ldrstr_sp_relative(struct kprobe *p, - struct pt_regs *regs); -void __kprobes t16_simulate_reladr(struct kprobe *p, struct pt_regs *regs); -void __kprobes t16_simulate_add_sp_imm(struct kprobe *p, struct pt_regs *regs); -void __kprobes t16_simulate_cbz(struct kprobe *p, struct pt_regs *regs); -void __kprobes t16_simulate_it(struct kprobe *p, struct pt_regs *regs); -void __kprobes t16_singlestep_it(struct kprobe *p, struct pt_regs *regs); -enum kprobe_insn __kprobes t16_decode_it(kprobe_opcode_t insn, - struct arch_specific_insn *asi); -void __kprobes t16_simulate_cond_branch(struct kprobe *p, struct pt_regs *regs); -enum kprobe_insn __kprobes t16_decode_cond_branch(kprobe_opcode_t insn, - struct arch_specific_insn *asi); -void __kprobes t16_simulate_branch(struct kprobe *p, struct pt_regs *regs); -void __kprobes t16_emulate_loregs_rwflags(struct kprobe *p, - struct pt_regs *regs); -void __kprobes t16_emulate_loregs_noitrwflags(struct kprobe *p, - struct pt_regs *regs); -void __kprobes t16_emulate_hiregs(struct kprobe *p, struct pt_regs *regs); -enum kprobe_insn __kprobes t16_decode_hiregs(kprobe_opcode_t insn, - struct arch_specific_insn *asi); -void __kprobes t16_emulate_push(struct kprobe *p, struct pt_regs *regs); -enum kprobe_insn __kprobes t16_decode_push(kprobe_opcode_t insn, - struct arch_specific_insn *asi); -void __kprobes t16_emulate_pop_nopc(struct kprobe *p, struct pt_regs *regs); -void __kprobes t16_emulate_pop_pc(struct kprobe *p, struct pt_regs *regs); -enum kprobe_insn __kprobes t16_decode_pop(kprobe_opcode_t insn, - struct arch_specific_insn *asi); +enum probes_t32_action { + PROBES_T32_EMULATE_NONE, + PROBES_T32_SIMULATE_NOP, + PROBES_T32_LDMSTM, + PROBES_T32_LDRDSTRD, + PROBES_T32_TABLE_BRANCH, + PROBES_T32_TST, + PROBES_T32_CMP, + PROBES_T32_MOV, + PROBES_T32_ADDSUB, + PROBES_T32_LOGICAL, + PROBES_T32_ADDWSUBW_PC, + PROBES_T32_ADDWSUBW, + PROBES_T32_MOVW, + PROBES_T32_SAT, + PROBES_T32_BITFIELD, + PROBES_T32_SEV, + PROBES_T32_WFE, + PROBES_T32_MRS, + PROBES_T32_BRANCH_COND, + PROBES_T32_BRANCH, + PROBES_T32_PLDI, + PROBES_T32_LDR_LIT, + PROBES_T32_LDRSTR, + PROBES_T32_SIGN_EXTEND, + PROBES_T32_MEDIA, + PROBES_T32_REVERSE, + PROBES_T32_MUL_ADD, + PROBES_T32_MUL_ADD2, + PROBES_T32_MUL_ADD_LONG, + NUM_PROBES_T32_ACTIONS +}; -void __kprobes t32_simulate_table_branch(struct kprobe *p, - struct pt_regs *regs); -void __kprobes t32_simulate_mrs(struct kprobe *p, struct pt_regs *regs); -void __kprobes t32_simulate_cond_branch(struct kprobe *p, struct pt_regs *regs); -enum kprobe_insn __kprobes t32_decode_cond_branch(kprobe_opcode_t insn, - struct arch_specific_insn *asi); -void __kprobes t32_simulate_branch(struct kprobe *p, struct pt_regs *regs); -void __kprobes t32_simulate_ldr_literal(struct kprobe *p, struct pt_regs *regs); -enum kprobe_insn __kprobes t32_decode_ldmstm(kprobe_opcode_t insn, - struct arch_specific_insn *asi); -void __kprobes t32_emulate_ldrdstrd(struct kprobe *p, struct pt_regs *regs); -void __kprobes t32_emulate_ldrstr(struct kprobe *p, struct pt_regs *regs); -void __kprobes t32_emulate_rd8rn16rm0_rwflags(struct kprobe *p, - struct pt_regs *regs); -void __kprobes t32_emulate_rd8pc16_noflags(struct kprobe *p, - struct pt_regs *regs); -void __kprobes t32_emulate_rd8rn16_noflags(struct kprobe *p, - struct pt_regs *regs); -void __kprobes t32_emulate_rdlo12rdhi8rn16rm0_noflags(struct kprobe *p, - struct pt_regs *regs); +enum probes_t16_action { + PROBES_T16_ADD_SP, + PROBES_T16_CBZ, + PROBES_T16_SIGN_EXTEND, + PROBES_T16_PUSH, + PROBES_T16_POP, + PROBES_T16_SEV, + PROBES_T16_WFE, + PROBES_T16_IT, + PROBES_T16_CMP, + PROBES_T16_ADDSUB, + PROBES_T16_LOGICAL, + PROBES_T16_BLX, + PROBES_T16_HIREGOPS, + PROBES_T16_LDR_LIT, + PROBES_T16_LDRHSTRH, + PROBES_T16_LDRSTR, + PROBES_T16_ADR, + PROBES_T16_LDMSTM, + PROBES_T16_BRANCH_COND, + PROBES_T16_BRANCH, + NUM_PROBES_T16_ACTIONS +}; #endif diff --git a/arch/arm/kernel/probes.c b/arch/arm/kernel/probes.c index 3a63f8f83cf8..efd92c5b4a52 100644 --- a/arch/arm/kernel/probes.c +++ b/arch/arm/kernel/probes.c @@ -381,7 +381,8 @@ static const int decode_struct_sizes[NUM_DECODE_TYPES] = { */ int __kprobes kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi, - const union decode_item *table, bool thumb) + const union decode_item *table, bool thumb, + const union decode_action *actions) { const struct decode_header *h = (struct decode_header *)table; const struct decode_header *next; @@ -415,18 +416,18 @@ kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi, case DECODE_TYPE_CUSTOM: { struct decode_custom *d = (struct decode_custom *)h; - return (*d->decoder.decoder)(insn, asi); + return actions[d->decoder.action].decoder(insn, asi, h); } case DECODE_TYPE_SIMULATE: { struct decode_simulate *d = (struct decode_simulate *)h; - asi->insn_handler = d->handler.handler; + asi->insn_handler = actions[d->handler.action].handler; return INSN_GOOD_NO_SLOT; } case DECODE_TYPE_EMULATE: { struct decode_emulate *d = (struct decode_emulate *)h; - asi->insn_handler = d->handler.handler; + asi->insn_handler = actions[d->handler.action].handler; set_emulated_insn(insn, asi, thumb); return INSN_GOOD; } diff --git a/arch/arm/kernel/probes.h b/arch/arm/kernel/probes.h index 17f656011aa3..5554f161bdac 100644 --- a/arch/arm/kernel/probes.h +++ b/arch/arm/kernel/probes.h @@ -133,7 +133,8 @@ void __kprobes kprobe_simulate_nop(struct kprobe *p, struct pt_regs *regs); void __kprobes kprobe_emulate_none(struct kprobe *p, struct pt_regs *regs); enum kprobe_insn __kprobes -kprobe_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi); +kprobe_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi, + const struct decode_header *h); /* * Test if load/store instructions writeback the address register. @@ -160,7 +161,7 @@ kprobe_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi); * {.bits = _type}, * {.bits = _mask}, * {.bits = _value}, - * {.handler = _handler}, + * {.action = _handler}, * * Initialising a specified member of the union means that the compiler * will produce a warning if the argument is of an incorrect type. @@ -173,19 +174,23 @@ kprobe_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi); * Instruction decoding jumps to parsing the new sub-table 'table'. * * DECODE_CUSTOM(mask, value, decoder) - * The custom function 'decoder' is called to the complete decoding - * of an instruction. + * The value of 'decoder' is used as an index into the array of + * action functions, and the retrieved decoder function is invoked + * to complete decoding of the instruction. * * DECODE_SIMULATE(mask, value, handler) - * Set the probes instruction handler to 'handler', this will be used - * to simulate the instruction when the probe is hit. Decoding returns - * with INSN_GOOD_NO_SLOT. + * The probes instruction handler is set to the value found by + * indexing into the action array using the value of 'handler'. This + * will be used to simulate the instruction when the probe is hit. + * Decoding returns with INSN_GOOD_NO_SLOT. * * DECODE_EMULATE(mask, value, handler) - * Set the probes instruction handler to 'handler', this will be used - * to emulate the instruction when the probe is hit. The modified - * instruction (see below) is placed in the probes instruction slot so it - * may be called by the emulation code. Decoding returns with INSN_GOOD. + * The probes instruction handler is set to the value found by + * indexing into the action array using the value of 'handler'. This + * will be used to emulate the instruction when the probe is hit. The + * modified instruction (see below) is placed in the probes instruction + * slot so it may be called by the emulation code. Decoding returns + * with INSN_GOOD. * * DECODE_REJECT(mask, value) * Instruction decoding fails with INSN_REJECTED @@ -238,7 +243,7 @@ kprobe_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi); * Here is a real example which matches ARM instructions of the form * "AND ,,, " * - * DECODE_EMULATEX (0x0e000090, 0x00000010, emulate_rd12rn16rm0rs8_rwflags, + * DECODE_EMULATEX (0x0e000090, 0x00000010, PROBES_DATA_PROCESSING_REG, * REGS(ANY, ANY, NOPC, 0, ANY)), * ^ ^ ^ ^ * Rn Rd Rs Rm @@ -249,7 +254,8 @@ kprobe_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi); * Decoding the instruction "AND R4, R5, R6, ASL R7" will be accepted and the * instruction will be modified to "AND R0, R2, R3, ASL R1" and then placed into * the kprobes instruction slot. This can then be called later by the handler - * function emulate_rd12rn16rm0rs8_rwflags in order to simulate the instruction. + * function emulate_rd12rn16rm0rs8_rwflags (a pointer to which is retrieved from + * the indicated slot in the action array), in order to simulate the instruction. */ enum decode_type { @@ -298,10 +304,17 @@ enum decode_reg_type { union decode_item { u32 bits; const union decode_item *table; - kprobe_insn_handler_t *handler; - kprobe_decode_insn_t *decoder; + int action; }; +typedef enum kprobe_insn (probes_custom_decode_t)(kprobe_opcode_t, + struct arch_specific_insn *, + const struct decode_header *); + +union decode_action { + kprobe_insn_handler_t *handler; + probes_custom_decode_t *decoder; +}; #define DECODE_END \ {.bits = DECODE_TYPE_END} @@ -336,7 +349,7 @@ struct decode_custom { #define DECODE_CUSTOM(_mask, _value, _decoder) \ DECODE_HEADER(DECODE_TYPE_CUSTOM, _mask, _value, 0), \ - {.decoder = (_decoder)} + {.action = (_decoder)} struct decode_simulate { @@ -346,7 +359,7 @@ struct decode_simulate { #define DECODE_SIMULATEX(_mask, _value, _handler, _regs) \ DECODE_HEADER(DECODE_TYPE_SIMULATE, _mask, _value, _regs), \ - {.handler = (_handler)} + {.action = (_handler)} #define DECODE_SIMULATE(_mask, _value, _handler) \ DECODE_SIMULATEX(_mask, _value, _handler, 0) @@ -359,7 +372,7 @@ struct decode_emulate { #define DECODE_EMULATEX(_mask, _value, _handler, _regs) \ DECODE_HEADER(DECODE_TYPE_EMULATE, _mask, _value, _regs), \ - {.handler = (_handler)} + {.action = (_handler)} #define DECODE_EMULATE(_mask, _value, _handler) \ DECODE_EMULATEX(_mask, _value, _handler, 0) @@ -384,14 +397,18 @@ struct decode_reject { #ifdef CONFIG_THUMB2_KERNEL extern const union decode_item kprobe_decode_thumb16_table[]; extern const union decode_item kprobe_decode_thumb32_table[]; +extern const union decode_action kprobes_t32_actions[]; +extern const union decode_action kprobes_t16_actions[]; #else extern const union decode_item kprobe_decode_arm_table[]; +extern const union decode_action kprobes_arm_actions[]; #endif extern kprobe_check_cc * const kprobe_condition_checks[16]; int kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi, - const union decode_item *table, bool thumb16); + const union decode_item *table, bool thumb16, + const union decode_action *actions); #endif