diff options
Diffstat (limited to 'arch/arm/kernel/probes.c')
-rw-r--r-- | arch/arm/kernel/probes.c | 18 |
1 files changed, 13 insertions, 5 deletions
diff --git a/arch/arm/kernel/probes.c b/arch/arm/kernel/probes.c index b6d9b855273c..f9dff12cf85c 100644 --- a/arch/arm/kernel/probes.c +++ b/arch/arm/kernel/probes.c @@ -257,7 +257,7 @@ set_emulated_insn(probes_opcode_t insn, struct arch_specific_insn *asi, * non-zero value, the corresponding nibble in pinsn is validated and modified * according to the type. */ -static bool __kprobes decode_regs(probes_opcode_t *pinsn, u32 regs) +static bool __kprobes decode_regs(probes_opcode_t *pinsn, u32 regs, bool modify) { probes_opcode_t insn = *pinsn; probes_opcode_t mask = 0xf; /* Start at least significant nibble */ @@ -323,7 +323,9 @@ static bool __kprobes decode_regs(probes_opcode_t *pinsn, u32 regs) insn |= new_bits & mask; } - *pinsn = insn; + if (modify) + *pinsn = insn; + return true; reject: @@ -385,13 +387,14 @@ static const int decode_struct_sizes[NUM_DECODE_TYPES] = { int __kprobes probes_decode_insn(probes_opcode_t insn, struct arch_specific_insn *asi, const union decode_item *table, bool thumb, - const union decode_action *actions) + bool emulate, const union decode_action *actions) { const struct decode_header *h = (struct decode_header *)table; const struct decode_header *next; bool matched = false; - insn = prepare_emulated_insn(insn, asi, thumb); + if (emulate) + insn = prepare_emulated_insn(insn, asi, thumb); for (;; h = next) { enum decode_type type = h->type_regs.bits & DECODE_TYPE_MASK; @@ -406,7 +409,7 @@ probes_decode_insn(probes_opcode_t insn, struct arch_specific_insn *asi, if (!matched && (insn & h->mask.bits) != h->value.bits) continue; - if (!decode_regs(&insn, regs)) + if (!decode_regs(&insn, regs, emulate)) return INSN_REJECTED; switch (type) { @@ -430,6 +433,11 @@ probes_decode_insn(probes_opcode_t insn, struct arch_specific_insn *asi, case DECODE_TYPE_EMULATE: { struct decode_emulate *d = (struct decode_emulate *)h; + + if (!emulate) + return actions[d->handler.action].decoder(insn, + asi, h); + asi->insn_handler = actions[d->handler.action].handler; set_emulated_insn(insn, asi, thumb); return INSN_GOOD; |