Intel PIN插桩malloc时RTN_InsertCall在特定位置缺失的问题
问题场景
测试Intel PIN的malloctrace示例时,使用以下测试二进制源码:
int main() { char *buf = malloc(sizeof(char)*50); //printf("Buf addr: %p\n", buf); // sanity check char *bar_buf = malloc(sizeof(char)*50); //printf("Bar_buf addr: %p\n", bar_buf); // sanity check free(buf); free(bar_buf); }
执行后输出如下:
...
malloc(0x32) <- first malloc
malloc(0x32) <- second malloc
returns 0x55cb2b4222e0
free(0x55cb2b4222a0) <- free of first malloc
free(0x55cb2b4222e0) <- free of second malloc
首次malloc的返回地址未输出,预期该返回值应为free(buf)传入的0x55cb2b4222a0,经排查确认是Intel PIN无法找到首次malloc后的正确插桩点导致。
解决方案
1. 改用函数返回探针插桩返回值
原malloctrace示例可能使用RTN_InsertCall在函数返回前插桩,这种方式在某些代码路径下可能遗漏首次调用的返回点。改用PIN_AddFunctionReturnProbe注册返回探针,确保每个malloc调用的返回值都被捕获:
修改malloctrace工具的插桩逻辑,在ImageLoad函数中处理malloc的RTN时:
RTN rtn = RTN_FindByName(image, "malloc"); if (RTN_Valid(rtn)) { RTN_Open(rtn); // 插桩函数入口,记录malloc的参数 RTN_InsertCall(rtn, IPOINT_BEFORE, (AFUNPTR)RecordMallocArg, IARG_FUNCARG_ENTRYPOINT_VALUE, 0, IARG_END); // 注册返回探针,捕获返回值 PIN_AddFunctionReturnProbe(rtn, (AFUNPTR)RecordMallocReturn, IARG_END); RTN_Close(rtn); }
实现对应的记录函数:
VOID RecordMallocArg(ADDRINT size) { printf("malloc(0x%x) <- %s malloc\n", (UINT32)size, (PIN_GetTid() == g_firstTid) ? "first" : "second"); } VOID RecordMallocReturn(ADDRINT ret_val) { printf(" returns %p\n", (void*)ret_val); }
2. 禁用测试二进制的编译器优化
编译测试代码时如果开启了优化(如-O2),编译器可能会对首次malloc的调用做指令重排或合并,导致PIN无法识别插桩点。编译时添加-O0参数禁用优化:
gcc -O0 test.c -o test
3. 验证PIN版本与环境兼容性
部分旧版本PIN在处理特定编译器生成的代码时存在兼容性问题,确保使用最新稳定版的PIN,且PIN的架构(x86/x86_64)与测试环境、编译的二进制一致。
验证效果
修改后重新执行PIN工具,输出应包含两个malloc的返回地址:
malloc(0x32) <- first malloc
returns 0x55cb2b4222a0
malloc(0x32) <- second malloc
returns 0x55cb2b4222e0
free(0x55cb2b4222a0) <- free of first malloc
free(0x55cb2b4222e0) <- free of second malloc
内容的提问来源于stack exchange,提问作者Jay

