From: Erik van der Kouwe Date: Fri, 26 Nov 2010 16:57:29 +0000 (-0600) Subject: disassemble the code around the RIP. It starts disassembly 64 bytes before and contin... X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=commitdiff_plain;h=7043e3314c5843994dbd6615aca71b0378950b3e;p=palacios.git disassemble the code around the RIP. It starts disassembly 64 bytes before and continues up to 32 bytes after the RIP --- diff --git a/palacios/include/palacios/vmm_xed.h b/palacios/include/palacios/vmm_xed.h index 95e68ec..ef1def2 100644 --- a/palacios/include/palacios/vmm_xed.h +++ b/palacios/include/palacios/vmm_xed.h @@ -22,6 +22,7 @@ #ifdef __V3VEE__ +int v3_disasm(struct guest_info * info, void *instr_ptr, addr_t * rip, int mark); #endif // ! __V3VEE__ diff --git a/palacios/src/palacios/vm_guest.c b/palacios/src/palacios/vm_guest.c index cca2359..e9ff5f7 100644 --- a/palacios/src/palacios/vm_guest.c +++ b/palacios/src/palacios/vm_guest.c @@ -29,6 +29,7 @@ #include #include #include +#include v3_cpu_mode_t v3_get_vm_cpu_mode(struct guest_info * info) { @@ -257,6 +258,55 @@ void v3_print_ctrl_regs(struct guest_info * info) { } +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) { + if (v3_gpa_to_hva(info, linear_addr, host_addr) == -1) return -1; + } else if (info->mem_mode == VIRTUAL_MEM) { + if (v3_gva_to_hva(info, linear_addr, host_addr) == -1) return -1; + } + return 0; +} + +static int v3_print_disassembly(struct guest_info * info) { + int passed_rip = 0; + addr_t rip, rip_linear, rip_host; + + /* we don't know where the instructions preceding RIP start, so we just take + * a guess and hope the instruction stream synced up with our disassembly + * some time before RIP; if it has not we correct RIP at that point + */ + + /* start disassembly 64 bytes before current RIP, continue 32 bytes after */ + rip = (addr_t) info->rip - 64; + while ((int) (rip - info->rip) < 32) { + /* always print RIP, even if the instructions before were bad */ + if (!passed_rip && rip >= info->rip) { + if (rip != info->rip) { + V3_Print("***** bad disassembly up to this point *****\n"); + rip = info->rip; + } + passed_rip = 1; + } + + /* look up host virtual address for this instruction */ + rip_linear = get_addr_linear(info, rip, &(info->segments.cs)); + if (safe_gva_to_hva(info, rip_linear, &rip_host) < 0) { + rip++; + continue; + } + + /* print disassembled instrcution (updates rip) */ + if (v3_disasm(info, (void *) rip_host, &rip, rip == info->rip) < 0) { + rip++; + continue; + } + } + + return 0; +} + + void v3_print_guest_state(struct guest_info * info) { addr_t linear_addr = 0; @@ -281,6 +331,8 @@ void v3_print_guest_state(struct guest_info * info) { v3_print_mem_map(info->vm_info); v3_print_stack(info); + + v3_print_disassembly(info); } diff --git a/palacios/src/palacios/vmm_xed.c b/palacios/src/palacios/vmm_xed.c index bd0d4f0..99ce14e 100644 --- a/palacios/src/palacios/vmm_xed.c +++ b/palacios/src/palacios/vmm_xed.c @@ -294,6 +294,55 @@ static int decode_string_op(struct guest_info * info, +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;