记录一下如何在Ubuntu系统中查看依赖库信息。
使用ldconfig
命令
命令说明
ldconfig
命令用于为共享库(shared library)依赖项配置符号链接(symbolic link)和缓存;- 默认搜索
/lib
和/usr/lib
目录以及/etc/ld.so.conf
配置文件中的目录; -
语法说明:
ldconfig [-nNvXV] [-f conf] [-C cache] [-r root] directory... ldconfig -l [-v] library... ldconfig -p
常用语法
-
更新符号链接并重新构建缓存(通常在新安装库时进行):
sudo ldconfig
-
更新指定目录的符号链接:
sudo ldconfig -n path/to/directory
-
打印缓存中的库并检查指定的库是否存在:
ldconfig -p | grep library_name ldconfig --print-cache | grep library_name
常用于检查系统中是否安装指定的共享库。
使用ldd
命令
命令说明
ldd
命令用于显示二进制文件的共享库依赖项;- 对于不受信任的二进制文件不能使用
ldd
命令,需要使用objdump
命令,将在后文中详述; - 对于不同系统架构的二进制文件不能使用
ldd
命令,需要使用readelf
命令,将在后文中详述; -
语法说明:
ldd [option]... file...
常用语法
-
显示二进制文件的共享库依赖项:
ldd path/to/binary
-
显示关于依赖项的所有信息:
ldd -v path/to/binary ldd --verbose path/to/binary
-
显示未使用的直接依赖项:
ldd -u path/to/binary ldd --unused path/to/binary
-
报告丢失的数据对象并进行数据重定位:
ldd -d path/to/binary ldd --data-relocs path/to/binary
-
报告丢失的数据对象和函数,并对于两者进行重定位:
ldd -r path/to/binary ldd --function-relocs path/to/binary
常用于检查链接共享库时存在的未定义符号问题,可能有四种原因:
- 未将依赖的共享库添加到
CMakeLists.txt
中或者依赖的共享库不存在; - 在生成依赖的共享库时未将
.cpp
文件添加到CMakeLists.txt
中; - 静态数据成员未在类外初始化;
- 在与C语言混合编程时没有添加
extern "C"
;
- 未将依赖的共享库添加到
使用objdump
命令
命令说明
objdump
命令用于查看关于对象文件的信息;-
语法说明:
objdump <option(s)> <file(s)>
常用语法
-
显示文件头(file header)信息:
objdump -f binary objdump --file-headers binary
-
显示可执行部分的反汇编(disassembled)输出:
objdump -d binary objdump --disassemble binary
-
以Intel语法显示可执行部分的反汇编输出:
objdump -M intel -d binary objdump --disassembler-options=intel --disassemble binary
-
显示完整二进制文件所有部分的十六进制转储(hex dump):
objdump -s binary objdump --full-contents binary
-
显示所有报头(header)的内容并查看共享库依赖项:
objdump -x binary | grep NEEDED objdump --all-headers binary | grep NEEDED
常用于查看共享库依赖项的名称。
使用readelf
命令
命令说明
readelf
命令用于显示ELF文件信息;-
语法说明:
readelf <option(s)> <file(s)>
常用语法
-
显示有关ELF文件的所有信息:
readelf -a path/to/binary readelf --all path/to/binary
-
显示ELF文件中存在的所有报头:
readelf -e path/to/binary readelf --headers path/to/binary
-
显示ELF文件的符号表部分中的条目:
readelf -s path/to/binary readelf --syms path/to/binary readelf --symbols path/to/binary
-
显示ELF文件的文件头中包含的信息:
readelf -h path/to/binary readelf --file-header path/to/binary
-
显示ELF文件的动态部分并查看共享库依赖项:
readelf -d path/to/binary | grep NEEDED readelf --dynamic path/to/binary | grep NEEDED
常用于查看不同系统架构下的共享库依赖项名称。
使用c++filt
命令
命令说明
c++filt
命令用于还原(demangle)C++和Java符号;-
语法说明:
c++filt [options] [mangled names]
- 常用于解析编译后的符号名,从而恢复编译前的函数名;
使用nm
命令
命令说明
nm
命令用于列出对象文件中的符号名称;-
语法说明:
nm [option(s)] [file(s)]
- 默认对象文件名为
a.out
;
常用语法
-
列出文件中的全局函数和外部函数,前缀为
T
:nm -g path/to/file.o nm --extern-only path/to/file.o
-
列出文件中的未定义符号:
nm -u path/to/file.o nm --undefined-only path/to/file.o
-
列出文件中的全部符号,包括调试符号:
nm -a path/to/file.o nm --debug-syms path/to/file.o
-
还原C++符号,使其可读:
nm -C path/to/file.o nm --demangle path/to/file.o
-
在每个符号前打印输入文件的名称并查看指定符号:
nm -A path/to/file.o | grep symbol_name nm --print-file-name path/to/file.o | grep symbol_name
常用于查看指定的符号是否被定义,未定义符号前缀为
U
。
使用chrpath
命令
命令说明
chrpath
命令用于查看和修改二进制文件的运行时路径(runtime path,rpath)和运行时搜索路径(run-time search path,runpath)信息;-
语法说明:
chrpath [-v|-d|-c|-r <path>] <program> [<program> ...]
- 可用于修改可执行文件的rpath信息,使其在依赖库发生变化的环境中运行,一般情况下不建议使用;
使用patchelf
命令
命令说明
patchelf
命令用于修改ELF文件信息;-
语法说明:
patchelf [--set-interpreter FILENAME] [--page-size SIZE] [--print-interpreter] [--print-soname] [--set-soname SONAME] [--set-rpath RPATH] [--remove-rpath] [--shrink-rpath] [--print-rpath] [--force-rpath] [--add-needed LIBRARY] [--remove-needed LIBRARY] [--replace-needed LIBRARY NEW_LIBRARY] [--print-needed] [--no-default-lib] [--debug] [--version] FILENAME
- 可用于修改可执行文件的rpath信息,使其在依赖库发生变化的环境中运行,一般情况下不建议使用;
参考
- undefined symbol问题的查找、定位与解决方法-CSDN博客
- Linux动态库undefined symbol原因定位与解决方法-CSDN博客
- Linux动态库undefined symbol原因定位与解决方法-博客园
- 未定义符号的链接问题通用解决方法-博客园
- c++符号表解析-CSDN博客
- ldconfig命令-五月的麦田
- C/C++开发技巧:ldconfig,ldd,objdump,readelf,lsof动态库命令行工具-CSDN博客
- linux下nm,objdump和ldd三大工具使用-CSDN博客
- C++的“坑”之一:undefined reference-CrackingOysters的文章-知乎
- mangle和demangle-博客园
- 一文搞懂动态链接库的各种路径的意义与设置-卷儿的文章-知乎
- NixOS/patchelf