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

时间:2013-12-13 23:18:57

标签: linux shared-libraries ld glibc dynamic-linking

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

我设置了新动态链接器(ld-2.18.so)的库路径,以便在旧libc之前找到新的libc-2.18.solibc)({ {1}})。但是,当我尝试使用新的libc-2.15.so运行程序时,会选择旧版ld,生成libc为什么会这样?

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

详情如下:

我已下载LD_LIBRARY_PATH并在glibc-2.18处构建了它。默认情况下,文件/opt/glibc-2.18丢失。我创建了它,并更新了新/opt/glibc-2.18/etc/ld.so.conf的库缓存,如下所示。我强调:glibc 之前找到新的libc

libc

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

$ 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:

如上所示,此程序内部使用旧的$ 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 之前找到,生成了一个SEGV:

libc

我也可以使用新库进行编译并按照以下方式烘焙新$ /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。< / p>

1 个答案:

答案 0 :(得分:5)

我明白了,问题在于OS 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找到具有不同ABI号码的libc.so.6的2个版本时,它会按照ABI号码降序排列ld.so.cache ,而不是按照出现的顺序。这可以通过交换位置,重建缓存(使用ldconfig)和列出缓存内容(使用ldconfig -p)来检查。仅当2 libc.so.6个文件具有相同的ABI版本时,它们才会按照外观顺序放入缓存中。

使用glibc配置--enable-kernel=2.6.24会使其使用与系统相同的ABI版本,从而修复问题陈述中的解决方案问题,而无需显式--rpathLD_LIBRARY_PATH