是否可以 运行 未剥离的二进制文件加载 LD_LIBRARY_PATH 中存在的未剥离的库

Is it possible to run unstripped binaries which loads unstripped libraries present in LD_LIBRARY_PATH

在我的目标 ARM 嵌入式系统中,所有应用程序和依赖库仅作为剥离版本提供。大多数二进制文件都存在于 /bin 中,/usr/bin 路径和存在于 /lib 中的库,/usr/lib 路径都被剥离。

但是有了这些我无法 运行 ValgrindGDB。因为两者都需要非剥离版本中存在的调试符号信息。因此,我将所有未剥离的(bins 和 libs)从我的开发服务器复制到不同路径的目标系统,比如(/tmp/test

Bins -- /tmp/test/usr/bin, /tmp/test/bin
Libs -- /tmp/test/usr/lib, /tmp/test/lib

当我尝试 运行 未剥离的二进制文件 时,进程 snmp_agent 崩溃了。

$LD_LIBRARY_PATH=/tmp/test/usr/lib/:/tmp/test/lib/ /tmp/test/usr/bin/snmp_agent -p 8000 &

即使我尝试了 运行ning 动态链接器,但这次链接器崩溃了。

$/tmp/test/lib/ld-2.24.so /tmp/test/usr/bin/snmp_agent -p 8000 &

执行 export 和执行非剥离 bin 时的核心转储:

root@myway:~# export LD_LIBRARY_PATH=/tmp/test/usr/lib/:/tmp/test/lib/; /tmp/test/usr/bin/snmp_agent -p 8000 &
[1] 21218
root@myway:~#
[1]+  Segmentation fault      (core dumped) /tmp/test/usr/bin/snmp_agent -p 8000
root@myway:~# 

在导出后获取 默认 linux cmds 的核心转储:

root@myway:~# ls
Segmentation fault (core dumped)
root@myway:~# env
Segmentation fault (core dumped)
root@myway:~# pwd
/home/root
root@myway:~# date
Segmentation fault (core dumped)

感谢@nidhoegger 建议使用 strace。 发现我 错过了带有 strace 输出的库的符号链接版本

open("/tmp/test/usr/lib/libm.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/tmp/test/lib/libm.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/lib/libm.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "7ELF[=17=][=17=][=17=][=17=][=17=][=17=][=17=][=17=][=17=][=17=]([=17=][=17=][=17=][=17=]=[=17=][=17=]04[=17=][=17=][=17=]"..., 512) = 512
fstat64(3, {st_mode=S_IFREG|0755, st_size=427500, ...}) = 0
mmap2(NULL, 491640, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x76351000
mprotect(0x763b8000, 65536, PROT_NONE)  = 0
mmap2(0x763c8000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x67000) = 0x763c8000
close(3)                                = 0

常规系统库路径中的符号链接库(剥离):

root@myway:~# ls -l /lib/libm.so.6
lrwxrwxrwx    1 root     root            12 Jun 22 11:30 /lib/libm.so.6 -> libm-2.24.so

我没有将未剥离库的 symlink 版本复制到我的路径 /tmp/test/usr/lib/tmp/test/lib/

root@myway:~# ls -l /tmp/test/lib/libm.so.6
ls: /tmp/test/lib/libm.so.6: No such file or directory
root@myway:~# ls -l /tmp/test/lib/libm-2.24.so
-rwxrwx---    1 root     root       4885456 Jun 22 20:15 /tmp/test/lib/libm-2.24.so

同样,我的未剥离程序正在尝试加载近 30 个依赖库(也使用 ldd 验证了这一点)并且所有这些库都没有指向原始 lib 文件的符号链接。那么缺少 symlink 文件 是导致崩溃的原因吗?

您正在有效地创建一个部分 chroot 环境,并且有几种工具可能会在这种情况下帮助您,但是我将描述我在手动执行此操作时使用的算法。

从二进制文件开始,以及与文件一起使用的 运行-time 加载程序。您已经有了 binlib 子目录结构。将 ld.so 复制到 lib 目录,并将二进制文件复制到 bin 目录。然后用这个命令开始:

env LD_LIBRARY_PATH=/tmp/test/lib:/tmp/test/usr/lib /tmp/test/lib/ld.so --list /tmp/test/bin/snmp_agent

它将给出这样的输出(这是来自一个完全不同的系统):

host$ /lib64/ld-linux-x86-64.so.2 --list /bin/ls
linux-vdso.so.1 (0x0000037433fc7000)
libselinux.so.1 => /lib/x86_64-linux-gnu/libselinux.so.1 (0x0000037433958000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x0000037433567000)
libpcre.so.3 => /lib/x86_64-linux-gnu/libpcre.so.3 (0x00000374332f5000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00000374330f1000)
/lib64/ld-linux-x86-64.so.2 (0x0000037433da2000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x0000037432ed2000)

任何未找到的库,或引用主机库的库,而不是 /tmp/test/{lib,usr/lib} 下的库,都应复制到 /tmp/test/lib

重复直到没有未解析的库。

为了执行,你做:

env LD_LIBRARY_PATH=/tmp/test/lib:/tmp/test/usr/lib /tmp/test/lib/ld.so /tmp/test/bin/snmp_agent -p 8000

接下来是 'runner' - 我通常将二进制文件重命名为 binary.real,并将它们全部保存在 单个 bin 目录中(这使得脚本容易得多)- 如果您选择保留 binusr/bin,则需要调整此 运行ner,并使用以下内容:

#!/bin/bash -p

dir=$(dirname "${BASH_SOURCE[0]}")
env LD_LIBRARY_PATH="$dir/../lib:$dir/../usr/lib" "$dir/../lib/ld.so" "[=13=].real" "$@"

现在你把这个文件的 copies/links 用于你想要 运行 的所有程序。

如果您 ld.so 比 v2.33 更新,那么您可以在直接调用 ld.so 时使用 -argv0 选项为其指定正确的 argv0 名称:

env LD_LIBRARY_PATH="$dir/../lib:$dir/../usr/lib" "$dir/../lib/ld.so" -argv0 "[=14=]" "[=14=].real" "$@"

So the lack of symlink file is the reason behind the crash?

不,崩溃背后的原因是您未剥离的二进制文件来自不同的构建。

如果差异是 由于剥离,您可以自由混合和匹配剥离和未剥离的二进制文件,但显然不能。

GLIBC 所有部分的原因(加载程序ld-linuxlibc.so.6libpthread.so.0libdl.so.2等) 必须完全匹配(必须来自同一个版本)解释为 here.