mirror of https://github.com/mgba-emu/mgba.git
Debugger: Convert breakpoints and watchpoints from linked-lists to vectors
This commit is contained in:
parent
16ba5bd05f
commit
e30674d053
1
CHANGES
1
CHANGES
|
@ -58,6 +58,7 @@ Misc:
|
||||||
- GBA RR: Add preliminary SRAM support for VBM loading
|
- GBA RR: Add preliminary SRAM support for VBM loading
|
||||||
- GBA RR: Add support for resets in movies
|
- GBA RR: Add support for resets in movies
|
||||||
- GBA Input: Consolidate GBA_KEY_NONE and GBA_NO_MAPPING
|
- GBA Input: Consolidate GBA_KEY_NONE and GBA_NO_MAPPING
|
||||||
|
- Debugger: Convert breakpoints and watchpoints from linked-lists to vectors
|
||||||
|
|
||||||
0.3.2: (2015-12-16)
|
0.3.2: (2015-12-16)
|
||||||
Bugfixes:
|
Bugfixes:
|
||||||
|
|
|
@ -12,10 +12,14 @@
|
||||||
|
|
||||||
const uint32_t ARM_DEBUGGER_ID = 0xDEADBEEF;
|
const uint32_t ARM_DEBUGGER_ID = 0xDEADBEEF;
|
||||||
|
|
||||||
static struct DebugBreakpoint* _lookupBreakpoint(struct DebugBreakpoint* breakpoints, uint32_t address) {
|
DEFINE_VECTOR(DebugBreakpointList, struct DebugBreakpoint);
|
||||||
for (; breakpoints; breakpoints = breakpoints->next) {
|
DEFINE_VECTOR(DebugWatchpointList, struct DebugWatchpoint);
|
||||||
if (breakpoints->address == address) {
|
|
||||||
return breakpoints;
|
static struct DebugBreakpoint* _lookupBreakpoint(struct DebugBreakpointList* breakpoints, uint32_t address) {
|
||||||
|
size_t i;
|
||||||
|
for (i = 0; i < DebugBreakpointListSize(breakpoints); ++i) {
|
||||||
|
if (DebugBreakpointListGetPointer(breakpoints, i)->address == address) {
|
||||||
|
return DebugBreakpointListGetPointer(breakpoints, i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -29,7 +33,7 @@ static void _checkBreakpoints(struct ARMDebugger* debugger) {
|
||||||
} else {
|
} else {
|
||||||
instructionLength = WORD_SIZE_THUMB;
|
instructionLength = WORD_SIZE_THUMB;
|
||||||
}
|
}
|
||||||
struct DebugBreakpoint* breakpoint = _lookupBreakpoint(debugger->breakpoints, debugger->cpu->gprs[ARM_PC] - instructionLength);
|
struct DebugBreakpoint* breakpoint = _lookupBreakpoint(&debugger->breakpoints, debugger->cpu->gprs[ARM_PC] - instructionLength);
|
||||||
if (!breakpoint) {
|
if (!breakpoint) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -52,11 +56,11 @@ void ARMDebuggerInit(struct ARMCore* cpu, struct ARMComponent* component) {
|
||||||
struct ARMDebugger* debugger = (struct ARMDebugger*) component;
|
struct ARMDebugger* debugger = (struct ARMDebugger*) component;
|
||||||
debugger->cpu = cpu;
|
debugger->cpu = cpu;
|
||||||
debugger->state = DEBUGGER_RUNNING;
|
debugger->state = DEBUGGER_RUNNING;
|
||||||
debugger->breakpoints = 0;
|
|
||||||
debugger->swBreakpoints = 0;
|
|
||||||
debugger->originalMemory = cpu->memory;
|
debugger->originalMemory = cpu->memory;
|
||||||
debugger->watchpoints = 0;
|
|
||||||
debugger->currentBreakpoint = 0;
|
debugger->currentBreakpoint = 0;
|
||||||
|
DebugBreakpointListInit(&debugger->breakpoints, 0);
|
||||||
|
DebugBreakpointListInit(&debugger->swBreakpoints, 0);
|
||||||
|
DebugWatchpointListInit(&debugger->watchpoints, 0);
|
||||||
if (debugger->init) {
|
if (debugger->init) {
|
||||||
debugger->init(debugger);
|
debugger->init(debugger);
|
||||||
}
|
}
|
||||||
|
@ -65,12 +69,15 @@ void ARMDebuggerInit(struct ARMCore* cpu, struct ARMComponent* component) {
|
||||||
void ARMDebuggerDeinit(struct ARMComponent* component) {
|
void ARMDebuggerDeinit(struct ARMComponent* component) {
|
||||||
struct ARMDebugger* debugger = (struct ARMDebugger*) component;
|
struct ARMDebugger* debugger = (struct ARMDebugger*) component;
|
||||||
debugger->deinit(debugger);
|
debugger->deinit(debugger);
|
||||||
|
DebugBreakpointListDeinit(&debugger->breakpoints);
|
||||||
|
DebugBreakpointListDeinit(&debugger->swBreakpoints);
|
||||||
|
DebugWatchpointListDeinit(&debugger->watchpoints);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ARMDebuggerRun(struct ARMDebugger* debugger) {
|
void ARMDebuggerRun(struct ARMDebugger* debugger) {
|
||||||
switch (debugger->state) {
|
switch (debugger->state) {
|
||||||
case DEBUGGER_RUNNING:
|
case DEBUGGER_RUNNING:
|
||||||
if (!debugger->breakpoints && !debugger->watchpoints) {
|
if (!DebugBreakpointListSize(&debugger->breakpoints) && !DebugWatchpointListSize(&debugger->watchpoints)) {
|
||||||
ARMRunLoop(debugger->cpu);
|
ARMRunLoop(debugger->cpu);
|
||||||
} else {
|
} else {
|
||||||
ARMRun(debugger->cpu);
|
ARMRun(debugger->cpu);
|
||||||
|
@ -105,7 +112,7 @@ void ARMDebuggerEnter(struct ARMDebugger* debugger, enum DebuggerEntryReason rea
|
||||||
struct ARMCore* cpu = debugger->cpu;
|
struct ARMCore* cpu = debugger->cpu;
|
||||||
cpu->nextEvent = cpu->cycles;
|
cpu->nextEvent = cpu->cycles;
|
||||||
if (reason == DEBUGGER_ENTER_BREAKPOINT) {
|
if (reason == DEBUGGER_ENTER_BREAKPOINT) {
|
||||||
struct DebugBreakpoint* breakpoint = _lookupBreakpoint(debugger->swBreakpoints, _ARMPCAddress(cpu));
|
struct DebugBreakpoint* breakpoint = _lookupBreakpoint(&debugger->swBreakpoints, _ARMPCAddress(cpu));
|
||||||
debugger->currentBreakpoint = breakpoint;
|
debugger->currentBreakpoint = breakpoint;
|
||||||
if (breakpoint && breakpoint->isSw) {
|
if (breakpoint && breakpoint->isSw) {
|
||||||
info->address = breakpoint->address;
|
info->address = breakpoint->address;
|
||||||
|
@ -122,11 +129,9 @@ void ARMDebuggerEnter(struct ARMDebugger* debugger, enum DebuggerEntryReason rea
|
||||||
}
|
}
|
||||||
|
|
||||||
void ARMDebuggerSetBreakpoint(struct ARMDebugger* debugger, uint32_t address) {
|
void ARMDebuggerSetBreakpoint(struct ARMDebugger* debugger, uint32_t address) {
|
||||||
struct DebugBreakpoint* breakpoint = malloc(sizeof(struct DebugBreakpoint));
|
struct DebugBreakpoint* breakpoint = DebugBreakpointListAppend(&debugger->breakpoints);
|
||||||
breakpoint->address = address;
|
breakpoint->address = address;
|
||||||
breakpoint->next = debugger->breakpoints;
|
|
||||||
breakpoint->isSw = false;
|
breakpoint->isSw = false;
|
||||||
debugger->breakpoints = breakpoint;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ARMDebuggerSetSoftwareBreakpoint(struct ARMDebugger* debugger, uint32_t address, enum ExecutionMode mode) {
|
bool ARMDebuggerSetSoftwareBreakpoint(struct ARMDebugger* debugger, uint32_t address, enum ExecutionMode mode) {
|
||||||
|
@ -135,57 +140,44 @@ bool ARMDebuggerSetSoftwareBreakpoint(struct ARMDebugger* debugger, uint32_t add
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct DebugBreakpoint* breakpoint = malloc(sizeof(struct DebugBreakpoint));
|
struct DebugBreakpoint* breakpoint = DebugBreakpointListAppend(&debugger->swBreakpoints);
|
||||||
breakpoint->address = address;
|
breakpoint->address = address;
|
||||||
breakpoint->next = debugger->swBreakpoints;
|
|
||||||
breakpoint->isSw = true;
|
breakpoint->isSw = true;
|
||||||
breakpoint->sw.opcode = opcode;
|
breakpoint->sw.opcode = opcode;
|
||||||
breakpoint->sw.mode = mode;
|
breakpoint->sw.mode = mode;
|
||||||
debugger->swBreakpoints = breakpoint;
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ARMDebuggerClearBreakpoint(struct ARMDebugger* debugger, uint32_t address) {
|
void ARMDebuggerClearBreakpoint(struct ARMDebugger* debugger, uint32_t address) {
|
||||||
struct DebugBreakpoint** previous = &debugger->breakpoints;
|
struct DebugBreakpointList* breakpoints = &debugger->breakpoints;
|
||||||
struct DebugBreakpoint* breakpoint;
|
size_t i;
|
||||||
struct DebugBreakpoint** next;
|
for (i = 0; i < DebugBreakpointListSize(breakpoints); ++i) {
|
||||||
while ((breakpoint = *previous)) {
|
if (DebugBreakpointListGetPointer(breakpoints, i)->address == address) {
|
||||||
next = &breakpoint->next;
|
DebugBreakpointListShift(breakpoints, i, 1);
|
||||||
if (breakpoint->address == address) {
|
|
||||||
*previous = *next;
|
|
||||||
free(breakpoint);
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
previous = next;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ARMDebuggerSetWatchpoint(struct ARMDebugger* debugger, uint32_t address, enum WatchpointType type) {
|
void ARMDebuggerSetWatchpoint(struct ARMDebugger* debugger, uint32_t address, enum WatchpointType type) {
|
||||||
if (!debugger->watchpoints) {
|
if (!DebugWatchpointListSize(&debugger->watchpoints)) {
|
||||||
ARMDebuggerInstallMemoryShim(debugger);
|
ARMDebuggerInstallMemoryShim(debugger);
|
||||||
}
|
}
|
||||||
struct DebugWatchpoint* watchpoint = malloc(sizeof(struct DebugWatchpoint));
|
struct DebugWatchpoint* watchpoint = DebugWatchpointListAppend(&debugger->watchpoints);
|
||||||
watchpoint->address = address;
|
watchpoint->address = address;
|
||||||
watchpoint->type = type;
|
watchpoint->type = type;
|
||||||
watchpoint->next = debugger->watchpoints;
|
|
||||||
debugger->watchpoints = watchpoint;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ARMDebuggerClearWatchpoint(struct ARMDebugger* debugger, uint32_t address) {
|
void ARMDebuggerClearWatchpoint(struct ARMDebugger* debugger, uint32_t address) {
|
||||||
struct DebugWatchpoint** previous = &debugger->watchpoints;
|
struct DebugWatchpointList* watchpoints = &debugger->watchpoints;
|
||||||
struct DebugWatchpoint* watchpoint;
|
size_t i;
|
||||||
struct DebugWatchpoint** next;
|
for (i = 0; i < DebugWatchpointListSize(watchpoints); ++i) {
|
||||||
while ((watchpoint = *previous)) {
|
if (DebugWatchpointListGetPointer(watchpoints, i)->address == address) {
|
||||||
next = &watchpoint->next;
|
DebugWatchpointListShift(watchpoints, i, 1);
|
||||||
if (watchpoint->address == address) {
|
|
||||||
*previous = *next;
|
|
||||||
free(watchpoint);
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
previous = next;
|
|
||||||
}
|
}
|
||||||
if (!debugger->watchpoints) {
|
if (!DebugWatchpointListSize(&debugger->watchpoints)) {
|
||||||
ARMDebuggerRemoveMemoryShim(debugger);
|
ARMDebuggerRemoveMemoryShim(debugger);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,8 @@
|
||||||
|
|
||||||
#include "util/common.h"
|
#include "util/common.h"
|
||||||
|
|
||||||
#include "arm.h"
|
#include "arm/arm.h"
|
||||||
|
#include "util/vector.h"
|
||||||
|
|
||||||
extern const uint32_t ARM_DEBUGGER_ID;
|
extern const uint32_t ARM_DEBUGGER_ID;
|
||||||
|
|
||||||
|
@ -20,7 +21,6 @@ enum DebuggerState {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DebugBreakpoint {
|
struct DebugBreakpoint {
|
||||||
struct DebugBreakpoint* next;
|
|
||||||
uint32_t address;
|
uint32_t address;
|
||||||
bool isSw;
|
bool isSw;
|
||||||
struct {
|
struct {
|
||||||
|
@ -36,11 +36,13 @@ enum WatchpointType {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DebugWatchpoint {
|
struct DebugWatchpoint {
|
||||||
struct DebugWatchpoint* next;
|
|
||||||
uint32_t address;
|
uint32_t address;
|
||||||
enum WatchpointType type;
|
enum WatchpointType type;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
DECLARE_VECTOR(DebugBreakpointList, struct DebugBreakpoint);
|
||||||
|
DECLARE_VECTOR(DebugWatchpointList, struct DebugWatchpoint);
|
||||||
|
|
||||||
enum DebuggerEntryReason {
|
enum DebuggerEntryReason {
|
||||||
DEBUGGER_ENTER_MANUAL,
|
DEBUGGER_ENTER_MANUAL,
|
||||||
DEBUGGER_ENTER_ATTACHED,
|
DEBUGGER_ENTER_ATTACHED,
|
||||||
|
@ -75,9 +77,9 @@ struct ARMDebugger {
|
||||||
enum DebuggerState state;
|
enum DebuggerState state;
|
||||||
struct ARMCore* cpu;
|
struct ARMCore* cpu;
|
||||||
|
|
||||||
struct DebugBreakpoint* breakpoints;
|
struct DebugBreakpointList breakpoints;
|
||||||
struct DebugBreakpoint* swBreakpoints;
|
struct DebugBreakpointList swBreakpoints;
|
||||||
struct DebugWatchpoint* watchpoints;
|
struct DebugWatchpointList watchpoints;
|
||||||
struct ARMMemory originalMemory;
|
struct ARMMemory originalMemory;
|
||||||
|
|
||||||
struct DebugBreakpoint* currentBreakpoint;
|
struct DebugBreakpoint* currentBreakpoint;
|
||||||
|
|
|
@ -79,9 +79,11 @@ CREATE_SHIM(setActiveRegion, void, (struct ARMCore* cpu, uint32_t address), addr
|
||||||
|
|
||||||
static bool _checkWatchpoints(struct ARMDebugger* debugger, uint32_t address, struct DebuggerEntryInfo* info, enum WatchpointType type, int width) {
|
static bool _checkWatchpoints(struct ARMDebugger* debugger, uint32_t address, struct DebuggerEntryInfo* info, enum WatchpointType type, int width) {
|
||||||
--width;
|
--width;
|
||||||
struct DebugWatchpoint* watchpoints;
|
struct DebugWatchpoint* watchpoint;
|
||||||
for (watchpoints = debugger->watchpoints; watchpoints; watchpoints = watchpoints->next) {
|
size_t i;
|
||||||
if (!((watchpoints->address ^ address) & ~width) && watchpoints->type & type) {
|
for (i = 0; i < DebugWatchpointListSize(&debugger->watchpoints); ++i) {
|
||||||
|
watchpoint = DebugWatchpointListGetPointer(&debugger->watchpoints, i);
|
||||||
|
if (!((watchpoint->address ^ address) & ~width) && watchpoint->type & type) {
|
||||||
switch (width + 1) {
|
switch (width + 1) {
|
||||||
case 1:
|
case 1:
|
||||||
info->oldValue = debugger->originalMemory.load8(debugger->cpu, address, 0);
|
info->oldValue = debugger->originalMemory.load8(debugger->cpu, address, 0);
|
||||||
|
@ -94,7 +96,7 @@ static bool _checkWatchpoints(struct ARMDebugger* debugger, uint32_t address, st
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
info->address = address;
|
info->address = address;
|
||||||
info->watchType = watchpoints->type;
|
info->watchType = watchpoint->type;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue