libtool
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Passing LD_RUN_PATH through to the linker


From: Kevin R. Bulgrien
Subject: Passing LD_RUN_PATH through to the linker
Date: Wed, 14 Dec 2022 23:25:24 -0600 (CST)

During attempts to build top-of-tree libssh2 on a dinosaur (SCO OpenServer 
5.0.7),
an issue with loading indirect dependencies of libssh2.so is occurring.  They 
can
be worked around by setting LD_LIBRARY_PATH at run-time, however it seems much
simpler to depend on DT_RPATH so the run-time environment does not require
management.

The linker behaves as defined at the link following (ironically, more completely
documented on this list than in the official documentation):

  https://lists.gnu.org/archive/html/bug-libtool/2002-08/msg00026.html

In essence, the libssh2 project is set up in a way so that DT_RUNPATH is set in
the build ELF objects and DT_RPATH is omitted.  I need to keep the original
vendor files and configuration, so have chosen to place the alternate
ELF binaries under /usr/local.

With a (slightly patched for this platform) copy of libssh2-1.10.1_DEV, and a
configure like:

  CONFIG_SHELL=/usr/bin/bash \
    ./configure \
      CONFIG_SHELL=/usr/bin/bash \
        --prefix=/usr/local \
          --with-libssl-prefix=/usr/local

The binary that uses the shared object has DT_RUNPATH:

  $ readelf -d example/.libs/ssh2

  Dynamic segment at offset 0x1adc contains 23 entries:
    Tag        Type                         Name/Value
   0x00000001 (NEEDED)                     Shared library: [libssh2.so.1]
   0x00000001 (NEEDED)                     Shared library: [libcrypto.so.3]
   0x00000001 (NEEDED)                     Shared library: [/usr/lib/libz.so.1]
   0x00000001 (NEEDED)                     Shared library: [libssl.so.3]
   0x00000001 (NEEDED)                     Shared library: 
[/usr/lib/libcrypt.so]
   0x00000001 (NEEDED)                     Shared library: [/usr/lib/libc.so.1] 
program interpreter
   0x0000000c (INIT)                       0x8049ac0
   0x0000000d (FINI)                       0x8049ad0
   0x0000001d (RUNPATH)                    Library runpath: [/usr/local/lib]
   ...

The shared object has DT_RUNPATH:

  $ readelf -d /usr/local/lib/libssh2.so

  Dynamic segment at offset 0xfb30 contains 21 entries:
    Tag        Type                         Name/Value
   0x00000001 (NEEDED)                     Shared library: [libcrypto.so.3]
   0x00000001 (NEEDED)                     Shared library: [/usr/lib/libz.so.1]
   0x00000001 (NEEDED)                     Shared library: [libssl.so.3]
   0x0000000c (INIT)                       0x4dae0
   0x0000000d (FINI)                       0x4daf0
   0x0000000e (SONAME)                     Library soname: [libssh2.so.1]
   0x0000001d (RUNPATH)                    Library runpath: [/usr/local/lib]
   ...

Though the direct dependency loads, the indirect does not when LD_LIBRARY_PATH 
is unset.

  $ echo "|$LD_LIBRARY_PATH|"
  ||
  $ export LD_DEBUG=16
  $ example/.libs/ssh2
  Object:  Search Path DT_RUNPATH
  /usr/local/lib
  Object: example/.libs/ssh2 Search Path LD_LIBRARY_PATH
  Object: example/.libs/ssh2 Search Path DT_RPATH
  Object: example/.libs/ssh2 Search Path DEFAULT
  /usr/lib
  search_dir_list: trying: /usr/local/lib/libssh2.so.1
  Object: /usr/local/lib/libssh2.so.1 Search Path DT_RUNPATH
  /usr/local/lib
  search_dir_list: trying: /usr/local/lib/libcrypto.so.3
  _rt_so_find: trying: /usr/lib/libz.so.1
  search_dir_list: trying: /usr/local/lib/libssl.so.3
  _rt_so_find: trying: /usr/lib/libcrypt.so
  search_dir_list: trying: /usr/local/lib/libcrypto.so.3
  _rt_so_find: trying: /usr/lib/libz.so.1
  search_dir_list: trying: /usr/local/lib/libssl.so.3
  _rt_so_find: trying: /usr/lib/libsocket.so.2
  search_dir_list: trying: /usr/lib/libnsl.so
  search_dir_list: trying: /usr/lib/libcrypto.so.3
  dynamic linker : example/.libs/ssh2 : could not open libcrypto.so.3
  Killed

  $ ls -l /usr/local/lib/libcrypto.so.3 
/opt/K/CSDI/openssl/3.0.3/usr/local/lib/libcrypto.so.3
  -rwxr-xr-x   1 root     sys      3731468 Dec 14 13:29 
/opt/K/CSDI/openssl/3.0.3/usr/local/lib/libcrypto.so.3
  lrwxrwxrwx   1 root     sys           54 Dec 14 13:29 
/usr/local/lib/libcrypto.so.3 -> 
/opt/K/CSDI/openssl/3.0.3/usr/local/lib/libcrypto.so.3

