Consider the shared object dependencies of /bin/bash
, which includes /lib64/ld-linux-x86-64.so.2
(dynamic linker/loader):
ldd /bin/bash
linux-vdso.so.1 (0x00007fffd0887000)
libtinfo.so.6 => /lib/x86_64-linux-gnu/libtinfo.so.6 (0x00007f57a04e3000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f57a04de000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f57a031d000)
/lib64/ld-linux-x86-64.so.2 (0x00007f57a0652000)
Inspecting /lib64/ld-linux-x86-64.so.2
shows that it is a symlink to /lib/x86_64-linux-gnu/ld-2.28.so
:
ls -la /lib64/ld-linux-x86-64.so.2
lrwxrwxrwx 1 root root 32 May 1 19:24 /lib64/ld-linux-x86-64.so.2 -> /lib/x86_64-linux-gnu/ld-2.28.so
Furthermore, file
reports /lib/x86_64-linux-gnu/ld-2.28.so
to itself be dynamically linked:
file -L /lib64/ld-linux-x86-64.so.2
/lib64/ld-linux-x86-64.so.2: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, BuildID[sha1]=f25dfd7b95be4ba386fd71080accae8c0732b711, stripped
I'd like to know:
- How can the dynamically linker/loader (
/lib64/ld-linux-x86-64.so.2
) itself be dynamically linked? Does it link itself at runtime? /lib/x86_64-linux-gnu/ld-2.28.so
is documented to handle a.out
binaries (man ld.so
), but/bin/bash
is an ELF executable?
The program ld.so handles a.out binaries, a format used long ago;
ld-linux.so* (/lib/ld-linux.so.1 for libc5, /lib/ld-linux.so.2 for
glibc2) han‐
dles ELF, which everybody has been using for years now.
Best Answer
Yes, it links itself when it initialises. Technically the dynamic linker doesn’t need object resolution and relocation for itself, since it’s fully resolved as-is, but it does define symbols and it has to take care of those when resolving the binary it’s “interpreting”, and those symbols are updated to point to their implementations in the loaded libraries. In particular, this affects
malloc
— the linker has a minimal version built-in, with the corresponding symbol, but that’s replaced by the C library’s version once it’s loaded and relocated (or even by an interposed version if there is one), with some care taken to ensure this doesn’t happen at a point where it might break the linker.The gory details are in
rtld.c
, in thedl_main
function.Note however that
ld.so
has no external dependencies. You can see the symbols involved withnm -D
; none of them are undefined.The manpage only refers to entries directly under
/lib
, i.e./lib/ld.so
(the libc 5 dynamic linker, which supportsa.out
) and/lib*/ld-linux*.so*
(the libc 6 dynamic linker, which supports ELF). The manpage is very specific, andld.so
is notld-2.28.so
.The dynamic linker found on the vast majority of current systems doesn’t include
a.out
support.file
andldd
report different things for the dynamic linker because they have different definitions of what constitutes a statically-linked binary. Forldd
, a binary is statically linked if it has noDT_NEEDED
symbols, i.e. no undefined symbols. Forfile
, an ELF binary is statically linked if it doesn’t have aPT_DYNAMIC
section (this will change in the release offile
following 5.37; it now uses the presence of aPT_INTERP
section as the indicator of a dynamically-linked binary, which matches the comment in the code).The GNU C library dynamic linker doesn’t have any
DT_NEEDED
symbols, but it does have aPT_DYNAMIC
section (since it is technically a shared library). As a result,ldd
(which is the dynamic linker) indicates that it’s statically linked, butfile
indicates that it’s dynamically linked. It doesn’t have aPT_INTERP
section, so the next release offile
will also indicate that it’s statically linked.(with
file
5.35)(with the currently in-development version of
file
).