-#ifndef DEBUG_XED
+#ifndef V3_CONFIG_DEBUG_DECODER
#undef PrintDebug
#define PrintDebug(fmt, args...)
#endif
static int get_memory_operand(struct guest_info * info, xed_decoded_inst_t * xed_instr, uint_t index, struct x86_operand * operand);
static int set_decoder_mode(struct guest_info * info, xed_state_t * state) {
- switch (info->cpu_mode) {
+ switch (v3_get_vm_cpu_mode(info)) {
case REAL:
if (state->mmode != XED_MACHINE_MODE_LEGACY_16) {
xed_state_init(state,
-int v3_basic_mem_decode(struct guest_info * info, addr_t instr_ptr, struct basic_instr_info * instr_info) {
- xed_decoded_inst_t xed_instr;
- xed_error_enum_t xed_error;
-
-
- if (set_decoder_mode(info, info->decoder_state) == -1) {
- PrintError("Could not set decoder mode\n");
- return -1;
- }
-
-
- xed_decoded_inst_zero_set_mode(&xed_instr, info->decoder_state);
-
- xed_error = xed_decode(&xed_instr,
- REINTERPRET_CAST(const xed_uint8_t *, instr_ptr),
- XED_MAX_INSTRUCTION_BYTES);
-
- if (xed_error != XED_ERROR_NONE) {
- PrintError("Xed error: %s\n", xed_error_enum_t2str(xed_error));
- return -1;
- }
-
- instr_info->instr_length = xed_decoded_inst_get_length(&xed_instr);
-
-
- if (xed_decoded_inst_number_of_memory_operands(&xed_instr) == 0) {
- PrintError("Tried to decode memory operation with no memory operands\n");
- return -1;
- }
-
- instr_info->op_size = xed_decoded_inst_get_memory_operand_length(&xed_instr, 0);
-
-
- xed_category_enum_t cat = xed_decoded_inst_get_category(&xed_instr);
- if (cat == XED_CATEGORY_STRINGOP) {
- instr_info->str_op = 1;
- } else {
- instr_info->str_op = 0;
- }
-
- xed_operand_values_t * operands = xed_decoded_inst_operands(&xed_instr);
- if (xed_operand_values_has_real_rep(operands)) {
- instr_info->has_rep = 1;
- } else {
- instr_info->has_rep = 0;
- }
+int v3_deinit_decoder(struct guest_info * core) {
+ V3_Free(core->decoder_state);
return 0;
}
+
+
static int decode_string_op(struct guest_info * info,
xed_decoded_inst_t * xed_instr, const xed_inst_t * xi,
struct x86_instr * instr) {
return -1;
}
+
if (get_memory_operand(info, xed_instr, 1, &(instr->src_operand)) == -1) {
PrintError("Could not get Source memory operand\n");
return -1;
}
+ instr->dst_operand.write = 1;
+ instr->src_operand.read = 1;
+
if (instr->prefixes.rep == 1) {
addr_t reg_addr = 0;
uint_t reg_length = 0;
&(instr->src_operand.size));
instr->src_operand.type = REG_OPERAND;
+ instr->src_operand.read = 1;
+ instr->dst_operand.write = 1;
+
if (instr->prefixes.rep == 1) {
addr_t reg_addr = 0;
uint_t reg_length = 0;
- xed_reg_to_v3_reg(info, xed_decoded_inst_get_reg(xed_instr, XED_OPERAND_REG1), ®_addr, ®_length);
+ xed_reg_to_v3_reg(info, xed_decoded_inst_get_reg(xed_instr, XED_OPERAND_REG1),
+ ®_addr, ®_length);
instr->str_op_length = MASK(*(addr_t *)reg_addr, reg_length);
} else {
instr->str_op_length = 1;
+int v3_disasm(struct guest_info * info, void *instr_ptr, addr_t * rip, int mark) {
+ char buffer[256];
+ int i;
+ unsigned length;
+ xed_decoded_inst_t xed_instr;
+ xed_error_enum_t xed_error;
+
+ /* disassemble the specified instruction */
+ if (set_decoder_mode(info, info->decoder_state) == -1) {
+ PrintError("Could not set decoder mode\n");
+ return -1;
+ }
+
+ xed_decoded_inst_zero_set_mode(&xed_instr, info->decoder_state);
+
+ xed_error = xed_decode(&xed_instr,
+ REINTERPRET_CAST(const xed_uint8_t *, instr_ptr),
+ XED_MAX_INSTRUCTION_BYTES);
+
+ if (xed_error != XED_ERROR_NONE) {
+ PrintError("Xed error: %s\n", xed_error_enum_t2str(xed_error));
+ return -1;
+ }
+
+ /* obtain string representation in AT&T syntax */
+ if (!xed_format_att(&xed_instr, buffer, sizeof(buffer), *rip)) {
+ PrintError("Xed error: cannot disaaemble\n");
+ return -1;
+ }
+
+ /* print address, opcode bytes and the disassembled instruction */
+ length = xed_decoded_inst_get_length(&xed_instr);
+ V3_Print("0x%p %c ", (void *) *rip, mark ? '*' : ' ');
+ for (i = 0; i < length; i++) {
+ unsigned char b = ((unsigned char *) instr_ptr)[i];
+ V3_Print("%x%x ", b >> 4, b & 0xf);
+ }
+ while (i++ < 8) {
+ V3_Print(" ");
+ }
+ V3_Print("%s\n", buffer);
+
+ /* move on to next instruction */
+ *rip += length;
+ return 0;
+}
+
+
+
int v3_decode(struct guest_info * info, addr_t instr_ptr, struct x86_instr * instr) {
xed_decoded_inst_t xed_instr;
xed_error_enum_t xed_error;
+ memset(instr, 0, sizeof(struct x86_instr));
+
v3_get_prefixes((uchar_t *)instr_ptr, &(instr->prefixes));
xed_iform_enum_t iform = xed_decoded_inst_get_iform_enum(&xed_instr);
-#ifdef DEBUG_XED
+#ifdef V3_CONFIG_DEBUG_DECODER
xed_iclass_enum_t iclass = xed_decoded_inst_get_iclass(&xed_instr);
PrintDebug("iform=%s, iclass=%s\n", xed_iform_enum_t2str(iform), xed_iclass_enum_t2str(iclass));
case XED_OPERAND_IMM0:
+ {
+ v3_op->size = xed_decoded_inst_get_immediate_width(&xed_instr);
+
+ if (v3_op->size > 4) {
+ PrintError("Unhandled 64 bit immediates\n");
+ return -1;
+ }
+ v3_op->operand = xed_decoded_inst_get_unsigned_immediate(&xed_instr);
+
+ v3_op->type = IMM_OPERAND;
+
+ }
+ break;
case XED_OPERAND_AGEN:
case XED_OPERAND_PTR:
case XED_OPERAND_RELBR:
return -1;
}
}
+
+// V3_Print("Operand 0 mode: %s\n", xed_operand_action_enum_t2str(xed_operand_rw(op)));
+
+
+ if (xed_operand_read(op)) {
+ v3_op->read = 1;
+ }
+
+ if (xed_operand_written(op)) {
+ v3_op->write = 1;
+ }
+
}
// set second operand
*/
v3_op = &(instr->src_operand);
+
if (xed_operand_is_register(op_enum)) {
xed_reg_enum_t xed_reg = xed_decoded_inst_get_reg(&xed_instr, op_enum);
int v3_reg_type = xed_reg_to_v3_reg(info,
return -1;
}
}
+
+// V3_Print("Operand 1 mode: %s\n", xed_operand_action_enum_t2str(xed_operand_rw(op)));
+
+ if (xed_operand_read(op)) {
+ v3_op->read = 1;
+ }
+
+ if (xed_operand_written(op)) {
+ v3_op->write = 1;
+ }
+
}
// set third operand
xed_operand_type_enum_t op_type = xed_operand_type(op);
xed_operand_enum_t op_enum = xed_operand_name(op);
+
+
if (xed_operand_is_register(op_enum)) {
xed_reg_enum_t xed_reg = xed_decoded_inst_get_reg(&xed_instr, op_enum);
int v3_reg_type = xed_reg_to_v3_reg(info,
instr->third_operand.type = REG_OPERAND;
+ PrintDebug("Operand 2 mode: %s\n", xed_operand_action_enum_t2str(xed_operand_rw(op)));
+
+
+ if (xed_operand_read(op)) {
+ instr->third_operand.read = 1;
+ }
+
+ if (xed_operand_written(op)) {
+ instr->third_operand.write = 1;
+ }
+
} else {
PrintError("Unhandled third operand type %s\n", xed_operand_type_enum_t2str(op_type));
instr->num_operands = 2;
}
-int v3_encode(struct guest_info * info, struct x86_instr * instr, char * instr_buf) {
+int v3_encode(struct guest_info * info, struct x86_instr * instr, uint8_t * instr_buf) {
return -1;
}
addr_t scale;
addr_t index;
ullong_t displacement;
- int addr_width = v3_get_addr_width(info);;
+ int addr_width = v3_get_addr_width(info);
+ v3_cpu_mode_t cpu_mode = v3_get_vm_cpu_mode(info);
// struct v3_segment * seg_reg;
PrintDebug("Xed mode = %s\n", xed_machine_mode_enum_t2str(xed_state_get_machine_mode(info->decoder_state)));
index = MASK(mem_op.index, mem_op.index_size);
scale = mem_op.scale;
- // This is a horrendous hack...
- // XED really screwed the pooch in calculating the displacement
- if (v3_get_cpu_mode(info) == LONG) {
- displacement = mem_op.displacement;
- } else {
- displacement = MASK(mem_op.displacement, mem_op.displacement_size);
- }
+ // XED returns the displacement as a 2s complement signed number, but it can
+ // have different sizes, depending on the instruction encoding.
+ // we put that into a 64 bit unsigned (the unsigned doesn't matter since
+ // we only ever do 2s complement arithmetic on it. However, this means we
+ // need to sign-extend what XED provides through 64 bits.
+ displacement = mem_op.displacement;
+ displacement <<= 64 - mem_op.displacement_size * 8;
+ displacement = ((sllong_t)displacement) >> (64 - mem_op.displacement_size * 8);
+
PrintDebug("Seg=%p, base=%p, index=%p, scale=%p, displacement=%p\n",
(void *)seg, (void *)base, (void *)index, (void *)scale, (void *)(addr_t)displacement);
- operand->operand = MASK((seg + base + (scale * index) + displacement), addr_width);
+ if (cpu_mode == REAL) {
+ operand->operand = seg + MASK((base + (scale * index) + displacement), addr_width);
+ } else {
+ operand->operand = MASK((seg + base + (scale * index) + displacement), addr_width);
+ }
return 0;
}
-static int xed_reg_to_v3_reg(struct guest_info * info, xed_reg_enum_t xed_reg, addr_t * v3_reg, uint_t * reg_len) {
+static int xed_reg_to_v3_reg(struct guest_info * info, xed_reg_enum_t xed_reg,
+ addr_t * v3_reg, uint_t * reg_len) {
PrintDebug("Xed Register: %s\n", xed_reg_enum_t2str(xed_reg));
case XED_IFORM_INVLPG_MEMb:
return V3_OP_INVLPG;
+ case XED_IFORM_INT_IMM:
+ return V3_OP_INT;
+
/* Data Instructions */