Add watchpoints
Jeffrey Pfau jeffrey@endrift.com
Thu, 26 Sep 2013 00:26:11 -0700
4 files changed,
157 insertions(+),
5 deletions(-)
M
src/debugger/debugger.c
→
src/debugger/debugger.c
@@ -1,5 +1,7 @@
#include "debugger.h" +#include "memory-debugger.h" + #include "arm.h" #include <signal.h>@@ -23,11 +25,6 @@ const char* charValue;
}; }; -struct DebugBreakpoint { - struct DebugBreakpoint* next; - int32_t address; -}; - static const char* ERROR_MISSING_ARGS = "Arguments missing"; static struct ARMDebugger* _activeDebugger;@@ -45,6 +42,7 @@ static void _readByte(struct ARMDebugger*, struct DebugVector*);
static void _readHalfword(struct ARMDebugger*, struct DebugVector*); static void _readWord(struct ARMDebugger*, struct DebugVector*); static void _setBreakpoint(struct ARMDebugger*, struct DebugVector*); +static void _setWatchpoint(struct ARMDebugger*, struct DebugVector*); static void _breakIntoDefault(int signal);@@ -70,6 +68,8 @@ { "rh", _readHalfword },
{ "rw", _readWord }, { "status", _printStatus }, { "x", _breakInto }, + { "w", _setWatchpoint }, + { "watch", _setWatchpoint }, { 0, 0 } };@@ -201,6 +201,21 @@ struct DebugBreakpoint* breakpoint = malloc(sizeof(struct DebugBreakpoint));
breakpoint->address = address; breakpoint->next = debugger->breakpoints; debugger->breakpoints = breakpoint; +} + +static void _setWatchpoint(struct ARMDebugger* debugger, struct DebugVector* dv) { + if (!dv || dv->type != INT_TYPE) { + printf("%s\n", ERROR_MISSING_ARGS); + return; + } + uint32_t address = dv->intValue; + if (debugger->cpu->memory != &debugger->memoryShim.d) { + ARMDebuggerInstallMemoryShim(debugger); + } + struct DebugBreakpoint* watchpoint = malloc(sizeof(struct DebugBreakpoint)); + watchpoint->address = address; + watchpoint->next = debugger->memoryShim.watchpoints; + debugger->memoryShim.watchpoints = watchpoint; } static void _checkBreakpoints(struct ARMDebugger* debugger) {@@ -532,6 +547,8 @@ debugger->cpu = cpu;
debugger->state = DEBUGGER_PAUSED; debugger->lastCommand = 0; debugger->breakpoints = 0; + debugger->memoryShim.p = debugger; + debugger->memoryShim.watchpoints = 0; _activeDebugger = debugger; signal(SIGINT, _breakIntoDefault); }
M
src/debugger/debugger.h
→
src/debugger/debugger.h
@@ -1,18 +1,34 @@
#ifndef DEBUGGER_H #define DEBUGGER_H +#include "arm.h" + enum DebuggerState { DEBUGGER_PAUSED, DEBUGGER_RUNNING, DEBUGGER_EXITING }; +struct DebugBreakpoint { + struct DebugBreakpoint* next; + int32_t address; +}; + +struct DebugMemoryShim { + struct ARMMemory d; + struct ARMMemory* original; + + struct ARMDebugger* p; + struct DebugBreakpoint* watchpoints; +}; + struct ARMDebugger { enum DebuggerState state; struct ARMCore* cpu; char* lastCommand; struct DebugBreakpoint* breakpoints; + struct DebugMemoryShim memoryShim; }; void ARMDebuggerInit(struct ARMDebugger*, struct ARMCore*);
A
src/debugger/memory-debugger.c
@@ -0,0 +1,109 @@
+#include "memory-debugger.h" + +#include "debugger.h" + +#include <string.h> + +static void ARMDebuggerShim_store32(struct ARMMemory*, uint32_t address, int32_t value, int* cycleCounter); +static void ARMDebuggerShim_store16(struct ARMMemory*, uint32_t address, int16_t value, int* cycleCounter); +static void ARMDebuggerShim_store8(struct ARMMemory*, uint32_t address, int8_t value, int* cycleCounter); +static void ARMDebuggerShim_setActiveRegion(struct ARMMemory* memory, uint32_t address); + +#define CREATE_SHIM(NAME, RETURN, TYPES, ARGS...) \ + static RETURN ARMDebuggerShim_ ## NAME TYPES { \ + struct DebugMemoryShim* debugMemory = (struct DebugMemoryShim*) memory; \ + return debugMemory->original->NAME(debugMemory->original, ARGS); \ + } + +CREATE_SHIM(load32, int32_t, (struct ARMMemory* memory, uint32_t address, int* cycleCounter), address, cycleCounter) +CREATE_SHIM(load16, int16_t, (struct ARMMemory* memory, uint32_t address, int* cycleCounter), address, cycleCounter) +CREATE_SHIM(loadU16, uint16_t, (struct ARMMemory* memory, uint32_t address, int* cycleCounter), address, cycleCounter) +CREATE_SHIM(load8, int8_t, (struct ARMMemory* memory, uint32_t address, int* cycleCounter), address, cycleCounter) +CREATE_SHIM(loadU8, uint8_t, (struct ARMMemory* memory, uint32_t address, int* cycleCounter), address, cycleCounter) +CREATE_SHIM(waitMultiple, int, (struct ARMMemory* memory, uint32_t startAddress, int count), startAddress, count) + +static int _checkWatchpoints(struct DebugBreakpoint* watchpoints, uint32_t address, int width) { + width -= 1; + for (; watchpoints; watchpoints = watchpoints->next) { + if (!((watchpoints->address ^ address) & ~width)) { + return 1; + } + } + return 0; +} + +void ARMDebuggerInstallMemoryShim(struct ARMDebugger* debugger) { + debugger->memoryShim.original = debugger->cpu->memory; + memcpy(&debugger->memoryShim.d, debugger->cpu->memory, sizeof(struct ARMMemory)); + debugger->memoryShim.d.store32 = ARMDebuggerShim_store32; + debugger->memoryShim.d.store16 = ARMDebuggerShim_store16; + debugger->memoryShim.d.store8 = ARMDebuggerShim_store8; + debugger->memoryShim.d.load32 = ARMDebuggerShim_load32; + debugger->memoryShim.d.load16 = ARMDebuggerShim_load16; + debugger->memoryShim.d.loadU16 = ARMDebuggerShim_loadU16; + debugger->memoryShim.d.load8 = ARMDebuggerShim_load8; + debugger->memoryShim.d.loadU8 = ARMDebuggerShim_loadU8; + debugger->memoryShim.d.setActiveRegion = ARMDebuggerShim_setActiveRegion; + debugger->memoryShim.d.waitMultiple = ARMDebuggerShim_waitMultiple; + debugger->cpu->memory = &debugger->memoryShim.d; +} + +int32_t ARMDebuggerLoad32(struct ARMMemory* memory, uint32_t address, int* cycleCounter) { + struct DebugMemoryShim* debugMemory = (struct DebugMemoryShim*) memory; + return debugMemory->original->load32(debugMemory->original, address, cycleCounter); +} + +int16_t ARMDebuggerLoad16(struct ARMMemory* memory, uint32_t address, int* cycleCounter) { + struct DebugMemoryShim* debugMemory = (struct DebugMemoryShim*) memory; + return debugMemory->original->load16(debugMemory->original, address, cycleCounter); +} + +uint16_t ARMDebuggerLoadU16(struct ARMMemory* memory, uint32_t address, int* cycleCounter) { + struct DebugMemoryShim* debugMemory = (struct DebugMemoryShim*) memory; + return debugMemory->original->loadU16(debugMemory->original, address, cycleCounter); +} + +int8_t ARMDebuggerLoad8(struct ARMMemory* memory, uint32_t address, int* cycleCounter) { + struct DebugMemoryShim* debugMemory = (struct DebugMemoryShim*) memory; + return debugMemory->original->load8(debugMemory->original, address, cycleCounter); +} + +uint8_t ARMDebuggerLoadU8(struct ARMMemory* memory, uint32_t address, int* cycleCounter) { + struct DebugMemoryShim* debugMemory = (struct DebugMemoryShim*) memory; + return debugMemory->original->loadU8(debugMemory->original, address, cycleCounter); +} + +void ARMDebuggerShim_store32(struct ARMMemory* memory, uint32_t address, int32_t value, int* cycleCounter) { + struct DebugMemoryShim* debugMemory = (struct DebugMemoryShim*) memory; + if (_checkWatchpoints(debugMemory->watchpoints, address, 4)) { + ARMDebuggerEnter(debugMemory->p); + } + debugMemory->original->store32(debugMemory->original, address, value, cycleCounter); +} + +void ARMDebuggerShim_store16(struct ARMMemory* memory, uint32_t address, int16_t value, int* cycleCounter) { + struct DebugMemoryShim* debugMemory = (struct DebugMemoryShim*) memory; + if (_checkWatchpoints(debugMemory->watchpoints, address, 2)) { + ARMDebuggerEnter(debugMemory->p); + } + debugMemory->original->store16(debugMemory->original, address, value, cycleCounter); +} + +void ARMDebuggerShim_store8(struct ARMMemory* memory, uint32_t address, int8_t value, int* cycleCounter) { + struct DebugMemoryShim* debugMemory = (struct DebugMemoryShim*) memory; + if (_checkWatchpoints(debugMemory->watchpoints, address, 1)) { + ARMDebuggerEnter(debugMemory->p); + } + debugMemory->original->store8(debugMemory->original, address, value, cycleCounter); +} + +void ARMDebuggerShim_setActiveRegion(struct ARMMemory* memory, uint32_t address) { + struct DebugMemoryShim* debugMemory = (struct DebugMemoryShim*) memory; + debugMemory->original->setActiveRegion(debugMemory->original, address); + memory->activeRegion = debugMemory->original->activeRegion; + memory->activeMask = debugMemory->original->activeMask; + memory->activePrefetchCycles32 = debugMemory->original->activePrefetchCycles32; + memory->activePrefetchCycles16 = debugMemory->original->activePrefetchCycles16; + memory->activeNonseqCycles32 = debugMemory->original->activeNonseqCycles32; + memory->activeNonseqCycles16 = debugMemory->original->activeNonseqCycles16; +}
A
src/debugger/memory-debugger.h
@@ -0,0 +1,10 @@
+#ifndef MEMORY_DEBUGGER_H +#define MEMORY_DEBUGGER_H + +#include "arm.h" + +struct ARMDebugger; + +void ARMDebuggerInstallMemoryShim(struct ARMDebugger* debugger); + +#endif