all repos — mgba @ 16ba5bd05ff423ba9bc98cb7615140b01ff49bd2

mGBA Game Boy Advance Emulator

Debugger: Fix watchpoints
Jeffrey Pfau jeffrey@endrift.com
Tue, 12 Jan 2016 17:43:09 -0800
commit

16ba5bd05ff423ba9bc98cb7615140b01ff49bd2

parent

b6f1ddc4fee136f02ad261b324d34c7f194d7b3a

M CHANGESCHANGES

@@ -30,6 +30,7 @@ - Util: Fix excessive memory allocation when decoding a PNG

- GBA: Fix Iridion II savetype - Libretro: Fix aspect ratio - Qt: Fix some potential crashes with the gamepad mapping + - Debugger: Fix watchpoints in gdb Misc: - Qt: Window size command line options are now supported - Qt: Increase usability of key mapper
M src/debugger/cli-debugger.csrc/debugger/cli-debugger.c

@@ -536,7 +536,7 @@ printf("%s\n", ERROR_MISSING_ARGS);

return; } uint32_t address = dv->intValue; - ARMDebuggerSetWatchpoint(&debugger->d, address); + ARMDebuggerSetWatchpoint(&debugger->d, address, WATCHPOINT_RW); // TODO: ro/wo } static void _breakIntoDefault(int signal) {
M src/debugger/debugger.csrc/debugger/debugger.c

@@ -161,12 +161,13 @@ previous = next;

} } -void ARMDebuggerSetWatchpoint(struct ARMDebugger* debugger, uint32_t address) { +void ARMDebuggerSetWatchpoint(struct ARMDebugger* debugger, uint32_t address, enum WatchpointType type) { if (!debugger->watchpoints) { ARMDebuggerInstallMemoryShim(debugger); } struct DebugWatchpoint* watchpoint = malloc(sizeof(struct DebugWatchpoint)); watchpoint->address = address; + watchpoint->type = type; watchpoint->next = debugger->watchpoints; debugger->watchpoints = watchpoint; }
M src/debugger/debugger.hsrc/debugger/debugger.h

@@ -32,7 +32,7 @@

enum WatchpointType { WATCHPOINT_WRITE = 1, WATCHPOINT_READ = 2, - WATCHPOINT_RW = 3 + WATCHPOINT_RW = WATCHPOINT_WRITE | WATCHPOINT_READ }; struct DebugWatchpoint {

@@ -101,7 +101,7 @@ void ARMDebuggerEnter(struct ARMDebugger*, enum DebuggerEntryReason, struct DebuggerEntryInfo*);

void ARMDebuggerSetBreakpoint(struct ARMDebugger* debugger, uint32_t address); bool ARMDebuggerSetSoftwareBreakpoint(struct ARMDebugger* debugger, uint32_t address, enum ExecutionMode mode); void ARMDebuggerClearBreakpoint(struct ARMDebugger* debugger, uint32_t address); -void ARMDebuggerSetWatchpoint(struct ARMDebugger* debugger, uint32_t address); +void ARMDebuggerSetWatchpoint(struct ARMDebugger* debugger, uint32_t address, enum WatchpointType type); void ARMDebuggerClearWatchpoint(struct ARMDebugger* debugger, uint32_t address); #endif
M src/debugger/gdb-stub.csrc/debugger/gdb-stub.c

@@ -40,9 +40,9 @@ case DEBUGGER_ENTER_MANUAL:

snprintf(stub->outgoing, GDB_STUB_MAX_LINE - 4, "S%02x", SIGINT); break; case DEBUGGER_ENTER_BREAKPOINT: - snprintf(stub->outgoing, GDB_STUB_MAX_LINE - 4, "S%02x", SIGTRAP); + snprintf(stub->outgoing, GDB_STUB_MAX_LINE - 4, "S%02x", SIGTRAP); // TODO: Use hwbreak/swbreak if gdb supports it break; - case DEBUGGER_ENTER_WATCHPOINT: // TODO: Make watchpoints raise with address + case DEBUGGER_ENTER_WATCHPOINT: if (info) { const char* type = 0; switch (info->watchType) {

@@ -56,7 +56,7 @@ case WATCHPOINT_RW:

type = "awatch"; break; } - snprintf(stub->outgoing, GDB_STUB_MAX_LINE - 4, "T%02x%s:%08X", SIGTRAP, type, info->address); + snprintf(stub->outgoing, GDB_STUB_MAX_LINE - 4, "T%02x%s:%08x;", SIGTRAP, type, info->address); } else { snprintf(stub->outgoing, GDB_STUB_MAX_LINE - 4, "S%02x", SIGTRAP); }

