mirror of https://github.com/mgba-emu/mgba.git
Restructure watchpoints
This commit is contained in:
parent
0f68dbc832
commit
7a4ca414e5
|
@ -36,7 +36,7 @@ if(BUILD_BBB OR BUILD_RASPI)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(DEBUGGER_SRC "${CMAKE_SOURCE_DIR}/src/debugger/debugger.c")
|
set(DEBUGGER_SRC "${CMAKE_SOURCE_DIR}/src/debugger/debugger.c;${CMAKE_SOURCE_DIR}/src/debugger/memory-debugger.c")
|
||||||
|
|
||||||
if(USE_CLI_DEBUGGER)
|
if(USE_CLI_DEBUGGER)
|
||||||
set(DEBUGGER_SRC "${DEBUGGER_SRC};${CMAKE_SOURCE_DIR}/src/debugger/cli-debugger.c")
|
set(DEBUGGER_SRC "${DEBUGGER_SRC};${CMAKE_SOURCE_DIR}/src/debugger/cli-debugger.c")
|
||||||
|
|
|
@ -111,7 +111,7 @@ struct ARMInterruptHandler {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ARMComponent {
|
struct ARMComponent {
|
||||||
long id;
|
uint32_t id;
|
||||||
void (*init)(struct ARMCore* cpu, struct ARMComponent* component);
|
void (*init)(struct ARMCore* cpu, struct ARMComponent* component);
|
||||||
void (*deinit)(struct ARMComponent* component);
|
void (*deinit)(struct ARMComponent* component);
|
||||||
};
|
};
|
||||||
|
|
|
@ -221,8 +221,8 @@ static void _setWatchpoint(struct CLIDebugger* debugger, struct DebugVector* dv)
|
||||||
printf("%s\n", ERROR_MISSING_ARGS);
|
printf("%s\n", ERROR_MISSING_ARGS);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// TODO: Redo watchpoints
|
uint32_t address = dv->intValue;
|
||||||
(void) (debugger);
|
ARMDebuggerSetWatchpoint(&debugger->d, address);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _breakIntoDefault(int signal) {
|
static void _breakIntoDefault(int signal) {
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
|
|
||||||
#include "memory-debugger.h"
|
#include "memory-debugger.h"
|
||||||
|
|
||||||
|
const uint32_t ARM_DEBUGGER_ID = 0xDEADBEEF;
|
||||||
|
|
||||||
static void _checkBreakpoints(struct ARMDebugger* debugger) {
|
static void _checkBreakpoints(struct ARMDebugger* debugger) {
|
||||||
struct DebugBreakpoint* breakpoint;
|
struct DebugBreakpoint* breakpoint;
|
||||||
int instructionLength;
|
int instructionLength;
|
||||||
|
@ -25,6 +27,7 @@ static void ARMDebuggerInit(struct ARMCore*, struct ARMComponent*);
|
||||||
static void ARMDebuggerDeinit(struct ARMComponent*);
|
static void ARMDebuggerDeinit(struct ARMComponent*);
|
||||||
|
|
||||||
void ARMDebuggerCreate(struct ARMDebugger* debugger) {
|
void ARMDebuggerCreate(struct ARMDebugger* debugger) {
|
||||||
|
debugger->d.id = ARM_DEBUGGER_ID;
|
||||||
debugger->d.init = ARMDebuggerInit;
|
debugger->d.init = ARMDebuggerInit;
|
||||||
debugger->d.deinit = ARMDebuggerDeinit;
|
debugger->d.deinit = ARMDebuggerDeinit;
|
||||||
}
|
}
|
||||||
|
@ -34,9 +37,8 @@ void ARMDebuggerInit(struct ARMCore* cpu, struct ARMComponent* component) {
|
||||||
debugger->cpu = cpu;
|
debugger->cpu = cpu;
|
||||||
debugger->state = DEBUGGER_RUNNING;
|
debugger->state = DEBUGGER_RUNNING;
|
||||||
debugger->breakpoints = 0;
|
debugger->breakpoints = 0;
|
||||||
debugger->memoryShim.original = cpu->memory;
|
debugger->originalMemory = cpu->memory;
|
||||||
debugger->memoryShim.p = debugger;
|
debugger->watchpoints = 0;
|
||||||
debugger->memoryShim.watchpoints = 0;
|
|
||||||
if (debugger->init) {
|
if (debugger->init) {
|
||||||
debugger->init(debugger);
|
debugger->init(debugger);
|
||||||
}
|
}
|
||||||
|
@ -105,9 +107,11 @@ void ARMDebuggerClearBreakpoint(struct ARMDebugger* debugger, uint32_t address)
|
||||||
}
|
}
|
||||||
|
|
||||||
void ARMDebuggerSetWatchpoint(struct ARMDebugger* debugger, uint32_t address) {
|
void ARMDebuggerSetWatchpoint(struct ARMDebugger* debugger, uint32_t address) {
|
||||||
// FIXME: Make watchpoints work again
|
if (!debugger->watchpoints) {
|
||||||
|
ARMDebuggerInstallMemoryShim(debugger);
|
||||||
|
}
|
||||||
struct DebugBreakpoint* watchpoint = malloc(sizeof(struct DebugBreakpoint));
|
struct DebugBreakpoint* watchpoint = malloc(sizeof(struct DebugBreakpoint));
|
||||||
watchpoint->address = address;
|
watchpoint->address = address;
|
||||||
watchpoint->next = debugger->memoryShim.watchpoints;
|
watchpoint->next = debugger->watchpoints;
|
||||||
debugger->memoryShim.watchpoints = watchpoint;
|
debugger->watchpoints = watchpoint;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
|
|
||||||
#include "arm.h"
|
#include "arm.h"
|
||||||
|
|
||||||
|
const uint32_t ARM_DEBUGGER_ID;
|
||||||
|
|
||||||
enum DebuggerState {
|
enum DebuggerState {
|
||||||
DEBUGGER_PAUSED,
|
DEBUGGER_PAUSED,
|
||||||
DEBUGGER_RUNNING,
|
DEBUGGER_RUNNING,
|
||||||
|
@ -17,13 +19,6 @@ struct DebugBreakpoint {
|
||||||
uint32_t address;
|
uint32_t address;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DebugMemoryShim {
|
|
||||||
struct ARMMemory original;
|
|
||||||
|
|
||||||
struct ARMDebugger* p;
|
|
||||||
struct DebugBreakpoint* watchpoints;
|
|
||||||
};
|
|
||||||
|
|
||||||
enum DebuggerEntryReason {
|
enum DebuggerEntryReason {
|
||||||
DEBUGGER_ENTER_MANUAL,
|
DEBUGGER_ENTER_MANUAL,
|
||||||
DEBUGGER_ENTER_ATTACHED,
|
DEBUGGER_ENTER_ATTACHED,
|
||||||
|
@ -45,7 +40,8 @@ struct ARMDebugger {
|
||||||
struct ARMCore* cpu;
|
struct ARMCore* cpu;
|
||||||
|
|
||||||
struct DebugBreakpoint* breakpoints;
|
struct DebugBreakpoint* breakpoints;
|
||||||
struct DebugMemoryShim memoryShim;
|
struct DebugBreakpoint* watchpoints;
|
||||||
|
struct ARMMemory originalMemory;
|
||||||
|
|
||||||
void (*init)(struct ARMDebugger*);
|
void (*init)(struct ARMDebugger*);
|
||||||
void (*deinit)(struct ARMDebugger*);
|
void (*deinit)(struct ARMDebugger*);
|
||||||
|
|
|
@ -4,23 +4,36 @@
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
static void ARMDebuggerShim_store32(struct ARMMemory*, uint32_t address, int32_t value, int* cycleCounter);
|
static void ARMDebuggerShim_store32(struct ARMCore*, 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_store16(struct ARMCore*, 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_store8(struct ARMCore*, uint32_t address, int8_t value, int* cycleCounter);
|
||||||
static void ARMDebuggerShim_setActiveRegion(struct ARMMemory* memory, uint32_t address);
|
static void ARMDebuggerShim_setActiveRegion(struct ARMCore* cpu, uint32_t address);
|
||||||
|
|
||||||
|
#define FIND_DEBUGGER(DEBUGGER, CPU) \
|
||||||
|
{ \
|
||||||
|
DEBUGGER = 0; \
|
||||||
|
int i; \
|
||||||
|
for (i = 0; i < CPU->numComponents; ++i) { \
|
||||||
|
if (CPU->components[i]->id == ARM_DEBUGGER_ID) { \
|
||||||
|
DEBUGGER = (struct ARMDebugger*) cpu->components[i]; \
|
||||||
|
break; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
#define CREATE_SHIM(NAME, RETURN, TYPES, ARGS...) \
|
#define CREATE_SHIM(NAME, RETURN, TYPES, ARGS...) \
|
||||||
static RETURN ARMDebuggerShim_ ## NAME TYPES { \
|
static RETURN ARMDebuggerShim_ ## NAME TYPES { \
|
||||||
struct DebugMemoryShim* debugMemory = (struct DebugMemoryShim*) memory; \
|
struct ARMDebugger* debugger; \
|
||||||
return debugMemory->original->NAME(debugMemory->original, ARGS); \
|
FIND_DEBUGGER(debugger, cpu); \
|
||||||
|
return debugger->originalMemory.NAME(cpu, ARGS); \
|
||||||
}
|
}
|
||||||
|
|
||||||
CREATE_SHIM(load32, int32_t, (struct ARMMemory* memory, uint32_t address, int* cycleCounter), address, cycleCounter)
|
CREATE_SHIM(load32, int32_t, (struct ARMCore* cpu, uint32_t address, int* cycleCounter), address, cycleCounter)
|
||||||
CREATE_SHIM(load16, int16_t, (struct ARMMemory* memory, uint32_t address, int* cycleCounter), address, cycleCounter)
|
CREATE_SHIM(load16, int16_t, (struct ARMCore* cpu, uint32_t address, int* cycleCounter), address, cycleCounter)
|
||||||
CREATE_SHIM(loadU16, uint16_t, (struct ARMMemory* memory, uint32_t address, int* cycleCounter), address, cycleCounter)
|
CREATE_SHIM(loadU16, uint16_t, (struct ARMCore* cpu, uint32_t address, int* cycleCounter), address, cycleCounter)
|
||||||
CREATE_SHIM(load8, int8_t, (struct ARMMemory* memory, uint32_t address, int* cycleCounter), address, cycleCounter)
|
CREATE_SHIM(load8, int8_t, (struct ARMCore* cpu, uint32_t address, int* cycleCounter), address, cycleCounter)
|
||||||
CREATE_SHIM(loadU8, uint8_t, (struct ARMMemory* memory, uint32_t address, int* cycleCounter), address, cycleCounter)
|
CREATE_SHIM(loadU8, uint8_t, (struct ARMCore* cpu, uint32_t address, int* cycleCounter), address, cycleCounter)
|
||||||
CREATE_SHIM(waitMultiple, int, (struct ARMMemory* memory, uint32_t startAddress, int count), startAddress, count)
|
CREATE_SHIM(waitMultiple, int, (struct ARMCore* cpu, uint32_t startAddress, int count), startAddress, count)
|
||||||
|
|
||||||
static int _checkWatchpoints(struct DebugBreakpoint* watchpoints, uint32_t address, int width) {
|
static int _checkWatchpoints(struct DebugBreakpoint* watchpoints, uint32_t address, int width) {
|
||||||
width -= 1;
|
width -= 1;
|
||||||
|
@ -33,52 +46,48 @@ static int _checkWatchpoints(struct DebugBreakpoint* watchpoints, uint32_t addre
|
||||||
}
|
}
|
||||||
|
|
||||||
void ARMDebuggerInstallMemoryShim(struct ARMDebugger* debugger) {
|
void ARMDebuggerInstallMemoryShim(struct ARMDebugger* debugger) {
|
||||||
debugger->memoryShim.original = debugger->cpu->memory;
|
debugger->originalMemory = debugger->cpu->memory;
|
||||||
memcpy(&debugger->memoryShim.d, debugger->cpu->memory, sizeof(struct ARMMemory));
|
debugger->cpu->memory.store32 = ARMDebuggerShim_store32;
|
||||||
debugger->memoryShim.d.store32 = ARMDebuggerShim_store32;
|
debugger->cpu->memory.store16 = ARMDebuggerShim_store16;
|
||||||
debugger->memoryShim.d.store16 = ARMDebuggerShim_store16;
|
debugger->cpu->memory.store8 = ARMDebuggerShim_store8;
|
||||||
debugger->memoryShim.d.store8 = ARMDebuggerShim_store8;
|
debugger->cpu->memory.load32 = ARMDebuggerShim_load32;
|
||||||
debugger->memoryShim.d.load32 = ARMDebuggerShim_load32;
|
debugger->cpu->memory.load16 = ARMDebuggerShim_load16;
|
||||||
debugger->memoryShim.d.load16 = ARMDebuggerShim_load16;
|
debugger->cpu->memory.loadU16 = ARMDebuggerShim_loadU16;
|
||||||
debugger->memoryShim.d.loadU16 = ARMDebuggerShim_loadU16;
|
debugger->cpu->memory.load8 = ARMDebuggerShim_load8;
|
||||||
debugger->memoryShim.d.load8 = ARMDebuggerShim_load8;
|
debugger->cpu->memory.loadU8 = ARMDebuggerShim_loadU8;
|
||||||
debugger->memoryShim.d.loadU8 = ARMDebuggerShim_loadU8;
|
debugger->cpu->memory.setActiveRegion = ARMDebuggerShim_setActiveRegion;
|
||||||
debugger->memoryShim.d.setActiveRegion = ARMDebuggerShim_setActiveRegion;
|
debugger->cpu->memory.waitMultiple = ARMDebuggerShim_waitMultiple;
|
||||||
debugger->memoryShim.d.waitMultiple = ARMDebuggerShim_waitMultiple;
|
|
||||||
debugger->cpu->memory = &debugger->memoryShim.d;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ARMDebuggerShim_store32(struct ARMMemory* memory, uint32_t address, int32_t value, int* cycleCounter) {
|
void ARMDebuggerShim_store32(struct ARMCore* cpu, uint32_t address, int32_t value, int* cycleCounter) {
|
||||||
struct DebugMemoryShim* debugMemory = (struct DebugMemoryShim*) memory;
|
struct ARMDebugger* debugger;
|
||||||
if (_checkWatchpoints(debugMemory->watchpoints, address, 4)) {
|
FIND_DEBUGGER(debugger, cpu);
|
||||||
ARMDebuggerEnter(debugMemory->p, DEBUGGER_ENTER_WATCHPOINT);
|
if (_checkWatchpoints(debugger->watchpoints, address, 4)) {
|
||||||
|
ARMDebuggerEnter(debugger, DEBUGGER_ENTER_WATCHPOINT);
|
||||||
}
|
}
|
||||||
debugMemory->original->store32(debugMemory->original, address, value, cycleCounter);
|
debugger->originalMemory.store32(debugger->cpu, address, value, cycleCounter);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ARMDebuggerShim_store16(struct ARMMemory* memory, uint32_t address, int16_t value, int* cycleCounter) {
|
void ARMDebuggerShim_store16(struct ARMCore* cpu, uint32_t address, int16_t value, int* cycleCounter) {
|
||||||
struct DebugMemoryShim* debugMemory = (struct DebugMemoryShim*) memory;
|
struct ARMDebugger* debugger;
|
||||||
if (_checkWatchpoints(debugMemory->watchpoints, address, 2)) {
|
FIND_DEBUGGER(debugger, cpu);
|
||||||
ARMDebuggerEnter(debugMemory->p, DEBUGGER_ENTER_WATCHPOINT);
|
if (_checkWatchpoints(debugger->watchpoints, address, 2)) {
|
||||||
|
ARMDebuggerEnter(debugger, DEBUGGER_ENTER_WATCHPOINT);
|
||||||
}
|
}
|
||||||
debugMemory->original->store16(debugMemory->original, address, value, cycleCounter);
|
debugger->originalMemory.store16(debugger->cpu, address, value, cycleCounter);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ARMDebuggerShim_store8(struct ARMMemory* memory, uint32_t address, int8_t value, int* cycleCounter) {
|
void ARMDebuggerShim_store8(struct ARMCore* cpu, uint32_t address, int8_t value, int* cycleCounter) {
|
||||||
struct DebugMemoryShim* debugMemory = (struct DebugMemoryShim*) memory;
|
struct ARMDebugger* debugger;
|
||||||
if (_checkWatchpoints(debugMemory->watchpoints, address, 1)) {
|
FIND_DEBUGGER(debugger, cpu);
|
||||||
ARMDebuggerEnter(debugMemory->p, DEBUGGER_ENTER_WATCHPOINT);
|
if (_checkWatchpoints(debugger->watchpoints, address, 1)) {
|
||||||
|
ARMDebuggerEnter(debugger, DEBUGGER_ENTER_WATCHPOINT);
|
||||||
}
|
}
|
||||||
debugMemory->original->store8(debugMemory->original, address, value, cycleCounter);
|
debugger->originalMemory.store8(debugger->cpu, address, value, cycleCounter);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ARMDebuggerShim_setActiveRegion(struct ARMMemory* memory, uint32_t address) {
|
void ARMDebuggerShim_setActiveRegion(struct ARMCore* cpu, uint32_t address) {
|
||||||
struct DebugMemoryShim* debugMemory = (struct DebugMemoryShim*) memory;
|
struct ARMDebugger* debugger;
|
||||||
debugMemory->original->setActiveRegion(debugMemory->original, address);
|
FIND_DEBUGGER(debugger, cpu);
|
||||||
memory->activeRegion = debugMemory->original->activeRegion;
|
debugger->originalMemory.setActiveRegion(cpu, address);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue