如何分析Linux平台二进制可执行文件中编译后函数及其依赖的大小
问题:有没有工具可以分析Linux下二进制可执行文件中编译完成的函数及其依赖的大小?
我的场景如下:
- 程序用C++编写,需要分析的依赖大多来自C库,运行平台为Linux
- 目标是缩减程序静态链接版本的体积,计划移除部分库函数调用自行实现替代逻辑,需要先明确哪些库函数带来的体积膨胀最多
举个简单示例,测试程序test.c代码如下:
int foo (int n) { return n+1; } int main(int argc, char** argv) { return foo(argc)+1; }
用gcc test.c编译后,objdump -d a.out输出的反汇编内容如下:
0000000000001129 <foo>: 1129: f3 0f 1e fa endbr64 112d: 55 push %rbp 112e: 48 89 e5 mov %rsp,%rbp 1131: 89 7d fc mov %edi,-0x4(%rbp) 1134: 8b 45 fc mov -0x4(%rbp),%eax 1137: 83 c0 01 add $0x1,%eax 113a: 5d pop %rbp 113b: c3 retq 000000000000113c <main>: 113c: f3 0f 1e fa endbr64 1140: 55 push %rbp 1141: 48 89 e5 mov %rsp,%rbp 1144: 48 83 ec 10 sub $0x10,%rsp 1148: 89 7d fc mov %edi,-0x4(%rbp) 114b: 48 89 75 f0 mov %rsi,-0x10(%rbp) 114f: 8b 45 fc mov -0x4(%rbp),%eax 1152: 89 c7 mov %eax,%edi 1154: e8 d0 ff ff ff callq 1129 <foo> 1159: 83 c0 01 add $0x1,%eax 115c: c9 leaveq 115d: c3 retq 115e: 66 90 xchg %ax,%ax
可以看到地址1154处main调用了foo,我需要的工具可以输出以下信息:
main的大小为36字节foo的大小为19字节main及其依赖的总大小为55字节(需要工具做递归下降搜索找到main依赖的所有函数)main依赖的函数包括:foo
如果工具还能统计这些函数使用的所有静态数据结构的体积,会是额外的加分项。
解决方案
首推Bloaty McBloatface
这是谷歌开源的二进制大小分析工具,原生支持Linux ELF格式,完全匹配你的需求:
- 自动解析C/C符号,支持demangle处理C的函数名
- 可以单独输出每个函数的自身代码大小
- 自带依赖树分析能力,从指定入口函数(比如main)递归遍历所有调用的函数,自动累加总大小,同时输出完整依赖列表
- 额外支持关联统计函数引用的静态数据(.rodata、.data段的常量、全局变量等)的体积,刚好覆盖你的加分需求
你给出的示例程序用Bloaty直接就能输出你要的所有统计结果,不需要额外二次开发。
轻量自定义方案(无需第三方工具)
如果不想额外安装工具,用系统自带的binutils工具链写个简单的小脚本就能实现:
- 用
nm --print-size 你的二进制文件导出所有函数的起始地址和自身大小,存成符号表字典 - 用
objdump -d 你的二进制文件解析所有函数的汇编代码,提取每个函数调用的目标函数名,建立完整的调用关系图 - 从你要统计的入口函数开始做DFS递归遍历所有可达函数,累加所有函数大小同时收集依赖列表即可
- 需要统计静态数据的话,再加一步用
readelf -r解析重定位表,把数据段符号和引用它的函数做关联即可
其他可选工具
- elfsize:轻量的ELF大小分析工具,支持基础的函数依赖统计,适合快速排查小项目
- 你提到的puncover也可以通过扩展脚本补充依赖统计能力,社区有现成的实现可以直接用
内容的提问来源于stack exchange,提问作者mpb
相关产品推荐
相关产品推荐

