sigreturn.S (3040B)
1/* SPDX-License-Identifier: GPL-2.0-only */ 2/* 3 * Sigreturn trampoline for returning from a signal when the SA_RESTORER 4 * flag is not set. It serves primarily as a hall of shame for crappy 5 * unwinders and features an exciting but mysterious NOP instruction. 6 * 7 * It's also fragile as hell, so please think twice before changing anything 8 * in here. 9 * 10 * Copyright (C) 2012 ARM Limited 11 * 12 * Author: Will Deacon <will.deacon@arm.com> 13 */ 14 15#include <linux/linkage.h> 16#include <asm/assembler.h> 17#include <asm/unistd.h> 18 19 .text 20 21/* 22 * NOTE!!! You may notice that all of the .cfi directives in this file have 23 * been commented out. This is because they have been shown to trigger segfaults 24 * in libgcc when unwinding out of a SIGCANCEL handler to invoke pthread 25 * cleanup handlers during the thread cancellation dance. By omitting the 26 * directives, we trigger an arm64-specific fallback path in the unwinder which 27 * recognises the signal frame and restores many of the registers directly from 28 * the sigcontext. Re-enabling the cfi directives here therefore needs to be 29 * much more comprehensive to reduce the risk of further regressions. 30 */ 31 32/* Ensure that the mysterious NOP can be associated with a function. */ 33// .cfi_startproc 34 35/* 36 * .cfi_signal_frame causes the corresponding Frame Description Entry (FDE) in 37 * the .eh_frame section to be annotated as a signal frame. This allows DWARF 38 * unwinders (e.g. libstdc++) to implement _Unwind_GetIPInfo() and identify 39 * the next frame using the unmodified return address instead of subtracting 1, 40 * which may yield the wrong FDE. 41 */ 42// .cfi_signal_frame 43 44/* 45 * Tell the unwinder where to locate the frame record linking back to the 46 * interrupted context. We don't provide unwind info for registers other than 47 * the frame pointer and the link register here; in practice, this is likely to 48 * be insufficient for unwinding in C/C++ based runtimes, especially without a 49 * means to restore the stack pointer. Thankfully, unwinders and debuggers 50 * already have baked-in strategies for attempting to unwind out of signals. 51 */ 52// .cfi_def_cfa x29, 0 53// .cfi_offset x29, 0 * 8 54// .cfi_offset x30, 1 * 8 55 56/* 57 * This mysterious NOP is required for some unwinders (e.g. libc++) that 58 * unconditionally subtract one from the result of _Unwind_GetIP() in order to 59 * identify the calling function. 60 * Hack borrowed from arch/powerpc/kernel/vdso64/sigtramp.S. 61 */ 62 nop // Mysterious NOP 63 64/* 65 * GDB, libgcc and libunwind rely on being able to identify the sigreturn 66 * instruction sequence to unwind from signal handlers. We cannot, therefore, 67 * use SYM_FUNC_START() here, as it will emit a BTI C instruction and break the 68 * unwinder. Thankfully, this function is only ever called from a RET and so 69 * omitting the landing pad is perfectly fine. 70 */ 71SYM_CODE_START(__kernel_rt_sigreturn) 72// PLEASE DO NOT MODIFY 73 mov x8, #__NR_rt_sigreturn 74// PLEASE DO NOT MODIFY 75 svc #0 76// PLEASE DO NOT MODIFY 77// .cfi_endproc 78SYM_CODE_END(__kernel_rt_sigreturn) 79 80emit_aarch64_feature_1_and