Skip to main content

mirage/router/
mod.rs

1use anyhow::Result;
2use serde::{Deserialize, Serialize};
3use std::path::Path;
4
5#[cfg(feature = "backend-geometric")]
6pub mod geometric;
7pub mod sqlite;
8
9#[cfg(feature = "backend-geometric")]
10pub use geometric::GeometricRouter;
11#[cfg(feature = "backend-sqlite")]
12pub use sqlite::SqliteRouter;
13
14// Priority-based Router type alias:
15// - Geometric takes priority if enabled
16// - Otherwise SQLite if enabled
17#[cfg(feature = "backend-geometric")]
18pub type Router = GeometricRouter;
19#[cfg(all(not(feature = "backend-geometric"), feature = "backend-sqlite"))]
20pub type Router = SqliteRouter;
21
22pub trait BackendRouter: Sized {
23    fn open(db_path: &Path) -> Result<Self>;
24    fn status(&self) -> Result<DatabaseStatus>;
25    fn load_cfg(&self, function_id: i64) -> Result<crate::cfg::Cfg>;
26    fn resolve_function(&self, name_or_id: &str) -> Result<i64>;
27    fn get_function_name(&self, function_id: i64) -> Option<String>;
28    fn get_function_file(&self, function_id: i64) -> Option<String>;
29    fn function_exists(&self, function_id: i64) -> bool;
30    fn enumerate_paths(&self, function_id: i64, max_paths: usize) -> Result<Vec<ExecutionPath>>;
31    fn get_cfg_blocks(&self, function_id: i64) -> Result<Vec<CfgBlockInfo>>;
32    fn get_dominators(&self, function_id: i64) -> Result<DominatorTree>;
33    fn get_loops(&self, function_id: i64) -> Result<Vec<NaturalLoop>>;
34    fn find_unreachable(&self, within_functions: bool) -> Result<Vec<UnreachableCode>>;
35    fn get_patterns(&self, function_id: i64) -> Result<Vec<BranchPattern>>;
36    fn get_frontiers(&self, function_id: i64) -> Result<DominanceFrontiers>;
37    fn find_cycles(&self) -> Result<Vec<CallCycle>>;
38    fn get_blast_zone(&self, function_id: i64, block_id: Option<i64>) -> Result<BlastZone>;
39    fn slice(&self, symbol: &str, direction: SliceDirection) -> Result<SliceResult>;
40    fn get_hotspots(&self) -> Result<Vec<Hotspot>>;
41    fn get_hotpaths(&self, function_id: Option<i64>) -> Result<Vec<HotPath>>;
42    fn verify_path(&self, path_id: &str) -> Result<PathVerification>;
43    fn get_icfg(&self, function_id: i64) -> Result<InterProceduralCfg>;
44    fn get_call_graph(&self) -> Result<CallGraph>;
45}
46
47#[derive(Debug, Clone, Serialize, Deserialize)]
48pub struct DatabaseStatus {
49    pub cfg_blocks: i64,
50    pub cfg_paths: i64,
51    pub cfg_dominators: i64,
52    pub mirage_schema_version: i32,
53    pub magellan_schema_version: i32,
54}
55
56#[derive(Debug, Clone, Serialize, Deserialize)]
57pub struct ExecutionPath {
58    pub path_id: String,
59    pub blocks: Vec<i64>,
60    pub length: usize,
61}
62
63#[derive(Debug, Clone, Serialize, Deserialize)]
64pub struct CfgBlockInfo {
65    pub id: i64,
66    pub kind: String,
67    pub terminator: Option<String>,
68    pub byte_start: u64,
69    pub byte_end: u64,
70    pub start_line: u64,
71    pub start_col: u64,
72    pub end_line: u64,
73    pub end_col: u64,
74}
75
76#[derive(Debug, Clone, Serialize, Deserialize)]
77pub struct DominatorTree {
78    pub function_id: i64,
79    pub dominators: std::collections::HashMap<i64, Vec<i64>>,
80}
81
82#[derive(Debug, Clone, Serialize, Deserialize)]
83pub struct NaturalLoop {
84    pub header: i64,
85    pub blocks: Vec<i64>,
86}
87
88#[derive(Debug, Clone, Serialize, Deserialize)]
89pub struct UnreachableCode {
90    pub function_id: i64,
91    pub block_id: i64,
92    pub reason: String,
93}
94
95#[derive(Debug, Clone, Serialize, Deserialize)]
96pub struct BranchPattern {
97    pub pattern_id: String,
98    pub kind: String,
99    pub blocks: Vec<i64>,
100}
101
102#[derive(Debug, Clone, Serialize, Deserialize)]
103pub struct DominanceFrontiers {
104    pub function_id: i64,
105    pub frontiers: std::collections::HashMap<i64, Vec<i64>>,
106}
107
108#[derive(Debug, Clone, Serialize, Deserialize)]
109pub struct CallCycle {
110    pub cycle_id: String,
111    pub functions: Vec<i64>,
112}
113
114#[derive(Debug, Clone, Serialize, Deserialize)]
115pub struct BlastZone {
116    pub center_function: i64,
117    pub center_block: Option<i64>,
118    pub affected_functions: Vec<i64>,
119    pub affected_blocks: Vec<i64>,
120}
121
122#[derive(Debug, Clone, Serialize, Deserialize)]
123pub struct SliceResult {
124    pub symbol: String,
125    pub direction: String,
126    pub affected_symbols: Vec<String>,
127}
128
129#[derive(Debug, Clone, Serialize, Deserialize)]
130pub struct Hotspot {
131    pub function_id: i64,
132    pub complexity: f64,
133    pub frequency: f64,
134}
135
136#[derive(Debug, Clone, Serialize, Deserialize)]
137pub struct HotPath {
138    pub path: Vec<i64>,
139    pub frequency: f64,
140}
141
142#[derive(Debug, Clone, Serialize, Deserialize)]
143pub struct PathVerification {
144    pub path_id: String,
145    pub valid: bool,
146    pub issues: Vec<String>,
147}
148
149#[derive(Debug, Clone, Serialize, Deserialize)]
150pub struct InterProceduralCfg {
151    pub entry_function: i64,
152    pub nodes: Vec<IcfgNode>,
153    pub edges: Vec<IcfgEdge>,
154}
155
156#[derive(Debug, Clone, Serialize, Deserialize)]
157pub struct IcfgNode {
158    pub id: i64,
159    pub function_id: i64,
160    pub block_id: i64,
161}
162
163#[derive(Debug, Clone, Serialize, Deserialize)]
164pub struct IcfgEdge {
165    pub from_node: i64,
166    pub to_node: i64,
167    pub kind: String,
168}
169
170#[derive(Debug, Clone, Serialize, Deserialize)]
171pub struct CallGraph {
172    pub nodes: Vec<CallGraphNode>,
173    pub edges: Vec<CallGraphEdge>,
174}
175
176#[derive(Debug, Clone, Serialize, Deserialize)]
177pub struct CallGraphNode {
178    pub id: i64,
179    pub function_name: String,
180}
181
182#[derive(Debug, Clone, Serialize, Deserialize)]
183pub struct CallGraphEdge {
184    pub caller_id: i64,
185    pub callee_id: i64,
186}
187
188pub enum SliceDirection {
189    Forward,
190    Backward,
191    Both,
192}