Not being intimately familiar with autotools/libtool makes it somewhat difficult
to know where to start.  I have made some attempts at looking into config.rpath
or various m4 edits along with autoreconf -fi, but have not been successful at
getting DT_RPATH written.  The attempts were likely completely bogus, but it
occurred to me to try to see if somewhere changing -R to -rpath would tell
libtool to do something differently.  It was hard to sort out which
switches were for libtool and which were for ld.  I managed only to block
DT_RUNPATH without producing an ELF with DT_RPATH.

I cannot build patchelf on this platform, but I have proven that setting 
DT_RPATH
works by using the readelf reported "Dynamic segment at offset 0x1adc" message.
For example:

  $ cat example/.libs/ssh2 | xxd >ssh2.xxd.orig
  $ cp ssh2.xxd.orig ssh2.xxd.edit
  $ vim ssh2.xxd.edit

  $ diff -U1 ssh2.xxd.orig ssh2.xxd.edit
  --- ssh2.xxd.orig       2022-12-14 21:35:09.000000000 -0600
  +++ ssh2.xxd.edit       2022-12-14 21:39:32.000000000 -0600
  @@ -433,3 +433,3 @@
   0001b00: b403 0000 0100 0000 c903 0000 0c00 0000  ................
  -0001b10: c09a 0408 0d00 0000 d09a 0408 1d00 0000  ................
  +0001b10: c09a 0408 0d00 0000 d09a 0408 0f00 0000  ................
   0001b20: dc03 0000 0400 0000 1481 0408 0500 0000  ................

  $ cat ssh2.xxd.edit | xxd -r >ssh2

  $ readelf -d ./ssh2

  Dynamic segment at offset 0x1adc contains 23 entries:
    Tag        Type                         Name/Value
   0x00000001 (NEEDED)                     Shared library: [libssh2.so.1]
   0x00000001 (NEEDED)                     Shared library: [libcrypto.so.3]
   0x00000001 (NEEDED)                     Shared library: [/usr/lib/libz.so.1]
   0x00000001 (NEEDED)                     Shared library: [libssl.so.3]
   0x00000001 (NEEDED)                     Shared library: 
[/usr/lib/libcrypt.so]
   0x00000001 (NEEDED)                     Shared library: [/usr/lib/libc.so.1] 
program interpreter
   0x0000000c (INIT)                       0x8049ac0
   0x0000000d (FINI)                       0x8049ad0
   0x0000000f (RPATH)                      Library rpath: [/usr/local/lib]
   ...

Now all the indirect dependencies load without having to set LD_LIBRARY_PATH at 
runtime:

  $ echo "|$LD_LIBRARY_PATH|"
  ||
  $ export LD_DEBUG=16
  $ ./ssh2
  Object: ./ssh2 Search Path LD_LIBRARY_PATH
  Object: ./ssh2 Search Path DT_RPATH
  /usr/local/lib
  Object: ./ssh2 Search Path DEFAULT
  /usr/lib
  search_dir_list: trying: /usr/local/lib/libssh2.so.1
  search_dir_list: trying: /usr/local/lib/libcrypto.so.3
  _rt_so_find: trying: /usr/lib/libz.so.1
  search_dir_list: trying: /usr/local/lib/libssl.so.3
  _rt_so_find: trying: /usr/lib/libcrypt.so
  search_dir_list: trying: /usr/local/lib/libcrypto.so.3
  _rt_so_find: trying: /usr/lib/libz.so.1
  search_dir_list: trying: /usr/local/lib/libssl.so.3
  _rt_so_find: trying: /usr/lib/libsocket.so.2
  search_dir_list: trying: /usr/local/lib/libnsl.so
  search_dir_list: trying: /usr/lib/libnsl.so
  search_dir_list: trying: /usr/local/lib/libcrypto.so.3
  _rt_so_find: trying: /usr/lib/libsocket.so.2
  search_dir_list: trying: /usr/local/lib/libnsl.so
  search_dir_list: trying: /usr/lib/libnsl.so
  Fingerprint: 88 EC C8 1B 18 E8 09 D6 1E A4 B3 5D E1 FE 74 30 8B 4D D7 CA
  Authentication methods: publickey,password,keyboard-interactive
          Authentication by password failed!
  all done!

On this platform, ld does not have a switch that acts like -rpath but will
write DT_RPATH when LD_RUN_PATH is defined in the environment and ld -R
will cause DT_RUNPATH creation in the linked binary.

Not having stumbled on a way to modify the project in a way that leaves
DT_RPATH defined and DT_RUNPATH not defined, it would be appreciated to
have some comment as to whether libtool actually could still cause ld
to see LD_RUN_PATH so it writes DT_RPATH.

I have tried --disable-rpath on a whim but sensibly, neither DT_RPATH or
DT_RUNPATH are placed in the ELF.

I realize I have not shared any libssh2 resources or posted to libssh2
lists, but I wonder if this is even a possibility with libtool.  A lot
of searches turn up folk using patchelf or comments saying that
DT_RPATH is deprecated, and such. 

Can anyone offer a pointer on where to look in autotools/libtool structure
to get DT_RPATH set in the linked binaries or comment on whether this is
even an option with libtool?   I'm finding difficulty differentiating
between -R and -rpath for libtool versus similar switches for ld.

--

Kevin R. Bulgrien



reply via email to

[Prev in Thread] Current Thread [Next in Thread]