Esempio n. 1
0
File: disas.c Progetto: JaonLin/pemu
int helper_pemu_trace(target_ulong pc)
{
		
		target_ulong target;
		xed_error_enum_t xed_error = disas_one_inst(pc);

		if(xed_error != XED_ERROR_NONE){
			return -1;
		}

		const xed_inst_t * xi = xed_decoded_inst_inst(&xedd_g);
		xed_iclass_enum_t opcode = xed_decoded_inst_get_iclass(&xedd_g);

	//	char inst_str[512];
	//	xed_decoded_inst_dump_intel_format(&xedd_g, inst_str, 
	//		   sizeof(inst_str), 0);	
		switch(opcode){
			case XED_ICLASS_JMP:
				target = Instrument_JMP(xi, pc);
				break;
			case XED_ICLASS_CALL_NEAR:
				target = Instrument_CALL_NEAR(xi,pc);
				break;
			case XED_ICLASS_RET_NEAR:
				target = Instrument_RET(xi);
				break;
			default:
				break;
		}
		PEMU_add_trace(target);
		return 0;
}
static void add_write_operands(xed_dot_graph_supp_t* gg,
                               xed_decoded_inst_t* xedd,
                               xed_dot_node_t* n)
{
    xed_uint_t i, noperands;
    xed_reg_enum_t r, r_enclosing;
    const xed_inst_t* xi =  0; 
    xi = xed_decoded_inst_inst(xedd);
    noperands = xed_inst_noperands(xi);

    for( i=0; i < noperands ; i++) {
        const xed_operand_t* op = xed_inst_operand(xi,i);
        xed_operand_enum_t opname = xed_operand_name(op);
        if (xed_operand_is_register(opname) ||
            xed_operand_is_memory_addressing_register(opname)) {

             if (xed_operand_written(op)) {
                 /* set n as the source of the value. */
                 /* ignoring partial writes */
                 r = xed_decoded_inst_get_reg(xedd, opname);
                 r_enclosing = xed_get_largest_enclosing_register(r);
                 gg->xed_reg_to_node[r_enclosing] = n;
             }
        }
    } /* for */
}
Esempio n. 3
0
unsigned int disas_get_target(unsigned int start_pc, struct PEMU_INST *inst)
{

	PEMU_read_mem(start_pc, 15, inst->PEMU_inst_buf);
	xed_decoded_inst_zero_set_mode(&inst->PEMU_xedd_g, &inst->PEMU_dstate);
	xed_error_enum_t xed_error = xed_decode(&inst->PEMU_xedd_g,
			XED_STATIC_CAST(const xed_uint8_t *, inst->PEMU_inst_buf), 15);


	if (xed_error != XED_ERROR_NONE) {
		fprintf(stderr, "error in disas_get_target\n");
		exit(0);
	}

	const xed_inst_t *xi = xed_decoded_inst_inst(&inst->PEMU_xedd_g);
	if(xed_decoded_inst_get_iclass(&inst->PEMU_xedd_g) != XED_ICLASS_CALL_NEAR) {
		return 0;
	}

	const xed_operand_t *op = xed_inst_operand(xi, 0);
	xed_reg_enum_t reg_id;
	xed_operand_enum_t op_name = xed_operand_name(op);
	unsigned int dest, tmp;
	
	if(operand_is_relbr(op_name, &dest)){
		dest += (start_pc +  xed_decoded_inst_get_length(&inst->PEMU_xedd_g));				
	}else if(operand_is_reg(op_name, &reg_id)){
		dest = PEMU_get_reg(reg_id);	
	}else if(operand_is_mem4(op_name, &dest,0)){
		PEMU_read_mem(dest, 4, &tmp);
		dest = tmp;
	}
	return dest;
}
Esempio n. 4
0
static target_ulong Instrument_CALL_NEAR(target_ulong pc)
{
	uint32_t mem_addr;
	xed_reg_enum_t  reg_id;
	target_ulong target;

	PEMU_read_mem(pc, 15, pemu_inst.PEMU_inst_buf);
	xed_decoded_inst_zero_set_mode(&pemu_inst.PEMU_xedd_g, &pemu_inst.PEMU_dstate);
	xed_error_enum_t xed_error = xed_decode(&pemu_inst.PEMU_xedd_g,
			XED_STATIC_CAST(const xed_uint8_t *, pemu_inst.PEMU_inst_buf), 15);

	const xed_inst_t * ins = xed_decoded_inst_inst(&pemu_inst.PEMU_xedd_g);
	const xed_operand_t *op = xed_inst_operand(ins, 0);
	xed_operand_enum_t op_name = xed_operand_name(op);
	
	if (operand_is_mem(op_name, &mem_addr, 0)) {
		PEMU_read_mem(mem_addr,sizeof(target) , &target);
	}
	else if (operand_is_reg(op_name, &reg_id)){
		target = PEMU_get_reg(reg_id);
	}
	else{
		int len = xed_decoded_inst_get_length(&pemu_inst.PEMU_xedd_g);
		target = xed_decoded_inst_get_branch_displacement(&pemu_inst.PEMU_xedd_g) + pc + len;
	}
	return target;
}
Esempio n. 5
0
bool IsRegisterOperand(xed_decoded_inst_t &xedd, int index)
{
    const xed_inst_t* inst = xed_decoded_inst_inst(&xedd);

    const xed_operand_t* operand = xed_inst_operand(inst, index);  //the first operand is the destination.
    xed_operand_enum_t oper_type = xed_operand_name(operand);


    switch(oper_type)
    {
        case XED_OPERAND_REG0:
        case XED_OPERAND_REG1:
        case XED_OPERAND_REG2:
        case XED_OPERAND_REG3:
        case XED_OPERAND_REG4:
        case XED_OPERAND_REG5:
        case XED_OPERAND_REG6:
        case XED_OPERAND_REG7:
        case XED_OPERAND_REG8:
        case XED_OPERAND_REG9:
        case XED_OPERAND_REG10:
        case XED_OPERAND_REG11:
        case XED_OPERAND_REG12:
        case XED_OPERAND_REG13:
        case XED_OPERAND_REG14:
        case XED_OPERAND_REG15: return true; break;
        default: break; 
    }

    return false;
}
Esempio n. 6
0
int RegisterOperandSize(xed_decoded_inst_t &xedd, int index)
{

    ASSERT(IsRegisterOperand(xedd, index));

    const xed_inst_t* inst = xed_decoded_inst_inst(&xedd);
    const xed_operand_t* operand = xed_inst_operand(inst, index);  //the first operand is the destination.
    xed_operand_enum_t oper_type = xed_operand_name(operand);

    xed_reg_enum_t reg = xed_decoded_inst_get_reg(&xedd, oper_type);

    int size = 0;
    switch(reg)
    {
        case XED_REG_AH:
        case XED_REG_AL:
        case XED_REG_BH:
        case XED_REG_BL:
        case XED_REG_CH:
        case XED_REG_CL:
        case XED_REG_DH:
        case XED_REG_DL: size = 8; break;

        case XED_REG_AX:
        case XED_REG_BX:
        case XED_REG_CX:
        case XED_REG_DX: size = 16; break;

        default: size = 32; break;
    }

    ASSERT(size != 0);
    return size;
}
Esempio n. 7
0
void check_for_mov_to_cr3(xed_decoded_inst_t* xedd)
{
    if (xed_decoded_inst_get_iclass(xedd) == XED_ICLASS_MOV_CR)
    {
        // we know mov_cr has 2 operands so we do not check
        // xed_inst_noperands.


        // get the skeleton (static info)
        const xed_inst_t* xi = xed_decoded_inst_inst(xedd);

        // get the dest operand (operand 0)
        const xed_operand_t* op = xed_inst_operand(xi,0);
        
        xed_operand_enum_t op_name = xed_operand_name(op);
        if (op_name == XED_OPERAND_REG0)
        {
            xed_reg_enum_t r = xed_decoded_inst_get_reg(xedd, op_name);
            if (r == XED_REG_CR3)
            {
                printf("Found a mov to CR3\n");
            }
        }
    }
}
Esempio n. 8
0
// Return the destination register of one instruction
xed_reg_enum_t DestRegister(xed_decoded_inst_t &xedd)
{

    const xed_inst_t* inst = xed_decoded_inst_inst(&xedd);

    unsigned int operandNum = xed_inst_noperands(inst);   // get the number of the operands 

    // if the instruction has no operands, return invalid
    if(operandNum == 0)
        return XED_REG_INVALID;


    const xed_operand_t* operand = xed_inst_operand(inst, 0);  //the first operand is the destination.
    xed_operand_enum_t oper_type = xed_operand_name(operand);

    xed_uint_t mark = xed_operand_is_register(oper_type);
    
    // check whether the operand is a register operand
    if(mark == 1)
    {
        xed_reg_enum_t reg = xed_decoded_inst_get_reg(&xedd, oper_type);
        ASSERT(reg != XED_REG_INVALID);

        return reg;
    }

    return XED_REG_INVALID;
}
Esempio n. 9
0
/* Allocate and initialize a new `Instruction' object given the associated
 * `xed_decoded_inst_t' structure.
 */
