diff --git a/CHANGES b/CHANGES index 3637665aa..20fd20be7 100644 --- a/CHANGES +++ b/CHANGES @@ -16,6 +16,7 @@ Features: - Optional automatic state saving/loading - Access to ur0 and uma0 partitions on the Vita - Partial support for MBC6, MMM01, TAMA and HuC-1 GB mappers + - GBA: ARMIPS/A22i-style and ELF symbol table support Bugfixes: - GB Audio: Make audio unsigned with bias (fixes mgba.io/i/749) - GB Serialize: Fix audio state loading diff --git a/include/mgba/internal/debugger/symbols.h b/include/mgba/internal/debugger/symbols.h index e8456f8c1..30801a446 100644 --- a/include/mgba/internal/debugger/symbols.h +++ b/include/mgba/internal/debugger/symbols.h @@ -20,6 +20,9 @@ bool mDebuggerSymbolLookup(const struct mDebuggerSymbols*, const char* name, int void mDebuggerSymbolAdd(struct mDebuggerSymbols*, const char* name, int32_t value, int segment); void mDebuggerSymbolRemove(struct mDebuggerSymbols*, const char* name); +struct VFile; +void mDebuggerLoadARMIPSSymbols(struct mDebuggerSymbols*, struct VFile* vf); + CXX_GUARD_END #endif diff --git a/src/debugger/symbols.c b/src/debugger/symbols.c index a9c874b54..26d392c3b 100644 --- a/src/debugger/symbols.c +++ b/src/debugger/symbols.c @@ -5,7 +5,9 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include +#include #include +#include struct mDebuggerSymbol { int32_t value; @@ -47,3 +49,40 @@ void mDebuggerSymbolAdd(struct mDebuggerSymbols* st, const char* name, int32_t v void mDebuggerSymbolRemove(struct mDebuggerSymbols* st, const char* name) { HashTableRemove(&st->names, name); } + +void mDebuggerLoadARMIPSSymbols(struct mDebuggerSymbols* st, struct VFile* vf) { + char line[512]; + + while (true) { + ssize_t bytesRead = vf->readline(vf, line, sizeof(line)); + if (bytesRead <= 0) { + break; + } + if (line[bytesRead - 1] == '\n') { + line[bytesRead - 1] = '\0'; + } + uint32_t address = 0; + const char* buf = line; + buf = hex32(buf, &address); + if (!buf) { + continue; + } + bytesRead -= 8; + + while (isspace((int) buf[0]) && bytesRead > 0) { + --bytesRead; + ++buf; + } + + if (!bytesRead) { + continue; + } + + if (buf[0] == '.') { + // Directives are not handled yet + continue; + } + + mDebuggerSymbolAdd(st, buf, address, -1); + } +} diff --git a/src/gb/debugger/symbols.c b/src/gb/debugger/symbols.c index 4fc113433..fdbdb9b54 100644 --- a/src/gb/debugger/symbols.c +++ b/src/gb/debugger/symbols.c @@ -25,13 +25,14 @@ void GBLoadSymbols(struct mDebuggerSymbols* st, struct VFile* vf) { uint8_t byte; const char* buf = line; - while (buf) { + while (buf && bytesRead >= 2) { buf = hex8(buf, &byte); if (!buf) { break; } address <<= 8; address += byte; + bytesRead -= 2; if (buf[0] == ':') { segment = address; @@ -42,14 +43,19 @@ void GBLoadSymbols(struct mDebuggerSymbols* st, struct VFile* vf) { break; } } - if (!buf) { + if (!buf || bytesRead < 1) { continue; } - while (isspace((int) buf[0])) { + while (isspace((int) buf[0]) && bytesRead > 0) { + --bytesRead; ++buf; } + if (!bytesRead) { + continue; + } + mDebuggerSymbolAdd(st, buf, address, segment); } } diff --git a/src/gba/core.c b/src/gba/core.c index 263399a12..40872f340 100644 --- a/src/gba/core.c +++ b/src/gba/core.c @@ -702,29 +702,38 @@ static void _GBACoreDetachDebugger(struct mCore* core) { } static void _GBACoreLoadSymbols(struct mCore* core, struct VFile* vf) { -#ifdef USE_ELF bool closeAfter = false; core->symbolTable = mDebuggerSymbolTableCreate(); #if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2 +#ifdef USE_ELF if (!vf) { closeAfter = true; vf = mDirectorySetOpenSuffix(&core->dirs, core->dirs.base, ".elf", O_RDONLY); } +#endif + if (!vf) { + closeAfter = true; + vf = mDirectorySetOpenSuffix(&core->dirs, core->dirs.base, ".sym", O_RDONLY); + } #endif if (!vf) { return; } +#ifdef USE_ELF struct ELF* elf = ELFOpen(vf); if (elf) { #ifdef USE_DEBUGGERS mCoreLoadELFSymbols(core->symbolTable, elf); #endif ELFClose(elf); + } else +#endif + { + mDebuggerLoadARMIPSSymbols(core->symbolTable, vf); } if (closeAfter) { vf->close(vf); } -#endif } static bool _GBACoreLookupIdentifier(struct mCore* core, const char* name, int32_t* value, int* segment) {