From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754408AbcFPLWM (ORCPT ); Thu, 16 Jun 2016 07:22:12 -0400 Received: from szxga04-in.huawei.com ([119.145.14.52]:32297 "EHLO szxga04-in.huawei.com" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S1754155AbcFPLWF (ORCPT ); Thu, 16 Jun 2016 07:22:05 -0400 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> <5752BCC8.7080205@huawei.com> <20160612174430.GA12067@yury-N73SV> CC: , , , , , , , , , , , , , , , , , , , , , , "Andrew Pinski" , Andrew Pinski , Hanjun Guo , "Zhangjian (Bamvor)" From: "Zhangjian (Bamvor)" Message-ID: <57628BB2.7080100@huawei.com> Date: Thu, 16 Jun 2016 19:21:22 +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: <20160612174430.GA12067@yury-N73SV> Content-Type: text/plain; charset="windows-1252"; format=flowed Content-Transfer-Encoding: 7bit X-Originating-IP: [10.111.72.170] X-CFilter-Loop: Reflected X-Mirapoint-Virus-RAPID-Raw: score=unknown(0), refid=str=0001.0A090201.57628BC3.0078,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: 17951ba79ac8b4969aa89c8fe62dfbac Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Hi, On 2016/6/13 1:44, Yury Norov wrote: > Hi Bamvor, > > Sorry, I missed this patch. > > On Sat, Jun 04, 2016 at 07:34:32PM +0800, Zhangjian (Bamvor) wrote: >> 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: >> >> 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; > > I think you are right here. The only nitpick is what for we send 2 > offsets just to add one to another inside setup_return()? > We can do like this: > > void setup_return(struct pt_regs *regs, struct k_sigaction *ka, > void __user *frame, off_t fp_off, int usig) > { > __sigrestore_t sigtramp; > > regs->regs[0] = usig; > regs->sp = (unsigned long)frame; > regs->regs[29] = regs->sp + fp_off; > [...] > } > > Where fp_off calculation is done by caller. > > setup_return(regs, &ksig->ka, frame, > offsetof(struct rt_sigframe, sig) + offsetof(struct sigframe, fp), > usig); > > For me it's more clear to understand what happens with this approach. > I don't think struct rt_sigframe will grow, but we can even introduce > some helper for it: > #define RT_SIGFRAME_FP_POS (offsetof(struct rt_sigframe, sig) + offsetof(struct sigframe, fp)) > > If no objections, I'll apply your patch with my fix in next series. Sure. Thanks. Regards Bamvor > >> 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; >> } >> -- >> 1.8.4.5 >> >> Regards >> >> Bamvor >> >>