Scripting: Expose info table to breakpoint/watchpoint callbacks (closes #3369)
This commit is contained in:
parent
d55ee872e3
commit
72ee6f9840
@ -769,7 +769,7 @@ static int64_t _addCallbackToBreakpoint(struct mScriptDebugger* debugger, struct
|
|||||||
return cbid;
|
return cbid;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _runCallbacks(struct mScriptDebugger* debugger, struct mScriptBreakpoint* point) {
|
static void _runCallbacks(struct mScriptDebugger* debugger, struct mScriptBreakpoint* point, struct mScriptValue* info) {
|
||||||
struct TableIterator iter;
|
struct TableIterator iter;
|
||||||
if (!HashTableIteratorStart(&point->callbacks, &iter)) {
|
if (!HashTableIteratorStart(&point->callbacks, &iter)) {
|
||||||
return;
|
return;
|
||||||
@ -778,6 +778,7 @@ static void _runCallbacks(struct mScriptDebugger* debugger, struct mScriptBreakp
|
|||||||
struct mScriptValue* fn = HashTableIteratorGetValue(&point->callbacks, &iter);
|
struct mScriptValue* fn = HashTableIteratorGetValue(&point->callbacks, &iter);
|
||||||
struct mScriptFrame frame;
|
struct mScriptFrame frame;
|
||||||
mScriptFrameInit(&frame);
|
mScriptFrameInit(&frame);
|
||||||
|
mSCRIPT_PUSH(&frame.stack, WTABLE, info);
|
||||||
mScriptContextInvoke(debugger->p->context, fn, &frame);
|
mScriptContextInvoke(debugger->p->context, fn, &frame);
|
||||||
mScriptFrameDeinit(&frame);
|
mScriptFrameDeinit(&frame);
|
||||||
} while (HashTableIteratorNext(&point->callbacks, &iter));
|
} while (HashTableIteratorNext(&point->callbacks, &iter));
|
||||||
@ -826,7 +827,33 @@ static void _scriptDebuggerEntered(struct mDebuggerModule* debugger, enum mDebug
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_runCallbacks(scriptDebugger, point);
|
struct mScriptValue cbInfo = {
|
||||||
|
.refs = mSCRIPT_VALUE_UNREF,
|
||||||
|
.flags = 0,
|
||||||
|
.type = mSCRIPT_TYPE_MS_TABLE,
|
||||||
|
};
|
||||||
|
cbInfo.type->alloc(&cbInfo);
|
||||||
|
|
||||||
|
// TODO: Intern strings
|
||||||
|
mScriptTableInsert(&cbInfo, mScriptStringCreateFromASCII("address"), mScriptValueCreateFromUInt(info->address));
|
||||||
|
if (info->width > 0) {
|
||||||
|
mScriptTableInsert(&cbInfo, mScriptStringCreateFromASCII("width"), mScriptValueCreateFromSInt(info->width));
|
||||||
|
}
|
||||||
|
if (info->segment >= 0) {
|
||||||
|
mScriptTableInsert(&cbInfo, mScriptStringCreateFromASCII("segment"), mScriptValueCreateFromSInt(info->segment));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reason == DEBUGGER_ENTER_WATCHPOINT) {
|
||||||
|
mScriptTableInsert(&cbInfo, mScriptStringCreateFromASCII("oldValue"), mScriptValueCreateFromSInt(info->type.wp.oldValue));
|
||||||
|
if (info->type.wp.accessType != WATCHPOINT_READ) {
|
||||||
|
mScriptTableInsert(&cbInfo, mScriptStringCreateFromASCII("newValue"), mScriptValueCreateFromSInt(info->type.wp.newValue));
|
||||||
|
}
|
||||||
|
mScriptTableInsert(&cbInfo, mScriptStringCreateFromASCII("accessType"), mScriptValueCreateFromSInt(info->type.wp.accessType));
|
||||||
|
}
|
||||||
|
|
||||||
|
_runCallbacks(scriptDebugger, point, &cbInfo);
|
||||||
|
|
||||||
|
cbInfo.type->free(&cbInfo);
|
||||||
debugger->isPaused = false;
|
debugger->isPaused = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -365,8 +365,10 @@ M_TEST_DEFINE(basicBreakpointGBA) {
|
|||||||
|
|
||||||
TEST_PROGRAM(
|
TEST_PROGRAM(
|
||||||
"hit = 0\n"
|
"hit = 0\n"
|
||||||
"function bkpt()\n"
|
"address = nil\n"
|
||||||
|
"function bkpt(info)\n"
|
||||||
" hit = hit + 1\n"
|
" hit = hit + 1\n"
|
||||||
|
" address = info.address\n"
|
||||||
"end"
|
"end"
|
||||||
);
|
);
|
||||||
TEST_PROGRAM("cbid = emu:setBreakpoint(bkpt, 0x020000C4)");
|
TEST_PROGRAM("cbid = emu:setBreakpoint(bkpt, 0x020000C4)");
|
||||||
@ -379,6 +381,7 @@ M_TEST_DEFINE(basicBreakpointGBA) {
|
|||||||
|
|
||||||
assert_int_equal(debugger.state, DEBUGGER_RUNNING);
|
assert_int_equal(debugger.state, DEBUGGER_RUNNING);
|
||||||
TEST_PROGRAM("assert(hit >= 1)");
|
TEST_PROGRAM("assert(hit >= 1)");
|
||||||
|
TEST_PROGRAM("assert(address == 0x020000C4)");
|
||||||
|
|
||||||
mScriptContextDeinit(&context);
|
mScriptContextDeinit(&context);
|
||||||
TEARDOWN_CORE;
|
TEARDOWN_CORE;
|
||||||
@ -404,8 +407,10 @@ M_TEST_DEFINE(basicBreakpointGB) {
|
|||||||
|
|
||||||
TEST_PROGRAM(
|
TEST_PROGRAM(
|
||||||
"hit = 0\n"
|
"hit = 0\n"
|
||||||
"function bkpt()\n"
|
"address = nil\n"
|
||||||
|
"function bkpt(info)\n"
|
||||||
" hit = hit + 1\n"
|
" hit = hit + 1\n"
|
||||||
|
" address = info.address\n"
|
||||||
"end"
|
"end"
|
||||||
);
|
);
|
||||||
TEST_PROGRAM("cbid = emu:setBreakpoint(bkpt, 0xF0)");
|
TEST_PROGRAM("cbid = emu:setBreakpoint(bkpt, 0xF0)");
|
||||||
@ -418,6 +423,7 @@ M_TEST_DEFINE(basicBreakpointGB) {
|
|||||||
|
|
||||||
assert_int_equal(debugger.state, DEBUGGER_RUNNING);
|
assert_int_equal(debugger.state, DEBUGGER_RUNNING);
|
||||||
TEST_PROGRAM("assert(hit >= 1)");
|
TEST_PROGRAM("assert(hit >= 1)");
|
||||||
|
TEST_PROGRAM("assert(address == 0xF0)");
|
||||||
|
|
||||||
mScriptContextDeinit(&context);
|
mScriptContextDeinit(&context);
|
||||||
TEARDOWN_CORE;
|
TEARDOWN_CORE;
|
||||||
@ -441,11 +447,22 @@ M_TEST_DEFINE(multipleBreakpoint) {
|
|||||||
|
|
||||||
TEST_PROGRAM(
|
TEST_PROGRAM(
|
||||||
"hit = 0\n"
|
"hit = 0\n"
|
||||||
"function bkpt1()\n"
|
"address = nil\n"
|
||||||
|
"function bkpt1(info)\n"
|
||||||
" hit = hit + 1\n"
|
" hit = hit + 1\n"
|
||||||
|
" if address then\n"
|
||||||
|
" address = (address + info.address) / 2\n"
|
||||||
|
" else\n"
|
||||||
|
" address = info.address\n"
|
||||||
|
" end\n"
|
||||||
"end\n"
|
"end\n"
|
||||||
"function bkpt2()\n"
|
"function bkpt2(info)\n"
|
||||||
" hit = hit + 100\n"
|
" hit = hit + 100\n"
|
||||||
|
" if address then\n"
|
||||||
|
" address = (address + info.address) / 2\n"
|
||||||
|
" else\n"
|
||||||
|
" address = info.address\n"
|
||||||
|
" end\n"
|
||||||
"end"
|
"end"
|
||||||
);
|
);
|
||||||
#ifdef M_CORE_GBA
|
#ifdef M_CORE_GBA
|
||||||
@ -465,6 +482,13 @@ M_TEST_DEFINE(multipleBreakpoint) {
|
|||||||
|
|
||||||
assert_int_equal(debugger.state, DEBUGGER_RUNNING);
|
assert_int_equal(debugger.state, DEBUGGER_RUNNING);
|
||||||
TEST_PROGRAM("assert(hit >= 101)");
|
TEST_PROGRAM("assert(hit >= 101)");
|
||||||
|
#ifdef M_CORE_GBA
|
||||||
|
TEST_PROGRAM("assert(address >= 0x020000C4)");
|
||||||
|
TEST_PROGRAM("assert(address <= 0x020000C8)");
|
||||||
|
#else
|
||||||
|
TEST_PROGRAM("assert(address >= 0xF0)");
|
||||||
|
TEST_PROGRAM("assert(address <= 0xF1)");
|
||||||
|
#endif
|
||||||
|
|
||||||
mScriptContextDeinit(&context);
|
mScriptContextDeinit(&context);
|
||||||
TEARDOWN_CORE;
|
TEARDOWN_CORE;
|
||||||
@ -479,13 +503,28 @@ M_TEST_DEFINE(basicWatchpoint) {
|
|||||||
core->reset(core);
|
core->reset(core);
|
||||||
mScriptContextAttachCore(&context, core);
|
mScriptContextAttachCore(&context, core);
|
||||||
|
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < 4; ++i) {
|
||||||
|
core->busWrite8(core, RAM_BASE + i, i + 1);
|
||||||
|
}
|
||||||
|
|
||||||
mDebuggerInit(&debugger);
|
mDebuggerInit(&debugger);
|
||||||
mDebuggerAttach(&debugger, core);
|
mDebuggerAttach(&debugger, core);
|
||||||
|
|
||||||
TEST_PROGRAM(
|
TEST_PROGRAM(
|
||||||
"hit = 0\n"
|
"hit = 0\n"
|
||||||
"function bkpt()\n"
|
"address = nil\n"
|
||||||
|
"width = nil\n"
|
||||||
|
"oldValue = nil\n"
|
||||||
|
"newValue = nil\n"
|
||||||
|
"accessType = nil\n"
|
||||||
|
"function bkpt(info)\n"
|
||||||
" hit = hit + 1\n"
|
" hit = hit + 1\n"
|
||||||
|
" address = info.address\n"
|
||||||
|
" width = info.width\n"
|
||||||
|
" oldValue = info.oldValue\n"
|
||||||
|
" newValue = info.newValue\n"
|
||||||
|
" accessType = info.accessType\n"
|
||||||
"end"
|
"end"
|
||||||
);
|
);
|
||||||
struct mScriptValue base = mSCRIPT_MAKE_S32(RAM_BASE);
|
struct mScriptValue base = mSCRIPT_MAKE_S32(RAM_BASE);
|
||||||
@ -499,7 +538,13 @@ M_TEST_DEFINE(basicWatchpoint) {
|
|||||||
uint8_t value;
|
uint8_t value;
|
||||||
|
|
||||||
// Read
|
// Read
|
||||||
TEST_PROGRAM("hit = 0");
|
TEST_PROGRAM(
|
||||||
|
"hit = 0\n"
|
||||||
|
"address = nil\n"
|
||||||
|
"width = nil\n"
|
||||||
|
"oldValue = nil\n"
|
||||||
|
"newValue = nil\n"
|
||||||
|
"accessType = nil\n");
|
||||||
value = core->rawRead8(core, RAM_BASE, -1);
|
value = core->rawRead8(core, RAM_BASE, -1);
|
||||||
TEST_PROGRAM("assert(hit == 0)");
|
TEST_PROGRAM("assert(hit == 0)");
|
||||||
core->busRead8(core, RAM_BASE);
|
core->busRead8(core, RAM_BASE);
|
||||||
@ -508,31 +553,71 @@ M_TEST_DEFINE(basicWatchpoint) {
|
|||||||
TEST_PROGRAM("assert(hit == 1)");
|
TEST_PROGRAM("assert(hit == 1)");
|
||||||
core->busWrite8(core, RAM_BASE, ~value);
|
core->busWrite8(core, RAM_BASE, ~value);
|
||||||
TEST_PROGRAM("assert(hit == 1)");
|
TEST_PROGRAM("assert(hit == 1)");
|
||||||
|
TEST_PROGRAM("assert(address == base)");
|
||||||
|
TEST_PROGRAM("assert(width == 1)");
|
||||||
|
TEST_PROGRAM("assert(oldValue == 1)");
|
||||||
|
TEST_PROGRAM("assert(newValue == nil)");
|
||||||
|
TEST_PROGRAM("assert(accessType == C.WATCHPOINT_TYPE.READ)");
|
||||||
|
|
||||||
// Write
|
// Write
|
||||||
TEST_PROGRAM("hit = 0");
|
TEST_PROGRAM(
|
||||||
|
"hit = 0\n"
|
||||||
|
"address = nil\n"
|
||||||
|
"width = nil\n"
|
||||||
|
"oldValue = nil\n"
|
||||||
|
"newValue = nil\n"
|
||||||
|
"accessType = nil\n");
|
||||||
value = core->rawRead8(core, RAM_BASE + 1, -1);
|
value = core->rawRead8(core, RAM_BASE + 1, -1);
|
||||||
TEST_PROGRAM("assert(hit == 0)");
|
TEST_PROGRAM("assert(hit == 0)");
|
||||||
core->busRead8(core, RAM_BASE + 1);
|
core->busRead8(core, RAM_BASE + 1);
|
||||||
TEST_PROGRAM("assert(hit == 0)");
|
TEST_PROGRAM("assert(hit == 0)");
|
||||||
core->busWrite8(core, RAM_BASE + 1, value);
|
core->busWrite8(core, RAM_BASE + 1, value);
|
||||||
TEST_PROGRAM("assert(hit == 1)");
|
TEST_PROGRAM("assert(hit == 1)");
|
||||||
|
TEST_PROGRAM("assert(oldValue == 2)");
|
||||||
|
TEST_PROGRAM("assert(newValue == 2)");
|
||||||
core->busWrite8(core, RAM_BASE + 1, ~value);
|
core->busWrite8(core, RAM_BASE + 1, ~value);
|
||||||
TEST_PROGRAM("assert(hit == 2)");
|
TEST_PROGRAM("assert(hit == 2)");
|
||||||
|
TEST_PROGRAM("assert(address == base + 1)");
|
||||||
|
TEST_PROGRAM("assert(width == 1)");
|
||||||
|
TEST_PROGRAM("assert(oldValue == 2)");
|
||||||
|
TEST_PROGRAM("assert(newValue == -3)");
|
||||||
|
TEST_PROGRAM("assert(accessType == C.WATCHPOINT_TYPE.WRITE)");
|
||||||
|
|
||||||
// RW
|
// RW
|
||||||
TEST_PROGRAM("hit = 0");
|
TEST_PROGRAM(
|
||||||
|
"hit = 0\n"
|
||||||
|
"address = nil\n"
|
||||||
|
"width = nil\n"
|
||||||
|
"oldValue = nil\n"
|
||||||
|
"newValue = nil\n"
|
||||||
|
"accessType = nil\n");
|
||||||
value = core->rawRead8(core, RAM_BASE + 2, -1);
|
value = core->rawRead8(core, RAM_BASE + 2, -1);
|
||||||
TEST_PROGRAM("assert(hit == 0)");
|
TEST_PROGRAM("assert(hit == 0)");
|
||||||
core->busRead8(core, RAM_BASE + 2);
|
core->busRead8(core, RAM_BASE + 2);
|
||||||
|
TEST_PROGRAM("assert(accessType == C.WATCHPOINT_TYPE.READ)");
|
||||||
TEST_PROGRAM("assert(hit == 1)");
|
TEST_PROGRAM("assert(hit == 1)");
|
||||||
|
TEST_PROGRAM("assert(oldValue == 3)");
|
||||||
|
TEST_PROGRAM("assert(newValue == nil)");
|
||||||
core->busWrite8(core, RAM_BASE + 2, value);
|
core->busWrite8(core, RAM_BASE + 2, value);
|
||||||
TEST_PROGRAM("assert(hit == 2)");
|
TEST_PROGRAM("assert(hit == 2)");
|
||||||
|
TEST_PROGRAM("assert(oldValue == 3)");
|
||||||
|
TEST_PROGRAM("assert(newValue == 3)");
|
||||||
core->busWrite8(core, RAM_BASE + 2, ~value);
|
core->busWrite8(core, RAM_BASE + 2, ~value);
|
||||||
TEST_PROGRAM("assert(hit == 3)");
|
TEST_PROGRAM("assert(hit == 3)");
|
||||||
|
TEST_PROGRAM("assert(address == base + 2)");
|
||||||
|
TEST_PROGRAM("assert(width == 1)");
|
||||||
|
TEST_PROGRAM("assert(oldValue == 3)");
|
||||||
|
TEST_PROGRAM("assert(newValue == -4)");
|
||||||
|
TEST_PROGRAM("assert(accessType == C.WATCHPOINT_TYPE.WRITE)");
|
||||||
|
|
||||||
// Change
|
// Change
|
||||||
TEST_PROGRAM("hit = 0");
|
TEST_PROGRAM(
|
||||||
|
"hit = 0\n"
|
||||||
|
"address = nil\n"
|
||||||
|
"width = nil\n"
|
||||||
|
"oldValue = nil\n"
|
||||||
|
"newValue = nil\n"
|
||||||
|
"accessType = nil\n");
|
||||||
value = core->rawRead8(core, RAM_BASE + 3, -1);
|
value = core->rawRead8(core, RAM_BASE + 3, -1);
|
||||||
TEST_PROGRAM("assert(hit == 0)");
|
TEST_PROGRAM("assert(hit == 0)");
|
||||||
core->busRead8(core, RAM_BASE + 3);
|
core->busRead8(core, RAM_BASE + 3);
|
||||||
@ -541,6 +626,11 @@ M_TEST_DEFINE(basicWatchpoint) {
|
|||||||
TEST_PROGRAM("assert(hit == 0)");
|
TEST_PROGRAM("assert(hit == 0)");
|
||||||
core->busWrite8(core, RAM_BASE + 3, ~value);
|
core->busWrite8(core, RAM_BASE + 3, ~value);
|
||||||
TEST_PROGRAM("assert(hit == 1)");
|
TEST_PROGRAM("assert(hit == 1)");
|
||||||
|
TEST_PROGRAM("assert(address == base + 3)");
|
||||||
|
TEST_PROGRAM("assert(width == 1)");
|
||||||
|
TEST_PROGRAM("assert(oldValue == 4)");
|
||||||
|
TEST_PROGRAM("assert(newValue == -5)");
|
||||||
|
TEST_PROGRAM("assert(accessType == C.WATCHPOINT_TYPE.WRITE)");
|
||||||
|
|
||||||
mScriptContextDeinit(&context);
|
mScriptContextDeinit(&context);
|
||||||
TEARDOWN_CORE;
|
TEARDOWN_CORE;
|
||||||
@ -728,8 +818,10 @@ M_TEST_DEFINE(rangeWatchpoint) {
|
|||||||
|
|
||||||
TEST_PROGRAM(
|
TEST_PROGRAM(
|
||||||
"hit = 0\n"
|
"hit = 0\n"
|
||||||
"function bkpt()\n"
|
"address = nil\n"
|
||||||
|
"function bkpt(info)\n"
|
||||||
" hit = hit + 1\n"
|
" hit = hit + 1\n"
|
||||||
|
" address = info.address\n"
|
||||||
"end"
|
"end"
|
||||||
);
|
);
|
||||||
struct mScriptValue base = mSCRIPT_MAKE_S32(RAM_BASE);
|
struct mScriptValue base = mSCRIPT_MAKE_S32(RAM_BASE);
|
||||||
@ -741,10 +833,13 @@ M_TEST_DEFINE(rangeWatchpoint) {
|
|||||||
TEST_PROGRAM("assert(hit == 0)");
|
TEST_PROGRAM("assert(hit == 0)");
|
||||||
core->busRead8(core, RAM_BASE);
|
core->busRead8(core, RAM_BASE);
|
||||||
TEST_PROGRAM("assert(hit == 1)");
|
TEST_PROGRAM("assert(hit == 1)");
|
||||||
|
TEST_PROGRAM("assert(address == base)");
|
||||||
core->busRead8(core, RAM_BASE + 1);
|
core->busRead8(core, RAM_BASE + 1);
|
||||||
TEST_PROGRAM("assert(hit == 3)");
|
TEST_PROGRAM("assert(hit == 3)");
|
||||||
|
TEST_PROGRAM("assert(address == base + 1)");
|
||||||
core->busRead8(core, RAM_BASE + 2);
|
core->busRead8(core, RAM_BASE + 2);
|
||||||
TEST_PROGRAM("assert(hit == 4)");
|
TEST_PROGRAM("assert(hit == 4)");
|
||||||
|
TEST_PROGRAM("assert(address == base + 2)");
|
||||||
|
|
||||||
mScriptContextDeinit(&context);
|
mScriptContextDeinit(&context);
|
||||||
TEARDOWN_CORE;
|
TEARDOWN_CORE;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user