instruction_t *new_instruction(xed_decoded_inst_t *decoded_inst,
        xed_uint64_t runtime_address)
{
    instruction_t *instruction;
    instruction = (instruction_t *)PyType_GenericNew(&type, NULL, NULL);
    instruction->decoded_inst = decoded_inst;
    instruction->inst = xed_decoded_inst_inst(decoded_inst);
    instruction->runtime_address = runtime_address;
    return instruction;
}
static void add_read_operands(xed_dot_graph_supp_t* gg,
                              xed_decoded_inst_t* xedd,
                              xed_dot_node_t* n)
{
    xed_uint_t i, noperands;
    xed_reg_enum_t r;
    const xed_inst_t* xi =  0;
    xed_bool_t found = 0;
    xi = xed_decoded_inst_inst(xedd);
    noperands = xed_inst_noperands(xi);
    
    for( i=0; i < noperands ; i++) {
        int memop = -1;
        const xed_operand_t* op = xed_inst_operand(xi,i);
        xed_operand_enum_t opname = xed_operand_name(op);
        if (xed_operand_is_register(opname) ||
            xed_operand_is_memory_addressing_register(opname)) {

             if (xed_operand_read(op)) {
                 /* add edge to n */
                 r = xed_decoded_inst_get_reg(xedd, opname);
                 found |= add_edge(gg, n, r);
             }
             continue;
        }
        if (opname == XED_OPERAND_MEM0) 
            memop = 0;
        else if (opname == XED_OPERAND_MEM1 ) 
            memop = 1;

        if (memop != -1) {
            /* get reads of base/index regs,  if any */
            xed_reg_enum_t base, indx;
            
            base = xed_decoded_inst_get_base_reg(xedd,memop);
            indx = xed_decoded_inst_get_index_reg(xedd,memop);
            if (base != XED_REG_INVALID) 
                found |= add_edge(gg, n, base);

            indx = xed_decoded_inst_get_index_reg(xedd,memop);
            if (indx != XED_REG_INVALID) 
                found |= add_edge(gg, n, indx);
        }
    } /* for */
    if (!found) {
        /* add an edge from start */
        xed_dot_edge(gg->g, gg->start, n);
    }
}
Esempio n. 11
0
bool IsImmediateOperand(xed_decoded_inst_t &xedd, int index)
{
    const xed_inst_t* inst = xed_decoded_inst_inst(&xedd);

    const xed_operand_t* operand = xed_inst_operand(inst, index);  //the first operand is the destination.
    xed_operand_enum_t oper_type = xed_operand_name(operand);


    switch(oper_type)
    {
        case XED_OPERAND_IMM0: return true;
        default: break; 
    }

    return false;
}
Esempio n. 12
0
void print_operands(xed_decoded_inst_t* xedd) {
    unsigned int i = 0;
    xed_inst_t const* const xi = xed_decoded_inst_inst(xedd);
    const unsigned int noperands = xed_inst_noperands(xi);

    for( i=0; i < noperands ; i++) { 
        xed_operand_t const* op = xed_inst_operand(xi,i);
        xed_operand_enum_t op_name = xed_operand_name(op);
        if (xed_operand_is_register(op_name)) {
            xed_reg_enum_t reg = xed_decoded_inst_get_reg(xedd,op_name);
            xed_operand_action_enum_t rw = xed_operand_rw(op);
            printf("%2d: %5s %5s\n", 
                   i,
                   xed_reg_enum_t2str(reg),
                   xed_operand_action_enum_t2str(rw));
        }
    }
}
Esempio n. 13
0
File: disas.c Progetto: JaonLin/pemu
int PEMU_disas_handle_branch(target_ulong pc)
{
		
		xed_error_enum_t xed_error = disas_one_inst(pc);

		if(xed_error != XED_ERROR_NONE){
			return 0;
		}

		xed_iclass_enum_t opcode = xed_decoded_inst_get_iclass(&xedd_g);

		switch(opcode){
			case XED_ICLASS_JMP:
			case XED_ICLASS_CALL_NEAR:
				{
					const xed_inst_t * ins = xed_decoded_inst_inst(&xedd_g);
					const xed_operand_t *op = xed_inst_operand(ins, 0);
					xed_operand_enum_t op_name = xed_operand_name(op);
					int len = xed_decoded_inst_get_length(&xedd_g);
					unsigned int rel;
					if(operand_is_relbr(op_name, &rel))
					{	
						unsigned long target = pc + len + rel;
						PEMU_add_trace(target);
						return 0;
					}
					return 1;
				}

				break;
			case XED_ICLASS_RET_NEAR:
				return 1;
			default:
				break;
		}
		return 0;
}
Esempio n. 14
0
TCA OfflineX86Code::collectJmpTargets(FILE  *file,
                                      TCA    fileStartAddr,
                                      TCA    codeStartAddr,
                                      uint64_t codeLen,
                                      vector<TCA> *jmpTargets) {

  xed_uint8_t* code = (xed_uint8_t*) alloca(codeLen);
  xed_uint8_t* frontier;
  TCA          ip;

  if (codeLen == 0) return 0;

  if (fseek(file, codeStartAddr - fileStartAddr, SEEK_SET)) {
    error("collectJmpTargets error: seeking file");
  }

  size_t readLen = fread(code, codeLen, 1, file);
  if (readLen != 1) error("collectJmpTargets error: reading file");

  xed_decoded_inst_t xedd;
  xed_iclass_enum_t iclass = XED_ICLASS_NOP;

  // Decode each instruction
  for (frontier = code, ip = codeStartAddr; frontier < code + codeLen; ) {

    xed_decoded_inst_zero_set_mode(&xedd, &xed_state);
    xed_decoded_inst_set_input_chip(&xedd, XED_CHIP_INVALID);
    xed_error_enum_t xed_error = xed_decode(&xedd, frontier, 15);

    if (xed_error != XED_ERROR_NONE) break;

    uint32_t instrLen = xed_decoded_inst_get_length(&xedd);

    iclass = xed_decoded_inst_get_iclass(&xedd);

    if (iclass >= XED_ICLASS_JB && iclass <= XED_ICLASS_JZ) {
      const xed_inst_t    *xi       = xed_decoded_inst_inst(&xedd);
      always_assert(xed_inst_noperands(xi) >= 1);
      const xed_operand_t *opnd     = xed_inst_operand(xi, 0);
      xed_operand_enum_t   opndName = xed_operand_name(opnd);

      if (opndName == XED_OPERAND_RELBR) {
        always_assert(xed_decoded_inst_get_branch_displacement_width(&xedd));
        xed_int32_t disp = xed_decoded_inst_get_branch_displacement(&xedd);
        TCA         addr = ip + instrLen + disp;
        jmpTargets->push_back(addr);
      }
    }

    frontier += instrLen;
    ip       += instrLen;
  }

  // If the code sequence falls thru, then add the next instruction as a
  // possible target
  bool fallsThru = (iclass != XED_ICLASS_JMP      &&
                    iclass != XED_ICLASS_JMP_FAR  &&
                    iclass != XED_ICLASS_RET_NEAR &&
                    iclass != XED_ICLASS_RET_FAR);
  if (fallsThru) {
    jmpTargets->push_back(ip);
    return ip;
  }
  return 0;
}
Esempio n. 15
0
static void print_inst(INST *inst)
{
//#if 0
	xed_decoded_inst_zero_set_mode(&xedd_g, &dstate);
	xed_error_enum_t xed_error = xed_decode(&xedd_g,
			XED_STATIC_CAST(const xed_uint8_t *,  inst->inst), 15);

#ifdef STATISTICS
			g_inst_num++;
#endif

//	fprintf(output, "\/\/0x%x\n", g_pc);

	if (xed_error == XED_ERROR_NONE) 
	{
#ifdef WINDOWS_FORMAT
		xed_decoded_inst_dump_intel_format(&xedd_g, g_inst_str, sizeof(g_inst_str), 0);
#else
		xed_decoded_inst_dump_att_format(&xedd_g, g_inst_str, sizeof(g_inst_str), 0);
		//xed_decoded_inst_dump_intel_format(&xedd_g, g_inst_str, sizeof(g_inst_str), 0);
#endif
		const xed_inst_t *xi = xed_decoded_inst_inst(&xedd_g);
	
		patch_operand(xi);
		
		switch(inst->type){
			case INCALL:
			case INJMP:
			case NORMAL:
				format_normal(xi);
				break;
			case JMP:
			case TAIL:
				format_jmp(xi);
				break;
			case CALL:
				format_direct_call(xi);
				break;
			case JCC:
			case LOOP:
				format_jcc(xi);
				break;
			case LEA_8:
			case LEA_16:
			case LEA_32:
				format_lea(xi);
			default:
				break;
		}
//		fprintf(stdout, "results:\"%s\\n\\t\"\n", inst_buffer);

		if(get_jmp_dst(g_pc))
#ifdef WINDOWS_FORMAT
			fprintf(output, "L_0x%x:\n", g_pc);
#else
			fprintf(output, "\"L_0x%x:\"\n", g_pc);
#endif

#ifdef DEBUG
		print_debug();
#endif

#ifdef WINDOWS_FORMAT
		fprintf(output, "%s\n", inst_buffer);
#else
		fprintf(output, "\"%s\\n\\t\"\n", inst_buffer);
#endif

		//patch safety guard
		switch(inst->type){
			case INJMP:
			case JCC:
				if(safety_guard[0]){
#ifdef WINDOWS_FORMAT
					fprintf(output, "%s\n", safety_guard);
#else
					fprintf(output, "\"%s\\n\\t\"\n", safety_guard);
#endif
				}
				break;
		}
	}
//#endif
}
Esempio n. 16
0
void print_operands(xed_decoded_inst_t* xedd) {
    unsigned int i, noperands;
    cout << "Operands" << endl;
    const xed_inst_t* xi = xed_decoded_inst_inst(xedd);
    noperands = xed_inst_noperands(xi);
    for( i=0; i < noperands ; i++) { 
        const xed_operand_t* op = xed_inst_operand(xi,i);
        xed_operand_enum_t op_name = xed_operand_name(op);
        cout << i << " " << xed_operand_enum_t2str(op_name) << " ";
        switch(op_name) {
          case XED_OPERAND_AGEN:
          case XED_OPERAND_MEM0:
          case XED_OPERAND_MEM1:
            // we print memops in a different function
            break;
          case XED_OPERAND_PTR:  // pointer (always in conjunction with a IMM0)
          case XED_OPERAND_RELBR: { // branch displacements
              xed_uint_t disp_bits = xed_decoded_inst_get_branch_displacement_width(xedd);
              if (disp_bits) {
                  //cout  << "BRANCH_DISPLACEMENT_BYTES= " << disp_bits << " ";
                  xed_int32_t disp = xed_decoded_inst_get_branch_displacement(xedd);
                  //cout << hex << setfill('0') << setw(8) << disp << setfill(' ') << dec;
              }
            }
            break;

          case XED_OPERAND_IMM0: { // immediates
              xed_uint_t width = xed_decoded_inst_get_immediate_width(xedd);
              if (xed_decoded_inst_get_immediate_is_signed(xedd)) {
                  xed_int32_t x =xed_decoded_inst_get_signed_immediate(xedd);
                  //cout << hex << setfill('0') << setw(8) << x << setfill(' ') << dec 
                  //     << '(' << width << ')';
              }
              else {
                  xed_uint64_t x = xed_decoded_inst_get_unsigned_immediate(xedd); 
                  //cout << hex << setfill('0') << setw(16) << x << setfill(' ') << dec 
                  //     << '(' << width << ')';
              }
              break;
          }
          case XED_OPERAND_IMM1: { // immediates
              xed_uint8_t x = xed_decoded_inst_get_second_immediate(xedd);
              //cout << hex << setfill('0') << setw(2) << (int)x << setfill(' ') << dec;
              break;
          }

          case XED_OPERAND_REG0:
          case XED_OPERAND_REG1:
          case XED_OPERAND_REG2:
          case XED_OPERAND_REG3:
          case XED_OPERAND_REG4:
          case XED_OPERAND_REG5:
          case XED_OPERAND_REG6:
          case XED_OPERAND_REG7:
          case XED_OPERAND_REG8:
          case XED_OPERAND_REG9:
          case XED_OPERAND_REG10:
          case XED_OPERAND_REG11:
          case XED_OPERAND_REG12:
          case XED_OPERAND_REG13:
          case XED_OPERAND_REG14:
          case XED_OPERAND_REG15: {
              xed_reg_enum_t r = xed_decoded_inst_get_reg(xedd, op_name);
              cout << xed_operand_enum_t2str(op_name) << "=" << xed_reg_enum_t2str(r);
              break;
          }
          default:
            //cout << "[Not currently printing value of field " << xed_operand_enum_t2str(op_name) << ']';
            break;

        }
        //cout << " " << xed_operand_visibility_enum_t2str(xed_operand_operand_visibility(op))
        //     << " / " << xed_operand_action_enum_t2str(xed_operand_rw(op))
        //     << " / " << xed_operand_width_enum_t2str(xed_operand_width(op));
        //cout << " bytes=" << xed_decoded_inst_operand_length(xedd,i);
        //cout << endl;
    }
}
Esempio n. 17
0
File: disas.c Progetto: JaonLin/pemu
int disas_trace_ex(target_ulong pc_start, TRACE trace)
{

//#define PEMU_DEBUG
#ifdef PEMU_DEBUG
	printf("New trace %x\n", pc_start);
#endif 
	target_ulong pc;
	char inst_str[256];
	int newtrace = 0;

	pc = pc_start;
	trace->trace_start = pc_start;
	BBL bbl= get_BBL(pc);
	trace->head = bbl;
	INS ins = NULL;
#ifdef PEMU_DEBUG
	printf("New BBL %x\n", pc_start);
#endif

	while(!newtrace){
		xed_error_enum_t xed_error = disas_one_inst(pc);

		if(xed_error != XED_ERROR_NONE){
			return -1;
		}
		xed_decoded_inst_dump_intel_format(&xedd_g, inst_str, 
			   sizeof(inst_str), 0);	

		xed_iclass_enum_t opcode = xed_decoded_inst_get_iclass(&xedd_g);
		int len = xed_decoded_inst_get_length(&xedd_g);
#ifdef PEMU_DEBUG
		printf("New INS %x %s\n", pc, inst_str);
#endif
		if(!ins){
			ins  = get_INS(pc);
			bbl->head = ins;
		}else{
			ins->next = get_INS(pc);
			ins = ins->next;
		}
		if(pemu_hook_funcs.inst_hook != 0) {
			pemu_inst.PEMU_inst_pc = pc;
			pemu_hook_funcs.inst_hook(ins, 0);
		 }

		bbl->inst_count ++;
		bbl-> size += len;
		switch(opcode){
			//case XED_ICLASS_CALL_FAR:
			case XED_ICLASS_CALL_NEAR:
			case XED_ICLASS_SYSENTER:
			case XED_ICLASS_INT:
			case XED_ICLASS_INT1:
			case XED_ICLASS_INT3:
			case XED_ICLASS_HLT:
			case XED_ICLASS_RET_FAR:
			case XED_ICLASS_RET_NEAR:
			case XED_ICLASS_JMP:
			case XED_ICLASS_JMP_FAR:
				newtrace = 1;
				break;
			//case XED_ICLASS_IRET:
			//case XED_ICLASS_IRETD:
			//case XED_ICLASS_IRETQ:
			case XED_ICLASS_JB:
			case XED_ICLASS_JBE:
			case XED_ICLASS_JL:
			case XED_ICLASS_JLE:
			case XED_ICLASS_JNB:
			case XED_ICLASS_JNBE:
			case XED_ICLASS_JNL: 
			case XED_ICLASS_JNLE:
			case XED_ICLASS_JNO:
			case XED_ICLASS_JNP:
			case XED_ICLASS_JNS:
			case XED_ICLASS_JNZ:
			case XED_ICLASS_JO:
			case XED_ICLASS_JP:
			case XED_ICLASS_JRCXZ:
			case XED_ICLASS_JS:
			case XED_ICLASS_JZ:
				{
				//add new trace target
				const xed_inst_t * xi = xed_decoded_inst_inst(&xedd_g);
				const xed_operand_t *op = xed_inst_operand(xi,0);
				xed_operand_enum_t opname = xed_operand_name(op);
				target_ulong rel;
				target_ulong target;
				rel = xed_decoded_inst_get_branch_displacement(&xedd_g);
				target  = pc + rel + len;
				PEMU_add_trace(target);
#ifdef PEMU_DEBUG
				printf("New target %x %d\n", target, bbl->inst_count);
#endif

				bbl->next = get_BBL(pc+len);
				bbl = bbl->next;
				ins = NULL;

#ifdef PEMU_DEBUG
				printf("New BBL %x\n", pc + len);
#endif
				break;
				}
			default:
				//TODO:
				break;
				//set_code_cache(pc, TAINTED);
				//printf("pc=%lu\tlen=%x\n", pc, len);

		}
		pc = pc + len;
	}
	
	if(pemu_hook_funcs.trace_hook != 0) 
		pemu_hook_funcs.trace_hook(trace, 0);
	
	BBL bblnext = trace->head;
    do{
	    bbl = bblnext;
		bblnext = bbl->next;

		INS ins;
		INS insnext = bbl->head;
		do{
			ins = insnext;
			insnext = ins->next;
			free(ins);
		}while(insnext!=NULL);
		free(bbl);
	}while(bblnext!=NULL);
	free(trace);
}
Esempio n. 18
0
File: trace.c Progetto: anhkgg/temu
/* This is the central function
  Given a memory address, reads a bunch of memory bytes and
    calls the disassembler to obtain the information
  Then it stores the information into the eh EntryHeader
*/
void decode_address(uint32_t address, EntryHeader *eh, int ignore_taint)
{
  unsigned char insn_buf[MAX_INSN_BYTES];
  unsigned int is_stackpush = 0, is_stackpop = 0;
  unsigned int stackpushpop_acc = 0;

  if (xed2chris_regmapping[XED_REG_EAX][0] == 0) {
    init_xed2chris();
    assert(xed2chris_regmapping[XED_REG_EAX][0] != 0);
  }

  /* Read memory from TEMU */
  TEMU_read_mem(address, MAX_INSN_BYTES, insn_buf);

  /* Disassemble instruction buffer */
  xed_decoded_inst_zero_set_mode(&xedd, &dstate);
  xed_error_enum_t xed_error =
    xed_decode(&xedd, STATIC_CAST(const xed_uint8_t*,insn_buf), MAX_INSN_BYTES);
  xed_bool_t okay = (xed_error == XED_ERROR_NONE);
  if (!okay) return;

  // Increase counters
  tstats.insn_counter_decoded++;

  int i;

  /* Clear out Entry header */
  memset(eh, 0, sizeof(EntryHeader));

  /* Copy the address and instruction size */
  eh->address = address;
  eh->inst_size = xed_decoded_inst_get_length(&xedd);
  if (eh->inst_size > MAX_INSN_BYTES) eh->inst_size = MAX_INSN_BYTES;

  /* Copy instruction rawbytes */
  memcpy(eh->rawbytes, insn_buf, eh->inst_size);

  /* Get the number of XED operands */
  const xed_inst_t* xi = xed_decoded_inst_inst(&xedd);
  int xed_ops = xed_inst_noperands(xi);
  int op_idx = -1;

  /* Get the category of the instruction */
  xed_category_enum_t category = xed_decoded_inst_get_category(&xedd);

  /* Iterate over the XED operands */
  for(i = 0; i < xed_ops; i++) {
  	if(op_idx >= MAX_NUM_OPERANDS)
  	  break;
    //assert(op_idx < MAX_NUM_OPERANDS);

    /* Get operand */
    const xed_operand_t* op = xed_inst_operand(xi,i);
    xed_operand_enum_t op_name = xed_operand_name(op);

    switch(op_name) {
      /* Register */
      case XED_OPERAND_REG0:
      case XED_OPERAND_REG1:
      case XED_OPERAND_REG2:
      case XED_OPERAND_REG3:
      case XED_OPERAND_REG4:
      case XED_OPERAND_REG5:
      case XED_OPERAND_REG6:
      case XED_OPERAND_REG7:
      case XED_OPERAND_REG8:
      case XED_OPERAND_REG9:
      case XED_OPERAND_REG10:
      case XED_OPERAND_REG11:
      case XED_OPERAND_REG12:
      case XED_OPERAND_REG13:
      case XED_OPERAND_REG14:
      case XED_OPERAND_REG15: {
        xed_reg_enum_t reg_id = xed_decoded_inst_get_reg(&xedd, op_name);
        int regnum = xed2chris_regmapping[reg_id][1];

        // Special handling for Push
        if (reg_id == XED_REG_STACKPUSH) is_stackpush = 1;
        else if (reg_id == XED_REG_STACKPOP) is_stackpop = 1;

        if (-1 == regnum)
          break;
        else {
	  op_idx++;
          eh->num_operands++;
          eh->operand[op_idx].type = TRegister;
          eh->operand[op_idx].addr = xed2chris_regmapping[reg_id][0];
	  eh->operand[op_idx].length = 
	    (uint8_t) xed_decoded_inst_operand_length (&xedd, i);
	  eh->operand[op_idx].access = (uint8_t) xed_operand_rw (op);
          eh->operand[op_idx].value = TEMU_cpu_regs[regnum];
          switch (eh->operand[op_idx].addr) {
            case ax_reg:
            case bx_reg:
            case cx_reg:
            case dx_reg:
            case bp_reg:
            case sp_reg:
            case si_reg:
            case di_reg:
              eh->operand[op_idx].value &= 0xFFFF;
              break;
            case al_reg:
            case bl_reg:
            case cl_reg:
            case dl_reg:
              eh->operand[op_idx].value &= 0xFF;
              break;
            case ah_reg:
            case bh_reg:
            case ch_reg:
            case dh_reg:
              eh->operand[op_idx].value = (eh->operand[i].value & 0xFF00) >> 8;
              break;
            default:
              break;
          }
        }
        if (ignore_taint == 0) set_operand_data(&(eh->operand[op_idx]));
        break;
      }

      /* Immediate */
      case XED_OPERAND_IMM0: {
        op_idx++;
        eh->num_operands++;
        eh->operand[op_idx].type = TImmediate;
	eh->operand[op_idx].length = 
	  (uint8_t) xed_decoded_inst_operand_length (&xedd, i);
	eh->operand[op_idx].access = (uint8_t) xed_operand_rw (op);
        //xed_uint_t width = xed_decoded_inst_get_immediate_width(&xedd);
        if (xed_decoded_inst_get_immediate_is_signed(&xedd)) {
          xed_int32_t signed_imm_val = 
	    xed_decoded_inst_get_signed_immediate(&xedd);
          eh->operand[op_idx].value = (uint32_t) signed_imm_val;
        }
        else {
          xed_uint64_t unsigned_imm_val =
            xed_decoded_inst_get_unsigned_immediate(&xedd);
          eh->operand[op_idx].value = (uint32_t) unsigned_imm_val;
        }
        break;
      break;
      }
      /* Special immediate only used in ENTER instruction */
      case XED_OPERAND_IMM1: {
        op_idx++;
        eh->num_operands++;
        eh->operand[op_idx].type = TImmediate;
	eh->operand[op_idx].length = 
	  (uint8_t) xed_decoded_inst_operand_length (&xedd, i);
	eh->operand[op_idx].access = (uint8_t) xed_operand_rw (op);
        xed_uint8_t unsigned_imm_val = 
	  xed_decoded_inst_get_second_immediate(&xedd);
        eh->operand[op_idx].value = (uint32_t) unsigned_imm_val;
        break;
      }


      /* Memory */
      case XED_OPERAND_AGEN:
      case XED_OPERAND_MEM0:
      case XED_OPERAND_MEM1: {
	unsigned long base = 0;
	unsigned long index = 0;
	unsigned long scale = 1;
	unsigned long segbase = 0;
	unsigned short segsel = 0;
	unsigned long displacement = 0;
	unsigned int j;
	size_t remaining = 0;

	/* Set memory index */
        int mem_idx = 0;
        if (op_name == XED_OPERAND_MEM1) mem_idx = 1;

	unsigned int memlen = xed_decoded_inst_operand_length (&xedd, i);

	for (j = 0; j < memlen; j+=4) {
	  /* Initialization */
	  base = 0;
	  index = 0;
	  scale = 1;
	  segbase = 0;
	  segsel = 0;
	  displacement = 0;
	  remaining = memlen - j;

	  op_idx++;
	  if(op_idx >= MAX_NUM_OPERANDS)
	    break;
	  //assert(op_idx < MAX_NUM_OPERANDS);
	  eh->num_operands++;
	  eh->operand[op_idx].type = TMemLoc;
	  eh->operand[op_idx].access = (uint8_t) xed_operand_rw (op);
	  eh->operand[op_idx].length = 
	    remaining > 4 ? 4 : (uint8_t) remaining;

	  // Get Segment register
	  xed_reg_enum_t seg_regid = 
	    xed_decoded_inst_get_seg_reg(&xedd,mem_idx);

	  if (seg_regid != XED_REG_INVALID) {
	    const xed_operand_values_t *xopv = 
	      xed_decoded_inst_operands_const(&xedd);
	    xed_bool_t default_segment = 
	      xed_operand_values_using_default_segment (xopv,mem_idx);

	    if (!default_segment) {
	      eh->num_operands++;
	      int segmentreg = xed2chris_regmapping[seg_regid][0] - 100;

	      segbase = TEMU_cpu_segs[segmentreg].base;
	      segsel = TEMU_cpu_segs[segmentreg].selector;

	      eh->memregs[op_idx][0].type = TRegister;
	      eh->memregs[op_idx][0].length = 2;
	      eh->memregs[op_idx][0].addr = xed2chris_regmapping[seg_regid][0];
	      eh->memregs[op_idx][0].access = (uint8_t) XED_OPERAND_ACTION_R;
	      eh->memregs[op_idx][0].value = segsel;
	      eh->memregs[op_idx][0].usage = memsegment;
	      if (ignore_taint == 0) 
		set_operand_data(&(eh->memregs[op_idx][0]));

	      int dt;
	      if (segsel & 0x4)       // ldt
		dt = TEMU_cpu_ldt->base;
	      else                    //gdt
		dt = TEMU_cpu_gdt->base;
	      segsel = segsel >> 3;

	      unsigned long segent = dt + 8 * segsel;
	      unsigned char segdes[8];
	      TEMU_read_mem(segent, 8, segdes);

#if 0
	      // debugging code to double check segbase value
	      unsigned long segbasenew = segdes[2] + segdes[3] * 256 +
	      segdes[4] * 256 * 256 + segdes[7] * 256 * 256 * 256;
	      if (segbase != segbasenew) {
		term_printf("segbase unexpected: 0x%08lX v.s 0x%08lX\n",
			segbase, segbasenew);
	      }
#endif
	      /* Segment descriptor is stored as a memory operand */
	      eh->num_operands+=2;
	      eh->memregs[op_idx][3].type = TMemLoc;
	      eh->memregs[op_idx][3].length = 4;
	      eh->memregs[op_idx][3].addr = segent;
	      eh->memregs[op_idx][3].access = 
		(uint8_t) XED_OPERAND_ACTION_INVALID;
	      eh->memregs[op_idx][3].value = *(uint32_t *) segdes;
	      eh->memregs[op_idx][3].tainted = 0;
	      eh->memregs[op_idx][3].usage = memsegent0;

	      eh->memregs[op_idx][4].type = TMemLoc;
	      eh->memregs[op_idx][4].length = 4;
	      eh->memregs[op_idx][4].addr = segent + 4;
	      eh->memregs[op_idx][4].access = 
		(uint8_t) XED_OPERAND_ACTION_INVALID;
	      eh->memregs[op_idx][4].value = *(uint32_t *) (segdes + 4);
	      eh->memregs[op_idx][4].tainted = 0;
	      eh->memregs[op_idx][4].usage = memsegent1;
	    }
	  }

	  // Get Base register
	  xed_reg_enum_t base_regid = 
	    xed_decoded_inst_get_base_reg(&xedd,mem_idx);
	  if (base_regid != XED_REG_INVALID) {
	    eh->num_operands++;
	    int basereg = xed2chris_regmapping[base_regid][1];
	    base = TEMU_cpu_regs[basereg];
	    eh->memregs[op_idx][1].type = TRegister;
	    eh->memregs[op_idx][1].addr = xed2chris_regmapping[base_regid][0];
	    eh->memregs[op_idx][1].length = 4;
	    eh->memregs[op_idx][1].access = (uint8_t) XED_OPERAND_ACTION_R;
	    eh->memregs[op_idx][1].value = base;
	    eh->memregs[op_idx][1].usage = membase;
	    if (ignore_taint == 0) set_operand_data(&(eh->memregs[op_idx][1]));
	  }
	  // Get Index register and Scale
	  xed_reg_enum_t index_regid = 
	    xed_decoded_inst_get_index_reg(&xedd,mem_idx);
	  if (mem_idx == 0 && index_regid != XED_REG_INVALID) {
	    eh->num_operands++;
	    int indexreg = xed2chris_regmapping[index_regid][1];
	    index = TEMU_cpu_regs[indexreg];
	    eh->memregs[op_idx][2].type = TRegister;
	    eh->memregs[op_idx][2].addr = xed2chris_regmapping[index_regid][0];
	    eh->memregs[op_idx][2].length = 4;
	    eh->memregs[op_idx][2].access = (uint8_t) XED_OPERAND_ACTION_R;
	    eh->memregs[op_idx][2].value = index;
	    eh->memregs[op_idx][2].usage = memindex;
	    if (ignore_taint == 0) set_operand_data(&(eh->memregs[op_idx][2]));

	    // Get Scale (AKA width) (only have a scale if the index exists)
	    if (xed_decoded_inst_get_scale(&xedd,i) != 0) {
	      scale = (unsigned long) xed_decoded_inst_get_scale(&xedd,mem_idx);
	    }
	  }
	  // Get displacement (AKA offset)
	  displacement = 
	    (unsigned long) xed_decoded_inst_get_memory_displacement
	    (&xedd,mem_idx);

	  // Fix displacement for:
	  //   1) Any instruction that pushes into the stack, since ESP is 
	  //        decremented before memory operand is written using ESP. 
	  //        Affects: ENTER,PUSH,PUSHA,PUSHF,CALL
	  if (is_stackpush) {
            stackpushpop_acc += eh->operand[op_idx].length;
            displacement = displacement - stackpushpop_acc -j;
	  }
	  //   2) Pop instructions where the 
	  //      destination operand is a memory location that uses ESP 
	  //        as base or index register. 
	  //      The pop operations increments ESP and the written memory 
	  //        location address needs to be adjusted.
	  //      Affects: pop (%esp)
	  else if ((category == XED_CATEGORY_POP) && (!is_stackpop)) {
	    if ((eh->memregs[op_idx][1].addr == esp_reg) || 
		(eh->memregs[op_idx][2].addr == esp_reg)) 
	    {
	      displacement = displacement + eh->operand[op_idx].length;
	    }
	  }

	  // Calculate memory address accessed
	  eh->operand[op_idx].addr =
	    j + segbase + base + index * scale + displacement;

	  // Special handling for LEA instructions
	  if (op_name == XED_OPERAND_AGEN) {
	    eh->operand[op_idx].type = TMemAddress;
	    eh->operand[op_idx].length = 4;
	    has_page_fault = 0; // LEA won't trigger page fault
	  }
	  else {
	    has_page_fault = TEMU_read_mem(eh->operand[op_idx].addr,
	      (int)(eh->operand[op_idx].length), 
	      (uint8_t *)&(eh->operand[op_idx].value));
	  }

	  // Check if instruction accesses user memory
	  // kernel_mem_start defined in shared/read_linux.c
	  if ((eh->operand[op_idx].addr < kernel_mem_start) &&
	    (op_name != XED_OPERAND_AGEN))
	  {
	    access_user_mem = 1;
	  }
	  if (ignore_taint == 0) set_operand_data(&(eh->operand[op_idx]));
	}
	break;
      }

      /* Jumps */
      case XED_OPERAND_PTR:  // pointer (always in conjunction with a IMM0)
      case XED_OPERAND_RELBR: { // branch displacements
          xed_uint_t disp = xed_decoded_inst_get_branch_displacement(&xedd);
	  /* Displacement is from instruction end */
	  /* Adjust displacement with instruction size */
	  disp = disp + eh->inst_size;
	  op_idx++;
	  eh->num_operands++;
	  eh->operand[op_idx].type = TJump;
	  eh->operand[op_idx].length = 4;
	  eh->operand[op_idx].access = (uint8_t) xed_operand_rw (op);
	  eh->operand[op_idx].value = disp;
          break;
      }

      /* Floating point registers */
      case XED_REG_X87CONTROL:
      case XED_REG_X87STATUS:
      case XED_REG_X87TOP:
      case XED_REG_X87TAG:
      case XED_REG_X87PUSH:
      case XED_REG_X87POP:
      case XED_REG_X87POP2:
          op_idx++;
          eh->num_operands++;
          eh->operand[op_idx].type = TFloatRegister;
          eh->operand[op_idx].length = 4;
	  eh->operand[op_idx].access = (uint8_t) xed_operand_rw (op);
      default:
        break;
     }
  }
Esempio n. 19
0
void OfflineX86Code::disasm(FILE* file,
                            TCA   fileStartAddr,
                            TCA   codeStartAddr,
                            uint64_t codeLen,
                            const PerfEventsMap<TCA>& perfEvents,
                            BCMappingInfo bcMappingInfo,
                            bool printAddr /* =true */,
                            bool printBinary /* =false */) {

  char codeStr[MAX_INSTR_ASM_LEN];
  xed_uint8_t* code = (xed_uint8_t*) alloca(codeLen);
  xed_uint8_t* frontier;
  TCA          ip;
  TCA          r10val = 0;
  size_t       currBC = 0;

  if (codeLen == 0) return;

  auto const offset = codeStartAddr - fileStartAddr;
  if (fseek(file, offset, SEEK_SET)) {
    error("disasm error: seeking file");
  }

  size_t readLen = fread(code, codeLen, 1, file);
  if (readLen != 1) {
    error("Failed to read {} bytes at offset {} from code file due to {}",
          codeLen, offset, feof(file) ? "EOF" : "read error");
  }

  xed_decoded_inst_t xedd;

  // Decode and print each instruction
  for (frontier = code, ip = codeStartAddr; frontier < code + codeLen; ) {

    xed_decoded_inst_zero_set_mode(&xedd, &xed_state);
    xed_decoded_inst_set_input_chip(&xedd, XED_CHIP_INVALID);
    xed_error_enum_t xed_error = xed_decode(&xedd, frontier, 15);

    if (xed_error != XED_ERROR_NONE) break;

    // Get disassembled instruction in codeStr
    if (!xed_format_context(xed_syntax, &xedd, codeStr,
                            MAX_INSTR_ASM_LEN, (uint64_t)ip, nullptr
#if XED_ENCODE_ORDER_MAX_ENTRIES != 28 // Newer version of XED library
                            , 0
#endif
                           )) {
      error("disasm error: xed_format_context failed");
    }

    // Annotate the x86 with its bytecode.
    currBC = printBCMapping(bcMappingInfo, currBC, (TCA)ip);

    if (printAddr) printf("%14p: ", ip);

    uint32_t instrLen = xed_decoded_inst_get_length(&xedd);

    if (printBinary) {
      uint32_t i;
      for (i=0; i < instrLen; i++) {
        printf("%02X", frontier[i]);
      }
      for (; i < 16; i++) {
        printf("  ");
      }
    }

    // For calls, we try to figure out the destination symbol name.
    // We look both at relative branches and the pattern:
    //    move r10, IMMEDIATE
    //    call r10
    xed_iclass_enum_t iclass = xed_decoded_inst_get_iclass(&xedd);
    string callDest = "";

    if (iclass == XED_ICLASS_CALL_NEAR || iclass == XED_ICLASS_CALL_FAR) {
      const xed_inst_t    *xi       = xed_decoded_inst_inst(&xedd);
      always_assert(xed_inst_noperands(xi) >= 1);
      const xed_operand_t *opnd     = xed_inst_operand(xi, 0);
      xed_operand_enum_t   opndName = xed_operand_name(opnd);

      if (opndName == XED_OPERAND_RELBR) {
        if (xed_decoded_inst_get_branch_displacement_width(&xedd)) {
          xed_int32_t disp = xed_decoded_inst_get_branch_displacement(&xedd);
          TCA         addr = ip + instrLen + disp;
          callDest = getSymbolName(addr);
        }
      } else if (opndName == XED_OPERAND_REG0) {
        if (xed_decoded_inst_get_reg(&xedd, opndName) == XED_REG_R10) {
          callDest = getSymbolName(r10val);
        }
      }
    } else if (iclass == XED_ICLASS_MOV) {
      // Look for moves into r10 and keep r10val updated
      const xed_inst_t* xi = xed_decoded_inst_inst(&xedd);

      always_assert(xed_inst_noperands(xi) >= 2);

      const xed_operand_t *destOpnd     = xed_inst_operand(xi, 0);
      xed_operand_enum_t   destOpndName = xed_operand_name(destOpnd);

      if (destOpndName == XED_OPERAND_REG0 &&
          xed_decoded_inst_get_reg(&xedd, destOpndName) == XED_REG_R10) {
        const xed_operand_t *srcOpnd     = xed_inst_operand(xi, 1);
        xed_operand_enum_t   srcOpndName = xed_operand_name(srcOpnd);
        if (srcOpndName == XED_OPERAND_IMM0) {
          TCA addr = (TCA)xed_decoded_inst_get_unsigned_immediate(&xedd);
          r10val = addr;
        }
      }
    }

    if (!perfEvents.empty()) {
      printEventStats((TCA)ip, instrLen, perfEvents);
    } else {
      printf("%48s", "");
    }
    printf("%s%s\n", codeStr, callDest.c_str());

    frontier += instrLen;
    ip       += instrLen;
  }
}