+void v3_print_instr(struct x86_instr * instr);
+
#define PREFIX_LOCK 0xF0
#define PREFIX_REPNE 0xF2
struct v3_gprs;
-static inline int decode_gpr(struct v3_gprs * gprs,
+static inline int decode_gpr(struct guest_info * core,
uint8_t reg_code,
struct x86_operand * reg) {
+ struct v3_gprs * gprs = &(core->vm_regs);
+
switch (reg_code) {
case 0:
reg->operand = (addr_t)&(gprs->rax);
}
break;
default:
+ PrintError("Invalid Reg Code (%d)\n", reg_code);
reg->operand = 0;
- break;
+ return -1;
}
return 0;
}
+
+
+static inline int decode_cr(struct guest_info * core,
+ uint8_t reg_code,
+ struct x86_operand * reg) {
+
+ struct v3_ctrl_regs * crs = &(core->ctrl_regs);
+
+ PrintDebug("\t Ctrl regs %d\n", reg_code);
+
+ switch (reg_code) {
+ case 0:
+ reg->operand = (addr_t)&(crs->cr0);
+ break;
+ case 2:
+ reg->operand = (addr_t)&(crs->cr2);
+ break;
+ case 3:
+ reg->operand = (addr_t)&(crs->cr3);
+ break;
+ case 4:
+ reg->operand = (addr_t)&(crs->cr4);
+ break;
+ default:
+ reg->operand = 0;
+ PrintError("Invalid Reg Code (%d)\n", reg_code);
+ return -1;
+ }
+
+ return 0;
+}
+
// This converts the displacement into the appropriate masked value
/*
QUESTION: Are the register Values signed ?????
val = (sint32_t)(reg & 0xffffffff); \
} else { \
PrintError("Error invalid displacement size (%d)\n", mode); \
- V3_ASSERT(0); \
+ /*V3_ASSERT(0);*/ \
} \
val; \
})
//PrintDebug("first operand = Register (RM=%d)\n",modrm->rm);
operand->type = REG_OPERAND;
- decode_gpr(gprs, modrm->rm, operand);
+ decode_gpr(core, modrm->rm, operand);
} else {
struct v3_segment * seg = NULL;
operand->type = REG_OPERAND;
// PrintDebug("first operand = Register (RM=%d)\n",modrm->rm);
- decode_gpr(gprs, modrm->rm, operand);
+ decode_gpr(core, modrm->rm, operand);
} else {
struct v3_segment * seg = NULL;
return INVALID_INSTR;
}
}
+
+
+
+static char * op_form_to_str(op_form_t form) {
+
+ switch (form) {
+ case LMSW: return "LMSW";
+ case SMSW: return "SMSW";
+ case CLTS: return "CLTS";
+ case INVLPG: return "INVLPG";
+ case MOV_CR2: return "MOV_CR2";
+ case MOV_2CR: return "MOV_2CR";
+ case MOV_DR2: return "MOV_DR2";
+ case MOV_2DR: return "MOV_2DR";
+ case MOV_SR2: return "MOV_SR2";
+ case MOV_2SR: return "MOV_2SR";
+ case MOV_MEM2_8: return "MOV_MEM2_8";
+ case MOV_MEM2: return "MOV_MEM2";
+ case MOV_2MEM_8: return "MOV_2MEM_8";
+ case MOV_2MEM: return "MOV_2MEM";
+ case MOV_MEM2AL_8: return "MOV_MEM2AL_8";
+ case MOV_MEM2AX: return "MOV_MEM2AX";
+ case MOV_AL2MEM_8: return "MOV_AL2MEM_8";
+ case MOV_AX2MEM: return "MOV_AX2MEM";
+ case MOV_IMM2_8: return "MOV_IMM2_8";
+ case MOV_IMM2: return "MOV_IMM2";
+ case MOVS_8: return "MOVS_8";
+ case MOVS: return "MOVS";
+ case MOVSX_8: return "MOVSX_8";
+ case MOVSX: return "MOVSX";
+ case MOVZX_8: return "MOVZX_8";
+ case MOVZX: return "MOVZX";
+ case HLT: return "HLT";
+ case PUSHF: return "PUSHF";
+ case POPF: return "POPF";
+ case ADC_2MEM_8: return "ADC_2MEM_8";
+ case ADC_2MEM: return "ADC_2MEM";
+ case ADC_MEM2_8: return "ADC_MEM2_8";
+ case ADC_MEM2: return "ADC_MEM2";
+ case ADC_IMM2_8: return "ADC_IMM2_8";
+ case ADC_IMM2: return "ADC_IMM2";
+ case ADC_IMM2SX_8: return "ADC_IMM2SX_8";
+ case ADD_IMM2_8: return "ADD_IMM2_8";
+ case ADD_IMM2: return "ADD_IMM2";
+ case ADD_IMM2SX_8: return "ADD_IMM2SX_8";
+ case ADD_2MEM_8: return "ADD_2MEM_8";
+ case ADD_2MEM: return "ADD_2MEM";
+ case ADD_MEM2_8: return "ADD_MEM2_8";
+ case ADD_MEM2: return "ADD_MEM2";
+ case AND_MEM2_8: return "AND_MEM2_8";
+ case AND_MEM2: return "AND_MEM2";
+ case AND_2MEM_8: return "AND_2MEM_8";
+ case AND_2MEM: return "AND_2MEM";
+ case AND_IMM2_8: return "AND_IMM2_8";
+ case AND_IMM2: return "AND_IMM2";
+ case AND_IMM2SX_8: return "AND_IMM2SX_8";
+ case OR_2MEM_8: return "OR_2MEM_8";
+ case OR_2MEM: return "OR_2MEM";
+ case OR_MEM2_8: return "OR_MEM2_8";
+ case OR_MEM2: return "OR_MEM2";
+ case OR_IMM2_8: return "OR_IMM2_8";
+ case OR_IMM2: return "OR_IMM2";
+ case OR_IMM2SX_8: return "OR_IMM2SX_8";
+ case SUB_2MEM_8: return "SUB_2MEM_8";
+ case SUB_2MEM: return "SUB_2MEM";
+ case SUB_MEM2_8: return "SUB_MEM2_8";
+ case SUB_MEM2: return "SUB_MEM2";
+ case SUB_IMM2_8: return "SUB_IMM2_8";
+ case SUB_IMM2: return "SUB_IMM2";
+ case SUB_IMM2SX_8: return "SUB_IMM2SX_8";
+ case XOR_2MEM_8: return "XOR_2MEM_8";
+ case XOR_2MEM: return "XOR_2MEM";
+ case XOR_MEM2_8: return "XOR_MEM2_8";
+ case XOR_MEM2: return "XOR_MEM2";
+ case XOR_IMM2_8: return "XOR_IMM2_8";
+ case XOR_IMM2: return "XOR_IMM2";
+ case XOR_IMM2SX_8: return "XOR_IMM2SX_8";
+ case INC_8: return "INC_8";
+ case INC: return "INC";
+ case DEC_8: return "DEC_8";
+ case DEC: return "DEC";
+ case NEG_8: return "NEG_8";
+ case NEG: return "NEG";
+ case NOT_8: return "NOT_8";
+ case NOT: return "NOT";
+ case XCHG_8: return "XCHG_8";
+ case XCHG: return "XCHG";
+ case SETB: return "SETB";
+ case SETBE: return "SETBE";
+ case SETL: return "SETL";
+ case SETLE: return "SETLE";
+ case SETNB: return "SETNB";
+ case SETNBE: return "SETNBE";
+ case SETNL: return "SETNL";
+ case SETNLE: return "SETNLE";
+ case SETNO: return "SETNO";
+ case SETNP: return "SETNP";
+ case SETNS: return "SETNS";
+ case SETNZ: return "SETNZ";
+ case SETP: return "SETP";
+ case SETS: return "SETS";
+ case SETZ: return "SETZ";
+ case SETO: return "SETO";
+ case STOS_8: return "STOS_8";
+ case STOS: return "STOS";
+
+ case INVALID_INSTR:
+ default:
+ return "INVALID_INSTR";
+ }
+}
V3_Print("32 bit Ctrl Regs:\n");
for (i = 0; reg_names[i] != NULL; i++) {
- V3_Print("\t%s=0x%p\n", reg_names[i], (void *)(addr_t)reg_ptr[i]);
+ V3_Print("\t%s=0x%p (at %p)\n", reg_names[i], (void *)(addr_t)reg_ptr[i], &(reg_ptr[i]));
}
V3_Print("\tEFER=0x%p\n", (void*)(addr_t)(guest_state->efer));
}
-
+#if 0
static int safe_gva_to_hva(struct guest_info * info, addr_t linear_addr, addr_t * host_addr) {
/* select the proper translation based on guest mode */
if (info->mem_mode == PHYSICAL_MEM) {
/* start disassembly 64 bytes before current RIP, continue 32 bytes after */
rip = (addr_t) info->rip - 64;
while ((int) (rip - info->rip) < 32) {
+ V3_Print("disassembly step\n");
+
/* always print RIP, even if the instructions before were bad */
if (!passed_rip && rip >= info->rip) {
if (rip != info->rip) {
rip++;
continue;
}
+
}
return 0;
}
+#endif
void v3_print_guest_state(struct guest_info * info) {
addr_t linear_addr = 0;
v3_print_stack(info);
- v3_print_disassembly(info);
+ // v3_print_disassembly(info);
}
void v3_print_guest_state_all(struct v3_vm_info * vm) {
V3_Print("32 bit GPRs:\n");
for (i = 0; reg_names[i] != NULL; i++) {
- V3_Print("\t%s=0x%p\n", reg_names[i], (void *)(addr_t)reg_ptr[i]);
+ V3_Print("\t%s=0x%p (at %p)\n", reg_names[i], (void *)(addr_t)reg_ptr[i], &(reg_ptr[i]));
}
}
V3_Print("64 bit GPRs:\n");
for (i = 0; reg_names[i] != NULL; i++) {
- V3_Print("\t%s=0x%p\n", reg_names[i], (void *)(addr_t)reg_ptr[i]);
+ V3_Print("\t%s=0x%p (at %p)\n", reg_names[i], (void *)(addr_t)reg_ptr[i], &(reg_ptr[i]));
}
}
}
}
}
+
+
+static char * op_type_to_str(v3_op_type_t type) {
+ switch (type) {
+ case V3_OP_MOVCR2: return "V3_OP_MOVCR2";
+ case V3_OP_MOV2CR: return "V3_OP_MOV2CR";
+ case V3_OP_SMSW: return "V3_OP_SMSW";
+ case V3_OP_LMSW: return "V3_OP_LMSW";
+ case V3_OP_CLTS: return "V3_OP_CLTS";
+ case V3_OP_INVLPG: return "V3_OP_INVLPG";
+ case V3_OP_ADC: return "V3_OP_ADC";
+ case V3_OP_ADD: return "V3_OP_ADD";
+ case V3_OP_AND: return "V3_OP_AND";
+ case V3_OP_OR: return "V3_OP_OR";
+ case V3_OP_XOR: return "V3_OP_XOR";
+ case V3_OP_SUB: return "V3_OP_SUB";
+ case V3_OP_INC: return "V3_OP_INC";
+ case V3_OP_DEC: return "V3_OP_DEC";
+ case V3_OP_NEG: return "V3_OP_NEG";
+ case V3_OP_MOV: return "V3_OP_MOV";
+ case V3_OP_NOT: return "V3_OP_NOT";
+ case V3_OP_XCHG: return "V3_OP_XCHG";
+ case V3_OP_SETB: return "V3_OP_SETB";
+ case V3_OP_SETBE: return "V3_OP_SETBE";
+ case V3_OP_SETL: return "V3_OP_SETL";
+ case V3_OP_SETLE: return "V3_OP_SETLE";
+ case V3_OP_SETNB: return "V3_OP_SETNB";
+ case V3_OP_SETNBE: return "V3_OP_SETNBE";
+ case V3_OP_SETNL: return "V3_OP_SETNL";
+ case V3_OP_SETNLE: return "V3_OP_SETNLE";
+ case V3_OP_SETNO: return "V3_OP_SETNO";
+ case V3_OP_SETNP: return "V3_OP_SETNP";
+ case V3_OP_SETNS: return "V3_OP_SETNS";
+ case V3_OP_SETNZ: return "V3_OP_SETNZ";
+ case V3_OP_SETO: return "V3_OP_SETO";
+ case V3_OP_SETP: return "V3_OP_SETP";
+ case V3_OP_SETS: return "V3_OP_SETS";
+ case V3_OP_SETZ: return "V3_OP_SETZ";
+ case V3_OP_MOVS: return "V3_OP_MOVS";
+ case V3_OP_STOS: return "V3_OP_STOS";
+ case V3_OP_MOVZX: return "V3_OP_MOVZX";
+ case V3_OP_MOVSX: return "V3_OP_MOVSX";
+ case V3_INVALID_OP:
+ default:
+ return "V3_INVALID_OP";
+ }
+}
+
+
+static char * operand_type_to_str(v3_operand_type_t op) {
+ switch (op) {
+ case REG_OPERAND: return "REG_OPERAND";
+ case MEM_OPERAND: return "MEM_OPERAND";
+ case IMM_OPERAND: return "IMM_OPERAND";
+ default:
+ return "INVALID_OPERAND";
+ }
+}
+
+
+static const ullong_t mask_1 = 0x00000000000000ffLL;
+static const ullong_t mask_2 = 0x000000000000ffffLL;
+static const ullong_t mask_4 = 0x00000000ffffffffLL;
+static const ullong_t mask_8 = 0xffffffffffffffffLL;
+
+
+#define MASK(val, length) ({ \
+ ullong_t mask = 0x0LL; \
+ switch (length) { \
+ case 1: \
+ mask = mask_1; \
+ break; \
+ case 2: \
+ mask = mask_2; \
+ break; \
+ case 4: \
+ mask = mask_4; \
+ break; \
+ case 8: \
+ mask = mask_8; \
+ break; \
+ } \
+ val & mask; \
+ })
+
+void v3_print_instr(struct x86_instr * instr) {
+ V3_Print("Instr: %s (Len: %d)\n", op_type_to_str(instr->op_type), instr->instr_length);
+
+ V3_Print("Prefixes= %x\n", *(uint32_t *)&(instr->prefixes));
+
+ if (instr->is_str_op) {
+ V3_Print("String OP (len=%d)\n", (uint32_t)instr->str_op_length);
+ }
+
+ V3_Print("Number of operands: %d\n", instr->num_operands);
+
+ if (instr->num_operands > 0) {
+ V3_Print("Src Operand (%s)\n", operand_type_to_str(instr->src_operand.type));
+ V3_Print("\tLen=%d (Addr: %p)\n", instr->src_operand.size,
+ (void *)instr->src_operand.operand);
+ if (instr->src_operand.type == REG_OPERAND) {
+ V3_Print("\tVal: %p\n", (void *)MASK(*(uint64_t *)(instr->src_operand.operand), instr->src_operand.size));
+ }
+ }
+
+ if (instr->num_operands > 1) {
+ V3_Print("Dst Operand (%s)\n", operand_type_to_str(instr->dst_operand.type));
+ V3_Print("\tLen=%d (Addr: %p)\n", instr->dst_operand.size,
+ (void *)instr->dst_operand.operand);
+ if (instr->dst_operand.type == REG_OPERAND) {
+ V3_Print("\tVal: %p\n", (void *)MASK(*(uint64_t *)(instr->dst_operand.operand), instr->dst_operand.size));
+ }
+ }
+
+ if (instr->num_operands > 2) {
+ V3_Print("Third Operand (%s)\n", operand_type_to_str(instr->third_operand.type));
+ V3_Print("\tLen=%d (Addr: %p)\n", instr->third_operand.size,
+ (void *)instr->third_operand.operand);
+ if (instr->third_operand.type == REG_OPERAND) {
+ V3_Print("\tVal: %p\n", (void *)MASK(*(uint64_t *)(instr->third_operand.operand), instr->third_operand.size));
+ }
+ }
+}
+
+
int v3_disasm(struct guest_info * info, void *instr_ptr, addr_t * rip, int mark) {
- return 0;
+ return -1;
}
int v3_encode(struct guest_info * info, struct x86_instr * instr, uint8_t * instr_buf) {
- return 0;
+ return -1;
}
int ret = 0;
int length = 0;
+
+ V3_Print("Decoding Instruction at %p\n", (void *)instr_ptr);
+
memset(instr, 0, sizeof(struct x86_instr));
// scan for prefixes
form = op_code_to_form((uint8_t *)(instr_ptr + length), &length);
+
+ V3_Print("\t decoded as (%s)\n", op_form_to_str(form));
+
if (form == INVALID_INSTR) {
PrintError("Could not find instruction form (%x)\n", *(uint32_t *)(instr_ptr + length));
return -1;
instr->instr_length += length;
+ v3_print_instr(instr);
+
return 0;
}
struct x86_instr * instr, op_form_t form) {
// get operational mode of the guest for operand width
uint8_t operand_width = get_operand_width(core, instr, form);
- uint8_t addr_width = get_addr_width(core, instr, form);;
+ uint8_t addr_width = get_addr_width(core, instr, form);
int ret = 0;
uint8_t * instr_start = instr_ptr;
+ PrintDebug("\tOperand width=%d, Addr width=%d\n", operand_width, addr_width);
+
switch (form) {
case ADC_IMM2_8:
case ADD_IMM2_8:
instr->src_operand.type = REG_OPERAND;
instr->src_operand.size = operand_width;
- decode_gpr(&(core->vm_regs), reg_code, &(instr->src_operand));
+ decode_gpr(core, reg_code, &(instr->src_operand));
instr->num_operands = 2;
break;
instr->dst_operand.size = operand_width;
instr->dst_operand.type = REG_OPERAND;
- decode_gpr(&(core->vm_regs), reg_code, &(instr->dst_operand));
+ decode_gpr(core, reg_code, &(instr->dst_operand));
instr->num_operands = 2;
}
// Source: DS:(E)SI
- // Source: ES:(E)DI
+ // Destination: ES:(E)DI
instr->src_operand.type = MEM_OPERAND;
instr->src_operand.size = operand_width;
instr->src_operand.operand = get_addr_linear(core, MASK(core->vm_regs.rsi, addr_width), &(core->segments.ds));
- instr->src_operand.type = MEM_OPERAND;
- instr->src_operand.size = operand_width;
- instr->src_operand.operand = get_addr_linear(core, MASK(core->vm_regs.rdi, addr_width), &(core->segments.es));
+ instr->dst_operand.type = MEM_OPERAND;
+ instr->dst_operand.size = operand_width;
+ instr->dst_operand.operand = get_addr_linear(core, MASK(core->vm_regs.rdi, addr_width), &(core->segments.es));
instr->num_operands = 2;
break;
+
+ case MOV_2CR: {
+ uint8_t reg_code = 0;
+
+ instr->src_operand.size = operand_width;
+
+ ret = decode_rm_operand(core, instr_ptr, instr, &(instr->src_operand),
+ ®_code);
+
+ if (ret == -1) {
+ PrintError("Error decoding operand for (%s)\n", op_form_to_str(form));
+ return -1;
+ }
+
+ instr_ptr += ret;
+
+ instr->dst_operand.type = REG_OPERAND;
+ instr->dst_operand.size = operand_width;
+ decode_cr(core, reg_code, &(instr->dst_operand));
+
+ instr->num_operands = 2;
+ break;
+ }
+ case MOV_CR2: {
+ uint8_t reg_code = 0;
+
+ instr->dst_operand.size = operand_width;
+
+ ret = decode_rm_operand(core, instr_ptr, instr, &(instr->dst_operand),
+ ®_code);
+
+ if (ret == -1) {
+ PrintError("Error decoding operand for (%s)\n", op_form_to_str(form));
+ return -1;
+ }
+
+ instr_ptr += ret;
+
+ instr->src_operand.type = REG_OPERAND;
+ instr->src_operand.size = operand_width;
+ decode_cr(core, reg_code, &(instr->src_operand));
+
+ instr->num_operands = 2;
+ break;
+ }
+ case STOS:
+ case STOS_8: {
+ instr->is_str_op = 1;
+
+ if (instr->prefixes.rep == 1) {
+ instr->str_op_length = MASK(core->vm_regs.rcx, operand_width);
+ } else {
+ instr->str_op_length = 1;
+ }
+
+ instr->src_operand.size = operand_width;
+ instr->src_operand.type = REG_OPERAND;
+ instr->src_operand.operand = (addr_t)&(core->vm_regs.rax);
+
+ instr->dst_operand.type = MEM_OPERAND;
+ instr->dst_operand.size = operand_width;
+ instr->dst_operand.operand = get_addr_linear(core, MASK(core->vm_regs.rdi, addr_width), &(core->segments.es));
+
+ instr->num_operands = 2;
+
+ break;
+ }
+ case INVLPG: {
+ uint8_t reg_code = 0;
+
+ // We use the dst operand here to maintain bug-for-bug compatibility with XED
+
+ instr->dst_operand.size = operand_width;
+
+ ret = decode_rm_operand(core, instr_ptr, instr, &(instr->dst_operand), ®_code);
+
+ if (ret == -1) {
+ PrintError("Error decoding operand for (%s)\n", op_form_to_str(form));
+ return -1;
+ }
+
+ instr_ptr += ret;
+
+ instr->num_operands = 1;
+ break;
+ }
+ case CLTS: {
+ // no operands.
+ break;
+
+ }
}
default:
- PrintError("Invalid Instruction form: %d\n", form);
+ PrintError("Invalid Instruction form: %s\n", op_form_to_str(form));
return -1;
}