summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--binaryninjaapi.h22
-rw-r--r--binaryninjacore.h18
-rw-r--r--mainthread.cpp82
-rw-r--r--python/__init__.py72
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()