How does ldd
knows it's depending on libc.so.6
,not libc.so.5
or libc.so.7
?
libc.so.6 => /lib64/libc.so.6 (0x00000034f4000000)
/lib64/ld-linux-x86-64.so.2 (0x00000034f3c00000)
It is recorded inside application binary itself (specified at compile time, more exactly at link step, done with ld
):
$ readelf -d /bin/echo
Dynamic section at offset 0x5f1c contains 21 entries:
Tag Type Name/Value
0x00000001 (NEEDED) Shared library: [libc.so.6]
...
(there are some additional columns for how elf does store information in dynamic section. but you can see that libc.so.6 is hardcoded with .6
suffix because of SONAME)
or even without any knowledge of ELF file format:
$ strings /bin/echo |grep libc.so
libc.so.6
To find, how does linker find a library (it is done at final step of compilation), use gcc
option -Wl,--verbose
(this asks gcc to pass option --verbose
to ld
):
$ gcc a.c -Wl,--verbose
...
attempt to open /usr/lib/gcc/i686-pc-linux-gnu/4.4.4/libc.so failed
attempt to open /usr/lib/gcc/i686-pc-linux-gnu/4.4.4/libc.a failed
attempt to open /usr/lib/gcc/i686-pc-linux-gnu/4.4.4/libc.so failed
attempt to open /usr/lib/gcc/i686-pc-linux-gnu/4.4.4/libc.a failed
attempt to open /usr/lib/gcc/i686-pc-linux-gnu/4.4.4/../../../libc.so succeeded
opened script file /usr/lib/gcc/i686-pc-linux-gnu/4.4.4/../../../libc.so
opened script file /usr/lib/gcc/i686-pc-linux-gnu/4.4.4/../../../libc.so
attempt to open /lib/libc.so.6 succeeded
/lib/libc.so.6
Linker doesn't know anything about .digit
suffix, it just iterate over all library search directories trying to open libLIBNAME.so
and libLIBNAME.a
, where LIBNAME is a string after -l
option. ( -lc
option is added by default).
First success is /usr/lib/libc.so
which itself is not a library, but a linker script (text file). Here is content from typical libc.so
script:
$ cat /usr/lib/libc.so
/* GNU ld script
Use the shared library, but some functions are only in
the static library, so try that secondarily. */
OUTPUT_FORMAT(elf32-i386)
GROUP ( /lib/libc.so.6 /usr/lib/libc_nonshared.a AS_NEEDED ( /lib/ld-linux.so.2 ) )
So, script /usr/lib/libc.so
is found earlier than actual library, and this script says, what file will be linked, libc.so.6
in this case.
In more common case, lib___.so
is symlink to some version like lib___.so.3.4.5
and there is SONAME field filled in lib___.so.3.4.5
which says to ld
link not to lib___.so
but to lib___.so.3.4
which is another symlink to lib___.so.3.4.5
. The .3.4
name will be recorded in NEEDED field of binary.