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 16 static ud_t sUDState; 17 static addr_t sCurrentReadAddress; 18 static void (*sSyntax)(ud_t *) = UD_SYN_ATT; 19 static unsigned int sVendor = UD_VENDOR_INTEL; 20 21 22 static int 23 read_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 37 static const char* 38 resolve_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 61 static void 62 setup_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 78 extern "C" void 79 disasm_arch_assert(const char *condition) 80 { 81 kprintf("assert: %s\n", condition); 82 } 83 84 85 status_t 86 disasm_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 139 status_t 140 disasm_arch_init() 141 { 142 ud_init(&sUDState); 143 // XXX: check for AMD and set sVendor; 144 return B_OK; 145 } 146 147 148 status_t 149 disasm_arch_fini() 150 { 151 return B_OK; 152 } 153 154 155