In Linux, what are the executable ELF files respectively for
- static linker
- dynamic linker
- loader
- dynamic loader?
Which of them are invoked
- by
execve()
- by
dlopen()
?
How are they invoked by execve()
or dlopen()
, to solve the chicken-egg problem that execve()
or dlopen()
are used for invoking executable files?
Thanks.
Best Answer
I take it you’re using Jeff Darcy’s definitions:
It doesn’t really make sense to try to split everything up; instead, you should consider the pairs of features:
/usr/bin/ld
typically, along with static libraries (.a
); the loader is the kernel;/usr/bin/ld
again, but with shared libraries (.so
); the loader is the binary’s interpreter, e.g./lib64/ld-linux-x86-64.so.2
(which maps to/lib/x86_64-linux-gnu/ld-2.24.so
currently) on Debian 9 on 64-bit x86, itself loaded by the kernel, which also loads the main executable;libdl
; the linker is split between the library and the program callinglibdl
.Perhaps some more explanation is called for in relation to the last point. When a program uses
libdl
to load a library, it callsdlopen
, which loads the named library, along with any of its dependencies which aren’t already available in the process, and links the named library with its dependencies. Thuslibdl
performs both loading (of the necessary libraries) and linking (of the libraries only, not the calling program). When the calling program needs to use a symbol from the named library, it callsdlsym
which returns the address of the requested symbol (if it can find it). Thus the calling program performs part of the linking.There is no chicken-and-egg problem with regards to
execve
ordlopen
. Programs compiled to useexecve
are compiled with the appropriate references tolibc
(which contains the wrapper most programs actually use) and theexecve
symbol (strictly speaking, the aforementioned wrapper). Those references are resolved either at compile-time (for statically-linked programs) or at load-time (for dynamically-linked programs); after that, the symbol is available for use and the program can callexecve
. The same goes fordlopen
: programs which want to usedlopen
are compiled with the appropriate references tolibdl
anddlopen
. The dynamic linker itself is a static binary, so the kernel can load it without the help of the dynamic linker. You’ll find lots more detail on this topic in How programs get run and How programs get run: ELF binaries.(Note that in all cases of dynamic linking, if lazy binding is enabled, linking can happen just-in-time, and not necessarily at load time.)