gpt4 book ai didi

linux - 备用 glibc 动态链接器 (ld.so) 的库路径顺序

转载 作者:IT王子 更新时间:2023-10-29 00:21:34 27 4
gpt4 key购买 nike

我需要使用备用 glibc版本,比我系统上安装的版本更新( 2.18 vs 2.15 )。涵盖了几个相关问题 herehere .我在这里问的具体问题如下:

我设置了新动态链接器 (ld-2.18.so) 的库路径,以便新的 libc ( libc-2.18.so ) 在旧 libc 之前被发现(libc-2.15.so)。但是,当我尝试使用新的 ld 运行程序时, 旧版本libc被拾起,生成一个 SEGV . 为什么会这样?

注意:我知道这可以通过使用 --rpath 来解决在编译时或 LD_LIBRARY_PATH在运行时。但是,我仍然想了解为什么仍然需要其中之一。

详情如下:

我下载了glibc-2.18并在 /opt/glibc-2.18 build 它.默认情况下,文件 /opt/glibc-2.18/etc/ld.so.conf不见了。我创建了它,并更新了新 glibc 的库缓存如下。我强调:新的 libc在旧libc之前找到:

$ cat /opt/glibc-2.18/etc/ld.so.conf
/opt/glibc-2.18/lib
/usr/local/lib
/lib/x86_64-linux-gnu
/usr/lib/x86_64-linux-gnu
/usr/lib/x86_64-linux-gnu/mesa
/lib
/usr/lib
$ /opt/glibc-2.18/sbin/ldconfig -v |& grep -E '^[^'$'\t'']|libc\.'
/opt/glibc-2.18/sbin/ldconfig: Path `/opt/glibc-2.18/lib' given more than once
/opt/glibc-2.18/sbin/ldconfig: Can't stat /opt/glibc-2.18/lib64: No such file or directory
/opt/glibc-2.18/sbin/ldconfig: Can't stat /opt/glibc-2.18/libx32: No such file or directory
/opt/glibc-2.18/lib:
libc.so.6 -> libc-2.18.so
/usr/local/lib:
/lib/x86_64-linux-gnu:
libc.so.6 -> libc-2.15.so
/usr/lib/x86_64-linux-gnu:
/usr/lib/x86_64-linux-gnu/mesa:
/lib:
/usr/lib:

然后,我创建了一个简单的 C 程序:

$ cat <<EOF >a.c
> #include <stdio.h>
> int main()
> {
> fprintf(stdout, "ok\n");
> return 0;
> }
> EOF
$ g++ a.c
$ file a.out
a.out: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=0x43b8484e3910072375d68418cb6327478266c0e9, not stripped
$ ldd a.out
linux-vdso.so.1 => (0x00007fffd7ffe000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fa7c47bd000)
/lib64/ld-linux-x86-64.so.2 (0x00007fa7c4b9b000)
$ readelf -a a.out | grep lib
[Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
000000601000 000100000007 R_X86_64_JUMP_SLO 0000000000000000 __libc_start_main + 0
1: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@GLIBC_2.2.5 (2)
46: 00000000004005f0 2 FUNC GLOBAL DEFAULT 13 __libc_csu_fini
52: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@@GLIBC_
57: 0000000000400560 137 FUNC GLOBAL DEFAULT 13 __libc_csu_init
000000: Version: 1 File: libc.so.6 Cnt: 1
$ objdump -x a.out | grep -A3 Version
Version References:
required from libc.so.6:
0x09691a75 0x00 02 GLIBC_2.2.5

如上所示,这个程序有旧的 ld内部硬编码。我可以用新的 ld 强制运行它,我期待新的路径 ld被使用(你可以看到新的 ld.so.cache 被打开)。然而,出于某种原因,我试图理解,旧的 libc在新的 libc 之前找到,生成 SEGV:

$ /opt/glibc-2.18/lib/ld-2.18.so ./a.out
Segmentation fault (core dumped)
$ strace /opt/glibc-2.18/lib/ld-2.18.so ./a.out |& grep open
open("./a.out", O_RDONLY|O_CLOEXEC) = 3
open("/opt/glibc-2.18/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
open("/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3

我还可以使用新库进行编译并嵌入新的 ld如下:

$ g++ -L/opt/glibc-2.18/lib -Wl,--dynamic-linker=/opt/glibc-2.18/lib/ld-2.18.so a.c -o a.2.18.out
$ file a.2.18.out
a.2.18.out: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=0x25ab43f3d29b49fa21385a15e43325e9fb904e81, not stripped
$ ldd a.2.18.out
linux-vdso.so.1 => (0x00007fffa68da000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f9df5cbe000)
/opt/glibc-2.18/lib/ld-2.18.so => /lib64/ld-linux-x86-64.so.2 (0x00007f9df609c000)
$ readelf -a a.2.18.out | grep lib
[Requesting program interpreter: /opt/glibc-2.18/lib/ld-2.18.so]
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
000000601000 000100000007 R_X86_64_JUMP_SLO 0000000000000000 __libc_start_main + 0
1: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@GLIBC_2.2.5 (2)
54: 0000000000400600 2 FUNC GLOBAL DEFAULT 13 __libc_csu_fini
60: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@@GLIBC_
65: 0000000000400570 137 FUNC GLOBAL DEFAULT 13 __libc_csu_init
000000: Version: 1 File: libc.so.6 Cnt: 1
$ objdump -x a.2.18.out | grep -A3 Version
Version References:
required from libc.so.6:
0x09691a75 0x00 02 GLIBC_2.2.5

不过,如果我尝试运行新程序,同样的事情会发生,旧的 libc正在使用而不是新的 libc :

$ ./a.2.18.out
Segmentation fault (core dumped)
$ strace ./a.2.18.out |& grep open
open("/opt/glibc-2.18/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
open("/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3

对于任一可执行文件,指定 LD_LIBRARY_PATH=/opt/glibc-2.18/lib使它工作。但是,我的问题是,鉴于新的 ld 的路径,为什么仍然需要这样做?一开始配置为拾取新的libc领先于旧libc .

最佳答案

我知道了,问题出在操作系统 ABI 版本上。也就是file所指示的数字,如:

$ file /lib/x86_64-linux-gnu/libc-2.15.so | grep -o "for GNU/Linux [0-9.]*"
for GNU/Linux 2.6.24

glibc 配置为 --prefix 时,它默认使用 ABI 版本更小(!!) 构建(在我的例子中,2.6.16) 比系统默认的 (2.6.24)。所以 libc-2.18 的 ABI 版本小于 libc-2.15

ldconfig 发现 2 个具有不同 ABI 编号的 libc.so.6 版本时,它会将它们放入 ld.so.cache < em>按 ABI 数字降序排列,而不是按出现顺序。这可以通过交换它们的位置、重建缓存(使用 ldconfig)和列出缓存内容(使用 ldconfig -p)来检查。只有当 2 个 libc.so.6 文件具有相同的 ABI 版本时,它们才会按照出现的顺序放入缓存中。

使用 --enable-kernel=2.6.24 配置 glibc 会导致它使用与系统相同的 ABI 版本,这反过来又修复了分辨率问题问题陈述,无需明确的 --rpathLD_LIBRARY_PATH

关于linux - 备用 glibc 动态链接器 (ld.so) 的库路径顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20577638/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com