libgcc/crtstuff.c compiled twice, and forced to -O2
Georg-Johann Lay
avr@gjlay.de
Sat Jun 20 15:42:48 GMT 2026
Am 20.06.26 um 15:47 schrieb R. Diez via Gcc-help:
> Hi all:
>
> I am building a cross-compiler toolchain for an embedded ARM target, see
> here: https://github.com/rdiez/DebugDue/tree/master/Toolchain
>
> I recently had to debug an issue on start-up, and that was harder then
> necessary, as libgcc/crtstuff.c is not built with debug information, see
> here: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=125899
>
> During my investigation, I have also realised the following:
>
> 1) File libgcc/crtstuff.c is compiled twice, once with -DCRT_BEGIN and
> once with -DCRT_END.
>
> Those options are apparently mutually exclusive. The file is split in
> half, one with #ifdef CRT_BEGIN, and the other with #ifdef CRT_END.
>
> Shouldn't this file be split into 2 files then?
>
> Or should we just get rid of CRT_BEGIN and CRT_END and compile the file
> only once?
>
> There is one variant though which is compiled only with -DCRT_BEGIN,
> according to this comment in file "libgcc/Makefile.in":
>
> # This is a version of crtbegin for -static links.
>
> I wonder why. Does a static build not need to call global destructors?
>
> My single-threaded, bare metal toolchain has no dynamic library / shared
> object support, but crtstuff.c is still getting compiled twice with -
> DCRT_BEGIN and -DCRT_END, and global destructors are called on termination.
>
> Proper termination is not very common in embedded software, but I am
It will become common once you start running testsuites.
> triggering it manually in order to debug memory leaks.
>
>
> 2) crtstuff.c is forcedly compiled with -O2, according to this in file
> "libgcc/Makefile.in":
>
> # Options to use when compiling crtbegin/end.
> CRTSTUFF_CFLAGS = -O2 $(GCC_CFLAGS) $(INCLUDES) $(MULTILIB_CFLAGS) -g0 \
> $(NO_PIE_CFLAGS) -finhibit-size-directive -fno-inline -fno-exceptions \
> -fno-zero-initialized-in-bss -fno-toplevel-reorder -fno-tree-vectorize \
> -fbuilding-libgcc -fno-stack-protector $(FORCE_EXPLICIT_EH_REGISTRY) \
> $(INHIBIT_LIBC_CFLAGS) $(USE_TM_CLONE_REGISTRY)
>
> I would say it does not make sense to always force -O2, or does it?
Can't you override it in your MULTILIB_CFLAGS?
You can also build a module once with specific options:
1) Go to the multilib build dir.
2) rm -f module.o ; make module.o
3) Record the issued compile command and adjust options to your liking.
There are also 2 ways to build the entire libgcc with custom flags:
(cd $builddir/multilib/libgcc; make clean all HOST_LIBGCC2_CFLAGS=...)
or
(cd $nuilddir; make all-target-libgcc CFLAGS_FOR_TARGET=...)
> Maybe the user wants -Os for the lot. While trying to debug my start-up
> problem, I tried to build the debug versions of all libraries with "-O0
> -DDEBUG", but crtstuff.c was still optimised, making debugging harder
> than necessary.
Adjust HOST_LIBGCC2_CFLAGS in libgcc's t-<target> make snippet.
Also you may consider optimized (asm) startup code, dropping crtstuff.c.
Johann
> Does it make sense anyway to specify -O2 für a single file? Will it not
> be overridden by LTO anyway?
>
> Regards,
> rdiez
More information about the Gcc-help
mailing list