Intel PIN工具内存访问值追踪:多内存访问相关技术问询
Intel PIN指令追踪工具内存访问插桩问题解答
你编写的内存访问插桩循环代码如下:
for(UINT32 memop_idx=0;memop_idx<memOperands;++memop_idx) { UINT32 op_idx=INS_MemoryOperandIndexToOperandIndex(ins,memop_idx); UINT32 scale = INS_OperandMemoryScale(ins,op_idx); INT32 disp = INS_OperandMemoryDisplacement(ins,op_idx); REG base_reg_full = REG_FullRegName(base_reg); REG index_reg_full= REG_FullRegName(index_reg); uint32_t op_header = OP_HEADER_MEM | (INS_MemoryOperandIsRead(ins,memop_idx)<<OP_HEADER_READ_SHIFT) | (INS_MemoryOperandIsWritten(ins,memop_idx)<<OP_HEADER_WRITE_SHIFT) | ((INS_RegWContain(ins,base_reg))<<OP_HEADER_BASE_UPDATE_SHIFT) | ((INS_RegWContain(ins,index_reg))<<OP_HEADER_INDEX_UPDATE_SHIFT) | ((REG_is_any_vector_reg(base_reg))<<OP_HEADER_BASE_VECTOR_SHIFT) | ((REG_is_any_vector_reg(index_reg))<<OP_HEADER_INDEX_VECTOR_SHIFT); INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)AddMemOp, IARG_UINT32,op_header, IARG_UINT32,base_reg, IARG_UINT32,index_reg, IARG_UINT32,base_reg_full, IARG_UINT32,index_reg_full, IARG_UINT32,scale, IARG_UINT32,disp, IARG_MULTI_MEMORYACCESS_EA, IARG_END); }
针对你提出的三个技术疑问,解答如下:
1. 如何避免重复处理已被IARG_MULTI_MEMORYACCESS_EA覆盖的操作数?
IARG_MULTI_MEMORYACCESS_EA会捕获指令所有内存访问(包括显式、隐式,以及gather/scatter的多元素访问),直接在循环中使用会导致重复处理。解决思路是拆分场景处理:
- 循环内只处理显式非多访问内存操作数:用
IARG_MEMORYOP_EA, memop_idx替代IARG_MULTI_MEMORYACCESS_EA,单独获取单个操作数的有效地址; - 单独处理两类特殊场景:
- 带隐式内存访问的指令(如
push/pop、字符串指令):通过INS_HasImplicitMemoryReference()判断,插入一次带IARG_MULTI_MEMORYACCESS_EA的调用处理隐式访问; - gather/scatter类向量指令:通过
INS_IsGatherScatter()判断,插入一次带IARG_MULTI_MEMORYACCESS_EA的调用,捕获所有向量元素的内存访问。
- 带隐式内存访问的指令(如
这样就能避免重复处理同一个内存操作数。
2. 仅隐式操作数会触发多内存访问?能否用INS_OperandIsImplicit识别?
这个结论不完全准确:
- 常规非向量指令中,确实只有带隐式内存操作数的指令会产生多内存访问(最多2个,比如
push同时修改栈指针和读写栈内存),这类隐式操作数可以用INS_OperandIsImplicit(op_idx)识别,它们是IARG_MULTI_MEMORYACCESS_EA额外处理的部分; - 但gather/scatter类向量指令是显式操作数但多访问,
INS_OperandIsImplicit返回false,但这类指令会一次性产生多个内存访问,同样需要IARG_MULTI_MEMORYACCESS_EA来捕获所有访问。
所以不能只靠INS_OperandIsImplicit覆盖所有IARG_MULTI_MEMORYACCESS_EA处理的场景。
3. gather/scatter指令能否不用IARG_MULTI_MEMORYACCESS_EA获取读写数值?
不行。gather/scatter指令的内存访问是运行时动态确定的:每个向量元素的地址由基址、索引寄存器中的动态值计算而来,静态插桩阶段无法预知所有访问的地址和数量。
IARG_MULTI_MEMORYACCESS_EA是PIN专门为这类指令设计的参数,它会在指令执行完成后,收集所有实际发生的内存访问的有效地址、读写数据等信息。如果不用它,你只能拿到基址、索引、比例等静态信息,无法获取每个元素实际读写的数值和对应地址。
内容的提问来源于stack exchange,提问作者Sai Aravind
相关产品推荐
相关产品推荐

