* Added option "-b <count>" to "dis". It causes up to <count>
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
This commit is contained in:
parent
1b20a9a58e
commit
23fdebca54
@ -1,6 +1,6 @@
|
||||
SubDir HAIKU_TOP src add-ons kernel debugger disasm ;
|
||||
|
||||
UsePrivateHeaders kernel ;
|
||||
UsePrivateKernelHeaders ;
|
||||
|
||||
KernelAddon <kdebug>disasm :
|
||||
disasm.cpp
|
||||
|
@ -5,6 +5,8 @@
|
||||
|
||||
#include <arch/debug.h>
|
||||
#include <debug.h>
|
||||
#include <elf.h>
|
||||
#include <kernel.h>
|
||||
#include <signal.h>
|
||||
|
||||
#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",
|
||||
"[ <address> [ <count> ] ]\n"
|
||||
"[ -b <back count> ] [ <address> [ <count> ] ]\n"
|
||||
"Prints disassembly at address.\n"
|
||||
" <address> - Address at which to start disassembling\n"
|
||||
" (defaults to current PC).\n"
|
||||
" <count> - Number of instructions to disassemble.\n", 0);
|
||||
" <address> - Address at which to start disassembling\n"
|
||||
" (defaults to current PC).\n"
|
||||
" <count> - Number of instructions to disassemble\n"
|
||||
" starting at <address>.\n"
|
||||
" -b <back count> - Number of instruction to disassemble before\n"
|
||||
" <address>.\n", 0);
|
||||
} else if (op == B_MODULE_UNINIT) {
|
||||
remove_debugger_command("dis", disasm_command);
|
||||
return disasm_arch_fini();
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user