Using IARG_MEMORYREAD_EA with PIN_SafeCopy

Type of IARG_MEMORYREAD_EA is defined as ADDRINT in PIN. I need to fetch a piece of data stored in IARG_MEMORYREAD_EA location of memory. As far as I understand the most proper way to fetch data from a specific address location is using PIN_SafeCopy function whose example usage is as following:

ADDRINT DoLoad(REG reg, ADDRINT * addr)
{
    *out << "Emulate loading from addr " << addr << " to " << REG_StringShort(reg) << endl;
    ADDRINT value;
    PIN_SafeCopy(&value, addr, sizeof(ADDRINT));
    return value;
}

when I try to pass IARG_MEMORYREAD_EA directly to this function, compiler says that the types are not matching, (ADDRINT * and ADDRINT). Obviously they don't but I couldn't be sure how should I use this function.

My current code is as the following:

INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)ProcessMemIns,
 IARG_CONTEXT,
 IARG_INST_PTR,
 IARG_MEMORYREAD_EA,
 IARG_MEMORYREAD2_EA,
 IARG_MEMORYREAD_SIZE,
 IARG_MEMORYWRITE_EA,
 IARG_MEMORYWRITE_SIZE,
 IARG_BOOL, INS_IsBranchOrCall(ins),
 IARG_BRANCH_TAKEN,
 IARG_UINT32,  INS_Category(ins),
 IARG_UINT32, INS_RegR(ins, 0),
 IARG_UINT32, INS_RegR(ins, 1),
 IARG_UINT32, INS_RegR(ins, 2),
 IARG_UINT32, INS_RegR(ins, 3),
 IARG_UINT32, INS_RegW(ins, 0),
 IARG_UINT32, INS_RegW(ins, 1),
 IARG_UINT32, INS_RegW(ins, 2),
 IARG_UINT32, INS_RegW(ins, 3),
 IARG_END);

and ProcessMemIns is:

VOID ProcessMemIns(
    CONTEXT * context,
    ADDRINT ip,
    ADDRINT raddr, ADDRINT raddr2, UINT32 rlen,
    ADDRINT waddr, UINT32  wlen,
    BOOL    isbranch,
    BOOL    isbranchtaken,
    UINT32  category,
    UINT32  rr0,
    UINT32  rr1,
    UINT32  rr2,
    UINT32  rr3,
    UINT32  rw0,
    UINT32  rw1,
    UINT32  rw2,
    UINT32  rw3)
{ // for memory address and register index, '0' means invalid
  if (pthreadsim->first_instrs < pthreadsim->skip_first)
  {
    pthreadsim->first_instrs++;
    return;
  }
  else if (pthreadsim->first_instrs == pthreadsim->skip_first)
  {
    pthreadsim->first_instrs++;
    pthreadsim->initiate(context);
  }

  /* Log for addresses and data */
  uint64_t data1 = -1, data2 = -1, data3 = -1;
  if (raddr > 0) {
    PIN_SafeCopy(&data1, raddr , sizeof(uint64_t));
    cout << "1A:" << hex << raddr << ",D:" << hex << data1 << endl;
  } 
  if (raddr2 > 0) {
    PIN_SafeCopy(&data1, raddr2 , sizeof(uint64_t));
    cout << "2A:" << hex << raddr2 << ",D:" << hex << data2 << endl;
  } 
  if (waddr > 0) {
    PIN_SafeCopy(&data1, waddr , sizeof(uint64_t));
    cout << "3A:" << hex << waddr << ",D:" << hex << data3 << endl;
  } 

  pthreadsim->process_ins(
    context,
    ip,
    raddr, raddr2, rlen,
    waddr,         wlen,
    isbranch,
    isbranchtaken,
    category,
    rr0, rr1, rr2, rr3,
    rw0, rw1, rw2, rw3);
}

As it is expected, I'm getting the following error message from compiler. invalid conversion from ‘LEVEL_BASE::ADDRINT {aka long unsigned int}’ to ‘const VOID* {aka const void*}’ [-fpermissive]

Is there a more proper way to use IARG_MEMORYREAD_EA for PIN_SafeCopy() or should I just define a pointer and use it for PIN_SafeCopy()?

Upvotes: 3

Views: 1091

Answers (1)

Neitsa
Neitsa

Reputation: 8176

The Intel PIN documentation states that IARG_MEMORYREAD_EA is an ADDRINT, although I do agree that the example with PIN_SafeCopy strangely uses ADDRINT*...

OTOH, an ADDRINT is a type that represents an address and in the case of IARG_MEMORYREAD_EA we know this is the effective address of a memory read (so, in the vast majority of cases, the ADDRINT is a valid pointer).

For DoLoad() I'd replace the ADDRINT* by just an ADDRINT.

For PIN_SafeCopy I'd cast the ADDRINT to void*, either by a C-style cast or reinterpet_cast<>: you already know it's a pointer but it's of the wrong type, and this why cast are for.

Upvotes: 3

Related Questions