if a shared library is linked to a binary, and the shared library also depends on other libs , what are the priorities (linker search order) of the RPATH of the shared library a
According to my observation, if there is an application main
which dynamically loads library first.so
, and the latter in turn dynamically loads library second.so
, and both main
and first.so
contain RPATH, then dynamic linker will search second.so
first using the first.so
's RPATH, resolving $ORIGIN as the first.so
's directory, and only if it fails, the linker will proceed to the main
's RPATH now resolving $ORIGIN as main
's directory.
This does not contradict the dynamic linker doc (look for Rpath token expansion):
$ORIGIN (or equivalently ${ORIGIN}): This expands to the directory containing the program or shared object. ...
To check this I've created a test application and two libraries: main
, liba
and libb
respectively. main
is linked against liba
, and liba
is linked against libb
:
main -> liba.so -> libb.so
The built binaries are located this way:
/cwd/main
/cwd/lib/liba.so
/cwd/lib/libb.so
Both main
and liba
are built with the --rpath=\$ORIGIN/lib
linker flag:
~$ readelf -a /cwd/main | grep ORIGIN
0x000000000000000f (RPATH) Library rpath: [$ORIGIN/lib]
~$ readelf -a /cwd/lib/liba.so | grep ORIGIN
0x000000000000000f (RPATH) Library rpath: [$ORIGIN/lib]
With the help of the LD_DEBUG environment variable I've checked how dynamic linker processes RPATH:
~$ LD_DEBUG=libs /cwd/main
: find library=liba.so [0]; searching
: search path=/cwd/lib/tls/x86_64:/cwd/lib/tls:/cwd/lib/x86_64:/cwd/lib (RPATH from file /cwd/main)
: trying file=/cwd/lib/tls/x86_64/liba.so
: trying file=/cwd/lib/tls/liba.so
: trying file=/cwd/lib/x86_64/liba.so
: trying file=/cwd/lib/liba.so
94313:
: find library=libc.so.6 [0]; searching
: search path=/cwd/lib (RPATH from file /cwd/main)
: trying file=/cwd/lib/libc.so.6
: search cache=/etc/ld.so.cache
: trying file=/lib/x86_64-linux-gnu/libc.so.6
94313:
: find library=libb.so [0]; searching
: search path=/cwd/lib/lib/tls/x86_64:/cwd/lib/lib/tls:/cwd/lib/lib/x86_64:/cwd/lib/lib (RPATH from file /cwd/lib/liba.so)
: trying file=/cwd/lib/lib/tls/x86_64/libb.so
: trying file=/cwd/lib/lib/tls/libb.so
: trying file=/cwd/lib/lib/x86_64/libb.so
: trying file=/cwd/lib/lib/libb.so
: search path=/cwd/lib (RPATH from file /cwd/main)
: trying file=/cwd/lib/libb.so
From that we can see, that the linker first encounters the need to load liba.so
and uses the main
binary's RPATH to resolve this. Then it encounters the need to load libb.so
and it first uses the liba.so
library's RPATH to resolve this. But since the RPATH is $ORIGIN/lib
and libb.so
is in the same directory as liba.so
, the linker fails to find libb.so
using liba.so
's RPATH. After that it falls back to main
's RPATH and only using the latter it succeeds to find libb.so
.
Test environment: Linux ubuntu 4.15.0-34-generic #37~16.04.1-Ubuntu (64-bit), /lib/x86_64-linux-gnu/ld-2.23.so.