如何获取Pin中存储指令写入的值?

时间:2018-03-07 01:59:39

标签: c++ intel instrumentation intel-pin

我目前正在使用Pin,我想获得商店指令正在编写的值。我面临的问题是,即使我可以在写入指令之前插入一个回调(使用IPOINT_BEFORE)并从将要写入的内存地址中获取一个值,但显然这不是正确的,因为写入没有发生了。我不能同时使用IARG_MEMORYWRITE_EA和IPOINT_AFTER作为参数。

我已设法在有加载指令时使其工作,因为该值已在内存中。代码如下。

void Read(THREADID tid, ADDRINT addr, ADDRINT inst){

  PIN_GetLock(&globalLock, 1);

  ADDRINT * addr_ptr = (ADDRINT*)addr;
  ADDRINT value;
  PIN_SafeCopy(&value, addr_ptr, sizeof(ADDRINT));

  fprintf(stderr,"Read: ADDR, VAL: %lx, %lu\n", addr, value);

  .
  .
  .

  PIN_ReleaseLock(&globalLock);
}

VOID instrumentTrace(TRACE trace, VOID *v)
{

  for (BBL bbl = TRACE_BblHead(trace); BBL_Valid(bbl); bbl = BBL_Next(bbl)) {
    for (INS ins = BBL_InsHead(bbl); INS_Valid(ins); ins = INS_Next(ins)) {  
      if(INS_IsMemoryRead(ins)) {
      INS_InsertCall(ins, 
             IPOINT_BEFORE, 
             (AFUNPTR)Read, 
             IARG_THREAD_ID,
             IARG_MEMORYREAD_EA,
             IARG_INST_PTR,
             IARG_END);
      } else if(INS_IsMemoryWrite(ins)) {
      INS_InsertCall(ins, 
             IPOINT_BEFORE, 
             (AFUNPTR)Write, 
             IARG_THREAD_ID,//thread id
             IARG_MEMORYWRITE_EA,//address being accessed
             IARG_INST_PTR,//instruction address of write
             IARG_END);
      }
    }
  }
}

如何获取存储指令写入内存的值?

1 个答案:

答案 0 :(得分:1)

我想我设法做了我想做的事。获取值的方法是每次程序中都有一个存储时,我会保存它将写入的内存地址。然后我检测每一条指令并调用WriteData函数,它实际上从我之前保存的内存地址中获取数据,就像读取一样。

这是获取加载指令值的代码。

void Read(THREADID tid, ADDRINT addr, ADDRINT inst){

  PIN_GetLock(&globalLock, 1);

  ADDRINT * addr_ptr = (ADDRINT*)addr;
  ADDRINT value;
  PIN_SafeCopy(&value, addr_ptr, sizeof(ADDRINT));

  fprintf(stderr,"Read: ADDR, VAL: %lx, %lx\n", addr, value);    
  ...          
  PIN_ReleaseLock(&globalLock);
}

这是获取商店指令地址的代码。

void Write(THREADID tid, ADDRINT addr, ADDRINT inst ){    

  PIN_GetLock(&globalLock, 1); 

  writeaddr = addr;
  writecount++;    
  ...    
  PIN_ReleaseLock(&globalLock);
}

这是从上一个商店的地址获取数据的代码。

void WriteData(){ 

  PIN_GetLock(&globalLock, 1);

  //Reading from memory      
  if (writecount > 0){

    ADDRINT * addr_ptr = (ADDRINT*)writeaddr;
    ADDRINT value;
    PIN_SafeCopy(&value, addr_ptr, sizeof(ADDRINT));

    fprintf(stderr,"Write: ADDR, Value: %lx, %lx\n", writeaddr, value);  

    writecount--;
  }

  PIN_ReleaseLock(&globalLock);

}

但仍存在一个小问题。以下是我使用的微基准测试数据,之后是终端中的打印输出。

for (i = 0; i < MAX; i++) {
        a[i] = i;
  }

  for (i = 0; i < MAX; i++) {
        a[i] = a[i] + 1;
        b[i] = a[i];
  }

MAX为5。

Write: ADDR, Value: 601078, 6f
Read: ADDR, VAL: 7ffd0560de10, 40051b
Write: ADDR, Value: 601080, 0
Write: ADDR, Value: 601084, 1
Write: ADDR, Value: 601088, 2
Write: ADDR, Value: 60108c, 3
Write: ADDR, Value: 601090, 4
Read: ADDR, VAL: 601080, 100000000
Write: ADDR, Value: 601080, 100000001
Write: ADDR, Value: 601060, 1
Read: ADDR, VAL: 601084, 200000001
Write: ADDR, Value: 601084, 200000002
Write: ADDR, Value: 601064, 2
Read: ADDR, VAL: 601088, 300000002
Write: ADDR, Value: 601088, 300000003
Write: ADDR, Value: 601068, 3
Read: ADDR, VAL: 60108c, 400000003
Write: ADDR, Value: 60108c, 400000004
Write: ADDR, Value: 60106c, 4
Read: ADDR, VAL: 601090, 4
Write: ADDR, Value: 601090, 5
Write: ADDR, Value: 601070, 5

从我们在终端中看到的,似乎第一次写入[i],按预期发生。但是,当程序读取相同的地址而不是获得1,2等时,它会获得100000001,依此类推。它正确地将它们递增1.但是当它们将它们存储到b [i]时,值再次正确。所以我想知道为什么我会从读取数据中遇到这种行为。