GNU二进制开发工具集-GNU Binutils
2018-05-07 15:45:51 阿炯

在Linux下开发的朋友们都不可避免地用到一些工具,包括:addr2line、ar、gprof、nm、objcopy、objdump、ranlib、size、strings、strip等等。其实这一系列的工具,就是所谓的 Binutils,当然 GNU 就表示它们都是可以自由地使用的 GNU 软件。这些工具有助于汇编、链接、反汇编和检查二进制可执行文件、目标文件、库和汇编代码。

GNU Binutils,是 GNU Binary Utilities 的简写,一般简称为 Binutils。中文可以翻译为 GNU 的二进制工具集,系一组二进制工具的集合。即 Binutils 不是指某一个工具,而是指一组工具,并且这些工具都是专门针对于二进制的。这些工具的目的是用于操作二进制文件的,而不是针对于文本或者源代码。在 Linux 环境下,这种二进制文件主要指 *.o 文件和 elf 执行文件。显然编译源代码的是 gcc,所以 Binutils 不包含 gcc(这是一种简单的说法,实际上还是有很多关联的)。

Binutils 工具

现在已经知道,Binutils 是一组工具集合,那到底包含了哪些工具呢?

其中比较重要的是 ld 和 as。

ld -- 链接器
将多个目标文件,链接成一个可执行文件(或目标库文件)。

as -- 汇编器
将汇编源代码,编译为(目标)机器代码。

另外还有下面这些相对次要的,但非常实用的工具:

addr2line
将地址转换为(源文件和)行号的工具,一般主要用于反汇编。

ar
用来操作(.a)档案文件,比如创建,修改,提取内容等。archive是一个包含多个被包含文件的单一文件(也称之为库文件),其结构保证了可以从中检索并得到原始的被包含文件(称之为archive中的member)。member的原始文件内容、模式(权限)、时间戳、所有着和组等属性都被保存在 archive中。member被提取后,他们的属性被恢复到初始状态。ar主要用于创建C库文件,即创建和管理静态库。

c++filt
解码 C++ 的符号

dlltool
创建Windows 动态库

gold
一个新的,速度更快的,只针对于ELF的链接器(可能还不是很成熟稳定)。

gprof
gprof被用来测量程序的性能。它记录每个函数被调用的次数以及相应的执行时间,这样就能锁定程序执行时花费时间最多的部分,对程序的优化就可集中于对它们的优化。

nlmconv
可以转换成NetWare Loadable Module目标文件格式

nm
列出目标文件中的符号。nm用来列出目标文件中的符号,可以帮助程序员定位和分析执行程序和目标文件中的符号信息和它的属性。如果没有目标文件作为参数传递给nm,nm假定目标文件为a.out。

objcopy
拷贝并翻译(转换)文件,可用于不同格式的二进制文件的转换。objcopy可以将一种格式的目标文件转化为另外一种格式的目标文件,它使用GNU BFD库进行读/写目标文件。使用BFD,objcopy就能将原格式的目标文件转化为不同格式的目标文件。

objdump
显示目标(二进制)文件中的信息。objdump用来显示目标文件的信息,可以通过选项控制显示那些特定信息,objdump一个最大的用处恐怕就是将C代码反汇编了,在嵌入式软件开发过程中也可以用它查看执行文件或库文件的信息。

ranlib
产生静态库的索引

readelf
显示 ELF(可执行和可链接格式) 格式的(目标)文件的信息。 readelf用来显示ELF格式目标文件的信息,可通过参数选项来控制显示哪些特定信息(注意: readelf不支持显示archive文档,也不支持64位的ELF文件)。

注意: readelf只能用于ELF格式目标文件,且选项中至少要指定一个(除V, H外)的选项。

size
显示目标文件或(.a)档案文件中的节(section)的大小。

strings
显示(二进制)文件中的(可打印)的字符串信息。

strip
从二进制文件中删除调试符号。一般用来把可执行文件中的一些信息(比如 debug 信息)去除掉,以实现在不影响程序功能的前提下,减少可执行文件的大小,减少程序的空间占用。

windmc
产生Windows消息资源

windres
Windows 资源档编译器

示例用法

objdump 检查二进制文件
objdump -d /bin/ls  # 反汇编 ls 命令
objdump -x /bin/ls  # 显示完整的二进制信息

nm 显示目标文件中的符号
nm /bin/ls  # 列出 ls 二进制文件中的符号

strings 提取可读文本
strings /bin/ls  # 从二进制文件中提取可读文本

readelf 检查 ELF 文件
readelf -h /bin/ls  # 显示 ELF 标头

strip 删除调试符号
strip myprogram  # 通过删除符号来减少二进制大小

创建并链接汇编程序
    编写一个汇编程序(hello.s)

.global _start
.section .text
_start:
    mov $1, %rax
    mov $1, %rdi
    mov $msg, %rsi
    mov $len, %rdx
    syscall

    mov $60, %rax
    xor %rdi, %rdi
    syscall

.section .data
msg: .ascii "Hello, Binutils!\n"
len = . - msg

用 as 组装
as hello.s -o hello.o

使用 ld 来链接
ld hello.o -o hello

运行程序
./hello

输出
Hello, Binutils!


最新版本:2.4
GNU Binutils v2.44 已于2025年2月上旬发布。值得一提的是,公告内容指出:与以往不同的是,本次发布的 binutils-2.44.tar 包不包含 gold linker 的源代码。因为 GNU Gold linker 已被弃用,除非有志愿者愿意继续开发和维护,否则最终将被移除。相关源代码可在 binutils-with-gold-2.44.tar tar 包中找到。往后奇数版本的 binutils(2.45、2.47 等)将只包含 binutils.2.xx.tar 包,而偶数版本将同时包含 binutils-2.xx.tar 和 binutils-with-gold-2.xx.tar 包,直到其被完全删除。

GNU Gold 由谷歌于二十多年前推出,旨在提高链接性能,使其比 GNU 链接器更快。事实证明,GNU Gold 确实达到了预期目的,并证明了更快地链接 ELF 对象是可能的。但随着谷歌更依赖于性能更优的 LLVM 工具链,GNU Gold 缺乏投资且开发活动逐渐停滞。科技网站 Phoronix 指出随着越来越多的企业组织转而使用 LLVM 工具链,以及那些希望获得更快 ELF 链接性能的人可能会转而使用 Mold 链接器,而不是投入资源来发展 GNU Gold。除非出现奇迹,否则 GNU Gold linker 将来可能会被彻底放弃。


官方主页:http://www.gnu.org/software/binutils/
参考页面:
GNU Binutils
GNU Binutils 详解