angr.analyses.decompiler.region_overlay

class angr.analyses.decompiler.region_overlay.OverlayManager

Bases: object

OverlayManager owns the single shared control-flow graph that all RegionOverlay objects are views of, plus the node-to-innermost-overlay ownership map.

All structural mutations of the shared graph must go through this class (usually via RegionOverlay methods) so that ownership, caches, and the undo log stay consistent.

__init__(graph, expose_loop_head_backedges=False)
Parameters:
  • graph (DiGraph)

  • expose_loop_head_backedges (bool)

graph
expose_loop_head_backedges
root
property version: int
owner_of(node)
Return type:

RegionOverlay | None

checkpoint()
Return type:

int

rollback(to)
Return type:

None

Parameters:

to (int)

commit(to)

Discard undo information past the given checkpoint. If the checkpoint is 0, stop recording entirely.

Return type:

None

Parameters:

to (int)

graph_add_edge(src, dst, **data)
Return type:

None

graph_remove_edge(src, dst)
Return type:

None

class angr.analyses.decompiler.region_overlay.RegionOverlay

Bases: object

A single-entry region marked over the shared graph held by an OverlayManager. The region tree is built out of RegionOverlay objects (RegionIdentifier emits them) and they are the only region type the decompiler uses.

Overlays form a tree (nested, never overlapping). An overlay’s members are either shared-graph nodes it owns directly or child overlays. The region graph and the region graph-with-successors are derived on demand from the shared graph by quotienting child overlays into single nodes; successors are likewise derived from edges that cross the region boundary, so they can never go stale.

Read-only API (head, graph, graph_with_successors, successors, cyclic, addr) mirrors the region container consumers expect; graph/graph_with_successors/successors are lazy zero-copy views.

Mutation verbs:

  • true structural changes (add_node, remove_node, add_edge, detach_edge, replace_nodes) pass through to the shared graph, so the effects are immediately visible to all enclosing regions;

  • hide_edge removes an edge from this overlay’s views only (the old “remove it from region graphs but keep the parent edge” pattern);

  • finalize(result_node) collapses a fully-structured region into a single node of its parent;

  • dissolve() merges an unsuccessfully-structured region back into its parent.

__init__(mgr, head, cyclic, cyclic_ancestor=False, parent=None)
Parameters:
head
cyclic
cyclic_ancestor
parent
children: list[RegionOverlay]
edge_marks: defaultdict[str, set[tuple[Any, Any]]]
replacement
property addr
property manager: OverlayManager
property members: set
ancestors()

All overlays enclosing this one, including this one itself.

Return type:

set[RegionOverlay]

underlying_nodes()

All shared-graph nodes inside this region (including nodes of nested regions).

Return type:

set

create_subregion(head, members, cyclic, cyclic_ancestor=False)

Carve a new child overlay out of this overlay. members must be a subset of this overlay’s members (shared-graph nodes owned by this overlay and/or existing child overlays); head must be one of them.

Return type:

RegionOverlay

Parameters:
successor_nodes()

The derived successor set of this region: representatives of all shared-graph nodes targeted by edges leaving the region.

Return type:

set

view_graph(full=False, include_marked=False, blacklisted_edges=frozenset({}))

A zero-copy, networkx-compatible view of this region (see RegionOverlayGraph).

Return type:

RegionOverlayGraph

Parameters:
view()

The region graph (members only): a zero-copy networkx-compatible view; treat it as read-only.

Return type:

RegionOverlayGraph

view_with_successors()

The region graph including successor nodes: a zero-copy view; treat it as read-only.

Return type:

RegionOverlayGraph

property raw_graph: RegionOverlayGraph

The member view including marked edges (the old graph with cyclic_refinement_outgoing attrs present).

property raw_graph_with_successors: RegionOverlayGraph

The with-successors view including marked edges.

property graph: DiGraph
property graph_with_successors: DiGraph
property successors: set
property full_graph: None
add_node(node)

Insert a new node into the shared graph as a direct member of this region.

Return type:

None

remove_node(node, absorbed_into=None, absorb_out_edges=True)

Remove a node. If node is a member (or a member overlay’s node), it is removed from the shared graph for real. If it is a successor of this region, the removal is interpreted as hiding all edges from this region to it (the successor belongs to an enclosing region and must survive).

When the node’s content has been absorbed into another node during structuring, pass that node as absorbed_into: in-edges from outside this region (e.g. abnormal loop entries) are then rewired to it instead of being dropped, so enclosing regions keep their entry edges. With absorb_out_edges (the default), out-edges crossing the region boundary (e.g. loop exits) are rewired to it as well, so the shared graph never loses the region’s exit flow; pass False only when the caller re-establishes every successor edge explicitly.

Return type:

None

Parameters:

absorb_out_edges (bool)

hide_edge_to_successor(succ)
Return type:

None

underlying_edge_pairs(src, dst)
Return type:

list[tuple[Any, Any]]

add_edge(src, dst, **data)

Add a real edge to the shared graph. Overlay endpoints are resolved to underlying nodes: the destination resolves to its entry (head chain); overlay sources are not supported. Endpoints that are not in the shared graph yet become members of this region (mirroring networkx’s implicit node creation).

