Re: libgcc/crtstuff.c compiled twice, and forced to -O2

Georg-Johann Lay via Gcc-help <[email protected]> Sat, 20 Jun 2026 17:42:48 +0200
Newsgroups gmane.comp.gcc.help
Message-ID <[email protected]>
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