/* 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); } }
VOID Instruction(INS ins, VOID *v) { for (REG reg=REG_XMM_BASE; reg <= REG_XMM_LAST; reg=static_cast<REG>((static_cast<INT32>(reg)+1))) { if (INS_RegRContain(ins, reg)) { INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(TestXmm), IARG_INST_PTR, IARG_REG_REFERENCE, reg, IARG_REG_REFERENCE, REG_XMM1, IARG_ADDRINT, READ, IARG_ADDRINT, (reg-REG_XMM_BASE), IARG_END); fprintf(outfile,"Instrumented read on ins %p %s\n", (void *)(INS_Address(ins)), INS_Disassemble(ins).c_str()); fflush (outfile); } if (INS_RegWContain(ins, reg)) { INS_InsertCall(ins, IPOINT_AFTER, AFUNPTR(TestXmm), IARG_INST_PTR, IARG_REG_REFERENCE, reg, IARG_REG_REFERENCE, REG_XMM1, IARG_ADDRINT, WRITE, IARG_ADDRINT, (reg-REG_XMM_BASE), IARG_END); fprintf(outfile,"Instrumented write on ins %p %s\n", (void *)(INS_Address(ins)), INS_Disassemble(ins).c_str()); fflush (outfile); } } }
VOID Image(IMG img, void *v) { 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); numRtnsFoundInImageCallback++; INS ins = RTN_InsHeadOnly(rtn); if (INS_Invalid() == ins) { // no instruction found - assert that RTN_InsHead(rtn) also doesn't find any INS ASSERTX (INS_Invalid() == RTN_InsHead(rtn)); RTN_Close(rtn); continue; } if (INS_HasFallThrough(ins)) { ADDRINT insAddress = INS_Address(ins); numRtnsInstrumentedFromImageCallback++; RTN_InsertCall( rtn, IPOINT_BEFORE, AFUNPTR(AtRtn), IARG_ADDRINT, RTN_Address(rtn), IARG_END); INS_InsertCall (ins, IPOINT_BEFORE, AFUNPTR(BeforeInsHeadOnly), IARG_ADDRINT, INS_Address(ins), IARG_END); INS_InsertCall (ins, IPOINT_AFTER, AFUNPTR(AfterInsHeadOnly), IARG_ADDRINT, INS_Address(ins), IARG_END); ins = RTN_InsHead(rtn); ASSERTX(INS_Invalid() != ins); ASSERTX(INS_Address(ins)==insAddress); INS_InsertCall (ins, IPOINT_BEFORE, AFUNPTR(BeforeInsHead), IARG_ADDRINT, insAddress, IARG_END); INS_InsertCall (ins, IPOINT_AFTER, AFUNPTR(AfterInsHead), IARG_ADDRINT, insAddress, IARG_END); } RTN_Close(rtn); } } }
VOID Trace (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)) { xed_iclass_enum_t iclass1 = static_cast<xed_iclass_enum_t>(INS_Opcode(ins)); if (iclass1 == XED_ICLASS_FLD1 && INS_Valid(INS_Next(ins))) { xed_iclass_enum_t iclass2 = static_cast<xed_iclass_enum_t>(INS_Opcode(INS_Next(ins))); if (iclass2 == XED_ICLASS_FLD1 && INS_Valid(INS_Next(INS_Next(ins)))) { xed_iclass_enum_t iclass3 = static_cast<xed_iclass_enum_t>(INS_Opcode(INS_Next(INS_Next(ins)))); if (iclass3 == XED_ICLASS_FLD1) { printf ("found fld1 sequence at %lx\n", (unsigned long)(INS_Address(INS_Next(INS_Next(ins))))); if (testNum == 0) { INS_InsertCall(INS_Next(INS_Next(ins)), IPOINT_AFTER, AFUNPTR(CallToUnMaskZeroDivideInMxcsr), IARG_END); printf ("Inserted call1 to UnMaskZeroDivideInMxcsr after instruction at %lx\n", (unsigned long)(INS_Address(INS_Next(INS_Next(ins))))); testNum++; } return; } } } } } }
VOID Trace(TRACE trace, VOID *v) { const INS beginIns = BBL_InsHead(TRACE_BblHead(trace)); const INS endIns = BBL_InsTail(TRACE_BblTail(trace)); const ADDRINT beginAddr = INS_Address(beginIns); const ADDRINT endAddr = INS_Address(endIns) + INS_Size(endIns) - 1; sandbox.CheckAddressRange(reinterpret_cast<const char *>(beginAddr), reinterpret_cast<const char *>(endAddr)); }
VOID instrument_ppm_cond_br(INS ins){ UINT32 index = index_condBr(INS_Address(ins)); if(index < 1){ /* We don't know the number of static conditional branch instructions up front, * so we double the size of the branch history tables as needed by calling this function */ if(numStatCondBranchInst >= brHist_size) reallocate_brHist(); index = numStatCondBranchInst; register_condBr(INS_Address(ins)); } INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)condBr, IARG_UINT32, index, IARG_BRANCH_TAKEN, IARG_END); }
VOID Instruction(INS ins, VOID *v) { ADDRINT loc = INS_Address(ins); if (gLogStart != -1 && loc == gLogStart) { INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)StartLogging, IARG_INST_PTR, IARG_END); } if (gLogStop != -1 && loc == gLogStop) { INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)StopLogging, IARG_INST_PTR, IARG_END); } if (loc >= moduleStart && loc <= moduleEnd) { INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)IncrementCount, IARG_INST_PTR, IARG_END); } }
VOID Trace(TRACE trace, VOID *v) { for (BBL bbl = TRACE_BblHead(trace); BBL_Valid(bbl); bbl = BBL_Next(bbl)) { DBG_PRINT(printf("Inst: Sequence address %p\n",(CHAR*)(INS_Address(BBL_InsHead(bbl))))); for (INS ins = BBL_InsHead(bbl); INS_Valid(ins); ins = INS_Next(ins)) { DBG_PRINT(printf("Inst: %p\n",(CHAR*)(INS_Address(ins)))); INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(docount_ins), IARG_INST_PTR, IARG_END); } INT32 icount = BBL_NumIns(bbl); DBG_PRINT(printf("Inst: -> control flow change (bbl size %d)\n", icount)); INS_InsertCall(BBL_InsTail(bbl), IPOINT_BEFORE, AFUNPTR(docount_bbl_ins), IARG_INST_PTR, IARG_UINT32, icount, IARG_END); } }
VOID Trace (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)) { xed_iclass_enum_t iclass1 = static_cast<xed_iclass_enum_t>(INS_Opcode(ins)); if (iclass1 == XED_ICLASS_FLD1 && INS_Valid(INS_Next(ins))) { xed_iclass_enum_t iclass2 = static_cast<xed_iclass_enum_t>(INS_Opcode(INS_Next(ins))); if (iclass2 == XED_ICLASS_FLD1 && INS_Valid(INS_Next(INS_Next(ins)))) { xed_iclass_enum_t iclass3 = static_cast<xed_iclass_enum_t>(INS_Opcode(INS_Next(INS_Next(ins)))); if (iclass3 == XED_ICLASS_FLD1) { printf ("tool: found fld1 sequence at %p\n", (void *)INS_Address(INS_Next(INS_Next(ins)))); fflush (stdout); // Insert an analysis call that will cause the xmm scratch registers to be spilled INS_InsertCall(INS_Next(INS_Next(ins)), IPOINT_AFTER, (AFUNPTR)SetXmmScratchesFun, IARG_END); return; } } } } } }
// record the page(s) occupied by the instruction VOID SANDBOX::RecordIns(INS ins) { const ADDRINT beginAddr = INS_Address(ins); const ADDRINT endAddr = beginAddr + INS_Size(ins) - 1; RecordAddressRange(reinterpret_cast<const char *>(beginAddr), reinterpret_cast<const char *>(endAddr)); }
/** * Converts a PIN instruction object into a disassembled string. **/ std::string dumpInstruction(INS ins) { std::stringstream ss; ADDRINT address = INS_Address(ins); // Generate address and module information ss << "0x" << setfill('0') << setw(8) << uppercase << hex << address << "::" << getModule(address) << " "; // Generate instruction byte encoding for (int i=0;i<INS_Size(ins);i++) { ss << setfill('0') << setw(2) << (((unsigned int) *(unsigned char*)(address + i)) & 0xFF) << " "; } for (int i=INS_Size(ins);i<8;i++) { ss << " "; } // Generate diassembled string ss << INS_Disassemble(ins); // Look up call information for direct calls if (INS_IsCall(ins) && INS_IsDirectBranchOrCall(ins)) { ss << " -> " << RTN_FindNameByAddress(INS_DirectBranchOrCallTargetAddress(ins)); } return ss.str(); }
// Is called for every instruction and instruments reads and writes VOID Instruction(INS ins, VOID *v) { BOOL hasReadSegmentedMemAccess = FALSE; BOOL hasWriteSegmentedMemAccess = FALSE; if (INS_SegmentRegPrefix(ins) == TESTED_SEG_REG) //INS_OperandMemorySegmentReg, INS_SegPrefixIsMemoryRead, INS_OperandMemoryDisplacement { if (INS_IsMemoryRead(ins)) { HandleAccess (ins, TRUE /* isRead*/, &hasReadSegmentedMemAccess) ; } if (INS_IsMemoryWrite(ins)) { HandleAccess (ins, FALSE /* isRead*/, &hasWriteSegmentedMemAccess); } if (!hasReadSegmentedMemAccess && !hasWriteSegmentedMemAccess) { fprintf(trace, "**ERROR SegMemAccess-Lies %p %s\n", INS_Address(ins), INS_Disassemble(ins).c_str()); hadError = TRUE; } } /*fprintf(trace, "%p %s\n", INS_Address(ins), INS_Disassemble(ins).c_str()); fflush (trace);*/ }
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); } }
// Offset the addressing of the first "or" instruction back by 4 bytes. static VOID modifyAddressing (RTN rtn) { for (INS ins = RTN_InsHead(rtn); INS_Valid(ins); ins = INS_Next(ins)) { if (INS_Opcode(ins) == XED_ICLASS_OR) { printf ("Rewriting address of ins\n%x: %s\n", INS_Address(ins), INS_Disassemble(ins).c_str()); // pass the original memory address accessed by the app instruction (i.e. before the rewrite) to AddrValueA INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(AddrValueA), IARG_MEMORYOP_EA, 0, IARG_END); INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(returnValueMinus4), IARG_MEMORYOP_EA, 0, IARG_RETURN_REGS, scratchReg, IARG_END); INS_RewriteMemoryOperand(ins, 0, scratchReg); // pass the original memory address accessed by the app instruction (i.e. before the rewrite) to AddrValueB INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(AddrValueB), IARG_MEMORYOP_EA, 0, IARG_END); instrumentationCount++; return; } } }
// 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); } }
/** * This function is called **/ void traceInst(INS ins, VOID*) { ADDRINT address = INS_Address(ins); if (isUnknownAddress(address)) { // The address is an address that does not belong to any loaded module. // This is potential shellcode. For these instructions a callback // function is inserted that dumps information to the trace file when // the instruction is actually executed. INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(dump_shellcode), IARG_PTR, new std::string(dumpInstruction(ins)), IARG_END ); } else { // The address is a legit address, meaning it is probably not part of // any shellcode. In this case we just log the instruction to dump it // later to show when control flow was transfered from legit code to // shellcode. legitInstructions.push_back(dumpInstruction(ins)); if (legitInstructions.size() > MAX_LEGIT_INSTRUCTION_LOG_SIZE) { // Log only up to MAX_LEGIT_INSTRUCTION_LOG_SIZE instructions or the whole // program before the shellcode will be dumped. legitInstructions.pop_front(); } } }
VOID Trace(TRACE trace, VOID *v) { BOOL rewrite = false; 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 we see an instruction that needs rewriting, then rewrite all if (SwizzleRefs.find(INS_Address(ins)) != SwizzleRefs.end()) rewrite = true; if (rewrite) { // If we suspect this instruction needs to be swizzled, generate safe, but slow code RewriteIns(ins); } else { // Generate code to check if swizzling is needed, but not do it CheckIns(ins, TRACE_Address(trace)); } } } }
VOID Trace (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)) { xed_iclass_enum_t iclass1 = static_cast<xed_iclass_enum_t>(INS_Opcode(ins)); if (iclass1 == XED_ICLASS_FLD1 && INS_Valid(INS_Next(ins))) { xed_iclass_enum_t iclass2 = static_cast<xed_iclass_enum_t>(INS_Opcode(INS_Next(ins))); if (iclass2 == XED_ICLASS_FLD1 && INS_Valid(INS_Next(INS_Next(ins)))) { xed_iclass_enum_t iclass3 = static_cast<xed_iclass_enum_t>(INS_Opcode(INS_Next(INS_Next(ins)))); if (iclass3 == XED_ICLASS_FLD1) { printf ("found fld1 sequence at %x\n", INS_Address(INS_Next(INS_Next(ins)))); { INS_InsertCall(INS_Next(INS_Next(ins)), IPOINT_AFTER, AFUNPTR(CallToFldzToTop3), IARG_END); printf ("Inserted call1 to FldzToTop3 after instruction at %x\n", INS_Address(INS_Next(INS_Next(ins)))); } } } } } } }
VOID Instruction(INS ins, VOID *v) { INS_InsertCall( ins, IPOINT_BEFORE, (AFUNPTR)insCallBack, IARG_ADDRINT, INS_Address(ins), IARG_PTR, new string(INS_Disassemble(ins)), IARG_END); }
VOID Instruction_ilp_one_only(INS ins, VOID* v){ INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)all_instr_full_count_always,IARG_THREAD_ID, IARG_END); ADDRINT insAddr = INS_Address(ins); ins_buffer_entry* e = findInsBufferEntry(insAddr); instrument_ilp_one(ins, e); }
VOID instruction_instrument(INS ins, VOID *v){ INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)do_count, IARG_ADDRINT, INS_Address( ins ), IARG_END); int MEM = 0; /* capture memory I/O here also */ if ( MEM ){ ; } }
static VOID Trace(TRACE trace, VOID *v) { RTN rtn = TRACE_Rtn(trace); ADDRINT version = TRACE_Version(trace); // If we are not in watch_rtn, switch back to base version if (!RTN_Valid(rtn) || RTN_Name(rtn) != watch_rtn) { if (version != VERSION_BASE) BBL_SetTargetVersion(TRACE_BblHead(trace), VERSION_BASE); return; } if (TRACE_Address(trace) == RTN_Address(rtn)) { INS ins = BBL_InsHead(TRACE_BblHead(trace)); if (version == VERSION_BASE) { // version_reg is used to select the version, use the first // argument of watch_rtn to set it INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(select_version), IARG_FUNCARG_ENTRYPOINT_VALUE, 0, IARG_RETURN_REGS, version_reg, IARG_END); // IF we are in the base version, decide if we should go to the // other versions // Note that the version instrumentation will occur before any // following instrumentation done on this ins INS_InsertVersionCase(ins, version_reg, 10, VERSION_1, IARG_END); INS_InsertVersionCase(ins, version_reg, 20, VERSION_2, IARG_END); printf ("Instrumentation at %p\n", reinterpret_cast<void *>(INS_Address(ins))); } } INS ins = BBL_InsHead(TRACE_BblHead(trace)); for (BBL bbl = TRACE_BblHead(trace); BBL_Valid(bbl); bbl = BBL_Next(bbl)) { // Instrumentation depends on version // These instrumentations occur after the preceeding version instrumentation // (i.e. the instrumentation inserted by the above INS_InsertVersionCase calls switch(version) { case VERSION_BASE: INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(Emit), IARG_PTR, "version base", IARG_END); break; case VERSION_1: INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(Emit), IARG_PTR, "version 1", IARG_END); break; case VERSION_2: INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(Emit), IARG_PTR, "version 2", IARG_END); break; default: assert(0); break; } } }
VOID Instruction(INS ins, VOID *v) { if (INS_OperandCount(ins) > 1 && INS_MemoryOperandIsRead(ins, 0) && INS_OperandIsReg(ins, 0)){ INS_InsertCall( ins, IPOINT_BEFORE, (AFUNPTR)ReadMem, IARG_ADDRINT, INS_Address(ins), IARG_PTR, new string(INS_Disassemble(ins)), IARG_UINT32, INS_OperandCount(ins), IARG_UINT32, INS_OperandReg(ins, 0), IARG_MEMORYOP_EA, 0, IARG_REG_VALUE, REG_STACK_PTR, IARG_END); } else if (INS_OperandCount(ins) > 1 && INS_MemoryOperandIsWritten(ins, 0)){ INS_InsertCall( ins, IPOINT_BEFORE, (AFUNPTR)WriteMem, IARG_ADDRINT, INS_Address(ins), IARG_PTR, new string(INS_Disassemble(ins)), IARG_UINT32, INS_OperandCount(ins), IARG_UINT32, INS_OperandReg(ins, 1), IARG_MEMORYOP_EA, 0, IARG_REG_VALUE, REG_STACK_PTR, IARG_END); } else if (INS_OperandCount(ins) > 1 && INS_OperandIsReg(ins, 0)){ INS_InsertCall( ins, IPOINT_BEFORE, (AFUNPTR)spreadRegTaint, IARG_ADDRINT, INS_Address(ins), IARG_PTR, new string(INS_Disassemble(ins)), IARG_UINT32, INS_OperandCount(ins), IARG_UINT32, INS_RegR(ins, 0), IARG_UINT32, INS_RegW(ins, 0), IARG_END); } if (INS_OperandCount(ins) > 1 && INS_OperandIsReg(ins, 0)){ INS_InsertCall( ins, IPOINT_BEFORE, (AFUNPTR)followData, IARG_ADDRINT, INS_Address(ins), IARG_PTR, new string(INS_Disassemble(ins)), IARG_UINT32, INS_RegR(ins, 0), IARG_END); } }
void InstructionTrace(INS ins, void* v) { // check if we just received a snapshot request bool snapshotStatus = CheckSnapshotEvent(); if (snapshotStatus) { // We just detected a monitoring change! Take a memory snapshot now TakeSnapshot(); // reset the event DisableSnapshotEvent(); } // check the monitoring event if we should still be monitoring or not bool monitoringStatus = CheckMonitoringEvent(); if (!monitoringStatus) { return; } instruction_trace trace; trace.tid = PIN_GetTid(); trace.address = INS_Address(ins); memset(trace.library_name, 0, 260); std::string libraryName; if (CHECK_LIBRARY_NAMES && GetLibraryName(trace.address, libraryName)) { snprintf(trace.library_name, sizeof(trace.library_name), "%s", libraryName.c_str()); } if (INS_IsCall(ins) == true) { trace.execution_depth = executionDepth++; } else if (INS_IsRet(ins) == true) { trace.execution_depth = executionDepth--; } else trace.execution_depth = executionDepth; trace.instruction_count = instructionCount++; #ifdef TARGET_WINDOWS trace.execution_time = WINDOWS::GetTickCount(); #else timeval time; gettimeofday(&time, NULL); unsigned long millis = (time.tv_sec * 1000) + (time.tv_usec / 1000); trace.execution_time = millis; #endif LogStruct(trace); }
VOID Instruction(INS ins, VOID *v) { if (INS_MemoryOperandIsRead(ins, 0) && INS_OperandIsReg(ins, 0)){ INS_InsertCall( ins, IPOINT_BEFORE, (AFUNPTR)ReadMem, IARG_ADDRINT, INS_Address(ins), IARG_PTR, new string(INS_Disassemble(ins)), IARG_MEMORYOP_EA, 0, IARG_END); } else if (INS_MemoryOperandIsWritten(ins, 0)){ INS_InsertCall( ins, IPOINT_BEFORE, (AFUNPTR)WriteMem, IARG_ADDRINT, INS_Address(ins), IARG_PTR, new string(INS_Disassemble(ins)), IARG_MEMORYOP_EA, 0, IARG_END); } }
/* We simply allocate space for the dis-assembled instruction strings and * let them leak. */ static char const * formatInstruction(INS ins) { ADDRINT ip = INS_Address(ins); string formatted = hexstr(ip) + " " + INS_Disassemble(ins); char * res = new char [formatted.length()+1]; strcpy (res, formatted.c_str()); return res; }
// Insert a call to an analysis routine that sets the scratch xmm registers, the call is inserted just after the // movdqa instruction of DoXmm (see xmm-asm-*.s) static VOID InstrumentRoutine(RTN rtn, VOID *) { if (RTN_Name(rtn) == "DoXmm") { RTN_Open(rtn); for (INS ins = RTN_InsHead(rtn); INS_Valid(ins); ins = INS_Next(ins)) { if (INS_Opcode(ins)==XED_ICLASS_MOVDQA) { fprintf (fp, "instrumenting ins %p %s\n", (void *)INS_Address(ins), INS_Disassemble(ins).c_str()); instrumentedMovdqa = TRUE; INS_InsertCall(ins, IPOINT_AFTER, (AFUNPTR)SetXmmScratchesFun, IARG_PTR, xmmInitVals, IARG_END); ipAfterMovdqa = INS_Address(INS_Next(ins)); fprintf (fp, "ipAfterMovdqa ins %p %s\n", (void *)ipAfterMovdqa, INS_Disassemble(INS_Next(ins)).c_str()); fflush (fp); } } RTN_Close(rtn); } }
// Insert a direct branch over the first mov immediate static VOID insertJump (RTN rtn) { for (INS ins = RTN_InsHead(rtn); INS_Valid(ins); ins = INS_Next(ins)) { if (INS_IsMov(ins) && INS_HasImmediateOperand(ins)) { INS_InsertDirectJump(ins, IPOINT_BEFORE, INS_Address(ins) + INS_Size(ins)); instrumentationCount++; return; } } }
VOID Trace(TRACE trace, VOID *v) { static BOOL programStart = TRUE; if (programStart) { programStart = FALSE; next_pc = (void*)INS_Address(BBL_InsHead(TRACE_BblHead(trace))); } for (BBL bbl = TRACE_BblHead(trace); BBL_Valid(bbl); bbl = BBL_Next(bbl)) { // check BBL entry PC INS_InsertCall( BBL_InsHead(bbl), IPOINT_BEFORE, (AFUNPTR)CheckPc, IARG_INST_PTR, IARG_END); INS tail = BBL_InsTail(bbl); if (INS_IsBranchOrCall(tail)) { // record taken branch targets INS_InsertCall( tail, IPOINT_BEFORE, AFUNPTR(RecordPc), IARG_INST_PTR, IARG_BRANCH_TARGET_ADDR, IARG_BRANCH_TAKEN, IARG_END); } if (INS_HasFallThrough(tail)) { // record fall-through INS_InsertCall( tail, IPOINT_AFTER, (AFUNPTR)RecordPc, IARG_INST_PTR, IARG_FALLTHROUGH_ADDR, IARG_BOOL, TRUE, IARG_END); } #if defined(TARGET_IA32) || defined(TARGET_IA32E) if (INS_IsSysenter(tail) || INS_HasRealRep(tail)) { // sysenter on x86 has some funny control flow that we can't correctly verify for now // Genuinely REP prefixed instructions are also odd, they appear to stutter. INS_InsertCall(tail, IPOINT_BEFORE, (AFUNPTR)Skip, IARG_END); } #endif } }
VOID DumpTrace(CHAR * message, TRACE trace) { fprintf(stderr,"\n%s:\n",message); 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)) { fprintf(stderr,"%p %s\n",(void*)INS_Address(ins),INS_Disassemble(ins).c_str()); } } }