From patchwork Sat Jun 4 11:34:32 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: zhangjian X-Patchwork-Id: 9154571 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 3D89160574 for ; Sat, 4 Jun 2016 11:38:08 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 18A7628327 for ; Sat, 4 Jun 2016 11:38:08 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id F003C28331; Sat, 4 Jun 2016 11:38:07 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.2 required=2.0 tests=BAYES_00, RCVD_IN_DNSWL_MED autolearn=unavailable version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 8C67028327 for ; Sat, 4 Jun 2016 11:38:07 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1b99sW-0003Pz-Q8; Sat, 04 Jun 2016 11:36:32 +0000 Received: from [58.251.152.179] (helo=szxga05-in.huawei.com) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1b99sS-0003P5-HG for linux-arm-kernel@lists.infradead.org; Sat, 04 Jun 2016 11:36:30 +0000 Received: from 172.24.1.45 (EHLO lggeml427-hub.china.huawei.com) ([172.24.1.45]) by szxrg05-dlp.huawei.com (MOS 4.4.6-GA FastPath queued) with ESMTP id BDD59320; Sat, 04 Jun 2016 19:23:23 +0800 (CST) Received: from [127.0.0.1] (10.111.72.170) by lggeml427-hub.china.huawei.com (10.72.61.79) with Microsoft SMTP Server id 14.3.235.1; Sat, 4 Jun 2016 19:34:46 +0800 Subject: Re: [PATCH 21/23] arm64: ilp32: introduce ilp32-specific handlers for sigframe and ucontext To: Yury Norov , , , , , , , , References: <1464048292-30136-1-git-send-email-ynorov@caviumnetworks.com> <1464048292-30136-22-git-send-email-ynorov@caviumnetworks.com> From: "Zhangjian (Bamvor)" Message-ID: <5752BCC8.7080205@huawei.com> Date: Sat, 4 Jun 2016 19:34:32 +0800 User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:38.0) Gecko/20100101 Thunderbird/38.1.0 MIME-Version: 1.0 In-Reply-To: <1464048292-30136-22-git-send-email-ynorov@caviumnetworks.com> X-Originating-IP: [10.111.72.170] X-CFilter-Loop: Reflected X-Mirapoint-Virus-RAPID-Raw: score=unknown(0), refid=str=0001.0A090201.5752BCE6.0038, ss=1, re=0.000, recu=0.000, reip=0.000, cl=1, cld=1, fgs=0, ip=0.0.0.0, so=2014-11-16 11:51:01, dmn=2013-03-21 17:37:32 X-Mirapoint-Loop-Id: 557a03b21d7f8a6874efd96c9e673120 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20160604_043629_126082_D5342BBF X-CRM114-Status: GOOD ( 14.31 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kilobyte@angband.pl, pinskia@gmail.com, szabolcs.nagy@arm.com, Nathan_Lynch@mentor.com, heiko.carstens@de.ibm.com, agraf@suse.de, Prasun.Kapoor@caviumnetworks.com, klimov.linux@gmail.com, Andrew Pinski , broonie@kernel.org, geert@linux-m68k.org, Andrew Pinski , Hanjun Guo , schwidefsky@de.ibm.com, "Zhangjian \(Bamvor\)" , philipp.tomsich@theobroma-systems.com, joseph@codesourcery.com, christoph.muellner@theobroma-systems.com Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP Hi, I found an issue of unwind with the following code. The correct backtrace should be: (gdb) where #0 0x004004d0 in my_sig (sig=11) at test_force3.c:16 #1 #2 func2 (num=0) at test_force3.c:22 #3 0x00400540 in func1 (num=1) at test_force3.c:28 #4 0x00400574 in main (argc=1, argv=0xffd7bc04) at test_force3.c:33 Without my patch, the backtrace is: (gdb) where #0 0x00400490 in my_sig (sig=11) at test_force3.c:16 #1 #2 0x004004e4 in main (argc=1, argv=0xffe6f8f4) at test_force3.c:33 With my patch which fix the wrong frame pointer(setup_return calculate the offset of fp through ilp32_sigframe instead of sigfreame), the backtrace is: (gdb) where #0 0x00400490 in my_sig (sig=11) at test_force3.c:16 #1 #2 func1 () at test_force3.c:28 #3 0x004004e4 in main (argc=1, argv=0xffe6f8f4) at test_force3.c:33 I am not sure there is still some issue in kernel. But it seem that the gdb of ilp32 does not work correctly when unwind without framepointer. The test code is: #include #include #include #include void my_sig(int sig) { printf("sig=%d\n", sig); *(int *)0 = 0x0; } void func2() { *(int *)0 = 0x0; } void func1() { func2(); } int main(int argc, char **argv) { signal(11, my_sig); func1(); return 0; } The full patch is as follows: From 7e364a765097f57aed2d73f94c1688c2e7343e79 Mon Sep 17 00:00:00 2001 From: Bamvor Jian Zhang Date: Sat, 4 Jun 2016 14:30:05 +0800 Subject: [PATCH] arm64: ilp32: fix for wrong fp offset when calculate the new fp ILP32 define its own sigframe(ilp32_sigframe) because of the difference uc_context. setup_return do not use ilp32 specific sigframe to calculate the new offset of fp which lead to wrong fp in signal handler. At this circumstance, gdb backtrace will miss one item: (gdb) where It should be: (gdb) where The test code is as follows: void my_sig(int sig) { printf("sig=%d\n", sig); *(int *)0 = 0x0; } void func2(int num) { printf("%s: %d\n", __FUNCTION__, num); *(int *)0 = 0x0; func2(num-1); } void func1(int num) { printf("%s\n", __FUNCTION__); func2(num - 1); } int main(int argc, char **argv) { signal(11, my_sig); func1(argc); return 0; } This patch fix this by passing the correct offset of fp to setup_return. Test pass on both ILP32 and LP64 in aarch64 EE. Signed-off-by: Bamvor Jian Zhang --- arch/arm64/include/asm/signal_common.h | 3 ++- arch/arm64/kernel/signal.c | 9 +++++---- arch/arm64/kernel/signal_ilp32.c | 4 ++-- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/arch/arm64/include/asm/signal_common.h b/arch/arm64/include/asm/signal_common.h index de93c71..a5d7b63 100644 --- a/arch/arm64/include/asm/signal_common.h +++ b/arch/arm64/include/asm/signal_common.h @@ -29,6 +29,7 @@ int setup_sigcontex(struct sigcontext __user *uc_mcontext, struct pt_regs *regs); int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sf); void setup_return(struct pt_regs *regs, struct k_sigaction *ka, - void __user *frame, off_t sigframe_off, int usig); + void __user *frame, off_t sigframe_off, off_t fp_off, + int usig); #endif /* __ASM_SIGNAL_COMMON_H */ diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c index 038bebe..e66a6e9 100644 --- a/arch/arm64/kernel/signal.c +++ b/arch/arm64/kernel/signal.c @@ -256,14 +256,14 @@ static struct rt_sigframe __user *get_sigframe(struct ksignal *ksig, } void setup_return(struct pt_regs *regs, struct k_sigaction *ka, - void __user *frame, off_t sigframe_off, int usig) + void __user *frame, off_t sigframe_off, off_t fp_off, + int usig) { __sigrestore_t sigtramp; regs->regs[0] = usig; regs->sp = (unsigned long)frame; - regs->regs[29] = regs->sp + sigframe_off + - offsetof(struct sigframe, fp); + regs->regs[29] = regs->sp + sigframe_off + fp_off; regs->pc = (unsigned long)ka->sa.sa_handler; if (ka->sa.sa_flags & SA_RESTORER) @@ -294,7 +294,8 @@ static int setup_rt_frame(int usig, struct ksignal *ksig, sigset_t *set, err |= setup_sigframe(&frame->sig, regs, set); if (err == 0) { setup_return(regs, &ksig->ka, frame, - offsetof(struct rt_sigframe, sig), usig); + offsetof(struct rt_sigframe, sig), + offsetof(struct sigframe, fp), usig); if (ksig->ka.sa.sa_flags & SA_SIGINFO) { err |= copy_siginfo_to_user(&frame->info, &ksig->info); regs->regs[1] = (unsigned long)&frame->info; diff --git a/arch/arm64/kernel/signal_ilp32.c b/arch/arm64/kernel/signal_ilp32.c index a8ea73e..9030f14 100644 --- a/arch/arm64/kernel/signal_ilp32.c +++ b/arch/arm64/kernel/signal_ilp32.c @@ -147,7 +147,6 @@ static struct ilp32_rt_sigframe __user *ilp32_get_sigframe(struct ksignal *ksig, struct ilp32_rt_sigframe __user *frame; sp = sp_top = sigsp(regs->sp, ksig); - sp = (sp - sizeof(struct ilp32_rt_sigframe)) & ~15; frame = (struct ilp32_rt_sigframe __user *)sp; @@ -183,7 +182,8 @@ int ilp32_setup_rt_frame(int usig, struct ksignal *ksig, err |= setup_ilp32_sigframe(&frame->sig, regs, set); if (err == 0) { setup_return(regs, &ksig->ka, frame, - offsetof(struct ilp32_rt_sigframe, sig), usig); + offsetof(struct ilp32_rt_sigframe, sig), + offsetof(struct ilp32_sigframe, fp), usig); regs->regs[1] = (unsigned long)&frame->info; regs->regs[2] = (unsigned long)&frame->sig.uc; }