binutils

Installation
SKILL.md

GNU Binutils

用途

引导完成 binutils 工具集的使用,涵盖二进制操作:静态库管理、符号剥离、地址到源码映射、以及符号名反混淆。

触发场景

  • "如何创建静态库?"
  • "如何在保留调试文件的同时剥离二进制符号?"
  • "我有一个崩溃地址,如何找到对应的源码行?"
  • "如何对 C++ 符号名进行反混淆?"
  • "如何提取或替换二进制文件中的节(section)?"

工作流程

1. ar — 静态库管理

# 创建静态库
ar rcs libfoo.a foo.o bar.o baz.o

# 列出内容
ar t libfoo.a

# 提取某个对象文件
ar x libfoo.a foo.o

# 添加/替换对象文件
ar r libfoo.a newbar.o

# 删除对象文件
ar d libfoo.a oldbar.o

# 显示符号索引
nm libfoo.a

# 重建符号索引(外部修改归档后使用)
ranlib libfoo.a

对于 LTO 归档,请使用 gcc-ar/gcc-ranlibllvm-ar,而非普通 ar

2. strip — 移除调试信息

# 剥离所有调试信息(缩减二进制体积)
strip --strip-all prog

# 仅剥离调试节(保留符号表)
strip --strip-debug prog

# 剥离不需要的符号(保留链接所需符号)
strip --strip-unneeded prog

# 原地操作
strip prog

# 输出到新文件
strip -o prog.stripped prog

3. objcopy — 二进制节操作

# 从二进制文件中分离调试信息
objcopy --only-keep-debug prog prog.debug
objcopy --strip-debug prog

# 添加 debuglink(GDB 可自动找到 prog.debug)
objcopy --add-gnu-debuglink=prog.debug prog

# 将二进制转换为其他格式
objcopy -O binary prog prog.bin      # 原始二进制(嵌入式)
objcopy -O srec prog prog.srec       # Motorola S-record

# 从文件添加一个节
objcopy --add-section .resources=data.bin prog

# 移除某个节
objcopy --remove-section .comment prog

# 修改节标志
objcopy --set-section-flags .data=alloc,contents,load,readonly prog

# 将二进制文件嵌入为符号
objcopy -I binary -O elf64-x86-64 \
    --rename-section .data=.rodata,alloc,load,readonly,data,contents \
    data.bin data.o
# 然后链接 data.o;通过 _binary_data_bin_start / _binary_data_bin_end 访问

4. addr2line — 地址转换为源码位置

# 将崩溃地址转换为源码行
addr2line -e prog -f 0x400a12
# 输出:
# my_function
# /home/user/src/main.c:42

# 多个地址
addr2line -e prog -f 0x400a12 0x400b34 0x400c56

# 内联帧(-i)
addr2line -e prog -f -i 0x400a12

# 常用方式:从回溯输出通过管道传入
cat crash.log | grep '0x[0-9a-f]' | grep -o '0x[0-9a-f]*' | \
  addr2line -e prog -f -i

需要二进制文件包含调试信息(编译时加 -g)。对于已剥离的二进制,使用未剥离版本或 .debug 文件。

5. c++filt — C++ 符号反混淆

# 反混淆单个符号
c++filt _ZN3foo3barEv
# 输出:foo::bar()

# 对 nm 输出进行反混淆
nm prog | c++filt

# 对崩溃日志进行反混淆
cat crash.log | c++filt

替代方案:nm -C prog(在 nm 内部直接反混淆)。

6. strings — 提取可打印字符串

strings prog                    # 所有长度 >= 4 的字符串
strings -n 8 prog               # 最小长度 8
strings -t x prog               # 带偏移量(十六进制)
strings -t d prog               # 带偏移量(十进制)

# 搜索特定字符串
strings prog | grep "version"
strings prog | grep "Copyright"

7. readelfobjdump 快速参考

(完整内容见 skills/binaries/elf-inspection

# 通过崩溃地址查找符号(addr2line 的替代方式)
objdump -d -M intel prog | grep -A5 "400a12:"

# 查找哪个对象文件定义了某符号
objdump -t prog | grep my_function

8. 交叉编译(Cross-binutils)

交叉编译时,使用目标平台前缀版本:

aarch64-linux-gnu-strip prog
aarch64-linux-gnu-objcopy --only-keep-debug prog prog.debug
aarch64-linux-gnu-addr2line -e prog 0x400a12
arm-none-eabi-nm libfirmware.a

完整的命令速查表(涵盖 ar、strip、objcopy、addr2line、strings、c++filt),参见 references/cheatsheet.md

相关技能

  • 使用 skills/binaries/elf-inspection 进行 readelf、nm、ldd、objdump 检查
  • 使用 skills/binaries/linkers-lto 了解链接器标志和 LTO
  • 使用 skills/debuggers/core-dumps 结合 objcopy --add-gnu-debuglink 管理调试文件
Related skills

More from killvxk/low-level-dev-skills-zh

Installs
1
First Seen
Mar 21, 2026