mirror of https://github.com/mgba-emu/mgba.git
Debugger: reverse symbol lookup
This commit is contained in:
parent
26555959f2
commit
044710c3a8
|
@ -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);
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
#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 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) {
|
||||
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) {
|
||||
|
|
Loading…
Reference in New Issue