On Hurd, 'ldd' from glibc does not find the dependent libraries when their lookup requires rpath entries that use $ORIGIN. On Linux, in contrast, this works. How to reproduce: Take main.c and lib.c from the attachments. On Hurd: $ gcc -Wall -shared -o libfoo.so lib.c $ mkdir inst1 $ gcc -Wall -o inst1/main main.c libfoo.so '-Wl,-rpath,$ORIGIN' $ mv libfoo.so inst1/libfoo.so $ inst1/main bar -> 42 $ ldd inst1/main libfoo.so => not found libc.so.0.3 => /lib/i386-gnu/libc.so.0.3 (0x01012000) /lib/ld.so => /lib/ld.so.1 (0x08000000) libmachuser.so.1 => /lib/i386-gnu/libmachuser.so.1 (0x01258000) libhurduser.so.0.3 => /lib/i386-gnu/libhurduser.so.0.3 (0x01271000) $ mv inst1 inst2 $ inst2/main bar -> 42 $ ldd inst2/main libfoo.so => not found libc.so.0.3 => /lib/i386-gnu/libc.so.0.3 (0x01012000) /lib/ld.so => /lib/ld.so.1 (0x08000000) libmachuser.so.1 => /lib/i386-gnu/libmachuser.so.1 (0x01258000) libhurduser.so.0.3 => /lib/i386-gnu/libhurduser.so.0.3 (0x01271000) $ ldd --version ldd (Debian GLIBC 2.28-7) 2.28 ... $ readelf -d inst2/main ... 0x0000001d (RUNPATH) Library runpath: [$ORIGIN] ... For comparison, on Linux (good results): $ gcc -Wall -shared -o libfoo.so lib.c $ mkdir inst1 $ gcc -Wall -o inst1/main main.c libfoo.so '-Wl,-rpath,$ORIGIN' $ mv libfoo.so inst1/libfoo.so $ inst1/main bar -> 42 $ ldd inst1/main linux-vdso.so.1 => (0x00007ffc75f32000) libfoo.so => /devel/ldd-bug/inst1/libfoo.so (0x00007f8c5357c000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f8c531b2000) /lib64/ld-linux-x86-64.so.2 (0x00007f8c5377e000) $ mv inst1 inst2 $ inst2/main bar -> 42 $ ldd inst2/main linux-vdso.so.1 => (0x00007fffcfb7d000) libfoo.so => /devel/ldd-bug/inst2/libfoo.so (0x00007f9ffbf2e000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f9ffbb64000) /lib64/ld-linux-x86-64.so.2 (0x00007f9ffc130000)
Created attachment 11639 [details] Test case
Created attachment 11640 [details] Test case
Created attachment 11641 [details] Test case Test case as a tar.gz file.
Mmm... What normally happens is you run the program, and the exec server sets the LD_ORIGIN_PATH environment variable for the dynamic linker to find it for $ORIGIN substitution (see exec/exec.c's do_exec). But here it's ld.so which loads the binary, so the variable wouldn't be set. Perhaps we need to make ld.so itself set LD_ORIGIN_PATH in that case.