Skip to content

Commit

Permalink
ARM: kprobes: Extend arch_specific_insn to add pointer to emulated in…
Browse files Browse the repository at this point in the history
…struction

When we come to emulating Thumb instructions then, to interwork
correctly, the code on in the instruction slot must be invoked with a
function pointer which has the least significant bit set. Rather that
set this by hand in every Thumb emulation function we will add a new
field for this purpose to arch_specific_insn, called insn_fn.

This also enables us to seamlessly share emulation functions between ARM
and Thumb code.

Signed-off-by: Jon Medhurst <tixy@yxit.co.uk>
Acked-by: Nicolas Pitre <nicolas.pitre@linaro.org>
  • Loading branch information
Jon Medhurst authored and Tixy committed Jul 13, 2011
1 parent c6a7d97 commit e296031
Show file tree
Hide file tree
Showing 2 changed files with 7 additions and 0 deletions.
2 changes: 2 additions & 0 deletions arch/arm/include/asm/kprobes.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,15 @@ struct kprobe;
typedef void (kprobe_insn_handler_t)(struct kprobe *, struct pt_regs *);
typedef unsigned long (kprobe_check_cc)(unsigned long);
typedef void (kprobe_insn_singlestep_t)(struct kprobe *, struct pt_regs *);
typedef void (kprobe_insn_fn_t)(void);

/* Architecture specific copy of original instruction. */
struct arch_specific_insn {
kprobe_opcode_t *insn;
kprobe_insn_handler_t *insn_handler;
kprobe_check_cc *insn_check_cc;
kprobe_insn_singlestep_t *insn_singlestep;
kprobe_insn_fn_t *insn_fn;
};

struct prev_kprobe {
Expand Down
5 changes: 5 additions & 0 deletions arch/arm/kernel/kprobes.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,15 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
kprobe_opcode_t insn;
kprobe_opcode_t tmp_insn[MAX_INSN_SIZE];
unsigned long addr = (unsigned long)p->addr;
bool thumb;
kprobe_decode_insn_t *decode_insn;
int is;

if (in_exception_text(addr))
return -EINVAL;

#ifdef CONFIG_THUMB2_KERNEL
thumb = true;
addr &= ~1; /* Bit 0 would normally be set to indicate Thumb code */
insn = ((u16 *)addr)[0];
if (is_wide_instruction(insn)) {
Expand All @@ -67,6 +69,7 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
} else
decode_insn = thumb16_kprobe_decode_insn;
#else /* !CONFIG_THUMB2_KERNEL */
thumb = false;
if (addr & 0x3)
return -EINVAL;
insn = *p->addr;
Expand All @@ -88,6 +91,8 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
p->ainsn.insn[is] = tmp_insn[is];
flush_insns(p->ainsn.insn,
sizeof(p->ainsn.insn[0]) * MAX_INSN_SIZE);
p->ainsn.insn_fn = (kprobe_insn_fn_t *)
((uintptr_t)p->ainsn.insn | thumb);
break;

case INSN_GOOD_NO_SLOT: /* instruction doesn't need insn slot */
Expand Down

0 comments on commit e296031

Please sign in to comment.