Skip to content

Commit

Permalink
ARM: Remove use of struct kprobe from generic probes code
Browse files Browse the repository at this point in the history
Change the generic ARM probes code to pass in the opcode and architecture-specific
structure separately instead of using struct kprobe, so we do not pollute
code being used only for uprobes or other non-kprobes instruction
interpretation.

Signed-off-by: David A. Long <dave.long@linaro.org>
Acked-by: Jon Medhurst <tixy@linaro.org>
  • Loading branch information
David A. Long committed Mar 18, 2014
1 parent 3e6cd39 commit 7579f4b
Show file tree
Hide file tree
Showing 10 changed files with 201 additions and 170 deletions.
9 changes: 7 additions & 2 deletions arch/arm/include/asm/probes.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,14 @@

struct kprobe;

typedef void (kprobe_insn_handler_t)(struct kprobe *, struct pt_regs *);
struct arch_specific_insn;
typedef void (kprobe_insn_handler_t)(kprobe_opcode_t,
struct arch_specific_insn *,
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_singlestep_t)(kprobe_opcode_t,
struct arch_specific_insn *,
struct pt_regs *);
typedef void (kprobe_insn_fn_t)(void);

/* Architecture specific copy of original instruction. */
Expand Down
61 changes: 31 additions & 30 deletions arch/arm/kernel/kprobes-arm.c
Original file line number Diff line number Diff line change
Expand Up @@ -72,12 +72,11 @@
"mov pc, "reg" \n\t"
#endif


static void __kprobes
emulate_ldrdstrd(struct kprobe *p, struct pt_regs *regs)
emulate_ldrdstrd(kprobe_opcode_t insn,
struct arch_specific_insn *asi, struct pt_regs *regs)
{
kprobe_opcode_t insn = p->opcode;
unsigned long pc = (unsigned long)p->addr + 8;
unsigned long pc = regs->ARM_pc + 4;
int rt = (insn >> 12) & 0xf;
int rn = (insn >> 16) & 0xf;
int rm = insn & 0xf;
Expand All @@ -92,7 +91,7 @@ emulate_ldrdstrd(struct kprobe *p, struct pt_regs *regs)
BLX("%[fn]")
: "=r" (rtv), "=r" (rt2v), "=r" (rnv)
: "0" (rtv), "1" (rt2v), "2" (rnv), "r" (rmv),
[fn] "r" (p->ainsn.insn_fn)
[fn] "r" (asi->insn_fn)
: "lr", "memory", "cc"
);

Expand All @@ -103,10 +102,10 @@ emulate_ldrdstrd(struct kprobe *p, struct pt_regs *regs)
}

static void __kprobes
emulate_ldr(struct kprobe *p, struct pt_regs *regs)
emulate_ldr(kprobe_opcode_t insn,
struct arch_specific_insn *asi, struct pt_regs *regs)
{
kprobe_opcode_t insn = p->opcode;
unsigned long pc = (unsigned long)p->addr + 8;
unsigned long pc = regs->ARM_pc + 4;
int rt = (insn >> 12) & 0xf;
int rn = (insn >> 16) & 0xf;
int rm = insn & 0xf;
Expand All @@ -119,7 +118,7 @@ emulate_ldr(struct kprobe *p, struct pt_regs *regs)
__asm__ __volatile__ (
BLX("%[fn]")
: "=r" (rtv), "=r" (rnv)
: "1" (rnv), "r" (rmv), [fn] "r" (p->ainsn.insn_fn)
: "1" (rnv), "r" (rmv), [fn] "r" (asi->insn_fn)
: "lr", "memory", "cc"
);

Expand All @@ -133,11 +132,11 @@ emulate_ldr(struct kprobe *p, struct pt_regs *regs)
}

static void __kprobes
emulate_str(struct kprobe *p, struct pt_regs *regs)
emulate_str(kprobe_opcode_t insn,
struct arch_specific_insn *asi, struct pt_regs *regs)
{
kprobe_opcode_t insn = p->opcode;
unsigned long rtpc = (unsigned long)p->addr + str_pc_offset;
unsigned long rnpc = (unsigned long)p->addr + 8;
unsigned long rtpc = regs->ARM_pc - 4 + str_pc_offset;
unsigned long rnpc = regs->ARM_pc + 4;
int rt = (insn >> 12) & 0xf;
int rn = (insn >> 16) & 0xf;
int rm = insn & 0xf;
Expand All @@ -151,7 +150,7 @@ emulate_str(struct kprobe *p, struct pt_regs *regs)
__asm__ __volatile__ (
BLX("%[fn]")
: "=r" (rnv)
: "r" (rtv), "0" (rnv), "r" (rmv), [fn] "r" (p->ainsn.insn_fn)
: "r" (rtv), "0" (rnv), "r" (rmv), [fn] "r" (asi->insn_fn)
: "lr", "memory", "cc"
);

Expand All @@ -160,10 +159,10 @@ emulate_str(struct kprobe *p, struct pt_regs *regs)
}

