ARM64 Windows下RtlLookupFunctionEntry函数大小计算过度问题咨询
ARM64 Windows下RtlLookupFunctionEntry获取函数大小异常的原因
关键差异:ARM64与x64的RUNTIME_FUNCTION语义不同
你遇到的问题核心是对ARM64 Windows unwind表的误解:
- x64平台的
PRUNTIME_FUNCTION中,FunctionLength直接对应单个函数的字节长度; - 但ARM64的
IMAGE_ARM64_RUNTIME_FUNCTION_ENTRY里的FunctionLength字段,代表的是unwind区域(Unwind Region)的长度,而非单个函数的长度。这个区域可包含多个逻辑独立的函数,共享同一条unwind信息。
ntdll.dll中函数的特殊表现
以你测试的NtClose为例,它实际只有8字节指令(svc 0x0F + ret),但这类系统调用存根在ntdll中是连续批量排列的,共用同一个unwind条目。RtlLookupFunctionEntry返回的FunctionLength对应的是整个连续区块的长度,因此数值会远大于单个函数的实际大小——这是ARM64 Windows标准模块的常规打包方式,属于设计特性而非bug。
自建项目结果不稳定的原因
你的项目重建后结果时好时坏,源于编译器的优化策略:
- 当编译器将多个短函数合并到同一个unwind区域时,返回的
FunctionLength会覆盖整个区块,导致大小超量; - 当函数被单独分配unwind信息时,
FunctionLength会匹配单个函数的实际长度。
正确获取函数边界的方法
既然ARM64的unwind表字段无法直接提供单个函数大小,可采用以下替代方案:
- 导出表差值法:对于导出函数,获取当前函数在导出表中的下一个函数地址,两者的差值即为当前函数的近似长度(适用于ntdll这类标准模块);
- 符号表查询:使用dbghelp库的
SymInitialize和SymGetSymFromAddr64接口,从符号表中获取准确的函数长度; - 编译期标记:针对自建项目,可手动添加函数起始/结束标记(如定义空函数作为结束锚点),或启用编译器特定选项生成函数边界信息。
你的测试代码中,直接用
FunctionLength *4计算大小的逻辑,在ARM64下仅当函数独占一个unwind区域时才有效,无法通用。
内容的提问来源于stack exchange,提问作者user30408201
相关产品推荐
相关产品推荐

