11541Srgrimes/* 21541Srgrimes * Copyright 2008, Fran��ois Revol, revol@free.fr 31541Srgrimes * Distributed under the terms of the MIT License. 41541Srgrimes */ 51541Srgrimes 61541Srgrimes#include <OS.h> 71541Srgrimes#include <KernelExport.h> 81541Srgrimes 91541Srgrimes#include <debug.h> 101541Srgrimes 111541Srgrimes#include "disasm_arch.h" 121541Srgrimes#include "elf.h" 131541Srgrimes#include "udis86.h" 141541Srgrimes 151541Srgrimes 161541Srgrimesstatic ud_t sUDState; 171541Srgrimesstatic addr_t sCurrentReadAddress; 181541Srgrimesstatic void (*sSyntax)(ud_t *) = UD_SYN_ATT; 191541Srgrimesstatic unsigned int sVendor = UD_VENDOR_INTEL; 201541Srgrimes 211541Srgrimes 221541Srgrimesstatic int 231541Srgrimesread_next_byte(struct ud*) 241541Srgrimes{ 251541Srgrimes uint8_t buffer; 261541Srgrimes if (debug_memcpy(B_CURRENT_TEAM, &buffer, (void*)sCurrentReadAddress, 1) 271541Srgrimes != B_OK) { 281541Srgrimes kprintf("<read fault>\n"); 291541Srgrimes return UD_EOI; 301541Srgrimes } 311541Srgrimes 321541Srgrimes sCurrentReadAddress++; 331541Srgrimes return buffer; 341541Srgrimes} 351541Srgrimes 361541Srgrimes 3722521Sdysonstatic const char* 3850477Speterresolve_symbol(struct ud*, uint64_t address, int64_t* offset) 391541Srgrimes{ 401541Srgrimes const char* symbolName; 411541Srgrimes addr_t baseAddress; 421541Srgrimes status_t error; 4376166Smarkm 4476166Smarkm if (IS_KERNEL_ADDRESS(address)) { 451541Srgrimes error = elf_debug_lookup_symbol_address(address, &baseAddress, 467090Sbde &symbolName, NULL, NULL); 477090Sbde } else { 4874927Sjhb error = elf_debug_lookup_user_symbol_address( 4976166Smarkm debug_get_debugged_thread()->team, address, &baseAddress, 5076166Smarkm &symbolName, NULL, NULL); 5177031Sru } 527090Sbde 5322579Smpp if (error != B_OK) 5422579Smpp return NULL; 5522521Sdyson 5622521Sdyson *offset = address - baseAddress; 5722521Sdyson return symbolName; 587090Sbde} 591541Srgrimes 601541Srgrimes 611541Srgrimesstatic void 621541Srgrimessetup_disassembler(addr_t where) 631541Srgrimes{ 641541Srgrimes ud_set_input_hook(&sUDState, &read_next_byte); 651541Srgrimes sCurrentReadAddress = where; 661541Srgrimes#ifdef __x86_64__ 671541Srgrimes ud_set_mode(&sUDState, 64); 681541Srgrimes#else 691541Srgrimes ud_set_mode(&sUDState, 32); 701541Srgrimes#endif 711541Srgrimes ud_set_pc(&sUDState, (uint64_t)where); 721541Srgrimes ud_set_syntax(&sUDState, sSyntax); 731541Srgrimes ud_set_vendor(&sUDState, sVendor); 741541Srgrimes ud_set_sym_resolver(&sUDState, resolve_symbol); 751541Srgrimes} 761541Srgrimes 771541Srgrimes 781541Srgrimesextern "C" void 791541Srgrimesdisasm_arch_assert(const char *condition) 801541Srgrimes{ 811541Srgrimes kprintf("assert: %s\n", condition); 821541Srgrimes} 831541Srgrimes 841541Srgrimes 851541Srgrimesstatus_t 861541Srgrimesdisasm_arch_dump_insns(addr_t where, int count, addr_t baseAddress, 871541Srgrimes int backCount) 881541Srgrimes{ 891541Srgrimes int skipCount = 0; 901541Srgrimes 911541Srgrimes if (backCount > 0) { 921541Srgrimes // count the instructions from base address to start address 931541Srgrimes setup_disassembler(baseAddress); 941541Srgrimes addr_t address = baseAddress; 951541Srgrimes int baseCount = 0; 961541Srgrimes int len; 971541Srgrimes while (address < where && (len = ud_disassemble(&sUDState)) >= 1) { 981541Srgrimes address += len; 991541Srgrimes baseCount++; 1001541Srgrimes } 1011541Srgrimes 1021541Srgrimes if (address == where) { 1031541Srgrimes if (baseCount > backCount) 1041541Srgrimes skipCount = baseCount - backCount; 10512595Sbde count += baseCount; 10612595Sbde } else 1071541Srgrimes baseAddress = where; 1081541Srgrimes } else 1091541Srgrimes baseAddress = where; 1101541Srgrimes 1111541Srgrimes setup_disassembler(baseAddress); 1121541Srgrimes 11374927Sjhb for (int i = 0; i < count; i++) { 1141541Srgrimes int ret; 1151541Srgrimes ret = ud_disassemble(&sUDState); 11669958Srwatson if (ret < 1) 11769958Srwatson break; 11869958Srwatson 11969958Srwatson if (skipCount > 0) { 12069958Srwatson skipCount--; 12169958Srwatson continue; 12269958Srwatson } 12369958Srwatson 12469958Srwatson addr_t address = (addr_t)ud_insn_off(&sUDState); 12569958Srwatson if (address == where) 1261541Srgrimes kprintf("\x1b[34m"); 1271541Srgrimes 1281541Srgrimes // TODO: dig operands and lookup symbols 1291541Srgrimes kprintf("0x%08lx: %16.16s\t%s\n", address, ud_insn_hex(&sUDState), 13074927Sjhb ud_insn_asm(&sUDState)); 13173918Sjhb 13273918Sjhb if (address == where) 13374927Sjhb kprintf("\x1b[m"); 13474927Sjhb } 13573918Sjhb return B_OK; 1361541Srgrimes} 13774996Sjhb 13873918Sjhb 13974927Sjhbstatus_t 14074927Sjhbdisasm_arch_init() 14173918Sjhb{ 1421541Srgrimes ud_init(&sUDState); 1431541Srgrimes // XXX: check for AMD and set sVendor; 1441541Srgrimes return B_OK; 1451541Srgrimes} 1461541Srgrimes 1471541Srgrimes 1481541Srgrimesstatus_t 1491541Srgrimesdisasm_arch_fini() 1501541Srgrimes{ 1511541Srgrimes return B_OK; 1526569Sdg} 1531541Srgrimes 1541541Srgrimes 1551541Srgrimes