[PATCH 0/6] Fix unwinding through sigreturn trampolines
Ard Biesheuvel
ardb at kernel.org
Mon Jul 6 05:41:29 EDT 2020
On Mon, 6 Jul 2020 at 12:29, Daniel Kiss <Daniel.Kiss at arm.com> wrote:
>
> Hi Ard,
>
> I like your suggestions and tuned a bit and now it works with the LLVM’s unwinders.
>
> Register 96 is out of the DWARF spec[1] and will collide with SVE registers[2] so 32 is better which is the reserved register for PC.
>
I just copied that from libgcc's implementation, so using the existing
reserved register for that indeed seems like a much better approach.
The only remaining question is how to deal with FP/SIMD and SVE
registers, but given Szabolcs's assertion that exceptions thrown in
signal handlers cannot be caught outside of them anyway, this does not
seem like a huge deal, with the exception of the nested function case
for pthread cleanup handlers but perhaps the solution for that is
'don't do that'.
> my version:
>
> #define ARM64_SIGFRAME_REGS_OFFSET 312 /* offsetof (struct rt_sigframe, uc.uc_mcontext.regs) */
>
> .text
> .cfi_startproc
> .cfi_signal_frame
>
> .cfi_def_cfa sp, ARM64_SIGFRAME_REGS_OFFSET
> .irp x, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, \
> 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, \
> 24, 25, 26, 27, 28, 29, 30, 31
> .cfi_offset \x, \x * 8
> .endr
>
> .cfi_offset 32, 32 * 8 // regs->pc
> .cfi_return_column 32
>
> nop
> ENTRY(__kernel_rt_sigreturn)
> mov x8, #__NR_rt_sigreturn
> svc #0
> .cfi_endproc
> ENDPROC(__kernel_rt_sigreturn)
>
> [1] https://developer.arm.com/documentation/ihi0057/e
> [2] https://developer.arm.com/documentation/100985/0000/
>
> >
> >
> >> On 23 Jun 2020, at 17:43, Ard Biesheuvel <ardb at kernel.org> wrote:
> >>
> >> On Tue, 23 Jun 2020 at 17:34, Daniel Kiss <Daniel.Kiss at arm.com> wrote:
> >>>
> >>> Hi Will,
> >>>
> >>> The CFI is correct for PowerPC[1] and X86[2] at least; I did not check others.
> >>> so LLVM’s unwinder can unwind/backtrace sigreturn without any specific hack on those architectures.
> >>> The a4eb355a3fda change implements the same CFI as PowerPC and X86 have so the generic unwind logic is able to process the sigreturn.
> >>
> >> It most certainly did not implement the same CFI. The x86 and PowerPC
> >> examples you quote have elaborate asm foo to emit the eh_frame by
> >> hand.
> >>
> >>> IMHO the kernel change was fine.
> >>>
> >>
> >> It creates easily reproducible segfaults in the libgcc unwinder.
> >>
> >>> I’m not comfortable to say the instruction sequence is the ABI that describe the unwinding information.
> >>> I guess the pattern matching was implemented due to the CFI was wrong.
> >>>
> >>> The .cfi_signal_frame could be useful once the entry is found, but needs the right .CFI annotations at the right place.
> >>>
> >>> This change definitely a not good for LLVM’s unwinder.
> >>>
> >>
> >> I agree that it would be better for the CFI to be correct, but that
> >> takes a bit of work at the very least, and even then, the variable
> >> nature of our sigframe may make it impossible to restore the FP/SIMD
> >> register state reliably.
> >>
> >> I did some tests with the below CFI directives, where
> >> ARM64_SIGFRAME_REGS_OFFSET is emitted by asm-offsets as the offset
> >> from the top of the sigframe to the regs[] array. This fixes the
> >> segfaults, and seems to do the right thing if i single step through
> >> the unwinder as it unwinds the stack in response to a call to
> >> pthread_cancel(). But we need a lot of testing to ensure that this is
> >> correct.
> >>
> >>
> >> .cfi_def_cfa_offset ARM64_SIGFRAME_REGS_OFFSET
> >> .irp r, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, \
> >> 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, \
> >> 24, 25, 26, 27, 28, 29, 30, 31
> >> .cfi_offset \r, \r * 8
> >> .endr
> >>
> >> .cfi_offset 96, 32 * 8 // regs->pc
> >> .cfi_return_column 96
> >
>
More information about the linux-arm-kernel
mailing list