Debugger: Fix watchpoints
Jeffrey Pfau jeffrey@endrift.com
Tue, 12 Jan 2016 17:43:09 -0800
6 files changed,
33 insertions(+),
23 deletions(-)
M
CHANGES
→
CHANGES
@@ -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.c
→
src/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.c
→
src/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.h
→
src/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.c
→
src/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.c
→
src/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);