Just found I can set LD_DEBUG to see the full translation process of ld.so. This seems to confirm what I've seen in the source: ld.so uses cwd instead of process file location for $ORIGIN interpolation.
$ mkdir -p /tmp/dummy/working/directory $ cd /tmp/dummy/working/directory $ which python /home/avallee/bin/python $ readelf -d $(which python) 0x0000000000000001 (NEEDED) Shared library: [libpython2.7.so.1.0] 0x000000000000000f (RPATH) Library rpath: [$ORIGIN/../lib] 0x000000006ffffffb (FLAGS_1) Flags: ORIGIN $ LD_DEBUG=1 python rtld loading: 'python' ... orig_path $ORIGIN/../lib new_path /tmp/dummy/working/directory/../lib <failure here> $ LD_DEBUG=1 $(which python) ... orig_path $ORIGIN/../lib new_path /home/avallee/bin/../lib <success here> On Fri, Dec 11, 2015 at 5:04 PM, Aurélien Vallée <[email protected]> wrote: > Hello, > > I have troubles understanding the interpretation of $ORIGIN on > OpenBSD. I'm switching to OpenBSD from Linux, so I may be biased in my > assumptions. > > I built a program (python in this example) with the following ld parameters: > > -Wl,origin,z > -Wl,rpath,'$ORIGIN/../lib' > > I can then check that the proper attributes were set on the binary: > > $ readelf -d python > ... > 0x0000000000000001 (NEEDED) Shared library: [libpython2.7.so.1.0] > ... > 0x000000000000000f (RPATH) Library rpath: [$ORIGIN/../lib] > ... > 0x000000006ffffffb (FLAGS_1) Flags: ORIGIN > > On the filesystem, everything is also correct, say I have: > > - The python binary located in ~/bin/python > - The python library located in ~/lib/libpython2.7.so.1.0 > > Now if I run python using its absolute or relative path, everything > works fine. However when I add python to my $PATH, and call it by name > (just "python"), the loader complains it cannot find > libpython2.7.so.1.0. > > e.g. with python in my $PATH: > > $ python > python: can't load library 'libpython2.7.so.1.0' > > That won't work, while: > > $ $(which python) > > or > > $ ~/bin/python > > or > > $ /home/.../bin/python > > These will work. > > Strangely, if I cd to the directory where python is located, then I > can issue just "python" and it will work. e.g: > > $ cd ~/bin > $ python > > It seems to me that $ORIGIN is interpreted as a relative path from the > elf file when calling it with an absolute path, or relative to the > path of the caller when using $PATH. > > I did not expect this behavior, as "man ld.so" states: > >> When resolving dependencies for the loaded objects, ld-elf.so.1 may be >> allowed to translate dynamic token strings in rpath and soname by setting >> -z origin option of the static linker ld(1). The following strings are >> recognized now: >> $ORIGIN Translated to the full path of the loaded object. > > Am I doing something wrong here, or is expected behavior? > > I've spent some time digging libexec/ld.so/resolve.c for an > explanation (I'm on -current snapshots from Dec 3 2015, last week). > It's not an easy lecture for a newcomer, so please forgive me if what > I say below is complete garbage. > > Here is what I found: > > 1) My elf binary is loaded and ends up in _dl_finalize_object() > > 2) My binary has RPATH and FLAGS_1 to ORIGIN, so _dl_origin_subst() is called > if (object->dyn.rpath) { > object->rpath = _dl_split_path(object->dyn.rpath); > if ((object->obj_flags & DF_1_ORIGIN) && _dl_trust) > _dl_origin_subst(object); > } > > 3) _dl_origin_subst() retrieves the original path of the elf object, > and applies $ORIGIN interpolation if necessary > if (_dl_origin_path(object, origin_path) != 0) > return; > > /* perform path substitutions on each segment of rpath */ > for (pp = object->rpath; *pp != NULL; pp++) { > _dl_origin_subst_path(object, origin_path, pp); > } > > 4) _dl_origin_subst_path() will use origin_path in case of $ORIGIN, so > back to _dl_origin_path() to understand what is used. > case SUBST_ORIGIN: > value = origin_path; > break; > > 5) _dl_origin_path() just uses _dl_realpath(_dl_dirname()) on the elf object. > > 6) _dl_dirname() will return "." if the path provided does not contain a '/' > > 7) _dl_realpath() will prepend the CWD to this. > > These last steps seems odd to me. Why is the CWD used here, when what > we really want is the directory containing the binary of the currently > running process (i.e. /proc/self/exe on linux). > Just my guess, I don't really know what I'm talking about. > > Anyway, explanations greatly appreciated! And again, please forgive > me if all that is just me doing stupid things. -- Aurélien Vallée Phone +33 9 77 19 85 61

