如何验证Intel PinTool中原始程序代码是否运行在Code Cache中?
验证Intel PinTool中代码是否运行在Code Cache的方法
问题背景
你尝试用以下代码获取当前指令地址,以此判断代码是否运行在Pin的Code Cache中:
#include <iostream> _declspec(naked) int f() { _asm { call $ + 5 pop eax ret } } int main() { std::cout << std::hex << "curIp " << f() << std::endl; return 0; }
32位编译后,无论是否用Pin追踪,返回的地址都是0x401025,这和预期的"Code Cache地址与原程序地址不同"不符,用异常相关代码验证也得到相同结果。
原因分析
Pin为了保证目标程序的兼容性,实现了透明地址重定向:它会把Code Cache中的指令地址映射回原程序的虚拟地址空间,所以通过常规的取IP指令(比如call $+5)得到的始终是原程序的地址,无法直接区分是否在Code Cache中执行。
正确验证方法
方法1:使用Pin内置API直接判断
Pin提供了PIN_IsCodeCacheAddress()函数,可直接传入当前指令地址,判断该地址是否属于Code Cache:
#include "pin.H" #include <iostream> VOID InsExecute(INS ins, VOID* v) { ADDRINT ip = INS_Address(ins); BOOL is_in_cc = PIN_IsCodeCacheAddress(ip); std::cout << std::hex << "IP: 0x" << ip << ", In Code Cache: " << (is_in_cc ? "Yes" : "No") << std::endl; } int main(int argc, char* argv[]) { PIN_Init(argc, argv); INS_AddInstrumentFunction(InsExecute, 0); PIN_StartProgram(); return 0; }
编译这个PinTool并运行目标程序,就能看到每条指令是否在Code Cache中执行。
方法2:检查内存页属性
Code Cache的内存页属性和原程序代码段不同:
- 原程序代码段通常是只读+可执行(PAGE_EXECUTE_READ)
- Pin的Code Cache内存是可写+可执行(PAGE_EXECUTE_READWRITE),因为需要动态生成和修改指令
可以用PIN_GetPhysicalMemoryProtection()或系统API获取当前IP所在页的属性,对比判断:
#include "pin.H" #include <iostream> #include <windows.h> // Windows平台适用,Linux替换为sys/mman.h VOID InsExecute(INS ins, VOID* v) { ADDRINT ip = INS_Address(ins); MEMORY_BASIC_INFORMATION mbi; VirtualQuery((LPCVOID)ip, &mbi, sizeof(mbi)); std::cout << std::hex << "IP: 0x" << ip << ", Protect: 0x" << mbi.Protect << ", In Code Cache: " << ((mbi.Protect & PAGE_EXECUTE_READWRITE) ? "Yes" : "No") << std::endl; } int main(int argc, char* argv[]) { PIN_Init(argc, argv); INS_AddInstrumentFunction(InsExecute, 0); PIN_StartProgram(); return 0; }
内容的提问来源于stack exchange,提问作者sbb
相关产品推荐
相关产品推荐

