GNU Binutils

(4 mins to read)

Binutils 是由很多处理汇编文件、目标文件以及库的二进制开发工具组成的集合。

as

汇编器,将汇编代码转化为目标文件。在不提供-o选项时,默认输出到a.out文件。

1
2
as file.s -o file.o
as --32/--64 file.s # 32/64 bit

目标文件

也叫可重定位文件,是经过编译但还未进行链接的中间文件。

ld

链接器,将若干目标文件链接为可执行文件。

1
2
ld file1.o file2.o -o exe
ld file.o --dynamic-linker /lib64/ld-linux-x86-64.so.2 -e main -lc -o exe

虽然说gcc在将源代码编译成汇编后就是依靠asld来生成最终的可执行文件(gcc -v显示的是collect2,不过这其实只是ld的封装),但是手动使用gcc -Sasld来生成可执行文件会产生很多问题(我到现在都还没成功),比如入口函数、程序终止等等。

nm

列出目标文件或可执行文件中的符号表。

1
2
3
4
5
nm file
-g # 列出全局符号
-u # 列出未定义符号
-a # 列出所有符号
--demangle # 还原C++中修饰了的符号

符号类型:大写为全局,小写为局部。

  • U: 未定义符号
  • T: 文本符号
  • D: 数据符号
  • B: bss符号
  • A: 绝对符号

size

列出目标文件或可执行文件中各个节的大小信息。

1
size file

输出包括text,data,bss,dec,hex和filename列,其中dec和hex是总大小的十进制和十六进制表示。

strings

列出目标文件或可执行文件中可打印的字符串,默认只搜索数据段。

1
2
3
strings file
strings -a file
string -n number file # 限制长度至少为number

strip

去除符号表,减小文件大小并加速执行。

1
2
3
4
5
strip file
strip --strip-all file
strip --strip-debug file
strip --strip-unneeded file
strip file -o stripped_file # 默认是替换源文件,-o则生成一个新文件

c++filt

还原修饰的C++符号。

1
c++filt _Z1fv

addr2line

将可执行文件中的地址翻译为对应的行号和文件名,需要编译信息(-g)。

1
addr2line -e exe --functions --demangle address 

可以将汇编代码和源文件代码一一对应起来,帮助理解。

gprof

用于程序性能分析,需要-pg选项以在每个函数入口处插入mcount函数用于插桩。

1
2
./exe # 运行后会生成一个gmon.out文件
gprof exe gmon.out > analysis.txt

缺点:

  • 计时基于采样,不准确
  • 只分析用户态代码
  • 不分析共享库代码
  • 只观测主线程,且不一定线程安全

ar

用于建立、修改静态库或从静态库中提取文件。其中静态库中包含了按照特定结构组织起来的一组目标文件(称为成员,有.a、.so、.o等类型),并保留各个文件的原始信息。

注:ar命令创建的文件用于存储编译后的目标文件以供链接,而tar命令创建的文件用于组织和归档文件和目录。这两种命令的主要用途和文件格式完全不同。

1
ar crv liba.a file1.o file2.o

ranlib

在更新静态库后,更新符号表信息(一般不需要使用,该功能等价于ar -s

1
ranlib liba.a

readelf

显示ELF格式文件的信息

1
2
3
4
5
6
7
readelf -h file
readelf -a file
readelf -s file # 符号表
readelf -r file # 可重定位表
readelf -S file # 节头表
readelf -l file # 程序头表
-W # 输出不换行

objdump

显示目标文件的信息

1
2
3
4
5
objdump -d file # 反汇编
objdump -d -S file # 与源代码对应
objdump -d -l file # 与源代码中的行号对应
objdump -M intel -d file # 使用intel格式
objdump -f file # 查看文件头信息

objcopy

将一种类型的目标文件转化为另一种类型。

1
objcopy --only-keep-debug file file.debuginfo # 抽取出调试信息

libiberty

libbfd

二进制描述符库。

libopcodes