static void __kprobes
emulate_rd12rn16rm0rs8_rwflags(struct kprobe *p, struct pt_regs *regs)
emulate_rd12rn16rm0rs8_rwflags(kprobe_opcode_t insn,
struct arch_specific_insn *asi, struct pt_regs *regs)
{
kprobe_opcode_t insn = p->opcode;
unsigned long pc = (unsigned long)p->addr + 8;
unsigned long pc = regs->ARM_pc + 4;
int rd = (insn >> 12) & 0xf;
int rn = (insn >> 16) & 0xf;
int rm = insn & 0xf;
Expand All @@ -183,7 +182,7 @@ emulate_rd12rn16rm0rs8_rwflags(struct kprobe *p, struct pt_regs *regs)
"mrs %[cpsr], cpsr \n\t"
: "=r" (rdv), [cpsr] "=r" (cpsr)
: "0" (rdv), "r" (rnv), "r" (rmv), "r" (rsv),
"1" (cpsr), [fn] "r" (p->ainsn.insn_fn)
"1" (cpsr), [fn] "r" (asi->insn_fn)
: "lr", "memory", "cc"
);

Expand All @@ -195,9 +194,9 @@ emulate_rd12rn16rm0rs8_rwflags(struct kprobe *p, struct pt_regs *regs)
}

static void __kprobes
emulate_rd12rn16rm0_rwflags_nopc(struct kprobe *p, struct pt_regs *regs)
emulate_rd12rn16rm0_rwflags_nopc(kprobe_opcode_t insn,
struct arch_specific_insn *asi, struct pt_regs *regs)
{
kprobe_opcode_t insn = p->opcode;
int rd = (insn >> 12) & 0xf;
int rn = (insn >> 16) & 0xf;
int rm = insn & 0xf;
Expand All @@ -213,7 +212,7 @@ emulate_rd12rn16rm0_rwflags_nopc(struct kprobe *p, struct pt_regs *regs)
"mrs %[cpsr], cpsr \n\t"
: "=r" (rdv), [cpsr] "=r" (cpsr)
: "0" (rdv), "r" (rnv), "r" (rmv),
"1" (cpsr), [fn] "r" (p->ainsn.insn_fn)
"1" (cpsr), [fn] "r" (asi->insn_fn)
: "lr", "memory", "cc"
);

Expand All @@ -222,9 +221,10 @@ emulate_rd12rn16rm0_rwflags_nopc(struct kprobe *p, struct pt_regs *regs)
}

static void __kprobes
emulate_rd16rn12rm0rs8_rwflags_nopc(struct kprobe *p, struct pt_regs *regs)
emulate_rd16rn12rm0rs8_rwflags_nopc(kprobe_opcode_t insn,
struct arch_specific_insn *asi,
struct pt_regs *regs)
{
kprobe_opcode_t insn = p->opcode;
int rd = (insn >> 16) & 0xf;
int rn = (insn >> 12) & 0xf;
int rm = insn & 0xf;
Expand All @@ -242,7 +242,7 @@ emulate_rd16rn12rm0rs8_rwflags_nopc(struct kprobe *p, struct pt_regs *regs)
"mrs %[cpsr], cpsr \n\t"
: "=r" (rdv), [cpsr] "=r" (cpsr)
: "0" (rdv), "r" (rnv), "r" (rmv), "r" (rsv),
"1" (cpsr), [fn] "r" (p->ainsn.insn_fn)
"1" (cpsr), [fn] "r" (asi->insn_fn)
: "lr", "memory", "cc"
);

Expand All @@ -251,9 +251,9 @@ emulate_rd16rn12rm0rs8_rwflags_nopc(struct kprobe *p, struct pt_regs *regs)
}

static void __kprobes
emulate_rd12rm0_noflags_nopc(struct kprobe *p, struct pt_regs *regs)
emulate_rd12rm0_noflags_nopc(kprobe_opcode_t insn,
struct arch_specific_insn *asi, struct pt_regs *regs)
{
kprobe_opcode_t insn = p->opcode;
int rd = (insn >> 12) & 0xf;
int rm = insn & 0xf;

Expand All @@ -263,17 +263,18 @@ emulate_rd12rm0_noflags_nopc(struct kprobe *p, struct pt_regs *regs)
__asm__ __volatile__ (
BLX("%[fn]")
: "=r" (rdv)
: "0" (rdv), "r" (rmv), [fn] "r" (p->ainsn.insn_fn)
: "0" (rdv), "r" (rmv), [fn] "r" (asi->insn_fn)
: "lr", "memory", "cc"
);

regs->uregs[rd] = rdv;
}

