linux/arch/loongarch/kernel
Xi Ruoyao e4878c37f6 LoongArch: vDSO: Emit GNU_EH_FRAME correctly
With -fno-asynchronous-unwind-tables and --no-eh-frame-hdr (the default
of the linker), the GNU_EH_FRAME segment (specified by vdso.lds.S) is
empty.  This is not valid, as the current DWARF specification mandates
the first byte of the EH frame to be the version number 1.  It causes
some unwinders to complain, for example the ClickHouse query profiler
spams the log with messages:

    clickhouse-server[365854]: libunwind: unsupported .eh_frame_hdr
    version: 127 at 7ffffffb0000

Here "127" is just the byte located at the p_vaddr (0, i.e. the
beginning of the vDSO) of the empty GNU_EH_FRAME segment. Cross-
checking with /proc/365854/maps has also proven 7ffffffb0000 is the
start of vDSO in the process VM image.

In LoongArch the -fno-asynchronous-unwind-tables option seems just a
MIPS legacy, and MIPS only uses this option to satisfy the MIPS-specific
"genvdso" program, per the commit cfd75c2db1 ("MIPS: VDSO: Explicitly
use -fno-asynchronous-unwind-tables").  IIRC it indicates some inherent
limitation of the MIPS ELF ABI and has nothing to do with LoongArch.  So
we can simply flip it over to -fasynchronous-unwind-tables and pass
--eh-frame-hdr for linking the vDSO, allowing the profilers to unwind the
stack for statistics even if the sample point is taken when the PC is in
the vDSO.

However simply adjusting the options above would exploit an issue: when
the libgcc unwinder saw the invalid GNU_EH_FRAME segment, it silently
falled back to a machine-specific routine to match the code pattern of
rt_sigreturn() and extract the registers saved in the sigframe if the
code pattern is matched.  As unwinding from signal handlers is vital for
libgcc to support pthread cancellation etc., the fall-back routine had
been silently keeping the LoongArch Linux systems functioning since
Linux 5.19.  But when we start to emit GNU_EH_FRAME with the correct
format, fall-back routine will no longer be used and libgcc will fail
to unwind the sigframe, and unwinding from signal handlers will no
longer work, causing dozens of glibc test failures.  To make it possible
to unwind from signal handlers again, it's necessary to code the unwind
info in __vdso_rt_sigreturn via .cfi_* directives.

The offsets in the .cfi_* directives depend on the layout of struct
sigframe, notably the offset of sigcontext in the sigframe.  To use the
offset in the assembly file, factor out struct sigframe into a header to
allow asm-offsets.c to output the offset for assembly.

To work around a long-term issue in the libgcc unwinder (the pc is
unconditionally substracted by 1: doing so is technically incorrect for
a signal frame), a nop instruction is included with the two real
instructions in __vdso_rt_sigreturn in the same FDE PC range.  The same
hack has been used on x86 for a long time.

Cc: stable@vger.kernel.org
Fixes: c6b99bed6b ("LoongArch: Add VDSO and VSYSCALL support")
Signed-off-by: Xi Ruoyao <xry111@xry111.site>
Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
2026-03-26 14:29:09 +08:00
..
.gitignore
Makefile LoongArch: Add ELF binary support for kexec_file 2025-10-02 22:39:08 +08:00
Makefile.syscalls LoongArch: Wire up memfd_secret system call 2026-02-10 19:31:12 +08:00
access-helper.h LoongArch: Add exception/interrupt handling 2022-06-03 20:09:28 +08:00
acpi.c LoongArch: Fix build warnings about export.h 2025-06-26 20:07:18 +08:00
alternative.c LoongArch: Fix build warnings about export.h 2025-06-26 20:07:18 +08:00
asm-offsets.c LoongArch: vDSO: Emit GNU_EH_FRAME correctly 2026-03-26 14:29:09 +08:00
cacheinfo.c LoongArch: Correct the cacheinfo sharing information 2025-01-25 18:51:33 +08:00
cpu-probe.c LoongArch: Add detection for SC.Q support 2026-02-10 19:31:06 +08:00
crash_dump.c LoongArch: Add kdump support 2022-10-12 16:36:19 +08:00
dma.c dma-mapping: Add helpers for dma_range_map bounds 2024-04-26 12:07:24 +02:00
efi-header.S LoongArch: Adjust boot & setup for 32BIT/64BIT 2025-12-08 18:09:17 +08:00
efi.c efi: Support EDID information 2025-12-16 14:40:51 +01:00
elf.c LoongArch: Fix build warnings about export.h 2025-06-26 20:07:18 +08:00
entry.S LoongArch: Adjust system call for 32BIT/64BIT 2025-12-08 18:09:17 +08:00
env.c LoongArch: Fix missing NULL checks for kstrdup() 2026-03-26 14:29:08 +08:00
fpu.S LoongArch: Adjust process management for 32BIT/64BIT 2025-12-08 18:09:17 +08:00
ftrace.c LoongArch/ftrace: Add basic support 2022-12-14 08:41:53 +08:00
ftrace_dyn.c LoongArch: ftrace: Use RCU in all users of __module_text_address(). 2025-03-10 11:54:45 +01:00
genex.S LoongArch: Move __arch_cpu_idle() to .cpuidle.text section 2025-05-14 22:17:52 +08:00
head.S LoongArch: Remove redundant code in head.S 2026-01-15 18:50:48 +08:00
hw_breakpoint.c LoongArch: Change 8 to 14 for LOONGARCH_MAX_{BRP,WRP} 2025-01-26 21:49:59 +08:00
idle.c LoongArch: Fix idle VS timer enqueue 2025-02-13 12:02:35 +08:00
image-vars.h sysfb: Replace screen_info with sysfb_primary_display 2025-12-16 14:12:44 +01:00
inst.c LoongArch: No need to flush icache if text copy failed 2026-03-16 10:36:01 +08:00
irq.c LoongArch: Switch to irq_set_nr_irqs() 2024-10-16 21:56:56 +02:00
jump_label.c LoongArch: Add jump-label implementation 2023-06-29 20:58:44 +08:00
kdebugfs.c LoongArch: Add debugfs entries to switch SFB/TSO state 2025-01-26 21:49:59 +08:00
kexec_efi.c LoongArch: kexec: Initialize the kexec_buf structure 2025-11-10 08:37:07 +08:00
kexec_elf.c LoongArch: kexec: Initialize the kexec_buf structure 2025-11-10 08:37:07 +08:00
kfpu.c LoongArch: Fix build warnings about export.h 2025-06-26 20:07:18 +08:00
kgdb.c LoongArch: Use IS_ERR_PCPU() macro for KGDB 2026-02-10 19:31:17 +08:00
kprobes.c LoongArch: Make the users of larch_insn_gen_break() constant 2024-07-20 22:41:07 +08:00
lbt.S LoongArch: Handle fp, lsx, lasx and lbt assembly symbols 2025-04-26 09:58:12 +08:00
machine_kexec.c LoongArch: Mask all interrupts during kexec/kdump 2025-11-20 14:42:05 +08:00
machine_kexec_file.c Convert 'alloc_flex' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00
mcount.S fgraph: Replace fgraph_ret_regs with ftrace_regs 2024-12-26 10:50:02 -05:00
mcount_dyn.S LoongArch: Refactor register restoration in ftrace_common_return 2025-12-31 15:19:20 +08:00
mem.c LoongArch: Consolidate max_pfn & max_low_pfn calculation 2025-11-10 08:37:06 +08:00
module-sections.c LoongArch: Adjust module loader for 32BIT/64BIT 2025-12-08 18:09:17 +08:00
module.c LoongArch: Adjust module loader for 32BIT/64BIT 2025-12-08 18:09:17 +08:00
numa.c LoongArch: Fix NUMA node parsing with numa_memblks 2025-11-20 14:42:05 +08:00
paravirt.c Loongarch: 2026-02-13 11:31:15 -08:00
perf_event.c LoongArch: Fix PMU counter allocation for mixed-type event groups 2026-01-17 10:56:43 +08:00
perf_regs.c LoongArch: Add perf events support 2022-10-12 16:36:14 +08:00
proc.c LoongArch: Replace seq_printf() with seq_puts() for simple strings 2026-02-10 19:31:12 +08:00
process.c LoongArch: Adjust process management for 32BIT/64BIT 2025-12-08 18:09:17 +08:00
ptrace.c LoongArch: Adjust process management for 32BIT/64BIT 2025-12-08 18:09:17 +08:00
relocate.c LoongArch: Adjust boot & setup for 32BIT/64BIT 2025-12-08 18:09:17 +08:00
relocate_kernel.S LoongArch: Make relocate_new_kernel_size be a .quad value 2025-08-03 22:49:47 +08:00
reset.c LoongArch: Fix idle VS timer enqueue 2025-02-13 12:02:35 +08:00
rethook.c LoongArch: Replace kretprobe with rethook 2023-06-29 20:58:44 +08:00
rethook.h LoongArch: Replace kretprobe with rethook 2023-06-29 20:58:44 +08:00
rethook_trampoline.S LoongArch: Add ORC stack unwinder support 2024-03-11 22:23:47 +08:00
setup.c treewide: Replace kmalloc with kmalloc_obj for non-scalar types 2026-02-21 01:02:28 -08:00
signal.c LoongArch: vDSO: Emit GNU_EH_FRAME correctly 2026-03-26 14:29:09 +08:00
smp.c LoongArch: Add HOTPLUG_SMT implementation 2026-02-10 19:31:13 +08:00
stacktrace.c LoongArch: Fix unreliable stack for live patching 2025-09-18 19:44:08 +08:00
switch.S LoongArch: Adjust process management for 32BIT/64BIT 2025-12-08 18:09:17 +08:00
syscall.c LoongArch: Adjust system call for 32BIT/64BIT 2025-12-08 18:09:17 +08:00
sysrq.c tty: sysrq: switch sysrq handlers from int to u8 2023-07-25 19:21:03 +02:00
time.c LoongArch: Adjust VDSO/VSYSCALL for 32BIT/64BIT 2025-12-08 18:09:17 +08:00
topology.c LoongArch: convert to use arch_cpu_is_hotpluggable() 2023-12-06 12:41:50 +09:00
traps.c LoongArch: Enable exception fixup for specific ADE subcode 2025-12-31 15:19:20 +08:00
unaligned.c LoongArch: Adjust misc routines for 32BIT/64BIT 2025-12-08 18:09:17 +08:00
unwind.c LoongArch: Set unwind stack type to unknown rather than set error flag 2023-12-09 15:49:15 +08:00
unwind_guess.c LoongArch: Fix build warnings about export.h 2025-06-26 20:07:18 +08:00
unwind_orc.c LoongArch: Remove some extern variables in source files 2026-02-10 19:31:14 +08:00
unwind_prologue.c LoongArch: Remove some extern variables in source files 2026-02-10 19:31:14 +08:00
uprobes.c LoongArch: uprobes: Remove redundant code about resume_era 2025-05-14 22:18:10 +08:00
vdso.c Convert more 'alloc_obj' cases to default GFP_KERNEL arguments 2026-02-21 20:03:00 -08:00
vmlinux.lds.S kbuild: Split .modinfo out from ELF_DETAILS 2026-02-26 11:50:19 -07:00