* 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 ;
|
SubDir HAIKU_TOP src add-ons kernel debugger disasm ;
|
||||||
|
|
||||||
UsePrivateHeaders kernel ;
|
UsePrivateKernelHeaders ;
|
||||||
|
|
||||||
KernelAddon <kdebug>disasm :
|
KernelAddon <kdebug>disasm :
|
||||||
disasm.cpp
|
disasm.cpp
|
||||||
|
@ -5,6 +5,8 @@
|
|||||||
|
|
||||||
#include <arch/debug.h>
|
#include <arch/debug.h>
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
#include <elf.h>
|
||||||
|
#include <kernel.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
|
||||||
#include "disasm_arch.h"
|
#include "disasm_arch.h"
|
||||||
@ -13,15 +15,29 @@
|
|||||||
int
|
int
|
||||||
disasm_command(int argc, char **argv)
|
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]);
|
print_debugger_command_usage(argv[0]);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// get PC
|
// get PC
|
||||||
uint64 pc;
|
uint64 pc;
|
||||||
if (argc >= 2) {
|
if (argi < argc) {
|
||||||
if (!evaluate_debug_expression(argv[1], &pc, false))
|
if (!evaluate_debug_expression(argv[argi++], &pc, false))
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
pc = (addr_t)arch_debug_get_interrupt_pc();
|
pc = (addr_t)arch_debug_get_interrupt_pc();
|
||||||
@ -33,14 +49,37 @@ disasm_command(int argc, char **argv)
|
|||||||
|
|
||||||
// get count
|
// get count
|
||||||
uint64 count = 10;
|
uint64 count = 10;
|
||||||
if (argc >= 3) {
|
if (argi < argc) {
|
||||||
if (!evaluate_debug_expression(argv[2], &count, false))
|
if (!evaluate_debug_expression(argv[argi++], &count, false))
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: autoincrement
|
// 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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,11 +95,14 @@ std_ops(int32 op, ...)
|
|||||||
return err;
|
return err;
|
||||||
return add_debugger_command_etc("dis", disasm_command,
|
return add_debugger_command_etc("dis", disasm_command,
|
||||||
"Print disassembly at address",
|
"Print disassembly at address",
|
||||||
"[ <address> [ <count> ] ]\n"
|
"[ -b <back count> ] [ <address> [ <count> ] ]\n"
|
||||||
"Prints disassembly at address.\n"
|
"Prints disassembly at address.\n"
|
||||||
" <address> - Address at which to start disassembling\n"
|
" <address> - Address at which to start disassembling\n"
|
||||||
" (defaults to current PC).\n"
|
" (defaults to current PC).\n"
|
||||||
" <count> - Number of instructions to disassemble.\n", 0);
|
" <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) {
|
} else if (op == B_MODULE_UNINIT) {
|
||||||
remove_debugger_command("dis", disasm_command);
|
remove_debugger_command("dis", disasm_command);
|
||||||
return disasm_arch_fini();
|
return disasm_arch_fini();
|
||||||
|
@ -12,7 +12,8 @@ extern "C" {
|
|||||||
extern status_t disasm_arch_init();
|
extern status_t disasm_arch_init();
|
||||||
extern status_t disasm_arch_fini();
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,8 @@
|
|||||||
#include "disasm_arch.h"
|
#include "disasm_arch.h"
|
||||||
|
|
||||||
status_t
|
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;
|
return ENOENT;
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,8 @@
|
|||||||
#include "disasm_arch.h"
|
#include "disasm_arch.h"
|
||||||
|
|
||||||
status_t
|
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;
|
return ENOENT;
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ DEFINES += __UD_STANDALONE__ ;
|
|||||||
DEFINES += assert=disasm_arch_assert ;
|
DEFINES += assert=disasm_arch_assert ;
|
||||||
DEFINES += __assert_fail=disasm_arch_assert ;
|
DEFINES += __assert_fail=disasm_arch_assert ;
|
||||||
|
|
||||||
local libUdis86Sources =
|
local libUdis86Sources =
|
||||||
decode.c
|
decode.c
|
||||||
input.c
|
input.c
|
||||||
itab.c
|
itab.c
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#include "disasm_arch.h"
|
#include "disasm_arch.h"
|
||||||
#include "udis86.h"
|
#include "udis86.h"
|
||||||
|
|
||||||
|
|
||||||
static ud_t sUDState;
|
static ud_t sUDState;
|
||||||
static addr_t sCurrentReadAddress;
|
static addr_t sCurrentReadAddress;
|
||||||
static void (*sSyntax)(ud_t *) = UD_SYN_ATT;
|
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
|
extern "C" void
|
||||||
disasm_arch_assert(const char *condition)
|
disasm_arch_assert(const char *condition)
|
||||||
{
|
{
|
||||||
@ -37,27 +50,54 @@ disasm_arch_assert(const char *condition)
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
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 skipCount = 0;
|
||||||
int i;
|
|
||||||
|
|
||||||
ud_set_input_hook(&sUDState, &read_next_byte);
|
if (backCount > 0) {
|
||||||
sCurrentReadAddress = where;
|
// count the instructions from base address to start address
|
||||||
ud_set_mode(&sUDState, 32);
|
setup_disassembler(baseAddress);
|
||||||
ud_set_pc(&sUDState, (uint64_t)where);
|
addr_t address = baseAddress;
|
||||||
ud_set_syntax(&sUDState, sSyntax);
|
int baseCount = 0;
|
||||||
ud_set_vendor(&sUDState, sVendor);
|
int len;
|
||||||
for (i = 0; i < count; i++) {
|
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;
|
int ret;
|
||||||
ret = ud_disassemble(&sUDState);
|
ret = ud_disassemble(&sUDState);
|
||||||
if (ret < 1)
|
if (ret < 1)
|
||||||
break;
|
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
|
// TODO: dig operands and lookup symbols
|
||||||
kprintf("0x%08lx: %16.16s\t%s\n",
|
kprintf("0x%08lx: %16.16s\t%s\n", address, ud_insn_hex(&sUDState),
|
||||||
(uint32)(/*where +*/ ud_insn_off(&sUDState)),
|
|
||||||
ud_insn_hex(&sUDState),
|
|
||||||
ud_insn_asm(&sUDState));
|
ud_insn_asm(&sUDState));
|
||||||
|
|
||||||
|
if (address == where)
|
||||||
|
kprintf("\x1b[m");
|
||||||
}
|
}
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user