[PATCH v2 8/9] ARM: call_with_stack: add unwind support
Arnd Bergmann
arnd at arndb.de
Tue Oct 5 05:22:03 PDT 2021
On Tue, Oct 5, 2021 at 9:15 AM Ard Biesheuvel <ardb at kernel.org> wrote:
>
> Restructure the code and add the unwind annotations so that both the
> frame pointer unwinder as well as the ELF unwind info based unwinder
> will be able to follow the call stack through call_with_stack().
>
> Note that the former cannot support GCC and Clang at the same time, as
> they use a different idiom for the prologue/epilogue. So the code uses
> the GCC idiom, adding full frame pointer based unwind support for GCC
> while preserving the existing behavior of the Clang version, which
> simply omits call_with_stack() from its call stack.
>
> Signed-off-by: Ard Biesheuvel <ardb at kernel.org>
I would like Nick to take a look at this for the clang support, he spent
some time on getting the frame pointer unwinder working with clang,
so he may have additional comments about this.
> ---
> arch/arm/lib/call_with_stack.S | 44 +++++++++++++++++---
> 1 file changed, 38 insertions(+), 6 deletions(-)
>
> diff --git a/arch/arm/lib/call_with_stack.S b/arch/arm/lib/call_with_stack.S
> index 28b0341ae786..133dffa2404a 100644
> --- a/arch/arm/lib/call_with_stack.S
> +++ b/arch/arm/lib/call_with_stack.S
> @@ -8,25 +8,57 @@
>
> #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.
> + */
> +
> +#if defined(CONFIG_THUMB2_KERNEL) || \
> + (defined(CONFIG_UNWINDER_FRAME_POINTER) && defined(CONFIG_CC_IS_CLANG))
> +/*
> + * Thumb-2 builds must use R7 as the frame pointer due to the way our unwind
> + * info based unwinder is constructed.
> + *
> + * The code below uses the GCC idiom for managing the frame pointer in the
> + * function prologue and epilogue, which Clang does not support. So the best we
> + * can do here is not touch the frame pointer at all: this will simply omit
> + * this frame when unwinding the call stack. So use R7 in this case as well,
> + * and leave R11 unmodified.
> */
> + fpreg .req r7
> +#else
> + fpreg .req fp
> +#endif
> +
> ENTRY(call_with_stack)
> - str sp, [r2, #-4]!
> - str lr, [r2, #-4]!
> +UNWIND( .fnstart )
> +UNWIND( .movsp ip )
> + mov ip, sp
> +
> +UNWIND( .pad #4 )
> +UNWIND( .save {fpreg, ip, lr} )
> +THUMB( sub sp, #4 )
> + push {fpreg, ip, lr ARM(, pc)}
> +
> +UNWIND( .setfp fpreg, ip, #-4 )
> + sub fpreg, ip, #4
>
> mov sp, r2
> mov r2, r0
> mov r0, r1
>
> - badr lr, 1f
> - ret r2
> + bl_r r2
>
> -1: ldr lr, [sp]
> - ldr sp, [sp, #4]
> + ldmdb fpreg, {fpreg, ip, lr}
> + mov sp, ip
> ret lr
> +UNWIND( .fnend )
> ENDPROC(call_with_stack)
> --
> 2.30.2
>
More information about the linux-arm-kernel
mailing list