如何获取程序或链接库中任意函数的字节长度?
函数字节长度获取方案
常见实现方式
- 符号表解析(最准确)
不管是Windows的PE格式、Linux的ELF格式还是macOS的Mach-O格式,二进制文件的符号表项本身就存储了每个函数的起始地址和字节长度,只要目标文件没有被strip删除符号,直接解析对应段的符号信息就能拿到准确值。- Windows平台可通过
SymFromAddr等调试辅助API直接读取符号中的函数长度 - Linux/macOS平台可通过
dladdr1接口从加载的动态库中读取函数符号的长度信息
- Windows平台可通过
- 编译期标记(自有代码适用)
如果是你自己源码中的函数,可以直接在目标函数末尾定义一个空的标记函数,通过地址差计算长度,需要关闭编译器的函数重排优化避免位置错乱,示例代码如下:// 目标函数 int target_calc(int a, int b) { return a + b * 2; } // 末尾标记函数,不要加任何逻辑 void target_calc_end() {} // 计算长度 size_t func_size = (size_t)target_calc_end - (size_t)target_calc; - 运行时指令扫描(无符号场景适用)
从函数起始地址开始逐字节解析指令,直到扫到属于该函数的最后一条ret/int3等终止类指令为止。这种方式需要依赖对应CPU架构的反汇编能力,适合没有符号表的场景。
是否有通用现成API?
没有跨平台的通用API可以直接获取任意函数的字节长度。所有平台的内置接口都依赖符号表存在,若二进制符号被删除,只能自己实现指令扫描逻辑,或者集成成熟的反汇编引擎辅助实现。
开发性价比参考
- 如果是自有代码的特定函数长度获取:用编译期标记方案,几行代码就能实现,性价比极高。
- 如果是带符号的二进制函数长度获取:直接调用对应平台的符号解析API,开发成本很低,性价比高。
- 如果是要做无符号二进制的通用函数长度识别:需要处理指令集解析、多分支ret、尾调用优化、函数内联等大量特殊场景,开发成本极高,若非核心业务需求,性价比极低。
注意事项
运行时指令扫描的准确率无法保证100%:如果函数存在多ret分支、尾调用跳转、函数共享尾部代码等编译优化情况,很容易出现计算结果偏大或偏小的问题,对准确率要求高的场景优先选择符号表解析方案。
内容的提问来源于stack exchange,提问作者pazdinho_
相关产品推荐
相关产品推荐

