mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-04 04:02:26 +00:00
5854e4d853
When using the frame pointer unwinder, it was found that the stack trace output of stack_trace_save() is incomplete if the stack contains call_with_stack(): [0x7f00002c] dump_stack_task+0x2c/0x90 [hrtimer] [0x7f0000a0] hrtimer_hander+0x10/0x18 [hrtimer] [0x801a67f0] __hrtimer_run_queues+0x1b0/0x3b4 [0x801a7350] hrtimer_run_queues+0xc4/0xd8 [0x801a597c] update_process_times+0x3c/0x88 [0x801b5a98] tick_periodic+0x50/0xd8 [0x801b5bf4] tick_handle_periodic+0x24/0x84 [0x8010ffc4] twd_handler+0x38/0x48 [0x8017d220] handle_percpu_devid_irq+0xa8/0x244 [0x80176e9c] generic_handle_domain_irq+0x2c/0x3c [0x8052e3a8] gic_handle_irq+0x7c/0x90 [0x808ab15c] generic_handle_arch_irq+0x60/0x80 [0x8051191c] call_with_stack+0x1c/0x20 For the frame pointer unwinder, unwind_frame() checks stackframe::fp by stackframe::sp. Since call_with_stack() switches the SP from one stack to another, stackframe::fp and stackframe: :sp will point to different stacks, so we can no longer check stackframe::fp by stackframe::sp. Skip checking stackframe::fp at this point to avoid this problem. Signed-off-by: Li Huafei <lihuafei1@huawei.com> Reviewed-by: Linus Waleij <linus.walleij@linaro.org> Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
52 lines
1.1 KiB
ArmAsm
52 lines
1.1 KiB
ArmAsm
/* SPDX-License-Identifier: GPL-2.0-only */
|
|
/*
|
|
* arch/arm/lib/call_with_stack.S
|
|
*
|
|
* Copyright (C) 2011 ARM Ltd.
|
|
* Written by Will Deacon <will.deacon@arm.com>
|
|
*/
|
|
|
|
#include <linux/linkage.h>
|
|
#include <asm/assembler.h>
|
|
#include <asm/unwind.h>
|
|
|
|
/*
|
|
* void call_with_stack(void (*fn)(void *), void *arg, void *sp)
|
|
*
|
|
* Change the stack to that pointed at by sp, then invoke fn(arg) with
|
|
* the new stack.
|
|
*
|
|
* The sequence below follows the APCS frame convention for frame pointer
|
|
* unwinding, and implements the unwinder annotations needed by the EABI
|
|
* unwinder.
|
|
*/
|
|
|
|
ENTRY(call_with_stack)
|
|
#if defined(CONFIG_UNWINDER_FRAME_POINTER) && defined(CONFIG_CC_IS_GCC)
|
|
mov ip, sp
|
|
push {fp, ip, lr, pc}
|
|
sub fp, ip, #4
|
|
#else
|
|
UNWIND( .fnstart )
|
|
UNWIND( .save {fpreg, lr} )
|
|
push {fpreg, lr}
|
|
UNWIND( .setfp fpreg, sp )
|
|
mov fpreg, sp
|
|
#endif
|
|
mov sp, r2
|
|
mov r2, r0
|
|
mov r0, r1
|
|
|
|
bl_r r2
|
|
|
|
#if defined(CONFIG_UNWINDER_FRAME_POINTER) && defined(CONFIG_CC_IS_GCC)
|
|
ldmdb fp, {fp, sp, pc}
|
|
#else
|
|
mov sp, fpreg
|
|
pop {fpreg, pc}
|
|
UNWIND( .fnend )
|
|
#endif
|
|
.globl call_with_stack_end
|
|
call_with_stack_end:
|
|
ENDPROC(call_with_stack)
|