7

On osx loader, @loader_path resolves to the position of the generic binary object, and @executable_path to the position of the executable. On Linux, apparently there's only $ORIGIN, which resolves to the executable path. Is there a hidden feature in the linux loader to specify a dynamic search path for a generic ELF object? Or maybe $ORIGIN behaves differently for so objects?

Linux also has $LIB and $PLATFORM, but they don't provide what I need.

Stefano Borini
  • 138,652
  • 96
  • 297
  • 431

2 Answers2

8

$ORIGIN is the location of the object being loaded, so it is different in the executable and shared libraries loaded by the executable.

Edit: Here's a small test I performed to check:

~$ mkdir /tmp/tests
~$ cd /tmp/tests
tests$ mkdir good bad
tests$ gcc -fPIC  -shared -o good/libtest.so -Wl,-rpath,\$ORIGIN -x c - <<< 'int puts(const char*); void foo() { puts("good"); }'
tests$ gcc -fPIC  -shared -o bad/libtest.so -Wl,-rpath,\$ORIGIN -x c - <<< 'int puts(const char*); void foo() { puts("bad"); }'
tests$ gcc -fPIC  -shared -o good/libtest2.so -Wl,-rpath,\$ORIGIN -x c - -ltest -Lgood <<< 'void foo(); void bar() { foo(); }'
tests$ gcc  -o bad/a.out good/libtest2.so -x c - -Wl,-rpath,\$ORIGIN -Wl,-rpath-link,good <<< 'void bar(); int main() { bar(); }'
tests$ 
tests$ readelf -d bad/* good/* | grep RPATH
 0x000000000000000f (RPATH)              Library rpath: [$ORIGIN]
 0x000000000000000f (RPATH)              Library rpath: [$ORIGIN]
 0x000000000000000f (RPATH)              Library rpath: [$ORIGIN]
 0x000000000000000f (RPATH)              Library rpath: [$ORIGIN]
tests$ 
tests$ ldd bad/a.out 
        linux-vdso.so.1 =>  (0x00007faf2f295000)
        good/libtest2.so (0x00007faf2f092000)
        libc.so.6 => /lib64/libc.so.6 (0x0000003949800000)
        libtest.so => /tmp/tests/good/libtest.so (0x00007faf2ee66000)
        /lib64/ld-linux-x86-64.so.2 (0x0000003949400000)
tests$ bad/a.out
good

I think that demonstrates it works, everything has RPATH=$ORIGIN, the executable is explicitly linked to libtest2.so, which picks up libtest.so in its own directory not the executable's.

Using LD_DEBUG=libs bad/a.out shows:

[...]
  17779:     find library=libtest.so [0]; searching
  17779:      search path=/tmp/tests/good/tls/x86_64:/tmp/tests/good/tls:/tmp/tests/good/x86_64:/tmp/tests/good              (RPATH from file good/libtest2.so)
[...]

i.e. when looking for the libtest.so dependency of good/libtest2.so the search path uses the RPATH from good/libtest2.so, which expands to /tmp/tests/good which is the $ORIGIN from good/libtest2.so not the $ORIGIN of the executable.

Jonathan Wakely
  • 166,810
  • 27
  • 341
  • 521
  • Not according to the manpage `ld.so understands the string $ORIGIN (or equivalently ${ORIGIN}) in an rpath specification to mean the directory containing the application executable.` – Stefano Borini Oct 09 '14 at 14:38
  • Hmm, maybe I'm thinking of Solaris then ... it disagrees with the GNU dynamic linker regarding the interpretation of `$ORIGIN` in shared libs, so maybe I got them the wrong way round. – Jonathan Wakely Oct 09 '14 at 14:44
  • I've just tested it, and an executable `bad/a.out` linked to `good/libtest2.so` which depends on `libtest.so` will get it from `good` not `bad`, i.e. it uses the shared library's `$ORIGIN` not the executable's – Jonathan Wakely Oct 09 '14 at 14:50
  • perfect! so the manpage is incorrect, or at least, unclear. Thank you! – Stefano Borini Oct 09 '14 at 14:54
  • It has been corrected in the latest [man-pages release](http://linux-man-pages.blogspot.co.uk/2015/01/man-pages-376-is-released.html) – Jonathan Wakely Jan 02 '15 at 23:07
-1

The linux loader searches in following order:

DT_RPATH (specified on gcc command line, ignored si DT_RUNPATH exist)

LD_LIBRARY_PATH (specified in the environment)

DT_RUNPATH (specified on gcc command line)

ld.so.conf (for directories specified on lines and compiled with ldconfig)

/lib and /usr/lib

P. Morel
  • 76
  • 3