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/cpu.h>
#include <mgba/core/log.h> #include <mgba/core/log.h>
#include <mgba-util/table.h>
#include <mgba-util/vector.h> #include <mgba-util/vector.h>
#include <mgba/internal/debugger/stack-trace.h> #include <mgba/internal/debugger/stack-trace.h>
@ -114,11 +115,11 @@ struct mDebuggerPlatform {
void (*checkBreakpoints)(struct mDebuggerPlatform*); void (*checkBreakpoints)(struct mDebuggerPlatform*);
bool (*clearBreakpoint)(struct mDebuggerPlatform*, ssize_t id); bool (*clearBreakpoint)(struct mDebuggerPlatform*, ssize_t id);
ssize_t (*setBreakpoint)(struct mDebuggerPlatform*, const struct mBreakpoint*); ssize_t (*setBreakpoint)(struct mDebuggerPlatform*, struct mDebuggerModule*, const struct mBreakpoint*);
void (*listBreakpoints)(struct mDebuggerPlatform*, struct mBreakpointList*); void (*listBreakpoints)(struct mDebuggerPlatform*, struct mDebuggerModule*, struct mBreakpointList*);
ssize_t (*setWatchpoint)(struct mDebuggerPlatform*, const struct mWatchpoint*); ssize_t (*setWatchpoint)(struct mDebuggerPlatform*, struct mDebuggerModule*, const struct mWatchpoint*);
void (*listWatchpoints)(struct mDebuggerPlatform*, struct mWatchpointList*); void (*listWatchpoints)(struct mDebuggerPlatform*, struct mDebuggerModule*, struct mWatchpointList*);
void (*trace)(struct mDebuggerPlatform*, char* out, size_t* length); void (*trace)(struct mDebuggerPlatform*, char* out, size_t* length);
@ -138,6 +139,7 @@ struct mDebugger {
struct mStackTrace stackTrace; struct mStackTrace stackTrace;
struct mDebuggerModuleList modules; struct mDebuggerModuleList modules;
struct Table pointOwner;
}; };
struct mDebuggerModule { struct mDebuggerModule {

View File

@ -45,7 +45,7 @@ struct ARMDebugger {
}; };
struct mDebuggerPlatform* ARMDebuggerPlatformCreate(void); 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 CXX_GUARD_END

View File

@ -159,7 +159,7 @@ static void _setBreakpointARM(struct CLIDebugger* debugger, struct CLIDebugVecto
return; return;
} }
uint32_t address = dv->intValue; 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) { if (id > 0) {
debugger->backend->printf(debugger->backend, INFO_BREAKPOINT_ADDED, id); debugger->backend->printf(debugger->backend, INFO_BREAKPOINT_ADDED, id);
} }
@ -172,7 +172,7 @@ static void _setBreakpointThumb(struct CLIDebugger* debugger, struct CLIDebugVec
return; return;
} }
uint32_t address = dv->intValue; 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) { if (id > 0) {
debugger->backend->printf(debugger->backend, INFO_BREAKPOINT_ADDED, id); debugger->backend->printf(debugger->backend, INFO_BREAKPOINT_ADDED, id);
} }

View File

