From 220b786c9ccd74d7126aa8e3255d94c770f2510e Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sat, 15 Jul 2017 19:51:33 -0700 Subject: [PATCH] Core: Add symbol lookups from scripts --- include/mgba/core/scripting.h | 3 +++ src/core/scripting.c | 25 +++++++++++++++++ src/debugger/cli-debugger.c | 5 ++++ src/platform/python/_builder.py | 48 +++++++++++++++++++++++++-------- src/platform/python/engine.c | 7 +++++ src/platform/python/lib.h | 1 + 6 files changed, 78 insertions(+), 11 deletions(-) diff --git a/include/mgba/core/scripting.h b/include/mgba/core/scripting.h index ae1964186..ebf8f88cf 100644 --- a/include/mgba/core/scripting.h +++ b/include/mgba/core/scripting.h @@ -24,6 +24,7 @@ struct mScriptEngine { bool (*isScript)(struct mScriptEngine*, const char* name, struct VFile* vf); bool (*loadScript)(struct mScriptEngine*, const char* name, struct VFile* vf); void (*run)(struct mScriptEngine*); + bool (*lookupSymbol)(struct mScriptEngine*, const char* name, int32_t* out); #ifdef USE_DEBUGGERS void (*debuggerEntered)(struct mScriptEngine*, enum mDebuggerEntryReason, struct mDebuggerEntryInfo*); @@ -44,6 +45,8 @@ void mScriptBridgeDebuggerEntered(struct mScriptBridge*, enum mDebuggerEntryReas void mScriptBridgeRun(struct mScriptBridge*); bool mScriptBridgeLoadScript(struct mScriptBridge*, const char* name); +bool mScriptBridgeLookupSymbol(struct mScriptBridge*, const char* name, int32_t* out); + CXX_GUARD_END #endif diff --git a/src/core/scripting.c b/src/core/scripting.c index e176aa843..9a0ee7698 100644 --- a/src/core/scripting.c +++ b/src/core/scripting.c @@ -19,6 +19,12 @@ struct mScriptInfo { bool success; }; +struct mScriptSymbol { + const char* name; + int32_t* out; + bool success; +}; + static void _seDeinit(void* value) { struct mScriptEngine* se = value; se->deinit(se); @@ -33,6 +39,15 @@ static void _seTryLoad(const char* key, void* value, void* user) { } } +static void _seLookupSymbol(const char* key, void* value, void* user) { + UNUSED(key); + struct mScriptEngine* se = value; + struct mScriptSymbol* si = user; + if (!si->success) { + si->success = se->lookupSymbol(se, si->name, si->out); + } +} + static void _seRun(const char* key, void* value, void* user) { UNUSED(key); UNUSED(user); @@ -111,3 +126,13 @@ bool mScriptBridgeLoadScript(struct mScriptBridge* sb, const char* name) { vf->close(vf); return info.success; } + +bool mScriptBridgeLookupSymbol(struct mScriptBridge* sb, const char* name, int32_t* out) { + struct mScriptSymbol info = { + .name = name, + .out = out, + .success = false + }; + HashTableEnumerate(&sb->engines, _seLookupSymbol, &info); + return info.success; +} diff --git a/src/debugger/cli-debugger.c b/src/debugger/cli-debugger.c index 9eb9801bd..871143436 100644 --- a/src/debugger/cli-debugger.c +++ b/src/debugger/cli-debugger.c @@ -551,6 +551,11 @@ static void _lookupIdentifier(struct mDebugger* debugger, const char* name, stru struct CLIDebugger* cliDebugger = (struct CLIDebugger*) debugger; if (cliDebugger->system) { uint32_t value; +#ifdef ENABLE_SCRIPTING + if (debugger->bridge && mScriptBridgeLookupSymbol(debugger->bridge, name, &dv->intValue)) { + return; + } +#endif if (debugger->core->symbolTable && mDebuggerSymbolLookup(debugger->core->symbolTable, name, &dv->intValue, &dv->segmentValue)) { return; } diff --git a/src/platform/python/_builder.py b/src/platform/python/_builder.py index 79947021e..4aa2116c1 100644 --- a/src/platform/python/_builder.py +++ b/src/platform/python/_builder.py @@ -72,22 +72,26 @@ ffi.embedding_api('\n'.join(lines)) ffi.embedding_init_code(""" from mgba._pylib import ffi, lib - debugger = None + symbols = {} + globalSyms = { + 'symbols': symbols + } pendingCode = [] @ffi.def_extern() - def mPythonSetDebugger(_debugger): + def mPythonSetDebugger(debugger): from mgba.debugger import NativeDebugger, CLIDebugger - global debugger - if debugger and debugger._native == _debugger: + oldDebugger = globalSyms.get('debugger') + if oldDebugger and oldDebugger._native == debugger: return - if not _debugger: - debugger = None + if oldDebugger and not debugger: + del globalSyms['debugger'] return - if _debugger.type == lib.DEBUGGER_CLI: - debugger = CLIDebugger(_debugger) + if debugger.type == lib.DEBUGGER_CLI: + debugger = CLIDebugger(debugger) else: - debugger = NativeDebugger(_debugger) + debugger = NativeDebugger(debugger) + globalSyms['debugger'] = debugger @ffi.def_extern() def mPythonLoadScript(name, vf): @@ -106,18 +110,40 @@ ffi.embedding_init_code(""" def mPythonRunPending(): global pendingCode for code in pendingCode: - exec(code) + exec(code, globalSyms, {}) pendingCode = [] @ffi.def_extern() def mPythonDebuggerEntered(reason, info): - global debugger + debugger = globalSyms['debugger'] if not debugger: return if info == ffi.NULL: info = None for cb in debugger._cbs: cb(reason, info) + + @ffi.def_extern() + def mPythonLookupSymbol(name, outptr): + name = ffi.string(name).decode('utf-8') + if name not in symbols: + return False + sym = symbols[name] + val = None + try: + val = int(sym) + except: + try: + val = sym() + except: + pass + if val is None: + return False + try: + outptr[0] = ffi.cast('int32_t', val) + return True + except: + return False """) if __name__ == "__main__": diff --git a/src/platform/python/engine.c b/src/platform/python/engine.c index d91db2a8f..19fe76c0c 100644 --- a/src/platform/python/engine.c +++ b/src/platform/python/engine.c @@ -21,6 +21,7 @@ static void mPythonScriptEngineDeinit(struct mScriptEngine*); static bool mPythonScriptEngineIsScript(struct mScriptEngine*, const char* name, struct VFile* vf); static bool mPythonScriptEngineLoadScript(struct mScriptEngine*, const char* name, struct VFile* vf); static void mPythonScriptEngineRun(struct mScriptEngine*); +static bool mPythonScriptEngineLookupSymbol(struct mScriptEngine*, const char* name, int32_t* out); #ifdef USE_DEBUGGERS static void mPythonScriptDebuggerEntered(struct mScriptEngine*, enum mDebuggerEntryReason, struct mDebuggerEntryInfo*); @@ -39,6 +40,7 @@ struct mPythonScriptEngine* mPythonCreateScriptEngine(void) { engine->d.isScript = mPythonScriptEngineIsScript; engine->d.loadScript = mPythonScriptEngineLoadScript; engine->d.run = mPythonScriptEngineRun; + engine->d.lookupSymbol = mPythonScriptEngineLookupSymbol; #ifdef USE_DEBUGGERS engine->d.debuggerEntered = mPythonScriptDebuggerEntered; #endif @@ -89,6 +91,11 @@ void mPythonScriptEngineRun(struct mScriptEngine* se) { mPythonRunPending(); } +bool mPythonScriptEngineLookupSymbol(struct mScriptEngine* se, const char* name, int32_t* out) { + struct mPythonScriptEngine* engine = (struct mPythonScriptEngine*) se; + return mPythonLookupSymbol(name, out); +} + #ifdef USE_DEBUGGERS void mPythonScriptDebuggerEntered(struct mScriptEngine* se, enum mDebuggerEntryReason reason, struct mDebuggerEntryInfo* info) { struct mPythonScriptEngine* engine = (struct mPythonScriptEngine*) se; diff --git a/src/platform/python/lib.h b/src/platform/python/lib.h index d2b49d7e1..9c6046a51 100644 --- a/src/platform/python/lib.h +++ b/src/platform/python/lib.h @@ -4,6 +4,7 @@ struct VFile; extern bool mPythonLoadScript(const char*, struct VFile*); extern void mPythonRunPending(); +extern bool mPythonLookupSymbol(const char* name, int32_t* out); #ifdef USE_DEBUGGERS extern void mPythonSetDebugger(struct mDebugger*);