16

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:

  1. How can the dynamically linker/loader (/lib64/ld-linux-x86-64.so.2) itself be dynamically linked? Does it link itself at runtime?
  2. /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.

3
  • The kernel does not care about such subtle taxonomic subtleties (and neither should you ;-)). The kernel only makes the difference between ELFs which need an interpreter and those which don't. And AFAIK, you cannot use an interpreter which itself needs one.
    – user313992
    Commented Sep 23, 2019 at 14:43
  • @StephenKitt mine hasn't (/lib/x86_64-linux-gnu/ld-2.28.so, debian 10 buster)
    – user313992
    Commented Sep 23, 2019 at 14:50
  • @mosvy yeah, sorry, I got mixed up between file’s erroneous comment about how it defines static binaries, and the reality of ld-2.28.so... The differentiator is PT_DYNAMIC. Commented Sep 23, 2019 at 14:53

2 Answers 2

22
  1. 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 the dl_main function.

    Note however that ld.so has no external dependencies. You can see the symbols involved with nm -D; none of them are undefined.

  2. The manpage only refers to entries directly under /lib, i.e. /lib/ld.so (the libc 5 dynamic linker, which supports a.out) and /lib*/ld-linux*.so* (the libc 6 dynamic linker, which supports ELF). The manpage is very specific, and ld.so is not ld-2.28.so.

    The dynamic linker found on the vast majority of current systems doesn’t include a.out support.

file and ldd report different things for the dynamic linker because they have different definitions of what constitutes a statically-linked binary. For ldd, a binary is statically linked if it has no DT_NEEDED symbols, i.e. no undefined symbols. For file, an ELF binary is statically linked if it doesn’t have a PT_DYNAMIC section (this will change in the release of file following 5.37; it now uses the presence of a PT_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 a PT_DYNAMIC section (since it is technically a shared library). As a result, ldd (which is the dynamic linker) indicates that it’s statically linked, but file indicates that it’s dynamically linked. It doesn’t have a PT_INTERP section, so the next release of file will also indicate that it’s statically linked.

$ ldd /lib64/ld-linux-x86-64.so.2
        statically linked

$ file $(readlink /lib64/ld-linux-x86-64.so.2)
/lib/x86_64-linux-gnu/ld-2.28.so: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, BuildID[sha1]=f25dfd7b95be4ba386fd71080accae8c0732b711, stripped

(with file 5.35)

$ file $(readlink /lib64/ld-linux-x86-64.so.2)
/lib/x86_64-linux-gnu/ld-2.28.so: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), statically linked, BuildID[sha1]=f25dfd7b95be4ba386fd71080accae8c0732b711, stripped

(with the currently in-development version of file).

13
  • 1
    Why is the word "interpreting" used in the context of dynamic linking? That word is usually used in the context of programing languages.
    – Shuzheng
    Commented Sep 23, 2019 at 17:16
  • What do you mean by "GNU C library dynamic linker"? Are you referring to /lib*/ld-linux*.so*, or a third dynamic linker?
    – Shuzheng
    Commented Sep 23, 2019 at 17:24
  • Where can you see ldd reports the dynamic linker as statically linked? Because it's list of shared object dependencies is empty?
    – Shuzheng
    Commented Sep 23, 2019 at 17:26
  • 1
    Dynamically-linked programs need some work done to them before they can be executed; that work is done by the dynamic linker, which ends up playing a similar role to an interpreter — it interprets the relocation tables etc. to produce something which the computer can run. Commented Sep 23, 2019 at 17:28
  • When I say “GNU C library dynamic linker”, I am referring to the implementation included in the GNU C library, usually shipped as /lib*/ld-linux*.so*. I specified the origin of the dynamic linker because there are other implementations available for Linux. Commented Sep 23, 2019 at 17:30
0
  1. I suspect the file program is wrong about the dynamically linker/loader being dynamically linked itself. The ldd program does not agree. At least not on my system (Debian Stretch):

    ldd /lib/x86_64-linux-gnu/ld-2.24.so
        statically linked
    
  2. man ld.so also reads: "ld-linux.so* handles ELF". On your system (and mine too by the way) both are symlinks to the same binary which I deduce is able to handle both ELF and the (old obsolete) a.out format.

3
  • what information do you add to the accepted answer?
    – miracle173
    Commented Sep 24, 2019 at 5:50
  • 2
    @miracle173 this answer is older than the accepted answer ;-). Commented Sep 24, 2019 at 6:38
  • you are right. I missed this. I thought the question and the accepted answer are very old and this answer was posted in the last hours. I cannot undo my downvote until someone modifies the post.
    – miracle173
    Commented Sep 24, 2019 at 13:13

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .