|
@@ -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;
|