[<prev] [next>] [day] [month] [year] [list]
Message-ID: <40854460DE090346+c30007da67d26ae0e8651732f32a8ede4926db14.1760463245.git.tanyuan@tinylab.org>
Date: Wed, 15 Oct 2025 14:19:20 +0800
From: Yuan Tan <tanyuan@...ylab.org>
To: arnd@...db.de,
masahiroy@...nel.org,
nathan@...nel.org,
palmer@...belt.com,
linux-kbuild@...r.kernel.org,
linux-riscv@...ts.infradead.org
Cc: linux-arch@...r.kernel.org,
linux-kernel@...r.kernel.org,
i@...kray.me,
tanyuan@...ylab.org,
falcon@...ylab.org,
ronbogo@...look.com,
z1652074432@...il.com,
lx24@....ynu.edu.cn
Subject: [PATCH v2 6/8] compiler.h: introduce PUSHSECTION macro to establish proper references
When a section is created by .pushsection in assembly, there is no
reference between the caller function and the newly created section. As a
result, --gc-sections may incorrectly discard the newly created section.
To prevent such incorrect garbage collection, kernel code often wraps these
sections with KEEP() in linker scripts. While this guarantees that the
sections are retained, it introduces a dependency inversion: unused
sections are kept unnecessarily, and any sections they reference are also
forcibly retained. This prevents the linker from eliminating truly unused
code or data.
Introduce a new PUSHSECTION macro in include/linux/compiler.h to create a
proper reference between the .pushsection caller and the generated section.
The macro is fully compatible with all existing .pushsection parameters and
has no side effects, making it safe to replace all current .pushsection
usages with this version.
PUSHSECTION works by emitting a unique label inside the new section, and
adding a relocation from the caller function to that label. This ensures
the linker recognizes the dependency and keeps both sections alive
together. So we don't need to wrap the section with KEEP() in linker
anymore.
To guarantee uniqueness of the section and label names, both __COUNTER__
and %= are used:
Either alone is insufficient:
- __COUNTER__ alone fails when the function containing PUSHSECTION is
inlined multiple times, causing duplicate labels.
- %= alone fails when multiple PUSHSECTION directives appear within a
single inline assembly block.
In assembly code, a separate definition is provided because the C macro
cannot ensure unique section/label names when expanded inside an assembler
macro (.macro).
Signed-off-by: Yuan Tan <tanyuan@...ylab.org>
Signed-off-by: Zhangjin Wu <falcon@...ylab.org>
Signed-off-by: Xiao Liu <lx24@....ynu.edu.cn>
Signed-off-by: Peihan Liu <ronbogo@...look.com>
---
include/linux/compiler.h | 43 +++++++++++++++++++++++++++++++++++++++-
1 file changed, 42 insertions(+), 1 deletion(-)
diff --git a/include/linux/compiler.h b/include/linux/compiler.h
index 5b45ea7dff3e..bba79cedbe24 100644
--- a/include/linux/compiler.h
+++ b/include/linux/compiler.h
@@ -3,6 +3,7 @@
#define __LINUX_COMPILER_H
#include <linux/compiler_types.h>
+#include <linux/stringify.h>
#ifndef __ASSEMBLY__
@@ -267,7 +268,47 @@ static inline void *offset_to_ptr(const int *off)
return (void *)((unsigned long)off + *off);
}
-#endif /* __ASSEMBLY__ */
+#ifdef CONFIG_PUSHSECTION_WITH_RELOC
+#define __PUSHSECTION_RELOC(lbl) ".reloc ., BFD_RELOC_NONE, " lbl "\n\t"
+#define __PUSHSECTION_HELPER(prefix) __stringify(prefix.%=) "_" __stringify(__COUNTER__)
+#define __PUSHSECTION_LABEL(lbl) lbl ":\n\t"
+#else
+#define __PUSHSECTION_RELOC(lbl)
+#define __PUSHSECTION_HELPER(prefix) __stringify(prefix)
+#define __PUSHSECTION_LABEL(lbl)
+#endif
+
+#define _PUSHSECTION(lbl, sec, ...) \
+ __PUSHSECTION_RELOC(lbl) \
+ ".pushsection " sec ", " #__VA_ARGS__ "\n\t" __PUSHSECTION_LABEL(lbl)
+
+#define PUSHSECTION(sec, ...) \
+ _PUSHSECTION(__PUSHSECTION_HELPER(.Lsec), __PUSHSECTION_HELPER(sec), __VA_ARGS__)
+
+#else /* __ASSEMBLY__ */
+
+#ifdef CONFIG_PUSHSECTION_WITH_RELOC
+#define __PUSHSECTION_RELOC .reloc ., BFD_RELOC_NONE, \label
+#define __PUSHSECTION_HELPER(prefix) prefix\().\@
+#define __PUSHSECTION_LABEL \label:
+#else
+#define __PUSHSECTION_RELOC
+#define __PUSHSECTION_HELPER(prefix) prefix
+#define __PUSHSECTION_LABEL
+#endif
+
+.macro _PUSHSECTION label:req, section:req, args:vararg
+ __PUSHSECTION_RELOC
+ .pushsection __PUSHSECTION_HELPER(\section), \args
+ __PUSHSECTION_LABEL
+.endm
+
+.macro PUSHSECTION section:req, args:vararg
+ _PUSHSECTION .Lsec\@, \section, \args
+.endm
+
+#endif /* !__ASSEMBLY__ */
+
#ifdef CONFIG_64BIT
#define ARCH_SEL(a,b) a
--
2.43.0
Powered by blists - more mailing lists