Linux – What differences and relations are between the various `libc.so`

linuxshared librarysoftware installation

On Lubntu 18.04

$ whereis libc
libc: /usr/lib/x86_64-linux-gnu/libc.a /usr/lib/x86_64-linux-gnu/libc.so /usr/share/man/man7/libc.7.gz

$ locate libc.so
/lib/i386-linux-gnu/libc.so.6
/lib/x86_64-linux-gnu/libc.so.6
/usr/lib/x86_64-linux-gnu/libc.so

$ ls -li /usr/lib/x86_64-linux-gnu/libc.so  /lib/x86_64-linux-gnu/libc.so.6 /lib/i386-linux-gnu/libc.so.6
 2101838 lrwxrwxrwx 1 root root  12 Apr 16 16:14 /lib/i386-linux-gnu/libc.so.6 -> libc-2.27.so
 2101796 lrwxrwxrwx 1 root root  12 May 13 20:09 /lib/x86_64-linux-gnu/libc.so.6 -> libc-2.27.so
15736469 -rw-r--r-- 1 root root 298 Apr 16 16:14 /usr/lib/x86_64-linux-gnu/libc.so

What differences and relations are between the various libc.so?

Which one is in use?

Thanks.

My question comes from https://stackoverflow.com/questions/50798907/why-does-loading-the-libc-shared-library-have-libraryloader-object-is-not-cal

Thanks.

Best Answer

They all serve different purposes:

  • /lib/i386-linux-gnu/libc.so.6 is a symbolic link to the 32-bit x86 C library, used to run 32-bit executables;
  • /lib/x86_64-linux-gnu/libc.so.6 is a symbolic link to the 64-bit x86 C library, used to run 64-bit executables;
  • /usr/lib/x86_64-linux-gnu/libc.so is (usually) a linker script pointing to the 64-bit C library (dynamic or shared, as needed) and dynamic linker, and is used to link 64-bit executables (when building them).

There are three different types of linking when building and running programs:

  • static linking: the build-time linker (ld) resolves all the objects used in the program during the build, merges the objects which are used, and produces an executable binary which doesn’t use external libraries;
  • dynamic linking, at build-time: ld resolves all objects used in the program, but instead of storing them in the executable, it only stores references to them;
  • dynamic linking, at run-time: the run-time linker (ld.so), or dynamic linker, resolves all the references stored in the executable, loading all the required libraries and updating all the object references before running the program.

The libc.so linker script provides instructions for ld, in the form of a linker script:

/* GNU ld script
   Use the shared library, but some functions are only in
   the static library, so try that secondarily.  */
OUTPUT_FORMAT(elf64-x86-64)
GROUP ( /lib/x86_64-linux-gnu/libc.so.6 /usr/lib/x86_64-linux-gnu/libc_nonshared.a  AS_NEEDED ( /lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 ) )

Usually dynamic libraries are set up using symlinks only (libfoo.so is used by ld, and points to libfoo.so.1 or whatever which is used by ld.so, and is itself typically a symlink to the currently-installed version of the library, e.g. libfoo.so.1.2.3). In the GNU C library’s case though programs being linked dynamically still need some symbols from the static library, so a linker script is used instead so that the linker can try both. The linker script also refers to the dynamic linker which will be used at runtime (/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 above), and whose name is embedded in executables (in .interp).

The terms “dynamic linker” and “dynamic loader” are synonymous and used interchangeably (see the ld.so manpage).

Related Question