@ -187,16 +187,18 @@ static struct ARMDebugBreakpoint* _lookupBreakpoint(struct ARMDebugBreakpointLis
return 0; return 0;
} }
static void _destroyBreakpoint(struct ARMDebugBreakpoint* breakpoint) { static void _destroyBreakpoint(struct mDebugger* debugger, struct ARMDebugBreakpoint* breakpoint) {
if (breakpoint->d.condition) { if (breakpoint->d.condition) {
parseFree(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) { if (watchpoint->condition) {
parseFree(watchpoint->condition); parseFree(watchpoint->condition);
} }
TableRemove(&debugger->pointOwner, watchpoint->id);
} }
static void ARMDebuggerCheckBreakpoints(struct mDebuggerPlatform* d) { static void ARMDebuggerCheckBreakpoints(struct mDebuggerPlatform* d) {
@ -220,7 +222,8 @@ static void ARMDebuggerCheckBreakpoints(struct mDebuggerPlatform* d) {
struct mDebuggerEntryInfo info = { struct mDebuggerEntryInfo info = {
.address = breakpoint->d.address, .address = breakpoint->d.address,
.type.bp.breakType = BREAKPOINT_HARDWARE, .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); 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 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 bool ARMDebuggerClearBreakpoint(struct mDebuggerPlatform*, ssize_t id);
static void ARMDebuggerListBreakpoints(struct mDebuggerPlatform*, struct mBreakpointList*); static void ARMDebuggerListBreakpoints(struct mDebuggerPlatform*, struct mDebuggerModule* owner, struct mBreakpointList*);
static ssize_t ARMDebuggerSetWatchpoint(struct mDebuggerPlatform*, const struct mWatchpoint*); static ssize_t ARMDebuggerSetWatchpoint(struct mDebuggerPlatform*, struct mDebuggerModule* owner, const struct mWatchpoint*);
static void ARMDebuggerListWatchpoints(struct mDebuggerPlatform*, struct mWatchpointList*); static void ARMDebuggerListWatchpoints(struct mDebuggerPlatform*, struct mDebuggerModule* owner, struct mWatchpointList*);
static void ARMDebuggerCheckBreakpoints(struct mDebuggerPlatform*); static void ARMDebuggerCheckBreakpoints(struct mDebuggerPlatform*);
static bool ARMDebuggerHasBreakpoints(struct mDebuggerPlatform*); static bool ARMDebuggerHasBreakpoints(struct mDebuggerPlatform*);
static void ARMDebuggerTrace(struct mDebuggerPlatform*, char* out, size_t* length); static void ARMDebuggerTrace(struct mDebuggerPlatform*, char* out, size_t* length);
@ -291,12 +294,12 @@ void ARMDebuggerDeinit(struct mDebuggerPlatform* platform) {
size_t i; size_t i;
for (i = 0; i < ARMDebugBreakpointListSize(&debugger->breakpoints); ++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); ARMDebugBreakpointListDeinit(&debugger->breakpoints);
for (i = 0; i < mWatchpointListSize(&debugger->watchpoints); ++i) { for (i = 0; i < mWatchpointListSize(&debugger->watchpoints); ++i) {
_destroyWatchpoint(mWatchpointListGetPointer(&debugger->watchpoints, i)); _destroyWatchpoint(debugger->d.p, mWatchpointListGetPointer(&debugger->watchpoints, i));
} }
ARMDebugBreakpointListDeinit(&debugger->swBreakpoints); ARMDebugBreakpointListDeinit(&debugger->swBreakpoints);
mWatchpointListDeinit(&debugger->watchpoints); 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; struct ARMDebugger* debugger = (struct ARMDebugger*) d;
uint32_t opcode; uint32_t opcode;
if (!debugger->setSoftwareBreakpoint || !debugger->setSoftwareBreakpoint(debugger, address, mode, &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->d.type = BREAKPOINT_SOFTWARE;
breakpoint->sw.opcode = opcode; breakpoint->sw.opcode = opcode;
breakpoint->sw.mode = mode; breakpoint->sw.mode = mode;
TableInsert(&debugger->d.p->pointOwner, id, owner);
return id; 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 ARMDebugger* debugger = (struct ARMDebugger*) d;
struct ARMDebugBreakpoint* breakpoint = ARMDebugBreakpointListAppend(&debugger->breakpoints); struct ARMDebugBreakpoint* breakpoint = ARMDebugBreakpointListAppend(&debugger->breakpoints);
ssize_t id = debugger->nextId; ssize_t id = debugger->nextId;
@ -354,6 +358,7 @@ static ssize_t ARMDebuggerSetBreakpoint(struct mDebuggerPlatform* d, const struc
breakpoint->d = *info; breakpoint->d = *info;
breakpoint->d.address &= ~1; // Clear Thumb bit since it's not part of a valid address breakpoint->d.address &= ~1; // Clear Thumb bit since it's not part of a valid address
breakpoint->d.id = id; breakpoint->d.id = id;
TableInsert(&debugger->d.p->pointOwner, id, owner);
if (info->type == BREAKPOINT_SOFTWARE) { if (info->type == BREAKPOINT_SOFTWARE) {
// TODO // TODO
abort(); abort();
@ -368,7 +373,7 @@ static bool ARMDebuggerClearBreakpoint(struct mDebuggerPlatform* d, ssize_t id)
struct ARMDebugBreakpointList* breakpoints = &debugger->breakpoints; struct ARMDebugBreakpointList* breakpoints = &debugger->breakpoints;
for (i = 0; i < ARMDebugBreakpointListSize(breakpoints); ++i) { for (i = 0; i < ARMDebugBreakpointListSize(breakpoints); ++i) {
if (ARMDebugBreakpointListGetPointer(breakpoints, i)->d.id == id) { if (ARMDebugBreakpointListGetPointer(breakpoints, i)->d.id == id) {
_destroyBreakpoint(ARMDebugBreakpointListGetPointer(breakpoints, i)); _destroyBreakpoint(debugger->d.p, ARMDebugBreakpointListGetPointer(breakpoints, i));
ARMDebugBreakpointListShift(breakpoints, i, 1); ARMDebugBreakpointListShift(breakpoints, i, 1);
return true; return true;
} }
@ -388,7 +393,7 @@ static bool ARMDebuggerClearBreakpoint(struct mDebuggerPlatform* d, ssize_t id)
struct mWatchpointList* watchpoints = &debugger->watchpoints; struct mWatchpointList* watchpoints = &debugger->watchpoints;
for (i = 0; i < mWatchpointListSize(watchpoints); ++i) { for (i = 0; i < mWatchpointListSize(watchpoints); ++i) {
if (mWatchpointListGetPointer(watchpoints, i)->id == id) { if (mWatchpointListGetPointer(watchpoints, i)->id == id) {
_destroyWatchpoint(mWatchpointListGetPointer(watchpoints, i)); _destroyWatchpoint(debugger->d.p, mWatchpointListGetPointer(watchpoints, i));
mWatchpointListShift(watchpoints, i, 1); mWatchpointListShift(watchpoints, i, 1);
if (!mWatchpointListSize(&debugger->watchpoints)) { if (!mWatchpointListSize(&debugger->watchpoints)) {
ARMDebuggerRemoveMemoryShim(debugger); ARMDebuggerRemoveMemoryShim(debugger);
@ -399,19 +404,29 @@ static bool ARMDebuggerClearBreakpoint(struct mDebuggerPlatform* d, ssize_t id)
return false; 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; struct ARMDebugger* debugger = (struct ARMDebugger*) d;
mBreakpointListClear(list); mBreakpointListClear(list);
size_t i, s; 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* hw = NULL;
struct ARMDebugBreakpoint* sw = NULL; struct ARMDebugBreakpoint* sw = NULL;
if (i < ARMDebugBreakpointListSize(&debugger->breakpoints)) { if (i < ARMDebugBreakpointListSize(&debugger->breakpoints)) {
hw = ARMDebugBreakpointListGetPointer(&debugger->breakpoints, i); hw = ARMDebugBreakpointListGetPointer(&debugger->breakpoints, i);
if (owner && TableLookup(&debugger->d.p->pointOwner, hw->d.id) != owner) {
hw = NULL;
}
} }
if (s < ARMDebugBreakpointListSize(&debugger->swBreakpoints)) { if (s < ARMDebugBreakpointListSize(&debugger->swBreakpoints)) {
sw = ARMDebugBreakpointListGetPointer(&debugger->swBreakpoints, s); 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); struct mBreakpoint* b = mBreakpointListAppend(list);
if (hw && sw) { if (hw && sw) {
if (hw->d.id < sw->d.id) { if (hw->d.id < sw->d.id) {
@ -427,8 +442,6 @@ static void ARMDebuggerListBreakpoints(struct mDebuggerPlatform* d, struct mBrea
} else if (sw) { } else if (sw) {
*b = sw->d; *b = sw->d;
++s; ++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; 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; struct ARMDebugger* debugger = (struct ARMDebugger*) d;
if (!mWatchpointListSize(&debugger->watchpoints)) { if (!mWatchpointListSize(&debugger->watchpoints)) {
ARMDebuggerInstallMemoryShim(debugger); ARMDebuggerInstallMemoryShim(debugger);
@ -448,13 +461,25 @@ static ssize_t ARMDebuggerSetWatchpoint(struct mDebuggerPlatform* d, const struc
++debugger->nextId; ++debugger->nextId;
*watchpoint = *info; *watchpoint = *info;
watchpoint->id = id; watchpoint->id = id;
TableInsert(&debugger->d.p->pointOwner, id, owner);
return id; 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; struct ARMDebugger* debugger = (struct ARMDebugger*) d;
mWatchpointListClear(list); mWatchpointListClear(list);
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); mWatchpointListCopy(list, &debugger->watchpoints);
}
} }
static void ARMDebuggerTrace(struct mDebuggerPlatform* d, char* out, size_t* length) { 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.watchType = watchpoint->type;
info->type.wp.accessType = type; info->type.wp.accessType = type;
info->pointId = watchpoint->id; info->pointId = watchpoint->id;
info->target = TableLookup(&debugger->d.p->pointOwner, watchpoint->id);
return true; return true;
} }
} }

View File

@ -648,7 +648,7 @@ static void _setBreakpoint(struct CLIDebugger* debugger, struct CLIDebugVector*
return; 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) { if (id > 0) {
debugger->backend->printf(debugger->backend, INFO_BREAKPOINT_ADDED, id); debugger->backend->printf(debugger->backend, INFO_BREAKPOINT_ADDED, id);
} }
@ -678,7 +678,7 @@ static void _setWatchpoint(struct CLIDebugger* debugger, struct CLIDebugVector*
return; 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) { if (id > 0) {
debugger->backend->printf(debugger->backend, INFO_WATCHPOINT_ADDED, id); debugger->backend->printf(debugger->backend, INFO_WATCHPOINT_ADDED, id);
} }
@ -720,7 +720,7 @@ static void _setRangeWatchpoint(struct CLIDebugger* debugger, struct CLIDebugVec
return; 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) { if (id > 0) {
debugger->backend->printf(debugger->backend, INFO_WATCHPOINT_ADDED, id); debugger->backend->printf(debugger->backend, INFO_WATCHPOINT_ADDED, id);
} }
@ -771,7 +771,7 @@ static void _listBreakpoints(struct CLIDebugger* debugger, struct CLIDebugVector
UNUSED(dv); UNUSED(dv);
struct mBreakpointList breakpoints; struct mBreakpointList breakpoints;
mBreakpointListInit(&breakpoints, 0); 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; size_t i;
for (i = 0; i < mBreakpointListSize(&breakpoints); ++i) { for (i = 0; i < mBreakpointListSize(&breakpoints); ++i) {
struct mBreakpoint* breakpoint = mBreakpointListGetPointer(&breakpoints, i); struct mBreakpoint* breakpoint = mBreakpointListGetPointer(&breakpoints, i);
@ -788,7 +788,7 @@ static void _listWatchpoints(struct CLIDebugger* debugger, struct CLIDebugVector
UNUSED(dv); UNUSED(dv);
struct mWatchpointList watchpoints; struct mWatchpointList watchpoints;
mWatchpointListInit(&watchpoints, 0); 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; size_t i;
for (i = 0; i < mWatchpointListSize(&watchpoints); ++i) { for (i = 0; i < mWatchpointListSize(&watchpoints); ++i) {
struct mWatchpoint* watchpoint = mWatchpointListGetPointer(&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) { void mDebuggerInit(struct mDebugger* debugger) {
memset(debugger, 0, sizeof(*debugger)); memset(debugger, 0, sizeof(*debugger));
mDebuggerModuleListInit(&debugger->modules, 4); mDebuggerModuleListInit(&debugger->modules, 4);
TableInit(&debugger->pointOwner, 0, NULL);
} }
void mDebuggerDeinit(struct mDebugger* debugger) { void mDebuggerDeinit(struct mDebugger* debugger) {
mDebuggerModuleListDeinit(&debugger->modules); mDebuggerModuleListDeinit(&debugger->modules);
TableDeinit(&debugger->pointOwner);
} }
void mDebuggerAttach(struct mDebugger* debugger, struct mCore* core) { 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]) { switch (message[0]) {
case '0': case '0':
case '1': 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; break;
case '2': case '2':
watchpoint.type = stub->watchpointsBehavior == GDB_WATCHPOINT_OVERRIDE_LOGIC_ANY_WRITE ? WATCHPOINT_WRITE : WATCHPOINT_WRITE_CHANGE; 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; break;
case '3': case '3':
watchpoint.type = WATCHPOINT_READ; 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; break;
case '4': case '4':
watchpoint.type = WATCHPOINT_RW; 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; break;
default: default:
stub->outgoing[0] = '\0'; stub->outgoing[0] = '\0';
@ -631,7 +631,7 @@ static void _clearBreakpoint(struct GDBStub* stub, const char* message) {
case '0': case '0':
case '1': case '1':
mBreakpointListInit(&breakpoints, 0); 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) { for (index = 0; index < mBreakpointListSize(&breakpoints); ++index) {
if (mBreakpointListGetPointer(&breakpoints, index)->address != address) { if (mBreakpointListGetPointer(&breakpoints, index)->address != address) {
continue; continue;
@ -644,7 +644,7 @@ static void _clearBreakpoint(struct GDBStub* stub, const char* message) {
case '3': case '3':
case '4': case '4':
mWatchpointListInit(&watchpoints, 0); 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) { for (index = 0; index < mWatchpointListSize(&watchpoints); ++index) {
struct mWatchpoint* watchpoint = mWatchpointListGetPointer(&watchpoints, index); struct mWatchpoint* watchpoint = mWatchpointListGetPointer(&watchpoints, index);
if (address >= watchpoint->minAddress && address < watchpoint->maxAddress) { if (address >= watchpoint->minAddress && address < watchpoint->maxAddress) {

View File

@ -25,16 +25,18 @@ static struct mBreakpoint* _lookupBreakpoint(struct mBreakpointList* breakpoints
return NULL; return NULL;
} }
static void _destroyBreakpoint(struct mBreakpoint* breakpoint) { static void _destroyBreakpoint(struct mDebugger* debugger, struct mBreakpoint* breakpoint) {
if (breakpoint->condition) { if (breakpoint->condition) {
parseFree(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) { if (watchpoint->condition) {
parseFree(watchpoint->condition); parseFree(watchpoint->condition);
} }
TableRemove(&debugger->pointOwner, watchpoint->id);
} }
static void SM83DebuggerCheckBreakpoints(struct mDebuggerPlatform* d) { static void SM83DebuggerCheckBreakpoints(struct mDebuggerPlatform* d) {
@ -52,7 +54,8 @@ static void SM83DebuggerCheckBreakpoints(struct mDebuggerPlatform* d) {
} }
struct mDebuggerEntryInfo info = { struct mDebuggerEntryInfo info = {
.address = breakpoint->address, .address = breakpoint->address,
.pointId = breakpoint->id .pointId = breakpoint->id,
.target = TableLookup(&d->p->pointOwner, breakpoint->id)
}; };
mDebuggerEnter(d->p, DEBUGGER_ENTER_BREAKPOINT, &info); 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 void SM83DebuggerEnter(struct mDebuggerPlatform* d, enum mDebuggerEntryReason reason, struct mDebuggerEntryInfo* info);
static ssize_t SM83DebuggerSetBreakpoint(struct mDebuggerPlatform*, const struct mBreakpoint*); static ssize_t SM83DebuggerSetBreakpoint(struct mDebuggerPlatform*, struct mDebuggerModule* owner, const struct mBreakpoint*);
static void SM83DebuggerListBreakpoints(struct mDebuggerPlatform*, struct mBreakpointList*); static void SM83DebuggerListBreakpoints(struct mDebuggerPlatform*, struct mDebuggerModule* owner, struct mBreakpointList*);
static bool SM83DebuggerClearBreakpoint(struct mDebuggerPlatform*, ssize_t id); static bool SM83DebuggerClearBreakpoint(struct mDebuggerPlatform*, ssize_t id);
static ssize_t SM83DebuggerSetWatchpoint(struct mDebuggerPlatform*, const struct mWatchpoint*); static ssize_t SM83DebuggerSetWatchpoint(struct mDebuggerPlatform*, struct mDebuggerModule* owner, const struct mWatchpoint*);
static void SM83DebuggerListWatchpoints(struct mDebuggerPlatform*, struct mWatchpointList*); static void SM83DebuggerListWatchpoints(struct mDebuggerPlatform*, struct mDebuggerModule* owner, struct mWatchpointList*);
static void SM83DebuggerCheckBreakpoints(struct mDebuggerPlatform*); static void SM83DebuggerCheckBreakpoints(struct mDebuggerPlatform*);
static bool SM83DebuggerHasBreakpoints(struct mDebuggerPlatform*); static bool SM83DebuggerHasBreakpoints(struct mDebuggerPlatform*);
static void SM83DebuggerTrace(struct mDebuggerPlatform*, char* out, size_t* length); 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; struct SM83Debugger* debugger = (struct SM83Debugger*) platform;
size_t i; size_t i;
for (i = 0; i < mBreakpointListSize(&debugger->breakpoints); ++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); mBreakpointListDeinit(&debugger->breakpoints);
for (i = 0; i < mWatchpointListSize(&debugger->watchpoints); ++i) { for (i = 0; i < mWatchpointListSize(&debugger->watchpoints); ++i) {
_destroyWatchpoint(mWatchpointListGetPointer(&debugger->watchpoints, i)); _destroyWatchpoint(debugger->d.p, mWatchpointListGetPointer(&debugger->watchpoints, i));
} }
mWatchpointListDeinit(&debugger->watchpoints); mWatchpointListDeinit(&debugger->watchpoints);
} }
@ -122,14 +125,14 @@ static void SM83DebuggerEnter(struct mDebuggerPlatform* platform, enum mDebugger
cpu->nextEvent = cpu->cycles; 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 SM83Debugger* debugger = (struct SM83Debugger*) d;
struct mBreakpoint* breakpoint = mBreakpointListAppend(&debugger->breakpoints); struct mBreakpoint* breakpoint = mBreakpointListAppend(&debugger->breakpoints);
*breakpoint = *info; *breakpoint = *info;
breakpoint->id = debugger->nextId; breakpoint->id = debugger->nextId;
TableInsert(&debugger->d.p->pointOwner, breakpoint->id, owner);
++debugger->nextId; ++debugger->nextId;
return breakpoint->id; return breakpoint->id;
} }
static bool SM83DebuggerClearBreakpoint(struct mDebuggerPlatform* d, ssize_t 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) { for (i = 0; i < mBreakpointListSize(breakpoints); ++i) {
struct mBreakpoint* breakpoint = mBreakpointListGetPointer(breakpoints, i); struct mBreakpoint* breakpoint = mBreakpointListGetPointer(breakpoints, i);
if (breakpoint->id == id) { if (breakpoint->id == id) {
_destroyBreakpoint(breakpoint); _destroyBreakpoint(debugger->d.p, breakpoint);
mBreakpointListShift(breakpoints, i, 1); mBreakpointListShift(breakpoints, i, 1);
return true; return true;
} }
@ -150,7 +153,7 @@ static bool SM83DebuggerClearBreakpoint(struct mDebuggerPlatform* d, ssize_t id)
for (i = 0; i < mWatchpointListSize(watchpoints); ++i) { for (i = 0; i < mWatchpointListSize(watchpoints); ++i) {
struct mWatchpoint* watchpoint = mWatchpointListGetPointer(watchpoints, i); struct mWatchpoint* watchpoint = mWatchpointListGetPointer(watchpoints, i);
if (watchpoint->id == id) { if (watchpoint->id == id) {
_destroyWatchpoint(watchpoint); _destroyWatchpoint(debugger->d.p, watchpoint);
mWatchpointListShift(watchpoints, i, 1); mWatchpointListShift(watchpoints, i, 1);
if (!mWatchpointListSize(&debugger->watchpoints)) { if (!mWatchpointListSize(&debugger->watchpoints)) {
SM83DebuggerRemoveMemoryShim(debugger); SM83DebuggerRemoveMemoryShim(debugger);
@ -166,7 +169,7 @@ static bool SM83DebuggerHasBreakpoints(struct mDebuggerPlatform* d) {
return mBreakpointListSize(&debugger->breakpoints) || mWatchpointListSize(&debugger->watchpoints); 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; struct SM83Debugger* debugger = (struct SM83Debugger*) d;
if (!mWatchpointListSize(&debugger->watchpoints)) { if (!mWatchpointListSize(&debugger->watchpoints)) {
SM83DebuggerInstallMemoryShim(debugger); SM83DebuggerInstallMemoryShim(debugger);
@ -174,20 +177,43 @@ static ssize_t SM83DebuggerSetWatchpoint(struct mDebuggerPlatform* d, const stru
struct mWatchpoint* watchpoint = mWatchpointListAppend(&debugger->watchpoints); struct mWatchpoint* watchpoint = mWatchpointListAppend(&debugger->watchpoints);
*watchpoint = *info; *watchpoint = *info;
watchpoint->id = debugger->nextId; watchpoint->id = debugger->nextId;
TableInsert(&debugger->d.p->pointOwner, watchpoint->id, owner);
++debugger->nextId; ++debugger->nextId;
return watchpoint->id; 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; struct SM83Debugger* debugger = (struct SM83Debugger*) d;
mBreakpointListClear(list); mBreakpointListClear(list);
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); 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; struct SM83Debugger* debugger = (struct SM83Debugger*) d;
mWatchpointListClear(list); mWatchpointListClear(list);
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); mWatchpointListCopy(list, &debugger->watchpoints);
}
} }
static void SM83DebuggerTrace(struct mDebuggerPlatform* d, char* out, size_t* length) { 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.watchType = watchpoint->type;
info->type.wp.accessType = type; info->type.wp.accessType = type;
info->pointId = watchpoint->id; info->pointId = watchpoint->id;
info->target = TableLookup(&debugger->d.p->pointOwner, watchpoint->id);
return true; return true;
} }
} }