2

I've been reading for a while about how the dynamic linker/loader works, RPATH vs RUNPATH, direct vs transitive dependencies, etc. My understanding so far is that if a binary has RPATH (not RUNPATH), then its RPATH is what the dynamic loader uses to find all dependencies, including transitive dependencies.

However it does not work in the following situation:

binary(RPATH) -> libB(RUNPATH)  -> libA

Toy example:

g++ a.cpp -shared -fPIC -o liba.so
g++ b.cpp -shared -fPIC -o libb.so -L. -la -Wl,-rpath=/foo
g++ main.cpp -L. -lb -la -Wl,-rpath=\$ORIGIN -Wl,--disable-new-dtags

Under this setup, the RPATH of the binary is not enough to find libA transitively:

$ ldd a.out
    linux-vdso.so.1 (0x00007ffd2dd81000)
    libb.so => /tmp/test/./libb.so (0x00007ff0d8217000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007ff0d800f000)
    /lib64/ld-linux-x86-64.so.2 (0x00007ff0d8223000)
    liba.so => not found

However if the RUNPATH from libB is removed, then libA can be found via the RPATH of the binary.

Is this expected? The docs only say:

Using the directories specified in the DT_RPATH dynamic section attribute of the binary if present and DT_RUNPATH attribute does not exist

DT_RUNPATH does not exist in the binary.

In my actual case libA and libB are third-party libs out of my control. Given that I need to have my binary and libraries in a non-standard location and I'd rather not patchelf third-party libs, is LD_LIBRARY_PATH really the only solution to have my binary find the libraries it needs?

To clarify, I'm running Ubuntu 20.04 with default GCC toolchain.

Thanks!

user1011113
  • 1,114
  • 8
  • 27

0 Answers0