1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
//! Control Flow Graph (CFG) construction and analysis.
//!
//! This module provides a proper graph abstraction over CIL basic blocks with
//! efficient traversal, dominator computation, and loop detection capabilities.
//!
//! # Architecture
//!
//! The CFG builds upon generic graph infrastructure, providing CIL-specific node
//! and edge types while leveraging shared algorithms for dominators, traversals,
//! and strongly connected components.
//!
//! # Key Components
//!
//! - [`ControlFlowGraph`] - The main CFG structure wrapping basic blocks
//! - [`CfgEdge`] - Edge representation with control flow semantics
//! - [`CfgEdgeKind`] - Classification of edge types (unconditional, conditional, etc.)
//!
//! # Edge Types
//!
//! The CFG distinguishes several types of control flow edges:
//!
//! - **Unconditional**: Direct jumps or fall-through to a single successor
//! - **Conditional True/False**: Branches based on a condition
//! - **Switch**: Multi-way branches with case values
//! - **Exception**: Edges to exception handlers
//!
//! # Lazy Computation
//!
//! Expensive analyses like dominator trees and loop information are computed
//! lazily on first access and cached for subsequent queries. This is implemented
//! using [`std::sync::OnceLock`] for thread-safe initialization.
//!
//! # Examples
//!
//! ## Building a CFG from Basic Blocks
//!
//! ```rust,ignore
//! use dotscope::analysis::ControlFlowGraph;
//! use dotscope::assembly::decode_blocks;
//!
//! let blocks = decode_blocks(data, offset, rva, Some(size))?;
//! let graph = ControlFlowGraph::from_basic_blocks(blocks)?;
//!
//! println!("CFG has {} blocks", graph.block_count());
//! println!("Entry block: {:?}", graph.entry());
//! ```
//!
//! ## Traversing the CFG
//!
//! ```rust,ignore
//! use dotscope::analysis::ControlFlowGraph;
//!
//! let graph = ControlFlowGraph::from_basic_blocks(blocks)?;
//!
//! // Iterate in reverse postorder (useful for data flow)
//! for block_id in graph.reverse_postorder() {
//! let block = graph.block(block_id).unwrap();
//! println!("Block {} at RVA 0x{:x}", block_id, block.basic_block.rva);
//! }
//! ```
//!
//! ## Computing Dominators
//!
//! ```rust,ignore
//! use dotscope::analysis::ControlFlowGraph;
//!
//! let graph = ControlFlowGraph::from_basic_blocks(blocks)?;
//! let dominators = graph.dominators();
//!
//! // Check domination relationships
//! if dominators.dominates(graph.entry(), some_block) {
//! println!("Entry dominates the target block");
//! }
//!
//! // Get dominance frontiers for SSA construction
//! let frontiers = graph.dominance_frontiers();
//! ```
//!
//! # Thread Safety
//!
//! [`ControlFlowGraph`] is [`Send`] and [`Sync`], enabling safe concurrent read
//! access after construction. The lazy-initialized dominator tree and loop info
//! use [`std::sync::OnceLock`] for thread-safe initialization.
pub use ;
pub use ;
pub use ControlFlowGraph;
pub use has_back_edges;
pub use ;
pub use ;