capa icon indicating copy to clipboard operation
capa copied to clipboard

use monitor().isCancelled() to control Ghidra execution

Open mike-hunhoff opened this issue 2 years ago • 3 comments

Calls to monitor().isCancelled() can be used to stop execution if a user chooses to cancel a script run. This is especially important for long runs. Let's use monitor().isCancelled() where it makes sense to ensure a good UX.

mike-hunhoff avatar Aug 16 '23 21:08 mike-hunhoff

Also, monitor().setProgress().

mike-hunhoff avatar Aug 17 '23 19:08 mike-hunhoff

some strategies:

  1. we could pass callbacks to find_capabilities and friends that are invoked e.g. after each function is matched. this way the callback could check monitor().isCancelled() upon each loop and raise an exception if necessary. likewise with setProgress().
  2. we could check isCancelled() from within Extractor.get_function_features() which we can assume is invoked once per function. we could raise an exception if Ghidra wants to exit. this strategy would not be appropriate for updating progress, though.
  3. what else?

(1) seems like the more robust design, though it will take a little work to thread this through. it'll also pollute the function signatures a bit, though we can provide default, empty callbacks so most callers don't have to do anything.

this infrastructure would also be used by the IDA extractor. because there are multiple extractors that need this functionality, it seems reasonable to investigate and implement.

williballenthin avatar Aug 23 '23 08:08 williballenthin


@dataclass
class CapaAnalysisCallbacks:
    on_analyze_function: Callable[...]


def find_capabilities(..., callbacks):
    ...
    for function in extractor.get_functions():
        callbacks.on_analyze_function(function)
        ...


def main(...):
    ...
    if is_ghidra:
        def on_ghidra_analyze_function(function_handle, index, total):
            if monitor.isCancelled():
                raise SystemExit(...)
            monitor.setProgress(index, total)
        callbacks = CapaAnalysisCallbacks(on_analyze_function=on_ghidra_analyze_function)
        find_capabilities(..., callbacks)

williballenthin avatar Aug 23 '23 08:08 williballenthin