10

On CentOS 7.2, I've built an app with g++ 4.8.5 that can't run because it can't find a library that does exist in its runpath. I'm pretty sure it worked two weeks ago. What could cause this?

$ ./app
./app: error while loading shared libraries: libhdf5.so.9: cannot open shared object file: No such file or directory

$ ldd ./app | grep libhdf5
    libhdf5.so.9 => not found

$ readelf app -d | grep path
 0x000000000000001d (RUNPATH)            Library runpath: [/opt/ProductName/lib:/opt/ProductName/lib/private]

$ ll /opt/ProductName/lib/libhdf5.so*
lrwxrwxrwx. 1 fotechd fotechd      16 Oct 26 14:38 /opt/ProductName/lib/libhdf5.so -> libhdf5.so.9.0.0
lrwxrwxrwx. 1 fotechd fotechd      16 Oct 26 14:38 /opt/ProductName/lib/libhdf5.so.9 -> libhdf5.so.9.0.0
-rwxr-xr-x. 1 fotechd fotechd 3316074 Oct 26 14:35 /opt/ProductName/lib/libhdf5.so.9.0.0

Setting LD_LIBRARY_PATH fixes it temporarily:

$ LD_LIBRARY_PATH=/opt/ProductName/lib ./app
...
OK
Qwertie
  • 16,354
  • 20
  • 105
  • 148

2 Answers2

11

I have been able to solve this issue on my side. For me it was because the not found library was an indirect one and runpath actually does not resolve indirect dependencies. I fixed it with using rpath instead of runpath by passing the additional -Wl,--disable-new-dtags linker option to the compiler.

There is a good and detailed explanation here: How to set RPATH and RUNPATH with GCC/LD?

Longfield
  • 1,505
  • 1
  • 12
  • 24
  • 1
    So you're saying that if your app loads an .so, which loads another .so, the second .so is unaffected by the runpath (but is affected by rpath)? – Qwertie Feb 15 '19 at 17:51
  • 1
    In my case I couldn't tell which dependencies are indirect since `ldd` only shows a flat list (and I'm new to the codebase). To get a proper tree structure you need to call `lddtree` instead, which is part of `pax-utils` (on CentOS I got it with `sudo yum install pax-utils --enablerepo=epel`). – Qwertie Feb 15 '19 at 17:55
  • Yes, that's exactly what an indirect dependency is: "a .so loaded by a .so". In my case, the not found .so was not in the list of (NEEDED) libraries you get with `readelf -d` – Longfield Feb 18 '19 at 09:51
0

In order to find the shared objects, dlopen() searches the following, in this order:

  • the runtime library search path that was set using the -rpath option to ld (see the Utilities Reference) when the binary was linked
  • directories specified by the LD_LIBRARY_PATH environment variable
  • directories specified by the _CS_LIBPATH configuration string

It seems dlopen() does not check on RUNPATH.

http://www.qnx.com/developers/docs/6.5.0SP1.update/com.qnx.doc.neutrino_lib_ref/d/dlopen.html

Samuel
  • 803
  • 8
  • 17