// Generate code to check if swizzling is needed, but not do it VOID CheckIns(INS ins, ADDRINT traceAddress) { if (INS_IsMemoryRead(ins) && INS_HasMemoryRead2(ins)) { INS_InsertIfCall(ins, IPOINT_BEFORE, AFUNPTR(SwizzleSpace2), IARG_MEMORYREAD_EA, IARG_MEMORYREAD2_EA, IARG_END); } else if (INS_IsMemoryRead(ins) && INS_IsMemoryWrite(ins)) { INS_InsertIfCall(ins, IPOINT_BEFORE, AFUNPTR(SwizzleSpace2), IARG_MEMORYREAD_EA, IARG_MEMORYWRITE_EA, IARG_END); } else if (INS_IsMemoryRead(ins)) { INS_InsertIfCall(ins, IPOINT_BEFORE, AFUNPTR(SwizzleSpace1), IARG_MEMORYREAD_EA, IARG_END); } else if (INS_IsMemoryWrite(ins)) { INS_InsertIfCall(ins, IPOINT_BEFORE, AFUNPTR(SwizzleSpace1), IARG_MEMORYWRITE_EA, IARG_END); } else { return; } INS_InsertThenCall(ins, IPOINT_BEFORE, AFUNPTR(Restart), IARG_INST_PTR, IARG_CONTEXT, IARG_ADDRINT, traceAddress, IARG_END); }
INT32 RecordRegisters(BBL bbl, UINT16 * stats, UINT32 max_stats) { UINT32 count = 0; for (INS ins = BBL_InsHead(bbl); INS_Valid(ins); ins = INS_Next(ins)) { if (count >= max_stats) { cerr << "Too many stats in this block" << endl; exit(1); } bool rmem = INS_IsMemoryRead(ins) || INS_HasMemoryRead2(ins); bool wmem = INS_IsMemoryWrite(ins); bool rw_mem = rmem & wmem; if (rw_mem) stats[count++] = PATTERN_MEM_RW; else if (rmem) stats[count++] = PATTERN_MEM_R; else if (wmem) stats[count++] = PATTERN_MEM_W; else if (INS_SegmentRegPrefix(ins) != REG_INVALID()) stats[count++] = PATTERN_NO_MEM_LIES; else stats[count++] = PATTERN_NO_MEM; } stats[count++] = 0; return count; }
/* instrumenting (instruction level) */ VOID instrument_stride(INS ins, VOID* v){ UINT32 index; if( INS_IsMemoryRead(ins) ){ // instruction has memory read operand index = stride_index_memRead1(INS_Address(ins)); INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)readMem_stride, IARG_UINT32, index, IARG_MEMORYREAD_EA, IARG_MEMORYREAD_SIZE, IARG_END); if( INS_HasMemoryRead2(ins) ){ // second memory read operand index = stride_index_memRead2(INS_Address(ins)); INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)readMem_stride, IARG_UINT32, index, IARG_MEMORYREAD2_EA, IARG_MEMORYREAD_SIZE, IARG_END); } } if( INS_IsMemoryWrite(ins) ){ // instruction has memory write operand index = stride_index_memWrite(INS_Address(ins)); INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)writeMem_stride, IARG_UINT32, index, IARG_MEMORYWRITE_EA, IARG_MEMORYWRITE_SIZE, IARG_END); } /* inserting calls for counting instructions (full) is done in mica.cpp */ if(interval_size != -1){ INS_InsertIfCall(ins, IPOINT_BEFORE, (AFUNPTR)stride_instr_intervals, IARG_END); INS_InsertThenCall(ins, IPOINT_BEFORE, (AFUNPTR)stride_instr_interval, IARG_END); } }
// 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); } }
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); } } }
static VOID InstrumentTrace(TRACE trace, VOID *v) { // Visit every basic block in the trace for (BBL bbl = TRACE_BblHead(trace); BBL_Valid(bbl); bbl = BBL_Next(bbl)) { // Insert a call to addTotal somewhere in each bbl, passing the number of instructions // in the BBL. BBL_InsertCall(bbl, IPOINT_ANYWHERE, (AFUNPTR)addTotal, IARG_UINT32, BBL_NumIns(bbl), IARG_END); if (KnobCountMemory) { // Compute the number of memory accesses generated by the BBL UINT32 reads = 0; UINT32 writes = 0; for (INS ins = BBL_InsHead(bbl); INS_Valid(ins); ins = INS_Next(ins)) { if (INS_IsMemoryRead(ins)) reads++; if (INS_HasMemoryRead2(ins)) reads++; if (INS_IsMemoryWrite(ins)) writes++; } // If we have memory accesses, then add instrumentation to count them. if (reads != 0 || writes != 0) { BBL_InsertCall(bbl, IPOINT_ANYWHERE, (AFUNPTR)addTotalMemops, IARG_UINT32, reads, IARG_UINT32, writes, IARG_END); } } } }
static VOID MemoryTrace(TRACE trace, INS ins) { if (!KnobTraceMemory) return; if (INS_IsMemoryRead(ins) || INS_HasMemoryRead2(ins) || INS_IsMemoryWrite(ins) ) { INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(EmitMemory), IARG_THREAD_ID, IARG_INST_PTR, IARG_BOOL, INS_IsMemoryWrite(ins), (INS_IsMemoryWrite(ins) ? IARG_MEMORYWRITE_EA : INS_IsMemoryRead(ins) ? IARG_MEMORYREAD_EA : IARG_MEMORYREAD2_EA), 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 log_ins(INS ins) { // dump the instruction INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR) &execute_instruction, IARG_INST_PTR, IARG_PTR, strdup(INS_Disassemble(ins).c_str()), IARG_END); // reads memory (1) if(INS_IsMemoryRead(ins) != 0) { INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR) &dump_read_memory, IARG_MEMORYREAD_EA, IARG_MEMORYREAD_SIZE, IARG_END); } // reads memory (2) if(INS_HasMemoryRead2(ins) != 0) { INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR) &dump_read_memory, IARG_MEMORYREAD2_EA, IARG_MEMORYREAD_SIZE, IARG_END); } IPOINT after = IPOINT_AFTER; if(INS_IsCall(ins) != 0) { // TODO is this correct? after = IPOINT_TAKEN_BRANCH; } else if(INS_IsSyscall(ins) != 0) { // TODO support syscalls return; } else if(INS_HasFallThrough(ins) == 0 && (INS_IsBranch(ins) != 0 || INS_IsRet(ins) != 0)) { // TODO is this correct? after = IPOINT_TAKEN_BRANCH; } // dump written memory if(INS_IsMemoryWrite(ins) != 0) { INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR) &dump_written_memory_before, IARG_MEMORYWRITE_EA, IARG_MEMORYWRITE_SIZE, IARG_END); INS_InsertCall(ins, after, (AFUNPTR) &dump_written_memory_after, IARG_END); } // dump all affected registers for (UINT32 i = 0; i < INS_OperandCount(ins); i++) { if(INS_OperandIsMemory(ins, i) != 0) { if(INS_OperandMemoryBaseReg(ins, i) != REG_INVALID()) { REG base_reg = INS_OperandMemoryBaseReg(ins, i); if(g_reg_index[base_reg] != 0) { INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR) &dump_reg_before, IARG_UINT32, g_reg_index[base_reg]-1, IARG_REG_VALUE, INS_OperandMemoryBaseReg(ins, i), IARG_END); INS_InsertCall(ins, after, (AFUNPTR) &dump_reg_r_after, IARG_UINT32, g_reg_index[base_reg]-1, IARG_END); } } if(INS_OperandMemoryIndexReg(ins, i) != REG_INVALID()) { REG index_reg = INS_OperandMemoryIndexReg(ins, i); if(g_reg_index[index_reg] != 0) { INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR) &dump_reg_before, IARG_UINT32, g_reg_index[index_reg]-1, IARG_REG_VALUE, INS_OperandMemoryIndexReg(ins, i), IARG_END); INS_InsertCall(ins, after, (AFUNPTR) &dump_reg_r_after, IARG_UINT32, g_reg_index[index_reg]-1, IARG_END); } } } if(INS_OperandIsReg(ins, i) != 0) { REG reg_index = REG_FullRegName(INS_OperandReg(ins, i)); if(INS_OperandReadAndWritten(ins, i) != 0) { if(g_reg_index[reg_index] != 0) { INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR) &dump_reg_before, IARG_UINT32, g_reg_index[reg_index]-1, IARG_REG_VALUE, reg_index, IARG_END); INS_InsertCall(ins, after, (AFUNPTR) &dump_reg_rw_after, IARG_UINT32, g_reg_index[reg_index]-1, IARG_REG_VALUE, reg_index, IARG_END); } } else if(INS_OperandRead(ins, i) != 0) { if(g_reg_index[reg_index] != 0) { INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR) &dump_reg_before, IARG_UINT32, g_reg_index[reg_index]-1, IARG_REG_VALUE, reg_index, IARG_END); INS_InsertCall(ins, after, (AFUNPTR) &dump_reg_r_after, IARG_UINT32, g_reg_index[reg_index]-1, IARG_END); } } else if(INS_OperandWritten(ins, i) != 0) { if(g_reg_index[reg_index] != 0) { INS_InsertCall(ins, after, (AFUNPTR) &dump_reg_w_after, IARG_UINT32, g_reg_index[reg_index]-1, IARG_REG_VALUE, reg_index, IARG_END); } } } } INS_InsertCall(ins, after, (AFUNPTR) &print_newline, 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 Image(IMG img, VOID *v){ for (UINT16 i = 0; i < n_excluded_lib_names; i++) { if (IMG_Name(img).find(excluded_lib_names[i]) != string::npos){ cout << "Excluded module: " << IMG_Name(img) << endl; return; } } for (SEC sec = IMG_SecHead(img); SEC_Valid(sec); sec = SEC_Next(sec)){ for (RTN rtn = SEC_RtnHead(sec); RTN_Valid(rtn); rtn = RTN_Next(rtn)) { RTN_Open(rtn); for (INS ins = RTN_InsHead(rtn); INS_Valid(ins); ins = INS_Next(ins)) { // Avoid instrumenting the instrumentation if (!INS_IsOriginal(ins)) continue; if(!SeqProgram) { if ((INS_IsMemoryWrite(ins) || INS_IsMemoryRead(ins)) && INS_HasFallThrough(ins)) { if (INS_IsMemoryWrite(ins) && INS_IsMemoryRead(ins) && INS_HasMemoryRead2(ins)) { INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)ProcessInst, IARG_THREAD_ID, IARG_MEMORYWRITE_EA, IARG_MEMORYREAD_EA, IARG_MEMORYREAD2_EA, IARG_INST_PTR, IARG_END); } else if (INS_IsMemoryWrite(ins) && INS_IsMemoryRead(ins) && !INS_HasMemoryRead2(ins)) { INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)ProcessInst, IARG_THREAD_ID, IARG_MEMORYWRITE_EA, IARG_MEMORYREAD_EA, IARG_ADDRINT, 0, IARG_INST_PTR, IARG_END); } else if (INS_IsMemoryWrite(ins) && !INS_IsMemoryRead(ins)) { INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)ProcessInst, IARG_THREAD_ID, IARG_MEMORYWRITE_EA, IARG_ADDRINT, 0, IARG_ADDRINT, 0, IARG_INST_PTR, IARG_END); } else if (!INS_IsMemoryWrite(ins) && INS_IsMemoryRead(ins) && INS_HasMemoryRead2(ins)) { INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)ProcessInst, IARG_THREAD_ID, IARG_ADDRINT, 0, IARG_MEMORYREAD_EA, IARG_MEMORYREAD2_EA, IARG_INST_PTR, IARG_END); } else if (!INS_IsMemoryWrite(ins) && INS_IsMemoryRead(ins) && !INS_HasMemoryRead2(ins)) { INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)ProcessInst, IARG_THREAD_ID, IARG_ADDRINT, 0, IARG_MEMORYREAD_EA, IARG_ADDRINT,0, IARG_INST_PTR, IARG_END); } else { //not a memory opeartion ASSERTX(0); } } } else { if(INS_IsBranch(ins)){ INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)ProcessBranch, IARG_BRANCH_TAKEN, IARG_INST_PTR, IARG_END); } } } RTN_Close(rtn); } } }
// Insert instrumentation to log memory addresses accessed. static VOID insertRepMemoryTraceInstrumentation(INS ins, UINT32 opIdx) { const opInfo * op = &opcodes[opIdx]; if (takesConditionalRep(opIdx)) { if (INS_IsMemoryRead(ins)) { INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)logMemoryAddress, IARG_UINT32, opIdx, IARG_FIRST_REP_ITERATION, IARG_MEMORYREAD_EA, IARG_EXECUTING, IARG_UINT32, op->size, IARG_UINT32, 0, /* Fake Eflags, since we're called at each iteration it doesn't matter */ IARG_ADDRINT, (ADDRINT)"Read ", IARG_END); } if (INS_HasMemoryRead2(ins)) { INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)logMemoryAddress, IARG_UINT32, opIdx, IARG_FIRST_REP_ITERATION, IARG_MEMORYREAD2_EA, IARG_EXECUTING, IARG_UINT32, op->size, IARG_UINT32, 0, /* Fake Eflags, since we're called at each iteration it doesn't matter */ IARG_ADDRINT, (ADDRINT)"Read2", IARG_END); } if (INS_IsMemoryWrite(ins)) { INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)logMemoryAddress, IARG_UINT32, opIdx, IARG_FIRST_REP_ITERATION, IARG_MEMORYWRITE_EA, IARG_EXECUTING, IARG_UINT32, op->size, IARG_UINT32, 0, /* Fake Eflags, since we're called at each iteration it doesn't matter */ IARG_ADDRINT, (ADDRINT)"Write", IARG_END); } } else { if (INS_IsMemoryRead(ins)) { INS_InsertIfCall(ins, IPOINT_BEFORE, (AFUNPTR)returnArg, IARG_FIRST_REP_ITERATION, IARG_END); INS_InsertThenCall(ins, IPOINT_BEFORE, (AFUNPTR)logMemoryAddress, IARG_UINT32, opIdx, IARG_BOOL, TRUE, /* First must be one else we wouldn't be called */ IARG_MEMORYREAD_EA, IARG_REG_VALUE, INS_RepCountRegister(ins), IARG_UINT32, op->size, IARG_REG_VALUE, REG_EFLAGS, IARG_ADDRINT, (ADDRINT)"Read ", IARG_END); } if (INS_HasMemoryRead2(ins)) { INS_InsertIfCall(ins, IPOINT_BEFORE, (AFUNPTR)returnArg, IARG_FIRST_REP_ITERATION, IARG_END); INS_InsertThenCall(ins, IPOINT_BEFORE, (AFUNPTR)logMemoryAddress, IARG_UINT32, opIdx, IARG_BOOL, TRUE, /* First must be one else we wouldn't be called */ IARG_MEMORYREAD2_EA, IARG_REG_VALUE, INS_RepCountRegister(ins), IARG_UINT32, op->size, IARG_REG_VALUE, REG_EFLAGS, IARG_ADDRINT, (ADDRINT)"Read2", IARG_END); } if (INS_IsMemoryWrite(ins)) { INS_InsertIfCall(ins, IPOINT_BEFORE, (AFUNPTR)returnArg, IARG_FIRST_REP_ITERATION, IARG_END); INS_InsertThenCall(ins, IPOINT_BEFORE, (AFUNPTR)logMemoryAddress, IARG_UINT32, opIdx, IARG_BOOL, TRUE, /* First must be one else we wouldn't be called */ IARG_MEMORYWRITE_EA, IARG_REG_VALUE, INS_RepCountRegister(ins), IARG_UINT32, op->size, IARG_REG_VALUE, REG_EFLAGS, IARG_ADDRINT, (ADDRINT)"Write", IARG_END); } } }
static void I_Trace(TRACE trace, void *v) { //FIXME if (PIN_IsSignalHandler()) {Sequence_ProcessSignalHandler(head)}; for(BBL bbl = TRACE_BblHead(trace); BBL_Valid(bbl); bbl = BBL_Next(bbl)) { INS tail = BBL_InsTail(bbl); // All memory reads/writes for( INS ins = BBL_InsHead(bbl); INS_Valid(ins); ins = INS_Next(ins) ) { if( INS_IsMemoryRead(ins) || INS_HasMemoryRead2(ins) || INS_IsMemoryWrite(ins) ) { INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)A_DoMem, IARG_BOOL, INS_IsMemoryWrite(ins), (INS_IsMemoryWrite(ins) ? IARG_MEMORYWRITE_EA : (INS_IsMemoryRead(ins) ? IARG_MEMORYREAD_EA : IARG_MEMORYREAD2_EA)), IARG_INST_PTR, IARG_END); } #if defined(TARGET_IA32) && defined (TARGET_WINDOWS) // on ia-32 windows need to identify // push // ret // in order to process callstack correctly if (ins != tail) { INS_InsertPredicatedCall(ins, IPOINT_BEFORE, (AFUNPTR)ProcessInst, IARG_INST_PTR, IARG_END); if (INS_Opcode(ins)==XED_ICLASS_PUSH) { RecordPush (ins); } } #endif } // All calls and returns if( INS_IsSyscall(tail) ) { INS_InsertPredicatedCall(tail, IPOINT_BEFORE, (AFUNPTR)A_ProcessSyscall, IARG_INST_PTR, IARG_SYSCALL_NUMBER, IARG_REG_VALUE, REG_STACK_PTR, IARG_SYSCALL_ARG0, IARG_END); } else { if( INS_IsCall(tail) ) { if( INS_IsDirectBranchOrCall(tail) ) { ADDRINT target = INS_DirectBranchOrCallTargetAddress(tail); INS_InsertPredicatedCall(tail, IPOINT_BEFORE, (AFUNPTR)A_ProcessDirectCall, IARG_INST_PTR, IARG_ADDRINT, target, IARG_REG_VALUE, REG_STACK_PTR, IARG_END); } else if( !IsPLT(trace) ) { INS_InsertPredicatedCall(tail, IPOINT_BEFORE, (AFUNPTR)A_ProcessIndirectCall, IARG_INST_PTR, IARG_BRANCH_TARGET_ADDR, IARG_REG_VALUE, REG_STACK_PTR, IARG_END); } } if( IsPLT(trace) ) { INS_InsertCall(tail, IPOINT_BEFORE, (AFUNPTR)A_ProcessStub, IARG_INST_PTR, IARG_BRANCH_TARGET_ADDR, IARG_REG_VALUE, REG_STACK_PTR, IARG_END); } if( INS_IsRet(tail) ) { INS_InsertPredicatedCall(tail, IPOINT_BEFORE, (AFUNPTR)A_ProcessReturn, IARG_INST_PTR, IARG_REG_VALUE, REG_STACK_PTR, IARG_END); } } } }
/* Trace instrumentation */ static void TRACE_Instrumentation(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)) { /* Check if the analysis me be unlocked */ tracer::pintool::checkUnlockAnalysis(INS_Address(ins)); if (!tracer::pintool::analysisTrigger.getState()) /* Analysis locked */ continue; if (tracer::pintool::instructionBlacklisted(INS_Address(ins)) == true || tracer::pintool::instructionWhitelisted(INS_Address(ins)) == false) /* Insruction blacklisted */ continue; /* Prepare the Triton's instruction */ triton::arch::Instruction* tritonInst = new triton::arch::Instruction(); /* Save memory read1 informations */ if (INS_IsMemoryRead(ins)) { INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)saveMemoryAccess, IARG_PTR, tritonInst, IARG_MEMORYREAD_EA, IARG_MEMORYREAD_SIZE, IARG_END); } /* Save memory read2 informations */ if (INS_HasMemoryRead2(ins)) { INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)saveMemoryAccess, IARG_PTR, tritonInst, IARG_MEMORYREAD2_EA, IARG_MEMORYREAD_SIZE, IARG_END); } /* Callback before */ INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)callbackBefore, IARG_PTR, tritonInst, IARG_INST_PTR, IARG_UINT32, INS_Size(ins), IARG_CONTEXT, IARG_THREAD_ID, IARG_END); /* Callback after */ /* Syscall after context must be catcher with INSERT_POINT.SYSCALL_EXIT */ if (INS_IsSyscall(ins) == false) { IPOINT where = IPOINT_AFTER; if (INS_HasFallThrough(ins) == false) where = IPOINT_TAKEN_BRANCH; INS_InsertCall(ins, where, (AFUNPTR)callbackAfter, IARG_PTR, tritonInst, IARG_CONTEXT, IARG_THREAD_ID, IARG_END); } /* I/O memory monitoring for snapshot */ if (INS_OperandCount(ins) > 1 && INS_MemoryOperandIsWritten(ins, 0)) { INS_InsertCall( ins, IPOINT_BEFORE, (AFUNPTR)callbackSnapshot, IARG_MEMORYOP_EA, 0, IARG_UINT32, INS_MemoryWriteSize(ins), IARG_END); } } } }
instruction::instruction(const INS& ins) { this->address = INS_Address(ins); this->next_address = INS_NextAddress(ins); // this->opcode = INS_Mnemonic(ins); this->opcode_size = static_cast<uint8_t>(INS_Size(ins)); this->opcode_buffer = std::shared_ptr<uint8_t>(new uint8_t[this->opcode_size], std::default_delete<uint8_t[]>()); PIN_SafeCopy(opcode_buffer.get(), reinterpret_cast<const VOID*>(this->address), this->opcode_size); this->disassemble = INS_Disassemble(ins); // including image, routine auto img = IMG_FindByAddress(this->address); this->including_image = IMG_Valid(img) ? IMG_Name(img) : ""; // this->including_routine = RTN_FindNameByAddress(this->address); PIN_LockClient(); auto routine = RTN_FindByAddress(this->address); PIN_UnlockClient(); if (RTN_Valid(routine)) { auto routine_mangled_name = RTN_Name(routine); this->including_routine_name = PIN_UndecorateSymbolName(routine_mangled_name, UNDECORATION_NAME_ONLY); } else this->including_routine_name = ""; // has fall through this->has_fall_through = INS_HasFallThrough(ins); // is call, ret or syscall this->is_call = INS_IsCall(ins); this->is_branch = INS_IsBranch(ins); this->is_ret = INS_IsRet(ins); this->is_syscall = INS_IsSyscall(ins); this->category = static_cast<xed_category_enum_t>(INS_Category(ins)); this->iclass = static_cast<xed_iclass_enum_t>(INS_Opcode(ins)); // read registers auto read_reg_number = INS_MaxNumRRegs(ins); for (decltype(read_reg_number) reg_id = 0; reg_id < read_reg_number; ++reg_id) { this->src_registers.push_back(INS_RegR(ins, reg_id)); } // written registers auto written_reg_number = INS_MaxNumWRegs(ins); for (decltype(written_reg_number) reg_id = 0; reg_id < written_reg_number; ++reg_id) { this->dst_registers.push_back(INS_RegW(ins, reg_id)); } auto is_special_reg = [](const REG& reg) -> bool { return (reg >= REG_MM_BASE); }; this->is_special = std::any_of(std::begin(this->src_registers), std::end(this->src_registers), is_special_reg) || std::any_of(std::begin(this->dst_registers), std::end(this->dst_registers), is_special_reg) || (this->category == XED_CATEGORY_X87_ALU) || (this->iclass == XED_ICLASS_XEND) || (this->category == XED_CATEGORY_LOGICAL_FP) || (this->iclass == XED_ICLASS_PUSHA) || (this->iclass == XED_ICLASS_PUSHAD) || (this->iclass == XED_ICLASS_PUSHF) || (this->iclass == XED_ICLASS_PUSHFD) || (this->iclass == XED_ICLASS_PUSHFQ); // is memory read, write this->is_memory_read = INS_IsMemoryRead(ins); this->is_memory_write = INS_IsMemoryWrite(ins); this->is_memory_read2 = INS_HasMemoryRead2(ins); }
// Pin calls this function every time a new instruction is encountered VOID Instruction(INS ins, VOID *v) { string *disptr = new string(INS_Disassemble(ins)); // reads if (INS_IsMemoryRead(ins)) { INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)readMemoryFunc, IARG_FAST_ANALYSIS_CALL, IARG_MEMORYREAD_EA, IARG_MEMORYREAD_PTR, IARG_THREAD_ID, IARG_PTR, disptr, IARG_INST_PTR, IARG_END); } // writes if (INS_IsMemoryWrite(ins)) { INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)writeMemoryFunc, IARG_FAST_ANALYSIS_CALL, IARG_THREAD_ID, IARG_MEMORYWRITE_EA, IARG_MEMORYWRITE_PTR , IARG_INST_PTR, IARG_PTR, disptr, IARG_END); } UINT32 memOperands = INS_MemoryOperandCount(ins); if (!INS_IsVgather(ins) && memOperands) { // OPs for (UINT32 memOp = 0; memOp < memOperands; memOp++) { if (INS_MemoryOperandIsRead(ins, memOp) || INS_MemoryOperandIsWritten(ins, memOp)) { INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)opMemoryFunc, IARG_FAST_ANALYSIS_CALL, IARG_MEMORYOP_EA, memOp, IARG_MEMORYOP_PTR, memOp, IARG_INST_PTR , IARG_PTR, disptr, IARG_END); } } } // READ2 if (INS_HasMemoryRead2(ins)) { INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)read2MemoryFunc, IARG_FAST_ANALYSIS_CALL, IARG_MEMORYREAD_EA, IARG_MEMORYREAD_PTR, IARG_MEMORYREAD2_EA, IARG_MEMORYREAD2_PTR, IARG_THREAD_ID, IARG_PTR, disptr, IARG_CONTEXT, IARG_INST_PTR, IARG_END); } }