X64平台编译时获取代码标签地址的实现方法咨询
针对你在X64平台适配代码完整性校验时遇到的「编译阶段获取代码标签地址」这个核心问题,结合你之前用MSVC开发Win32程序的背景,我整理了几个实用的解决方案,刚好能解决你的痛点:
方案1:使用MSVC内置的__label__关键字(最贴合原有逻辑)
X64下MSVC虽然砍掉了内联汇编,但提供了__label__关键字来在函数内定义标签,并且可以用&&运算符直接获取标签的编译时绝对地址。你可以把原来的宏改成__forceinline函数,结合这个特性无缝迁移:
// 替换原来的宏,改成__forceinline函数 __forceinline void AsmCrcCodeMrk(void* DescriptorAddr, void* StartAddr, void* EndAddr, int Id, void* BPA) { // 这里可以保留或调整你的CRC校验触发逻辑,核心是接收编译时确定的地址参数 } // 实际使用示例 void YourProcedure() { __label__ codemark1_start, codemark1_end; codemark1_start: // 你需要校验的代码片段 <Some code> codemark1_end: // 直接传入编译时解析的标签地址,完全符合你的需求 AsmCrcCodeMrk(MyTinyBuff, &&codemark1_start, &&codemark1_end, 1, &YourProcedure); }
这个方法几乎不需要改动原有的代码结构,原来的标签定义方式完全保留,只是把内联汇编里的地址获取逻辑换成了编译器原生支持的语法,迁移成本极低。
方案2:利用自定义代码段(适合批量校验场景)
如果你的完整性校验是针对多个固定代码块,也可以把需要校验的代码放到自定义段中,通过段的起始/结束符号来获取编译时地址:
首先定义自定义代码段:
#pragma section("MY_CHECK_SEG", read, execute) #define CHECK_SEG __declspec(allocate("MY_CHECK_SEG"))
然后把需要校验的代码放到这个段里:
CHECK_SEG void CodeBlockToVerify() { // 你需要校验的代码逻辑 <Some code> }
接着通过链接器自动生成的段符号获取地址:
extern "C" { extern void* _MY_CHECK_SEG_start; extern void* _MY_CHECK_SEG_end; } // 调用校验函数 AsmCrcCodeMrk(MyTinyBuff, &_MY_CHECK_SEG_start, &_MY_CHECK_SEG_end, 1, &CodeBlockToVerify);
这个方法适合批量管理需要校验的代码块,但需要调整代码的组织结构,灵活性不如标签方式。
补充说明
- 如果你用的是GCC/Clang的X64环境,语法会更简单:不需要
__label__关键字,直接在函数内定义标签后用&&label即可获取地址。 - 无论用哪种方法,记得确保你的CRC计算工具能正确识别这些编译时生成的地址,和Win32下的校验逻辑做好兼容。
内容的提问来源于stack exchange,提问作者Ilya Sokolov
相关产品推荐
相关产品推荐

