Debugger: reverse symbol lookup

This commit is contained in:
Adam Higerd 2020-07-31 20:00:59 -05:00 committed by Vicki Pfau
parent 26555959f2
commit 044710c3a8
3 changed files with 66 additions and 3 deletions

View File

@ -16,6 +16,7 @@ struct mDebuggerSymbols* mDebuggerSymbolTableCreate(void);
void mDebuggerSymbolTableDestroy(struct mDebuggerSymbols*); void mDebuggerSymbolTableDestroy(struct mDebuggerSymbols*);
bool mDebuggerSymbolLookup(const struct mDebuggerSymbols*, const char* name, int32_t* value, int* segment); 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 mDebuggerSymbolAdd(struct mDebuggerSymbols*, const char* name, int32_t value, int segment);
void mDebuggerSymbolRemove(struct mDebuggerSymbols*, const char* name); void mDebuggerSymbolRemove(struct mDebuggerSymbols*, const char* name);

View File

@ -72,6 +72,8 @@ static void _source(struct CLIDebugger*, struct CLIDebugVector*);
static void _backtrace(struct CLIDebugger*, struct CLIDebugVector*); static void _backtrace(struct CLIDebugger*, struct CLIDebugVector*);
static void _finish(struct CLIDebugger*, struct CLIDebugVector*); static void _finish(struct CLIDebugger*, struct CLIDebugVector*);
static void _setStackTraceMode(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[] = { static struct CLIDebuggerCommandSummary _debuggerCommands[] = {
{ "backtrace", _backtrace, "i", "Print backtrace of all or specified frames" }, { "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/1", _readByte, "I", "Read a byte from a specified offset" },
{ "r/2", _readHalfword, "I", "Read a halfword 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" }, { "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" }, { "status", _printStatus, "", "Print the current status" },
{ "symbol", _findSymbol, "I", "Find the symbol name for an address" },
{ "trace", _trace, "Is", "Trace a number of instructions" }, { "trace", _trace, "Is", "Trace a number of instructions" },
{ "w/1", _writeByte, "II", "Write a byte at a specified offset" }, { "w/1", _writeByte, "II", "Write a byte at a specified offset" },
{ "w/2", _writeHalfword, "II", "Write a halfword 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; frames = dv->intValue;
} }
ssize_t i; ssize_t i;
struct mDebuggerSymbols* symbolTable = debugger->d.core->symbolTable;
for (i = 0; i < frames; ++i) { for (i = 0; i < frames; ++i) {
char trace[1024]; char trace[1024];
size_t traceSize = sizeof(trace) - 2; size_t traceSize = sizeof(trace) - 2;
mStackTraceFormatFrame(stack, i, trace, &traceSize); mStackTraceFormatFrame(stack, symbolTable, i, trace, &traceSize);
debugger->backend->printf(debugger->backend, "%s", trace); 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); 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");
}
}

View File

@ -7,6 +7,7 @@
#include <mgba-util/string.h> #include <mgba-util/string.h>
#include <mgba-util/table.h> #include <mgba-util/table.h>
#include <mgba-util/hash.h>
#include <mgba-util/vfs.h> #include <mgba-util/vfs.h>
struct mDebuggerSymbol { struct mDebuggerSymbol {
@ -16,16 +17,19 @@ struct mDebuggerSymbol {
struct mDebuggerSymbols { struct mDebuggerSymbols {
struct Table names; struct Table names;
struct Table reverse;
}; };
struct mDebuggerSymbols* mDebuggerSymbolTableCreate(void) { struct mDebuggerSymbols* mDebuggerSymbolTableCreate(void) {
struct mDebuggerSymbols* st = malloc(sizeof(*st)); struct mDebuggerSymbols* st = malloc(sizeof(*st));
HashTableInit(&st->names, 0, free); HashTableInit(&st->names, 0, free);
HashTableInit(&st->reverse, 0, free);
return st; return st;
} }
void mDebuggerSymbolTableDestroy(struct mDebuggerSymbols* st) { void mDebuggerSymbolTableDestroy(struct mDebuggerSymbols* st) {
HashTableDeinit(&st->names); HashTableDeinit(&st->names);
HashTableDeinit(&st->reverse);
free(st); free(st);
} }
@ -39,15 +43,25 @@ bool mDebuggerSymbolLookup(const struct mDebuggerSymbols* st, const char* name,
return true; 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) { void mDebuggerSymbolAdd(struct mDebuggerSymbols* st, const char* name, int32_t value, int segment) {
struct mDebuggerSymbol* sym = malloc(sizeof(*sym)); struct mDebuggerSymbol* sym = malloc(sizeof(*sym));
sym->value = value; sym->value = value;
sym->segment = segment; sym->segment = segment;
HashTableInsert(&st->names, name, sym); HashTableInsert(&st->names, name, sym);
HashTableInsertBinary(&st->reverse, sym, sizeof(*sym), strdup(name));
} }
void mDebuggerSymbolRemove(struct mDebuggerSymbols* st, const char* 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) { void mDebuggerLoadARMIPSSymbols(struct mDebuggerSymbols* st, struct VFile* vf) {