From patchwork Sat Jul 9 10:57:04 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tixy X-Patchwork-Id: 958982 Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) by demeter2.kernel.org (8.14.4/8.14.4) with ESMTP id p69B1kme020001 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Sat, 9 Jul 2011 11:02:07 GMT Received: from canuck.infradead.org ([2001:4978:20e::1]) by merlin.infradead.org with esmtps (Exim 4.76 #1 (Red Hat Linux)) id 1QfVGw-0002r0-FJ; Sat, 09 Jul 2011 11:00:32 +0000 Received: from localhost ([127.0.0.1] helo=canuck.infradead.org) by canuck.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1QfVGt-00052J-0u; Sat, 09 Jul 2011 11:00:27 +0000 Received: from casper.infradead.org ([2001:770:15f::2]) by canuck.infradead.org with esmtps (Exim 4.76 #1 (Red Hat Linux)) id 1QfVEU-0004P1-UF for linux-arm-kernel@canuck.infradead.org; Sat, 09 Jul 2011 10:57:59 +0000 Received: from smarthost02.mail.zen.net.uk ([212.23.3.141]) by casper.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1QfVEP-0006Cj-Gt for linux-arm-kernel@lists.infradead.org; Sat, 09 Jul 2011 10:57:57 +0000 Received: from [82.69.122.217] (helo=plug1) by smarthost02.mail.zen.net.uk with esmtpsa (TLS-1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.63) (envelope-from ) id 1QfVEN-0005hQ-SR for linux-arm-kernel@lists.infradead.org; Sat, 09 Jul 2011 10:57:52 +0000 Received: from [192.168.2.20] (helo=computer2) by plug1 with esmtp (Exim 4.72) (envelope-from ) id 1QfVEL-0003gw-Me for linux-arm-kernel@lists.infradead.org; Sat, 09 Jul 2011 11:57:49 +0100 Received: from tixy by computer2 with local (Exim 4.72) (envelope-from ) id 1QfVEL-0005Tu-II for linux-arm-kernel@lists.infradead.org; Sat, 09 Jul 2011 11:57:49 +0100 From: Tixy To: linux-arm-kernel@lists.infradead.org Subject: [PATCH 17/51] ARM: kprobes: Add hooks to override singlestep() Date: Sat, 9 Jul 2011 11:57:04 +0100 Message-Id: <1310209058-20980-18-git-send-email-tixy@yxit.co.uk> X-Mailer: git-send-email 1.7.2.5 In-Reply-To: <1310209058-20980-1-git-send-email-tixy@yxit.co.uk> References: <1310209058-20980-1-git-send-email-tixy@yxit.co.uk> X-Originating-Smarthost02-IP: [82.69.122.217] X-CRM114-Version: 20090807-BlameThorstenAndJenny ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20110709_115753_851338_DEFA89A0 X-CRM114-Status: GOOD ( 19.81 ) X-Spam-Score: -1.9 (-) X-Spam-Report: SpamAssassin version 3.3.2-r929478 on casper.infradead.org summary: Content analysis details: (-1.9 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at http://www.dnswl.org/, no trust [212.23.3.141 listed in list.dnswl.org] -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: linux-arm-kernel-bounces@lists.infradead.org Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter2.kernel.org [140.211.167.43]); Sat, 09 Jul 2011 11:02:07 +0000 (UTC) From: Jon Medhurst When a probe fires we must single-step the instruction which was replaced by a breakpoint. As the steps to do this vary between ARM and Thumb instructions we need a way to customise single-stepping. This is done by adding a new hook called insn_singlestep to arch_specific_insn which is initialised by the instruction decoding functions. These single-step hooks must update PC and call the instruction handler. For Thumb instructions an additional step of updating ITSTATE is needed. We do this after calling the handler because some handlers will need to test if they are running in an IT block. Signed-off-by: Jon Medhurst --- arch/arm/include/asm/kprobes.h | 9 +++++---- arch/arm/kernel/kprobes-arm.c | 7 +++++++ arch/arm/kernel/kprobes-thumb.c | 16 ++++++++++++++++ arch/arm/kernel/kprobes.c | 8 +++----- 4 files changed, 31 insertions(+), 9 deletions(-) diff --git a/arch/arm/include/asm/kprobes.h b/arch/arm/include/asm/kprobes.h index 57d37d5..1e9ff56 100644 --- a/arch/arm/include/asm/kprobes.h +++ b/arch/arm/include/asm/kprobes.h @@ -32,14 +32,15 @@ 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 *); /* 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_opcode_t *insn; + kprobe_insn_handler_t *insn_handler; + kprobe_check_cc *insn_check_cc; + kprobe_insn_singlestep_t *insn_singlestep; }; struct prev_kprobe { diff --git a/arch/arm/kernel/kprobes-arm.c b/arch/arm/kernel/kprobes-arm.c index 0262b29..a1143e8 100644 --- a/arch/arm/kernel/kprobes-arm.c +++ b/arch/arm/kernel/kprobes-arm.c @@ -1494,6 +1494,12 @@ space_cccc_11xx(kprobe_opcode_t insn, struct arch_specific_insn *asi) return INSN_REJECTED; } +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, @@ -1509,6 +1515,7 @@ space_cccc_11xx(kprobe_opcode_t insn, struct arch_specific_insn *asi) 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]; asi->insn[1] = KPROBE_RETURN_INSTRUCTION; diff --git a/arch/arm/kernel/kprobes-thumb.c b/arch/arm/kernel/kprobes-thumb.c index 24a188b..973c3eb 100644 --- a/arch/arm/kernel/kprobes-thumb.c +++ b/arch/arm/kernel/kprobes-thumb.c @@ -33,9 +33,24 @@ static unsigned long __kprobes thumb_check_cc(unsigned long 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 INSN_REJECTED; } @@ -43,6 +58,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) { + asi->insn_singlestep = thumb32_singlestep; asi->insn_check_cc = thumb_check_cc; return INSN_REJECTED; } diff --git a/arch/arm/kernel/kprobes.c b/arch/arm/kernel/kprobes.c index 9104b03..3c5ed77 100644 --- a/arch/arm/kernel/kprobes.c +++ b/arch/arm/kernel/kprobes.c @@ -227,12 +227,10 @@ singlestep_skip(struct kprobe *p, struct pt_regs *regs) #endif } -static void __kprobes singlestep(struct kprobe *p, struct pt_regs *regs, - struct kprobe_ctlblk *kcb) +static inline void __kprobes +singlestep(struct kprobe *p, struct pt_regs *regs, struct kprobe_ctlblk *kcb) { - regs->ARM_pc += 4; - if (p->ainsn.insn_check_cc(regs->ARM_cpsr)) - p->ainsn.insn_handler(p, regs); + p->ainsn.insn_singlestep(p, regs); } /*