From 7012f9c6662e564d9a64e3d0dd86aa1028f8853d Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Wed, 15 Jan 2025 23:46:20 -0800 Subject: [PATCH] Debugger: Allow memory access logs to operate read-only --- include/mgba/debugger/debugger.h | 1 + .../mgba/internal/debugger/access-logger.h | 4 ++ src/debugger/access-logger.c | 48 +++++++++++++++---- src/platform/qt/MemoryAccessLogController.cpp | 1 + src/platform/test/fuzz-main.c | 1 + 5 files changed, 46 insertions(+), 9 deletions(-) diff --git a/include/mgba/debugger/debugger.h b/include/mgba/debugger/debugger.h index 7cf89882b..230a95564 100644 --- a/include/mgba/debugger/debugger.h +++ b/include/mgba/debugger/debugger.h @@ -257,6 +257,7 @@ bool mDebuggerIsShutdown(const struct mDebugger*); struct mDebuggerModule* mDebuggerCreateModule(enum mDebuggerType type, struct mCore*); void mDebuggerModuleSetNeedsCallback(struct mDebuggerModule*); +void mDebuggerModuleClearNeedsCallback(struct mDebuggerModule*); bool mDebuggerLookupIdentifier(struct mDebugger* debugger, const char* name, int32_t* value, int* segment); diff --git a/include/mgba/internal/debugger/access-logger.h b/include/mgba/internal/debugger/access-logger.h index b839bd5b1..180168f3a 100644 --- a/include/mgba/internal/debugger/access-logger.h +++ b/include/mgba/internal/debugger/access-logger.h @@ -23,6 +23,7 @@ struct mDebuggerAccessLogRegion { uint32_t segmentStart; mDebuggerAccessLogFlags* block; mDebuggerAccessLogFlagsEx* blockEx; + ssize_t watchpoint; }; DECLARE_VECTOR(mDebuggerAccessLogRegionList, struct mDebuggerAccessLogRegion); @@ -41,6 +42,9 @@ void mDebuggerAccessLoggerDeinit(struct mDebuggerAccessLogger*); bool mDebuggerAccessLoggerOpen(struct mDebuggerAccessLogger*, struct VFile*, int mode); bool mDebuggerAccessLoggerClose(struct mDebuggerAccessLogger*); +void mDebuggerAccessLoggerStart(struct mDebuggerAccessLogger*); +void mDebuggerAccessLoggerStop(struct mDebuggerAccessLogger*); + int mDebuggerAccessLoggerWatchMemoryBlockId(struct mDebuggerAccessLogger*, size_t id, mDebuggerAccessLogRegionFlags); int mDebuggerAccessLoggerWatchMemoryBlockName(struct mDebuggerAccessLogger*, const char* internalName, mDebuggerAccessLogRegionFlags); diff --git a/src/debugger/access-logger.c b/src/debugger/access-logger.c index fbe681432..7133565e9 100644 --- a/src/debugger/access-logger.c +++ b/src/debugger/access-logger.c @@ -71,7 +71,6 @@ static void _mDebuggerAccessLoggerEntered(struct mDebuggerModule* debugger, enum mDebuggerAccessLogFlags flags = 0; mDebuggerAccessLogFlagsEx flagsEx = 0; - int i; switch (reason) { case DEBUGGER_ENTER_WATCHPOINT: switch (info->type.wp.accessSource) { @@ -257,13 +256,18 @@ static bool _setupRegion(struct mDebuggerAccessLogger* logger, struct mDebuggerA return false; } - struct mWatchpoint wp = { - .segment = -1, - .minAddress = region->start, - .maxAddress = region->end, - .type = WATCHPOINT_RW, - }; - logger->d.p->platform->setWatchpoint(logger->d.p->platform, &logger->d, &wp); + if (region->watchpoint < 0) { + struct mWatchpoint wp = { + .segment = -1, + .minAddress = region->start, + .maxAddress = region->end, + .type = WATCHPOINT_RW, + }; + region->watchpoint = logger->d.p->platform->setWatchpoint(logger->d.p->platform, &logger->d, &wp); + } + if (region->watchpoint < 0) { + return false; + } mDebuggerModuleSetNeedsCallback(&logger->d); return true; } @@ -307,7 +311,7 @@ static bool mDebuggerAccessLoggerLoad(struct mDebuggerAccessLogger* logger) { LOAD_32LE(region->end, 0, &info->end); LOAD_32LE(region->size, 0, &info->size); LOAD_32LE(region->segmentStart, 0, &info->segmentStart); - if (!_setupRegion(logger, region, info)) { + if (!_mapRegion(logger, region, info)) { mDebuggerAccessLogRegionListClear(&logger->regions); return false; } @@ -352,6 +356,30 @@ bool mDebuggerAccessLoggerOpen(struct mDebuggerAccessLogger* logger, struct VFil return loaded; } +void mDebuggerAccessLoggerStart(struct mDebuggerAccessLogger* logger) { + size_t i; + for (i = 0; i < logger->mapped->header.nRegions; ++i) { + struct mDebuggerAccessLogRegionInfo* info = &logger->mapped->regionInfo[i]; + struct mDebuggerAccessLogRegion* region = mDebuggerAccessLogRegionListGetPointer(&logger->regions, i); + if (!_setupRegion(logger, region, info)) { + return; + } + } +} + +void mDebuggerAccessLoggerStop(struct mDebuggerAccessLogger* logger) { + size_t i; + for (i = 0; i < logger->mapped->header.nRegions; ++i) { + struct mDebuggerAccessLogRegion* region = mDebuggerAccessLogRegionListGetPointer(&logger->regions, i); + if (region->watchpoint < 0) { + continue; + } + logger->d.p->platform->clearBreakpoint(logger->d.p->platform, region->watchpoint); + region->watchpoint = -1; + } + logger->d.needsCallback = false; +} + static int _mDebuggerAccessLoggerWatchMemoryBlock(struct mDebuggerAccessLogger* logger, const struct mCoreMemoryBlock* block, mDebuggerAccessLogRegionFlags flags) { if (mDebuggerAccessLogRegionListSize(&logger->regions) >= logger->mapped->header.regionCapacity) { return -1; @@ -423,6 +451,7 @@ static int _mDebuggerAccessLoggerWatchMemoryBlock(struct mDebuggerAccessLogger* region->size = block->size; region->segmentStart = block->segmentStart; region->block = (mDebuggerAccessLogFlags*) ((uintptr_t) logger->backing + fileEnd); + region->watchpoint = -1; struct mDebuggerAccessLogRegionInfo* info = &logger->mapped->regionInfo[id]; STORE_32LE(region->start, 0, &info->start); @@ -451,6 +480,7 @@ bool mDebuggerAccessLoggerClose(struct mDebuggerAccessLogger* logger) { if (!logger->backing) { return true; } + mDebuggerAccessLoggerStop(logger); mDebuggerAccessLogRegionListClear(&logger->regions); logger->backing->unmap(logger->backing, logger->mapped, logger->backing->size(logger->backing)); logger->mapped = NULL; diff --git a/src/platform/qt/MemoryAccessLogController.cpp b/src/platform/qt/MemoryAccessLogController.cpp index 9691dcadf..c2f2216d5 100644 --- a/src/platform/qt/MemoryAccessLogController.cpp +++ b/src/platform/qt/MemoryAccessLogController.cpp @@ -93,6 +93,7 @@ void MemoryAccessLogController::start(bool loadExisting, bool logExtra) { LOG(QT, ERROR) << tr("Failed to open memory log file"); return; } + mDebuggerAccessLoggerStart(&m_logger); m_active = true; emit loggingChanged(true); diff --git a/src/platform/test/fuzz-main.c b/src/platform/test/fuzz-main.c index 143edaba1..5fdfff8a3 100644 --- a/src/platform/test/fuzz-main.c +++ b/src/platform/test/fuzz-main.c @@ -130,6 +130,7 @@ int main(int argc, char** argv) { mDebuggerAccessLoggerInit(&accessLog); mDebuggerAttachModule(&debugger, &accessLog.d); mDebuggerAccessLoggerOpen(&accessLog, vf, O_RDWR); + mDebuggerAccessLoggerStart(&accessLog); hasDebugger = true; }