static void __kprobes
emulate_rdlo12rdhi16rn0rm8_rwflags_nopc(struct kprobe *p, struct pt_regs *regs)
emulate_rdlo12rdhi16rn0rm8_rwflags_nopc(kprobe_opcode_t insn,
struct arch_specific_insn *asi,
struct pt_regs *regs)
{
kprobe_opcode_t insn = p->opcode;
int rdlo = (insn >> 12) & 0xf;
int rdhi = (insn >> 16) & 0xf;
int rn = insn & 0xf;
Expand All @@ -291,7 +292,7 @@ emulate_rdlo12rdhi16rn0rm8_rwflags_nopc(struct kprobe *p, struct pt_regs *regs)
"mrs %[cpsr], cpsr \n\t"
: "=r" (rdlov), "=r" (rdhiv), [cpsr] "=r" (cpsr)
: "0" (rdlov), "1" (rdhiv), "r" (rnv), "r" (rmv),
"2" (cpsr), [fn] "r" (p->ainsn.insn_fn)
"2" (cpsr), [fn] "r" (asi->insn_fn)
: "lr", "memory", "cc"
);

Expand Down
40 changes: 26 additions & 14 deletions arch/arm/kernel/kprobes-common.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@
#include "kprobes.h"


static void __kprobes simulate_ldm1stm1(struct kprobe *p, struct pt_regs *regs)
static void __kprobes simulate_ldm1stm1(kprobe_opcode_t insn,
struct arch_specific_insn *asi,
struct pt_regs *regs)
{
kprobe_opcode_t insn = p->opcode;
int rn = (insn >> 16) & 0xf;
int lbit = insn & (1 << 20);
int wbit = insn & (1 << 21);
Expand Down Expand Up @@ -58,24 +59,31 @@ static void __kprobes simulate_ldm1stm1(struct kprobe *p, struct pt_regs *regs)
}
}

static void __kprobes simulate_stm1_pc(struct kprobe *p, struct pt_regs *regs)
static void __kprobes simulate_stm1_pc(kprobe_opcode_t insn,
struct arch_specific_insn *asi,
struct pt_regs *regs)
{
regs->ARM_pc = (long)p->addr + str_pc_offset;
simulate_ldm1stm1(p, regs);
regs->ARM_pc = (long)p->addr + 4;
unsigned long addr = regs->ARM_pc - 4;

regs->ARM_pc = (long)addr + str_pc_offset;
simulate_ldm1stm1(insn, asi, regs);
regs->ARM_pc = (long)addr + 4;
}

static void __kprobes simulate_ldm1_pc(struct kprobe *p, struct pt_regs *regs)
static void __kprobes simulate_ldm1_pc(kprobe_opcode_t insn,
struct arch_specific_insn *asi,
struct pt_regs *regs)
{
simulate_ldm1stm1(p, regs);
simulate_ldm1stm1(insn, asi, regs);
load_write_pc(regs->ARM_pc, regs);
}

static void __kprobes
emulate_generic_r0_12_noflags(struct kprobe *p, struct pt_regs *regs)
emulate_generic_r0_12_noflags(kprobe_opcode_t insn,
struct arch_specific_insn *asi, struct pt_regs *regs)
{
register void *rregs asm("r1") = regs;
register void *rfn asm("lr") = p->ainsn.insn_fn;
register void *rfn asm("lr") = asi->insn_fn;

__asm__ __volatile__ (
"stmdb sp!, {%[regs], r11} \n\t"
Expand All @@ -99,15 +107,19 @@ emulate_generic_r0_12_noflags(struct kprobe *p, struct pt_regs *regs)
}

static void __kprobes
emulate_generic_r2_14_noflags(struct kprobe *p, struct pt_regs *regs)
emulate_generic_r2_14_noflags(kprobe_opcode_t insn,
struct arch_specific_insn *asi, struct pt_regs *regs)
{
emulate_generic_r0_12_noflags(p, (struct pt_regs *)(regs->uregs+2));
emulate_generic_r0_12_noflags(insn, asi,
(struct pt_regs *)(regs->uregs+2));
}

static void __kprobes
emulate_ldm_r3_15(struct kprobe *p, struct pt_regs *regs)
emulate_ldm_r3_15(kprobe_opcode_t insn,
struct arch_specific_insn *asi, struct pt_regs *regs)
{
emulate_generic_r0_12_noflags(p, (struct pt_regs *)(regs->uregs+3));
emulate_generic_r0_12_noflags(insn, asi,
(struct pt_regs *)(regs->uregs+3));
load_write_pc(regs->ARM_pc, regs);
}

Expand Down
Loading

0 comments on commit 7579f4b

Please sign in to comment.