Add watchpoints

This commit is contained in:
Jeffrey Pfau 2013-09-26 00:26:11 -07:00
parent 99769695d7
commit a7182b8df9
4 changed files with 157 additions and 5 deletions

View File

@ -1,5 +1,7 @@
#include "debugger.h"
#include "memory-debugger.h"
#include "arm.h"
#include <signal.h>
@ -23,11 +25,6 @@ struct DebugVector {
};
};
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 @@ struct {
{ "rw", _readWord },
{ "status", _printStatus },
{ "x", _breakInto },
{ "w", _setWatchpoint },
{ "watch", _setWatchpoint },
{ 0, 0 }
};
@ -203,6 +203,21 @@ static void _setBreakpoint(struct ARMDebugger* debugger, struct DebugVector* dv)
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) {
struct DebugBreakpoint* breakpoint;
int instructionLength;
@ -532,6 +547,8 @@ void ARMDebuggerInit(struct ARMDebugger* debugger, struct ARMCore* cpu) {
debugger->state = DEBUGGER_PAUSED;
debugger->lastCommand = 0;
debugger->breakpoints = 0;
debugger->memoryShim.p = debugger;
debugger->memoryShim.watchpoints = 0;
_activeDebugger = debugger;
signal(SIGINT, _breakIntoDefault);
}

View File

@ -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*);

View File

@ -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;
}

View File

@ -0,0 +1,10 @@
#ifndef MEMORY_DEBUGGER_H
#define MEMORY_DEBUGGER_H
#include "arm.h"
struct ARMDebugger;
void ARMDebuggerInstallMemoryShim(struct ARMDebugger* debugger);
#endif