Exemple #1
0
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);
            
            for (INS ins = RTN_InsHead(rtn); INS_Valid(ins); ins = INS_Next(ins))
            {
                if( INS_IsPredicated(ins) )
                    GlobalStatsStatic.predicated[ INS_Category(ins) ]++;
                else
                    GlobalStatsStatic.unpredicated[ INS_Category(ins) ]++;
            }

            RTN_Close(rtn);
        }
    }

    if( KnobProfileStaticOnly.Value() )
    {
        Fini(0,0);
        exit(0);
    }
}
Exemple #2
0
UINT16 INS_GetStatsIndex(INS ins)
{
    if( INS_IsPredicated(ins) )
        return MAX_INDEX + INS_Category(ins);
    else
        return INS_Category(ins);
}
VOID CountsUpdate(INS ins)
{
    if (INS_FullRegRContain(ins, REG_EAX) && XED_CATEGORY_WIDENOP != INS_Category(ins)) fullRegRContainCount++;
    if (INS_IsInterrupt(ins)) interruptCount++;
    if (INS_IsRDTSC(ins)) rdtscCount++;
    if (INS_IsSysret(ins)) sysretCount++;
    if (INS_IsXchg(ins)) xchgCount++;

    if (INS_IsDirectFarJump(ins)) {
        directFarJumpCount++;

        UINT32 displacement; UINT16 segment;
        INS_GetFarPointer(ins, segment, displacement);
        TEST(segment == 0xabcd && displacement == 0x14, "INS_GetFarPointer failed");
    }
    if (INS_MemoryIndexReg(ins) != REG_INVALID() && XED_CATEGORY_WIDENOP != INS_Category(ins)) memoryIndexRegCount++;
}
Exemple #4
0
/* 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);
	}
}
VOID Ins( INS ins, VOID *v )
{
    if (KnobDetach > 0 && scount > KnobDetach)
        return;

    if (KnobLog)
    {
        void *addr = Addrint2VoidStar(INS_Address(ins));
        string disasm = INS_Disassemble(ins);
        PrintIns(addr, disasm.c_str());
    }

    scount++;

    // call and return need also stack manipulation (see emu_stack.cpp)
    // conditional jumps need handling the condition (not supported yet)
    if (INS_IsCall(ins) || INS_IsRet(ins) || INS_Category(ins) == XED_CATEGORY_COND_BR)
        return;

    if (INS_IsIndirectBranchOrCall(ins))
    {
        INS_InsertCall(ins, IPOINT_BEFORE,
            AFUNPTR(EmuIndJmp),
            IARG_BRANCH_TARGET_ADDR,
            IARG_RETURN_REGS, scratchReg, IARG_END);

        INS_InsertIndirectJump(ins, IPOINT_AFTER, scratchReg);

        INS_Delete(ins);
    }
    else if (INS_IsDirectBranchOrCall(ins))
    {
        ADDRINT tgt = INS_DirectBranchOrCallTargetAddress(ins);

        INS_InsertDirectJump(ins, IPOINT_AFTER, tgt);

        INS_Delete(ins);
    }
}
Exemple #6
0
VOID Trace(TRACE trace, VOID *v)
{
    if ( KnobNoSharedLibs.Value()
         && IMG_Type(SEC_Img(RTN_Sec(TRACE_Rtn(trace)))) == IMG_TYPE_SHAREDLIB)
        return;
    
    const BOOL accurate_handling_of_predicates = KnobProfilePredicated.Value();
    
    for (BBL bbl = TRACE_BblHead(trace); BBL_Valid(bbl); bbl = BBL_Next(bbl))
    {
        // Summarize the stats for the bbl in a 0 terminated list
        // This is done at instrumentation time
        UINT16 * stats = new UINT16[BBL_NumIns(bbl) + 1];

        INT32 index = 0;
        for (INS ins = BBL_InsHead(bbl); INS_Valid(ins); ins = INS_Next(ins))
        {
            // Count the number of times a predicated instruction is actually executed
            // this is expensive and hence disabled by default
            if( INS_IsPredicated(ins) && accurate_handling_of_predicates )
            {
                INS_InsertPredicatedCall(ins,
                                         IPOINT_BEFORE,
                                         AFUNPTR(docount),
                                         IARG_PTR, &(GlobalStatsDynamic.predicated_true[INS_Category(ins)]),
                                         IARG_END);    
            }
            
            stats[index++] = INS_GetStatsIndex(ins);
        }
        stats[index] = 0;

        // Insert instrumentation to count the number of times the bbl is executed
        BBLSTATS * bblstats = new BBLSTATS(stats);
        INS_InsertCall(BBL_InsHead(bbl), IPOINT_BEFORE, AFUNPTR(docount), IARG_PTR, &(bblstats->_counter), IARG_END);

        // Remember the counter and stats so we can compute a summary at the end
        statsList.push_back(bblstats);
    }
}
// Returns a pointer to an IRBuilder object.
// It is up to the user to delete it when times come.
IRBuilder *createIRBuilder(INS ins) {

  uint64 address         = INS_Address(ins);
  std::string disas      = INS_Disassemble(ins);
  INT32 opcode           = INS_Opcode(ins);

  IRBuilder *ir = nullptr;

  switch (opcode) {

    case XED_ICLASS_ADC:
      ir = new AdcIRBuilder(address, disas);
      break;

    case XED_ICLASS_ADD:
      ir = new AddIRBuilder(address, disas);
      break;

    case XED_ICLASS_AND:
      ir = new AndIRBuilder(address, disas);
      break;

    case XED_ICLASS_ANDNPD:
      ir = new AndnpdIRBuilder(address, disas);
      break;

    case XED_ICLASS_ANDNPS:
      ir = new AndnpsIRBuilder(address, disas);
      break;

    case XED_ICLASS_ANDPD:
      ir = new AndpdIRBuilder(address, disas);
      break;

    case XED_ICLASS_ANDPS:
      ir = new AndpsIRBuilder(address, disas);
      break;

    case XED_ICLASS_BSWAP:
      ir = new BswapIRBuilder(address, disas);
      break;

    case XED_ICLASS_CALL_FAR:
    case XED_ICLASS_CALL_NEAR:
      ir = new CallIRBuilder(address, disas);
      break;

    case XED_ICLASS_CBW:
      ir = new CbwIRBuilder(address, disas);
      break;

    case XED_ICLASS_CDQE:
      ir = new CdqeIRBuilder(address, disas);
      break;

    case XED_ICLASS_CLC:
      ir = new ClcIRBuilder(address, disas);
      break;

    case XED_ICLASS_CLD:
      ir = new CldIRBuilder(address, disas);
      break;

    case XED_ICLASS_CMC:
      ir = new CmcIRBuilder(address, disas);
      break;

    case XED_ICLASS_CMOVB:
      ir = new CmovbIRBuilder(address, disas);
      break;

    case XED_ICLASS_CMOVBE:
      ir = new CmovbeIRBuilder(address, disas);
      break;

    case XED_ICLASS_CMOVL:
      ir = new CmovlIRBuilder(address, disas);
      break;

    case XED_ICLASS_CMOVLE:
      ir = new CmovleIRBuilder(address, disas);
      break;

    case XED_ICLASS_CMOVNB:
      ir = new CmovnbIRBuilder(address, disas);
      break;

    case XED_ICLASS_CMOVNBE:
      ir = new CmovnbeIRBuilder(address, disas);
      break;

    case XED_ICLASS_CMOVNL:
      ir = new CmovnlIRBuilder(address, disas);
      break;

    case XED_ICLASS_CMOVNLE:
      ir = new CmovnleIRBuilder(address, disas);
      break;

    case XED_ICLASS_CMOVNO:
      ir = new CmovnoIRBuilder(address, disas);
      break;

    case XED_ICLASS_CMOVNP:
      ir = new CmovnpIRBuilder(address, disas);
      break;

    case XED_ICLASS_CMOVNS:
      ir = new CmovnsIRBuilder(address, disas);
      break;

    case XED_ICLASS_CMOVNZ:
      ir = new CmovnzIRBuilder(address, disas);
      break;

    case XED_ICLASS_CMOVO:
      ir = new CmovoIRBuilder(address, disas);
      break;

    case XED_ICLASS_CMOVP:
      ir = new CmovpIRBuilder(address, disas);
      break;

    case XED_ICLASS_CMOVS:
      ir = new CmovsIRBuilder(address, disas);
      break;

    case XED_ICLASS_CMOVZ:
      ir = new CmovzIRBuilder(address, disas);
      break;

    case XED_ICLASS_CMP:
      ir = new CmpIRBuilder(address, disas);
      break;

    case XED_ICLASS_CQO:
      ir = new CqoIRBuilder(address, disas);
      break;

    case XED_ICLASS_CWDE:
      ir = new CwdeIRBuilder(address, disas);
      break;

    case XED_ICLASS_DEC:
      ir = new DecIRBuilder(address, disas);
      break;

    case XED_ICLASS_DIV:
      ir = new DivIRBuilder(address, disas);
      break;

    case XED_ICLASS_IDIV:
      ir = new IdivIRBuilder(address, disas);
      break;

    case XED_ICLASS_IMUL:
      ir = new ImulIRBuilder(address, disas);
      break;

    case XED_ICLASS_INC:
      ir = new IncIRBuilder(address, disas);
      break;

    case XED_ICLASS_JB:
      ir = new JbIRBuilder(address, disas);
      break;

    case XED_ICLASS_JBE:
      ir = new JbIRBuilder(address, disas);
      break;

    case XED_ICLASS_JL:
      ir = new JlIRBuilder(address, disas);
      break;

    case XED_ICLASS_JLE:
      ir = new JleIRBuilder(address, disas);
      break;

    case XED_ICLASS_JMP:
      ir = new JmpIRBuilder(address, disas);
      break;

    case XED_ICLASS_JNB:
      ir = new JnbIRBuilder(address, disas);
      break;

    case XED_ICLASS_JNBE:
      ir = new JnbeIRBuilder(address, disas);
      break;

    case XED_ICLASS_JNL:
      ir = new JnlIRBuilder(address, disas);
      break;

    case XED_ICLASS_JNLE:
      ir = new JnleIRBuilder(address, disas);
      break;

    case XED_ICLASS_JNO:
      ir = new JnoIRBuilder(address, disas);
      break;

    case XED_ICLASS_JNP:
      ir = new JnpIRBuilder(address, disas);
      break;

    case XED_ICLASS_JNS:
      ir = new JnsIRBuilder(address, disas);
      break;

    case XED_ICLASS_JNZ:
      ir = new JnzIRBuilder(address, disas);
      break;

    case XED_ICLASS_JO:
      ir = new JoIRBuilder(address, disas);
      break;

    case XED_ICLASS_JP:
      ir = new JpIRBuilder(address, disas);
      break;

    case XED_ICLASS_JS:
      ir = new JsIRBuilder(address, disas);
      break;

    case XED_ICLASS_JZ:
      ir = new JzIRBuilder(address, disas);
      break;

    case XED_ICLASS_LEA:
      ir = new LeaIRBuilder(address, disas);
      break;

    case XED_ICLASS_LEAVE:
      ir = new LeaveIRBuilder(address, disas);
      break;

    case XED_ICLASS_MOV:
      ir = new MovIRBuilder(address, disas);
      break;

    case XED_ICLASS_MOVAPD:
      ir = new MovapdIRBuilder(address, disas);
      break;

    case XED_ICLASS_MOVAPS:
      ir = new MovapsIRBuilder(address, disas);
      break;

    case XED_ICLASS_MOVDQA:
      ir = new MovdqaIRBuilder(address, disas);
      break;

    case XED_ICLASS_MOVDQU:
      ir = new MovdquIRBuilder(address, disas);
      break;

    case XED_ICLASS_MOVHLPS:
      ir = new MovhlpsIRBuilder(address, disas);
      break;

    case XED_ICLASS_MOVHPD:
      ir = new MovhpdIRBuilder(address, disas);
      break;

    case XED_ICLASS_MOVHPS:
      ir = new MovhpsIRBuilder(address, disas);
      break;

    case XED_ICLASS_MOVLHPS:
      ir = new MovlhpsIRBuilder(address, disas);
      break;

    case XED_ICLASS_MOVLPD:
      ir = new MovlpdIRBuilder(address, disas);
      break;

    case XED_ICLASS_MOVLPS:
      ir = new MovlpsIRBuilder(address, disas);
      break;

    case XED_ICLASS_MOVSX:
    case XED_ICLASS_MOVSXD:
      ir = new MovsxIRBuilder(address, disas);
      break;

    case XED_ICLASS_MOVZX:
      ir = new MovzxIRBuilder(address, disas);
      break;

    case XED_ICLASS_MUL:
      ir = new MulIRBuilder(address, disas);
      break;

    case XED_ICLASS_NEG:
      ir = new NegIRBuilder(address, disas);
      break;

    case XED_ICLASS_NOT:
      ir = new NotIRBuilder(address, disas);
      break;

    case XED_ICLASS_OR:
      ir = new OrIRBuilder(address, disas);
      break;

    case XED_ICLASS_ORPD:
      ir = new OrpdIRBuilder(address, disas);
      break;

    case XED_ICLASS_ORPS:
      ir = new OrpsIRBuilder(address, disas);
      break;

    case XED_ICLASS_POP:
      ir = new PopIRBuilder(address, disas);
      break;

    case XED_ICLASS_PUSH:
      ir = new PushIRBuilder(address, disas);
      break;

    case XED_ICLASS_RET_FAR:
    case XED_ICLASS_RET_NEAR:
      ir = new RetIRBuilder(address, disas);
      break;

    case XED_ICLASS_ROL:
      ir = new RolIRBuilder(address, disas);
      break;

    case XED_ICLASS_ROR:
      ir = new RorIRBuilder(address, disas);
      break;

    case XED_ICLASS_SAR:
      ir = new SarIRBuilder(address, disas);
      break;

    case XED_ICLASS_SBB:
      ir = new SbbIRBuilder(address, disas);
      break;

    case XED_ICLASS_SETB:
      ir = new SetbIRBuilder(address, disas);
      break;

    case XED_ICLASS_SETBE:
      ir = new SetbeIRBuilder(address, disas);
      break;

    case XED_ICLASS_SETL:
      ir = new SetlIRBuilder(address, disas);
      break;

    case XED_ICLASS_SETLE:
      ir = new SetleIRBuilder(address, disas);
      break;

    case XED_ICLASS_SETNB:
      ir = new SetnbIRBuilder(address, disas);
      break;

    case XED_ICLASS_SETNBE:
      ir = new SetnbeIRBuilder(address, disas);
      break;

    case XED_ICLASS_SETNL:
      ir = new SetnlIRBuilder(address, disas);
      break;

    case XED_ICLASS_SETNLE:
      ir = new SetnleIRBuilder(address, disas);
      break;

    case XED_ICLASS_SETNO:
      ir = new SetnoIRBuilder(address, disas);
      break;

    case XED_ICLASS_SETNP:
      ir = new SetnpIRBuilder(address, disas);
      break;

    case XED_ICLASS_SETNS:
      ir = new SetnsIRBuilder(address, disas);
      break;

    case XED_ICLASS_SETNZ:
      ir = new SetnzIRBuilder(address, disas);
      break;

    case XED_ICLASS_SETO:
      ir = new SetoIRBuilder(address, disas);
      break;

    case XED_ICLASS_SETP:
      ir = new SetpIRBuilder(address, disas);
      break;

    case XED_ICLASS_SETS:
      ir = new SetsIRBuilder(address, disas);
      break;

    case XED_ICLASS_SETZ:
      ir = new SetzIRBuilder(address, disas);
      break;

    case XED_ICLASS_SHL:
      // XED_ICLASS_SAL is also a SHL
      ir = new ShlIRBuilder(address, disas);
      break;

    case XED_ICLASS_SHR:
      ir = new ShrIRBuilder(address, disas);
      break;

    case XED_ICLASS_STC:
      ir = new StcIRBuilder(address, disas);
      break;

    case XED_ICLASS_STD:
      ir = new StdIRBuilder(address, disas);
      break;

    case XED_ICLASS_SUB:
      ir = new SubIRBuilder(address, disas);
      break;

    case XED_ICLASS_TEST:
      ir = new TestIRBuilder(address, disas);
      break;

    case XED_ICLASS_XADD:
      ir = new XaddIRBuilder(address, disas);
      break;

    case XED_ICLASS_XCHG:
      ir = new XchgIRBuilder(address, disas);
      break;

    case XED_ICLASS_XOR:
      ir = new XorIRBuilder(address, disas);
      break;

    case XED_ICLASS_XORPD:
      ir = new XorpdIRBuilder(address, disas);
      break;

    case XED_ICLASS_XORPS:
      ir = new XorpsIRBuilder(address, disas);
      break;

    default:
      ir = new NullIRBuilder(address, disas);
      break;
  }

  // Populate the operands
  const uint32 n = INS_OperandCount(ins);

  for (uint32 i = 0; i < n; ++i) {
    IRBuilderOperand::operand_t type;
    uint32 size = 0;
    uint64 val  = 0;

    //Effective address = Displacement + BaseReg + IndexReg * Scale
    uint64 displacement = 0;
    uint64 baseReg      = ID_INVALID;
    uint64 indexReg     = ID_INVALID;
    uint64 memoryScale  = 0;

    /* Special case */
    if (INS_IsDirectBranchOrCall(ins)){
      ir->addOperand(TritonOperand(IRBuilderOperand::IMM, INS_DirectBranchOrCallTargetAddress(ins), 0));
      if (INS_MemoryOperandIsWritten(ins, 0))
        ir->addOperand(TritonOperand(IRBuilderOperand::MEM_W, 0, INS_MemoryWriteSize(ins)));
      break;
    }

    /* Immediate */
    if (INS_OperandIsImmediate(ins, i)) {
      type = IRBuilderOperand::IMM;
      val = INS_OperandImmediate(ins, i);
    }

    /* Register */
    else if (INS_OperandIsReg(ins, i)) {
      type = IRBuilderOperand::REG;
      REG reg = INS_OperandReg(ins, i);
      val = PINConverter::convertDBIReg2TritonReg(reg); // store the register ID.
      if (REG_valid(reg)) {
        // check needed because instructions like "xgetbv 0" make
        // REG_Size crash.
        size = REG_Size(reg);
      }
    }

    /* Memory */
    else if (INS_MemoryOperandCount(ins) > 0) {
      /* Memory read */
      if (INS_MemoryOperandIsRead(ins, 0)) {
        type = IRBuilderOperand::MEM_R;
        size = INS_MemoryReadSize(ins);
      }
      /* Memory write */
      else {
        type = IRBuilderOperand::MEM_W;
        size = INS_MemoryWriteSize(ins);
      }
    }

    /* load effective address instruction */
    else if (INS_OperandIsAddressGenerator(ins, i)) {
      REG reg;
      type          = IRBuilderOperand::LEA;
      displacement  = INS_OperandMemoryDisplacement(ins, i);
      memoryScale   = INS_OperandMemoryScale(ins, i);

      reg = INS_OperandMemoryBaseReg(ins, i);
      if (REG_valid(reg))
        baseReg = PINConverter::convertDBIReg2TritonReg(reg);

      reg = INS_OperandMemoryIndexReg(ins, i);
      if (REG_valid(reg))
        indexReg = PINConverter::convertDBIReg2TritonReg(reg);
    }

    /* Undefined */
    else {
      // std::cout << "[DEBUG] Unknown kind of operand: " << INS_Disassemble(ins) << std::endl;
      continue;
    }

    ir->addOperand(TritonOperand(type, val, size, displacement, baseReg, indexReg, memoryScale));
  }

  // Setup the opcode in the IRbuilder
  ir->setOpcode(opcode);
  ir->setOpcodeCategory(INS_Category(ins));
  ir->setNextAddress(INS_NextAddress(ins));

  return ir;
}
Exemple #8
0
/* 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);
	}
}
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);
}