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

angr-management support for the decompilation inlining #1246

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
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
2 changes: 2 additions & 0 deletions angrmanagement/ui/views/code_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ def decomp() -> None:
options=self._options.option_and_values,
optimization_passes=self._options.selected_passes,
peephole_optimizations=self._options.selected_peephole_opts,
inline_functions=self._options.selected_inlines,
vars_must_struct=self.vars_must_struct,
on_finish=decomp_ready,
blocking=True,
Expand Down Expand Up @@ -340,6 +341,7 @@ def _on_new_function(
self.decompile(focus=focus, focus_addr=focus_addr, flavor=flavor)
self._last_function = self._function.am_obj

self._options.reload()
console_view = self.workspace.view_manager.first_view_in_category("console")
if console_view is not None:
console_view.set_current_function(self._function.am_obj)
Expand Down
38 changes: 38 additions & 0 deletions angrmanagement/ui/widgets/qdecomp_options.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ class OptionType:
OPTION = 1
OPTIMIZATION_PASS = 2
PEEPHOLE_OPTIMIZATION = 3
INLINED_FUNCTION = 3


class QDecompilationOption(QTreeWidgetItem):
Expand Down Expand Up @@ -70,6 +71,13 @@ def state(self):
return bool(self.checkState(0) == Qt.CheckState.Checked)


class FunctionInlineOption:
def __init__(self, func):
self.NAME = func.name
self.function = func
self.DESCRIPTION = f"Inline the {self.NAME} function during decompilation."


class QDecompilationOptions(QWidget):
"""
The widget for selecting values for decompilation options. Will synchronize its status back to its parent (passed
Expand Down Expand Up @@ -98,6 +106,7 @@ def __init__(self, code_view, instance: Instance) -> None:
self._qoptions = []
self._qoptipasses = []
self._qpeephole_opts = []
self._qinlines = []

self._init_widgets()

Expand Down Expand Up @@ -149,6 +158,14 @@ def selected_peephole_opts(self):
selected.append(item.option)
return selected

@property
def selected_inlines(self):
selected = []
for item in self._qinlines:
if item.state:
selected.append(item.option.function)
return selected

@property
def option_and_values(self):
return [(item.option, item.state) for item in self._qoptions]
Expand Down Expand Up @@ -201,11 +218,13 @@ def _reload_options(self, reset_values: bool = False) -> None:
vals_options = dict(self.option_and_values)
vals_peephole = self.selected_peephole_opts
vals_passes = self.selected_passes
vals_inlines = set(self.selected_inlines)

self._treewidget.clear()
self._qoptions.clear()
self._qoptipasses.clear()
self._qpeephole_opts.clear()
self._qinlines.clear()

categories = {}

Expand Down Expand Up @@ -239,6 +258,25 @@ def _reload_options(self, reset_values: bool = False) -> None:
w = QDecompilationOption(po_category, opt_, OptionType.PEEPHOLE_OPTIMIZATION, enabled=enabled)
self._qpeephole_opts.append(w)

inlining_category = QTreeWidgetItem(self._treewidget, ["Inlined Functions"])
categories["inlining_opts"] = inlining_category
if not self._instance.project.am_none:
for function in self._instance.project.kb.functions.values():
if function.is_plt or function.is_simprocedure:
continue
enabled = False if reset_values else function in vals_inlines
w = QDecompilationOption(
inlining_category, FunctionInlineOption(function), OptionType.INLINED_FUNCTION, enabled=enabled
)
self._qinlines.append(w)

if not self._code_view.function.am_none:
reachable_functions = set(self._code_view.function.functions_reachable())
for w in self._qinlines:
w.setHidden(
w.option.function == self._code_view.function or w.option.function not in reachable_functions
)

# expand all
self._treewidget.expandAll()

Expand Down
Loading