diff --git a/src/add-ons/kernel/debugger/disasm/Jamfile b/src/add-ons/kernel/debugger/disasm/Jamfile index facbf0a314..034cf17cd5 100644 --- a/src/add-ons/kernel/debugger/disasm/Jamfile +++ b/src/add-ons/kernel/debugger/disasm/Jamfile @@ -1,6 +1,6 @@ SubDir HAIKU_TOP src add-ons kernel debugger disasm ; -UsePrivateHeaders kernel ; +UsePrivateKernelHeaders ; KernelAddon disasm : disasm.cpp diff --git a/src/add-ons/kernel/debugger/disasm/disasm.cpp b/src/add-ons/kernel/debugger/disasm/disasm.cpp index 7d379cdff5..93e77955fa 100644 --- a/src/add-ons/kernel/debugger/disasm/disasm.cpp +++ b/src/add-ons/kernel/debugger/disasm/disasm.cpp @@ -5,6 +5,8 @@ #include #include +#include +#include #include #include "disasm_arch.h" @@ -13,15 +15,29 @@ int disasm_command(int argc, char **argv) { - if (argc > 3) { + int argi = 1; + + // get back count + uint64 backCount = 0; + if (argi < argc && strcmp(argv[argi], "-b") == 0) { + if (++argi >= argc) { + print_debugger_command_usage(argv[0]); + return 0; + } + + if (!evaluate_debug_expression(argv[argi++], &backCount, false)) + return 0; + } + + if (argi + 2 < argc) { print_debugger_command_usage(argv[0]); return 0; } // get PC uint64 pc; - if (argc >= 2) { - if (!evaluate_debug_expression(argv[1], &pc, false)) + if (argi < argc) { + if (!evaluate_debug_expression(argv[argi++], &pc, false)) return 0; } else { pc = (addr_t)arch_debug_get_interrupt_pc(); @@ -33,14 +49,37 @@ disasm_command(int argc, char **argv) // get count uint64 count = 10; - if (argc >= 3) { - if (!evaluate_debug_expression(argv[2], &count, false)) + if (argi < argc) { + if (!evaluate_debug_expression(argv[argi++], &count, false)) return 0; } // TODO: autoincrement - disasm_arch_dump_insns((addr_t)pc, count); + // if back count is given, compute base address + addr_t baseAddress = 0; + if (backCount > 0) { + status_t error; + const char *symbol; + const char *imageName; + bool exactMatch; + + if (IS_KERNEL_ADDRESS(pc)) { + error = elf_debug_lookup_symbol_address(pc, &baseAddress, &symbol, + &imageName, &exactMatch); + } else { + error = elf_debug_lookup_user_symbol_address( + debug_get_debugged_thread()->team, pc, &baseAddress, &symbol, + &imageName, &exactMatch); + } + + if (error != B_OK) { + baseAddress = 0; + backCount = 0; + } + } + + disasm_arch_dump_insns((addr_t)pc, count, baseAddress, backCount); return 0; } @@ -56,11 +95,14 @@ std_ops(int32 op, ...) return err; return add_debugger_command_etc("dis", disasm_command, "Print disassembly at address", - "[
[ ] ]\n" + "[ -b ] [
[ ] ]\n" "Prints disassembly at address.\n" - "
- Address at which to start disassembling\n" - " (defaults to current PC).\n" - " - Number of instructions to disassemble.\n", 0); + "
- Address at which to start disassembling\n" + " (defaults to current PC).\n" + " - Number of instructions to disassemble\n" + " starting at
.\n" + " -b - Number of instruction to disassemble before\n" + "
.\n", 0); } else if (op == B_MODULE_UNINIT) { remove_debugger_command("dis", disasm_command); return disasm_arch_fini(); diff --git a/src/add-ons/kernel/debugger/disasm/disasm_arch.h b/src/add-ons/kernel/debugger/disasm/disasm_arch.h index adee93c1d2..2243670288 100644 --- a/src/add-ons/kernel/debugger/disasm/disasm_arch.h +++ b/src/add-ons/kernel/debugger/disasm/disasm_arch.h @@ -12,7 +12,8 @@ extern "C" { extern status_t disasm_arch_init(); extern status_t disasm_arch_fini(); -extern status_t disasm_arch_dump_insns(addr_t where, int count); +extern status_t disasm_arch_dump_insns(addr_t where, int count, + addr_t baseAddress, int backCount); #ifdef __cplusplus } diff --git a/src/add-ons/kernel/debugger/disasm/m68k/disasm_arch.cpp b/src/add-ons/kernel/debugger/disasm/m68k/disasm_arch.cpp index 074b398806..00d68f7adf 100644 --- a/src/add-ons/kernel/debugger/disasm/m68k/disasm_arch.cpp +++ b/src/add-ons/kernel/debugger/disasm/m68k/disasm_arch.cpp @@ -8,7 +8,8 @@ #include "disasm_arch.h" status_t -disasm_arch_dump_insns(addr_t where, int count) +disasm_arch_dump_insns(addr_t where, int count, addr_t baseAddress, + int backCount) { return ENOENT; } diff --git a/src/add-ons/kernel/debugger/disasm/ppc/disasm_arch.cpp b/src/add-ons/kernel/debugger/disasm/ppc/disasm_arch.cpp index 074b398806..00d68f7adf 100644 --- a/src/add-ons/kernel/debugger/disasm/ppc/disasm_arch.cpp +++ b/src/add-ons/kernel/debugger/disasm/ppc/disasm_arch.cpp @@ -8,7 +8,8 @@ #include "disasm_arch.h" status_t -disasm_arch_dump_insns(addr_t where, int count) +disasm_arch_dump_insns(addr_t where, int count, addr_t baseAddress, + int backCount) { return ENOENT; } diff --git a/src/add-ons/kernel/debugger/disasm/x86/Jamfile b/src/add-ons/kernel/debugger/disasm/x86/Jamfile index f05d11decd..b14f5d322a 100644 --- a/src/add-ons/kernel/debugger/disasm/x86/Jamfile +++ b/src/add-ons/kernel/debugger/disasm/x86/Jamfile @@ -7,7 +7,7 @@ DEFINES += __UD_STANDALONE__ ; DEFINES += assert=disasm_arch_assert ; DEFINES += __assert_fail=disasm_arch_assert ; -local libUdis86Sources = +local libUdis86Sources = decode.c input.c itab.c diff --git a/src/add-ons/kernel/debugger/disasm/x86/disasm_arch.cpp b/src/add-ons/kernel/debugger/disasm/x86/disasm_arch.cpp index 348a0fca25..377cf3f9b9 100644 --- a/src/add-ons/kernel/debugger/disasm/x86/disasm_arch.cpp +++ b/src/add-ons/kernel/debugger/disasm/x86/disasm_arch.cpp @@ -9,6 +9,7 @@ #include "disasm_arch.h" #include "udis86.h" + static ud_t sUDState; static addr_t sCurrentReadAddress; static void (*sSyntax)(ud_t *) = UD_SYN_ATT; @@ -29,6 +30,18 @@ read_next_byte(struct ud*) } +static void +setup_disassembler(addr_t where) +{ + ud_set_input_hook(&sUDState, &read_next_byte); + sCurrentReadAddress = where; + ud_set_mode(&sUDState, 32); + ud_set_pc(&sUDState, (uint64_t)where); + ud_set_syntax(&sUDState, sSyntax); + ud_set_vendor(&sUDState, sVendor); +} + + extern "C" void disasm_arch_assert(const char *condition) { @@ -37,27 +50,54 @@ disasm_arch_assert(const char *condition) status_t -disasm_arch_dump_insns(addr_t where, int count) +disasm_arch_dump_insns(addr_t where, int count, addr_t baseAddress, + int backCount) { - //status_t err; - int i; + int skipCount = 0; - ud_set_input_hook(&sUDState, &read_next_byte); - sCurrentReadAddress = where; - ud_set_mode(&sUDState, 32); - ud_set_pc(&sUDState, (uint64_t)where); - ud_set_syntax(&sUDState, sSyntax); - ud_set_vendor(&sUDState, sVendor); - for (i = 0; i < count; i++) { + if (backCount > 0) { + // count the instructions from base address to start address + setup_disassembler(baseAddress); + addr_t address = baseAddress; + int baseCount = 0; + int len; + while (address < where && (len = ud_disassemble(&sUDState)) >= 1) { + address += len; + baseCount++; + } + + if (address == where) { + if (baseCount > backCount) + skipCount = baseCount - backCount; + count += baseCount; + } else + baseAddress = where; + } else + baseAddress = where; + + setup_disassembler(baseAddress); + + for (int i = 0; i < count; i++) { int ret; ret = ud_disassemble(&sUDState); if (ret < 1) break; + + if (skipCount > 0) { + skipCount--; + continue; + } + + addr_t address = (addr_t)ud_insn_off(&sUDState); + if (address == where) + kprintf("\x1b[34m"); + // TODO: dig operands and lookup symbols - kprintf("0x%08lx: %16.16s\t%s\n", - (uint32)(/*where +*/ ud_insn_off(&sUDState)), - ud_insn_hex(&sUDState), + kprintf("0x%08lx: %16.16s\t%s\n", address, ud_insn_hex(&sUDState), ud_insn_asm(&sUDState)); + + if (address == where) + kprintf("\x1b[m"); } return B_OK; }