Linux

了解 LD_ASSUME_KERNEL 用法

  • March 30, 2022

我試圖理解LD_ASSUME_KERNEL我係統上的 env 變數(Debian/bullseye+bpo)。

根據:

$ 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/>.

這裡的重要部分是手冊中的這句話:

在執行時,動態連結器確定正在執行的核心的 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失敗。

引用自:https://unix.stackexchange.com/questions/697352