0

I'm trying to setup and run a scientific application on Debian 8 guest OS (OpenVZ containerized environment). Since the OS-bundled GNU C++ library is quite old and doesn't contain all needed symbols, I have created a special directory to contain newer version of libstdc++.so.6 and set LD_LIBRARY_PATH environment variable to point to that directory. Also, I have made sure that the target application does not have SUID permission set (since, in that case, LD_LIBRARY_PATH could be ignored on some platforms). Despite all that, ldd <APP_EXECUTABLE> command still shows that it uses default system location /usr/lib/x86_64-linux-gnu. Why LD_LIBRARY_PATH is being ignored?

P.S. I have also tried using LD_PRELOAD environment variable, but it was ignored as well.

  • 1
    I don't remember exactly what the case on debian 8 was, but with older gcc/binutils version it was the case that --enable-new-dtags was not the default and the DT_RPATH burnt into the binary would override any LD_LIBRARY_PATH. You can check with readelf -a <your_binary_or_so> | egrep 'RPATH|RUNPATH'. – mosvy Jul 19 at 23:53
  • @mosvy Thank you. The readelf command that you suggested produces the following output: 0x000000000000000f (RPATH) Library rpath: [$ORIGIN/../lib]. If I understand correctly, a set RPATH implies that LD_LIBRARY_PATH is not applicable. I've read that a set RPATH could be changed by using chrpath. Would it be a feasible solution in my case? – Aleksandr Blekh Jul 20 at 0:41
  • @mosvy ... Or, perhaps, an even easier solution would be to create a symlink in <APP_DIR/lib>, pointing to the shared library version, containing required symbols. What do you think? – Aleksandr Blekh Jul 20 at 0:45
  • 1
    The latter would be a better solution. – mosvy Jul 20 at 0:50
  • 1
    No idea, it should work. It certainly does in my testing. strace it, run ldd on it. Maybe the symlink you created is broken. – mosvy Jul 20 at 1:04
1

The contents of the standard system library directories (usually /lib and /usr/lib) and any directories defined in /etc/ld.so.conf file and/or /etc/ld.so.conf.d/*.conf files are examined by the ldconfig command and the results are cached in /etc/ld.so.cache. The ldconfig command is normally run automatically by the package management tools whenever you install or remove library packages.

The dynamic loader uses this cache to speed up finding the required libraries whenever a new program is loaded.

If you add or remove symlinks within system library directories manually, you will most likely have to run ldconfig as root afterwards to make the system refresh the cache and so make your changes effective. Without running that command, the dynamic loader will have no clue that the library paths have changed, and will happily keep using the library paths from the old cache.

Although the above is essentially the basic mechanism for looking up libraries, it can be overridden by using the LD_LIBRARY_PATH(= "check these library directories first") or LD_PRELOAD(= "always load this library first) environment variables.

It is also possible to embed library path information into the program binary itself, using section attributes named DT_RPATH (deprecated) or DT_RUNPATH. These will also override the cache mechanism, but as far as I know their use is fairly unusual, precisely because it tends to lead into problems like the original question when you need a program to work in a system/environment that is no longer an exact match of the system the program was developed for.

  • 1
    nope, using LD_LIBRARY_PATH or the DT_RPATH / DT_RUNPATH dynamic section attributes will override /etc/ld.so.cache, please read the order in the ld.so(8) manpage. – mosvy Jul 20 at 9:32
  • 1
    the OP had tried to create a link in the $ORIGIN/../lib path pointed by the binary's DT_RPATH and, for some reason, it didn't work (or at least that's my understanding of it). – mosvy Jul 20 at 9:37
  • Thank you very much for your answer (+1 for desire to help). However, it seems that @mosvy is correct in that LD_LIBRARY_PATH or DT_RPATH / DT_RUNPATH attributes override loader cache. @mosvy: Your understanding of my symlink solution attempt is correct as well. Later today, I plan to try the chrpath solution. Even though it's less elegant, I'm afraid that it might be the only feasible approach at this time (I still plan to investigate why my LD_LIBRARY_PATH and $ORIGIN/../lib symlink solutions didn't work). – Aleksandr Blekh Jul 20 at 9:49
  • I think that I might have figured out the reason why my original two approaches did not work. It seems that I accidentally/somehow deployed a 32-bit version of GNU C++ library on a 64-bit system, which, obviously, loader was not happy about ... :-) Now, the challenge is to make sure that I install the newer version of the library in a safe way (to maintain the original / OS-bundled version intact). I guess, I will just download a relevant .deb package, install it locally (not system-wide) and try either LD_LIBRARY_PATH, or symlink approach. – Aleksandr Blekh Jul 20 at 10:13
  • 1
    I updated my answer to incorporate the comments of @mosvy ... but accidentally mixing in a 32-bit library package on otherwise fully 64-bit system may indeed cause some confusion and unhappiness. However, I think Debian 8 can deal with 64/32 bitness using the multiarch mechanism: you can run a 32-bit application on a 64-bit system, if the necessary 32-bit libraries are available. But you can never satisfy a library requirement of a 64-bit program with a 32-bit library, or vice versa. – telcoM Jul 20 at 10:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.