45

This page says about order for library search in ld.so:

Unless loading object has RUNPATH:
    RPATH of the loading object,
        then the RPATH of its loader (unless it has a RUNPATH), ...,
        until the end of the chain, which is either the executable
        or an object loaded by dlopen
    Unless executable has RUNPATH:
        RPATH of the executable
LD_LIBRARY_PATH
RUNPATH of the loading object
ld.so.cache
default dirs

And then suggests:

When you ship binaries, either use RPATH and not RUNPATH or ensure LD_LIBRARY_PATH is set before they are run.

So, using RPATH with RUNPATH is bad because RUNPATH kind-of cancels RPATH so indirect dynamic loading doesn't work as expected? But why then RPATH got deprecated in favor of RUNPATH?

Can somebody explain the situation?

Jonathon Reinhart
  • 132,704
  • 33
  • 254
  • 328
zaharpopov
  • 16,882
  • 23
  • 75
  • 93
  • 8
    I found [this](https://gitlab.kitware.com/cmake/community/wikis/doc/cmake/RPATH-handling) article from cmake's handling of RPATH/RUNPATH informative, so leave it here for the next googler – dashesy May 10 '18 at 22:07

3 Answers3

45

When you ship a binary, it's good to provide means for the users to accommodate the binary to the specifics of their own system, among other things, adjusting library search paths.

A user can generally tweak LD_LIBRARY_PATH and /etc/ld.so.conf, both of which are with lower precedence than DT_RPATH, i.e. you can't override what is hardcoded in the binary, whereas if you use DT_RUNPATH instead, a user can override it with LD_LIBRARY_PATH.

(FWIW, I think ld.so.conf should also take precedence over DT_RUNPATH, but, anyway, at least we've got LD_LIBRARY_PATH).

Also, I strongly disagree with the suggestion above to use DT_RPATH. IMO, its best to use neither DT_RPATH nor DT_RUNPATH in shipped binaries.

unless

you ship all your dependent libraries with your executables and wish to ensure that things JustWork(tm) after installation, in this case use DT_RPATH.

larsks
  • 277,717
  • 41
  • 399
  • 399
chill
  • 16,470
  • 2
  • 40
  • 44
  • 2
    problem is, RUNPATH is recommended over RPATH, and RPATH is deprecated, but RUNPATH is currently not supported by all systems. so what I do **today** to make application work? as Qt article show, when using plugins it is useful to use RPATH more than RUNPATH. so the whole situation is very confusing here – zaharpopov Nov 07 '11 at 08:50
  • 1
    @zaharpopov, The best approach I would recommend and follow myself is to produce applications which are nicely integrated in the target platform, which would include, among other things, *not distributing competing versions of the platform's shared libraries*. I think this is the root of the problem and hacks and slashes around `DT_RPATH` and friends are an ill-directed effort trying to side-step the problem instead of solving it. – chill Nov 07 '11 at 09:15
  • 2
    this not simple. with Qt problem was the app wants newer version of Qt libs than exist on system. some systems have outdated Qt SOs, so what would you do then? i think it make sense distribute Qt SOs with you if you need a specific version – zaharpopov Nov 07 '11 at 13:01
  • @zaharpopov, yes, it may make sense for the application vendors, which are generally concerned only with their own application and not with the big picture. But it does not make sense from the point of view of system vendors and integrators and it's *them* who deprecated `DT_RPATH`. – chill Nov 07 '11 at 14:06
33

Chill's answer is exactly right; I wanted to simply add some color, from a recent reading of the glibc source ([master 8b0ccb2], in 2.17). To be clear, if a library is not found in the location specified by a given level, the next level is tried. If a library is found at a given level, the search stops.

Dynamic Library Search Order:

  1. DT_RPATH in the ELF binary, unless DT_RUNPATH set.
  2. LD_LIBRARY_PATH entries, unless setuid/setgid
  3. DT_RUNPATH in ELF binary
  4. /etc/ld.so.cache entries, unless -z nodeflib given at link time
  5. /lib, /usr/lib unless -z nodeflib
  6. Done, "not found".
FDS
  • 4,999
  • 2
  • 22
  • 13
17

But why then RPATH got deprecated in favor of RUNPATH?

When DT_RPATH was introduced, it had precedence over all other parameters. This made impossible to override the libraries search path even for development purposes. Therefore another parameter, LD_RUNPATH, was introduced that has lower precedence than LD_LIBRARY_PATH.

More details can be found in the "How to write shared libraries" work written by Ulrich Drepper.

MichaelGoren
  • 961
  • 9
  • 15
  • 4
    This answer explains the need for `DT_RUNPATH`, but not why `DT_RPATH` is deprecated. Both have their own usage, and `DT_RUNPATH` breaks `libtool` when `LD_LIBRARY_PATH` is used: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=859732 – vinc17 Jun 01 '17 at 16:27
  • @vinc17 One reason for deprecation could be that the behavior of DT_RPATH to not be overridable is generally undesired. It has to work that way for compatibility reasons, thus if the behavior cannot be changed as desired, it will be removed instead and first step is to deprecate it. – Mecki Oct 31 '19 at 13:57
  • @Mecki If you want the path to be overridable, then you can use `DT_RUNPATH`. There is no need to drop `DT_RPATH`. – vinc17 Oct 31 '19 at 20:41
  • @vinc17 There is, if you don't want to have anything that is not overridable as DT_RPATH isn't and that cannot be changed anymore, so it can only be dropped and removed. That's exactly what I already explained in my fist comment. You say "you have the choice" but this choice is maybe not desired as it may have security implications for example. – Mecki Nov 04 '19 at 17:03
  • @Mecki What you're saying does not make any sense. I repeat: If you want the path to be overridable, use `DT_RUNPATH`. And the choice is desired as there are cases where `DT_RUNPATH` will just break. And there are obviously no security implications with the choice. – vinc17 Nov 05 '19 at 07:57
  • 1
    @vinc17 It's not about me wanting something to be overriable, it's about the Linux developers (those people developing Linux itself!) not wanting that something exists which isn't overridable and RT_PATH is not overridable, thus it must stop existing. If you don't get that, then I can't help you. I'm pretty sure every other reader here understands what I'm saying. – Mecki Nov 05 '19 at 09:46
  • 1
    @Mecki They could make `DT_RPATH` overridable by some other environment variable (well, I think that `LD_PRELOAD` can already be used for that, but with drawbacks). Alternatively, they could introduce a new environment variable that would have a lower precedence than `DT_RUNPATH` (thus the user could use that instead of `LD_LIBRARY_PATH`). Both would solve the issue with `libtool`. – vinc17 Dec 21 '19 at 02:53
  • 1
    link dead, this works for now: https://akkadia.org/drepper/dsohowto.pdf – shibormot Dec 14 '21 at 18:32