Debugger: Make created debug items, e.g. breakpoints, owned by modules

This commit is contained in:
Vicki Pfau 2022-12-11 22:08:41 -08:00
parent b21a6158f4
commit 8efb3fb5df
10 changed files with 113 additions and 56 deletions

View File

@ -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 {

View File

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

View File

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

View File

@ -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) {

View File

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

View File

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

View File

@ -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) {

View File

@ -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) {

View File

@ -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) {

View File

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