diff options
| -rw-r--r-- | binaryninjaapi.h | 22 | ||||
| -rw-r--r-- | binaryninjacore.h | 18 | ||||
| -rw-r--r-- | mainthread.cpp | 82 | ||||
| -rw-r--r-- | python/__init__.py | 72 |
4 files changed, 194 insertions, 0 deletions
diff --git a/binaryninjaapi.h b/binaryninjaapi.h index c8d54c18..d3234dcc 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -273,6 +273,8 @@ namespace BinaryNinja class Platform; class Type; class DataBuffer; + class MainThreadAction; + class MainThreadActionHandler; /*! Logs to the error console with the given BNLogLevel. @@ -365,6 +367,10 @@ namespace BinaryNinja Type** outType, std::vector<std::string>& outVarName); + void RegisterMainThread(MainThreadActionHandler* handler); + Ref<MainThreadAction> ExecuteOnMainThread(const std::function<void()>& action); + void ExecuteOnMainThreadAndWait(const std::function<void()>& action); + class DataBuffer { BNDataBuffer* m_buffer; @@ -2153,4 +2159,20 @@ namespace BinaryNinja CoreScriptingProvider(BNScriptingProvider* provider); virtual Ref<ScriptingInstance> CreateNewInstance() override; }; + + class MainThreadAction: public CoreRefCountObject<BNMainThreadAction, + BNNewMainThreadActionReference, BNFreeMainThreadAction> + { + public: + MainThreadAction(BNMainThreadAction* action); + void Execute(); + bool IsDone() const; + void Wait(); + }; + + class MainThreadActionHandler + { + public: + virtual void AddMainThreadAction(MainThreadAction* action) = 0; + }; } diff --git a/binaryninjacore.h b/binaryninjacore.h index 61ecb235..2ba6f7e6 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -101,6 +101,7 @@ extern "C" struct BNDisassemblySettings; struct BNScriptingProvider; struct BNScriptingInstance; + struct BNMainThreadAction; //! Console log levels enum BNLogLevel @@ -1006,6 +1007,12 @@ extern "C" void (*inputReadyStateChanged)(void* ctxt, BNScriptingProviderInputReadyState state); }; + struct BNMainThreadCallbacks + { + void* context; + void (*addAction)(void* ctxt, BNMainThreadAction* action); + }; + BINARYNINJACOREAPI char* BNAllocString(const char* contents); BINARYNINJACOREAPI void BNFreeString(char* str); @@ -1922,6 +1929,17 @@ extern "C" BINARYNINJACOREAPI void BNSetScriptingInstanceCurrentAddress(BNScriptingInstance* instance, uint64_t addr); BINARYNINJACOREAPI void BNSetScriptingInstanceCurrentSelection(BNScriptingInstance* instance, uint64_t begin, uint64_t end); + + // Main thread actions + BINARYNINJACOREAPI void BNRegisterMainThread(BNMainThreadCallbacks* callbacks); + BINARYNINJACOREAPI BNMainThreadAction* BNNewMainThreadActionReference(BNMainThreadAction* action); + BINARYNINJACOREAPI void BNFreeMainThreadAction(BNMainThreadAction* action); + BINARYNINJACOREAPI void BNExecuteMainThreadAction(BNMainThreadAction* action); + BINARYNINJACOREAPI bool BNIsMainThreadActionDone(BNMainThreadAction* action); + BINARYNINJACOREAPI void BNWaitForMainThreadAction(BNMainThreadAction* action); + BINARYNINJACOREAPI BNMainThreadAction* BNExecuteOnMainThread(void* ctxt, void (*func)(void* ctxt)); + BINARYNINJACOREAPI void BNExecuteOnMainThreadAndWait(void* ctxt, void (*func)(void* ctxt)); + #ifdef __cplusplus } #endif diff --git a/mainthread.cpp b/mainthread.cpp new file mode 100644 index 00000000..8e9d9d50 --- /dev/null +++ b/mainthread.cpp @@ -0,0 +1,82 @@ +#include "binaryninjaapi.h" + +using namespace BinaryNinja; +using namespace std; + + +struct MainThreadActionContext +{ + function<void()> action; +}; + + +MainThreadAction::MainThreadAction(BNMainThreadAction* action) +{ + m_object = action; +} + + +void MainThreadAction::Execute() +{ + BNExecuteMainThreadAction(m_object); +} + + +bool MainThreadAction::IsDone() const +{ + return BNIsMainThreadActionDone(m_object); +} + + +void MainThreadAction::Wait() +{ + BNWaitForMainThreadAction(m_object); +} + + +static void AddMainThreadAction(void* ctxt, BNMainThreadAction* action) +{ + MainThreadActionHandler* handler = (MainThreadActionHandler*)ctxt; + handler->AddMainThreadAction(new MainThreadAction(action)); +} + + +void BinaryNinja::RegisterMainThread(MainThreadActionHandler* handler) +{ + BNMainThreadCallbacks cb; + cb.context = handler; + cb.addAction = AddMainThreadAction; + BNRegisterMainThread(&cb); +} + + +static void ExecuteAction(void* ctxt) +{ + MainThreadActionContext* action = (MainThreadActionContext*)ctxt; + action->action(); + delete action; +} + + +Ref<MainThreadAction> BinaryNinja::ExecuteOnMainThread(const function<void()>& action) +{ + MainThreadActionContext* ctxt = new MainThreadActionContext; + ctxt->action = action; + BNMainThreadAction* obj = BNExecuteOnMainThread(ctxt, ExecuteAction); + return obj ? new MainThreadAction(obj) : nullptr; +} + + +static void ExecuteActionLocal(void* ctxt) +{ + MainThreadActionContext* action = (MainThreadActionContext*)ctxt; + action->action(); +} + + +void BinaryNinja::ExecuteOnMainThreadAndWait(const function<void()>& action) +{ + MainThreadActionContext ctxt; + ctxt.action = action; + BNExecuteOnMainThreadAndWait(&ctxt, ExecuteActionLocal); +} diff --git a/python/__init__.py b/python/__init__.py index 3b0ce739..b88c5beb 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -9480,6 +9480,7 @@ class PythonScriptingInstance(ScriptingInstance): self.locals["current_function"] = self.active_func self.locals["current_basic_block"] = self.active_block self.locals["current_address"] = self.active_addr + self.locals["here"] = self.active_addr self.locals["current_selection"] = (self.active_selection_begin, self.active_selection_end) self.interpreter.runsource(code) @@ -9558,6 +9559,44 @@ class PythonScriptingProvider(ScriptingProvider): name = "Python" instance_class = PythonScriptingInstance +class MainThreadAction(object): + def __init__(self, handle): + self.handle = handle + + def __del__(self): + core.BNFreeMainThreadAction(self.handle) + + def execute(self): + core.BNExecuteMainThreadAction(self.handle) + + @property + def done(self): + return core.BNIsMainThreadActionDone(self.handle) + + def wait(self): + core.BNWaitForMainThreadAction(self.handle) + +class MainThreadActionHandler(object): + _main_thread = None + + def __init__(self): + self._cb = core.BNMainThreadCallbacks() + self._cb.context = 0 + self._cb.addAction = self._cb.addAction.__class__(self._add_action) + + def register(self): + self.__class__._main_thread = self + core.BNRegisterMainThread(self._cb) + + def _add_action(self, ctxt, action): + try: + self.add_action(MainThreadAction(action)) + except: + log_error(traceback.format_exc()) + + def add_action(self, action): + pass + def LLIL_TEMP(n): return n | 0x80000000 @@ -9820,6 +9859,39 @@ def redirect_output_to_log(): global _output_to_log _output_to_log = True +class _MainThreadActionContext: + _actions = [] + + def __init__(self, func): + self.func = func + self.interpreter = None + if "value" in dir(PythonScriptingInstance._interpreter): + self.interpreter = PythonScriptingInstance._interpreter.value + self.__class__._actions.append(self) + self.callback = ctypes.CFUNCTYPE(None, ctypes.c_void_p)(lambda ctxt: self.execute()) + + def execute(self): + old_interpreter = None + if "value" in dir(PythonScriptingInstance._interpreter): + old_interpreter = PythonScriptingInstance._interpreter.value + PythonScriptingInstance._interpreter.value = self.interpreter + try: + self.func() + finally: + PythonScriptingInstance._interpreter.value = old_interpreter + self.__class__._actions.remove(self) + +def execute_on_main_thread(func): + action = _MainThreadActionContext(func) + obj = core.BNExecuteOnMainThread(0, action.callback) + if obj: + return MainThreadAction(obj) + return None + +def execute_on_main_thread_and_wait(func): + action = _MainThreadActionContext(func) + core.BNExecuteOnMainThreadAndWait(0, action.callback) + bundled_plugin_path = core.BNGetBundledPluginDirectory() user_plugin_path = core.BNGetUserPluginDirectory() |
