INT32 RecordRegisters(BBL bbl, UINT16 * stats) { INT32 count = 0; for (INS ins = BBL_InsHead(bbl); INS_Valid(ins); ins = INS_Next(ins)) { const UINT32 max_r = INS_MaxNumRRegs(ins); for( UINT32 i=0; i < max_r; i++ ) { const REG reg = INS_RegR(ins, i ); if( REG_is_gr(reg) ) { stats[count++] = REG_GetStatsIndex(reg,FALSE); } #if 0 // This is for arm else if( REG_is_aggregate(reg) ) { REGSET regset = INS_RegAggregateR(ins); for( REG reg = REGSET_PopNext(regset); REG_valid(reg); reg = REGSET_PopNext(regset) ) { stats[count++] = REG_GetStatsIndex(reg,FALSE); } } #endif } const UINT32 max_w = INS_MaxNumWRegs(ins); for( UINT32 i=0; i < max_w; i++ ) { const REG reg = INS_RegW(ins, i ); if( REG_is_gr(reg) ) { stats[count++] = REG_GetStatsIndex(reg,TRUE); } #if 0 else if( REG_is_aggregate(reg) ) { REGSET regset = INS_RegAggregateW(ins); for( REG reg = REGSET_PopNext(regset); REG_valid(reg); reg = REGSET_PopNext(regset) ) { stats[count++] = REG_GetStatsIndex(reg,TRUE); } } #endif } } stats[count++] = 0; return count; }
// Pin calls this function every time a new instruction is encountered VOID Instruction(INS ins, VOID *v) { // Insert a call to updateSpacingInfo before every instruction. // You may need to add arguments to the call. INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)docount, IARG_END); UINT32 regnum = INS_MaxNumWRegs(ins); UINT32 reg,i,j,flag; REG tmp; regn++; for(i=0; i<regnum; i++){ tmp=INS_RegW(ins, i); if(REG_is_partialreg(tmp)){ INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)updateSpacingInfoW,IARG_UINT32, (UINT32)REG_FullRegName(tmp), IARG_END); INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)updateSpacingInfoW,IARG_UINT32, (UINT32)tmp, IARG_END); } // if((UINT32)tmp==REG_EAX) printf("eax %u\n",tmp); // if((UINT32)tmp==REG_RBASE) printf("base %u\n",tmp); // if((UINT32)tmp== REG_ESI) printf("esi %u\n",tmp); if((UINT32)tmp==REG_AL || (UINT32)tmp==REG_AH) INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)updateSpacingInfoW,IARG_UINT32, (UINT32)REG_AX, IARG_END); else if((UINT32)tmp==REG_BL || (UINT32)tmp==REG_BH) INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)updateSpacingInfoW,IARG_UINT32, (UINT32)REG_BX, IARG_END); else if((UINT32)tmp==REG_CL || (UINT32)tmp==REG_CH) INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)updateSpacingInfoW,IARG_UINT32, (UINT32)REG_CX, IARG_END); else if((UINT32)tmp==REG_DL || (UINT32)tmp==REG_CH) INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)updateSpacingInfoW,IARG_UINT32, (UINT32)REG_DX, IARG_END); } regnum = INS_MaxNumRRegs(ins); for(i=0; i<regnum; i++){ reg=(UINT32)INS_RegR(ins, i); //if(reg>200 || reg<0) printf("Error2: reg=%u\n",reg); //reg=writereg[reg]; //if(reg>regn) printf("Error3\n"); //if(reg>0 && regn-reg < maxSize && reg<regn) dependancySpacing[regn-reg]++; flag=0; for(j=0;j<i;j++) if(readreg[j]==reg){flag=1;break;} if(flag==0) { INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)updateSpacingInfoR, IARG_UINT32, reg, IARG_END); readreg[i]=reg; } else{ readreg[i]=-1; } } }
VOID Instruction(INS ins, VOID *v) { ADDRINT nextAddr = INS_NextAddress(ins); UINT32 maxRRegs = INS_MaxNumRRegs(ins); UINT32 maxWRegs = INS_MaxNumWRegs(ins); USIZE sz = INS_Size(ins); INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)RecordFirstInstructionInfo, IARG_THREAD_ID, IARG_INST_PTR, IARG_ADDRINT, nextAddr, IARG_UINT32, maxRRegs, IARG_UINT32, maxWRegs, IARG_ADDRINT, sz, IARG_UINT32, 'r', IARG_END); }
VOID WriteShadows(INS ins, BOOL * live) { for (UINT32 i = 0; i < INS_MaxNumWRegs(ins); i++) { REG reg = INS_RegW(ins, i); if (!GpReg(reg)) continue; if (!live[RegIndex(reg)]) continue; // If this instruction writes a register that is used as a base register in // a memory operation later in the trace, then translate the address and // write it to a shadow register INS_InsertCall(ins, IPOINT_AFTER, AFUNPTR(ProcessAddress), IARG_REG_VALUE, reg, IARG_INST_PTR, IARG_RETURN_REGS, ShadowReg(reg), IARG_END); live[RegIndex(reg)] = false; } }
// Pin calls this function every time a new instruction is encountered VOID Instruction(INS ins, VOID *v) { const UINT32 max_r = INS_MaxNumRRegs(ins); for( UINT32 i=0; i < max_r; i++ ) { const REG reg = INS_RegR(ins, i ); if (reg==REG_STATUS_FLAGS || reg==REG_DF_FLAG) { printf ("Error encountered unexpected flag reg at ins: %s\n", INS_Disassemble(ins).c_str()); numFailures++; } else if (reg==REG_GFLAGS) { numFlagRegs++; } } const UINT32 max_w = INS_MaxNumWRegs(ins); for( UINT32 i=0; i < max_w; i++ ) { const REG reg = INS_RegW(ins, i ); if (reg==REG_STATUS_FLAGS || reg==REG_DF_FLAG) { printf ("Error encountered unexpected flag reg at ins: %s\n", INS_Disassemble(ins).c_str()); numFailures++; } else if (reg==REG_GFLAGS) { numFlagRegs++; } } }
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); } }
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); }
VOID Instruction(INS ins, VOID *v) { ADDRINT nextAddr = INS_NextAddress(ins); UINT32 maxRRegs = INS_MaxNumRRegs(ins); UINT32 maxWRegs = INS_MaxNumWRegs(ins); ADDRINT sz = INS_Size(ins); if (numContextsInstrumented < 100) { numContextsInstrumented++; INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)RecordContext, // 4 dummy params to get the real params to be pushed on the stack in Intel64 IARG_UINT32, 1, IARG_UINT32, 2, IARG_UINT32, 3, IARG_UINT32, 4, IARG_CONTEXT, IARG_END); INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)RecordContextFastCall, IARG_FAST_ANALYSIS_CALL, IARG_CONTEXT, IARG_END); INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)VerifyContext, IARG_INST_PTR, IARG_CONTEXT, IARG_END); } else if (numRegularInstrumented < 100) { numRegularInstrumented++; INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)RecordInstructionInfoFastCall, IARG_FAST_ANALYSIS_CALL, IARG_THREAD_ID, IARG_INST_PTR, IARG_REG_VALUE, REG_GFLAGS, IARG_ADDRINT, nextAddr, IARG_UINT32, maxRRegs, IARG_UINT32, maxWRegs, IARG_ADDRINT, sz, #ifdef TARGET_IA32E IARG_ADDRINT, 0xdeadbeefdeadbeefLL, #else IARG_ADDRINT, 0xdeadbeef, #endif IARG_REG_VALUE, REG_GDX, IARG_REG_VALUE, REG_GDX, IARG_REG_VALUE, REG_GDX, IARG_REG_VALUE, REG_GDX, IARG_REG_VALUE, REG_GDX, IARG_REG_VALUE, REG_GDX, IARG_END); INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)RecordInstructionInfo, // 4 dummy params to get the real params to be pushed on the stack in Intel64 IARG_UINT32, 1, IARG_UINT32, 2, IARG_UINT32, 3, IARG_UINT32, 4, IARG_THREAD_ID, IARG_INST_PTR, IARG_REG_VALUE, REG_GFLAGS, IARG_ADDRINT, nextAddr, IARG_UINT32, maxRRegs, IARG_UINT32, maxWRegs, IARG_ADDRINT, sz, #ifdef TARGET_IA32E IARG_ADDRINT, 0xdeadbeefdeadbeefLL, #else IARG_ADDRINT, 0xdeadbeef, #endif IARG_REG_VALUE, REG_GDX, IARG_REG_VALUE, REG_GDX, IARG_REG_VALUE, REG_GDX, IARG_REG_VALUE, REG_GDX, IARG_REG_VALUE, REG_GDX, IARG_REG_VALUE, REG_GDX, IARG_END); INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)VerifyInstructionInfo, IARG_THREAD_ID, IARG_INST_PTR, IARG_REG_VALUE, REG_GFLAGS, IARG_ADDRINT, nextAddr, IARG_UINT32, maxRRegs, IARG_UINT32, maxWRegs, IARG_ADDRINT, sz, #ifdef TARGET_IA32E IARG_ADDRINT, 0xdeadbeefdeadbeefLL, #else IARG_ADDRINT, 0xdeadbeef, #endif IARG_REG_VALUE, REG_GDX, IARG_REG_VALUE, REG_GDX, IARG_REG_VALUE, REG_GDX, IARG_REG_VALUE, REG_GDX, IARG_REG_VALUE, REG_GDX, IARG_REG_VALUE, REG_GDX, IARG_END); } }