Search code examples
linkerldd

Understanding ldd output


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)

Solution

  • 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.