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

Reply via email to