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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
// Kernel-ABI signal-return trampoline for Linux/x86_64.
//
// On x86_64 the kernel's `__setup_rt_frame` (arch/x86/kernel/signal_64.c)
// requires `SA_RESTORER` set and `sa_restorer` pointing at a userspace
// `rt_sigreturn(2)` trampoline — otherwise it returns `-EFAULT` and the
// process gets `SIGSEGV` on signal-handler return. glibc and musl ship
// `__restore_rt`; we ship our own equivalent here so that we own the kernel
// ABI end-to-end and are not implicitly dependent on libc.
//
// Two-instruction trampoline. Stack is already pointing at the rt_sigframe
// the kernel set up before jumping to the handler; `rt_sigreturn` reads it.
//
// `.cfi_signal_frame` tells gdb / perf / Rust unwinders that this is a
// signal trampoline so backtraces step past the interrupted context
// correctly. `.hidden` keeps the symbol private to this binary.
//
// Note: aarch64 and riscv64 have no userspace restorer. On aarch64 the
// kernel sets x30 (LR) to the vDSO `__kernel_rt_sigreturn` trampoline;
// on riscv64 the kernel similarly routes signal-return through the vDSO.
// `<asm-generic/signal.h>` does not include `sa_restorer` for either arch
// because `__ARCH_HAS_SA_RESTORER` is undefined. No trampoline is needed
// or possible on those architectures — the kernel/vDSO owns the path.
//
// References:
// * arch/x86/kernel/signal_64.c::__setup_rt_frame
// * arch/x86/entry/syscalls/syscall_64.tbl (__NR_rt_sigreturn = 15)
// * glibc sysdeps/unix/sysv/linux/x86_64/sigaction.c::restore_rt
// * musl src/signal/x86_64/restore.s
global_asm!;
extern "C"