Build with -Wa,--gsframe-3 flags to generate a .sframe section. This
will be used for in-kernel reliable stacktrace in cases where the frame
pointer alone is insufficient.

Currently, the sframe format only supports arm64, x86_64 and s390x
architectures.

Signed-off-by: Weinan Liu <[email protected]>
Signed-off-by: Dylan Hatch <[email protected]>
Reviewed-by: Prasanna Kumar T S M <[email protected]>
---
 MAINTAINERS                            |  1 +
 Makefile                               |  8 ++++++++
 arch/Kconfig                           |  7 +++++++
 arch/arm64/Kconfig                     |  1 +
 arch/arm64/Kconfig.debug               | 13 +++++++++++++
 arch/arm64/include/asm/unwind_sframe.h | 12 ++++++++++++
 arch/arm64/kernel/vdso/Makefile        |  2 +-
 include/asm-generic/vmlinux.lds.h      | 15 +++++++++++++++
 8 files changed, 58 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm64/include/asm/unwind_sframe.h

diff --git a/MAINTAINERS b/MAINTAINERS
index cfc7dec88da4..a7d75f9cb5f4 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -27561,6 +27561,7 @@ STACK UNWINDING
 M:     Josh Poimboeuf <[email protected]>
 M:     Steven Rostedt <[email protected]>
 S:     Maintained
+F:     arch/*/include/asm/unwind_sframe.h
 F:     include/linux/sframe.h
 F:     include/linux/unwind*.h
 F:     kernel/unwind/
diff --git a/Makefile b/Makefile
index 2b15f0b4a0cb..e03d09ea6a23 100644
--- a/Makefile
+++ b/Makefile
@@ -1110,6 +1110,14 @@ endif
 # Ensure compilers do not transform certain loops into calls to wcslen()
 KBUILD_CFLAGS += -fno-builtin-wcslen
 
+# build with sframe table
+ifdef CONFIG_SFRAME_UNWINDER
+CC_FLAGS_SFRAME := -Wa,--gsframe-3
+KBUILD_CFLAGS  += $(CC_FLAGS_SFRAME)
+KBUILD_AFLAGS  += $(CC_FLAGS_SFRAME)
+export CC_FLAGS_SFRAME
+endif
+
 # change __FILE__ to the relative path to the source directory
 ifdef building_out_of_srctree
 KBUILD_CPPFLAGS += -fmacro-prefix-map=$(srcroot)/=
diff --git a/arch/Kconfig b/arch/Kconfig
index 6695c222c728..c87e489fa978 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -520,6 +520,13 @@ config SFRAME_VALIDATION
 
          If unsure, say N.
 
+config ARCH_SUPPORTS_SFRAME_UNWINDER
+       bool
+       help
+         An architecture can select this if it  enables the sframe (Simple
+         Frame) unwinder for unwinding kernel stack traces. It uses unwind
+         table that is directly generatedby toolchain based on DWARF CFI 
information.
+
 config HAVE_PERF_REGS
        bool
        help
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 38dba5f7e4d2..189bc199ad2e 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -112,6 +112,7 @@ config ARM64
        select ARCH_SUPPORTS_SCHED_SMT
        select ARCH_SUPPORTS_SCHED_CLUSTER
        select ARCH_SUPPORTS_SCHED_MC
+       select ARCH_SUPPORTS_SFRAME_UNWINDER
        select ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH
        select ARCH_WANT_COMPAT_IPC_PARSE_VERSION if COMPAT
        select ARCH_WANT_DEFAULT_BPF_JIT
diff --git a/arch/arm64/Kconfig.debug b/arch/arm64/Kconfig.debug
index 265c4461031f..df291d64812f 100644
--- a/arch/arm64/Kconfig.debug
+++ b/arch/arm64/Kconfig.debug
@@ -20,4 +20,17 @@ config ARM64_RELOC_TEST
        depends on m
        tristate "Relocation testing module"
 
+config SFRAME_UNWINDER
+       bool "Sframe unwinder"
+       depends on AS_SFRAME3
+       depends on 64BIT
+       depends on ARCH_SUPPORTS_SFRAME_UNWINDER
+       select SFRAME_LOOKUP
+       help
+         This option enables the sframe (Simple Frame) unwinder for unwinding
+         kernel stack traces. It uses unwind table that is directly generated
+         by toolchain based on DWARF CFI information. In, practice this can
+         provide more reliable stacktrace results than unwinding with frame
+         pointers alone.
+
 source "drivers/hwtracing/coresight/Kconfig"
diff --git a/arch/arm64/include/asm/unwind_sframe.h 
b/arch/arm64/include/asm/unwind_sframe.h
new file mode 100644
index 000000000000..1682c079e387
--- /dev/null
+++ b/arch/arm64/include/asm/unwind_sframe.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_ARM64_UNWIND_SFRAME_H
+#define _ASM_ARM64_UNWIND_SFRAME_H
+
+#ifdef CONFIG_ARM64
+
+#define SFRAME_REG_SP  31
+#define SFRAME_REG_FP  29
+
+#endif
+
+#endif /* _ASM_ARM64_UNWIND_SFRAME_H */
diff --git a/arch/arm64/kernel/vdso/Makefile b/arch/arm64/kernel/vdso/Makefile
index 7dec05dd33b7..c60ef921956f 100644
--- a/arch/arm64/kernel/vdso/Makefile
+++ b/arch/arm64/kernel/vdso/Makefile
@@ -38,7 +38,7 @@ ccflags-y += -DDISABLE_BRANCH_PROFILING -DBUILD_VDSO
 CC_FLAGS_REMOVE_VDSO := $(CC_FLAGS_FTRACE) -Os $(CC_FLAGS_SCS) \
                        $(RANDSTRUCT_CFLAGS) $(KSTACK_ERASE_CFLAGS) \
                        $(GCC_PLUGINS_CFLAGS) \
