【发布时间】:2020-12-23 18:41:22
【问题描述】:
我想验证程序运行时使用的动态链接器是通过file、readelf -l 或ldd 提到的那个。我的动机源于在机器上的不同空间中存在多个动态链接器,它们不应该混合搭配。
到目前为止,我发现验证动态链接器的最佳方法是通过gdb。通过查看info proc mappings 的输出,我可以确定哪个动态链接器被映射到地址空间并正在使用中。我试图避免使用gdb,因为它需要我通过它运行测试套件和其他东西。
使用LD_DEBUG 环境变量似乎是一种替代解决方案,可以让我在程序执行之后(或期间)轻松保存日志以进行验证。但是,我不确定哪个选项会给我最好的信息。我认为scopes 或libs 可能是不错的选择,但libs 并不总是提到动态链接器。例如,这是一个简单的 hello world 程序的输出:
$ LD_DEBUG=libs ./test0
24579: find library=libc.so.6 [0]; searching
24579: search cache=/etc/ld.so.cache
24579: trying file=/lib/x86_64-linux-gnu/libc.so.6
24579:
24579:
24579: calling init: /lib/x86_64-linux-gnu/libc.so.6
24579:
24579:
24579: initialize program: ./test0
24579:
24579:
24579: transferring control: ./test0
24579:
hello world
24579:
24579: calling fini: ./test0 [0]
24579:
$ LD_DEBUG=libs ./test0-gnu-cross
24581: find library=libc.so.6 [0]; searching
24581: search path=/usr/local/gnu-cross/x86_64-linux-gnu/lib/glibc-hwcaps/x86-64-v4:/usr/local/gnu-cross/x86_64-linux-gnu/lib/glibc-hwcaps/x86-64-v3:/usr/local/gnu-cross/x86_64-linux-gnu/lib/glibc-hwcaps/x86-64-v2:/usr/local/gnu-cross/x86_64-linux-gnu/lib/tls/haswell/avx512_1/x86_64:/usr/local/gnu-cross/x86_64-linux-gnu/lib/tls/haswell/avx512_1:/usr/local/gnu-cross/x86_64-linux-gnu/lib/tls/haswell/x86_64:/usr/local/gnu-cross/x86_64-linux-gnu/lib/tls/haswell:/usr/local/gnu-cross/x86_64-linux-gnu/lib/tls/avx512_1/x86_64:/usr/local/gnu-cross/x86_64-linux-gnu/lib/tls/avx512_1:/usr/local/gnu-cross/x86_64-linux-gnu/lib/tls/x86_64:/usr/local/gnu-cross/x86_64-linux-gnu/lib/tls:/usr/local/gnu-cross/x86_64-linux-gnu/lib/haswell/avx512_1/x86_64:/usr/local/gnu-cross/x86_64-linux-gnu/lib/haswell/avx512_1:/usr/local/gnu-cross/x86_64-linux-gnu/lib/haswell/x86_64:/usr/local/gnu-cross/x86_64-linux-gnu/lib/haswell:/usr/local/gnu-cross/x86_64-linux-gnu/lib/avx512_1/x86_64:/usr/local/gnu-cross/x86_64-linux-gnu/lib/avx512_1:/usr/local/gnu-cross/x86_64-linux-gnu/lib/x86_64:/usr/local/gnu-cross/x86_64-linux-gnu/lib (RPATH from file ./test0-gnu-cross)
24581: trying file=/usr/local/gnu-cross/x86_64-linux-gnu/lib/glibc-hwcaps/x86-64-v4/libc.so.6
24581: trying file=/usr/local/gnu-cross/x86_64-linux-gnu/lib/glibc-hwcaps/x86-64-v3/libc.so.6
24581: trying file=/usr/local/gnu-cross/x86_64-linux-gnu/lib/glibc-hwcaps/x86-64-v2/libc.so.6
24581: trying file=/usr/local/gnu-cross/x86_64-linux-gnu/lib/tls/haswell/avx512_1/x86_64/libc.so.6
24581: trying file=/usr/local/gnu-cross/x86_64-linux-gnu/lib/tls/haswell/avx512_1/libc.so.6
24581: trying file=/usr/local/gnu-cross/x86_64-linux-gnu/lib/tls/haswell/x86_64/libc.so.6
24581: trying file=/usr/local/gnu-cross/x86_64-linux-gnu/lib/tls/haswell/libc.so.6
24581: trying file=/usr/local/gnu-cross/x86_64-linux-gnu/lib/tls/avx512_1/x86_64/libc.so.6
24581: trying file=/usr/local/gnu-cross/x86_64-linux-gnu/lib/tls/avx512_1/libc.so.6
24581: trying file=/usr/local/gnu-cross/x86_64-linux-gnu/lib/tls/x86_64/libc.so.6
24581: trying file=/usr/local/gnu-cross/x86_64-linux-gnu/lib/tls/libc.so.6
24581: trying file=/usr/local/gnu-cross/x86_64-linux-gnu/lib/haswell/avx512_1/x86_64/libc.so.6
24581: trying file=/usr/local/gnu-cross/x86_64-linux-gnu/lib/haswell/avx512_1/libc.so.6
24581: trying file=/usr/local/gnu-cross/x86_64-linux-gnu/lib/haswell/x86_64/libc.so.6
24581: trying file=/usr/local/gnu-cross/x86_64-linux-gnu/lib/haswell/libc.so.6
24581: trying file=/usr/local/gnu-cross/x86_64-linux-gnu/lib/avx512_1/x86_64/libc.so.6
24581: trying file=/usr/local/gnu-cross/x86_64-linux-gnu/lib/avx512_1/libc.so.6
24581: trying file=/usr/local/gnu-cross/x86_64-linux-gnu/lib/x86_64/libc.so.6
24581: trying file=/usr/local/gnu-cross/x86_64-linux-gnu/lib/libc.so.6
24581:
24581:
24581: calling init: /usr/local/gnu-cross/x86_64-linux-gnu/lib/ld-linux-x86-64.so.2
24581:
24581:
24581: calling init: /usr/local/gnu-cross/x86_64-linux-gnu/lib/libc.so.6
24581:
24581:
24581: initialize program: ./test0-gnu-cross
24581:
24581:
24581: transferring control: ./test0-gnu-cross
24581:
hello world
24581:
24581: calling fini: ./test0-gnu-cross [0]
24581:
如您所见,使用标准 Debian/GNU 工具链构建并使用系统动态链接器的程序 test0 并没有说明这一点。
scopes 选项看起来更有帮助,但我不明白输出在说什么:
$ LD_DEBUG=scopes ./test0
24577:
24577: Initial object scopes
24577: object=./test0 [0]
24577: scope 0: ./test0 /lib/x86_64-linux-gnu/libc.so.6 /lib64/ld-linux-x86-64.so.2
24577:
24577: object=linux-vdso.so.1 [0]
24577: scope 0: ./test0 /lib/x86_64-linux-gnu/libc.so.6 /lib64/ld-linux-x86-64.so.2
24577: scope 1: linux-vdso.so.1
24577:
24577: object=/lib/x86_64-linux-gnu/libc.so.6 [0]
24577: scope 0: ./test0 /lib/x86_64-linux-gnu/libc.so.6 /lib64/ld-linux-x86-64.so.2
24577:
24577: object=/lib64/ld-linux-x86-64.so.2 [0]
24577: no scope
24577:
hello world
$ LD_DEBUG=scopes ./test0-gnu-cross
24576:
24576: Initial object scopes
24576: object=./test0-gnu-cross [0]
24576: scope 0: ./test0-gnu-cross /usr/local/gnu-cross/x86_64-linux-gnu/lib/libc.so.6 /usr/local/gnu-cross/x86_64-linux-gnu/lib/ld-linux-x86-64.so.2
24576:
24576: object=linux-vdso.so.1 [0]
24576: scope 0: ./test0-gnu-cross /usr/local/gnu-cross/x86_64-linux-gnu/lib/libc.so.6 /usr/local/gnu-cross/x86_64-linux-gnu/lib/ld-linux-x86-64.so.2
24576: scope 1: linux-vdso.so.1
24576:
24576: object=/usr/local/gnu-cross/x86_64-linux-gnu/lib/libc.so.6 [0]
24576: scope 0: ./test0-gnu-cross /usr/local/gnu-cross/x86_64-linux-gnu/lib/libc.so.6 /usr/local/gnu-cross/x86_64-linux-gnu/lib/ld-linux-x86-64.so.2
24576:
24576: object=/usr/local/gnu-cross/x86_64-linux-gnu/lib/ld-linux-x86-64.so.2 [0]
24576: no scope
24576:
hello world
总之,我想找到一种验证正在使用的动态链接器的好方法。除非您能想到更好的选择,否则LD_DEBUG 似乎是一个不错的选择,但我很难理解如何在这种情况下有效地使用它。
感谢您的帮助:)
【问题讨论】:
-
info proc mappings似乎提供了/proc/self/maps中包含的信息,因此仅阅读后者可能就足够了 -
@CraigEstey 使用该解决方案,我不必在程序终止之前竞相阅读
/proc/<pid>/maps吗?有没有办法预测接下来会生成什么 PID,然后在/proc中等待它的创建?
标签: c linux dynamic-linking