Re: [RFC] Don't create sframes during build

From: Indu Bhagat

Date: Thu Jan 29 2026 - 20:00:06 EST


On 1/29/26 2:23 PM, Nathan Chancellor wrote:
On Thu, Jan 29, 2026 at 10:13:03AM +0100, Jens Remus wrote:
Instead of dropping .sframe for kernel during final link it would be
better not to generate it to save some CPU cycles and disk space.
...
What about:

diff --git a/Makefile b/Makefile
--- a/Makefile
+++ b/Makefile
@@ -906,6 +906,11 @@ KBUILD_CFLAGS += $(call cc-option,--param=allow-store-data-races=0)
KBUILD_CFLAGS += $(call cc-option,-fno-allow-store-data-races)
endif

+# No .sframe generation for kernel if enabled in assembler by default
+CC_FLAGS_SFRAME := $(call as-option,-Wa$(comma)--gsframe=no)
+KBUILD_CFLAGS += $(CC_FLAGS_SFRAME)
+KBUILD_AFLAGS += $(CC_FLAGS_SFRAME)
+
ifdef CONFIG_READABLE_ASM
# Disable optimizations that make assembler listings hard to read.
# reorder blocks reorders the control in the function

This seems like a good start for the main kernel build. I still have an
issue with bleeding edge binutils with mismatched .sframe input
sections, which does not appear to disappear with -Wa,--gsframe=no.

$ cat test.c
void atexit();
void main() { atexit(); }

$ gcc --version | head -1
gcc (GCC) 15.2.1 20260103

$ ld --version | head -1
GNU ld (GNU Binutils) 2.45.50.20260128

$ gcc -o /dev/null test.c
.../binutils/2.45.50-2026-01-27_18-02-52-e8108cc5e6fe1748dc6033a297dd2c1c6234de78/bin/ld: input SFrame sections with different format versions prevent .sframe generation
.../binutils/2.45.50-2026-01-27_18-02-52-e8108cc5e6fe1748dc6033a297dd2c1c6234de78/bin/ld: final link failed
collect2: error: ld returned 1 exit status

$ gcc -o /dev/null -Wa,--gsframe=no test.c
.../binutils/2.45.50-2026-01-27_18-02-52-e8108cc5e6fe1748dc6033a297dd2c1c6234de78/bin/ld: input SFrame sections with different format versions prevent .sframe generation
.../binutils/2.45.50-2026-01-27_18-02-52-e8108cc5e6fe1748dc6033a297dd2c1c6234de78/bin/ld: final link failed
collect2: error: ld returned 1 exit status

$ gcc -o /dev/null -Wl,--discard-sframe test.c

This was extracted from an error I see while building libiberty in
binutils due to the atexit() configure test failing then the fallback to
on_exit() resulting in an error but I also notice it when building
tools/objtool, which is a host tool:

$ make -skj"$(nproc)" ARCH=x86_64 mrproper defconfig prepare
.../binutils/2.45.50-2026-01-27_18-02-52-e8108cc5e6fe1748dc6033a297dd2c1c6234de78/bin/ld: input SFrame sections with different format versions prevent .sframe generation
.../binutils/2.45.50-2026-01-27_18-02-52-e8108cc5e6fe1748dc6033a297dd2c1c6234de78/bin/ld: final link failed
collect2: error: ld returned 1 exit status
make[5]: *** [Makefile:127: tools/objtool/objtool] Error 1
...

It looks like several distribution ELF objects and libraries on my
system (Arch Linux) have .sframe sections in them, so maybe we still
need -Wl,--discard-sframe? They all appear to be SFrame v2 objects so if
no objects in the build have SFrame v3 sections from -Wa,--gsframe=no,
it seems odd that there is an error but maybe there is something else
going on?


As to whats going on:

Some Arch Linux releases seem to have glibc configured with --enable-sframe, which is likely the cause of the SFrame V2 objects on your system. Frederick (from ArchLinux is in CC) is planning to roll out a release with a glibc built without --enable-sframe.

Next, GNU ld creates linker-generated .sframe for the (linker-generated) .plt sections (on x86_64 and s390x), if GNU ld sees any input objects have .sframe in them[*], unless --discard-sframe is specified. These are now SFrame V3 (after Jan 15 when SFrame V3 was merged). The choice to drop the support for V2/V3 object mixing in the GNU ld was made to save implementation complexity in linkers and (WIP) stacktracers supporting SFrame, by adopting SFrame V3 and above.

So, --discard-sframe is the remedy if you have V2 sections lying around.

[*] The bug in the GNU Binutils snapshots between Jan 15 and Jan 24 was that these linker-generated .sframe for .plt were enthusiastically created even when _none_ of the inputs had .sframe in them (for x86_64 and s390x), unless --discard-sframe was specified.