diff --git a/CMakeLists.txt b/CMakeLists.txt index cd754fd90..05aa152aa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -395,6 +395,7 @@ find_feature(USE_SQLITE3 "sqlite3") set(DEBUGGER_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/debugger/debugger.c ${CMAKE_CURRENT_SOURCE_DIR}/src/debugger/parser.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/debugger/symbols.c ${CMAKE_CURRENT_SOURCE_DIR}/src/debugger/cli-debugger.c) set(FEATURE_SRC) @@ -603,7 +604,8 @@ if(M_CORE_GB) list(APPEND DEBUGGER_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/lr35902/debugger/cli-debugger.c ${CMAKE_CURRENT_SOURCE_DIR}/src/lr35902/debugger/debugger.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/gb/debugger/cli.c) + ${CMAKE_CURRENT_SOURCE_DIR}/src/gb/debugger/cli.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/gb/debugger/symbols.c) list(APPEND TEST_SRC ${LR35902_TEST_SRC} ${GB_TEST_SRC}) diff --git a/include/mgba/core/core.h b/include/mgba/core/core.h index f7238f861..99c57a037 100644 --- a/include/mgba/core/core.h +++ b/include/mgba/core/core.h @@ -39,12 +39,14 @@ enum mCoreChecksumType { struct mCoreConfig; struct mCoreSync; +struct mDebuggerSymbols; struct mStateExtdata; struct mVideoLogContext; struct mCore { void* cpu; void* board; struct mDebugger* debugger; + struct mDebuggerSymbols* symbolTable; #if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2 struct mDirectorySet dirs; @@ -135,6 +137,8 @@ struct mCore { struct CLIDebuggerSystem* (*cliDebuggerSystem)(struct mCore*); void (*attachDebugger)(struct mCore*, struct mDebugger*); void (*detachDebugger)(struct mCore*); + + void (*loadSymbols)(struct mCore*, struct VFile*); #endif struct mCheatDevice* (*cheatDevice)(struct mCore*); diff --git a/include/mgba/internal/debugger/debugger.h b/include/mgba/internal/debugger/debugger.h index fac608c73..a54c353c8 100644 --- a/include/mgba/internal/debugger/debugger.h +++ b/include/mgba/internal/debugger/debugger.h @@ -94,6 +94,7 @@ struct mDebuggerPlatform { void (*checkBreakpoints)(struct mDebuggerPlatform*); }; +struct mDebuggerSymbols; struct mDebugger { struct mCPUComponent d; struct mDebuggerPlatform* platform; diff --git a/include/mgba/internal/debugger/symbols.h b/include/mgba/internal/debugger/symbols.h new file mode 100644 index 000000000..e8456f8c1 --- /dev/null +++ b/include/mgba/internal/debugger/symbols.h @@ -0,0 +1,25 @@ +/* Copyright (c) 2013-2017 Jeffrey Pfau + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef DEBUGGER_SYMBOLS_H +#define DEBUGGER_SYMBOLS_H + +#include + +CXX_GUARD_START + +struct mDebuggerSymbols; + +struct mDebuggerSymbols* mDebuggerSymbolTableCreate(void); +void mDebuggerSymbolTableDestroy(struct mDebuggerSymbols*); + +bool mDebuggerSymbolLookup(const 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); + +CXX_GUARD_END + +#endif diff --git a/include/mgba/internal/gb/debugger/symbols.h b/include/mgba/internal/gb/debugger/symbols.h new file mode 100644 index 000000000..ae893f289 --- /dev/null +++ b/include/mgba/internal/gb/debugger/symbols.h @@ -0,0 +1,19 @@ +/* Copyright (c) 2013-2017 Jeffrey Pfau + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef GB_SYMBOLS_H +#define GB_SYMBOLS_H + +#include + +CXX_GUARD_START + +struct mDebuggerSymbols; +struct VFile; +void GBLoadSymbols(struct mDebuggerSymbols*, struct VFile* vf); + +CXX_GUARD_END + +#endif diff --git a/src/debugger/cli-debugger.c b/src/debugger/cli-debugger.c index c142ed60c..dcf1bd4fe 100644 --- a/src/debugger/cli-debugger.c +++ b/src/debugger/cli-debugger.c @@ -5,6 +5,8 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include +#include + #include #include #include @@ -497,7 +499,11 @@ static uint32_t _performOperation(enum Operation operation, uint32_t current, ui static void _lookupIdentifier(struct mDebugger* debugger, const char* name, struct CLIDebugVector* dv) { struct CLIDebugger* cliDebugger = (struct CLIDebugger*) debugger; if (cliDebugger->system) { - uint32_t value = cliDebugger->system->lookupPlatformIdentifier(cliDebugger->system, name, dv); + uint32_t value; + if (debugger->core->symbolTable && mDebuggerSymbolLookup(debugger->core->symbolTable, name, &dv->intValue, &dv->segmentValue)) { + return; + } + value = cliDebugger->system->lookupPlatformIdentifier(cliDebugger->system, name, dv); if (dv->type != CLIDV_ERROR_TYPE) { dv->intValue = value; return; diff --git a/src/debugger/debugger.c b/src/debugger/debugger.c index 49da5fde6..bf7b9d99c 100644 --- a/src/debugger/debugger.c +++ b/src/debugger/debugger.c @@ -62,6 +62,9 @@ void mDebuggerAttach(struct mDebugger* debugger, struct mCore* core) { debugger->d.init = mDebuggerInit; debugger->d.deinit = mDebuggerDeinit; debugger->core = core; + if (!debugger->core->symbolTable) { + debugger->core->loadSymbols(debugger->core, NULL); + } debugger->platform = core->debuggerPlatform(core); debugger->platform->p = debugger; core->attachDebugger(core, debugger); diff --git a/src/debugger/symbols.c b/src/debugger/symbols.c new file mode 100644 index 000000000..a9c874b54 --- /dev/null +++ b/src/debugger/symbols.c @@ -0,0 +1,49 @@ +/* Copyright (c) 2013-2017 Jeffrey Pfau + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include + +#include + +struct mDebuggerSymbol { + int32_t value; + int segment; +}; + +struct mDebuggerSymbols { + struct Table names; +}; + +struct mDebuggerSymbols* mDebuggerSymbolTableCreate(void) { + struct mDebuggerSymbols* st = malloc(sizeof(*st)); + HashTableInit(&st->names, 0, free); + return st; +} + +void mDebuggerSymbolTableDestroy(struct mDebuggerSymbols* st) { + HashTableDeinit(&st->names); + free(st); +} + +bool mDebuggerSymbolLookup(const struct mDebuggerSymbols* st, const char* name, int32_t* value, int* segment) { + struct mDebuggerSymbol* sym = HashTableLookup(&st->names, name); + if (!sym) { + return false; + } + *value = sym->value; + *segment = sym->segment; + return true; +} + +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); +} + +void mDebuggerSymbolRemove(struct mDebuggerSymbols* st, const char* name) { + HashTableRemove(&st->names, name); +} diff --git a/src/gb/core.c b/src/gb/core.c index 0bcc2aa9d..29e1b0c6f 100644 --- a/src/gb/core.c +++ b/src/gb/core.c @@ -6,7 +6,9 @@ #include #include +#include #include +#include #include #include #include @@ -90,8 +92,11 @@ static void _GBCoreDeinit(struct mCore* core) { GBDestroy(core->board); mappedMemoryFree(core->cpu, sizeof(struct LR35902Core)); mappedMemoryFree(core->board, sizeof(struct GB)); -#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2 +#if defined USE_DEBUGGERS && (!defined(MINIMAL_CORE) || MINIMAL_CORE < 2) mDirectorySetDeinit(&core->dirs); + if (core->symbolTable) { + mDebuggerSymbolTableDestroy(core->symbolTable); + } #endif struct GBCore* gbcore = (struct GBCore*) core; @@ -552,6 +557,19 @@ static void _GBCoreDetachDebugger(struct mCore* core) { cpu->components[CPU_COMPONENT_DEBUGGER] = NULL; core->debugger = NULL; } + +static void _GBCoreLoadSymbols(struct mCore* core, struct VFile* vf) { + core->symbolTable = mDebuggerSymbolTableCreate(); +#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2 + if (!vf) { + vf = mDirectorySetOpenSuffix(&core->dirs, core->dirs.base, ".sym", O_RDONLY); + } +#endif + if (!vf) { + return; + } + GBLoadSymbols(core->symbolTable, vf); +} #endif static struct mCheatDevice* _GBCoreCheatDevice(struct mCore* core) { @@ -671,6 +689,7 @@ struct mCore* GBCoreCreate(void) { core->cpu = NULL; core->board = NULL; core->debugger = NULL; + core->symbolTable = NULL; core->init = _GBCoreInit; core->deinit = _GBCoreDeinit; core->platform = _GBCorePlatform; @@ -728,6 +747,7 @@ struct mCore* GBCoreCreate(void) { core->cliDebuggerSystem = _GBCoreCliDebuggerSystem; core->attachDebugger = _GBCoreAttachDebugger; core->detachDebugger = _GBCoreDetachDebugger; + core->loadSymbols = _GBCoreLoadSymbols; #endif core->cheatDevice = _GBCoreCheatDevice; core->savedataClone = _GBCoreSavedataClone; diff --git a/src/gb/debugger/symbols.c b/src/gb/debugger/symbols.c new file mode 100644 index 000000000..4fc113433 --- /dev/null +++ b/src/gb/debugger/symbols.c @@ -0,0 +1,55 @@ +/* Copyright (c) 2013-2016 Jeffrey Pfau + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include + +#include +#include +#include + +void GBLoadSymbols(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'; + } + int segment = -1; + uint32_t address = 0; + + uint8_t byte; + const char* buf = line; + while (buf) { + buf = hex8(buf, &byte); + if (!buf) { + break; + } + address <<= 8; + address += byte; + + if (buf[0] == ':') { + segment = address; + address = 0; + ++buf; + } + if (isspace((int) buf[0])) { + break; + } + } + if (!buf) { + continue; + } + + while (isspace((int) buf[0])) { + ++buf; + } + + mDebuggerSymbolAdd(st, buf, address, segment); + } +} diff --git a/src/gba/core.c b/src/gba/core.c index 6888594ba..6f81e2570 100644 --- a/src/gba/core.c +++ b/src/gba/core.c @@ -72,6 +72,7 @@ static bool _GBACoreInit(struct mCore* core) { core->cpu = cpu; core->board = gba; core->debugger = NULL; + core->symbolTable = NULL; gbacore->overrides = NULL; gbacore->debuggerPlatform = NULL; gbacore->cheatDevice = NULL; @@ -555,6 +556,10 @@ static void _GBACoreDetachDebugger(struct mCore* core) { GBADetachDebugger(core->board); core->debugger = NULL; } + +static void _GBACoreLoadSymbols(struct mCore* core, struct VFile* vf) { + // TODO +} #endif static struct mCheatDevice* _GBACoreCheatDevice(struct mCore* core) { @@ -747,6 +752,7 @@ struct mCore* GBACoreCreate(void) { core->cliDebuggerSystem = _GBACoreCliDebuggerSystem; core->attachDebugger = _GBACoreAttachDebugger; core->detachDebugger = _GBACoreDetachDebugger; + core->loadSymbols = _GBACoreLoadSymbols; #endif core->cheatDevice = _GBACoreCheatDevice; core->savedataClone = _GBACoreSavedataClone;