Thanks to visit codestin.com
Credit goes to github.com

Skip to content
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
1 change: 1 addition & 0 deletions angr/analyses/decompiler/clinic.py
Original file line number Diff line number Diff line change
Expand Up @@ -1816,6 +1816,7 @@ def _recover_and_link_variables(
self.function, # pylint:disable=unused-variable
fail_fast=self._fail_fast, # type:ignore
func_graph=ail_graph,
entry_node_addr=self.entry_node_addr,
kb=tmp_kb, # type:ignore
track_sp=False,
func_args=arg_list,
Expand Down
32 changes: 30 additions & 2 deletions angr/analyses/variable_recovery/variable_recovery_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
import logging
from collections import defaultdict

import networkx

import archinfo
import claripy
from claripy.annotation import Annotation
Expand Down Expand Up @@ -86,8 +88,18 @@ class VariableRecoveryBase(Analysis):
The base class for VariableRecovery and VariableRecoveryFast.
"""

def __init__(self, func, max_iterations, store_live_variables: bool, vvar_to_vvar: dict[int, int] | None = None):
def __init__(
self,
func,
max_iterations,
store_live_variables: bool,
vvar_to_vvar: dict[int, int] | None = None,
func_graph: networkx.DiGraph | None = None,
entry_node_addr: int | tuple[int, int | None] | None = None,
):
self.function = func
self.func_graph = func_graph
self.entry_node_addr = entry_node_addr
self.variable_manager = self.kb.variables

self._max_iterations = max_iterations
Expand Down Expand Up @@ -120,7 +132,23 @@ def get_variable_definitions(self, block_addr):

def initialize_dominance_frontiers(self):
# Computer the dominance frontier for each node in the graph
df = self.project.analyses.DominanceFrontier(self.function)
func_entry = None
if self.func_graph is not None:
entry_node_addr = self.entry_node_addr if self.entry_node_addr is not None else self.function.addr
assert entry_node_addr is not None
if isinstance(entry_node_addr, int):
func_entry = next(iter(node for node in self.func_graph if node.addr == entry_node_addr))
elif isinstance(entry_node_addr, tuple):
func_entry = next(
iter(
node
for node in self.func_graph
if node.addr == entry_node_addr[0] and node.idx == entry_node_addr[1]
)
)
else:
raise TypeError(f"Unsupported entry node address type: {type(entry_node_addr)}")
df = self.project.analyses.DominanceFrontier(self.function, func_graph=self.func_graph, entry=func_entry)
self._dominance_frontiers = defaultdict(set)
for b0, domfront in df.frontiers.items():
for d in domfront:
Expand Down
13 changes: 11 additions & 2 deletions angr/analyses/variable_recovery/variable_recovery_fast.py
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,7 @@ def __init__(
self,
func: Function | str | int,
func_graph: networkx.DiGraph | None = None,
entry_node_addr: int | tuple[int, int | None] | None = None,
max_iterations: int = 2,
low_priority=False,
track_sp=True,
Expand All @@ -259,10 +260,18 @@ def __init__(
function_graph_visitor = visitors.FunctionGraphVisitor(func, graph=func_graph)

# Make sure the function is not empty
if not func.block_addrs_set or func.startpoint is None:
if (not func.block_addrs_set or func.startpoint is None) and not func_graph:
raise AngrVariableRecoveryError(f"Function {func!r} is empty.")

VariableRecoveryBase.__init__(self, func, max_iterations, store_live_variables, vvar_to_vvar=vvar_to_vvar)
VariableRecoveryBase.__init__(
self,
func,
max_iterations,
store_live_variables,
vvar_to_vvar=vvar_to_vvar,
func_graph=func_graph_with_calls,
entry_node_addr=entry_node_addr,
)
ForwardAnalysis.__init__(
self, order_jobs=True, allow_merging=True, allow_widening=False, graph_visitor=function_graph_visitor
)
Expand Down
21 changes: 20 additions & 1 deletion angr/utils/graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -534,11 +534,30 @@ def _pd_link(self, v, w):

def _pd_eval(self, v):
assert self._ancestor is not None
assert self._semi is not None
assert self._label is not None

if self._ancestor[v.index] is None:
return v
self._pd_compress(v)

# pd_compress without recursion
queue = []
current = v
ancestor = self._ancestor[current.index]
greater_ancestor = self._ancestor[ancestor.index]
while greater_ancestor is not None:
queue.append(current)
current, ancestor = ancestor, greater_ancestor
greater_ancestor = self._ancestor[ancestor.index]

for vv in reversed(queue):
if (
self._semi[self._label[self._ancestor[vv.index].index].index].index
< self._semi[self._label[vv.index].index].index
):
self._label[vv.index] = self._label[self._ancestor[vv.index].index]
self._ancestor[vv.index] = self._ancestor[self._ancestor[vv.index].index]

return self._label[v.index]

def _pd_compress(self, v):
Expand Down