From 101b889d324e0b071eca2c8d4af00347514db184 Mon Sep 17 00:00:00 2001 From: Rihi <19492038+rihi@users.noreply.github.com> Date: Thu, 7 Nov 2024 15:42:25 +0100 Subject: [PATCH] Run disassembling and matcher loading only once per binary instead of per function (#438) --- decompiler/frontend/binaryninja/frontend.py | 4 ++-- decompiler/frontend/binaryninja/tagging.py | 21 +++++++++++++-------- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/decompiler/frontend/binaryninja/frontend.py b/decompiler/frontend/binaryninja/frontend.py index dd0b9ebe5..3a158e3b1 100644 --- a/decompiler/frontend/binaryninja/frontend.py +++ b/decompiler/frontend/binaryninja/frontend.py @@ -39,6 +39,7 @@ class BinaryninjaFrontend(Frontend): def __init__(self, bv: BinaryView): """Create a new binaryninja view with the given path.""" self._bv = bv if type(bv) == BinaryView else bv.getCurrentFunction().view + self._tagging = CompilerIdiomsTagging(self._bv) @classmethod def from_path(cls, path: str, options: Options): @@ -70,8 +71,7 @@ def lift(self, task: DecompilerTask): task.function_return_type = lifter.lift(function.return_type) task.function_parameters = [lifter.lift(param_type) for param_type in function.type.parameters] - tagging = CompilerIdiomsTagging(self._bv, function.start, task.options) - tagging.run() + self._tagging.run(function, task.options) task.cfg = parser.parse(function) task.complex_types = parser.complex_types diff --git a/decompiler/frontend/binaryninja/tagging.py b/decompiler/frontend/binaryninja/tagging.py index 50c2e261a..a008a462b 100644 --- a/decompiler/frontend/binaryninja/tagging.py +++ b/decompiler/frontend/binaryninja/tagging.py @@ -1,6 +1,8 @@ import logging +import binaryninja.function from binaryninja import BinaryView +from compiler_idioms.disassembly.smda_disassembly import SMDADisassembly from compiler_idioms.matcher import Matcher from decompiler.util.options import Options @@ -11,23 +13,26 @@ class CompilerIdiomsTagging: TAG_SYMBOL = "⚙" TAG_PREFIX = "compiler_idiom: " - def __init__(self, binary_view: BinaryView, start: int, options: Options): + def __init__(self, binary_view: BinaryView): self._bv = binary_view - self._function_start = start - self._enabled = options.getboolean("compiler-idioms-tagging.enabled", fallback=True) - self._debug_submodules = options.getboolean("logging.debug-submodules") + self._disassembly = SMDADisassembly(self._bv.file.filename) + self._matcher = Matcher() - def run(self): + def run(self, function: binaryninja.function.Function, options: Options): """ Matches idioms in the function (disassembly) currently being decompiled. For each found match creates a tag that contains info for original computation reconstruction. """ - if not self._enabled: + enabled = options.getboolean("compiler-idioms-tagging.enabled", fallback=True) + debug_submodules = options.getboolean("logging.debug-submodules") + + if not enabled: return try: - matches = Matcher().find_idioms_in_function(self._bv.file.filename, self._function_start) + instructions = self._disassembly.get_smda_function_at(function.start) + matches = self._matcher._match_single_function(instructions) except Exception as e: - if self._debug_submodules: + if debug_submodules: raise RuntimeError(e) logging.warning("Compiler idioms matching failed, continue without compiler idioms.") return