[RFC PATCH v1 20/25] unwind_user/eh_frame/x86: Enable eh_frame unwinding on x86

Jens Remus <[email protected]>
Newsgroups org.kernel.vger.linux-trace-kernel,org.kernel.vger.linux-kernel,org.kernel.vger.linux-s390
Message-ID <[email protected]>
The x86-64 .eh_frame implementation works well with GCC and Clang
generated code.  Enable it.

Signed-off-by: Jens Remus <[email protected]>
---
 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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.