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 "elf.h" 13#include "udis86.h" 14 15 16static ud_t sUDState; 17static addr_t sCurrentReadAddress; 18static void (*sSyntax)(ud_t *) = UD_SYN_ATT; 19static unsigned int sVendor = UD_VENDOR_INTEL; 20 21 22static int 23read_next_byte(struct ud*) 24{ 25 uint8_t buffer; 26 if (debug_memcpy(B_CURRENT_TEAM, &buffer, (void*)sCurrentReadAddress, 1) 27 != B_OK) { 28 kprintf("<read fault>\n"); 29 return UD_EOI; 30 } 31 32 sCurrentReadAddress++; 33 return buffer; 34} 35 36 37static const char* 38resolve_symbol(struct ud*, uint64_t address, int64_t* offset) 39{ 40 const char* symbolName; 41 addr_t baseAddress; 42 status_t error; 43 44 if (IS_KERNEL_ADDRESS(address)) { 45 error = elf_debug_lookup_symbol_address(address, &baseAddress, 46 &symbolName, NULL, NULL); 47 } else { 48 error = elf_debug_lookup_user_symbol_address( 49 debug_get_debugged_thread()->team, address, &baseAddress, 50 &symbolName, NULL, NULL); 51 } 52 53 if (error != B_OK) 54 return NULL; 55 56 *offset = address - baseAddress; 57 return symbolName; 58} 59 60 61static void 62setup_disassembler(addr_t where) 63{ 64 ud_set_input_hook(&sUDState, &read_next_byte); 65 sCurrentReadAddress = where; 66#ifdef __x86_64__ 67 ud_set_mode(&sUDState, 64); 68#else 69 ud_set_mode(&sUDState, 32); 70#endif 71 ud_set_pc(&sUDState, (uint64_t)where); 72 ud_set_syntax(&sUDState, sSyntax); 73 ud_set_vendor(&sUDState, sVendor); 74 ud_set_sym_resolver(&sUDState, resolve_symbol); 75} 76 77 78extern "C" void 79disasm_arch_assert(const char *condition) 80{ 81 kprintf("assert: %s\n", condition); 82} 83 84 85status_t 86disasm_arch_dump_insns(addr_t where, int count, addr_t baseAddress, 87 int backCount) 88{ 89 int skipCount = 0; 90 91 if (backCount > 0) { 92 // count the instructions from base address to start address 93 setup_disassembler(baseAddress); 94 addr_t address = baseAddress; 95 int baseCount = 0; 96 int len; 97 while (address < where && (len = ud_disassemble(&sUDState)) >= 1) { 98 address += len; 99 baseCount++; 100 } 101 102 if (address == where) { 103 if (baseCount > backCount) 104 skipCount = baseCount - backCount; 105 count += baseCount; 106 } else 107 baseAddress = where; 108 } else 109 baseAddress = where; 110 111 setup_disassembler(baseAddress); 112 113 for (int i = 0; i < count; i++) { 114 int ret; 115 ret = ud_disassemble(&sUDState); 116 if (ret < 1) 117 break; 118 119 if (skipCount > 0) { 120 skipCount--; 121 continue; 122 } 123 124 addr_t address = (addr_t)ud_insn_off(&sUDState); 125 if (address == where) 126 kprintf("\x1b[34m"); 127 128 // TODO: dig operands and lookup symbols 129 kprintf("0x%08lx: %16.16s\t%s\n", address, ud_insn_hex(&sUDState), 130 ud_insn_asm(&sUDState)); 131 132 if (address == where) 133 kprintf("\x1b[m"); 134 } 135 return B_OK; 136} 137 138 139status_t 140disasm_arch_init() 141{ 142 ud_init(&sUDState); 143 // XXX: check for AMD and set sVendor; 144 return B_OK; 145} 146 147 148status_t 149disasm_arch_fini() 150{ 151 return B_OK; 152} 153 154 155