考虑 的共享对象依赖性/bin/bash
,其中包括/lib64/ld-linux-x86-64.so.2
(动态链接器/加载器):
ldd /bin/bash
linux-vdso.so.1 (0x00007fffd0887000)
libtinfo.so.6 => /lib/x86_64-linux-gnu/libtinfo.so.6 (0x00007f57a04e3000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f57a04de000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f57a031d000)
/lib64/ld-linux-x86-64.so.2 (0x00007f57a0652000)
检查/lib64/ld-linux-x86-64.so.2
表明它是一个符号链接/lib/x86_64-linux-gnu/ld-2.28.so
:
ls -la /lib64/ld-linux-x86-64.so.2
lrwxrwxrwx 1 root root 32 May 1 19:24 /lib64/ld-linux-x86-64.so.2 -> /lib/x86_64-linux-gnu/ld-2.28.so
此外,file
报告/lib/x86_64-linux-gnu/ld-2.28.so
本身可以动态链接:
file -L /lib64/ld-linux-x86-64.so.2
/lib64/ld-linux-x86-64.so.2: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, BuildID[sha1]=f25dfd7b95be4ba386fd71080accae8c0732b711, stripped
我想知道:
- 动态链接器/加载器()本身如何
/lib64/ld-linux-x86-64.so.2
动态链接?它在运行时链接自己吗? /lib/x86_64-linux-gnu/ld-2.28.so
被记录为处理 a.out 二进制文件 (man ld.so
),但/bin/bash
ELF 是可执行文件吗?
程序 ld.so 处理 a.out 二进制文件,这是很久以前使用的格式; ld-linux.so*(对于 libc5 来说是 /lib/ld-linux.so.1,对于 glibc2 来说是 /lib/ld-linux.so.2)处理 ELF,每个人都已经使用它很多年了。
答案1
是的,它在初始化时会自行链接。从技术上讲,动态链接器本身不需要对象解析和重定位,因为它按原样完全解析,但它确实定义了符号,并且在解析它“解释”的二进制文件时必须处理这些符号,并且这些符号被更新指向它们在加载的库中的实现。特别是,这会影响
malloc
- 链接器有一个内置的最小版本,带有相应的符号,但一旦加载和重定位,它就会被 C 库的版本替换(或者甚至被插入的版本,如果有的话),需要小心采取措施确保这种情况不会发生在可能破坏链接器的地方。血淋淋的细节在
rtld.c
,在dl_main
函数中。但请注意,它
ld.so
没有外部依赖项。您可以看到涉及的符号nm -D
;它们都不是未定义的。联机帮助页仅引用直接位于
/lib
,IE/lib/ld.so
(libc 5 动态链接器,支持a.out
) 和/lib*/ld-linux*.so*
(libc 6 动态链接器,支持 ELF)。联机帮助页是非常具体的,ld.so
并不是ld-2.28.so
。当前绝大多数系统上的动态链接器不包含
a.out
支持。
file
并ldd
为动态链接器报告不同的内容,因为它们对静态链接二进制文件的构成有不同的定义。对于ldd
,如果二进制文件没有DT_NEEDED
符号,则它是静态链接的,IE没有未定义的符号。对于file
,如果 ELF 二进制文件没有PT_DYNAMIC
节,则它是静态链接的(这将在以下 5.37 版本中更改file
;现在PT_INTERP
使用节的存在作为动态链接二进制文件的指示符,与代码中的注释匹配)。
GNU C 库动态链接器没有任何DT_NEEDED
符号,但它有一个PT_DYNAMIC
部分(因为它在技术上是一个共享库)。结果,ldd
(即动态链接器)指示它是静态链接的,但file
指示它是动态链接的。它没有PT_INTERP
节,因此下一个版本file
也将表明它是静态链接的。
$ ldd /lib64/ld-linux-x86-64.so.2
statically linked
$ file $(readlink /lib64/ld-linux-x86-64.so.2)
/lib/x86_64-linux-gnu/ld-2.28.so: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, BuildID[sha1]=f25dfd7b95be4ba386fd71080accae8c0732b711, stripped
(file
5.35)
$ file $(readlink /lib64/ld-linux-x86-64.so.2)
/lib/x86_64-linux-gnu/ld-2.28.so: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), statically linked, BuildID[sha1]=f25dfd7b95be4ba386fd71080accae8c0732b711, stripped
(当前正在开发的版本file
)。
答案2
我怀疑
file
程序对于动态链接器/加载器本身的动态链接是错误的。程序ldd
不同意。至少在我的系统上没有(Debian Stretch):ldd /lib/x86_64-linux-gnu/ld-2.24.so statically linked
man ld.so
还读到:“ld-linux.so* 处理 ELF”。在你的系统上(顺便说一下,我的系统上也是如此),两者都是指向同一个二进制文件的符号链接,我推断它能够处理 ELF 和(旧的过时的)a.out 格式。