From 044710c3a809f48f95dfd1be160bc219461e3aea Mon Sep 17 00:00:00 2001 From: Adam Higerd Date: Fri, 31 Jul 2020 20:00:59 -0500 Subject: [PATCH] Debugger: reverse symbol lookup --- include/mgba/internal/debugger/symbols.h | 1 + src/debugger/cli-debugger.c | 52 +++++++++++++++++++++++- src/debugger/symbols.c | 16 +++++++- 3 files changed, 66 insertions(+), 3 deletions(-) diff --git a/include/mgba/internal/debugger/symbols.h b/include/mgba/internal/debugger/symbols.h index 30801a446..12af32564 100644 --- a/include/mgba/internal/debugger/symbols.h +++ b/include/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); diff --git a/src/debugger/cli-debugger.c b/src/debugger/cli-debugger.c index 178457c40..dae2bc527 100644 --- a/src/debugger/cli-debugger.c +++ b/src/debugger/cli-debugger.c @@ -72,6 +72,8 @@ static void _source(struct CLIDebugger*, struct CLIDebugVector*); 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 @@ static struct CLIDebuggerCommandSummary _debuggerCommands[] = { { "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 @@ static void _backtrace(struct CLIDebugger* debugger, struct CLIDebugVector* dv) 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 @@ static void _setStackTraceMode(struct CLIDebugger* debugger, struct CLIDebugVect 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"); + } +} diff --git a/src/debugger/symbols.c b/src/debugger/symbols.c index 26d392c3b..1cfa246a3 100644 --- a/src/debugger/symbols.c +++ b/src/debugger/symbols.c @@ -7,6 +7,7 @@ #include #include +#include #include struct mDebuggerSymbol { @@ -16,16 +17,19 @@ struct mDebuggerSymbol { 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 @@ bool mDebuggerSymbolLookup(const struct mDebuggerSymbols* st, const char* name, 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) {