I'm adding c++ runtime and exception support to the Linux kernel. For that, I need to provide my own lib/gcc and lib/libstdc++instead of the standard libraries provided by the compiler.

So, I am confused with the flags that are to be passed to the linker. In a normal kernel's top-level Makefile, LD = $(CROSS_COMPILE)ld which enables the kernel to use the default standard libraries and startup files. For my kernel I'm using LD = $(CROSS_COMPILE)ld -nostdlib -nodefaultlibs -nostartfiles as said in a documentation. What I understood from gcc documentation is that passing -nostdlib to the linker is that of passing both -nodefaultlibs -nostartfiles. What's actually the difference between these flags?


These flags are defined in GCC’s spec files, so the best way to determine the differences between them is to look there:

gcc -dumpspecs

The relevant part is the link_command definition. This shows that -nostdlib, -nodefaultlibs and -nostartfiles have the following impact:

  • %{!nostdlib:%{!nodefaultlibs:%:pass-through-libs(%(link_gcc_c_sequence))}} — this adds libgcc, libpthread, libc, libieee as necessary, using a macro and the lib and libgcc spec strings;
  • %{!nostdlib:%{!nostartfiles:%S}} — this adds the startfile spec string, , which specifies the object files to add to handle startup (crti.o etc.)
  • %{!nostdlib:%{fvtable-verify=std: -lvtv -u_vtable_map_vars_start -u_vtable_map_vars_end} %{fvtable-verify=preinit: -lvtv -u_vtable_map_vars_start -u_vtable_map_vars_end}} — this adds virtual table verification using libvtv
  • %{!nostdlib:%{!nodefaultlibs:%{mmpx:%{fcheck-pointer-bounds: %{static:--whole-archive -lmpx --no-whole-archive %:include(libmpx.spec)%(link_libmpx)} %{!static:%{static-libmpx:-Bstatic --whole-archive} %{!static-libmpx:--push-state --no-as-needed} -lmpx %{!static-libmpx:--pop-state} %{static-libmpx:--no-whole-archive -Bdynamic %:include(libmpx.spec)%(link_libmpx)}}}}%{mmpx:%{fcheck-pointer-bounds:%{!fno-chkp-use-wrappers: %{static:-lmpxwrappers} %{!static:%{static-libmpxwrappers:-Bstatic} -lmpxwrappers %{static-libmpxwrappers: -Bdynamic}}}}}}} — this handles libmpx
  • %{!nostdlib:%{!nodefaultlibs:%{%:sanitize(address): %{static-libasan:%:include(libsanitizer.spec)%(link_libasan)} %{static:%ecannot specify -static with -fsanitize=address}} %{%:sanitize(thread): %{static-libtsan:%:include(libsanitizer.spec)%(link_libtsan)} %{static:%ecannot specify -static with -fsanitize=thread}} %{%:sanitize(undefined):%{static-libubsan:-Bstatic} -lubsan %{static-libubsan:-Bdynamic} %{static-libubsan:%:include(libsanitizer.spec)%(link_libubsan)}} %{%:sanitize(leak): %{static-liblsan:%:include(libsanitizer.spec)%(link_liblsan)}}}} — this handles the various sanitisation options
  • %{!nostdlib:%{!nodefaultlibs:%(link_ssp) %(link_gcc_c_sequence)}} — this adds the stack protection options and repeats the C link sequence (whose libraries were already specified at the start)
  • %{!nostdlib:%{!nostartfiles:%E}} — this adds the endfile spec string, which specifies the object files to add to handle left-overs (crtfastmath.o, crtend.o etc.)

As you understood from the documentation, -nostdlib is a superset of -nodefaultlibs and -nostartfiles. It also disables virtual table verification.

So -nostdlib is sufficient to disable all the related features; -nodefaultlibs and -nostartfiles don’t add anything to it. (But it doesn’t hurt to mention them too.)

  • OK I got it. But I cannot understand why there occurs a misalignment of load segments of vmlinux when the line LD = $(CROSS_COMPILE)ld -nostdlib is changed to LD = $(CROSS_COMPILE)ld -nostdlib -nodefaultlibs -nostartfiles. Instead of aligning at a mutiple of 2MB, they align at 1KB or something like that. – Jaya Kommuru Jun 27 '18 at 12:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.