1 /* 2 * Copyright 2008, François Revol, revol@free.fr 3 * Distributed under the terms of the MIT License. 4 */ 5 6 #include <OS.h> 7 #include <KernelExport.h> 8 9 #include <debug.h> 10 11 #include "disasm_arch.h" 12 #include "udis86.h" 13 14 15 static ud_t sUDState; 16 static addr_t sCurrentReadAddress; 17 static void (*sSyntax)(ud_t *) = UD_SYN_ATT; 18 static unsigned int sVendor = UD_VENDOR_INTEL; 19 20 21 static int 22 read_next_byte(struct ud*) 23 { 24 uint8_t buffer; 25 if (debug_memcpy(B_CURRENT_TEAM, &buffer, (void*)sCurrentReadAddress, 1) 26 != B_OK) { 27 kprintf("<read fault>\n"); 28 return UD_EOI; 29 } 30 31 sCurrentReadAddress++; 32 return buffer; 33 } 34 35 36 static void 37 setup_disassembler(addr_t where) 38 { 39 ud_set_input_hook(&sUDState, &read_next_byte); 40 sCurrentReadAddress = where; 41 ud_set_mode(&sUDState, 32); 42 ud_set_pc(&sUDState, (uint64_t)where); 43 ud_set_syntax(&sUDState, sSyntax); 44 ud_set_vendor(&sUDState, sVendor); 45 } 46 47 48 extern "C" void 49 disasm_arch_assert(const char *condition) 50 { 51 kprintf("assert: %s\n", condition); 52 } 53 54 55 status_t 56 disasm_arch_dump_insns(addr_t where, int count, addr_t baseAddress, 57 int backCount) 58 { 59 int skipCount = 0; 60 61 if (backCount > 0) { 62 // count the instructions from base address to start address 63 setup_disassembler(baseAddress); 64 addr_t address = baseAddress; 65 int baseCount = 0; 66 int len; 67 while (address < where && (len = ud_disassemble(&sUDState)) >= 1) { 68 address += len; 69 baseCount++; 70 } 71 72 if (address == where) { 73 if (baseCount > backCount) 74 skipCount = baseCount - backCount; 75 count += baseCount; 76 } else 77 baseAddress = where; 78 } else 79 baseAddress = where; 80 81 setup_disassembler(baseAddress); 82 83 for (int i = 0; i < count; i++) { 84 int ret; 85 ret = ud_disassemble(&sUDState); 86 if (ret < 1) 87 break; 88 89 if (skipCount > 0) { 90 skipCount--; 91 continue; 92 } 93 94 addr_t address = (addr_t)ud_insn_off(&sUDState); 95 if (address == where) 96 kprintf("\x1b[34m"); 97 98 // TODO: dig operands and lookup symbols 99 kprintf("0x%08lx: %16.16s\t%s\n", address, ud_insn_hex(&sUDState), 100 ud_insn_asm(&sUDState)); 101 102 if (address == where) 103 kprintf("\x1b[m"); 104 } 105 return B_OK; 106 } 107 108 109 status_t 110 disasm_arch_init() 111 { 112 ud_init(&sUDState); 113 // XXX: check for AMD and set sVendor; 114 return B_OK; 115 } 116 117 status_t 118 disasm_arch_fini() 119 { 120 return B_OK; 121 } 122 123 124