[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
- Passing LD_RUN_PATH through to the linker,
Kevin R. Bulgrien <=