summary refs log tree commit diff
diff options
context:
space:
mode:
authorDaniel Jacobowitz <dan@codesourcery.com>2010-02-02 18:22:16 +0100
committerRussell King <rmk+kernel@arm.linux.org.uk>2010-02-15 21:39:52 +0000
commitd23bc1b3a7e6db935acb9a949a5985d9b77dfd13 (patch)
tree878b262eff95267cbd3b125885ff7bad21e25b89
parent1a28e3d977860dc760909083df625b300f695680 (diff)
downloadlinux-d23bc1b3a7e6db935acb9a949a5985d9b77dfd13.tar.gz
ARM: 5912/1: Define a 32-bit Thumb-2 breakpoint instruction
Recognize 0xf7f0 0xa000 as a 32-bit breakpoint instruction for
Thumb-2.

Signed-off-by: Daniel Jacobowitz <dan@codesourcery.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
-rw-r--r--arch/arm/kernel/ptrace.c31
1 files changed, 31 insertions, 0 deletions
diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c
index a2ea3854cb3c..bd56673c6a69 100644
--- a/arch/arm/kernel/ptrace.c
+++ b/arch/arm/kernel/ptrace.c
@@ -499,10 +499,41 @@ static struct undef_hook thumb_break_hook = {
 	.fn		= break_trap,
 };
 
+static int thumb2_break_trap(struct pt_regs *regs, unsigned int instr)
+{
+	unsigned int instr2;
+	void __user *pc;
+
+	/* Check the second half of the instruction.  */
+	pc = (void __user *)(instruction_pointer(regs) + 2);
+
+	if (processor_mode(regs) == SVC_MODE) {
+		instr2 = *(u16 *) pc;
+	} else {
+		get_user(instr2, (u16 __user *)pc);
+	}
+
+	if (instr2 == 0xa000) {
+		ptrace_break(current, regs);
+		return 0;
+	} else {
+		return 1;
+	}
+}
+
+static struct undef_hook thumb2_break_hook = {
+	.instr_mask	= 0xffff,
+	.instr_val	= 0xf7f0,
+	.cpsr_mask	= PSR_T_BIT,
+	.cpsr_val	= PSR_T_BIT,
+	.fn		= thumb2_break_trap,
+};
+
 static int __init ptrace_break_init(void)
 {
 	register_undef_hook(&arm_break_hook);
 	register_undef_hook(&thumb_break_hook);
+	register_undef_hook(&thumb2_break_hook);
 	return 0;
 }