@@ -317,9 +317,17 @@ strncpy(stub->outgoing, "OK", GDB_STUB_MAX_LINE - 4);

_sendMessage(stub); break; case '2': + ARMDebuggerSetWatchpoint(&stub->d, address, WATCHPOINT_WRITE); + strncpy(stub->outgoing, "OK", GDB_STUB_MAX_LINE - 4); + _sendMessage(stub); + break; case '3': + ARMDebuggerSetWatchpoint(&stub->d, address, WATCHPOINT_READ); + strncpy(stub->outgoing, "OK", GDB_STUB_MAX_LINE - 4); + _sendMessage(stub); + break; case '4': - ARMDebuggerSetWatchpoint(&stub->d, address); + ARMDebuggerSetWatchpoint(&stub->d, address, WATCHPOINT_RW); strncpy(stub->outgoing, "OK", GDB_STUB_MAX_LINE - 4); _sendMessage(stub); break;
M src/debugger/memory-debugger.csrc/debugger/memory-debugger.c

@@ -11,7 +11,7 @@ #include "util/math.h"

#include <string.h> -static bool _checkWatchpoints(struct ARMDebugger* debugger, uint32_t address, struct DebuggerEntryInfo* info, int width); +static bool _checkWatchpoints(struct ARMDebugger* debugger, uint32_t address, struct DebuggerEntryInfo* info, enum WatchpointType type, int width); #define FIND_DEBUGGER(DEBUGGER, CPU) \ { \

@@ -32,18 +32,18 @@ FIND_DEBUGGER(debugger, cpu); \

return debugger->originalMemory.NAME(cpu, __VA_ARGS__); \ } -#define CREATE_WATCHPOINT_SHIM(NAME, WIDTH, RETURN, TYPES, ...) \ +#define CREATE_WATCHPOINT_SHIM(NAME, WIDTH, RETURN, TYPES, ACCESS_TYPE, ...) \ static RETURN ARMDebuggerShim_ ## NAME TYPES { \ struct ARMDebugger* debugger; \ FIND_DEBUGGER(debugger, cpu); \ struct DebuggerEntryInfo info; \ - if (_checkWatchpoints(debugger, address, &info, WIDTH)) { \ + if (_checkWatchpoints(debugger, address, &info, ACCESS_TYPE, WIDTH)) { \ ARMDebuggerEnter(debugger, DEBUGGER_ENTER_WATCHPOINT, &info); \ } \ return debugger->originalMemory.NAME(cpu, __VA_ARGS__); \ } -#define CREATE_MULTIPLE_WATCHPOINT_SHIM(NAME) \ +#define CREATE_MULTIPLE_WATCHPOINT_SHIM(NAME, ACCESS_TYPE) \ static uint32_t ARMDebuggerShim_ ## NAME (struct ARMCore* cpu, uint32_t address, int mask, enum LSMDirection direction, int* cycleCounter) { \ struct ARMDebugger* debugger; \ FIND_DEBUGGER(debugger, cpu); \

@@ -60,28 +60,28 @@ } \

