// Pin calls this function every time a new instruction is encountered VOID Inst(INS ins, VOID *v) { ADDRINT pc = INS_Address (ins); if ( pc == StartAddr ) RecordFlag = true; if ( pc == EndAddr ) RecordFlag = false; if ( RecordFlag && pc < 0x01000000 ) { if ( MinAddr > pc ) MinAddr = pc; if ( MaxAddr < pc ) MaxAddr = pc; INS_InsertCall( ins, IPOINT_BEFORE, (AFUNPTR)profile_code, IARG_INST_PTR, IARG_END ); if (INS_IsMemoryWrite(ins)) INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(profile_mem_write), IARG_INST_PTR, IARG_END); if ( INS_HasMemoryRead2(ins) ) INS_InsertPredicatedCall(ins, IPOINT_BEFORE, AFUNPTR(profile_mem_read), IARG_INST_PTR, IARG_END); if ( INS_IsMemoryRead(ins) ) INS_InsertPredicatedCall(ins, IPOINT_BEFORE, AFUNPTR(profile_mem_read), IARG_INST_PTR, IARG_END); } }
// Is called for every instruction and instruments reads and writes VOID Instruction(INS ins, VOID *v) { // Instruments memory accesses using a predicated call, i.e. // the instrumentation is called iff the instruction will actually be executed. // // On the IA-32 and Intel(R) 64 architectures conditional moves and REP // prefixed instructions appear as predicated instructions in Pin. UINT32 memOperands = INS_MemoryOperandCount(ins); // Iterate over each memory operand of the instruction. for (UINT32 memOp = 0; memOp < memOperands; memOp++) { if (INS_MemoryOperandIsRead(ins, memOp)) { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR)RecordMemRead, IARG_INST_PTR, IARG_MEMORYOP_EA, memOp, IARG_END); } // Note that in some architectures a single memory operand can be // both read and written (for instance incl (%eax) on IA-32) // In that case we instrument it once for read and once for write. if (INS_MemoryOperandIsWritten(ins, memOp)) { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR)RecordMemWrite, IARG_INST_PTR, IARG_MEMORYOP_EA, memOp, IARG_END); } } }
static void Instruction(INS ins, void *v) { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR)do_count, IARG_END); // Filters out non memory reference instructions. if (!INS_IsMemoryRead(ins) && !INS_IsMemoryWrite(ins)) return; // Filters out references to stack. if (INS_IsStackRead(ins) || INS_IsStackWrite(ins)) return; // Filters out instructions out of main executable. IMG img = IMG_FindByAddress(INS_Address(ins)); if (!IMG_Valid(img) || !IMG_IsMainExecutable(img)) return; unsigned i; unsigned int mem_op = INS_MemoryOperandCount(ins); for (i = 0; i < mem_op; i++) { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR)check_addr, IARG_INST_PTR, IARG_MEMORYOP_EA, i, IARG_END); } }
VOID Instruction(INS ins, VOID * v) { if(INS_IsMemoryWrite(ins)) { INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(CaptureWriteEa), IARG_THREAD_ID, IARG_MEMORYWRITE_EA, IARG_END); if(INS_HasFallThrough(ins)) { INS_InsertPredicatedCall(ins, IPOINT_AFTER, AFUNPTR(EmitWrite), IARG_THREAD_ID, IARG_MEMORYWRITE_SIZE, IARG_END); } if(INS_IsBranchOrCall(ins)) { INS_InsertPredicatedCall(ins, IPOINT_TAKEN_BRANCH, AFUNPTR(EmitWrite), IARG_THREAD_ID, IARG_MEMORYWRITE_SIZE, IARG_END); } } UINT32 memOperands = INS_MemoryOperandCount(ins); int write_operands = 0; for(UINT32 memOp = 0; memOp < memOperands; memOp++) { if(INS_MemoryOperandIsWritten(ins, memOp)) { write_operands++; } } assert(write_operands <= 1); }
// Is called for every instruction and instruments reads and writes VOID Instruction(INS ins, VOID *v) { // Insert a call to docount before every instruction, no arguments are passed INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)docount,IARG_THREAD_ID, IARG_END); // instruments loads using a predicated call, i.e. // the call happens iff the load will be actually executed // (this does not matter for ia32 but arm and ipf have predicated instructions) if (INS_IsMemoryRead(ins)) { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR)RecordMemRead, IARG_INST_PTR, IARG_MEMORYREAD_EA, IARG_THREAD_ID, IARG_END); } // instruments stores using a predicated call, i.e. // the call happens iff the store will be actually executed if (INS_IsMemoryWrite(ins)) { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR)RecordMemWrite, IARG_INST_PTR, IARG_MEMORYWRITE_EA, IARG_THREAD_ID, IARG_END); } }
LOCALFUN VOID Instruction(INS ins, void * v) { if (INS_IsMemoryRead(ins)) { const UINT32 size = INS_MemoryReadSize(ins); // we assume accesses <= 4 bytes stay in the same cache line // to speed up cache access lookups const AFUNPTR countFun = (size <= 4 ? (AFUNPTR) MemRefSingle : (AFUNPTR) MemRefMulti); // only predicated-on memory instructions access D-cache INS_InsertPredicatedCall( ins, IPOINT_BEFORE, countFun, IARG_UINT32, CACHE_BASE::ACCESS_TYPE_LOAD, IARG_MEMORYREAD_EA, IARG_MEMORYREAD_SIZE, IARG_END); } if (INS_IsMemoryWrite(ins)) { const UINT32 size = INS_MemoryWriteSize(ins); const AFUNPTR countFun = (size <= 4 ? (AFUNPTR) MemRefSingle : (AFUNPTR) MemRefMulti); // only predicated-on memory instructions access D-cache INS_InsertPredicatedCall( ins, IPOINT_BEFORE, countFun, IARG_UINT32, CACHE_BASE::ACCESS_TYPE_STORE, IARG_MEMORYWRITE_EA, IARG_MEMORYWRITE_SIZE, IARG_END); } }
VOID Instruction(INS ins, VOID *v) { // instruments loads using a predicated call, i.e. // the call happens iff the load will be actually executed if (INS_IsMemoryRead(ins)) { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR)RecordMem, IARG_INST_PTR, IARG_UINT32, 'R', IARG_MEMORYREAD_EA, IARG_MEMORYREAD_SIZE, IARG_UINT32, INS_IsPrefetch(ins), IARG_END); } if (INS_HasMemoryRead2(ins)) { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR)RecordMem, IARG_INST_PTR, IARG_UINT32, 'R', IARG_MEMORYREAD2_EA, IARG_MEMORYREAD_SIZE, IARG_UINT32, INS_IsPrefetch(ins), IARG_END); } // instruments stores using a predicated call, i.e. // the call happens iff the store will be actually executed if (INS_IsMemoryWrite(ins)) { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR)RecordWriteAddrSize, IARG_MEMORYWRITE_EA, IARG_MEMORYWRITE_SIZE, IARG_END); if (INS_HasFallThrough(ins)) { INS_InsertCall( ins, IPOINT_AFTER, (AFUNPTR)RecordMemWrite, IARG_INST_PTR, IARG_END); } if (INS_IsBranchOrCall(ins)) { INS_InsertCall( ins, IPOINT_TAKEN_BRANCH, (AFUNPTR)RecordMemWrite, IARG_INST_PTR, IARG_END); } } }
VOID PvxHandleInstruction(INS ins) { if(INS_IsMemoryWrite(ins)) { INS_InsertPredicatedCall(ins, IPOINT_BEFORE, (AFUNPTR) PvxHandleMemoryWrite, IARG_INST_PTR, IARG_MEMORYWRITE_EA, IARG_MEMORYWRITE_SIZE, IARG_END); } if(INS_IsBranchOrCall(ins)) { INS_InsertPredicatedCall(ins, IPOINT_BEFORE, (AFUNPTR) PvxHandleBranch, IARG_INST_PTR, IARG_BRANCH_TARGET_ADDR, IARG_END); } }
/* ===================================================================== */ VOID Instruction(INS ins, void * v) { if (INS_IsMemoryRead(ins)) { // map sparse INS addresses to dense IDs const UINT32 size = INS_MemoryReadSize(ins); const BOOL single = (size <= 4); if( single ) { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR) LoadSingle, IARG_MEMORYREAD_EA, IARG_END); } else { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR) LoadMulti, IARG_MEMORYREAD_EA, IARG_MEMORYREAD_SIZE, IARG_END); } } if ( INS_IsMemoryWrite(ins) ) { // map sparse INS addresses to dense IDs const UINT32 size = INS_MemoryWriteSize(ins); const BOOL single = (size <= 4); if( single ) { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR) StoreSingle, IARG_MEMORYWRITE_EA, IARG_END); } else { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR) StoreMulti, IARG_MEMORYWRITE_EA, IARG_MEMORYWRITE_SIZE, IARG_END); } } }
VOID Instruction(INS ins, VOID *v) { // instruments stores using a predicated call, i.e. // the call happens iff the store will be actually executed if (INS_IsMemoryWrite(ins)) { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR)RecordWriteAddrSize, IARG_MEMORYWRITE_EA, IARG_MEMORYWRITE_SIZE, IARG_INST_PTR, IARG_END); #if 0 if (INS_HasFallThrough(ins)) { INS_InsertCall( ins, IPOINT_AFTER, (AFUNPTR)RecordMemWrite, IARG_INST_PTR, IARG_END); } if (INS_IsBranchOrCall(ins)) { INS_InsertCall( ins, IPOINT_TAKEN_BRANCH, (AFUNPTR)RecordMemWrite, IARG_INST_PTR, IARG_END); } #endif } }
static VOID instrument_instruction(INS ins, VOID *v) { UINT32 memops = INS_MemoryOperandCount(ins); for (UINT32 memop = 0; memop < memops; memop++) { if (INS_MemoryOperandIsRead(ins, memop)) { INS_InsertPredicatedCall(ins, IPOINT_BEFORE, (AFUNPTR)rec_memread, IARG_INST_PTR, IARG_MEMORYOP_EA, memop, IARG_END); } if (INS_MemoryOperandIsWritten(ins, memop)) { INS_InsertPredicatedCall(ins, IPOINT_BEFORE, (AFUNPTR)rec_memwrite, IARG_INST_PTR, IARG_MEMORYOP_EA, memop, IARG_END); } } }
void Instruction(INS ins, VOID *v){ if(INS_IsMemoryWrite(ins)){ INS_InsertPredicatedCall( ins, IPOINT_BEFORE, AFUNPTR(RecordMemWrite), IARG_INST_PTR,IARG_MEMORYWRITE_EA,IARG_MEMORYWRITE_SIZE, IARG_END); } }
// determines whether or not the instruction is a call VOID Instruction(INS ins, VOID *v) { if (INS_IsCall(ins)) { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR)RecordCall, IARG_INST_PTR, IARG_BRANCH_TARGET_ADDR, IARG_END); } }
VOID Instruction(INS ins, VOID *v) { UINT32 memOperands = INS_MemoryOperandCount(ins); for (UINT32 memOp = 0; memOp < memOperands; memOp++) { if (INS_MemoryOperandIsWritten(ins, memOp)) { INS_InsertPredicatedCall(ins, IPOINT_BEFORE, (AFUNPTR)RecordMemWrite, IARG_INST_PTR, IARG_MEMORYOP_EA, memOp, IARG_END); } } }
VOID Routine(RTN rtn, VOID *v) { std::string name = PIN_UndecorateSymbolName(RTN_Name(rtn).c_str(), UNDECORATION_NAME_ONLY); std::vector<std::string>::iterator it; for (it = userFuncs.begin(); it != userFuncs.end(); ++it) { std::string userFunc = *it; if (name.find(userFunc) == std::string::npos) continue; RTN_Open(rtn); // For each instruction of the routine for (INS ins = RTN_InsHead(rtn); INS_Valid(ins); ins = INS_Next(ins)) { UINT32 memOperands = INS_MemoryOperandCount(ins); // Iterate over each memory operand of the instruction. for (UINT32 memOp = 0; memOp < memOperands; memOp++) { if (INS_IsStackRead(ins) || INS_IsStackWrite(ins)) break; if (INS_MemoryOperandIsRead(ins, memOp)) { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR)RecordMemRead, IARG_INST_PTR, IARG_MEMORYOP_EA, memOp, IARG_THREAD_ID, IARG_END); } if (INS_MemoryOperandIsWritten(ins, memOp)) { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR)RecordMemWrite, IARG_INST_PTR, IARG_MEMORYOP_EA, memOp, IARG_THREAD_ID, IARG_END); } } } RTN_Close(rtn); } }
VOID CheckMagicValue(INS ins, VOID *v) { UINT32 memOperands = INS_MemoryOperandCount(ins); for (UINT32 memOp = 0; memOp < memOperands; memOp++) { if (INS_MemoryOperandIsRead(ins, memOp)) { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR)CheckMagicOnRead, IARG_INST_PTR, IARG_MEMORYOP_EA, memOp, IARG_END ); } if (INS_MemoryOperandIsWritten(ins, memOp)) { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR)CheckMagicOnWrite, IARG_INST_PTR, IARG_MEMORYOP_EA, memOp, IARG_END ); } } }
LOCALFUN VOID Instruction(INS ins, VOID *v) { // all instruction fetches access I-cache INS_InsertCall( ins, IPOINT_BEFORE, (AFUNPTR)InsRef, IARG_INST_PTR, IARG_END); if (INS_IsMemoryRead(ins)) { const UINT32 size = INS_MemoryReadSize(ins); const AFUNPTR countFun = (size <= 4 ? (AFUNPTR) MemRefSingle : (AFUNPTR) MemRefMulti); // only predicated-on memory instructions access D-cache INS_InsertPredicatedCall( ins, IPOINT_BEFORE, countFun, IARG_MEMORYREAD_EA, IARG_MEMORYREAD_SIZE, IARG_UINT32, CACHE_BASE::ACCESS_TYPE_LOAD, IARG_END); } if (INS_IsMemoryWrite(ins)) { const UINT32 size = INS_MemoryWriteSize(ins); const AFUNPTR countFun = (size <= 4 ? (AFUNPTR) MemRefSingle : (AFUNPTR) MemRefMulti); // only predicated-on memory instructions access D-cache INS_InsertPredicatedCall( ins, IPOINT_BEFORE, countFun, IARG_MEMORYWRITE_EA, IARG_MEMORYWRITE_SIZE, IARG_UINT32, CACHE_BASE::ACCESS_TYPE_STORE, IARG_END); } }
void processMemoryReadInstruction(INS ins, const char* imageName) { UINT32 memoryOperandCount = INS_MemoryOperandCount(ins); for (UINT32 i = 0; i < memoryOperandCount; ++i) { if (INS_MemoryOperandIsRead(ins, i)) { INS_InsertPredicatedCall(ins, IPOINT_BEFORE, (AFUNPTR) Read, IARG_THREAD_ID, IARG_MEMORYOP_EA, i, IARG_REG_VALUE, REG_STACK_PTR, //pass current stack ptr IARG_PTR, imageName, IARG_INST_PTR, IARG_MEMORYWRITE_SIZE, IARG_CALL_ORDER, CALL_ORDER_FIRST + 30, IARG_END); } } }
void instruction (INS ins, void *v) { if (INS_IsMemoryRead(ins)) { INS_InsertPredicatedCall(ins, IPOINT_BEFORE, AFUNPTR(on_load), IARG_THREAD_ID, IARG_INST_PTR, IARG_MEMORYREAD_EA, IARG_MEMORYREAD_SIZE, IARG_ADDRINT, INS_Opcode(ins), IARG_END); } if (INS_HasMemoryRead2(ins)) { INS_InsertPredicatedCall(ins, IPOINT_BEFORE, AFUNPTR(on_load), IARG_THREAD_ID, IARG_INST_PTR, IARG_MEMORYREAD2_EA, IARG_MEMORYREAD_SIZE, IARG_ADDRINT, INS_Opcode(ins), IARG_END); } if (INS_IsMemoryWrite(ins)) { //TODO get value. see SimpleExamples/pinatrace.cpp INS_InsertPredicatedCall(ins, IPOINT_BEFORE, AFUNPTR(on_store), IARG_THREAD_ID, IARG_INST_PTR, IARG_MEMORYWRITE_EA, IARG_MEMORYWRITE_SIZE, IARG_ADDRINT, INS_Opcode(ins), IARG_END); } }
VOID Instruction(INS ins, VOID *v) { INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)UseToolStack, IARG_END); // This is added for regression testing // (when executed with win_divide_by_zero_exception application) // multiple instrumentations of branch taken for(int i = 0; i < 10; i++) { if (INS_IsBranchOrCall(ins)) { INS_InsertPredicatedCall(ins, IPOINT_TAKEN_BRANCH, (AFUNPTR)UseToolStack, IARG_END); } } }
// Is called for every instruction and instruments reads and writes VOID Instruction(INS ins, VOID *v) { // Instruments memory accesses using a predicated call, i.e. // the instrumentation is called iff the instruction will actually be executed. // // On the IA-32 and Intel(R) 64 architectures conditional moves and REP // prefixed instructions appear as predicated instructions in Pin. UINT32 memOperands = INS_MemoryOperandCount(ins); // Iterate over each memory operand of the instruction. for (UINT32 memOp = 0; memOp < memOperands; memOp++) { /*if (INS_MemoryOperandIsRead(ins, memOp)) { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR)RecordMemRead, IARG_INST_PTR, IARG_MEMORYOP_EA, memOp, IARG_END); }*/ // Note that in some architectures a single memory operand can be // both read and written (for instance incl (%eax) on IA-32) // In that case we instrument it once for read and once for write. if (INS_MemoryOperandIsWritten(ins, memOp)) { xed_decoded_inst_t* xedd = INS_XedDec(ins); xed_syntax_enum_t syntax = XED_SYNTAX_INTEL; // XED_SYNTAX_ATT, XED_SYNTAX_XED const UINT32 BUFLEN = 100; //char buffer[BUFLEN]; ADDRINT addr = INS_Address(ins); BOOL ok = xed_format(syntax, xedd, writeInstruction, BUFLEN, static_cast<UINT64>(addr)); if (ok){ } INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR)RecordMemWrite, IARG_INST_PTR, IARG_MEMORYOP_EA, memOp, IARG_END); } } }
VOID Trace(TRACE trace, VOID *v) { if ( KnobNoSharedLibs.Value() && IMG_Type(SEC_Img(RTN_Sec(TRACE_Rtn(trace)))) == IMG_TYPE_SHAREDLIB) return; const BOOL accurate_handling_of_predicates = KnobProfilePredicated.Value(); for (BBL bbl = TRACE_BblHead(trace); BBL_Valid(bbl); bbl = BBL_Next(bbl)) { // Summarize the stats for the bbl in a 0 terminated list // This is done at instrumentation time UINT16 * stats = new UINT16[BBL_NumIns(bbl) + 1]; INT32 index = 0; for (INS ins = BBL_InsHead(bbl); INS_Valid(ins); ins = INS_Next(ins)) { // Count the number of times a predicated instruction is actually executed // this is expensive and hence disabled by default if( INS_IsPredicated(ins) && accurate_handling_of_predicates ) { INS_InsertPredicatedCall(ins, IPOINT_BEFORE, AFUNPTR(docount), IARG_PTR, &(GlobalStatsDynamic.predicated_true[INS_Category(ins)]), IARG_END); } stats[index++] = INS_GetStatsIndex(ins); } stats[index] = 0; // Insert instrumentation to count the number of times the bbl is executed BBLSTATS * bblstats = new BBLSTATS(stats); INS_InsertCall(BBL_InsHead(bbl), IPOINT_BEFORE, AFUNPTR(docount), IARG_PTR, &(bblstats->_counter), IARG_END); // Remember the counter and stats so we can compute a summary at the end statsList.push_back(bblstats); } }
VOID Instruction(INS ins, void * v) { UINT32 memOperands = INS_MemoryOperandCount(ins); // Instrument each memory operand. If the operand is both read and written // it will be processed twice. // Iterating over memory operands ensures that instructions on IA-32 with // two read operands (such as SCAS and CMPS) are correctly handled. for (UINT32 memOp = 0; memOp < memOperands; memOp++) { const UINT32 size = INS_MemoryOperandSize(ins, memOp); const BOOL single = (size <= 4); if (INS_MemoryOperandIsRead(ins, memOp)) { if( KnobTrackLoads ) { // map sparse INS addresses to dense IDs const ADDRINT iaddr = INS_Address(ins); const UINT32 instId = profile.Map(iaddr); if( single ) { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR) LoadSingle, IARG_MEMORYOP_EA, memOp, IARG_UINT32, instId, IARG_END); } else { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR) LoadMulti, IARG_MEMORYOP_EA, memOp, IARG_UINT32, size, IARG_UINT32, instId, IARG_END); } } else { if( single ) { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR) LoadSingleFast, IARG_MEMORYOP_EA, memOp, IARG_END); } else { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR) LoadMultiFast, IARG_MEMORYOP_EA, memOp, IARG_UINT32, size, IARG_END); } } } if (INS_MemoryOperandIsWritten(ins, memOp)) { if( KnobTrackStores ) { const ADDRINT iaddr = INS_Address(ins); const UINT32 instId = profile.Map(iaddr); if( single ) { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR) StoreSingle, IARG_MEMORYOP_EA, memOp, IARG_UINT32, instId, IARG_END); } else { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR) StoreMulti, IARG_MEMORYOP_EA,memOp, IARG_UINT32, size, IARG_UINT32, instId, IARG_END); } } else { if( single ) { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR) StoreSingleFast, IARG_MEMORYOP_EA, memOp, IARG_END); } else { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR) StoreMultiFast, IARG_MEMORYOP_EA, memOp, IARG_UINT32, size, IARG_END); } } } } }
VOID instruction(INS ins, void *v) { UINT32 numOperands = INS_OperandCount(ins); int numOpMems = 0; for (unsigned int i = 0; i < numOperands; i++) { //check number of reads and writes if (INS_OperandIsMemory(ins, i)) numOpMems++; } if (numOpMems > 2) { std::cout << "number of operands = " << numOpMems << std::endl; } const ADDRINT iaddr = INS_Address(ins); UINT32 idx; struct PC item; item.refs = 0; item.miss = 0; item.pc = iaddr; iCachePC.push_back(item); idx = iCachePC.size() - 1; INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR) iCacheCount, IARG_ADDRINT, iaddr, IARG_UINT32, idx, IARG_END); if (INS_IsMemoryRead(ins)) { struct PC readItem; readItem.refs = 0; readItem.miss = 0; readItem.pc = iaddr; readItem.isLoad = 1; dCachePC.push_back(readItem); UINT32 idx2 = dCachePC.size()-1; INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR) dCacheCount, IARG_ADDRINT, iaddr, IARG_MEMORYREAD_EA, IARG_MEMORYREAD_SIZE, IARG_UINT32, idx2, IARG_UINT32, 1, IARG_UINT32, 0, IARG_END); if (INS_HasMemoryRead2(ins)) { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR) dCacheCount, IARG_ADDRINT, iaddr, IARG_MEMORYREAD2_EA, IARG_MEMORYREAD_SIZE, IARG_UINT32, idx2, IARG_UINT32, 1, IARG_UINT32, 1, IARG_END); } } if (INS_IsMemoryWrite(ins)) { struct PC writeItem; writeItem.refs = 0; writeItem.miss = 0; writeItem.pc = iaddr; writeItem.isLoad = 0; dCachePC.push_back(writeItem); UINT32 idx2 = dCachePC.size()-1; INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR) dCacheCount, IARG_ADDRINT, iaddr, IARG_MEMORYWRITE_EA, IARG_MEMORYWRITE_SIZE, IARG_UINT32, idx2, IARG_UINT32, 0, IARG_UINT32, 0, IARG_END); } }
VOID Instruction(INS ins, void * v) { if (INS_IsMemoryRead(ins) && INS_IsStandardMemop(ins)) { // map sparse INS addresses to dense IDs const ADDRINT iaddr = INS_Address(ins); const UINT32 instId = profile.Map(iaddr); const UINT32 size = INS_MemoryReadSize(ins); const BOOL single = (size <= 4); if( KnobTrackLoads ) { if( single ) { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR) LoadSingle, IARG_MEMORYREAD_EA, IARG_UINT32, instId, IARG_END); } else { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR) LoadMulti, IARG_MEMORYREAD_EA, IARG_MEMORYREAD_SIZE, IARG_UINT32, instId, IARG_END); } } else { if( single ) { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR) LoadSingleFast, IARG_MEMORYREAD_EA, IARG_END); } else { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR) LoadMultiFast, IARG_MEMORYREAD_EA, IARG_MEMORYREAD_SIZE, IARG_END); } } } if ( INS_IsMemoryWrite(ins) && INS_IsStandardMemop(ins)) { // map sparse INS addresses to dense IDs const ADDRINT iaddr = INS_Address(ins); const UINT32 instId = profile.Map(iaddr); const UINT32 size = INS_MemoryWriteSize(ins); const BOOL single = (size <= 4); if( KnobTrackStores ) { if( single ) { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR) StoreSingle, IARG_MEMORYWRITE_EA, IARG_UINT32, instId, IARG_END); } else { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR) StoreMulti, IARG_MEMORYWRITE_EA, IARG_MEMORYWRITE_SIZE, IARG_UINT32, instId, IARG_END); } } else { if( single ) { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR) StoreSingleFast, IARG_MEMORYWRITE_EA, IARG_END); } else { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR) StoreMultiFast, IARG_MEMORYWRITE_EA, IARG_MEMORYWRITE_SIZE, IARG_END); } } } }
VOID HandleAccess (INS ins, BOOL isRead, BOOL *hasSegmentedMemAccess) { UINT32 operandCount = INS_OperandCount (ins); UINT32 i, displacement, scale; REG baseReg = REG_INVALID(), indexReg = REG_INVALID(); *hasSegmentedMemAccess = FALSE; for (i=0; i<operandCount; i++) { if (INS_OperandIsMemory (ins, i) && (INS_OperandMemorySegmentReg (ins, i) == TESTED_SEG_REG ) && ((isRead && INS_OperandRead (ins, i)) || (!isRead && INS_OperandWritten (ins, i))) ) { displacement = INS_OperandMemoryDisplacement (ins, i); baseReg = INS_OperandMemoryBaseReg (ins, i); indexReg = INS_OperandMemoryIndexReg (ins, i); scale = INS_OperandMemoryScale (ins, i); *hasSegmentedMemAccess = TRUE; break; } } /*fprintf(trace, " SegMemAccess-%s (hasSegmentedMemAccess %d) (operand %d) %p %s\n", isRead?"READ":"WRITE", *hasSegmentedMemAccess, i, INS_Address(ins), INS_Disassemble(ins).c_str());*/ if (baseReg != REG_INVALID()) { if (indexReg != REG_INVALID()) { if (isRead) { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR)AnalyzeSegmentedMemAccessBaseIndexDispl, IARG_INST_PTR, IARG_MEMORYREAD_EA, IARG_UINT32, BASE_INDEX_DISPLACEMENT_ADDRESSING_READ_TYPE, IARG_REG_VALUE, baseReg, IARG_REG_VALUE, indexReg, IARG_UINT32, scale, IARG_UINT32, displacement, IARG_THREAD_ID, IARG_END); } else { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR)AnalyzeSegmentedMemAccessBaseIndexDispl, IARG_INST_PTR, IARG_MEMORYWRITE_EA, IARG_UINT32, BASE_INDEX_DISPLACEMENT_ADDRESSING_WRITE_TYPE, IARG_REG_VALUE, baseReg, IARG_REG_VALUE, indexReg, IARG_UINT32, scale, IARG_UINT32, displacement, IARG_THREAD_ID, IARG_END); } } else { if (isRead) { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR)AnalyzeSegmentedMemAccessBaseDispl, IARG_INST_PTR, IARG_MEMORYREAD_EA, IARG_UINT32, BASE_DISPLACEMENT_ADDRESSING_READ_TYPE, IARG_REG_VALUE, baseReg, IARG_UINT32, displacement, IARG_THREAD_ID, IARG_END); } else { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR)AnalyzeSegmentedMemAccessBaseDispl, IARG_INST_PTR, IARG_MEMORYWRITE_EA, IARG_UINT32, BASE_DISPLACEMENT_ADDRESSING_WRITE_TYPE, IARG_REG_VALUE, baseReg, IARG_UINT32, displacement, IARG_THREAD_ID, IARG_END); } } } else if (indexReg != REG_INVALID()) { if (isRead) { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR)AnalyzeSegmentedMemAccessIndexDispl, IARG_INST_PTR, IARG_MEMORYREAD_EA, IARG_UINT32, INDEX_DISPLACEMENT_ADDRESSING_READ_TYPE, IARG_REG_VALUE, indexReg, IARG_UINT32, scale, IARG_UINT32, displacement, IARG_THREAD_ID, IARG_END); } else { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR)AnalyzeSegmentedMemAccessIndexDispl, IARG_INST_PTR, IARG_MEMORYWRITE_EA, IARG_UINT32, INDEX_DISPLACEMENT_ADDRESSING_WRITE_TYPE, IARG_REG_VALUE, indexReg, IARG_UINT32, scale, IARG_UINT32, displacement, IARG_THREAD_ID, IARG_END); } } else if (*hasSegmentedMemAccess) { if (isRead) { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR)AnalyzeSegmentedMemAccessDispl, IARG_INST_PTR, IARG_MEMORYREAD_EA, IARG_UINT32, DISPLACEMENT_ONLY_ADDRESSING_READ_TYPE, IARG_UINT32, displacement, IARG_THREAD_ID, IARG_END); } else { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR)AnalyzeSegmentedMemAccessDispl, IARG_INST_PTR, IARG_MEMORYWRITE_EA, IARG_UINT32, DISPLACEMENT_ONLY_ADDRESSING_WRITE_TYPE, IARG_UINT32, displacement, IARG_THREAD_ID, IARG_END); } } }
VOID Trace(TRACE trace, VOID *v) { const BOOL print_args = KnobPrintArgs.Value(); for (BBL bbl = TRACE_BblHead(trace); BBL_Valid(bbl); bbl = BBL_Next(bbl)) { INS tail = BBL_InsTail(bbl); if( INS_IsCall(tail) ) { if( INS_IsDirectBranchOrCall(tail) ) { const ADDRINT target = INS_DirectBranchOrCallTargetAddress(tail); if( print_args ) { INS_InsertPredicatedCall(tail, IPOINT_BEFORE, AFUNPTR(do_call_args), IARG_PTR, Target2String(target), IARG_G_ARG0_CALLER, IARG_END); } else { INS_InsertPredicatedCall(tail, IPOINT_BEFORE, AFUNPTR(do_call), IARG_PTR, Target2String(target), IARG_END); } } else { if( print_args ) { INS_InsertCall(tail, IPOINT_BEFORE, AFUNPTR(do_call_args_indirect), IARG_BRANCH_TARGET_ADDR, IARG_BRANCH_TAKEN, IARG_G_ARG0_CALLER, IARG_END); } else { INS_InsertCall(tail, IPOINT_BEFORE, AFUNPTR(do_call_indirect), IARG_BRANCH_TARGET_ADDR, IARG_BRANCH_TAKEN, IARG_END); } } } else { // sometimes code is not in an image RTN rtn = TRACE_Rtn(trace); // also track stup jumps into share libraries if( RTN_Valid(rtn) && !INS_IsDirectBranchOrCall(tail) && ".plt" == SEC_Name( RTN_Sec( rtn ) )) { if( print_args ) { INS_InsertCall(tail, IPOINT_BEFORE, AFUNPTR(do_call_args_indirect), IARG_BRANCH_TARGET_ADDR, IARG_BRANCH_TAKEN, IARG_G_ARG0_CALLER, IARG_END); } else { INS_InsertCall(tail, IPOINT_BEFORE, AFUNPTR(do_call_indirect), IARG_BRANCH_TARGET_ADDR, IARG_BRANCH_TAKEN, IARG_END); } } } } }
VOID Instruction(INS ins, void * v) { // track the write operations if ( INS_IsStackWrite(ins) ) { // map sparse INS addresses to dense IDs //const ADDRINT iaddr = INS_Address(ins); #ifdef STACK const UINT32 size = INS_MemoryWriteSize(ins); const BOOL single = (size <= 4); if( single ) { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR) StoreSingle, IARG_MEMORYWRITE_EA, IARG_ADDRINT, INS_Address(ins), IARG_END); } else { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR) StoreMulti, IARG_MEMORYWRITE_EA, IARG_MEMORYWRITE_SIZE, IARG_END); } #endif ; } else if( INS_IsMemoryWrite(ins) ) { #ifdef HEAP const UINT32 size = INS_MemoryWriteSize(ins); const BOOL single = (size <= 4); if( single ) { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR) StoreSingleH, IARG_MEMORYWRITE_EA, IARG_ADDRINT, INS_Address(ins), IARG_END); } else { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR) StoreMultiH, IARG_MEMORYWRITE_EA, IARG_MEMORYWRITE_SIZE, IARG_END); } #endif ; } #ifdef STACK // track the frame allocation/deallocation // record the count of function entry and exit via "CALL" and "Execution of the return address-instruction" // assume that the entry instruction will be executed once within each frame INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR) CallEnd, IARG_ADDRINT, INS_Address(ins), IARG_END); if( INS_Opcode(ins) == XED_ICLASS_CALL_NEAR ) { ADDRINT nextAddr = INS_NextAddress(ins); //cerr << hex << nextAddr; //ADDRINT callee = INS_DirectBranchOrCallTargetAddress(ins); //cerr << "->" << callee << endl; INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR) CallBegin, IARG_ADDRINT, nextAddr, IARG_BRANCH_TARGET_ADDR, IARG_END); } #endif }
// ------------------------------------------------------------- // Trace instrumentation function // ------------------------------------------------------------- void I_Trace(TRACE trace, void *v) { BOOL isPLT = IsPLT(TRACE_Rtn(trace)); #if DEBUG_INS printf("-- Instrumenting trace %X of function %s\n", TRACE_Address(trace), RTN_Valid(TRACE_Rtn(trace)) ? RTN_Name(TRACE_Rtn(trace)).c_str() : "<unknown_routine>"); #endif // scan BBLs within the current trace for (BBL bbl = TRACE_BblHead(trace); BBL_Valid(bbl); bbl = BBL_Next(bbl)) { // instrument memory reads and writes for(INS ins = BBL_InsHead(bbl); INS_Valid(ins); ins = INS_Next(ins)) Instruction(ins); INS tail = BBL_InsTail(bbl); // skip system calls if ( INS_IsSyscall(tail) ) continue; // instrument .plt stub calls if ( isPLT ) { #if DEBUG_INS printf(" > .plt stub call\n"); #endif if (gSetup.callingSite) { if (gSetup.memBuf) INS_InsertCall(tail, IPOINT_BEFORE, (AFUNPTR)A_ProcessIndirectCallCSBuf, IARG_FAST_ANALYSIS_CALL, IARG_INST_PTR, IARG_BRANCH_TARGET_ADDR, IARG_REG_VALUE, REG_STACK_PTR, IARG_THREAD_ID, IARG_CONTEXT, IARG_END); else INS_InsertCall(tail, IPOINT_BEFORE, (AFUNPTR)A_ProcessIndirectCallCS, IARG_FAST_ANALYSIS_CALL, IARG_INST_PTR, IARG_BRANCH_TARGET_ADDR, IARG_REG_VALUE, REG_STACK_PTR, IARG_THREAD_ID, IARG_END); } else { if (gSetup.memBuf) INS_InsertCall(tail, IPOINT_BEFORE, (AFUNPTR)A_ProcessIndirectCallBuf, IARG_FAST_ANALYSIS_CALL, IARG_BRANCH_TARGET_ADDR, IARG_REG_VALUE, REG_STACK_PTR, IARG_THREAD_ID, IARG_CONTEXT, IARG_END); else INS_InsertCall(tail, IPOINT_BEFORE, (AFUNPTR)A_ProcessIndirectCall, IARG_FAST_ANALYSIS_CALL, IARG_BRANCH_TARGET_ADDR, IARG_REG_VALUE, REG_STACK_PTR, IARG_THREAD_ID, IARG_END); } continue; } // instrument all calls and returns if ( INS_IsCall(tail) ) { // direct call if( INS_IsDirectBranchOrCall(tail) ) { // get target address ADDRINT target = Target2FunAddr(INS_DirectBranchOrCallTargetAddress(tail)); #if DEBUG_INS printf(" > Direct call to %s\n", Target2RtnName(target).c_str()); #endif // instrument direct call: target address determined here if (gSetup.callingSite) { if (gSetup.memBuf) INS_InsertPredicatedCall(tail, IPOINT_BEFORE, (AFUNPTR)A_ProcessDirectCallCSBuf, IARG_FAST_ANALYSIS_CALL, IARG_INST_PTR, IARG_ADDRINT, target, IARG_REG_VALUE, REG_STACK_PTR, IARG_THREAD_ID, IARG_CONTEXT, IARG_END); else INS_InsertPredicatedCall(tail, IPOINT_BEFORE, (AFUNPTR)A_ProcessDirectCallCS, IARG_FAST_ANALYSIS_CALL, IARG_INST_PTR, IARG_ADDRINT, target, IARG_REG_VALUE, REG_STACK_PTR, IARG_THREAD_ID, IARG_END); } else { if (gSetup.memBuf) INS_InsertPredicatedCall(tail, IPOINT_BEFORE, (AFUNPTR)A_ProcessDirectCallBuf, IARG_FAST_ANALYSIS_CALL, IARG_ADDRINT, target, IARG_REG_VALUE, REG_STACK_PTR, IARG_THREAD_ID, IARG_CONTEXT, IARG_END); else INS_InsertPredicatedCall(tail, IPOINT_BEFORE, (AFUNPTR)A_ProcessDirectCall, IARG_FAST_ANALYSIS_CALL, IARG_ADDRINT, target, IARG_REG_VALUE, REG_STACK_PTR, IARG_THREAD_ID, IARG_END); } } // indirect call: target address determined at call time else { #if DEBUG_INS printf(" > Indirect call\n"); #endif // instrument indirect call if (gSetup.callingSite) { if (gSetup.memBuf) INS_InsertPredicatedCall(tail, IPOINT_BEFORE, (AFUNPTR)A_ProcessIndirectCallCSBuf, IARG_FAST_ANALYSIS_CALL, IARG_INST_PTR, IARG_BRANCH_TARGET_ADDR, IARG_REG_VALUE, REG_STACK_PTR, IARG_THREAD_ID, IARG_CONTEXT, IARG_END); else INS_InsertPredicatedCall(tail, IPOINT_BEFORE, (AFUNPTR)A_ProcessIndirectCallCS, IARG_FAST_ANALYSIS_CALL, IARG_INST_PTR, IARG_BRANCH_TARGET_ADDR, IARG_REG_VALUE, REG_STACK_PTR, IARG_THREAD_ID, IARG_END); } else { if (gSetup.memBuf) INS_InsertPredicatedCall(tail, IPOINT_BEFORE, (AFUNPTR)A_ProcessIndirectCallBuf, IARG_FAST_ANALYSIS_CALL, IARG_BRANCH_TARGET_ADDR, IARG_REG_VALUE, REG_STACK_PTR, IARG_THREAD_ID, IARG_CONTEXT, IARG_END); else INS_InsertPredicatedCall(tail, IPOINT_BEFORE, (AFUNPTR)A_ProcessIndirectCall, IARG_FAST_ANALYSIS_CALL, IARG_BRANCH_TARGET_ADDR, IARG_REG_VALUE, REG_STACK_PTR, IARG_THREAD_ID, IARG_END); } } continue; } if ( INS_IsRet(tail) ) { #if DEBUG_INS printf(" > return\n"); #endif if (gSetup.memBuf) INS_InsertPredicatedCall(tail, IPOINT_BEFORE, (AFUNPTR)A_ProcessReturnBuf, IARG_FAST_ANALYSIS_CALL, IARG_REG_VALUE, REG_STACK_PTR, IARG_THREAD_ID, IARG_CONTEXT, IARG_END); else INS_InsertPredicatedCall(tail, IPOINT_BEFORE, (AFUNPTR)A_ProcessReturn, IARG_FAST_ANALYSIS_CALL, IARG_REG_VALUE, REG_STACK_PTR, IARG_THREAD_ID, IARG_END); } } }
// ------------------------------------------------------------- // Instruction instrumentation function // ------------------------------------------------------------- // Is called for every instruction and instruments reads and writes VOID Instruction(INS ins) { // Instruments memory accesses using a predicated call, i.e. // the instrumentation is called iff the instruction will actually be executed. // // The IA-64 architecture has explicitly predicated instructions. // On the IA-32 and Intel(R) 64 architectures conditional moves and REP // prefixed instructions appear as predicated instructions in Pin. UINT32 memOperands = INS_MemoryOperandCount(ins); // Iterate over each memory operand of the instruction. for (UINT32 memOp = 0; memOp < memOperands; memOp++) { if (INS_MemoryOperandIsRead(ins, memOp)) { #if DEBUG_INS printf("-- Instrumenting read operation at instruction address %X\n", INS_Address(ins)); #endif if (gSetup.memBuf) { // if using memory operations buffering, bypass user-defined callbacks INS_InsertFillBufferPredicated(ins, IPOINT_BEFORE, buf_id, IARG_MEMORYOP_EA, memOp, offsetof(STool_TMemRec, addr), IARG_BOOL, FALSE, offsetof(STool_TMemRec, isWrite), IARG_END); } else if (gSetup.memRead) { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR)A_MemRead, IARG_FAST_ANALYSIS_CALL, IARG_THREAD_ID, IARG_MEMORYOP_EA, memOp, IARG_END); } } // Note that in some architectures a single memory operand can be // both read and written (for instance incl (%eax) on IA-32) // In that case we instrument it once for read and once for write. if (INS_MemoryOperandIsWritten(ins, memOp)) { #if DEBUG_INS printf("-- Instrumenting write operation at instruction address %X\n", INS_Address(ins)); #endif if (gSetup.memBuf) { // if using memory operations buffering, bypass user-defined callbacks INS_InsertFillBufferPredicated(ins, IPOINT_BEFORE, buf_id, IARG_MEMORYOP_EA, memOp, offsetof(STool_TMemRec, addr), IARG_BOOL, TRUE, offsetof(STool_TMemRec, isWrite), IARG_END); } else if (gSetup.memWrite) { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR)A_MemWrite, IARG_FAST_ANALYSIS_CALL, IARG_THREAD_ID, IARG_MEMORYOP_EA, memOp, IARG_END); } } } }