* [PATCH v4 00/16] uprobes: Add uprobes support for ARM
@ 2013-12-16 4:08 David Long
2013-12-16 4:08 ` [PATCH v4 01/16] uprobes: allow ignoring of probe hits David Long
` (15 more replies)
0 siblings, 16 replies; 34+ messages in thread
From: David Long @ 2013-12-16 4:08 UTC (permalink / raw)
To: linux-arm-kernel
From: "David A. Long" <dave.long@linaro.org>
This patch series adds basic uprobes support to ARM. It is based on patches
developed earlier by Rabin Vincent. That approach of adding hooks into
the kprobes instruction parsing code was not well received. This approach
separates the ARM instruction parsing code in kprobes out into a separate set
of functions which can be used by both kprobes and uprobes. Both kprobes and
uprobes then provide their own semantic action tables to process the results of
the parsing.
The following are noteworthy changes made for v4:
1) The dependency on kprobe.h is now correctly fixed.
2) A few changes to correctly support bigendian.
3) Remove the opcode address arg from the emulate and simulate functions
and just get the address from the pt_regs structure instead.
This patchset is based on v3.13-rc4.
David A. Long (15):
uprobes: allow ignoring of probe hits
ARM: move shared uprobe/kprobe definitions into new include file
ARM: Move generic arm instruction parsing code to new files for
sharing between features
ARM: move generic thumb instruction parsing code to new files for use
by other feature
ARM: use a function table for determining instruction interpreter
actions
ARM: Remove use of struct kprobe from generic probes code
ARM: Use new opcode type in ARM kprobes/uprobes code
ARM: Make the kprobes condition_check symbol names more generic
ARM: Change more ARM kprobes symbol names to something more
ARM: Rename the shared kprobes/uprobe return value enum
ARM: Change the remaining shared kprobes/uprobes symbols to something
generic
ARM: Add an emulate flag to the kprobes/uprobes instruction decode
functions
ARM: Make arch_specific_insn a define for new arch_probes_insn
structure
ARM: add uprobes support
ARM: Remove uprobes dependency on kprobes
Jon Medhurst (Tixy) (1):
ARM: Disable jprobes test when built into thumb-mode kernel
arch/arm/Kconfig | 3 +
arch/arm/include/asm/kprobes.h | 15 +-
arch/arm/include/asm/probes.h | 25 +
arch/arm/include/asm/ptrace.h | 6 +
arch/arm/include/asm/thread_info.h | 5 +-
arch/arm/include/asm/uprobes.h | 36 +
arch/arm/kernel/Makefile | 7 +-
arch/arm/kernel/kprobes-arm.c | 804 ++------------
arch/arm/kernel/kprobes-common.c | 468 +-------
arch/arm/kernel/kprobes-test.c | 18 +-
arch/arm/kernel/kprobes-thumb.c | 1142 +++-----------------
arch/arm/kernel/kprobes.c | 24 +-
arch/arm/kernel/kprobes.h | 399 +------
arch/arm/kernel/{kprobes-arm.c => probes-arm.c} | 441 ++------
arch/arm/kernel/probes-arm.h | 72 ++
.../arm/kernel/{kprobes-thumb.c => probes-thumb.c} | 771 ++-----------
arch/arm/kernel/probes-thumb.h | 95 ++
arch/arm/kernel/{kprobes-common.c => probes.c} | 215 +---
arch/arm/kernel/{kprobes.h => probes.h} | 91 +-
arch/arm/kernel/signal.c | 4 +
arch/arm/kernel/uprobes-arm.c | 223 ++++
arch/arm/kernel/uprobes.c | 198 ++++
arch/arm/kernel/uprobes.h | 27 +
include/linux/uprobes.h | 1 +
kernel/events/uprobes.c | 9 +
25 files changed, 1271 insertions(+), 3828 deletions(-)
create mode 100644 arch/arm/include/asm/probes.h
create mode 100644 arch/arm/include/asm/uprobes.h
copy arch/arm/kernel/{kprobes-arm.c => probes-arm.c} (64%)
create mode 100644 arch/arm/kernel/probes-arm.h
copy arch/arm/kernel/{kprobes-thumb.c => probes-thumb.c} (56%)
create mode 100644 arch/arm/kernel/probes-thumb.h
copy arch/arm/kernel/{kprobes-common.c => probes.c} (67%)
copy arch/arm/kernel/{kprobes.h => probes.h} (85%)
create mode 100644 arch/arm/kernel/uprobes-arm.c
create mode 100644 arch/arm/kernel/uprobes.c
create mode 100644 arch/arm/kernel/uprobes.h
--
1.8.1.2
^ permalink raw reply [flat|nested] 34+ messages in thread
* [PATCH v4 01/16] uprobes: allow ignoring of probe hits
2013-12-16 4:08 [PATCH v4 00/16] uprobes: Add uprobes support for ARM David Long
@ 2013-12-16 4:08 ` David Long
2013-12-16 4:08 ` [PATCH v4 02/16] ARM: move shared uprobe/kprobe definitions into new include file David Long
` (14 subsequent siblings)
15 siblings, 0 replies; 34+ messages in thread
From: David Long @ 2013-12-16 4:08 UTC (permalink / raw)
To: linux-arm-kernel
From: "David A. Long" <dave.long@linaro.org>
Allow arches to decided to ignore a probe hit. ARM will use this to
only call handlers if the conditions to execute a conditionally executed
instruction are satisfied.
Signed-off-by: David A. Long <dave.long@linaro.org>
Acked-by: Oleg Nesterov <oleg@redhat.com>
---
include/linux/uprobes.h | 1 +
kernel/events/uprobes.c | 9 +++++++++
2 files changed, 10 insertions(+)
diff --git a/include/linux/uprobes.h b/include/linux/uprobes.h
index 319eae7..197a36e 100644
--- a/include/linux/uprobes.h
+++ b/include/linux/uprobes.h
@@ -134,6 +134,7 @@ extern bool arch_uprobe_xol_was_trapped(struct task_struct *tsk);
extern int arch_uprobe_exception_notify(struct notifier_block *self, unsigned long val, void *data);
extern void arch_uprobe_abort_xol(struct arch_uprobe *aup, struct pt_regs *regs);
extern unsigned long arch_uretprobe_hijack_return_addr(unsigned long trampoline_vaddr, struct pt_regs *regs);
+extern bool __weak arch_uprobe_ignore(struct arch_uprobe *aup, struct pt_regs *regs);
#else /* !CONFIG_UPROBES */
struct uprobes_state {
};
diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index 24b7d6c..4eec7ce 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -1778,6 +1778,11 @@ static bool handle_trampoline(struct pt_regs *regs)
return true;
}
+bool __weak arch_uprobe_ignore(struct arch_uprobe *aup, struct pt_regs *regs)
+{
+ return false;
+}
+
/*
* Run handler and ask thread to singlestep.
* Ensure all non-fatal signals cannot interrupt thread while it singlesteps.
@@ -1828,7 +1833,11 @@ static void handle_swbp(struct pt_regs *regs)
if (unlikely(!test_bit(UPROBE_COPY_INSN, &uprobe->flags)))
goto out;
+ if (arch_uprobe_ignore(&uprobe->arch, regs))
+ goto out;
+
handler_chain(uprobe, regs);
+
if (can_skip_sstep(uprobe, regs))
goto out;
--
1.8.1.2
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH v4 02/16] ARM: move shared uprobe/kprobe definitions into new include file
2013-12-16 4:08 [PATCH v4 00/16] uprobes: Add uprobes support for ARM David Long
2013-12-16 4:08 ` [PATCH v4 01/16] uprobes: allow ignoring of probe hits David Long
@ 2013-12-16 4:08 ` David Long
2013-12-20 12:46 ` Jon Medhurst (Tixy)
2013-12-16 4:08 ` [PATCH v4 03/16] ARM: Move generic arm instruction parsing code to new files for sharing between features David Long
` (13 subsequent siblings)
15 siblings, 1 reply; 34+ messages in thread
From: David Long @ 2013-12-16 4:08 UTC (permalink / raw)
To: linux-arm-kernel
From: "David A. Long" <dave.long@linaro.org>
Separate the kprobe-only definitions from the definitions needed by
both kprobes and uprobes.
Signed-off-by: David A. Long <dave.long@linaro.org>
---
arch/arm/include/asm/kprobes.h | 15 +--------------
arch/arm/include/asm/probes.h | 18 ++++++++++++++++++
2 files changed, 19 insertions(+), 14 deletions(-)
create mode 100644 arch/arm/include/asm/probes.h
diff --git a/arch/arm/include/asm/kprobes.h b/arch/arm/include/asm/kprobes.h
index f82ec22..30fc11b 100644
--- a/arch/arm/include/asm/kprobes.h
+++ b/arch/arm/include/asm/kprobes.h
@@ -28,21 +28,8 @@
#define kretprobe_blacklist_size 0
typedef u32 kprobe_opcode_t;
-
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;
-};
+#include <asm/probes.h>
struct prev_kprobe {
struct kprobe *kp;
diff --git a/arch/arm/include/asm/probes.h b/arch/arm/include/asm/probes.h
new file mode 100644
index 0000000..21da148
--- /dev/null
+++ b/arch/arm/include/asm/probes.h
@@ -0,0 +1,18 @@
+#ifndef _ASM_PROBES_H
+#define _ASM_PROBES_H
+
+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;
+};
+
+#endif
--
1.8.1.2
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH v4 03/16] ARM: Move generic arm instruction parsing code to new files for sharing between features
2013-12-16 4:08 [PATCH v4 00/16] uprobes: Add uprobes support for ARM David Long
2013-12-16 4:08 ` [PATCH v4 01/16] uprobes: allow ignoring of probe hits David Long
2013-12-16 4:08 ` [PATCH v4 02/16] ARM: move shared uprobe/kprobe definitions into new include file David Long
@ 2013-12-16 4:08 ` David Long
2013-12-16 4:08 ` [PATCH v4 04/16] ARM: move generic thumb instruction parsing code to new files for use by other feature David Long
` (12 subsequent siblings)
15 siblings, 0 replies; 34+ messages in thread
From: David Long @ 2013-12-16 4:08 UTC (permalink / raw)
To: linux-arm-kernel
From: "David A. Long" <dave.long@linaro.org>
Move the arm version of the kprobes instruction parsing code into more generic
files from where it can be used by uprobes and possibly other subsystems. The
symbol names will be made more generic in a subsequent part of this patchset.
Signed-off-by: David A. Long <dave.long@linaro.org>
---
arch/arm/include/asm/probes.h | 2 +
arch/arm/kernel/Makefile | 4 +-
arch/arm/kernel/kprobes-arm.c | 722 +-----------------------
arch/arm/kernel/kprobes-common.c | 421 --------------
arch/arm/kernel/kprobes.h | 373 +-----------
arch/arm/kernel/{kprobes-arm.c => probes-arm.c} | 298 +---------
arch/arm/kernel/probes-arm.h | 38 ++
arch/arm/kernel/{kprobes-common.c => probes.c} | 144 +----
arch/arm/kernel/{kprobes.h => probes.h} | 51 +-
9 files changed, 75 insertions(+), 1978 deletions(-)
copy arch/arm/kernel/{kprobes-arm.c => probes-arm.c} (76%)
create mode 100644 arch/arm/kernel/probes-arm.h
copy arch/arm/kernel/{kprobes-common.c => probes.c} (75%)
copy arch/arm/kernel/{kprobes.h => probes.h} (92%)
diff --git a/arch/arm/include/asm/probes.h b/arch/arm/include/asm/probes.h
index 21da148..edf5abe 100644
--- a/arch/arm/include/asm/probes.h
+++ b/arch/arm/include/asm/probes.h
@@ -1,6 +1,8 @@
#ifndef _ASM_PROBES_H
#define _ASM_PROBES_H
+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 *);
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index a30fc9b..4c8b13e 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -50,11 +50,11 @@ obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o insn.o
obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o insn.o
obj-$(CONFIG_JUMP_LABEL) += jump_label.o insn.o patch.o
obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o
-obj-$(CONFIG_KPROBES) += kprobes.o kprobes-common.o patch.o
+obj-$(CONFIG_KPROBES) += probes.o kprobes.o kprobes-common.o patch.o
ifdef CONFIG_THUMB2_KERNEL
obj-$(CONFIG_KPROBES) += kprobes-thumb.o
else
-obj-$(CONFIG_KPROBES) += kprobes-arm.o
+obj-$(CONFIG_KPROBES) += kprobes-arm.o probes-arm.o
endif
obj-$(CONFIG_ARM_KPROBES_TEST) += test-kprobes.o
test-kprobes-objs := kprobes-test.o
diff --git a/arch/arm/kernel/kprobes-arm.c b/arch/arm/kernel/kprobes-arm.c
index 8a30c89..a359475 100644
--- a/arch/arm/kernel/kprobes-arm.c
+++ b/arch/arm/kernel/kprobes-arm.c
@@ -63,10 +63,7 @@
#include <linux/module.h>
#include "kprobes.h"
-
-#define sign_extend(x, signbit) ((x) | (0 - ((x) & (1 << (signbit)))))
-
-#define branch_displacement(insn) sign_extend(((insn) & 0xffffff) << 2, 25)
+#include "probes-arm.h"
#if __LINUX_ARM_ARCH__ >= 6
#define BLX(reg) "blx "reg" \n\t"
@@ -75,88 +72,8 @@
"mov pc, "reg" \n\t"
#endif
-/*
- * To avoid the complications of mimicing single-stepping on a
- * processor without a Next-PC or a single-step mode, and to
- * avoid having to deal with the side-effects of boosting, we
- * simulate or emulate (almost) all ARM instructions.
- *
- * "Simulation" is where the instruction's behavior is duplicated in
- * C code. "Emulation" is where the original instruction is rewritten
- * and executed, often by altering its registers.
- *
- * By having all behavior of the kprobe'd instruction completed before
- * returning from the kprobe_handler(), all locks (scheduler and
- * interrupt) can safely be released. There is no need for secondary
- * breakpoints, no race with MP or preemptable kernels, nor having to
- * clean up resources counts at a later time impacting overall system
- * performance. By rewriting the instruction, only the minimum registers
- * need to be loaded and saved back optimizing performance.
- *
- * Calling the insnslot_*_rwflags version of a function doesn't hurt
- * anything even when the CPSR flags aren't updated by the
- * instruction. It's just a little slower in return for saving
- * a little space by not having a duplicate function that doesn't
- * update the flags. (The same optimization can be said for
- * instructions that do or don't perform register writeback)
- * Also, instructions can either read the flags, only write the
- * flags, or read and write the flags. To save combinations
- * rather than for sheer performance, flag functions just assume
- * read and write of flags.
- */
-
-static void __kprobes simulate_bbl(struct kprobe *p, struct pt_regs *regs)
-{
- kprobe_opcode_t insn = p->opcode;
- long iaddr = (long)p->addr;
- int disp = branch_displacement(insn);
-
- if (insn & (1 << 24))
- regs->ARM_lr = iaddr + 4;
-
- regs->ARM_pc = iaddr + 8 + disp;
-}
-
-static void __kprobes simulate_blx1(struct kprobe *p, struct pt_regs *regs)
-{
- kprobe_opcode_t insn = p->opcode;
- long iaddr = (long)p->addr;
- int disp = branch_displacement(insn);
-
- regs->ARM_lr = iaddr + 4;
- regs->ARM_pc = iaddr + 8 + disp + ((insn >> 23) & 0x2);
- regs->ARM_cpsr |= PSR_T_BIT;
-}
-static void __kprobes simulate_blx2bx(struct kprobe *p, struct pt_regs *regs)
-{
- kprobe_opcode_t insn = p->opcode;
- int rm = insn & 0xf;
- long rmv = regs->uregs[rm];
-
- if (insn & (1 << 5))
- regs->ARM_lr = (long)p->addr + 4;
-
- regs->ARM_pc = rmv & ~0x1;
- regs->ARM_cpsr &= ~PSR_T_BIT;
- if (rmv & 0x1)
- regs->ARM_cpsr |= PSR_T_BIT;
-}
-
-static void __kprobes simulate_mrs(struct kprobe *p, struct pt_regs *regs)
-{
- kprobe_opcode_t insn = p->opcode;
- int rd = (insn >> 12) & 0xf;
- unsigned long mask = 0xf8ff03df; /* Mask out execution state */
- regs->uregs[rd] = regs->ARM_cpsr & mask;
-}
-
-static void __kprobes simulate_mov_ipsp(struct kprobe *p, struct pt_regs *regs)
-{
- regs->uregs[12] = regs->uregs[13];
-}
-
-static void __kprobes
+void __kprobes
emulate_ldrdstrd(struct kprobe *p, struct pt_regs *regs)
{
kprobe_opcode_t insn = p->opcode;
@@ -185,7 +102,7 @@ emulate_ldrdstrd(struct kprobe *p, struct pt_regs *regs)
regs->uregs[rn] = rnv;
}
-static void __kprobes
+void __kprobes
emulate_ldr(struct kprobe *p, struct pt_regs *regs)
{
kprobe_opcode_t insn = p->opcode;
@@ -215,7 +132,7 @@ emulate_ldr(struct kprobe *p, struct pt_regs *regs)
regs->uregs[rn] = rnv;
}
-static void __kprobes
+void __kprobes
emulate_str(struct kprobe *p, struct pt_regs *regs)
{
kprobe_opcode_t insn = p->opcode;
@@ -242,7 +159,7 @@ emulate_str(struct kprobe *p, struct pt_regs *regs)
regs->uregs[rn] = rnv;
}
-static void __kprobes
+void __kprobes
emulate_rd12rn16rm0rs8_rwflags(struct kprobe *p, struct pt_regs *regs)
{
kprobe_opcode_t insn = p->opcode;
@@ -277,7 +194,7 @@ emulate_rd12rn16rm0rs8_rwflags(struct kprobe *p, struct pt_regs *regs)
regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK);
}
-static void __kprobes
+void __kprobes
emulate_rd12rn16rm0_rwflags_nopc(struct kprobe *p, struct pt_regs *regs)
{
kprobe_opcode_t insn = p->opcode;
@@ -304,7 +221,7 @@ emulate_rd12rn16rm0_rwflags_nopc(struct kprobe *p, struct pt_regs *regs)
regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK);
}
-static void __kprobes
+void __kprobes
emulate_rd16rn12rm0rs8_rwflags_nopc(struct kprobe *p, struct pt_regs *regs)
{
kprobe_opcode_t insn = p->opcode;
@@ -333,7 +250,7 @@ emulate_rd16rn12rm0rs8_rwflags_nopc(struct kprobe *p, struct pt_regs *regs)
regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK);
}
-static void __kprobes
+void __kprobes
emulate_rd12rm0_noflags_nopc(struct kprobe *p, struct pt_regs *regs)
{
kprobe_opcode_t insn = p->opcode;
@@ -353,7 +270,7 @@ emulate_rd12rm0_noflags_nopc(struct kprobe *p, struct pt_regs *regs)
regs->uregs[rd] = rdv;
}
-static void __kprobes
+void __kprobes
emulate_rdlo12rdhi16rn0rm8_rwflags_nopc(struct kprobe *p, struct pt_regs *regs)
{
kprobe_opcode_t insn = p->opcode;
@@ -382,624 +299,3 @@ emulate_rdlo12rdhi16rn0rm8_rwflags_nopc(struct kprobe *p, struct pt_regs *regs)
regs->uregs[rdhi] = rdhiv;
regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK);
}
-
-/*
- * For the instruction masking and comparisons in all the "space_*"
- * functions below, Do _not_ rearrange the order of tests unless
- * you're very, very sure of what you are doing. For the sake of
- * efficiency, the masks for some tests sometimes assume other test
- * have been done prior to them so the number of patterns to test
- * for an instruction set can be as broad as possible to reduce the
- * number of tests needed.
- */
-
-static const union decode_item arm_1111_table[] = {
- /* Unconditional instructions */
-
- /* memory hint 1111 0100 x001 xxxx xxxx xxxx xxxx xxxx */
- /* PLDI (immediate) 1111 0100 x101 xxxx xxxx xxxx xxxx xxxx */
- /* PLDW (immediate) 1111 0101 x001 xxxx xxxx xxxx xxxx xxxx */
- /* PLD (immediate) 1111 0101 x101 xxxx xxxx xxxx xxxx xxxx */
- DECODE_SIMULATE (0xfe300000, 0xf4100000, kprobe_simulate_nop),
-
- /* memory hint 1111 0110 x001 xxxx xxxx xxxx xxx0 xxxx */
- /* PLDI (register) 1111 0110 x101 xxxx xxxx xxxx xxx0 xxxx */
- /* PLDW (register) 1111 0111 x001 xxxx xxxx xxxx xxx0 xxxx */
- /* PLD (register) 1111 0111 x101 xxxx xxxx xxxx xxx0 xxxx */
- DECODE_SIMULATE (0xfe300010, 0xf6100000, kprobe_simulate_nop),
-
- /* BLX (immediate) 1111 101x xxxx xxxx xxxx xxxx xxxx xxxx */
- DECODE_SIMULATE (0xfe000000, 0xfa000000, simulate_blx1),
-
- /* CPS 1111 0001 0000 xxx0 xxxx xxxx xx0x xxxx */
- /* SETEND 1111 0001 0000 0001 xxxx xxxx 0000 xxxx */
- /* SRS 1111 100x x1x0 xxxx xxxx xxxx xxxx xxxx */
- /* RFE 1111 100x x0x1 xxxx xxxx xxxx xxxx xxxx */
-
- /* Coprocessor instructions... */
- /* MCRR2 1111 1100 0100 xxxx xxxx xxxx xxxx xxxx */
- /* MRRC2 1111 1100 0101 xxxx xxxx xxxx xxxx xxxx */
- /* LDC2 1111 110x xxx1 xxxx xxxx xxxx xxxx xxxx */
- /* STC2 1111 110x xxx0 xxxx xxxx xxxx xxxx xxxx */
- /* CDP2 1111 1110 xxxx xxxx xxxx xxxx xxx0 xxxx */
- /* MCR2 1111 1110 xxx0 xxxx xxxx xxxx xxx1 xxxx */
- /* MRC2 1111 1110 xxx1 xxxx xxxx xxxx xxx1 xxxx */
-
- /* Other unallocated instructions... */
- DECODE_END
-};
-
-static const union decode_item arm_cccc_0001_0xx0____0xxx_table[] = {
- /* Miscellaneous instructions */
-
- /* MRS cpsr cccc 0001 0000 xxxx xxxx xxxx 0000 xxxx */
- DECODE_SIMULATEX(0x0ff000f0, 0x01000000, simulate_mrs,
- REGS(0, NOPC, 0, 0, 0)),
-
- /* BX cccc 0001 0010 xxxx xxxx xxxx 0001 xxxx */
- DECODE_SIMULATE (0x0ff000f0, 0x01200010, simulate_blx2bx),
-
- /* BLX (register) cccc 0001 0010 xxxx xxxx xxxx 0011 xxxx */
- DECODE_SIMULATEX(0x0ff000f0, 0x01200030, simulate_blx2bx,
- REGS(0, 0, 0, 0, NOPC)),
-
- /* CLZ cccc 0001 0110 xxxx xxxx xxxx 0001 xxxx */
- DECODE_EMULATEX (0x0ff000f0, 0x01600010, emulate_rd12rm0_noflags_nopc,
- REGS(0, NOPC, 0, 0, NOPC)),
-
- /* QADD cccc 0001 0000 xxxx xxxx xxxx 0101 xxxx */
- /* QSUB cccc 0001 0010 xxxx xxxx xxxx 0101 xxxx */
- /* QDADD cccc 0001 0100 xxxx xxxx xxxx 0101 xxxx */
- /* QDSUB cccc 0001 0110 xxxx xxxx xxxx 0101 xxxx */
- DECODE_EMULATEX (0x0f9000f0, 0x01000050, emulate_rd12rn16rm0_rwflags_nopc,
- REGS(NOPC, NOPC, 0, 0, NOPC)),
-
- /* BXJ cccc 0001 0010 xxxx xxxx xxxx 0010 xxxx */
- /* MSR cccc 0001 0x10 xxxx xxxx xxxx 0000 xxxx */
- /* MRS spsr cccc 0001 0100 xxxx xxxx xxxx 0000 xxxx */
- /* BKPT 1110 0001 0010 xxxx xxxx xxxx 0111 xxxx */
- /* SMC cccc 0001 0110 xxxx xxxx xxxx 0111 xxxx */
- /* And unallocated instructions... */
- DECODE_END
-};
-
-static const union decode_item arm_cccc_0001_0xx0____1xx0_table[] = {
- /* Halfword multiply and multiply-accumulate */
-
- /* SMLALxy cccc 0001 0100 xxxx xxxx xxxx 1xx0 xxxx */
- DECODE_EMULATEX (0x0ff00090, 0x01400080, emulate_rdlo12rdhi16rn0rm8_rwflags_nopc,
- REGS(NOPC, NOPC, NOPC, 0, NOPC)),
-
- /* SMULWy cccc 0001 0010 xxxx xxxx xxxx 1x10 xxxx */
- DECODE_OR (0x0ff000b0, 0x012000a0),
- /* SMULxy cccc 0001 0110 xxxx xxxx xxxx 1xx0 xxxx */
- DECODE_EMULATEX (0x0ff00090, 0x01600080, emulate_rd16rn12rm0rs8_rwflags_nopc,
- REGS(NOPC, 0, NOPC, 0, NOPC)),
-
- /* SMLAxy cccc 0001 0000 xxxx xxxx xxxx 1xx0 xxxx */
- DECODE_OR (0x0ff00090, 0x01000080),
- /* SMLAWy cccc 0001 0010 xxxx xxxx xxxx 1x00 xxxx */
- DECODE_EMULATEX (0x0ff000b0, 0x01200080, emulate_rd16rn12rm0rs8_rwflags_nopc,
- REGS(NOPC, NOPC, NOPC, 0, NOPC)),
-
- DECODE_END
-};
-
-static const union decode_item arm_cccc_0000_____1001_table[] = {
- /* Multiply and multiply-accumulate */
-
- /* MUL cccc 0000 0000 xxxx xxxx xxxx 1001 xxxx */
- /* MULS cccc 0000 0001 xxxx xxxx xxxx 1001 xxxx */
- DECODE_EMULATEX (0x0fe000f0, 0x00000090, emulate_rd16rn12rm0rs8_rwflags_nopc,
- REGS(NOPC, 0, NOPC, 0, NOPC)),
-
- /* MLA cccc 0000 0010 xxxx xxxx xxxx 1001 xxxx */
- /* MLAS cccc 0000 0011 xxxx xxxx xxxx 1001 xxxx */
- DECODE_OR (0x0fe000f0, 0x00200090),
- /* MLS cccc 0000 0110 xxxx xxxx xxxx 1001 xxxx */
- DECODE_EMULATEX (0x0ff000f0, 0x00600090, emulate_rd16rn12rm0rs8_rwflags_nopc,
- REGS(NOPC, NOPC, NOPC, 0, NOPC)),
-
- /* UMAAL cccc 0000 0100 xxxx xxxx xxxx 1001 xxxx */
- DECODE_OR (0x0ff000f0, 0x00400090),
- /* UMULL cccc 0000 1000 xxxx xxxx xxxx 1001 xxxx */
- /* UMULLS cccc 0000 1001 xxxx xxxx xxxx 1001 xxxx */
- /* UMLAL cccc 0000 1010 xxxx xxxx xxxx 1001 xxxx */
- /* UMLALS cccc 0000 1011 xxxx xxxx xxxx 1001 xxxx */
- /* SMULL cccc 0000 1100 xxxx xxxx xxxx 1001 xxxx */
- /* SMULLS cccc 0000 1101 xxxx xxxx xxxx 1001 xxxx */
- /* SMLAL cccc 0000 1110 xxxx xxxx xxxx 1001 xxxx */
- /* SMLALS cccc 0000 1111 xxxx xxxx xxxx 1001 xxxx */
- DECODE_EMULATEX (0x0f8000f0, 0x00800090, emulate_rdlo12rdhi16rn0rm8_rwflags_nopc,
- REGS(NOPC, NOPC, NOPC, 0, NOPC)),
-
- DECODE_END
-};
-
-static const union decode_item arm_cccc_0001_____1001_table[] = {
- /* Synchronization primitives */
-
-#if __LINUX_ARM_ARCH__ < 6
- /* Deprecated on ARMv6 and may be UNDEFINED on v7 */
- /* SMP/SWPB cccc 0001 0x00 xxxx xxxx xxxx 1001 xxxx */
- DECODE_EMULATEX (0x0fb000f0, 0x01000090, emulate_rd12rn16rm0_rwflags_nopc,
- REGS(NOPC, NOPC, 0, 0, NOPC)),
-#endif
- /* LDREX/STREX{,D,B,H} cccc 0001 1xxx xxxx xxxx xxxx 1001 xxxx */
- /* And unallocated instructions... */
- DECODE_END
-};
-
-static const union decode_item arm_cccc_000x_____1xx1_table[] = {
- /* Extra load/store instructions */
-
- /* STRHT cccc 0000 xx10 xxxx xxxx xxxx 1011 xxxx */
- /* ??? cccc 0000 xx10 xxxx xxxx xxxx 11x1 xxxx */
- /* LDRHT cccc 0000 xx11 xxxx xxxx xxxx 1011 xxxx */
- /* LDRSBT cccc 0000 xx11 xxxx xxxx xxxx 1101 xxxx */
- /* LDRSHT cccc 0000 xx11 xxxx xxxx xxxx 1111 xxxx */
- DECODE_REJECT (0x0f200090, 0x00200090),
-
- /* LDRD/STRD lr,pc,{... cccc 000x x0x0 xxxx 111x xxxx 1101 xxxx */
- DECODE_REJECT (0x0e10e0d0, 0x0000e0d0),
-
- /* LDRD (register) cccc 000x x0x0 xxxx xxxx xxxx 1101 xxxx */
- /* STRD (register) cccc 000x x0x0 xxxx xxxx xxxx 1111 xxxx */
- DECODE_EMULATEX (0x0e5000d0, 0x000000d0, emulate_ldrdstrd,
- REGS(NOPCWB, NOPCX, 0, 0, NOPC)),
-
- /* LDRD (immediate) cccc 000x x1x0 xxxx xxxx xxxx 1101 xxxx */
- /* STRD (immediate) cccc 000x x1x0 xxxx xxxx xxxx 1111 xxxx */
- DECODE_EMULATEX (0x0e5000d0, 0x004000d0, emulate_ldrdstrd,
- REGS(NOPCWB, NOPCX, 0, 0, 0)),
-
- /* STRH (register) cccc 000x x0x0 xxxx xxxx xxxx 1011 xxxx */
- DECODE_EMULATEX (0x0e5000f0, 0x000000b0, emulate_str,
- REGS(NOPCWB, NOPC, 0, 0, NOPC)),
-
- /* LDRH (register) cccc 000x x0x1 xxxx xxxx xxxx 1011 xxxx */
- /* LDRSB (register) cccc 000x x0x1 xxxx xxxx xxxx 1101 xxxx */
- /* LDRSH (register) cccc 000x x0x1 xxxx xxxx xxxx 1111 xxxx */
- DECODE_EMULATEX (0x0e500090, 0x00100090, emulate_ldr,
- REGS(NOPCWB, NOPC, 0, 0, NOPC)),
-
- /* STRH (immediate) cccc 000x x1x0 xxxx xxxx xxxx 1011 xxxx */
- DECODE_EMULATEX (0x0e5000f0, 0x004000b0, emulate_str,
- REGS(NOPCWB, NOPC, 0, 0, 0)),
-
- /* LDRH (immediate) cccc 000x x1x1 xxxx xxxx xxxx 1011 xxxx */
- /* LDRSB (immediate) cccc 000x x1x1 xxxx xxxx xxxx 1101 xxxx */
- /* LDRSH (immediate) cccc 000x x1x1 xxxx xxxx xxxx 1111 xxxx */
- DECODE_EMULATEX (0x0e500090, 0x00500090, emulate_ldr,
- REGS(NOPCWB, NOPC, 0, 0, 0)),
-
- DECODE_END
-};
-
-static const union decode_item arm_cccc_000x_table[] = {
- /* Data-processing (register) */
-
- /* <op>S PC, ... cccc 000x xxx1 xxxx 1111 xxxx xxxx xxxx */
- DECODE_REJECT (0x0e10f000, 0x0010f000),
-
- /* MOV IP, SP 1110 0001 1010 0000 1100 0000 0000 1101 */
- DECODE_SIMULATE (0xffffffff, 0xe1a0c00d, simulate_mov_ipsp),
-
- /* TST (register) cccc 0001 0001 xxxx xxxx xxxx xxx0 xxxx */
- /* TEQ (register) cccc 0001 0011 xxxx xxxx xxxx xxx0 xxxx */
- /* CMP (register) cccc 0001 0101 xxxx xxxx xxxx xxx0 xxxx */
- /* CMN (register) cccc 0001 0111 xxxx xxxx xxxx xxx0 xxxx */
- DECODE_EMULATEX (0x0f900010, 0x01100000, emulate_rd12rn16rm0rs8_rwflags,
- REGS(ANY, 0, 0, 0, ANY)),
-
- /* MOV (register) cccc 0001 101x xxxx xxxx xxxx xxx0 xxxx */
- /* MVN (register) cccc 0001 111x xxxx xxxx xxxx xxx0 xxxx */
- DECODE_EMULATEX (0x0fa00010, 0x01a00000, emulate_rd12rn16rm0rs8_rwflags,
- REGS(0, ANY, 0, 0, ANY)),
-
- /* AND (register) cccc 0000 000x xxxx xxxx xxxx xxx0 xxxx */
- /* EOR (register) cccc 0000 001x xxxx xxxx xxxx xxx0 xxxx */
- /* SUB (register) cccc 0000 010x xxxx xxxx xxxx xxx0 xxxx */
- /* RSB (register) cccc 0000 011x xxxx xxxx xxxx xxx0 xxxx */
- /* ADD (register) cccc 0000 100x xxxx xxxx xxxx xxx0 xxxx */
- /* ADC (register) cccc 0000 101x xxxx xxxx xxxx xxx0 xxxx */
- /* SBC (register) cccc 0000 110x xxxx xxxx xxxx xxx0 xxxx */
- /* RSC (register) cccc 0000 111x xxxx xxxx xxxx xxx0 xxxx */
- /* ORR (register) cccc 0001 100x xxxx xxxx xxxx xxx0 xxxx */
- /* BIC (register) cccc 0001 110x xxxx xxxx xxxx xxx0 xxxx */
- DECODE_EMULATEX (0x0e000010, 0x00000000, emulate_rd12rn16rm0rs8_rwflags,
- REGS(ANY, ANY, 0, 0, ANY)),
-
- /* TST (reg-shift reg) cccc 0001 0001 xxxx xxxx xxxx 0xx1 xxxx */
- /* TEQ (reg-shift reg) cccc 0001 0011 xxxx xxxx xxxx 0xx1 xxxx */
- /* CMP (reg-shift reg) cccc 0001 0101 xxxx xxxx xxxx 0xx1 xxxx */
- /* CMN (reg-shift reg) cccc 0001 0111 xxxx xxxx xxxx 0xx1 xxxx */
- DECODE_EMULATEX (0x0f900090, 0x01100010, emulate_rd12rn16rm0rs8_rwflags,
- REGS(ANY, 0, NOPC, 0, ANY)),
-
- /* MOV (reg-shift reg) cccc 0001 101x xxxx xxxx xxxx 0xx1 xxxx */
- /* MVN (reg-shift reg) cccc 0001 111x xxxx xxxx xxxx 0xx1 xxxx */
- DECODE_EMULATEX (0x0fa00090, 0x01a00010, emulate_rd12rn16rm0rs8_rwflags,
- REGS(0, ANY, NOPC, 0, ANY)),
-
- /* AND (reg-shift reg) cccc 0000 000x xxxx xxxx xxxx 0xx1 xxxx */
- /* EOR (reg-shift reg) cccc 0000 001x xxxx xxxx xxxx 0xx1 xxxx */
- /* SUB (reg-shift reg) cccc 0000 010x xxxx xxxx xxxx 0xx1 xxxx */
- /* RSB (reg-shift reg) cccc 0000 011x xxxx xxxx xxxx 0xx1 xxxx */
- /* ADD (reg-shift reg) cccc 0000 100x xxxx xxxx xxxx 0xx1 xxxx */
- /* ADC (reg-shift reg) cccc 0000 101x xxxx xxxx xxxx 0xx1 xxxx */
- /* SBC (reg-shift reg) cccc 0000 110x xxxx xxxx xxxx 0xx1 xxxx */
- /* RSC (reg-shift reg) cccc 0000 111x xxxx xxxx xxxx 0xx1 xxxx */
- /* ORR (reg-shift reg) cccc 0001 100x xxxx xxxx xxxx 0xx1 xxxx */
- /* BIC (reg-shift reg) cccc 0001 110x xxxx xxxx xxxx 0xx1 xxxx */
- DECODE_EMULATEX (0x0e000090, 0x00000010, emulate_rd12rn16rm0rs8_rwflags,
- REGS(ANY, ANY, NOPC, 0, ANY)),
-
- DECODE_END
-};
-
-static const union decode_item arm_cccc_001x_table[] = {
- /* Data-processing (immediate) */
-
- /* MOVW cccc 0011 0000 xxxx xxxx xxxx xxxx xxxx */
- /* MOVT cccc 0011 0100 xxxx xxxx xxxx xxxx xxxx */
- DECODE_EMULATEX (0x0fb00000, 0x03000000, emulate_rd12rm0_noflags_nopc,
- REGS(0, NOPC, 0, 0, 0)),
-
- /* YIELD cccc 0011 0010 0000 xxxx xxxx 0000 0001 */
- DECODE_OR (0x0fff00ff, 0x03200001),
- /* SEV cccc 0011 0010 0000 xxxx xxxx 0000 0100 */
- DECODE_EMULATE (0x0fff00ff, 0x03200004, kprobe_emulate_none),
- /* NOP cccc 0011 0010 0000 xxxx xxxx 0000 0000 */
- /* WFE cccc 0011 0010 0000 xxxx xxxx 0000 0010 */
- /* WFI cccc 0011 0010 0000 xxxx xxxx 0000 0011 */
- DECODE_SIMULATE (0x0fff00fc, 0x03200000, kprobe_simulate_nop),
- /* DBG cccc 0011 0010 0000 xxxx xxxx ffff xxxx */
- /* unallocated hints cccc 0011 0010 0000 xxxx xxxx xxxx xxxx */
- /* MSR (immediate) cccc 0011 0x10 xxxx xxxx xxxx xxxx xxxx */
- DECODE_REJECT (0x0fb00000, 0x03200000),
-
- /* <op>S PC, ... cccc 001x xxx1 xxxx 1111 xxxx xxxx xxxx */
- DECODE_REJECT (0x0e10f000, 0x0210f000),
-
- /* TST (immediate) cccc 0011 0001 xxxx xxxx xxxx xxxx xxxx */
- /* TEQ (immediate) cccc 0011 0011 xxxx xxxx xxxx xxxx xxxx */
- /* CMP (immediate) cccc 0011 0101 xxxx xxxx xxxx xxxx xxxx */
- /* CMN (immediate) cccc 0011 0111 xxxx xxxx xxxx xxxx xxxx */
- DECODE_EMULATEX (0x0f900000, 0x03100000, emulate_rd12rn16rm0rs8_rwflags,
- REGS(ANY, 0, 0, 0, 0)),
-
- /* MOV (immediate) cccc 0011 101x xxxx xxxx xxxx xxxx xxxx */
- /* MVN (immediate) cccc 0011 111x xxxx xxxx xxxx xxxx xxxx */
- DECODE_EMULATEX (0x0fa00000, 0x03a00000, emulate_rd12rn16rm0rs8_rwflags,
- REGS(0, ANY, 0, 0, 0)),
-
- /* AND (immediate) cccc 0010 000x xxxx xxxx xxxx xxxx xxxx */
- /* EOR (immediate) cccc 0010 001x xxxx xxxx xxxx xxxx xxxx */
- /* SUB (immediate) cccc 0010 010x xxxx xxxx xxxx xxxx xxxx */
- /* RSB (immediate) cccc 0010 011x xxxx xxxx xxxx xxxx xxxx */
- /* ADD (immediate) cccc 0010 100x xxxx xxxx xxxx xxxx xxxx */
- /* ADC (immediate) cccc 0010 101x xxxx xxxx xxxx xxxx xxxx */
- /* SBC (immediate) cccc 0010 110x xxxx xxxx xxxx xxxx xxxx */
- /* RSC (immediate) cccc 0010 111x xxxx xxxx xxxx xxxx xxxx */
- /* ORR (immediate) cccc 0011 100x xxxx xxxx xxxx xxxx xxxx */
- /* BIC (immediate) cccc 0011 110x xxxx xxxx xxxx xxxx xxxx */
- DECODE_EMULATEX (0x0e000000, 0x02000000, emulate_rd12rn16rm0rs8_rwflags,
- REGS(ANY, ANY, 0, 0, 0)),
-
- DECODE_END
-};
-
-static const union decode_item arm_cccc_0110_____xxx1_table[] = {
- /* Media instructions */
-
- /* SEL cccc 0110 1000 xxxx xxxx xxxx 1011 xxxx */
- DECODE_EMULATEX (0x0ff000f0, 0x068000b0, emulate_rd12rn16rm0_rwflags_nopc,
- REGS(NOPC, NOPC, 0, 0, NOPC)),
-
- /* SSAT cccc 0110 101x xxxx xxxx xxxx xx01 xxxx */
- /* USAT cccc 0110 111x xxxx xxxx xxxx xx01 xxxx */
- DECODE_OR(0x0fa00030, 0x06a00010),
- /* SSAT16 cccc 0110 1010 xxxx xxxx xxxx 0011 xxxx */
- /* USAT16 cccc 0110 1110 xxxx xxxx xxxx 0011 xxxx */
- DECODE_EMULATEX (0x0fb000f0, 0x06a00030, emulate_rd12rn16rm0_rwflags_nopc,
- REGS(0, NOPC, 0, 0, NOPC)),
-
- /* REV cccc 0110 1011 xxxx xxxx xxxx 0011 xxxx */
- /* REV16 cccc 0110 1011 xxxx xxxx xxxx 1011 xxxx */
- /* RBIT cccc 0110 1111 xxxx xxxx xxxx 0011 xxxx */
- /* REVSH cccc 0110 1111 xxxx xxxx xxxx 1011 xxxx */
- DECODE_EMULATEX (0x0fb00070, 0x06b00030, emulate_rd12rm0_noflags_nopc,
- REGS(0, NOPC, 0, 0, NOPC)),
-
- /* ??? cccc 0110 0x00 xxxx xxxx xxxx xxx1 xxxx */
- DECODE_REJECT (0x0fb00010, 0x06000010),
- /* ??? cccc 0110 0xxx xxxx xxxx xxxx 1011 xxxx */
- DECODE_REJECT (0x0f8000f0, 0x060000b0),
- /* ??? cccc 0110 0xxx xxxx xxxx xxxx 1101 xxxx */
- DECODE_REJECT (0x0f8000f0, 0x060000d0),
- /* SADD16 cccc 0110 0001 xxxx xxxx xxxx 0001 xxxx */
- /* SADDSUBX cccc 0110 0001 xxxx xxxx xxxx 0011 xxxx */
- /* SSUBADDX cccc 0110 0001 xxxx xxxx xxxx 0101 xxxx */
- /* SSUB16 cccc 0110 0001 xxxx xxxx xxxx 0111 xxxx */
- /* SADD8 cccc 0110 0001 xxxx xxxx xxxx 1001 xxxx */
- /* SSUB8 cccc 0110 0001 xxxx xxxx xxxx 1111 xxxx */
- /* QADD16 cccc 0110 0010 xxxx xxxx xxxx 0001 xxxx */
- /* QADDSUBX cccc 0110 0010 xxxx xxxx xxxx 0011 xxxx */
- /* QSUBADDX cccc 0110 0010 xxxx xxxx xxxx 0101 xxxx */
- /* QSUB16 cccc 0110 0010 xxxx xxxx xxxx 0111 xxxx */
- /* QADD8 cccc 0110 0010 xxxx xxxx xxxx 1001 xxxx */
- /* QSUB8 cccc 0110 0010 xxxx xxxx xxxx 1111 xxxx */
- /* SHADD16 cccc 0110 0011 xxxx xxxx xxxx 0001 xxxx */
- /* SHADDSUBX cccc 0110 0011 xxxx xxxx xxxx 0011 xxxx */
- /* SHSUBADDX cccc 0110 0011 xxxx xxxx xxxx 0101 xxxx */
- /* SHSUB16 cccc 0110 0011 xxxx xxxx xxxx 0111 xxxx */
- /* SHADD8 cccc 0110 0011 xxxx xxxx xxxx 1001 xxxx */
- /* SHSUB8 cccc 0110 0011 xxxx xxxx xxxx 1111 xxxx */
- /* UADD16 cccc 0110 0101 xxxx xxxx xxxx 0001 xxxx */
- /* UADDSUBX cccc 0110 0101 xxxx xxxx xxxx 0011 xxxx */
- /* USUBADDX cccc 0110 0101 xxxx xxxx xxxx 0101 xxxx */
- /* USUB16 cccc 0110 0101 xxxx xxxx xxxx 0111 xxxx */
- /* UADD8 cccc 0110 0101 xxxx xxxx xxxx 1001 xxxx */
- /* USUB8 cccc 0110 0101 xxxx xxxx xxxx 1111 xxxx */
- /* UQADD16 cccc 0110 0110 xxxx xxxx xxxx 0001 xxxx */
- /* UQADDSUBX cccc 0110 0110 xxxx xxxx xxxx 0011 xxxx */
- /* UQSUBADDX cccc 0110 0110 xxxx xxxx xxxx 0101 xxxx */
- /* UQSUB16 cccc 0110 0110 xxxx xxxx xxxx 0111 xxxx */
- /* UQADD8 cccc 0110 0110 xxxx xxxx xxxx 1001 xxxx */
- /* UQSUB8 cccc 0110 0110 xxxx xxxx xxxx 1111 xxxx */
- /* UHADD16 cccc 0110 0111 xxxx xxxx xxxx 0001 xxxx */
- /* UHADDSUBX cccc 0110 0111 xxxx xxxx xxxx 0011 xxxx */
- /* UHSUBADDX cccc 0110 0111 xxxx xxxx xxxx 0101 xxxx */
- /* UHSUB16 cccc 0110 0111 xxxx xxxx xxxx 0111 xxxx */
- /* UHADD8 cccc 0110 0111 xxxx xxxx xxxx 1001 xxxx */
- /* UHSUB8 cccc 0110 0111 xxxx xxxx xxxx 1111 xxxx */
- DECODE_EMULATEX (0x0f800010, 0x06000010, emulate_rd12rn16rm0_rwflags_nopc,
- REGS(NOPC, NOPC, 0, 0, NOPC)),
-
- /* PKHBT cccc 0110 1000 xxxx xxxx xxxx x001 xxxx */
- /* PKHTB cccc 0110 1000 xxxx xxxx xxxx x101 xxxx */
- DECODE_EMULATEX (0x0ff00030, 0x06800010, emulate_rd12rn16rm0_rwflags_nopc,
- REGS(NOPC, NOPC, 0, 0, NOPC)),
-
- /* ??? cccc 0110 1001 xxxx xxxx xxxx 0111 xxxx */
- /* ??? cccc 0110 1101 xxxx xxxx xxxx 0111 xxxx */
- DECODE_REJECT (0x0fb000f0, 0x06900070),
-
- /* SXTB16 cccc 0110 1000 1111 xxxx xxxx 0111 xxxx */
- /* SXTB cccc 0110 1010 1111 xxxx xxxx 0111 xxxx */
- /* SXTH cccc 0110 1011 1111 xxxx xxxx 0111 xxxx */
- /* UXTB16 cccc 0110 1100 1111 xxxx xxxx 0111 xxxx */
- /* UXTB cccc 0110 1110 1111 xxxx xxxx 0111 xxxx */
- /* UXTH cccc 0110 1111 1111 xxxx xxxx 0111 xxxx */
- DECODE_EMULATEX (0x0f8f00f0, 0x068f0070, emulate_rd12rm0_noflags_nopc,
- REGS(0, NOPC, 0, 0, NOPC)),
-
- /* SXTAB16 cccc 0110 1000 xxxx xxxx xxxx 0111 xxxx */
- /* SXTAB cccc 0110 1010 xxxx xxxx xxxx 0111 xxxx */
- /* SXTAH cccc 0110 1011 xxxx xxxx xxxx 0111 xxxx */
- /* UXTAB16 cccc 0110 1100 xxxx xxxx xxxx 0111 xxxx */
- /* UXTAB cccc 0110 1110 xxxx xxxx xxxx 0111 xxxx */
- /* UXTAH cccc 0110 1111 xxxx xxxx xxxx 0111 xxxx */
- DECODE_EMULATEX (0x0f8000f0, 0x06800070, emulate_rd12rn16rm0_rwflags_nopc,
- REGS(NOPCX, NOPC, 0, 0, NOPC)),
-
- DECODE_END
-};
-
-static const union decode_item arm_cccc_0111_____xxx1_table[] = {
- /* Media instructions */
-
- /* UNDEFINED cccc 0111 1111 xxxx xxxx xxxx 1111 xxxx */
- DECODE_REJECT (0x0ff000f0, 0x07f000f0),
-
- /* SMLALD cccc 0111 0100 xxxx xxxx xxxx 00x1 xxxx */
- /* SMLSLD cccc 0111 0100 xxxx xxxx xxxx 01x1 xxxx */
- DECODE_EMULATEX (0x0ff00090, 0x07400010, emulate_rdlo12rdhi16rn0rm8_rwflags_nopc,
- REGS(NOPC, NOPC, NOPC, 0, NOPC)),
-
- /* SMUAD cccc 0111 0000 xxxx 1111 xxxx 00x1 xxxx */
- /* SMUSD cccc 0111 0000 xxxx 1111 xxxx 01x1 xxxx */
- DECODE_OR (0x0ff0f090, 0x0700f010),
- /* SMMUL cccc 0111 0101 xxxx 1111 xxxx 00x1 xxxx */
- DECODE_OR (0x0ff0f0d0, 0x0750f010),
- /* USAD8 cccc 0111 1000 xxxx 1111 xxxx 0001 xxxx */
- DECODE_EMULATEX (0x0ff0f0f0, 0x0780f010, emulate_rd16rn12rm0rs8_rwflags_nopc,
- REGS(NOPC, 0, NOPC, 0, NOPC)),
-
- /* SMLAD cccc 0111 0000 xxxx xxxx xxxx 00x1 xxxx */
- /* SMLSD cccc 0111 0000 xxxx xxxx xxxx 01x1 xxxx */
- DECODE_OR (0x0ff00090, 0x07000010),
- /* SMMLA cccc 0111 0101 xxxx xxxx xxxx 00x1 xxxx */
- DECODE_OR (0x0ff000d0, 0x07500010),
- /* USADA8 cccc 0111 1000 xxxx xxxx xxxx 0001 xxxx */
- DECODE_EMULATEX (0x0ff000f0, 0x07800010, emulate_rd16rn12rm0rs8_rwflags_nopc,
- REGS(NOPC, NOPCX, NOPC, 0, NOPC)),
-
- /* SMMLS cccc 0111 0101 xxxx xxxx xxxx 11x1 xxxx */
- DECODE_EMULATEX (0x0ff000d0, 0x075000d0, emulate_rd16rn12rm0rs8_rwflags_nopc,
- REGS(NOPC, NOPC, NOPC, 0, NOPC)),
-
- /* SBFX cccc 0111 101x xxxx xxxx xxxx x101 xxxx */
- /* UBFX cccc 0111 111x xxxx xxxx xxxx x101 xxxx */
- DECODE_EMULATEX (0x0fa00070, 0x07a00050, emulate_rd12rm0_noflags_nopc,
- REGS(0, NOPC, 0, 0, NOPC)),
-
- /* BFC cccc 0111 110x xxxx xxxx xxxx x001 1111 */
- DECODE_EMULATEX (0x0fe0007f, 0x07c0001f, emulate_rd12rm0_noflags_nopc,
- REGS(0, NOPC, 0, 0, 0)),
-
- /* BFI cccc 0111 110x xxxx xxxx xxxx x001 xxxx */
- DECODE_EMULATEX (0x0fe00070, 0x07c00010, emulate_rd12rm0_noflags_nopc,
- REGS(0, NOPC, 0, 0, NOPCX)),
-
- DECODE_END
-};
-
-static const union decode_item arm_cccc_01xx_table[] = {
- /* Load/store word and unsigned byte */
-
- /* LDRB/STRB pc,[...] cccc 01xx x0xx xxxx xxxx xxxx xxxx xxxx */
- DECODE_REJECT (0x0c40f000, 0x0440f000),
-
- /* STRT cccc 01x0 x010 xxxx xxxx xxxx xxxx xxxx */
- /* LDRT cccc 01x0 x011 xxxx xxxx xxxx xxxx xxxx */
- /* STRBT cccc 01x0 x110 xxxx xxxx xxxx xxxx xxxx */
- /* LDRBT cccc 01x0 x111 xxxx xxxx xxxx xxxx xxxx */
- DECODE_REJECT (0x0d200000, 0x04200000),
-
- /* STR (immediate) cccc 010x x0x0 xxxx xxxx xxxx xxxx xxxx */
- /* STRB (immediate) cccc 010x x1x0 xxxx xxxx xxxx xxxx xxxx */
- DECODE_EMULATEX (0x0e100000, 0x04000000, emulate_str,
- REGS(NOPCWB, ANY, 0, 0, 0)),
-
- /* LDR (immediate) cccc 010x x0x1 xxxx xxxx xxxx xxxx xxxx */
- /* LDRB (immediate) cccc 010x x1x1 xxxx xxxx xxxx xxxx xxxx */
- DECODE_EMULATEX (0x0e100000, 0x04100000, emulate_ldr,
- REGS(NOPCWB, ANY, 0, 0, 0)),
-
- /* STR (register) cccc 011x x0x0 xxxx xxxx xxxx xxxx xxxx */
- /* STRB (register) cccc 011x x1x0 xxxx xxxx xxxx xxxx xxxx */
- DECODE_EMULATEX (0x0e100000, 0x06000000, emulate_str,
- REGS(NOPCWB, ANY, 0, 0, NOPC)),
-
- /* LDR (register) cccc 011x x0x1 xxxx xxxx xxxx xxxx xxxx */
- /* LDRB (register) cccc 011x x1x1 xxxx xxxx xxxx xxxx xxxx */
- DECODE_EMULATEX (0x0e100000, 0x06100000, emulate_ldr,
- REGS(NOPCWB, ANY, 0, 0, NOPC)),
-
- DECODE_END
-};
-
-static const union decode_item arm_cccc_100x_table[] = {
- /* Block data transfer instructions */
-
- /* LDM cccc 100x x0x1 xxxx xxxx xxxx xxxx xxxx */
- /* STM cccc 100x x0x0 xxxx xxxx xxxx xxxx xxxx */
- DECODE_CUSTOM (0x0e400000, 0x08000000, kprobe_decode_ldmstm),
-
- /* STM (user registers) cccc 100x x1x0 xxxx xxxx xxxx xxxx xxxx */
- /* LDM (user registers) cccc 100x x1x1 xxxx 0xxx xxxx xxxx xxxx */
- /* LDM (exception ret) cccc 100x x1x1 xxxx 1xxx xxxx xxxx xxxx */
- DECODE_END
-};
-
-const union decode_item kprobe_decode_arm_table[] = {
- /*
- * Unconditional instructions
- * 1111 xxxx xxxx xxxx xxxx xxxx xxxx xxxx
- */
- DECODE_TABLE (0xf0000000, 0xf0000000, arm_1111_table),
-
- /*
- * Miscellaneous instructions
- * cccc 0001 0xx0 xxxx xxxx xxxx 0xxx xxxx
- */
- DECODE_TABLE (0x0f900080, 0x01000000, arm_cccc_0001_0xx0____0xxx_table),
-
- /*
- * Halfword multiply and multiply-accumulate
- * cccc 0001 0xx0 xxxx xxxx xxxx 1xx0 xxxx
- */
- DECODE_TABLE (0x0f900090, 0x01000080, arm_cccc_0001_0xx0____1xx0_table),
-
- /*
- * Multiply and multiply-accumulate
- * cccc 0000 xxxx xxxx xxxx xxxx 1001 xxxx
- */
- DECODE_TABLE (0x0f0000f0, 0x00000090, arm_cccc_0000_____1001_table),
-
- /*
- * Synchronization primitives
- * cccc 0001 xxxx xxxx xxxx xxxx 1001 xxxx
- */
- DECODE_TABLE (0x0f0000f0, 0x01000090, arm_cccc_0001_____1001_table),
-
- /*
- * Extra load/store instructions
- * cccc 000x xxxx xxxx xxxx xxxx 1xx1 xxxx
- */
- DECODE_TABLE (0x0e000090, 0x00000090, arm_cccc_000x_____1xx1_table),
-
- /*
- * Data-processing (register)
- * cccc 000x xxxx xxxx xxxx xxxx xxx0 xxxx
- * Data-processing (register-shifted register)
- * cccc 000x xxxx xxxx xxxx xxxx 0xx1 xxxx
- */
- DECODE_TABLE (0x0e000000, 0x00000000, arm_cccc_000x_table),
-
- /*
- * Data-processing (immediate)
- * cccc 001x xxxx xxxx xxxx xxxx xxxx xxxx
- */
- DECODE_TABLE (0x0e000000, 0x02000000, arm_cccc_001x_table),
-
- /*
- * Media instructions
- * cccc 011x xxxx xxxx xxxx xxxx xxx1 xxxx
- */
- DECODE_TABLE (0x0f000010, 0x06000010, arm_cccc_0110_____xxx1_table),
- DECODE_TABLE (0x0f000010, 0x07000010, arm_cccc_0111_____xxx1_table),
-
- /*
- * Load/store word and unsigned byte
- * cccc 01xx xxxx xxxx xxxx xxxx xxxx xxxx
- */
- DECODE_TABLE (0x0c000000, 0x04000000, arm_cccc_01xx_table),
-
- /*
- * Block data transfer instructions
- * cccc 100x xxxx xxxx xxxx xxxx xxxx xxxx
- */
- DECODE_TABLE (0x0e000000, 0x08000000, arm_cccc_100x_table),
-
- /* B cccc 1010 xxxx xxxx xxxx xxxx xxxx xxxx */
- /* BL cccc 1011 xxxx xxxx xxxx xxxx xxxx xxxx */
- DECODE_SIMULATE (0x0e000000, 0x0a000000, simulate_bbl),
-
- /*
- * Supervisor Call, and coprocessor instructions
- */
-
- /* MCRR cccc 1100 0100 xxxx xxxx xxxx xxxx xxxx */
- /* MRRC cccc 1100 0101 xxxx xxxx xxxx xxxx xxxx */
- /* LDC cccc 110x xxx1 xxxx xxxx xxxx xxxx xxxx */
- /* STC cccc 110x xxx0 xxxx xxxx xxxx xxxx xxxx */
- /* CDP cccc 1110 xxxx xxxx xxxx xxxx xxx0 xxxx */
- /* MCR cccc 1110 xxx0 xxxx xxxx xxxx xxx1 xxxx */
- /* MRC cccc 1110 xxx1 xxxx xxxx xxxx xxx1 xxxx */
- /* SVC cccc 1111 xxxx xxxx xxxx xxxx xxxx xxxx */
- DECODE_REJECT (0x0c000000, 0x0c000000),
-
- DECODE_END
-};
-#ifdef CONFIG_ARM_KPROBES_TEST_MODULE
-EXPORT_SYMBOL_GPL(kprobe_decode_arm_table);
-#endif
-
-static void __kprobes arm_singlestep(struct kprobe *p, struct pt_regs *regs)
-{
- regs->ARM_pc += 4;
- p->ainsn.insn_handler(p, regs);
-}
-
-/* Return:
- * INSN_REJECTED If instruction is one not allowed to kprobe,
- * INSN_GOOD If instruction is supported and uses instruction slot,
- * INSN_GOOD_NO_SLOT If instruction is supported but doesn't use its slot.
- *
- * For instructions we don't want to kprobe (INSN_REJECTED return result):
- * These are generally ones that modify the processor state making
- * them "hard" to simulate such as switches processor modes or
- * make accesses in alternate modes. Any of these could be simulated
- * if the work was put into it, but low return considering they
- * should also be very rare.
- */
-enum kprobe_insn __kprobes
-arm_kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi)
-{
- asi->insn_singlestep = arm_singlestep;
- asi->insn_check_cc = kprobe_condition_checks[insn>>28];
- return kprobe_decode_insn(insn, asi, kprobe_decode_arm_table, false);
-}
diff --git a/arch/arm/kernel/kprobes-common.c b/arch/arm/kernel/kprobes-common.c
index 18a7628..ed47b54 100644
--- a/arch/arm/kernel/kprobes-common.c
+++ b/arch/arm/kernel/kprobes-common.c
@@ -18,170 +18,6 @@
#include "kprobes.h"
-#ifndef find_str_pc_offset
-
-/*
- * For STR and STM instructions, an ARM core may choose to use either
- * a +8 or a +12 displacement from the current instruction's address.
- * Whichever value is chosen for a given core, it must be the same for
- * both instructions and may not change. This function measures it.
- */
-
-int str_pc_offset;
-
-void __init find_str_pc_offset(void)
-{
- int addr, scratch, ret;
-
- __asm__ (
- "sub %[ret], pc, #4 \n\t"
- "str pc, %[addr] \n\t"
- "ldr %[scr], %[addr] \n\t"
- "sub %[ret], %[scr], %[ret] \n\t"
- : [ret] "=r" (ret), [scr] "=r" (scratch), [addr] "+m" (addr));
-
- str_pc_offset = ret;
-}
-
-#endif /* !find_str_pc_offset */
-
-
-#ifndef test_load_write_pc_interworking
-
-bool load_write_pc_interworks;
-
-void __init test_load_write_pc_interworking(void)
-{
- int arch = cpu_architecture();
- BUG_ON(arch == CPU_ARCH_UNKNOWN);
- load_write_pc_interworks = arch >= CPU_ARCH_ARMv5T;
-}
-
-#endif /* !test_load_write_pc_interworking */
-
-
-#ifndef test_alu_write_pc_interworking
-
-bool alu_write_pc_interworks;
-
-void __init test_alu_write_pc_interworking(void)
-{
- int arch = cpu_architecture();
- BUG_ON(arch == CPU_ARCH_UNKNOWN);
- alu_write_pc_interworks = arch >= CPU_ARCH_ARMv7;
-}
-
-#endif /* !test_alu_write_pc_interworking */
-
-
-void __init arm_kprobe_decode_init(void)
-{
- find_str_pc_offset();
- test_load_write_pc_interworking();
- test_alu_write_pc_interworking();
-}
-
-
-static unsigned long __kprobes __check_eq(unsigned long cpsr)
-{
- return cpsr & PSR_Z_BIT;
-}
-
-static unsigned long __kprobes __check_ne(unsigned long cpsr)
-{
- return (~cpsr) & PSR_Z_BIT;
-}
-
-static unsigned long __kprobes __check_cs(unsigned long cpsr)
-{
- return cpsr & PSR_C_BIT;
-}
-
-static unsigned long __kprobes __check_cc(unsigned long cpsr)
-{
- return (~cpsr) & PSR_C_BIT;
-}
-
-static unsigned long __kprobes __check_mi(unsigned long cpsr)
-{
- return cpsr & PSR_N_BIT;
-}
-
-static unsigned long __kprobes __check_pl(unsigned long cpsr)
-{
- return (~cpsr) & PSR_N_BIT;
-}
-
-static unsigned long __kprobes __check_vs(unsigned long cpsr)
-{
- return cpsr & PSR_V_BIT;
-}
-
-static unsigned long __kprobes __check_vc(unsigned long cpsr)
-{
- return (~cpsr) & PSR_V_BIT;
-}
-
-static unsigned long __kprobes __check_hi(unsigned long cpsr)
-{
- cpsr &= ~(cpsr >> 1); /* PSR_C_BIT &= ~PSR_Z_BIT */
- return cpsr & PSR_C_BIT;
-}
-
-static unsigned long __kprobes __check_ls(unsigned long cpsr)
-{
- cpsr &= ~(cpsr >> 1); /* PSR_C_BIT &= ~PSR_Z_BIT */
- return (~cpsr) & PSR_C_BIT;
-}
-
-static unsigned long __kprobes __check_ge(unsigned long cpsr)
-{
- cpsr ^= (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
- return (~cpsr) & PSR_N_BIT;
-}
-
-static unsigned long __kprobes __check_lt(unsigned long cpsr)
-{
- cpsr ^= (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
- return cpsr & PSR_N_BIT;
-}
-
-static unsigned long __kprobes __check_gt(unsigned long cpsr)
-{
- unsigned long temp = cpsr ^ (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
- temp |= (cpsr << 1); /* PSR_N_BIT |= PSR_Z_BIT */
- return (~temp) & PSR_N_BIT;
-}
-
-static unsigned long __kprobes __check_le(unsigned long cpsr)
-{
- unsigned long temp = cpsr ^ (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
- temp |= (cpsr << 1); /* PSR_N_BIT |= PSR_Z_BIT */
- return temp & PSR_N_BIT;
-}
-
-static unsigned long __kprobes __check_al(unsigned long cpsr)
-{
- return true;
-}
-
-kprobe_check_cc * const kprobe_condition_checks[16] = {
- &__check_eq, &__check_ne, &__check_cs, &__check_cc,
- &__check_mi, &__check_pl, &__check_vs, &__check_vc,
- &__check_hi, &__check_ls, &__check_ge, &__check_lt,
- &__check_gt, &__check_le, &__check_al, &__check_al
-};
-
-
-void __kprobes kprobe_simulate_nop(struct kprobe *p, struct pt_regs *regs)
-{
-}
-
-void __kprobes kprobe_emulate_none(struct kprobe *p, struct pt_regs *regs)
-{
- p->ainsn.insn_fn();
-}
-
static void __kprobes simulate_ldm1stm1(struct kprobe *p, struct pt_regs *regs)
{
kprobe_opcode_t insn = p->opcode;
@@ -319,260 +155,3 @@ kprobe_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi)
return INSN_GOOD_NO_SLOT;
}
-
-/*
- * Prepare an instruction slot to receive an instruction for emulating.
- * This is done by placing a subroutine return after the location where the
- * instruction will be placed. We also modify ARM instructions to be
- * unconditional as the condition code will already be checked before any
- * emulation handler is called.
- */
-static kprobe_opcode_t __kprobes
-prepare_emulated_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi,
- bool thumb)
-{
-#ifdef CONFIG_THUMB2_KERNEL
- if (thumb) {
- u16 *thumb_insn = (u16 *)asi->insn;
- thumb_insn[1] = 0x4770; /* Thumb bx lr */
- thumb_insn[2] = 0x4770; /* Thumb bx lr */
- return insn;
- }
- asi->insn[1] = 0xe12fff1e; /* ARM bx lr */
-#else
- asi->insn[1] = 0xe1a0f00e; /* mov pc, lr */
-#endif
- /* Make an ARM instruction unconditional */
- if (insn < 0xe0000000)
- insn = (insn | 0xe0000000) & ~0x10000000;
- return insn;
-}
-
-/*
- * Write a (probably modified) instruction into the slot previously prepared by
- * prepare_emulated_insn
- */
-static void __kprobes
-set_emulated_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi,
- bool thumb)
-{
-#ifdef CONFIG_THUMB2_KERNEL
- if (thumb) {
- u16 *ip = (u16 *)asi->insn;
- if (is_wide_instruction(insn))
- *ip++ = insn >> 16;
- *ip++ = insn;
- return;
- }
-#endif
- asi->insn[0] = insn;
-}
-
-/*
- * When we modify the register numbers encoded in an instruction to be emulated,
- * the new values come from this define. For ARM and 32-bit Thumb instructions
- * this gives...
- *
- * bit position 16 12 8 4 0
- * ---------------+---+---+---+---+---+
- * register r2 r0 r1 -- r3
- */
-#define INSN_NEW_BITS 0x00020103
-
-/* Each nibble has same value as that at INSN_NEW_BITS bit 16 */
-#define INSN_SAMEAS16_BITS 0x22222222
-
-/*
- * Validate and modify each of the registers encoded in an instruction.
- *
- * Each nibble in regs contains a value from enum decode_reg_type. For each
- * non-zero value, the corresponding nibble in pinsn is validated and modified
- * according to the type.
- */
-static bool __kprobes decode_regs(kprobe_opcode_t* pinsn, u32 regs)
-{
- kprobe_opcode_t insn = *pinsn;
- kprobe_opcode_t mask = 0xf; /* Start at least significant nibble */
-
- for (; regs != 0; regs >>= 4, mask <<= 4) {
-
- kprobe_opcode_t new_bits = INSN_NEW_BITS;
-
- switch (regs & 0xf) {
-
- case REG_TYPE_NONE:
- /* Nibble not a register, skip to next */
- continue;
-
- case REG_TYPE_ANY:
- /* Any register is allowed */
- break;
-
- case REG_TYPE_SAMEAS16:
- /* Replace register with same as@bit position 16 */
- new_bits = INSN_SAMEAS16_BITS;
- break;
-
- case REG_TYPE_SP:
- /* Only allow SP (R13) */
- if ((insn ^ 0xdddddddd) & mask)
- goto reject;
- break;
-
- case REG_TYPE_PC:
- /* Only allow PC (R15) */
- if ((insn ^ 0xffffffff) & mask)
- goto reject;
- break;
-
- case REG_TYPE_NOSP:
- /* Reject SP (R13) */
- if (((insn ^ 0xdddddddd) & mask) == 0)
- goto reject;
- break;
-
- case REG_TYPE_NOSPPC:
- case REG_TYPE_NOSPPCX:
- /* Reject SP and PC (R13 and R15) */
- if (((insn ^ 0xdddddddd) & 0xdddddddd & mask) == 0)
- goto reject;
- break;
-
- case REG_TYPE_NOPCWB:
- if (!is_writeback(insn))
- break; /* No writeback, so any register is OK */
- /* fall through... */
- case REG_TYPE_NOPC:
- case REG_TYPE_NOPCX:
- /* Reject PC (R15) */
- if (((insn ^ 0xffffffff) & mask) == 0)
- goto reject;
- break;
- }
-
- /* Replace value of nibble with new register number... */
- insn &= ~mask;
- insn |= new_bits & mask;
- }
-
- *pinsn = insn;
- return true;
-
-reject:
- return false;
-}
-
-static const int decode_struct_sizes[NUM_DECODE_TYPES] = {
- [DECODE_TYPE_TABLE] = sizeof(struct decode_table),
- [DECODE_TYPE_CUSTOM] = sizeof(struct decode_custom),
- [DECODE_TYPE_SIMULATE] = sizeof(struct decode_simulate),
- [DECODE_TYPE_EMULATE] = sizeof(struct decode_emulate),
- [DECODE_TYPE_OR] = sizeof(struct decode_or),
- [DECODE_TYPE_REJECT] = sizeof(struct decode_reject)
-};
-
-/*
- * kprobe_decode_insn operates on data tables in order to decode an ARM
- * architecture instruction onto which a kprobe has been placed.
- *
- * These instruction decoding tables are a concatenation of entries each
- * of which consist of one of the following structs:
- *
- * decode_table
- * decode_custom
- * decode_simulate
- * decode_emulate
- * decode_or
- * decode_reject
- *
- * Each of these starts with a struct decode_header which has the following
- * fields:
- *
- * type_regs
- * mask
- * value
- *
- * The least significant DECODE_TYPE_BITS of type_regs contains a value
- * from enum decode_type, this indicates which of the decode_* structs
- * the entry contains. The value DECODE_TYPE_END indicates the end of the
- * table.
- *
- * When the table is parsed, each entry is checked in turn to see if it
- * matches the instruction to be decoded using the test:
- *
- * (insn & mask) == value
- *
- * If no match is found before the end of the table is reached then decoding
- * fails with INSN_REJECTED.
- *
- * When a match is found, decode_regs() is called to validate and modify each
- * of the registers encoded in the instruction; the data it uses to do this
- * is (type_regs >> DECODE_TYPE_BITS). A validation failure will cause decoding
- * to fail with INSN_REJECTED.
- *
- * Once the instruction has passed the above tests, further processing
- * depends on the type of the table entry's decode struct.
- *
- */
-int __kprobes
-kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi,
- const union decode_item *table, bool thumb)
-{
- const struct decode_header *h = (struct decode_header *)table;
- const struct decode_header *next;
- bool matched = false;
-
- insn = prepare_emulated_insn(insn, asi, thumb);
-
- for (;; h = next) {
- enum decode_type type = h->type_regs.bits & DECODE_TYPE_MASK;
- u32 regs = h->type_regs.bits >> DECODE_TYPE_BITS;
-
- if (type == DECODE_TYPE_END)
- return INSN_REJECTED;
-
- next = (struct decode_header *)
- ((uintptr_t)h + decode_struct_sizes[type]);
-
- if (!matched && (insn & h->mask.bits) != h->value.bits)
- continue;
-
- if (!decode_regs(&insn, regs))
- return INSN_REJECTED;
-
- switch (type) {
-
- case DECODE_TYPE_TABLE: {
- struct decode_table *d = (struct decode_table *)h;
- next = (struct decode_header *)d->table.table;
- break;
- }
-
- case DECODE_TYPE_CUSTOM: {
- struct decode_custom *d = (struct decode_custom *)h;
- return (*d->decoder.decoder)(insn, asi);
- }
-
- case DECODE_TYPE_SIMULATE: {
- struct decode_simulate *d = (struct decode_simulate *)h;
- asi->insn_handler = d->handler.handler;
- return INSN_GOOD_NO_SLOT;
- }
-
- case DECODE_TYPE_EMULATE: {
- struct decode_emulate *d = (struct decode_emulate *)h;
- asi->insn_handler = d->handler.handler;
- set_emulated_insn(insn, asi, thumb);
- return INSN_GOOD;
- }
-
- case DECODE_TYPE_OR:
- matched = true;
- break;
-
- case DECODE_TYPE_REJECT:
- default:
- return INSN_REJECTED;
- }
- }
- }
diff --git a/arch/arm/kernel/kprobes.h b/arch/arm/kernel/kprobes.h
index 38945f7..aa68c0e 100644
--- a/arch/arm/kernel/kprobes.h
+++ b/arch/arm/kernel/kprobes.h
@@ -52,377 +52,6 @@ enum kprobe_insn arm_kprobe_decode_insn(kprobe_opcode_t,
void __init arm_kprobe_decode_init(void);
-extern kprobe_check_cc * const kprobe_condition_checks[16];
-
-
-#if __LINUX_ARM_ARCH__ >= 7
-
-/* str_pc_offset is architecturally defined from ARMv7 onwards */
-#define str_pc_offset 8
-#define find_str_pc_offset()
-
-#else /* __LINUX_ARM_ARCH__ < 7 */
-
-/* We need a run-time check to determine str_pc_offset */
-extern int str_pc_offset;
-void __init find_str_pc_offset(void);
-
-#endif
-
-
-/*
- * Update ITSTATE after normal execution of an IT block instruction.
- *
- * The 8 IT state bits are split into two parts in CPSR:
- * ITSTATE<1:0> are in CPSR<26:25>
- * ITSTATE<7:2> are in CPSR<15:10>
- */
-static inline unsigned long it_advance(unsigned long cpsr)
- {
- if ((cpsr & 0x06000400) == 0) {
- /* ITSTATE<2:0> == 0 means end of IT block, so clear IT state */
- cpsr &= ~PSR_IT_MASK;
- } else {
- /* We need to shift left ITSTATE<4:0> */
- const unsigned long mask = 0x06001c00; /* Mask ITSTATE<4:0> */
- unsigned long it = cpsr & mask;
- it <<= 1;
- it |= it >> (27 - 10); /* Carry ITSTATE<2> to correct place */
- it &= mask;
- cpsr &= ~mask;
- cpsr |= it;
- }
- return cpsr;
-}
-
-static inline void __kprobes bx_write_pc(long pcv, struct pt_regs *regs)
-{
- long cpsr = regs->ARM_cpsr;
- if (pcv & 0x1) {
- cpsr |= PSR_T_BIT;
- pcv &= ~0x1;
- } else {
- cpsr &= ~PSR_T_BIT;
- pcv &= ~0x2; /* Avoid UNPREDICTABLE address allignment */
- }
- regs->ARM_cpsr = cpsr;
- regs->ARM_pc = pcv;
-}
-
-
-#if __LINUX_ARM_ARCH__ >= 6
-
-/* Kernels built for >= ARMv6 should never run on <= ARMv5 hardware, so... */
-#define load_write_pc_interworks true
-#define test_load_write_pc_interworking()
-
-#else /* __LINUX_ARM_ARCH__ < 6 */
-
-/* We need run-time testing to determine if load_write_pc() should interwork. */
-extern bool load_write_pc_interworks;
-void __init test_load_write_pc_interworking(void);
-
-#endif
-
-static inline void __kprobes load_write_pc(long pcv, struct pt_regs *regs)
-{
- if (load_write_pc_interworks)
- bx_write_pc(pcv, regs);
- else
- regs->ARM_pc = pcv;
-}
-
-
-#if __LINUX_ARM_ARCH__ >= 7
-
-#define alu_write_pc_interworks true
-#define test_alu_write_pc_interworking()
-
-#elif __LINUX_ARM_ARCH__ <= 5
-
-/* Kernels built for <= ARMv5 should never run on >= ARMv6 hardware, so... */
-#define alu_write_pc_interworks false
-#define test_alu_write_pc_interworking()
-
-#else /* __LINUX_ARM_ARCH__ == 6 */
-
-/* We could be an ARMv6 binary on ARMv7 hardware so we need a run-time check. */
-extern bool alu_write_pc_interworks;
-void __init test_alu_write_pc_interworking(void);
-
-#endif /* __LINUX_ARM_ARCH__ == 6 */
-
-static inline void __kprobes alu_write_pc(long pcv, struct pt_regs *regs)
-{
- if (alu_write_pc_interworks)
- bx_write_pc(pcv, regs);
- else
- regs->ARM_pc = pcv;
-}
-
-
-void __kprobes kprobe_simulate_nop(struct kprobe *p, struct pt_regs *regs);
-void __kprobes kprobe_emulate_none(struct kprobe *p, struct pt_regs *regs);
-
-enum kprobe_insn __kprobes
-kprobe_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi);
-
-/*
- * Test if load/store instructions writeback the address register.
- * if P (bit 24) == 0 or W (bit 21) == 1
- */
-#define is_writeback(insn) ((insn ^ 0x01000000) & 0x01200000)
-
-/*
- * The following definitions and macros are used to build instruction
- * decoding tables for use by kprobe_decode_insn.
- *
- * These tables are a concatenation of entries each of which consist of one of
- * the decode_* structs. All of the fields in every type of decode structure
- * are of the union type decode_item, therefore the entire decode table can be
- * viewed as an array of these and declared like:
- *
- * static const union decode_item table_name[] = {};
- *
- * In order to construct each entry in the table, macros are used to
- * initialise a number of sequential decode_item values in a layout which
- * matches the relevant struct. E.g. DECODE_SIMULATE initialise a struct
- * decode_simulate by initialising four decode_item objects like this...
- *
- * {.bits = _type},
- * {.bits = _mask},
- * {.bits = _value},
- * {.handler = _handler},
- *
- * Initialising a specified member of the union means that the compiler
- * will produce a warning if the argument is of an incorrect type.
- *
- * Below is a list of each of the macros used to initialise entries and a
- * description of the action performed when that entry is matched to an
- * instruction. A match is found when (instruction & mask) == value.
- *
- * DECODE_TABLE(mask, value, table)
- * Instruction decoding jumps to parsing the new sub-table 'table'.
- *
- * DECODE_CUSTOM(mask, value, decoder)
- * The custom function 'decoder' is called to the complete decoding
- * of an instruction.
- *
- * DECODE_SIMULATE(mask, value, handler)
- * Set the probes instruction handler to 'handler', this will be used
- * to simulate the instruction when the probe is hit. Decoding returns
- * with INSN_GOOD_NO_SLOT.
- *
- * DECODE_EMULATE(mask, value, handler)
- * Set the probes instruction handler to 'handler', this will be used
- * to emulate the instruction when the probe is hit. The modified
- * instruction (see below) is placed in the probes instruction slot so it
- * may be called by the emulation code. Decoding returns with INSN_GOOD.
- *
- * DECODE_REJECT(mask, value)
- * Instruction decoding fails with INSN_REJECTED
- *
- * DECODE_OR(mask, value)
- * This allows the mask/value test of multiple table entries to be
- * logically ORed. Once an 'or' entry is matched the decoding action to
- * be performed is that of the next entry which isn't an 'or'. E.g.
- *
- * DECODE_OR (mask1, value1)
- * DECODE_OR (mask2, value2)
- * DECODE_SIMULATE (mask3, value3, simulation_handler)
- *
- * This means that if any of the three mask/value pairs match the
- * instruction being decoded, then 'simulation_handler' will be used
- * for it.
- *
- * Both the SIMULATE and EMULATE macros have a second form which take an
- * additional 'regs' argument.
- *
- * DECODE_SIMULATEX(mask, value, handler, regs)
- * DECODE_EMULATEX (mask, value, handler, regs)
- *
- * These are used to specify what kind of CPU register is encoded in each of the
- * least significant 5 nibbles of the instruction being decoded. The regs value
- * is specified using the REGS macro, this takes any of the REG_TYPE_* values
- * from enum decode_reg_type as arguments; only the '*' part of the name is
- * given. E.g.
- *
- * REGS(0, ANY, NOPC, 0, ANY)
- *
- * This indicates an instruction is encoded like:
- *
- * bits 19..16 ignore
- * bits 15..12 any register allowed here
- * bits 11.. 8 any register except PC allowed here
- * bits 7.. 4 ignore
- * bits 3.. 0 any register allowed here
- *
- * This register specification is checked after a decode table entry is found to
- * match an instruction (through the mask/value test). Any invalid register then
- * found in the instruction will cause decoding to fail with INSN_REJECTED. In
- * the above example this would happen if bits 11..8 of the instruction were
- * 1111, indicating R15 or PC.
- *
- * As well as checking for legal combinations of registers, this data is also
- * used to modify the registers encoded in the instructions so that an
- * emulation routines can use it. (See decode_regs() and INSN_NEW_BITS.)
- *
- * Here is a real example which matches ARM instructions of the form
- * "AND <Rd>,<Rn>,<Rm>,<shift> <Rs>"
- *
- * DECODE_EMULATEX (0x0e000090, 0x00000010, emulate_rd12rn16rm0rs8_rwflags,
- * REGS(ANY, ANY, NOPC, 0, ANY)),
- * ^ ^ ^ ^
- * Rn Rd Rs Rm
- *
- * Decoding the instruction "AND R4, R5, R6, ASL R15" will be rejected because
- * Rs == R15
- *
- * Decoding the instruction "AND R4, R5, R6, ASL R7" will be accepted and the
- * instruction will be modified to "AND R0, R2, R3, ASL R1" and then placed into
- * the kprobes instruction slot. This can then be called later by the handler
- * function emulate_rd12rn16rm0rs8_rwflags in order to simulate the instruction.
- */
-
-enum decode_type {
- DECODE_TYPE_END,
- DECODE_TYPE_TABLE,
- DECODE_TYPE_CUSTOM,
- DECODE_TYPE_SIMULATE,
- DECODE_TYPE_EMULATE,
- DECODE_TYPE_OR,
- DECODE_TYPE_REJECT,
- NUM_DECODE_TYPES /* Must be last enum */
-};
-
-#define DECODE_TYPE_BITS 4
-#define DECODE_TYPE_MASK ((1 << DECODE_TYPE_BITS) - 1)
-
-enum decode_reg_type {
- REG_TYPE_NONE = 0, /* Not a register, ignore */
- REG_TYPE_ANY, /* Any register allowed */
- REG_TYPE_SAMEAS16, /* Register should be same as that@bits 19..16 */
- REG_TYPE_SP, /* Register must be SP */
- REG_TYPE_PC, /* Register must be PC */
- REG_TYPE_NOSP, /* Register must not be SP */
- REG_TYPE_NOSPPC, /* Register must not be SP or PC */
- REG_TYPE_NOPC, /* Register must not be PC */
- REG_TYPE_NOPCWB, /* No PC if load/store write-back flag also set */
-
- /* The following types are used when the encoding for PC indicates
- * another instruction form. This distiction only matters for test
- * case coverage checks.
- */
- REG_TYPE_NOPCX, /* Register must not be PC */
- REG_TYPE_NOSPPCX, /* Register must not be SP or PC */
-
- /* Alias to allow '0' arg to be used in REGS macro. */
- REG_TYPE_0 = REG_TYPE_NONE
-};
-
-#define REGS(r16, r12, r8, r4, r0) \
- ((REG_TYPE_##r16) << 16) + \
- ((REG_TYPE_##r12) << 12) + \
- ((REG_TYPE_##r8) << 8) + \
- ((REG_TYPE_##r4) << 4) + \
- (REG_TYPE_##r0)
-
-union decode_item {
- u32 bits;
- const union decode_item *table;
- kprobe_insn_handler_t *handler;
- kprobe_decode_insn_t *decoder;
-};
-
-
-#define DECODE_END \
- {.bits = DECODE_TYPE_END}
-
-
-struct decode_header {
- union decode_item type_regs;
- union decode_item mask;
- union decode_item value;
-};
-
-#define DECODE_HEADER(_type, _mask, _value, _regs) \
- {.bits = (_type) | ((_regs) << DECODE_TYPE_BITS)}, \
- {.bits = (_mask)}, \
- {.bits = (_value)}
-
-
-struct decode_table {
- struct decode_header header;
- union decode_item table;
-};
-
-#define DECODE_TABLE(_mask, _value, _table) \
- DECODE_HEADER(DECODE_TYPE_TABLE, _mask, _value, 0), \
- {.table = (_table)}
-
-
-struct decode_custom {
- struct decode_header header;
- union decode_item decoder;
-};
-
-#define DECODE_CUSTOM(_mask, _value, _decoder) \
- DECODE_HEADER(DECODE_TYPE_CUSTOM, _mask, _value, 0), \
- {.decoder = (_decoder)}
-
-
-struct decode_simulate {
- struct decode_header header;
- union decode_item handler;
-};
-
-#define DECODE_SIMULATEX(_mask, _value, _handler, _regs) \
- DECODE_HEADER(DECODE_TYPE_SIMULATE, _mask, _value, _regs), \
- {.handler = (_handler)}
-
-#define DECODE_SIMULATE(_mask, _value, _handler) \
- DECODE_SIMULATEX(_mask, _value, _handler, 0)
-
-
-struct decode_emulate {
- struct decode_header header;
- union decode_item handler;
-};
-
-#define DECODE_EMULATEX(_mask, _value, _handler, _regs) \
- DECODE_HEADER(DECODE_TYPE_EMULATE, _mask, _value, _regs), \
- {.handler = (_handler)}
-
-#define DECODE_EMULATE(_mask, _value, _handler) \
- DECODE_EMULATEX(_mask, _value, _handler, 0)
-
-
-struct decode_or {
- struct decode_header header;
-};
-
-#define DECODE_OR(_mask, _value) \
- DECODE_HEADER(DECODE_TYPE_OR, _mask, _value, 0)
-
-
-struct decode_reject {
- struct decode_header header;
-};
-
-#define DECODE_REJECT(_mask, _value) \
- DECODE_HEADER(DECODE_TYPE_REJECT, _mask, _value, 0)
-
-
-#ifdef CONFIG_THUMB2_KERNEL
-extern const union decode_item kprobe_decode_thumb16_table[];
-extern const union decode_item kprobe_decode_thumb32_table[];
-#else
-extern const union decode_item kprobe_decode_arm_table[];
-#endif
-
-
-int kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi,
- const union decode_item *table, bool thumb16);
-
+#include "probes.h"
#endif /* _ARM_KERNEL_KPROBES_H */
diff --git a/arch/arm/kernel/kprobes-arm.c b/arch/arm/kernel/probes-arm.c
similarity index 76%
copy from arch/arm/kernel/kprobes-arm.c
copy to arch/arm/kernel/probes-arm.c
index 8a30c89..3286412 100644
--- a/arch/arm/kernel/kprobes-arm.c
+++ b/arch/arm/kernel/probes-arm.c
@@ -1,5 +1,7 @@
/*
- * arch/arm/kernel/kprobes-decode.c
+ * arch/arm/kernel/probes-arm.c
+ *
+ * Some code moved here from arch/arm/kernel/kprobes-arm.c
*
* Copyright (C) 2006, 2007 Motorola Inc.
*
@@ -13,68 +15,17 @@
* General Public License for more details.
*/
-/*
- * We do not have hardware single-stepping on ARM, This
- * effort is further complicated by the ARM not having a
- * "next PC" register. Instructions that change the PC
- * can't be safely single-stepped in a MP environment, so
- * we have a lot of work to do:
- *
- * In the prepare phase:
- * *) If it is an instruction that does anything
- * with the CPU mode, we reject it for a kprobe.
- * (This is out of laziness rather than need. The
- * instructions could be simulated.)
- *
- * *) Otherwise, decode the instruction rewriting its
- * registers to take fixed, ordered registers and
- * setting a handler for it to run the instruction.
- *
- * In the execution phase by an instruction's handler:
- *
- * *) If the PC is written to by the instruction, the
- * instruction must be fully simulated in software.
- *
- * *) Otherwise, a modified form of the instruction is
- * directly executed. Its handler calls the
- * instruction in insn[0]. In insn[1] is a
- * "mov pc, lr" to return.
- *
- * Before calling, load up the reordered registers
- * from the original instruction's registers. If one
- * of the original input registers is the PC, compute
- * and adjust the appropriate input register.
- *
- * After call completes, copy the output registers to
- * the original instruction's original registers.
- *
- * We don't use a real breakpoint instruction since that
- * would have us in the kernel go from SVC mode to SVC
- * mode losing the link register. Instead we use an
- * undefined instruction. To simplify processing, the
- * undefined instruction used for kprobes must be reserved
- * exclusively for kprobes use.
- *
- * TODO: ifdef out some instruction decoding based on architecture.
- */
-
+#include <linux/compiler.h>
#include <linux/kernel.h>
-#include <linux/kprobes.h>
-#include <linux/module.h>
+#include <linux/kprobes.h>
#include "kprobes.h"
+#include "probes-arm.h"
#define sign_extend(x, signbit) ((x) | (0 - ((x) & (1 << (signbit)))))
#define branch_displacement(insn) sign_extend(((insn) & 0xffffff) << 2, 25)
-#if __LINUX_ARM_ARCH__ >= 6
-#define BLX(reg) "blx "reg" \n\t"
-#else
-#define BLX(reg) "mov lr, pc \n\t" \
- "mov pc, "reg" \n\t"
-#endif
-
/*
* To avoid the complications of mimicing single-stepping on a
* processor without a Next-PC or a single-step mode, and to
@@ -105,7 +56,7 @@
* read and write of flags.
*/
-static void __kprobes simulate_bbl(struct kprobe *p, struct pt_regs *regs)
+void __kprobes simulate_bbl(struct kprobe *p, struct pt_regs *regs)
{
kprobe_opcode_t insn = p->opcode;
long iaddr = (long)p->addr;
@@ -117,7 +68,7 @@ static void __kprobes simulate_bbl(struct kprobe *p, struct pt_regs *regs)
regs->ARM_pc = iaddr + 8 + disp;
}
-static void __kprobes simulate_blx1(struct kprobe *p, struct pt_regs *regs)
+void __kprobes simulate_blx1(struct kprobe *p, struct pt_regs *regs)
{
kprobe_opcode_t insn = p->opcode;
long iaddr = (long)p->addr;
@@ -128,7 +79,7 @@ static void __kprobes simulate_blx1(struct kprobe *p, struct pt_regs *regs)
regs->ARM_cpsr |= PSR_T_BIT;
}
-static void __kprobes simulate_blx2bx(struct kprobe *p, struct pt_regs *regs)
+void __kprobes simulate_blx2bx(struct kprobe *p, struct pt_regs *regs)
{
kprobe_opcode_t insn = p->opcode;
int rm = insn & 0xf;
@@ -143,7 +94,7 @@ static void __kprobes simulate_blx2bx(struct kprobe *p, struct pt_regs *regs)
regs->ARM_cpsr |= PSR_T_BIT;
}
-static void __kprobes simulate_mrs(struct kprobe *p, struct pt_regs *regs)
+void __kprobes simulate_mrs(struct kprobe *p, struct pt_regs *regs)
{
kprobe_opcode_t insn = p->opcode;
int rd = (insn >> 12) & 0xf;
@@ -151,238 +102,11 @@ static void __kprobes simulate_mrs(struct kprobe *p, struct pt_regs *regs)
regs->uregs[rd] = regs->ARM_cpsr & mask;
}
-static void __kprobes simulate_mov_ipsp(struct kprobe *p, struct pt_regs *regs)
+void __kprobes simulate_mov_ipsp(struct kprobe *p, struct pt_regs *regs)
{
regs->uregs[12] = regs->uregs[13];
}
-static void __kprobes
-emulate_ldrdstrd(struct kprobe *p, struct pt_regs *regs)
-{
- kprobe_opcode_t insn = p->opcode;
- unsigned long pc = (unsigned long)p->addr + 8;
- int rt = (insn >> 12) & 0xf;
- int rn = (insn >> 16) & 0xf;
- int rm = insn & 0xf;
-
- register unsigned long rtv asm("r0") = regs->uregs[rt];
- register unsigned long rt2v asm("r1") = regs->uregs[rt+1];
- register unsigned long rnv asm("r2") = (rn == 15) ? pc
- : regs->uregs[rn];
- register unsigned long rmv asm("r3") = regs->uregs[rm];
-
- __asm__ __volatile__ (
- BLX("%[fn]")
- : "=r" (rtv), "=r" (rt2v), "=r" (rnv)
- : "0" (rtv), "1" (rt2v), "2" (rnv), "r" (rmv),
- [fn] "r" (p->ainsn.insn_fn)
- : "lr", "memory", "cc"
- );
-
- regs->uregs[rt] = rtv;
- regs->uregs[rt+1] = rt2v;
- if (is_writeback(insn))
- regs->uregs[rn] = rnv;
-}
-
-static void __kprobes
-emulate_ldr(struct kprobe *p, struct pt_regs *regs)
-{
- kprobe_opcode_t insn = p->opcode;
- unsigned long pc = (unsigned long)p->addr + 8;
- int rt = (insn >> 12) & 0xf;
- int rn = (insn >> 16) & 0xf;
- int rm = insn & 0xf;
-
- register unsigned long rtv asm("r0");
- register unsigned long rnv asm("r2") = (rn == 15) ? pc
- : regs->uregs[rn];
- register unsigned long rmv asm("r3") = regs->uregs[rm];
-
- __asm__ __volatile__ (
- BLX("%[fn]")
- : "=r" (rtv), "=r" (rnv)
- : "1" (rnv), "r" (rmv), [fn] "r" (p->ainsn.insn_fn)
- : "lr", "memory", "cc"
- );
-
- if (rt == 15)
- load_write_pc(rtv, regs);
- else
- regs->uregs[rt] = rtv;
-
- if (is_writeback(insn))
- regs->uregs[rn] = rnv;
-}
-
-static void __kprobes
-emulate_str(struct kprobe *p, 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;
- int rt = (insn >> 12) & 0xf;
- int rn = (insn >> 16) & 0xf;
- int rm = insn & 0xf;
-
- register unsigned long rtv asm("r0") = (rt == 15) ? rtpc
- : regs->uregs[rt];
- register unsigned long rnv asm("r2") = (rn == 15) ? rnpc
- : regs->uregs[rn];
- register unsigned long rmv asm("r3") = regs->uregs[rm];
-
- __asm__ __volatile__ (
- BLX("%[fn]")
- : "=r" (rnv)
- : "r" (rtv), "0" (rnv), "r" (rmv), [fn] "r" (p->ainsn.insn_fn)
- : "lr", "memory", "cc"
- );
-
- if (is_writeback(insn))
- regs->uregs[rn] = rnv;
-}
-
-static void __kprobes
-emulate_rd12rn16rm0rs8_rwflags(struct kprobe *p, struct pt_regs *regs)
-{
- kprobe_opcode_t insn = p->opcode;
- unsigned long pc = (unsigned long)p->addr + 8;
- int rd = (insn >> 12) & 0xf;
- int rn = (insn >> 16) & 0xf;
- int rm = insn & 0xf;
- int rs = (insn >> 8) & 0xf;
-
- register unsigned long rdv asm("r0") = regs->uregs[rd];
- register unsigned long rnv asm("r2") = (rn == 15) ? pc
- : regs->uregs[rn];
- register unsigned long rmv asm("r3") = (rm == 15) ? pc
- : regs->uregs[rm];
- register unsigned long rsv asm("r1") = regs->uregs[rs];
- unsigned long cpsr = regs->ARM_cpsr;
-
- __asm__ __volatile__ (
- "msr cpsr_fs, %[cpsr] \n\t"
- BLX("%[fn]")
- "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)
- : "lr", "memory", "cc"
- );
-
- if (rd == 15)
- alu_write_pc(rdv, regs);
- else
- regs->uregs[rd] = rdv;
- regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK);
-}
-
-static void __kprobes
-emulate_rd12rn16rm0_rwflags_nopc(struct kprobe *p, struct pt_regs *regs)
-{
- kprobe_opcode_t insn = p->opcode;
- int rd = (insn >> 12) & 0xf;
- int rn = (insn >> 16) & 0xf;
- int rm = insn & 0xf;
-
- register unsigned long rdv asm("r0") = regs->uregs[rd];
- register unsigned long rnv asm("r2") = regs->uregs[rn];
- register unsigned long rmv asm("r3") = regs->uregs[rm];
- unsigned long cpsr = regs->ARM_cpsr;
-
- __asm__ __volatile__ (
- "msr cpsr_fs, %[cpsr] \n\t"
- BLX("%[fn]")
- "mrs %[cpsr], cpsr \n\t"
- : "=r" (rdv), [cpsr] "=r" (cpsr)
- : "0" (rdv), "r" (rnv), "r" (rmv),
- "1" (cpsr), [fn] "r" (p->ainsn.insn_fn)
- : "lr", "memory", "cc"
- );
-
- regs->uregs[rd] = rdv;
- regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK);
-}
-
-static void __kprobes
-emulate_rd16rn12rm0rs8_rwflags_nopc(struct kprobe *p, struct pt_regs *regs)
-{
- kprobe_opcode_t insn = p->opcode;
- int rd = (insn >> 16) & 0xf;
- int rn = (insn >> 12) & 0xf;
- int rm = insn & 0xf;
- int rs = (insn >> 8) & 0xf;
-
- register unsigned long rdv asm("r2") = regs->uregs[rd];
- register unsigned long rnv asm("r0") = regs->uregs[rn];
- register unsigned long rmv asm("r3") = regs->uregs[rm];
- register unsigned long rsv asm("r1") = regs->uregs[rs];
- unsigned long cpsr = regs->ARM_cpsr;
-
- __asm__ __volatile__ (
- "msr cpsr_fs, %[cpsr] \n\t"
- BLX("%[fn]")
- "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)
- : "lr", "memory", "cc"
- );
-
- regs->uregs[rd] = rdv;
- regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK);
-}
-
-static void __kprobes
-emulate_rd12rm0_noflags_nopc(struct kprobe *p, struct pt_regs *regs)
-{
- kprobe_opcode_t insn = p->opcode;
- int rd = (insn >> 12) & 0xf;
- int rm = insn & 0xf;
-
- register unsigned long rdv asm("r0") = regs->uregs[rd];
- register unsigned long rmv asm("r3") = regs->uregs[rm];
-
- __asm__ __volatile__ (
- BLX("%[fn]")
- : "=r" (rdv)
- : "0" (rdv), "r" (rmv), [fn] "r" (p->ainsn.insn_fn)
- : "lr", "memory", "cc"
- );
-
- regs->uregs[rd] = rdv;
-}
-
-static void __kprobes
-emulate_rdlo12rdhi16rn0rm8_rwflags_nopc(struct kprobe *p, struct pt_regs *regs)
-{
- kprobe_opcode_t insn = p->opcode;
- int rdlo = (insn >> 12) & 0xf;
- int rdhi = (insn >> 16) & 0xf;
- int rn = insn & 0xf;
- int rm = (insn >> 8) & 0xf;
-
- register unsigned long rdlov asm("r0") = regs->uregs[rdlo];
- register unsigned long rdhiv asm("r2") = regs->uregs[rdhi];
- register unsigned long rnv asm("r3") = regs->uregs[rn];
- register unsigned long rmv asm("r1") = regs->uregs[rm];
- unsigned long cpsr = regs->ARM_cpsr;
-
- __asm__ __volatile__ (
- "msr cpsr_fs, %[cpsr] \n\t"
- BLX("%[fn]")
- "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)
- : "lr", "memory", "cc"
- );
-
- regs->uregs[rdlo] = rdlov;
- regs->uregs[rdhi] = rdhiv;
- regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK);
-}
-
/*
* For the instruction masking and comparisons in all the "space_*"
* functions below, Do _not_ rearrange the order of tests unless
diff --git a/arch/arm/kernel/probes-arm.h b/arch/arm/kernel/probes-arm.h
new file mode 100644
index 0000000..8608472
--- /dev/null
+++ b/arch/arm/kernel/probes-arm.h
@@ -0,0 +1,38 @@
+/*
+ * arch/arm/kernel/probes-arm.h
+ *
+ * Copyright 2013 Linaro Ltd.
+ * Written by: David A. Long
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#ifndef _ARM_KERNEL_PROBES_ARM_H
+#define _ARM_KERNEL_PROBES_ARM_H
+
+void __kprobes simulate_bbl(struct kprobe *p, struct pt_regs *regs);
+void __kprobes simulate_blx1(struct kprobe *p, struct pt_regs *regs);
+void __kprobes simulate_blx2bx(struct kprobe *p, struct pt_regs *regs);
+void __kprobes simulate_mrs(struct kprobe *p, struct pt_regs *regs);
+void __kprobes simulate_mov_ipsp(struct kprobe *p, struct pt_regs *regs);
+
+void __kprobes emulate_ldrdstrd(struct kprobe *p, struct pt_regs *regs);
+void __kprobes emulate_ldr(struct kprobe *p, struct pt_regs *regs);
+void __kprobes emulate_str(struct kprobe *p, struct pt_regs *regs);
+void __kprobes emulate_rd12rn16rm0rs8_rwflags(struct kprobe *p,
+ struct pt_regs *regs);
+void __kprobes emulate_rd12rn16rm0_rwflags_nopc(struct kprobe *p,
+ struct pt_regs *regs);
+void __kprobes emulate_rd16rn12rm0rs8_rwflags_nopc(struct kprobe *p,
+ struct pt_regs *regs);
+void __kprobes emulate_rd12rm0_noflags_nopc(struct kprobe *p,
+ struct pt_regs *regs);
+void __kprobes emulate_rdlo12rdhi16rn0rm8_rwflags_nopc(struct kprobe *p,
+ struct pt_regs *regs);
+
+#endif
diff --git a/arch/arm/kernel/kprobes-common.c b/arch/arm/kernel/probes.c
similarity index 75%
copy from arch/arm/kernel/kprobes-common.c
copy to arch/arm/kernel/probes.c
index 18a7628..839bf97 100644
--- a/arch/arm/kernel/kprobes-common.c
+++ b/arch/arm/kernel/probes.c
@@ -1,5 +1,5 @@
/*
- * arch/arm/kernel/kprobes-common.c
+ * arch/arm/kernel/probes.c
*
* Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>.
*
@@ -182,144 +182,6 @@ void __kprobes kprobe_emulate_none(struct kprobe *p, struct pt_regs *regs)
p->ainsn.insn_fn();
}
-static void __kprobes simulate_ldm1stm1(struct kprobe *p, 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);
- int ubit = insn & (1 << 23);
- int pbit = insn & (1 << 24);
- long *addr = (long *)regs->uregs[rn];
- int reg_bit_vector;
- int reg_count;
-
- reg_count = 0;
- reg_bit_vector = insn & 0xffff;
- while (reg_bit_vector) {
- reg_bit_vector &= (reg_bit_vector - 1);
- ++reg_count;
- }
-
- if (!ubit)
- addr -= reg_count;
- addr += (!pbit == !ubit);
-
- reg_bit_vector = insn & 0xffff;
- while (reg_bit_vector) {
- int reg = __ffs(reg_bit_vector);
- reg_bit_vector &= (reg_bit_vector - 1);
- if (lbit)
- regs->uregs[reg] = *addr++;
- else
- *addr++ = regs->uregs[reg];
- }
-
- if (wbit) {
- if (!ubit)
- addr -= reg_count;
- addr -= (!pbit == !ubit);
- regs->uregs[rn] = (long)addr;
- }
-}
-
-static void __kprobes simulate_stm1_pc(struct kprobe *p, struct pt_regs *regs)
-{
- regs->ARM_pc = (long)p->addr + str_pc_offset;
- simulate_ldm1stm1(p, regs);
- regs->ARM_pc = (long)p->addr + 4;
-}
-
-static void __kprobes simulate_ldm1_pc(struct kprobe *p, struct pt_regs *regs)
-{
- simulate_ldm1stm1(p, regs);
- load_write_pc(regs->ARM_pc, regs);
-}
-
-static void __kprobes
-emulate_generic_r0_12_noflags(struct kprobe *p, struct pt_regs *regs)
-{
- register void *rregs asm("r1") = regs;
- register void *rfn asm("lr") = p->ainsn.insn_fn;
-
- __asm__ __volatile__ (
- "stmdb sp!, {%[regs], r11} \n\t"
- "ldmia %[regs], {r0-r12} \n\t"
-#if __LINUX_ARM_ARCH__ >= 6
- "blx %[fn] \n\t"
-#else
- "str %[fn], [sp, #-4]! \n\t"
- "adr lr, 1f \n\t"
- "ldr pc, [sp], #4 \n\t"
- "1: \n\t"
-#endif
- "ldr lr, [sp], #4 \n\t" /* lr = regs */
- "stmia lr, {r0-r12} \n\t"
- "ldr r11, [sp], #4 \n\t"
- : [regs] "=r" (rregs), [fn] "=r" (rfn)
- : "0" (rregs), "1" (rfn)
- : "r0", "r2", "r3", "r4", "r5", "r6", "r7",
- "r8", "r9", "r10", "r12", "memory", "cc"
- );
-}
-
-static void __kprobes
-emulate_generic_r2_14_noflags(struct kprobe *p, struct pt_regs *regs)
-{
- emulate_generic_r0_12_noflags(p, (struct pt_regs *)(regs->uregs+2));
-}
-
-static void __kprobes
-emulate_ldm_r3_15(struct kprobe *p, struct pt_regs *regs)
-{
- emulate_generic_r0_12_noflags(p, (struct pt_regs *)(regs->uregs+3));
- load_write_pc(regs->ARM_pc, regs);
-}
-
-enum kprobe_insn __kprobes
-kprobe_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi)
-{
- kprobe_insn_handler_t *handler = 0;
- unsigned reglist = insn & 0xffff;
- int is_ldm = insn & 0x100000;
- int rn = (insn >> 16) & 0xf;
-
- if (rn <= 12 && (reglist & 0xe000) == 0) {
- /* Instruction only uses registers in the range R0..R12 */
- handler = emulate_generic_r0_12_noflags;
-
- } else if (rn >= 2 && (reglist & 0x8003) == 0) {
- /* Instruction only uses registers in the range R2..R14 */
- rn -= 2;
- reglist >>= 2;
- handler = emulate_generic_r2_14_noflags;
-
- } else if (rn >= 3 && (reglist & 0x0007) == 0) {
- /* Instruction only uses registers in the range R3..R15 */
- if (is_ldm && (reglist & 0x8000)) {
- rn -= 3;
- reglist >>= 3;
- handler = emulate_ldm_r3_15;
- }
- }
-
- if (handler) {
- /* We can emulate the instruction in (possibly) modified form */
- asi->insn[0] = (insn & 0xfff00000) | (rn << 16) | reglist;
- asi->insn_handler = handler;
- return INSN_GOOD;
- }
-
- /* Fallback to slower simulation... */
- if (reglist & 0x8000)
- handler = is_ldm ? simulate_ldm1_pc : simulate_stm1_pc;
- else
- handler = simulate_ldm1stm1;
- asi->insn_handler = handler;
- return INSN_GOOD_NO_SLOT;
-}
-
-
/*
* Prepare an instruction slot to receive an instruction for emulating.
* This is done by placing a subroutine return after the location where the
@@ -389,7 +251,7 @@ set_emulated_insn(kprobe_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(kprobe_opcode_t* pinsn, u32 regs)
+static bool __kprobes decode_regs(kprobe_opcode_t *pinsn, u32 regs)
{
kprobe_opcode_t insn = *pinsn;
kprobe_opcode_t mask = 0xf; /* Start at least significant nibble */
@@ -574,5 +436,5 @@ kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi,
default:
return INSN_REJECTED;
}
- }
}
+}
diff --git a/arch/arm/kernel/kprobes.h b/arch/arm/kernel/probes.h
similarity index 92%
copy from arch/arm/kernel/kprobes.h
copy to arch/arm/kernel/probes.h
index 38945f7..d14d224 100644
--- a/arch/arm/kernel/kprobes.h
+++ b/arch/arm/kernel/probes.h
@@ -1,5 +1,5 @@
/*
- * arch/arm/kernel/kprobes.h
+ * arch/arm/kernel/probes.h
*
* Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>.
*
@@ -16,44 +16,10 @@
* General Public License for more details.
*/
-#ifndef _ARM_KERNEL_KPROBES_H
-#define _ARM_KERNEL_KPROBES_H
-
-/*
- * These undefined instructions must be unique and
- * reserved solely for kprobes' use.
- */
-#define KPROBE_ARM_BREAKPOINT_INSTRUCTION 0x07f001f8
-#define KPROBE_THUMB16_BREAKPOINT_INSTRUCTION 0xde18
-#define KPROBE_THUMB32_BREAKPOINT_INSTRUCTION 0xf7f0a018
-
-
-enum kprobe_insn {
- INSN_REJECTED,
- INSN_GOOD,
- INSN_GOOD_NO_SLOT
-};
-
-typedef enum kprobe_insn (kprobe_decode_insn_t)(kprobe_opcode_t,
- struct arch_specific_insn *);
-
-#ifdef CONFIG_THUMB2_KERNEL
-
-enum kprobe_insn thumb16_kprobe_decode_insn(kprobe_opcode_t,
- struct arch_specific_insn *);
-enum kprobe_insn thumb32_kprobe_decode_insn(kprobe_opcode_t,
- struct arch_specific_insn *);
-
-#else /* !CONFIG_THUMB2_KERNEL */
-
-enum kprobe_insn arm_kprobe_decode_insn(kprobe_opcode_t,
- struct arch_specific_insn *);
-#endif
-
-void __init arm_kprobe_decode_init(void);
-
-extern kprobe_check_cc * const kprobe_condition_checks[16];
+#ifndef _ARM_KERNEL_PROBES_H
+#define _ARM_KERNEL_PROBES_H
+#include <linux/kprobes.h>
#if __LINUX_ARM_ARCH__ >= 7
@@ -321,11 +287,11 @@ enum decode_reg_type {
};
#define REGS(r16, r12, r8, r4, r0) \
- ((REG_TYPE_##r16) << 16) + \
+ (((REG_TYPE_##r16) << 16) + \
((REG_TYPE_##r12) << 12) + \
((REG_TYPE_##r8) << 8) + \
((REG_TYPE_##r4) << 4) + \
- (REG_TYPE_##r0)
+ (REG_TYPE_##r0))
union decode_item {
u32 bits;
@@ -420,9 +386,10 @@ extern const union decode_item kprobe_decode_thumb32_table[];
extern const union decode_item kprobe_decode_arm_table[];
#endif
+extern kprobe_check_cc * const kprobe_condition_checks[16];
+
int kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi,
const union decode_item *table, bool thumb16);
-
-#endif /* _ARM_KERNEL_KPROBES_H */
+#endif
--
1.8.1.2
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH v4 04/16] ARM: move generic thumb instruction parsing code to new files for use by other feature
2013-12-16 4:08 [PATCH v4 00/16] uprobes: Add uprobes support for ARM David Long
` (2 preceding siblings ...)
2013-12-16 4:08 ` [PATCH v4 03/16] ARM: Move generic arm instruction parsing code to new files for sharing between features David Long
@ 2013-12-16 4:08 ` David Long
2013-12-20 12:46 ` Jon Medhurst (Tixy)
2013-12-16 4:08 ` [PATCH v4 05/16] ARM: use a function table for determining instruction interpreter actions David Long
` (11 subsequent siblings)
15 siblings, 1 reply; 34+ messages in thread
From: David Long @ 2013-12-16 4:08 UTC (permalink / raw)
To: linux-arm-kernel
From: "David A. Long" <dave.long@linaro.org>
Move the thumb version of the kprobes instruction parsing code into more generic
files from where it can be used by uprobes and possibly other subsystems. The
symbol names will be made more generic in a subsequent part of this patchset.
Signed-off-by: David A. Long <dave.long@linaro.org>
---
arch/arm/kernel/Makefile | 2 +-
arch/arm/kernel/kprobes-thumb.c | 933 +--------------------
.../arm/kernel/{kprobes-thumb.c => probes-thumb.c} | 594 +------------
arch/arm/kernel/probes-thumb.h | 136 +++
4 files changed, 176 insertions(+), 1489 deletions(-)
copy arch/arm/kernel/{kprobes-thumb.c => probes-thumb.c} (67%)
create mode 100644 arch/arm/kernel/probes-thumb.h
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index 4c8b13e..bb739f2 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -52,7 +52,7 @@ obj-$(CONFIG_JUMP_LABEL) += jump_label.o insn.o patch.o
obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o
obj-$(CONFIG_KPROBES) += probes.o kprobes.o kprobes-common.o patch.o
ifdef CONFIG_THUMB2_KERNEL
-obj-$(CONFIG_KPROBES) += kprobes-thumb.o
+obj-$(CONFIG_KPROBES) += kprobes-thumb.o probes-thumb.o
else
obj-$(CONFIG_KPROBES) += kprobes-arm.o probes-arm.o
endif
diff --git a/arch/arm/kernel/kprobes-thumb.c b/arch/arm/kernel/kprobes-thumb.c
index 6123daf..ebc13c1 100644
--- a/arch/arm/kernel/kprobes-thumb.c
+++ b/arch/arm/kernel/kprobes-thumb.c
@@ -13,6 +13,7 @@
#include <linux/module.h>
#include "kprobes.h"
+#include "probes-thumb.h"
/*
@@ -38,7 +39,9 @@ static inline unsigned long __kprobes thumb_probe_pc(struct kprobe *p)
return (unsigned long)p->addr - 1 + 4;
}
-static void __kprobes
+/* t32 thumb actions */
+
+void __kprobes
t32_simulate_table_branch(struct kprobe *p, struct pt_regs *regs)
{
kprobe_opcode_t insn = p->opcode;
@@ -58,7 +61,7 @@ t32_simulate_table_branch(struct kprobe *p, struct pt_regs *regs)
regs->ARM_pc = pc + 2 * halfwords;
}
-static void __kprobes
+void __kprobes
t32_simulate_mrs(struct kprobe *p, struct pt_regs *regs)
{
kprobe_opcode_t insn = p->opcode;
@@ -67,7 +70,7 @@ t32_simulate_mrs(struct kprobe *p, struct pt_regs *regs)
regs->uregs[rd] = regs->ARM_cpsr & mask;
}
-static void __kprobes
+void __kprobes
t32_simulate_cond_branch(struct kprobe *p, struct pt_regs *regs)
{
kprobe_opcode_t insn = p->opcode;
@@ -82,7 +85,7 @@ t32_simulate_cond_branch(struct kprobe *p, struct pt_regs *regs)
regs->ARM_pc = pc + (offset * 2);
}
-static enum kprobe_insn __kprobes
+enum kprobe_insn __kprobes
t32_decode_cond_branch(kprobe_opcode_t insn, struct arch_specific_insn *asi)
{
int cc = (insn >> 22) & 0xf;
@@ -91,7 +94,7 @@ t32_decode_cond_branch(kprobe_opcode_t insn, struct arch_specific_insn *asi)
return INSN_GOOD_NO_SLOT;
}
-static void __kprobes
+void __kprobes
t32_simulate_branch(struct kprobe *p, struct pt_regs *regs)
{
kprobe_opcode_t insn = p->opcode;
@@ -119,7 +122,7 @@ t32_simulate_branch(struct kprobe *p, struct pt_regs *regs)
regs->ARM_pc = pc + (offset * 2);
}
-static void __kprobes
+void __kprobes
t32_simulate_ldr_literal(struct kprobe *p, struct pt_regs *regs)
{
kprobe_opcode_t insn = p->opcode;
@@ -157,7 +160,7 @@ t32_simulate_ldr_literal(struct kprobe *p, struct pt_regs *regs)
regs->uregs[rt] = rtv;
}
-static enum kprobe_insn __kprobes
+enum kprobe_insn __kprobes
t32_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi)
{
enum kprobe_insn ret = kprobe_decode_ldmstm(insn, asi);
@@ -170,7 +173,7 @@ t32_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi)
return ret;
}
-static void __kprobes
+void __kprobes
t32_emulate_ldrdstrd(struct kprobe *p, struct pt_regs *regs)
{
kprobe_opcode_t insn = p->opcode;
@@ -197,7 +200,7 @@ t32_emulate_ldrdstrd(struct kprobe *p, struct pt_regs *regs)
regs->uregs[rt2] = rt2v;
}
-static void __kprobes
+void __kprobes
t32_emulate_ldrstr(struct kprobe *p, struct pt_regs *regs)
{
kprobe_opcode_t insn = p->opcode;
@@ -223,7 +226,7 @@ t32_emulate_ldrstr(struct kprobe *p, struct pt_regs *regs)
regs->uregs[rt] = rtv;
}
-static void __kprobes
+void __kprobes
t32_emulate_rd8rn16rm0_rwflags(struct kprobe *p, struct pt_regs *regs)
{
kprobe_opcode_t insn = p->opcode;
@@ -250,7 +253,7 @@ t32_emulate_rd8rn16rm0_rwflags(struct kprobe *p, struct pt_regs *regs)
regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK);
}
-static void __kprobes
+void __kprobes
t32_emulate_rd8pc16_noflags(struct kprobe *p, struct pt_regs *regs)
{
kprobe_opcode_t insn = p->opcode;
@@ -270,7 +273,7 @@ t32_emulate_rd8pc16_noflags(struct kprobe *p, struct pt_regs *regs)
regs->uregs[rd] = rdv;
}
-static void __kprobes
+void __kprobes
t32_emulate_rd8rn16_noflags(struct kprobe *p, struct pt_regs *regs)
{
kprobe_opcode_t insn = p->opcode;
@@ -290,7 +293,7 @@ t32_emulate_rd8rn16_noflags(struct kprobe *p, struct pt_regs *regs)
regs->uregs[rd] = rdv;
}
-static void __kprobes
+void __kprobes
t32_emulate_rdlo12rdhi8rn16rm0_noflags(struct kprobe *p, struct pt_regs *regs)
{
kprobe_opcode_t insn = p->opcode;
@@ -315,640 +318,9 @@ t32_emulate_rdlo12rdhi8rn16rm0_noflags(struct kprobe *p, struct pt_regs *regs)
regs->uregs[rdlo] = rdlov;
regs->uregs[rdhi] = rdhiv;
}
+/* t16 thumb actions */
-/* These emulation encodings are functionally equivalent... */
-#define t32_emulate_rd8rn16rm0ra12_noflags \
- t32_emulate_rdlo12rdhi8rn16rm0_noflags
-
-static const union decode_item t32_table_1110_100x_x0xx[] = {
- /* Load/store multiple instructions */
-
- /* Rn is PC 1110 100x x0xx 1111 xxxx xxxx xxxx xxxx */
- DECODE_REJECT (0xfe4f0000, 0xe80f0000),
-
- /* SRS 1110 1000 00x0 xxxx xxxx xxxx xxxx xxxx */
- /* RFE 1110 1000 00x1 xxxx xxxx xxxx xxxx xxxx */
- DECODE_REJECT (0xffc00000, 0xe8000000),
- /* SRS 1110 1001 10x0 xxxx xxxx xxxx xxxx xxxx */
- /* RFE 1110 1001 10x1 xxxx xxxx xxxx xxxx xxxx */
- DECODE_REJECT (0xffc00000, 0xe9800000),
-
- /* STM Rn, {...pc} 1110 100x x0x0 xxxx 1xxx xxxx xxxx xxxx */
- DECODE_REJECT (0xfe508000, 0xe8008000),
- /* LDM Rn, {...lr,pc} 1110 100x x0x1 xxxx 11xx xxxx xxxx xxxx */
- DECODE_REJECT (0xfe50c000, 0xe810c000),
- /* LDM/STM Rn, {...sp} 1110 100x x0xx xxxx xx1x xxxx xxxx xxxx */
- DECODE_REJECT (0xfe402000, 0xe8002000),
-
- /* STMIA 1110 1000 10x0 xxxx xxxx xxxx xxxx xxxx */
- /* LDMIA 1110 1000 10x1 xxxx xxxx xxxx xxxx xxxx */
- /* STMDB 1110 1001 00x0 xxxx xxxx xxxx xxxx xxxx */
- /* LDMDB 1110 1001 00x1 xxxx xxxx xxxx xxxx xxxx */
- DECODE_CUSTOM (0xfe400000, 0xe8000000, t32_decode_ldmstm),
-
- DECODE_END
-};
-
-static const union decode_item t32_table_1110_100x_x1xx[] = {
- /* Load/store dual, load/store exclusive, table branch */
-
- /* STRD (immediate) 1110 1000 x110 xxxx xxxx xxxx xxxx xxxx */
- /* LDRD (immediate) 1110 1000 x111 xxxx xxxx xxxx xxxx xxxx */
- DECODE_OR (0xff600000, 0xe8600000),
- /* STRD (immediate) 1110 1001 x1x0 xxxx xxxx xxxx xxxx xxxx */
- /* LDRD (immediate) 1110 1001 x1x1 xxxx xxxx xxxx xxxx xxxx */
- DECODE_EMULATEX (0xff400000, 0xe9400000, t32_emulate_ldrdstrd,
- REGS(NOPCWB, NOSPPC, NOSPPC, 0, 0)),
-
- /* TBB 1110 1000 1101 xxxx xxxx xxxx 0000 xxxx */
- /* TBH 1110 1000 1101 xxxx xxxx xxxx 0001 xxxx */
- DECODE_SIMULATEX(0xfff000e0, 0xe8d00000, t32_simulate_table_branch,
- REGS(NOSP, 0, 0, 0, NOSPPC)),
-
- /* STREX 1110 1000 0100 xxxx xxxx xxxx xxxx xxxx */
- /* LDREX 1110 1000 0101 xxxx xxxx xxxx xxxx xxxx */
- /* STREXB 1110 1000 1100 xxxx xxxx xxxx 0100 xxxx */
- /* STREXH 1110 1000 1100 xxxx xxxx xxxx 0101 xxxx */
- /* STREXD 1110 1000 1100 xxxx xxxx xxxx 0111 xxxx */
- /* LDREXB 1110 1000 1101 xxxx xxxx xxxx 0100 xxxx */
- /* LDREXH 1110 1000 1101 xxxx xxxx xxxx 0101 xxxx */
- /* LDREXD 1110 1000 1101 xxxx xxxx xxxx 0111 xxxx */
- /* And unallocated instructions... */
- DECODE_END
-};
-
-static const union decode_item t32_table_1110_101x[] = {
- /* Data-processing (shifted register) */
-
- /* TST 1110 1010 0001 xxxx xxxx 1111 xxxx xxxx */
- /* TEQ 1110 1010 1001 xxxx xxxx 1111 xxxx xxxx */
- DECODE_EMULATEX (0xff700f00, 0xea100f00, t32_emulate_rd8rn16rm0_rwflags,
- REGS(NOSPPC, 0, 0, 0, NOSPPC)),
-
- /* CMN 1110 1011 0001 xxxx xxxx 1111 xxxx xxxx */
- DECODE_OR (0xfff00f00, 0xeb100f00),
- /* CMP 1110 1011 1011 xxxx xxxx 1111 xxxx xxxx */
- DECODE_EMULATEX (0xfff00f00, 0xebb00f00, t32_emulate_rd8rn16rm0_rwflags,
- REGS(NOPC, 0, 0, 0, NOSPPC)),
-
- /* MOV 1110 1010 010x 1111 xxxx xxxx xxxx xxxx */
- /* MVN 1110 1010 011x 1111 xxxx xxxx xxxx xxxx */
- DECODE_EMULATEX (0xffcf0000, 0xea4f0000, t32_emulate_rd8rn16rm0_rwflags,
- REGS(0, 0, NOSPPC, 0, NOSPPC)),
-
- /* ??? 1110 1010 101x xxxx xxxx xxxx xxxx xxxx */
- /* ??? 1110 1010 111x xxxx xxxx xxxx xxxx xxxx */
- DECODE_REJECT (0xffa00000, 0xeaa00000),
- /* ??? 1110 1011 001x xxxx xxxx xxxx xxxx xxxx */
- DECODE_REJECT (0xffe00000, 0xeb200000),
- /* ??? 1110 1011 100x xxxx xxxx xxxx xxxx xxxx */
- DECODE_REJECT (0xffe00000, 0xeb800000),
- /* ??? 1110 1011 111x xxxx xxxx xxxx xxxx xxxx */
- DECODE_REJECT (0xffe00000, 0xebe00000),
-
- /* ADD/SUB SP, SP, Rm, LSL #0..3 */
- /* 1110 1011 x0xx 1101 x000 1101 xx00 xxxx */
- DECODE_EMULATEX (0xff4f7f30, 0xeb0d0d00, t32_emulate_rd8rn16rm0_rwflags,
- REGS(SP, 0, SP, 0, NOSPPC)),
-
- /* ADD/SUB SP, SP, Rm, shift */
- /* 1110 1011 x0xx 1101 xxxx 1101 xxxx xxxx */
- DECODE_REJECT (0xff4f0f00, 0xeb0d0d00),
-
- /* ADD/SUB Rd, SP, Rm, shift */
- /* 1110 1011 x0xx 1101 xxxx xxxx xxxx xxxx */
- DECODE_EMULATEX (0xff4f0000, 0xeb0d0000, t32_emulate_rd8rn16rm0_rwflags,
- REGS(SP, 0, NOPC, 0, NOSPPC)),
-
- /* AND 1110 1010 000x xxxx xxxx xxxx xxxx xxxx */
- /* BIC 1110 1010 001x xxxx xxxx xxxx xxxx xxxx */
- /* ORR 1110 1010 010x xxxx xxxx xxxx xxxx xxxx */
- /* ORN 1110 1010 011x xxxx xxxx xxxx xxxx xxxx */
- /* EOR 1110 1010 100x xxxx xxxx xxxx xxxx xxxx */
- /* PKH 1110 1010 110x xxxx xxxx xxxx xxxx xxxx */
- /* ADD 1110 1011 000x xxxx xxxx xxxx xxxx xxxx */
- /* ADC 1110 1011 010x xxxx xxxx xxxx xxxx xxxx */
- /* SBC 1110 1011 011x xxxx xxxx xxxx xxxx xxxx */
- /* SUB 1110 1011 101x xxxx xxxx xxxx xxxx xxxx */
- /* RSB 1110 1011 110x xxxx xxxx xxxx xxxx xxxx */
- DECODE_EMULATEX (0xfe000000, 0xea000000, t32_emulate_rd8rn16rm0_rwflags,
- REGS(NOSPPC, 0, NOSPPC, 0, NOSPPC)),
-
- DECODE_END
-};
-
-static const union decode_item t32_table_1111_0x0x___0[] = {
- /* Data-processing (modified immediate) */
-
- /* TST 1111 0x00 0001 xxxx 0xxx 1111 xxxx xxxx */
- /* TEQ 1111 0x00 1001 xxxx 0xxx 1111 xxxx xxxx */
- DECODE_EMULATEX (0xfb708f00, 0xf0100f00, t32_emulate_rd8rn16rm0_rwflags,
- REGS(NOSPPC, 0, 0, 0, 0)),
-
- /* CMN 1111 0x01 0001 xxxx 0xxx 1111 xxxx xxxx */
- DECODE_OR (0xfbf08f00, 0xf1100f00),
- /* CMP 1111 0x01 1011 xxxx 0xxx 1111 xxxx xxxx */
- DECODE_EMULATEX (0xfbf08f00, 0xf1b00f00, t32_emulate_rd8rn16rm0_rwflags,
- REGS(NOPC, 0, 0, 0, 0)),
-
- /* MOV 1111 0x00 010x 1111 0xxx xxxx xxxx xxxx */
- /* MVN 1111 0x00 011x 1111 0xxx xxxx xxxx xxxx */
- DECODE_EMULATEX (0xfbcf8000, 0xf04f0000, t32_emulate_rd8rn16rm0_rwflags,
- REGS(0, 0, NOSPPC, 0, 0)),
-
- /* ??? 1111 0x00 101x xxxx 0xxx xxxx xxxx xxxx */
- DECODE_REJECT (0xfbe08000, 0xf0a00000),
- /* ??? 1111 0x00 110x xxxx 0xxx xxxx xxxx xxxx */
- /* ??? 1111 0x00 111x xxxx 0xxx xxxx xxxx xxxx */
- DECODE_REJECT (0xfbc08000, 0xf0c00000),
- /* ??? 1111 0x01 001x xxxx 0xxx xxxx xxxx xxxx */
- DECODE_REJECT (0xfbe08000, 0xf1200000),
- /* ??? 1111 0x01 100x xxxx 0xxx xxxx xxxx xxxx */
- DECODE_REJECT (0xfbe08000, 0xf1800000),
- /* ??? 1111 0x01 111x xxxx 0xxx xxxx xxxx xxxx */
- DECODE_REJECT (0xfbe08000, 0xf1e00000),
-
- /* ADD Rd, SP, #imm 1111 0x01 000x 1101 0xxx xxxx xxxx xxxx */
- /* SUB Rd, SP, #imm 1111 0x01 101x 1101 0xxx xxxx xxxx xxxx */
- DECODE_EMULATEX (0xfb4f8000, 0xf10d0000, t32_emulate_rd8rn16rm0_rwflags,
- REGS(SP, 0, NOPC, 0, 0)),
-
- /* AND 1111 0x00 000x xxxx 0xxx xxxx xxxx xxxx */
- /* BIC 1111 0x00 001x xxxx 0xxx xxxx xxxx xxxx */
- /* ORR 1111 0x00 010x xxxx 0xxx xxxx xxxx xxxx */
- /* ORN 1111 0x00 011x xxxx 0xxx xxxx xxxx xxxx */
- /* EOR 1111 0x00 100x xxxx 0xxx xxxx xxxx xxxx */
- /* ADD 1111 0x01 000x xxxx 0xxx xxxx xxxx xxxx */
- /* ADC 1111 0x01 010x xxxx 0xxx xxxx xxxx xxxx */
- /* SBC 1111 0x01 011x xxxx 0xxx xxxx xxxx xxxx */
- /* SUB 1111 0x01 101x xxxx 0xxx xxxx xxxx xxxx */
- /* RSB 1111 0x01 110x xxxx 0xxx xxxx xxxx xxxx */
- DECODE_EMULATEX (0xfa008000, 0xf0000000, t32_emulate_rd8rn16rm0_rwflags,
- REGS(NOSPPC, 0, NOSPPC, 0, 0)),
-
- DECODE_END
-};
-
-static const union decode_item t32_table_1111_0x1x___0[] = {
- /* Data-processing (plain binary immediate) */
-
- /* ADDW Rd, PC, #imm 1111 0x10 0000 1111 0xxx xxxx xxxx xxxx */
- DECODE_OR (0xfbff8000, 0xf20f0000),
- /* SUBW Rd, PC, #imm 1111 0x10 1010 1111 0xxx xxxx xxxx xxxx */
- DECODE_EMULATEX (0xfbff8000, 0xf2af0000, t32_emulate_rd8pc16_noflags,
- REGS(PC, 0, NOSPPC, 0, 0)),
-
- /* ADDW SP, SP, #imm 1111 0x10 0000 1101 0xxx 1101 xxxx xxxx */
- DECODE_OR (0xfbff8f00, 0xf20d0d00),
- /* SUBW SP, SP, #imm 1111 0x10 1010 1101 0xxx 1101 xxxx xxxx */
- DECODE_EMULATEX (0xfbff8f00, 0xf2ad0d00, t32_emulate_rd8rn16_noflags,
- REGS(SP, 0, SP, 0, 0)),
-
- /* ADDW 1111 0x10 0000 xxxx 0xxx xxxx xxxx xxxx */
- DECODE_OR (0xfbf08000, 0xf2000000),
- /* SUBW 1111 0x10 1010 xxxx 0xxx xxxx xxxx xxxx */
- DECODE_EMULATEX (0xfbf08000, 0xf2a00000, t32_emulate_rd8rn16_noflags,
- REGS(NOPCX, 0, NOSPPC, 0, 0)),
-
- /* MOVW 1111 0x10 0100 xxxx 0xxx xxxx xxxx xxxx */
- /* MOVT 1111 0x10 1100 xxxx 0xxx xxxx xxxx xxxx */
- DECODE_EMULATEX (0xfb708000, 0xf2400000, t32_emulate_rd8rn16_noflags,
- REGS(0, 0, NOSPPC, 0, 0)),
-
- /* SSAT16 1111 0x11 0010 xxxx 0000 xxxx 00xx xxxx */
- /* SSAT 1111 0x11 00x0 xxxx 0xxx xxxx xxxx xxxx */
- /* USAT16 1111 0x11 1010 xxxx 0000 xxxx 00xx xxxx */
- /* USAT 1111 0x11 10x0 xxxx 0xxx xxxx xxxx xxxx */
- DECODE_EMULATEX (0xfb508000, 0xf3000000, t32_emulate_rd8rn16rm0_rwflags,
- REGS(NOSPPC, 0, NOSPPC, 0, 0)),
-
- /* SFBX 1111 0x11 0100 xxxx 0xxx xxxx xxxx xxxx */
- /* UFBX 1111 0x11 1100 xxxx 0xxx xxxx xxxx xxxx */
- DECODE_EMULATEX (0xfb708000, 0xf3400000, t32_emulate_rd8rn16_noflags,
- REGS(NOSPPC, 0, NOSPPC, 0, 0)),
-
- /* BFC 1111 0x11 0110 1111 0xxx xxxx xxxx xxxx */
- DECODE_EMULATEX (0xfbff8000, 0xf36f0000, t32_emulate_rd8rn16_noflags,
- REGS(0, 0, NOSPPC, 0, 0)),
-
- /* BFI 1111 0x11 0110 xxxx 0xxx xxxx xxxx xxxx */
- DECODE_EMULATEX (0xfbf08000, 0xf3600000, t32_emulate_rd8rn16_noflags,
- REGS(NOSPPCX, 0, NOSPPC, 0, 0)),
-
- DECODE_END
-};
-
-static const union decode_item t32_table_1111_0xxx___1[] = {
- /* Branches and miscellaneous control */
-
- /* YIELD 1111 0011 1010 xxxx 10x0 x000 0000 0001 */
- DECODE_OR (0xfff0d7ff, 0xf3a08001),
- /* SEV 1111 0011 1010 xxxx 10x0 x000 0000 0100 */
- DECODE_EMULATE (0xfff0d7ff, 0xf3a08004, kprobe_emulate_none),
- /* NOP 1111 0011 1010 xxxx 10x0 x000 0000 0000 */
- /* WFE 1111 0011 1010 xxxx 10x0 x000 0000 0010 */
- /* WFI 1111 0011 1010 xxxx 10x0 x000 0000 0011 */
- DECODE_SIMULATE (0xfff0d7fc, 0xf3a08000, kprobe_simulate_nop),
-
- /* MRS Rd, CPSR 1111 0011 1110 xxxx 10x0 xxxx xxxx xxxx */
- DECODE_SIMULATEX(0xfff0d000, 0xf3e08000, t32_simulate_mrs,
- REGS(0, 0, NOSPPC, 0, 0)),
-
- /*
- * Unsupported instructions
- * 1111 0x11 1xxx xxxx 10x0 xxxx xxxx xxxx
- *
- * MSR 1111 0011 100x xxxx 10x0 xxxx xxxx xxxx
- * DBG hint 1111 0011 1010 xxxx 10x0 x000 1111 xxxx
- * Unallocated hints 1111 0011 1010 xxxx 10x0 x000 xxxx xxxx
- * CPS 1111 0011 1010 xxxx 10x0 xxxx xxxx xxxx
- * CLREX/DSB/DMB/ISB 1111 0011 1011 xxxx 10x0 xxxx xxxx xxxx
- * BXJ 1111 0011 1100 xxxx 10x0 xxxx xxxx xxxx
- * SUBS PC,LR,#<imm8> 1111 0011 1101 xxxx 10x0 xxxx xxxx xxxx
- * MRS Rd, SPSR 1111 0011 1111 xxxx 10x0 xxxx xxxx xxxx
- * SMC 1111 0111 1111 xxxx 1000 xxxx xxxx xxxx
- * UNDEFINED 1111 0111 1111 xxxx 1010 xxxx xxxx xxxx
- * ??? 1111 0111 1xxx xxxx 1010 xxxx xxxx xxxx
- */
- DECODE_REJECT (0xfb80d000, 0xf3808000),
-
- /* Bcc 1111 0xxx xxxx xxxx 10x0 xxxx xxxx xxxx */
- DECODE_CUSTOM (0xf800d000, 0xf0008000, t32_decode_cond_branch),
-
- /* BLX 1111 0xxx xxxx xxxx 11x0 xxxx xxxx xxx0 */
- DECODE_OR (0xf800d001, 0xf000c000),
- /* B 1111 0xxx xxxx xxxx 10x1 xxxx xxxx xxxx */
- /* BL 1111 0xxx xxxx xxxx 11x1 xxxx xxxx xxxx */
- DECODE_SIMULATE (0xf8009000, 0xf0009000, t32_simulate_branch),
-
- DECODE_END
-};
-
-static const union decode_item t32_table_1111_100x_x0x1__1111[] = {
- /* Memory hints */
-
- /* PLD (literal) 1111 1000 x001 1111 1111 xxxx xxxx xxxx */
- /* PLI (literal) 1111 1001 x001 1111 1111 xxxx xxxx xxxx */
- DECODE_SIMULATE (0xfe7ff000, 0xf81ff000, kprobe_simulate_nop),
-
- /* PLD{W} (immediate) 1111 1000 10x1 xxxx 1111 xxxx xxxx xxxx */
- DECODE_OR (0xffd0f000, 0xf890f000),
- /* PLD{W} (immediate) 1111 1000 00x1 xxxx 1111 1100 xxxx xxxx */
- DECODE_OR (0xffd0ff00, 0xf810fc00),
- /* PLI (immediate) 1111 1001 1001 xxxx 1111 xxxx xxxx xxxx */
- DECODE_OR (0xfff0f000, 0xf990f000),
- /* PLI (immediate) 1111 1001 0001 xxxx 1111 1100 xxxx xxxx */
- DECODE_SIMULATEX(0xfff0ff00, 0xf910fc00, kprobe_simulate_nop,
- REGS(NOPCX, 0, 0, 0, 0)),
-
- /* PLD{W} (register) 1111 1000 00x1 xxxx 1111 0000 00xx xxxx */
- DECODE_OR (0xffd0ffc0, 0xf810f000),
- /* PLI (register) 1111 1001 0001 xxxx 1111 0000 00xx xxxx */
- DECODE_SIMULATEX(0xfff0ffc0, 0xf910f000, kprobe_simulate_nop,
- REGS(NOPCX, 0, 0, 0, NOSPPC)),
-
- /* Other unallocated instructions... */
- DECODE_END
-};
-
-static const union decode_item t32_table_1111_100x[] = {
- /* Store/Load single data item */
-
- /* ??? 1111 100x x11x xxxx xxxx xxxx xxxx xxxx */
- DECODE_REJECT (0xfe600000, 0xf8600000),
-
- /* ??? 1111 1001 0101 xxxx xxxx xxxx xxxx xxxx */
- DECODE_REJECT (0xfff00000, 0xf9500000),
-
- /* ??? 1111 100x 0xxx xxxx xxxx 10x0 xxxx xxxx */
- DECODE_REJECT (0xfe800d00, 0xf8000800),
-
- /* STRBT 1111 1000 0000 xxxx xxxx 1110 xxxx xxxx */
- /* STRHT 1111 1000 0010 xxxx xxxx 1110 xxxx xxxx */
- /* STRT 1111 1000 0100 xxxx xxxx 1110 xxxx xxxx */
- /* LDRBT 1111 1000 0001 xxxx xxxx 1110 xxxx xxxx */
- /* LDRSBT 1111 1001 0001 xxxx xxxx 1110 xxxx xxxx */
- /* LDRHT 1111 1000 0011 xxxx xxxx 1110 xxxx xxxx */
- /* LDRSHT 1111 1001 0011 xxxx xxxx 1110 xxxx xxxx */
- /* LDRT 1111 1000 0101 xxxx xxxx 1110 xxxx xxxx */
- DECODE_REJECT (0xfe800f00, 0xf8000e00),
-
- /* STR{,B,H} Rn,[PC...] 1111 1000 xxx0 1111 xxxx xxxx xxxx xxxx */
- DECODE_REJECT (0xff1f0000, 0xf80f0000),
-
- /* STR{,B,H} PC,[Rn...] 1111 1000 xxx0 xxxx 1111 xxxx xxxx xxxx */
- DECODE_REJECT (0xff10f000, 0xf800f000),
-
- /* LDR (literal) 1111 1000 x101 1111 xxxx xxxx xxxx xxxx */
- DECODE_SIMULATEX(0xff7f0000, 0xf85f0000, t32_simulate_ldr_literal,
- REGS(PC, ANY, 0, 0, 0)),
-
- /* STR (immediate) 1111 1000 0100 xxxx xxxx 1xxx xxxx xxxx */
- /* LDR (immediate) 1111 1000 0101 xxxx xxxx 1xxx xxxx xxxx */
- DECODE_OR (0xffe00800, 0xf8400800),
- /* STR (immediate) 1111 1000 1100 xxxx xxxx xxxx xxxx xxxx */
- /* LDR (immediate) 1111 1000 1101 xxxx xxxx xxxx xxxx xxxx */
- DECODE_EMULATEX (0xffe00000, 0xf8c00000, t32_emulate_ldrstr,
- REGS(NOPCX, ANY, 0, 0, 0)),
-
- /* STR (register) 1111 1000 0100 xxxx xxxx 0000 00xx xxxx */
- /* LDR (register) 1111 1000 0101 xxxx xxxx 0000 00xx xxxx */
- DECODE_EMULATEX (0xffe00fc0, 0xf8400000, t32_emulate_ldrstr,
- REGS(NOPCX, ANY, 0, 0, NOSPPC)),
-
- /* LDRB (literal) 1111 1000 x001 1111 xxxx xxxx xxxx xxxx */
- /* LDRSB (literal) 1111 1001 x001 1111 xxxx xxxx xxxx xxxx */
- /* LDRH (literal) 1111 1000 x011 1111 xxxx xxxx xxxx xxxx */
- /* LDRSH (literal) 1111 1001 x011 1111 xxxx xxxx xxxx xxxx */
- DECODE_SIMULATEX(0xfe5f0000, 0xf81f0000, t32_simulate_ldr_literal,
- REGS(PC, NOSPPCX, 0, 0, 0)),
-
- /* STRB (immediate) 1111 1000 0000 xxxx xxxx 1xxx xxxx xxxx */
- /* STRH (immediate) 1111 1000 0010 xxxx xxxx 1xxx xxxx xxxx */
- /* LDRB (immediate) 1111 1000 0001 xxxx xxxx 1xxx xxxx xxxx */
- /* LDRSB (immediate) 1111 1001 0001 xxxx xxxx 1xxx xxxx xxxx */
- /* LDRH (immediate) 1111 1000 0011 xxxx xxxx 1xxx xxxx xxxx */
- /* LDRSH (immediate) 1111 1001 0011 xxxx xxxx 1xxx xxxx xxxx */
- DECODE_OR (0xfec00800, 0xf8000800),
- /* STRB (immediate) 1111 1000 1000 xxxx xxxx xxxx xxxx xxxx */
- /* STRH (immediate) 1111 1000 1010 xxxx xxxx xxxx xxxx xxxx */
- /* LDRB (immediate) 1111 1000 1001 xxxx xxxx xxxx xxxx xxxx */
- /* LDRSB (immediate) 1111 1001 1001 xxxx xxxx xxxx xxxx xxxx */
- /* LDRH (immediate) 1111 1000 1011 xxxx xxxx xxxx xxxx xxxx */
- /* LDRSH (immediate) 1111 1001 1011 xxxx xxxx xxxx xxxx xxxx */
- DECODE_EMULATEX (0xfec00000, 0xf8800000, t32_emulate_ldrstr,
- REGS(NOPCX, NOSPPCX, 0, 0, 0)),
-
- /* STRB (register) 1111 1000 0000 xxxx xxxx 0000 00xx xxxx */
- /* STRH (register) 1111 1000 0010 xxxx xxxx 0000 00xx xxxx */
- /* LDRB (register) 1111 1000 0001 xxxx xxxx 0000 00xx xxxx */
- /* LDRSB (register) 1111 1001 0001 xxxx xxxx 0000 00xx xxxx */
- /* LDRH (register) 1111 1000 0011 xxxx xxxx 0000 00xx xxxx */
- /* LDRSH (register) 1111 1001 0011 xxxx xxxx 0000 00xx xxxx */
- DECODE_EMULATEX (0xfe800fc0, 0xf8000000, t32_emulate_ldrstr,
- REGS(NOPCX, NOSPPCX, 0, 0, NOSPPC)),
-
- /* Other unallocated instructions... */
- DECODE_END
-};
-
-static const union decode_item t32_table_1111_1010___1111[] = {
- /* Data-processing (register) */
-
- /* ??? 1111 1010 011x xxxx 1111 xxxx 1xxx xxxx */
- DECODE_REJECT (0xffe0f080, 0xfa60f080),
-
- /* SXTH 1111 1010 0000 1111 1111 xxxx 1xxx xxxx */
- /* UXTH 1111 1010 0001 1111 1111 xxxx 1xxx xxxx */
- /* SXTB16 1111 1010 0010 1111 1111 xxxx 1xxx xxxx */
- /* UXTB16 1111 1010 0011 1111 1111 xxxx 1xxx xxxx */
- /* SXTB 1111 1010 0100 1111 1111 xxxx 1xxx xxxx */
- /* UXTB 1111 1010 0101 1111 1111 xxxx 1xxx xxxx */
- DECODE_EMULATEX (0xff8ff080, 0xfa0ff080, t32_emulate_rd8rn16rm0_rwflags,
- REGS(0, 0, NOSPPC, 0, NOSPPC)),
-
-
- /* ??? 1111 1010 1xxx xxxx 1111 xxxx 0x11 xxxx */
- DECODE_REJECT (0xff80f0b0, 0xfa80f030),
- /* ??? 1111 1010 1x11 xxxx 1111 xxxx 0xxx xxxx */
- DECODE_REJECT (0xffb0f080, 0xfab0f000),
-
- /* SADD16 1111 1010 1001 xxxx 1111 xxxx 0000 xxxx */
- /* SASX 1111 1010 1010 xxxx 1111 xxxx 0000 xxxx */
- /* SSAX 1111 1010 1110 xxxx 1111 xxxx 0000 xxxx */
- /* SSUB16 1111 1010 1101 xxxx 1111 xxxx 0000 xxxx */
- /* SADD8 1111 1010 1000 xxxx 1111 xxxx 0000 xxxx */
- /* SSUB8 1111 1010 1100 xxxx 1111 xxxx 0000 xxxx */
-
- /* QADD16 1111 1010 1001 xxxx 1111 xxxx 0001 xxxx */
- /* QASX 1111 1010 1010 xxxx 1111 xxxx 0001 xxxx */
- /* QSAX 1111 1010 1110 xxxx 1111 xxxx 0001 xxxx */
- /* QSUB16 1111 1010 1101 xxxx 1111 xxxx 0001 xxxx */
- /* QADD8 1111 1010 1000 xxxx 1111 xxxx 0001 xxxx */
- /* QSUB8 1111 1010 1100 xxxx 1111 xxxx 0001 xxxx */
-
- /* SHADD16 1111 1010 1001 xxxx 1111 xxxx 0010 xxxx */
- /* SHASX 1111 1010 1010 xxxx 1111 xxxx 0010 xxxx */
- /* SHSAX 1111 1010 1110 xxxx 1111 xxxx 0010 xxxx */
- /* SHSUB16 1111 1010 1101 xxxx 1111 xxxx 0010 xxxx */
- /* SHADD8 1111 1010 1000 xxxx 1111 xxxx 0010 xxxx */
- /* SHSUB8 1111 1010 1100 xxxx 1111 xxxx 0010 xxxx */
-
- /* UADD16 1111 1010 1001 xxxx 1111 xxxx 0100 xxxx */
- /* UASX 1111 1010 1010 xxxx 1111 xxxx 0100 xxxx */
- /* USAX 1111 1010 1110 xxxx 1111 xxxx 0100 xxxx */
- /* USUB16 1111 1010 1101 xxxx 1111 xxxx 0100 xxxx */
- /* UADD8 1111 1010 1000 xxxx 1111 xxxx 0100 xxxx */
- /* USUB8 1111 1010 1100 xxxx 1111 xxxx 0100 xxxx */
-
- /* UQADD16 1111 1010 1001 xxxx 1111 xxxx 0101 xxxx */
- /* UQASX 1111 1010 1010 xxxx 1111 xxxx 0101 xxxx */
- /* UQSAX 1111 1010 1110 xxxx 1111 xxxx 0101 xxxx */
- /* UQSUB16 1111 1010 1101 xxxx 1111 xxxx 0101 xxxx */
- /* UQADD8 1111 1010 1000 xxxx 1111 xxxx 0101 xxxx */
- /* UQSUB8 1111 1010 1100 xxxx 1111 xxxx 0101 xxxx */
-
- /* UHADD16 1111 1010 1001 xxxx 1111 xxxx 0110 xxxx */
- /* UHASX 1111 1010 1010 xxxx 1111 xxxx 0110 xxxx */
- /* UHSAX 1111 1010 1110 xxxx 1111 xxxx 0110 xxxx */
- /* UHSUB16 1111 1010 1101 xxxx 1111 xxxx 0110 xxxx */
- /* UHADD8 1111 1010 1000 xxxx 1111 xxxx 0110 xxxx */
- /* UHSUB8 1111 1010 1100 xxxx 1111 xxxx 0110 xxxx */
- DECODE_OR (0xff80f080, 0xfa80f000),
-
- /* SXTAH 1111 1010 0000 xxxx 1111 xxxx 1xxx xxxx */
- /* UXTAH 1111 1010 0001 xxxx 1111 xxxx 1xxx xxxx */
- /* SXTAB16 1111 1010 0010 xxxx 1111 xxxx 1xxx xxxx */
- /* UXTAB16 1111 1010 0011 xxxx 1111 xxxx 1xxx xxxx */
- /* SXTAB 1111 1010 0100 xxxx 1111 xxxx 1xxx xxxx */
- /* UXTAB 1111 1010 0101 xxxx 1111 xxxx 1xxx xxxx */
- DECODE_OR (0xff80f080, 0xfa00f080),
-
- /* QADD 1111 1010 1000 xxxx 1111 xxxx 1000 xxxx */
- /* QDADD 1111 1010 1000 xxxx 1111 xxxx 1001 xxxx */
- /* QSUB 1111 1010 1000 xxxx 1111 xxxx 1010 xxxx */
- /* QDSUB 1111 1010 1000 xxxx 1111 xxxx 1011 xxxx */
- DECODE_OR (0xfff0f0c0, 0xfa80f080),
-
- /* SEL 1111 1010 1010 xxxx 1111 xxxx 1000 xxxx */
- DECODE_OR (0xfff0f0f0, 0xfaa0f080),
-
- /* LSL 1111 1010 000x xxxx 1111 xxxx 0000 xxxx */
- /* LSR 1111 1010 001x xxxx 1111 xxxx 0000 xxxx */
- /* ASR 1111 1010 010x xxxx 1111 xxxx 0000 xxxx */
- /* ROR 1111 1010 011x xxxx 1111 xxxx 0000 xxxx */
- DECODE_EMULATEX (0xff80f0f0, 0xfa00f000, t32_emulate_rd8rn16rm0_rwflags,
- REGS(NOSPPC, 0, NOSPPC, 0, NOSPPC)),
-
- /* CLZ 1111 1010 1010 xxxx 1111 xxxx 1000 xxxx */
- DECODE_OR (0xfff0f0f0, 0xfab0f080),
-
- /* REV 1111 1010 1001 xxxx 1111 xxxx 1000 xxxx */
- /* REV16 1111 1010 1001 xxxx 1111 xxxx 1001 xxxx */
- /* RBIT 1111 1010 1001 xxxx 1111 xxxx 1010 xxxx */
- /* REVSH 1111 1010 1001 xxxx 1111 xxxx 1011 xxxx */
- DECODE_EMULATEX (0xfff0f0c0, 0xfa90f080, t32_emulate_rd8rn16_noflags,
- REGS(NOSPPC, 0, NOSPPC, 0, SAMEAS16)),
-
- /* Other unallocated instructions... */
- DECODE_END
-};
-
-static const union decode_item t32_table_1111_1011_0[] = {
- /* Multiply, multiply accumulate, and absolute difference */
-
- /* ??? 1111 1011 0000 xxxx 1111 xxxx 0001 xxxx */
- DECODE_REJECT (0xfff0f0f0, 0xfb00f010),
- /* ??? 1111 1011 0111 xxxx 1111 xxxx 0001 xxxx */
- DECODE_REJECT (0xfff0f0f0, 0xfb70f010),
-
- /* SMULxy 1111 1011 0001 xxxx 1111 xxxx 00xx xxxx */
- DECODE_OR (0xfff0f0c0, 0xfb10f000),
- /* MUL 1111 1011 0000 xxxx 1111 xxxx 0000 xxxx */
- /* SMUAD{X} 1111 1011 0010 xxxx 1111 xxxx 000x xxxx */
- /* SMULWy 1111 1011 0011 xxxx 1111 xxxx 000x xxxx */
- /* SMUSD{X} 1111 1011 0100 xxxx 1111 xxxx 000x xxxx */
- /* SMMUL{R} 1111 1011 0101 xxxx 1111 xxxx 000x xxxx */
- /* USAD8 1111 1011 0111 xxxx 1111 xxxx 0000 xxxx */
- DECODE_EMULATEX (0xff80f0e0, 0xfb00f000, t32_emulate_rd8rn16rm0_rwflags,
- REGS(NOSPPC, 0, NOSPPC, 0, NOSPPC)),
-
- /* ??? 1111 1011 0111 xxxx xxxx xxxx 0001 xxxx */
- DECODE_REJECT (0xfff000f0, 0xfb700010),
-
- /* SMLAxy 1111 1011 0001 xxxx xxxx xxxx 00xx xxxx */
- DECODE_OR (0xfff000c0, 0xfb100000),
- /* MLA 1111 1011 0000 xxxx xxxx xxxx 0000 xxxx */
- /* MLS 1111 1011 0000 xxxx xxxx xxxx 0001 xxxx */
- /* SMLAD{X} 1111 1011 0010 xxxx xxxx xxxx 000x xxxx */
- /* SMLAWy 1111 1011 0011 xxxx xxxx xxxx 000x xxxx */
- /* SMLSD{X} 1111 1011 0100 xxxx xxxx xxxx 000x xxxx */
- /* SMMLA{R} 1111 1011 0101 xxxx xxxx xxxx 000x xxxx */
- /* SMMLS{R} 1111 1011 0110 xxxx xxxx xxxx 000x xxxx */
- /* USADA8 1111 1011 0111 xxxx xxxx xxxx 0000 xxxx */
- DECODE_EMULATEX (0xff8000c0, 0xfb000000, t32_emulate_rd8rn16rm0ra12_noflags,
- REGS(NOSPPC, NOSPPCX, NOSPPC, 0, NOSPPC)),
-
- /* Other unallocated instructions... */
- DECODE_END
-};
-
-static const union decode_item t32_table_1111_1011_1[] = {
- /* Long multiply, long multiply accumulate, and divide */
-
- /* UMAAL 1111 1011 1110 xxxx xxxx xxxx 0110 xxxx */
- DECODE_OR (0xfff000f0, 0xfbe00060),
- /* SMLALxy 1111 1011 1100 xxxx xxxx xxxx 10xx xxxx */
- DECODE_OR (0xfff000c0, 0xfbc00080),
- /* SMLALD{X} 1111 1011 1100 xxxx xxxx xxxx 110x xxxx */
- /* SMLSLD{X} 1111 1011 1101 xxxx xxxx xxxx 110x xxxx */
- DECODE_OR (0xffe000e0, 0xfbc000c0),
- /* SMULL 1111 1011 1000 xxxx xxxx xxxx 0000 xxxx */
- /* UMULL 1111 1011 1010 xxxx xxxx xxxx 0000 xxxx */
- /* SMLAL 1111 1011 1100 xxxx xxxx xxxx 0000 xxxx */
- /* UMLAL 1111 1011 1110 xxxx xxxx xxxx 0000 xxxx */
- DECODE_EMULATEX (0xff9000f0, 0xfb800000, t32_emulate_rdlo12rdhi8rn16rm0_noflags,
- REGS(NOSPPC, NOSPPC, NOSPPC, 0, NOSPPC)),
-
- /* SDIV 1111 1011 1001 xxxx xxxx xxxx 1111 xxxx */
- /* UDIV 1111 1011 1011 xxxx xxxx xxxx 1111 xxxx */
- /* Other unallocated instructions... */
- DECODE_END
-};
-
-const union decode_item kprobe_decode_thumb32_table[] = {
-
- /*
- * Load/store multiple instructions
- * 1110 100x x0xx xxxx xxxx xxxx xxxx xxxx
- */
- DECODE_TABLE (0xfe400000, 0xe8000000, t32_table_1110_100x_x0xx),
-
- /*
- * Load/store dual, load/store exclusive, table branch
- * 1110 100x x1xx xxxx xxxx xxxx xxxx xxxx
- */
- DECODE_TABLE (0xfe400000, 0xe8400000, t32_table_1110_100x_x1xx),
-
- /*
- * Data-processing (shifted register)
- * 1110 101x xxxx xxxx xxxx xxxx xxxx xxxx
- */
- DECODE_TABLE (0xfe000000, 0xea000000, t32_table_1110_101x),
-
- /*
- * Coprocessor instructions
- * 1110 11xx xxxx xxxx xxxx xxxx xxxx xxxx
- */
- DECODE_REJECT (0xfc000000, 0xec000000),
-
- /*
- * Data-processing (modified immediate)
- * 1111 0x0x xxxx xxxx 0xxx xxxx xxxx xxxx
- */
- DECODE_TABLE (0xfa008000, 0xf0000000, t32_table_1111_0x0x___0),
-
- /*
- * Data-processing (plain binary immediate)
- * 1111 0x1x xxxx xxxx 0xxx xxxx xxxx xxxx
- */
- DECODE_TABLE (0xfa008000, 0xf2000000, t32_table_1111_0x1x___0),
-
- /*
- * Branches and miscellaneous control
- * 1111 0xxx xxxx xxxx 1xxx xxxx xxxx xxxx
- */
- DECODE_TABLE (0xf8008000, 0xf0008000, t32_table_1111_0xxx___1),
-
- /*
- * Advanced SIMD element or structure load/store instructions
- * 1111 1001 xxx0 xxxx xxxx xxxx xxxx xxxx
- */
- DECODE_REJECT (0xff100000, 0xf9000000),
-
- /*
- * Memory hints
- * 1111 100x x0x1 xxxx 1111 xxxx xxxx xxxx
- */
- DECODE_TABLE (0xfe50f000, 0xf810f000, t32_table_1111_100x_x0x1__1111),
-
- /*
- * Store single data item
- * 1111 1000 xxx0 xxxx xxxx xxxx xxxx xxxx
- * Load single data items
- * 1111 100x xxx1 xxxx xxxx xxxx xxxx xxxx
- */
- DECODE_TABLE (0xfe000000, 0xf8000000, t32_table_1111_100x),
-
- /*
- * Data-processing (register)
- * 1111 1010 xxxx xxxx 1111 xxxx xxxx xxxx
- */
- DECODE_TABLE (0xff00f000, 0xfa00f000, t32_table_1111_1010___1111),
-
- /*
- * Multiply, multiply accumulate, and absolute difference
- * 1111 1011 0xxx xxxx xxxx xxxx xxxx xxxx
- */
- DECODE_TABLE (0xff800000, 0xfb000000, t32_table_1111_1011_0),
-
- /*
- * Long multiply, long multiply accumulate, and divide
- * 1111 1011 1xxx xxxx xxxx xxxx xxxx xxxx
- */
- DECODE_TABLE (0xff800000, 0xfb800000, t32_table_1111_1011_1),
-
- /*
- * Coprocessor instructions
- * 1111 11xx xxxx xxxx xxxx xxxx xxxx xxxx
- */
- DECODE_END
-};
-#ifdef CONFIG_ARM_KPROBES_TEST_MODULE
-EXPORT_SYMBOL_GPL(kprobe_decode_thumb32_table);
-#endif
-
-static void __kprobes
+void __kprobes
t16_simulate_bxblx(struct kprobe *p, struct pt_regs *regs)
{
kprobe_opcode_t insn = p->opcode;
@@ -962,7 +334,7 @@ t16_simulate_bxblx(struct kprobe *p, struct pt_regs *regs)
bx_write_pc(rmv, regs);
}
-static void __kprobes
+void __kprobes
t16_simulate_ldr_literal(struct kprobe *p, struct pt_regs *regs)
{
kprobe_opcode_t insn = p->opcode;
@@ -972,7 +344,7 @@ t16_simulate_ldr_literal(struct kprobe *p, struct pt_regs *regs)
regs->uregs[rt] = base[index];
}
-static void __kprobes
+void __kprobes
t16_simulate_ldrstr_sp_relative(struct kprobe *p, struct pt_regs *regs)
{
kprobe_opcode_t insn = p->opcode;
@@ -985,7 +357,7 @@ t16_simulate_ldrstr_sp_relative(struct kprobe *p, struct pt_regs *regs)
base[index] = regs->uregs[rt];
}
-static void __kprobes
+void __kprobes
t16_simulate_reladr(struct kprobe *p, struct pt_regs *regs)
{
kprobe_opcode_t insn = p->opcode;
@@ -996,7 +368,7 @@ t16_simulate_reladr(struct kprobe *p, struct pt_regs *regs)
regs->uregs[rt] = base + offset * 4;
}
-static void __kprobes
+void __kprobes
t16_simulate_add_sp_imm(struct kprobe *p, struct pt_regs *regs)
{
kprobe_opcode_t insn = p->opcode;
@@ -1007,7 +379,7 @@ t16_simulate_add_sp_imm(struct kprobe *p, struct pt_regs *regs)
regs->ARM_sp += imm * 4;
}
-static void __kprobes
+void __kprobes
t16_simulate_cbz(struct kprobe *p, struct pt_regs *regs)
{
kprobe_opcode_t insn = p->opcode;
@@ -1021,7 +393,7 @@ t16_simulate_cbz(struct kprobe *p, struct pt_regs *regs)
}
}
-static void __kprobes
+void __kprobes
t16_simulate_it(struct kprobe *p, struct pt_regs *regs)
{
/*
@@ -1038,21 +410,21 @@ t16_simulate_it(struct kprobe *p, struct pt_regs *regs)
regs->ARM_cpsr = cpsr;
}
-static void __kprobes
+void __kprobes
t16_singlestep_it(struct kprobe *p, struct pt_regs *regs)
{
regs->ARM_pc += 2;
t16_simulate_it(p, regs);
}
-static enum kprobe_insn __kprobes
+enum kprobe_insn __kprobes
t16_decode_it(kprobe_opcode_t insn, struct arch_specific_insn *asi)
{
asi->insn_singlestep = t16_singlestep_it;
return INSN_GOOD_NO_SLOT;
}
-static void __kprobes
+void __kprobes
t16_simulate_cond_branch(struct kprobe *p, struct pt_regs *regs)
{
kprobe_opcode_t insn = p->opcode;
@@ -1062,7 +434,7 @@ t16_simulate_cond_branch(struct kprobe *p, struct pt_regs *regs)
regs->ARM_pc = pc + (offset * 2);
}
-static enum kprobe_insn __kprobes
+enum kprobe_insn __kprobes
t16_decode_cond_branch(kprobe_opcode_t insn, struct arch_specific_insn *asi)
{
int cc = (insn >> 8) & 0xf;
@@ -1071,7 +443,7 @@ t16_decode_cond_branch(kprobe_opcode_t insn, struct arch_specific_insn *asi)
return INSN_GOOD_NO_SLOT;
}
-static void __kprobes
+void __kprobes
t16_simulate_branch(struct kprobe *p, struct pt_regs *regs)
{
kprobe_opcode_t insn = p->opcode;
@@ -1103,13 +475,13 @@ t16_emulate_loregs(struct kprobe *p, struct pt_regs *regs)
return (oldcpsr & ~APSR_MASK) | (newcpsr & APSR_MASK);
}
-static void __kprobes
+void __kprobes
t16_emulate_loregs_rwflags(struct kprobe *p, struct pt_regs *regs)
{
regs->ARM_cpsr = t16_emulate_loregs(p, regs);
}
-static void __kprobes
+void __kprobes
t16_emulate_loregs_noitrwflags(struct kprobe *p, struct pt_regs *regs)
{
unsigned long cpsr = t16_emulate_loregs(p, regs);
@@ -1117,7 +489,7 @@ t16_emulate_loregs_noitrwflags(struct kprobe *p, struct pt_regs *regs)
regs->ARM_cpsr = cpsr;
}
-static void __kprobes
+void __kprobes
t16_emulate_hiregs(struct kprobe *p, struct pt_regs *regs)
{
kprobe_opcode_t insn = p->opcode;
@@ -1148,7 +520,7 @@ t16_emulate_hiregs(struct kprobe *p, struct pt_regs *regs)
regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK);
}
-static enum kprobe_insn __kprobes
+enum kprobe_insn __kprobes
t16_decode_hiregs(kprobe_opcode_t insn, struct arch_specific_insn *asi)
{
insn &= ~0x00ff;
@@ -1158,7 +530,7 @@ t16_decode_hiregs(kprobe_opcode_t insn, struct arch_specific_insn *asi)
return INSN_GOOD;
}
-static void __kprobes
+void __kprobes
t16_emulate_push(struct kprobe *p, struct pt_regs *regs)
{
__asm__ __volatile__ (
@@ -1174,7 +546,7 @@ t16_emulate_push(struct kprobe *p, struct pt_regs *regs)
);
}
-static enum kprobe_insn __kprobes
+enum kprobe_insn __kprobes
t16_decode_push(kprobe_opcode_t insn, struct arch_specific_insn *asi)
{
/*
@@ -1188,7 +560,7 @@ t16_decode_push(kprobe_opcode_t insn, struct arch_specific_insn *asi)
return INSN_GOOD;
}
-static void __kprobes
+void __kprobes
t16_emulate_pop_nopc(struct kprobe *p, struct pt_regs *regs)
{
__asm__ __volatile__ (
@@ -1204,7 +576,7 @@ t16_emulate_pop_nopc(struct kprobe *p, struct pt_regs *regs)
);
}
-static void __kprobes
+void __kprobes
t16_emulate_pop_pc(struct kprobe *p, struct pt_regs *regs)
{
register unsigned long pc asm("r8");
@@ -1224,7 +596,7 @@ t16_emulate_pop_pc(struct kprobe *p, struct pt_regs *regs)
bx_write_pc(pc, regs);
}
-static enum kprobe_insn __kprobes
+enum kprobe_insn __kprobes
t16_decode_pop(kprobe_opcode_t insn, struct arch_specific_insn *asi)
{
/*
@@ -1238,232 +610,3 @@ t16_decode_pop(kprobe_opcode_t insn, struct arch_specific_insn *asi)
: t16_emulate_pop_nopc;
return INSN_GOOD;
}
-
-static const union decode_item t16_table_1011[] = {
- /* Miscellaneous 16-bit instructions */
-
- /* ADD (SP plus immediate) 1011 0000 0xxx xxxx */
- /* SUB (SP minus immediate) 1011 0000 1xxx xxxx */
- DECODE_SIMULATE (0xff00, 0xb000, t16_simulate_add_sp_imm),
-
- /* CBZ 1011 00x1 xxxx xxxx */
- /* CBNZ 1011 10x1 xxxx xxxx */
- DECODE_SIMULATE (0xf500, 0xb100, t16_simulate_cbz),
-
- /* SXTH 1011 0010 00xx xxxx */
- /* SXTB 1011 0010 01xx xxxx */
- /* UXTH 1011 0010 10xx xxxx */
- /* UXTB 1011 0010 11xx xxxx */
- /* REV 1011 1010 00xx xxxx */
- /* REV16 1011 1010 01xx xxxx */
- /* ??? 1011 1010 10xx xxxx */
- /* REVSH 1011 1010 11xx xxxx */
- DECODE_REJECT (0xffc0, 0xba80),
- DECODE_EMULATE (0xf500, 0xb000, t16_emulate_loregs_rwflags),
-
- /* PUSH 1011 010x xxxx xxxx */
- DECODE_CUSTOM (0xfe00, 0xb400, t16_decode_push),
- /* POP 1011 110x xxxx xxxx */
- DECODE_CUSTOM (0xfe00, 0xbc00, t16_decode_pop),
-
- /*
- * If-Then, and hints
- * 1011 1111 xxxx xxxx
- */
-
- /* YIELD 1011 1111 0001 0000 */
- DECODE_OR (0xffff, 0xbf10),
- /* SEV 1011 1111 0100 0000 */
- DECODE_EMULATE (0xffff, 0xbf40, kprobe_emulate_none),
- /* NOP 1011 1111 0000 0000 */
- /* WFE 1011 1111 0010 0000 */
- /* WFI 1011 1111 0011 0000 */
- DECODE_SIMULATE (0xffcf, 0xbf00, kprobe_simulate_nop),
- /* Unassigned hints 1011 1111 xxxx 0000 */
- DECODE_REJECT (0xff0f, 0xbf00),
- /* IT 1011 1111 xxxx xxxx */
- DECODE_CUSTOM (0xff00, 0xbf00, t16_decode_it),
-
- /* SETEND 1011 0110 010x xxxx */
- /* CPS 1011 0110 011x xxxx */
- /* BKPT 1011 1110 xxxx xxxx */
- /* And unallocated instructions... */
- DECODE_END
-};
-
-const union decode_item kprobe_decode_thumb16_table[] = {
-
- /*
- * Shift (immediate), add, subtract, move, and compare
- * 00xx xxxx xxxx xxxx
- */
-
- /* CMP (immediate) 0010 1xxx xxxx xxxx */
- DECODE_EMULATE (0xf800, 0x2800, t16_emulate_loregs_rwflags),
-
- /* ADD (register) 0001 100x xxxx xxxx */
- /* SUB (register) 0001 101x xxxx xxxx */
- /* LSL (immediate) 0000 0xxx xxxx xxxx */
- /* LSR (immediate) 0000 1xxx xxxx xxxx */
- /* ASR (immediate) 0001 0xxx xxxx xxxx */
- /* ADD (immediate, Thumb) 0001 110x xxxx xxxx */
- /* SUB (immediate, Thumb) 0001 111x xxxx xxxx */
- /* MOV (immediate) 0010 0xxx xxxx xxxx */
- /* ADD (immediate, Thumb) 0011 0xxx xxxx xxxx */
- /* SUB (immediate, Thumb) 0011 1xxx xxxx xxxx */
- DECODE_EMULATE (0xc000, 0x0000, t16_emulate_loregs_noitrwflags),
-
- /*
- * 16-bit Thumb data-processing instructions
- * 0100 00xx xxxx xxxx
- */
-
- /* TST (register) 0100 0010 00xx xxxx */
- DECODE_EMULATE (0xffc0, 0x4200, t16_emulate_loregs_rwflags),
- /* CMP (register) 0100 0010 10xx xxxx */
- /* CMN (register) 0100 0010 11xx xxxx */
- DECODE_EMULATE (0xff80, 0x4280, t16_emulate_loregs_rwflags),
- /* AND (register) 0100 0000 00xx xxxx */
- /* EOR (register) 0100 0000 01xx xxxx */
- /* LSL (register) 0100 0000 10xx xxxx */
- /* LSR (register) 0100 0000 11xx xxxx */
- /* ASR (register) 0100 0001 00xx xxxx */
- /* ADC (register) 0100 0001 01xx xxxx */
- /* SBC (register) 0100 0001 10xx xxxx */
- /* ROR (register) 0100 0001 11xx xxxx */
- /* RSB (immediate) 0100 0010 01xx xxxx */
- /* ORR (register) 0100 0011 00xx xxxx */
- /* MUL 0100 0011 00xx xxxx */
- /* BIC (register) 0100 0011 10xx xxxx */
- /* MVN (register) 0100 0011 10xx xxxx */
- DECODE_EMULATE (0xfc00, 0x4000, t16_emulate_loregs_noitrwflags),
-
- /*
- * Special data instructions and branch and exchange
- * 0100 01xx xxxx xxxx
- */
-
- /* BLX pc 0100 0111 1111 1xxx */
- DECODE_REJECT (0xfff8, 0x47f8),
-
- /* BX (register) 0100 0111 0xxx xxxx */
- /* BLX (register) 0100 0111 1xxx xxxx */
- DECODE_SIMULATE (0xff00, 0x4700, t16_simulate_bxblx),
-
- /* ADD pc, pc 0100 0100 1111 1111 */
- DECODE_REJECT (0xffff, 0x44ff),
-
- /* ADD (register) 0100 0100 xxxx xxxx */
- /* CMP (register) 0100 0101 xxxx xxxx */
- /* MOV (register) 0100 0110 xxxx xxxx */
- DECODE_CUSTOM (0xfc00, 0x4400, t16_decode_hiregs),
-
- /*
- * Load from Literal Pool
- * LDR (literal) 0100 1xxx xxxx xxxx
- */
- DECODE_SIMULATE (0xf800, 0x4800, t16_simulate_ldr_literal),
-
- /*
- * 16-bit Thumb Load/store instructions
- * 0101 xxxx xxxx xxxx
- * 011x xxxx xxxx xxxx
- * 100x xxxx xxxx xxxx
- */
-
- /* STR (register) 0101 000x xxxx xxxx */
- /* STRH (register) 0101 001x xxxx xxxx */
- /* STRB (register) 0101 010x xxxx xxxx */
- /* LDRSB (register) 0101 011x xxxx xxxx */
- /* LDR (register) 0101 100x xxxx xxxx */
- /* LDRH (register) 0101 101x xxxx xxxx */
- /* LDRB (register) 0101 110x xxxx xxxx */
- /* LDRSH (register) 0101 111x xxxx xxxx */
- /* STR (immediate, Thumb) 0110 0xxx xxxx xxxx */
- /* LDR (immediate, Thumb) 0110 1xxx xxxx xxxx */
- /* STRB (immediate, Thumb) 0111 0xxx xxxx xxxx */
- /* LDRB (immediate, Thumb) 0111 1xxx xxxx xxxx */
- DECODE_EMULATE (0xc000, 0x4000, t16_emulate_loregs_rwflags),
- /* STRH (immediate, Thumb) 1000 0xxx xxxx xxxx */
- /* LDRH (immediate, Thumb) 1000 1xxx xxxx xxxx */
- DECODE_EMULATE (0xf000, 0x8000, t16_emulate_loregs_rwflags),
- /* STR (immediate, Thumb) 1001 0xxx xxxx xxxx */
- /* LDR (immediate, Thumb) 1001 1xxx xxxx xxxx */
- DECODE_SIMULATE (0xf000, 0x9000, t16_simulate_ldrstr_sp_relative),
-
- /*
- * Generate PC-/SP-relative address
- * ADR (literal) 1010 0xxx xxxx xxxx
- * ADD (SP plus immediate) 1010 1xxx xxxx xxxx
- */
- DECODE_SIMULATE (0xf000, 0xa000, t16_simulate_reladr),
-
- /*
- * Miscellaneous 16-bit instructions
- * 1011 xxxx xxxx xxxx
- */
- DECODE_TABLE (0xf000, 0xb000, t16_table_1011),
-
- /* STM 1100 0xxx xxxx xxxx */
- /* LDM 1100 1xxx xxxx xxxx */
- DECODE_EMULATE (0xf000, 0xc000, t16_emulate_loregs_rwflags),
-
- /*
- * Conditional branch, and Supervisor Call
- */
-
- /* Permanently UNDEFINED 1101 1110 xxxx xxxx */
- /* SVC 1101 1111 xxxx xxxx */
- DECODE_REJECT (0xfe00, 0xde00),
-
- /* Conditional branch 1101 xxxx xxxx xxxx */
- DECODE_CUSTOM (0xf000, 0xd000, t16_decode_cond_branch),
-
- /*
- * Unconditional branch
- * B 1110 0xxx xxxx xxxx
- */
- DECODE_SIMULATE (0xf800, 0xe000, t16_simulate_branch),
-
- DECODE_END
-};
-#ifdef CONFIG_ARM_KPROBES_TEST_MODULE
-EXPORT_SYMBOL_GPL(kprobe_decode_thumb16_table);
-#endif
-
-static unsigned long __kprobes thumb_check_cc(unsigned long cpsr)
-{
- if (unlikely(in_it_block(cpsr)))
- return kprobe_condition_checks[current_cond(cpsr)](cpsr);
- return true;
-}
-
-static void __kprobes thumb16_singlestep(struct kprobe *p, struct pt_regs *regs)
-{
- regs->ARM_pc += 2;
- p->ainsn.insn_handler(p, regs);
- regs->ARM_cpsr = it_advance(regs->ARM_cpsr);
-}
-
-static void __kprobes thumb32_singlestep(struct kprobe *p, struct pt_regs *regs)
-{
- regs->ARM_pc += 4;
- p->ainsn.insn_handler(p, regs);
- regs->ARM_cpsr = it_advance(regs->ARM_cpsr);
-}
-
-enum kprobe_insn __kprobes
-thumb16_kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi)
-{
- asi->insn_singlestep = thumb16_singlestep;
- asi->insn_check_cc = thumb_check_cc;
- return kprobe_decode_insn(insn, asi, kprobe_decode_thumb16_table, true);
-}
-
-enum kprobe_insn __kprobes
-thumb32_kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi)
-{
- asi->insn_singlestep = thumb32_singlestep;
- asi->insn_check_cc = thumb_check_cc;
- return kprobe_decode_insn(insn, asi, kprobe_decode_thumb32_table, true);
-}
diff --git a/arch/arm/kernel/kprobes-thumb.c b/arch/arm/kernel/probes-thumb.c
similarity index 67%
copy from arch/arm/kernel/kprobes-thumb.c
copy to arch/arm/kernel/probes-thumb.c
index 6123daf..65fbb4a 100644
--- a/arch/arm/kernel/kprobes-thumb.c
+++ b/arch/arm/kernel/probes-thumb.c
@@ -13,308 +13,7 @@
#include <linux/module.h>
#include "kprobes.h"
-
-
-/*
- * True if current instruction is in an IT block.
- */
-#define in_it_block(cpsr) ((cpsr & 0x06000c00) != 0x00000000)
-
-/*
- * Return the condition code to check for the currently executing instruction.
- * This is in ITSTATE<7:4> which is in CPSR<15:12> but is only valid if
- * in_it_block returns true.
- */
-#define current_cond(cpsr) ((cpsr >> 12) & 0xf)
-
-/*
- * Return the PC value for a probe in thumb code.
- * This is the address of the probed instruction plus 4.
- * We subtract one because the address will have bit zero set to indicate
- * a pointer to thumb code.
- */
-static inline unsigned long __kprobes thumb_probe_pc(struct kprobe *p)
-{
- return (unsigned long)p->addr - 1 + 4;
-}
-
-static void __kprobes
-t32_simulate_table_branch(struct kprobe *p, struct pt_regs *regs)
-{
- kprobe_opcode_t insn = p->opcode;
- unsigned long pc = thumb_probe_pc(p);
- int rn = (insn >> 16) & 0xf;
- int rm = insn & 0xf;
-
- unsigned long rnv = (rn == 15) ? pc : regs->uregs[rn];
- unsigned long rmv = regs->uregs[rm];
- unsigned int halfwords;
-
- if (insn & 0x10) /* TBH */
- halfwords = ((u16 *)rnv)[rmv];
- else /* TBB */
- halfwords = ((u8 *)rnv)[rmv];
-
- regs->ARM_pc = pc + 2 * halfwords;
-}
-
-static void __kprobes
-t32_simulate_mrs(struct kprobe *p, struct pt_regs *regs)
-{
- kprobe_opcode_t insn = p->opcode;
- int rd = (insn >> 8) & 0xf;
- unsigned long mask = 0xf8ff03df; /* Mask out execution state */
- regs->uregs[rd] = regs->ARM_cpsr & mask;
-}
-
-static void __kprobes
-t32_simulate_cond_branch(struct kprobe *p, struct pt_regs *regs)
-{
- kprobe_opcode_t insn = p->opcode;
- unsigned long pc = thumb_probe_pc(p);
-
- long offset = insn & 0x7ff; /* imm11 */
- offset += (insn & 0x003f0000) >> 5; /* imm6 */
- offset += (insn & 0x00002000) << 4; /* J1 */
- offset += (insn & 0x00000800) << 7; /* J2 */
- offset -= (insn & 0x04000000) >> 7; /* Apply sign bit */
-
- regs->ARM_pc = pc + (offset * 2);
-}
-
-static enum kprobe_insn __kprobes
-t32_decode_cond_branch(kprobe_opcode_t insn, struct arch_specific_insn *asi)
-{
- int cc = (insn >> 22) & 0xf;
- asi->insn_check_cc = kprobe_condition_checks[cc];
- asi->insn_handler = t32_simulate_cond_branch;
- return INSN_GOOD_NO_SLOT;
-}
-
-static void __kprobes
-t32_simulate_branch(struct kprobe *p, struct pt_regs *regs)
-{
- kprobe_opcode_t insn = p->opcode;
- unsigned long pc = thumb_probe_pc(p);
-
- long offset = insn & 0x7ff; /* imm11 */
- offset += (insn & 0x03ff0000) >> 5; /* imm10 */
- offset += (insn & 0x00002000) << 9; /* J1 */
- offset += (insn & 0x00000800) << 10; /* J2 */
- if (insn & 0x04000000)
- offset -= 0x00800000; /* Apply sign bit */
- else
- offset ^= 0x00600000; /* Invert J1 and J2 */
-
- if (insn & (1 << 14)) {
- /* BL or BLX */
- regs->ARM_lr = (unsigned long)p->addr + 4;
- if (!(insn & (1 << 12))) {
- /* BLX so switch to ARM mode */
- regs->ARM_cpsr &= ~PSR_T_BIT;
- pc &= ~3;
- }
- }
-
- regs->ARM_pc = pc + (offset * 2);
-}
-
-static void __kprobes
-t32_simulate_ldr_literal(struct kprobe *p, struct pt_regs *regs)
-{
- kprobe_opcode_t insn = p->opcode;
- unsigned long addr = thumb_probe_pc(p) & ~3;
- int rt = (insn >> 12) & 0xf;
- unsigned long rtv;
-
- long offset = insn & 0xfff;
- if (insn & 0x00800000)
- addr += offset;
- else
- addr -= offset;
-
- if (insn & 0x00400000) {
- /* LDR */
- rtv = *(unsigned long *)addr;
- if (rt == 15) {
- bx_write_pc(rtv, regs);
- return;
- }
- } else if (insn & 0x00200000) {
- /* LDRH */
- if (insn & 0x01000000)
- rtv = *(s16 *)addr;
- else
- rtv = *(u16 *)addr;
- } else {
- /* LDRB */
- if (insn & 0x01000000)
- rtv = *(s8 *)addr;
- else
- rtv = *(u8 *)addr;
- }
-
- regs->uregs[rt] = rtv;
-}
-
-static enum kprobe_insn __kprobes
-t32_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi)
-{
- enum kprobe_insn ret = kprobe_decode_ldmstm(insn, asi);
-
- /* Fixup modified instruction to have halfwords in correct order...*/
- insn = asi->insn[0];
- ((u16 *)asi->insn)[0] = insn >> 16;
- ((u16 *)asi->insn)[1] = insn & 0xffff;
-
- return ret;
-}
-
-static void __kprobes
-t32_emulate_ldrdstrd(struct kprobe *p, struct pt_regs *regs)
-{
- kprobe_opcode_t insn = p->opcode;
- unsigned long pc = thumb_probe_pc(p) & ~3;
- int rt1 = (insn >> 12) & 0xf;
- int rt2 = (insn >> 8) & 0xf;
- int rn = (insn >> 16) & 0xf;
-
- register unsigned long rt1v asm("r0") = regs->uregs[rt1];
- register unsigned long rt2v asm("r1") = regs->uregs[rt2];
- register unsigned long rnv asm("r2") = (rn == 15) ? pc
- : regs->uregs[rn];
-
- __asm__ __volatile__ (
- "blx %[fn]"
- : "=r" (rt1v), "=r" (rt2v), "=r" (rnv)
- : "0" (rt1v), "1" (rt2v), "2" (rnv), [fn] "r" (p->ainsn.insn_fn)
- : "lr", "memory", "cc"
- );
-
- if (rn != 15)
- regs->uregs[rn] = rnv; /* Writeback base register */
- regs->uregs[rt1] = rt1v;
- regs->uregs[rt2] = rt2v;
-}
-
-static void __kprobes
-t32_emulate_ldrstr(struct kprobe *p, struct pt_regs *regs)
-{
- kprobe_opcode_t insn = p->opcode;
- int rt = (insn >> 12) & 0xf;
- int rn = (insn >> 16) & 0xf;
- int rm = insn & 0xf;
-
- register unsigned long rtv asm("r0") = regs->uregs[rt];
- register unsigned long rnv asm("r2") = regs->uregs[rn];
- register unsigned long rmv asm("r3") = regs->uregs[rm];
-
- __asm__ __volatile__ (
- "blx %[fn]"
- : "=r" (rtv), "=r" (rnv)
- : "0" (rtv), "1" (rnv), "r" (rmv), [fn] "r" (p->ainsn.insn_fn)
- : "lr", "memory", "cc"
- );
-
- regs->uregs[rn] = rnv; /* Writeback base register */
- if (rt == 15) /* Can't be true for a STR as they aren't allowed */
- bx_write_pc(rtv, regs);
- else
- regs->uregs[rt] = rtv;
-}
-
-static void __kprobes
-t32_emulate_rd8rn16rm0_rwflags(struct kprobe *p, struct pt_regs *regs)
-{
- kprobe_opcode_t insn = p->opcode;
- int rd = (insn >> 8) & 0xf;
- int rn = (insn >> 16) & 0xf;
- int rm = insn & 0xf;
-
- register unsigned long rdv asm("r1") = regs->uregs[rd];
- register unsigned long rnv asm("r2") = regs->uregs[rn];
- register unsigned long rmv asm("r3") = regs->uregs[rm];
- unsigned long cpsr = regs->ARM_cpsr;
-
- __asm__ __volatile__ (
- "msr cpsr_fs, %[cpsr] \n\t"
- "blx %[fn] \n\t"
- "mrs %[cpsr], cpsr \n\t"
- : "=r" (rdv), [cpsr] "=r" (cpsr)
- : "0" (rdv), "r" (rnv), "r" (rmv),
- "1" (cpsr), [fn] "r" (p->ainsn.insn_fn)
- : "lr", "memory", "cc"
- );
-
- regs->uregs[rd] = rdv;
- regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK);
-}
-
-static void __kprobes
-t32_emulate_rd8pc16_noflags(struct kprobe *p, struct pt_regs *regs)
-{
- kprobe_opcode_t insn = p->opcode;
- unsigned long pc = thumb_probe_pc(p);
- int rd = (insn >> 8) & 0xf;
-
- register unsigned long rdv asm("r1") = regs->uregs[rd];
- register unsigned long rnv asm("r2") = pc & ~3;
-
- __asm__ __volatile__ (
- "blx %[fn]"
- : "=r" (rdv)
- : "0" (rdv), "r" (rnv), [fn] "r" (p->ainsn.insn_fn)
- : "lr", "memory", "cc"
- );
-
- regs->uregs[rd] = rdv;
-}
-
-static void __kprobes
-t32_emulate_rd8rn16_noflags(struct kprobe *p, struct pt_regs *regs)
-{
- kprobe_opcode_t insn = p->opcode;
- int rd = (insn >> 8) & 0xf;
- int rn = (insn >> 16) & 0xf;
-
- register unsigned long rdv asm("r1") = regs->uregs[rd];
- register unsigned long rnv asm("r2") = regs->uregs[rn];
-
- __asm__ __volatile__ (
- "blx %[fn]"
- : "=r" (rdv)
- : "0" (rdv), "r" (rnv), [fn] "r" (p->ainsn.insn_fn)
- : "lr", "memory", "cc"
- );
-
- regs->uregs[rd] = rdv;
-}
-
-static void __kprobes
-t32_emulate_rdlo12rdhi8rn16rm0_noflags(struct kprobe *p, struct pt_regs *regs)
-{
- kprobe_opcode_t insn = p->opcode;
- int rdlo = (insn >> 12) & 0xf;
- int rdhi = (insn >> 8) & 0xf;
- int rn = (insn >> 16) & 0xf;
- int rm = insn & 0xf;
-
- register unsigned long rdlov asm("r0") = regs->uregs[rdlo];
- register unsigned long rdhiv asm("r1") = regs->uregs[rdhi];
- register unsigned long rnv asm("r2") = regs->uregs[rn];
- register unsigned long rmv asm("r3") = regs->uregs[rm];
-
- __asm__ __volatile__ (
- "blx %[fn]"
- : "=r" (rdlov), "=r" (rdhiv)
- : "0" (rdlov), "1" (rdhiv), "r" (rnv), "r" (rmv),
- [fn] "r" (p->ainsn.insn_fn)
- : "lr", "memory", "cc"
- );
-
- regs->uregs[rdlo] = rdlov;
- regs->uregs[rdhi] = rdhiv;
-}
+#include "probes-thumb.h"
/* These emulation encodings are functionally equivalent... */
#define t32_emulate_rd8rn16rm0ra12_noflags \
@@ -948,297 +647,6 @@ const union decode_item kprobe_decode_thumb32_table[] = {
EXPORT_SYMBOL_GPL(kprobe_decode_thumb32_table);
#endif
-static void __kprobes
-t16_simulate_bxblx(struct kprobe *p, struct pt_regs *regs)
-{
- kprobe_opcode_t insn = p->opcode;
- unsigned long pc = thumb_probe_pc(p);
- int rm = (insn >> 3) & 0xf;
- unsigned long rmv = (rm == 15) ? pc : regs->uregs[rm];
-
- if (insn & (1 << 7)) /* BLX ? */
- regs->ARM_lr = (unsigned long)p->addr + 2;
-
- bx_write_pc(rmv, regs);
-}
-
-static void __kprobes
-t16_simulate_ldr_literal(struct kprobe *p, struct pt_regs *regs)
-{
- kprobe_opcode_t insn = p->opcode;
- unsigned long* base = (unsigned long *)(thumb_probe_pc(p) & ~3);
- long index = insn & 0xff;
- int rt = (insn >> 8) & 0x7;
- regs->uregs[rt] = base[index];
-}
-
-static void __kprobes
-t16_simulate_ldrstr_sp_relative(struct kprobe *p, struct pt_regs *regs)
-{
- kprobe_opcode_t insn = p->opcode;
- unsigned long* base = (unsigned long *)regs->ARM_sp;
- long index = insn & 0xff;
- int rt = (insn >> 8) & 0x7;
- if (insn & 0x800) /* LDR */
- regs->uregs[rt] = base[index];
- else /* STR */
- base[index] = regs->uregs[rt];
-}
-
-static void __kprobes
-t16_simulate_reladr(struct kprobe *p, struct pt_regs *regs)
-{
- kprobe_opcode_t insn = p->opcode;
- unsigned long base = (insn & 0x800) ? regs->ARM_sp
- : (thumb_probe_pc(p) & ~3);
- long offset = insn & 0xff;
- int rt = (insn >> 8) & 0x7;
- regs->uregs[rt] = base + offset * 4;
-}
-
-static void __kprobes
-t16_simulate_add_sp_imm(struct kprobe *p, struct pt_regs *regs)
-{
- kprobe_opcode_t insn = p->opcode;
- long imm = insn & 0x7f;
- if (insn & 0x80) /* SUB */
- regs->ARM_sp -= imm * 4;
- else /* ADD */
- regs->ARM_sp += imm * 4;
-}
-
-static void __kprobes
-t16_simulate_cbz(struct kprobe *p, struct pt_regs *regs)
-{
- kprobe_opcode_t insn = p->opcode;
- int rn = insn & 0x7;
- kprobe_opcode_t nonzero = regs->uregs[rn] ? insn : ~insn;
- if (nonzero & 0x800) {
- long i = insn & 0x200;
- long imm5 = insn & 0xf8;
- unsigned long pc = thumb_probe_pc(p);
- regs->ARM_pc = pc + (i >> 3) + (imm5 >> 2);
- }
-}
-
-static void __kprobes
-t16_simulate_it(struct kprobe *p, struct pt_regs *regs)
-{
- /*
- * The 8 IT state bits are split into two parts in CPSR:
- * ITSTATE<1:0> are in CPSR<26:25>
- * ITSTATE<7:2> are in CPSR<15:10>
- * The new IT state is in the lower byte of insn.
- */
- kprobe_opcode_t insn = p->opcode;
- unsigned long cpsr = regs->ARM_cpsr;
- cpsr &= ~PSR_IT_MASK;
- cpsr |= (insn & 0xfc) << 8;
- cpsr |= (insn & 0x03) << 25;
- regs->ARM_cpsr = cpsr;
-}
-
-static void __kprobes
-t16_singlestep_it(struct kprobe *p, struct pt_regs *regs)
-{
- regs->ARM_pc += 2;
- t16_simulate_it(p, regs);
-}
-
-static enum kprobe_insn __kprobes
-t16_decode_it(kprobe_opcode_t insn, struct arch_specific_insn *asi)
-{
- asi->insn_singlestep = t16_singlestep_it;
- return INSN_GOOD_NO_SLOT;
-}
-
-static void __kprobes
-t16_simulate_cond_branch(struct kprobe *p, struct pt_regs *regs)
-{
- kprobe_opcode_t insn = p->opcode;
- unsigned long pc = thumb_probe_pc(p);
- long offset = insn & 0x7f;
- offset -= insn & 0x80; /* Apply sign bit */
- regs->ARM_pc = pc + (offset * 2);
-}
-
-static enum kprobe_insn __kprobes
-t16_decode_cond_branch(kprobe_opcode_t insn, struct arch_specific_insn *asi)
-{
- int cc = (insn >> 8) & 0xf;
- asi->insn_check_cc = kprobe_condition_checks[cc];
- asi->insn_handler = t16_simulate_cond_branch;
- return INSN_GOOD_NO_SLOT;
-}
-
-static void __kprobes
-t16_simulate_branch(struct kprobe *p, struct pt_regs *regs)
-{
- kprobe_opcode_t insn = p->opcode;
- unsigned long pc = thumb_probe_pc(p);
- long offset = insn & 0x3ff;
- offset -= insn & 0x400; /* Apply sign bit */
- regs->ARM_pc = pc + (offset * 2);
-}
-
-static unsigned long __kprobes
-t16_emulate_loregs(struct kprobe *p, struct pt_regs *regs)
-{
- unsigned long oldcpsr = regs->ARM_cpsr;
- unsigned long newcpsr;
-
- __asm__ __volatile__ (
- "msr cpsr_fs, %[oldcpsr] \n\t"
- "ldmia %[regs], {r0-r7} \n\t"
- "blx %[fn] \n\t"
- "stmia %[regs], {r0-r7} \n\t"
- "mrs %[newcpsr], cpsr \n\t"
- : [newcpsr] "=r" (newcpsr)
- : [oldcpsr] "r" (oldcpsr), [regs] "r" (regs),
- [fn] "r" (p->ainsn.insn_fn)
- : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
- "lr", "memory", "cc"
- );
-
- return (oldcpsr & ~APSR_MASK) | (newcpsr & APSR_MASK);
-}
-
-static void __kprobes
-t16_emulate_loregs_rwflags(struct kprobe *p, struct pt_regs *regs)
-{
- regs->ARM_cpsr = t16_emulate_loregs(p, regs);
-}
-
-static void __kprobes
-t16_emulate_loregs_noitrwflags(struct kprobe *p, struct pt_regs *regs)
-{
- unsigned long cpsr = t16_emulate_loregs(p, regs);
- if (!in_it_block(cpsr))
- regs->ARM_cpsr = cpsr;
-}
-
-static void __kprobes
-t16_emulate_hiregs(struct kprobe *p, struct pt_regs *regs)
-{
- kprobe_opcode_t insn = p->opcode;
- unsigned long pc = thumb_probe_pc(p);
- int rdn = (insn & 0x7) | ((insn & 0x80) >> 4);
- int rm = (insn >> 3) & 0xf;
-
- register unsigned long rdnv asm("r1");
- register unsigned long rmv asm("r0");
- unsigned long cpsr = regs->ARM_cpsr;
-
- rdnv = (rdn == 15) ? pc : regs->uregs[rdn];
- rmv = (rm == 15) ? pc : regs->uregs[rm];
-
- __asm__ __volatile__ (
- "msr cpsr_fs, %[cpsr] \n\t"
- "blx %[fn] \n\t"
- "mrs %[cpsr], cpsr \n\t"
- : "=r" (rdnv), [cpsr] "=r" (cpsr)
- : "0" (rdnv), "r" (rmv), "1" (cpsr), [fn] "r" (p->ainsn.insn_fn)
- : "lr", "memory", "cc"
- );
-
- if (rdn == 15)
- rdnv &= ~1;
-
- regs->uregs[rdn] = rdnv;
- regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK);
-}
-
-static enum kprobe_insn __kprobes
-t16_decode_hiregs(kprobe_opcode_t insn, struct arch_specific_insn *asi)
-{
- insn &= ~0x00ff;
- insn |= 0x001; /* Set Rdn = R1 and Rm = R0 */
- ((u16 *)asi->insn)[0] = insn;
- asi->insn_handler = t16_emulate_hiregs;
- return INSN_GOOD;
-}
-
-static void __kprobes
-t16_emulate_push(struct kprobe *p, struct pt_regs *regs)
-{
- __asm__ __volatile__ (
- "ldr r9, [%[regs], #13*4] \n\t"
- "ldr r8, [%[regs], #14*4] \n\t"
- "ldmia %[regs], {r0-r7} \n\t"
- "blx %[fn] \n\t"
- "str r9, [%[regs], #13*4] \n\t"
- :
- : [regs] "r" (regs), [fn] "r" (p->ainsn.insn_fn)
- : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9",
- "lr", "memory", "cc"
- );
-}
-
-static enum kprobe_insn __kprobes
-t16_decode_push(kprobe_opcode_t insn, struct arch_specific_insn *asi)
-{
- /*
- * To simulate a PUSH we use a Thumb-2 "STMDB R9!, {registers}"
- * and call it with R9=SP and LR in the register list represented
- * by R8.
- */
- ((u16 *)asi->insn)[0] = 0xe929; /* 1st half STMDB R9!,{} */
- ((u16 *)asi->insn)[1] = insn & 0x1ff; /* 2nd half (register list) */
- asi->insn_handler = t16_emulate_push;
- return INSN_GOOD;
-}
-
-static void __kprobes
-t16_emulate_pop_nopc(struct kprobe *p, struct pt_regs *regs)
-{
- __asm__ __volatile__ (
- "ldr r9, [%[regs], #13*4] \n\t"
- "ldmia %[regs], {r0-r7} \n\t"
- "blx %[fn] \n\t"
- "stmia %[regs], {r0-r7} \n\t"
- "str r9, [%[regs], #13*4] \n\t"
- :
- : [regs] "r" (regs), [fn] "r" (p->ainsn.insn_fn)
- : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r9",
- "lr", "memory", "cc"
- );
-}
-
-static void __kprobes
-t16_emulate_pop_pc(struct kprobe *p, struct pt_regs *regs)
-{
- register unsigned long pc asm("r8");
-
- __asm__ __volatile__ (
- "ldr r9, [%[regs], #13*4] \n\t"
- "ldmia %[regs], {r0-r7} \n\t"
- "blx %[fn] \n\t"
- "stmia %[regs], {r0-r7} \n\t"
- "str r9, [%[regs], #13*4] \n\t"
- : "=r" (pc)
- : [regs] "r" (regs), [fn] "r" (p->ainsn.insn_fn)
- : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r9",
- "lr", "memory", "cc"
- );
-
- bx_write_pc(pc, regs);
-}
-
-static enum kprobe_insn __kprobes
-t16_decode_pop(kprobe_opcode_t insn, struct arch_specific_insn *asi)
-{
- /*
- * To simulate a POP we use a Thumb-2 "LDMDB R9!, {registers}"
- * and call it with R9=SP and PC in the register list represented
- * by R8.
- */
- ((u16 *)asi->insn)[0] = 0xe8b9; /* 1st half LDMIA R9!,{} */
- ((u16 *)asi->insn)[1] = insn & 0x1ff; /* 2nd half (register list) */
- asi->insn_handler = insn & 0x100 ? t16_emulate_pop_pc
- : t16_emulate_pop_nopc;
- return INSN_GOOD;
-}
-
static const union decode_item t16_table_1011[] = {
/* Miscellaneous 16-bit instructions */
diff --git a/arch/arm/kernel/probes-thumb.h b/arch/arm/kernel/probes-thumb.h
new file mode 100644
index 0000000..3f39210
--- /dev/null
+++ b/arch/arm/kernel/probes-thumb.h
@@ -0,0 +1,136 @@
+/*
+ * arch/arm/kernel/probes-arm.h
+ *
+ * Copyright 2013 Linaro Ltd.
+ * Written by: David A. Long
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#ifndef _ARM_KERNEL_PROBES_THUMB_H
+#define _ARM_KERNEL_PROBES_THUMB_H
+
+/*
+ * True if current instruction is in an IT block.
+ */
+#define in_it_block(cpsr) ((cpsr & 0x06000c00) != 0x00000000)
+
+/*
+ * Return the condition code to check for the currently executing instruction.
+ * This is in ITSTATE<7:4> which is in CPSR<15:12> but is only valid if
+ * in_it_block returns true.
+ */
+#define current_cond(cpsr) ((cpsr >> 12) & 0xf)
+
+enum probes_t32_action {
+ PROBES_T32_EMULATE_NONE,
+ PROBES_T32_SIMULATE_NOP,
+ PROBES_T32_LDMSTM,
+ PROBES_T32_LDRDSTRD,
+ PROBES_T32_TABLE_BRANCH,
+ PROBES_T32_TST,
+ PROBES_T32_CMP,
+ PROBES_T32_MOV,
+ PROBES_T32_ADDSUB,
+ PROBES_T32_LOGICAL,
+ PROBES_T32_ADDWSUBW_PC,
+ PROBES_T32_ADDWSUBW,
+ PROBES_T32_MOVW,
+ PROBES_T32_SAT,
+ PROBES_T32_BITFIELD,
+ PROBES_T32_SEV,
+ PROBES_T32_WFE,
+ PROBES_T32_MRS,
+ PROBES_T32_BRANCH_COND,
+ PROBES_T32_BRANCH,
+ PROBES_T32_PLDI,
+ PROBES_T32_LDR_LIT,
+ PROBES_T32_LDRSTR,
+ PROBES_T32_SIGN_EXTEND,
+ PROBES_T32_MEDIA,
+ PROBES_T32_REVERSE,
+ PROBES_T32_MUL_ADD,
+ PROBES_T32_MUL_ADD2,
+ PROBES_T32_MUL_ADD_LONG
+};
+
+enum probes_t16_action {
+ PROBES_T16_ADD_SP,
+ PROBES_T16_CBZ,
+ PROBES_T16_SIGN_EXTEND,
+ PROBES_T16_PUSH,
+ PROBES_T16_POP,
+ PROBES_T16_SEV,
+ PROBES_T16_WFE,
+ PROBES_T16_IT,
+ PROBES_T16_CMP,
+ PROBES_T16_ADDSUB,
+ PROBES_T16_LOGICAL,
+ PROBES_T16_BLX,
+ PROBES_T16_HIREGOPS,
+ PROBES_T16_LDR_LIT,
+ PROBES_T16_LDRHSTRH,
+ PROBES_T16_LDRSTR,
+ PROBES_T16_ADR,
+ PROBES_T16_LDMSTM,
+ PROBES_T16_BRANCH_COND,
+ PROBES_T16_BRANCH
+};
+
+void __kprobes t16_simulate_bxblx(struct kprobe *p, struct pt_regs *regs);
+void __kprobes t16_simulate_ldr_literal(struct kprobe *p, struct pt_regs *regs);
+void __kprobes t16_simulate_ldrstr_sp_relative(struct kprobe *p,
+ struct pt_regs *regs);
+void __kprobes t16_simulate_reladr(struct kprobe *p, struct pt_regs *regs);
+void __kprobes t16_simulate_add_sp_imm(struct kprobe *p, struct pt_regs *regs);
+void __kprobes t16_simulate_cbz(struct kprobe *p, struct pt_regs *regs);
+void __kprobes t16_simulate_it(struct kprobe *p, struct pt_regs *regs);
+void __kprobes t16_singlestep_it(struct kprobe *p, struct pt_regs *regs);
+enum kprobe_insn __kprobes t16_decode_it(kprobe_opcode_t insn,
+ struct arch_specific_insn *asi);
+void __kprobes t16_simulate_cond_branch(struct kprobe *p, struct pt_regs *regs);
+enum kprobe_insn __kprobes t16_decode_cond_branch(kprobe_opcode_t insn,
+ struct arch_specific_insn *asi);
+void __kprobes t16_simulate_branch(struct kprobe *p, struct pt_regs *regs);
+void __kprobes t16_emulate_loregs_rwflags(struct kprobe *p,
+ struct pt_regs *regs);
+void __kprobes t16_emulate_loregs_noitrwflags(struct kprobe *p,
+ struct pt_regs *regs);
+void __kprobes t16_emulate_hiregs(struct kprobe *p, struct pt_regs *regs);
+enum kprobe_insn __kprobes t16_decode_hiregs(kprobe_opcode_t insn,
+ struct arch_specific_insn *asi);
+void __kprobes t16_emulate_push(struct kprobe *p, struct pt_regs *regs);
+enum kprobe_insn __kprobes t16_decode_push(kprobe_opcode_t insn,
+ struct arch_specific_insn *asi);
+void __kprobes t16_emulate_pop_nopc(struct kprobe *p, struct pt_regs *regs);
+void __kprobes t16_emulate_pop_pc(struct kprobe *p, struct pt_regs *regs);
+enum kprobe_insn __kprobes t16_decode_pop(kprobe_opcode_t insn,
+ struct arch_specific_insn *asi);
+
+void __kprobes t32_simulate_table_branch(struct kprobe *p,
+ struct pt_regs *regs);
+void __kprobes t32_simulate_mrs(struct kprobe *p, struct pt_regs *regs);
+void __kprobes t32_simulate_cond_branch(struct kprobe *p, struct pt_regs *regs);
+enum kprobe_insn __kprobes t32_decode_cond_branch(kprobe_opcode_t insn,
+ struct arch_specific_insn *asi);
+void __kprobes t32_simulate_branch(struct kprobe *p, struct pt_regs *regs);
+void __kprobes t32_simulate_ldr_literal(struct kprobe *p, struct pt_regs *regs);
+enum kprobe_insn __kprobes t32_decode_ldmstm(kprobe_opcode_t insn,
+ struct arch_specific_insn *asi);
+void __kprobes t32_emulate_ldrdstrd(struct kprobe *p, struct pt_regs *regs);
+void __kprobes t32_emulate_ldrstr(struct kprobe *p, struct pt_regs *regs);
+void __kprobes t32_emulate_rd8rn16rm0_rwflags(struct kprobe *p,
+ struct pt_regs *regs);
+void __kprobes t32_emulate_rd8pc16_noflags(struct kprobe *p,
+ struct pt_regs *regs);
+void __kprobes t32_emulate_rd8rn16_noflags(struct kprobe *p,
+ struct pt_regs *regs);
+void __kprobes t32_emulate_rdlo12rdhi8rn16rm0_noflags(struct kprobe *p,
+ struct pt_regs *regs);
+
+#endif
--
1.8.1.2
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH v4 05/16] ARM: use a function table for determining instruction interpreter actions
2013-12-16 4:08 [PATCH v4 00/16] uprobes: Add uprobes support for ARM David Long
` (3 preceding siblings ...)
2013-12-16 4:08 ` [PATCH v4 04/16] ARM: move generic thumb instruction parsing code to new files for use by other feature David Long
@ 2013-12-16 4:08 ` David Long
2013-12-20 12:45 ` Jon Medhurst (Tixy)
2013-12-16 4:08 ` [PATCH v4 06/16] ARM: Disable jprobes test when built into thumb-mode kernel David Long
` (10 subsequent siblings)
15 siblings, 1 reply; 34+ messages in thread
From: David Long @ 2013-12-16 4:08 UTC (permalink / raw)
To: linux-arm-kernel
From: "David A. Long" <dave.long@linaro.org>
Make the instruction interpreter call back to semantic action functions
through a function pointer array provided by the invoker. The interpreter
decodes the instructions into groups and uses the group number to index
into the supplied array. kprobes and uprobes code will each supply their
own array of functions.
Signed-off-by: David A. Long <dave.long@linaro.org>
---
arch/arm/kernel/kprobes-arm.c | 41 +++++++++++
arch/arm/kernel/kprobes-common.c | 3 +-
arch/arm/kernel/kprobes-thumb.c | 92 ++++++++++++++++++------
arch/arm/kernel/kprobes.c | 10 ++-
arch/arm/kernel/kprobes.h | 14 ++--
arch/arm/kernel/probes-arm.c | 114 +++++++++++++++---------------
arch/arm/kernel/probes-arm.h | 37 ++++++++++
arch/arm/kernel/probes-thumb.c | 149 +++++++++++++++++++--------------------
arch/arm/kernel/probes-thumb.h | 14 ++--
arch/arm/kernel/probes.c | 13 ++--
arch/arm/kernel/probes.h | 15 ++--
11 files changed, 325 insertions(+), 177 deletions(-)
diff --git a/arch/arm/kernel/kprobes-arm.c b/arch/arm/kernel/kprobes-arm.c
index a359475..ee329ff 100644
--- a/arch/arm/kernel/kprobes-arm.c
+++ b/arch/arm/kernel/kprobes-arm.c
@@ -299,3 +299,44 @@ emulate_rdlo12rdhi16rn0rm8_rwflags_nopc(struct kprobe *p, struct pt_regs *regs)
regs->uregs[rdhi] = rdhiv;
regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK);
}
+
+const union decode_item kprobes_arm_actions[] = {
+ [PROBES_EMULATE_NONE] = {.handler = kprobe_emulate_none},
+ [PROBES_SIMULATE_NOP] = {.handler = kprobe_simulate_nop},
+ [PROBES_PRELOAD_IMM] = {.handler = kprobe_simulate_nop},
+ [PROBES_PRELOAD_REG] = {.handler = kprobe_simulate_nop},
+ [PROBES_BRANCH_IMM] = {.handler = simulate_blx1},
+ [PROBES_MRS] = {.handler = simulate_mrs},
+ [PROBES_BRANCH_REG] = {.handler = simulate_blx2bx},
+ [PROBES_CLZ] = {.handler = emulate_rd12rm0_noflags_nopc},
+ [PROBES_SATURATING_ARITHMETIC] = {
+ .handler = emulate_rd12rn16rm0_rwflags_nopc},
+ [PROBES_MUL1] = {.handler = emulate_rdlo12rdhi16rn0rm8_rwflags_nopc},
+ [PROBES_MUL2] = {.handler = emulate_rd16rn12rm0rs8_rwflags_nopc},
+ [PROBES_SWP] = {.handler = emulate_rd12rn16rm0_rwflags_nopc},
+ [PROBES_LDRSTRD] = {.handler = emulate_ldrdstrd},
+ [PROBES_LOAD_EXTRA] = {.handler = emulate_ldr},
+ [PROBES_LOAD] = {.handler = emulate_ldr},
+ [PROBES_STORE_EXTRA] = {.handler = emulate_str},
+ [PROBES_STORE] = {.handler = emulate_str},
+ [PROBES_MOV_IP_SP] = {.handler = simulate_mov_ipsp},
+ [PROBES_DATA_PROCESSING_REG] = {
+ .handler = emulate_rd12rn16rm0rs8_rwflags},
+ [PROBES_DATA_PROCESSING_IMM] = {
+ .handler = emulate_rd12rn16rm0rs8_rwflags},
+ [PROBES_MOV_HALFWORD] = {.handler = emulate_rd12rm0_noflags_nopc},
+ [PROBES_SEV] = {.handler = kprobe_emulate_none},
+ [PROBES_WFE] = {.handler = kprobe_simulate_nop},
+ [PROBES_SATURATE] = {.handler = emulate_rd12rn16rm0_rwflags_nopc},
+ [PROBES_REV] = {.handler = emulate_rd12rm0_noflags_nopc},
+ [PROBES_MMI] = {.handler = emulate_rd12rn16rm0_rwflags_nopc},
+ [PROBES_PACK] = {.handler = emulate_rd12rn16rm0_rwflags_nopc},
+ [PROBES_EXTEND] = {.handler = emulate_rd12rm0_noflags_nopc},
+ [PROBES_EXTEND_ADD] = {.handler = emulate_rd12rn16rm0_rwflags_nopc},
+ [PROBES_MUL_ADD_LONG] = {
+ .handler = emulate_rdlo12rdhi16rn0rm8_rwflags_nopc},
+ [PROBES_MUL_ADD] = {.handler = emulate_rd16rn12rm0rs8_rwflags_nopc},
+ [PROBES_BITFIELD] = {.handler = emulate_rd12rm0_noflags_nopc},
+ [PROBES_BRANCH] = {.handler = simulate_bbl},
+ [PROBES_LDMSTM] = {.decoder = kprobe_decode_ldmstm}
+};
diff --git a/arch/arm/kernel/kprobes-common.c b/arch/arm/kernel/kprobes-common.c
index ed47b54..554720c 100644
--- a/arch/arm/kernel/kprobes-common.c
+++ b/arch/arm/kernel/kprobes-common.c
@@ -113,7 +113,8 @@ emulate_ldm_r3_15(struct kprobe *p, struct pt_regs *regs)
}
enum kprobe_insn __kprobes
-kprobe_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi)
+kprobe_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi,
+ struct decode_header *h)
{
kprobe_insn_handler_t *handler = 0;
unsigned reglist = insn & 0xffff;
diff --git a/arch/arm/kernel/kprobes-thumb.c b/arch/arm/kernel/kprobes-thumb.c
index ebc13c1..5990866 100644
--- a/arch/arm/kernel/kprobes-thumb.c
+++ b/arch/arm/kernel/kprobes-thumb.c
@@ -15,18 +15,9 @@
#include "kprobes.h"
#include "probes-thumb.h"
-
-/*
- * True if current instruction is in an IT block.
- */
-#define in_it_block(cpsr) ((cpsr & 0x06000c00) != 0x00000000)
-
-/*
- * Return the condition code to check for the currently executing instruction.
- * This is in ITSTATE<7:4> which is in CPSR<15:12> but is only valid if
- * in_it_block returns true.
- */
-#define current_cond(cpsr) ((cpsr >> 12) & 0xf)
+/* These emulation encodings are functionally equivalent... */
+#define t32_emulate_rd8rn16rm0ra12_noflags \
+ t32_emulate_rdlo12rdhi8rn16rm0_noflags
/*
* Return the PC value for a probe in thumb code.
@@ -86,7 +77,8 @@ t32_simulate_cond_branch(struct kprobe *p, struct pt_regs *regs)
}
enum kprobe_insn __kprobes
-t32_decode_cond_branch(kprobe_opcode_t insn, struct arch_specific_insn *asi)
+t32_decode_cond_branch(kprobe_opcode_t insn, struct arch_specific_insn *asi,
+ struct decode_header *d)
{
int cc = (insn >> 22) & 0xf;
asi->insn_check_cc = kprobe_condition_checks[cc];
@@ -161,9 +153,10 @@ t32_simulate_ldr_literal(struct kprobe *p, struct pt_regs *regs)
}
enum kprobe_insn __kprobes
-t32_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi)
+t32_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi,
+ struct decode_header *d)
{
- enum kprobe_insn ret = kprobe_decode_ldmstm(insn, asi);
+ enum kprobe_insn ret = kprobe_decode_ldmstm(insn, asi, d);
/* Fixup modified instruction to have halfwords in correct order...*/
insn = asi->insn[0];
@@ -418,7 +411,8 @@ t16_singlestep_it(struct kprobe *p, struct pt_regs *regs)
}
enum kprobe_insn __kprobes
-t16_decode_it(kprobe_opcode_t insn, struct arch_specific_insn *asi)
+t16_decode_it(kprobe_opcode_t insn, struct arch_specific_insn *asi,
+ struct decode_header *d)
{
asi->insn_singlestep = t16_singlestep_it;
return INSN_GOOD_NO_SLOT;
@@ -435,7 +429,8 @@ t16_simulate_cond_branch(struct kprobe *p, struct pt_regs *regs)
}
enum kprobe_insn __kprobes
-t16_decode_cond_branch(kprobe_opcode_t insn, struct arch_specific_insn *asi)
+t16_decode_cond_branch(kprobe_opcode_t insn, struct arch_specific_insn *asi,
+ struct decode_header *d)
{
int cc = (insn >> 8) & 0xf;
asi->insn_check_cc = kprobe_condition_checks[cc];
@@ -521,7 +516,8 @@ t16_emulate_hiregs(struct kprobe *p, struct pt_regs *regs)
}
enum kprobe_insn __kprobes
-t16_decode_hiregs(kprobe_opcode_t insn, struct arch_specific_insn *asi)
+t16_decode_hiregs(kprobe_opcode_t insn, struct arch_specific_insn *asi,
+ struct decode_header *d)
{
insn &= ~0x00ff;
insn |= 0x001; /* Set Rdn = R1 and Rm = R0 */
@@ -547,7 +543,8 @@ t16_emulate_push(struct kprobe *p, struct pt_regs *regs)
}
enum kprobe_insn __kprobes
-t16_decode_push(kprobe_opcode_t insn, struct arch_specific_insn *asi)
+t16_decode_push(kprobe_opcode_t insn, struct arch_specific_insn *asi,
+ struct decode_header *d)
{
/*
* To simulate a PUSH we use a Thumb-2 "STMDB R9!, {registers}"
@@ -597,7 +594,8 @@ t16_emulate_pop_pc(struct kprobe *p, struct pt_regs *regs)
}
enum kprobe_insn __kprobes
-t16_decode_pop(kprobe_opcode_t insn, struct arch_specific_insn *asi)
+t16_decode_pop(kprobe_opcode_t insn, struct arch_specific_insn *asi,
+ struct decode_header *d)
{
/*
* To simulate a POP we use a Thumb-2 "LDMDB R9!, {registers}"
@@ -610,3 +608,57 @@ t16_decode_pop(kprobe_opcode_t insn, struct arch_specific_insn *asi)
: t16_emulate_pop_nopc;
return INSN_GOOD;
}
+
+const union decode_item kprobes_t16_actions[] = {
+ [PROBES_T16_ADD_SP] = {.handler = t16_simulate_add_sp_imm},
+ [PROBES_T16_CBZ] = {.handler = t16_simulate_cbz},
+ [PROBES_T16_SIGN_EXTEND] = {.handler = t16_emulate_loregs_rwflags},
+ [PROBES_T16_PUSH] = {.decoder = t16_decode_push},
+ [PROBES_T16_POP] = {.decoder = t16_decode_pop},
+ [PROBES_T16_SEV] = {.handler = kprobe_emulate_none},
+ [PROBES_T16_WFE] = {.handler = kprobe_simulate_nop},
+ [PROBES_T16_IT] = {.decoder = t16_decode_it},
+ [PROBES_T16_CMP] = {.handler = t16_emulate_loregs_rwflags},
+ [PROBES_T16_ADDSUB] = {.handler = t16_emulate_loregs_noitrwflags},
+ [PROBES_T16_LOGICAL] = {.handler = t16_emulate_loregs_noitrwflags},
+ [PROBES_T16_LDR_LIT] = {.handler = t16_simulate_ldr_literal},
+ [PROBES_T16_BLX] = {.handler = t16_simulate_bxblx},
+ [PROBES_T16_HIREGOPS] = {.decoder = t16_decode_hiregs},
+ [PROBES_T16_LDRHSTRH] = {.handler = t16_emulate_loregs_rwflags},
+ [PROBES_T16_LDRSTR] = {.handler = t16_simulate_ldrstr_sp_relative},
+ [PROBES_T16_ADR] = {.handler = t16_simulate_reladr},
+ [PROBES_T16_LDMSTM] = {.handler = t16_emulate_loregs_rwflags},
+ [PROBES_T16_BRANCH_COND] = {.decoder = t16_decode_cond_branch},
+ [PROBES_T16_BRANCH] = {.handler = t16_simulate_branch},
+};
+
+const union decode_item kprobes_t32_actions[] = {
+ [PROBES_T32_LDMSTM] = {.decoder = t32_decode_ldmstm},
+ [PROBES_T32_LDRDSTRD] = {.handler = t32_emulate_ldrdstrd},
+ [PROBES_T32_TABLE_BRANCH] = {.handler = t32_simulate_table_branch},
+ [PROBES_T32_TST] = {.handler = t32_emulate_rd8rn16rm0_rwflags},
+ [PROBES_T32_MOV] = {.handler = t32_emulate_rd8rn16rm0_rwflags},
+ [PROBES_T32_ADDSUB] = {.handler = t32_emulate_rd8rn16rm0_rwflags},
+ [PROBES_T32_LOGICAL] = {.handler = t32_emulate_rd8rn16rm0_rwflags},
+ [PROBES_T32_CMP] = {.handler = t32_emulate_rd8rn16rm0_rwflags},
+ [PROBES_T32_ADDWSUBW_PC] = {.handler = t32_emulate_rd8pc16_noflags,},
+ [PROBES_T32_ADDWSUBW] = {.handler = t32_emulate_rd8rn16_noflags},
+ [PROBES_T32_MOVW] = {.handler = t32_emulate_rd8rn16_noflags},
+ [PROBES_T32_SAT] = {.handler = t32_emulate_rd8rn16rm0_rwflags},
+ [PROBES_T32_BITFIELD] = {.handler = t32_emulate_rd8rn16_noflags},
+ [PROBES_T32_SEV] = {.handler = kprobe_emulate_none},
+ [PROBES_T32_WFE] = {.handler = kprobe_simulate_nop},
+ [PROBES_T32_MRS] = {.handler = t32_simulate_mrs},
+ [PROBES_T32_BRANCH_COND] = {.decoder = t32_decode_cond_branch},
+ [PROBES_T32_BRANCH] = {.handler = t32_simulate_branch},
+ [PROBES_T32_PLDI] = {.handler = kprobe_simulate_nop},
+ [PROBES_T32_LDR_LIT] = {.handler = t32_simulate_ldr_literal},
+ [PROBES_T32_LDRSTR] = {.handler = t32_emulate_ldrstr},
+ [PROBES_T32_SIGN_EXTEND] = {.handler = t32_emulate_rd8rn16rm0_rwflags},
+ [PROBES_T32_MEDIA] = {.handler = t32_emulate_rd8rn16rm0_rwflags},
+ [PROBES_T32_REVERSE] = {.handler = t32_emulate_rd8rn16_noflags},
+ [PROBES_T32_MUL_ADD] = {.handler = t32_emulate_rd8rn16rm0_rwflags},
+ [PROBES_T32_MUL_ADD2] = {.handler = t32_emulate_rd8rn16rm0ra12_noflags},
+ [PROBES_T32_MUL_ADD_LONG] =
+ {.handler = t32_emulate_rdlo12rdhi8rn16rm0_noflags},
+};
diff --git a/arch/arm/kernel/kprobes.c b/arch/arm/kernel/kprobes.c
index a7b621e..a18b4ca 100644
--- a/arch/arm/kernel/kprobes.c
+++ b/arch/arm/kernel/kprobes.c
@@ -54,6 +54,7 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
unsigned long addr = (unsigned long)p->addr;
bool thumb;
kprobe_decode_insn_t *decode_insn;
+ const union decode_item *actions;
int is;
if (in_exception_text(addr))
@@ -67,20 +68,25 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
insn <<= 16;
insn |= ((u16 *)addr)[1];
decode_insn = thumb32_kprobe_decode_insn;
- } else
+ actions = kprobes_t32_actions;
+ } else {
decode_insn = thumb16_kprobe_decode_insn;
+ actions = kprobes_t16_actions;
+ }
#else /* !CONFIG_THUMB2_KERNEL */
thumb = false;
if (addr & 0x3)
return -EINVAL;
insn = *p->addr;
decode_insn = arm_kprobe_decode_insn;
+ actions = kprobes_arm_actions;
#endif
p->opcode = insn;
p->ainsn.insn = tmp_insn;
- switch ((*decode_insn)(insn, &p->ainsn)) {
+ switch ((*decode_insn)
+ (insn, &p->ainsn, (struct decode_header *) actions)) {
case INSN_REJECTED: /* not supported */
return -EINVAL;
diff --git a/arch/arm/kernel/kprobes.h b/arch/arm/kernel/kprobes.h
index aa68c0e..5ce81dc 100644
--- a/arch/arm/kernel/kprobes.h
+++ b/arch/arm/kernel/kprobes.h
@@ -27,6 +27,7 @@
#define KPROBE_THUMB16_BREAKPOINT_INSTRUCTION 0xde18
#define KPROBE_THUMB32_BREAKPOINT_INSTRUCTION 0xf7f0a018
+struct decode_header;
enum kprobe_insn {
INSN_REJECTED,
@@ -35,19 +36,24 @@ enum kprobe_insn {
};
typedef enum kprobe_insn (kprobe_decode_insn_t)(kprobe_opcode_t,
- struct arch_specific_insn *);
+ struct arch_specific_insn *,
+ struct decode_header *actions);
#ifdef CONFIG_THUMB2_KERNEL
enum kprobe_insn thumb16_kprobe_decode_insn(kprobe_opcode_t,
- struct arch_specific_insn *);
+ struct arch_specific_insn *,
+ struct decode_header *);
enum kprobe_insn thumb32_kprobe_decode_insn(kprobe_opcode_t,
- struct arch_specific_insn *);
+ struct arch_specific_insn *,
+ struct decode_header *);
#else /* !CONFIG_THUMB2_KERNEL */
enum kprobe_insn arm_kprobe_decode_insn(kprobe_opcode_t,
- struct arch_specific_insn *);
+ struct arch_specific_insn *,
+ struct decode_header *);
+
#endif
void __init arm_kprobe_decode_init(void);
diff --git a/arch/arm/kernel/probes-arm.c b/arch/arm/kernel/probes-arm.c
index 3286412..665cd0d 100644
--- a/arch/arm/kernel/probes-arm.c
+++ b/arch/arm/kernel/probes-arm.c
@@ -124,16 +124,16 @@ static const union decode_item arm_1111_table[] = {
/* PLDI (immediate) 1111 0100 x101 xxxx xxxx xxxx xxxx xxxx */
/* PLDW (immediate) 1111 0101 x001 xxxx xxxx xxxx xxxx xxxx */
/* PLD (immediate) 1111 0101 x101 xxxx xxxx xxxx xxxx xxxx */
- DECODE_SIMULATE (0xfe300000, 0xf4100000, kprobe_simulate_nop),
+ DECODE_SIMULATE (0xfe300000, 0xf4100000, PROBES_PRELOAD_IMM),
/* memory hint 1111 0110 x001 xxxx xxxx xxxx xxx0 xxxx */
/* PLDI (register) 1111 0110 x101 xxxx xxxx xxxx xxx0 xxxx */
/* PLDW (register) 1111 0111 x001 xxxx xxxx xxxx xxx0 xxxx */
/* PLD (register) 1111 0111 x101 xxxx xxxx xxxx xxx0 xxxx */
- DECODE_SIMULATE (0xfe300010, 0xf6100000, kprobe_simulate_nop),
+ DECODE_SIMULATE (0xfe300010, 0xf6100000, PROBES_PRELOAD_REG),
/* BLX (immediate) 1111 101x xxxx xxxx xxxx xxxx xxxx xxxx */
- DECODE_SIMULATE (0xfe000000, 0xfa000000, simulate_blx1),
+ DECODE_SIMULATE (0xfe000000, 0xfa000000, PROBES_BRANCH_IMM),
/* CPS 1111 0001 0000 xxx0 xxxx xxxx xx0x xxxx */
/* SETEND 1111 0001 0000 0001 xxxx xxxx 0000 xxxx */
@@ -157,25 +157,25 @@ static const union decode_item arm_cccc_0001_0xx0____0xxx_table[] = {
/* Miscellaneous instructions */
/* MRS cpsr cccc 0001 0000 xxxx xxxx xxxx 0000 xxxx */
- DECODE_SIMULATEX(0x0ff000f0, 0x01000000, simulate_mrs,
+ DECODE_SIMULATEX(0x0ff000f0, 0x01000000, PROBES_MRS,
REGS(0, NOPC, 0, 0, 0)),
/* BX cccc 0001 0010 xxxx xxxx xxxx 0001 xxxx */
- DECODE_SIMULATE (0x0ff000f0, 0x01200010, simulate_blx2bx),
+ DECODE_SIMULATE (0x0ff000f0, 0x01200010, PROBES_BRANCH_REG),
/* BLX (register) cccc 0001 0010 xxxx xxxx xxxx 0011 xxxx */
- DECODE_SIMULATEX(0x0ff000f0, 0x01200030, simulate_blx2bx,
+ DECODE_SIMULATEX(0x0ff000f0, 0x01200030, PROBES_BRANCH_REG,
REGS(0, 0, 0, 0, NOPC)),
/* CLZ cccc 0001 0110 xxxx xxxx xxxx 0001 xxxx */
- DECODE_EMULATEX (0x0ff000f0, 0x01600010, emulate_rd12rm0_noflags_nopc,
+ DECODE_EMULATEX (0x0ff000f0, 0x01600010, PROBES_CLZ,
REGS(0, NOPC, 0, 0, NOPC)),
/* QADD cccc 0001 0000 xxxx xxxx xxxx 0101 xxxx */
/* QSUB cccc 0001 0010 xxxx xxxx xxxx 0101 xxxx */
/* QDADD cccc 0001 0100 xxxx xxxx xxxx 0101 xxxx */
/* QDSUB cccc 0001 0110 xxxx xxxx xxxx 0101 xxxx */
- DECODE_EMULATEX (0x0f9000f0, 0x01000050, emulate_rd12rn16rm0_rwflags_nopc,
+ DECODE_EMULATEX (0x0f9000f0, 0x01000050, PROBES_SATURATING_ARITHMETIC,
REGS(NOPC, NOPC, 0, 0, NOPC)),
/* BXJ cccc 0001 0010 xxxx xxxx xxxx 0010 xxxx */
@@ -191,19 +191,19 @@ static const union decode_item arm_cccc_0001_0xx0____1xx0_table[] = {
/* Halfword multiply and multiply-accumulate */
/* SMLALxy cccc 0001 0100 xxxx xxxx xxxx 1xx0 xxxx */
- DECODE_EMULATEX (0x0ff00090, 0x01400080, emulate_rdlo12rdhi16rn0rm8_rwflags_nopc,
+ DECODE_EMULATEX (0x0ff00090, 0x01400080, PROBES_MUL1,
REGS(NOPC, NOPC, NOPC, 0, NOPC)),
/* SMULWy cccc 0001 0010 xxxx xxxx xxxx 1x10 xxxx */
DECODE_OR (0x0ff000b0, 0x012000a0),
/* SMULxy cccc 0001 0110 xxxx xxxx xxxx 1xx0 xxxx */
- DECODE_EMULATEX (0x0ff00090, 0x01600080, emulate_rd16rn12rm0rs8_rwflags_nopc,
+ DECODE_EMULATEX (0x0ff00090, 0x01600080, PROBES_MUL2,
REGS(NOPC, 0, NOPC, 0, NOPC)),
/* SMLAxy cccc 0001 0000 xxxx xxxx xxxx 1xx0 xxxx */
DECODE_OR (0x0ff00090, 0x01000080),
/* SMLAWy cccc 0001 0010 xxxx xxxx xxxx 1x00 xxxx */
- DECODE_EMULATEX (0x0ff000b0, 0x01200080, emulate_rd16rn12rm0rs8_rwflags_nopc,
+ DECODE_EMULATEX (0x0ff000b0, 0x01200080, PROBES_MUL2,
REGS(NOPC, NOPC, NOPC, 0, NOPC)),
DECODE_END
@@ -214,14 +214,14 @@ static const union decode_item arm_cccc_0000_____1001_table[] = {
/* MUL cccc 0000 0000 xxxx xxxx xxxx 1001 xxxx */
/* MULS cccc 0000 0001 xxxx xxxx xxxx 1001 xxxx */
- DECODE_EMULATEX (0x0fe000f0, 0x00000090, emulate_rd16rn12rm0rs8_rwflags_nopc,
+ DECODE_EMULATEX (0x0fe000f0, 0x00000090, PROBES_MUL2,
REGS(NOPC, 0, NOPC, 0, NOPC)),
/* MLA cccc 0000 0010 xxxx xxxx xxxx 1001 xxxx */
/* MLAS cccc 0000 0011 xxxx xxxx xxxx 1001 xxxx */
DECODE_OR (0x0fe000f0, 0x00200090),
/* MLS cccc 0000 0110 xxxx xxxx xxxx 1001 xxxx */
- DECODE_EMULATEX (0x0ff000f0, 0x00600090, emulate_rd16rn12rm0rs8_rwflags_nopc,
+ DECODE_EMULATEX (0x0ff000f0, 0x00600090, PROBES_MUL2,
REGS(NOPC, NOPC, NOPC, 0, NOPC)),
/* UMAAL cccc 0000 0100 xxxx xxxx xxxx 1001 xxxx */
@@ -234,7 +234,7 @@ static const union decode_item arm_cccc_0000_____1001_table[] = {
/* SMULLS cccc 0000 1101 xxxx xxxx xxxx 1001 xxxx */
/* SMLAL cccc 0000 1110 xxxx xxxx xxxx 1001 xxxx */
/* SMLALS cccc 0000 1111 xxxx xxxx xxxx 1001 xxxx */
- DECODE_EMULATEX (0x0f8000f0, 0x00800090, emulate_rdlo12rdhi16rn0rm8_rwflags_nopc,
+ DECODE_EMULATEX (0x0f8000f0, 0x00800090, PROBES_MUL1,
REGS(NOPC, NOPC, NOPC, 0, NOPC)),
DECODE_END
@@ -246,7 +246,7 @@ static const union decode_item arm_cccc_0001_____1001_table[] = {
#if __LINUX_ARM_ARCH__ < 6
/* Deprecated on ARMv6 and may be UNDEFINED on v7 */
/* SMP/SWPB cccc 0001 0x00 xxxx xxxx xxxx 1001 xxxx */
- DECODE_EMULATEX (0x0fb000f0, 0x01000090, emulate_rd12rn16rm0_rwflags_nopc,
+ DECODE_EMULATEX (0x0fb000f0, 0x01000090, PROBES_SWP,
REGS(NOPC, NOPC, 0, 0, NOPC)),
#endif
/* LDREX/STREX{,D,B,H} cccc 0001 1xxx xxxx xxxx xxxx 1001 xxxx */
@@ -269,32 +269,32 @@ static const union decode_item arm_cccc_000x_____1xx1_table[] = {
/* LDRD (register) cccc 000x x0x0 xxxx xxxx xxxx 1101 xxxx */
/* STRD (register) cccc 000x x0x0 xxxx xxxx xxxx 1111 xxxx */
- DECODE_EMULATEX (0x0e5000d0, 0x000000d0, emulate_ldrdstrd,
+ DECODE_EMULATEX (0x0e5000d0, 0x000000d0, PROBES_LDRSTRD,
REGS(NOPCWB, NOPCX, 0, 0, NOPC)),
/* LDRD (immediate) cccc 000x x1x0 xxxx xxxx xxxx 1101 xxxx */
/* STRD (immediate) cccc 000x x1x0 xxxx xxxx xxxx 1111 xxxx */
- DECODE_EMULATEX (0x0e5000d0, 0x004000d0, emulate_ldrdstrd,
+ DECODE_EMULATEX (0x0e5000d0, 0x004000d0, PROBES_LDRSTRD,
REGS(NOPCWB, NOPCX, 0, 0, 0)),
/* STRH (register) cccc 000x x0x0 xxxx xxxx xxxx 1011 xxxx */
- DECODE_EMULATEX (0x0e5000f0, 0x000000b0, emulate_str,
+ DECODE_EMULATEX (0x0e5000f0, 0x000000b0, PROBES_STORE_EXTRA,
REGS(NOPCWB, NOPC, 0, 0, NOPC)),
/* LDRH (register) cccc 000x x0x1 xxxx xxxx xxxx 1011 xxxx */
/* LDRSB (register) cccc 000x x0x1 xxxx xxxx xxxx 1101 xxxx */
/* LDRSH (register) cccc 000x x0x1 xxxx xxxx xxxx 1111 xxxx */
- DECODE_EMULATEX (0x0e500090, 0x00100090, emulate_ldr,
+ DECODE_EMULATEX (0x0e500090, 0x00100090, PROBES_LOAD_EXTRA,
REGS(NOPCWB, NOPC, 0, 0, NOPC)),
/* STRH (immediate) cccc 000x x1x0 xxxx xxxx xxxx 1011 xxxx */
- DECODE_EMULATEX (0x0e5000f0, 0x004000b0, emulate_str,
+ DECODE_EMULATEX (0x0e5000f0, 0x004000b0, PROBES_STORE_EXTRA,
REGS(NOPCWB, NOPC, 0, 0, 0)),
/* LDRH (immediate) cccc 000x x1x1 xxxx xxxx xxxx 1011 xxxx */
/* LDRSB (immediate) cccc 000x x1x1 xxxx xxxx xxxx 1101 xxxx */
/* LDRSH (immediate) cccc 000x x1x1 xxxx xxxx xxxx 1111 xxxx */
- DECODE_EMULATEX (0x0e500090, 0x00500090, emulate_ldr,
+ DECODE_EMULATEX (0x0e500090, 0x00500090, PROBES_LOAD_EXTRA,
REGS(NOPCWB, NOPC, 0, 0, 0)),
DECODE_END
@@ -307,18 +307,18 @@ static const union decode_item arm_cccc_000x_table[] = {
DECODE_REJECT (0x0e10f000, 0x0010f000),
/* MOV IP, SP 1110 0001 1010 0000 1100 0000 0000 1101 */
- DECODE_SIMULATE (0xffffffff, 0xe1a0c00d, simulate_mov_ipsp),
+ DECODE_SIMULATE (0xffffffff, 0xe1a0c00d, PROBES_MOV_IP_SP),
/* TST (register) cccc 0001 0001 xxxx xxxx xxxx xxx0 xxxx */
/* TEQ (register) cccc 0001 0011 xxxx xxxx xxxx xxx0 xxxx */
/* CMP (register) cccc 0001 0101 xxxx xxxx xxxx xxx0 xxxx */
/* CMN (register) cccc 0001 0111 xxxx xxxx xxxx xxx0 xxxx */
- DECODE_EMULATEX (0x0f900010, 0x01100000, emulate_rd12rn16rm0rs8_rwflags,
+ DECODE_EMULATEX (0x0f900010, 0x01100000, PROBES_DATA_PROCESSING_REG,
REGS(ANY, 0, 0, 0, ANY)),
/* MOV (register) cccc 0001 101x xxxx xxxx xxxx xxx0 xxxx */
/* MVN (register) cccc 0001 111x xxxx xxxx xxxx xxx0 xxxx */
- DECODE_EMULATEX (0x0fa00010, 0x01a00000, emulate_rd12rn16rm0rs8_rwflags,
+ DECODE_EMULATEX (0x0fa00010, 0x01a00000, PROBES_DATA_PROCESSING_REG,
REGS(0, ANY, 0, 0, ANY)),
/* AND (register) cccc 0000 000x xxxx xxxx xxxx xxx0 xxxx */
@@ -331,19 +331,19 @@ static const union decode_item arm_cccc_000x_table[] = {
/* RSC (register) cccc 0000 111x xxxx xxxx xxxx xxx0 xxxx */
/* ORR (register) cccc 0001 100x xxxx xxxx xxxx xxx0 xxxx */
/* BIC (register) cccc 0001 110x xxxx xxxx xxxx xxx0 xxxx */
- DECODE_EMULATEX (0x0e000010, 0x00000000, emulate_rd12rn16rm0rs8_rwflags,
+ DECODE_EMULATEX (0x0e000010, 0x00000000, PROBES_DATA_PROCESSING_REG,
REGS(ANY, ANY, 0, 0, ANY)),
/* TST (reg-shift reg) cccc 0001 0001 xxxx xxxx xxxx 0xx1 xxxx */
/* TEQ (reg-shift reg) cccc 0001 0011 xxxx xxxx xxxx 0xx1 xxxx */
/* CMP (reg-shift reg) cccc 0001 0101 xxxx xxxx xxxx 0xx1 xxxx */
/* CMN (reg-shift reg) cccc 0001 0111 xxxx xxxx xxxx 0xx1 xxxx */
- DECODE_EMULATEX (0x0f900090, 0x01100010, emulate_rd12rn16rm0rs8_rwflags,
+ DECODE_EMULATEX (0x0f900090, 0x01100010, PROBES_DATA_PROCESSING_REG,
REGS(ANY, 0, NOPC, 0, ANY)),
/* MOV (reg-shift reg) cccc 0001 101x xxxx xxxx xxxx 0xx1 xxxx */
/* MVN (reg-shift reg) cccc 0001 111x xxxx xxxx xxxx 0xx1 xxxx */
- DECODE_EMULATEX (0x0fa00090, 0x01a00010, emulate_rd12rn16rm0rs8_rwflags,
+ DECODE_EMULATEX (0x0fa00090, 0x01a00010, PROBES_DATA_PROCESSING_REG,
REGS(0, ANY, NOPC, 0, ANY)),
/* AND (reg-shift reg) cccc 0000 000x xxxx xxxx xxxx 0xx1 xxxx */
@@ -356,7 +356,7 @@ static const union decode_item arm_cccc_000x_table[] = {
/* RSC (reg-shift reg) cccc 0000 111x xxxx xxxx xxxx 0xx1 xxxx */
/* ORR (reg-shift reg) cccc 0001 100x xxxx xxxx xxxx 0xx1 xxxx */
/* BIC (reg-shift reg) cccc 0001 110x xxxx xxxx xxxx 0xx1 xxxx */
- DECODE_EMULATEX (0x0e000090, 0x00000010, emulate_rd12rn16rm0rs8_rwflags,
+ DECODE_EMULATEX (0x0e000090, 0x00000010, PROBES_DATA_PROCESSING_REG,
REGS(ANY, ANY, NOPC, 0, ANY)),
DECODE_END
@@ -367,17 +367,17 @@ static const union decode_item arm_cccc_001x_table[] = {
/* MOVW cccc 0011 0000 xxxx xxxx xxxx xxxx xxxx */
/* MOVT cccc 0011 0100 xxxx xxxx xxxx xxxx xxxx */
- DECODE_EMULATEX (0x0fb00000, 0x03000000, emulate_rd12rm0_noflags_nopc,
+ DECODE_EMULATEX (0x0fb00000, 0x03000000, PROBES_DATA_PROCESSING_IMM,
REGS(0, NOPC, 0, 0, 0)),
/* YIELD cccc 0011 0010 0000 xxxx xxxx 0000 0001 */
DECODE_OR (0x0fff00ff, 0x03200001),
/* SEV cccc 0011 0010 0000 xxxx xxxx 0000 0100 */
- DECODE_EMULATE (0x0fff00ff, 0x03200004, kprobe_emulate_none),
+ DECODE_EMULATE (0x0fff00ff, 0x03200004, PROBES_EMULATE_NONE),
/* NOP cccc 0011 0010 0000 xxxx xxxx 0000 0000 */
/* WFE cccc 0011 0010 0000 xxxx xxxx 0000 0010 */
/* WFI cccc 0011 0010 0000 xxxx xxxx 0000 0011 */
- DECODE_SIMULATE (0x0fff00fc, 0x03200000, kprobe_simulate_nop),
+ DECODE_SIMULATE (0x0fff00fc, 0x03200000, PROBES_SIMULATE_NOP),
/* DBG cccc 0011 0010 0000 xxxx xxxx ffff xxxx */
/* unallocated hints cccc 0011 0010 0000 xxxx xxxx xxxx xxxx */
/* MSR (immediate) cccc 0011 0x10 xxxx xxxx xxxx xxxx xxxx */
@@ -390,12 +390,12 @@ static const union decode_item arm_cccc_001x_table[] = {
/* TEQ (immediate) cccc 0011 0011 xxxx xxxx xxxx xxxx xxxx */
/* CMP (immediate) cccc 0011 0101 xxxx xxxx xxxx xxxx xxxx */
/* CMN (immediate) cccc 0011 0111 xxxx xxxx xxxx xxxx xxxx */
- DECODE_EMULATEX (0x0f900000, 0x03100000, emulate_rd12rn16rm0rs8_rwflags,
+ DECODE_EMULATEX (0x0f900000, 0x03100000, PROBES_DATA_PROCESSING_IMM,
REGS(ANY, 0, 0, 0, 0)),
/* MOV (immediate) cccc 0011 101x xxxx xxxx xxxx xxxx xxxx */
/* MVN (immediate) cccc 0011 111x xxxx xxxx xxxx xxxx xxxx */
- DECODE_EMULATEX (0x0fa00000, 0x03a00000, emulate_rd12rn16rm0rs8_rwflags,
+ DECODE_EMULATEX (0x0fa00000, 0x03a00000, PROBES_DATA_PROCESSING_IMM,
REGS(0, ANY, 0, 0, 0)),
/* AND (immediate) cccc 0010 000x xxxx xxxx xxxx xxxx xxxx */
@@ -408,7 +408,7 @@ static const union decode_item arm_cccc_001x_table[] = {
/* RSC (immediate) cccc 0010 111x xxxx xxxx xxxx xxxx xxxx */
/* ORR (immediate) cccc 0011 100x xxxx xxxx xxxx xxxx xxxx */
/* BIC (immediate) cccc 0011 110x xxxx xxxx xxxx xxxx xxxx */
- DECODE_EMULATEX (0x0e000000, 0x02000000, emulate_rd12rn16rm0rs8_rwflags,
+ DECODE_EMULATEX (0x0e000000, 0x02000000, PROBES_DATA_PROCESSING_IMM,
REGS(ANY, ANY, 0, 0, 0)),
DECODE_END
@@ -418,7 +418,7 @@ static const union decode_item arm_cccc_0110_____xxx1_table[] = {
/* Media instructions */
/* SEL cccc 0110 1000 xxxx xxxx xxxx 1011 xxxx */
- DECODE_EMULATEX (0x0ff000f0, 0x068000b0, emulate_rd12rn16rm0_rwflags_nopc,
+ DECODE_EMULATEX (0x0ff000f0, 0x068000b0, PROBES_SATURATE,
REGS(NOPC, NOPC, 0, 0, NOPC)),
/* SSAT cccc 0110 101x xxxx xxxx xxxx xx01 xxxx */
@@ -426,14 +426,14 @@ static const union decode_item arm_cccc_0110_____xxx1_table[] = {
DECODE_OR(0x0fa00030, 0x06a00010),
/* SSAT16 cccc 0110 1010 xxxx xxxx xxxx 0011 xxxx */
/* USAT16 cccc 0110 1110 xxxx xxxx xxxx 0011 xxxx */
- DECODE_EMULATEX (0x0fb000f0, 0x06a00030, emulate_rd12rn16rm0_rwflags_nopc,
+ DECODE_EMULATEX (0x0fb000f0, 0x06a00030, PROBES_SATURATE,
REGS(0, NOPC, 0, 0, NOPC)),
/* REV cccc 0110 1011 xxxx xxxx xxxx 0011 xxxx */
/* REV16 cccc 0110 1011 xxxx xxxx xxxx 1011 xxxx */
/* RBIT cccc 0110 1111 xxxx xxxx xxxx 0011 xxxx */
/* REVSH cccc 0110 1111 xxxx xxxx xxxx 1011 xxxx */
- DECODE_EMULATEX (0x0fb00070, 0x06b00030, emulate_rd12rm0_noflags_nopc,
+ DECODE_EMULATEX (0x0fb00070, 0x06b00030, PROBES_REV,
REGS(0, NOPC, 0, 0, NOPC)),
/* ??? cccc 0110 0x00 xxxx xxxx xxxx xxx1 xxxx */
@@ -478,12 +478,12 @@ static const union decode_item arm_cccc_0110_____xxx1_table[] = {
/* UHSUB16 cccc 0110 0111 xxxx xxxx xxxx 0111 xxxx */
/* UHADD8 cccc 0110 0111 xxxx xxxx xxxx 1001 xxxx */
/* UHSUB8 cccc 0110 0111 xxxx xxxx xxxx 1111 xxxx */
- DECODE_EMULATEX (0x0f800010, 0x06000010, emulate_rd12rn16rm0_rwflags_nopc,
+ DECODE_EMULATEX (0x0f800010, 0x06000010, PROBES_MMI,
REGS(NOPC, NOPC, 0, 0, NOPC)),
/* PKHBT cccc 0110 1000 xxxx xxxx xxxx x001 xxxx */
/* PKHTB cccc 0110 1000 xxxx xxxx xxxx x101 xxxx */
- DECODE_EMULATEX (0x0ff00030, 0x06800010, emulate_rd12rn16rm0_rwflags_nopc,
+ DECODE_EMULATEX (0x0ff00030, 0x06800010, PROBES_PACK,
REGS(NOPC, NOPC, 0, 0, NOPC)),
/* ??? cccc 0110 1001 xxxx xxxx xxxx 0111 xxxx */
@@ -496,7 +496,7 @@ static const union decode_item arm_cccc_0110_____xxx1_table[] = {
/* UXTB16 cccc 0110 1100 1111 xxxx xxxx 0111 xxxx */
/* UXTB cccc 0110 1110 1111 xxxx xxxx 0111 xxxx */
/* UXTH cccc 0110 1111 1111 xxxx xxxx 0111 xxxx */
- DECODE_EMULATEX (0x0f8f00f0, 0x068f0070, emulate_rd12rm0_noflags_nopc,
+ DECODE_EMULATEX (0x0f8f00f0, 0x068f0070, PROBES_EXTEND,
REGS(0, NOPC, 0, 0, NOPC)),
/* SXTAB16 cccc 0110 1000 xxxx xxxx xxxx 0111 xxxx */
@@ -505,7 +505,7 @@ static const union decode_item arm_cccc_0110_____xxx1_table[] = {
/* UXTAB16 cccc 0110 1100 xxxx xxxx xxxx 0111 xxxx */
/* UXTAB cccc 0110 1110 xxxx xxxx xxxx 0111 xxxx */
/* UXTAH cccc 0110 1111 xxxx xxxx xxxx 0111 xxxx */
- DECODE_EMULATEX (0x0f8000f0, 0x06800070, emulate_rd12rn16rm0_rwflags_nopc,
+ DECODE_EMULATEX (0x0f8000f0, 0x06800070, PROBES_EXTEND_ADD,
REGS(NOPCX, NOPC, 0, 0, NOPC)),
DECODE_END
@@ -519,7 +519,7 @@ static const union decode_item arm_cccc_0111_____xxx1_table[] = {
/* SMLALD cccc 0111 0100 xxxx xxxx xxxx 00x1 xxxx */
/* SMLSLD cccc 0111 0100 xxxx xxxx xxxx 01x1 xxxx */
- DECODE_EMULATEX (0x0ff00090, 0x07400010, emulate_rdlo12rdhi16rn0rm8_rwflags_nopc,
+ DECODE_EMULATEX (0x0ff00090, 0x07400010, PROBES_MUL_ADD_LONG,
REGS(NOPC, NOPC, NOPC, 0, NOPC)),
/* SMUAD cccc 0111 0000 xxxx 1111 xxxx 00x1 xxxx */
@@ -528,7 +528,7 @@ static const union decode_item arm_cccc_0111_____xxx1_table[] = {
/* SMMUL cccc 0111 0101 xxxx 1111 xxxx 00x1 xxxx */
DECODE_OR (0x0ff0f0d0, 0x0750f010),
/* USAD8 cccc 0111 1000 xxxx 1111 xxxx 0001 xxxx */
- DECODE_EMULATEX (0x0ff0f0f0, 0x0780f010, emulate_rd16rn12rm0rs8_rwflags_nopc,
+ DECODE_EMULATEX (0x0ff0f0f0, 0x0780f010, PROBES_MUL_ADD,
REGS(NOPC, 0, NOPC, 0, NOPC)),
/* SMLAD cccc 0111 0000 xxxx xxxx xxxx 00x1 xxxx */
@@ -537,24 +537,24 @@ static const union decode_item arm_cccc_0111_____xxx1_table[] = {
/* SMMLA cccc 0111 0101 xxxx xxxx xxxx 00x1 xxxx */
DECODE_OR (0x0ff000d0, 0x07500010),
/* USADA8 cccc 0111 1000 xxxx xxxx xxxx 0001 xxxx */
- DECODE_EMULATEX (0x0ff000f0, 0x07800010, emulate_rd16rn12rm0rs8_rwflags_nopc,
+ DECODE_EMULATEX (0x0ff000f0, 0x07800010, PROBES_MUL_ADD,
REGS(NOPC, NOPCX, NOPC, 0, NOPC)),
/* SMMLS cccc 0111 0101 xxxx xxxx xxxx 11x1 xxxx */
- DECODE_EMULATEX (0x0ff000d0, 0x075000d0, emulate_rd16rn12rm0rs8_rwflags_nopc,
+ DECODE_EMULATEX (0x0ff000d0, 0x075000d0, PROBES_MUL_ADD,
REGS(NOPC, NOPC, NOPC, 0, NOPC)),
/* SBFX cccc 0111 101x xxxx xxxx xxxx x101 xxxx */
/* UBFX cccc 0111 111x xxxx xxxx xxxx x101 xxxx */
- DECODE_EMULATEX (0x0fa00070, 0x07a00050, emulate_rd12rm0_noflags_nopc,
+ DECODE_EMULATEX (0x0fa00070, 0x07a00050, PROBES_BITFIELD,
REGS(0, NOPC, 0, 0, NOPC)),
/* BFC cccc 0111 110x xxxx xxxx xxxx x001 1111 */
- DECODE_EMULATEX (0x0fe0007f, 0x07c0001f, emulate_rd12rm0_noflags_nopc,
+ DECODE_EMULATEX (0x0fe0007f, 0x07c0001f, PROBES_BITFIELD,
REGS(0, NOPC, 0, 0, 0)),
/* BFI cccc 0111 110x xxxx xxxx xxxx x001 xxxx */
- DECODE_EMULATEX (0x0fe00070, 0x07c00010, emulate_rd12rm0_noflags_nopc,
+ DECODE_EMULATEX (0x0fe00070, 0x07c00010, PROBES_BITFIELD,
REGS(0, NOPC, 0, 0, NOPCX)),
DECODE_END
@@ -574,22 +574,22 @@ static const union decode_item arm_cccc_01xx_table[] = {
/* STR (immediate) cccc 010x x0x0 xxxx xxxx xxxx xxxx xxxx */
/* STRB (immediate) cccc 010x x1x0 xxxx xxxx xxxx xxxx xxxx */
- DECODE_EMULATEX (0x0e100000, 0x04000000, emulate_str,
+ DECODE_EMULATEX (0x0e100000, 0x04000000, PROBES_STORE,
REGS(NOPCWB, ANY, 0, 0, 0)),
/* LDR (immediate) cccc 010x x0x1 xxxx xxxx xxxx xxxx xxxx */
/* LDRB (immediate) cccc 010x x1x1 xxxx xxxx xxxx xxxx xxxx */
- DECODE_EMULATEX (0x0e100000, 0x04100000, emulate_ldr,
+ DECODE_EMULATEX (0x0e100000, 0x04100000, PROBES_LOAD,
REGS(NOPCWB, ANY, 0, 0, 0)),
/* STR (register) cccc 011x x0x0 xxxx xxxx xxxx xxxx xxxx */
/* STRB (register) cccc 011x x1x0 xxxx xxxx xxxx xxxx xxxx */
- DECODE_EMULATEX (0x0e100000, 0x06000000, emulate_str,
+ DECODE_EMULATEX (0x0e100000, 0x06000000, PROBES_STORE,
REGS(NOPCWB, ANY, 0, 0, NOPC)),
/* LDR (register) cccc 011x x0x1 xxxx xxxx xxxx xxxx xxxx */
/* LDRB (register) cccc 011x x1x1 xxxx xxxx xxxx xxxx xxxx */
- DECODE_EMULATEX (0x0e100000, 0x06100000, emulate_ldr,
+ DECODE_EMULATEX (0x0e100000, 0x06100000, PROBES_LOAD,
REGS(NOPCWB, ANY, 0, 0, NOPC)),
DECODE_END
@@ -600,7 +600,7 @@ static const union decode_item arm_cccc_100x_table[] = {
/* LDM cccc 100x x0x1 xxxx xxxx xxxx xxxx xxxx */
/* STM cccc 100x x0x0 xxxx xxxx xxxx xxxx xxxx */
- DECODE_CUSTOM (0x0e400000, 0x08000000, kprobe_decode_ldmstm),
+ DECODE_CUSTOM (0x0e400000, 0x08000000, PROBES_LDMSTM),
/* STM (user registers) cccc 100x x1x0 xxxx xxxx xxxx xxxx xxxx */
/* LDM (user registers) cccc 100x x1x1 xxxx 0xxx xxxx xxxx xxxx */
@@ -680,7 +680,7 @@ const union decode_item kprobe_decode_arm_table[] = {
/* B cccc 1010 xxxx xxxx xxxx xxxx xxxx xxxx */
/* BL cccc 1011 xxxx xxxx xxxx xxxx xxxx xxxx */
- DECODE_SIMULATE (0x0e000000, 0x0a000000, simulate_bbl),
+ DECODE_SIMULATE (0x0e000000, 0x0a000000, PROBES_BRANCH),
/*
* Supervisor Call, and coprocessor instructions
@@ -721,9 +721,11 @@ static void __kprobes arm_singlestep(struct kprobe *p, struct pt_regs *regs)
* should also be very rare.
*/
enum kprobe_insn __kprobes
-arm_kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi)
+arm_kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi,
+ struct decode_header *actions)
{
asi->insn_singlestep = arm_singlestep;
asi->insn_check_cc = kprobe_condition_checks[insn>>28];
- return kprobe_decode_insn(insn, asi, kprobe_decode_arm_table, false);
+ return kprobe_decode_insn(insn, asi, kprobe_decode_arm_table, false,
+ (const union decode_item *) actions);
}
diff --git a/arch/arm/kernel/probes-arm.h b/arch/arm/kernel/probes-arm.h
index 8608472..f8e0f7a 100644
--- a/arch/arm/kernel/probes-arm.h
+++ b/arch/arm/kernel/probes-arm.h
@@ -15,6 +15,43 @@
#ifndef _ARM_KERNEL_PROBES_ARM_H
#define _ARM_KERNEL_PROBES_ARM_H
+enum probes_arm_action {
+ PROBES_EMULATE_NONE,
+ PROBES_SIMULATE_NOP,
+ PROBES_PRELOAD_IMM,
+ PROBES_PRELOAD_REG,
+ PROBES_BRANCH_IMM,
+ PROBES_BRANCH_REG,
+ PROBES_MRS,
+ PROBES_CLZ,
+ PROBES_SATURATING_ARITHMETIC,
+ PROBES_MUL1,
+ PROBES_MUL2,
+ PROBES_SWP,
+ PROBES_LDRSTRD,
+ PROBES_LOAD,
+ PROBES_STORE,
+ PROBES_LOAD_EXTRA,
+ PROBES_STORE_EXTRA,
+ PROBES_MOV_IP_SP,
+ PROBES_DATA_PROCESSING_REG,
+ PROBES_DATA_PROCESSING_IMM,
+ PROBES_MOV_HALFWORD,
+ PROBES_SEV,
+ PROBES_WFE,
+ PROBES_SATURATE,
+ PROBES_REV,
+ PROBES_MMI,
+ PROBES_PACK,
+ PROBES_EXTEND,
+ PROBES_EXTEND_ADD,
+ PROBES_MUL_ADD_LONG,
+ PROBES_MUL_ADD,
+ PROBES_BITFIELD,
+ PROBES_BRANCH,
+ PROBES_LDMSTM
+};
+
void __kprobes simulate_bbl(struct kprobe *p, struct pt_regs *regs);
void __kprobes simulate_blx1(struct kprobe *p, struct pt_regs *regs);
void __kprobes simulate_blx2bx(struct kprobe *p, struct pt_regs *regs);
diff --git a/arch/arm/kernel/probes-thumb.c b/arch/arm/kernel/probes-thumb.c
index 65fbb4a..bf2f1e9 100644
--- a/arch/arm/kernel/probes-thumb.c
+++ b/arch/arm/kernel/probes-thumb.c
@@ -15,9 +15,6 @@
#include "kprobes.h"
#include "probes-thumb.h"
-/* These emulation encodings are functionally equivalent... */
-#define t32_emulate_rd8rn16rm0ra12_noflags \
- t32_emulate_rdlo12rdhi8rn16rm0_noflags
static const union decode_item t32_table_1110_100x_x0xx[] = {
/* Load/store multiple instructions */
@@ -43,7 +40,7 @@ static const union decode_item t32_table_1110_100x_x0xx[] = {
/* LDMIA 1110 1000 10x1 xxxx xxxx xxxx xxxx xxxx */
/* STMDB 1110 1001 00x0 xxxx xxxx xxxx xxxx xxxx */
/* LDMDB 1110 1001 00x1 xxxx xxxx xxxx xxxx xxxx */
- DECODE_CUSTOM (0xfe400000, 0xe8000000, t32_decode_ldmstm),
+ DECODE_CUSTOM (0xfe400000, 0xe8000000, PROBES_T32_LDMSTM),
DECODE_END
};
@@ -56,12 +53,12 @@ static const union decode_item t32_table_1110_100x_x1xx[] = {
DECODE_OR (0xff600000, 0xe8600000),
/* STRD (immediate) 1110 1001 x1x0 xxxx xxxx xxxx xxxx xxxx */
/* LDRD (immediate) 1110 1001 x1x1 xxxx xxxx xxxx xxxx xxxx */
- DECODE_EMULATEX (0xff400000, 0xe9400000, t32_emulate_ldrdstrd,
+ DECODE_EMULATEX (0xff400000, 0xe9400000, PROBES_T32_LDRDSTRD,
REGS(NOPCWB, NOSPPC, NOSPPC, 0, 0)),
/* TBB 1110 1000 1101 xxxx xxxx xxxx 0000 xxxx */
/* TBH 1110 1000 1101 xxxx xxxx xxxx 0001 xxxx */
- DECODE_SIMULATEX(0xfff000e0, 0xe8d00000, t32_simulate_table_branch,
+ DECODE_SIMULATEX(0xfff000e0, 0xe8d00000, PROBES_T32_TABLE_BRANCH,
REGS(NOSP, 0, 0, 0, NOSPPC)),
/* STREX 1110 1000 0100 xxxx xxxx xxxx xxxx xxxx */
@@ -81,18 +78,18 @@ static const union decode_item t32_table_1110_101x[] = {
/* TST 1110 1010 0001 xxxx xxxx 1111 xxxx xxxx */
/* TEQ 1110 1010 1001 xxxx xxxx 1111 xxxx xxxx */
- DECODE_EMULATEX (0xff700f00, 0xea100f00, t32_emulate_rd8rn16rm0_rwflags,
+ DECODE_EMULATEX (0xff700f00, 0xea100f00, PROBES_T32_TST,
REGS(NOSPPC, 0, 0, 0, NOSPPC)),
/* CMN 1110 1011 0001 xxxx xxxx 1111 xxxx xxxx */
DECODE_OR (0xfff00f00, 0xeb100f00),
/* CMP 1110 1011 1011 xxxx xxxx 1111 xxxx xxxx */
- DECODE_EMULATEX (0xfff00f00, 0xebb00f00, t32_emulate_rd8rn16rm0_rwflags,
+ DECODE_EMULATEX (0xfff00f00, 0xebb00f00, PROBES_T32_TST,
REGS(NOPC, 0, 0, 0, NOSPPC)),
/* MOV 1110 1010 010x 1111 xxxx xxxx xxxx xxxx */
/* MVN 1110 1010 011x 1111 xxxx xxxx xxxx xxxx */
- DECODE_EMULATEX (0xffcf0000, 0xea4f0000, t32_emulate_rd8rn16rm0_rwflags,
+ DECODE_EMULATEX (0xffcf0000, 0xea4f0000, PROBES_T32_MOV,
REGS(0, 0, NOSPPC, 0, NOSPPC)),
/* ??? 1110 1010 101x xxxx xxxx xxxx xxxx xxxx */
@@ -107,7 +104,7 @@ static const union decode_item t32_table_1110_101x[] = {
/* ADD/SUB SP, SP, Rm, LSL #0..3 */
/* 1110 1011 x0xx 1101 x000 1101 xx00 xxxx */
- DECODE_EMULATEX (0xff4f7f30, 0xeb0d0d00, t32_emulate_rd8rn16rm0_rwflags,
+ DECODE_EMULATEX (0xff4f7f30, 0xeb0d0d00, PROBES_T32_ADDSUB,
REGS(SP, 0, SP, 0, NOSPPC)),
/* ADD/SUB SP, SP, Rm, shift */
@@ -116,7 +113,7 @@ static const union decode_item t32_table_1110_101x[] = {
/* ADD/SUB Rd, SP, Rm, shift */
/* 1110 1011 x0xx 1101 xxxx xxxx xxxx xxxx */
- DECODE_EMULATEX (0xff4f0000, 0xeb0d0000, t32_emulate_rd8rn16rm0_rwflags,
+ DECODE_EMULATEX (0xff4f0000, 0xeb0d0000, PROBES_T32_ADDSUB,
REGS(SP, 0, NOPC, 0, NOSPPC)),
/* AND 1110 1010 000x xxxx xxxx xxxx xxxx xxxx */
@@ -130,7 +127,7 @@ static const union decode_item t32_table_1110_101x[] = {
/* SBC 1110 1011 011x xxxx xxxx xxxx xxxx xxxx */
/* SUB 1110 1011 101x xxxx xxxx xxxx xxxx xxxx */
/* RSB 1110 1011 110x xxxx xxxx xxxx xxxx xxxx */
- DECODE_EMULATEX (0xfe000000, 0xea000000, t32_emulate_rd8rn16rm0_rwflags,
+ DECODE_EMULATEX (0xfe000000, 0xea000000, PROBES_T32_LOGICAL,
REGS(NOSPPC, 0, NOSPPC, 0, NOSPPC)),
DECODE_END
@@ -141,18 +138,18 @@ static const union decode_item t32_table_1111_0x0x___0[] = {
/* TST 1111 0x00 0001 xxxx 0xxx 1111 xxxx xxxx */
/* TEQ 1111 0x00 1001 xxxx 0xxx 1111 xxxx xxxx */
- DECODE_EMULATEX (0xfb708f00, 0xf0100f00, t32_emulate_rd8rn16rm0_rwflags,
+ DECODE_EMULATEX (0xfb708f00, 0xf0100f00, PROBES_T32_TST,
REGS(NOSPPC, 0, 0, 0, 0)),
/* CMN 1111 0x01 0001 xxxx 0xxx 1111 xxxx xxxx */
DECODE_OR (0xfbf08f00, 0xf1100f00),
/* CMP 1111 0x01 1011 xxxx 0xxx 1111 xxxx xxxx */
- DECODE_EMULATEX (0xfbf08f00, 0xf1b00f00, t32_emulate_rd8rn16rm0_rwflags,
+ DECODE_EMULATEX (0xfbf08f00, 0xf1b00f00, PROBES_T32_CMP,
REGS(NOPC, 0, 0, 0, 0)),
/* MOV 1111 0x00 010x 1111 0xxx xxxx xxxx xxxx */
/* MVN 1111 0x00 011x 1111 0xxx xxxx xxxx xxxx */
- DECODE_EMULATEX (0xfbcf8000, 0xf04f0000, t32_emulate_rd8rn16rm0_rwflags,
+ DECODE_EMULATEX (0xfbcf8000, 0xf04f0000, PROBES_T32_MOV,
REGS(0, 0, NOSPPC, 0, 0)),
/* ??? 1111 0x00 101x xxxx 0xxx xxxx xxxx xxxx */
@@ -169,7 +166,7 @@ static const union decode_item t32_table_1111_0x0x___0[] = {
/* ADD Rd, SP, #imm 1111 0x01 000x 1101 0xxx xxxx xxxx xxxx */
/* SUB Rd, SP, #imm 1111 0x01 101x 1101 0xxx xxxx xxxx xxxx */
- DECODE_EMULATEX (0xfb4f8000, 0xf10d0000, t32_emulate_rd8rn16rm0_rwflags,
+ DECODE_EMULATEX (0xfb4f8000, 0xf10d0000, PROBES_T32_ADDSUB,
REGS(SP, 0, NOPC, 0, 0)),
/* AND 1111 0x00 000x xxxx 0xxx xxxx xxxx xxxx */
@@ -182,7 +179,7 @@ static const union decode_item t32_table_1111_0x0x___0[] = {
/* SBC 1111 0x01 011x xxxx 0xxx xxxx xxxx xxxx */
/* SUB 1111 0x01 101x xxxx 0xxx xxxx xxxx xxxx */
/* RSB 1111 0x01 110x xxxx 0xxx xxxx xxxx xxxx */
- DECODE_EMULATEX (0xfa008000, 0xf0000000, t32_emulate_rd8rn16rm0_rwflags,
+ DECODE_EMULATEX (0xfa008000, 0xf0000000, PROBES_T32_LOGICAL,
REGS(NOSPPC, 0, NOSPPC, 0, 0)),
DECODE_END
@@ -194,44 +191,44 @@ static const union decode_item t32_table_1111_0x1x___0[] = {
/* ADDW Rd, PC, #imm 1111 0x10 0000 1111 0xxx xxxx xxxx xxxx */
DECODE_OR (0xfbff8000, 0xf20f0000),
/* SUBW Rd, PC, #imm 1111 0x10 1010 1111 0xxx xxxx xxxx xxxx */
- DECODE_EMULATEX (0xfbff8000, 0xf2af0000, t32_emulate_rd8pc16_noflags,
+ DECODE_EMULATEX (0xfbff8000, 0xf2af0000, PROBES_T32_ADDWSUBW_PC,
REGS(PC, 0, NOSPPC, 0, 0)),
/* ADDW SP, SP, #imm 1111 0x10 0000 1101 0xxx 1101 xxxx xxxx */
DECODE_OR (0xfbff8f00, 0xf20d0d00),
/* SUBW SP, SP, #imm 1111 0x10 1010 1101 0xxx 1101 xxxx xxxx */
- DECODE_EMULATEX (0xfbff8f00, 0xf2ad0d00, t32_emulate_rd8rn16_noflags,
+ DECODE_EMULATEX (0xfbff8f00, 0xf2ad0d00, PROBES_T32_ADDWSUBW,
REGS(SP, 0, SP, 0, 0)),
/* ADDW 1111 0x10 0000 xxxx 0xxx xxxx xxxx xxxx */
DECODE_OR (0xfbf08000, 0xf2000000),
/* SUBW 1111 0x10 1010 xxxx 0xxx xxxx xxxx xxxx */
- DECODE_EMULATEX (0xfbf08000, 0xf2a00000, t32_emulate_rd8rn16_noflags,
+ DECODE_EMULATEX (0xfbf08000, 0xf2a00000, PROBES_T32_ADDWSUBW,
REGS(NOPCX, 0, NOSPPC, 0, 0)),
/* MOVW 1111 0x10 0100 xxxx 0xxx xxxx xxxx xxxx */
/* MOVT 1111 0x10 1100 xxxx 0xxx xxxx xxxx xxxx */
- DECODE_EMULATEX (0xfb708000, 0xf2400000, t32_emulate_rd8rn16_noflags,
+ DECODE_EMULATEX (0xfb708000, 0xf2400000, PROBES_T32_MOVW,
REGS(0, 0, NOSPPC, 0, 0)),
/* SSAT16 1111 0x11 0010 xxxx 0000 xxxx 00xx xxxx */
/* SSAT 1111 0x11 00x0 xxxx 0xxx xxxx xxxx xxxx */
/* USAT16 1111 0x11 1010 xxxx 0000 xxxx 00xx xxxx */
/* USAT 1111 0x11 10x0 xxxx 0xxx xxxx xxxx xxxx */
- DECODE_EMULATEX (0xfb508000, 0xf3000000, t32_emulate_rd8rn16rm0_rwflags,
+ DECODE_EMULATEX (0xfb508000, 0xf3000000, PROBES_T32_SAT,
REGS(NOSPPC, 0, NOSPPC, 0, 0)),
/* SFBX 1111 0x11 0100 xxxx 0xxx xxxx xxxx xxxx */
/* UFBX 1111 0x11 1100 xxxx 0xxx xxxx xxxx xxxx */
- DECODE_EMULATEX (0xfb708000, 0xf3400000, t32_emulate_rd8rn16_noflags,
+ DECODE_EMULATEX (0xfb708000, 0xf3400000, PROBES_T32_BITFIELD,
REGS(NOSPPC, 0, NOSPPC, 0, 0)),
/* BFC 1111 0x11 0110 1111 0xxx xxxx xxxx xxxx */
- DECODE_EMULATEX (0xfbff8000, 0xf36f0000, t32_emulate_rd8rn16_noflags,
+ DECODE_EMULATEX (0xfbff8000, 0xf36f0000, PROBES_T32_BITFIELD,
REGS(0, 0, NOSPPC, 0, 0)),
/* BFI 1111 0x11 0110 xxxx 0xxx xxxx xxxx xxxx */
- DECODE_EMULATEX (0xfbf08000, 0xf3600000, t32_emulate_rd8rn16_noflags,
+ DECODE_EMULATEX (0xfbf08000, 0xf3600000, PROBES_T32_BITFIELD,
REGS(NOSPPCX, 0, NOSPPC, 0, 0)),
DECODE_END
@@ -243,14 +240,14 @@ static const union decode_item t32_table_1111_0xxx___1[] = {
/* YIELD 1111 0011 1010 xxxx 10x0 x000 0000 0001 */
DECODE_OR (0xfff0d7ff, 0xf3a08001),
/* SEV 1111 0011 1010 xxxx 10x0 x000 0000 0100 */
- DECODE_EMULATE (0xfff0d7ff, 0xf3a08004, kprobe_emulate_none),
+ DECODE_EMULATE (0xfff0d7ff, 0xf3a08004, PROBES_T32_SEV),
/* NOP 1111 0011 1010 xxxx 10x0 x000 0000 0000 */
/* WFE 1111 0011 1010 xxxx 10x0 x000 0000 0010 */
/* WFI 1111 0011 1010 xxxx 10x0 x000 0000 0011 */
- DECODE_SIMULATE (0xfff0d7fc, 0xf3a08000, kprobe_simulate_nop),
+ DECODE_SIMULATE (0xfff0d7fc, 0xf3a08000, PROBES_T32_WFE),
/* MRS Rd, CPSR 1111 0011 1110 xxxx 10x0 xxxx xxxx xxxx */
- DECODE_SIMULATEX(0xfff0d000, 0xf3e08000, t32_simulate_mrs,
+ DECODE_SIMULATEX(0xfff0d000, 0xf3e08000, PROBES_T32_MRS,
REGS(0, 0, NOSPPC, 0, 0)),
/*
@@ -272,13 +269,13 @@ static const union decode_item t32_table_1111_0xxx___1[] = {
DECODE_REJECT (0xfb80d000, 0xf3808000),
/* Bcc 1111 0xxx xxxx xxxx 10x0 xxxx xxxx xxxx */
- DECODE_CUSTOM (0xf800d000, 0xf0008000, t32_decode_cond_branch),
+ DECODE_CUSTOM (0xf800d000, 0xf0008000, PROBES_T32_BRANCH_COND),
/* BLX 1111 0xxx xxxx xxxx 11x0 xxxx xxxx xxx0 */
DECODE_OR (0xf800d001, 0xf000c000),
/* B 1111 0xxx xxxx xxxx 10x1 xxxx xxxx xxxx */
/* BL 1111 0xxx xxxx xxxx 11x1 xxxx xxxx xxxx */
- DECODE_SIMULATE (0xf8009000, 0xf0009000, t32_simulate_branch),
+ DECODE_SIMULATE (0xf8009000, 0xf0009000, PROBES_T32_BRANCH),
DECODE_END
};
@@ -288,7 +285,7 @@ static const union decode_item t32_table_1111_100x_x0x1__1111[] = {
/* PLD (literal) 1111 1000 x001 1111 1111 xxxx xxxx xxxx */
/* PLI (literal) 1111 1001 x001 1111 1111 xxxx xxxx xxxx */
- DECODE_SIMULATE (0xfe7ff000, 0xf81ff000, kprobe_simulate_nop),
+ DECODE_SIMULATE (0xfe7ff000, 0xf81ff000, PROBES_T32_PLDI),
/* PLD{W} (immediate) 1111 1000 10x1 xxxx 1111 xxxx xxxx xxxx */
DECODE_OR (0xffd0f000, 0xf890f000),
@@ -297,13 +294,13 @@ static const union decode_item t32_table_1111_100x_x0x1__1111[] = {
/* PLI (immediate) 1111 1001 1001 xxxx 1111 xxxx xxxx xxxx */
DECODE_OR (0xfff0f000, 0xf990f000),
/* PLI (immediate) 1111 1001 0001 xxxx 1111 1100 xxxx xxxx */
- DECODE_SIMULATEX(0xfff0ff00, 0xf910fc00, kprobe_simulate_nop,
+ DECODE_SIMULATEX(0xfff0ff00, 0xf910fc00, PROBES_T32_PLDI,
REGS(NOPCX, 0, 0, 0, 0)),
/* PLD{W} (register) 1111 1000 00x1 xxxx 1111 0000 00xx xxxx */
DECODE_OR (0xffd0ffc0, 0xf810f000),
/* PLI (register) 1111 1001 0001 xxxx 1111 0000 00xx xxxx */
- DECODE_SIMULATEX(0xfff0ffc0, 0xf910f000, kprobe_simulate_nop,
+ DECODE_SIMULATEX(0xfff0ffc0, 0xf910f000, PROBES_T32_PLDI,
REGS(NOPCX, 0, 0, 0, NOSPPC)),
/* Other unallocated instructions... */
@@ -339,7 +336,7 @@ static const union decode_item t32_table_1111_100x[] = {
DECODE_REJECT (0xff10f000, 0xf800f000),
/* LDR (literal) 1111 1000 x101 1111 xxxx xxxx xxxx xxxx */
- DECODE_SIMULATEX(0xff7f0000, 0xf85f0000, t32_simulate_ldr_literal,
+ DECODE_SIMULATEX(0xff7f0000, 0xf85f0000, PROBES_T32_LDR_LIT,
REGS(PC, ANY, 0, 0, 0)),
/* STR (immediate) 1111 1000 0100 xxxx xxxx 1xxx xxxx xxxx */
@@ -347,19 +344,19 @@ static const union decode_item t32_table_1111_100x[] = {
DECODE_OR (0xffe00800, 0xf8400800),
/* STR (immediate) 1111 1000 1100 xxxx xxxx xxxx xxxx xxxx */
/* LDR (immediate) 1111 1000 1101 xxxx xxxx xxxx xxxx xxxx */
- DECODE_EMULATEX (0xffe00000, 0xf8c00000, t32_emulate_ldrstr,
+ DECODE_EMULATEX (0xffe00000, 0xf8c00000, PROBES_T32_LDRSTR,
REGS(NOPCX, ANY, 0, 0, 0)),
/* STR (register) 1111 1000 0100 xxxx xxxx 0000 00xx xxxx */
/* LDR (register) 1111 1000 0101 xxxx xxxx 0000 00xx xxxx */
- DECODE_EMULATEX (0xffe00fc0, 0xf8400000, t32_emulate_ldrstr,
+ DECODE_EMULATEX (0xffe00fc0, 0xf8400000, PROBES_T32_LDRSTR,
REGS(NOPCX, ANY, 0, 0, NOSPPC)),
/* LDRB (literal) 1111 1000 x001 1111 xxxx xxxx xxxx xxxx */
/* LDRSB (literal) 1111 1001 x001 1111 xxxx xxxx xxxx xxxx */
/* LDRH (literal) 1111 1000 x011 1111 xxxx xxxx xxxx xxxx */
/* LDRSH (literal) 1111 1001 x011 1111 xxxx xxxx xxxx xxxx */
- DECODE_SIMULATEX(0xfe5f0000, 0xf81f0000, t32_simulate_ldr_literal,
+ DECODE_SIMULATEX(0xfe5f0000, 0xf81f0000, PROBES_T32_LDR_LIT,
REGS(PC, NOSPPCX, 0, 0, 0)),
/* STRB (immediate) 1111 1000 0000 xxxx xxxx 1xxx xxxx xxxx */
@@ -375,7 +372,7 @@ static const union decode_item t32_table_1111_100x[] = {
/* LDRSB (immediate) 1111 1001 1001 xxxx xxxx xxxx xxxx xxxx */
/* LDRH (immediate) 1111 1000 1011 xxxx xxxx xxxx xxxx xxxx */
/* LDRSH (immediate) 1111 1001 1011 xxxx xxxx xxxx xxxx xxxx */
- DECODE_EMULATEX (0xfec00000, 0xf8800000, t32_emulate_ldrstr,
+ DECODE_EMULATEX (0xfec00000, 0xf8800000, PROBES_T32_LDRSTR,
REGS(NOPCX, NOSPPCX, 0, 0, 0)),
/* STRB (register) 1111 1000 0000 xxxx xxxx 0000 00xx xxxx */
@@ -384,7 +381,7 @@ static const union decode_item t32_table_1111_100x[] = {
/* LDRSB (register) 1111 1001 0001 xxxx xxxx 0000 00xx xxxx */
/* LDRH (register) 1111 1000 0011 xxxx xxxx 0000 00xx xxxx */
/* LDRSH (register) 1111 1001 0011 xxxx xxxx 0000 00xx xxxx */
- DECODE_EMULATEX (0xfe800fc0, 0xf8000000, t32_emulate_ldrstr,
+ DECODE_EMULATEX (0xfe800fc0, 0xf8000000, PROBES_T32_LDRSTR,
REGS(NOPCX, NOSPPCX, 0, 0, NOSPPC)),
/* Other unallocated instructions... */
@@ -403,7 +400,7 @@ static const union decode_item t32_table_1111_1010___1111[] = {
/* UXTB16 1111 1010 0011 1111 1111 xxxx 1xxx xxxx */
/* SXTB 1111 1010 0100 1111 1111 xxxx 1xxx xxxx */
/* UXTB 1111 1010 0101 1111 1111 xxxx 1xxx xxxx */
- DECODE_EMULATEX (0xff8ff080, 0xfa0ff080, t32_emulate_rd8rn16rm0_rwflags,
+ DECODE_EMULATEX (0xff8ff080, 0xfa0ff080, PROBES_T32_SIGN_EXTEND,
REGS(0, 0, NOSPPC, 0, NOSPPC)),
@@ -476,7 +473,7 @@ static const union decode_item t32_table_1111_1010___1111[] = {
/* LSR 1111 1010 001x xxxx 1111 xxxx 0000 xxxx */
/* ASR 1111 1010 010x xxxx 1111 xxxx 0000 xxxx */
/* ROR 1111 1010 011x xxxx 1111 xxxx 0000 xxxx */
- DECODE_EMULATEX (0xff80f0f0, 0xfa00f000, t32_emulate_rd8rn16rm0_rwflags,
+ DECODE_EMULATEX (0xff80f0f0, 0xfa00f000, PROBES_T32_MEDIA,
REGS(NOSPPC, 0, NOSPPC, 0, NOSPPC)),
/* CLZ 1111 1010 1010 xxxx 1111 xxxx 1000 xxxx */
@@ -486,7 +483,7 @@ static const union decode_item t32_table_1111_1010___1111[] = {
/* REV16 1111 1010 1001 xxxx 1111 xxxx 1001 xxxx */
/* RBIT 1111 1010 1001 xxxx 1111 xxxx 1010 xxxx */
/* REVSH 1111 1010 1001 xxxx 1111 xxxx 1011 xxxx */
- DECODE_EMULATEX (0xfff0f0c0, 0xfa90f080, t32_emulate_rd8rn16_noflags,
+ DECODE_EMULATEX (0xfff0f0c0, 0xfa90f080, PROBES_T32_REVERSE,
REGS(NOSPPC, 0, NOSPPC, 0, SAMEAS16)),
/* Other unallocated instructions... */
@@ -509,7 +506,7 @@ static const union decode_item t32_table_1111_1011_0[] = {
/* SMUSD{X} 1111 1011 0100 xxxx 1111 xxxx 000x xxxx */
/* SMMUL{R} 1111 1011 0101 xxxx 1111 xxxx 000x xxxx */
/* USAD8 1111 1011 0111 xxxx 1111 xxxx 0000 xxxx */
- DECODE_EMULATEX (0xff80f0e0, 0xfb00f000, t32_emulate_rd8rn16rm0_rwflags,
+ DECODE_EMULATEX (0xff80f0e0, 0xfb00f000, PROBES_T32_MUL_ADD,
REGS(NOSPPC, 0, NOSPPC, 0, NOSPPC)),
/* ??? 1111 1011 0111 xxxx xxxx xxxx 0001 xxxx */
@@ -525,7 +522,7 @@ static const union decode_item t32_table_1111_1011_0[] = {
/* SMMLA{R} 1111 1011 0101 xxxx xxxx xxxx 000x xxxx */
/* SMMLS{R} 1111 1011 0110 xxxx xxxx xxxx 000x xxxx */
/* USADA8 1111 1011 0111 xxxx xxxx xxxx 0000 xxxx */
- DECODE_EMULATEX (0xff8000c0, 0xfb000000, t32_emulate_rd8rn16rm0ra12_noflags,
+ DECODE_EMULATEX (0xff8000c0, 0xfb000000, PROBES_T32_MUL_ADD2,
REGS(NOSPPC, NOSPPCX, NOSPPC, 0, NOSPPC)),
/* Other unallocated instructions... */
@@ -546,7 +543,7 @@ static const union decode_item t32_table_1111_1011_1[] = {
/* UMULL 1111 1011 1010 xxxx xxxx xxxx 0000 xxxx */
/* SMLAL 1111 1011 1100 xxxx xxxx xxxx 0000 xxxx */
/* UMLAL 1111 1011 1110 xxxx xxxx xxxx 0000 xxxx */
- DECODE_EMULATEX (0xff9000f0, 0xfb800000, t32_emulate_rdlo12rdhi8rn16rm0_noflags,
+ DECODE_EMULATEX (0xff9000f0, 0xfb800000, PROBES_T32_MUL_ADD_LONG,
REGS(NOSPPC, NOSPPC, NOSPPC, 0, NOSPPC)),
/* SDIV 1111 1011 1001 xxxx xxxx xxxx 1111 xxxx */
@@ -646,17 +643,16 @@ const union decode_item kprobe_decode_thumb32_table[] = {
#ifdef CONFIG_ARM_KPROBES_TEST_MODULE
EXPORT_SYMBOL_GPL(kprobe_decode_thumb32_table);
#endif
-
static const union decode_item t16_table_1011[] = {
/* Miscellaneous 16-bit instructions */
/* ADD (SP plus immediate) 1011 0000 0xxx xxxx */
/* SUB (SP minus immediate) 1011 0000 1xxx xxxx */
- DECODE_SIMULATE (0xff00, 0xb000, t16_simulate_add_sp_imm),
+ DECODE_SIMULATE (0xff00, 0xb000, PROBES_T16_ADD_SP),
/* CBZ 1011 00x1 xxxx xxxx */
/* CBNZ 1011 10x1 xxxx xxxx */
- DECODE_SIMULATE (0xf500, 0xb100, t16_simulate_cbz),
+ DECODE_SIMULATE (0xf500, 0xb100, PROBES_T16_CBZ),
/* SXTH 1011 0010 00xx xxxx */
/* SXTB 1011 0010 01xx xxxx */
@@ -667,12 +663,12 @@ static const union decode_item t16_table_1011[] = {
/* ??? 1011 1010 10xx xxxx */
/* REVSH 1011 1010 11xx xxxx */
DECODE_REJECT (0xffc0, 0xba80),
- DECODE_EMULATE (0xf500, 0xb000, t16_emulate_loregs_rwflags),
+ DECODE_EMULATE (0xf500, 0xb000, PROBES_T16_SIGN_EXTEND),
/* PUSH 1011 010x xxxx xxxx */
- DECODE_CUSTOM (0xfe00, 0xb400, t16_decode_push),
+ DECODE_CUSTOM (0xfe00, 0xb400, PROBES_T16_PUSH),
/* POP 1011 110x xxxx xxxx */
- DECODE_CUSTOM (0xfe00, 0xbc00, t16_decode_pop),
+ DECODE_CUSTOM (0xfe00, 0xbc00, PROBES_T16_POP),
/*
* If-Then, and hints
@@ -682,15 +678,15 @@ static const union decode_item t16_table_1011[] = {
/* YIELD 1011 1111 0001 0000 */
DECODE_OR (0xffff, 0xbf10),
/* SEV 1011 1111 0100 0000 */
- DECODE_EMULATE (0xffff, 0xbf40, kprobe_emulate_none),
+ DECODE_EMULATE (0xffff, 0xbf40, PROBES_T16_SEV),
/* NOP 1011 1111 0000 0000 */
/* WFE 1011 1111 0010 0000 */
/* WFI 1011 1111 0011 0000 */
- DECODE_SIMULATE (0xffcf, 0xbf00, kprobe_simulate_nop),
+ DECODE_SIMULATE (0xffcf, 0xbf00, PROBES_T16_WFE),
/* Unassigned hints 1011 1111 xxxx 0000 */
DECODE_REJECT (0xff0f, 0xbf00),
/* IT 1011 1111 xxxx xxxx */
- DECODE_CUSTOM (0xff00, 0xbf00, t16_decode_it),
+ DECODE_CUSTOM (0xff00, 0xbf00, PROBES_T16_IT),
/* SETEND 1011 0110 010x xxxx */
/* CPS 1011 0110 011x xxxx */
@@ -707,7 +703,7 @@ const union decode_item kprobe_decode_thumb16_table[] = {
*/
/* CMP (immediate) 0010 1xxx xxxx xxxx */
- DECODE_EMULATE (0xf800, 0x2800, t16_emulate_loregs_rwflags),
+ DECODE_EMULATE (0xf800, 0x2800, PROBES_T16_CMP),
/* ADD (register) 0001 100x xxxx xxxx */
/* SUB (register) 0001 101x xxxx xxxx */
@@ -719,7 +715,7 @@ const union decode_item kprobe_decode_thumb16_table[] = {
/* MOV (immediate) 0010 0xxx xxxx xxxx */
/* ADD (immediate, Thumb) 0011 0xxx xxxx xxxx */
/* SUB (immediate, Thumb) 0011 1xxx xxxx xxxx */
- DECODE_EMULATE (0xc000, 0x0000, t16_emulate_loregs_noitrwflags),
+ DECODE_EMULATE (0xc000, 0x0000, PROBES_T16_ADDSUB),
/*
* 16-bit Thumb data-processing instructions
@@ -727,10 +723,10 @@ const union decode_item kprobe_decode_thumb16_table[] = {
*/
/* TST (register) 0100 0010 00xx xxxx */
- DECODE_EMULATE (0xffc0, 0x4200, t16_emulate_loregs_rwflags),
+ DECODE_EMULATE (0xffc0, 0x4200, PROBES_T16_CMP),
/* CMP (register) 0100 0010 10xx xxxx */
/* CMN (register) 0100 0010 11xx xxxx */
- DECODE_EMULATE (0xff80, 0x4280, t16_emulate_loregs_rwflags),
+ DECODE_EMULATE (0xff80, 0x4280, PROBES_T16_CMP),
/* AND (register) 0100 0000 00xx xxxx */
/* EOR (register) 0100 0000 01xx xxxx */
/* LSL (register) 0100 0000 10xx xxxx */
@@ -744,7 +740,7 @@ const union decode_item kprobe_decode_thumb16_table[] = {
/* MUL 0100 0011 00xx xxxx */
/* BIC (register) 0100 0011 10xx xxxx */
/* MVN (register) 0100 0011 10xx xxxx */
- DECODE_EMULATE (0xfc00, 0x4000, t16_emulate_loregs_noitrwflags),
+ DECODE_EMULATE (0xfc00, 0x4000, PROBES_T16_LOGICAL),
/*
* Special data instructions and branch and exchange
@@ -756,7 +752,7 @@ const union decode_item kprobe_decode_thumb16_table[] = {
/* BX (register) 0100 0111 0xxx xxxx */
/* BLX (register) 0100 0111 1xxx xxxx */
- DECODE_SIMULATE (0xff00, 0x4700, t16_simulate_bxblx),
+ DECODE_SIMULATE (0xff00, 0x4700, PROBES_T16_BLX),
/* ADD pc, pc 0100 0100 1111 1111 */
DECODE_REJECT (0xffff, 0x44ff),
@@ -764,13 +760,13 @@ const union decode_item kprobe_decode_thumb16_table[] = {
/* ADD (register) 0100 0100 xxxx xxxx */
/* CMP (register) 0100 0101 xxxx xxxx */
/* MOV (register) 0100 0110 xxxx xxxx */
- DECODE_CUSTOM (0xfc00, 0x4400, t16_decode_hiregs),
+ DECODE_CUSTOM (0xfc00, 0x4400, PROBES_T16_HIREGOPS),
/*
* Load from Literal Pool
* LDR (literal) 0100 1xxx xxxx xxxx
*/
- DECODE_SIMULATE (0xf800, 0x4800, t16_simulate_ldr_literal),
+ DECODE_SIMULATE (0xf800, 0x4800, PROBES_T16_LDR_LIT),
/*
* 16-bit Thumb Load/store instructions
@@ -791,20 +787,20 @@ const union decode_item kprobe_decode_thumb16_table[] = {
/* LDR (immediate, Thumb) 0110 1xxx xxxx xxxx */
/* STRB (immediate, Thumb) 0111 0xxx xxxx xxxx */
/* LDRB (immediate, Thumb) 0111 1xxx xxxx xxxx */
- DECODE_EMULATE (0xc000, 0x4000, t16_emulate_loregs_rwflags),
+ DECODE_EMULATE (0xc000, 0x4000, PROBES_T16_LDRHSTRH),
/* STRH (immediate, Thumb) 1000 0xxx xxxx xxxx */
/* LDRH (immediate, Thumb) 1000 1xxx xxxx xxxx */
- DECODE_EMULATE (0xf000, 0x8000, t16_emulate_loregs_rwflags),
+ DECODE_EMULATE (0xf000, 0x8000, PROBES_T16_LDRHSTRH),
/* STR (immediate, Thumb) 1001 0xxx xxxx xxxx */
/* LDR (immediate, Thumb) 1001 1xxx xxxx xxxx */
- DECODE_SIMULATE (0xf000, 0x9000, t16_simulate_ldrstr_sp_relative),
+ DECODE_SIMULATE (0xf000, 0x9000, PROBES_T16_LDRSTR),
/*
* Generate PC-/SP-relative address
* ADR (literal) 1010 0xxx xxxx xxxx
* ADD (SP plus immediate) 1010 1xxx xxxx xxxx
*/
- DECODE_SIMULATE (0xf000, 0xa000, t16_simulate_reladr),
+ DECODE_SIMULATE (0xf000, 0xa000, PROBES_T16_ADR),
/*
* Miscellaneous 16-bit instructions
@@ -814,7 +810,7 @@ const union decode_item kprobe_decode_thumb16_table[] = {
/* STM 1100 0xxx xxxx xxxx */
/* LDM 1100 1xxx xxxx xxxx */
- DECODE_EMULATE (0xf000, 0xc000, t16_emulate_loregs_rwflags),
+ DECODE_EMULATE (0xf000, 0xc000, PROBES_T16_LDMSTM),
/*
* Conditional branch, and Supervisor Call
@@ -825,19 +821,16 @@ const union decode_item kprobe_decode_thumb16_table[] = {
DECODE_REJECT (0xfe00, 0xde00),
/* Conditional branch 1101 xxxx xxxx xxxx */
- DECODE_CUSTOM (0xf000, 0xd000, t16_decode_cond_branch),
+ DECODE_CUSTOM (0xf000, 0xd000, PROBES_T16_BRANCH_COND),
/*
* Unconditional branch
* B 1110 0xxx xxxx xxxx
*/
- DECODE_SIMULATE (0xf800, 0xe000, t16_simulate_branch),
+ DECODE_SIMULATE (0xf800, 0xe000, PROBES_T16_BRANCH),
DECODE_END
};
-#ifdef CONFIG_ARM_KPROBES_TEST_MODULE
-EXPORT_SYMBOL_GPL(kprobe_decode_thumb16_table);
-#endif
static unsigned long __kprobes thumb_check_cc(unsigned long cpsr)
{
@@ -861,17 +854,21 @@ static void __kprobes thumb32_singlestep(struct kprobe *p, struct pt_regs *regs)
}
enum kprobe_insn __kprobes
-thumb16_kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi)
+thumb16_kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi,
+ struct decode_header *actions)
{
asi->insn_singlestep = thumb16_singlestep;
asi->insn_check_cc = thumb_check_cc;
- return kprobe_decode_insn(insn, asi, kprobe_decode_thumb16_table, true);
+ return kprobe_decode_insn(insn, asi, kprobe_decode_thumb16_table, true,
+ (const union decode_item *) actions);
}
enum kprobe_insn __kprobes
-thumb32_kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi)
+thumb32_kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi,
+ struct decode_header *actions)
{
asi->insn_singlestep = thumb32_singlestep;
asi->insn_check_cc = thumb_check_cc;
- return kprobe_decode_insn(insn, asi, kprobe_decode_thumb32_table, true);
+ return kprobe_decode_insn(insn, asi, kprobe_decode_thumb32_table, true,
+ (const union decode_item *) actions);
}
diff --git a/arch/arm/kernel/probes-thumb.h b/arch/arm/kernel/probes-thumb.h
index 3f39210..381ad3a 100644
--- a/arch/arm/kernel/probes-thumb.h
+++ b/arch/arm/kernel/probes-thumb.h
@@ -92,10 +92,10 @@ void __kprobes t16_simulate_cbz(struct kprobe *p, struct pt_regs *regs);
void __kprobes t16_simulate_it(struct kprobe *p, struct pt_regs *regs);
void __kprobes t16_singlestep_it(struct kprobe *p, struct pt_regs *regs);
enum kprobe_insn __kprobes t16_decode_it(kprobe_opcode_t insn,
- struct arch_specific_insn *asi);
+ struct arch_specific_insn *asi, struct decode_header *d);
void __kprobes t16_simulate_cond_branch(struct kprobe *p, struct pt_regs *regs);
enum kprobe_insn __kprobes t16_decode_cond_branch(kprobe_opcode_t insn,
- struct arch_specific_insn *asi);
+ struct arch_specific_insn *asi, struct decode_header *d);
void __kprobes t16_simulate_branch(struct kprobe *p, struct pt_regs *regs);
void __kprobes t16_emulate_loregs_rwflags(struct kprobe *p,
struct pt_regs *regs);
@@ -103,25 +103,25 @@ void __kprobes t16_emulate_loregs_noitrwflags(struct kprobe *p,
struct pt_regs *regs);
void __kprobes t16_emulate_hiregs(struct kprobe *p, struct pt_regs *regs);
enum kprobe_insn __kprobes t16_decode_hiregs(kprobe_opcode_t insn,
- struct arch_specific_insn *asi);
+ struct arch_specific_insn *asi, struct decode_header *d);
void __kprobes t16_emulate_push(struct kprobe *p, struct pt_regs *regs);
enum kprobe_insn __kprobes t16_decode_push(kprobe_opcode_t insn,
- struct arch_specific_insn *asi);
+ struct arch_specific_insn *asi, struct decode_header *d);
void __kprobes t16_emulate_pop_nopc(struct kprobe *p, struct pt_regs *regs);
void __kprobes t16_emulate_pop_pc(struct kprobe *p, struct pt_regs *regs);
enum kprobe_insn __kprobes t16_decode_pop(kprobe_opcode_t insn,
- struct arch_specific_insn *asi);
+ struct arch_specific_insn *asi, struct decode_header *d);
void __kprobes t32_simulate_table_branch(struct kprobe *p,
struct pt_regs *regs);
void __kprobes t32_simulate_mrs(struct kprobe *p, struct pt_regs *regs);
void __kprobes t32_simulate_cond_branch(struct kprobe *p, struct pt_regs *regs);
enum kprobe_insn __kprobes t32_decode_cond_branch(kprobe_opcode_t insn,
- struct arch_specific_insn *asi);
+ struct arch_specific_insn *asi, struct decode_header *d);
void __kprobes t32_simulate_branch(struct kprobe *p, struct pt_regs *regs);
void __kprobes t32_simulate_ldr_literal(struct kprobe *p, struct pt_regs *regs);
enum kprobe_insn __kprobes t32_decode_ldmstm(kprobe_opcode_t insn,
- struct arch_specific_insn *asi);
+ struct arch_specific_insn *asi, struct decode_header *d);
void __kprobes t32_emulate_ldrdstrd(struct kprobe *p, struct pt_regs *regs);
void __kprobes t32_emulate_ldrstr(struct kprobe *p, struct pt_regs *regs);
void __kprobes t32_emulate_rd8rn16rm0_rwflags(struct kprobe *p,
diff --git a/arch/arm/kernel/probes.c b/arch/arm/kernel/probes.c
index 839bf97..1bcf5da 100644
--- a/arch/arm/kernel/probes.c
+++ b/arch/arm/kernel/probes.c
@@ -378,10 +378,11 @@ static const int decode_struct_sizes[NUM_DECODE_TYPES] = {
*/
int __kprobes
kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi,
- const union decode_item *table, bool thumb)
+ const union decode_item *table, bool thumb,
+ const union decode_item *actions)
{
- const struct decode_header *h = (struct decode_header *)table;
- const struct decode_header *next;
+ struct decode_header *h = (struct decode_header *)table;
+ struct decode_header *next;
bool matched = false;
insn = prepare_emulated_insn(insn, asi, thumb);
@@ -412,18 +413,18 @@ kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi,
case DECODE_TYPE_CUSTOM: {
struct decode_custom *d = (struct decode_custom *)h;
- return (*d->decoder.decoder)(insn, asi);
+ return actions[d->decoder.bits].decoder(insn, asi, h);
}
case DECODE_TYPE_SIMULATE: {
struct decode_simulate *d = (struct decode_simulate *)h;
- asi->insn_handler = d->handler.handler;
+ asi->insn_handler = actions[d->handler.bits].handler;
return INSN_GOOD_NO_SLOT;
}
case DECODE_TYPE_EMULATE: {
struct decode_emulate *d = (struct decode_emulate *)h;
- asi->insn_handler = d->handler.handler;
+ asi->insn_handler = actions[d->handler.bits].handler;
set_emulated_insn(insn, asi, thumb);
return INSN_GOOD;
}
diff --git a/arch/arm/kernel/probes.h b/arch/arm/kernel/probes.h
index d14d224..2238972 100644
--- a/arch/arm/kernel/probes.h
+++ b/arch/arm/kernel/probes.h
@@ -131,7 +131,8 @@ void __kprobes kprobe_simulate_nop(struct kprobe *p, struct pt_regs *regs);
void __kprobes kprobe_emulate_none(struct kprobe *p, struct pt_regs *regs);
enum kprobe_insn __kprobes
-kprobe_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi);
+kprobe_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi,
+ struct decode_header *h);
/*
* Test if load/store instructions writeback the address register.
@@ -334,7 +335,7 @@ struct decode_custom {
#define DECODE_CUSTOM(_mask, _value, _decoder) \
DECODE_HEADER(DECODE_TYPE_CUSTOM, _mask, _value, 0), \
- {.decoder = (_decoder)}
+ {.bits = (_decoder)}
struct decode_simulate {
@@ -344,7 +345,7 @@ struct decode_simulate {
#define DECODE_SIMULATEX(_mask, _value, _handler, _regs) \
DECODE_HEADER(DECODE_TYPE_SIMULATE, _mask, _value, _regs), \
- {.handler = (_handler)}
+ {.bits = (_handler)}
#define DECODE_SIMULATE(_mask, _value, _handler) \
DECODE_SIMULATEX(_mask, _value, _handler, 0)
@@ -357,7 +358,7 @@ struct decode_emulate {
#define DECODE_EMULATEX(_mask, _value, _handler, _regs) \
DECODE_HEADER(DECODE_TYPE_EMULATE, _mask, _value, _regs), \
- {.handler = (_handler)}
+ {.bits = (_handler)}
#define DECODE_EMULATE(_mask, _value, _handler) \
DECODE_EMULATEX(_mask, _value, _handler, 0)
@@ -382,14 +383,18 @@ struct decode_reject {
#ifdef CONFIG_THUMB2_KERNEL
extern const union decode_item kprobe_decode_thumb16_table[];
extern const union decode_item kprobe_decode_thumb32_table[];
+extern const union decode_item kprobes_t32_actions[];
+extern const union decode_item kprobes_t16_actions[];
#else
extern const union decode_item kprobe_decode_arm_table[];
+extern const union decode_item kprobes_arm_actions[];
#endif
extern kprobe_check_cc * const kprobe_condition_checks[16];
int kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi,
- const union decode_item *table, bool thumb16);
+ const union decode_item *table, bool thumb16,
+ const union decode_item *actions);
#endif
--
1.8.1.2
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH v4 06/16] ARM: Disable jprobes test when built into thumb-mode kernel
2013-12-16 4:08 [PATCH v4 00/16] uprobes: Add uprobes support for ARM David Long
` (4 preceding siblings ...)
2013-12-16 4:08 ` [PATCH v4 05/16] ARM: use a function table for determining instruction interpreter actions David Long
@ 2013-12-16 4:08 ` David Long
2013-12-16 4:08 ` [PATCH v4 07/16] ARM: Remove use of struct kprobe from generic probes code David Long
` (9 subsequent siblings)
15 siblings, 0 replies; 34+ messages in thread
From: David Long @ 2013-12-16 4:08 UTC (permalink / raw)
To: linux-arm-kernel
From: "Jon Medhurst (Tixy)" <tixy@linaro.org>
For now the jprobes tests fail on ARM for when built into a kernel compiled
in thumb mode. They work fine for ARM kernels, and when built as a loadable
module.
Signed-off-by: "Jon Medhurst (Tixy)" <tixy@linaro.org>
Signed-off-by: David A. Long <dave.long@linaro.org>
---
arch/arm/kernel/kprobes-test.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/arch/arm/kernel/kprobes-test.c b/arch/arm/kernel/kprobes-test.c
index 0cd63d0..65230b2 100644
--- a/arch/arm/kernel/kprobes-test.c
+++ b/arch/arm/kernel/kprobes-test.c
@@ -221,6 +221,7 @@ static int pre_handler_called;
static int post_handler_called;
static int jprobe_func_called;
static int kretprobe_handler_called;
+static int tests_failed;
#define FUNC_ARG1 0x12345678
#define FUNC_ARG2 0xabcdef
@@ -457,6 +458,13 @@ static int run_api_tests(long (*func)(long, long))
pr_info(" jprobe\n");
ret = test_jprobe(func);
+#if defined(CONFIG_THUMB2_KERNEL) && !defined(MODULE)
+ if (ret == -EINVAL) {
+ pr_err("FAIL: Known longtime bug with jprobe on Thumb kernels");
+ tests_failed = ret;
+ ret = 0;
+ }
+#endif
if (ret < 0)
return ret;
@@ -1667,6 +1675,8 @@ static int __init run_all_tests(void)
out:
if (ret == 0)
+ ret = tests_failed;
+ if (ret == 0)
pr_info("Finished kprobe tests OK\n");
else
pr_err("kprobe tests failed\n");
--
1.8.1.2
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH v4 07/16] ARM: Remove use of struct kprobe from generic probes code
2013-12-16 4:08 [PATCH v4 00/16] uprobes: Add uprobes support for ARM David Long
` (5 preceding siblings ...)
2013-12-16 4:08 ` [PATCH v4 06/16] ARM: Disable jprobes test when built into thumb-mode kernel David Long
@ 2013-12-16 4:08 ` David Long
2013-12-20 13:55 ` Jon Medhurst (Tixy)
2013-12-16 4:08 ` [PATCH v4 08/16] ARM: Use new opcode type in ARM kprobes/uprobes code David Long
` (8 subsequent siblings)
15 siblings, 1 reply; 34+ messages in thread
From: David Long @ 2013-12-16 4:08 UTC (permalink / raw)
To: linux-arm-kernel
From: "David A. Long" <dave.long@linaro.org>
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>
---
arch/arm/include/asm/probes.h | 9 +-
arch/arm/kernel/kprobes-arm.c | 77 ++++++-------
arch/arm/kernel/kprobes-common.c | 42 ++++---
arch/arm/kernel/kprobes-thumb.c | 239 +++++++++++++++++++--------------------
arch/arm/kernel/kprobes.c | 2 +-
arch/arm/kernel/kprobes.h | 2 +-
arch/arm/kernel/probes-arm.c | 33 +++---
arch/arm/kernel/probes-arm.h | 29 ++---
arch/arm/kernel/probes-thumb.c | 18 ++-
arch/arm/kernel/probes-thumb.h | 51 ---------
arch/arm/kernel/probes.c | 14 ++-
arch/arm/kernel/probes.h | 8 +-
12 files changed, 246 insertions(+), 278 deletions(-)
diff --git a/arch/arm/include/asm/probes.h b/arch/arm/include/asm/probes.h
index edf5abe..a7b0a79 100644
--- a/arch/arm/include/asm/probes.h
+++ b/arch/arm/include/asm/probes.h
@@ -3,9 +3,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. */
diff --git a/arch/arm/kernel/kprobes-arm.c b/arch/arm/kernel/kprobes-arm.c
index ee329ff..394b611 100644
--- a/arch/arm/kernel/kprobes-arm.c
+++ b/arch/arm/kernel/kprobes-arm.c
@@ -72,12 +72,11 @@
"mov pc, "reg" \n\t"
#endif
-
-void __kprobes
-emulate_ldrdstrd(struct kprobe *p, struct pt_regs *regs)
+static void __kprobes
+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;
@@ -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"
);
@@ -102,11 +101,11 @@ emulate_ldrdstrd(struct kprobe *p, struct pt_regs *regs)
regs->uregs[rn] = rnv;
}
-void __kprobes
-emulate_ldr(struct kprobe *p, struct pt_regs *regs)
+static void __kprobes
+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;
@@ -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"
);
@@ -132,12 +131,12 @@ emulate_ldr(struct kprobe *p, struct pt_regs *regs)
regs->uregs[rn] = rnv;
}
-void __kprobes
-emulate_str(struct kprobe *p, struct pt_regs *regs)
+static void __kprobes
+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;
@@ -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"
);
@@ -159,11 +158,11 @@ emulate_str(struct kprobe *p, struct pt_regs *regs)
regs->uregs[rn] = rnv;
}
-void __kprobes
-emulate_rd12rn16rm0rs8_rwflags(struct kprobe *p, struct pt_regs *regs)
+static void __kprobes
+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;
@@ -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"
);
@@ -194,10 +193,10 @@ emulate_rd12rn16rm0rs8_rwflags(struct kprobe *p, struct pt_regs *regs)
regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK);
}
-void __kprobes
-emulate_rd12rn16rm0_rwflags_nopc(struct kprobe *p, struct pt_regs *regs)
+static void __kprobes
+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;
@@ -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"
);
@@ -221,10 +220,11 @@ emulate_rd12rn16rm0_rwflags_nopc(struct kprobe *p, struct pt_regs *regs)
regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK);
}
-void __kprobes
-emulate_rd16rn12rm0rs8_rwflags_nopc(struct kprobe *p, struct pt_regs *regs)
+static void __kprobes
+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;
@@ -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"
);
@@ -250,10 +250,10 @@ emulate_rd16rn12rm0rs8_rwflags_nopc(struct kprobe *p, struct pt_regs *regs)
regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK);
}
-void __kprobes
-emulate_rd12rm0_noflags_nopc(struct kprobe *p, struct pt_regs *regs)
+static void __kprobes
+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;
@@ -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;
}
-void __kprobes
-emulate_rdlo12rdhi16rn0rm8_rwflags_nopc(struct kprobe *p, struct pt_regs *regs)
+static void __kprobes
+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;
@@ -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"
);
diff --git a/arch/arm/kernel/kprobes-common.c b/arch/arm/kernel/kprobes-common.c
index 554720c..45590a4 100644
--- a/arch/arm/kernel/kprobes-common.c
+++ b/arch/arm/kernel/kprobes-common.c
@@ -18,9 +18,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);
@@ -59,24 +60,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"
@@ -100,21 +108,25 @@ 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);
}
enum kprobe_insn __kprobes
kprobe_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi,
- struct decode_header *h)
+ struct decode_header *h)
{
kprobe_insn_handler_t *handler = 0;
unsigned reglist = insn & 0xffff;
diff --git a/arch/arm/kernel/kprobes-thumb.c b/arch/arm/kernel/kprobes-thumb.c
index 5990866..d0bbbf7 100644
--- a/arch/arm/kernel/kprobes-thumb.c
+++ b/arch/arm/kernel/kprobes-thumb.c
@@ -19,24 +19,13 @@
#define t32_emulate_rd8rn16rm0ra12_noflags \
t32_emulate_rdlo12rdhi8rn16rm0_noflags
-/*
- * Return the PC value for a probe in thumb code.
- * This is the address of the probed instruction plus 4.
- * We subtract one because the address will have bit zero set to indicate
- * a pointer to thumb code.
- */
-static inline unsigned long __kprobes thumb_probe_pc(struct kprobe *p)
-{
- return (unsigned long)p->addr - 1 + 4;
-}
-
/* t32 thumb actions */
-void __kprobes
-t32_simulate_table_branch(struct kprobe *p, struct pt_regs *regs)
+static void __kprobes
+t32_simulate_table_branch(kprobe_opcode_t insn,
+ struct arch_specific_insn *asi, struct pt_regs *regs)
{
- kprobe_opcode_t insn = p->opcode;
- unsigned long pc = thumb_probe_pc(p);
+ unsigned long pc = regs->ARM_pc;
int rn = (insn >> 16) & 0xf;
int rm = insn & 0xf;
@@ -52,20 +41,20 @@ t32_simulate_table_branch(struct kprobe *p, struct pt_regs *regs)
regs->ARM_pc = pc + 2 * halfwords;
}
-void __kprobes
-t32_simulate_mrs(struct kprobe *p, struct pt_regs *regs)
+static void __kprobes
+t32_simulate_mrs(kprobe_opcode_t insn,
+ struct arch_specific_insn *asi, struct pt_regs *regs)
{
- kprobe_opcode_t insn = p->opcode;
int rd = (insn >> 8) & 0xf;
unsigned long mask = 0xf8ff03df; /* Mask out execution state */
regs->uregs[rd] = regs->ARM_cpsr & mask;
}
-void __kprobes
-t32_simulate_cond_branch(struct kprobe *p, struct pt_regs *regs)
+static void __kprobes
+t32_simulate_cond_branch(kprobe_opcode_t insn,
+ struct arch_specific_insn *asi, struct pt_regs *regs)
{
- kprobe_opcode_t insn = p->opcode;
- unsigned long pc = thumb_probe_pc(p);
+ unsigned long pc = regs->ARM_pc;
long offset = insn & 0x7ff; /* imm11 */
offset += (insn & 0x003f0000) >> 5; /* imm6 */
@@ -76,7 +65,7 @@ t32_simulate_cond_branch(struct kprobe *p, struct pt_regs *regs)
regs->ARM_pc = pc + (offset * 2);
}
-enum kprobe_insn __kprobes
+static enum kprobe_insn __kprobes
t32_decode_cond_branch(kprobe_opcode_t insn, struct arch_specific_insn *asi,
struct decode_header *d)
{
@@ -86,11 +75,11 @@ t32_decode_cond_branch(kprobe_opcode_t insn, struct arch_specific_insn *asi,
return INSN_GOOD_NO_SLOT;
}
-void __kprobes
-t32_simulate_branch(struct kprobe *p, struct pt_regs *regs)
+static void __kprobes
+t32_simulate_branch(kprobe_opcode_t insn,
+ struct arch_specific_insn *asi, struct pt_regs *regs)
{
- kprobe_opcode_t insn = p->opcode;
- unsigned long pc = thumb_probe_pc(p);
+ unsigned long pc = regs->ARM_pc;
long offset = insn & 0x7ff; /* imm11 */
offset += (insn & 0x03ff0000) >> 5; /* imm10 */
@@ -103,7 +92,7 @@ t32_simulate_branch(struct kprobe *p, struct pt_regs *regs)
if (insn & (1 << 14)) {
/* BL or BLX */
- regs->ARM_lr = (unsigned long)p->addr + 4;
+ regs->ARM_lr = regs->ARM_pc | 1;
if (!(insn & (1 << 12))) {
/* BLX so switch to ARM mode */
regs->ARM_cpsr &= ~PSR_T_BIT;
@@ -114,11 +103,11 @@ t32_simulate_branch(struct kprobe *p, struct pt_regs *regs)
regs->ARM_pc = pc + (offset * 2);
}
-void __kprobes
-t32_simulate_ldr_literal(struct kprobe *p, struct pt_regs *regs)
+static void __kprobes
+t32_simulate_ldr_literal(kprobe_opcode_t insn,
+ struct arch_specific_insn *asi, struct pt_regs *regs)
{
- kprobe_opcode_t insn = p->opcode;
- unsigned long addr = thumb_probe_pc(p) & ~3;
+ unsigned long addr = regs->ARM_pc & ~3;
int rt = (insn >> 12) & 0xf;
unsigned long rtv;
@@ -166,11 +155,11 @@ t32_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi,
return ret;
}
-void __kprobes
-t32_emulate_ldrdstrd(struct kprobe *p, struct pt_regs *regs)
+static void __kprobes
+t32_emulate_ldrdstrd(kprobe_opcode_t insn,
+ struct arch_specific_insn *asi, struct pt_regs *regs)
{
- kprobe_opcode_t insn = p->opcode;
- unsigned long pc = thumb_probe_pc(p) & ~3;
+ unsigned long pc = regs->ARM_pc & ~3;
int rt1 = (insn >> 12) & 0xf;
int rt2 = (insn >> 8) & 0xf;
int rn = (insn >> 16) & 0xf;
@@ -183,7 +172,7 @@ t32_emulate_ldrdstrd(struct kprobe *p, struct pt_regs *regs)
__asm__ __volatile__ (
"blx %[fn]"
: "=r" (rt1v), "=r" (rt2v), "=r" (rnv)
- : "0" (rt1v), "1" (rt2v), "2" (rnv), [fn] "r" (p->ainsn.insn_fn)
+ : "0" (rt1v), "1" (rt2v), "2" (rnv), [fn] "r" (asi->insn_fn)
: "lr", "memory", "cc"
);
@@ -193,10 +182,10 @@ t32_emulate_ldrdstrd(struct kprobe *p, struct pt_regs *regs)
regs->uregs[rt2] = rt2v;
}
-void __kprobes
-t32_emulate_ldrstr(struct kprobe *p, struct pt_regs *regs)
+static void __kprobes
+t32_emulate_ldrstr(kprobe_opcode_t insn,
+ struct arch_specific_insn *asi, struct pt_regs *regs)
{
- kprobe_opcode_t insn = p->opcode;
int rt = (insn >> 12) & 0xf;
int rn = (insn >> 16) & 0xf;
int rm = insn & 0xf;
@@ -208,7 +197,7 @@ t32_emulate_ldrstr(struct kprobe *p, struct pt_regs *regs)
__asm__ __volatile__ (
"blx %[fn]"
: "=r" (rtv), "=r" (rnv)
- : "0" (rtv), "1" (rnv), "r" (rmv), [fn] "r" (p->ainsn.insn_fn)
+ : "0" (rtv), "1" (rnv), "r" (rmv), [fn] "r" (asi->insn_fn)
: "lr", "memory", "cc"
);
@@ -219,10 +208,10 @@ t32_emulate_ldrstr(struct kprobe *p, struct pt_regs *regs)
regs->uregs[rt] = rtv;
}
-void __kprobes
-t32_emulate_rd8rn16rm0_rwflags(struct kprobe *p, struct pt_regs *regs)
+static void __kprobes
+t32_emulate_rd8rn16rm0_rwflags(kprobe_opcode_t insn,
+ struct arch_specific_insn *asi, struct pt_regs *regs)
{
- kprobe_opcode_t insn = p->opcode;
int rd = (insn >> 8) & 0xf;
int rn = (insn >> 16) & 0xf;
int rm = insn & 0xf;
@@ -238,7 +227,7 @@ t32_emulate_rd8rn16rm0_rwflags(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"
);
@@ -246,11 +235,11 @@ t32_emulate_rd8rn16rm0_rwflags(struct kprobe *p, struct pt_regs *regs)
regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK);
}
-void __kprobes
-t32_emulate_rd8pc16_noflags(struct kprobe *p, struct pt_regs *regs)
+static void __kprobes
+t32_emulate_rd8pc16_noflags(kprobe_opcode_t insn,
+ struct arch_specific_insn *asi, struct pt_regs *regs)
{
- kprobe_opcode_t insn = p->opcode;
- unsigned long pc = thumb_probe_pc(p);
+ unsigned long pc = regs->ARM_pc;
int rd = (insn >> 8) & 0xf;
register unsigned long rdv asm("r1") = regs->uregs[rd];
@@ -259,17 +248,17 @@ t32_emulate_rd8pc16_noflags(struct kprobe *p, struct pt_regs *regs)
__asm__ __volatile__ (
"blx %[fn]"
: "=r" (rdv)
- : "0" (rdv), "r" (rnv), [fn] "r" (p->ainsn.insn_fn)
+ : "0" (rdv), "r" (rnv), [fn] "r" (asi->insn_fn)
: "lr", "memory", "cc"
);
regs->uregs[rd] = rdv;
}
-void __kprobes
-t32_emulate_rd8rn16_noflags(struct kprobe *p, struct pt_regs *regs)
+static void __kprobes
+t32_emulate_rd8rn16_noflags(kprobe_opcode_t insn,
+ struct arch_specific_insn *asi, struct pt_regs *regs)
{
- kprobe_opcode_t insn = p->opcode;
int rd = (insn >> 8) & 0xf;
int rn = (insn >> 16) & 0xf;
@@ -279,17 +268,18 @@ t32_emulate_rd8rn16_noflags(struct kprobe *p, struct pt_regs *regs)
__asm__ __volatile__ (
"blx %[fn]"
: "=r" (rdv)
- : "0" (rdv), "r" (rnv), [fn] "r" (p->ainsn.insn_fn)
+ : "0" (rdv), "r" (rnv), [fn] "r" (asi->insn_fn)
: "lr", "memory", "cc"
);
regs->uregs[rd] = rdv;
}
-void __kprobes
-t32_emulate_rdlo12rdhi8rn16rm0_noflags(struct kprobe *p, struct pt_regs *regs)
+static void __kprobes
+t32_emulate_rdlo12rdhi8rn16rm0_noflags(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 >> 8) & 0xf;
int rn = (insn >> 16) & 0xf;
@@ -304,7 +294,7 @@ t32_emulate_rdlo12rdhi8rn16rm0_noflags(struct kprobe *p, struct pt_regs *regs)
"blx %[fn]"
: "=r" (rdlov), "=r" (rdhiv)
: "0" (rdlov), "1" (rdhiv), "r" (rnv), "r" (rmv),
- [fn] "r" (p->ainsn.insn_fn)
+ [fn] "r" (asi->insn_fn)
: "lr", "memory", "cc"
);
@@ -313,34 +303,34 @@ t32_emulate_rdlo12rdhi8rn16rm0_noflags(struct kprobe *p, struct pt_regs *regs)
}
/* t16 thumb actions */
-void __kprobes
-t16_simulate_bxblx(struct kprobe *p, struct pt_regs *regs)
+static void __kprobes
+t16_simulate_bxblx(kprobe_opcode_t insn,
+ struct arch_specific_insn *asi, struct pt_regs *regs)
{
- kprobe_opcode_t insn = p->opcode;
- unsigned long pc = thumb_probe_pc(p);
+ unsigned long pc = regs->ARM_pc + 2;
int rm = (insn >> 3) & 0xf;
unsigned long rmv = (rm == 15) ? pc : regs->uregs[rm];
if (insn & (1 << 7)) /* BLX ? */
- regs->ARM_lr = (unsigned long)p->addr + 2;
+ regs->ARM_lr = regs->ARM_pc | 1;
bx_write_pc(rmv, regs);
}
-void __kprobes
-t16_simulate_ldr_literal(struct kprobe *p, struct pt_regs *regs)
+static void __kprobes
+t16_simulate_ldr_literal(kprobe_opcode_t insn,
+ struct arch_specific_insn *asi, struct pt_regs *regs)
{
- kprobe_opcode_t insn = p->opcode;
- unsigned long* base = (unsigned long *)(thumb_probe_pc(p) & ~3);
+ unsigned long *base = (unsigned long *)((regs->ARM_pc + 2) & ~3);
long index = insn & 0xff;
int rt = (insn >> 8) & 0x7;
regs->uregs[rt] = base[index];
}
-void __kprobes
-t16_simulate_ldrstr_sp_relative(struct kprobe *p, struct pt_regs *regs)
+static void __kprobes
+t16_simulate_ldrstr_sp_relative(kprobe_opcode_t insn,
+ struct arch_specific_insn *asi, struct pt_regs *regs)
{
- kprobe_opcode_t insn = p->opcode;
unsigned long* base = (unsigned long *)regs->ARM_sp;
long index = insn & 0xff;
int rt = (insn >> 8) & 0x7;
@@ -350,21 +340,21 @@ t16_simulate_ldrstr_sp_relative(struct kprobe *p, struct pt_regs *regs)
base[index] = regs->uregs[rt];
}
-void __kprobes
-t16_simulate_reladr(struct kprobe *p, struct pt_regs *regs)
+static void __kprobes
+t16_simulate_reladr(kprobe_opcode_t insn,
+ struct arch_specific_insn *asi, struct pt_regs *regs)
{
- kprobe_opcode_t insn = p->opcode;
unsigned long base = (insn & 0x800) ? regs->ARM_sp
- : (thumb_probe_pc(p) & ~3);
+ : ((regs->ARM_pc + 2) & ~3);
long offset = insn & 0xff;
int rt = (insn >> 8) & 0x7;
regs->uregs[rt] = base + offset * 4;
}
-void __kprobes
-t16_simulate_add_sp_imm(struct kprobe *p, struct pt_regs *regs)
+static void __kprobes
+t16_simulate_add_sp_imm(kprobe_opcode_t insn,
+ struct arch_specific_insn *asi, struct pt_regs *regs)
{
- kprobe_opcode_t insn = p->opcode;
long imm = insn & 0x7f;
if (insn & 0x80) /* SUB */
regs->ARM_sp -= imm * 4;
@@ -372,22 +362,23 @@ t16_simulate_add_sp_imm(struct kprobe *p, struct pt_regs *regs)
regs->ARM_sp += imm * 4;
}
-void __kprobes
-t16_simulate_cbz(struct kprobe *p, struct pt_regs *regs)
+static void __kprobes
+t16_simulate_cbz(kprobe_opcode_t insn,
+ struct arch_specific_insn *asi, struct pt_regs *regs)
{
- kprobe_opcode_t insn = p->opcode;
int rn = insn & 0x7;
kprobe_opcode_t nonzero = regs->uregs[rn] ? insn : ~insn;
if (nonzero & 0x800) {
long i = insn & 0x200;
long imm5 = insn & 0xf8;
- unsigned long pc = thumb_probe_pc(p);
+ unsigned long pc = regs->ARM_pc + 2;
regs->ARM_pc = pc + (i >> 3) + (imm5 >> 2);
}
}
-void __kprobes
-t16_simulate_it(struct kprobe *p, struct pt_regs *regs)
+static void __kprobes
+t16_simulate_it(kprobe_opcode_t insn,
+ struct arch_specific_insn *asi, struct pt_regs *regs)
{
/*
* The 8 IT state bits are split into two parts in CPSR:
@@ -395,7 +386,6 @@ t16_simulate_it(struct kprobe *p, struct pt_regs *regs)
* ITSTATE<7:2> are in CPSR<15:10>
* The new IT state is in the lower byte of insn.
*/
- kprobe_opcode_t insn = p->opcode;
unsigned long cpsr = regs->ARM_cpsr;
cpsr &= ~PSR_IT_MASK;
cpsr |= (insn & 0xfc) << 8;
@@ -403,14 +393,15 @@ t16_simulate_it(struct kprobe *p, struct pt_regs *regs)
regs->ARM_cpsr = cpsr;
}
-void __kprobes
-t16_singlestep_it(struct kprobe *p, struct pt_regs *regs)
+static void __kprobes
+t16_singlestep_it(kprobe_opcode_t insn,
+ struct arch_specific_insn *asi, struct pt_regs *regs)
{
regs->ARM_pc += 2;
- t16_simulate_it(p, regs);
+ t16_simulate_it(insn, asi, regs);
}
-enum kprobe_insn __kprobes
+static enum kprobe_insn __kprobes
t16_decode_it(kprobe_opcode_t insn, struct arch_specific_insn *asi,
struct decode_header *d)
{
@@ -418,17 +409,17 @@ t16_decode_it(kprobe_opcode_t insn, struct arch_specific_insn *asi,
return INSN_GOOD_NO_SLOT;
}
-void __kprobes
-t16_simulate_cond_branch(struct kprobe *p, struct pt_regs *regs)
+static void __kprobes
+t16_simulate_cond_branch(kprobe_opcode_t insn,
+ struct arch_specific_insn *asi, struct pt_regs *regs)
{
- kprobe_opcode_t insn = p->opcode;
- unsigned long pc = thumb_probe_pc(p);
+ unsigned long pc = regs->ARM_pc + 2;
long offset = insn & 0x7f;
offset -= insn & 0x80; /* Apply sign bit */
regs->ARM_pc = pc + (offset * 2);
}
-enum kprobe_insn __kprobes
+static enum kprobe_insn __kprobes
t16_decode_cond_branch(kprobe_opcode_t insn, struct arch_specific_insn *asi,
struct decode_header *d)
{
@@ -438,18 +429,19 @@ t16_decode_cond_branch(kprobe_opcode_t insn, struct arch_specific_insn *asi,
return INSN_GOOD_NO_SLOT;
}
-void __kprobes
-t16_simulate_branch(struct kprobe *p, struct pt_regs *regs)
+static void __kprobes
+t16_simulate_branch(kprobe_opcode_t insn,
+ struct arch_specific_insn *asi, struct pt_regs *regs)
{
- kprobe_opcode_t insn = p->opcode;
- unsigned long pc = thumb_probe_pc(p);
+ unsigned long pc = regs->ARM_pc + 2;
long offset = insn & 0x3ff;
offset -= insn & 0x400; /* Apply sign bit */
regs->ARM_pc = pc + (offset * 2);
}
static unsigned long __kprobes
-t16_emulate_loregs(struct kprobe *p, struct pt_regs *regs)
+t16_emulate_loregs(kprobe_opcode_t insn,
+ struct arch_specific_insn *asi, struct pt_regs *regs)
{
unsigned long oldcpsr = regs->ARM_cpsr;
unsigned long newcpsr;
@@ -462,7 +454,7 @@ t16_emulate_loregs(struct kprobe *p, struct pt_regs *regs)
"mrs %[newcpsr], cpsr \n\t"
: [newcpsr] "=r" (newcpsr)
: [oldcpsr] "r" (oldcpsr), [regs] "r" (regs),
- [fn] "r" (p->ainsn.insn_fn)
+ [fn] "r" (asi->insn_fn)
: "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
"lr", "memory", "cc"
);
@@ -470,25 +462,27 @@ t16_emulate_loregs(struct kprobe *p, struct pt_regs *regs)
return (oldcpsr & ~APSR_MASK) | (newcpsr & APSR_MASK);
}
-void __kprobes
-t16_emulate_loregs_rwflags(struct kprobe *p, struct pt_regs *regs)
+static void __kprobes
+t16_emulate_loregs_rwflags(kprobe_opcode_t insn,
+ struct arch_specific_insn *asi, struct pt_regs *regs)
{
- regs->ARM_cpsr = t16_emulate_loregs(p, regs);
+ regs->ARM_cpsr = t16_emulate_loregs(insn, asi, regs);
}
-void __kprobes
-t16_emulate_loregs_noitrwflags(struct kprobe *p, struct pt_regs *regs)
+static void __kprobes
+t16_emulate_loregs_noitrwflags(kprobe_opcode_t insn,
+ struct arch_specific_insn *asi, struct pt_regs *regs)
{
- unsigned long cpsr = t16_emulate_loregs(p, regs);
+ unsigned long cpsr = t16_emulate_loregs(insn, asi, regs);
if (!in_it_block(cpsr))
regs->ARM_cpsr = cpsr;
}
-void __kprobes
-t16_emulate_hiregs(struct kprobe *p, struct pt_regs *regs)
+static void __kprobes
+t16_emulate_hiregs(kprobe_opcode_t insn,
+ struct arch_specific_insn *asi, struct pt_regs *regs)
{
- kprobe_opcode_t insn = p->opcode;
- unsigned long pc = thumb_probe_pc(p);
+ unsigned long pc = regs->ARM_pc + 2;
int rdn = (insn & 0x7) | ((insn & 0x80) >> 4);
int rm = (insn >> 3) & 0xf;
@@ -504,7 +498,7 @@ t16_emulate_hiregs(struct kprobe *p, struct pt_regs *regs)
"blx %[fn] \n\t"
"mrs %[cpsr], cpsr \n\t"
: "=r" (rdnv), [cpsr] "=r" (cpsr)
- : "0" (rdnv), "r" (rmv), "1" (cpsr), [fn] "r" (p->ainsn.insn_fn)
+ : "0" (rdnv), "r" (rmv), "1" (cpsr), [fn] "r" (asi->insn_fn)
: "lr", "memory", "cc"
);
@@ -515,7 +509,7 @@ t16_emulate_hiregs(struct kprobe *p, struct pt_regs *regs)
regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK);
}
-enum kprobe_insn __kprobes
+static enum kprobe_insn __kprobes
t16_decode_hiregs(kprobe_opcode_t insn, struct arch_specific_insn *asi,
struct decode_header *d)
{
@@ -526,8 +520,9 @@ t16_decode_hiregs(kprobe_opcode_t insn, struct arch_specific_insn *asi,
return INSN_GOOD;
}
-void __kprobes
-t16_emulate_push(struct kprobe *p, struct pt_regs *regs)
+static void __kprobes
+t16_emulate_push(kprobe_opcode_t insn,
+ struct arch_specific_insn *asi, struct pt_regs *regs)
{
__asm__ __volatile__ (
"ldr r9, [%[regs], #13*4] \n\t"
@@ -536,13 +531,13 @@ t16_emulate_push(struct kprobe *p, struct pt_regs *regs)
"blx %[fn] \n\t"
"str r9, [%[regs], #13*4] \n\t"
:
- : [regs] "r" (regs), [fn] "r" (p->ainsn.insn_fn)
+ : [regs] "r" (regs), [fn] "r" (asi->insn_fn)
: "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9",
"lr", "memory", "cc"
);
}
-enum kprobe_insn __kprobes
+static enum kprobe_insn __kprobes
t16_decode_push(kprobe_opcode_t insn, struct arch_specific_insn *asi,
struct decode_header *d)
{
@@ -557,8 +552,9 @@ t16_decode_push(kprobe_opcode_t insn, struct arch_specific_insn *asi,
return INSN_GOOD;
}
-void __kprobes
-t16_emulate_pop_nopc(struct kprobe *p, struct pt_regs *regs)
+static void __kprobes
+t16_emulate_pop_nopc(kprobe_opcode_t insn,
+ struct arch_specific_insn *asi, struct pt_regs *regs)
{
__asm__ __volatile__ (
"ldr r9, [%[regs], #13*4] \n\t"
@@ -567,14 +563,15 @@ t16_emulate_pop_nopc(struct kprobe *p, struct pt_regs *regs)
"stmia %[regs], {r0-r7} \n\t"
"str r9, [%[regs], #13*4] \n\t"
:
- : [regs] "r" (regs), [fn] "r" (p->ainsn.insn_fn)
+ : [regs] "r" (regs), [fn] "r" (asi->insn_fn)
: "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r9",
"lr", "memory", "cc"
);
}
-void __kprobes
-t16_emulate_pop_pc(struct kprobe *p, struct pt_regs *regs)
+static void __kprobes
+t16_emulate_pop_pc(kprobe_opcode_t insn,
+ struct arch_specific_insn *asi, struct pt_regs *regs)
{
register unsigned long pc asm("r8");
@@ -585,7 +582,7 @@ t16_emulate_pop_pc(struct kprobe *p, struct pt_regs *regs)
"stmia %[regs], {r0-r7} \n\t"
"str r9, [%[regs], #13*4] \n\t"
: "=r" (pc)
- : [regs] "r" (regs), [fn] "r" (p->ainsn.insn_fn)
+ : [regs] "r" (regs), [fn] "r" (asi->insn_fn)
: "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r9",
"lr", "memory", "cc"
);
diff --git a/arch/arm/kernel/kprobes.c b/arch/arm/kernel/kprobes.c
index a18b4ca..19c55aa 100644
--- a/arch/arm/kernel/kprobes.c
+++ b/arch/arm/kernel/kprobes.c
@@ -203,7 +203,7 @@ singlestep_skip(struct kprobe *p, struct pt_regs *regs)
static inline void __kprobes
singlestep(struct kprobe *p, struct pt_regs *regs, struct kprobe_ctlblk *kcb)
{
- p->ainsn.insn_singlestep(p, regs);
+ p->ainsn.insn_singlestep(p->opcode, &p->ainsn, regs);
}
/*
diff --git a/arch/arm/kernel/kprobes.h b/arch/arm/kernel/kprobes.h
index 5ce81dc..6c1ed3c 100644
--- a/arch/arm/kernel/kprobes.h
+++ b/arch/arm/kernel/kprobes.h
@@ -37,7 +37,7 @@ enum kprobe_insn {
typedef enum kprobe_insn (kprobe_decode_insn_t)(kprobe_opcode_t,
struct arch_specific_insn *,
- struct decode_header *actions);
+ struct decode_header *);
#ifdef CONFIG_THUMB2_KERNEL
diff --git a/arch/arm/kernel/probes-arm.c b/arch/arm/kernel/probes-arm.c
index 665cd0d..3aba9c3 100644
--- a/arch/arm/kernel/probes-arm.c
+++ b/arch/arm/kernel/probes-arm.c
@@ -18,8 +18,7 @@
#include <linux/compiler.h>
#include <linux/kernel.h>
-#include <linux/kprobes.h>
-#include "kprobes.h"
+#include "probes.h"
#include "probes-arm.h"
#define sign_extend(x, signbit) ((x) | (0 - ((x) & (1 << (signbit)))))
@@ -56,10 +55,10 @@
* read and write of flags.
*/
-void __kprobes simulate_bbl(struct kprobe *p, struct pt_regs *regs)
+void __kprobes simulate_bbl(kprobe_opcode_t insn,
+ struct arch_specific_insn *asi, struct pt_regs *regs)
{
- kprobe_opcode_t insn = p->opcode;
- long iaddr = (long)p->addr;
+ long iaddr = (long) regs->ARM_pc - 4;
int disp = branch_displacement(insn);
if (insn & (1 << 24))
@@ -68,10 +67,10 @@ void __kprobes simulate_bbl(struct kprobe *p, struct pt_regs *regs)
regs->ARM_pc = iaddr + 8 + disp;
}
-void __kprobes simulate_blx1(struct kprobe *p, struct pt_regs *regs)
+void __kprobes simulate_blx1(kprobe_opcode_t insn,
+ struct arch_specific_insn *asi, struct pt_regs *regs)
{
- kprobe_opcode_t insn = p->opcode;
- long iaddr = (long)p->addr;
+ long iaddr = (long) regs->ARM_pc - 4;
int disp = branch_displacement(insn);
regs->ARM_lr = iaddr + 4;
@@ -79,14 +78,14 @@ void __kprobes simulate_blx1(struct kprobe *p, struct pt_regs *regs)
regs->ARM_cpsr |= PSR_T_BIT;
}
-void __kprobes simulate_blx2bx(struct kprobe *p, struct pt_regs *regs)
+void __kprobes simulate_blx2bx(kprobe_opcode_t insn,
+ struct arch_specific_insn *asi, struct pt_regs *regs)
{
- kprobe_opcode_t insn = p->opcode;
int rm = insn & 0xf;
long rmv = regs->uregs[rm];
if (insn & (1 << 5))
- regs->ARM_lr = (long)p->addr + 4;
+ regs->ARM_lr = (long) regs->ARM_pc;
regs->ARM_pc = rmv & ~0x1;
regs->ARM_cpsr &= ~PSR_T_BIT;
@@ -94,15 +93,16 @@ void __kprobes simulate_blx2bx(struct kprobe *p, struct pt_regs *regs)
regs->ARM_cpsr |= PSR_T_BIT;
}
-void __kprobes simulate_mrs(struct kprobe *p, struct pt_regs *regs)
+void __kprobes simulate_mrs(kprobe_opcode_t insn,
+ struct arch_specific_insn *asi, struct pt_regs *regs)
{
- kprobe_opcode_t insn = p->opcode;
int rd = (insn >> 12) & 0xf;
unsigned long mask = 0xf8ff03df; /* Mask out execution state */
regs->uregs[rd] = regs->ARM_cpsr & mask;
}
-void __kprobes simulate_mov_ipsp(struct kprobe *p, struct pt_regs *regs)
+void __kprobes simulate_mov_ipsp(kprobe_opcode_t insn,
+ struct arch_specific_insn *asi, struct pt_regs *regs)
{
regs->uregs[12] = regs->uregs[13];
}
@@ -702,10 +702,11 @@ const union decode_item kprobe_decode_arm_table[] = {
EXPORT_SYMBOL_GPL(kprobe_decode_arm_table);
#endif
-static void __kprobes arm_singlestep(struct kprobe *p, struct pt_regs *regs)
+static void __kprobes arm_singlestep(kprobe_opcode_t insn,
+ struct arch_specific_insn *asi, struct pt_regs *regs)
{
regs->ARM_pc += 4;
- p->ainsn.insn_handler(p, regs);
+ asi->insn_handler(insn, asi, regs);
}
/* Return:
diff --git a/arch/arm/kernel/probes-arm.h b/arch/arm/kernel/probes-arm.h
index f8e0f7a..2c9e841 100644
--- a/arch/arm/kernel/probes-arm.h
+++ b/arch/arm/kernel/probes-arm.h
@@ -52,24 +52,15 @@ enum probes_arm_action {
PROBES_LDMSTM
};
-void __kprobes simulate_bbl(struct kprobe *p, struct pt_regs *regs);
-void __kprobes simulate_blx1(struct kprobe *p, struct pt_regs *regs);
-void __kprobes simulate_blx2bx(struct kprobe *p, struct pt_regs *regs);
-void __kprobes simulate_mrs(struct kprobe *p, struct pt_regs *regs);
-void __kprobes simulate_mov_ipsp(struct kprobe *p, struct pt_regs *regs);
-
-void __kprobes emulate_ldrdstrd(struct kprobe *p, struct pt_regs *regs);
-void __kprobes emulate_ldr(struct kprobe *p, struct pt_regs *regs);
-void __kprobes emulate_str(struct kprobe *p, struct pt_regs *regs);
-void __kprobes emulate_rd12rn16rm0rs8_rwflags(struct kprobe *p,
- struct pt_regs *regs);
-void __kprobes emulate_rd12rn16rm0_rwflags_nopc(struct kprobe *p,
- struct pt_regs *regs);
-void __kprobes emulate_rd16rn12rm0rs8_rwflags_nopc(struct kprobe *p,
- struct pt_regs *regs);
-void __kprobes emulate_rd12rm0_noflags_nopc(struct kprobe *p,
- struct pt_regs *regs);
-void __kprobes emulate_rdlo12rdhi16rn0rm8_rwflags_nopc(struct kprobe *p,
- struct pt_regs *regs);
+void __kprobes simulate_bbl(kprobe_opcode_t opcode,
+ struct arch_specific_insn *asi, struct pt_regs *regs);
+void __kprobes simulate_blx1(kprobe_opcode_t opcode,
+ struct arch_specific_insn *asi, struct pt_regs *regs);
+void __kprobes simulate_blx2bx(kprobe_opcode_t opcode,
+ struct arch_specific_insn *asi, struct pt_regs *regs);
+void __kprobes simulate_mrs(kprobe_opcode_t opcode,
+ struct arch_specific_insn *asi, struct pt_regs *regs);
+void __kprobes simulate_mov_ipsp(kprobe_opcode_t opcode,
+ struct arch_specific_insn *asi, struct pt_regs *regs);
#endif
diff --git a/arch/arm/kernel/probes-thumb.c b/arch/arm/kernel/probes-thumb.c
index bf2f1e9..fb79dd9 100644
--- a/arch/arm/kernel/probes-thumb.c
+++ b/arch/arm/kernel/probes-thumb.c
@@ -9,10 +9,9 @@
*/
#include <linux/kernel.h>
-#include <linux/kprobes.h>
#include <linux/module.h>
-#include "kprobes.h"
+#include "probes.h"
#include "probes-thumb.h"
@@ -831,6 +830,9 @@ const union decode_item kprobe_decode_thumb16_table[] = {
DECODE_END
};
+#ifdef CONFIG_ARM_KPROBES_TEST_MODULE
+EXPORT_SYMBOL_GPL(kprobe_decode_thumb16_table);
+#endif
static unsigned long __kprobes thumb_check_cc(unsigned long cpsr)
{
@@ -839,17 +841,21 @@ static unsigned long __kprobes thumb_check_cc(unsigned long cpsr)
return true;
}
-static void __kprobes thumb16_singlestep(struct kprobe *p, struct pt_regs *regs)
+static void __kprobes thumb16_singlestep(kprobe_opcode_t opcode,
+ struct arch_specific_insn *asi,
+ struct pt_regs *regs)
{
regs->ARM_pc += 2;
- p->ainsn.insn_handler(p, regs);
+ asi->insn_handler(opcode, asi, regs);
regs->ARM_cpsr = it_advance(regs->ARM_cpsr);
}
-static void __kprobes thumb32_singlestep(struct kprobe *p, struct pt_regs *regs)
+static void __kprobes thumb32_singlestep(kprobe_opcode_t opcode,
+ struct arch_specific_insn *asi,
+ struct pt_regs *regs)
{
regs->ARM_pc += 4;
- p->ainsn.insn_handler(p, regs);
+ asi->insn_handler(opcode, asi, regs);
regs->ARM_cpsr = it_advance(regs->ARM_cpsr);
}
diff --git a/arch/arm/kernel/probes-thumb.h b/arch/arm/kernel/probes-thumb.h
index 381ad3a..f024a4c 100644
--- a/arch/arm/kernel/probes-thumb.h
+++ b/arch/arm/kernel/probes-thumb.h
@@ -82,55 +82,4 @@ enum probes_t16_action {
PROBES_T16_BRANCH
};
-void __kprobes t16_simulate_bxblx(struct kprobe *p, struct pt_regs *regs);
-void __kprobes t16_simulate_ldr_literal(struct kprobe *p, struct pt_regs *regs);
-void __kprobes t16_simulate_ldrstr_sp_relative(struct kprobe *p,
- struct pt_regs *regs);
-void __kprobes t16_simulate_reladr(struct kprobe *p, struct pt_regs *regs);
-void __kprobes t16_simulate_add_sp_imm(struct kprobe *p, struct pt_regs *regs);
-void __kprobes t16_simulate_cbz(struct kprobe *p, struct pt_regs *regs);
-void __kprobes t16_simulate_it(struct kprobe *p, struct pt_regs *regs);
-void __kprobes t16_singlestep_it(struct kprobe *p, struct pt_regs *regs);
-enum kprobe_insn __kprobes t16_decode_it(kprobe_opcode_t insn,
- struct arch_specific_insn *asi, struct decode_header *d);
-void __kprobes t16_simulate_cond_branch(struct kprobe *p, struct pt_regs *regs);
-enum kprobe_insn __kprobes t16_decode_cond_branch(kprobe_opcode_t insn,
- struct arch_specific_insn *asi, struct decode_header *d);
-void __kprobes t16_simulate_branch(struct kprobe *p, struct pt_regs *regs);
-void __kprobes t16_emulate_loregs_rwflags(struct kprobe *p,
- struct pt_regs *regs);
-void __kprobes t16_emulate_loregs_noitrwflags(struct kprobe *p,
- struct pt_regs *regs);
-void __kprobes t16_emulate_hiregs(struct kprobe *p, struct pt_regs *regs);
-enum kprobe_insn __kprobes t16_decode_hiregs(kprobe_opcode_t insn,
- struct arch_specific_insn *asi, struct decode_header *d);
-void __kprobes t16_emulate_push(struct kprobe *p, struct pt_regs *regs);
-enum kprobe_insn __kprobes t16_decode_push(kprobe_opcode_t insn,
- struct arch_specific_insn *asi, struct decode_header *d);
-void __kprobes t16_emulate_pop_nopc(struct kprobe *p, struct pt_regs *regs);
-void __kprobes t16_emulate_pop_pc(struct kprobe *p, struct pt_regs *regs);
-enum kprobe_insn __kprobes t16_decode_pop(kprobe_opcode_t insn,
- struct arch_specific_insn *asi, struct decode_header *d);
-
-void __kprobes t32_simulate_table_branch(struct kprobe *p,
- struct pt_regs *regs);
-void __kprobes t32_simulate_mrs(struct kprobe *p, struct pt_regs *regs);
-void __kprobes t32_simulate_cond_branch(struct kprobe *p, struct pt_regs *regs);
-enum kprobe_insn __kprobes t32_decode_cond_branch(kprobe_opcode_t insn,
- struct arch_specific_insn *asi, struct decode_header *d);
-void __kprobes t32_simulate_branch(struct kprobe *p, struct pt_regs *regs);
-void __kprobes t32_simulate_ldr_literal(struct kprobe *p, struct pt_regs *regs);
-enum kprobe_insn __kprobes t32_decode_ldmstm(kprobe_opcode_t insn,
- struct arch_specific_insn *asi, struct decode_header *d);
-void __kprobes t32_emulate_ldrdstrd(struct kprobe *p, struct pt_regs *regs);
-void __kprobes t32_emulate_ldrstr(struct kprobe *p, struct pt_regs *regs);
-void __kprobes t32_emulate_rd8rn16rm0_rwflags(struct kprobe *p,
- struct pt_regs *regs);
-void __kprobes t32_emulate_rd8pc16_noflags(struct kprobe *p,
- struct pt_regs *regs);
-void __kprobes t32_emulate_rd8rn16_noflags(struct kprobe *p,
- struct pt_regs *regs);
-void __kprobes t32_emulate_rdlo12rdhi8rn16rm0_noflags(struct kprobe *p,
- struct pt_regs *regs);
-
#endif
diff --git a/arch/arm/kernel/probes.c b/arch/arm/kernel/probes.c
index 1bcf5da..b2db250 100644
--- a/arch/arm/kernel/probes.c
+++ b/arch/arm/kernel/probes.c
@@ -12,11 +12,9 @@
*/
#include <linux/kernel.h>
-#include <linux/kprobes.h>
#include <asm/system_info.h>
-#include "kprobes.h"
-
+#include "probes.h"
#ifndef find_str_pc_offset
@@ -173,13 +171,17 @@ kprobe_check_cc * const kprobe_condition_checks[16] = {
};
-void __kprobes kprobe_simulate_nop(struct kprobe *p, struct pt_regs *regs)
+void __kprobes kprobe_simulate_nop(kprobe_opcode_t opcode,
+ struct arch_specific_insn *asi,
+ struct pt_regs *regs)
{
}
-void __kprobes kprobe_emulate_none(struct kprobe *p, struct pt_regs *regs)
+void __kprobes kprobe_emulate_none(kprobe_opcode_t opcode,
+ struct arch_specific_insn *asi,
+ struct pt_regs *regs)
{
- p->ainsn.insn_fn();
+ asi->insn_fn();
}
/*
diff --git a/arch/arm/kernel/probes.h b/arch/arm/kernel/probes.h
index 2238972..45151a1 100644
--- a/arch/arm/kernel/probes.h
+++ b/arch/arm/kernel/probes.h
@@ -20,6 +20,7 @@
#define _ARM_KERNEL_PROBES_H
#include <linux/kprobes.h>
+#include "kprobes.h"
#if __LINUX_ARM_ARCH__ >= 7
@@ -35,6 +36,7 @@ void __init find_str_pc_offset(void);
#endif
+struct decode_header;
/*
* Update ITSTATE after normal execution of an IT block instruction.
@@ -127,8 +129,10 @@ static inline void __kprobes alu_write_pc(long pcv, struct pt_regs *regs)
}
-void __kprobes kprobe_simulate_nop(struct kprobe *p, struct pt_regs *regs);
-void __kprobes kprobe_emulate_none(struct kprobe *p, struct pt_regs *regs);
+void __kprobes kprobe_simulate_nop(kprobe_opcode_t, struct arch_specific_insn *,
+ struct pt_regs *regs);
+void __kprobes kprobe_emulate_none(kprobe_opcode_t, struct arch_specific_insn *,
+ struct pt_regs *regs);
enum kprobe_insn __kprobes
kprobe_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi,
--
1.8.1.2
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH v4 08/16] ARM: Use new opcode type in ARM kprobes/uprobes code
2013-12-16 4:08 [PATCH v4 00/16] uprobes: Add uprobes support for ARM David Long
` (6 preceding siblings ...)
2013-12-16 4:08 ` [PATCH v4 07/16] ARM: Remove use of struct kprobe from generic probes code David Long
@ 2013-12-16 4:08 ` David Long
2013-12-16 4:08 ` [PATCH v4 09/16] ARM: Make the kprobes condition_check symbol names more generic David Long
` (7 subsequent siblings)
15 siblings, 0 replies; 34+ messages in thread
From: David Long @ 2013-12-16 4:08 UTC (permalink / raw)
To: linux-arm-kernel
From: "David A. Long" <dave.long@linaro.org>
For any ARM kprobes/uprobes code interfacing to the generic ARM probes code
use a new probes_opcode_t type to avoid a dependency on kprobes definitions.
Signed-off-by: David A. Long <dave.long@linaro.org>
---
arch/arm/include/asm/probes.h | 7 ++--
arch/arm/kernel/kprobes-arm.c | 16 ++++-----
arch/arm/kernel/kprobes-common.c | 14 ++++----
arch/arm/kernel/kprobes-thumb.c | 72 ++++++++++++++++++++--------------------
arch/arm/kernel/kprobes.h | 8 ++---
arch/arm/kernel/probes-arm.c | 14 ++++----
arch/arm/kernel/probes-arm.h | 10 +++---
arch/arm/kernel/probes-thumb.c | 8 ++---
arch/arm/kernel/probes.c | 20 +++++------
arch/arm/kernel/probes.h | 8 ++---
10 files changed, 89 insertions(+), 88 deletions(-)
diff --git a/arch/arm/include/asm/probes.h b/arch/arm/include/asm/probes.h
index a7b0a79..8032591 100644
--- a/arch/arm/include/asm/probes.h
+++ b/arch/arm/include/asm/probes.h
@@ -2,20 +2,21 @@
#define _ASM_PROBES_H
struct kprobe;
+typedef u32 probes_opcode_t;
struct arch_specific_insn;
-typedef void (kprobe_insn_handler_t)(kprobe_opcode_t,
+typedef void (kprobe_insn_handler_t)(probes_opcode_t,
struct arch_specific_insn *,
struct pt_regs *);
typedef unsigned long (kprobe_check_cc)(unsigned long);
-typedef void (kprobe_insn_singlestep_t)(kprobe_opcode_t,
+typedef void (kprobe_insn_singlestep_t)(probes_opcode_t,
struct arch_specific_insn *,
struct pt_regs *);
typedef void (kprobe_insn_fn_t)(void);
/* Architecture specific copy of original instruction. */
struct arch_specific_insn {
- kprobe_opcode_t *insn;
+ probes_opcode_t *insn;
kprobe_insn_handler_t *insn_handler;
kprobe_check_cc *insn_check_cc;
kprobe_insn_singlestep_t *insn_singlestep;
diff --git a/arch/arm/kernel/kprobes-arm.c b/arch/arm/kernel/kprobes-arm.c
index 394b611..1fe3a44 100644
--- a/arch/arm/kernel/kprobes-arm.c
+++ b/arch/arm/kernel/kprobes-arm.c
@@ -73,7 +73,7 @@
#endif
static void __kprobes
-emulate_ldrdstrd(kprobe_opcode_t insn,
+emulate_ldrdstrd(probes_opcode_t insn,
struct arch_specific_insn *asi, struct pt_regs *regs)
{
unsigned long pc = regs->ARM_pc + 4;
@@ -102,7 +102,7 @@ emulate_ldrdstrd(kprobe_opcode_t insn,
}
static void __kprobes
-emulate_ldr(kprobe_opcode_t insn,
+emulate_ldr(probes_opcode_t insn,
struct arch_specific_insn *asi, struct pt_regs *regs)
{
unsigned long pc = regs->ARM_pc + 4;
@@ -132,7 +132,7 @@ emulate_ldr(kprobe_opcode_t insn,
}
static void __kprobes
-emulate_str(kprobe_opcode_t insn,
+emulate_str(probes_opcode_t insn,
struct arch_specific_insn *asi, struct pt_regs *regs)
{
unsigned long rtpc = regs->ARM_pc - 4 + str_pc_offset;
@@ -159,7 +159,7 @@ emulate_str(kprobe_opcode_t insn,
}
static void __kprobes
-emulate_rd12rn16rm0rs8_rwflags(kprobe_opcode_t insn,
+emulate_rd12rn16rm0rs8_rwflags(probes_opcode_t insn,
struct arch_specific_insn *asi, struct pt_regs *regs)
{
unsigned long pc = regs->ARM_pc + 4;
@@ -194,7 +194,7 @@ emulate_rd12rn16rm0rs8_rwflags(kprobe_opcode_t insn,
}
static void __kprobes
-emulate_rd12rn16rm0_rwflags_nopc(kprobe_opcode_t insn,
+emulate_rd12rn16rm0_rwflags_nopc(probes_opcode_t insn,
struct arch_specific_insn *asi, struct pt_regs *regs)
{
int rd = (insn >> 12) & 0xf;
@@ -221,7 +221,7 @@ emulate_rd12rn16rm0_rwflags_nopc(kprobe_opcode_t insn,
}
static void __kprobes
-emulate_rd16rn12rm0rs8_rwflags_nopc(kprobe_opcode_t insn,
+emulate_rd16rn12rm0rs8_rwflags_nopc(probes_opcode_t insn,
struct arch_specific_insn *asi,
struct pt_regs *regs)
{
@@ -251,7 +251,7 @@ emulate_rd16rn12rm0rs8_rwflags_nopc(kprobe_opcode_t insn,
}
static void __kprobes
-emulate_rd12rm0_noflags_nopc(kprobe_opcode_t insn,
+emulate_rd12rm0_noflags_nopc(probes_opcode_t insn,
struct arch_specific_insn *asi, struct pt_regs *regs)
{
int rd = (insn >> 12) & 0xf;
@@ -271,7 +271,7 @@ emulate_rd12rm0_noflags_nopc(kprobe_opcode_t insn,
}
static void __kprobes
-emulate_rdlo12rdhi16rn0rm8_rwflags_nopc(kprobe_opcode_t insn,
+emulate_rdlo12rdhi16rn0rm8_rwflags_nopc(probes_opcode_t insn,
struct arch_specific_insn *asi,
struct pt_regs *regs)
{
diff --git a/arch/arm/kernel/kprobes-common.c b/arch/arm/kernel/kprobes-common.c
index 45590a4..bd3d8c5 100644
--- a/arch/arm/kernel/kprobes-common.c
+++ b/arch/arm/kernel/kprobes-common.c
@@ -18,7 +18,7 @@
#include "kprobes.h"
-static void __kprobes simulate_ldm1stm1(kprobe_opcode_t insn,
+static void __kprobes simulate_ldm1stm1(probes_opcode_t insn,
struct arch_specific_insn *asi,
struct pt_regs *regs)
{
@@ -60,7 +60,7 @@ static void __kprobes simulate_ldm1stm1(kprobe_opcode_t insn,
}
}
-static void __kprobes simulate_stm1_pc(kprobe_opcode_t insn,
+static void __kprobes simulate_stm1_pc(probes_opcode_t insn,
struct arch_specific_insn *asi,
struct pt_regs *regs)
{
@@ -71,7 +71,7 @@ static void __kprobes simulate_stm1_pc(kprobe_opcode_t insn,
regs->ARM_pc = (long)addr + 4;
}
-static void __kprobes simulate_ldm1_pc(kprobe_opcode_t insn,
+static void __kprobes simulate_ldm1_pc(probes_opcode_t insn,
struct arch_specific_insn *asi,
struct pt_regs *regs)
{
@@ -80,7 +80,7 @@ static void __kprobes simulate_ldm1_pc(kprobe_opcode_t insn,
}
static void __kprobes
-emulate_generic_r0_12_noflags(kprobe_opcode_t insn,
+emulate_generic_r0_12_noflags(probes_opcode_t insn,
struct arch_specific_insn *asi, struct pt_regs *regs)
{
register void *rregs asm("r1") = regs;
@@ -108,7 +108,7 @@ emulate_generic_r0_12_noflags(kprobe_opcode_t insn,
}
static void __kprobes
-emulate_generic_r2_14_noflags(kprobe_opcode_t insn,
+emulate_generic_r2_14_noflags(probes_opcode_t insn,
struct arch_specific_insn *asi, struct pt_regs *regs)
{
emulate_generic_r0_12_noflags(insn, asi,
@@ -116,7 +116,7 @@ emulate_generic_r2_14_noflags(kprobe_opcode_t insn,
}
static void __kprobes
-emulate_ldm_r3_15(kprobe_opcode_t insn,
+emulate_ldm_r3_15(probes_opcode_t insn,
struct arch_specific_insn *asi, struct pt_regs *regs)
{
emulate_generic_r0_12_noflags(insn, asi,
@@ -125,7 +125,7 @@ emulate_ldm_r3_15(kprobe_opcode_t insn,
}
enum kprobe_insn __kprobes
-kprobe_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi,
+kprobe_decode_ldmstm(probes_opcode_t insn, struct arch_specific_insn *asi,
struct decode_header *h)
{
kprobe_insn_handler_t *handler = 0;
diff --git a/arch/arm/kernel/kprobes-thumb.c b/arch/arm/kernel/kprobes-thumb.c
index d0bbbf7..c648c31 100644
--- a/arch/arm/kernel/kprobes-thumb.c
+++ b/arch/arm/kernel/kprobes-thumb.c
@@ -22,7 +22,7 @@
/* t32 thumb actions */
static void __kprobes
-t32_simulate_table_branch(kprobe_opcode_t insn,
+t32_simulate_table_branch(probes_opcode_t insn,
struct arch_specific_insn *asi, struct pt_regs *regs)
{
unsigned long pc = regs->ARM_pc;
@@ -42,7 +42,7 @@ t32_simulate_table_branch(kprobe_opcode_t insn,
}
static void __kprobes
-t32_simulate_mrs(kprobe_opcode_t insn,
+t32_simulate_mrs(probes_opcode_t insn,
struct arch_specific_insn *asi, struct pt_regs *regs)
{
int rd = (insn >> 8) & 0xf;
@@ -51,7 +51,7 @@ t32_simulate_mrs(kprobe_opcode_t insn,
}
static void __kprobes
-t32_simulate_cond_branch(kprobe_opcode_t insn,
+t32_simulate_cond_branch(probes_opcode_t insn,
struct arch_specific_insn *asi, struct pt_regs *regs)
{
unsigned long pc = regs->ARM_pc;
@@ -66,7 +66,7 @@ t32_simulate_cond_branch(kprobe_opcode_t insn,
}
static enum kprobe_insn __kprobes
-t32_decode_cond_branch(kprobe_opcode_t insn, struct arch_specific_insn *asi,
+t32_decode_cond_branch(probes_opcode_t insn, struct arch_specific_insn *asi,
struct decode_header *d)
{
int cc = (insn >> 22) & 0xf;
@@ -76,7 +76,7 @@ t32_decode_cond_branch(kprobe_opcode_t insn, struct arch_specific_insn *asi,
}
static void __kprobes
-t32_simulate_branch(kprobe_opcode_t insn,
+t32_simulate_branch(probes_opcode_t insn,
struct arch_specific_insn *asi, struct pt_regs *regs)
{
unsigned long pc = regs->ARM_pc;
@@ -104,7 +104,7 @@ t32_simulate_branch(kprobe_opcode_t insn,
}
static void __kprobes
-t32_simulate_ldr_literal(kprobe_opcode_t insn,
+t32_simulate_ldr_literal(probes_opcode_t insn,
struct arch_specific_insn *asi, struct pt_regs *regs)
{
unsigned long addr = regs->ARM_pc & ~3;
@@ -142,7 +142,7 @@ t32_simulate_ldr_literal(kprobe_opcode_t insn,
}
enum kprobe_insn __kprobes
-t32_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi,
+t32_decode_ldmstm(probes_opcode_t insn, struct arch_specific_insn *asi,
struct decode_header *d)
{
enum kprobe_insn ret = kprobe_decode_ldmstm(insn, asi, d);
@@ -156,7 +156,7 @@ t32_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi,
}
static void __kprobes
-t32_emulate_ldrdstrd(kprobe_opcode_t insn,
+t32_emulate_ldrdstrd(probes_opcode_t insn,
struct arch_specific_insn *asi, struct pt_regs *regs)
{
unsigned long pc = regs->ARM_pc & ~3;
@@ -183,7 +183,7 @@ t32_emulate_ldrdstrd(kprobe_opcode_t insn,
}
static void __kprobes
-t32_emulate_ldrstr(kprobe_opcode_t insn,
+t32_emulate_ldrstr(probes_opcode_t insn,
struct arch_specific_insn *asi, struct pt_regs *regs)
{
int rt = (insn >> 12) & 0xf;
@@ -209,7 +209,7 @@ t32_emulate_ldrstr(kprobe_opcode_t insn,
}
static void __kprobes
-t32_emulate_rd8rn16rm0_rwflags(kprobe_opcode_t insn,
+t32_emulate_rd8rn16rm0_rwflags(probes_opcode_t insn,
struct arch_specific_insn *asi, struct pt_regs *regs)
{
int rd = (insn >> 8) & 0xf;
@@ -236,7 +236,7 @@ t32_emulate_rd8rn16rm0_rwflags(kprobe_opcode_t insn,
}
static void __kprobes
-t32_emulate_rd8pc16_noflags(kprobe_opcode_t insn,
+t32_emulate_rd8pc16_noflags(probes_opcode_t insn,
struct arch_specific_insn *asi, struct pt_regs *regs)
{
unsigned long pc = regs->ARM_pc;
@@ -256,7 +256,7 @@ t32_emulate_rd8pc16_noflags(kprobe_opcode_t insn,
}
static void __kprobes
-t32_emulate_rd8rn16_noflags(kprobe_opcode_t insn,
+t32_emulate_rd8rn16_noflags(probes_opcode_t insn,
struct arch_specific_insn *asi, struct pt_regs *regs)
{
int rd = (insn >> 8) & 0xf;
@@ -276,7 +276,7 @@ t32_emulate_rd8rn16_noflags(kprobe_opcode_t insn,
}
static void __kprobes
-t32_emulate_rdlo12rdhi8rn16rm0_noflags(kprobe_opcode_t insn,
+t32_emulate_rdlo12rdhi8rn16rm0_noflags(probes_opcode_t insn,
struct arch_specific_insn *asi,
struct pt_regs *regs)
{
@@ -304,7 +304,7 @@ t32_emulate_rdlo12rdhi8rn16rm0_noflags(kprobe_opcode_t insn,
/* t16 thumb actions */
static void __kprobes
-t16_simulate_bxblx(kprobe_opcode_t insn,
+t16_simulate_bxblx(probes_opcode_t insn,
struct arch_specific_insn *asi, struct pt_regs *regs)
{
unsigned long pc = regs->ARM_pc + 2;
@@ -318,7 +318,7 @@ t16_simulate_bxblx(kprobe_opcode_t insn,
}
static void __kprobes
-t16_simulate_ldr_literal(kprobe_opcode_t insn,
+t16_simulate_ldr_literal(probes_opcode_t insn,
struct arch_specific_insn *asi, struct pt_regs *regs)
{
unsigned long *base = (unsigned long *)((regs->ARM_pc + 2) & ~3);
@@ -328,7 +328,7 @@ t16_simulate_ldr_literal(kprobe_opcode_t insn,
}
static void __kprobes
-t16_simulate_ldrstr_sp_relative(kprobe_opcode_t insn,
+t16_simulate_ldrstr_sp_relative(probes_opcode_t insn,
struct arch_specific_insn *asi, struct pt_regs *regs)
{
unsigned long* base = (unsigned long *)regs->ARM_sp;
@@ -341,7 +341,7 @@ t16_simulate_ldrstr_sp_relative(kprobe_opcode_t insn,
}
static void __kprobes
-t16_simulate_reladr(kprobe_opcode_t insn,
+t16_simulate_reladr(probes_opcode_t insn,
struct arch_specific_insn *asi, struct pt_regs *regs)
{
unsigned long base = (insn & 0x800) ? regs->ARM_sp
@@ -352,7 +352,7 @@ t16_simulate_reladr(kprobe_opcode_t insn,
}
static void __kprobes
-t16_simulate_add_sp_imm(kprobe_opcode_t insn,
+t16_simulate_add_sp_imm(probes_opcode_t insn,
struct arch_specific_insn *asi, struct pt_regs *regs)
{
long imm = insn & 0x7f;
@@ -363,11 +363,11 @@ t16_simulate_add_sp_imm(kprobe_opcode_t insn,
}
static void __kprobes
-t16_simulate_cbz(kprobe_opcode_t insn,
+t16_simulate_cbz(probes_opcode_t insn,
struct arch_specific_insn *asi, struct pt_regs *regs)
{
int rn = insn & 0x7;
- kprobe_opcode_t nonzero = regs->uregs[rn] ? insn : ~insn;
+ probes_opcode_t nonzero = regs->uregs[rn] ? insn : ~insn;
if (nonzero & 0x800) {
long i = insn & 0x200;
long imm5 = insn & 0xf8;
@@ -377,7 +377,7 @@ t16_simulate_cbz(kprobe_opcode_t insn,
}
static void __kprobes
-t16_simulate_it(kprobe_opcode_t insn,
+t16_simulate_it(probes_opcode_t insn,
struct arch_specific_insn *asi, struct pt_regs *regs)
{
/*
@@ -394,7 +394,7 @@ t16_simulate_it(kprobe_opcode_t insn,
}
static void __kprobes
-t16_singlestep_it(kprobe_opcode_t insn,
+t16_singlestep_it(probes_opcode_t insn,
struct arch_specific_insn *asi, struct pt_regs *regs)
{
regs->ARM_pc += 2;
@@ -402,7 +402,7 @@ t16_singlestep_it(kprobe_opcode_t insn,
}
static enum kprobe_insn __kprobes
-t16_decode_it(kprobe_opcode_t insn, struct arch_specific_insn *asi,
+t16_decode_it(probes_opcode_t insn, struct arch_specific_insn *asi,
struct decode_header *d)
{
asi->insn_singlestep = t16_singlestep_it;
@@ -410,7 +410,7 @@ t16_decode_it(kprobe_opcode_t insn, struct arch_specific_insn *asi,
}
static void __kprobes
-t16_simulate_cond_branch(kprobe_opcode_t insn,
+t16_simulate_cond_branch(probes_opcode_t insn,
struct arch_specific_insn *asi, struct pt_regs *regs)
{
unsigned long pc = regs->ARM_pc + 2;
@@ -420,7 +420,7 @@ t16_simulate_cond_branch(kprobe_opcode_t insn,
}
static enum kprobe_insn __kprobes
-t16_decode_cond_branch(kprobe_opcode_t insn, struct arch_specific_insn *asi,
+t16_decode_cond_branch(probes_opcode_t insn, struct arch_specific_insn *asi,
struct decode_header *d)
{
int cc = (insn >> 8) & 0xf;
@@ -430,7 +430,7 @@ t16_decode_cond_branch(kprobe_opcode_t insn, struct arch_specific_insn *asi,
}
static void __kprobes
-t16_simulate_branch(kprobe_opcode_t insn,
+t16_simulate_branch(probes_opcode_t insn,
struct arch_specific_insn *asi, struct pt_regs *regs)
{
unsigned long pc = regs->ARM_pc + 2;
@@ -440,7 +440,7 @@ t16_simulate_branch(kprobe_opcode_t insn,
}
static unsigned long __kprobes
-t16_emulate_loregs(kprobe_opcode_t insn,
+t16_emulate_loregs(probes_opcode_t insn,
struct arch_specific_insn *asi, struct pt_regs *regs)
{
unsigned long oldcpsr = regs->ARM_cpsr;
@@ -463,14 +463,14 @@ t16_emulate_loregs(kprobe_opcode_t insn,
}
static void __kprobes
-t16_emulate_loregs_rwflags(kprobe_opcode_t insn,
+t16_emulate_loregs_rwflags(probes_opcode_t insn,
struct arch_specific_insn *asi, struct pt_regs *regs)
{
regs->ARM_cpsr = t16_emulate_loregs(insn, asi, regs);
}
static void __kprobes
-t16_emulate_loregs_noitrwflags(kprobe_opcode_t insn,
+t16_emulate_loregs_noitrwflags(probes_opcode_t insn,
struct arch_specific_insn *asi, struct pt_regs *regs)
{
unsigned long cpsr = t16_emulate_loregs(insn, asi, regs);
@@ -479,7 +479,7 @@ t16_emulate_loregs_noitrwflags(kprobe_opcode_t insn,
}
static void __kprobes
-t16_emulate_hiregs(kprobe_opcode_t insn,
+t16_emulate_hiregs(probes_opcode_t insn,
struct arch_specific_insn *asi, struct pt_regs *regs)
{
unsigned long pc = regs->ARM_pc + 2;
@@ -510,7 +510,7 @@ t16_emulate_hiregs(kprobe_opcode_t insn,
}
static enum kprobe_insn __kprobes
-t16_decode_hiregs(kprobe_opcode_t insn, struct arch_specific_insn *asi,
+t16_decode_hiregs(probes_opcode_t insn, struct arch_specific_insn *asi,
struct decode_header *d)
{
insn &= ~0x00ff;
@@ -521,7 +521,7 @@ t16_decode_hiregs(kprobe_opcode_t insn, struct arch_specific_insn *asi,
}
static void __kprobes
-t16_emulate_push(kprobe_opcode_t insn,
+t16_emulate_push(probes_opcode_t insn,
struct arch_specific_insn *asi, struct pt_regs *regs)
{
__asm__ __volatile__ (
@@ -538,7 +538,7 @@ t16_emulate_push(kprobe_opcode_t insn,
}
static enum kprobe_insn __kprobes
-t16_decode_push(kprobe_opcode_t insn, struct arch_specific_insn *asi,
+t16_decode_push(probes_opcode_t insn, struct arch_specific_insn *asi,
struct decode_header *d)
{
/*
@@ -553,7 +553,7 @@ t16_decode_push(kprobe_opcode_t insn, struct arch_specific_insn *asi,
}
static void __kprobes
-t16_emulate_pop_nopc(kprobe_opcode_t insn,
+t16_emulate_pop_nopc(probes_opcode_t insn,
struct arch_specific_insn *asi, struct pt_regs *regs)
{
__asm__ __volatile__ (
@@ -570,7 +570,7 @@ t16_emulate_pop_nopc(kprobe_opcode_t insn,
}
static void __kprobes
-t16_emulate_pop_pc(kprobe_opcode_t insn,
+t16_emulate_pop_pc(probes_opcode_t insn,
struct arch_specific_insn *asi, struct pt_regs *regs)
{
register unsigned long pc asm("r8");
@@ -591,7 +591,7 @@ t16_emulate_pop_pc(kprobe_opcode_t insn,
}
enum kprobe_insn __kprobes
-t16_decode_pop(kprobe_opcode_t insn, struct arch_specific_insn *asi,
+t16_decode_pop(probes_opcode_t insn, struct arch_specific_insn *asi,
struct decode_header *d)
{
/*
diff --git a/arch/arm/kernel/kprobes.h b/arch/arm/kernel/kprobes.h
index 6c1ed3c..c8a8413 100644
--- a/arch/arm/kernel/kprobes.h
+++ b/arch/arm/kernel/kprobes.h
@@ -35,22 +35,22 @@ enum kprobe_insn {
INSN_GOOD_NO_SLOT
};
-typedef enum kprobe_insn (kprobe_decode_insn_t)(kprobe_opcode_t,
+typedef enum kprobe_insn (kprobe_decode_insn_t)(probes_opcode_t,
struct arch_specific_insn *,
struct decode_header *);
#ifdef CONFIG_THUMB2_KERNEL
-enum kprobe_insn thumb16_kprobe_decode_insn(kprobe_opcode_t,
+enum kprobe_insn thumb16_kprobe_decode_insn(probes_opcode_t,
struct arch_specific_insn *,
struct decode_header *);
-enum kprobe_insn thumb32_kprobe_decode_insn(kprobe_opcode_t,
+enum kprobe_insn thumb32_kprobe_decode_insn(probes_opcode_t,
struct arch_specific_insn *,
struct decode_header *);
#else /* !CONFIG_THUMB2_KERNEL */
-enum kprobe_insn arm_kprobe_decode_insn(kprobe_opcode_t,
+enum kprobe_insn arm_kprobe_decode_insn(probes_opcode_t,
struct arch_specific_insn *,
struct decode_header *);
diff --git a/arch/arm/kernel/probes-arm.c b/arch/arm/kernel/probes-arm.c
index 3aba9c3..e50fb03 100644
--- a/arch/arm/kernel/probes-arm.c
+++ b/arch/arm/kernel/probes-arm.c
@@ -55,7 +55,7 @@
* read and write of flags.
*/
-void __kprobes simulate_bbl(kprobe_opcode_t insn,
+void __kprobes simulate_bbl(probes_opcode_t insn,
struct arch_specific_insn *asi, struct pt_regs *regs)
{
long iaddr = (long) regs->ARM_pc - 4;
@@ -67,7 +67,7 @@ void __kprobes simulate_bbl(kprobe_opcode_t insn,
regs->ARM_pc = iaddr + 8 + disp;
}
-void __kprobes simulate_blx1(kprobe_opcode_t insn,
+void __kprobes simulate_blx1(probes_opcode_t insn,
struct arch_specific_insn *asi, struct pt_regs *regs)
{
long iaddr = (long) regs->ARM_pc - 4;
@@ -78,7 +78,7 @@ void __kprobes simulate_blx1(kprobe_opcode_t insn,
regs->ARM_cpsr |= PSR_T_BIT;
}
-void __kprobes simulate_blx2bx(kprobe_opcode_t insn,
+void __kprobes simulate_blx2bx(probes_opcode_t insn,
struct arch_specific_insn *asi, struct pt_regs *regs)
{
int rm = insn & 0xf;
@@ -93,7 +93,7 @@ void __kprobes simulate_blx2bx(kprobe_opcode_t insn,
regs->ARM_cpsr |= PSR_T_BIT;
}
-void __kprobes simulate_mrs(kprobe_opcode_t insn,
+void __kprobes simulate_mrs(probes_opcode_t insn,
struct arch_specific_insn *asi, struct pt_regs *regs)
{
int rd = (insn >> 12) & 0xf;
@@ -101,7 +101,7 @@ void __kprobes simulate_mrs(kprobe_opcode_t insn,
regs->uregs[rd] = regs->ARM_cpsr & mask;
}
-void __kprobes simulate_mov_ipsp(kprobe_opcode_t insn,
+void __kprobes simulate_mov_ipsp(probes_opcode_t insn,
struct arch_specific_insn *asi, struct pt_regs *regs)
{
regs->uregs[12] = regs->uregs[13];
@@ -702,7 +702,7 @@ const union decode_item kprobe_decode_arm_table[] = {
EXPORT_SYMBOL_GPL(kprobe_decode_arm_table);
#endif
-static void __kprobes arm_singlestep(kprobe_opcode_t insn,
+static void __kprobes arm_singlestep(probes_opcode_t insn,
struct arch_specific_insn *asi, struct pt_regs *regs)
{
regs->ARM_pc += 4;
@@ -722,7 +722,7 @@ static void __kprobes arm_singlestep(kprobe_opcode_t insn,
* should also be very rare.
*/
enum kprobe_insn __kprobes
-arm_kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi,
+arm_kprobe_decode_insn(probes_opcode_t insn, struct arch_specific_insn *asi,
struct decode_header *actions)
{
asi->insn_singlestep = arm_singlestep;
diff --git a/arch/arm/kernel/probes-arm.h b/arch/arm/kernel/probes-arm.h
index 2c9e841..2662ada 100644
--- a/arch/arm/kernel/probes-arm.h
+++ b/arch/arm/kernel/probes-arm.h
@@ -52,15 +52,15 @@ enum probes_arm_action {
PROBES_LDMSTM
};
-void __kprobes simulate_bbl(kprobe_opcode_t opcode,
+void __kprobes simulate_bbl(probes_opcode_t opcode,
struct arch_specific_insn *asi, struct pt_regs *regs);
-void __kprobes simulate_blx1(kprobe_opcode_t opcode,
+void __kprobes simulate_blx1(probes_opcode_t opcode,
struct arch_specific_insn *asi, struct pt_regs *regs);
-void __kprobes simulate_blx2bx(kprobe_opcode_t opcode,
+void __kprobes simulate_blx2bx(probes_opcode_t opcode,
struct arch_specific_insn *asi, struct pt_regs *regs);
-void __kprobes simulate_mrs(kprobe_opcode_t opcode,
+void __kprobes simulate_mrs(probes_opcode_t opcode,
struct arch_specific_insn *asi, struct pt_regs *regs);
-void __kprobes simulate_mov_ipsp(kprobe_opcode_t opcode,
+void __kprobes simulate_mov_ipsp(probes_opcode_t opcode,
struct arch_specific_insn *asi, struct pt_regs *regs);
#endif
diff --git a/arch/arm/kernel/probes-thumb.c b/arch/arm/kernel/probes-thumb.c
index fb79dd9..e6dbbc3 100644
--- a/arch/arm/kernel/probes-thumb.c
+++ b/arch/arm/kernel/probes-thumb.c
@@ -841,7 +841,7 @@ static unsigned long __kprobes thumb_check_cc(unsigned long cpsr)
return true;
}
-static void __kprobes thumb16_singlestep(kprobe_opcode_t opcode,
+static void __kprobes thumb16_singlestep(probes_opcode_t opcode,
struct arch_specific_insn *asi,
struct pt_regs *regs)
{
@@ -850,7 +850,7 @@ static void __kprobes thumb16_singlestep(kprobe_opcode_t opcode,
regs->ARM_cpsr = it_advance(regs->ARM_cpsr);
}
-static void __kprobes thumb32_singlestep(kprobe_opcode_t opcode,
+static void __kprobes thumb32_singlestep(probes_opcode_t opcode,
struct arch_specific_insn *asi,
struct pt_regs *regs)
{
@@ -860,7 +860,7 @@ static void __kprobes thumb32_singlestep(kprobe_opcode_t opcode,
}
enum kprobe_insn __kprobes
-thumb16_kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi,
+thumb16_kprobe_decode_insn(probes_opcode_t insn, struct arch_specific_insn *asi,
struct decode_header *actions)
{
asi->insn_singlestep = thumb16_singlestep;
@@ -870,7 +870,7 @@ thumb16_kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi,
}
enum kprobe_insn __kprobes
-thumb32_kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi,
+thumb32_kprobe_decode_insn(probes_opcode_t insn, struct arch_specific_insn *asi,
struct decode_header *actions)
{
asi->insn_singlestep = thumb32_singlestep;
diff --git a/arch/arm/kernel/probes.c b/arch/arm/kernel/probes.c
index b2db250..7354448 100644
--- a/arch/arm/kernel/probes.c
+++ b/arch/arm/kernel/probes.c
@@ -171,13 +171,13 @@ kprobe_check_cc * const kprobe_condition_checks[16] = {
};
-void __kprobes kprobe_simulate_nop(kprobe_opcode_t opcode,
+void __kprobes kprobe_simulate_nop(probes_opcode_t opcode,
struct arch_specific_insn *asi,
struct pt_regs *regs)
{
}
-void __kprobes kprobe_emulate_none(kprobe_opcode_t opcode,
+void __kprobes kprobe_emulate_none(probes_opcode_t opcode,
struct arch_specific_insn *asi,
struct pt_regs *regs)
{
@@ -191,8 +191,8 @@ void __kprobes kprobe_emulate_none(kprobe_opcode_t opcode,
* unconditional as the condition code will already be checked before any
* emulation handler is called.
*/
-static kprobe_opcode_t __kprobes
-prepare_emulated_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi,
+static probes_opcode_t __kprobes
+prepare_emulated_insn(probes_opcode_t insn, struct arch_specific_insn *asi,
bool thumb)
{
#ifdef CONFIG_THUMB2_KERNEL
@@ -217,7 +217,7 @@ prepare_emulated_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi,
* prepare_emulated_insn
*/
static void __kprobes
-set_emulated_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi,
+set_emulated_insn(probes_opcode_t insn, struct arch_specific_insn *asi,
bool thumb)
{
#ifdef CONFIG_THUMB2_KERNEL
@@ -253,14 +253,14 @@ set_emulated_insn(kprobe_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(kprobe_opcode_t *pinsn, u32 regs)
+static bool __kprobes decode_regs(probes_opcode_t *pinsn, u32 regs)
{
- kprobe_opcode_t insn = *pinsn;
- kprobe_opcode_t mask = 0xf; /* Start at least significant nibble */
+ probes_opcode_t insn = *pinsn;
+ probes_opcode_t mask = 0xf; /* Start at least significant nibble */
for (; regs != 0; regs >>= 4, mask <<= 4) {
- kprobe_opcode_t new_bits = INSN_NEW_BITS;
+ probes_opcode_t new_bits = INSN_NEW_BITS;
switch (regs & 0xf) {
@@ -379,7 +379,7 @@ static const int decode_struct_sizes[NUM_DECODE_TYPES] = {
*
*/
int __kprobes
-kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi,
+kprobe_decode_insn(probes_opcode_t insn, struct arch_specific_insn *asi,
const union decode_item *table, bool thumb,
const union decode_item *actions)
{
diff --git a/arch/arm/kernel/probes.h b/arch/arm/kernel/probes.h
index 45151a1..c0536b1 100644
--- a/arch/arm/kernel/probes.h
+++ b/arch/arm/kernel/probes.h
@@ -129,13 +129,13 @@ static inline void __kprobes alu_write_pc(long pcv, struct pt_regs *regs)
}
-void __kprobes kprobe_simulate_nop(kprobe_opcode_t, struct arch_specific_insn *,
+void __kprobes kprobe_simulate_nop(probes_opcode_t, struct arch_specific_insn *,
struct pt_regs *regs);
-void __kprobes kprobe_emulate_none(kprobe_opcode_t, struct arch_specific_insn *,
+void __kprobes kprobe_emulate_none(probes_opcode_t, struct arch_specific_insn *,
struct pt_regs *regs);
enum kprobe_insn __kprobes
-kprobe_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi,
+kprobe_decode_ldmstm(probes_opcode_t insn, struct arch_specific_insn *asi,
struct decode_header *h);
/*
@@ -397,7 +397,7 @@ extern const union decode_item kprobes_arm_actions[];
extern kprobe_check_cc * const kprobe_condition_checks[16];
-int kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi,
+int kprobe_decode_insn(probes_opcode_t insn, struct arch_specific_insn *asi,
const union decode_item *table, bool thumb16,
const union decode_item *actions);
--
1.8.1.2
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH v4 09/16] ARM: Make the kprobes condition_check symbol names more generic
2013-12-16 4:08 [PATCH v4 00/16] uprobes: Add uprobes support for ARM David Long
` (7 preceding siblings ...)
2013-12-16 4:08 ` [PATCH v4 08/16] ARM: Use new opcode type in ARM kprobes/uprobes code David Long
@ 2013-12-16 4:08 ` David Long
2013-12-16 4:08 ` [PATCH v4 10/16] ARM: Change more ARM kprobes symbol names to something more David Long
` (6 subsequent siblings)
15 siblings, 0 replies; 34+ messages in thread
From: David Long @ 2013-12-16 4:08 UTC (permalink / raw)
To: linux-arm-kernel
From: "David A. Long" <dave.long@linaro.org>
In preparation for sharing the ARM kprobes instruction interpreting
code with uprobes, make the symbols names less kprobes-specific.
Signed-off-by: David A. Long <dave.long@linaro.org>
---
arch/arm/include/asm/probes.h | 4 ++--
arch/arm/kernel/kprobes-thumb.c | 4 ++--
arch/arm/kernel/probes-arm.c | 2 +-
arch/arm/kernel/probes-thumb.c | 2 +-
arch/arm/kernel/probes.c | 2 +-
arch/arm/kernel/probes.h | 2 +-
6 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/arch/arm/include/asm/probes.h b/arch/arm/include/asm/probes.h
index 8032591..81b05b0 100644
--- a/arch/arm/include/asm/probes.h
+++ b/arch/arm/include/asm/probes.h
@@ -8,7 +8,7 @@ struct arch_specific_insn;
typedef void (kprobe_insn_handler_t)(probes_opcode_t,
struct arch_specific_insn *,
struct pt_regs *);
-typedef unsigned long (kprobe_check_cc)(unsigned long);
+typedef unsigned long (probes_check_cc)(unsigned long);
typedef void (kprobe_insn_singlestep_t)(probes_opcode_t,
struct arch_specific_insn *,
struct pt_regs *);
@@ -18,7 +18,7 @@ typedef void (kprobe_insn_fn_t)(void);
struct arch_specific_insn {
probes_opcode_t *insn;
kprobe_insn_handler_t *insn_handler;
- kprobe_check_cc *insn_check_cc;
+ probes_check_cc *insn_check_cc;
kprobe_insn_singlestep_t *insn_singlestep;
kprobe_insn_fn_t *insn_fn;
};
diff --git a/arch/arm/kernel/kprobes-thumb.c b/arch/arm/kernel/kprobes-thumb.c
index c648c31..da1e24b 100644
--- a/arch/arm/kernel/kprobes-thumb.c
+++ b/arch/arm/kernel/kprobes-thumb.c
@@ -70,7 +70,7 @@ t32_decode_cond_branch(probes_opcode_t insn, struct arch_specific_insn *asi,
struct decode_header *d)
{
int cc = (insn >> 22) & 0xf;
- asi->insn_check_cc = kprobe_condition_checks[cc];
+ asi->insn_check_cc = probes_condition_checks[cc];
asi->insn_handler = t32_simulate_cond_branch;
return INSN_GOOD_NO_SLOT;
}
@@ -424,7 +424,7 @@ t16_decode_cond_branch(probes_opcode_t insn, struct arch_specific_insn *asi,
struct decode_header *d)
{
int cc = (insn >> 8) & 0xf;
- asi->insn_check_cc = kprobe_condition_checks[cc];
+ asi->insn_check_cc = probes_condition_checks[cc];
asi->insn_handler = t16_simulate_cond_branch;
return INSN_GOOD_NO_SLOT;
}
diff --git a/arch/arm/kernel/probes-arm.c b/arch/arm/kernel/probes-arm.c
index e50fb03..95ef3e3 100644
--- a/arch/arm/kernel/probes-arm.c
+++ b/arch/arm/kernel/probes-arm.c
@@ -726,7 +726,7 @@ arm_kprobe_decode_insn(probes_opcode_t insn, struct arch_specific_insn *asi,
struct decode_header *actions)
{
asi->insn_singlestep = arm_singlestep;
- asi->insn_check_cc = kprobe_condition_checks[insn>>28];
+ asi->insn_check_cc = probes_condition_checks[insn>>28];
return kprobe_decode_insn(insn, asi, kprobe_decode_arm_table, false,
(const union decode_item *) actions);
}
diff --git a/arch/arm/kernel/probes-thumb.c b/arch/arm/kernel/probes-thumb.c
index e6dbbc3..055faf0 100644
--- a/arch/arm/kernel/probes-thumb.c
+++ b/arch/arm/kernel/probes-thumb.c
@@ -837,7 +837,7 @@ EXPORT_SYMBOL_GPL(kprobe_decode_thumb16_table);
static unsigned long __kprobes thumb_check_cc(unsigned long cpsr)
{
if (unlikely(in_it_block(cpsr)))
- return kprobe_condition_checks[current_cond(cpsr)](cpsr);
+ return probes_condition_checks[current_cond(cpsr)](cpsr);
return true;
}
diff --git a/arch/arm/kernel/probes.c b/arch/arm/kernel/probes.c
index 7354448..36fafd2 100644
--- a/arch/arm/kernel/probes.c
+++ b/arch/arm/kernel/probes.c
@@ -163,7 +163,7 @@ static unsigned long __kprobes __check_al(unsigned long cpsr)
return true;
}
-kprobe_check_cc * const kprobe_condition_checks[16] = {
+probes_check_cc * const probes_condition_checks[16] = {
&__check_eq, &__check_ne, &__check_cs, &__check_cc,
&__check_mi, &__check_pl, &__check_vs, &__check_vc,
&__check_hi, &__check_ls, &__check_ge, &__check_lt,
diff --git a/arch/arm/kernel/probes.h b/arch/arm/kernel/probes.h
index c0536b1..e7c7a92 100644
--- a/arch/arm/kernel/probes.h
+++ b/arch/arm/kernel/probes.h
@@ -394,7 +394,7 @@ extern const union decode_item kprobe_decode_arm_table[];
extern const union decode_item kprobes_arm_actions[];
#endif
-extern kprobe_check_cc * const kprobe_condition_checks[16];
+extern probes_check_cc * const probes_condition_checks[16];
int kprobe_decode_insn(probes_opcode_t insn, struct arch_specific_insn *asi,
--
1.8.1.2
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH v4 10/16] ARM: Change more ARM kprobes symbol names to something more
2013-12-16 4:08 [PATCH v4 00/16] uprobes: Add uprobes support for ARM David Long
` (8 preceding siblings ...)
2013-12-16 4:08 ` [PATCH v4 09/16] ARM: Make the kprobes condition_check symbol names more generic David Long
@ 2013-12-16 4:08 ` David Long
2013-12-16 4:08 ` [PATCH v4 11/16] ARM: Rename the shared kprobes/uprobe return value enum David Long
` (5 subsequent siblings)
15 siblings, 0 replies; 34+ messages in thread
From: David Long @ 2013-12-16 4:08 UTC (permalink / raw)
To: linux-arm-kernel
From: "David A. Long" <dave.long@linaro.org>
Change kprobe_emulate_none, kprobe_simulate_nop, and arm_kprobe_decode_init
function names to something more appropriate for code being shared
outside of the kprobes subsystem. Also, move the new arm_probes_decode_init
declaration out of the kprobes.h include file and into the probes.h include file.
Signed-off-by: David A. Long <dave.long@linaro.org>
---
arch/arm/kernel/kprobes-arm.c | 12 ++++++------
arch/arm/kernel/kprobes-thumb.c | 10 +++++-----
arch/arm/kernel/kprobes.c | 2 +-
arch/arm/kernel/kprobes.h | 2 --
arch/arm/kernel/probes.c | 6 +++---
arch/arm/kernel/probes.h | 6 ++++--
6 files changed, 19 insertions(+), 19 deletions(-)
diff --git a/arch/arm/kernel/kprobes-arm.c b/arch/arm/kernel/kprobes-arm.c
index 1fe3a44..ccb10bc 100644
--- a/arch/arm/kernel/kprobes-arm.c
+++ b/arch/arm/kernel/kprobes-arm.c
@@ -302,10 +302,10 @@ emulate_rdlo12rdhi16rn0rm8_rwflags_nopc(probes_opcode_t insn,
}
const union decode_item kprobes_arm_actions[] = {
- [PROBES_EMULATE_NONE] = {.handler = kprobe_emulate_none},
- [PROBES_SIMULATE_NOP] = {.handler = kprobe_simulate_nop},
- [PROBES_PRELOAD_IMM] = {.handler = kprobe_simulate_nop},
- [PROBES_PRELOAD_REG] = {.handler = kprobe_simulate_nop},
+ [PROBES_EMULATE_NONE] = {.handler = probes_emulate_none},
+ [PROBES_SIMULATE_NOP] = {.handler = probes_simulate_nop},
+ [PROBES_PRELOAD_IMM] = {.handler = probes_simulate_nop},
+ [PROBES_PRELOAD_REG] = {.handler = probes_simulate_nop},
[PROBES_BRANCH_IMM] = {.handler = simulate_blx1},
[PROBES_MRS] = {.handler = simulate_mrs},
[PROBES_BRANCH_REG] = {.handler = simulate_blx2bx},
@@ -326,8 +326,8 @@ const union decode_item kprobes_arm_actions[] = {
[PROBES_DATA_PROCESSING_IMM] = {
.handler = emulate_rd12rn16rm0rs8_rwflags},
[PROBES_MOV_HALFWORD] = {.handler = emulate_rd12rm0_noflags_nopc},
- [PROBES_SEV] = {.handler = kprobe_emulate_none},
- [PROBES_WFE] = {.handler = kprobe_simulate_nop},
+ [PROBES_SEV] = {.handler = probes_emulate_none},
+ [PROBES_WFE] = {.handler = probes_simulate_nop},
[PROBES_SATURATE] = {.handler = emulate_rd12rn16rm0_rwflags_nopc},
[PROBES_REV] = {.handler = emulate_rd12rm0_noflags_nopc},
[PROBES_MMI] = {.handler = emulate_rd12rn16rm0_rwflags_nopc},
diff --git a/arch/arm/kernel/kprobes-thumb.c b/arch/arm/kernel/kprobes-thumb.c
index da1e24b..9a78a72 100644
--- a/arch/arm/kernel/kprobes-thumb.c
+++ b/arch/arm/kernel/kprobes-thumb.c
@@ -612,8 +612,8 @@ const union decode_item kprobes_t16_actions[] = {
[PROBES_T16_SIGN_EXTEND] = {.handler = t16_emulate_loregs_rwflags},
[PROBES_T16_PUSH] = {.decoder = t16_decode_push},
[PROBES_T16_POP] = {.decoder = t16_decode_pop},
- [PROBES_T16_SEV] = {.handler = kprobe_emulate_none},
- [PROBES_T16_WFE] = {.handler = kprobe_simulate_nop},
+ [PROBES_T16_SEV] = {.handler = probes_emulate_none},
+ [PROBES_T16_WFE] = {.handler = probes_simulate_nop},
[PROBES_T16_IT] = {.decoder = t16_decode_it},
[PROBES_T16_CMP] = {.handler = t16_emulate_loregs_rwflags},
[PROBES_T16_ADDSUB] = {.handler = t16_emulate_loregs_noitrwflags},
@@ -643,12 +643,12 @@ const union decode_item kprobes_t32_actions[] = {
[PROBES_T32_MOVW] = {.handler = t32_emulate_rd8rn16_noflags},
[PROBES_T32_SAT] = {.handler = t32_emulate_rd8rn16rm0_rwflags},
[PROBES_T32_BITFIELD] = {.handler = t32_emulate_rd8rn16_noflags},
- [PROBES_T32_SEV] = {.handler = kprobe_emulate_none},
- [PROBES_T32_WFE] = {.handler = kprobe_simulate_nop},
+ [PROBES_T32_SEV] = {.handler = probes_emulate_none},
+ [PROBES_T32_WFE] = {.handler = probes_simulate_nop},
[PROBES_T32_MRS] = {.handler = t32_simulate_mrs},
[PROBES_T32_BRANCH_COND] = {.decoder = t32_decode_cond_branch},
[PROBES_T32_BRANCH] = {.handler = t32_simulate_branch},
- [PROBES_T32_PLDI] = {.handler = kprobe_simulate_nop},
+ [PROBES_T32_PLDI] = {.handler = probes_simulate_nop},
[PROBES_T32_LDR_LIT] = {.handler = t32_simulate_ldr_literal},
[PROBES_T32_LDRSTR] = {.handler = t32_emulate_ldrstr},
[PROBES_T32_SIGN_EXTEND] = {.handler = t32_emulate_rd8rn16rm0_rwflags},
diff --git a/arch/arm/kernel/kprobes.c b/arch/arm/kernel/kprobes.c
index 19c55aa..31bc9b7 100644
--- a/arch/arm/kernel/kprobes.c
+++ b/arch/arm/kernel/kprobes.c
@@ -613,7 +613,7 @@ static struct undef_hook kprobes_arm_break_hook = {
int __init arch_init_kprobes()
{
- arm_kprobe_decode_init();
+ arm_probes_decode_init();
#ifdef CONFIG_THUMB2_KERNEL
register_undef_hook(&kprobes_thumb16_break_hook);
register_undef_hook(&kprobes_thumb32_break_hook);
diff --git a/arch/arm/kernel/kprobes.h b/arch/arm/kernel/kprobes.h
index c8a8413..eba5a2f 100644
--- a/arch/arm/kernel/kprobes.h
+++ b/arch/arm/kernel/kprobes.h
@@ -56,8 +56,6 @@ enum kprobe_insn arm_kprobe_decode_insn(probes_opcode_t,
#endif
-void __init arm_kprobe_decode_init(void);
-
#include "probes.h"
#endif /* _ARM_KERNEL_KPROBES_H */
diff --git a/arch/arm/kernel/probes.c b/arch/arm/kernel/probes.c
index 36fafd2..c63b0f6 100644
--- a/arch/arm/kernel/probes.c
+++ b/arch/arm/kernel/probes.c
@@ -72,7 +72,7 @@ void __init test_alu_write_pc_interworking(void)
#endif /* !test_alu_write_pc_interworking */
-void __init arm_kprobe_decode_init(void)
+void __init arm_probes_decode_init(void)
{
find_str_pc_offset();
test_load_write_pc_interworking();
@@ -171,13 +171,13 @@ probes_check_cc * const probes_condition_checks[16] = {
};
-void __kprobes kprobe_simulate_nop(probes_opcode_t opcode,
+void __kprobes probes_simulate_nop(probes_opcode_t opcode,
struct arch_specific_insn *asi,
struct pt_regs *regs)
{
}
-void __kprobes kprobe_emulate_none(probes_opcode_t opcode,
+void __kprobes probes_emulate_none(probes_opcode_t opcode,
struct arch_specific_insn *asi,
struct pt_regs *regs)
{
diff --git a/arch/arm/kernel/probes.h b/arch/arm/kernel/probes.h
index e7c7a92..48ccbcb 100644
--- a/arch/arm/kernel/probes.h
+++ b/arch/arm/kernel/probes.h
@@ -22,6 +22,8 @@
#include <linux/kprobes.h>
#include "kprobes.h"
+void __init arm_probes_decode_init(void);
+
#if __LINUX_ARM_ARCH__ >= 7
/* str_pc_offset is architecturally defined from ARMv7 onwards */
@@ -129,9 +131,9 @@ static inline void __kprobes alu_write_pc(long pcv, struct pt_regs *regs)
}
-void __kprobes kprobe_simulate_nop(probes_opcode_t, struct arch_specific_insn *,
+void __kprobes probes_simulate_nop(probes_opcode_t, struct arch_specific_insn *,
struct pt_regs *regs);
-void __kprobes kprobe_emulate_none(probes_opcode_t, struct arch_specific_insn *,
+void __kprobes probes_emulate_none(probes_opcode_t, struct arch_specific_insn *,
struct pt_regs *regs);
enum kprobe_insn __kprobes
--
1.8.1.2
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH v4 11/16] ARM: Rename the shared kprobes/uprobe return value enum
2013-12-16 4:08 [PATCH v4 00/16] uprobes: Add uprobes support for ARM David Long
` (9 preceding siblings ...)
2013-12-16 4:08 ` [PATCH v4 10/16] ARM: Change more ARM kprobes symbol names to something more David Long
@ 2013-12-16 4:08 ` David Long
2013-12-16 4:08 ` [PATCH v4 12/16] ARM: Change the remaining shared kprobes/uprobes symbols to something generic David Long
` (4 subsequent siblings)
15 siblings, 0 replies; 34+ messages in thread
From: David Long @ 2013-12-16 4:08 UTC (permalink / raw)
To: linux-arm-kernel
From: "David A. Long" <dave.long@linaro.org>
Change the name of kprobes_insn to probes_insn so it can be shared between
kprobes and uprobes without confusion.
Signed-off-by: David A. Long <dave.long@linaro.org>
---
arch/arm/kernel/kprobes-common.c | 2 +-
arch/arm/kernel/kprobes-thumb.c | 16 ++++++++--------
arch/arm/kernel/kprobes.h | 14 ++++----------
arch/arm/kernel/probes-arm.c | 2 +-
arch/arm/kernel/probes-thumb.c | 4 ++--
arch/arm/kernel/probes.h | 7 ++++++-
6 files changed, 22 insertions(+), 23 deletions(-)
diff --git a/arch/arm/kernel/kprobes-common.c b/arch/arm/kernel/kprobes-common.c
index bd3d8c5..f8a1589 100644
--- a/arch/arm/kernel/kprobes-common.c
+++ b/arch/arm/kernel/kprobes-common.c
@@ -124,7 +124,7 @@ emulate_ldm_r3_15(probes_opcode_t insn,
load_write_pc(regs->ARM_pc, regs);
}
-enum kprobe_insn __kprobes
+enum probes_insn __kprobes
kprobe_decode_ldmstm(probes_opcode_t insn, struct arch_specific_insn *asi,
struct decode_header *h)
{
diff --git a/arch/arm/kernel/kprobes-thumb.c b/arch/arm/kernel/kprobes-thumb.c
index 9a78a72..9624abb 100644
--- a/arch/arm/kernel/kprobes-thumb.c
+++ b/arch/arm/kernel/kprobes-thumb.c
@@ -65,7 +65,7 @@ t32_simulate_cond_branch(probes_opcode_t insn,
regs->ARM_pc = pc + (offset * 2);
}
-static enum kprobe_insn __kprobes
+static enum probes_insn __kprobes
t32_decode_cond_branch(probes_opcode_t insn, struct arch_specific_insn *asi,
struct decode_header *d)
{
@@ -141,11 +141,11 @@ t32_simulate_ldr_literal(probes_opcode_t insn,
regs->uregs[rt] = rtv;
}
-enum kprobe_insn __kprobes
+enum probes_insn __kprobes
t32_decode_ldmstm(probes_opcode_t insn, struct arch_specific_insn *asi,
struct decode_header *d)
{
- enum kprobe_insn ret = kprobe_decode_ldmstm(insn, asi, d);
+ enum probes_insn ret = kprobe_decode_ldmstm(insn, asi, d);
/* Fixup modified instruction to have halfwords in correct order...*/
insn = asi->insn[0];
@@ -401,7 +401,7 @@ t16_singlestep_it(probes_opcode_t insn,
t16_simulate_it(insn, asi, regs);
}
-static enum kprobe_insn __kprobes
+static enum probes_insn __kprobes
t16_decode_it(probes_opcode_t insn, struct arch_specific_insn *asi,
struct decode_header *d)
{
@@ -419,7 +419,7 @@ t16_simulate_cond_branch(probes_opcode_t insn,
regs->ARM_pc = pc + (offset * 2);
}
-static enum kprobe_insn __kprobes
+static enum probes_insn __kprobes
t16_decode_cond_branch(probes_opcode_t insn, struct arch_specific_insn *asi,
struct decode_header *d)
{
@@ -509,7 +509,7 @@ t16_emulate_hiregs(probes_opcode_t insn,
regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK);
}
-static enum kprobe_insn __kprobes
+static enum probes_insn __kprobes
t16_decode_hiregs(probes_opcode_t insn, struct arch_specific_insn *asi,
struct decode_header *d)
{
@@ -537,7 +537,7 @@ t16_emulate_push(probes_opcode_t insn,
);
}
-static enum kprobe_insn __kprobes
+static enum probes_insn __kprobes
t16_decode_push(probes_opcode_t insn, struct arch_specific_insn *asi,
struct decode_header *d)
{
@@ -590,7 +590,7 @@ t16_emulate_pop_pc(probes_opcode_t insn,
bx_write_pc(pc, regs);
}
-enum kprobe_insn __kprobes
+enum probes_insn __kprobes
t16_decode_pop(probes_opcode_t insn, struct arch_specific_insn *asi,
struct decode_header *d)
{
diff --git a/arch/arm/kernel/kprobes.h b/arch/arm/kernel/kprobes.h
index eba5a2f..2c8a888 100644
--- a/arch/arm/kernel/kprobes.h
+++ b/arch/arm/kernel/kprobes.h
@@ -29,28 +29,22 @@
struct decode_header;
-enum kprobe_insn {
- INSN_REJECTED,
- INSN_GOOD,
- INSN_GOOD_NO_SLOT
-};
-
-typedef enum kprobe_insn (kprobe_decode_insn_t)(probes_opcode_t,
+typedef enum probes_insn (kprobe_decode_insn_t)(probes_opcode_t,
struct arch_specific_insn *,
struct decode_header *);
#ifdef CONFIG_THUMB2_KERNEL
-enum kprobe_insn thumb16_kprobe_decode_insn(probes_opcode_t,
+enum probes_insn thumb16_kprobe_decode_insn(probes_opcode_t,
struct arch_specific_insn *,
struct decode_header *);
-enum kprobe_insn thumb32_kprobe_decode_insn(probes_opcode_t,
+enum probes_insn thumb32_kprobe_decode_insn(probes_opcode_t,
struct arch_specific_insn *,
struct decode_header *);
#else /* !CONFIG_THUMB2_KERNEL */
-enum kprobe_insn arm_kprobe_decode_insn(probes_opcode_t,
+enum probes_insn arm_kprobe_decode_insn(probes_opcode_t,
struct arch_specific_insn *,
struct decode_header *);
diff --git a/arch/arm/kernel/probes-arm.c b/arch/arm/kernel/probes-arm.c
index 95ef3e3..3bec735 100644
--- a/arch/arm/kernel/probes-arm.c
+++ b/arch/arm/kernel/probes-arm.c
@@ -721,7 +721,7 @@ static void __kprobes arm_singlestep(probes_opcode_t insn,
* if the work was put into it, but low return considering they
* should also be very rare.
*/
-enum kprobe_insn __kprobes
+enum probes_insn __kprobes
arm_kprobe_decode_insn(probes_opcode_t insn, struct arch_specific_insn *asi,
struct decode_header *actions)
{
diff --git a/arch/arm/kernel/probes-thumb.c b/arch/arm/kernel/probes-thumb.c
index 055faf0..64ae4b3 100644
--- a/arch/arm/kernel/probes-thumb.c
+++ b/arch/arm/kernel/probes-thumb.c
@@ -859,7 +859,7 @@ static void __kprobes thumb32_singlestep(probes_opcode_t opcode,
regs->ARM_cpsr = it_advance(regs->ARM_cpsr);
}
-enum kprobe_insn __kprobes
+enum probes_insn __kprobes
thumb16_kprobe_decode_insn(probes_opcode_t insn, struct arch_specific_insn *asi,
struct decode_header *actions)
{
@@ -869,7 +869,7 @@ thumb16_kprobe_decode_insn(probes_opcode_t insn, struct arch_specific_insn *asi,
(const union decode_item *) actions);
}
-enum kprobe_insn __kprobes
+enum probes_insn __kprobes
thumb32_kprobe_decode_insn(probes_opcode_t insn, struct arch_specific_insn *asi,
struct decode_header *actions)
{
diff --git a/arch/arm/kernel/probes.h b/arch/arm/kernel/probes.h
index 48ccbcb..577fb35 100644
--- a/arch/arm/kernel/probes.h
+++ b/arch/arm/kernel/probes.h
@@ -136,7 +136,7 @@ void __kprobes probes_simulate_nop(probes_opcode_t, struct arch_specific_insn *,
void __kprobes probes_emulate_none(probes_opcode_t, struct arch_specific_insn *,
struct pt_regs *regs);
-enum kprobe_insn __kprobes
+enum probes_insn __kprobes
kprobe_decode_ldmstm(probes_opcode_t insn, struct arch_specific_insn *asi,
struct decode_header *h);
@@ -385,6 +385,11 @@ struct decode_reject {
#define DECODE_REJECT(_mask, _value) \
DECODE_HEADER(DECODE_TYPE_REJECT, _mask, _value, 0)
+enum probes_insn {
+ INSN_REJECTED,
+ INSN_GOOD,
+ INSN_GOOD_NO_SLOT
+};
#ifdef CONFIG_THUMB2_KERNEL
extern const union decode_item kprobe_decode_thumb16_table[];
--
1.8.1.2
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH v4 12/16] ARM: Change the remaining shared kprobes/uprobes symbols to something generic
2013-12-16 4:08 [PATCH v4 00/16] uprobes: Add uprobes support for ARM David Long
` (10 preceding siblings ...)
2013-12-16 4:08 ` [PATCH v4 11/16] ARM: Rename the shared kprobes/uprobe return value enum David Long
@ 2013-12-16 4:08 ` David Long
2013-12-16 4:08 ` [PATCH v4 13/16] ARM: Add an emulate flag to the kprobes/uprobes instruction decode functions David Long
` (3 subsequent siblings)
15 siblings, 0 replies; 34+ messages in thread
From: David Long @ 2013-12-16 4:08 UTC (permalink / raw)
To: linux-arm-kernel
From: "David A. Long" <dave.long@linaro.org>
Any more ARM kprobes/uprobes symbols which have "kprobe" in the name must be
changed to the more generic "probes" or other non-kprobes specific symbol.
Signed-off-by: David A. Long <dave.long@linaro.org>
---
arch/arm/include/asm/probes.h | 13 ++++++------
arch/arm/kernel/kprobes-common.c | 2 +-
arch/arm/kernel/kprobes-test.c | 8 ++++---
arch/arm/kernel/kprobes.c | 13 ++++++------
arch/arm/kernel/kprobes.h | 25 ++++++++++------------
arch/arm/kernel/probes-arm.c | 12 +++++------
arch/arm/kernel/probes-arm.h | 6 ++++++
arch/arm/kernel/probes-thumb.c | 26 +++++++++++------------
arch/arm/kernel/probes-thumb.h | 10 +++++++++
arch/arm/kernel/probes.c | 4 ++--
arch/arm/kernel/probes.h | 46 +++++++++++++---------------------------
11 files changed, 82 insertions(+), 83 deletions(-)
diff --git a/arch/arm/include/asm/probes.h b/arch/arm/include/asm/probes.h
index 81b05b0..614977b 100644
--- a/arch/arm/include/asm/probes.h
+++ b/arch/arm/include/asm/probes.h
@@ -1,26 +1,25 @@
#ifndef _ASM_PROBES_H
#define _ASM_PROBES_H
-struct kprobe;
typedef u32 probes_opcode_t;
struct arch_specific_insn;
-typedef void (kprobe_insn_handler_t)(probes_opcode_t,
+typedef void (probes_insn_handler_t)(probes_opcode_t,
struct arch_specific_insn *,
struct pt_regs *);
typedef unsigned long (probes_check_cc)(unsigned long);
-typedef void (kprobe_insn_singlestep_t)(probes_opcode_t,
+typedef void (probes_insn_singlestep_t)(probes_opcode_t,
struct arch_specific_insn *,
struct pt_regs *);
-typedef void (kprobe_insn_fn_t)(void);
+typedef void (probes_insn_fn_t)(void);
/* Architecture specific copy of original instruction. */
struct arch_specific_insn {
probes_opcode_t *insn;
- kprobe_insn_handler_t *insn_handler;
+ probes_insn_handler_t *insn_handler;
probes_check_cc *insn_check_cc;
- kprobe_insn_singlestep_t *insn_singlestep;
- kprobe_insn_fn_t *insn_fn;
+ probes_insn_singlestep_t *insn_singlestep;
+ probes_insn_fn_t *insn_fn;
};
#endif
diff --git a/arch/arm/kernel/kprobes-common.c b/arch/arm/kernel/kprobes-common.c
index f8a1589..0c485ca 100644
--- a/arch/arm/kernel/kprobes-common.c
+++ b/arch/arm/kernel/kprobes-common.c
@@ -128,7 +128,7 @@ enum probes_insn __kprobes
kprobe_decode_ldmstm(probes_opcode_t insn, struct arch_specific_insn *asi,
struct decode_header *h)
{
- kprobe_insn_handler_t *handler = 0;
+ probes_insn_handler_t *handler = 0;
unsigned reglist = insn & 0xffff;
int is_ldm = insn & 0x100000;
int rn = (insn >> 16) & 0xf;
diff --git a/arch/arm/kernel/kprobes-test.c b/arch/arm/kernel/kprobes-test.c
index 65230b2..a1f155c 100644
--- a/arch/arm/kernel/kprobes-test.c
+++ b/arch/arm/kernel/kprobes-test.c
@@ -205,6 +205,8 @@
#include <asm/opcodes.h>
#include "kprobes.h"
+#include "probes-arm.h"
+#include "probes-thumb.h"
#include "kprobes-test.h"
@@ -1616,7 +1618,7 @@ static int __init run_all_tests(void)
goto out;
pr_info("ARM instruction simulation\n");
- ret = run_test_cases(kprobe_arm_test_cases, kprobe_decode_arm_table);
+ ret = run_test_cases(kprobe_arm_test_cases, probes_decode_arm_table);
if (ret)
goto out;
@@ -1639,13 +1641,13 @@ static int __init run_all_tests(void)
pr_info("16-bit Thumb instruction simulation\n");
ret = run_test_cases(kprobe_thumb16_test_cases,
- kprobe_decode_thumb16_table);
+ probes_decode_thumb16_table);
if (ret)
goto out;
pr_info("32-bit Thumb instruction simulation\n");
ret = run_test_cases(kprobe_thumb32_test_cases,
- kprobe_decode_thumb32_table);
+ probes_decode_thumb32_table);
if (ret)
goto out;
#endif
diff --git a/arch/arm/kernel/kprobes.c b/arch/arm/kernel/kprobes.c
index 31bc9b7..0d9d49b 100644
--- a/arch/arm/kernel/kprobes.c
+++ b/arch/arm/kernel/kprobes.c
@@ -29,6 +29,8 @@
#include <asm/cacheflush.h>
#include "kprobes.h"
+#include "probes-arm.h"
+#include "probes-thumb.h"
#include "patch.h"
#define MIN_STACK_SIZE(addr) \
@@ -67,10 +69,10 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
if (is_wide_instruction(insn)) {
insn <<= 16;
insn |= ((u16 *)addr)[1];
- decode_insn = thumb32_kprobe_decode_insn;
+ decode_insn = thumb32_probes_decode_insn;
actions = kprobes_t32_actions;
} else {
- decode_insn = thumb16_kprobe_decode_insn;
+ decode_insn = thumb16_probes_decode_insn;
actions = kprobes_t16_actions;
}
#else /* !CONFIG_THUMB2_KERNEL */
@@ -78,15 +80,14 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
if (addr & 0x3)
return -EINVAL;
insn = *p->addr;
- decode_insn = arm_kprobe_decode_insn;
+ decode_insn = arm_probes_decode_insn;
actions = kprobes_arm_actions;
#endif
p->opcode = insn;
p->ainsn.insn = tmp_insn;
- switch ((*decode_insn)
- (insn, &p->ainsn, (struct decode_header *) actions)) {
+ switch ((*decode_insn)(insn, &p->ainsn, actions)) {
case INSN_REJECTED: /* not supported */
return -EINVAL;
@@ -98,7 +99,7 @@ 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 *)
+ p->ainsn.insn_fn = (probes_insn_fn_t *)
((uintptr_t)p->ainsn.insn | thumb);
break;
diff --git a/arch/arm/kernel/kprobes.h b/arch/arm/kernel/kprobes.h
index 2c8a888..e1305a8 100644
--- a/arch/arm/kernel/kprobes.h
+++ b/arch/arm/kernel/kprobes.h
@@ -19,6 +19,8 @@
#ifndef _ARM_KERNEL_KPROBES_H
#define _ARM_KERNEL_KPROBES_H
+#include "probes.h"
+
/*
* These undefined instructions must be unique and
* reserved solely for kprobes' use.
@@ -27,29 +29,24 @@
#define KPROBE_THUMB16_BREAKPOINT_INSTRUCTION 0xde18
#define KPROBE_THUMB32_BREAKPOINT_INSTRUCTION 0xf7f0a018
-struct decode_header;
+enum probes_insn __kprobes
+kprobe_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi,
+ struct decode_header *h);
-typedef enum probes_insn (kprobe_decode_insn_t)(probes_opcode_t,
- struct arch_specific_insn *,
- struct decode_header *);
+typedef enum probes_insn (kprobe_decode_insn_t)(kprobe_opcode_t,
+ struct arch_specific_insn *,
+ const union decode_item *);
#ifdef CONFIG_THUMB2_KERNEL
-enum probes_insn thumb16_kprobe_decode_insn(probes_opcode_t,
- struct arch_specific_insn *,
- struct decode_header *);
-enum probes_insn thumb32_kprobe_decode_insn(probes_opcode_t,
- struct arch_specific_insn *,
- struct decode_header *);
+extern const union decode_item kprobes_t32_actions[];
+extern const union decode_item kprobes_t16_actions[];
#else /* !CONFIG_THUMB2_KERNEL */
-enum probes_insn arm_kprobe_decode_insn(probes_opcode_t,
- struct arch_specific_insn *,
- struct decode_header *);
+extern const union decode_item kprobes_arm_actions[];
#endif
-#include "probes.h"
#endif /* _ARM_KERNEL_KPROBES_H */
diff --git a/arch/arm/kernel/probes-arm.c b/arch/arm/kernel/probes-arm.c
index 3bec735..a44c3ad 100644
--- a/arch/arm/kernel/probes-arm.c
+++ b/arch/arm/kernel/probes-arm.c
@@ -608,7 +608,7 @@ static const union decode_item arm_cccc_100x_table[] = {
DECODE_END
};
-const union decode_item kprobe_decode_arm_table[] = {
+const union decode_item probes_decode_arm_table[] = {
/*
* Unconditional instructions
* 1111 xxxx xxxx xxxx xxxx xxxx xxxx xxxx
@@ -699,7 +699,7 @@ const union decode_item kprobe_decode_arm_table[] = {
DECODE_END
};
#ifdef CONFIG_ARM_KPROBES_TEST_MODULE
-EXPORT_SYMBOL_GPL(kprobe_decode_arm_table);
+EXPORT_SYMBOL_GPL(probes_decode_arm_table);
#endif
static void __kprobes arm_singlestep(probes_opcode_t insn,
@@ -722,11 +722,11 @@ static void __kprobes arm_singlestep(probes_opcode_t insn,
* should also be very rare.
*/
enum probes_insn __kprobes
-arm_kprobe_decode_insn(probes_opcode_t insn, struct arch_specific_insn *asi,
- struct decode_header *actions)
+arm_probes_decode_insn(probes_opcode_t insn, struct arch_specific_insn *asi,
+ const union decode_item *actions)
{
asi->insn_singlestep = arm_singlestep;
asi->insn_check_cc = probes_condition_checks[insn>>28];
- return kprobe_decode_insn(insn, asi, kprobe_decode_arm_table, false,
- (const union decode_item *) actions);
+ return probes_decode_insn(insn, asi, probes_decode_arm_table, false,
+ actions);
}
diff --git a/arch/arm/kernel/probes-arm.h b/arch/arm/kernel/probes-arm.h
index 2662ada..7f81199 100644
--- a/arch/arm/kernel/probes-arm.h
+++ b/arch/arm/kernel/probes-arm.h
@@ -63,4 +63,10 @@ void __kprobes simulate_mrs(probes_opcode_t opcode,
void __kprobes simulate_mov_ipsp(probes_opcode_t opcode,
struct arch_specific_insn *asi, struct pt_regs *regs);
+extern const union decode_item probes_decode_arm_table[];
+
+enum probes_insn arm_probes_decode_insn(probes_opcode_t,
+ struct arch_specific_insn *,
+ const union decode_item *actions);
+
#endif
diff --git a/arch/arm/kernel/probes-thumb.c b/arch/arm/kernel/probes-thumb.c
index 64ae4b3..3f250e9 100644
--- a/arch/arm/kernel/probes-thumb.c
+++ b/arch/arm/kernel/probes-thumb.c
@@ -1,5 +1,5 @@
/*
- * arch/arm/kernel/kprobes-thumb.c
+ * arch/arm/kernel/probes-thumb.c
*
* Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>.
*
@@ -551,7 +551,7 @@ static const union decode_item t32_table_1111_1011_1[] = {
DECODE_END
};
-const union decode_item kprobe_decode_thumb32_table[] = {
+const union decode_item probes_decode_thumb32_table[] = {
/*
* Load/store multiple instructions
@@ -640,7 +640,7 @@ const union decode_item kprobe_decode_thumb32_table[] = {
DECODE_END
};
#ifdef CONFIG_ARM_KPROBES_TEST_MODULE
-EXPORT_SYMBOL_GPL(kprobe_decode_thumb32_table);
+EXPORT_SYMBOL_GPL(probes_decode_thumb32_table);
#endif
static const union decode_item t16_table_1011[] = {
/* Miscellaneous 16-bit instructions */
@@ -694,7 +694,7 @@ static const union decode_item t16_table_1011[] = {
DECODE_END
};
-const union decode_item kprobe_decode_thumb16_table[] = {
+const union decode_item probes_decode_thumb16_table[] = {
/*
* Shift (immediate), add, subtract, move, and compare
@@ -831,7 +831,7 @@ const union decode_item kprobe_decode_thumb16_table[] = {
DECODE_END
};
#ifdef CONFIG_ARM_KPROBES_TEST_MODULE
-EXPORT_SYMBOL_GPL(kprobe_decode_thumb16_table);
+EXPORT_SYMBOL_GPL(probes_decode_thumb16_table);
#endif
static unsigned long __kprobes thumb_check_cc(unsigned long cpsr)
@@ -860,21 +860,21 @@ static void __kprobes thumb32_singlestep(probes_opcode_t opcode,
}
enum probes_insn __kprobes
-thumb16_kprobe_decode_insn(probes_opcode_t insn, struct arch_specific_insn *asi,
- struct decode_header *actions)
+thumb16_probes_decode_insn(probes_opcode_t insn, struct arch_specific_insn *asi,
+ const union decode_item *actions)
{
asi->insn_singlestep = thumb16_singlestep;
asi->insn_check_cc = thumb_check_cc;
- return kprobe_decode_insn(insn, asi, kprobe_decode_thumb16_table, true,
- (const union decode_item *) actions);
+ return probes_decode_insn(insn, asi, probes_decode_thumb16_table, true,
+ actions);
}
enum probes_insn __kprobes
-thumb32_kprobe_decode_insn(probes_opcode_t insn, struct arch_specific_insn *asi,
- struct decode_header *actions)
+thumb32_probes_decode_insn(probes_opcode_t insn, struct arch_specific_insn *asi,
+ const union decode_item *actions)
{
asi->insn_singlestep = thumb32_singlestep;
asi->insn_check_cc = thumb_check_cc;
- return kprobe_decode_insn(insn, asi, kprobe_decode_thumb32_table, true,
- (const union decode_item *) actions);
+ return probes_decode_insn(insn, asi, probes_decode_thumb32_table, true,
+ actions);
}
diff --git a/arch/arm/kernel/probes-thumb.h b/arch/arm/kernel/probes-thumb.h
index f024a4c..556f067 100644
--- a/arch/arm/kernel/probes-thumb.h
+++ b/arch/arm/kernel/probes-thumb.h
@@ -82,4 +82,14 @@ enum probes_t16_action {
PROBES_T16_BRANCH
};
+extern const union decode_item probes_decode_thumb32_table[];
+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_item *actions);
+enum probes_insn __kprobes
+thumb32_probes_decode_insn(probes_opcode_t insn, struct arch_specific_insn *asi,
+ const union decode_item *actions);
+
#endif
diff --git a/arch/arm/kernel/probes.c b/arch/arm/kernel/probes.c
index c63b0f6..a0a4220 100644
--- a/arch/arm/kernel/probes.c
+++ b/arch/arm/kernel/probes.c
@@ -336,7 +336,7 @@ static const int decode_struct_sizes[NUM_DECODE_TYPES] = {
};
/*
- * kprobe_decode_insn operates on data tables in order to decode an ARM
+ * probes_decode_insn operates on data tables in order to decode an ARM
* architecture instruction onto which a kprobe has been placed.
*
* These instruction decoding tables are a concatenation of entries each
@@ -379,7 +379,7 @@ static const int decode_struct_sizes[NUM_DECODE_TYPES] = {
*
*/
int __kprobes
-kprobe_decode_insn(probes_opcode_t insn, struct arch_specific_insn *asi,
+probes_decode_insn(probes_opcode_t insn, struct arch_specific_insn *asi,
const union decode_item *table, bool thumb,
const union decode_item *actions)
{
diff --git a/arch/arm/kernel/probes.h b/arch/arm/kernel/probes.h
index 577fb35..9591c2c 100644
--- a/arch/arm/kernel/probes.h
+++ b/arch/arm/kernel/probes.h
@@ -19,11 +19,12 @@
#ifndef _ARM_KERNEL_PROBES_H
#define _ARM_KERNEL_PROBES_H
-#include <linux/kprobes.h>
-#include "kprobes.h"
+#include <asm/probes.h>
void __init arm_probes_decode_init(void);
+extern probes_check_cc * const probes_condition_checks[16];
+
#if __LINUX_ARM_ARCH__ >= 7
/* str_pc_offset is architecturally defined from ARMv7 onwards */
@@ -38,7 +39,6 @@ void __init find_str_pc_offset(void);
#endif
-struct decode_header;
/*
* Update ITSTATE after normal execution of an IT block instruction.
@@ -130,16 +130,6 @@ static inline void __kprobes alu_write_pc(long pcv, struct pt_regs *regs)
regs->ARM_pc = pcv;
}
-
-void __kprobes probes_simulate_nop(probes_opcode_t, struct arch_specific_insn *,
- struct pt_regs *regs);
-void __kprobes probes_emulate_none(probes_opcode_t, struct arch_specific_insn *,
- struct pt_regs *regs);
-
-enum probes_insn __kprobes
-kprobe_decode_ldmstm(probes_opcode_t insn, struct arch_specific_insn *asi,
- struct decode_header *h);
-
/*
* Test if load/store instructions writeback the address register.
* if P (bit 24) == 0 or W (bit 21) == 1
@@ -148,7 +138,7 @@ kprobe_decode_ldmstm(probes_opcode_t insn, struct arch_specific_insn *asi,
/*
* The following definitions and macros are used to build instruction
- * decoding tables for use by kprobe_decode_insn.
+ * decoding tables for use by probes_decode_insn.
*
* These tables are a concatenation of entries each of which consist of one of
* the decode_* structs. All of the fields in every type of decode structure
@@ -300,11 +290,14 @@ enum decode_reg_type {
((REG_TYPE_##r4) << 4) + \
(REG_TYPE_##r0))
+struct decode_header;
union decode_item {
u32 bits;
const union decode_item *table;
- kprobe_insn_handler_t *handler;
- kprobe_decode_insn_t *decoder;
+ probes_insn_handler_t *handler;
+ enum probes_insn (*decoder)(probes_opcode_t,
+ struct arch_specific_insn *,
+ struct decode_header *);
};
@@ -391,21 +384,12 @@ enum probes_insn {
INSN_GOOD_NO_SLOT
};
-#ifdef CONFIG_THUMB2_KERNEL
-extern const union decode_item kprobe_decode_thumb16_table[];
-extern const union decode_item kprobe_decode_thumb32_table[];
-extern const union decode_item kprobes_t32_actions[];
-extern const union decode_item kprobes_t16_actions[];
-#else
-extern const union decode_item kprobe_decode_arm_table[];
-extern const union decode_item kprobes_arm_actions[];
-#endif
-
-extern probes_check_cc * const probes_condition_checks[16];
-
+probes_insn_handler_t probes_simulate_nop;
+probes_insn_handler_t probes_emulate_none;
-int kprobe_decode_insn(probes_opcode_t insn, struct arch_specific_insn *asi,
- const union decode_item *table, bool thumb16,
- const union decode_item *actions);
+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 *actions);
#endif
--
1.8.1.2
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH v4 13/16] ARM: Add an emulate flag to the kprobes/uprobes instruction decode functions
2013-12-16 4:08 [PATCH v4 00/16] uprobes: Add uprobes support for ARM David Long
` (11 preceding siblings ...)
2013-12-16 4:08 ` [PATCH v4 12/16] ARM: Change the remaining shared kprobes/uprobes symbols to something generic David Long
@ 2013-12-16 4:08 ` David Long
2013-12-20 14:58 ` Jon Medhurst (Tixy)
2013-12-16 4:08 ` [PATCH v4 14/16] ARM: Make arch_specific_insn a define for new arch_probes_insn structure David Long
` (2 subsequent siblings)
15 siblings, 1 reply; 34+ messages in thread
From: David Long @ 2013-12-16 4:08 UTC (permalink / raw)
To: linux-arm-kernel
From: "David A. Long" <dave.long@linaro.org>
Add an emulate flag into the instruction interpreter, primarily for uprobes
support.
Signed-off-by: David A. Long <dave.long@linaro.org>
---
arch/arm/kernel/kprobes.c | 3 ++-
arch/arm/kernel/kprobes.h | 1 +
arch/arm/kernel/probes-arm.c | 4 ++--
arch/arm/kernel/probes-arm.h | 2 +-
arch/arm/kernel/probes-thumb.c | 8 ++++----
arch/arm/kernel/probes-thumb.h | 4 ++--
arch/arm/kernel/probes.c | 32 +++++++++++++++++++++++---------
arch/arm/kernel/probes.h | 2 +-
8 files changed, 36 insertions(+), 20 deletions(-)
diff --git a/arch/arm/kernel/kprobes.c b/arch/arm/kernel/kprobes.c
index 0d9d49b..04690f9 100644
--- a/arch/arm/kernel/kprobes.c
+++ b/arch/arm/kernel/kprobes.c
@@ -87,7 +87,8 @@ 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;
diff --git a/arch/arm/kernel/kprobes.h b/arch/arm/kernel/kprobes.h
index e1305a8..580d82c 100644
--- a/arch/arm/kernel/kprobes.h
+++ b/arch/arm/kernel/kprobes.h
@@ -35,6 +35,7 @@ kprobe_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi,
typedef enum probes_insn (kprobe_decode_insn_t)(kprobe_opcode_t,
struct arch_specific_insn *,
+ bool,
const union decode_item *);
#ifdef CONFIG_THUMB2_KERNEL
diff --git a/arch/arm/kernel/probes-arm.c b/arch/arm/kernel/probes-arm.c
index a44c3ad..01e99f7 100644
--- a/arch/arm/kernel/probes-arm.c
+++ b/arch/arm/kernel/probes-arm.c
@@ -723,10 +723,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_item *actions)
+ bool emulate, const union decode_item *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);
}
diff --git a/arch/arm/kernel/probes-arm.h b/arch/arm/kernel/probes-arm.h
index 7f81199..904033c 100644
--- a/arch/arm/kernel/probes-arm.h
+++ b/arch/arm/kernel/probes-arm.h
@@ -66,7 +66,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_item *actions);
#endif
diff --git a/arch/arm/kernel/probes-thumb.c b/arch/arm/kernel/probes-thumb.c
index 3f250e9..2ad0880 100644
--- a/arch/arm/kernel/probes-thumb.c
+++ b/arch/arm/kernel/probes-thumb.c
@@ -861,20 +861,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_item *actions)
+ bool emulate, const union decode_item *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_item *actions)
+ bool emulate, const union decode_item *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);
}
diff --git a/arch/arm/kernel/probes-thumb.h b/arch/arm/kernel/probes-thumb.h
index 556f067..78be667 100644
--- a/arch/arm/kernel/probes-thumb.h
+++ b/arch/arm/kernel/probes-thumb.h
@@ -87,9 +87,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_item *actions);
+ bool emulate, const union decode_item *actions);
enum probes_insn __kprobes
thumb32_probes_decode_insn(probes_opcode_t insn, struct arch_specific_insn *asi,
- const union decode_item *actions);
+ bool emulate, const union decode_item *actions);
#endif
diff --git a/arch/arm/kernel/probes.c b/arch/arm/kernel/probes.c
index a0a4220..e691e12 100644
--- a/arch/arm/kernel/probes.c
+++ b/arch/arm/kernel/probes.c
@@ -193,7 +193,7 @@ void __kprobes probes_emulate_none(probes_opcode_t opcode,
*/
static probes_opcode_t __kprobes
prepare_emulated_insn(probes_opcode_t insn, struct arch_specific_insn *asi,
- bool thumb)
+ bool thumb)
{
#ifdef CONFIG_THUMB2_KERNEL
if (thumb) {
@@ -218,7 +218,7 @@ prepare_emulated_insn(probes_opcode_t insn, struct arch_specific_insn *asi,
*/
static void __kprobes
set_emulated_insn(probes_opcode_t insn, struct arch_specific_insn *asi,
- bool thumb)
+ bool thumb)
{
#ifdef CONFIG_THUMB2_KERNEL
if (thumb) {
@@ -253,7 +253,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 */
@@ -317,9 +317,16 @@ static bool __kprobes decode_regs(probes_opcode_t *pinsn, u32 regs)
/* Replace value of nibble with new register number... */
insn &= ~mask;
insn |= new_bits & mask;
+ if (modify) {
+ /* Replace value of nibble with new register number */
+ insn &= ~mask;
+ insn |= new_bits & mask;
+ }
}
- *pinsn = insn;
+ if (modify)
+ *pinsn = insn;
+
return true;
reject:
@@ -380,14 +387,15 @@ 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_item *actions)
+ const union decode_item *table, bool thumb,
+ bool emulate, const union decode_item *actions)
{
struct decode_header *h = (struct decode_header *)table;
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;
@@ -402,7 +410,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) {
@@ -415,7 +423,8 @@ probes_decode_insn(probes_opcode_t insn, struct arch_specific_insn *asi,
case DECODE_TYPE_CUSTOM: {
struct decode_custom *d = (struct decode_custom *)h;
- return actions[d->decoder.bits].decoder(insn, asi, h);
+ return actions[d->decoder.bits].decoder(insn,
+ asi, h);
}
case DECODE_TYPE_SIMULATE: {
@@ -426,6 +435,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.bits].decoder(insn,
+ asi, h);
+
asi->insn_handler = actions[d->handler.bits].handler;
set_emulated_insn(insn, asi, thumb);
return INSN_GOOD;
diff --git a/arch/arm/kernel/probes.h b/arch/arm/kernel/probes.h
index 9591c2c..233ab7b 100644
--- a/arch/arm/kernel/probes.h
+++ b/arch/arm/kernel/probes.h
@@ -389,7 +389,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_item *actions);
#endif
--
1.8.1.2
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH v4 14/16] ARM: Make arch_specific_insn a define for new arch_probes_insn structure
2013-12-16 4:08 [PATCH v4 00/16] uprobes: Add uprobes support for ARM David Long
` (12 preceding siblings ...)
2013-12-16 4:08 ` [PATCH v4 13/16] ARM: Add an emulate flag to the kprobes/uprobes instruction decode functions David Long
@ 2013-12-16 4:08 ` David Long
2013-12-16 4:08 ` [PATCH v4 15/16] ARM: add uprobes support David Long
2013-12-16 4:08 ` [PATCH v4 16/16] ARM: Remove uprobes dependency on kprobes David Long
15 siblings, 0 replies; 34+ messages in thread
From: David Long @ 2013-12-16 4:08 UTC (permalink / raw)
To: linux-arm-kernel
From: "David A. Long" <dave.long@linaro.org>
Because the common underlying code for ARM kprobes and uprobes needs
to share a common architecrure-specific context structure, and because
the generic kprobes include file insists on defining this to a dummy
structure when kprobes is not configured, a new common structure is
required which can exist when uprobes is configured without kprobes.
In this case kprobes will define a dummy structure, but without the
define aliasing the two structure tags it will not affect uprobes and
the shared probes code.
Signed-off-by: David A. Long <dave.long@linaro.org>
---
arch/arm/include/asm/kprobes.h | 2 ++
arch/arm/include/asm/probes.h | 8 ++---
arch/arm/kernel/kprobes-arm.c | 16 ++++-----
arch/arm/kernel/kprobes-common.c | 14 ++++----
arch/arm/kernel/kprobes-thumb.c | 70 ++++++++++++++++++++--------------------
arch/arm/kernel/kprobes.h | 4 +--
arch/arm/kernel/probes-arm.c | 14 ++++----
arch/arm/kernel/probes-arm.h | 12 +++----
arch/arm/kernel/probes-thumb.c | 8 ++---
arch/arm/kernel/probes-thumb.h | 4 +--
arch/arm/kernel/probes.c | 10 +++---
arch/arm/kernel/probes.h | 4 +--
12 files changed, 84 insertions(+), 82 deletions(-)
diff --git a/arch/arm/include/asm/kprobes.h b/arch/arm/include/asm/kprobes.h
index 30fc11b..87b8aa2 100644
--- a/arch/arm/include/asm/kprobes.h
+++ b/arch/arm/include/asm/kprobes.h
@@ -31,6 +31,8 @@ typedef u32 kprobe_opcode_t;
struct kprobe;
#include <asm/probes.h>
+#define arch_specific_insn arch_probes_insn
+
struct prev_kprobe {
struct kprobe *kp;
unsigned int status;
diff --git a/arch/arm/include/asm/probes.h b/arch/arm/include/asm/probes.h
index 614977b..36775ff 100644
--- a/arch/arm/include/asm/probes.h
+++ b/arch/arm/include/asm/probes.h
@@ -3,18 +3,18 @@
typedef u32 probes_opcode_t;
-struct arch_specific_insn;
+struct arch_probes_insn;
typedef void (probes_insn_handler_t)(probes_opcode_t,
- struct arch_specific_insn *,
+ struct arch_probes_insn *,
struct pt_regs *);
typedef unsigned long (probes_check_cc)(unsigned long);
typedef void (probes_insn_singlestep_t)(probes_opcode_t,
- struct arch_specific_insn *,
+ struct arch_probes_insn *,
struct pt_regs *);
typedef void (probes_insn_fn_t)(void);
/* Architecture specific copy of original instruction. */
-struct arch_specific_insn {
+struct arch_probes_insn {
probes_opcode_t *insn;
probes_insn_handler_t *insn_handler;
probes_check_cc *insn_check_cc;
diff --git a/arch/arm/kernel/kprobes-arm.c b/arch/arm/kernel/kprobes-arm.c
index ccb10bc..bb1dec2 100644
--- a/arch/arm/kernel/kprobes-arm.c
+++ b/arch/arm/kernel/kprobes-arm.c
@@ -74,7 +74,7 @@
static void __kprobes
emulate_ldrdstrd(probes_opcode_t insn,
- struct arch_specific_insn *asi, struct pt_regs *regs)
+ struct arch_probes_insn *asi, struct pt_regs *regs)
{
unsigned long pc = regs->ARM_pc + 4;
int rt = (insn >> 12) & 0xf;
@@ -103,7 +103,7 @@ emulate_ldrdstrd(probes_opcode_t insn,
static void __kprobes
emulate_ldr(probes_opcode_t insn,
- struct arch_specific_insn *asi, struct pt_regs *regs)
+ struct arch_probes_insn *asi, struct pt_regs *regs)
{
unsigned long pc = regs->ARM_pc + 4;
int rt = (insn >> 12) & 0xf;
@@ -133,7 +133,7 @@ emulate_ldr(probes_opcode_t insn,
static void __kprobes
emulate_str(probes_opcode_t insn,
- struct arch_specific_insn *asi, struct pt_regs *regs)
+ struct arch_probes_insn *asi, struct pt_regs *regs)
{
unsigned long rtpc = regs->ARM_pc - 4 + str_pc_offset;
unsigned long rnpc = regs->ARM_pc + 4;
@@ -160,7 +160,7 @@ emulate_str(probes_opcode_t insn,
static void __kprobes
emulate_rd12rn16rm0rs8_rwflags(probes_opcode_t insn,
- struct arch_specific_insn *asi, struct pt_regs *regs)
+ struct arch_probes_insn *asi, struct pt_regs *regs)
{
unsigned long pc = regs->ARM_pc + 4;
int rd = (insn >> 12) & 0xf;
@@ -195,7 +195,7 @@ emulate_rd12rn16rm0rs8_rwflags(probes_opcode_t insn,
static void __kprobes
emulate_rd12rn16rm0_rwflags_nopc(probes_opcode_t insn,
- struct arch_specific_insn *asi, struct pt_regs *regs)
+ struct arch_probes_insn *asi, struct pt_regs *regs)
{
int rd = (insn >> 12) & 0xf;
int rn = (insn >> 16) & 0xf;
@@ -222,7 +222,7 @@ emulate_rd12rn16rm0_rwflags_nopc(probes_opcode_t insn,
static void __kprobes
emulate_rd16rn12rm0rs8_rwflags_nopc(probes_opcode_t insn,
- struct arch_specific_insn *asi,
+ struct arch_probes_insn *asi,
struct pt_regs *regs)
{
int rd = (insn >> 16) & 0xf;
@@ -252,7 +252,7 @@ emulate_rd16rn12rm0rs8_rwflags_nopc(probes_opcode_t insn,
static void __kprobes
emulate_rd12rm0_noflags_nopc(probes_opcode_t insn,
- struct arch_specific_insn *asi, struct pt_regs *regs)
+ struct arch_probes_insn *asi, struct pt_regs *regs)
{
int rd = (insn >> 12) & 0xf;
int rm = insn & 0xf;
@@ -272,7 +272,7 @@ emulate_rd12rm0_noflags_nopc(probes_opcode_t insn,
static void __kprobes
emulate_rdlo12rdhi16rn0rm8_rwflags_nopc(probes_opcode_t insn,
- struct arch_specific_insn *asi,
+ struct arch_probes_insn *asi,
struct pt_regs *regs)
{
int rdlo = (insn >> 12) & 0xf;
diff --git a/arch/arm/kernel/kprobes-common.c b/arch/arm/kernel/kprobes-common.c
index 0c485ca..3ee8a7b 100644
--- a/arch/arm/kernel/kprobes-common.c
+++ b/arch/arm/kernel/kprobes-common.c
@@ -19,7 +19,7 @@
static void __kprobes simulate_ldm1stm1(probes_opcode_t insn,
- struct arch_specific_insn *asi,
+ struct arch_probes_insn *asi,
struct pt_regs *regs)
{
int rn = (insn >> 16) & 0xf;
@@ -61,7 +61,7 @@ static void __kprobes simulate_ldm1stm1(probes_opcode_t insn,
}
static void __kprobes simulate_stm1_pc(probes_opcode_t insn,
- struct arch_specific_insn *asi,
+ struct arch_probes_insn *asi,
struct pt_regs *regs)
{
unsigned long addr = regs->ARM_pc - 4;
@@ -72,7 +72,7 @@ static void __kprobes simulate_stm1_pc(probes_opcode_t insn,
}
static void __kprobes simulate_ldm1_pc(probes_opcode_t insn,
- struct arch_specific_insn *asi,
+ struct arch_probes_insn *asi,
struct pt_regs *regs)
{
simulate_ldm1stm1(insn, asi, regs);
@@ -81,7 +81,7 @@ static void __kprobes simulate_ldm1_pc(probes_opcode_t insn,
static void __kprobes
emulate_generic_r0_12_noflags(probes_opcode_t insn,
- struct arch_specific_insn *asi, struct pt_regs *regs)
+ struct arch_probes_insn *asi, struct pt_regs *regs)
{
register void *rregs asm("r1") = regs;
register void *rfn asm("lr") = asi->insn_fn;
@@ -109,7 +109,7 @@ emulate_generic_r0_12_noflags(probes_opcode_t insn,
static void __kprobes
emulate_generic_r2_14_noflags(probes_opcode_t insn,
- struct arch_specific_insn *asi, struct pt_regs *regs)
+ struct arch_probes_insn *asi, struct pt_regs *regs)
{
emulate_generic_r0_12_noflags(insn, asi,
(struct pt_regs *)(regs->uregs+2));
@@ -117,7 +117,7 @@ emulate_generic_r2_14_noflags(probes_opcode_t insn,
static void __kprobes
emulate_ldm_r3_15(probes_opcode_t insn,
- struct arch_specific_insn *asi, struct pt_regs *regs)
+ struct arch_probes_insn *asi, struct pt_regs *regs)
{
emulate_generic_r0_12_noflags(insn, asi,
(struct pt_regs *)(regs->uregs+3));
@@ -125,7 +125,7 @@ emulate_ldm_r3_15(probes_opcode_t insn,
}
enum probes_insn __kprobes
-kprobe_decode_ldmstm(probes_opcode_t insn, struct arch_specific_insn *asi,
+kprobe_decode_ldmstm(probes_opcode_t insn, struct arch_probes_insn *asi,
struct decode_header *h)
{
probes_insn_handler_t *handler = 0;
diff --git a/arch/arm/kernel/kprobes-thumb.c b/arch/arm/kernel/kprobes-thumb.c
index 9624abb..eb31108 100644
--- a/arch/arm/kernel/kprobes-thumb.c
+++ b/arch/arm/kernel/kprobes-thumb.c
@@ -23,7 +23,7 @@
static void __kprobes
t32_simulate_table_branch(probes_opcode_t insn,
- struct arch_specific_insn *asi, struct pt_regs *regs)
+ struct arch_probes_insn *asi, struct pt_regs *regs)
{
unsigned long pc = regs->ARM_pc;
int rn = (insn >> 16) & 0xf;
@@ -43,7 +43,7 @@ t32_simulate_table_branch(probes_opcode_t insn,
static void __kprobes
t32_simulate_mrs(probes_opcode_t insn,
- struct arch_specific_insn *asi, struct pt_regs *regs)
+ struct arch_probes_insn *asi, struct pt_regs *regs)
{
int rd = (insn >> 8) & 0xf;
unsigned long mask = 0xf8ff03df; /* Mask out execution state */
@@ -52,7 +52,7 @@ t32_simulate_mrs(probes_opcode_t insn,
static void __kprobes
t32_simulate_cond_branch(probes_opcode_t insn,
- struct arch_specific_insn *asi, struct pt_regs *regs)
+ struct arch_probes_insn *asi, struct pt_regs *regs)
{
unsigned long pc = regs->ARM_pc;
@@ -66,7 +66,7 @@ t32_simulate_cond_branch(probes_opcode_t insn,
}
static enum probes_insn __kprobes
-t32_decode_cond_branch(probes_opcode_t insn, struct arch_specific_insn *asi,
+t32_decode_cond_branch(probes_opcode_t insn, struct arch_probes_insn *asi,
struct decode_header *d)
{
int cc = (insn >> 22) & 0xf;
@@ -77,7 +77,7 @@ t32_decode_cond_branch(probes_opcode_t insn, struct arch_specific_insn *asi,
static void __kprobes
t32_simulate_branch(probes_opcode_t insn,
- struct arch_specific_insn *asi, struct pt_regs *regs)
+ struct arch_probes_insn *asi, struct pt_regs *regs)
{
unsigned long pc = regs->ARM_pc;
@@ -105,7 +105,7 @@ t32_simulate_branch(probes_opcode_t insn,
static void __kprobes
t32_simulate_ldr_literal(probes_opcode_t insn,
- struct arch_specific_insn *asi, struct pt_regs *regs)
+ struct arch_probes_insn *asi, struct pt_regs *regs)
{
unsigned long addr = regs->ARM_pc & ~3;
int rt = (insn >> 12) & 0xf;
@@ -142,7 +142,7 @@ t32_simulate_ldr_literal(probes_opcode_t insn,
}
enum probes_insn __kprobes
-t32_decode_ldmstm(probes_opcode_t insn, struct arch_specific_insn *asi,
+t32_decode_ldmstm(probes_opcode_t insn, struct arch_probes_insn *asi,
struct decode_header *d)
{
enum probes_insn ret = kprobe_decode_ldmstm(insn, asi, d);
@@ -157,7 +157,7 @@ t32_decode_ldmstm(probes_opcode_t insn, struct arch_specific_insn *asi,
static void __kprobes
t32_emulate_ldrdstrd(probes_opcode_t insn,
- struct arch_specific_insn *asi, struct pt_regs *regs)
+ struct arch_probes_insn *asi, struct pt_regs *regs)
{
unsigned long pc = regs->ARM_pc & ~3;
int rt1 = (insn >> 12) & 0xf;
@@ -184,7 +184,7 @@ t32_emulate_ldrdstrd(probes_opcode_t insn,
static void __kprobes
t32_emulate_ldrstr(probes_opcode_t insn,
- struct arch_specific_insn *asi, struct pt_regs *regs)
+ struct arch_probes_insn *asi, struct pt_regs *regs)
{
int rt = (insn >> 12) & 0xf;
int rn = (insn >> 16) & 0xf;
@@ -210,7 +210,7 @@ t32_emulate_ldrstr(probes_opcode_t insn,
static void __kprobes
t32_emulate_rd8rn16rm0_rwflags(probes_opcode_t insn,
- struct arch_specific_insn *asi, struct pt_regs *regs)
+ struct arch_probes_insn *asi, struct pt_regs *regs)
{
int rd = (insn >> 8) & 0xf;
int rn = (insn >> 16) & 0xf;
@@ -237,7 +237,7 @@ t32_emulate_rd8rn16rm0_rwflags(probes_opcode_t insn,
static void __kprobes
t32_emulate_rd8pc16_noflags(probes_opcode_t insn,
- struct arch_specific_insn *asi, struct pt_regs *regs)
+ struct arch_probes_insn *asi, struct pt_regs *regs)
{
unsigned long pc = regs->ARM_pc;
int rd = (insn >> 8) & 0xf;
@@ -257,7 +257,7 @@ t32_emulate_rd8pc16_noflags(probes_opcode_t insn,
static void __kprobes
t32_emulate_rd8rn16_noflags(probes_opcode_t insn,
- struct arch_specific_insn *asi, struct pt_regs *regs)
+ struct arch_probes_insn *asi, struct pt_regs *regs)
{
int rd = (insn >> 8) & 0xf;
int rn = (insn >> 16) & 0xf;
@@ -277,7 +277,7 @@ t32_emulate_rd8rn16_noflags(probes_opcode_t insn,
static void __kprobes
t32_emulate_rdlo12rdhi8rn16rm0_noflags(probes_opcode_t insn,
- struct arch_specific_insn *asi,
+ struct arch_probes_insn *asi,
struct pt_regs *regs)
{
int rdlo = (insn >> 12) & 0xf;
@@ -305,7 +305,7 @@ t32_emulate_rdlo12rdhi8rn16rm0_noflags(probes_opcode_t insn,
static void __kprobes
t16_simulate_bxblx(probes_opcode_t insn,
- struct arch_specific_insn *asi, struct pt_regs *regs)
+ struct arch_probes_insn *asi, struct pt_regs *regs)
{
unsigned long pc = regs->ARM_pc + 2;
int rm = (insn >> 3) & 0xf;
@@ -319,7 +319,7 @@ t16_simulate_bxblx(probes_opcode_t insn,
static void __kprobes
t16_simulate_ldr_literal(probes_opcode_t insn,
- struct arch_specific_insn *asi, struct pt_regs *regs)
+ struct arch_probes_insn *asi, struct pt_regs *regs)
{
unsigned long *base = (unsigned long *)((regs->ARM_pc + 2) & ~3);
long index = insn & 0xff;
@@ -329,7 +329,7 @@ t16_simulate_ldr_literal(probes_opcode_t insn,
static void __kprobes
t16_simulate_ldrstr_sp_relative(probes_opcode_t insn,
- struct arch_specific_insn *asi, struct pt_regs *regs)
+ struct arch_probes_insn *asi, struct pt_regs *regs)
{
unsigned long* base = (unsigned long *)regs->ARM_sp;
long index = insn & 0xff;
@@ -342,7 +342,7 @@ t16_simulate_ldrstr_sp_relative(probes_opcode_t insn,
static void __kprobes
t16_simulate_reladr(probes_opcode_t insn,
- struct arch_specific_insn *asi, struct pt_regs *regs)
+ struct arch_probes_insn *asi, struct pt_regs *regs)
{
unsigned long base = (insn & 0x800) ? regs->ARM_sp
: ((regs->ARM_pc + 2) & ~3);
@@ -353,7 +353,7 @@ t16_simulate_reladr(probes_opcode_t insn,
static void __kprobes
t16_simulate_add_sp_imm(probes_opcode_t insn,
- struct arch_specific_insn *asi, struct pt_regs *regs)
+ struct arch_probes_insn *asi, struct pt_regs *regs)
{
long imm = insn & 0x7f;
if (insn & 0x80) /* SUB */
@@ -364,7 +364,7 @@ t16_simulate_add_sp_imm(probes_opcode_t insn,
static void __kprobes
t16_simulate_cbz(probes_opcode_t insn,
- struct arch_specific_insn *asi, struct pt_regs *regs)
+ struct arch_probes_insn *asi, struct pt_regs *regs)
{
int rn = insn & 0x7;
probes_opcode_t nonzero = regs->uregs[rn] ? insn : ~insn;
@@ -378,7 +378,7 @@ t16_simulate_cbz(probes_opcode_t insn,
static void __kprobes
t16_simulate_it(probes_opcode_t insn,
- struct arch_specific_insn *asi, struct pt_regs *regs)
+ struct arch_probes_insn *asi, struct pt_regs *regs)
{
/*
* The 8 IT state bits are split into two parts in CPSR:
@@ -395,14 +395,14 @@ t16_simulate_it(probes_opcode_t insn,
static void __kprobes
t16_singlestep_it(probes_opcode_t insn,
- struct arch_specific_insn *asi, struct pt_regs *regs)
+ struct arch_probes_insn *asi, struct pt_regs *regs)
{
regs->ARM_pc += 2;
t16_simulate_it(insn, asi, regs);
}
static enum probes_insn __kprobes
-t16_decode_it(probes_opcode_t insn, struct arch_specific_insn *asi,
+t16_decode_it(probes_opcode_t insn, struct arch_probes_insn *asi,
struct decode_header *d)
{
asi->insn_singlestep = t16_singlestep_it;
@@ -411,7 +411,7 @@ t16_decode_it(probes_opcode_t insn, struct arch_specific_insn *asi,
static void __kprobes
t16_simulate_cond_branch(probes_opcode_t insn,
- struct arch_specific_insn *asi, struct pt_regs *regs)
+ struct arch_probes_insn *asi, struct pt_regs *regs)
{
unsigned long pc = regs->ARM_pc + 2;
long offset = insn & 0x7f;
@@ -420,7 +420,7 @@ t16_simulate_cond_branch(probes_opcode_t insn,
}
static enum probes_insn __kprobes
-t16_decode_cond_branch(probes_opcode_t insn, struct arch_specific_insn *asi,
+t16_decode_cond_branch(probes_opcode_t insn, struct arch_probes_insn *asi,
struct decode_header *d)
{
int cc = (insn >> 8) & 0xf;
@@ -431,7 +431,7 @@ t16_decode_cond_branch(probes_opcode_t insn, struct arch_specific_insn *asi,
static void __kprobes
t16_simulate_branch(probes_opcode_t insn,
- struct arch_specific_insn *asi, struct pt_regs *regs)
+ struct arch_probes_insn *asi, struct pt_regs *regs)
{
unsigned long pc = regs->ARM_pc + 2;
long offset = insn & 0x3ff;
@@ -441,7 +441,7 @@ t16_simulate_branch(probes_opcode_t insn,
static unsigned long __kprobes
t16_emulate_loregs(probes_opcode_t insn,
- struct arch_specific_insn *asi, struct pt_regs *regs)
+ struct arch_probes_insn *asi, struct pt_regs *regs)
{
unsigned long oldcpsr = regs->ARM_cpsr;
unsigned long newcpsr;
@@ -464,14 +464,14 @@ t16_emulate_loregs(probes_opcode_t insn,
static void __kprobes
t16_emulate_loregs_rwflags(probes_opcode_t insn,
- struct arch_specific_insn *asi, struct pt_regs *regs)
+ struct arch_probes_insn *asi, struct pt_regs *regs)
{
regs->ARM_cpsr = t16_emulate_loregs(insn, asi, regs);
}
static void __kprobes
t16_emulate_loregs_noitrwflags(probes_opcode_t insn,
- struct arch_specific_insn *asi, struct pt_regs *regs)
+ struct arch_probes_insn *asi, struct pt_regs *regs)
{
unsigned long cpsr = t16_emulate_loregs(insn, asi, regs);
if (!in_it_block(cpsr))
@@ -480,7 +480,7 @@ t16_emulate_loregs_noitrwflags(probes_opcode_t insn,
static void __kprobes
t16_emulate_hiregs(probes_opcode_t insn,
- struct arch_specific_insn *asi, struct pt_regs *regs)
+ struct arch_probes_insn *asi, struct pt_regs *regs)
{
unsigned long pc = regs->ARM_pc + 2;
int rdn = (insn & 0x7) | ((insn & 0x80) >> 4);
@@ -510,7 +510,7 @@ t16_emulate_hiregs(probes_opcode_t insn,
}
static enum probes_insn __kprobes
-t16_decode_hiregs(probes_opcode_t insn, struct arch_specific_insn *asi,
+t16_decode_hiregs(probes_opcode_t insn, struct arch_probes_insn *asi,
struct decode_header *d)
{
insn &= ~0x00ff;
@@ -522,7 +522,7 @@ t16_decode_hiregs(probes_opcode_t insn, struct arch_specific_insn *asi,
static void __kprobes
t16_emulate_push(probes_opcode_t insn,
- struct arch_specific_insn *asi, struct pt_regs *regs)
+ struct arch_probes_insn *asi, struct pt_regs *regs)
{
__asm__ __volatile__ (
"ldr r9, [%[regs], #13*4] \n\t"
@@ -538,7 +538,7 @@ t16_emulate_push(probes_opcode_t insn,
}
static enum probes_insn __kprobes
-t16_decode_push(probes_opcode_t insn, struct arch_specific_insn *asi,
+t16_decode_push(probes_opcode_t insn, struct arch_probes_insn *asi,
struct decode_header *d)
{
/*
@@ -554,7 +554,7 @@ t16_decode_push(probes_opcode_t insn, struct arch_specific_insn *asi,
static void __kprobes
t16_emulate_pop_nopc(probes_opcode_t insn,
- struct arch_specific_insn *asi, struct pt_regs *regs)
+ struct arch_probes_insn *asi, struct pt_regs *regs)
{
__asm__ __volatile__ (
"ldr r9, [%[regs], #13*4] \n\t"
@@ -571,7 +571,7 @@ t16_emulate_pop_nopc(probes_opcode_t insn,
static void __kprobes
t16_emulate_pop_pc(probes_opcode_t insn,
- struct arch_specific_insn *asi, struct pt_regs *regs)
+ struct arch_probes_insn *asi, struct pt_regs *regs)
{
register unsigned long pc asm("r8");
@@ -591,7 +591,7 @@ t16_emulate_pop_pc(probes_opcode_t insn,
}
enum probes_insn __kprobes
-t16_decode_pop(probes_opcode_t insn, struct arch_specific_insn *asi,
+t16_decode_pop(probes_opcode_t insn, struct arch_probes_insn *asi,
struct decode_header *d)
{
/*
diff --git a/arch/arm/kernel/kprobes.h b/arch/arm/kernel/kprobes.h
index 580d82c..841416c 100644
--- a/arch/arm/kernel/kprobes.h
+++ b/arch/arm/kernel/kprobes.h
@@ -30,11 +30,11 @@
#define KPROBE_THUMB32_BREAKPOINT_INSTRUCTION 0xf7f0a018
enum probes_insn __kprobes
-kprobe_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi,
+kprobe_decode_ldmstm(kprobe_opcode_t insn, struct arch_probes_insn *asi,
struct decode_header *h);
typedef enum probes_insn (kprobe_decode_insn_t)(kprobe_opcode_t,
- struct arch_specific_insn *,
+ struct arch_probes_insn *,
bool,
const union decode_item *);
diff --git a/arch/arm/kernel/probes-arm.c b/arch/arm/kernel/probes-arm.c
index 01e99f7..e9b54f7 100644
--- a/arch/arm/kernel/probes-arm.c
+++ b/arch/arm/kernel/probes-arm.c
@@ -56,7 +56,7 @@
*/
void __kprobes simulate_bbl(probes_opcode_t insn,
- struct arch_specific_insn *asi, struct pt_regs *regs)
+ struct arch_probes_insn *asi, struct pt_regs *regs)
{
long iaddr = (long) regs->ARM_pc - 4;
int disp = branch_displacement(insn);
@@ -68,7 +68,7 @@ void __kprobes simulate_bbl(probes_opcode_t insn,
}
void __kprobes simulate_blx1(probes_opcode_t insn,
- struct arch_specific_insn *asi, struct pt_regs *regs)
+ struct arch_probes_insn *asi, struct pt_regs *regs)
{
long iaddr = (long) regs->ARM_pc - 4;
int disp = branch_displacement(insn);
@@ -79,7 +79,7 @@ void __kprobes simulate_blx1(probes_opcode_t insn,
}
void __kprobes simulate_blx2bx(probes_opcode_t insn,
- struct arch_specific_insn *asi, struct pt_regs *regs)
+ struct arch_probes_insn *asi, struct pt_regs *regs)
{
int rm = insn & 0xf;
long rmv = regs->uregs[rm];
@@ -94,7 +94,7 @@ void __kprobes simulate_blx2bx(probes_opcode_t insn,
}
void __kprobes simulate_mrs(probes_opcode_t insn,
- struct arch_specific_insn *asi, struct pt_regs *regs)
+ struct arch_probes_insn *asi, struct pt_regs *regs)
{
int rd = (insn >> 12) & 0xf;
unsigned long mask = 0xf8ff03df; /* Mask out execution state */
@@ -102,7 +102,7 @@ void __kprobes simulate_mrs(probes_opcode_t insn,
}
void __kprobes simulate_mov_ipsp(probes_opcode_t insn,
- struct arch_specific_insn *asi, struct pt_regs *regs)
+ struct arch_probes_insn *asi, struct pt_regs *regs)
{
regs->uregs[12] = regs->uregs[13];
}
@@ -703,7 +703,7 @@ EXPORT_SYMBOL_GPL(probes_decode_arm_table);
#endif
static void __kprobes arm_singlestep(probes_opcode_t insn,
- struct arch_specific_insn *asi, struct pt_regs *regs)
+ struct arch_probes_insn *asi, struct pt_regs *regs)
{
regs->ARM_pc += 4;
asi->insn_handler(insn, asi, regs);
@@ -722,7 +722,7 @@ static void __kprobes arm_singlestep(probes_opcode_t insn,
* should also be very rare.
*/
enum probes_insn __kprobes
-arm_probes_decode_insn(probes_opcode_t insn, struct arch_specific_insn *asi,
+arm_probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi,
bool emulate, const union decode_item *actions)
{
asi->insn_singlestep = arm_singlestep;
diff --git a/arch/arm/kernel/probes-arm.h b/arch/arm/kernel/probes-arm.h
index 904033c..984aaa7 100644
--- a/arch/arm/kernel/probes-arm.h
+++ b/arch/arm/kernel/probes-arm.h
@@ -53,20 +53,20 @@ enum probes_arm_action {
};
void __kprobes simulate_bbl(probes_opcode_t opcode,
- struct arch_specific_insn *asi, struct pt_regs *regs);
+ struct arch_probes_insn *asi, struct pt_regs *regs);
void __kprobes simulate_blx1(probes_opcode_t opcode,
- struct arch_specific_insn *asi, struct pt_regs *regs);
+ struct arch_probes_insn *asi, struct pt_regs *regs);
void __kprobes simulate_blx2bx(probes_opcode_t opcode,
- struct arch_specific_insn *asi, struct pt_regs *regs);
+ struct arch_probes_insn *asi, struct pt_regs *regs);
void __kprobes simulate_mrs(probes_opcode_t opcode,
- struct arch_specific_insn *asi, struct pt_regs *regs);
+ struct arch_probes_insn *asi, struct pt_regs *regs);
void __kprobes simulate_mov_ipsp(probes_opcode_t opcode,
- struct arch_specific_insn *asi, struct pt_regs *regs);
+ struct arch_probes_insn *asi, struct pt_regs *regs);
extern const union decode_item probes_decode_arm_table[];
enum probes_insn arm_probes_decode_insn(probes_opcode_t,
- struct arch_specific_insn *, bool emulate,
+ struct arch_probes_insn *, bool emulate,
const union decode_item *actions);
#endif
diff --git a/arch/arm/kernel/probes-thumb.c b/arch/arm/kernel/probes-thumb.c
index 2ad0880..9cf56d8 100644
--- a/arch/arm/kernel/probes-thumb.c
+++ b/arch/arm/kernel/probes-thumb.c
@@ -842,7 +842,7 @@ static unsigned long __kprobes thumb_check_cc(unsigned long cpsr)
}
static void __kprobes thumb16_singlestep(probes_opcode_t opcode,
- struct arch_specific_insn *asi,
+ struct arch_probes_insn *asi,
struct pt_regs *regs)
{
regs->ARM_pc += 2;
@@ -851,7 +851,7 @@ static void __kprobes thumb16_singlestep(probes_opcode_t opcode,
}
static void __kprobes thumb32_singlestep(probes_opcode_t opcode,
- struct arch_specific_insn *asi,
+ struct arch_probes_insn *asi,
struct pt_regs *regs)
{
regs->ARM_pc += 4;
@@ -860,7 +860,7 @@ 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,
+thumb16_probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi,
bool emulate, const union decode_item *actions)
{
asi->insn_singlestep = thumb16_singlestep;
@@ -870,7 +870,7 @@ thumb16_probes_decode_insn(probes_opcode_t insn, struct arch_specific_insn *asi,
}
enum probes_insn __kprobes
-thumb32_probes_decode_insn(probes_opcode_t insn, struct arch_specific_insn *asi,
+thumb32_probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi,
bool emulate, const union decode_item *actions)
{
asi->insn_singlestep = thumb32_singlestep;
diff --git a/arch/arm/kernel/probes-thumb.h b/arch/arm/kernel/probes-thumb.h
index 78be667..2916222 100644
--- a/arch/arm/kernel/probes-thumb.h
+++ b/arch/arm/kernel/probes-thumb.h
@@ -86,10 +86,10 @@ extern const union decode_item probes_decode_thumb32_table[];
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,
+thumb16_probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi,
bool emulate, const union decode_item *actions);
enum probes_insn __kprobes
-thumb32_probes_decode_insn(probes_opcode_t insn, struct arch_specific_insn *asi,
+thumb32_probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi,
bool emulate, const union decode_item *actions);
#endif
diff --git a/arch/arm/kernel/probes.c b/arch/arm/kernel/probes.c
index e691e12..e194955 100644
--- a/arch/arm/kernel/probes.c
+++ b/arch/arm/kernel/probes.c
@@ -172,13 +172,13 @@ probes_check_cc * const probes_condition_checks[16] = {
void __kprobes probes_simulate_nop(probes_opcode_t opcode,
- struct arch_specific_insn *asi,
+ struct arch_probes_insn *asi,
struct pt_regs *regs)
{
}
void __kprobes probes_emulate_none(probes_opcode_t opcode,
- struct arch_specific_insn *asi,
+ struct arch_probes_insn *asi,
struct pt_regs *regs)
{
asi->insn_fn();
@@ -192,7 +192,7 @@ void __kprobes probes_emulate_none(probes_opcode_t opcode,
* emulation handler is called.
*/
static probes_opcode_t __kprobes
-prepare_emulated_insn(probes_opcode_t insn, struct arch_specific_insn *asi,
+prepare_emulated_insn(probes_opcode_t insn, struct arch_probes_insn *asi,
bool thumb)
{
#ifdef CONFIG_THUMB2_KERNEL
@@ -217,7 +217,7 @@ prepare_emulated_insn(probes_opcode_t insn, struct arch_specific_insn *asi,
* prepare_emulated_insn
*/
static void __kprobes
-set_emulated_insn(probes_opcode_t insn, struct arch_specific_insn *asi,
+set_emulated_insn(probes_opcode_t insn, struct arch_probes_insn *asi,
bool thumb)
{
#ifdef CONFIG_THUMB2_KERNEL
@@ -386,7 +386,7 @@ static const int decode_struct_sizes[NUM_DECODE_TYPES] = {
*
*/
int __kprobes
-probes_decode_insn(probes_opcode_t insn, struct arch_specific_insn *asi,
+probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi,
const union decode_item *table, bool thumb,
bool emulate, const union decode_item *actions)
{
diff --git a/arch/arm/kernel/probes.h b/arch/arm/kernel/probes.h
index 233ab7b..2a1eb32 100644
--- a/arch/arm/kernel/probes.h
+++ b/arch/arm/kernel/probes.h
@@ -296,7 +296,7 @@ union decode_item {
const union decode_item *table;
probes_insn_handler_t *handler;
enum probes_insn (*decoder)(probes_opcode_t,
- struct arch_specific_insn *,
+ struct arch_probes_insn *,
struct decode_header *);
};
@@ -388,7 +388,7 @@ probes_insn_handler_t probes_simulate_nop;
probes_insn_handler_t probes_emulate_none;
int __kprobes
-probes_decode_insn(probes_opcode_t insn, struct arch_specific_insn *asi,
+probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi,
const union decode_item *table, bool thumb, bool emulate,
const union decode_item *actions);
--
1.8.1.2
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH v4 15/16] ARM: add uprobes support
2013-12-16 4:08 [PATCH v4 00/16] uprobes: Add uprobes support for ARM David Long
` (13 preceding siblings ...)
2013-12-16 4:08 ` [PATCH v4 14/16] ARM: Make arch_specific_insn a define for new arch_probes_insn structure David Long
@ 2013-12-16 4:08 ` David Long
2013-12-20 18:34 ` Jon Medhurst (Tixy)
2013-12-16 4:08 ` [PATCH v4 16/16] ARM: Remove uprobes dependency on kprobes David Long
15 siblings, 1 reply; 34+ messages in thread
From: David Long @ 2013-12-16 4:08 UTC (permalink / raw)
To: linux-arm-kernel
From: "David A. Long" <dave.long@linaro.org>
Using Rabin Vincent's ARM uprobes patches as a base, enable uprobes
support on ARM.
Caveats:
- Thumb is not supported
- XOL abort/trap handling is not implemented
Signed-off-by: David A. Long <dave.long@linaro.org>
---
arch/arm/Kconfig | 4 +
arch/arm/include/asm/ptrace.h | 6 +
arch/arm/include/asm/thread_info.h | 5 +-
arch/arm/include/asm/uprobes.h | 36 ++++++
arch/arm/kernel/Makefile | 1 +
arch/arm/kernel/signal.c | 4 +
arch/arm/kernel/uprobes-arm.c | 223 +++++++++++++++++++++++++++++++++++++
arch/arm/kernel/uprobes.c | 198 ++++++++++++++++++++++++++++++++
arch/arm/kernel/uprobes.h | 27 +++++
9 files changed, 503 insertions(+), 1 deletion(-)
create mode 100644 arch/arm/include/asm/uprobes.h
create mode 100644 arch/arm/kernel/uprobes-arm.c
create mode 100644 arch/arm/kernel/uprobes.c
create mode 100644 arch/arm/kernel/uprobes.h
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index c1f1a7e..fec5a6b 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -203,6 +203,10 @@ config ZONE_DMA
config NEED_DMA_MAP_STATE
def_bool y
+config ARCH_SUPPORTS_UPROBES
+ depends on KPROBES
+ def_bool y
+
config ARCH_HAS_DMA_SET_COHERENT_MASK
bool
diff --git a/arch/arm/include/asm/ptrace.h b/arch/arm/include/asm/ptrace.h
index 04c99f3..ee688b0a 100644
--- a/arch/arm/include/asm/ptrace.h
+++ b/arch/arm/include/asm/ptrace.h
@@ -80,6 +80,12 @@ static inline long regs_return_value(struct pt_regs *regs)
#define instruction_pointer(regs) (regs)->ARM_pc
+static inline void instruction_pointer_set(struct pt_regs *regs,
+ unsigned long val)
+{
+ instruction_pointer(regs) = val;
+}
+
#ifdef CONFIG_SMP
extern unsigned long profile_pc(struct pt_regs *regs);
#else
diff --git a/arch/arm/include/asm/thread_info.h b/arch/arm/include/asm/thread_info.h
index 71a06b2..f989d7c 100644
--- a/arch/arm/include/asm/thread_info.h
+++ b/arch/arm/include/asm/thread_info.h
@@ -153,6 +153,7 @@ extern int vfp_restore_user_hwstate(struct user_vfp __user *,
#define TIF_SIGPENDING 0
#define TIF_NEED_RESCHED 1
#define TIF_NOTIFY_RESUME 2 /* callback before returning to user */
+#define TIF_UPROBE 7
#define TIF_SYSCALL_TRACE 8
#define TIF_SYSCALL_AUDIT 9
#define TIF_SYSCALL_TRACEPOINT 10
@@ -165,6 +166,7 @@ extern int vfp_restore_user_hwstate(struct user_vfp __user *,
#define _TIF_SIGPENDING (1 << TIF_SIGPENDING)
#define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED)
#define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME)
+#define _TIF_UPROBE (1 << TIF_UPROBE)
#define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE)
#define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT)
#define _TIF_SYSCALL_TRACEPOINT (1 << TIF_SYSCALL_TRACEPOINT)
@@ -178,7 +180,8 @@ extern int vfp_restore_user_hwstate(struct user_vfp __user *,
/*
* Change these and you break ASM code in entry-common.S
*/
-#define _TIF_WORK_MASK (_TIF_NEED_RESCHED | _TIF_SIGPENDING | _TIF_NOTIFY_RESUME)
+#define _TIF_WORK_MASK (_TIF_NEED_RESCHED | _TIF_SIGPENDING | \
+ _TIF_NOTIFY_RESUME | _TIF_UPROBE)
#endif /* __KERNEL__ */
#endif /* __ASM_ARM_THREAD_INFO_H */
diff --git a/arch/arm/include/asm/uprobes.h b/arch/arm/include/asm/uprobes.h
new file mode 100644
index 0000000..c99c92b
--- /dev/null
+++ b/arch/arm/include/asm/uprobes.h
@@ -0,0 +1,36 @@
+#ifndef _ASM_UPROBES_H
+#define _ASM_UPROBES_H
+
+#include <asm/probes.h>
+#include <asm/opcodes.h>
+
+typedef u32 uprobe_opcode_t;
+
+#define MAX_UINSN_BYTES 4
+#define UPROBE_XOL_SLOT_BYTES 64
+
+#define UPROBE_SWBP_ARM_INSN 0xe7f001f9
+#define UPROBE_SS_ARM_INSN 0xe7f001fa
+#define UPROBE_SWBP_INSN __opcode_to_mem_arm(UPROBE_SWBP_ARM_INSN)
+#define UPROBE_SWBP_INSN_SIZE 4
+
+struct arch_uprobe_task {
+ u32 backup;
+};
+
+struct arch_uprobe {
+ u8 insn[MAX_UINSN_BYTES];
+ unsigned long ixol[2];
+ uprobe_opcode_t bpinsn;
+ bool simulate;
+ u32 pcreg;
+ void (*prehandler)(struct arch_uprobe *auprobe,
+ struct arch_uprobe_task *autask,
+ struct pt_regs *regs);
+ void (*posthandler)(struct arch_uprobe *auprobe,
+ struct arch_uprobe_task *autask,
+ struct pt_regs *regs);
+ struct arch_probes_insn asi;
+};
+
+#endif
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index bb739f2..a766bcb 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -50,6 +50,7 @@ obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o insn.o
obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o insn.o
obj-$(CONFIG_JUMP_LABEL) += jump_label.o insn.o patch.o
obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o
+obj-$(CONFIG_UPROBES) += probes.o probes-arm.o uprobes.o uprobes-arm.o
obj-$(CONFIG_KPROBES) += probes.o kprobes.o kprobes-common.o patch.o
ifdef CONFIG_THUMB2_KERNEL
obj-$(CONFIG_KPROBES) += kprobes-thumb.o probes-thumb.o
diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
index 04d6388..bd19834 100644
--- a/arch/arm/kernel/signal.c
+++ b/arch/arm/kernel/signal.c
@@ -13,6 +13,7 @@
#include <linux/personality.h>
#include <linux/uaccess.h>
#include <linux/tracehook.h>
+#include <linux/uprobes.h>
#include <asm/elf.h>
#include <asm/cacheflush.h>
@@ -590,6 +591,9 @@ do_work_pending(struct pt_regs *regs, unsigned int thread_flags, int syscall)
return restart;
}
syscall = 0;
+ } else if (thread_flags & _TIF_UPROBE) {
+ clear_thread_flag(TIF_UPROBE);
+ uprobe_notify_resume(regs);
} else {
clear_thread_flag(TIF_NOTIFY_RESUME);
tracehook_notify_resume(regs);
diff --git a/arch/arm/kernel/uprobes-arm.c b/arch/arm/kernel/uprobes-arm.c
new file mode 100644
index 0000000..d96f77c
--- /dev/null
+++ b/arch/arm/kernel/uprobes-arm.c
@@ -0,0 +1,223 @@
+#include <linux/kernel.h>
+#include <linux/wait.h>
+#include <linux/uprobes.h>
+#include <linux/module.h>
+
+#include "probes.h"
+#include "probes-arm.h"
+#include "uprobes.h"
+
+static int uprobes_substitute_pc(unsigned long *pinsn, u32 oregs)
+{
+ probes_opcode_t insn = __mem_to_opcode_arm(*pinsn);
+ probes_opcode_t temp;
+ probes_opcode_t mask;
+ int freereg;
+ u32 free = 0xffff;
+ u32 regs;
+
+ for (regs = oregs; regs; regs >>= 4, insn >>= 4) {
+ if ((regs & 0xf) == REG_TYPE_NONE)
+ continue;
+
+ free &= ~(1 << (insn & 0xf));
+ }
+
+ /* No PC, no problem */
+ if (free & (1 << 15))
+ return 15;
+
+ if (!free)
+ return -1;
+
+ /*
+ * fls instead of ffs ensures that for "ldrd r0, r1, [pc]" we would
+ * pick LR instead of R1.
+ */
+ freereg = free = fls(free) - 1;
+
+ temp = __mem_to_opcode_arm(*pinsn);
+ insn = temp;
+ regs = oregs;
+ mask = 0xf;
+
+ for (; regs; regs >>= 4, mask <<= 4, free <<= 4, temp >>= 4) {
+ if ((regs & 0xf) == REG_TYPE_NONE)
+ continue;
+
+ if ((temp & 0xf) != 15)
+ continue;
+
+ insn &= ~mask;
+ insn |= free & mask;
+ }
+
+ *pinsn = __opcode_to_mem_arm(insn);
+ return freereg;
+}
+
+static void uprobe_set_pc(struct arch_uprobe *auprobe,
+ struct arch_uprobe_task *autask,
+ struct pt_regs *regs)
+{
+ u32 pcreg = auprobe->pcreg;
+
+ autask->backup = regs->uregs[pcreg];
+ regs->uregs[pcreg] = regs->ARM_pc + 8;
+}
+
+static void uprobe_unset_pc(struct arch_uprobe *auprobe,
+ struct arch_uprobe_task *autask,
+ struct pt_regs *regs)
+{
+ /* PC will be taken care of by common code */
+ regs->uregs[auprobe->pcreg] = autask->backup;
+}
+
+static void uprobe_aluwrite_pc(struct arch_uprobe *auprobe,
+ struct arch_uprobe_task *autask,
+ struct pt_regs *regs)
+{
+ u32 pcreg = auprobe->pcreg;
+
+ alu_write_pc(regs->uregs[pcreg], regs);
+ regs->uregs[pcreg] = autask->backup;
+}
+
+static void uprobe_write_pc(struct arch_uprobe *auprobe,
+ struct arch_uprobe_task *autask,
+ struct pt_regs *regs)
+{
+ u32 pcreg = auprobe->pcreg;
+
+ load_write_pc(regs->uregs[pcreg], regs);
+ regs->uregs[pcreg] = autask->backup;
+}
+
+enum probes_insn
+decode_pc_ro(probes_opcode_t insn, struct arch_probes_insn *asi,
+ struct decode_header *d)
+{
+ struct arch_uprobe *auprobe = container_of(asi, struct arch_uprobe,
+ asi);
+ struct decode_emulate *decode = (struct decode_emulate *) d;
+ u32 regs = decode->header.type_regs.bits >> DECODE_TYPE_BITS;
+ int reg;
+
+ reg = uprobes_substitute_pc(&auprobe->ixol[0], regs);
+ if (reg == 15)
+ return INSN_GOOD;
+
+ if (reg == -1)
+ return INSN_REJECTED;
+
+ auprobe->pcreg = reg;
+ auprobe->prehandler = uprobe_set_pc;
+ auprobe->posthandler = uprobe_unset_pc;
+
+ return INSN_GOOD;
+}
+
+enum probes_insn
+decode_wb_pc(probes_opcode_t insn, struct arch_probes_insn *asi,
+ struct decode_header *d, bool alu)
+{
+ struct arch_uprobe *auprobe = container_of(asi, struct arch_uprobe,
+ asi);
+ enum probes_insn ret = decode_pc_ro(insn, asi, d);
+
+ if (((insn >> 12) & 0xf) == 15)
+ auprobe->posthandler = alu ? uprobe_aluwrite_pc
+ : uprobe_write_pc;
+
+ return ret;
+}
+
+enum probes_insn
+decode_rd12rn16rm0rs8_rwflags(probes_opcode_t insn,
+ struct arch_probes_insn *asi,
+ struct decode_header *d)
+{
+ return decode_wb_pc(insn, asi, d, true);
+}
+
+enum probes_insn
+decode_ldr(probes_opcode_t insn, struct arch_probes_insn *asi,
+ struct decode_header *d)
+{
+ return decode_wb_pc(insn, asi, d, false);
+}
+
+enum probes_insn
+uprobe_decode_ldmstm(probes_opcode_t insn,
+ struct arch_probes_insn *asi, struct decode_header *d)
+{
+ struct arch_uprobe *auprobe = container_of(asi, struct arch_uprobe,
+ asi);
+ unsigned reglist = insn & 0xffff;
+ int rn = (insn >> 16) & 0xf;
+ int lbit = insn & (1 << 20);
+ unsigned used = reglist | (1 << rn);
+
+ if (rn == 15)
+ return INSN_REJECTED;
+
+ if (!(used & (1 << 15)))
+ return INSN_GOOD;
+
+ if (used & (1 << 14))
+ return INSN_REJECTED;
+
+ /* Use LR instead of PC */
+ insn ^= 0xc000;
+
+ auprobe->pcreg = 14;
+ auprobe->ixol[0] = __opcode_to_mem_arm(insn);
+
+ auprobe->prehandler = uprobe_set_pc;
+ if (lbit)
+ auprobe->posthandler = uprobe_write_pc;
+ else
+ auprobe->posthandler = uprobe_unset_pc;
+
+ return INSN_GOOD;
+}
+
+const union decode_item uprobes_probes_actions[] = {
+ [PROBES_EMULATE_NONE] {.handler = probes_simulate_nop},
+ [PROBES_SIMULATE_NOP] = {.handler = probes_simulate_nop},
+ [PROBES_PRELOAD_IMM] = {.handler = probes_simulate_nop},
+ [PROBES_PRELOAD_REG] = {.handler = probes_simulate_nop},
+ [PROBES_BRANCH_IMM] = {.handler = simulate_blx1},
+ [PROBES_MRS] = {.handler = simulate_mrs},
+ [PROBES_BRANCH_REG] = {.handler = simulate_blx2bx},
+ [PROBES_CLZ] = {.handler = probes_simulate_nop},
+ [PROBES_SATURATING_ARITHMETIC] = {.handler = probes_simulate_nop},
+ [PROBES_MUL1] = {.handler = probes_simulate_nop},
+ [PROBES_MUL2] = {.handler = probes_simulate_nop},
+ [PROBES_SWP] = {.handler = probes_simulate_nop},
+ [PROBES_LDRSTRD] = {.decoder = decode_pc_ro},
+ [PROBES_LOAD_EXTRA] = {.decoder = decode_pc_ro},
+ [PROBES_LOAD] = {.decoder = decode_ldr},
+ [PROBES_STORE_EXTRA] = {.decoder = decode_pc_ro},
+ [PROBES_STORE] = {.decoder = decode_pc_ro},
+ [PROBES_MOV_IP_SP] = {.handler = simulate_mov_ipsp},
+ [PROBES_DATA_PROCESSING_REG] = {
+ .decoder = decode_rd12rn16rm0rs8_rwflags},
+ [PROBES_DATA_PROCESSING_IMM] = {
+ .decoder = decode_rd12rn16rm0rs8_rwflags},
+ [PROBES_MOV_HALFWORD] = {.handler = probes_simulate_nop},
+ [PROBES_SEV] = {.handler = probes_simulate_nop},
+ [PROBES_WFE] = {.handler = probes_simulate_nop},
+ [PROBES_SATURATE] = {.handler = probes_simulate_nop},
+ [PROBES_REV] = {.handler = probes_simulate_nop},
+ [PROBES_MMI] = {.handler = probes_simulate_nop},
+ [PROBES_PACK] = {.handler = probes_simulate_nop},
+ [PROBES_EXTEND] = {.handler = probes_simulate_nop},
+ [PROBES_EXTEND_ADD] = {.handler = probes_simulate_nop},
+ [PROBES_MUL_ADD_LONG] = {.handler = probes_simulate_nop},
+ [PROBES_MUL_ADD] = {.handler = probes_simulate_nop},
+ [PROBES_BITFIELD] = {.handler = probes_simulate_nop},
+ [PROBES_BRANCH] = {.handler = simulate_bbl},
+ [PROBES_LDMSTM] = {.decoder = uprobe_decode_ldmstm}
+};
diff --git a/arch/arm/kernel/uprobes.c b/arch/arm/kernel/uprobes.c
new file mode 100644
index 0000000..ae18549
--- /dev/null
+++ b/arch/arm/kernel/uprobes.c
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) 2012 Rabin Vincent <rabin@rab.in>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/highmem.h>
+#include <linux/sched.h>
+#include <linux/uprobes.h>
+#include <linux/notifier.h>
+
+#include <asm/opcodes.h>
+#include <asm/traps.h>
+
+#include "probes.h"
+#include "probes-arm.h"
+#include "uprobes.h"
+
+bool is_swbp_insn(uprobe_opcode_t *insn)
+{
+ return (__mem_to_opcode_arm(*insn) & 0x0fffffff) ==
+ (UPROBE_SWBP_ARM_INSN & 0x0fffffff);
+}
+
+int set_swbp(struct arch_uprobe *auprobe, struct mm_struct *mm,
+ unsigned long vaddr)
+{
+ return uprobe_write_opcode(mm, vaddr,
+ __opcode_to_mem_arm(auprobe->bpinsn));
+}
+
+bool arch_uprobe_ignore(struct arch_uprobe *auprobe, struct pt_regs *regs)
+{
+ if (!auprobe->asi.insn_check_cc(regs->ARM_cpsr)) {
+ regs->ARM_pc += 4;
+ return true;
+ }
+
+ return false;
+}
+
+bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs)
+{
+ void *addr;
+ probes_opcode_t opcode;
+
+ if (!auprobe->simulate)
+ return false;
+
+ addr = (void *) regs->ARM_pc;
+ opcode = __mem_to_opcode_arm(*(unsigned int *) auprobe->insn);
+
+ auprobe->asi.insn_singlestep(opcode, &auprobe->asi, regs);
+
+ return true;
+}
+
+unsigned long
+arch_uretprobe_hijack_return_addr(unsigned long trampoline_vaddr,
+ struct pt_regs *regs)
+{
+ unsigned long orig_ret_vaddr;
+
+ orig_ret_vaddr = regs->ARM_lr;
+ /* Replace the return addr with trampoline addr */
+ regs->ARM_lr = trampoline_vaddr;
+ return orig_ret_vaddr;
+}
+
+int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe, struct mm_struct *mm,
+ unsigned long addr)
+{
+ unsigned int insn;
+ unsigned int bpinsn;
+ enum probes_insn ret;
+
+ /* Thumb not yet support */
+ if (addr & 0x3)
+ return -EINVAL;
+
+ insn = __mem_to_opcode_arm(*(unsigned int *)auprobe->insn);
+ auprobe->ixol[0] = __opcode_to_mem_arm(insn);
+ auprobe->ixol[1] = __opcode_to_mem_arm(UPROBE_SS_ARM_INSN);
+
+ ret = arm_probes_decode_insn(insn, &auprobe->asi, false,
+ uprobes_probes_actions);
+ switch (ret) {
+ case INSN_REJECTED:
+ return -EINVAL;
+
+ case INSN_GOOD_NO_SLOT:
+ auprobe->simulate = true;
+ break;
+
+ case INSN_GOOD:
+ default:
+ break;
+ }
+
+ bpinsn = UPROBE_SWBP_ARM_INSN & 0x0fffffff;
+ if (insn >= 0xe0000000)
+ bpinsn |= 0xe0000000; /* Unconditional instruction */
+ else
+ bpinsn |= insn & 0xf0000000; /* Copy condition from insn */
+
+ auprobe->bpinsn = bpinsn;
+
+ return 0;
+}
+
+int arch_uprobe_pre_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
+{
+ struct uprobe_task *utask = current->utask;
+
+ if (auprobe->prehandler)
+ auprobe->prehandler(auprobe, &utask->autask, regs);
+
+ regs->ARM_pc = utask->xol_vaddr;
+
+ return 0;
+}
+
+int arch_uprobe_post_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
+{
+ struct uprobe_task *utask = current->utask;
+
+ regs->ARM_pc = utask->vaddr + 4;
+
+ if (auprobe->posthandler)
+ auprobe->posthandler(auprobe, &utask->autask, regs);
+
+ return 0;
+}
+
+bool arch_uprobe_xol_was_trapped(struct task_struct *t)
+{
+ /* TODO: implement */
+ return false;
+}
+
+void arch_uprobe_abort_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
+{
+ /* TODO: implement */
+}
+
+int arch_uprobe_exception_notify(struct notifier_block *self,
+ unsigned long val, void *data)
+{
+ return NOTIFY_DONE;
+}
+
+static int uprobe_trap_handler(struct pt_regs *regs, unsigned int instr)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+ instr &= 0x0fffffff;
+ if (instr == (UPROBE_SWBP_ARM_INSN & 0x0fffffff))
+ uprobe_pre_sstep_notifier(regs);
+ else if (instr == (UPROBE_SS_ARM_INSN & 0x0fffffff))
+ uprobe_post_sstep_notifier(regs);
+ local_irq_restore(flags);
+
+ return 0;
+}
+
+unsigned long uprobe_get_swbp_addr(struct pt_regs *regs)
+{
+ return instruction_pointer(regs);
+}
+
+static struct undef_hook uprobes_arm_break_hook = {
+ .instr_mask = 0x0fffffff,
+ .instr_val = (UPROBE_SWBP_ARM_INSN & 0x0fffffff),
+ .cpsr_mask = MODE_MASK,
+ .cpsr_val = USR_MODE,
+ .fn = uprobe_trap_handler,
+};
+
+static struct undef_hook uprobes_arm_ss_hook = {
+ .instr_mask = 0x0fffffff,
+ .instr_val = (UPROBE_SS_ARM_INSN & 0x0fffffff),
+ .cpsr_mask = MODE_MASK,
+ .cpsr_val = USR_MODE,
+ .fn = uprobe_trap_handler,
+};
+
+static int arch_uprobes_init(void)
+{
+ register_undef_hook(&uprobes_arm_break_hook);
+ register_undef_hook(&uprobes_arm_ss_hook);
+
+ return 0;
+}
+device_initcall(arch_uprobes_init);
diff --git a/arch/arm/kernel/uprobes.h b/arch/arm/kernel/uprobes.h
new file mode 100644
index 0000000..1e09b4f
--- /dev/null
+++ b/arch/arm/kernel/uprobes.h
@@ -0,0 +1,27 @@
+#ifndef __ARM_KERNEL_UPROBES_H
+#define __ARM_KERNEL_UPROBES_H
+
+enum probes_insn uprobe_decode_ldmstm(probes_opcode_t insn,
+ struct arch_probes_insn *asi,
+ struct decode_header *d);
+
+enum probes_insn decode_ldr(probes_opcode_t insn,
+ struct arch_probes_insn *asi,
+ struct decode_header *d);
+
+enum probes_insn
+decode_rd12rn16rm0rs8_rwflags(probes_opcode_t insn,
+ struct arch_probes_insn *asi,
+ struct decode_header *d);
+
+enum probes_insn
+decode_wb_pc(probes_opcode_t insn, struct arch_probes_insn *asi,
+ struct decode_header *d, bool alu);
+
+enum probes_insn
+decode_pc_ro(probes_opcode_t insn, struct arch_probes_insn *asi,
+ struct decode_header *d);
+
+extern const union decode_item uprobes_probes_actions[];
+
+#endif
--
1.8.1.2
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH v4 16/16] ARM: Remove uprobes dependency on kprobes
2013-12-16 4:08 [PATCH v4 00/16] uprobes: Add uprobes support for ARM David Long
` (14 preceding siblings ...)
2013-12-16 4:08 ` [PATCH v4 15/16] ARM: add uprobes support David Long
@ 2013-12-16 4:08 ` David Long
15 siblings, 0 replies; 34+ messages in thread
From: David Long @ 2013-12-16 4:08 UTC (permalink / raw)
To: linux-arm-kernel
From: "David A. Long" <dave.long@linaro.org>
Now that arm uprobes support has been made separate from the arm kprobes code
the Kconfig can be changed to reflect that.
Signed-off-by: David A. Long <dave.long@linaro.org>
---
arch/arm/Kconfig | 1 -
1 file changed, 1 deletion(-)
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index fec5a6b..9ddc4ae 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -204,7 +204,6 @@ config NEED_DMA_MAP_STATE
def_bool y
config ARCH_SUPPORTS_UPROBES
- depends on KPROBES
def_bool y
config ARCH_HAS_DMA_SET_COHERENT_MASK
--
1.8.1.2
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH v4 05/16] ARM: use a function table for determining instruction interpreter actions
2013-12-16 4:08 ` [PATCH v4 05/16] ARM: use a function table for determining instruction interpreter actions David Long
@ 2013-12-20 12:45 ` Jon Medhurst (Tixy)
2014-01-15 16:25 ` David Long
0 siblings, 1 reply; 34+ messages in thread
From: Jon Medhurst (Tixy) @ 2013-12-20 12:45 UTC (permalink / raw)
To: linux-arm-kernel
On Sun, 2013-12-15 at 23:08 -0500, David Long wrote:
> From: "David A. Long" <dave.long@linaro.org>
>
> Make the instruction interpreter call back to semantic action functions
> through a function pointer array provided by the invoker. The interpreter
> decodes the instructions into groups and uses the group number to index
> into the supplied array. kprobes and uprobes code will each supply their
> own array of functions.
>
> Signed-off-by: David A. Long <dave.long@linaro.org>
> ---
Because I've been very slow in reviewing these I've only just noticed
that some of the the comments I made on version one of this patch didn't
get a response. I've copied them again below (slightly edited) and
heavily trimmed the patch...
> arch/arm/kernel/kprobes-arm.c | 41 +++++++++++
> arch/arm/kernel/kprobes-common.c | 3 +-
> arch/arm/kernel/kprobes-thumb.c | 92 ++++++++++++++++++------
> arch/arm/kernel/kprobes.c | 10 ++-
> arch/arm/kernel/kprobes.h | 14 ++--
> arch/arm/kernel/probes-arm.c | 114 +++++++++++++++---------------
> arch/arm/kernel/probes-arm.h | 37 ++++++++++
> arch/arm/kernel/probes-thumb.c | 149 +++++++++++++++++++--------------------
> arch/arm/kernel/probes-thumb.h | 14 ++--
> arch/arm/kernel/probes.c | 13 ++--
> arch/arm/kernel/probes.h | 15 ++--
> 11 files changed, 325 insertions(+), 177 deletions(-)
>
> diff --git a/arch/arm/kernel/kprobes-arm.c b/arch/arm/kernel/kprobes-arm.c
> index a359475..ee329ff 100644
> --- a/arch/arm/kernel/kprobes-arm.c
> +++ b/arch/arm/kernel/kprobes-arm.c
> @@ -299,3 +299,44 @@ emulate_rdlo12rdhi16rn0rm8_rwflags_nopc(struct kprobe *p, struct pt_regs *regs)
> regs->uregs[rdhi] = rdhiv;
> regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK);
> }
> +
> +const union decode_item kprobes_arm_actions[] = {
I think it's best if we don't reuse the decode_item type here, this is a
different sort of table so probably best to have it's own union. Also,
if we do that, then decode_item can be simplified as it won't need to
have function pointers in it, i.e. we could end up with...
union decode_action {
kprobe_insn_handler_t *handler;
kprobe_custom_decode_t *decoder;
};
union decode_item {
u32 bits;
const union decode_item *table;
};
typedef enum kprobe_insn (kprobe_custom_decode_t)(kprobe_opcode_t,
struct arch_specific_insn *,
union decode_action *actions);
A second point, I think it would be a good idea to make sure these
action arrays are the size we expect by adding an entry at the end of
the relevant enumeration and using that to set the size of the arrays.
E.g. for this one
enum probes_arm_action {
...
...
NUM_PROBES_ARM_ACTIONS
};
and then use it like:
const union decode_action kprobes_arm_actions[NUM_PROBES_ARM_ACTIONS] = {
That way, we at least make any uninitialised entries are null (I
assume?) which is safer than accidentally indexing beyond the array.
> + [PROBES_EMULATE_NONE] = {.handler = kprobe_emulate_none},
> + [PROBES_SIMULATE_NOP] = {.handler = kprobe_simulate_nop},
> + [PROBES_PRELOAD_IMM] = {.handler = kprobe_simulate_nop},
[...]
> diff --git a/arch/arm/kernel/probes.h b/arch/arm/kernel/probes.h
> index d14d224..2238972 100644
> --- a/arch/arm/kernel/probes.h
> +++ b/arch/arm/kernel/probes.h
> @@ -131,7 +131,8 @@ void __kprobes kprobe_simulate_nop(struct kprobe *p, struct pt_regs *regs);
> void __kprobes kprobe_emulate_none(struct kprobe *p, struct pt_regs *regs);
>
> enum kprobe_insn __kprobes
> -kprobe_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi);
> +kprobe_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi,
> + struct decode_header *h);
>
> /*
> * Test if load/store instructions writeback the address register.
> @@ -334,7 +335,7 @@ struct decode_custom {
>
> #define DECODE_CUSTOM(_mask, _value, _decoder) \
> DECODE_HEADER(DECODE_TYPE_CUSTOM, _mask, _value, 0), \
> - {.decoder = (_decoder)}
> + {.bits = (_decoder)}
>
This third and final comment is probably just bike shedding...
'bits' looks a bit funny here. I've been trying to think of a way of
making it nicer but it's difficult. The actual value is one of three
different enums, so if we were to add another members to decode_item it
would just have to be "int action", at least that would read nicer in
these macros and where it gets read out in probes_decode_insn.
--
Tixy
^ permalink raw reply [flat|nested] 34+ messages in thread
* [PATCH v4 04/16] ARM: move generic thumb instruction parsing code to new files for use by other feature
2013-12-16 4:08 ` [PATCH v4 04/16] ARM: move generic thumb instruction parsing code to new files for use by other feature David Long
@ 2013-12-20 12:46 ` Jon Medhurst (Tixy)
2014-01-15 16:41 ` David Long
0 siblings, 1 reply; 34+ messages in thread
From: Jon Medhurst (Tixy) @ 2013-12-20 12:46 UTC (permalink / raw)
To: linux-arm-kernel
On Sun, 2013-12-15 at 23:08 -0500, David Long wrote:
> From: "David A. Long" <dave.long@linaro.org>
>
> Move the thumb version of the kprobes instruction parsing code into more generic
> files from where it can be used by uprobes and possibly other subsystems. The
> symbol names will be made more generic in a subsequent part of this patchset.
>
> Signed-off-by: David A. Long <dave.long@linaro.org>
> ---
I just have two comments about probes-thumb.h ...
[...]
> diff --git a/arch/arm/kernel/probes-thumb.h b/arch/arm/kernel/probes-thumb.h
> new file mode 100644
> index 0000000..3f39210
> --- /dev/null
> +++ b/arch/arm/kernel/probes-thumb.h
> @@ -0,0 +1,136 @@
> +/*
> + * arch/arm/kernel/probes-arm.h
> + *
> + * Copyright 2013 Linaro Ltd.
> + * Written by: David A. Long
> + *
> + * The code contained herein is licensed under the GNU General Public
> + * License. You may obtain a copy of the GNU General Public License
> + * Version 2 or later at the following locations:
> + *
> + * http://www.opensource.org/licenses/gpl-license.html
> + * http://www.gnu.org/copyleft/gpl.html
> + */
> +
> +#ifndef _ARM_KERNEL_PROBES_THUMB_H
> +#define _ARM_KERNEL_PROBES_THUMB_H
> +
> +/*
> + * True if current instruction is in an IT block.
> + */
> +#define in_it_block(cpsr) ((cpsr & 0x06000c00) != 0x00000000)
> +
> +/*
> + * Return the condition code to check for the currently executing instruction.
> + * This is in ITSTATE<7:4> which is in CPSR<15:12> but is only valid if
> + * in_it_block returns true.
> + */
> +#define current_cond(cpsr) ((cpsr >> 12) & 0xf)
Looks like you forgot to remove above two #defines from kprobes-thumb.c
when you moved them to this header file.
Also...
> +enum probes_t32_action {
> + PROBES_T32_EMULATE_NONE,
> + PROBES_T32_SIMULATE_NOP,
> + PROBES_T32_LDMSTM,
> + PROBES_T32_LDRDSTRD,
> + PROBES_T32_TABLE_BRANCH,
> + PROBES_T32_TST,
> + PROBES_T32_CMP,
> + PROBES_T32_MOV,
> + PROBES_T32_ADDSUB,
> + PROBES_T32_LOGICAL,
> + PROBES_T32_ADDWSUBW_PC,
> + PROBES_T32_ADDWSUBW,
> + PROBES_T32_MOVW,
> + PROBES_T32_SAT,
> + PROBES_T32_BITFIELD,
> + PROBES_T32_SEV,
> + PROBES_T32_WFE,
> + PROBES_T32_MRS,
> + PROBES_T32_BRANCH_COND,
> + PROBES_T32_BRANCH,
> + PROBES_T32_PLDI,
> + PROBES_T32_LDR_LIT,
> + PROBES_T32_LDRSTR,
> + PROBES_T32_SIGN_EXTEND,
> + PROBES_T32_MEDIA,
> + PROBES_T32_REVERSE,
> + PROBES_T32_MUL_ADD,
> + PROBES_T32_MUL_ADD2,
> + PROBES_T32_MUL_ADD_LONG
> +};
> +
> +enum probes_t16_action {
> + PROBES_T16_ADD_SP,
> + PROBES_T16_CBZ,
> + PROBES_T16_SIGN_EXTEND,
> + PROBES_T16_PUSH,
> + PROBES_T16_POP,
> + PROBES_T16_SEV,
> + PROBES_T16_WFE,
> + PROBES_T16_IT,
> + PROBES_T16_CMP,
> + PROBES_T16_ADDSUB,
> + PROBES_T16_LOGICAL,
> + PROBES_T16_BLX,
> + PROBES_T16_HIREGOPS,
> + PROBES_T16_LDR_LIT,
> + PROBES_T16_LDRHSTRH,
> + PROBES_T16_LDRSTR,
> + PROBES_T16_ADR,
> + PROBES_T16_LDMSTM,
> + PROBES_T16_BRANCH_COND,
> + PROBES_T16_BRANCH
> +};
> +
I think the above two enums belong in the next patch in the series, i.e.
"[PATCH v4 05/16] ARM: use a function table for determining instruction
interpreter actions"
--
Tixy
^ permalink raw reply [flat|nested] 34+ messages in thread
* [PATCH v4 02/16] ARM: move shared uprobe/kprobe definitions into new include file
2013-12-16 4:08 ` [PATCH v4 02/16] ARM: move shared uprobe/kprobe definitions into new include file David Long
@ 2013-12-20 12:46 ` Jon Medhurst (Tixy)
2014-01-15 16:43 ` David Long
0 siblings, 1 reply; 34+ messages in thread
From: Jon Medhurst (Tixy) @ 2013-12-20 12:46 UTC (permalink / raw)
To: linux-arm-kernel
On Sun, 2013-12-15 at 23:08 -0500, David Long wrote:
> From: "David A. Long" <dave.long@linaro.org>
>
> Separate the kprobe-only definitions from the definitions needed by
> both kprobes and uprobes.
>
> Signed-off-by: David A. Long <dave.long@linaro.org>
> ---
> arch/arm/include/asm/kprobes.h | 15 +--------------
> arch/arm/include/asm/probes.h | 18 ++++++++++++++++++
> 2 files changed, 19 insertions(+), 14 deletions(-)
> create mode 100644 arch/arm/include/asm/probes.h
>
> diff --git a/arch/arm/include/asm/kprobes.h b/arch/arm/include/asm/kprobes.h
> index f82ec22..30fc11b 100644
> --- a/arch/arm/include/asm/kprobes.h
> +++ b/arch/arm/include/asm/kprobes.h
> @@ -28,21 +28,8 @@
> #define kretprobe_blacklist_size 0
>
> typedef u32 kprobe_opcode_t;
> -
> 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;
> -};
> +#include <asm/probes.h>
>
> struct prev_kprobe {
> struct kprobe *kp;
> diff --git a/arch/arm/include/asm/probes.h b/arch/arm/include/asm/probes.h
> new file mode 100644
> index 0000000..21da148
> --- /dev/null
> +++ b/arch/arm/include/asm/probes.h
> @@ -0,0 +1,18 @@
This new file doesn't have any copyright/license notice, I suggest you
copy the one from kprobes.h and include a note to say this new files
contents were copied, e.g. start it like...
/*
* arch/arm/include/asm/probes.h
*
* Original contents copied from arch/arm/include/asm/kprobes.h
* which contains the following notice...
*
* Copyright (C) 2006, 2007 Motorola Inc.
*
* This program is free software; you can redistribute it and/or modify
[...]
> +#ifndef _ASM_PROBES_H
> +#define _ASM_PROBES_H
> +
> +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;
> +};
> +
> +#endif
^ permalink raw reply [flat|nested] 34+ messages in thread
* [PATCH v4 07/16] ARM: Remove use of struct kprobe from generic probes code
2013-12-16 4:08 ` [PATCH v4 07/16] ARM: Remove use of struct kprobe from generic probes code David Long
@ 2013-12-20 13:55 ` Jon Medhurst (Tixy)
2014-01-15 16:44 ` David Long
0 siblings, 1 reply; 34+ messages in thread
From: Jon Medhurst (Tixy) @ 2013-12-20 13:55 UTC (permalink / raw)
To: linux-arm-kernel
On Sun, 2013-12-15 at 23:08 -0500, David Long wrote:
> From: "David A. Long" <dave.long@linaro.org>
>
> 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>
> ---
> arch/arm/include/asm/probes.h | 9 +-
> arch/arm/kernel/kprobes-arm.c | 77 ++++++-------
> arch/arm/kernel/kprobes-common.c | 42 ++++---
> arch/arm/kernel/kprobes-thumb.c | 239 +++++++++++++++++++--------------------
> arch/arm/kernel/kprobes.c | 2 +-
> arch/arm/kernel/kprobes.h | 2 +-
> arch/arm/kernel/probes-arm.c | 33 +++---
> arch/arm/kernel/probes-arm.h | 29 ++---
> arch/arm/kernel/probes-thumb.c | 18 ++-
> arch/arm/kernel/probes-thumb.h | 51 ---------
> arch/arm/kernel/probes.c | 14 ++-
> arch/arm/kernel/probes.h | 8 +-
> 12 files changed, 246 insertions(+), 278 deletions(-)
Looks OK to me, though it looks like this patch includes some header
file cleanups that should have been part of the previous patch? I.e. all
the changes to probes-thumb.h and probes-arm.h. And also the
re-application of 'static' to functions in kprobes-thumb.c and
kprobes-arm.c.
I'm not sure it's worth the hassle of trying to unpick those changes
though, it doesn't impact the end result or bisect-bility.
--
Tixy
> diff --git a/arch/arm/include/asm/probes.h b/arch/arm/include/asm/probes.h
> index edf5abe..a7b0a79 100644
> --- a/arch/arm/include/asm/probes.h
> +++ b/arch/arm/include/asm/probes.h
> @@ -3,9 +3,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. */
> diff --git a/arch/arm/kernel/kprobes-arm.c b/arch/arm/kernel/kprobes-arm.c
> index ee329ff..394b611 100644
> --- a/arch/arm/kernel/kprobes-arm.c
> +++ b/arch/arm/kernel/kprobes-arm.c
> @@ -72,12 +72,11 @@
> "mov pc, "reg" \n\t"
> #endif
>
> -
> -void __kprobes
> -emulate_ldrdstrd(struct kprobe *p, struct pt_regs *regs)
> +static void __kprobes
> +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;
> @@ -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"
> );
>
> @@ -102,11 +101,11 @@ emulate_ldrdstrd(struct kprobe *p, struct pt_regs *regs)
> regs->uregs[rn] = rnv;
> }
>
> -void __kprobes
> -emulate_ldr(struct kprobe *p, struct pt_regs *regs)
> +static void __kprobes
> +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;
> @@ -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"
> );
>
> @@ -132,12 +131,12 @@ emulate_ldr(struct kprobe *p, struct pt_regs *regs)
> regs->uregs[rn] = rnv;
> }
>
> -void __kprobes
> -emulate_str(struct kprobe *p, struct pt_regs *regs)
> +static void __kprobes
> +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;
> @@ -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"
> );
>
> @@ -159,11 +158,11 @@ emulate_str(struct kprobe *p, struct pt_regs *regs)
> regs->uregs[rn] = rnv;
> }
>
> -void __kprobes
> -emulate_rd12rn16rm0rs8_rwflags(struct kprobe *p, struct pt_regs *regs)
> +static void __kprobes
> +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;
> @@ -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"
> );
>
> @@ -194,10 +193,10 @@ emulate_rd12rn16rm0rs8_rwflags(struct kprobe *p, struct pt_regs *regs)
> regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK);
> }
>
> -void __kprobes
> -emulate_rd12rn16rm0_rwflags_nopc(struct kprobe *p, struct pt_regs *regs)
> +static void __kprobes
> +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;
> @@ -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"
> );
>
> @@ -221,10 +220,11 @@ emulate_rd12rn16rm0_rwflags_nopc(struct kprobe *p, struct pt_regs *regs)
> regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK);
> }
>
> -void __kprobes
> -emulate_rd16rn12rm0rs8_rwflags_nopc(struct kprobe *p, struct pt_regs *regs)
> +static void __kprobes
> +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;
> @@ -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"
> );
>
> @@ -250,10 +250,10 @@ emulate_rd16rn12rm0rs8_rwflags_nopc(struct kprobe *p, struct pt_regs *regs)
> regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK);
> }
>
> -void __kprobes
> -emulate_rd12rm0_noflags_nopc(struct kprobe *p, struct pt_regs *regs)
> +static void __kprobes
> +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;
>
> @@ -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;
> }
>
> -void __kprobes
> -emulate_rdlo12rdhi16rn0rm8_rwflags_nopc(struct kprobe *p, struct pt_regs *regs)
> +static void __kprobes
> +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;
> @@ -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"
> );
>
> diff --git a/arch/arm/kernel/kprobes-common.c b/arch/arm/kernel/kprobes-common.c
> index 554720c..45590a4 100644
> --- a/arch/arm/kernel/kprobes-common.c
> +++ b/arch/arm/kernel/kprobes-common.c
> @@ -18,9 +18,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);
> @@ -59,24 +60,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"
> @@ -100,21 +108,25 @@ 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);
> }
>
> enum kprobe_insn __kprobes
> kprobe_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi,
> - struct decode_header *h)
> + struct decode_header *h)
> {
> kprobe_insn_handler_t *handler = 0;
> unsigned reglist = insn & 0xffff;
> diff --git a/arch/arm/kernel/kprobes-thumb.c b/arch/arm/kernel/kprobes-thumb.c
> index 5990866..d0bbbf7 100644
> --- a/arch/arm/kernel/kprobes-thumb.c
> +++ b/arch/arm/kernel/kprobes-thumb.c
> @@ -19,24 +19,13 @@
> #define t32_emulate_rd8rn16rm0ra12_noflags \
> t32_emulate_rdlo12rdhi8rn16rm0_noflags
>
> -/*
> - * Return the PC value for a probe in thumb code.
> - * This is the address of the probed instruction plus 4.
> - * We subtract one because the address will have bit zero set to indicate
> - * a pointer to thumb code.
> - */
> -static inline unsigned long __kprobes thumb_probe_pc(struct kprobe *p)
> -{
> - return (unsigned long)p->addr - 1 + 4;
> -}
> -
> /* t32 thumb actions */
>
> -void __kprobes
> -t32_simulate_table_branch(struct kprobe *p, struct pt_regs *regs)
> +static void __kprobes
> +t32_simulate_table_branch(kprobe_opcode_t insn,
> + struct arch_specific_insn *asi, struct pt_regs *regs)
> {
> - kprobe_opcode_t insn = p->opcode;
> - unsigned long pc = thumb_probe_pc(p);
> + unsigned long pc = regs->ARM_pc;
> int rn = (insn >> 16) & 0xf;
> int rm = insn & 0xf;
>
> @@ -52,20 +41,20 @@ t32_simulate_table_branch(struct kprobe *p, struct pt_regs *regs)
> regs->ARM_pc = pc + 2 * halfwords;
> }
>
> -void __kprobes
> -t32_simulate_mrs(struct kprobe *p, struct pt_regs *regs)
> +static void __kprobes
> +t32_simulate_mrs(kprobe_opcode_t insn,
> + struct arch_specific_insn *asi, struct pt_regs *regs)
> {
> - kprobe_opcode_t insn = p->opcode;
> int rd = (insn >> 8) & 0xf;
> unsigned long mask = 0xf8ff03df; /* Mask out execution state */
> regs->uregs[rd] = regs->ARM_cpsr & mask;
> }
>
> -void __kprobes
> -t32_simulate_cond_branch(struct kprobe *p, struct pt_regs *regs)
> +static void __kprobes
> +t32_simulate_cond_branch(kprobe_opcode_t insn,
> + struct arch_specific_insn *asi, struct pt_regs *regs)
> {
> - kprobe_opcode_t insn = p->opcode;
> - unsigned long pc = thumb_probe_pc(p);
> + unsigned long pc = regs->ARM_pc;
>
> long offset = insn & 0x7ff; /* imm11 */
> offset += (insn & 0x003f0000) >> 5; /* imm6 */
> @@ -76,7 +65,7 @@ t32_simulate_cond_branch(struct kprobe *p, struct pt_regs *regs)
> regs->ARM_pc = pc + (offset * 2);
> }
>
> -enum kprobe_insn __kprobes
> +static enum kprobe_insn __kprobes
> t32_decode_cond_branch(kprobe_opcode_t insn, struct arch_specific_insn *asi,
> struct decode_header *d)
> {
> @@ -86,11 +75,11 @@ t32_decode_cond_branch(kprobe_opcode_t insn, struct arch_specific_insn *asi,
> return INSN_GOOD_NO_SLOT;
> }
>
> -void __kprobes
> -t32_simulate_branch(struct kprobe *p, struct pt_regs *regs)
> +static void __kprobes
> +t32_simulate_branch(kprobe_opcode_t insn,
> + struct arch_specific_insn *asi, struct pt_regs *regs)
> {
> - kprobe_opcode_t insn = p->opcode;
> - unsigned long pc = thumb_probe_pc(p);
> + unsigned long pc = regs->ARM_pc;
>
> long offset = insn & 0x7ff; /* imm11 */
> offset += (insn & 0x03ff0000) >> 5; /* imm10 */
> @@ -103,7 +92,7 @@ t32_simulate_branch(struct kprobe *p, struct pt_regs *regs)
>
> if (insn & (1 << 14)) {
> /* BL or BLX */
> - regs->ARM_lr = (unsigned long)p->addr + 4;
> + regs->ARM_lr = regs->ARM_pc | 1;
> if (!(insn & (1 << 12))) {
> /* BLX so switch to ARM mode */
> regs->ARM_cpsr &= ~PSR_T_BIT;
> @@ -114,11 +103,11 @@ t32_simulate_branch(struct kprobe *p, struct pt_regs *regs)
> regs->ARM_pc = pc + (offset * 2);
> }
>
> -void __kprobes
> -t32_simulate_ldr_literal(struct kprobe *p, struct pt_regs *regs)
> +static void __kprobes
> +t32_simulate_ldr_literal(kprobe_opcode_t insn,
> + struct arch_specific_insn *asi, struct pt_regs *regs)
> {
> - kprobe_opcode_t insn = p->opcode;
> - unsigned long addr = thumb_probe_pc(p) & ~3;
> + unsigned long addr = regs->ARM_pc & ~3;
> int rt = (insn >> 12) & 0xf;
> unsigned long rtv;
>
> @@ -166,11 +155,11 @@ t32_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi,
> return ret;
> }
>
> -void __kprobes
> -t32_emulate_ldrdstrd(struct kprobe *p, struct pt_regs *regs)
> +static void __kprobes
> +t32_emulate_ldrdstrd(kprobe_opcode_t insn,
> + struct arch_specific_insn *asi, struct pt_regs *regs)
> {
> - kprobe_opcode_t insn = p->opcode;
> - unsigned long pc = thumb_probe_pc(p) & ~3;
> + unsigned long pc = regs->ARM_pc & ~3;
> int rt1 = (insn >> 12) & 0xf;
> int rt2 = (insn >> 8) & 0xf;
> int rn = (insn >> 16) & 0xf;
> @@ -183,7 +172,7 @@ t32_emulate_ldrdstrd(struct kprobe *p, struct pt_regs *regs)
> __asm__ __volatile__ (
> "blx %[fn]"
> : "=r" (rt1v), "=r" (rt2v), "=r" (rnv)
> - : "0" (rt1v), "1" (rt2v), "2" (rnv), [fn] "r" (p->ainsn.insn_fn)
> + : "0" (rt1v), "1" (rt2v), "2" (rnv), [fn] "r" (asi->insn_fn)
> : "lr", "memory", "cc"
> );
>
> @@ -193,10 +182,10 @@ t32_emulate_ldrdstrd(struct kprobe *p, struct pt_regs *regs)
> regs->uregs[rt2] = rt2v;
> }
>
> -void __kprobes
> -t32_emulate_ldrstr(struct kprobe *p, struct pt_regs *regs)
> +static void __kprobes
> +t32_emulate_ldrstr(kprobe_opcode_t insn,
> + struct arch_specific_insn *asi, struct pt_regs *regs)
> {
> - kprobe_opcode_t insn = p->opcode;
> int rt = (insn >> 12) & 0xf;
> int rn = (insn >> 16) & 0xf;
> int rm = insn & 0xf;
> @@ -208,7 +197,7 @@ t32_emulate_ldrstr(struct kprobe *p, struct pt_regs *regs)
> __asm__ __volatile__ (
> "blx %[fn]"
> : "=r" (rtv), "=r" (rnv)
> - : "0" (rtv), "1" (rnv), "r" (rmv), [fn] "r" (p->ainsn.insn_fn)
> + : "0" (rtv), "1" (rnv), "r" (rmv), [fn] "r" (asi->insn_fn)
> : "lr", "memory", "cc"
> );
>
> @@ -219,10 +208,10 @@ t32_emulate_ldrstr(struct kprobe *p, struct pt_regs *regs)
> regs->uregs[rt] = rtv;
> }
>
> -void __kprobes
> -t32_emulate_rd8rn16rm0_rwflags(struct kprobe *p, struct pt_regs *regs)
> +static void __kprobes
> +t32_emulate_rd8rn16rm0_rwflags(kprobe_opcode_t insn,
> + struct arch_specific_insn *asi, struct pt_regs *regs)
> {
> - kprobe_opcode_t insn = p->opcode;
> int rd = (insn >> 8) & 0xf;
> int rn = (insn >> 16) & 0xf;
> int rm = insn & 0xf;
> @@ -238,7 +227,7 @@ t32_emulate_rd8rn16rm0_rwflags(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"
> );
>
> @@ -246,11 +235,11 @@ t32_emulate_rd8rn16rm0_rwflags(struct kprobe *p, struct pt_regs *regs)
> regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK);
> }
>
> -void __kprobes
> -t32_emulate_rd8pc16_noflags(struct kprobe *p, struct pt_regs *regs)
> +static void __kprobes
> +t32_emulate_rd8pc16_noflags(kprobe_opcode_t insn,
> + struct arch_specific_insn *asi, struct pt_regs *regs)
> {
> - kprobe_opcode_t insn = p->opcode;
> - unsigned long pc = thumb_probe_pc(p);
> + unsigned long pc = regs->ARM_pc;
> int rd = (insn >> 8) & 0xf;
>
> register unsigned long rdv asm("r1") = regs->uregs[rd];
> @@ -259,17 +248,17 @@ t32_emulate_rd8pc16_noflags(struct kprobe *p, struct pt_regs *regs)
> __asm__ __volatile__ (
> "blx %[fn]"
> : "=r" (rdv)
> - : "0" (rdv), "r" (rnv), [fn] "r" (p->ainsn.insn_fn)
> + : "0" (rdv), "r" (rnv), [fn] "r" (asi->insn_fn)
> : "lr", "memory", "cc"
> );
>
> regs->uregs[rd] = rdv;
> }
>
> -void __kprobes
> -t32_emulate_rd8rn16_noflags(struct kprobe *p, struct pt_regs *regs)
> +static void __kprobes
> +t32_emulate_rd8rn16_noflags(kprobe_opcode_t insn,
> + struct arch_specific_insn *asi, struct pt_regs *regs)
> {
> - kprobe_opcode_t insn = p->opcode;
> int rd = (insn >> 8) & 0xf;
> int rn = (insn >> 16) & 0xf;
>
> @@ -279,17 +268,18 @@ t32_emulate_rd8rn16_noflags(struct kprobe *p, struct pt_regs *regs)
> __asm__ __volatile__ (
> "blx %[fn]"
> : "=r" (rdv)
> - : "0" (rdv), "r" (rnv), [fn] "r" (p->ainsn.insn_fn)
> + : "0" (rdv), "r" (rnv), [fn] "r" (asi->insn_fn)
> : "lr", "memory", "cc"
> );
>
> regs->uregs[rd] = rdv;
> }
>
> -void __kprobes
> -t32_emulate_rdlo12rdhi8rn16rm0_noflags(struct kprobe *p, struct pt_regs *regs)
> +static void __kprobes
> +t32_emulate_rdlo12rdhi8rn16rm0_noflags(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 >> 8) & 0xf;
> int rn = (insn >> 16) & 0xf;
> @@ -304,7 +294,7 @@ t32_emulate_rdlo12rdhi8rn16rm0_noflags(struct kprobe *p, struct pt_regs *regs)
> "blx %[fn]"
> : "=r" (rdlov), "=r" (rdhiv)
> : "0" (rdlov), "1" (rdhiv), "r" (rnv), "r" (rmv),
> - [fn] "r" (p->ainsn.insn_fn)
> + [fn] "r" (asi->insn_fn)
> : "lr", "memory", "cc"
> );
>
> @@ -313,34 +303,34 @@ t32_emulate_rdlo12rdhi8rn16rm0_noflags(struct kprobe *p, struct pt_regs *regs)
> }
> /* t16 thumb actions */
>
> -void __kprobes
> -t16_simulate_bxblx(struct kprobe *p, struct pt_regs *regs)
> +static void __kprobes
> +t16_simulate_bxblx(kprobe_opcode_t insn,
> + struct arch_specific_insn *asi, struct pt_regs *regs)
> {
> - kprobe_opcode_t insn = p->opcode;
> - unsigned long pc = thumb_probe_pc(p);
> + unsigned long pc = regs->ARM_pc + 2;
> int rm = (insn >> 3) & 0xf;
> unsigned long rmv = (rm == 15) ? pc : regs->uregs[rm];
>
> if (insn & (1 << 7)) /* BLX ? */
> - regs->ARM_lr = (unsigned long)p->addr + 2;
> + regs->ARM_lr = regs->ARM_pc | 1;
>
> bx_write_pc(rmv, regs);
> }
>
> -void __kprobes
> -t16_simulate_ldr_literal(struct kprobe *p, struct pt_regs *regs)
> +static void __kprobes
> +t16_simulate_ldr_literal(kprobe_opcode_t insn,
> + struct arch_specific_insn *asi, struct pt_regs *regs)
> {
> - kprobe_opcode_t insn = p->opcode;
> - unsigned long* base = (unsigned long *)(thumb_probe_pc(p) & ~3);
> + unsigned long *base = (unsigned long *)((regs->ARM_pc + 2) & ~3);
> long index = insn & 0xff;
> int rt = (insn >> 8) & 0x7;
> regs->uregs[rt] = base[index];
> }
>
> -void __kprobes
> -t16_simulate_ldrstr_sp_relative(struct kprobe *p, struct pt_regs *regs)
> +static void __kprobes
> +t16_simulate_ldrstr_sp_relative(kprobe_opcode_t insn,
> + struct arch_specific_insn *asi, struct pt_regs *regs)
> {
> - kprobe_opcode_t insn = p->opcode;
> unsigned long* base = (unsigned long *)regs->ARM_sp;
> long index = insn & 0xff;
> int rt = (insn >> 8) & 0x7;
> @@ -350,21 +340,21 @@ t16_simulate_ldrstr_sp_relative(struct kprobe *p, struct pt_regs *regs)
> base[index] = regs->uregs[rt];
> }
>
> -void __kprobes
> -t16_simulate_reladr(struct kprobe *p, struct pt_regs *regs)
> +static void __kprobes
> +t16_simulate_reladr(kprobe_opcode_t insn,
> + struct arch_specific_insn *asi, struct pt_regs *regs)
> {
> - kprobe_opcode_t insn = p->opcode;
> unsigned long base = (insn & 0x800) ? regs->ARM_sp
> - : (thumb_probe_pc(p) & ~3);
> + : ((regs->ARM_pc + 2) & ~3);
> long offset = insn & 0xff;
> int rt = (insn >> 8) & 0x7;
> regs->uregs[rt] = base + offset * 4;
> }
>
> -void __kprobes
> -t16_simulate_add_sp_imm(struct kprobe *p, struct pt_regs *regs)
> +static void __kprobes
> +t16_simulate_add_sp_imm(kprobe_opcode_t insn,
> + struct arch_specific_insn *asi, struct pt_regs *regs)
> {
> - kprobe_opcode_t insn = p->opcode;
> long imm = insn & 0x7f;
> if (insn & 0x80) /* SUB */
> regs->ARM_sp -= imm * 4;
> @@ -372,22 +362,23 @@ t16_simulate_add_sp_imm(struct kprobe *p, struct pt_regs *regs)
> regs->ARM_sp += imm * 4;
> }
>
> -void __kprobes
> -t16_simulate_cbz(struct kprobe *p, struct pt_regs *regs)
> +static void __kprobes
> +t16_simulate_cbz(kprobe_opcode_t insn,
> + struct arch_specific_insn *asi, struct pt_regs *regs)
> {
> - kprobe_opcode_t insn = p->opcode;
> int rn = insn & 0x7;
> kprobe_opcode_t nonzero = regs->uregs[rn] ? insn : ~insn;
> if (nonzero & 0x800) {
> long i = insn & 0x200;
> long imm5 = insn & 0xf8;
> - unsigned long pc = thumb_probe_pc(p);
> + unsigned long pc = regs->ARM_pc + 2;
> regs->ARM_pc = pc + (i >> 3) + (imm5 >> 2);
> }
> }
>
> -void __kprobes
> -t16_simulate_it(struct kprobe *p, struct pt_regs *regs)
> +static void __kprobes
> +t16_simulate_it(kprobe_opcode_t insn,
> + struct arch_specific_insn *asi, struct pt_regs *regs)
> {
> /*
> * The 8 IT state bits are split into two parts in CPSR:
> @@ -395,7 +386,6 @@ t16_simulate_it(struct kprobe *p, struct pt_regs *regs)
> * ITSTATE<7:2> are in CPSR<15:10>
> * The new IT state is in the lower byte of insn.
> */
> - kprobe_opcode_t insn = p->opcode;
> unsigned long cpsr = regs->ARM_cpsr;
> cpsr &= ~PSR_IT_MASK;
> cpsr |= (insn & 0xfc) << 8;
> @@ -403,14 +393,15 @@ t16_simulate_it(struct kprobe *p, struct pt_regs *regs)
> regs->ARM_cpsr = cpsr;
> }
>
> -void __kprobes
> -t16_singlestep_it(struct kprobe *p, struct pt_regs *regs)
> +static void __kprobes
> +t16_singlestep_it(kprobe_opcode_t insn,
> + struct arch_specific_insn *asi, struct pt_regs *regs)
> {
> regs->ARM_pc += 2;
> - t16_simulate_it(p, regs);
> + t16_simulate_it(insn, asi, regs);
> }
>
> -enum kprobe_insn __kprobes
> +static enum kprobe_insn __kprobes
> t16_decode_it(kprobe_opcode_t insn, struct arch_specific_insn *asi,
> struct decode_header *d)
> {
> @@ -418,17 +409,17 @@ t16_decode_it(kprobe_opcode_t insn, struct arch_specific_insn *asi,
> return INSN_GOOD_NO_SLOT;
> }
>
> -void __kprobes
> -t16_simulate_cond_branch(struct kprobe *p, struct pt_regs *regs)
> +static void __kprobes
> +t16_simulate_cond_branch(kprobe_opcode_t insn,
> + struct arch_specific_insn *asi, struct pt_regs *regs)
> {
> - kprobe_opcode_t insn = p->opcode;
> - unsigned long pc = thumb_probe_pc(p);
> + unsigned long pc = regs->ARM_pc + 2;
> long offset = insn & 0x7f;
> offset -= insn & 0x80; /* Apply sign bit */
> regs->ARM_pc = pc + (offset * 2);
> }
>
> -enum kprobe_insn __kprobes
> +static enum kprobe_insn __kprobes
> t16_decode_cond_branch(kprobe_opcode_t insn, struct arch_specific_insn *asi,
> struct decode_header *d)
> {
> @@ -438,18 +429,19 @@ t16_decode_cond_branch(kprobe_opcode_t insn, struct arch_specific_insn *asi,
> return INSN_GOOD_NO_SLOT;
> }
>
> -void __kprobes
> -t16_simulate_branch(struct kprobe *p, struct pt_regs *regs)
> +static void __kprobes
> +t16_simulate_branch(kprobe_opcode_t insn,
> + struct arch_specific_insn *asi, struct pt_regs *regs)
> {
> - kprobe_opcode_t insn = p->opcode;
> - unsigned long pc = thumb_probe_pc(p);
> + unsigned long pc = regs->ARM_pc + 2;
> long offset = insn & 0x3ff;
> offset -= insn & 0x400; /* Apply sign bit */
> regs->ARM_pc = pc + (offset * 2);
> }
>
> static unsigned long __kprobes
> -t16_emulate_loregs(struct kprobe *p, struct pt_regs *regs)
> +t16_emulate_loregs(kprobe_opcode_t insn,
> + struct arch_specific_insn *asi, struct pt_regs *regs)
> {
> unsigned long oldcpsr = regs->ARM_cpsr;
> unsigned long newcpsr;
> @@ -462,7 +454,7 @@ t16_emulate_loregs(struct kprobe *p, struct pt_regs *regs)
> "mrs %[newcpsr], cpsr \n\t"
> : [newcpsr] "=r" (newcpsr)
> : [oldcpsr] "r" (oldcpsr), [regs] "r" (regs),
> - [fn] "r" (p->ainsn.insn_fn)
> + [fn] "r" (asi->insn_fn)
> : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
> "lr", "memory", "cc"
> );
> @@ -470,25 +462,27 @@ t16_emulate_loregs(struct kprobe *p, struct pt_regs *regs)
> return (oldcpsr & ~APSR_MASK) | (newcpsr & APSR_MASK);
> }
>
> -void __kprobes
> -t16_emulate_loregs_rwflags(struct kprobe *p, struct pt_regs *regs)
> +static void __kprobes
> +t16_emulate_loregs_rwflags(kprobe_opcode_t insn,
> + struct arch_specific_insn *asi, struct pt_regs *regs)
> {
> - regs->ARM_cpsr = t16_emulate_loregs(p, regs);
> + regs->ARM_cpsr = t16_emulate_loregs(insn, asi, regs);
> }
>
> -void __kprobes
> -t16_emulate_loregs_noitrwflags(struct kprobe *p, struct pt_regs *regs)
> +static void __kprobes
> +t16_emulate_loregs_noitrwflags(kprobe_opcode_t insn,
> + struct arch_specific_insn *asi, struct pt_regs *regs)
> {
> - unsigned long cpsr = t16_emulate_loregs(p, regs);
> + unsigned long cpsr = t16_emulate_loregs(insn, asi, regs);
> if (!in_it_block(cpsr))
> regs->ARM_cpsr = cpsr;
> }
>
> -void __kprobes
> -t16_emulate_hiregs(struct kprobe *p, struct pt_regs *regs)
> +static void __kprobes
> +t16_emulate_hiregs(kprobe_opcode_t insn,
> + struct arch_specific_insn *asi, struct pt_regs *regs)
> {
> - kprobe_opcode_t insn = p->opcode;
> - unsigned long pc = thumb_probe_pc(p);
> + unsigned long pc = regs->ARM_pc + 2;
> int rdn = (insn & 0x7) | ((insn & 0x80) >> 4);
> int rm = (insn >> 3) & 0xf;
>
> @@ -504,7 +498,7 @@ t16_emulate_hiregs(struct kprobe *p, struct pt_regs *regs)
> "blx %[fn] \n\t"
> "mrs %[cpsr], cpsr \n\t"
> : "=r" (rdnv), [cpsr] "=r" (cpsr)
> - : "0" (rdnv), "r" (rmv), "1" (cpsr), [fn] "r" (p->ainsn.insn_fn)
> + : "0" (rdnv), "r" (rmv), "1" (cpsr), [fn] "r" (asi->insn_fn)
> : "lr", "memory", "cc"
> );
>
> @@ -515,7 +509,7 @@ t16_emulate_hiregs(struct kprobe *p, struct pt_regs *regs)
> regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK);
> }
>
> -enum kprobe_insn __kprobes
> +static enum kprobe_insn __kprobes
> t16_decode_hiregs(kprobe_opcode_t insn, struct arch_specific_insn *asi,
> struct decode_header *d)
> {
> @@ -526,8 +520,9 @@ t16_decode_hiregs(kprobe_opcode_t insn, struct arch_specific_insn *asi,
> return INSN_GOOD;
> }
>
> -void __kprobes
> -t16_emulate_push(struct kprobe *p, struct pt_regs *regs)
> +static void __kprobes
> +t16_emulate_push(kprobe_opcode_t insn,
> + struct arch_specific_insn *asi, struct pt_regs *regs)
> {
> __asm__ __volatile__ (
> "ldr r9, [%[regs], #13*4] \n\t"
> @@ -536,13 +531,13 @@ t16_emulate_push(struct kprobe *p, struct pt_regs *regs)
> "blx %[fn] \n\t"
> "str r9, [%[regs], #13*4] \n\t"
> :
> - : [regs] "r" (regs), [fn] "r" (p->ainsn.insn_fn)
> + : [regs] "r" (regs), [fn] "r" (asi->insn_fn)
> : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9",
> "lr", "memory", "cc"
> );
> }
>
> -enum kprobe_insn __kprobes
> +static enum kprobe_insn __kprobes
> t16_decode_push(kprobe_opcode_t insn, struct arch_specific_insn *asi,
> struct decode_header *d)
> {
> @@ -557,8 +552,9 @@ t16_decode_push(kprobe_opcode_t insn, struct arch_specific_insn *asi,
> return INSN_GOOD;
> }
>
> -void __kprobes
> -t16_emulate_pop_nopc(struct kprobe *p, struct pt_regs *regs)
> +static void __kprobes
> +t16_emulate_pop_nopc(kprobe_opcode_t insn,
> + struct arch_specific_insn *asi, struct pt_regs *regs)
> {
> __asm__ __volatile__ (
> "ldr r9, [%[regs], #13*4] \n\t"
> @@ -567,14 +563,15 @@ t16_emulate_pop_nopc(struct kprobe *p, struct pt_regs *regs)
> "stmia %[regs], {r0-r7} \n\t"
> "str r9, [%[regs], #13*4] \n\t"
> :
> - : [regs] "r" (regs), [fn] "r" (p->ainsn.insn_fn)
> + : [regs] "r" (regs), [fn] "r" (asi->insn_fn)
> : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r9",
> "lr", "memory", "cc"
> );
> }
>
> -void __kprobes
> -t16_emulate_pop_pc(struct kprobe *p, struct pt_regs *regs)
> +static void __kprobes
> +t16_emulate_pop_pc(kprobe_opcode_t insn,
> + struct arch_specific_insn *asi, struct pt_regs *regs)
> {
> register unsigned long pc asm("r8");
>
> @@ -585,7 +582,7 @@ t16_emulate_pop_pc(struct kprobe *p, struct pt_regs *regs)
> "stmia %[regs], {r0-r7} \n\t"
> "str r9, [%[regs], #13*4] \n\t"
> : "=r" (pc)
> - : [regs] "r" (regs), [fn] "r" (p->ainsn.insn_fn)
> + : [regs] "r" (regs), [fn] "r" (asi->insn_fn)
> : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r9",
> "lr", "memory", "cc"
> );
> diff --git a/arch/arm/kernel/kprobes.c b/arch/arm/kernel/kprobes.c
> index a18b4ca..19c55aa 100644
> --- a/arch/arm/kernel/kprobes.c
> +++ b/arch/arm/kernel/kprobes.c
> @@ -203,7 +203,7 @@ singlestep_skip(struct kprobe *p, struct pt_regs *regs)
> static inline void __kprobes
> singlestep(struct kprobe *p, struct pt_regs *regs, struct kprobe_ctlblk *kcb)
> {
> - p->ainsn.insn_singlestep(p, regs);
> + p->ainsn.insn_singlestep(p->opcode, &p->ainsn, regs);
> }
>
> /*
> diff --git a/arch/arm/kernel/kprobes.h b/arch/arm/kernel/kprobes.h
> index 5ce81dc..6c1ed3c 100644
> --- a/arch/arm/kernel/kprobes.h
> +++ b/arch/arm/kernel/kprobes.h
> @@ -37,7 +37,7 @@ enum kprobe_insn {
>
> typedef enum kprobe_insn (kprobe_decode_insn_t)(kprobe_opcode_t,
> struct arch_specific_insn *,
> - struct decode_header *actions);
> + struct decode_header *);
>
> #ifdef CONFIG_THUMB2_KERNEL
>
> diff --git a/arch/arm/kernel/probes-arm.c b/arch/arm/kernel/probes-arm.c
> index 665cd0d..3aba9c3 100644
> --- a/arch/arm/kernel/probes-arm.c
> +++ b/arch/arm/kernel/probes-arm.c
> @@ -18,8 +18,7 @@
> #include <linux/compiler.h>
> #include <linux/kernel.h>
>
> -#include <linux/kprobes.h>
> -#include "kprobes.h"
> +#include "probes.h"
> #include "probes-arm.h"
>
> #define sign_extend(x, signbit) ((x) | (0 - ((x) & (1 << (signbit)))))
> @@ -56,10 +55,10 @@
> * read and write of flags.
> */
>
> -void __kprobes simulate_bbl(struct kprobe *p, struct pt_regs *regs)
> +void __kprobes simulate_bbl(kprobe_opcode_t insn,
> + struct arch_specific_insn *asi, struct pt_regs *regs)
> {
> - kprobe_opcode_t insn = p->opcode;
> - long iaddr = (long)p->addr;
> + long iaddr = (long) regs->ARM_pc - 4;
> int disp = branch_displacement(insn);
>
> if (insn & (1 << 24))
> @@ -68,10 +67,10 @@ void __kprobes simulate_bbl(struct kprobe *p, struct pt_regs *regs)
> regs->ARM_pc = iaddr + 8 + disp;
> }
>
> -void __kprobes simulate_blx1(struct kprobe *p, struct pt_regs *regs)
> +void __kprobes simulate_blx1(kprobe_opcode_t insn,
> + struct arch_specific_insn *asi, struct pt_regs *regs)
> {
> - kprobe_opcode_t insn = p->opcode;
> - long iaddr = (long)p->addr;
> + long iaddr = (long) regs->ARM_pc - 4;
> int disp = branch_displacement(insn);
>
> regs->ARM_lr = iaddr + 4;
> @@ -79,14 +78,14 @@ void __kprobes simulate_blx1(struct kprobe *p, struct pt_regs *regs)
> regs->ARM_cpsr |= PSR_T_BIT;
> }
>
> -void __kprobes simulate_blx2bx(struct kprobe *p, struct pt_regs *regs)
> +void __kprobes simulate_blx2bx(kprobe_opcode_t insn,
> + struct arch_specific_insn *asi, struct pt_regs *regs)
> {
> - kprobe_opcode_t insn = p->opcode;
> int rm = insn & 0xf;
> long rmv = regs->uregs[rm];
>
> if (insn & (1 << 5))
> - regs->ARM_lr = (long)p->addr + 4;
> + regs->ARM_lr = (long) regs->ARM_pc;
>
> regs->ARM_pc = rmv & ~0x1;
> regs->ARM_cpsr &= ~PSR_T_BIT;
> @@ -94,15 +93,16 @@ void __kprobes simulate_blx2bx(struct kprobe *p, struct pt_regs *regs)
> regs->ARM_cpsr |= PSR_T_BIT;
> }
>
> -void __kprobes simulate_mrs(struct kprobe *p, struct pt_regs *regs)
> +void __kprobes simulate_mrs(kprobe_opcode_t insn,
> + struct arch_specific_insn *asi, struct pt_regs *regs)
> {
> - kprobe_opcode_t insn = p->opcode;
> int rd = (insn >> 12) & 0xf;
> unsigned long mask = 0xf8ff03df; /* Mask out execution state */
> regs->uregs[rd] = regs->ARM_cpsr & mask;
> }
>
> -void __kprobes simulate_mov_ipsp(struct kprobe *p, struct pt_regs *regs)
> +void __kprobes simulate_mov_ipsp(kprobe_opcode_t insn,
> + struct arch_specific_insn *asi, struct pt_regs *regs)
> {
> regs->uregs[12] = regs->uregs[13];
> }
> @@ -702,10 +702,11 @@ const union decode_item kprobe_decode_arm_table[] = {
> EXPORT_SYMBOL_GPL(kprobe_decode_arm_table);
> #endif
>
> -static void __kprobes arm_singlestep(struct kprobe *p, struct pt_regs *regs)
> +static void __kprobes arm_singlestep(kprobe_opcode_t insn,
> + struct arch_specific_insn *asi, struct pt_regs *regs)
> {
> regs->ARM_pc += 4;
> - p->ainsn.insn_handler(p, regs);
> + asi->insn_handler(insn, asi, regs);
> }
>
> /* Return:
> diff --git a/arch/arm/kernel/probes-arm.h b/arch/arm/kernel/probes-arm.h
> index f8e0f7a..2c9e841 100644
> --- a/arch/arm/kernel/probes-arm.h
> +++ b/arch/arm/kernel/probes-arm.h
> @@ -52,24 +52,15 @@ enum probes_arm_action {
> PROBES_LDMSTM
> };
>
> -void __kprobes simulate_bbl(struct kprobe *p, struct pt_regs *regs);
> -void __kprobes simulate_blx1(struct kprobe *p, struct pt_regs *regs);
> -void __kprobes simulate_blx2bx(struct kprobe *p, struct pt_regs *regs);
> -void __kprobes simulate_mrs(struct kprobe *p, struct pt_regs *regs);
> -void __kprobes simulate_mov_ipsp(struct kprobe *p, struct pt_regs *regs);
> -
> -void __kprobes emulate_ldrdstrd(struct kprobe *p, struct pt_regs *regs);
> -void __kprobes emulate_ldr(struct kprobe *p, struct pt_regs *regs);
> -void __kprobes emulate_str(struct kprobe *p, struct pt_regs *regs);
> -void __kprobes emulate_rd12rn16rm0rs8_rwflags(struct kprobe *p,
> - struct pt_regs *regs);
> -void __kprobes emulate_rd12rn16rm0_rwflags_nopc(struct kprobe *p,
> - struct pt_regs *regs);
> -void __kprobes emulate_rd16rn12rm0rs8_rwflags_nopc(struct kprobe *p,
> - struct pt_regs *regs);
> -void __kprobes emulate_rd12rm0_noflags_nopc(struct kprobe *p,
> - struct pt_regs *regs);
> -void __kprobes emulate_rdlo12rdhi16rn0rm8_rwflags_nopc(struct kprobe *p,
> - struct pt_regs *regs);
> +void __kprobes simulate_bbl(kprobe_opcode_t opcode,
> + struct arch_specific_insn *asi, struct pt_regs *regs);
> +void __kprobes simulate_blx1(kprobe_opcode_t opcode,
> + struct arch_specific_insn *asi, struct pt_regs *regs);
> +void __kprobes simulate_blx2bx(kprobe_opcode_t opcode,
> + struct arch_specific_insn *asi, struct pt_regs *regs);
> +void __kprobes simulate_mrs(kprobe_opcode_t opcode,
> + struct arch_specific_insn *asi, struct pt_regs *regs);
> +void __kprobes simulate_mov_ipsp(kprobe_opcode_t opcode,
> + struct arch_specific_insn *asi, struct pt_regs *regs);
>
> #endif
> diff --git a/arch/arm/kernel/probes-thumb.c b/arch/arm/kernel/probes-thumb.c
> index bf2f1e9..fb79dd9 100644
> --- a/arch/arm/kernel/probes-thumb.c
> +++ b/arch/arm/kernel/probes-thumb.c
> @@ -9,10 +9,9 @@
> */
>
> #include <linux/kernel.h>
> -#include <linux/kprobes.h>
> #include <linux/module.h>
>
> -#include "kprobes.h"
> +#include "probes.h"
> #include "probes-thumb.h"
>
>
> @@ -831,6 +830,9 @@ const union decode_item kprobe_decode_thumb16_table[] = {
>
> DECODE_END
> };
> +#ifdef CONFIG_ARM_KPROBES_TEST_MODULE
> +EXPORT_SYMBOL_GPL(kprobe_decode_thumb16_table);
> +#endif
>
> static unsigned long __kprobes thumb_check_cc(unsigned long cpsr)
> {
> @@ -839,17 +841,21 @@ static unsigned long __kprobes thumb_check_cc(unsigned long cpsr)
> return true;
> }
>
> -static void __kprobes thumb16_singlestep(struct kprobe *p, struct pt_regs *regs)
> +static void __kprobes thumb16_singlestep(kprobe_opcode_t opcode,
> + struct arch_specific_insn *asi,
> + struct pt_regs *regs)
> {
> regs->ARM_pc += 2;
> - p->ainsn.insn_handler(p, regs);
> + asi->insn_handler(opcode, asi, regs);
> regs->ARM_cpsr = it_advance(regs->ARM_cpsr);
> }
>
> -static void __kprobes thumb32_singlestep(struct kprobe *p, struct pt_regs *regs)
> +static void __kprobes thumb32_singlestep(kprobe_opcode_t opcode,
> + struct arch_specific_insn *asi,
> + struct pt_regs *regs)
> {
> regs->ARM_pc += 4;
> - p->ainsn.insn_handler(p, regs);
> + asi->insn_handler(opcode, asi, regs);
> regs->ARM_cpsr = it_advance(regs->ARM_cpsr);
> }
>
> diff --git a/arch/arm/kernel/probes-thumb.h b/arch/arm/kernel/probes-thumb.h
> index 381ad3a..f024a4c 100644
> --- a/arch/arm/kernel/probes-thumb.h
> +++ b/arch/arm/kernel/probes-thumb.h
> @@ -82,55 +82,4 @@ enum probes_t16_action {
> PROBES_T16_BRANCH
> };
>
> -void __kprobes t16_simulate_bxblx(struct kprobe *p, struct pt_regs *regs);
> -void __kprobes t16_simulate_ldr_literal(struct kprobe *p, struct pt_regs *regs);
> -void __kprobes t16_simulate_ldrstr_sp_relative(struct kprobe *p,
> - struct pt_regs *regs);
> -void __kprobes t16_simulate_reladr(struct kprobe *p, struct pt_regs *regs);
> -void __kprobes t16_simulate_add_sp_imm(struct kprobe *p, struct pt_regs *regs);
> -void __kprobes t16_simulate_cbz(struct kprobe *p, struct pt_regs *regs);
> -void __kprobes t16_simulate_it(struct kprobe *p, struct pt_regs *regs);
> -void __kprobes t16_singlestep_it(struct kprobe *p, struct pt_regs *regs);
> -enum kprobe_insn __kprobes t16_decode_it(kprobe_opcode_t insn,
> - struct arch_specific_insn *asi, struct decode_header *d);
> -void __kprobes t16_simulate_cond_branch(struct kprobe *p, struct pt_regs *regs);
> -enum kprobe_insn __kprobes t16_decode_cond_branch(kprobe_opcode_t insn,
> - struct arch_specific_insn *asi, struct decode_header *d);
> -void __kprobes t16_simulate_branch(struct kprobe *p, struct pt_regs *regs);
> -void __kprobes t16_emulate_loregs_rwflags(struct kprobe *p,
> - struct pt_regs *regs);
> -void __kprobes t16_emulate_loregs_noitrwflags(struct kprobe *p,
> - struct pt_regs *regs);
> -void __kprobes t16_emulate_hiregs(struct kprobe *p, struct pt_regs *regs);
> -enum kprobe_insn __kprobes t16_decode_hiregs(kprobe_opcode_t insn,
> - struct arch_specific_insn *asi, struct decode_header *d);
> -void __kprobes t16_emulate_push(struct kprobe *p, struct pt_regs *regs);
> -enum kprobe_insn __kprobes t16_decode_push(kprobe_opcode_t insn,
> - struct arch_specific_insn *asi, struct decode_header *d);
> -void __kprobes t16_emulate_pop_nopc(struct kprobe *p, struct pt_regs *regs);
> -void __kprobes t16_emulate_pop_pc(struct kprobe *p, struct pt_regs *regs);
> -enum kprobe_insn __kprobes t16_decode_pop(kprobe_opcode_t insn,
> - struct arch_specific_insn *asi, struct decode_header *d);
> -
> -void __kprobes t32_simulate_table_branch(struct kprobe *p,
> - struct pt_regs *regs);
> -void __kprobes t32_simulate_mrs(struct kprobe *p, struct pt_regs *regs);
> -void __kprobes t32_simulate_cond_branch(struct kprobe *p, struct pt_regs *regs);
> -enum kprobe_insn __kprobes t32_decode_cond_branch(kprobe_opcode_t insn,
> - struct arch_specific_insn *asi, struct decode_header *d);
> -void __kprobes t32_simulate_branch(struct kprobe *p, struct pt_regs *regs);
> -void __kprobes t32_simulate_ldr_literal(struct kprobe *p, struct pt_regs *regs);
> -enum kprobe_insn __kprobes t32_decode_ldmstm(kprobe_opcode_t insn,
> - struct arch_specific_insn *asi, struct decode_header *d);
> -void __kprobes t32_emulate_ldrdstrd(struct kprobe *p, struct pt_regs *regs);
> -void __kprobes t32_emulate_ldrstr(struct kprobe *p, struct pt_regs *regs);
> -void __kprobes t32_emulate_rd8rn16rm0_rwflags(struct kprobe *p,
> - struct pt_regs *regs);
> -void __kprobes t32_emulate_rd8pc16_noflags(struct kprobe *p,
> - struct pt_regs *regs);
> -void __kprobes t32_emulate_rd8rn16_noflags(struct kprobe *p,
> - struct pt_regs *regs);
> -void __kprobes t32_emulate_rdlo12rdhi8rn16rm0_noflags(struct kprobe *p,
> - struct pt_regs *regs);
> -
> #endif
> diff --git a/arch/arm/kernel/probes.c b/arch/arm/kernel/probes.c
> index 1bcf5da..b2db250 100644
> --- a/arch/arm/kernel/probes.c
> +++ b/arch/arm/kernel/probes.c
> @@ -12,11 +12,9 @@
> */
>
> #include <linux/kernel.h>
> -#include <linux/kprobes.h>
> #include <asm/system_info.h>
>
> -#include "kprobes.h"
> -
> +#include "probes.h"
>
> #ifndef find_str_pc_offset
>
> @@ -173,13 +171,17 @@ kprobe_check_cc * const kprobe_condition_checks[16] = {
> };
>
>
> -void __kprobes kprobe_simulate_nop(struct kprobe *p, struct pt_regs *regs)
> +void __kprobes kprobe_simulate_nop(kprobe_opcode_t opcode,
> + struct arch_specific_insn *asi,
> + struct pt_regs *regs)
> {
> }
>
> -void __kprobes kprobe_emulate_none(struct kprobe *p, struct pt_regs *regs)
> +void __kprobes kprobe_emulate_none(kprobe_opcode_t opcode,
> + struct arch_specific_insn *asi,
> + struct pt_regs *regs)
> {
> - p->ainsn.insn_fn();
> + asi->insn_fn();
> }
>
> /*
> diff --git a/arch/arm/kernel/probes.h b/arch/arm/kernel/probes.h
> index 2238972..45151a1 100644
> --- a/arch/arm/kernel/probes.h
> +++ b/arch/arm/kernel/probes.h
> @@ -20,6 +20,7 @@
> #define _ARM_KERNEL_PROBES_H
>
> #include <linux/kprobes.h>
> +#include "kprobes.h"
>
> #if __LINUX_ARM_ARCH__ >= 7
>
> @@ -35,6 +36,7 @@ void __init find_str_pc_offset(void);
>
> #endif
>
> +struct decode_header;
>
> /*
> * Update ITSTATE after normal execution of an IT block instruction.
> @@ -127,8 +129,10 @@ static inline void __kprobes alu_write_pc(long pcv, struct pt_regs *regs)
> }
>
>
> -void __kprobes kprobe_simulate_nop(struct kprobe *p, struct pt_regs *regs);
> -void __kprobes kprobe_emulate_none(struct kprobe *p, struct pt_regs *regs);
> +void __kprobes kprobe_simulate_nop(kprobe_opcode_t, struct arch_specific_insn *,
> + struct pt_regs *regs);
> +void __kprobes kprobe_emulate_none(kprobe_opcode_t, struct arch_specific_insn *,
> + struct pt_regs *regs);
>
> enum kprobe_insn __kprobes
> kprobe_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi,
^ permalink raw reply [flat|nested] 34+ messages in thread
* [PATCH v4 13/16] ARM: Add an emulate flag to the kprobes/uprobes instruction decode functions
2013-12-16 4:08 ` [PATCH v4 13/16] ARM: Add an emulate flag to the kprobes/uprobes instruction decode functions David Long
@ 2013-12-20 14:58 ` Jon Medhurst (Tixy)
2014-01-15 19:31 ` David Long
0 siblings, 1 reply; 34+ messages in thread
From: Jon Medhurst (Tixy) @ 2013-12-20 14:58 UTC (permalink / raw)
To: linux-arm-kernel
On Sun, 2013-12-15 at 23:08 -0500, David Long wrote:
> From: "David A. Long" <dave.long@linaro.org>
>
> Add an emulate flag into the instruction interpreter, primarily for uprobes
> support.
>
> Signed-off-by: David A. Long <dave.long@linaro.org>
> ---
> arch/arm/kernel/kprobes.c | 3 ++-
> arch/arm/kernel/kprobes.h | 1 +
> arch/arm/kernel/probes-arm.c | 4 ++--
> arch/arm/kernel/probes-arm.h | 2 +-
> arch/arm/kernel/probes-thumb.c | 8 ++++----
> arch/arm/kernel/probes-thumb.h | 4 ++--
> arch/arm/kernel/probes.c | 32 +++++++++++++++++++++++---------
> arch/arm/kernel/probes.h | 2 +-
> 8 files changed, 36 insertions(+), 20 deletions(-)
>
> diff --git a/arch/arm/kernel/kprobes.c b/arch/arm/kernel/kprobes.c
> index 0d9d49b..04690f9 100644
> --- a/arch/arm/kernel/kprobes.c
> +++ b/arch/arm/kernel/kprobes.c
> @@ -87,7 +87,8 @@ 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)) {
Any reason why the function args need splitting over two lines?
> case INSN_REJECTED: /* not supported */
> return -EINVAL;
>
[...]
> --- a/arch/arm/kernel/probes.c
> +++ b/arch/arm/kernel/probes.c
> @@ -193,7 +193,7 @@ void __kprobes probes_emulate_none(probes_opcode_t opcode,
> */
> static probes_opcode_t __kprobes
> prepare_emulated_insn(probes_opcode_t insn, struct arch_specific_insn *asi,
> - bool thumb)
> + bool thumb)
Seems like a spurious indentation change.
> {
> #ifdef CONFIG_THUMB2_KERNEL
> if (thumb) {
> @@ -218,7 +218,7 @@ prepare_emulated_insn(probes_opcode_t insn, struct arch_specific_insn *asi,
> */
> static void __kprobes
> set_emulated_insn(probes_opcode_t insn, struct arch_specific_insn *asi,
> - bool thumb)
> + bool thumb)
Another spurious whitespace change.
> {
> #ifdef CONFIG_THUMB2_KERNEL
> if (thumb) {
> @@ -253,7 +253,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 */
> @@ -317,9 +317,16 @@ static bool __kprobes decode_regs(probes_opcode_t *pinsn, u32 regs)
> /* Replace value of nibble with new register number... */
> insn &= ~mask;
> insn |= new_bits & mask;
> + if (modify) {
> + /* Replace value of nibble with new register number */
> + insn &= ~mask;
> + insn |= new_bits & mask;
> + }
Huh? As is, the above addition doesn't do anything because insn has
already been modified. I guess you played with the idea that you needed
to avoid changing insn (you don't) and then didn't undo the experiment
quite right. :-)
> }
>
> - *pinsn = insn;
> + if (modify)
> + *pinsn = insn;
> +
> return true;
>
> reject:
> @@ -380,14 +387,15 @@ 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_item *actions)
> + const union decode_item *table, bool thumb,
> + bool emulate, const union decode_item *actions)
> {
> struct decode_header *h = (struct decode_header *)table;
> 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;
> @@ -402,7 +410,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) {
> @@ -415,7 +423,8 @@ probes_decode_insn(probes_opcode_t insn, struct arch_specific_insn *asi,
>
> case DECODE_TYPE_CUSTOM: {
> struct decode_custom *d = (struct decode_custom *)h;
> - return actions[d->decoder.bits].decoder(insn, asi, h);
> + return actions[d->decoder.bits].decoder(insn,
> + asi, h);
No need to split the above line, you haven't changed it and it doesn't
exceed 80 characters anyway.
[Rest of patch cut]
--
Tixy
^ permalink raw reply [flat|nested] 34+ messages in thread
* [PATCH v4 15/16] ARM: add uprobes support
2013-12-16 4:08 ` [PATCH v4 15/16] ARM: add uprobes support David Long
@ 2013-12-20 18:34 ` Jon Medhurst (Tixy)
2013-12-20 19:00 ` Rabin Vincent
` (2 more replies)
0 siblings, 3 replies; 34+ messages in thread
From: Jon Medhurst (Tixy) @ 2013-12-20 18:34 UTC (permalink / raw)
To: linux-arm-kernel
On Sun, 2013-12-15 at 23:08 -0500, David Long wrote:
> From: "David A. Long" <dave.long@linaro.org>
>
> Using Rabin Vincent's ARM uprobes patches as a base, enable uprobes
> support on ARM.
>
> Caveats:
>
> - Thumb is not supported
> - XOL abort/trap handling is not implemented
I shall repeat my comment from version one of the patch...
What are the consequences of this, e.g. is it possible for a probe to
get stuck in an infinite loop of faulting? I hope there are no integrity
issues for the kernel itself.
Would be good if someone familiar with uprobes working could answer
that.
I've a few other comments...
[...]
> +++ b/arch/arm/kernel/uprobes-arm.c
> @@ -0,0 +1,223 @@
> +#include <linux/kernel.h>
> +#include <linux/wait.h>
> +#include <linux/uprobes.h>
> +#include <linux/module.h>
> +
> +#include "probes.h"
> +#include "probes-arm.h"
> +#include "uprobes.h"
> +
> +static int uprobes_substitute_pc(unsigned long *pinsn, u32 oregs)
> +{
> + probes_opcode_t insn = __mem_to_opcode_arm(*pinsn);
> + probes_opcode_t temp;
> + probes_opcode_t mask;
> + int freereg;
> + u32 free = 0xffff;
> + u32 regs;
> +
> + for (regs = oregs; regs; regs >>= 4, insn >>= 4) {
> + if ((regs & 0xf) == REG_TYPE_NONE)
> + continue;
> +
> + free &= ~(1 << (insn & 0xf));
> + }
> +
> + /* No PC, no problem */
> + if (free & (1 << 15))
> + return 15;
> +
> + if (!free)
> + return -1;
> +
> + /*
> + * fls instead of ffs ensures that for "ldrd r0, r1, [pc]" we would
> + * pick LR instead of R1.
Do we know why this is desirable, i.e. preferring the higher numbered
registers? If there isn't a preference, then no need for comment really.
Also, the comment as is is wrong, should be "...pick LR instead of R2"
because R1 wouldn't be chosen as the instruction already uses it.
> + */
> + freereg = free = fls(free) - 1;
> +
> +
[...]
> +const union decode_item uprobes_probes_actions[] = {
> + [PROBES_EMULATE_NONE] {.handler = probes_simulate_nop},
There is a missing '=' in the line above. Interesting that GCC doesn't
complain (I tried compiling this patch and it didn't).
> + [PROBES_SIMULATE_NOP] = {.handler = probes_simulate_nop},
> + [PROBES_PRELOAD_IMM] = {.handler = probes_simulate_nop},
> + [PROBES_PRELOAD_REG] = {.handler = probes_simulate_nop},
> + [PROBES_BRANCH_IMM] = {.handler = simulate_blx1},
> + [PROBES_MRS] = {.handler = simulate_mrs},
> + [PROBES_BRANCH_REG] = {.handler = simulate_blx2bx},
> + [PROBES_CLZ] = {.handler = probes_simulate_nop},
> + [PROBES_SATURATING_ARITHMETIC] = {.handler = probes_simulate_nop},
> + [PROBES_MUL1] = {.handler = probes_simulate_nop},
> + [PROBES_MUL2] = {.handler = probes_simulate_nop},
> + [PROBES_SWP] = {.handler = probes_simulate_nop},
> + [PROBES_LDRSTRD] = {.decoder = decode_pc_ro},
> + [PROBES_LOAD_EXTRA] = {.decoder = decode_pc_ro},
> + [PROBES_LOAD] = {.decoder = decode_ldr},
> + [PROBES_STORE_EXTRA] = {.decoder = decode_pc_ro},
> + [PROBES_STORE] = {.decoder = decode_pc_ro},
> + [PROBES_MOV_IP_SP] = {.handler = simulate_mov_ipsp},
> + [PROBES_DATA_PROCESSING_REG] = {
> + .decoder = decode_rd12rn16rm0rs8_rwflags},
> + [PROBES_DATA_PROCESSING_IMM] = {
> + .decoder = decode_rd12rn16rm0rs8_rwflags},
> + [PROBES_MOV_HALFWORD] = {.handler = probes_simulate_nop},
> + [PROBES_SEV] = {.handler = probes_simulate_nop},
> + [PROBES_WFE] = {.handler = probes_simulate_nop},
> + [PROBES_SATURATE] = {.handler = probes_simulate_nop},
> + [PROBES_REV] = {.handler = probes_simulate_nop},
> + [PROBES_MMI] = {.handler = probes_simulate_nop},
> + [PROBES_PACK] = {.handler = probes_simulate_nop},
> + [PROBES_EXTEND] = {.handler = probes_simulate_nop},
> + [PROBES_EXTEND_ADD] = {.handler = probes_simulate_nop},
> + [PROBES_MUL_ADD_LONG] = {.handler = probes_simulate_nop},
> + [PROBES_MUL_ADD] = {.handler = probes_simulate_nop},
> + [PROBES_BITFIELD] = {.handler = probes_simulate_nop},
> + [PROBES_BRANCH] = {.handler = simulate_bbl},
> + [PROBES_LDMSTM] = {.decoder = uprobe_decode_ldmstm}
> +};
> diff --git a/arch/arm/kernel/uprobes.c b/arch/arm/kernel/uprobes.c
> new file mode 100644
> index 0000000..ae18549
> --- /dev/null
> +++ b/arch/arm/kernel/uprobes.c
[...]
> +bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs)
> +{
> + void *addr;
'addr' is not used so this line can be deleted
> + probes_opcode_t opcode;
> +
> + if (!auprobe->simulate)
> + return false;
> +
> + addr = (void *) regs->ARM_pc;
and so can this line ^^^
> + opcode = __mem_to_opcode_arm(*(unsigned int *) auprobe->insn);
> +
> + auprobe->asi.insn_singlestep(opcode, &auprobe->asi, regs);
> +
> + return true;
> +}
> +
[rest of patch snipped]
--
Tixy
^ permalink raw reply [flat|nested] 34+ messages in thread
* [PATCH v4 15/16] ARM: add uprobes support
2013-12-20 18:34 ` Jon Medhurst (Tixy)
@ 2013-12-20 19:00 ` Rabin Vincent
2013-12-20 19:47 ` Jon Medhurst (Tixy)
2013-12-23 15:32 ` Oleg Nesterov
2014-01-21 16:51 ` David Long
2 siblings, 1 reply; 34+ messages in thread
From: Rabin Vincent @ 2013-12-20 19:00 UTC (permalink / raw)
To: linux-arm-kernel
2013/12/20 Jon Medhurst (Tixy) <tixy@linaro.org>
> On Sun, 2013-12-15 at 23:08 -0500, David Long wrote:
> > +static int uprobes_substitute_pc(unsigned long *pinsn, u32 oregs)
> > +{
> > + probes_opcode_t insn = __mem_to_opcode_arm(*pinsn);
> > + probes_opcode_t temp;
> > + probes_opcode_t mask;
> > + int freereg;
> > + u32 free = 0xffff;
> > + u32 regs;
> > +
> > + for (regs = oregs; regs; regs >>= 4, insn >>= 4) {
> > + if ((regs & 0xf) == REG_TYPE_NONE)
> > + continue;
> > +
> > + free &= ~(1 << (insn & 0xf));
> > + }
> > +
> > + /* No PC, no problem */
> > + if (free & (1 << 15))
> > + return 15;
> > +
> > + if (!free)
> > + return -1;
> > +
> > + /*
> > + * fls instead of ffs ensures that for "ldrd r0, r1, [pc]" we would
> > + * pick LR instead of R1.
>
> Do we know why this is desirable, i.e. preferring the higher numbered
> registers? If there isn't a preference, then no need for comment really.
>
> Also, the comment as is is wrong, should be "...pick LR instead of R2"
> because R1 wouldn't be chosen as the instruction already uses it.
The second destination register of LDRD (R1 in the example above) is
not encoded in the instruction and so the code above would believe it
is free. Using ffs instead of fls would thus lead to R1 being used to
substitute PC.
^ permalink raw reply [flat|nested] 34+ messages in thread
* [PATCH v4 15/16] ARM: add uprobes support
2013-12-20 19:00 ` Rabin Vincent
@ 2013-12-20 19:47 ` Jon Medhurst (Tixy)
0 siblings, 0 replies; 34+ messages in thread
From: Jon Medhurst (Tixy) @ 2013-12-20 19:47 UTC (permalink / raw)
To: linux-arm-kernel
On Fri, 2013-12-20 at 20:00 +0100, Rabin Vincent wrote:
> 2013/12/20 Jon Medhurst (Tixy) <tixy@linaro.org>
> > On Sun, 2013-12-15 at 23:08 -0500, David Long wrote:
> > > +static int uprobes_substitute_pc(unsigned long *pinsn, u32 oregs)
> > > +{
> > > + probes_opcode_t insn = __mem_to_opcode_arm(*pinsn);
> > > + probes_opcode_t temp;
> > > + probes_opcode_t mask;
> > > + int freereg;
> > > + u32 free = 0xffff;
> > > + u32 regs;
> > > +
> > > + for (regs = oregs; regs; regs >>= 4, insn >>= 4) {
> > > + if ((regs & 0xf) == REG_TYPE_NONE)
> > > + continue;
> > > +
> > > + free &= ~(1 << (insn & 0xf));
> > > + }
> > > +
> > > + /* No PC, no problem */
> > > + if (free & (1 << 15))
> > > + return 15;
> > > +
> > > + if (!free)
> > > + return -1;
> > > +
> > > + /*
> > > + * fls instead of ffs ensures that for "ldrd r0, r1, [pc]" we would
> > > + * pick LR instead of R1.
> >
> > Do we know why this is desirable, i.e. preferring the higher numbered
> > registers? If there isn't a preference, then no need for comment really.
> >
> > Also, the comment as is is wrong, should be "...pick LR instead of R2"
> > because R1 wouldn't be chosen as the instruction already uses it.
>
> The second destination register of LDRD (R1 in the example above) is
> not encoded in the instruction
Ah, that's the fact I'd missed, so the code and comment in this patch is
correct.
Thanks
--
Tixy
^ permalink raw reply [flat|nested] 34+ messages in thread
* [PATCH v4 15/16] ARM: add uprobes support
2013-12-20 18:34 ` Jon Medhurst (Tixy)
2013-12-20 19:00 ` Rabin Vincent
@ 2013-12-23 15:32 ` Oleg Nesterov
2014-01-21 16:51 ` David Long
2 siblings, 0 replies; 34+ messages in thread
From: Oleg Nesterov @ 2013-12-23 15:32 UTC (permalink / raw)
To: linux-arm-kernel
On 12/20, Jon Medhurst (Tixy) wrote:
>
> On Sun, 2013-12-15 at 23:08 -0500, David Long wrote:
> > From: "David A. Long" <dave.long@linaro.org>
> >
> > Caveats:
> >
> > - Thumb is not supported
> > - XOL abort/trap handling is not implemented
>
> I shall repeat my comment from version one of the patch...
>
> What are the consequences of this, e.g. is it possible for a probe to
> get stuck in an infinite loop of faulting? I hope there are no integrity
> issues for the kernel itself.
Unless there is something arm-specific, the kernel should be fine. The
task should notice a signal after handle_singlestep() before it returns
to the user-mode.
But of course the probed application can be confused. And I have no idea
what arm does if, say, a single-stepped xol insn triggers the page fault.
We need to change instruction_pointer() back to the faulted (probed) insn
if the page fault fails. But since because arch_uprobe_xol_was_trapped()
is not implemented this won't happen.
Oleg.
^ permalink raw reply [flat|nested] 34+ messages in thread
* [PATCH v4 05/16] ARM: use a function table for determining instruction interpreter actions
2013-12-20 12:45 ` Jon Medhurst (Tixy)
@ 2014-01-15 16:25 ` David Long
0 siblings, 0 replies; 34+ messages in thread
From: David Long @ 2014-01-15 16:25 UTC (permalink / raw)
To: linux-arm-kernel
On 12/20/13 07:45, Jon Medhurst (Tixy) wrote:
> On Sun, 2013-12-15 at 23:08 -0500, David Long wrote:
>> From: "David A. Long" <dave.long@linaro.org>
>>
>> Make the instruction interpreter call back to semantic action functions
>> through a function pointer array provided by the invoker. The interpreter
>> decodes the instructions into groups and uses the group number to index
>> into the supplied array. kprobes and uprobes code will each supply their
>> own array of functions.
>>
>> Signed-off-by: David A. Long <dave.long@linaro.org>
>> ---
>
> Because I've been very slow in reviewing these I've only just noticed
> that some of the the comments I made on version one of this patch didn't
> get a response. I've copied them again below (slightly edited) and
> heavily trimmed the patch...
>
>> arch/arm/kernel/kprobes-arm.c | 41 +++++++++++
>> arch/arm/kernel/kprobes-common.c | 3 +-
>> arch/arm/kernel/kprobes-thumb.c | 92 ++++++++++++++++++------
>> arch/arm/kernel/kprobes.c | 10 ++-
>> arch/arm/kernel/kprobes.h | 14 ++--
>> arch/arm/kernel/probes-arm.c | 114 +++++++++++++++---------------
>> arch/arm/kernel/probes-arm.h | 37 ++++++++++
>> arch/arm/kernel/probes-thumb.c | 149 +++++++++++++++++++--------------------
>> arch/arm/kernel/probes-thumb.h | 14 ++--
>> arch/arm/kernel/probes.c | 13 ++--
>> arch/arm/kernel/probes.h | 15 ++--
>> 11 files changed, 325 insertions(+), 177 deletions(-)
>>
>> diff --git a/arch/arm/kernel/kprobes-arm.c b/arch/arm/kernel/kprobes-arm.c
>> index a359475..ee329ff 100644
>> --- a/arch/arm/kernel/kprobes-arm.c
>> +++ b/arch/arm/kernel/kprobes-arm.c
>> @@ -299,3 +299,44 @@ emulate_rdlo12rdhi16rn0rm8_rwflags_nopc(struct kprobe *p, struct pt_regs *regs)
>> regs->uregs[rdhi] = rdhiv;
>> regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK);
>> }
>> +
>> +const union decode_item kprobes_arm_actions[] = {
>
> I think it's best if we don't reuse the decode_item type here, this is a
> different sort of table so probably best to have it's own union. Also,
> if we do that, then decode_item can be simplified as it won't need to
> have function pointers in it, i.e. we could end up with...
>
> union decode_action {
> kprobe_insn_handler_t *handler;
> kprobe_custom_decode_t *decoder;
> };
>
> union decode_item {
> u32 bits;
> const union decode_item *table;
> };
>
> typedef enum kprobe_insn (kprobe_custom_decode_t)(kprobe_opcode_t,
> struct arch_specific_insn *,
> union decode_action *actions);
>
>
I've added the following:
typedef enum kprobe_insn (probes_custom_decode_t)(kprobe_opcode_t,
struct arch_specific_insn *,
struct decode_header *);
union decode_action {
kprobe_insn_handler_t *handler;
probes_custom_decode_t *decoder;
};
Note the third argument actually passed into the decoder functions is
the decode table entry. decode_action is only used to select a
decode/emulate/simullate function.
> A second point, I think it would be a good idea to make sure these
> action arrays are the size we expect by adding an entry at the end of
> the relevant enumeration and using that to set the size of the arrays.
> E.g. for this one
>
> enum probes_arm_action {
> ...
> ...
> NUM_PROBES_ARM_ACTIONS
> };
>
> and then use it like:
>
> const union decode_action kprobes_arm_actions[NUM_PROBES_ARM_ACTIONS] = {
>
> That way, we at least make any uninitialised entries are null (I
> assume?) which is safer than accidentally indexing beyond the array.
>
>
Done.
>> + [PROBES_EMULATE_NONE] = {.handler = kprobe_emulate_none},
>> + [PROBES_SIMULATE_NOP] = {.handler = kprobe_simulate_nop},
>> + [PROBES_PRELOAD_IMM] = {.handler = kprobe_simulate_nop},
>
> [...]
>
>
>> diff --git a/arch/arm/kernel/probes.h b/arch/arm/kernel/probes.h
>> index d14d224..2238972 100644
>> --- a/arch/arm/kernel/probes.h
>> +++ b/arch/arm/kernel/probes.h
>> @@ -131,7 +131,8 @@ void __kprobes kprobe_simulate_nop(struct kprobe *p, struct pt_regs *regs);
>> void __kprobes kprobe_emulate_none(struct kprobe *p, struct pt_regs *regs);
>>
>> enum kprobe_insn __kprobes
>> -kprobe_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi);
>> +kprobe_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi,
>> + struct decode_header *h);
>>
>> /*
>> * Test if load/store instructions writeback the address register.
>> @@ -334,7 +335,7 @@ struct decode_custom {
>>
>> #define DECODE_CUSTOM(_mask, _value, _decoder) \
>> DECODE_HEADER(DECODE_TYPE_CUSTOM, _mask, _value, 0), \
>> - {.decoder = (_decoder)}
>> + {.bits = (_decoder)}
>>
>
> This third and final comment is probably just bike shedding...
>
> 'bits' looks a bit funny here. I've been trying to think of a way of
> making it nicer but it's difficult. The actual value is one of three
> different enums, so if we were to add another members to decode_item it
> would just have to be "int action", at least that would read nicer in
> these macros and where it gets read out in probes_decode_insn.
>
I agree. I've added an "int action" to the decode_item union, and use
it instead of "bits" for the action array index.
I've also updated the description of how this all works, in the comments.
-dl
^ permalink raw reply [flat|nested] 34+ messages in thread
* [PATCH v4 04/16] ARM: move generic thumb instruction parsing code to new files for use by other feature
2013-12-20 12:46 ` Jon Medhurst (Tixy)
@ 2014-01-15 16:41 ` David Long
0 siblings, 0 replies; 34+ messages in thread
From: David Long @ 2014-01-15 16:41 UTC (permalink / raw)
To: linux-arm-kernel
On 12/20/13 07:46, Jon Medhurst (Tixy) wrote:
> On Sun, 2013-12-15 at 23:08 -0500, David Long wrote:
>> From: "David A. Long" <dave.long@linaro.org>
>>
>> Move the thumb version of the kprobes instruction parsing code into more generic
>> files from where it can be used by uprobes and possibly other subsystems. The
>> symbol names will be made more generic in a subsequent part of this patchset.
>>
>> Signed-off-by: David A. Long <dave.long@linaro.org>
>> ---
>
> I just have two comments about probes-thumb.h ...
>
> [...]
>
>> diff --git a/arch/arm/kernel/probes-thumb.h b/arch/arm/kernel/probes-thumb.h
>> new file mode 100644
>> index 0000000..3f39210
>> --- /dev/null
>> +++ b/arch/arm/kernel/probes-thumb.h
>> @@ -0,0 +1,136 @@
>> +/*
>> + * arch/arm/kernel/probes-arm.h
>> + *
>> + * Copyright 2013 Linaro Ltd.
>> + * Written by: David A. Long
>> + *
>> + * The code contained herein is licensed under the GNU General Public
>> + * License. You may obtain a copy of the GNU General Public License
>> + * Version 2 or later at the following locations:
>> + *
>> + * http://www.opensource.org/licenses/gpl-license.html
>> + * http://www.gnu.org/copyleft/gpl.html
>> + */
>> +
>> +#ifndef _ARM_KERNEL_PROBES_THUMB_H
>> +#define _ARM_KERNEL_PROBES_THUMB_H
>> +
>> +/*
>> + * True if current instruction is in an IT block.
>> + */
>> +#define in_it_block(cpsr) ((cpsr & 0x06000c00) != 0x00000000)
>> +
>> +/*
>> + * Return the condition code to check for the currently executing instruction.
>> + * This is in ITSTATE<7:4> which is in CPSR<15:12> but is only valid if
>> + * in_it_block returns true.
>> + */
>> +#define current_cond(cpsr) ((cpsr >> 12) & 0xf)
>
> Looks like you forgot to remove above two #defines from kprobes-thumb.c
> when you moved them to this header file.
Fixed.
> Also...
>
>> +enum probes_t32_action {
>> + PROBES_T32_EMULATE_NONE,
>> + PROBES_T32_SIMULATE_NOP,
>> + PROBES_T32_LDMSTM,
>> + PROBES_T32_LDRDSTRD,
>> + PROBES_T32_TABLE_BRANCH,
>> + PROBES_T32_TST,
>> + PROBES_T32_CMP,
>> + PROBES_T32_MOV,
>> + PROBES_T32_ADDSUB,
>> + PROBES_T32_LOGICAL,
>> + PROBES_T32_ADDWSUBW_PC,
>> + PROBES_T32_ADDWSUBW,
>> + PROBES_T32_MOVW,
>> + PROBES_T32_SAT,
>> + PROBES_T32_BITFIELD,
>> + PROBES_T32_SEV,
>> + PROBES_T32_WFE,
>> + PROBES_T32_MRS,
>> + PROBES_T32_BRANCH_COND,
>> + PROBES_T32_BRANCH,
>> + PROBES_T32_PLDI,
>> + PROBES_T32_LDR_LIT,
>> + PROBES_T32_LDRSTR,
>> + PROBES_T32_SIGN_EXTEND,
>> + PROBES_T32_MEDIA,
>> + PROBES_T32_REVERSE,
>> + PROBES_T32_MUL_ADD,
>> + PROBES_T32_MUL_ADD2,
>> + PROBES_T32_MUL_ADD_LONG
>> +};
>> +
>> +enum probes_t16_action {
>> + PROBES_T16_ADD_SP,
>> + PROBES_T16_CBZ,
>> + PROBES_T16_SIGN_EXTEND,
>> + PROBES_T16_PUSH,
>> + PROBES_T16_POP,
>> + PROBES_T16_SEV,
>> + PROBES_T16_WFE,
>> + PROBES_T16_IT,
>> + PROBES_T16_CMP,
>> + PROBES_T16_ADDSUB,
>> + PROBES_T16_LOGICAL,
>> + PROBES_T16_BLX,
>> + PROBES_T16_HIREGOPS,
>> + PROBES_T16_LDR_LIT,
>> + PROBES_T16_LDRHSTRH,
>> + PROBES_T16_LDRSTR,
>> + PROBES_T16_ADR,
>> + PROBES_T16_LDMSTM,
>> + PROBES_T16_BRANCH_COND,
>> + PROBES_T16_BRANCH
>> +};
>> +
>
Moved.
-dl
^ permalink raw reply [flat|nested] 34+ messages in thread
* [PATCH v4 02/16] ARM: move shared uprobe/kprobe definitions into new include file
2013-12-20 12:46 ` Jon Medhurst (Tixy)
@ 2014-01-15 16:43 ` David Long
0 siblings, 0 replies; 34+ messages in thread
From: David Long @ 2014-01-15 16:43 UTC (permalink / raw)
To: linux-arm-kernel
On 12/20/13 07:46, Jon Medhurst (Tixy) wrote:
> On Sun, 2013-12-15 at 23:08 -0500, David Long wrote:
>> From: "David A. Long" <dave.long@linaro.org>
>>
>> Separate the kprobe-only definitions from the definitions needed by
>> both kprobes and uprobes.
>>
>> Signed-off-by: David A. Long <dave.long@linaro.org>
>> ---
>> arch/arm/include/asm/kprobes.h | 15 +--------------
>> arch/arm/include/asm/probes.h | 18 ++++++++++++++++++
>> 2 files changed, 19 insertions(+), 14 deletions(-)
>> create mode 100644 arch/arm/include/asm/probes.h
>>
>> diff --git a/arch/arm/include/asm/kprobes.h b/arch/arm/include/asm/kprobes.h
>> index f82ec22..30fc11b 100644
>> --- a/arch/arm/include/asm/kprobes.h
>> +++ b/arch/arm/include/asm/kprobes.h
>> @@ -28,21 +28,8 @@
>> #define kretprobe_blacklist_size 0
>>
>> typedef u32 kprobe_opcode_t;
>> -
>> 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;
>> -};
>> +#include <asm/probes.h>
>>
>> struct prev_kprobe {
>> struct kprobe *kp;
>> diff --git a/arch/arm/include/asm/probes.h b/arch/arm/include/asm/probes.h
>> new file mode 100644
>> index 0000000..21da148
>> --- /dev/null
>> +++ b/arch/arm/include/asm/probes.h
>> @@ -0,0 +1,18 @@
>
> This new file doesn't have any copyright/license notice, I suggest you
> copy the one from kprobes.h and include a note to say this new files
> contents were copied, e.g. start it like...
>
> /*
> * arch/arm/include/asm/probes.h
> *
> * Original contents copied from arch/arm/include/asm/kprobes.h
> * which contains the following notice...
> *
> * Copyright (C) 2006, 2007 Motorola Inc.
> *
> * This program is free software; you can redistribute it and/or modify
> [...]
>
Fixed.
>> +#ifndef _ASM_PROBES_H
>> +#define _ASM_PROBES_H
>> +
>> +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;
>> +};
>> +
>> +#endif
>
-dl
^ permalink raw reply [flat|nested] 34+ messages in thread
* [PATCH v4 07/16] ARM: Remove use of struct kprobe from generic probes code
2013-12-20 13:55 ` Jon Medhurst (Tixy)
@ 2014-01-15 16:44 ` David Long
0 siblings, 0 replies; 34+ messages in thread
From: David Long @ 2014-01-15 16:44 UTC (permalink / raw)
To: linux-arm-kernel
On 12/20/13 08:55, Jon Medhurst (Tixy) wrote:
> On Sun, 2013-12-15 at 23:08 -0500, David Long wrote:
>> From: "David A. Long" <dave.long@linaro.org>
>>
>> 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>
>> ---
>> arch/arm/include/asm/probes.h | 9 +-
>> arch/arm/kernel/kprobes-arm.c | 77 ++++++-------
>> arch/arm/kernel/kprobes-common.c | 42 ++++---
>> arch/arm/kernel/kprobes-thumb.c | 239 +++++++++++++++++++--------------------
>> arch/arm/kernel/kprobes.c | 2 +-
>> arch/arm/kernel/kprobes.h | 2 +-
>> arch/arm/kernel/probes-arm.c | 33 +++---
>> arch/arm/kernel/probes-arm.h | 29 ++---
>> arch/arm/kernel/probes-thumb.c | 18 ++-
>> arch/arm/kernel/probes-thumb.h | 51 ---------
>> arch/arm/kernel/probes.c | 14 ++-
>> arch/arm/kernel/probes.h | 8 +-
>> 12 files changed, 246 insertions(+), 278 deletions(-)
>
> Looks OK to me, though it looks like this patch includes some header
> file cleanups that should have been part of the previous patch? I.e. all
> the changes to probes-thumb.h and probes-arm.h. And also the
> re-application of 'static' to functions in kprobes-thumb.c and
> kprobes-arm.c.
>
> I'm not sure it's worth the hassle of trying to unpick those changes
> though, it doesn't impact the end result or bisect-bility.
>
I moved the changes around as suggested.
-dl
^ permalink raw reply [flat|nested] 34+ messages in thread
* [PATCH v4 13/16] ARM: Add an emulate flag to the kprobes/uprobes instruction decode functions
2013-12-20 14:58 ` Jon Medhurst (Tixy)
@ 2014-01-15 19:31 ` David Long
2014-01-16 9:18 ` Jon Medhurst (Tixy)
0 siblings, 1 reply; 34+ messages in thread
From: David Long @ 2014-01-15 19:31 UTC (permalink / raw)
To: linux-arm-kernel
On 12/20/13 09:58, Jon Medhurst (Tixy) wrote:
> On Sun, 2013-12-15 at 23:08 -0500, David Long wrote:
>> From: "David A. Long" <dave.long@linaro.org>
>>
>> Add an emulate flag into the instruction interpreter, primarily for uprobes
>> support.
>>
>> Signed-off-by: David A. Long <dave.long@linaro.org>
>> ---
>> arch/arm/kernel/kprobes.c | 3 ++-
>> arch/arm/kernel/kprobes.h | 1 +
>> arch/arm/kernel/probes-arm.c | 4 ++--
>> arch/arm/kernel/probes-arm.h | 2 +-
>> arch/arm/kernel/probes-thumb.c | 8 ++++----
>> arch/arm/kernel/probes-thumb.h | 4 ++--
>> arch/arm/kernel/probes.c | 32 +++++++++++++++++++++++---------
>> arch/arm/kernel/probes.h | 2 +-
>> 8 files changed, 36 insertions(+), 20 deletions(-)
>>
>> diff --git a/arch/arm/kernel/kprobes.c b/arch/arm/kernel/kprobes.c
>> index 0d9d49b..04690f9 100644
>> --- a/arch/arm/kernel/kprobes.c
>> +++ b/arch/arm/kernel/kprobes.c
>> @@ -87,7 +87,8 @@ 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)) {
>
> Any reason why the function args need splitting over two lines?
I undid the that change.
>> case INSN_REJECTED: /* not supported */
>> return -EINVAL;
>>
>
> [...]
>
>> --- a/arch/arm/kernel/probes.c
>> +++ b/arch/arm/kernel/probes.c
>> @@ -193,7 +193,7 @@ void __kprobes probes_emulate_none(probes_opcode_t opcode,
>> */
>> static probes_opcode_t __kprobes
>> prepare_emulated_insn(probes_opcode_t insn, struct arch_specific_insn *asi,
>> - bool thumb)
>> + bool thumb)
>
> Seems like a spurious indentation change.
Fixed.
>> {
>> #ifdef CONFIG_THUMB2_KERNEL
>> if (thumb) {
>> @@ -218,7 +218,7 @@ prepare_emulated_insn(probes_opcode_t insn, struct arch_specific_insn *asi,
>> */
>> static void __kprobes
>> set_emulated_insn(probes_opcode_t insn, struct arch_specific_insn *asi,
>> - bool thumb)
>> + bool thumb)
>
> Another spurious whitespace change.
Fixed.
>> {
>> #ifdef CONFIG_THUMB2_KERNEL
>> if (thumb) {
>> @@ -253,7 +253,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 */
>> @@ -317,9 +317,16 @@ static bool __kprobes decode_regs(probes_opcode_t *pinsn, u32 regs)
>> /* Replace value of nibble with new register number... */
>> insn &= ~mask;
>> insn |= new_bits & mask;
>> + if (modify) {
>> + /* Replace value of nibble with new register number */
>> + insn &= ~mask;
>> + insn |= new_bits & mask;
>> + }
>
> Huh? As is, the above addition doesn't do anything because insn has
> already been modified. I guess you played with the idea that you needed
> to avoid changing insn (you don't) and then didn't undo the experiment
> quite right. :-)
>
The conditional modification of the instruction was part of Rabin's
original work for uprobes, but I messed up the merge from an earlier
working version of my patches. My intention was/is to delete the old
unconditional code. Sounds like maybe you disagree though. The intent
is to only modify the instruction in the kprobes case.
>> }
>>
>> - *pinsn = insn;
>> + if (modify)
>> + *pinsn = insn;
>> +
>> return true;
>>
>> reject:
>> @@ -380,14 +387,15 @@ 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_item *actions)
>> + const union decode_item *table, bool thumb,
>> + bool emulate, const union decode_item *actions)
>> {
>> struct decode_header *h = (struct decode_header *)table;
>> 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;
>> @@ -402,7 +410,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) {
>> @@ -415,7 +423,8 @@ probes_decode_insn(probes_opcode_t insn, struct arch_specific_insn *asi,
>>
>> case DECODE_TYPE_CUSTOM: {
>> struct decode_custom *d = (struct decode_custom *)h;
>> - return actions[d->decoder.bits].decoder(insn, asi, h);
>> + return actions[d->decoder.bits].decoder(insn,
>> + asi, h);
>
> No need to split the above line, you haven't changed it and it doesn't
> exceed 80 characters anyway.
Fixed.
> [Rest of patch cut]
>
-dl
^ permalink raw reply [flat|nested] 34+ messages in thread
* [PATCH v4 13/16] ARM: Add an emulate flag to the kprobes/uprobes instruction decode functions
2014-01-15 19:31 ` David Long
@ 2014-01-16 9:18 ` Jon Medhurst (Tixy)
2014-01-16 18:12 ` David Long
0 siblings, 1 reply; 34+ messages in thread
From: Jon Medhurst (Tixy) @ 2014-01-16 9:18 UTC (permalink / raw)
To: linux-arm-kernel
On Wed, 2014-01-15 at 14:31 -0500, David Long wrote:
> On 12/20/13 09:58, Jon Medhurst (Tixy) wrote:
> > On Sun, 2013-12-15 at 23:08 -0500, David Long wrote:
[...]
> >> {
> >> #ifdef CONFIG_THUMB2_KERNEL
> >> if (thumb) {
> >> @@ -253,7 +253,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 */
> >> @@ -317,9 +317,16 @@ static bool __kprobes decode_regs(probes_opcode_t *pinsn, u32 regs)
> >> /* Replace value of nibble with new register number... */
> >> insn &= ~mask;
> >> insn |= new_bits & mask;
> >> + if (modify) {
> >> + /* Replace value of nibble with new register number */
> >> + insn &= ~mask;
> >> + insn |= new_bits & mask;
> >> + }
> >
> > Huh? As is, the above addition doesn't do anything because insn has
> > already been modified. I guess you played with the idea that you needed
> > to avoid changing insn (you don't) and then didn't undo the experiment
> > quite right. :-)
> >
>
> The conditional modification of the instruction was part of Rabin's
> original work for uprobes, but I messed up the merge from an earlier
> working version of my patches. My intention was/is to delete the old
> unconditional code. Sounds like maybe you disagree though. The intent
> is to only modify the instruction in the kprobes case.
'insn' is the local variable containing the instruction value we're
processing. It doesn't matter if we change that, we just need to avoid
updating the instruction in memory, which the code in the next chunk
already correctly checks for...
> >> }
> >>
> >> - *pinsn = insn;
> >> + if (modify)
> >> + *pinsn = insn;
> >> +
> >> return true;
> >>
So only one of these 'if (modify)' checks is required for code
correctness, and I suggest keeping the second one as it's more explicit
and defensive.
--
Tixy
^ permalink raw reply [flat|nested] 34+ messages in thread
* [PATCH v4 13/16] ARM: Add an emulate flag to the kprobes/uprobes instruction decode functions
2014-01-16 9:18 ` Jon Medhurst (Tixy)
@ 2014-01-16 18:12 ` David Long
0 siblings, 0 replies; 34+ messages in thread
From: David Long @ 2014-01-16 18:12 UTC (permalink / raw)
To: linux-arm-kernel
On 01/16/14 04:18, Jon Medhurst (Tixy) wrote:
> On Wed, 2014-01-15 at 14:31 -0500, David Long wrote:
>> On 12/20/13 09:58, Jon Medhurst (Tixy) wrote:
>>> On Sun, 2013-12-15 at 23:08 -0500, David Long wrote:
> [...]
>>>> {
>>>> #ifdef CONFIG_THUMB2_KERNEL
>>>> if (thumb) {
>>>> @@ -253,7 +253,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 */
>>>> @@ -317,9 +317,16 @@ static bool __kprobes decode_regs(probes_opcode_t *pinsn, u32 regs)
>>>> /* Replace value of nibble with new register number... */
>>>> insn &= ~mask;
>>>> insn |= new_bits & mask;
>>>> + if (modify) {
>>>> + /* Replace value of nibble with new register number */
>>>> + insn &= ~mask;
>>>> + insn |= new_bits & mask;
>>>> + }
>>>
>>> Huh? As is, the above addition doesn't do anything because insn has
>>> already been modified. I guess you played with the idea that you needed
>>> to avoid changing insn (you don't) and then didn't undo the experiment
>>> quite right. :-)
>>>
>>
>> The conditional modification of the instruction was part of Rabin's
>> original work for uprobes, but I messed up the merge from an earlier
>> working version of my patches. My intention was/is to delete the old
>> unconditional code. Sounds like maybe you disagree though. The intent
>> is to only modify the instruction in the kprobes case.
>
> 'insn' is the local variable containing the instruction value we're
> processing. It doesn't matter if we change that, we just need to avoid
> updating the instruction in memory, which the code in the next chunk
> already correctly checks for...
>
>>>> }
>>>>
>>>> - *pinsn = insn;
>>>> + if (modify)
>>>> + *pinsn = insn;
>>>> +
>>>> return true;
>>>>
>
> So only one of these 'if (modify)' checks is required for code
> correctness, and I suggest keeping the second one as it's more explicit
> and defensive.
>
>
OK, I see your point. I shall simplify the code as you have suggested.
-dl
^ permalink raw reply [flat|nested] 34+ messages in thread
* [PATCH v4 15/16] ARM: add uprobes support
2013-12-20 18:34 ` Jon Medhurst (Tixy)
2013-12-20 19:00 ` Rabin Vincent
2013-12-23 15:32 ` Oleg Nesterov
@ 2014-01-21 16:51 ` David Long
2 siblings, 0 replies; 34+ messages in thread
From: David Long @ 2014-01-21 16:51 UTC (permalink / raw)
To: linux-arm-kernel
On 12/20/13 13:34, Jon Medhurst (Tixy) wrote:
> On Sun, 2013-12-15 at 23:08 -0500, David Long wrote:
>> From: "David A. Long" <dave.long@linaro.org>
>>
>> Using Rabin Vincent's ARM uprobes patches as a base, enable uprobes
>> support on ARM.
>>
>> Caveats:
>>
>> - Thumb is not supported
>> - XOL abort/trap handling is not implemented
>
> I shall repeat my comment from version one of the patch...
>
> What are the consequences of this, e.g. is it possible for a probe to
> get stuck in an infinite loop of faulting? I hope there are no integrity
> issues for the kernel itself.
>
> Would be good if someone familiar with uprobes working could answer
> that.
Testing shows it does indeed get stuck continuously trapping. The
process is killable. Fortunately all the infrastructure is already
there for fixing this. I've patched the code to detect the trap and
allow it to be processed, using the powerpc uprobes code as a model.
The changes required are fairly small and entirely in the
architecture-specific code.
As mentioned before, thumb support is a follow-on project.
> I've a few other comments...
[snip]
>
>
>> +const union decode_item uprobes_probes_actions[] = {
>> + [PROBES_EMULATE_NONE] {.handler = probes_simulate_nop},
>
> There is a missing '=' in the line above. Interesting that GCC doesn't
> complain (I tried compiling this patch and it didn't).
>
That is indeed odd. I have fixed it (my code, not the compiler).
[snip]
>> +bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs)
>> +{
>> + void *addr;
>
> 'addr' is not used so this line can be deleted
>
>> + probes_opcode_t opcode;
>> +
>> + if (!auprobe->simulate)
>> + return false;
>> +
>> + addr = (void *) regs->ARM_pc;
>
> and so can this line ^^^
Fixed.
>
>> + opcode = __mem_to_opcode_arm(*(unsigned int *) auprobe->insn);
>> +
>> + auprobe->asi.insn_singlestep(opcode, &auprobe->asi, regs);
>> +
>> + return true;
>> +}
>> +
>
Fixed.
> [rest of patch snipped]
>
-dl
^ permalink raw reply [flat|nested] 34+ messages in thread
end of thread, other threads:[~2014-01-21 16:51 UTC | newest]
Thread overview: 34+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-12-16 4:08 [PATCH v4 00/16] uprobes: Add uprobes support for ARM David Long
2013-12-16 4:08 ` [PATCH v4 01/16] uprobes: allow ignoring of probe hits David Long
2013-12-16 4:08 ` [PATCH v4 02/16] ARM: move shared uprobe/kprobe definitions into new include file David Long
2013-12-20 12:46 ` Jon Medhurst (Tixy)
2014-01-15 16:43 ` David Long
2013-12-16 4:08 ` [PATCH v4 03/16] ARM: Move generic arm instruction parsing code to new files for sharing between features David Long
2013-12-16 4:08 ` [PATCH v4 04/16] ARM: move generic thumb instruction parsing code to new files for use by other feature David Long
2013-12-20 12:46 ` Jon Medhurst (Tixy)
2014-01-15 16:41 ` David Long
2013-12-16 4:08 ` [PATCH v4 05/16] ARM: use a function table for determining instruction interpreter actions David Long
2013-12-20 12:45 ` Jon Medhurst (Tixy)
2014-01-15 16:25 ` David Long
2013-12-16 4:08 ` [PATCH v4 06/16] ARM: Disable jprobes test when built into thumb-mode kernel David Long
2013-12-16 4:08 ` [PATCH v4 07/16] ARM: Remove use of struct kprobe from generic probes code David Long
2013-12-20 13:55 ` Jon Medhurst (Tixy)
2014-01-15 16:44 ` David Long
2013-12-16 4:08 ` [PATCH v4 08/16] ARM: Use new opcode type in ARM kprobes/uprobes code David Long
2013-12-16 4:08 ` [PATCH v4 09/16] ARM: Make the kprobes condition_check symbol names more generic David Long
2013-12-16 4:08 ` [PATCH v4 10/16] ARM: Change more ARM kprobes symbol names to something more David Long
2013-12-16 4:08 ` [PATCH v4 11/16] ARM: Rename the shared kprobes/uprobe return value enum David Long
2013-12-16 4:08 ` [PATCH v4 12/16] ARM: Change the remaining shared kprobes/uprobes symbols to something generic David Long
2013-12-16 4:08 ` [PATCH v4 13/16] ARM: Add an emulate flag to the kprobes/uprobes instruction decode functions David Long
2013-12-20 14:58 ` Jon Medhurst (Tixy)
2014-01-15 19:31 ` David Long
2014-01-16 9:18 ` Jon Medhurst (Tixy)
2014-01-16 18:12 ` David Long
2013-12-16 4:08 ` [PATCH v4 14/16] ARM: Make arch_specific_insn a define for new arch_probes_insn structure David Long
2013-12-16 4:08 ` [PATCH v4 15/16] ARM: add uprobes support David Long
2013-12-20 18:34 ` Jon Medhurst (Tixy)
2013-12-20 19:00 ` Rabin Vincent
2013-12-20 19:47 ` Jon Medhurst (Tixy)
2013-12-23 15:32 ` Oleg Nesterov
2014-01-21 16:51 ` David Long
2013-12-16 4:08 ` [PATCH v4 16/16] ARM: Remove uprobes dependency on kprobes David Long
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).