优先用 ldd 查直接依赖,ldd 失效时用 readelf -d | grep needed 更可靠;objdump -p 仅显示链接声明的库名,不校验存在性,且对 strip/加壳文件兼容性差。

怎么用 objdump 查某个二进制依赖哪些动态库
objdump 本身不直接列出动态依赖,它主要看符号和重定位信息。真要查依赖,得用 objdump -p 配合 Dynamic Section 输出,但结果不直观,还容易漏掉间接依赖。
实操建议:
- 优先用
ldd:比如ldd /usr/bin/python3,它会递归显示所有直接依赖的.so路径和是否找到 - 如果目标文件没执行权限或被 strip 过,
ldd可能报错或不准,这时才轮到objdump -p binary | grep NEEDED -
objdump -p输出里的NEEDED行只反映链接时声明的库名(如libm.so.6),不包含路径,也不校验是否存在 - 注意:静态链接的程序不会出现
NEEDED条目,objdump -p看不到任何动态依赖
readelf -d 比 objdump -p 更靠谱吗
是的。readelf -d 专为 ELF 动态段设计,输出更稳定、字段更明确,尤其对被 strip 或加壳的二进制兼容性更好。
常见错误现象:用 objdump -p 看不到 NEEDED,但程序运行时报 undefined symbol——很可能是因为动态段被修改或隐藏,而 readelf -d 仍能读出原始 DT_NEEDED 条目。
实操建议:
- 查依赖库名:
readelf -d binary | grep NEEDED - 查运行时搜索路径:
readelf -d binary | grep -E "(RUNPATH|RPATH)" - 如果输出为空,不代表没依赖,可能是静态链接,或用了
-z noexecstack等非常规链接选项干扰了段解析
为什么 ldd 显示 “not found”,但程序还能跑
因为 ldd 是在当前 shell 环境下模拟 loader 行为,它不读 /etc/ld.so.cache 以外的缓存,也不加载 LD_PRELOAD,更不会走 gcc 编译时硬编码的 RUNPATH 路径(除非你显式设置 LD_LIBRARY_PATH)。
使用场景:容器里、chroot 环境、或程序自己 setenv 了 LD_LIBRARY_PATH 后再 exec,都会让 ldd 判断失效。
实操建议:
- 用
strace -e trace=openat,openat64 /path/to/binary true 2>&1 | grep '\.so'看实际打开的库路径 - 检查
readelf -d binary | grep RUNPATH,然后手动去那些路径下找对应.so -
ldd的 “not found” 只代表它找不到,不是 loader 找不到——loader 有更多查找路径和缓存机制
静态链接、PIE、musl 会导致哪些误判
这三类情况会让所有基于 NEEDED 的工具失效或误导人。
性能 / 兼容性影响:
- 静态链接二进制(如用
gcc -static编译):readelf -d和objdump -p都不会输出NEEDED,但程序体积大、无法热更新 libc - PIE(Position Independent Executable):不影响依赖检测,但某些旧版
ldd会误报 “not a dynamic executable”,此时必须用readelf -h确认Type: EXEC (Executable file)还是DYN (Shared object file) - musl libc 程序:不依赖
glibc的.so,但ldd在 glibc 系统上会提示 “not a dynamic executable” 或直接失败;正确做法是用file binary看是否含 “musl”,再换 musl 环境查
真正难搞的是混合链接:部分函数动态、部分静态,或者用了 dlopen 延迟加载——这些根本不会出现在 NEEDED 里,只能靠运行时抓 syscall 或分析源码。










