mirror of https://github.com/mgba-emu/mgba.git
Debugger: Make created debug items, e.g. breakpoints, owned by modules
This commit is contained in:
parent
b21a6158f4
commit
8efb3fb5df
|
@ -12,6 +12,7 @@ CXX_GUARD_START
|
|||
|
||||
#include <mgba/core/cpu.h>
|
||||
#include <mgba/core/log.h>
|
||||
#include <mgba-util/table.h>
|
||||
#include <mgba-util/vector.h>
|
||||
#include <mgba/internal/debugger/stack-trace.h>
|
||||
|
||||
|
@ -114,11 +115,11 @@ struct mDebuggerPlatform {
|
|||
void (*checkBreakpoints)(struct mDebuggerPlatform*);
|
||||
bool (*clearBreakpoint)(struct mDebuggerPlatform*, ssize_t id);
|
||||
|
||||
ssize_t (*setBreakpoint)(struct mDebuggerPlatform*, const struct mBreakpoint*);
|
||||
void (*listBreakpoints)(struct mDebuggerPlatform*, struct mBreakpointList*);
|
||||
ssize_t (*setBreakpoint)(struct mDebuggerPlatform*, struct mDebuggerModule*, const struct mBreakpoint*);
|
||||
void (*listBreakpoints)(struct mDebuggerPlatform*, struct mDebuggerModule*, struct mBreakpointList*);
|
||||
|
||||
ssize_t (*setWatchpoint)(struct mDebuggerPlatform*, const struct mWatchpoint*);
|
||||
void (*listWatchpoints)(struct mDebuggerPlatform*, struct mWatchpointList*);
|
||||
ssize_t (*setWatchpoint)(struct mDebuggerPlatform*, struct mDebuggerModule*, const struct mWatchpoint*);
|
||||
void (*listWatchpoints)(struct mDebuggerPlatform*, struct mDebuggerModule*, struct mWatchpointList*);
|
||||
|
||||
void (*trace)(struct mDebuggerPlatform*, char* out, size_t* length);
|
||||
|
||||
|
@ -138,6 +139,7 @@ struct mDebugger {
|
|||
struct mStackTrace stackTrace;
|
||||
|
||||
struct mDebuggerModuleList modules;
|
||||
struct Table pointOwner;
|
||||
};
|
||||
|
||||
struct mDebuggerModule {
|
||||
|
|
|
@ -45,7 +45,7 @@ struct ARMDebugger {
|
|||
};
|
||||
|
||||
struct mDebuggerPlatform* ARMDebuggerPlatformCreate(void);
|
||||
ssize_t ARMDebuggerSetSoftwareBreakpoint(struct mDebuggerPlatform* debugger, uint32_t address, enum ExecutionMode mode);
|
||||
ssize_t ARMDebuggerSetSoftwareBreakpoint(struct mDebuggerPlatform* debugger, struct mDebuggerModule* owner, uint32_t address, enum ExecutionMode mode);
|
||||
|
||||
CXX_GUARD_END
|
||||
|
||||
|
|
|
@ -159,7 +159,7 @@ static void _setBreakpointARM(struct CLIDebugger* debugger, struct CLIDebugVecto
|
|||
return;
|
||||
}
|
||||
uint32_t address = dv->intValue;
|
||||
ssize_t id = ARMDebuggerSetSoftwareBreakpoint(debugger->d.p->platform, address, MODE_ARM);
|
||||
ssize_t id = ARMDebuggerSetSoftwareBreakpoint(debugger->d.p->platform, &debugger->d, address, MODE_ARM);
|
||||
if (id > 0) {
|
||||
debugger->backend->printf(debugger->backend, INFO_BREAKPOINT_ADDED, id);
|
||||
}
|
||||
|
@ -172,7 +172,7 @@ static void _setBreakpointThumb(struct CLIDebugger* debugger, struct CLIDebugVec
|
|||
return;
|
||||
}
|
||||
uint32_t address = dv->intValue;
|
||||
ssize_t id = ARMDebuggerSetSoftwareBreakpoint(debugger->d.p->platform, address, MODE_THUMB);
|
||||
ssize_t id = ARMDebuggerSetSoftwareBreakpoint(debugger->d.p->platform, &debugger->d, address, MODE_THUMB);
|
||||
if (id > 0) {
|
||||
debugger->backend->printf(debugger->backend, INFO_BREAKPOINT_ADDED, id);
|
||||
}
|
||||
|
|
|
@ -187,16 +187,18 @@ static struct ARMDebugBreakpoint* _lookupBreakpoint(struct ARMDebugBreakpointLis
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void _destroyBreakpoint(struct ARMDebugBreakpoint* breakpoint) {
|
||||
static void _destroyBreakpoint(struct mDebugger* debugger, struct ARMDebugBreakpoint* breakpoint) {
|
||||
if (breakpoint->d.condition) {
|
||||
parseFree(breakpoint->d.condition);
|
||||
}
|
||||
TableRemove(&debugger->pointOwner, breakpoint->d.id);
|
||||
}
|
||||
|
||||
static void _destroyWatchpoint(struct mWatchpoint* watchpoint) {
|
||||
static void _destroyWatchpoint(struct mDebugger* debugger, struct mWatchpoint* watchpoint) {
|
||||
if (watchpoint->condition) {
|
||||
parseFree(watchpoint->condition);
|
||||
}
|
||||
TableRemove(&debugger->pointOwner, watchpoint->id);
|
||||
}
|
||||
|
||||
static void ARMDebuggerCheckBreakpoints(struct mDebuggerPlatform* d) {
|
||||
|
@ -220,7 +222,8 @@ static void ARMDebuggerCheckBreakpoints(struct mDebuggerPlatform* d) {
|
|||
struct mDebuggerEntryInfo info = {
|
||||
.address = breakpoint->d.address,
|
||||
.type.bp.breakType = BREAKPOINT_HARDWARE,
|
||||
.pointId = breakpoint->d.id
|
||||
.pointId = breakpoint->d.id,
|
||||
.target = TableLookup(&d->p->pointOwner, breakpoint->d.id)
|
||||
};
|
||||
mDebuggerEnter(d->p, DEBUGGER_ENTER_BREAKPOINT, &info);
|
||||
}
|
||||
|
@ -230,11 +233,11 @@ static void ARMDebuggerDeinit(struct mDebuggerPlatform* platform);
|
|||
|
||||
static void ARMDebuggerEnter(struct mDebuggerPlatform* d, enum mDebuggerEntryReason reason, struct mDebuggerEntryInfo* info);
|
||||
|
||||
static ssize_t ARMDebuggerSetBreakpoint(struct mDebuggerPlatform*, const struct mBreakpoint*);
|
||||
static ssize_t ARMDebuggerSetBreakpoint(struct mDebuggerPlatform*, struct mDebuggerModule* owner, const struct mBreakpoint*);
|
||||
static bool ARMDebuggerClearBreakpoint(struct mDebuggerPlatform*, ssize_t id);
|
||||
static void ARMDebuggerListBreakpoints(struct mDebuggerPlatform*, struct mBreakpointList*);
|
||||
static ssize_t ARMDebuggerSetWatchpoint(struct mDebuggerPlatform*, const struct mWatchpoint*);
|
||||
static void ARMDebuggerListWatchpoints(struct mDebuggerPlatform*, struct mWatchpointList*);
|
||||
static void ARMDebuggerListBreakpoints(struct mDebuggerPlatform*, struct mDebuggerModule* owner, struct mBreakpointList*);
|
||||
static ssize_t ARMDebuggerSetWatchpoint(struct mDebuggerPlatform*, struct mDebuggerModule* owner, const struct mWatchpoint*);
|
||||
static void ARMDebuggerListWatchpoints(struct mDebuggerPlatform*, struct mDebuggerModule* owner, struct mWatchpointList*);
|
||||
static void ARMDebuggerCheckBreakpoints(struct mDebuggerPlatform*);
|
||||
static bool ARMDebuggerHasBreakpoints(struct mDebuggerPlatform*);
|
||||
static void ARMDebuggerTrace(struct mDebuggerPlatform*, char* out, size_t* length);
|
||||
|
@ -291,12 +294,12 @@ void ARMDebuggerDeinit(struct mDebuggerPlatform* platform) {
|
|||
|
||||
size_t i;
|
||||
for (i = 0; i < ARMDebugBreakpointListSize(&debugger->breakpoints); ++i) {
|
||||
_destroyBreakpoint(ARMDebugBreakpointListGetPointer(&debugger->breakpoints, i));
|
||||
_destroyBreakpoint(debugger->d.p, ARMDebugBreakpointListGetPointer(&debugger->breakpoints, i));
|
||||
}
|
||||
ARMDebugBreakpointListDeinit(&debugger->breakpoints);
|
||||
|
||||
for (i = 0; i < mWatchpointListSize(&debugger->watchpoints); ++i) {
|
||||
_destroyWatchpoint(mWatchpointListGetPointer(&debugger->watchpoints, i));
|
||||
_destroyWatchpoint(debugger->d.p, mWatchpointListGetPointer(&debugger->watchpoints, i));
|
||||
}
|
||||
ARMDebugBreakpointListDeinit(&debugger->swBreakpoints);
|
||||
mWatchpointListDeinit(&debugger->watchpoints);
|
||||
|
@ -325,7 +328,7 @@ static void ARMDebuggerEnter(struct mDebuggerPlatform* platform, enum mDebuggerE
|
|||
}
|
||||
}
|
||||
|
||||
ssize_t ARMDebuggerSetSoftwareBreakpoint(struct mDebuggerPlatform* d, uint32_t address, enum ExecutionMode mode) {
|
||||
ssize_t ARMDebuggerSetSoftwareBreakpoint(struct mDebuggerPlatform* d, struct mDebuggerModule* owner, uint32_t address, enum ExecutionMode mode) {
|
||||
struct ARMDebugger* debugger = (struct ARMDebugger*) d;
|
||||
uint32_t opcode;
|
||||
if (!debugger->setSoftwareBreakpoint || !debugger->setSoftwareBreakpoint(debugger, address, mode, &opcode)) {
|
||||
|
@ -342,11 +345,12 @@ ssize_t ARMDebuggerSetSoftwareBreakpoint(struct mDebuggerPlatform* d, uint32_t a
|
|||
breakpoint->d.type = BREAKPOINT_SOFTWARE;
|
||||
breakpoint->sw.opcode = opcode;
|
||||
breakpoint->sw.mode = mode;
|
||||
TableInsert(&debugger->d.p->pointOwner, id, owner);
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
static ssize_t ARMDebuggerSetBreakpoint(struct mDebuggerPlatform* d, const struct mBreakpoint* info) {
|
||||
static ssize_t ARMDebuggerSetBreakpoint(struct mDebuggerPlatform* d, struct mDebuggerModule* owner, const struct mBreakpoint* info) {
|
||||
struct ARMDebugger* debugger = (struct ARMDebugger*) d;
|
||||
struct ARMDebugBreakpoint* breakpoint = ARMDebugBreakpointListAppend(&debugger->breakpoints);
|
||||
ssize_t id = debugger->nextId;
|
||||
|
@ -354,6 +358,7 @@ static ssize_t ARMDebuggerSetBreakpoint(struct mDebuggerPlatform* d, const struc
|
|||
breakpoint->d = *info;
|
||||
breakpoint->d.address &= ~1; // Clear Thumb bit since it's not part of a valid address
|
||||
breakpoint->d.id = id;
|
||||
TableInsert(&debugger->d.p->pointOwner, id, owner);
|
||||
if (info->type == BREAKPOINT_SOFTWARE) {
|
||||
// TODO
|
||||
abort();
|
||||
|
@ -368,7 +373,7 @@ static bool ARMDebuggerClearBreakpoint(struct mDebuggerPlatform* d, ssize_t id)
|
|||
struct ARMDebugBreakpointList* breakpoints = &debugger->breakpoints;
|
||||
for (i = 0; i < ARMDebugBreakpointListSize(breakpoints); ++i) {
|
||||
if (ARMDebugBreakpointListGetPointer(breakpoints, i)->d.id == id) {
|
||||
_destroyBreakpoint(ARMDebugBreakpointListGetPointer(breakpoints, i));
|
||||
_destroyBreakpoint(debugger->d.p, ARMDebugBreakpointListGetPointer(breakpoints, i));
|
||||
ARMDebugBreakpointListShift(breakpoints, i, 1);
|
||||
return true;
|
||||
}
|
||||
|
@ -388,7 +393,7 @@ static bool ARMDebuggerClearBreakpoint(struct mDebuggerPlatform* d, ssize_t id)
|
|||
struct mWatchpointList* watchpoints = &debugger->watchpoints;
|
||||
for (i = 0; i < mWatchpointListSize(watchpoints); ++i) {
|
||||
if (mWatchpointListGetPointer(watchpoints, i)->id == id) {
|
||||
_destroyWatchpoint(mWatchpointListGetPointer(watchpoints, i));
|
||||
_destroyWatchpoint(debugger->d.p, mWatchpointListGetPointer(watchpoints, i));
|
||||
mWatchpointListShift(watchpoints, i, 1);
|
||||
if (!mWatchpointListSize(&debugger->watchpoints)) {
|
||||
ARMDebuggerRemoveMemoryShim(debugger);
|
||||
|
@ -399,19 +404,29 @@ static bool ARMDebuggerClearBreakpoint(struct mDebuggerPlatform* d, ssize_t id)
|
|||
return false;
|
||||
}
|
||||
|
||||
static void ARMDebuggerListBreakpoints(struct mDebuggerPlatform* d, struct mBreakpointList* list) {
|
||||
static void ARMDebuggerListBreakpoints(struct mDebuggerPlatform* d, struct mDebuggerModule* owner, struct mBreakpointList* list) {
|
||||
struct ARMDebugger* debugger = (struct ARMDebugger*) d;
|
||||
mBreakpointListClear(list);
|
||||
size_t i, s;
|
||||
for (i = 0, s = 0; i < ARMDebugBreakpointListSize(&debugger->breakpoints) || s < ARMDebugBreakpointListSize(&debugger->swBreakpoints);) {
|
||||
for (i = 0; i < ARMDebugBreakpointListSize(&debugger->breakpoints) || s < ARMDebugBreakpointListSize(&debugger->swBreakpoints);) {
|
||||
struct ARMDebugBreakpoint* hw = NULL;
|
||||
struct ARMDebugBreakpoint* sw = NULL;
|
||||
if (i < ARMDebugBreakpointListSize(&debugger->breakpoints)) {
|
||||
hw = ARMDebugBreakpointListGetPointer(&debugger->breakpoints, i);
|
||||
if (owner && TableLookup(&debugger->d.p->pointOwner, hw->d.id) != owner) {
|
||||
hw = NULL;
|
||||
}
|
||||
}
|
||||
if (s < ARMDebugBreakpointListSize(&debugger->swBreakpoints)) {
|
||||
sw = ARMDebugBreakpointListGetPointer(&debugger->swBreakpoints, s);
|
||||
if (owner && TableLookup(&debugger->d.p->pointOwner, sw->d.id) != owner) {
|
||||
sw = NULL;
|
||||
}
|
||||
}
|
||||
if (!hw && !sw) {
|
||||
continue;
|
||||
}
|
||||
|
||||
struct mBreakpoint* b = mBreakpointListAppend(list);
|
||||
if (hw && sw) {
|
||||
if (hw->d.id < sw->d.id) {
|
||||
|
@ -427,8 +442,6 @@ static void ARMDebuggerListBreakpoints(struct mDebuggerPlatform* d, struct mBrea
|
|||
} else if (sw) {
|
||||
*b = sw->d;
|
||||
++s;
|
||||
} else {
|
||||
abort(); // Should be unreachable
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -438,7 +451,7 @@ static bool ARMDebuggerHasBreakpoints(struct mDebuggerPlatform* d) {
|
|||
return ARMDebugBreakpointListSize(&debugger->breakpoints) || mWatchpointListSize(&debugger->watchpoints) || debugger->stackTraceMode != STACK_TRACE_DISABLED;
|
||||
}
|
||||
|
||||
static ssize_t ARMDebuggerSetWatchpoint(struct mDebuggerPlatform* d, const struct mWatchpoint* info) {
|
||||
static ssize_t ARMDebuggerSetWatchpoint(struct mDebuggerPlatform* d, struct mDebuggerModule* owner, const struct mWatchpoint* info) {
|
||||
struct ARMDebugger* debugger = (struct ARMDebugger*) d;
|
||||
if (!mWatchpointListSize(&debugger->watchpoints)) {
|
||||
ARMDebuggerInstallMemoryShim(debugger);
|
||||
|
@ -448,13 +461,25 @@ static ssize_t ARMDebuggerSetWatchpoint(struct mDebuggerPlatform* d, const struc
|
|||
++debugger->nextId;
|
||||
*watchpoint = *info;
|
||||
watchpoint->id = id;
|
||||
TableInsert(&debugger->d.p->pointOwner, id, owner);
|
||||
return id;
|
||||
}
|
||||
|
||||
static void ARMDebuggerListWatchpoints(struct mDebuggerPlatform* d, struct mWatchpointList* list) {
|
||||
static void ARMDebuggerListWatchpoints(struct mDebuggerPlatform* d, struct mDebuggerModule* owner, struct mWatchpointList* list) {
|
||||
struct ARMDebugger* debugger = (struct ARMDebugger*) d;
|
||||
mWatchpointListClear(list);
|
||||
mWatchpointListCopy(list, &debugger->watchpoints);
|
||||
if (owner) {
|
||||
size_t i;
|
||||
for (i = 0; i < mWatchpointListSize(&debugger->watchpoints); ++i) {
|
||||
struct mWatchpoint* point = mWatchpointListGetPointer(&debugger->watchpoints, i);
|
||||
if (TableLookup(&debugger->d.p->pointOwner, point->id) != owner) {
|
||||
continue;
|
||||
}
|
||||
memcpy(mWatchpointListAppend(list), point, sizeof(*point));
|
||||
}
|
||||
} else {
|
||||
mWatchpointListCopy(list, &debugger->watchpoints);
|
||||
}
|
||||
}
|
||||
|
||||
static void ARMDebuggerTrace(struct mDebuggerPlatform* d, char* out, size_t* length) {
|
||||
|
|
|
@ -130,6 +130,7 @@ static bool _checkWatchpoints(struct ARMDebugger* debugger, uint32_t address, st
|
|||
info->type.wp.watchType = watchpoint->type;
|
||||
info->type.wp.accessType = type;
|
||||
info->pointId = watchpoint->id;
|
||||
info->target = TableLookup(&debugger->d.p->pointOwner, watchpoint->id);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -648,7 +648,7 @@ static void _setBreakpoint(struct CLIDebugger* debugger, struct CLIDebugVector*
|
|||
return;
|
||||
}
|
||||
}
|
||||
ssize_t id = debugger->d.p->platform->setBreakpoint(debugger->d.p->platform, &breakpoint);
|
||||
ssize_t id = debugger->d.p->platform->setBreakpoint(debugger->d.p->platform, &debugger->d, &breakpoint);
|
||||
if (id > 0) {
|
||||
debugger->backend->printf(debugger->backend, INFO_BREAKPOINT_ADDED, id);
|
||||
}
|
||||
|
@ -678,7 +678,7 @@ static void _setWatchpoint(struct CLIDebugger* debugger, struct CLIDebugVector*
|
|||
return;
|
||||
}
|
||||
}
|
||||
ssize_t id = debugger->d.p->platform->setWatchpoint(debugger->d.p->platform, &watchpoint);
|
||||
ssize_t id = debugger->d.p->platform->setWatchpoint(debugger->d.p->platform, &debugger->d, &watchpoint);
|
||||
if (id > 0) {
|
||||
debugger->backend->printf(debugger->backend, INFO_WATCHPOINT_ADDED, id);
|
||||
}
|
||||
|
@ -720,7 +720,7 @@ static void _setRangeWatchpoint(struct CLIDebugger* debugger, struct CLIDebugVec
|
|||
return;
|
||||
}
|
||||
}
|
||||
ssize_t id = debugger->d.p->platform->setWatchpoint(debugger->d.p->platform, &watchpoint);
|
||||
ssize_t id = debugger->d.p->platform->setWatchpoint(debugger->d.p->platform, &debugger->d, &watchpoint);
|
||||
if (id > 0) {
|
||||
debugger->backend->printf(debugger->backend, INFO_WATCHPOINT_ADDED, id);
|
||||
}
|
||||
|
@ -771,7 +771,7 @@ static void _listBreakpoints(struct CLIDebugger* debugger, struct CLIDebugVector
|
|||
UNUSED(dv);
|
||||
struct mBreakpointList breakpoints;
|
||||
mBreakpointListInit(&breakpoints, 0);
|
||||
debugger->d.p->platform->listBreakpoints(debugger->d.p->platform, &breakpoints);
|
||||
debugger->d.p->platform->listBreakpoints(debugger->d.p->platform, &debugger->d, &breakpoints);
|
||||
size_t i;
|
||||
for (i = 0; i < mBreakpointListSize(&breakpoints); ++i) {
|
||||
struct mBreakpoint* breakpoint = mBreakpointListGetPointer(&breakpoints, i);
|
||||
|
@ -788,7 +788,7 @@ static void _listWatchpoints(struct CLIDebugger* debugger, struct CLIDebugVector
|
|||
UNUSED(dv);
|
||||
struct mWatchpointList watchpoints;
|
||||
mWatchpointListInit(&watchpoints, 0);
|
||||
debugger->d.p->platform->listWatchpoints(debugger->d.p->platform, &watchpoints);
|
||||
debugger->d.p->platform->listWatchpoints(debugger->d.p->platform, &debugger->d, &watchpoints);
|
||||
size_t i;
|
||||
for (i = 0; i < mWatchpointListSize(&watchpoints); ++i) {
|
||||
struct mWatchpoint* watchpoint = mWatchpointListGetPointer(&watchpoints, i);
|
||||
|
|
|
@ -71,10 +71,12 @@ struct mDebuggerModule* mDebuggerCreateModule(enum mDebuggerType type, struct mC
|
|||
void mDebuggerInit(struct mDebugger* debugger) {
|
||||
memset(debugger, 0, sizeof(*debugger));
|
||||
mDebuggerModuleListInit(&debugger->modules, 4);
|
||||
TableInit(&debugger->pointOwner, 0, NULL);
|
||||
}
|
||||
|
||||
void mDebuggerDeinit(struct mDebugger* debugger) {
|
||||
mDebuggerModuleListDeinit(&debugger->modules);
|
||||
TableDeinit(&debugger->pointOwner);
|
||||
}
|
||||
|
||||
void mDebuggerAttach(struct mDebugger* debugger, struct mCore* core) {
|
||||
|
|
|
@ -596,19 +596,19 @@ static void _setBreakpoint(struct GDBStub* stub, const char* message) {
|
|||
switch (message[0]) {
|
||||
case '0':
|
||||
case '1':
|
||||
stub->d.p->platform->setBreakpoint(stub->d.p->platform, &breakpoint);
|
||||
stub->d.p->platform->setBreakpoint(stub->d.p->platform, &stub->d, &breakpoint);
|
||||
break;
|
||||
case '2':
|
||||
watchpoint.type = stub->watchpointsBehavior == GDB_WATCHPOINT_OVERRIDE_LOGIC_ANY_WRITE ? WATCHPOINT_WRITE : WATCHPOINT_WRITE_CHANGE;
|
||||
stub->d.p->platform->setWatchpoint(stub->d.p->platform, &watchpoint);
|
||||
stub->d.p->platform->setWatchpoint(stub->d.p->platform, &stub->d, &watchpoint);
|
||||
break;
|
||||
case '3':
|
||||
watchpoint.type = WATCHPOINT_READ;
|
||||
stub->d.p->platform->setWatchpoint(stub->d.p->platform, &watchpoint);
|
||||
stub->d.p->platform->setWatchpoint(stub->d.p->platform, &stub->d, &watchpoint);
|
||||
break;
|
||||
case '4':
|
||||
watchpoint.type = WATCHPOINT_RW;
|
||||
stub->d.p->platform->setWatchpoint(stub->d.p->platform, &watchpoint);
|
||||
stub->d.p->platform->setWatchpoint(stub->d.p->platform, &stub->d, &watchpoint);
|
||||
break;
|
||||
default:
|
||||
stub->outgoing[0] = '\0';
|
||||
|
@ -631,7 +631,7 @@ static void _clearBreakpoint(struct GDBStub* stub, const char* message) {
|
|||
case '0':
|
||||
case '1':
|
||||
mBreakpointListInit(&breakpoints, 0);
|
||||
stub->d.p->platform->listBreakpoints(stub->d.p->platform, &breakpoints);
|
||||
stub->d.p->platform->listBreakpoints(stub->d.p->platform, &stub->d, &breakpoints);
|
||||
for (index = 0; index < mBreakpointListSize(&breakpoints); ++index) {
|
||||
if (mBreakpointListGetPointer(&breakpoints, index)->address != address) {
|
||||
continue;
|
||||
|
@ -644,7 +644,7 @@ static void _clearBreakpoint(struct GDBStub* stub, const char* message) {
|
|||
case '3':
|
||||
case '4':
|
||||
mWatchpointListInit(&watchpoints, 0);
|
||||
stub->d.p->platform->listWatchpoints(stub->d.p->platform, &watchpoints);
|
||||
stub->d.p->platform->listWatchpoints(stub->d.p->platform, &stub->d, &watchpoints);
|
||||
for (index = 0; index < mWatchpointListSize(&watchpoints); ++index) {
|
||||
struct mWatchpoint* watchpoint = mWatchpointListGetPointer(&watchpoints, index);
|
||||
if (address >= watchpoint->minAddress && address < watchpoint->maxAddress) {
|
||||
|
|
|
@ -25,16 +25,18 @@ static struct mBreakpoint* _lookupBreakpoint(struct mBreakpointList* breakpoints
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static void _destroyBreakpoint(struct mBreakpoint* breakpoint) {
|
||||
static void _destroyBreakpoint(struct mDebugger* debugger, struct mBreakpoint* breakpoint) {
|
||||
if (breakpoint->condition) {
|
||||
parseFree(breakpoint->condition);
|
||||
}
|
||||
TableRemove(&debugger->pointOwner, breakpoint->id);
|
||||
}
|
||||
|
||||
static void _destroyWatchpoint(struct mWatchpoint* watchpoint) {
|
||||
static void _destroyWatchpoint(struct mDebugger* debugger, struct mWatchpoint* watchpoint) {
|
||||
if (watchpoint->condition) {
|
||||
parseFree(watchpoint->condition);
|
||||
}
|
||||
TableRemove(&debugger->pointOwner, watchpoint->id);
|
||||
}
|
||||
|
||||
static void SM83DebuggerCheckBreakpoints(struct mDebuggerPlatform* d) {
|
||||
|
@ -52,7 +54,8 @@ static void SM83DebuggerCheckBreakpoints(struct mDebuggerPlatform* d) {
|
|||
}
|
||||
struct mDebuggerEntryInfo info = {
|
||||
.address = breakpoint->address,
|
||||
.pointId = breakpoint->id
|
||||
.pointId = breakpoint->id,
|
||||
.target = TableLookup(&d->p->pointOwner, breakpoint->id)
|
||||
};
|
||||
mDebuggerEnter(d->p, DEBUGGER_ENTER_BREAKPOINT, &info);
|
||||
}
|
||||
|
@ -62,11 +65,11 @@ static void SM83DebuggerDeinit(struct mDebuggerPlatform* platform);
|
|||
|
||||
static void SM83DebuggerEnter(struct mDebuggerPlatform* d, enum mDebuggerEntryReason reason, struct mDebuggerEntryInfo* info);
|
||||
|
||||
static ssize_t SM83DebuggerSetBreakpoint(struct mDebuggerPlatform*, const struct mBreakpoint*);
|
||||
static void SM83DebuggerListBreakpoints(struct mDebuggerPlatform*, struct mBreakpointList*);
|
||||
static ssize_t SM83DebuggerSetBreakpoint(struct mDebuggerPlatform*, struct mDebuggerModule* owner, const struct mBreakpoint*);
|
||||
static void SM83DebuggerListBreakpoints(struct mDebuggerPlatform*, struct mDebuggerModule* owner, struct mBreakpointList*);
|
||||
static bool SM83DebuggerClearBreakpoint(struct mDebuggerPlatform*, ssize_t id);
|
||||
static ssize_t SM83DebuggerSetWatchpoint(struct mDebuggerPlatform*, const struct mWatchpoint*);
|
||||
static void SM83DebuggerListWatchpoints(struct mDebuggerPlatform*, struct mWatchpointList*);
|
||||
static ssize_t SM83DebuggerSetWatchpoint(struct mDebuggerPlatform*, struct mDebuggerModule* owner, const struct mWatchpoint*);
|
||||
static void SM83DebuggerListWatchpoints(struct mDebuggerPlatform*, struct mDebuggerModule* owner, struct mWatchpointList*);
|
||||
static void SM83DebuggerCheckBreakpoints(struct mDebuggerPlatform*);
|
||||
static bool SM83DebuggerHasBreakpoints(struct mDebuggerPlatform*);
|
||||
static void SM83DebuggerTrace(struct mDebuggerPlatform*, char* out, size_t* length);
|
||||
|
@ -104,12 +107,12 @@ void SM83DebuggerDeinit(struct mDebuggerPlatform* platform) {
|
|||
struct SM83Debugger* debugger = (struct SM83Debugger*) platform;
|
||||
size_t i;
|
||||
for (i = 0; i < mBreakpointListSize(&debugger->breakpoints); ++i) {
|
||||
_destroyBreakpoint(mBreakpointListGetPointer(&debugger->breakpoints, i));
|
||||
_destroyBreakpoint(debugger->d.p, mBreakpointListGetPointer(&debugger->breakpoints, i));
|
||||
}
|
||||
mBreakpointListDeinit(&debugger->breakpoints);
|
||||
|
||||
for (i = 0; i < mWatchpointListSize(&debugger->watchpoints); ++i) {
|
||||
_destroyWatchpoint(mWatchpointListGetPointer(&debugger->watchpoints, i));
|
||||
_destroyWatchpoint(debugger->d.p, mWatchpointListGetPointer(&debugger->watchpoints, i));
|
||||
}
|
||||
mWatchpointListDeinit(&debugger->watchpoints);
|
||||
}
|
||||
|
@ -122,14 +125,14 @@ static void SM83DebuggerEnter(struct mDebuggerPlatform* platform, enum mDebugger
|
|||
cpu->nextEvent = cpu->cycles;
|
||||
}
|
||||
|
||||
static ssize_t SM83DebuggerSetBreakpoint(struct mDebuggerPlatform* d, const struct mBreakpoint* info) {
|
||||
static ssize_t SM83DebuggerSetBreakpoint(struct mDebuggerPlatform* d, struct mDebuggerModule* owner, const struct mBreakpoint* info) {
|
||||
struct SM83Debugger* debugger = (struct SM83Debugger*) d;
|
||||
struct mBreakpoint* breakpoint = mBreakpointListAppend(&debugger->breakpoints);
|
||||
*breakpoint = *info;
|
||||
breakpoint->id = debugger->nextId;
|
||||
TableInsert(&debugger->d.p->pointOwner, breakpoint->id, owner);
|
||||
++debugger->nextId;
|
||||
return breakpoint->id;
|
||||
|
||||
}
|
||||
|
||||
static bool SM83DebuggerClearBreakpoint(struct mDebuggerPlatform* d, ssize_t id) {
|
||||
|
@ -140,7 +143,7 @@ static bool SM83DebuggerClearBreakpoint(struct mDebuggerPlatform* d, ssize_t id)
|
|||
for (i = 0; i < mBreakpointListSize(breakpoints); ++i) {
|
||||
struct mBreakpoint* breakpoint = mBreakpointListGetPointer(breakpoints, i);
|
||||
if (breakpoint->id == id) {
|
||||
_destroyBreakpoint(breakpoint);
|
||||
_destroyBreakpoint(debugger->d.p, breakpoint);
|
||||
mBreakpointListShift(breakpoints, i, 1);
|
||||
return true;
|
||||
}
|
||||
|
@ -150,7 +153,7 @@ static bool SM83DebuggerClearBreakpoint(struct mDebuggerPlatform* d, ssize_t id)
|
|||
for (i = 0; i < mWatchpointListSize(watchpoints); ++i) {
|
||||
struct mWatchpoint* watchpoint = mWatchpointListGetPointer(watchpoints, i);
|
||||
if (watchpoint->id == id) {
|
||||
_destroyWatchpoint(watchpoint);
|
||||
_destroyWatchpoint(debugger->d.p, watchpoint);
|
||||
mWatchpointListShift(watchpoints, i, 1);
|
||||
if (!mWatchpointListSize(&debugger->watchpoints)) {
|
||||
SM83DebuggerRemoveMemoryShim(debugger);
|
||||
|
@ -166,7 +169,7 @@ static bool SM83DebuggerHasBreakpoints(struct mDebuggerPlatform* d) {
|
|||
return mBreakpointListSize(&debugger->breakpoints) || mWatchpointListSize(&debugger->watchpoints);
|
||||
}
|
||||
|
||||
static ssize_t SM83DebuggerSetWatchpoint(struct mDebuggerPlatform* d, const struct mWatchpoint* info) {
|
||||
static ssize_t SM83DebuggerSetWatchpoint(struct mDebuggerPlatform* d, struct mDebuggerModule* owner, const struct mWatchpoint* info) {
|
||||
struct SM83Debugger* debugger = (struct SM83Debugger*) d;
|
||||
if (!mWatchpointListSize(&debugger->watchpoints)) {
|
||||
SM83DebuggerInstallMemoryShim(debugger);
|
||||
|
@ -174,20 +177,43 @@ static ssize_t SM83DebuggerSetWatchpoint(struct mDebuggerPlatform* d, const stru
|
|||
struct mWatchpoint* watchpoint = mWatchpointListAppend(&debugger->watchpoints);
|
||||
*watchpoint = *info;
|
||||
watchpoint->id = debugger->nextId;
|
||||
TableInsert(&debugger->d.p->pointOwner, watchpoint->id, owner);
|
||||
++debugger->nextId;
|
||||
return watchpoint->id;
|
||||
}
|
||||
|
||||
static void SM83DebuggerListBreakpoints(struct mDebuggerPlatform* d, struct mBreakpointList* list) {
|
||||
static void SM83DebuggerListBreakpoints(struct mDebuggerPlatform* d, struct mDebuggerModule* owner, struct mBreakpointList* list) {
|
||||
struct SM83Debugger* debugger = (struct SM83Debugger*) d;
|
||||
mBreakpointListClear(list);
|
||||
mBreakpointListCopy(list, &debugger->breakpoints);
|
||||
if (owner) {
|
||||
size_t i;
|
||||
for (i = 0; i < mBreakpointListSize(&debugger->breakpoints); ++i) {
|
||||
struct mBreakpoint* point = mBreakpointListGetPointer(&debugger->breakpoints, i);
|
||||
if (TableLookup(&debugger->d.p->pointOwner, point->id) != owner) {
|
||||
continue;
|
||||
}
|
||||
memcpy(mBreakpointListAppend(list), point, sizeof(*point));
|
||||
}
|
||||
} else {
|
||||
mBreakpointListCopy(list, &debugger->breakpoints);
|
||||
}
|
||||
}
|
||||
|
||||
static void SM83DebuggerListWatchpoints(struct mDebuggerPlatform* d, struct mWatchpointList* list) {
|
||||
static void SM83DebuggerListWatchpoints(struct mDebuggerPlatform* d, struct mDebuggerModule* owner, struct mWatchpointList* list) {
|
||||
struct SM83Debugger* debugger = (struct SM83Debugger*) d;
|
||||
mWatchpointListClear(list);
|
||||
mWatchpointListCopy(list, &debugger->watchpoints);
|
||||
if (owner) {
|
||||
size_t i;
|
||||
for (i = 0; i < mWatchpointListSize(&debugger->watchpoints); ++i) {
|
||||
struct mWatchpoint* point = mWatchpointListGetPointer(&debugger->watchpoints, i);
|
||||
if (TableLookup(&debugger->d.p->pointOwner, point->id) != owner) {
|
||||
continue;
|
||||
}
|
||||
memcpy(mWatchpointListAppend(list), point, sizeof(*point));
|
||||
}
|
||||
} else {
|
||||
mWatchpointListCopy(list, &debugger->watchpoints);
|
||||
}
|
||||
}
|
||||
|
||||
static void SM83DebuggerTrace(struct mDebuggerPlatform* d, char* out, size_t* length) {
|
||||
|
|
|
@ -65,6 +65,7 @@ static bool _checkWatchpoints(struct SM83Debugger* debugger, uint16_t address, s
|
|||
info->type.wp.watchType = watchpoint->type;
|
||||
info->type.wp.accessType = type;
|
||||
info->pointId = watchpoint->id;
|
||||
info->target = TableLookup(&debugger->d.p->pointOwner, watchpoint->id);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue