Skip to content

Commit

Permalink
Feat: Add an API for start callbacks (#134)
Browse files Browse the repository at this point in the history
  • Loading branch information
mahaloz authored Nov 7, 2024
1 parent 650cf12 commit 48536ee
Show file tree
Hide file tree
Showing 5 changed files with 28 additions and 8 deletions.
6 changes: 4 additions & 2 deletions examples/change_watcher_plugin/bs_change_watcher/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,13 @@ def create_plugin(*args, **kwargs):
FunctionHeader, StackVariable, Enum, Struct, GlobalVariable, Comment, Context
)

decompiler_started_event_callbacks = [lambda *x, **y: print(f"[BSChangeWatcher] Started with plugin version {__version__}")]
decompiler_opened_callbacks = [lambda *x, **y: print(f"[BSChangeWatcher] Started with plugin version {__version__}")]
decompiler_closed_callbacks = [lambda *x, **y: print(f"[BSChangeWatcher] Goodbye!")]
deci = DecompilerInterface.discover(
plugin_name="ArtifactChangeWatcher",
init_plugin=True,
decompiler_started_callbacks=decompiler_started_event_callbacks,
decompiler_opened_callbacks=decompiler_opened_callbacks,
decompiler_closed_callbacks=decompiler_closed_callbacks,
# passing the flag below forces click recording to start on decompiler startup
# force_click_recording = True,
gui_init_args=args,
Expand Down
2 changes: 1 addition & 1 deletion libbs/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
__version__ = "2.4.0"
__version__ = "2.5.0"


import logging
Expand Down
25 changes: 21 additions & 4 deletions libbs/api/decompiler_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@ def __init__(
# [artifact_class] = list(callback_func)
artifact_change_callbacks: Optional[Dict[Type[Artifact], List[Callable]]] = None,
undo_event_callbacks: Optional[List[Callable]] = None,
decompiler_started_callbacks: Optional[List[Callable]] = None,
decompiler_opened_callbacks: Optional[List[Callable]] = None,
decompiler_closed_callbacks: Optional[List[Callable]] = None,
thread_artifact_callbacks: bool = True,
force_click_recording: bool = False,
):
Expand Down Expand Up @@ -92,7 +93,8 @@ def __init__(
# callback functions, keyed by Artifact class
self.artifact_change_callbacks = artifact_change_callbacks or defaultdict(list)
self.undo_event_callbacks = undo_event_callbacks or []
self.decompiler_started_callbacks = decompiler_started_callbacks or []
self.decompiler_opened_callbacks = decompiler_opened_callbacks or []
self.decompiler_closed_callbacks = decompiler_closed_callbacks or []
self._thread_artifact_callbacks = thread_artifact_callbacks

# artifact dict aliases:
Expand Down Expand Up @@ -637,8 +639,23 @@ def _set_function_header(self, fheader: FunctionHeader, **kwargs) -> bool:
# lift it ONCE inside this function. Each one will return the lifted form, for easier overriding.
#

def decompiler_started_event(self, **kwargs):
for callback_func in self.decompiler_started_callbacks:
def decompiler_opened_event(self, **kwargs):
"""
This function is called when the decompiler platform this interface is running on is opened for the first time.
In the presence of a decompiler with multiple tabs, this function will still only be called once.
"""
for callback_func in self.decompiler_opened_callbacks:
if self._thread_artifact_callbacks:
threading.Thread(target=callback_func, kwargs=kwargs, daemon=True).start()
else:
callback_func(**kwargs)

def decompiler_closed_event(self, **kwargs):
"""
This function is called when the decompiler platform this interface is running on is closing/closed.
In the presence of a decompiler with multiple tabs, this function will still only be called once.
"""
for callback_func in self.decompiler_closed_callbacks:
if self._thread_artifact_callbacks:
threading.Thread(target=callback_func, kwargs=kwargs, daemon=True).start()
else:
Expand Down
1 change: 1 addition & 0 deletions libbs/decompilers/ida/compat.py
Original file line number Diff line number Diff line change
Expand Up @@ -1732,6 +1732,7 @@ def run(self, arg):
pass

def term(self):
self.interface.decompiler_closed_event()
del self.interface

cls = GenericIDAPlugin
Expand Down
2 changes: 1 addition & 1 deletion libbs/decompilers/ida/interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ def _init_gui_hooks(self):
hook.hook()

def _init_gui_plugin(self, *args, **kwargs):
self.decompiler_started_event()
self.decompiler_opened_event()
plugin_cls_name = self._plugin_name + "_cls"
IDAPluginCls = compat.generate_generic_ida_plugic_cls(cls_name=plugin_cls_name)
return IDAPluginCls(*args, name=self._plugin_name, interface=self, **kwargs)
Expand Down

0 comments on commit 48536ee

Please sign in to comment.