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#[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}