/* 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); } }
// Instrumentation routines. // Insert code for counting how many times the instruction is executed static VOID insertRepExecutionCountInstrumentation (INS ins, UINT32 opIdx) { if (takesConditionalRep(opIdx)) { // We have no smart way to lessen the number of // instrumentation calls because we can't determine when // the conditional instruction will finish. So we just // let the instruction execute and have our // instrumentation be called on each iteration. This is // the simplest way of handling REP prefixed instructions, where // each iteration appears as a separate instruction, and // is independently instrumented. INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)addCount, IARG_INST_PTR, IARG_UINT32, opIdx, IARG_FIRST_REP_ITERATION, IARG_EXECUTING, IARG_END); } else { // The number of iterations is determined solely by the count register value, // therefore we can log all we need at the start of each REP "loop", and skip the // instrumentation on all the other iterations of the REP prefixed operation. Simply use // IF/THEN instrumentation which tests IARG_FIRST_REP_ITERATION. INS_InsertIfCall(ins, IPOINT_BEFORE, (AFUNPTR)returnArg, IARG_FIRST_REP_ITERATION, IARG_END); INS_InsertThenCall(ins, IPOINT_BEFORE, (AFUNPTR)addCount, IARG_INST_PTR, IARG_UINT32, opIdx, IARG_UINT32, 1, IARG_REG_VALUE, INS_RepCountRegister(ins), IARG_END); } }
static VOID InsertIfBridgeThenNoBridge(RTN rtn) { RTN_Open(rtn); INS_InsertIfCall(RTN_InsHead(rtn), IPOINT_BEFORE, AFUNPTR(IfBridge), IARG_BRIDGE_IF, IARG_END); INS_InsertThenCall(RTN_InsHead(rtn), IPOINT_BEFORE, AFUNPTR(ThenNoBridge), IARG_END); RTN_Close(rtn); }
// Pin calls this function every time a new basic block is encountered // It inserts a call to docount VOID Trace(TRACE trace, VOID *v) { // Visit every basic block in the trace 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_InsertIfCall(ins, IPOINT_BEFORE, (AFUNPTR)ReadAlways, IARG_MEMORYREAD_EA, IARG_END); INS_InsertThenCall(ins, IPOINT_BEFORE, (AFUNPTR)ReadRare, IARG_MEMORYREAD_EA, IARG_END); } } // Always()->Rare() are partially inlined BBL_InsertIfCall(bbl, IPOINT_BEFORE, (AFUNPTR)Always, IARG_END); BBL_InsertThenCall(bbl, IPOINT_BEFORE, (AFUNPTR)Rare, IARG_END); // Always()->Rare() are partially inlined BBL_InsertIfCall(bbl, IPOINT_BEFORE, (AFUNPTR)AlwaysNoinline, IARG_END); BBL_InsertThenCall(bbl, IPOINT_BEFORE, (AFUNPTR)RareNoinline, IARG_END); // Noinline() is not inlined BBL_InsertCall(bbl, IPOINT_BEFORE, (AFUNPTR)Noinline, IARG_END); } }
static VOID InsertIfInlineThenInline(RTN rtn) { RTN_Open(rtn); INS_InsertIfCall(RTN_InsHead(rtn), IPOINT_BEFORE, AFUNPTR(IfInline), IARG_END); INS_InsertThenCall(RTN_InsHead(rtn), IPOINT_BEFORE, AFUNPTR(ThenInline), IARG_END); RTN_Close(rtn); }
VOID Instruction(INS ins, VOID *v) { /* Should cause an error since a different action value is passed to "INS_InsertIfCall" and its * corresponding "INS_InsertThenCall". */ INS_InsertIfCall(ins, IPOINT_BEFORE , (AFUNPTR)IfFunction, IARG_END); INS_InsertThenCall(ins, IPOINT_AFTER, (AFUNPTR)ThenFunction, IARG_END); }
// Pin calls this function every time a new instruction is encountered VOID Instruction(INS ins, VOID *v) { // CountDown() is called for every instruction executed INS_InsertIfCall(ins, IPOINT_BEFORE, (AFUNPTR)CountDown, IARG_END); // PrintIp() is called only when the last CountDown() returns a non-zero value. INS_InsertThenCall(ins, IPOINT_BEFORE, (AFUNPTR)PrintIp, IARG_INST_PTR, IARG_END); }
VOID Instruction(INS ins, VOID *v) { INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)docount, IARG_END); INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)UpdateIcountByAdd, IARG_PTR, &icount2, IARG_END); INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)UpdateIcountByInc, IARG_PTR, &icount3, IARG_END); INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)UpdateIcountByDecInc, IARG_PTR, &icount4, IARG_END); INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)UpdateIcountBySub, IARG_PTR, &icount5, IARG_END); INS_InsertIfCall(ins, IPOINT_BEFORE, (AFUNPTR)IfFuncWithAddThatCannotBeChangedToLea, IARG_END); INS_InsertThenCall(ins, IPOINT_BEFORE, (AFUNPTR)ThenFuncThatShouldNeverBeCalled, IARG_END); }
static VOID InstrumentRoutine(INS ins, VOID *) { if (numThenCalls > 10) { return; } if (INS_IsMemoryRead(ins)) { INS_InsertIfCall(ins, IPOINT_BEFORE, (AFUNPTR)IfFunc, IARG_END); INS_InsertThenCall(ins, IPOINT_BEFORE, (AFUNPTR)ThenFunc, IARG_MEMORYREAD_EA, // pass a parameter IARG_END); } }
static VOID OnRoutine(RTN rtn, VOID *) { #if defined(TARGET_MAC) if (RTN_Name(rtn) == "_DoThenInstrumentation") #else if (RTN_Name(rtn) == "DoThenInstrumentation") #endif { RTN_Open(rtn); INS_InsertIfCall(RTN_InsHead(rtn), IPOINT_BEFORE, AFUNPTR(IfTrue), IARG_END); INS_InsertThenCall(RTN_InsHead(rtn), IPOINT_BEFORE, AFUNPTR(ThenFunction), IARG_END); RTN_Close(rtn); } }
VOID Image(IMG img, VOID * v) { if (strstr (IMG_Name(img).c_str(), "flags_at_analysis_app")==NULL) { 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)) { // Prepare for processing of RTN, an RTN is not broken up into BBLs, // it is merely a sequence of INSs RTN_Open(rtn); for (INS ins = RTN_InsHead(rtn); INS_Valid(ins); ins = INS_Next(ins)) { if (INS_Opcode(ins)==XED_ICLASS_POPF || INS_Opcode(ins)==XED_ICLASS_POPFD || INS_Opcode(ins)==XED_ICLASS_POPFQ) { // popf is the marker printf ("found popf in rtn %s\n", RTN_Name(rtn).c_str()); if (!INS_Valid(INS_Next(ins)) || !INS_Valid(INS_Next(INS_Next(ins)))) { printf ("wrong popf marker found\n"); exit (-1); } printf ("next ins should be cmp al, 0x81 it is %s\n", INS_Disassemble(INS_Next(ins)).c_str()); printf ("next ins should be xor ecx, ecx it is %s\n", INS_Disassemble(INS_Next(INS_Next(ins))).c_str()); // Insert analysis calls to read the value of the flags register just after the cmp al, 0x81 - the OF flag should be set INS_InsertIfCall(INS_Next(INS_Next(ins)), IPOINT_BEFORE, (AFUNPTR)IfReturnTrue, IARG_INST_PTR, IARG_END); INS_InsertThenCall(INS_Next(INS_Next(ins)), IPOINT_BEFORE, (AFUNPTR)ThenFunc, IARG_REG_VALUE, REG_GFLAGS, IARG_END); INS_InsertCall(INS_Next(INS_Next(ins)), IPOINT_BEFORE, (AFUNPTR)AnalysisFunc, IARG_REG_VALUE, REG_GFLAGS, IARG_END); } } // to preserve space, release data associated with RTN after we have processed it RTN_Close(rtn); } } }
// Pin calls this function every time a new instruction is encountered VOID Instruction(INS ins, VOID *v) { if (INS_IsSyscall(ins) && INS_HasFallThrough(ins)) { // CountDown() is called for every instruction executed INS_InsertIfCall(ins, IPOINT_AFTER, (AFUNPTR)CountDown, IARG_END); // PrintIp() is called only when the last CountDown() returns a non-zero value. INS_InsertThenCall(ins, IPOINT_AFTER, (AFUNPTR)PrintIp, IARG_INST_PTR, IARG_END); // return value only available after INS_InsertCall(ins, IPOINT_AFTER, AFUNPTR(SysAfter), IARG_INST_PTR, IARG_END); } }
/* instrumenting (instruction level) */ VOID instrument_ppm(INS ins, VOID* v){ char cat[50]; strcpy(cat,CATEGORY_StringShort(INS_Category(ins)).c_str()); if(strcmp(cat,"COND_BR") == 0){ instrument_ppm_cond_br(ins); } /* inserting calls for counting instructions (full) is done in mica.cpp */ if(interval_size != -1){ INS_InsertIfCall(ins, IPOINT_BEFORE, (AFUNPTR)ppm_instr_intervals,IARG_END); /* only called if interval is 'full' */ INS_InsertThenCall(ins, IPOINT_BEFORE, (AFUNPTR)ppm_instr_interval,IARG_END); } }
// Insert instrumentation to count memory operations // The optimisations here are similar to those above. static VOID insertRepMemoryCountInstrumentation(INS ins, UINT32 opIdx) { const opInfo * op = &opcodes[opIdx]; if (takesConditionalRep(opIdx)) { INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)addMemops, IARG_UINT32, opIdx, IARG_EXECUTING, IARG_UINT32, op->reads, IARG_UINT32, op->writes, IARG_END); } else { INS_InsertIfCall(ins, IPOINT_BEFORE, (AFUNPTR)returnArg, IARG_FIRST_REP_ITERATION, IARG_END); INS_InsertThenCall(ins, IPOINT_BEFORE, (AFUNPTR)addMemops, IARG_UINT32, opIdx, IARG_REG_VALUE, INS_RepCountRegister(ins), IARG_UINT32, op->reads, IARG_UINT32, op->writes, IARG_END); } }
/* instrumenting (instruction level) */ VOID instrument_itypes(INS ins, VOID* v){ int i,j; char cat[50]; char opcode[50]; strcpy(cat,CATEGORY_StringShort(INS_Category(ins)).c_str()); strcpy(opcode,INS_Mnemonic(ins).c_str()); BOOL categorized = false; // go over all groups, increase group count if instruction matches that group // group counts are increased at most once per instruction executed, // even if the instruction matches multiple identifiers in that group for(i=0; i < number_of_groups; i++){ for(j=0; j < group_ids_cnt[i]; j++){ if(group_identifiers[i][j].type == identifier_type::ID_TYPE_CATEGORY){ if(strcmp(group_identifiers[i][j].str, cat) == 0){ INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)itypes_count, IARG_UINT32, i, IARG_END); categorized = true; break; } } else{ if(group_identifiers[i][j].type == identifier_type::ID_TYPE_OPCODE){ if(strcmp(group_identifiers[i][j].str, opcode) == 0){ INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)itypes_count, IARG_UINT32, i, IARG_END); categorized = true; break; } } else{ if(group_identifiers[i][j].type == identifier_type::ID_TYPE_SPECIAL){ if(strcmp(group_identifiers[i][j].str, "mem_read") == 0 && INS_IsMemoryRead(ins) ){ INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)itypes_count, IARG_UINT32, i, IARG_END); categorized = true; break; } else{ if(strcmp(group_identifiers[i][j].str, "mem_write") == 0 && INS_IsMemoryWrite(ins) ){ INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)itypes_count, IARG_UINT32, i, IARG_END); categorized = true; break; } else{ } } } else{ cerr << "ERROR! Unknown identifier type specified (" << group_identifiers[i][j].type << ")." << endl; } } } } } // count instruction that don't fit in any of the specified categories in the last group if( !categorized ){ INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)itypes_count, IARG_UINT32, (unsigned int)number_of_groups, IARG_END); // check whether this category is already known in the 'other' group for(i=0; i < other_ids_cnt; i++){ if(strcmp(other_group_identifiers[i].str, cat) == 0) break; } // if a new instruction category is found, add it to the set if(i == other_ids_cnt){ other_group_identifiers[other_ids_cnt].type = identifier_type::ID_TYPE_CATEGORY; other_group_identifiers[other_ids_cnt].str = (char*)malloc((strlen(cat)+1)*sizeof(char)); strcpy(other_group_identifiers[other_ids_cnt].str, cat); other_ids_cnt++; } // prepare for (possible) next category if(other_ids_cnt >= other_ids_max_cnt){ other_ids_max_cnt *= 2; other_group_identifiers = (identifier*)realloc(other_group_identifiers, other_ids_max_cnt*sizeof(identifier)); } } /* inserting calls for counting instructions is done in mica.cpp */ if(interval_size != -1){ INS_InsertIfCall(ins, IPOINT_BEFORE, (AFUNPTR)itypes_instr_intervals,IARG_END); /* only called if interval is 'full' */ INS_InsertThenCall(ins, IPOINT_BEFORE, (AFUNPTR)itypes_instr_interval,IARG_END); } }
VOID instrument_reg(INS ins, ins_buffer_entry* e){ UINT32 i, maxNumRegsProd, maxNumRegsCons, regReadCnt, regWriteCnt, opCnt, regOpCnt; REG reg; if(!e->setRead){ maxNumRegsCons = INS_MaxNumRRegs(ins); // maximum number of register consumations (reads) regReadCnt = 0; for(i = 0; i < maxNumRegsCons; i++){ // finding all register operands which are read reg = INS_RegR(ins,i); //assert(((UINT32)reg) < MAX_NUM_REGS); /* only consider valid general-purpose registers (any bit-width) and floating-point registers, * i.e. exlude branch, segment and pin registers, among others */ if(REG_valid(reg) && (REG_is_fr(reg) || REG_is_mm(reg) || REG_is_xmm(reg) || REG_is_gr(reg) || REG_is_gr8(reg) || REG_is_gr16(reg) || REG_is_gr32(reg) || REG_is_gr64(reg))){ regReadCnt++; } } e->regReadCnt = regReadCnt; e->regsRead = (REG*) checked_malloc(regReadCnt*sizeof(REG)); regReadCnt = 0; for(i = 0; i < maxNumRegsCons; i++){ // finding all register operands which are read reg = INS_RegR(ins,i); //assert(((UINT32)reg) < MAX_NUM_REGS); /* only consider valid general-purpose registers (any bit-width) and floating-point registers, * i.e. exlude branch, segment and pin registers, among others */ if(REG_valid(reg) && (REG_is_fr(reg) || REG_is_mm(reg) || REG_is_xmm(reg) || REG_is_gr(reg) || REG_is_gr8(reg) || REG_is_gr16(reg) || REG_is_gr32(reg) || REG_is_gr64(reg))){ e->regsRead[regReadCnt++] = reg; } } e->setRead = true; } if(!e->setWritten){ maxNumRegsProd = INS_MaxNumWRegs(ins); regWriteCnt = 0; for(i=0; i < maxNumRegsProd; i++){ reg = INS_RegW(ins, i); //assert(((UINT32)reg) < MAX_NUM_REGS); /* only consider valid general-purpose registers (any bit-width) and floating-point registers, * i.e. exlude branch, segment and pin registers, among others */ if(REG_valid(reg) && (REG_is_fr(reg) || REG_is_mm(reg) || REG_is_xmm(reg) || REG_is_gr(reg) || REG_is_gr8(reg) || REG_is_gr16(reg) || REG_is_gr32(reg) || REG_is_gr64(reg))){ regWriteCnt++; } } e->regWriteCnt = regWriteCnt; e->regsWritten = (REG*)checked_malloc(regWriteCnt*sizeof(REG)); regWriteCnt = 0; for(i=0; i < maxNumRegsProd; i++){ reg = INS_RegW(ins, i); //assert(((UINT32)reg) < MAX_NUM_REGS); /* only consider valid general-purpose registers (any bit-width) and floating-point registers, * i.e. exlude branch, segment and pin registers, among others */ if(REG_valid(reg) && (REG_is_fr(reg) || REG_is_mm(reg) || REG_is_xmm(reg) || REG_is_gr(reg) || REG_is_gr8(reg) || REG_is_gr16(reg) || REG_is_gr32(reg) || REG_is_gr64(reg))){ e->regsWritten[regWriteCnt++] = reg; } } e->setWritten = true; } if(!e->setRegOpCnt){ regOpCnt = 0; opCnt = INS_OperandCount(ins); for(i = 0; i < opCnt; i++){ if(INS_OperandIsReg(ins,i)) regOpCnt++; } /*if(regOpCnt >= MAX_NUM_OPER){ cerr << "BOOM! -> MAX_NUM_OPER is exceeded! (" << regOpCnt << ")" << endl; exit(1); }*/ e->regOpCnt = regOpCnt; e->setRegOpCnt = true; } if(interval_size == -1){ INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)reg_instr_full, IARG_PTR, (void*)e, IARG_END); } else{ INS_InsertIfCall(ins, IPOINT_BEFORE, (AFUNPTR)reg_instr_intervals, IARG_PTR, (void*)e, IARG_END); /* only called if interval is full */ INS_InsertThenCall(ins, IPOINT_BEFORE, (AFUNPTR)reg_instr_interval, IARG_END); } }
// Pin calls this function before a code sequence is executed for the first time VOID TraceCalls(INS ins, VOID *v) { // If we don't have a proper config, we cannot instrument anything if (config == NULL) { return; } ADDRINT addr = INS_Address(ins); IMG img = IMG_FindByAddress(addr); // We are interested only calls from the JITted code. That code is not part of any valid image if (IMG_Valid(img) && img != config->img) { return; } // We don't know the origins of the calls (only the targets) so we need to instrument every call if (INS_IsCall(ins)) { bool ok = false; if (INS_RegRContain(ins, REG_EAX) || INS_RegRContain(ins, REG_EDX)) { ok = true; } else if (INS_IsDirectCall(ins)) { ADDRINT target_addr = INS_DirectBranchOrCallTargetAddress(ins); IMG target_img = IMG_FindByAddress(target_addr); if (!IMG_Valid(img) || img == config->img) { ok = true; } } if (ok) { // Select which call analysis function to use depending on whether we are in fast mode AFUNPTR analysisFunc = (AFUNPTR)MethodCallAnalysis; if (KnobFast.Value()) { analysisFunc = (AFUNPTR)MethodCallAnalysisFast; } ADDRINT ret_addr = INS_NextAddress(ins); INS_InsertIfCall(ins, IPOINT_BEFORE, (AFUNPTR)ShouldCallBeAnalyzed, IARG_FUNCARG_CALLSITE_REFERENCE, 0, IARG_ADDRINT, ret_addr, IARG_BRANCH_TARGET_ADDR, IARG_END); INS_InsertThenCall(ins, IPOINT_BEFORE, analysisFunc, IARG_FUNCARG_CALLSITE_REFERENCE, 0, IARG_ADDRINT, ret_addr, IARG_BRANCH_TARGET_ADDR, IARG_END); returnAddressToInstument[ret_addr] = true; return; } } if (returnAddressToInstument.find(addr) != returnAddressToInstument.end()) { // Select which call analysis function to use depending on whether we are in fast mode AFUNPTR analysisFuncIf = (AFUNPTR)ShouldReturnAddressBeAnalyzed; AFUNPTR analysisFuncThen = (AFUNPTR)ReturnValueAnalysis; if (KnobFast.Value()) { analysisFuncIf = (AFUNPTR)ShouldReturnAddressBeAnalyzedFast; analysisFuncThen = (AFUNPTR)ReturnValueAnalysisFast; } INS_InsertIfCall(ins, IPOINT_BEFORE, analysisFuncIf, IARG_ADDRINT, addr, IARG_END); INS_InsertThenCall(ins, IPOINT_BEFORE, analysisFuncThen, IARG_ADDRINT, addr, IARG_REG_VALUE, REG_EAX, IARG_FUNCARG_CALLSITE_REFERENCE, 0, IARG_END); return; } }
VOID Instruction(INS ins, VOID *v) { //Should cause an error since Pin does not support IPOINT_ANYWHERE with the function: "INS_InsertThenCall" INS_InsertIfCall(ins, IPOINT_BEFORE , (AFUNPTR)IfFunction, IARG_END); INS_InsertThenCall(ins, IPOINT_ANYWHERE, (AFUNPTR)ThenFunction, IARG_END); }
VOID Instruction(INS ins, VOID *v) { UINT32 where = 0; if (INS_Opcode(ins) == XED_ICLASS_FNOP) { instrumenting = !instrumenting; } if (!instrumenting) return; #if (0) INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)printRegisterDiffs, IARG_THREAD_ID, IARG_CONTEXT, IARG_UINT32, where++, IARG_END); INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)printInstruction, IARG_THREAD_ID, IARG_ADDRINT, VoidStar2Addrint(formatInstruction(ins)), IARG_END); #endif INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)printRegisterDiffs, IARG_THREAD_ID, IARG_CONTEXT, IARG_UINT32, where++, IARG_END); // Find string ops only. if (INS_IsStringop(ins)) { for (UINT32 bit =0; bit < 5; bit++) { INS_InsertIfCall (ins, IPOINT_AFTER, (AFUNPTR)predicate, IARG_UINT32, bit, IARG_INST_PTR, IARG_END); INS_InsertThenCall (ins, IPOINT_AFTER, (AFUNPTR)addCount,IARG_UINT32, bit, IARG_END); } INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)printRegisterDiffs, IARG_THREAD_ID, IARG_CONTEXT, IARG_UINT32, where++, IARG_END); INS_InsertCall (ins, IPOINT_BEFORE, (AFUNPTR)countInst, IARG_UINT32, 0, IARG_END); INS_InsertCall (ins, IPOINT_AFTER, (AFUNPTR)countInst, IARG_UINT32, 1, IARG_END); INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)printRegisterDiffs, IARG_THREAD_ID, IARG_CONTEXT, IARG_UINT32, where++, IARG_END); INS_InsertCall( ins, IPOINT_BEFORE, (AFUNPTR) printSz, IARG_MEMORYREAD_SIZE, IARG_INST_PTR, IARG_EXECUTING, IARG_REG_VALUE, REG_ECX, IARG_END); INS_InsertCall( ins, IPOINT_AFTER, (AFUNPTR) printCntVal, IARG_REG_VALUE,REG_ECX, IARG_END); INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)printRegisterDiffs, IARG_THREAD_ID, IARG_CONTEXT, IARG_UINT32, where++, IARG_END); INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR) printSzPredicated, IARG_MEMORYREAD_SIZE, IARG_INST_PTR, IARG_EXECUTING, IARG_REG_VALUE, REG_ECX, IARG_END); INS_InsertPredicatedCall( ins, IPOINT_AFTER, (AFUNPTR) printCntValPredicated, IARG_REG_VALUE,REG_ECX, IARG_END); INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)printRegisterDiffs, IARG_THREAD_ID, IARG_CONTEXT, IARG_UINT32, where++, IARG_END); if (INS_HasRealRep(ins)) { INS_InsertIfCall(ins, IPOINT_BEFORE, (AFUNPTR)firstTime, IARG_END); INS_InsertThenCall(ins, IPOINT_BEFORE, (AFUNPTR)checkFirstRep, IARG_FIRST_REP_ITERATION, IARG_END); INS_InsertCall (ins, IPOINT_BEFORE, (AFUNPTR)countReps, IARG_FIRST_REP_ITERATION, IARG_EXECUTING, IARG_END); } } }
// 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); } } }