all repos — mgba @ 044710c3a809f48f95dfd1be160bc219461e3aea

mGBA Game Boy Advance Emulator

Debugger: reverse symbol lookup
Adam Higerd chighland@gmail.com
Fri, 31 Jul 2020 20:00:59 -0500
commit

044710c3a809f48f95dfd1be160bc219461e3aea

parent

26555959f25ba2d28e7be154e952a1779db8badb

3 files changed, 66 insertions(+), 3 deletions(-)

jump to
M include/mgba/internal/debugger/symbols.hinclude/mgba/internal/debugger/symbols.h

@@ -16,6 +16,7 @@ struct mDebuggerSymbols* mDebuggerSymbolTableCreate(void);

void mDebuggerSymbolTableDestroy(struct mDebuggerSymbols*); bool mDebuggerSymbolLookup(const struct mDebuggerSymbols*, const char* name, int32_t* value, int* segment); +const char* mDebuggerSymbolReverseLookup(const struct mDebuggerSymbols*, int32_t value, int segment); void mDebuggerSymbolAdd(struct mDebuggerSymbols*, const char* name, int32_t value, int segment); void mDebuggerSymbolRemove(struct mDebuggerSymbols*, const char* name);
M src/debugger/cli-debugger.csrc/debugger/cli-debugger.c

@@ -72,6 +72,8 @@ #endif

static void _backtrace(struct CLIDebugger*, struct CLIDebugVector*); static void _finish(struct CLIDebugger*, struct CLIDebugVector*); static void _setStackTraceMode(struct CLIDebugger*, struct CLIDebugVector*); +static void _setSymbol(struct CLIDebugger*, struct CLIDebugVector*); +static void _findSymbol(struct CLIDebugger*, struct CLIDebugVector*); static struct CLIDebuggerCommandSummary _debuggerCommands[] = { { "backtrace", _backtrace, "i", "Print backtrace of all or specified frames" },

@@ -92,8 +94,10 @@ { "reset", _reset, "", "Reset the emulation" },

{ "r/1", _readByte, "I", "Read a byte from a specified offset" }, { "r/2", _readHalfword, "I", "Read a halfword from a specified offset" }, { "r/4", _readWord, "I", "Read a word from a specified offset" }, - { "stack", _setStackTraceMode, "S", "Changes the stack tracing mode" }, + { "set", _setSymbol, "SI", "Assign a symbol to an address" }, + { "stack", _setStackTraceMode, "S", "Change the stack tracing mode" }, { "status", _printStatus, "", "Print the current status" }, + { "symbol", _findSymbol, "I", "Find the symbol name for an address" }, { "trace", _trace, "Is", "Trace a number of instructions" }, { "w/1", _writeByte, "II", "Write a byte at a specified offset" }, { "w/2", _writeHalfword, "II", "Write a halfword at a specified offset" },

@@ -1178,10 +1182,11 @@ if (dv && dv->type == CLIDV_INT_TYPE && dv->intValue < frames) {

frames = dv->intValue; } ssize_t i; + struct mDebuggerSymbols* symbolTable = debugger->d.core->symbolTable; for (i = 0; i < frames; ++i) { char trace[1024]; size_t traceSize = sizeof(trace) - 2; - mStackTraceFormatFrame(stack, i, trace, &traceSize); + mStackTraceFormatFrame(stack, symbolTable, i, trace, &traceSize); debugger->backend->printf(debugger->backend, "%s", trace); } }

@@ -1232,3 +1237,46 @@ } else {

debugger->backend->printf(debugger->backend, "%s\n", ERROR_INVALID_ARGS); } } + +static void _setSymbol(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { + struct mDebuggerSymbols* symbolTable = debugger->d.core->symbolTable; + if (!symbolTable) { + debugger->backend->printf(debugger->backend, "No symbol table available.\n"); + return; + } + if (!dv || !dv->next) { + debugger->backend->printf(debugger->backend, "%s\n", ERROR_MISSING_ARGS); + return; + } + if (dv->type != CLIDV_CHAR_TYPE || dv->next->type != CLIDV_INT_TYPE) { + debugger->backend->printf(debugger->backend, "%s\n", ERROR_INVALID_ARGS); + return; + } + mDebuggerSymbolAdd(symbolTable, dv->charValue, dv->next->intValue, dv->next->segmentValue); +} + +static void _findSymbol(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { + struct mDebuggerSymbols* symbolTable = debugger->d.core->symbolTable; + if (!symbolTable) { + debugger->backend->printf(debugger->backend, "No symbol table available.\n"); + return; + } + if (!dv) { + debugger->backend->printf(debugger->backend, "%s\n", ERROR_MISSING_ARGS); + return; + } + if (dv->type != CLIDV_INT_TYPE) { + debugger->backend->printf(debugger->backend, "%s\n", ERROR_INVALID_ARGS); + return; + } + const char* name = mDebuggerSymbolReverseLookup(symbolTable, dv->intValue, dv->segmentValue); + if (name) { + if (dv->segmentValue >= 0) { + debugger->backend->printf(debugger->backend, " 0x%02X:%08X = %s\n", dv->segmentValue, dv->intValue, name); + } else { + debugger->backend->printf(debugger->backend, " 0x%08X = %s\n", dv->intValue, name); + } + } else { + debugger->backend->printf(debugger->backend, "Not found.\n"); + } +}
M src/debugger/symbols.csrc/debugger/symbols.c

@@ -7,6 +7,7 @@ #include <mgba/internal/debugger/symbols.h>

#include <mgba-util/string.h> #include <mgba-util/table.h> +#include <mgba-util/hash.h> #include <mgba-util/vfs.h> struct mDebuggerSymbol {

@@ -16,16 +17,19 @@ };

struct mDebuggerSymbols { struct Table names; + struct Table reverse; }; struct mDebuggerSymbols* mDebuggerSymbolTableCreate(void) { struct mDebuggerSymbols* st = malloc(sizeof(*st)); HashTableInit(&st->names, 0, free); + HashTableInit(&st->reverse, 0, free); return st; } void mDebuggerSymbolTableDestroy(struct mDebuggerSymbols* st) { HashTableDeinit(&st->names); + HashTableDeinit(&st->reverse); free(st); }

@@ -39,15 +43,25 @@ *segment = sym->segment;

return true; } +const char* mDebuggerSymbolReverseLookup(const struct mDebuggerSymbols* st, int32_t value, int segment) { + struct mDebuggerSymbol sym = { value, segment }; + return HashTableLookupBinary(&st->reverse, &sym, sizeof(sym)); +} + void mDebuggerSymbolAdd(struct mDebuggerSymbols* st, const char* name, int32_t value, int segment) { struct mDebuggerSymbol* sym = malloc(sizeof(*sym)); sym->value = value; sym->segment = segment; HashTableInsert(&st->names, name, sym); + HashTableInsertBinary(&st->reverse, sym, sizeof(*sym), strdup(name)); } void mDebuggerSymbolRemove(struct mDebuggerSymbols* st, const char* name) { - HashTableRemove(&st->names, name); + struct mDebuggerSymbol* sym = HashTableLookup(&st->names, name); + if (sym) { + HashTableRemoveBinary(&st->reverse, sym, sizeof(*sym)); + HashTableRemove(&st->names, name); + } } void mDebuggerLoadARMIPSSymbols(struct mDebuggerSymbols* st, struct VFile* vf) {