help
Compiles the Palacios library with debugging symbols
+choice
+ prompt "X86 decoder"
+ default XED
+
+config XED
+ bool "XED decoder library"
+ help
+ This uses the XED decoder library from pintools
+
+config V3_DECODER
+ bool "Internal Palacios decoder"
+ help
+ This selects the internal V3Vee x86 decoder
+
+
+endchoice
menu "Supported host OS features"
};
-struct basic_instr_info {
- uint_t instr_length;
- uint_t op_size;
- uint_t str_op : 1;
- uint_t has_rep : 1;
-};
-
-
-
/************************/
/* EXTERNAL DECODER API */
/************************/
int v3_encode(struct guest_info * info, struct x86_instr * instr, char * instr_buf);
-/*
- * Gets the operand size for a memory operation
- *
- */
-int v3_basic_mem_decode(struct guest_info * info, addr_t instr_ptr, struct basic_instr_info * instr_info);
-
-
/* Removes a rep prefix in place */
void v3_strip_rep_prefix(uchar_t * instr, int length);
void v3_get_prefixes(uchar_t * instr, struct x86_prefixes * prefixes);
-/*
- * JRL: Some of this was taken from the Xen sources...
- */
-
-#define PACKED __attribute__((packed))
-
-#define MODRM_MOD(x) ((x >> 6) & 0x3)
-#define MODRM_REG(x) ((x >> 3) & 0x7)
-#define MODRM_RM(x) (x & 0x7)
-
-struct modrm_byte {
- uint_t rm : 3 PACKED;
- uint_t reg : 3 PACKED;
- uint_t mod : 2 PACKED;
-};
-
-
-#define SIB_BASE(x) ((x >> 6) & 0x3)
-#define SIB_INDEX(x) ((x >> 3) & 0x7)
-#define SIB_SCALE(x) (x & 0x7)
-
-struct sib_byte {
- uint_t base : 3 PACKED;
- uint_t index : 3 PACKED;
- uint_t scale : 2 PACKED;
-};
-
-
-
-#define MAKE_INSTR(nm, ...) static const uchar_t V3_OPCODE_##nm[] = { __VA_ARGS__ }
-
-/*
- * Here's how it works:
- * First byte: Length.
- * Following bytes: Opcode bytes.
- * Special case: Last byte, if zero, doesn't need to match.
- */
-MAKE_INSTR(INVD, 2, 0x0f, 0x08);
-MAKE_INSTR(CPUID, 2, 0x0f, 0xa2);
-MAKE_INSTR(RDMSR, 2, 0x0f, 0x32);
-MAKE_INSTR(WRMSR, 2, 0x0f, 0x30);
-MAKE_INSTR(RDTSC, 2, 0x0f, 0x31);
-MAKE_INSTR(RDTSCP, 3, 0x0f, 0x01, 0xf9);
-MAKE_INSTR(CLI, 1, 0xfa);
-MAKE_INSTR(STI, 1, 0xfb);
-MAKE_INSTR(RDPMC, 2, 0x0f, 0x33);
-MAKE_INSTR(CLGI, 3, 0x0f, 0x01, 0xdd);
-MAKE_INSTR(STGI, 3, 0x0f, 0x01, 0xdc);
-MAKE_INSTR(VMRUN, 3, 0x0f, 0x01, 0xd8);
-MAKE_INSTR(VMLOAD, 3, 0x0f, 0x01, 0xda);
-MAKE_INSTR(VMSAVE, 3, 0x0f, 0x01, 0xdb);
-MAKE_INSTR(VMCALL, 3, 0x0f, 0x01, 0xd9);
-MAKE_INSTR(PAUSE, 2, 0xf3, 0x90);
-MAKE_INSTR(SKINIT, 3, 0x0f, 0x01, 0xde);
-MAKE_INSTR(MOV2CR, 3, 0x0f, 0x22, 0x00);
-MAKE_INSTR(MOVCR2, 3, 0x0f, 0x20, 0x00);
-MAKE_INSTR(MOV2DR, 3, 0x0f, 0x23, 0x00);
-MAKE_INSTR(MOVDR2, 3, 0x0f, 0x21, 0x00);
-MAKE_INSTR(PUSHF, 1, 0x9c);
-MAKE_INSTR(POPF, 1, 0x9d);
-MAKE_INSTR(RSM, 2, 0x0f, 0xaa);
-MAKE_INSTR(INVLPG, 3, 0x0f, 0x01, 0x00);
-MAKE_INSTR(INVLPGA,3, 0x0f, 0x01, 0xdf);
-MAKE_INSTR(HLT, 1, 0xf4);
-MAKE_INSTR(CLTS, 2, 0x0f, 0x06);
-MAKE_INSTR(LMSW, 3, 0x0f, 0x01, 0x00);
-MAKE_INSTR(SMSW, 3, 0x0f, 0x01, 0x00);
#define PREFIX_LOCK 0xF0
#define PREFIX_OP_SIZE 0x66
#define PREFIX_ADDR_SIZE 0x67
-int v3_opcode_cmp(const uchar_t * op1, const uchar_t * op2);
+
static inline int is_prefix_byte(uchar_t byte) {
}
+
static inline addr_t get_addr_linear(struct guest_info * info, addr_t addr, struct v3_segment * seg) {
switch (info->cpu_mode) {
case REAL:
}
-typedef enum {INVALID_ADDR_TYPE, REG, DISP0, DISP8, DISP16, DISP32} modrm_mode_t;
-typedef enum {INVALID_REG_SIZE, REG64, REG32, REG16, REG8} reg_size_t;
-
-
-
-
-
-
-struct v3_gprs;
-
-static inline addr_t decode_register(struct v3_gprs * gprs, char reg_code, reg_size_t reg_size) {
- addr_t reg_addr;
-
- switch (reg_code) {
- case 0:
- reg_addr = (addr_t)&(gprs->rax);
- break;
- case 1:
- reg_addr = (addr_t)&(gprs->rcx);
- break;
- case 2:
- reg_addr = (addr_t)&(gprs->rdx);
- break;
- case 3:
- reg_addr = (addr_t)&(gprs->rbx);
- break;
- case 4:
- if (reg_size == REG8) {
- reg_addr = (addr_t)&(gprs->rax) + 1;
- } else {
- reg_addr = (addr_t)&(gprs->rsp);
- }
- break;
- case 5:
- if (reg_size == REG8) {
- reg_addr = (addr_t)&(gprs->rcx) + 1;
- } else {
- reg_addr = (addr_t)&(gprs->rbp);
- }
- break;
- case 6:
- if (reg_size == REG8) {
- reg_addr = (addr_t)&(gprs->rdx) + 1;
- } else {
- reg_addr = (addr_t)&(gprs->rsi);
- }
- break;
- case 7:
- if (reg_size == REG8) {
- reg_addr = (addr_t)&(gprs->rbx) + 1;
- } else {
- reg_addr = (addr_t)&(gprs->rdi);
- }
- break;
- default:
- reg_addr = 0;
- break;
- }
-
- return reg_addr;
-}
-
-
-
-static inline v3_operand_type_t decode_operands16(struct v3_gprs * gprs, // input/output
- char * modrm_instr, // input
- int * offset, // output
- addr_t * first_operand, // output
- addr_t * second_operand, // output
- reg_size_t reg_size) { // input
-
- struct modrm_byte * modrm = (struct modrm_byte *)modrm_instr;
- addr_t base_addr = 0;
- modrm_mode_t mod_mode = 0;
- v3_operand_type_t addr_type = INVALID_OPERAND;
- char * instr_cursor = modrm_instr;
-
- // PrintDebug("ModRM mod=%d\n", modrm->mod);
-
- instr_cursor += 1;
-
- if (modrm->mod == 3) {
- mod_mode = REG;
- addr_type = REG_OPERAND;
- //PrintDebug("first operand = Register (RM=%d)\n",modrm->rm);
-
- *first_operand = decode_register(gprs, modrm->rm, reg_size);
-
- } else {
-
- addr_type = MEM_OPERAND;
-
- if (modrm->mod == 0) {
- mod_mode = DISP0;
- } else if (modrm->mod == 1) {
- mod_mode = DISP8;
- } else if (modrm->mod == 2) {
- mod_mode = DISP16;
- }
-
- switch (modrm->rm) {
- case 0:
- base_addr = gprs->rbx + gprs->rsi;
- break;
- case 1:
- base_addr = gprs->rbx + gprs->rdi;
- break;
- case 2:
- base_addr = gprs->rbp + gprs->rsi;
- break;
- case 3:
- base_addr = gprs->rbp + gprs->rdi;
- break;
- case 4:
- base_addr = gprs->rsi;
- break;
- case 5:
- base_addr = gprs->rdi;
- break;
- case 6:
- if (modrm->mod == 0) {
- base_addr = 0;
- mod_mode = DISP16;
- } else {
- base_addr = gprs->rbp;
- }
- break;
- case 7:
- base_addr = gprs->rbx;
- break;
- }
-
-
-
- if (mod_mode == DISP8) {
- base_addr += (uchar_t)*(instr_cursor);
- instr_cursor += 1;
- } else if (mod_mode == DISP16) {
- base_addr += (ushort_t)*(instr_cursor);
- instr_cursor += 2;
- }
-
- *first_operand = base_addr;
- }
-
- *offset += (instr_cursor - modrm_instr);
- *second_operand = decode_register(gprs, modrm->reg, reg_size);
-
- return addr_type;
-}
-
-
-
-static inline v3_operand_type_t decode_operands32(struct v3_gprs * gprs, // input/output
- uchar_t * modrm_instr, // input
- int * offset, // output
- addr_t * first_operand, // output
- addr_t * second_operand, // output
- reg_size_t reg_size) { // input
-
- uchar_t * instr_cursor = modrm_instr;
- struct modrm_byte * modrm = (struct modrm_byte *)modrm_instr;
- addr_t base_addr = 0;
- modrm_mode_t mod_mode = 0;
- uint_t has_sib_byte = 0;
- v3_operand_type_t addr_type = INVALID_OPERAND;
-
-
-
- instr_cursor += 1;
-
- if (modrm->mod == 3) {
- mod_mode = REG;
- addr_type = REG_OPERAND;
-
- // PrintDebug("first operand = Register (RM=%d)\n",modrm->rm);
-
- *first_operand = decode_register(gprs, modrm->rm, reg_size);
-
- } else {
-
- addr_type = MEM_OPERAND;
-
- if (modrm->mod == 0) {
- mod_mode = DISP0;
- } else if (modrm->mod == 1) {
- mod_mode = DISP8;
- } else if (modrm->mod == 2) {
- mod_mode = DISP32;
- }
-
- switch (modrm->rm) {
- case 0:
- base_addr = gprs->rax;
- break;
- case 1:
- base_addr = gprs->rcx;
- break;
- case 2:
- base_addr = gprs->rdx;
- break;
- case 3:
- base_addr = gprs->rbx;
- break;
- case 4:
- has_sib_byte = 1;
- break;
- case 5:
- if (modrm->mod == 0) {
- base_addr = 0;
- mod_mode = DISP32;
- } else {
- base_addr = gprs->rbp;
- }
- break;
- case 6:
- base_addr = gprs->rsi;
- break;
- case 7:
- base_addr = gprs->rdi;
- break;
- }
-
- if (has_sib_byte) {
- instr_cursor += 1;
- struct sib_byte * sib = (struct sib_byte *)(instr_cursor);
- int scale = 1;
-
- instr_cursor += 1;
-
-
- if (sib->scale == 1) {
- scale = 2;
- } else if (sib->scale == 2) {
- scale = 4;
- } else if (sib->scale == 3) {
- scale = 8;
- }
-
-
- switch (sib->index) {
- case 0:
- base_addr = gprs->rax;
- break;
- case 1:
- base_addr = gprs->rcx;
- break;
- case 2:
- base_addr = gprs->rdx;
- break;
- case 3:
- base_addr = gprs->rbx;
- break;
- case 4:
- base_addr = 0;
- break;
- case 5:
- base_addr = gprs->rbp;
- break;
- case 6:
- base_addr = gprs->rsi;
- break;
- case 7:
- base_addr = gprs->rdi;
- break;
- }
-
- base_addr *= scale;
-
-
- switch (sib->base) {
- case 0:
- base_addr += gprs->rax;
- break;
- case 1:
- base_addr += gprs->rcx;
- break;
- case 2:
- base_addr += gprs->rdx;
- break;
- case 3:
- base_addr += gprs->rbx;
- break;
- case 4:
- base_addr += gprs->rsp;
- break;
- case 5:
- if (modrm->mod != 0) {
- base_addr += gprs->rbp;
- }
- break;
- case 6:
- base_addr += gprs->rsi;
- break;
- case 7:
- base_addr += gprs->rdi;
- break;
- }
-
- }
-
-
- if (mod_mode == DISP8) {
- base_addr += (uchar_t)*(instr_cursor);
- instr_cursor += 1;
- } else if (mod_mode == DISP32) {
- base_addr += (uint_t)*(instr_cursor);
- instr_cursor += 4;
- }
-
-
- *first_operand = base_addr;
- }
-
- *offset += (instr_cursor - modrm_instr);
-
- *second_operand = decode_register(gprs, modrm->reg, reg_size);
-
- return addr_type;
-}
-
-
#endif // !__V3VEE__
+++ /dev/null
-/*
- * This file is part of the Palacios Virtual Machine Monitor developed
- * by the V3VEE Project with funding from the United States National
- * Science Foundation and the Department of Energy.
- *
- * The V3VEE Project is a joint project between Northwestern University
- * and the University of New Mexico. You can find out more at
- * http://www.v3vee.org
- *
- * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu>
- * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org>
- * All rights reserved.
- *
- * Author: Jack Lange <jarusl@cs.northwestern.edu>
- *
- * This is free software. You are permitted to use,
- * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
- */
-
-#ifndef __VMM_EMULATOR_H__
-#define __VMM_EMULATOR_H__
-
-#ifdef __V3VEE__
-
-#include <palacios/vmm_list.h>
-#include <palacios/vmm_shadow_paging.h>
-#include <palacios/vmm_paging.h>
-
-
-
-
-
-
-
-
-struct emulation_state {
-
- uint_t running : 1;
- uint_t instr_length;
-
- uint_t tf_enabled : 1;
-};
-
-
-int v3_init_emulator(struct guest_info * info);
-
-
-int v3_emulation_exit_handler(struct guest_info * info);
-
-int v3_emulate_memory_write(struct guest_info * info, addr_t fault_gva,
- int (*write)(addr_t write_addr, void * src, uint_t length, void * priv_data),
- addr_t write_addr, void * private_data);
-int v3_emulate_memory_read(struct guest_info * info, addr_t fault_gva,
- int (*read)(addr_t read_addr, void * dst, uint_t length, void * priv_data),
- addr_t read_addr, void * private_data);
-
-
-#endif // !__V3VEE__
-
-#endif
-obj-y := libxed.a \
- v3-xed-compat.o
+obj-$(CONFIG_XED) := libxed.a \
+ v3-xed-compat.o
-obj-y := libxed32e.a \
- v3-xed-compat.o
+obj-$(CONFIG_XED) := libxed32e.a \
+ v3-xed-compat.o
vmm_string.o \
vmm_time.o \
vmm_util.o \
- vmm_xed.o \
vmm_binaries.o \
vmm_cpuid.o \
vmm_xml.o \
vmm_mtrr.o \
+
+obj-$(CONFIG_XED) += vmm_xed.o
+obj-$(CONFIG_V3_DECODER) += vmm_v3dec.o
+
obj-$(CONFIG_SVM) += svm.o \
svm_io.o \
svm_lowlevel.o \
if (vm->num_cores > avail_cores) {
- PrintError("Attempted to start a VM with too many cores (vm->num_cores = %d, avail_cores = %d, MAX=%d)\n", vm->num_cores, avail_cores, MAX_CORES);
+ PrintError("Attempted to start a VM with too many cores (vm->num_cores = %d, avail_cores = %d, MAX=%d)\n",
+ vm->num_cores, avail_cores, MAX_CORES);
return -1;
}
#include <palacios/vmm_decoder.h>
-int v3_opcode_cmp(const uchar_t * op1, const uchar_t * op2) {
- if (op1[0] != op2[0]) {
- return op1[0] - op2[0];;
- } else {
- return memcmp(op1 + 1, op2 + 1, op1[0]);
- }
-}
+
void v3_get_prefixes(uchar_t * instr, struct x86_prefixes * prefixes) {
+++ /dev/null
-/*
- * This file is part of the Palacios Virtual Machine Monitor developed
- * by the V3VEE Project with funding from the United States National
- * Science Foundation and the Department of Energy.
- *
- * The V3VEE Project is a joint project between Northwestern University
- * and the University of New Mexico. You can find out more at
- * http://www.v3vee.org
- *
- * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu>
- * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org>
- * All rights reserved.
- *
- * Author: Jack Lange <jarusl@cs.northwestern.edu>
- *
- * This is free software. You are permitted to use,
- * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
- */
-
-#include <palacios/vmm.h>
-#include <palacios/vmm_emulator.h>
-#include <palacios/vm_guest_mem.h>
-#include <palacios/vmm_decoder.h>
-#include <palacios/vmm_debug.h>
-#include <palacios/vmcb.h>
-#include <palacios/vmm_ctrl_regs.h>
-
-
-#ifndef CONFIG_DEBUG_EMULATOR
-#undef PrintDebug
-#define PrintDebug(fmt, args...)
-#endif
-
-
-int v3_init_emulator(struct guest_info * info) {
-
-
- emulator->tf_enabled = 0;
-
- return 0;
-}
-
-
-
-
-
-
-
-
-
-
-static int set_stepping(struct guest_info * info) {
- vmcb_ctrl_t * ctrl_area = GET_VMCB_CTRL_AREA((vmcb_t*)(info->vmm_data));
- ctrl_area->exceptions.db = 1;
-
- info->emulator.tf_enabled = ((struct rflags *)&(info->ctrl_regs.rflags))->tf;
-
- ((struct rflags *)&(info->ctrl_regs.rflags))->tf = 1;
-
- return 0;
-}
-
-
-static int unset_stepping(struct guest_info * info) {
- vmcb_ctrl_t * ctrl_area = GET_VMCB_CTRL_AREA((vmcb_t*)(info->vmm_data));
- ctrl_area->exceptions.db = 0;
-
- ((struct rflags *)&(info->ctrl_regs.rflags))->tf = info->emulator.tf_enabled;
-
- if (info->emulator.tf_enabled) {
- // Inject breakpoint exception into guest
- }
-
- return 0;
-
-}
-
-
-int v3_emulate_memory_read(struct guest_info * info, addr_t read_gva,
- int (*read)(addr_t read_addr, void * dst, uint_t length, void * priv_data),
- addr_t read_gpa, void * private_data) {
- struct basic_instr_info instr_info;
- uchar_t instr[15];
- int ret;
- addr_t data_addr_offset = PAGE_OFFSET(read_gva);
-
- PrintDebug("Emulating Read\n");
-
- if (info->mem_mode == PHYSICAL_MEM) {
- ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
- } else {
- ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
- }
-
- if (ret == -1) {
- PrintError("Could not read guest memory\n");
- return -1;
- }
-
-#ifdef CONFIG_DEBUG_EMULATOR
- PrintDebug("Instr (15 bytes) at %p:\n", (void *)(addr_t)instr);
- PrintTraceMemDump(instr, 15);
-#endif
-
-
- if (v3_basic_mem_decode(info, (addr_t)instr, &instr_info) == -1) {
- PrintError("Could not do a basic memory instruction decode\n");
- V3_Free(data_page);
- return -1;
- }
-
- // Read the data directly onto the emulated page
- ret = read(read_gpa, (void *)(data_page->page_addr + data_addr_offset), instr_info.op_size, private_data);
- if ((ret == -1) || ((uint_t)ret != instr_info.op_size)) {
- PrintError("Read error in emulator\n");
- return -1;
- }
-
-
-
- // setup_code_page(info, instr, &instr_info);
- set_stepping(info);
-
- info->emulator.running = 1;
- info->run_state = VM_EMULATING;
- info->emulator.instr_length = instr_info.instr_length;
-
- return 0;
-}
-
-
-
-int v3_emulate_memory_write(struct guest_info * info, addr_t write_gva,
- int (*write)(addr_t write_addr, void * src, uint_t length, void * priv_data),
- addr_t write_gpa, void * private_data) {
-
- struct basic_instr_info instr_info;
- uchar_t instr[15];
- int ret;
- addr_t data_addr_offset = PAGE_OFFSET(write_gva);
- int i;
-
- PrintDebug("Emulating Write for instruction at 0x%p\n", (void *)(addr_t)(info->rip));
-
- if (info->mem_mode == PHYSICAL_MEM) {
- ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
- } else {
- ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
- }
-
-
-
- if (v3_basic_mem_decode(info, (addr_t)instr, &instr_info) == -1) {
- PrintError("Could not do a basic memory instruction decode\n");
- V3_Free(write_op);
- V3_Free(data_page);
- return -1;
- }
-
- if (instr_info.has_rep==1) {
- PrintDebug("Emulated instruction has rep\n");
- }
-
-
- if (info->emulator.running == 0) {
- // setup_code_page(info, instr, &instr_info);
- set_stepping(info);
- info->emulator.running = 1;
- info->run_state = VM_EMULATING;
- info->emulator.instr_length = instr_info.instr_length;
- }
-
- return 0;
-}
-
-
-// end emulation
-int v3_emulation_exit_handler(struct guest_info * info) {
-
- unset_stepping(info);
-
-
- PrintDebug("returning from emulation\n");
-
- return 0;
-}
--- /dev/null
+/*
+ * This file is part of the Palacios Virtual Machine Monitor developed
+ * by the V3VEE Project with funding from the United States National
+ * Science Foundation and the Department of Energy.
+ *
+ * The V3VEE Project is a joint project between Northwestern University
+ * and the University of New Mexico. You can find out more at
+ * http://www.v3vee.org
+ *
+ * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu>
+ * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org>
+ * All rights reserved.
+ *
+ * Author: Jack Lange <jarusl@cs.northwestern.edu>
+ *
+ * This is free software. You are permitted to use,
+ * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
+ */
+
+#include <palacios/vmm_decoder.h>
+
+
+/* .... Giant fucking switch tables */
+
+
+
+#define MODRM_MOD(x) (((x) >> 6) & 0x3)
+#define MODRM_REG(x) (((x) >> 3) & 0x7)
+#define MODRM_RM(x) ((x) & 0x7)
+
+struct modrm_byte {
+ uint_t rm : 3;
+ uint_t reg : 3;
+ uint_t mod : 2;
+} __attribute__((packed));
+
+
+#define SIB_BASE(x) (((x) >> 6) & 0x3)
+#define SIB_INDEX(x) (((x) >> 3) & 0x7)
+#define SIB_SCALE(x) ((x) & 0x7)
+
+struct sib_byte {
+ uint_t base : 3;
+ uint_t index : 3;
+ uint_t scale : 2;
+} __attribute__((packed));
+
+
+
+
+typedef enum {
+ INVALID_INSTR,
+ LMSW,
+ SMSW,
+ CLTS,
+ INVLPG,
+
+ MOV_CR2,
+ MOV_2CR,
+ MOV_DR2,
+ MOV_2DR,
+ MOV_SR2,
+ MOV_2SR,
+
+ MOV_2GPR_8,
+ MOV_2GPR,
+ MOV_GPR2_8,
+ MOV_GPR2,
+ MOV_MEM2AL_8,
+ MOV_MEM2AX,
+ MOV_AL2MEM_8,
+ MOV_AX2MEM,
+ MOV_IMM2_8,
+ MOV_IMM2,
+
+ MOVS_8,
+ MOVS,
+ MOVSX_8,
+ MOVSX,
+ MOVZX_8,
+ MOVZX,
+
+ HLT,
+ PUSHF,
+ POPF,
+
+ ADC_2MEM_8,
+ ADC_2MEM,
+ ADC_MEM2_8,
+ ADC_MEM2,
+ ADC_IMM2_8,
+ ADC_IMM2,
+ ADC_IMM2SX_8,
+ ADD_IMM2_8,
+ ADD_IMM2,
+ ADD_IMM2SX_8,
+ ADD_2MEM_8,
+ ADD_2MEM,
+ ADD_MEM2_8,
+ ADD_MEM2,
+ AND_MEM2_8,
+ AND_MEM2,
+ AND_2MEM_8,
+ AND_2MEM,
+ AND_IMM2_8,
+ AND_IMM2,
+ AND_IMM2SX_8,
+ OR_2MEM_8,
+ OR_2MEM,
+ OR_MEM2_8,
+ OR_MEM2,
+ OR_IMM2_8,
+ OR_IMM2,
+ OR_IMM2SX_8,
+ SUB_2MEM_8,
+ SUB_2MEM,
+ SUB_MEM2_8,
+ SUB_MEM2,
+ SUB_IMM2_8,
+ SUB_IMM2,
+ SUB_IMM2SX_8,
+ XOR_2MEM_8,
+ XOR_2MEM,
+ XOR_MEM2_8,
+ XOR_MEM2,
+ XOR_IMM2_8,
+ XOR_IMM2,
+ XOR_IMM2SX_8,
+
+ INC_8,
+ INC,
+ DEC_8,
+ DEC,
+ NEG_8,
+ NEG,
+ NOT_8,
+ NOT,
+ XCHG_8,
+ XCHG,
+
+ SETB,
+ SETBE,
+ SETL,
+ SETLE,
+ SETNB,
+ SETNBE,
+ SETNL,
+ SETNLE,
+ SETNO,
+ SETNP,
+ SETNS,
+ SETNZ,
+ SETP,
+ SETS,
+ SETZ,
+ SETO,
+
+ STOS_8,
+ STOS
+} op_form_t;
+
+static op_form_t op_code_to_form(uint8_t * instr);
+
+
+
+typedef enum {INVALID_ADDR_TYPE, REG, DISP0, DISP8, DISP16, DISP32} modrm_mode_t;
+typedef enum {INVALID_REG_SIZE, REG64, REG32, REG16, REG8} reg_size_t;
+
+
+struct v3_gprs;
+
+static inline addr_t decode_register(struct v3_gprs * gprs, char reg_code, reg_size_t reg_size) {
+ addr_t reg_addr;
+
+ switch (reg_code) {
+ case 0:
+ reg_addr = (addr_t)&(gprs->rax);
+ break;
+ case 1:
+ reg_addr = (addr_t)&(gprs->rcx);
+ break;
+ case 2:
+ reg_addr = (addr_t)&(gprs->rdx);
+ break;
+ case 3:
+ reg_addr = (addr_t)&(gprs->rbx);
+ break;
+ case 4:
+ if (reg_size == REG8) {
+ reg_addr = (addr_t)&(gprs->rax) + 1;
+ } else {
+ reg_addr = (addr_t)&(gprs->rsp);
+ }
+ break;
+ case 5:
+ if (reg_size == REG8) {
+ reg_addr = (addr_t)&(gprs->rcx) + 1;
+ } else {
+ reg_addr = (addr_t)&(gprs->rbp);
+ }
+ break;
+ case 6:
+ if (reg_size == REG8) {
+ reg_addr = (addr_t)&(gprs->rdx) + 1;
+ } else {
+ reg_addr = (addr_t)&(gprs->rsi);
+ }
+ break;
+ case 7:
+ if (reg_size == REG8) {
+ reg_addr = (addr_t)&(gprs->rbx) + 1;
+ } else {
+ reg_addr = (addr_t)&(gprs->rdi);
+ }
+ break;
+ default:
+ reg_addr = 0;
+ break;
+ }
+
+ return reg_addr;
+}
+
+
+
+static inline v3_operand_type_t decode_operands16(struct v3_gprs * gprs, // input/output
+ char * modrm_instr, // input
+ int * offset, // output
+ addr_t * first_operand, // output
+ addr_t * second_operand, // output
+ reg_size_t reg_size) { // input
+
+ struct modrm_byte * modrm = (struct modrm_byte *)modrm_instr;
+ addr_t base_addr = 0;
+ modrm_mode_t mod_mode = 0;
+ v3_operand_type_t addr_type = INVALID_OPERAND;
+ char * instr_cursor = modrm_instr;
+
+ // PrintDebug("ModRM mod=%d\n", modrm->mod);
+
+ instr_cursor += 1;
+
+ if (modrm->mod == 3) {
+ mod_mode = REG;
+ addr_type = REG_OPERAND;
+ //PrintDebug("first operand = Register (RM=%d)\n",modrm->rm);
+
+ *first_operand = decode_register(gprs, modrm->rm, reg_size);
+
+ } else {
+
+ addr_type = MEM_OPERAND;
+
+ if (modrm->mod == 0) {
+ mod_mode = DISP0;
+ } else if (modrm->mod == 1) {
+ mod_mode = DISP8;
+ } else if (modrm->mod == 2) {
+ mod_mode = DISP16;
+ }
+
+ switch (modrm->rm) {
+ case 0:
+ base_addr = gprs->rbx + gprs->rsi;
+ break;
+ case 1:
+ base_addr = gprs->rbx + gprs->rdi;
+ break;
+ case 2:
+ base_addr = gprs->rbp + gprs->rsi;
+ break;
+ case 3:
+ base_addr = gprs->rbp + gprs->rdi;
+ break;
+ case 4:
+ base_addr = gprs->rsi;
+ break;
+ case 5:
+ base_addr = gprs->rdi;
+ break;
+ case 6:
+ if (modrm->mod == 0) {
+ base_addr = 0;
+ mod_mode = DISP16;
+ } else {
+ base_addr = gprs->rbp;
+ }
+ break;
+ case 7:
+ base_addr = gprs->rbx;
+ break;
+ }
+
+
+
+ if (mod_mode == DISP8) {
+ base_addr += (uchar_t)*(instr_cursor);
+ instr_cursor += 1;
+ } else if (mod_mode == DISP16) {
+ base_addr += (ushort_t)*(instr_cursor);
+ instr_cursor += 2;
+ }
+
+ *first_operand = base_addr;
+ }
+
+ *offset += (instr_cursor - modrm_instr);
+ *second_operand = decode_register(gprs, modrm->reg, reg_size);
+
+ return addr_type;
+}
+
+
+
+static inline v3_operand_type_t decode_operands32(struct v3_gprs * gprs, // input/output
+ uchar_t * modrm_instr, // input
+ int * offset, // output
+ addr_t * first_operand, // output
+ addr_t * second_operand, // output
+ reg_size_t reg_size) { // input
+
+ uchar_t * instr_cursor = modrm_instr;
+ struct modrm_byte * modrm = (struct modrm_byte *)modrm_instr;
+ addr_t base_addr = 0;
+ modrm_mode_t mod_mode = 0;
+ uint_t has_sib_byte = 0;
+ v3_operand_type_t addr_type = INVALID_OPERAND;
+
+
+
+ instr_cursor += 1;
+
+ if (modrm->mod == 3) {
+ mod_mode = REG;
+ addr_type = REG_OPERAND;
+
+ // PrintDebug("first operand = Register (RM=%d)\n",modrm->rm);
+
+ *first_operand = decode_register(gprs, modrm->rm, reg_size);
+
+ } else {
+
+ addr_type = MEM_OPERAND;
+
+ if (modrm->mod == 0) {
+ mod_mode = DISP0;
+ } else if (modrm->mod == 1) {
+ mod_mode = DISP8;
+ } else if (modrm->mod == 2) {
+ mod_mode = DISP32;
+ }
+
+ switch (modrm->rm) {
+ case 0:
+ base_addr = gprs->rax;
+ break;
+ case 1:
+ base_addr = gprs->rcx;
+ break;
+ case 2:
+ base_addr = gprs->rdx;
+ break;
+ case 3:
+ base_addr = gprs->rbx;
+ break;
+ case 4:
+ has_sib_byte = 1;
+ break;
+ case 5:
+ if (modrm->mod == 0) {
+ base_addr = 0;
+ mod_mode = DISP32;
+ } else {
+ base_addr = gprs->rbp;
+ }
+ break;
+ case 6:
+ base_addr = gprs->rsi;
+ break;
+ case 7:
+ base_addr = gprs->rdi;
+ break;
+ }
+
+ if (has_sib_byte) {
+ instr_cursor += 1;
+ struct sib_byte * sib = (struct sib_byte *)(instr_cursor);
+ int scale = 1;
+
+ instr_cursor += 1;
+
+
+ if (sib->scale == 1) {
+ scale = 2;
+ } else if (sib->scale == 2) {
+ scale = 4;
+ } else if (sib->scale == 3) {
+ scale = 8;
+ }
+
+
+ switch (sib->index) {
+ case 0:
+ base_addr = gprs->rax;
+ break;
+ case 1:
+ base_addr = gprs->rcx;
+ break;
+ case 2:
+ base_addr = gprs->rdx;
+ break;
+ case 3:
+ base_addr = gprs->rbx;
+ break;
+ case 4:
+ base_addr = 0;
+ break;
+ case 5:
+ base_addr = gprs->rbp;
+ break;
+ case 6:
+ base_addr = gprs->rsi;
+ break;
+ case 7:
+ base_addr = gprs->rdi;
+ break;
+ }
+
+ base_addr *= scale;
+
+
+ switch (sib->base) {
+ case 0:
+ base_addr += gprs->rax;
+ break;
+ case 1:
+ base_addr += gprs->rcx;
+ break;
+ case 2:
+ base_addr += gprs->rdx;
+ break;
+ case 3:
+ base_addr += gprs->rbx;
+ break;
+ case 4:
+ base_addr += gprs->rsp;
+ break;
+ case 5:
+ if (modrm->mod != 0) {
+ base_addr += gprs->rbp;
+ }
+ break;
+ case 6:
+ base_addr += gprs->rsi;
+ break;
+ case 7:
+ base_addr += gprs->rdi;
+ break;
+ }
+
+ }
+
+
+ if (mod_mode == DISP8) {
+ base_addr += (uchar_t)*(instr_cursor);
+ instr_cursor += 1;
+ } else if (mod_mode == DISP32) {
+ base_addr += (uint_t)*(instr_cursor);
+ instr_cursor += 4;
+ }
+
+
+ *first_operand = base_addr;
+ }
+
+ *offset += (instr_cursor - modrm_instr);
+
+ *second_operand = decode_register(gprs, modrm->reg, reg_size);
+
+ return addr_type;
+}
+
+
+
+static inline op_form_t op_code_to_form_0f(uint8_t * instr) {
+ switch (instr[1]) {
+ case 0x01: {
+ struct modrm_byte * modrm = (struct modrm_byte *)&(instr[2]);
+
+ switch (modrm->reg) {
+ case 4:
+ return SMSW;
+ case 6:
+ return LMSW;
+ case 7:
+ return INVLPG;
+ default:
+ return INVALID_INSTR;
+ }
+ }
+
+ case 0x06:
+ return CLTS;
+ case 0x20:
+ return MOV_CR2;
+ case 0x21:
+ return MOV_DR2;
+
+ case 0x22:
+ return MOV_2CR;
+ case 0x23:
+ return MOV_2DR;
+
+ case 0x90:
+ return SETO;
+ case 0x91:
+ return SETNO;
+ case 0x92:
+ return SETB;
+ case 0x93:
+ return SETNB;
+ case 0x94:
+ return SETZ;
+ case 0x95:
+ return SETNZ;
+ case 0x96:
+ return SETBE;
+ case 0x97:
+ return SETNBE;
+ case 0x98:
+ return SETS;
+ case 0x99:
+ return SETNS;
+ case 0x9a:
+ return SETP;
+ case 0x9b:
+ return SETNP;
+ case 0x9c:
+ return SETL;
+ case 0x9d:
+ return SETNL;
+ case 0x9e:
+ return SETLE;
+ case 0x9f:
+ return SETNLE;
+
+ case 0xb6:
+ return MOVZX_8;
+ case 0xb7:
+ return MOVZX;
+
+ case 0xbe:
+ return MOVSX_8;
+ case 0xbf:
+ return MOVSX;
+
+
+ default:
+ return INVALID_INSTR;
+ }
+}
+
+
+static op_form_t op_code_to_form(uint8_t * instr) {
+ switch (instr[0]) {
+ case 0x00:
+ return ADD_2MEM_8;
+ case 0x01:
+ return ADD_2MEM;
+ case 0x02:
+ return ADD_MEM2_8;
+ case 0x03:
+ return ADD_MEM2;
+
+ case 0x08:
+ return OR_2MEM_8;
+ case 0x09:
+ return OR_2MEM;
+ case 0x0a:
+ return OR_MEM2_8;
+ case 0x0b:
+ return OR_MEM2;
+
+
+ case 0x0f:
+ return op_code_to_form_0f(instr);
+
+ case 0x10:
+ return ADC_2MEM_8;
+ case 0x11:
+ return ADC_2MEM;
+ case 0x12:
+ return ADC_MEM2_8;
+ case 0x13:
+ return ADC_MEM2;
+
+ case 0x20:
+ return AND_2MEM_8;
+ case 0x21:
+ return AND_2MEM;
+ case 0x22:
+ return AND_MEM2_8;
+ case 0x23:
+ return AND_MEM2;
+
+ case 0x28:
+ return SUB_2MEM_8;
+ case 0x29:
+ return SUB_2MEM;
+ case 0x2a:
+ return SUB_MEM2_8;
+ case 0x2b:
+ return SUB_MEM2;
+
+
+ case 0x30:
+ return XOR_2MEM_8;
+ case 0x31:
+ return XOR_2MEM;
+ case 0x32:
+ return XOR_MEM2_8;
+ case 0x33:
+ return XOR_MEM2;
+
+ case 0x80:{
+ struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]);
+
+ switch (modrm->reg) {
+ case 0:
+ return ADD_IMM2_8;
+ case 1:
+ return OR_IMM2_8;
+ case 2:
+ return ADC_IMM2_8;
+ case 4:
+ return AND_IMM2_8;
+ case 5:
+ return SUB_IMM2_8;
+ case 6:
+ return XOR_IMM2_8;
+ default:
+ return INVALID_INSTR;
+ }
+ }
+ case 0x81: {
+ struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]);
+
+ switch (modrm->reg) {
+ case 0:
+ return ADD_IMM2;
+ case 1:
+ return OR_IMM2;
+ case 2:
+ return ADC_IMM2;
+ case 4:
+ return AND_IMM2;
+ case 5:
+ return SUB_IMM2;
+ case 6:
+ return XOR_IMM2;
+ default:
+ return INVALID_INSTR;
+ }
+ }
+ case 0x83: {
+ struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]);
+
+ switch (modrm->reg) {
+ case 0:
+ return ADD_IMM2SX_8;
+ case 1:
+ return OR_IMM2SX_8;
+ case 2:
+ return ADC_IMM2SX_8;
+ case 4:
+ return AND_IMM2SX_8;
+ case 5:
+ return SUB_IMM2SX_8;
+ case 6:
+ return XOR_IMM2SX_8;
+ default:
+ return INVALID_INSTR;
+ }
+ }
+
+ case 0x86:
+ return XCHG_8;
+ case 0x87:
+ return XCHG;
+ case 0x88:
+ return MOV_2GPR_8;
+ case 0x89:
+ return MOV_2GPR;
+ case 0x8a:
+ return MOV_GPR2_8;
+ case 0x8b:
+ return MOV_GPR2;
+
+ case 0x8c:
+ return MOV_SR2;
+ case 0x8e:
+ return MOV_2SR;
+
+
+ case 0x9c:
+ return PUSHF;
+ case 0x9d:
+ return POPF;
+
+ case 0xa0:
+ return MOV_MEM2AL_8;
+ case 0xa1:
+ return MOV_MEM2AX;
+ case 0xa2:
+ return MOV_AL2MEM_8;
+ case 0xa3:
+ return MOV_AX2MEM;
+
+ case 0xa4:
+ return MOVS_8;
+ case 0xa5:
+ return MOVS;
+
+ case 0xaa:
+ return STOS_8;
+ case 0xab:
+ return STOS;
+
+ case 0xc6:
+ return MOV_IMM2_8;
+ case 0xc7:
+ return MOV_IMM2;
+
+ case 0xf4:
+ return HLT;
+
+
+ case 0xf6: {
+ struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]);
+
+ switch (modrm->reg) {
+ case 2:
+ return NOT_8;
+ case 3:
+ return NEG_8;
+ default:
+ return INVALID_INSTR;
+ }
+ }
+ case 0xf7: {
+ struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]);
+
+ switch (modrm->reg) {
+ case 2:
+ return NOT;
+ case 3:
+ return NEG;
+ default:
+ return INVALID_INSTR;
+ }
+ }
+
+
+ case 0xfe: {
+ struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]);
+
+ switch (modrm->reg) {
+ case 0:
+ return INC_8;
+ case 1:
+ return DEC_8;
+ default:
+ return INVALID_INSTR;
+ }
+ }
+
+ case 0xff: {
+ struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]);
+
+ switch (modrm->reg) {
+ case 0:
+ return INC;
+ case 1:
+ return DEC;
+ default:
+ return INVALID_INSTR;
+ }
+ }
+
+ default:
+ return INVALID_INSTR;
+ }
+}
+
+int v3_disasm(struct guest_info * info, void *instr_ptr, addr_t * rip, int mark) {
+ return 0;
+}
+
+
+
+int v3_init_decoder(struct guest_info * core) {
+ return 0;
+}
+
+
+int v3_deinit_decoder(struct guest_info * core) {
+ return 0;
+}
+
+
+int v3_encode(struct guest_info * info, struct x86_instr * instr, char * instr_buf) {
+ return 0;
+}
+
+int v3_decode(struct guest_info * info, addr_t instr_ptr, struct x86_instr * instr) {
+ op_code_to_form((void *)instr_ptr);
+
+ return 0;
+}
}
-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;
- }
-
- return 0;
-}
static int decode_string_op(struct guest_info * info,