angr.utils.graph¶
- angr.utils.graph.shallow_reverse(g)¶
Make a shallow copy of a directional graph and reverse the edges. This is a workaround to solve the issue that one cannot easily make a shallow reversed copy of a graph in NetworkX 2, since networkx.reverse(copy=False) now returns a GraphView, and GraphViews are always read-only.
- Parameters:
g (networkx.DiGraph) – The graph to reverse.
- Returns:
A new networkx.DiGraph that has all nodes and all edges of the original graph, with edges reversed.
- angr.utils.graph.inverted_idoms(graph, end_node=None)¶
Invert the given graph and generate the immediate dominator tree on the inverted graph. This is useful for computing post-dominators.
- Parameters:
graph – The graph to invert and generate immediate dominator tree for.
- Returns:
A tuple of the inverted graph and the immediate dominator tree.
- angr.utils.graph.to_acyclic_graph(graph, node_order=None, loop_heads=None)¶
Convert a given DiGraph into an acyclic graph.
- Parameters:
graph – The graph to convert.
ordered_nodes – A list of nodes sorted in a topological order.
loop_heads – A list of known loop head nodes.
- Returns:
The converted acyclic graph.
- angr.utils.graph.dfs_back_edges(graph, start_node, *, visit_all_nodes=False, visited=None)¶
Perform an iterative DFS traversal of the graph, returning back edges.
- Parameters:
graph – The graph to traverse.
start_node – The node where to start the traversal.
- Returns:
An iterator of ‘backward’ edges.
- angr.utils.graph.subgraph_between_nodes(graph, source, frontier, include_frontier=False)¶
For a directed graph, return a subgraph that includes all nodes going from a source node to a target node.
- angr.utils.graph.dominates(idom, dominator_node, node)¶
- angr.utils.graph.compute_dominance_frontier(graph, domtree)¶
Compute a dominance frontier based on the given post-dominator tree.
This implementation is based on figure 2 of paper An Efficient Method of Computing Static Single Assignment Form by Ron Cytron, etc.
- Parameters:
graph – The graph where we want to compute the dominance frontier.
domtree – The dominator tree
- Returns:
A dict of dominance frontier
- class angr.utils.graph.TemporaryNode¶
Bases:
objectA temporary node.
Used as the start node and end node in post-dominator tree generation. Also used in some test cases.
- __init__(label)¶
- class angr.utils.graph.ContainerNode¶
Bases:
GenericA container node.
Only used in dominator tree generation. We did this so we can set the index property without modifying the original object.
- __init__(obj)¶
- Parameters:
obj (T)
- property obj: T¶
- class angr.utils.graph.Dominators¶
Bases:
GenericDescribes dominators in a graph.
- __init__(graph, entry_node, successors_func=None, reverse=False)¶
- dom: networkx.DiGraph[T]
- class angr.utils.graph.PostDominators¶
Bases:
Dominators,GenericDescribe post-dominators in a graph.
- __init__(graph, entry_node, successors_func=None)¶
- property post_dom: networkx.DiGraph[T]¶
- class angr.utils.graph.SCCPlaceholder¶
Bases:
objectDescribes a placeholder for strongly-connected-components in a graph.
- __init__(scc_id, addr)¶
- scc_id
- addr
- class angr.utils.graph.GraphUtils¶
Bases:
objectA helper class with some static methods and algorithms implemented, that in fact, might take more than just normal CFGs.
- static find_merge_points(function_addr, function_endpoints, graph)¶
Given a local transition graph of a function, find all merge points inside, and then perform a quasi-topological sort of those merge points.
A merge point might be one of the following cases: - two or more paths come together, and ends at the same address. - end of the current function
- Parameters:
- Returns:
A list of ordered addresses of merge points.
- Return type:
- static find_widening_points(function_addr, function_endpoints, graph)¶
Given a local transition graph of a function, find all widening points inside.
Correctly choosing widening points is very important in order to not lose too much information during static analysis. We mainly consider merge points that has at least one loop back edges coming in as widening points.
- Parameters:
- Returns:
A list of addresses of widening points.
- Return type:
- static dfs_postorder_nodes_deterministic(graph, source)¶
- Parameters:
graph (networkx.DiGraph[T])
source (T)
- Return type:
Iterator[T]
- static dfs_postorder_nodes_deterministic_multi(graph, sources)¶
Deterministic post-order DFS covering multiple source nodes with a single shared
visitedset. Equivalent todfs_postorder_nodes_deterministicover a synthetic super-source connected to every node insources(sources are traversed in_sort_nodeorder), but without mutating the graph – so it works directly on a zero-copy overlay view. Use it for multi-entry acyclic graphs.- Parameters:
graph (networkx.DiGraph[T])
sources (Iterable[T])
- Return type:
Iterator[T]
- static reverse_post_order_sort_nodes(graph, nodes=None)¶
Sort a given set of nodes in reverse post ordering.
- Parameters:
graph (networkx.DiGraph) – A local transition graph of a function.
nodes (iterable) – A collection of nodes to sort.
- Returns:
A list of sorted nodes.
- Return type:
- static quasi_topological_sort_nodes(graph, nodes=None, loop_heads=None, panic_mode_threshold=3000)¶
Sort a given set of nodes from a graph based on the following rules:
# - if A -> B and not B -> A, then we have A < B # - if A -> B and B -> A, then the ordering is undefined
Following the above rules gives us a quasi-topological sorting of nodes in the graph. It also works for cyclic graphs.
- Parameters:
graph (
DiGraph) – A local transition graph of the function.nodes (
list|None) – A list of nodes to sort. None if you want to sort all nodes inside the graph.loop_heads (
list|None) – A list of nodes that should be treated loop heads.panic_mode_threshold (
int) – Threshold of nodes in an SCC to begin aggressively removing edges.
- Return type:
- Returns:
A list of ordered nodes.
- static loop_nesting_forest(graph, start_node)¶
Generates the loop-nesting forest for the provided directional graph. This is not the algorithm proposed by Ramalingam.
- Parameters:
graph (
DiGraph) – the graph to generate the loop-nesting forest for.start_node – the node to start traversing the graph from.
- Return type:
OrderedDict[Any,DiGraph]- Returns:
An ordered dict of loop heads to their corresponding loop nodes.
- class angr.utils.graph.LinkedListNode¶
Bases:
GenericA node in a linked list.
- __init__(v)¶
- Parameters:
v (T)
- v: T
- next: LinkedListNode | None
- prev: LinkedListNode | None
- class angr.utils.graph.DirectedGraphHelper¶
Bases:
GenericA helper class for accelerating some graph algorithms on directed graphs.
_node_order keeps a dictionary of nodes and their order in a quasi-topological sort of the region full graph (graph_with_successors). _generate_node_order() initializes this dictionary. we then update this dictionary when new nodes are created.
We do not populate _node_order when working on acyclic graphs because it’s not used for acyclic graphs.
- __init__(graph, cyclic_graph, head)¶
- reset()¶
- dfs_postorder_nodes_deterministic(source)¶
Post-order DFS traversal of the directed graph using cache. Avoids acyclic-graph conversion or full-graph traversal when cache is available.
- replace_node(old_node, new_node)¶
Update cache when a node is replaced in the graph.
- Parameters:
old_node (T)
new_node (T)
- replace_nodes(old_node_0, old_node_1, new_node)¶
Update cache when multiple nodes are replaced by a single node in the graph.
- Return type:
- Parameters:
old_node_0 (T)
old_node_1 (T)
new_node (T)
- remove_node(node)¶
Update cache when a node is removed from the graph.
- Parameters:
node (T)
- to_acyclic_by_order(graph)¶
- Parameters:
graph (RegionOverlayGraph[T])
- Return type:
networkx.DiGraph[T]