Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Pipeline #446

Merged
merged 2 commits into from
Nov 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion decompiler/backend/codegenerator.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
from decompiler.backend.variabledeclarations import GlobalDeclarationGenerator, LocalDeclarationGenerator
from decompiler.task import DecompilerTask

FAIL_MESSAGE = "Decompilation Failed!\n"


class CodeGenerator:
"""Class in charge of emitting C-code from pseudo code."""
Expand Down Expand Up @@ -53,7 +55,8 @@ def generate_function(self, task: DecompilerTask) -> str:
@staticmethod
def generate_failure_message(task: DecompilerTask):
"""Returns the message to be shown for a failed task."""
msg = f"Failed to decompile {task.name}"
msg = FAIL_MESSAGE
msg += f"Failed to decompile {task.name}"
if origin := task.failure_origin: # checks if the string is empty (should never be None when this method is called)
msg += f" due to error during {origin}."
return msg
3 changes: 1 addition & 2 deletions decompiler/frontend/binaryninja/frontend.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,7 @@ def lift(self, task: DecompilerTask):
task.cfg = parser.parse(function)
task.complex_types = parser.complex_types
except Exception as e:
task.fail("Function lifting")
logging.exception(f"Failed to decompile {task.name}, error during function lifting")
task.fail("Function lifting", e)

if task.options.getboolean("pipeline.debug", fallback=False):
raise e
Expand Down
5 changes: 2 additions & 3 deletions decompiler/pipeline/pipeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from __future__ import annotations

from logging import debug, error, warning
from logging import debug, warning
from typing import List

from decompiler.pipeline.controlflowanalysis.restructuring import PatternIndependentRestructuring
Expand Down Expand Up @@ -108,8 +108,7 @@ def run(self, task: DecompilerTask):
if show_all or stage.name in showed_stages:
self._show_stage(task, f"After {stage.name}", print_ascii, show_in_tabs)
except Exception as e:
task.fail(origin=stage.name)
error(f"Failed to decompile {task.name}, error during stage {stage.name}: {e}")
task.fail(origin=stage.name, exception=e)
if debug_mode:
raise e
break
Expand Down
6 changes: 4 additions & 2 deletions decompiler/task.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
"""Module describing tasks to be handled by the decompiler pipleline."""

from dataclasses import dataclass, field
from typing import List
from logging import error
from typing import List, Optional

from decompiler.structures.ast.syntaxtree import AbstractSyntaxTree
from decompiler.structures.graphs.cfg import ControlFlowGraph
Expand Down Expand Up @@ -39,12 +40,13 @@ def graph(self):
def syntax_tree(self):
return self.ast

def fail(self, origin: str = ""):
def fail(self, origin: str = "", exception: Optional[Exception] = None):
"""Sets the task to be failed by setting the failure origin."""
if self.failure_origin is not None:
raise RuntimeError("Tried failing already failed task")

self._failure_origin = origin
error(f"Failed to decompile {self.name}, error during stage {origin}: {exception}")

@property
def failed(self) -> bool:
Expand Down
3 changes: 2 additions & 1 deletion tests/test_sample_binaries.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@
import subprocess

import pytest
from decompiler.backend.codegenerator import FAIL_MESSAGE


def test_sample(test_cases):
"""Test the decompiler with the given test case."""
sample, function_name = test_cases
output = subprocess.run(("python", "decompile.py", sample, function_name), check=True, capture_output=True).stdout.decode("utf-8")
assert "Failed to decompile due to error during " not in output
assert FAIL_MESSAGE not in output


def test_globals():
Expand Down
Loading