ARM: Add an emulate flag to the kprobes/uprobes instruction decode functions
Add an emulate flag into the instruction interpreter, primarily for uprobes support. Signed-off-by: David A. Long <dave.long@linaro.org> Acked-by: Jon Medhurst <tixy@linaro.org>
This commit is contained in:
parent
47e190fafd
commit
602cd2609e
|
@ -89,7 +89,7 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
|
|||
p->opcode = insn;
|
||||
p->ainsn.insn = tmp_insn;
|
||||
|
||||
switch ((*decode_insn)(insn, &p->ainsn, actions)) {
|
||||
switch ((*decode_insn)(insn, &p->ainsn, true, actions)) {
|
||||
case INSN_REJECTED: /* not supported */
|
||||
return -EINVAL;
|
||||
|
||||
|
|
|
@ -35,6 +35,7 @@ kprobe_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi,
|
|||
|
||||
typedef enum probes_insn (kprobe_decode_insn_t)(probes_opcode_t,
|
||||
struct arch_specific_insn *,
|
||||
bool,
|
||||
const union decode_action *);
|
||||
|
||||
#ifdef CONFIG_THUMB2_KERNEL
|
||||
|
|
|
@ -725,10 +725,10 @@ static void __kprobes arm_singlestep(probes_opcode_t insn,
|
|||
*/
|
||||
enum probes_insn __kprobes
|
||||
arm_probes_decode_insn(probes_opcode_t insn, struct arch_specific_insn *asi,
|
||||
const union decode_action *actions)
|
||||
bool emulate, const union decode_action *actions)
|
||||
{
|
||||
asi->insn_singlestep = arm_singlestep;
|
||||
asi->insn_check_cc = probes_condition_checks[insn>>28];
|
||||
return probes_decode_insn(insn, asi, probes_decode_arm_table, false,
|
||||
actions);
|
||||
emulate, actions);
|
||||
}
|
||||
|
|
|
@ -67,7 +67,7 @@ void __kprobes simulate_mov_ipsp(probes_opcode_t opcode,
|
|||
extern const union decode_item probes_decode_arm_table[];
|
||||
|
||||
enum probes_insn arm_probes_decode_insn(probes_opcode_t,
|
||||
struct arch_specific_insn *,
|
||||
struct arch_specific_insn *, bool emulate,
|
||||
const union decode_action *actions);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -863,20 +863,20 @@ static void __kprobes thumb32_singlestep(probes_opcode_t opcode,
|
|||
|
||||
enum probes_insn __kprobes
|
||||
thumb16_probes_decode_insn(probes_opcode_t insn, struct arch_specific_insn *asi,
|
||||
const union decode_action *actions)
|
||||
bool emulate, const union decode_action *actions)
|
||||
{
|
||||
asi->insn_singlestep = thumb16_singlestep;
|
||||
asi->insn_check_cc = thumb_check_cc;
|
||||
return probes_decode_insn(insn, asi, probes_decode_thumb16_table, true,
|
||||
actions);
|
||||
emulate, actions);
|
||||
}
|
||||
|
||||
enum probes_insn __kprobes
|
||||
thumb32_probes_decode_insn(probes_opcode_t insn, struct arch_specific_insn *asi,
|
||||
const union decode_action *actions)
|
||||
bool emulate, const union decode_action *actions)
|
||||
{
|
||||
asi->insn_singlestep = thumb32_singlestep;
|
||||
asi->insn_check_cc = thumb_check_cc;
|
||||
return probes_decode_insn(insn, asi, probes_decode_thumb32_table, true,
|
||||
actions);
|
||||
emulate, actions);
|
||||
}
|
||||
|
|
|
@ -89,9 +89,9 @@ extern const union decode_item probes_decode_thumb16_table[];
|
|||
|
||||
enum probes_insn __kprobes
|
||||
thumb16_probes_decode_insn(probes_opcode_t insn, struct arch_specific_insn *asi,
|
||||
const union decode_action *actions);
|
||||
bool emulate, const union decode_action *actions);
|
||||
enum probes_insn __kprobes
|
||||
thumb32_probes_decode_insn(probes_opcode_t insn, struct arch_specific_insn *asi,
|
||||
const union decode_action *actions);
|
||||
bool emulate, const union decode_action *actions);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -401,7 +401,7 @@ probes_insn_handler_t probes_emulate_none;
|
|||
|
||||
int __kprobes
|
||||
probes_decode_insn(probes_opcode_t insn, struct arch_specific_insn *asi,
|
||||
const union decode_item *table, bool thumb,
|
||||
const union decode_item *table, bool thumb, bool emulate,
|
||||
const union decode_action *actions);
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue