我试图理解LD_ASSUME_KERNEL
我的系统(Debian/bullseye+bpo)上的 env 变量。
根据:
$ man pthreads
我应该能够运行这样的东西,但是在我的系统上,我得到的是:
% LD_ASSUME_KERNEL=2.2.5 ldd /bin/ls
/bin/bash: error while loading shared libraries: libdl.so.2: cannot open shared object file: No such file or directory
这对于我来说有点太低了,无法理解发生了什么。我无法理解LD_ASSUME_KERNEL
我的系统上的实现是否有些损坏,或者我是否未能正确阅读文档。
其他一些失败的尝试:
% LD_TRACE_LOADED_OBJECTS=1 LD_ASSUME_KERNEL=2.2.5 ldd
linux-vdso.so.1 (0x00007ffe3f7e0000)
libtinfo.so.6 => /lib/x86_64-linux-gnu/libtinfo.so.6 (0x00007f5399001000)
libdl.so.2 => not found
libc.so.6 => not found
libc.so.6 => not found
和
% LD_TRACE_LOADED_OBJECTS=1 LD_ASSUME_KERNEL=2.4.19 ldd
linux-vdso.so.1 (0x00007ffeaacb9000)
libtinfo.so.6 => /lib/x86_64-linux-gnu/libtinfo.so.6 (0x00007f861cb18000)
libdl.so.2 => not found
libc.so.6 => not found
libc.so.6 => not found
尽管:
% LD_TRACE_LOADED_OBJECTS=1 ldd
linux-vdso.so.1 (0x00007ffc929a9000)
libtinfo.so.6 => /lib/x86_64-linux-gnu/libtinfo.so.6 (0x00007fa319a29000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fa319a23000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fa31985e000)
/lib64/ld-linux-x86-64.so.2 (0x00007fa319aaa000)
参考:
$ man pthreads
[...]
Selecting the threading implementation: LD_ASSUME_KERNEL
On systems with a glibc that supports both LinuxThreads and NPTL (i.e., glibc 2.3.x), the LD_ASSUME_KERNEL environment variable can be used to override the dynamic linker's default choice of threading implementation. This variable tells the dynamic linker to assume that it is running on top of a particular kernel version. By specifying a kernel version that does not provide the support required by NPTL, we can force the use of LinuxThreads. (The most likely reason for doing this is to run a (broken) application that depends on some nonconformant behavior in LinuxThreads.)
For example:
bash$ $( LD_ASSUME_KERNEL=2.2.5 ldd /bin/ls | grep libc.so | \
awk '{print $3}' ) | egrep -i 'threads|nptl'
linuxthreads-0.10 by Xavier Leroy
同样适用于:
$ man ld.so
[...]
LD_ASSUME_KERNEL (since glibc 2.2.3)
Each shared object can inform the dynamic linker of the minimum kernel ABI version that it requires. (This requirement is encoded in an ELF note section that is viewable via readelf -n as
a section labeled NT_GNU_ABI_TAG.) At run time, the dynamic linker determines the ABI version of the running kernel and will reject loading shared objects that specify minimum ABI versions
that exceed that ABI version.
LD_ASSUME_KERNEL can be used to cause the dynamic linker to assume that it is running on a system with a different kernel ABI version. For example, the following command line causes the
dynamic linker to assume it is running on Linux 2.2.5 when loading the shared objects required by myprog:
$ LD_ASSUME_KERNEL=2.2.5 ./myprog
On systems that provide multiple versions of a shared object (in different directories in the search path) that have different minimum kernel ABI version requirements, LD_ASSUME_KERNEL can
be used to select the version of the object that is used (dependent on the directory search order).
Historically, the most common use of the LD_ASSUME_KERNEL feature was to manually select the older LinuxThreads POSIX threads implementation on systems that provided both LinuxThreads and
NPTL (which latter was typically the default on such systems); see pthreads(7).
% apt-cache policy manpages
manpages:
Installed: 5.10-1
Candidate: 5.10-1
Version table:
*** 5.10-1 500
500 http://deb.debian.org/debian bullseye/main amd64 Packages
500 http://deb.debian.org/debian bullseye/main i386 Packages
100 /var/lib/dpkg/status
附带说明一下,以下各项的输出始终相同:
/lib/x86_64-linux-gnu/libc.so.6
LD_ASSUME_KERNEL=2.2.5 /lib/x86_64-linux-gnu/libc.so.6
LD_ASSUME_KERNEL=2.4.19 /lib/x86_64-linux-gnu/libc.so.6
我得到:
GNU C Library (Debian GLIBC 2.31-13+deb11u3) stable release version 2.31.
Copyright (C) 2020 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
Compiled by GNU CC version 10.2.1 20210110.
libc ABIs: UNIQUE IFUNC ABSOLUTE
For bug reporting instructions, please see:
<http://www.debian.org/Bugs/>.
答案1
这里最重要的部分是手册中的这段引用:
在运行时,动态链接器确定正在运行的内核的 ABI 版本,并将拒绝加载指定超过该 ABI 版本的最小 ABI 版本的共享对象。
file
会告诉您给定库的最低 ABI 版本是什么;由于您正在运行x86_64
,您应该发现在许多情况下最低 ABI 版本是 3.2.0:
$ file -L /lib/x86_64-linux-gnu/libc.so.6
/lib/x86_64-linux-gnu/libc-2.31.so: ELF 64-bit LSB shared object, x86-64, version 1 (GNU/Linux), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=2e5abcee94f3bcbed7bba094f341070a2585a2ba, for GNU/Linux 3.2.0, stripped
在您的系统中,例外情况是libtinfo.so.6
,它没有声明最小 ABI:
$ file -L /lib/x86_64-linux-gnu/libtinfo.so.6
/lib/x86_64-linux-gnu/libtinfo.so.6: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, BuildID[sha1]=d6920dbdd057f44edaf4c1fbce191b5854dfd9e6, stripped
设置LD_ASSUME_KERNEL
为小于 3.2.0 的值会指示动态链接器拒绝任何需要 3.2.0 或更高版本的库;由于您的系统不提供要求较低的受影响库的其他版本,因此ld.so
会失败。