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*);
|
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);
|
||||||
|
|
|
@ -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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
Loading…
Reference in New Issue