unsigned i; \ for (i = 0; i < popcount; ++i) { \ struct DebuggerEntryInfo info; \ - if (_checkWatchpoints(debugger, base + 4 * i, &info, 4)) { \ + if (_checkWatchpoints(debugger, base + 4 * i, &info, ACCESS_TYPE, 4)) { \ ARMDebuggerEnter(debugger, DEBUGGER_ENTER_WATCHPOINT, &info); \ } \ } \ return debugger->originalMemory.NAME(cpu, address, mask, direction, cycleCounter); \ } -CREATE_WATCHPOINT_SHIM(load32, 4, uint32_t, (struct ARMCore* cpu, uint32_t address, int* cycleCounter), address, cycleCounter) -CREATE_WATCHPOINT_SHIM(load16, 2, uint32_t, (struct ARMCore* cpu, uint32_t address, int* cycleCounter), address, cycleCounter) -CREATE_WATCHPOINT_SHIM(load8, 1, uint32_t, (struct ARMCore* cpu, uint32_t address, int* cycleCounter), address, cycleCounter) -CREATE_WATCHPOINT_SHIM(store32, 4, void, (struct ARMCore* cpu, uint32_t address, int32_t value, int* cycleCounter), address, value, cycleCounter) -CREATE_WATCHPOINT_SHIM(store16, 2, void, (struct ARMCore* cpu, uint32_t address, int16_t value, int* cycleCounter), address, value, cycleCounter) -CREATE_WATCHPOINT_SHIM(store8, 1, void, (struct ARMCore* cpu, uint32_t address, int8_t value, int* cycleCounter), address, value, cycleCounter) -CREATE_MULTIPLE_WATCHPOINT_SHIM(loadMultiple) -CREATE_MULTIPLE_WATCHPOINT_SHIM(storeMultiple) +CREATE_WATCHPOINT_SHIM(load32, 4, uint32_t, (struct ARMCore* cpu, uint32_t address, int* cycleCounter), WATCHPOINT_READ, address, cycleCounter) +CREATE_WATCHPOINT_SHIM(load16, 2, uint32_t, (struct ARMCore* cpu, uint32_t address, int* cycleCounter), WATCHPOINT_READ, address, cycleCounter) +CREATE_WATCHPOINT_SHIM(load8, 1, uint32_t, (struct ARMCore* cpu, uint32_t address, int* cycleCounter), WATCHPOINT_READ, address, cycleCounter) +CREATE_WATCHPOINT_SHIM(store32, 4, void, (struct ARMCore* cpu, uint32_t address, int32_t value, int* cycleCounter), WATCHPOINT_WRITE, address, value, cycleCounter) +CREATE_WATCHPOINT_SHIM(store16, 2, void, (struct ARMCore* cpu, uint32_t address, int16_t value, int* cycleCounter), WATCHPOINT_WRITE, address, value, cycleCounter) +CREATE_WATCHPOINT_SHIM(store8, 1, void, (struct ARMCore* cpu, uint32_t address, int8_t value, int* cycleCounter), WATCHPOINT_WRITE, address, value, cycleCounter) +CREATE_MULTIPLE_WATCHPOINT_SHIM(loadMultiple, WATCHPOINT_READ) +CREATE_MULTIPLE_WATCHPOINT_SHIM(storeMultiple, WATCHPOINT_WRITE) CREATE_SHIM(setActiveRegion, void, (struct ARMCore* cpu, uint32_t address), address) -static bool _checkWatchpoints(struct ARMDebugger* debugger, uint32_t address, struct DebuggerEntryInfo* info, int width) { +static bool _checkWatchpoints(struct ARMDebugger* debugger, uint32_t address, struct DebuggerEntryInfo* info, enum WatchpointType type, int width) { --width; struct DebugWatchpoint* watchpoints; for (watchpoints = debugger->watchpoints; watchpoints; watchpoints = watchpoints->next) { - if (!((watchpoints->address ^ address) & ~width)) { + if (!((watchpoints->address ^ address) & ~width) && watchpoints->type & type) { switch (width + 1) { case 1: info->oldValue = debugger->originalMemory.load8(debugger->cpu, address, 0);