[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