From 23fdebca54748818f55701fc086e652b7d375949 Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Sun, 24 Aug 2008 21:53:43 +0000 Subject: [PATCH] * Added option "-b " to "dis". It causes up to instructions to be printed before the given address. The feature is implemented by looking up the address of the previous symbol for the given address and disassembling forward (two passes). * The instuction at given address is printed highlighted (blue). git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@27191 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/add-ons/kernel/debugger/disasm/Jamfile | 2 +- src/add-ons/kernel/debugger/disasm/disasm.cpp | 62 ++++++++++++++--- .../kernel/debugger/disasm/disasm_arch.h | 3 +- .../debugger/disasm/m68k/disasm_arch.cpp | 3 +- .../debugger/disasm/ppc/disasm_arch.cpp | 3 +- .../kernel/debugger/disasm/x86/Jamfile | 2 +- .../debugger/disasm/x86/disasm_arch.cpp | 66 +++++++++++++++---- 7 files changed, 113 insertions(+), 28 deletions(-) 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; }