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 instrumentTrace( TRACE trace, VOID *v ) { for ( BBL bbl = TRACE_BblHead( trace ); BBL_Valid( bbl ); bbl = BBL_Next( bbl ) ) { INS ins = BBL_InsHead( bbl ); INS_InsertCall( ins, IPOINT_BEFORE, (AFUNPTR) startBasicBlock, IARG_THREAD_ID, IARG_CONTEXT, IARG_UINT32, BBL_NumIns( bbl ), IARG_END ); UINT32 instPos = 0; for ( ; INS_Valid( ins ); ins = INS_Next( ins ) ) { if ( INS_IsMemoryRead( ins ) ) { INS_InsertCall( ins, IPOINT_BEFORE, (AFUNPTR) memOp, IARG_THREAD_ID, IARG_UINT32, instPos, IARG_MEMORYREAD_EA, IARG_MEMORYREAD_SIZE, IARG_BOOL, true, IARG_BOOL, INS_IsStackRead( ins ), IARG_END ); } if ( INS_IsMemoryWrite( ins ) ) { INS_InsertCall( ins, IPOINT_BEFORE, (AFUNPTR) memOp, IARG_THREAD_ID, IARG_UINT32, instPos, IARG_MEMORYWRITE_EA, IARG_MEMORYWRITE_SIZE, IARG_BOOL, false, IARG_BOOL, INS_IsStackWrite( ins ), IARG_END ); } instPos++; } } }
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); } }
// Is called for every instruction and instruments reads and writes VOID Instruction(INS ins, VOID *v) { BOOL readsMemory, writesMemory, hasReadSegmentedMemAccess, hasWriteSegmentedMemAccess; if (INS_EffectiveAddressWidth(ins)==16) { if (INS_SegmentRegPrefix(ins) == TESTED_SEG_REG) { readsMemory = INS_SegPrefixIsMemoryRead(ins); writesMemory = INS_SegPrefixIsMemoryWrite(ins); if(readsMemory) { if (INS_IsMemoryRead(ins)) { HandleSegmentedAccess (ins, TRUE /* isRead*/, &hasReadSegmentedMemAccess) ; } } if (writesMemory) { if (INS_IsMemoryWrite(ins)) { HandleSegmentedAccess (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; } else { fprintf (trace, "Instrumented ins: %x %s\n", INS_Address(ins), INS_Disassemble(ins).c_str()); } fflush(trace); } else if (INS_IsMemoryRead(ins) || INS_IsMemoryWrite(ins)) { fprintf (trace, "Instrumented ins: %x %s\n", INS_Address(ins), INS_Disassemble(ins).c_str()); fflush (trace); HandleAccess (ins, INS_IsMemoryRead(ins)) ; } } #ifndef TARGET_LINUX UINT32 operandCount = INS_OperandCount (ins); UINT32 i; for (i=0; i<operandCount; i++) { if (INS_OperandIsReg (ins, i) && REG_is_seg(INS_OperandReg (ins, i)) && INS_OperandWritten(ins, i)) { fprintf(trace, "**ERROR SegOperand-WRITE, not supported %p %s\n", INS_Address(ins), INS_Disassemble(ins).c_str()); fflush(trace); hadError = TRUE; } } #endif /*fprintf(trace, "%p %s\n", INS_Address(ins), INS_Disassemble(ins).c_str()); fflush (trace);*/ }
VOID Emulate2Address(OPCODE opcode, INS ins, ADDRINT (*OpRM)(ADDRINT,ADDRINT*), ADDRINT (*OpRV)(ADDRINT,ADDRINT), VOID (*OpMV)(ADDRINT*,ADDRINT)) { if (INS_Opcode(ins) != opcode) return; if (INS_OperandIsMemory(ins, 0) // This will filter out segment overrides && INS_IsMemoryWrite(ins)) { if (INS_OperandIsReg(ins, 1) && REG_is_gr(INS_OperandReg(ins, 1))) { // Source register, dst memory INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(OpMV), IARG_MEMORYWRITE_EA, IARG_REG_VALUE, INS_OperandReg(ins, 1), IARG_END); INS_Delete(ins); } else { ASSERTX(!INS_OperandIsMemory(ins, 1)); } } else if (INS_OperandIsReg(ins, 0)) { REG dst = INS_OperandReg(ins, 0); if ((dst == REG_SEG_GS) || (dst == REG_SEG_FS)) return; if (INS_OperandIsReg(ins, 1)) { // Source register, dst register INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(OpRV), IARG_REG_VALUE, INS_OperandReg(ins, 0), IARG_REG_VALUE, INS_OperandReg(ins, 1), IARG_RETURN_REGS, INS_OperandReg(ins, 0), IARG_END); INS_Delete(ins); } else if (INS_OperandIsMemory(ins, 1) // This will filter out segment overrides && INS_IsMemoryRead(ins)) { // Source register, dst register INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(OpRM), IARG_REG_VALUE, INS_OperandReg(ins, 0), IARG_MEMORYREAD_EA, IARG_RETURN_REGS, INS_OperandReg(ins, 0), IARG_END); INS_Delete(ins); } } #if 0 if (KnobCount == icount) fprintf(stderr,"Last one %s\n",INS_Disassemble(ins).c_str()); else if (icount > KnobCount) return; icount++; #endif }
VOID Instruction(INS ins, VOID *v) { if (INS_IsMemoryRead(ins) && !instrumentedReadFromIpWithNoOffset) { BOOL readsFromIpWithNoOffset = FALSE; for (UINT32 i = 0; i < INS_OperandCount(ins); i++) { if (!INS_OperandIsMemory(ins, i)) continue; if (INS_OperandMemoryBaseReg(ins, i) == REG_INST_PTR && INS_OperandMemoryDisplacement(ins, i)==0) { readsFromIpWithNoOffset = TRUE; break; } } if (!readsFromIpWithNoOffset) { return; } instrumentedReadFromIpWithNoOffset = TRUE; // only instrument one of these printf ("Instrumenting [ip] read %p %s\n", INS_Address(ins), INS_Disassemble(ins).c_str()); globalIpOfReadRecordedAtInstrumentationTime = INS_Address(ins); globalReadInsSize = INS_Size(ins); fflush (stdout); INS_InsertCall(ins,IPOINT_BEFORE, (AFUNPTR)IpReadBefore, IARG_INST_PTR, IARG_MEMORYREAD_EA, IARG_REG_VALUE, REG_INST_PTR, IARG_END); INS_InsertCall(ins,IPOINT_AFTER, (AFUNPTR)IpReadAfter, IARG_REG_VALUE, REG_INST_PTR, IARG_END); } else if (INS_IsMemoryWrite(ins) && !instrumentedWriteFromIpWithNoOffset) { /* const xed_decoded_inst_t* xedd = INS_XedDec(ins); xed_reg_enum_t breg1 = xed_decoded_inst_get_base_reg(xedd,0); if (breg1== XED_REG_RIP) { readsFromIpWithNoOffset = TRUE; } */ BOOL writesFromIpWithNoOffset = FALSE; for (UINT32 i = 0; i < INS_OperandCount(ins); i++) { if (!INS_OperandIsMemory(ins, i)) continue; if (INS_OperandMemoryBaseReg(ins, i) == REG_INST_PTR && INS_OperandMemoryDisplacement(ins, i)==0) { writesFromIpWithNoOffset = TRUE; break; } } if (!writesFromIpWithNoOffset) { return; } instrumentedReadFromIpWithNoOffset = TRUE; // only instrument one of these printf ("Instrumenting [ip] write %p %s\n", INS_Address(ins), INS_Disassemble(ins).c_str()); globalIpOfWriteRecordedAtInstrumentationTime = INS_Address(ins); globalWriteInsSize = INS_Size(ins); fflush (stdout); INS_InsertCall(ins,IPOINT_BEFORE, (AFUNPTR)IpWriteBefore, IARG_INST_PTR, IARG_MEMORYWRITE_EA, IARG_REG_VALUE, REG_INST_PTR, IARG_END); INS_InsertCall(ins,IPOINT_AFTER, (AFUNPTR)IpWriteAfter, IARG_REG_VALUE, REG_INST_PTR, 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 Instruction(INS ins, void * v) { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR) ExecInst, IARG_END); ADDRINT iaddr = INS_Address(ins); //if (iaddr > 42254050) //{ // RTN rtn = INS_Rtn(ins); // cout << RTN_Name(rtn) << ":\t"; // cout << hex << iaddr << INS_Disassemble(ins) << endl; //} 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_INST_PTR, IARG_MEMORYREAD_EA, IARG_END); } else { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR) LoadMulti, //IARG_INST_PTR, 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 ) { g_hWriteInstIsL[iaddr] = false; INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR) StoreSingle, //IARG_INST_PTR, IARG_ADDRINT, iaddr, IARG_MEMORYWRITE_EA, IARG_END); } else { for( UINT32 i = 0; i < size; ++ i) { ADDRINT addr1 = iaddr + (i << 2); g_hWriteInstIsL[addr1] = false; } INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR) StoreMulti, //IARG_INST_PTR, IARG_ADDRINT, iaddr, IARG_MEMORYWRITE_EA, IARG_MEMORYWRITE_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); } }
// This function is called before every instruction is executed VOID instrument_routine(RTN rtn, void *ip) { string name = RTN_Name(rtn); if(name == "ivan") { RTN_Open(rtn); for (INS ins = RTN_InsHead(rtn); INS_Valid(ins); ins = INS_Next(ins)) { int opCount = INS_OperandCount(ins); int opcode = INS_Opcode(ins); if(INS_IsMemoryRead(ins)) { for(int i = 0; i< opCount; i++) { if(INS_MemoryOperandIsRead(ins,i)) { /* INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)RecordMemRead,IARG_PTR,ins, IARG_INST_PTR, IARG_MEMORYOP_EA, i, IARG_END); */ cout<<"opcode:"<<INS_Opcode(ins)<<", mnemonic: "<<INS_Mnemonic(ins)<<endl; if(INS_Opcode(ins)!= XED_ICLASS_RET_NEAR) { REG scratchReg = GetScratchReg(i); INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(GetMemAddress), IARG_MEMORYOP_EA, i, IARG_RETURN_REGS, scratchReg, IARG_END); INS_RewriteMemoryOperand(ins, i, scratchReg); } } } } if(INS_IsMemoryWrite(ins)) { for(int i = 0; i< opCount; i++) { /* if(INS_OperandIsImmediate(ins,i)) { cout<<"immediate "<<INS_OperandImmediate(ins,i)<<endl; } */ if(INS_MemoryOperandIsWritten(ins,i) && INS_HasFallThrough(ins)) { /* INS_InsertCall( ins, IPOINT_BEFORE, (AFUNPTR)RecordMemWrite, IARG_INST_PTR, IARG_MEMORYOP_EA, i, IARG_END); INS_InsertCall( ins, IPOINT_AFTER, (AFUNPTR)RecordMemWrite, IARG_INST_PTR, IARG_MEMORYOP_EA, i, IARG_END); */ if(opcode != XED_ICLASS_PUSH) { REG scratchReg = GetScratchReg(i); INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(GetMemAddress), IARG_MEMORYOP_EA, i, IARG_RETURN_REGS, scratchReg, IARG_END); INS_RewriteMemoryOperand(ins, i, scratchReg); } } } } } RTN_Close(rtn); } }
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); } }
VOID Trace(TRACE trace, VOID *v) { if(TAINT_Analysis_On&&TAINT_Instrumentation_On) { for (BBL bbl = TRACE_BblHead(trace); BBL_Valid(bbl); bbl = BBL_Next(bbl)) { if(bbl_taintedmem) BBL_InsertCall(bbl,IPOINT_BEFORE,(AFUNPTR)bblBegin,IARG_END); for (INS ins = BBL_InsHead(bbl); INS_Valid(ins); ins = INS_Next(ins)) { INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)checkEIP,IARG_INST_PTR,IARG_END); if(INS_IsCall(ins))//detect overflow of stack { INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)MemofRetAddr, IARG_MEMORYOP_EA, 0, IARG_END); } if ( INS_Opcode(ins) >= XED_ICLASS_MOV && INS_Opcode(ins) <= XED_ICLASS_MOVZX )//&& INS_Address(ins) == 0x7c80a2f0)//||INS_Address(ins)==0x7c80a2f3))//||( (INS_Opcode(ins) >= XED_ICLASS_POP) && (INS_Opcode(ins) <= XED_ICLASS_POPFQ))||((INS_Opcode(ins) >= XED_ICLASS_PUSH) && (INS_Opcode(ins) <= XED_ICLASS_PUSHFQ))||(INS_Opcode(ins) == XED_ICLASS_LEA)) { if (INS_has_immed(ins)) { if (INS_IsMemoryWrite(ins)) //immed -> mem { INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)ImmedCleanMem, IARG_MEMORYOP_EA, 0, IARG_END); } else //immed -> reg { REG insreg1 = INS_get_write_reg(ins); INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)ImmedCleanReg, IARG_ADDRINT, (ADDRINT)insreg1, IARG_END); } } else if (INS_IsMemoryRead(ins)) //mem -> reg { //in this case we call MemTaintReg to copy the taint if relevant REG insreg2 = INS_get_write_reg(ins); REG basereg2 = INS_get_mem_basereg(ins); REG indexreg2 = INS_get_mem_indexreg(ins); //ADDRINT insadd = INS_Address(ins); //string insdis = INS_Disassemble(ins); //out << "instruction 2 opcode " << INS_Opcode(ins)<<endl; INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)MemTaintReg, IARG_MEMORYOP_EA, 0, IARG_UINT32,INS_MemoryScale(ins), IARG_ADDRINT, (ADDRINT)basereg2, IARG_ADDRINT, (ADDRINT)indexreg2, IARG_ADDRINT, (ADDRINT)insreg2, IARG_UINT32, INS_Opcode(ins), IARG_INST_PTR, IARG_END); } else if (INS_IsMemoryWrite(ins)) //reg -> mem { //in this case we call RegTaintMem to copy the taint if relevant REG insreg3 = INS_get_read_reg(ins); REG basereg3 = INS_get_memwr_basereg(ins); REG indexreg3 = INS_get_memwr_indexreg(ins); //ADDRINT insadd = INS_Address(ins); //IARG_INST_PTR INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)RegTaintMem, IARG_ADDRINT,(ADDRINT)insreg3, IARG_UINT32,INS_MemoryScale(ins), IARG_ADDRINT, (ADDRINT)basereg3, IARG_ADDRINT, (ADDRINT)indexreg3, IARG_MEMORYOP_EA, 0, IARG_UINT32, INS_Opcode(ins), IARG_INST_PTR, IARG_END); } else if (INS_RegR(ins, 0) != REG_INVALID()) //reg -> reg { //in this case we call RegTaintReg REG Rreg = INS_get_read_reg(ins); REG Wreg = INS_get_write_reg(ins); //ADDRINT insadd = INS_Address(ins); INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)RegTaintReg, IARG_ADDRINT, (ADDRINT)Rreg, IARG_ADDRINT, (ADDRINT)Wreg, IARG_UINT32, INS_Opcode(ins), IARG_INST_PTR, IARG_END); } else //should never happen { out << "serious error?!\n" << endl; } } // IF opcode is a MOV /* if(bbl_taintedmem == 1&&INS_IsBranch(ins)) { out << BBL_Address(bbl) <<endl; out << INS_Address(ins)<<endl; out << INS_NextAddress(ins)<<endl; out << INS_DirectBranchOrCallTargetAddress(ins)<<endl; out << " taintBBL: "<<endl; out << INS_Disassemble(ins) <<endl; if(INS_NextAddress(ins)>=BBL_Address(bbl)&&INS_NextAddress(ins)<=INS_Address(ins)) { out << "find bbl loop"<<endl; //bblLoop = 1; } } */ if(bbl_taintedmem ==1 && ins==BBL_InsTail(bbl)) { // out <<"find tainted bbl " <<endl; // out <<"bbl start address: "<< BBL_Address(bbl) <<endl; // out <<"bbl size: "<<BBL_Size(bbl) << endl; // out <<"bbl head: "<< INS_Disassemble(BBL_InsHead(bbl))<<endl; // out <<"bbl tail: "<< INS_Disassemble(ins) <<endl; if(INS_DirectBranchOrCallTargetAddress(ins)>=BBL_Address(bbl)&&INS_DirectBranchOrCallTargetAddress(ins)<=INS_Address(ins)) { out<<endl<<"this tainted bbl is a loop"<<endl; //BBL_InsertCall(bbl,IPOINT_AFTER,(AFUNPTR)loopBblEnd,IARG_END); } } }// For INS } // For BBL }//for enable DTA } // VOID Trace
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 }
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); } } } }
/* ===================================================================== */ 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); } } }
// Is called for every instruction and instruments reads and writes VOID Instruction(TRACE trace, VOID *v) { // 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(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)) { // 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_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); //INS_InsertCall(ins, IPOINT_AFTER, (AFUNPTR)PrintValue, IARG_ADDRINT,&mem_value,IARG_END); /* INS_InsertFillBuffer( ins, IPOINT_AFTER, bufId, IARG_ADDRINT,mem_value,offsetof(struct MEMREF, value), //IARG_REG_VALUE,INS_OperandReg(ins,1),offsetof(struct MEMREF, value), IARG_END); */ } if (INS_IsBranchOrCall(ins)) { INS_InsertCall( ins, IPOINT_TAKEN_BRANCH, (AFUNPTR)RecordMemWrite, IARG_INST_PTR, 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); } } } }
// 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); } } }
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) { PIN_LockClient(); IMG img = IMG_FindByAddress(INS_Address(ins)); PIN_UnlockClient(); if (IMG_Valid(img) && IMG_IsMainExecutable(img)){ if (INS_IsCall(ins)){ INS_InsertCall( ins, IPOINT_BEFORE, (AFUNPTR)PrologueAnalysis, IARG_ADDRINT, INS_Address(ins), IARG_ADDRINT, INS_NextAddress(ins), IARG_PTR, new string(INS_Disassemble(ins)), IARG_END); } else if (INS_IsRet(ins)){ INS_InsertCall( ins, IPOINT_BEFORE, (AFUNPTR)EpilogueAnalysis, IARG_ADDRINT, INS_Address(ins), IARG_ADDRINT, INS_NextAddress(ins), IARG_PTR, new string(INS_Disassemble(ins)), 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_END); } /* Value Set Analysis */ if (INS_Opcode(ins) == XED_ICLASS_MOV && INS_RegR(ins, 0) == REG_RBP && INS_RegR(ins, 1) == REG_INVALID() && INS_IsMemoryWrite(ins)){ INS_InsertCall( ins, IPOINT_BEFORE, (AFUNPTR)ValueSetAnalysis, IARG_ADDRINT, INS_Address(ins), IARG_PTR, new string(INS_Disassemble(ins)), IARG_REG_VALUE, REG_RSP, IARG_REG_VALUE, REG_RBP, IARG_MEMORYOP_EA, 0, IARG_END); } /* Analyzes stack overflow */ if (INS_MemoryOperandIsWritten(ins, 0)){ INS_InsertCall( ins, IPOINT_BEFORE, (AFUNPTR)WriteMemAnalysis, IARG_ADDRINT, INS_Address(ins), IARG_PTR, new string(INS_Disassemble(ins)), IARG_MEMORYOP_EA, 0, IARG_END); } /* Timer Handler - And instruction counter */ INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)timerHandler, IARG_ADDRINT, INS_Address(INS_Prev(ins)), IARG_ADDRINT, INS_Address(ins), IARG_ADDRINT, INS_Address(INS_Next(ins)), IARG_PTR, new string(INS_Disassemble(ins)), IARG_END); } }