-                       $(CC_FLAGS_LTO) $(CC_FLAGS_CFI) \
+                       $(CC_FLAGS_LTO) $(CC_FLAGS_CFI) $(CC_FLAGS_SFRAME) \
                        -Wmissing-prototypes -Wmissing-declarations
 
 CC_FLAGS_ADD_VDSO := -O2 -mcmodel=tiny -fasynchronous-unwind-tables
diff --git a/include/asm-generic/vmlinux.lds.h 
b/include/asm-generic/vmlinux.lds.h
index 1e1580febe4b..0a5c2f6cc4c0 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -491,6 +491,8 @@
                *(.rodata1)                                             \
        }                                                               \
                                                                        \
+       SFRAME                                                          \
+                                                                       \
        /* PCI quirks */                                                \
        .pci_fixup        : AT(ADDR(.pci_fixup) - LOAD_OFFSET) {        \
                BOUNDED_SECTION_PRE_LABEL(.pci_fixup_early,  _pci_fixups_early, 
 __start, __end) \
@@ -911,6 +913,19 @@
 #define TRACEDATA
 #endif
 
+#ifdef CONFIG_SFRAME_UNWINDER
+#define SFRAME                                                 \
+       /* sframe */                                            \
+       .sframe : AT(ADDR(.sframe) - LOAD_OFFSET) {             \
+               __start_sframe_header = .;                      \
+               KEEP(*(.sframe))                                \
+               KEEP(*(.init.sframe))                           \
+               __stop_sframe_header = .;                       \
+       }
+#else
+#define SFRAME
+#endif
+
 #ifdef CONFIG_PRINTK_INDEX
 #define PRINTK_INDEX                                                   \
        .printk_index : AT(ADDR(.printk_index) - LOAD_OFFSET) {         \
-- 
2.53.0.1213.gd9a14994de-goog


Reply via email to