nikitablack
nikitablack

Reputation: 4663

Why my executable runs with `RPATH` but not with `RUNPATH`

I build an executable app that uses liba. liba in turn needs libb. libb in turn needs libc. The dependency looks like this: app -> liba -> libb -> libc. The app and liba are built by me while libb and libc are 3rd party. I do not know how they were compiled, but I know that they both are in the same folder and I have a CMake config to find libb.


A setup that is not working.

In CMake I find the package for libb, publically link the lib to liba and finally link liba to app. The app compiles fine but running it I'm getting: error while loading shared libraries: libc: cannot open shared object file: No such file or directory. I.e. the last library, which symbols I don't even use directly can not be found.

I inspect my library liba with readelf -d liba | grep PATH:

...
0x000000000000001d (RUNPATH)            Library runpath: [/path/to/dir/with/both/libb/and/libc:]
...

So the path is inside my liba, it's correct and points to both libb and libc.

Next, I inspect the loading search paths with LD_DEBUG=libs ./app:

...
     27012: find library=libb [0]; searching
     27012:  search path=/*a lot of paths INCLUDING the needed path*/       (RUNPATH from file ./app)
...
     27012: find library=libc [0]; searching
     27012:  search cache=/etc/ld.so.cache
     27012:  search path=/*a lot of system paths, but the needed path is MISSING*/      (system search path)

     27012:   trying file=/lib/x86_64/libc
     many other tries
...

How can that be that libb is found in RUNPATH but libc not???! Why the libc uses system search path instead of RUNPATH??


A setup that is working

Next, I try to use a RPATH when build my library liba by setting -Wl,--disable-new-dtags flag. Now readelf -d liba | grep PATH prints me the same path as before, but abbreviated with RPATH instead of RUNPATH and LD_DEBUG=libs ./app prints:

...
     27012: find library=libb [0]; searching
     27012:  search path=/*a lot of paths INCLUDING the needed path*/       (RUNPATH from file ./app)
...
     27012: find library=libc [0]; searching
     27012:  search path=/*a lot of paths INCLUDING the needed path*/       (RUNPATH from file ./app)
...

Now both libraries use RUNPATH but I can't understand why. Why the hell they use RUNPATH though the lib was compiled with explicit RPATH?? Where does this come from?


Update:

Here by [libc] I mean my 3rd party library (a, b, c), not the system one.

readelf -d libb | grep NEEDED
 0x0000000000000001 (NEEDED)             Shared library: [libboost_thread.so.1.65.1]
 0x0000000000000001 (NEEDED)             Shared library: [libboost_system.so.1.65.1]
 0x0000000000000001 (NEEDED)             Shared library: [libc]
 0x0000000000000001 (NEEDED)             Shared library: [libpthread.so.0]
 0x0000000000000001 (NEEDED)             Shared library: [libstdc++.so.6]
 0x0000000000000001 (NEEDED)             Shared library: [libm.so.6]
 0x0000000000000001 (NEEDED)             Shared library: [libgcc_s.so.1]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
 0x0000000000000001 (NEEDED)             Shared library: [ld-linux-x86-64.so.2]

Update 2:

After more reading, I was able to formulate the search request more precisely and immediately found the explanation. For example, here:

c++ secondary dependency resolution with runpath

Dynamic linking with rpath not working under Ubuntu 17.10

Upvotes: 0

Views: 1034

Answers (0)

Related Questions