angr.analyses.decompiler.region_simplifiers.expr_folding

class angr.analyses.decompiler.region_simplifiers.expr_folding.LocationBase

Bases: object

class angr.analyses.decompiler.region_simplifiers.expr_folding.StatementLocation

Bases: LocationBase

Describes the location of a statement.

__init__(block_addr, block_idx, stmt_idx, phi_stmt=False)
Parameters:

phi_stmt (bool)

block_addr
block_idx
stmt_idx
phi_stmt
copy()
class angr.analyses.decompiler.region_simplifiers.expr_folding.ExpressionLocation

Bases: LocationBase

Describes the location of an expression.

__init__(block_addr, block_idx, stmt_idx, expr_idx, phi_stmt=False)
Parameters:

phi_stmt (bool)

block_addr
block_idx
stmt_idx
expr_idx
phi_stmt
statement_location()
Return type:

StatementLocation

class angr.analyses.decompiler.region_simplifiers.expr_folding.ConditionLocation

Bases: LocationBase

Describes the location of a condition.

__init__(cond_node_addr, case_idx=None)
Parameters:

case_idx (int | None)

node_addr
case_idx
class angr.analyses.decompiler.region_simplifiers.expr_folding.ConditionalBreakLocation

Bases: LocationBase

Describes the location of a conditional break.

__init__(node_addr)
node_addr
class angr.analyses.decompiler.region_simplifiers.expr_folding.LoopNodeFinder

Bases: SequenceWalker

Returns all loops in a given region.

__init__(node)
Parameters:

node (SequenceNode)

loop_nodes: list[LoopNode]
class angr.analyses.decompiler.region_simplifiers.expr_folding.MultiStatementExpressionAssignmentFinder

Bases: AILBlockRewriter

Process statements in MultiStatementExpression objects and find assignments.

__init__(stmt_handler)
class angr.analyses.decompiler.region_simplifiers.expr_folding.ExpressionUseFinder

Bases: AILBlockRewriter

Find where each variable is used.

Additionally, determine if the expression being walked has load expressions inside. Such expressions can only be safely folded if there are no Store statements between the expression defining location and its use sites. For example, we can only safely fold variable assignments that use Load() when there are no Store()s between the assignment and its use site. Otherwise, the loaded expression may get updated later by a Store() statement.

Here is a real AIL block:

v16 = ((int)v23->field_5) + 1 & 255;
v23->field_5 = ((char)(((int)v23->field_5) + 1 & 255));
v13 = printf("Recieved packet %d for connection with %d\n", v16, a0 & 255);

In this case, folding v16 into the last printf() expression would be incorrect, since v23->field_5 is updated by the second statement.

__init__()
uses: defaultdict[int, set[tuple[Expression, ExpressionLocation | None]]]
has_load
class angr.analyses.decompiler.region_simplifiers.expr_folding.ExpressionCounter

Bases: SequenceWalker

Find all expressions that are assigned once and only used once.

__init__(node)
assignments: defaultdict[Any, set[tuple]]
outerscope_uses: dict[int, set[tuple[Expression, LocationBase | None]]]
all_uses: dict[int, set[tuple[Expression, LocationBase | None]]]
class angr.analyses.decompiler.region_simplifiers.expr_folding.ExpressionSpotter

Bases: VVarUsesCollector

ExpressionSpotter collects uses of vvars and existence of Call expressions.

__init__()
has_calls: bool
has_loads: bool
class angr.analyses.decompiler.region_simplifiers.expr_folding.InterferenceChecker

Bases: SequenceWalker

Detect for every pair of definition (assignment) - use if there is anything that may interfere with the definition.

Interferences may be caused by:

  • another call

  • function return

  • store statements

  • load expressions

  • Condition and CascadingCondition nodes

__init__(assignments, uses, node)
Parameters:
interfered_assignments: set[int]
class angr.analyses.decompiler.region_simplifiers.expr_folding.ExpressionReplacer

Bases: AILBlockRewriter

__init__(assignments, uses)
Parameters:
class angr.analyses.decompiler.region_simplifiers.expr_folding.ExpressionFolder

Bases: SequenceWalker

__init__(assignments, uses, node)
Parameters:
class angr.analyses.decompiler.region_simplifiers.expr_folding.StoreStatementFinder

Bases: SequenceWalker

Determine if there are any Store statements between two given statements.

This class overrides _handle_Sequence() and _handle_MultiNode() to ensure they traverse nodes from top to bottom.

__init__(node, intervals)
Parameters:

intervals (Iterable[tuple[StatementLocation, LocationBase]])

interval_to_hasstore: dict[tuple[StatementLocation, StatementLocation], bool]
has_store(start, end)
Return type:

bool

Parameters: