Linux二进制文件操作工具
1 快速查看工具
可以利用file和size来简单直接的查看二进制文件的细节。
1.1 file
命令行工具file可以用于查看几乎任何类型文件的详细信息。如
1.2 size
命令行工具size能够快速地获取ELF节的字节长度。
2 详细信息分析工具
可以使用binutils的工具集合获取有关二进制文件属性的详细信息。下面介绍ldd,nm,objdump,readelf工具。
2.1 ldd
ldd命令可以显示出二进制文件启动时需要静态加载的动态库的完整列表(加载时依赖项)。
链接器会将直接依赖项的列表写入二进制文件的ELF格式字段中,在分析加载时依赖项时,ldd首先会扫描二进制文件并尝试找到这些信息。通过递归搜索完成后,ldd会收集找到的依赖项,然后去掉重复项,将结果打印出来。
ldd搜索顺序:
如果指定了RUNPATH字段(即DT_RUNPATH字段非空)
- LD_LIBRARY_PATH。
- runpath(DT_RUNPATH)。
- ld.so.cache。
- 默认库路径(/lib64和/usr/lib64)。
如果未指定RUNPATH字段(即DT_RUNPATH字段为空) - 被加载库的RPATH,然后是二进制文件的RPATH,直到可执行文件或者动态库将这些库全部加载完毕。
- LD_LIBRARY_PATH。
- ld.so.cache。
- 默认库路径(/lib64和/usr/lib64)。
ldd rocketmq
由于在一些环境下,ldd会尝试执行程序获取依赖信息,不够安全,可采用下面方法:
objdump –p /path/to/program |grep NEEDED
readelf –d /path/to/program |grep NEEDED
但是这两个命令提供的依赖项列表远不如ldd提供的完整。
2.2 nm
nm可以列出二进制文件的符合列表。该工具可以输出符合并显示出对应的符合类型。如果二进制文件包含C++代码,默认会打印出经过名称修饰之后的符号名。下面介绍几种常用用法:
nm <二进制文件路径>:列出二进制文件的所有符合。对于共享库而言,不仅会列出导出的符号,也会列出其他所有符号,如果使用strip去除了库文件的某些符号,那么在不使用-D参数时,nm将找不到这些去除的符号。
nm –D <二进制文件路径>:只列出动态节中的符号(即动态库中导出的或对外可见的符号)。
nm -D rocketmq
nm –C<二进制文件路径>:列出未经过名称修饰的格式。
nm -C rocketmq
nm –C —no-demangle<二进制文件路径>:打印出共享库中名称修饰后的动态符号。
nm -C --no-demangle rocketmq
nm –A <库文件路径>/*|grep symbol-name:当你在相同目录下的二进制文件中搜索符号时,该命令非常有用,因为-A选项会将所有在库中找到的符号名打印出来。
nm –u <二进制文件路径>:列出库中未定义的符号。
2.3 objdump
objdump功能最丰富的二进制分析工具,不仅支持ELF格式,还有大概50中其他格式。
1) 解析ELF头
objdump命令的-f选项可以用来获取目标文件头信息。ELF头提供了大量有用的信息。尤其可以通过ELF头信息快速获取二进制文件的类型和入口点信息。查看静态库时,会打印出在库中找到的每个目标文件的ELF头信息。
objdump -f rocketmq
objdump -f a.exe
objdump -f librocketmq.so
objdump -f libhiredis.a
2) 列出并查看节信息
objdump -h rocketmq
3) 列出所有符号
objdump -t rocketmq
4) 只列出动态符号
objdump -T rocketmq
5) 查看动态节
主要关注后半部分的输出。
objdump -p rocketm
6) 查看重定位节
objdump -R rocketmq
7) 查看节中的数据
objdump -s -j .got rocketmq
8) 列出并查看段
objdump -p rocketmq
第一部分为段的名称
9) 反汇编代码
objdump -d -s -M intel rocketmq |grep -A 10 "doConsumeMessage"
- objdump和nm的等价功能
nm <二进制文件路径> 等价于 objdump –t <二进制文件路径>
nm –D <二进制文件路径> 等价于 objdump –T <二进制文件路径>
nm –C <二进制文件路径> 等价于 objdump –C <二进制文件路径>
2.4 readelf
readelf和objdump功能类似,区别在于,只支持ELF二进制格式;不依赖于二进制文件描述库。
1) 解析ELF头
readelf –h命令行选项用于获取目标文件头信息。ELF头提供了大量有用的信息。尤其可以通过ELF头信息快速获取二进制文件的类型和入口点信息。查看静态库时,会打印出在库中找到的每个目标文件的ELF头信息。
readelf -h rocketmq
readelf -h librocketmq.so
readelf -h libhiredis.a
2) 列出并查看节信息
readelf -S rocketmq
3) 列出所有符号
readelf --symbols rocketmq
4) 只列出动态符号
readelf --dyn-syms rocketmq
5) 查看动态节
readelf -d rocketmq
6) 查看重定位节
readelf -r rocketmq
7) 查看节中数据
readelf -x .got rocketmq
8) 列出并查看段
readelf --segments rocketmq
9) 检测二进制文件是否包含调试信息
readelf --debug-dump rocketmq
由于有可能打印会特别多,可使用统计行数查看readelf --debug-dump rocketmq |wc
–l
3 部署阶段工具
3.1 chrpath
chrpath可以修改ELF文件的rpath(DT_RPATH字段)。
可以在DT_RPATH原始字符串长度的范围内对其进行修改。
可以删除原有的DT_RPATH字段。
如果原始是空的,不能使用任何的非空字符串替代原有字段。
可以将DT_RPATH转换成DT_RUNPATH。
用于替换的字符串长度不能超过原始长度。
修改:
readelf -d rocketmq |grep RPATH
chrpath -r /bin ./rocketmq
readelf -d rocketmq |grep RPATH
删除
readelf -d rocketmq |grep RPATH
chrpath -d rocketmq
readelf -d rocketmq |grep RPATH
3.3 strip
可以清楚所有动态加载过程中不需要的库文件符号。
strip teststrip.so
nm teststrip.so
3.4 ldconfig
将共享库文件的路径作为输入参数传递给ldconfig时,ldconfig会搜索共享库路径,并更新用于记录这些信息的文件:
/etc/ld.so.conf文件:包含了一组目录列表,默认会扫描里面的库文件。
/etc/ld.so.cache文件:将多个路径作为输入参数传递给ldconfig时,ldconfig会将整个扫描过程中查找到动态库的文件名以ASCII文本列表的形式写入这个文件。
ldd rocketmq
ldconfig /mnt/hgfs/share/tool/
ldd rocketmq
上一篇: 订单超时取消之延迟队列