summaryrefslogtreecommitdiff
path: root/arch/arm/kernel/kprobes-thumb.c
diff options
context:
space:
mode:
authorJon Medhurst <tixy@yxit.co.uk>2011-04-20 19:29:52 +0100
committerTixy <tixy@medhuaa1.miniserver.com>2011-07-13 17:32:42 +0000
commiteaf4f33feca2704ad1d06f1ef6b427712c506cc0 (patch)
tree852ca3e5cb599b697226717cba72b9c505f2785c /arch/arm/kernel/kprobes-thumb.c
parentaceb487ab2ea0dca43f5131e456f45bc9f8c1bed (diff)
ARM: kprobes: Add condition code checking to Thumb emulation
Signed-off-by: Jon Medhurst <tixy@yxit.co.uk> Acked-by: Nicolas Pitre <nicolas.pitre@linaro.org>
Diffstat (limited to 'arch/arm/kernel/kprobes-thumb.c')
-rw-r--r--arch/arm/kernel/kprobes-thumb.c22
1 files changed, 22 insertions, 0 deletions
diff --git a/arch/arm/kernel/kprobes-thumb.c b/arch/arm/kernel/kprobes-thumb.c
index ac6b2d138ee5..24a188b1601a 100644
--- a/arch/arm/kernel/kprobes-thumb.c
+++ b/arch/arm/kernel/kprobes-thumb.c
@@ -13,14 +13,36 @@
#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)
+
+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;
+}
+
enum kprobe_insn __kprobes
thumb16_kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi)
{
+ asi->insn_check_cc = thumb_check_cc;
return INSN_REJECTED;
}
enum kprobe_insn __kprobes
thumb32_kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi)
{
+ asi->insn_check_cc = thumb_check_cc;
return INSN_REJECTED;
}