[RFC PATCH v1 20/25] unwind_user/eh_frame/x86: Enable eh_frame unwinding on x86
From: Jens Remus
Date: Tue Aug 18 2026 - 10:55:45 EST
The x86-64 .eh_frame implementation works well with GCC and Clang
generated code. Enable it.
Signed-off-by: Jens Remus <jremus@xxxxxxxxxxxxx>
---
arch/x86/Kconfig | 1 +
arch/x86/include/asm/unwind_user.h | 40 +++++++++++++++++++++
arch/x86/include/asm/unwind_user_eh_frame.h | 22 ++++++++++++
3 files changed, 63 insertions(+)
create mode 100644 arch/x86/include/asm/unwind_user_eh_frame.h
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index bdad90f210e4..fe7919915084 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -300,6 +300,7 @@ config X86
select HAVE_SYSCALL_TRACEPOINTS
select HAVE_UACCESS_VALIDATION if HAVE_OBJTOOL
select HAVE_UNSTABLE_SCHED_CLOCK
+ select HAVE_UNWIND_USER_EH_FRAME if X86_64
select HAVE_UNWIND_USER_FP if X86_64
select HAVE_USER_RETURN_NOTIFIER
select HAVE_GENERIC_VDSO
diff --git a/arch/x86/include/asm/unwind_user.h b/arch/x86/include/asm/unwind_user.h
index c96645c824d1..df1966bcb0f6 100644
--- a/arch/x86/include/asm/unwind_user.h
+++ b/arch/x86/include/asm/unwind_user.h
@@ -4,6 +4,7 @@
#ifdef CONFIG_UNWIND_USER
+#include <linux/sched/task_stack.h>
#include <asm/ptrace.h>
#include <asm/uprobes.h>
@@ -15,6 +16,45 @@ static inline int unwind_user_word_size(struct pt_regs *regs)
return user_64bit_mode(regs) ? 8 : 4;
}
+#ifdef CONFIG_X86_64
+
+static inline int unwind_user_get_reg(unsigned long *val, unsigned int regnum)
+{
+ struct pt_regs *regs = task_pt_regs(current);
+
+ /* TODO: eh_frame is currently limited to x86-64 */
+ if (!user_64bit_mode(regs))
+ return -EINVAL;
+
+ switch (regnum) {
+ /* DWARF register numbers 0..15 */
+ case 0: *val = regs->ax; break;
+ case 1: *val = regs->dx; break;
+ case 2: *val = regs->cx; break;
+ case 3: *val = regs->bx; break;
+ case 4: *val = regs->si; break;
+ case 5: *val = regs->di; break;
+ case 6: *val = regs->bp; break;
+ case 7: *val = regs->sp; break;
+ case 8: *val = regs->r8; break;
+ case 9: *val = regs->r9; break;
+ case 10: *val = regs->r10; break;
+ case 11: *val = regs->r11; break;
+ case 12: *val = regs->r12; break;
+ case 13: *val = regs->r13; break;
+ case 14: *val = regs->r14; break;
+ case 15: *val = regs->r15; break;
+ default:
+ pr_debug("%s (%d): %s(%u): unsupported register number\n",
+ current->comm, current->pid, __func__, regnum);
+ return -EINVAL;
+ }
+ return 0;
+}
+#define unwind_user_get_reg unwind_user_get_reg
+
+#endif /* CONFIG_X86_64 */
+
#endif /* CONFIG_UNWIND_USER */
#ifdef CONFIG_HAVE_UNWIND_USER_FP
diff --git a/arch/x86/include/asm/unwind_user_eh_frame.h b/arch/x86/include/asm/unwind_user_eh_frame.h
new file mode 100644
index 000000000000..fdccbda2fe4b
--- /dev/null
+++ b/arch/x86/include/asm/unwind_user_eh_frame.h
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_X86_UNWIND_USER_EH_FRAME_H
+#define _ASM_X86_UNWIND_USER_EH_FRAME_H
+
+#ifdef CONFIG_X86_64
+
+#define EH_FRAME_REG_SP 7 /* designated stack pointer register */
+#define EH_FRAME_REG_FP 6 /* designated frame pointer register */
+#define EH_FRAME_REG_RA 16 /* (pseudo) return address register */
+
+/* Instructions must be 1-byte aligned */
+#define EH_FRAME_MAX_CODE_ALIGN 1
+
+/* Stack grows towards lower addresses and SP must be 8-byte aligned */
+#define EH_FRAME_MIN_DATA_ALIGN -8
+#define EH_FRAME_MAX_DATA_ALIGN -1
+
+#endif
+
+#include <asm-generic/unwind_user_eh_frame.h>
+
+#endif /* _ASM_X86_UNWIND_USER_EH_FRAME_H */
--
2.53.0