Some notes on shared libraries with ld

by Martin Monperrus
On Linux, shared libraries (aka dynamically linked libraries) are handled with the ld* set of tools from libc-bin. I've recently encountered some bugs related to this, here are some raw notes on this technology.

How to list the shared libraries required by an executable?

ldd lists the names of the required libraries and where they are found on the system.
For instance, in the following, ls depends on libselinux.so.1 which is found in /lib/i386-linux-gnu/.
$ ldd  /bin/ls
	linux-gate.so.1 =>  (0xb7725000)
	libselinux.so.1 => /lib/i386-linux-gnu/libselinux.so.1 (0xb76d5000)
	librt.so.1 => /lib/i386-linux-gnu/i686/cmov/librt.so.1 (0xb76cc000)
	libacl.so.1 => /lib/i386-linux-gnu/libacl.so.1 (0xb76c1000)
	libc.so.6 => /lib/i386-linux-gnu/i686/cmov/libc.so.6 (0xb7564000)
	libdl.so.2 => /lib/i386-linux-gnu/i686/cmov/libdl.so.2 (0xb7560000)
	/lib/ld-linux.so.2 (0xb7726000)
	libpthread.so.0 => /lib/i386-linux-gnu/i686/cmov/libpthread.so.0 (0xb7547000)
	libattr.so.1 => /lib/i386-linux-gnu/libattr.so.1 (0xb7541000)

How to list the missing symbols of an executable?

Sometimes, although the output of ldd seems correct, some symbols are not found at runtime (Undefined symbol...).
ldd has additional switches to try to completely resolve all symbols of an executable (-r, -d to "perform relocations for both data objects and functions, and report any missing objects or functions").

The point is that it happens that ldd finds a shared library with the correct name, but that the found one is of a slightly different version. In that case, symbols may still be missing. For instance:
$ ldd -r /usr/lib/libatlas.so
    linux-gate.so.1 => (0xb7841000)
    libm.so.6 => /lib/libm.so.6 (0xb74f2000)
    libpthread.so.0 => /lib/libpthread.so.0 (0xb74d8000)
    libc.so.6 => /lib/libc.so.6 (0xb737a000)
    /lib/ld-linux.so.2 (0xb7842000)
undefined symbol: ATL_thread_free (/usr/lib/libatlas.so)
undefined symbol: ATL_join_tree (/usr/lib/libatlas.so)
undefined symbol: ATL_free_tree (/usr/lib/libatlas.so)
undefined symbol: ATL_wait_tree (/usr/lib/libatlas.so)
undefined symbol: ATL_signal_tree (/usr/lib/libatlas.so)
undefined symbol: ATL_thread_init (/usr/lib/libatlas.so)
(from http://sourceforge.net/apps/trac/sourceforge/ticket/21016)

How to configure shared library resolution?

To configure the resolution of ld.so/ldd, one has to add directory paths in /etc/ld.so.conf or in /etc/ld.so.conf.d/*. Then, a call to $ ldconfig updates /etc/ld.so.cache accordingly. Note that those manually defined directories are mixed with pre-configured ones (such as /lib).

How to change the priority order of directories of shared libraries?

The priority order is: 1) /etc/ld.so.conf 2) files in /etc/ld.so.conf.d/* by alphabetical order, 3) pre-configured directories.
To output the directory order used for resolving shared libraries:
$ ldconfig -v | grep "^/"
ldconfig: Path `/lib/i386-linux-gnu' given more than once
ldconfig: Path `/usr/lib/i386-linux-gnu' given more than once
/lib/i386-linux-gnu:
/usr/lib/i386-linux-gnu:
/usr/lib/alsa-lib:
/usr/local/lib:
/usr/lib/mozilla:
/lib:
/usr/lib:
Tagged as: