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/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 {
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
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) {
|
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.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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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);
|
||||||
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;
|
struct SM83Debugger* debugger = (struct SM83Debugger*) d;
|
||||||
mWatchpointListClear(list);
|
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) {
|
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.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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue