C++(Qt)软件调试---binutils工具集详解(39)
C++(Qt)软件调试—binutils工具集详解(39)
文章目录
- C++(Qt)软件调试---binutils工具集详解(39)
- @[toc]
- 1 概述🐜
- 2 binutils包含的工具
- 3 主要工具详细说明
- 3.1 ld - GNU 链接器
- 3.2 as - GNU 汇编器
- 3.3 gold - GNU 链接器(快速版)
- 4 其他工具详细说明
- 4.1 addr2line
- 4.2 ar
- 4.3 c++filt
- 4.4 dlltool
- 4.5 elfedit
- 4.6 gprof
- 4.7 gprofng
- 4.8 nlmconv
- 4.9 nm
- 4.10 objcopy
- 4.11 objdump
- 4.12 ranlib
- 4.13 readelf
- 4.14 size
- 4.15 strings
- 4.16 strip
- 4.17 windmc
- 4.18 windres
- 5 地址
文章目录
- C++(Qt)软件调试---binutils工具集详解(39)
- @[toc]
- 1 概述🐜
- 2 binutils包含的工具
- 3 主要工具详细说明
- 3.1 ld - GNU 链接器
- 3.2 as - GNU 汇编器
- 3.3 gold - GNU 链接器(快速版)
- 4 其他工具详细说明
- 4.1 addr2line
- 4.2 ar
- 4.3 c++filt
- 4.4 dlltool
- 4.5 elfedit
- 4.6 gprof
- 4.7 gprofng
- 4.8 nlmconv
- 4.9 nm
- 4.10 objcopy
- 4.11 objdump
- 4.12 ranlib
- 4.13 readelf
- 4.14 size
- 4.15 strings
- 4.16 strip
- 4.17 windmc
- 4.18 windres
- 5 地址
更多精彩内容 |
---|
👉内容导航 👈 |
👉C++软件调试 👈 |
1 概述🐜
binutils
(Binary Utilities)是一套用于处理二进制目标文件的工具集合,主要面向编译器和链接器生成的目标文件和可执行文件。是GCC编译器套件的重要组成部分,广泛应用于Linux、BSD等类Unix系统以及嵌入式开发环境中;
部分工具可用于Windows,不过在Windows中支持不完整。
学习 Binutils 有以下几个重要原因(还有其他更多的用途这里不列出来):
理解程序构建过程
编译链接原理:Binutils 包含了
as
(汇编器)、ld
(链接器)等工具,帮助理解代码如何从源文件转换为可执行文件目标文件分析:通过
objdump
、readelf
等工具可以深入理解 ELF 文件格式和程序结构调试和性能优化
调试支持:
addr2line
、nm
等工具可以帮助定位程序问题和分析符号信息性能分析:通过分析目标文件和符号表,可以进行程序大小优化和性能调优
内存布局:理解程序在内存中的布局和加载过程
逆向工程和安全研究
二进制分析:安全研究人员需要使用 Binutils 中的工具来分析恶意软件或进行漏洞研究
反汇编:
objdump
可以用来反汇编程序,分析其行为
环境 | 说明 |
---|---|
系统 | ubuntu20.04、windows10 |
2 binutils包含的工具
主要工具
ld
- GNU 链接器as
- GNU 汇编器gold
- 一种新的、更快的、仅支持 ELF 的链接器
其他工具
addr2line
- 将地址转换为文件名和行号ar
- 用于创建、修改和提取档案文件的工具c++filt
- 用于解码 C++ 符号的过滤器dlltool
- 创建用于构建和使用 DLL 的文件elfedit
- 允许修改 ELF 格式文件gprof
- 显示性能分析信息gprofng
- 收集并显示应用程序性能数据nlmconv
- 将目标代码转换为 NLM 格式nm
- 列出目标文件中的符号objcopy
- 复制和转换目标文件objdump
- 显示目标文件中的信息ranlib
- 为档案文件内容生成索引readelf
- 显示任何 ELF 格式目标文件中的信息size
- 列出目标文件或档案文件的节大小strings
- 列出文件中的可打印字符串strip
- 丢弃符号windmc
- Windows 兼容的消息编译器windres
- Windows 资源文件编译器
相关库文件
libbfd
- 用于操作多种不同格式二进制文件的库libctf
- 用于操作 CTF 调试格式的库libopcodes
- 用于汇编和反汇编多种不同汇编语言的库libsframe
- 用于操作 SFRAME 调试格式的库
3 主要工具详细说明
3.1 ld - GNU 链接器
GNU Binutils 中的链接器,用于将编译后的目标文件(.o)和库文件(.a/.so)链接成可执行文件或共享库。它主要负责地址分配、符号解析和重定位。
实际中通常使用编译器完成链接,会自动调用
ld
并设置必要的参数。
主要功能
- 符号解析:解析不同目标文件中的符号引用和定义
- 重定位:调整代码和数据的地址引用
- 段合并:将输入文件中的段合并到输出文件中
- 库处理:链接静态库和动态库
使用场景:
- 将编译后的目标文件合并为最终可执行程序
- 创建共享库(.so文件)
- 处理符号解析和重定位
使用方法:
ld [选项] 目标文件... -o 输出文件
3.2 as - GNU 汇编器
as
命令是 GNU 汇编器(GNU Assembler)的命令行工具,用于将汇编语言源代码编译成目标文件。它是 GNU Binutils 工具集的一部分,通常与
gcc
编译器一起使用。
- 通常由
gcc
自动调用,用户无需直接使用;- 生成的目标文件需要通过
ld
链接器进行链接;- 可以与
objdump
、nm
等工具配合分析目标文件;
主要功能
- 汇编翻译:将汇编语言代码转换为机器码格式的目标文件
- 符号处理:处理汇编代码中的标签、变量名等符号
- 重定位信息生成:为目标文件生成重定位信息,供链接器使用
使用场景:
- 编译汇编语言程序
- 将.s或.S文件转换为.o目标文件
- 嵌入到编译流程中处理内联汇编
使用方法:
as [选项] 源文件.s -o 输出文件.o
3.3 gold - GNU 链接器(快速版)
gold
是一个更快的链接器实现,专门针对大型应用程序进行了优化;它在链接速度方面比传统
ld
链接器有显著提升,特别是在处理大量目标文件时表现优异;GNU
ld
的替代品;
性能优势
- 快速链接:比传统
ld
链接器快得多,特别是在大型项目中 - 并行处理:能够利用多核处理器提高链接速度
- 内存效率:更有效地管理内存使用
- 增量链接:支持更快的增量构建
使用场景:
- 大型项目链接加速
- 需要更快链接速度的构建环境
- 仅处理 ELF 格式的系统(如Linux)
使用方法:
gold [选项] 输入文件... -o 输出文件
或通过 gcc 调用:
gcc -fuse-ld=gold [其他选项] 文件...
4 其他工具详细说明
4.1 addr2line
addr2line
是一个 GNU binutils 工具集中的命令行工具,主要用于将程序的内存地址转换为对应的源代码文件名和行号。这对于调试程序、分析崩溃日志或性能分析非常有用。
功能
- 地址到源码映射:将二进制程序中的内存地址转换为源代码位置(文件名:行号)
- 调试信息解析:利用程序中的调试信息(如 DWARF)进行地址解析
使用场景
- 程序崩溃调试:当程序产生段错误(core dump)时,根据栈回溯中的地址定位具体出错位置
- 性能分析:配合性能分析工具,将采样地址映射到源代码
- 调试辅助:在没有完整调试环境时提供地址解析功能
- 逆向工程:帮助理解二进制程序的行为和结构
使用方法
# 将地址转换为文件名和行号
addr2line -e myprogram 0x400526# 显示地址、函数名和源码位置
addr2line -a -f -e myprogram 0x400526# 只显示文件名(不包含路径)和行号
addr2line -s -e myprogram 0x400526
常用选项
-e --exe=<executable>
:指定要分析的可执行文件(默认为 a.out)-b --target=<bfdname>
:设置二进制文件格式(如 elf64-x86-64)-j --section=<name>
:读取相对于指定段的偏移量而非绝对地址-a --addresses
:显示原始地址-f --functions
:显示函数名称-s --basenames
:只显示文件名,去除目录路径-p --pretty-print
:以更易读的格式显示输出-i --inlines
:展开内联函数信息-C --demangle[=style]
:将 C++ 符号名还原为可读格式,可选 demangle 风格-R --recurse-limit
:启用 demangle 时的递归限制(默认启用)-r --no-recurse-limit
:禁用 demangle 时的递归限制
注意事项
- 调试信息要求:目标程序必须在编译时包含调试信息(使用
-g
选项) - 地址格式:地址应为虚拟内存地址,通常以 0x 开头
- stripped 程序:对于去除了符号表的程序,功能会受限
- PIE 程序:对于位置无关可执行程序,可能需要考虑加载基址
4.2 ar
功能
ar
(archiver) 是创建和维护静态库(.a文件)的工具,可以将多个目标文件打包成一个档案文件。
使用场景
- 构建静态链接库供其他程序使用
- 管理大型项目的目标文件集合
- 创建备份档案文件
使用方法
ar [选项] 归档文件名 [成员文件...]
# 创建一个包含多个目标文件的静态库
ar rcs libmylib.a file1.o file2.o file3.o
# 列出库中包含的所有文件
ar t libmylib.a
# 从库中提取特定文件
ar x libmylib.a file1.o
# 向已存在的库中添加新文件
ar r libmylib.a newfile.o
常用操作符:
r
插入文件到档案中(替换已存在的文件)c
创建档案文件s
写入索引(相当于运行ranlib)t
列出档案内容x
提取文件
4.3 c++filt
功能
c++filt
用于解码C++编译器产生的修饰(mangled)符号名,将其转换为人类可读的形式。
使用场景
- 链接错误分析:解读链接器报告的未解析符号
- 调试符号分析:理解符号表中的C++函数名
- 反汇编分析:将汇编代码中的修饰符号还原
使用方法
c++filt [options] [mangled_names...]
echo "_ZNSsD1Ev" | c++filt # 通过管道解码
nm executable | c++filt # 解码nm输出中的符号
常用选项:
-_
允许下划线开头的符号-n
不省略下划线前缀-p
不解码函数参数和返回值类型
4.4 dlltool
功能
dlltool
是一个用于创建 DLL (动态链接库) 相关文件的工具,主要在 MinGW 和 Cygwin 环境中使用。
使用场景
- 在MinGW/MSYS环境下开发Windows DLL
- 创建与Windows DLL交互的导入库
- 生成DEF文件定义DLL导出符号
使用方法
dlltool [options] [--input-def def-file] [--output-lib lib-file] [--dllname dll-name]
dlltool --def mydll.def --dllname mydll.dll --output-lib libmydll.a
主要选项:
--def
指定DEF文件--output-lib
生成导入库--dllname
指定目标DLL名称--export-all-symbols
导出所有全局符号
4.5 elfedit
功能
elfedit
是一个用于编辑 ELF (Executable and Linkable Format) 文件的工具。ELF 是 Unix 和类 Unix 系统(如 Linux)中标准的可执行文件、目标代码、共享库和核心转储文件格式。
使用场景
- 跨平台兼容性调整,将二进制文件标记为适用于不同架构
- 调整交叉编译后生成的目标文件属性,确保生成的可执行文件符合目标系统的 ABI 要求
- 更改目标文件类型以配合调试工具,修改 OSABI 以匹配特定运行环境
- 分析恶意软件时修改其标识信息,绕过基于 ELF 头信息的简单安全检查
- 准备适用于特定容器环境的可执行文件,调整二进制文件以适应不同的虚拟化平台
- 学习 ELF 文件格式的实验工具,验证不同属性对程序加载的影响
使用方法
elfedit [options] elf-file# 修改 ELF 文件的机器类型
elfedit --input-mach i386 --output-mach x86_64 program.elf# 修改 ELF 文件的 OSABI
elfedit --output-osabi linux program.elf# 启用 x86 特性
elfedit --enable-x86-feature feature_name program.elf
主要命令:
--input-mach <machine>
: 设置输入文件的机器类型--output-mach <machine>
: 设置输出文件的机器类型--input-type <type>
: 设置输入文件的文件类型--output-type <type>
: 设置输出文件的文件类型--input-osabi <osabi>
: 设置输入文件的 OSABI (Operating System Application Binary Interface)--output-osabi <osabi>
: 设置输出文件的 OSABI--enable-x86-feature <feature>
: 启用指定的 x86 特性--disable-x86-feature <feature>
: 禁用指定的 x86 特性
4.6 gprof
功能
gprof
是 GNU 的性能分析工具,用于分析 C、C++ 等程序的执行性能。它通过收集程序运行时的函数调用信息和执行时间数据,帮助开发者找出程序中的性能瓶颈。
gprof
更适合传统的应用程序分析和教学用途,而 perf
是现代 Linux 系统下的首选性能分析工具。
基本工作原理
- 编译时插桩: 程序需要用
-pg
选项编译,会在每个函数中插入分析代码 - 运行时数据收集: 程序运行时会生成
gmon.out
文件,记录函数调用关系和时间信息 - 数据分析:
gprof
读取可执行文件和gmon.out
数据,生成性能分析报告
使用场景
- 程序性能优化:识别热点函数和瓶颈
- 算法效率分析:比较不同实现的性能特征
- 程序行为研究:了解函数调用模式
使用方法
# 1. 编译程序时添加 -pg 选项
gcc -pg -o myprogram myprogram.c# 2. 运行程序生成 gmon.out
./myprogram# 3. 使用 gprof 分析性能
gprof myprogram gmon.out > analysis.txt# 只显示扁平性能分析,不显示调用图
gprof -p myprogram gmon.out# 设置最小调用次数阈值
gprof -m 10 myprogram gmon.out# 排除特定函数
gprof -e init_function myprogram gmon.out# 显示所有函数包括未调用的
gprof -z myprogram gmon.out# 生成带注释的源代码
gprof -S myprogram gmon.out
输出包括:
- 扁平概要:每个函数的时间消耗
- 调用图:函数间的调用关系和时间分布
4.7 gprofng
功能
gprofng
是 Oracle 开发的新一代性能分析工具,是传统gprof
工具的现代化替代品。- 它提供了更强大、更灵活的性能分析能力,并解决了传统
gprof
的许多限制。 gprofng
采用了现代性能分析的理念,使用采样(sampling)而非插桩(instrumentation)的方式来收集性能数据,避免了传统gprof
对程序性能的巨大影响。- 主要在 Solaris 和 illumos 系统上可用。
主要特点
-
低侵入性
-
无需重新编译程序(不需要
-pg
选项) -
对程序运行性能影响极小
-
可以分析正在运行的进程
-
-
多维度分析
-
支持用户空间和内核空间分析
-
提供多种数据视图(火焰图、调用树等)
-
支持多线程和多进程分析
-
-
现代化界面
-
提供图形化用户界面
-
支持命令行界面
-
可生成交互式 HTML 报告
-
使用场景
- 更精确的性能测量
- 多线程应用性能分析
- 更详细的调用栈跟踪
使用方法
# 收集指定程序的性能数据
gprofng collect your_program# 收集正在运行的进程数据
gprofng collect -p PID# 收集系统范围的性能数据
gprofng collect -s# 分析收集到的数据
gprofng display experiment_name# 生成火焰图
gprofng display -flamegraph experiment_name# 生成调用树
gprofng display -calltree experiment_name
4.8 nlmconv
功能
nlmconv
将通用目标文件转换为NetWare Loadable Module(NLM)格式。
使用场景
- 开发NetWare服务器应用程序
- 移植Unix/Linux程序到NetWare平台
- 创建NetWare服务模块
使用方法
nlmconv [options] input-file
nlmconv -T nlm32-i386 input.o output.nlm
4.9 nm
功能
nm
是一个用于列出目标文件中符号表的命令行工具,在 Unix 和类 Unix 系统(如 Linux)中广泛使用。
它可以帮助开发者查看可执行文件、目标文件(.o 文件)、静态库(.a 文件)和共享库(.so 文件)中的符号信息。
使用场景
- 调试程序: 检查可执行文件是否包含预期的函数和变量
- 库开发: 验证库导出了正确的符号
- 链接问题诊断: 查找未解析的符号或重复定义的符号
- 逆向工程: 分析二进制文件的结构和依赖关系
使用方法
nm [options] object-file...
nm executable # 显示所有符号
nm -D shared_library.so # 显示动态符号表
nm -g executable # 只显示全局符号
主要选项说明
-
-a, --debug-syms
:显示仅供调试器使用的符号 -
-A, --print-file-name
:在每个符号前打印输入文件名 -
-D, --dynamic
:显示动态符号而非普通符号 -
--defined-only
:仅显示已定义的符号 -
-g, --extern-only
:仅显示外部符号 -
-u, --undefined-only
:仅显示未定义的符号 -
--special-syms
:在输出中包含特殊符号 -
--synthetic
:同时显示合成符号 -
-B
:等同于--format=bsd
-
-f, --format=FORMAT
:使用指定的输出格式,可选:bsd
(默认)sysv
posix
-
-P, --portability
:等同于--format=posix
-
-o
:等同于-A
-
-n, --numeric-sort
:按地址数值排序符号 -
-p, --no-sort
:不对符号排序 -
-r, --reverse-sort
:反向排序 -
--size-sort
:按符号大小排序 -
-C, --demangle[=STYLE]
:将低级符号名解码为用户级名称- STYLE 可选:
auto
(默认)、gnu
、lucid
、arm
、hp
、edg
、gnu-v3
、java
、gnat
- STYLE 可选:
-
--no-demangle
:不解码低级符号名 -
--recurse-limit
:启用解码递归限制(默认) -
--no-recurse-limit
:禁用解码递归限制 -
-l, --line-numbers
:使用调试信息查找每个符号的文件名和行号 -
-S, --print-size
:打印已定义符号的大小 -
-s, --print-armap
:包含归档成员符号的索引 -
-t, --radix=RADIX
:使用指定进制打印符号值 -
--target=BFDNAME
:指定目标对象格式 -
--with-symbol-versions
:在符号名后显示版本字符串 -
--plugin NAME
:加载指定插件 -
-h, --help
:显示此帮助信息 -
-V, --version
:显示程序版本号
符号类型标记:
T/t
文本段中的符号D/d
数据段中的符号B/b
BSS段中的符号U
未定义符号W/w
弱符号
注意事项
- 对于剥离了符号表的二进制文件(使用 strip 命令处理过),
nm
可能无法显示有意义的信息 - 不同架构的目标文件可能需要特定版本的
nm
工具 - 在交叉编译环境中,需要使用对应目标平台的
nm
工具
4.10 objcopy
功能
objcopy
是 GNU Binutils 工具集中的一个重要工具,用于复制和转换目标文件(object files)。
它可以在不同格式之间转换二进制文件,并对文件内容进行各种修改。
使用场景
- 删除或保留特定段(sections)
- 操作符号表(添加、删除、重命名符号)
- 修改段属性和地址
- 填充数据间隙
- 分离调试信息以便调试时使用
- 发布版本时去除调试信息和其他不需要的信息
- 在嵌入式开发中,经常需要将可执行文件转换为适合烧录的格式
- 创建适合特定内存布局的内核模块
使用方法
objcopy [options] infile outfile
objcopy -O binary executable bootsect.bin # 转换为原始二进制格式
objcopy --strip-debug executable stripped # 去除调试信息
objcopy --only-section=.text input output # 只保留.text段
常用选项
-
-I
,--input-target <bfdname>
:指定输入文件格式 -
-O
,--output-target <bfdname>
:指定输出文件格式 -
-F
,--target <bfdname>
:同时设置输入和输出格式 -
-B
,--binary-architecture <arch>
:当输入无架构信息时设置输出架构 -
-S
,--strip-all
:移除所有符号和重定位信息 -
-g
,--strip-debug
:移除所有调试符号和段 -
-N
,--strip-symbol <name>
:不复制指定符号 -
-K
,--keep-symbol <name>
:保留指定符号(不被strip) -
-L
,--localize-symbol <name>
:将符号标记为本地符号 -
-G
,--keep-global-symbol <name>
:除指定符号外,其他都本地化 -
-W
,--weaken-symbol <name>
:将符号标记为弱符号 -
-x
,--discard-all
:移除所有非全局符号 -
-X
,--discard-locals
:移除编译器生成的符号 -
-j
,--only-section <name>
:只复制指定段到输出 -
-R
,--remove-section <name>
:从输出中移除指定段 -
--keep-section <name>
:不strip指定段 -
--only-keep-debug
:只保留调试信息 -
--extract-symbol
:移除段内容但保留符号 -
--set-start <addr>
:设置起始地址 -
--change-start <incr>
:将起始地址增加指定值 -
--change-addresses <incr>
:将LMA、VMA和起始地址都增加指定值 -
--change-section-address <name>{=|+|-}<val>
:修改指定段的LMA和VMA -
--change-section-lma/vma <name>{=|+|-}<val>
:单独修改段的LMA或VMA -
--gap-fill <val>
:用指定值填充段之间的空隙 -
--pad-to <addr>
:将最后一段填充到指定地址 -
--set-section-alignment <name>=<align>
:设置段的对齐方式 -
-p
,--preserve-dates
:保留修改/访问时间戳 -
-w
,--wildcard
:允许在符号比较中使用通配符 -
-v
,--verbose
:显示详细处理信息 -
--add-section <name>=<file>
:从文件中添加新段 -
--dump-section <name>=<file>
:将段内容转储到文件 -
--rename-section <old>=<new>[,<flags>]
:重命名段 -
--redefine-sym <old>=<new>
:重新定义符号名
注意事项
- 备份原文件:某些操作会修改原文件,建议先备份
- 格式兼容性:不是所有格式之间都能相互转换
- 符号依赖:移除关键符号可能导致程序无法运行
- 地址对齐:修改地址时需考虑处理器的对齐要求
- 权限问题:某些操作可能需要特殊权限
- 交叉编译环境:确保使用正确的目标平台格式
4.11 objdump
功能
objdump
是一个用于显示目标文件(object files)信息的命令行工具,属于 GNU Binutils 套件的一部分。
它可以用来查看可执行文件、目标文件和库文件的详细信息,包括文件头、节头、符号表、反汇编代码等。
主要用途
- 文件分析:查看目标文件的结构和内容
- 调试支持:显示调试信息和符号表
- 反汇编:将机器码转换为汇编代码
- 格式检查:验证文件格式和架构兼容性
使用场景
- 程序调试:分析可执行文件结构和符号信息
- 逆向工程:查看程序的汇编代码实现
- 开发支持:检查编译器输出的目标文件
- 系统分析:分析库文件和系统二进制文件
使用方法
objdump [options] object-file...
# 反汇编可执行文件
objdump -d program# 显示文件头信息
objdump -f program# 显示所有节头信息
objdump -h program# 混合显示源码和反汇编
objdump -S program# 只反汇编特定函数
objdump --disassemble=main program
常用选项
-
-f, --file-headers
:显示文件头信息 -
-h, --headers
:显示节头信息 -
-p, --private-headers
:显示特定格式的文件头 -
-d, --disassemble
:反汇编可执行节 -
-D, --disassemble-all
:反汇编所有节 -
-S, --source
:混合显示源代码和反汇编 -
-t, --syms
:显示符号表 -
-g, --debugging
:显示调试信息 -
-r, --reloc
:显示重定位信息 -
-j, --section=NAME
:只处理指定节 -
-C, --demangle
:解码修饰的符号名 -
-M, --disassembler-options
:传递反汇编器选项
注意事项
- 必需选项:至少需要指定一个主选项(如
-d
、-h
等)才能执行 - 文件格式:支持多种目标文件格式(ELF、PE等)
- 架构相关:需要与目标文件的架构匹配
- 权限要求:需要对目标文件有读取权限
- 大文件处理:对于大型文件可能需要较长时间处理
- 输出格式:某些选项会产生大量输出,建议配合管道使用
4.12 ranlib
功能
ranlib
是一个用于处理静态库(archive)的工具,主要功能是为静态库生成索引以加快访问速度。
使用场景
- 创建静态库后必须运行以生成索引
- 更新档案文件后重新生成索引
- 保证链接器能正确找到库中符号
使用方法
ranlib archive-file
ar rcs libname.a *.o # ar的s选项会自动调用ranlib
主要选项
@<file>
:从指定文件中读取选项参数--plugin <name>
:加载指定的插件-D
:在符号映射中使用零作为时间戳(默认行为)-U
:在符号映射中使用实际的时间戳-t
:更新静态库符号映射的时间戳-h
,--help
:显示帮助信息-v
,--version
:显示版本信息
4.13 readelf
功能
readelf
专门用于显示ELF格式目标文件的详细信息,比objdump更专注于ELF结构。
readelf
主要用于查看 ELF 文件的各种元数据信息,包括但不限于:
- ELF 文件头
- 程序头表(段)
- 节区头表
- 符号表
- 重定位信息
- 动态链接信息
- 调试信息(DWARF)
使用场景
- 调试与逆向工程
- 分析可执行文件结构
- 查看符号表和重定位信息
- 检查动态链接依赖关系
- 编译构建过程分析
- 验证目标文件是否正确生成
- 检查节区布局和内存映射
- 分析程序加载和运行机制
- 系统级编程
- 理解 ELF 文件格式细节
- 分析共享库和可执行文件的内部结构
- 排查链接和加载问题
- 安全审计
- 检查二进制文件属性
- 分析潜在的安全特性(如 NX、PIE 等)
使用方法
readelf [options] elf-file
# 显示文件头信息
readelf -h a.out # 显示所有节区信息
readelf -S a.out # 显示符号表
readelf -s a.out # 显示动态段信息
readelf -d a.out # 以十六进制显示 .text 节内容
readelf -x .text a.out # 显示所有调试信息
readelf -w a.out
注意事项
- 输入文件要求
- 只能处理符合 ELF 格式的文件
- 对于非 ELF 文件会提示错误
- 权限限制
- 需要有读取目标文件的权限
- 输出量控制
- 某些选项会产生大量输出,建议配合管道使用(如
less
或grep
)
- 某些选项会产生大量输出,建议配合管道使用(如
- 版本差异
- 不同版本的
readelf
可能存在选项差异 - 建议查阅当前系统上的具体帮助信息
- 不同版本的
- 特殊格式支持
- 对某些特殊的 ELF 扩展格式可能需要特定版本的支持
4.14 size
功能
size
命令的主要功能是显示目标文件或可执行文件中各节区的大小,包括文本段(代码)、数据段(已初始化数据)、BSS段(未初始化数据)等。
这对于了解程序的内存分布和优化程序大小很有帮助。
使用场景
- 程序大小分析
- 评估程序的整体大小
- 分析代码段、数据段和BSS段的占比
- 嵌入式开发
- 监控程序占用的Flash和RAM大小
- 优化资源受限环境下的程序尺寸
- 性能调优
- 识别占用空间较大的节区
- 分析内存布局对性能的影响
- 构建系统集成
- 在Makefile中检查生成文件大小
- 自动化构建过程中监控二进制文件增长
- 比较不同版本
- 对比不同编译选项产生的文件大小差异
- 追踪代码变更对二进制大小的影响
使用方法
size [options] object-file...
# 基本用法,显示默认格式
size a.out# 使用 System V 格式显示详细节区信息
size -A a.out# 以十六进制显示数值
size -x a.out# 显示多个文件并计算总计(Berkeley 格式)
size -t *.o# 显示 COMMON 符号大小
size --common test.o# 指定特定目标格式
size --target=elf32-i386 program.bin
注意事项
- 默认文件行为
- 如果没有指定文件,会尝试读取
a.out
- 如果没有指定文件,会尝试读取
- 格式兼容性
- 不同输出格式提供的信息详略程度不同
- Berkeley 格式简洁,System V 格式详细
- 目标平台相关
- 输出结果与目标平台架构有关
- 同一源码在不同平台上可能产生不同大小
- 符号处理
- COMMON 符号的处理可能因选项而异
- 使用
--common
选项可以获得更准确的统计
- 文件格式支持
- 确保输入文件格式在支持列表中
- 必要时使用
--target
指定正确的格式
4.15 strings
功能
strings
是一个用于从二进制文件中提取可打印字符串的实用工具,主要用于分析和调试二进制程序。
- 从二进制文件中提取可打印的字符串序列
- 默认查找至少4个字符长度的NUL终止字符串
- 支持多种文件格式和编码方式
- 常用于逆向工程、恶意软件分析和程序调试
使用场景
- 程序分析: 从编译后的程序中提取硬编码的字符串
- 安全分析: 检查二进制文件中是否包含可疑字符串
- 调试辅助: 查看程序中包含的文本信息
- 逆向工程: 理解未知二进制文件的功能
- 恶意软件检测: 搜索潜在的恶意URL或命令
使用方法
strings [options] file...
# 提取文件中的所有字符串(至少4个字符)
strings myfile# 提取至少8个字符长度的字符串
strings -n 8 myfile# 显示字符串在文件中的位置(十六进制)
strings -t x myfile# 只扫描数据段并显示文件名
strings -d -f myfile# 指定字符编码(16位小端)
strings -e l myfile
常用选项
-a
,--all
: 扫描整个文件(默认行为)-d
,--data
: 仅扫描文件的数据段-f
,--print-file-name
: 在每个字符串前打印文件名-n NUMBER
,--bytes=NUMBER
: 设置最小字符串长度(默认为4)-t {o,d,x}
,--radix={o,d,x}
: 以八进制、十进制或十六进制显示字符串位置-e ENCODING
,--encoding=ENCODING
: 指定字符编码格式-T TARGET
,--target=BFDNAME
: 指定二进制文件格式-h
,--help
: 显示帮助信息-v
,-V
,--version
: 显示版本信息
注意事项
- 默认行为: 默认只查找至少4个字符的字符串,可通过
-n
选项调整 - 文件格式支持: 支持多种目标格式(elf64-x86-64, elf32-i386等)
- 编码处理: 对于非ASCII编码的字符串可能需要指定
-e
选项 - 性能考虑: 对于大文件,使用
-d
选项可以提高扫描速度 - 输出控制: 可使用
-s
选项自定义字符串分隔符
4.16 strip
功能
strip
是一个用于从目标文件中删除符号表和调试信息的工具,常用于减小可执行文件或共享库的大小。
使用场景
- 发布版本优化
- 移除调试信息减小可执行文件大小
- 提高程序运行效率
- 保护源码
- 删除符号信息增加逆向工程难度
- 嵌入式开发
- 减少存储空间占用
- 优化内存使用
使用方法
strip [options] file...
# 基本使用:移除所有符号信息
strip program# 保留调试信息
strip --only-keep-debug program.debug# 移除调试信息但保留符号表
strip --strip-debug program# 保留特定符号
strip -K main -K important_func program# 移除指定节区
strip -R .comment -R .note program
注意事项
- 备份原始文件:
strip
操作不可逆,建议先备份重要文件 - 调试影响:剥离后的文件无法进行源码级调试
- 动态链接:过度剥离可能导致动态链接失败
- 符号依赖:某些符号对程序运行是必需的,不能随意移除
- 平台兼容性:不同平台支持的目标格式可能不同
4.17 windmc
功能
windmc.exe
是一个用于处理消息编译(Message Compiler)的工具,主要用于将 .mc
文件编译成资源文件和头文件。
使用场景
- 开发Windows应用程序的本地化支持
- 创建多语言版本的应用程序
- 管理程序中的错误和状态消息
使用方法
windmc [options] msgfile.mc
# 基本编译
windmc messages.mc# 指定头文件输出目录
windmc -h include messages.mc# 指定资源文件输出目录
windmc -r resources messages.mc# 使用UTF16输入和详细模式
windmc -u -v messages.mc
主要选项
-
-a
,--ascii_in
: 指定输入文件为 ASCII 格式 -
-A
,--ascii_out
: 以 ASCII 格式写入二进制消息 -
-u
,--unicode_in
: 指定输入文件为 UTF16 格式 -
-U
,--unicode_out
: 以 UTF16 格式写入二进制消息 -
-b
,--binprefix
: 为生成的 [.bin](javascript:void(0)) 文件添加前缀以确保唯一性 -
-e
,--extension=<extension>
: 设置导出头文件的扩展名 -
-h
,--headerdir=<directory>
: 设置头文件的导出目录 -
-r
,--rcdir=<directory>
: 设置资源文件(.rc)的导出目录 -
-x
,--xdbg=<directory>
: 指定创建.dbg
C 包含文件的目录,该文件将消息 ID 映射到符号名称 -
-C
,--codepage_in=<val>
: 设置读取.mc
文本文件时使用的代码页 -
-O
,--codepage_out=<val>
: 设置写入文本文件时使用的代码页 -
-d
,--decimal_values
: 以十进制格式打印值到文本文件 -
-m
,--maxlength=<val>
: 设置允许的最大消息长度 -
-n
,--nullterminate
: 自动为字符串添加零终止符 -
-o
,--hresult_use
: 使用 HRESULT 定义而不是状态码定义 -
-c
,--customflag
: 为消息设置自定义标志 -
-F
,--target <target>
: 指定输出目标的字节序(endianness) -
-H
,--help
: 显示帮助信息 -
-v
,--verbose
: 详细模式,显示处理过程信息 -
-V
,--version
: 显示版本信息
4.18 windres
功能
windres
是一个用于处理 Windows 资源文件的工具,通常与 MinGW 或 Strawberry Perl 等 Windows 开发环境一起使用。
使用场景
- 为Windows应用程序添加图标、菜单、对话框等资源
- 编译Windows版本程序所需的各种资源
- 国际化支持:编译不同语言的资源文件
使用方法
windres [options] input-file output-file
windres resource.rc resource.o # 编译资源文件
windres -i input.rc -o output.o # 指定输入输出文件
参数说明
-
-i
,--input=<file>
:指定输入文件名 -
-o
,--output=<file>
:指定输出文件名 -
-J
,--input-format=<format>
:指定输入格式 -
-O
,--output-format=<format>
:指定输出格式 -
-F
,--target=<target>
:指定 COFF 目标格式 -
--preprocessor=<program>
:指定用于预处理.rc
文件的程序 -
--preprocessor-arg=<arg>
:添加预处理器参数 -
-I
,--include-dir=<dir>
:添加预处理时的包含目录 -
-D
,--define <sym>[=<val>]
:在预处理时定义符号 -
-U
,--undefine <sym>
:在预处理时取消定义符号 -
-v
,--verbose
:详细模式,显示处理过程 -
-c
,--codepage=<codepage>
:指定默认代码页 -
-l
,--language=<val>
:设置读取.rc
文件时的语言 -
--use-temp-file
:使用临时文件而不是popen
来读取预处理器输出 -
--no-use-temp-file
:使用popen
(默认行为) -
-r
:为了与 Windows 的rc
工具兼容而被忽略 -
@<file>
:从文件中读取选项 -
-h
,--help
:显示帮助信息 -
-V
,--version
:显示版本信息
格式说明
支持的格式包括:
rc
:资源脚本文件res
:编译后的资源文件coff
:COFF 对象文件
5 地址
- GNU Binutils
- Binutils - GNU 项目 - 自由软件基金会
- 下载地址