Return type:

None

detach_edge(src, dst)

Remove an edge from the shared graph for real (e.g., when the edge has been virtualized into a goto). Overlay endpoints remove all underlying edges between the two node sets.

Return type:

None

mark_edge(src, dst, **attrs)

Mark a view-level edge (e.g. cyclic_refinement_outgoing) so RegionOverlayGraph hides it by default. Marks live in overlay state, never reach the shared graph, and are remapped/cleared with the region.

Return type:

None

absorb_successor_into(succ, new_node)

Absorb a successor node into a structured member node in this region’s with-successors view only (the successor still belongs to an enclosing region): the successor’s view out-edges are re-attached to the member node as view-only extra edges, then the successor disappears from this region’s views.

Return type:

None

drop_edge_marks_from(node, key)

Clear marks on all out-edges of a node (the new_node after a replace), undoably.

Return type:

None

remove_edge_with_successors_only(src, dst)

Hide an edge from the with-successors view only, leaving the member view and the shared graph alone (a rare asymmetric bookkeeping pattern in Phoenix’s switch-case structuring).

Return type:

None

hide_edge(src, dst)

Remove an edge from this overlay’s views only. Enclosing regions still see the underlying edge(s).

Return type:

None

replace_nodes(old_node_0, new_node, old_node_1=None, self_loop=True)

Replace one or two member nodes with a new node, preserving and rewiring all underlying edges (including edges from/to nodes outside this region, which is how results become visible to enclosing regions).

Mirrors StructurerBase.replace_nodes, with one deliberate difference: in-edges of old_node_1 from outside this region are rewired to new_node instead of being dropped (they are entry edges owned by enclosing regions, e.g. abnormal loop entries).

Return type:

None

Parameters:

self_loop (bool)

snapshot_successors()

Capture this region’s structural successors and how many member edges reach each, taken before the region is structured. finalize() uses it to re-establish the region-to-successor edges that structuring removes when it virtualizes/refines the corresponding control-flow edges into gotos or breaks.

Return type:

set

finalize(result_node=None, succ_snapshot=None)

Collapse this fully-structured region into its parent: the region must consist of a single member node (the structuring result), which takes the region’s place among the parent’s members. Returns that node.

succ_snapshot (from snapshot_successors() before structuring) is used to re-establish the edges from result_node to the region’s successors: structuring may have removed the live control-flow edges (refining them into breaks/gotos), but the structured region still flows to those successors and enclosing regions must see that. A successor whose every member edge was virtualized is a pure goto target and is not reconnected.

collapse_to(result_node)

Collapse this region into its parent by replacing all of its member nodes with a single external result node (the structuring result). Used by structurers that compute their result without destructively reducing the shared graph (e.g. DreamStructurer): the region’s members are still present, so their crossing in/out edges are rewired onto result_node and the members are removed. Returns result_node.

This is the non-self-collapsing counterpart of finalize(); the legacy GraphRegion path called replace_region() for the same purpose.

dissolve()

Merge this region back into its parent (the failure path of structuring): members are reparented, and edges hidden in this region stay hidden in the parent (matching how partially-structured region graphs were merged back before).

Return type:

None

class angr.analyses.decompiler.region_overlay.RegionOverlayGraph

Bases: DiGraph

A read-only, networkx-compatible view of a RegionOverlay that stores no copy of the region’s subgraph: all queries traverse the original shared graph through the overlay’s membership. Compatible with every networkx algorithm and DiGraph read method because the graph’s storage mappings are replaced with lazy atlases.

  • full selects the with-successors view (the old graph_with_successors) over the member view.

  • Edges marked through RegionOverlay.mark_edge (e.g. cyclic_refinement_outgoing) are filtered out by default; pass all_edges=True to the query methods, or use with_all_edges(), to include them.

  • to_acyclic() derives a view with additional edges blacklisted (e.g. the region head’s in-edges), replacing the acyclic graph copies that structuring used to make.

property full_view: RegionOverlayGraph

The with-successors sibling of this view (zero-copy).

property member_view: RegionOverlayGraph

The members-only sibling of this view (zero-copy).

with_all_edges()

A sibling view that includes edges marked through RegionOverlay.mark_edge.

Return type:

RegionOverlayGraph

filtered()

A sibling view that hides edges marked through RegionOverlay.mark_edge (the default).

Return type:

RegionOverlayGraph

to_acyclic_by_order(node_order)

An acyclic view of this graph, obtained by blacklisting back edges (edges whose source is ordered at or after their destination in node_order). Replaces utils.graph.to_acyclic_graph without a copy.

Return type:

RegionOverlayGraph

to_acyclic(blacklisted_edges)

A new view with the given (view-level) edges additionally blacklisted; used to traverse the region as an acyclic graph without copying it.

Return type:

RegionOverlayGraph

materialize()

An independent networkx.DiGraph copy of this view.

Return type:

DiGraph

edge_marked(u, v, mark_name=None)
Return type:

bool

Parameters:

mark_name (str | None)