1use binaryninjacore_sys::*;
18
19use crate::high_level_il::HighLevelILFunction;
20use crate::low_level_il::LowLevelILRegularFunction;
21use crate::medium_level_il::MediumLevelILFunction;
22use crate::rc::*;
23use crate::render_layer::CoreRenderLayer;
24
25pub mod edge;
26pub mod node;
27
28use crate::binary_view::BinaryView;
29use crate::function::Function;
30use crate::string::IntoCStr;
31pub use edge::EdgeStyle;
32pub use edge::FlowGraphEdge;
33pub use node::FlowGraphNode;
34
35pub type EdgePenStyle = BNEdgePenStyle;
36pub type ThemeColor = BNThemeColor;
37pub type FlowGraphOption = BNFlowGraphOption;
38
39#[derive(PartialEq, Eq, Hash)]
40pub struct FlowGraph {
41 pub(crate) handle: *mut BNFlowGraph,
42}
43
44impl FlowGraph {
45 pub(crate) unsafe fn from_raw(raw: *mut BNFlowGraph) -> Self {
46 Self { handle: raw }
47 }
48
49 pub(crate) unsafe fn ref_from_raw(raw: *mut BNFlowGraph) -> Ref<Self> {
50 Ref::new(Self { handle: raw })
51 }
52
53 pub fn new() -> Ref<Self> {
54 unsafe { FlowGraph::ref_from_raw(BNCreateFlowGraph()) }
55 }
56
57 pub fn has_updates(&self) -> bool {
58 let query_mode = unsafe { BNFlowGraphUpdateQueryMode(self.handle) };
59 match query_mode {
60 true => unsafe { BNFlowGraphHasUpdates(self.handle) },
61 false => false,
62 }
63 }
64
65 pub fn update(&self) -> Option<Ref<Self>> {
66 let new_graph = unsafe { BNUpdateFlowGraph(self.handle) };
67 if new_graph.is_null() {
68 return None;
69 }
70 Some(unsafe { FlowGraph::ref_from_raw(new_graph) })
71 }
72
73 pub fn show(&self, title: &str) {
74 let raw_title = title.to_cstr();
75 match self.view() {
76 None => unsafe {
77 BNShowGraphReport(std::ptr::null_mut(), raw_title.as_ptr(), self.handle);
78 },
79 Some(view) => unsafe {
80 BNShowGraphReport(view.handle, raw_title.as_ptr(), self.handle);
81 },
82 }
83 }
84
85 pub fn is_layout_complete(&self) -> bool {
87 unsafe { BNIsFlowGraphLayoutComplete(self.handle) }
88 }
89
90 pub fn nodes(&self) -> Array<FlowGraphNode> {
91 let mut count: usize = 0;
92 let nodes_ptr = unsafe { BNGetFlowGraphNodes(self.handle, &mut count as *mut usize) };
93 unsafe { Array::new(nodes_ptr, count, ()) }
94 }
95
96 pub fn function(&self) -> Option<Ref<Function>> {
97 unsafe {
98 let func_ptr = BNGetFunctionForFlowGraph(self.handle);
99 match func_ptr.is_null() {
100 false => Some(Function::ref_from_raw(func_ptr)),
101 true => None,
102 }
103 }
104 }
105
106 pub fn set_function(&self, func: Option<&Function>) {
107 let func_ptr = func.map(|f| f.handle).unwrap_or(std::ptr::null_mut());
108 unsafe { BNSetFunctionForFlowGraph(self.handle, func_ptr) }
109 }
110
111 pub fn view(&self) -> Option<Ref<BinaryView>> {
112 unsafe {
113 let view_ptr = BNGetViewForFlowGraph(self.handle);
114 match view_ptr.is_null() {
115 false => Some(BinaryView::ref_from_raw(view_ptr)),
116 true => None,
117 }
118 }
119 }
120
121 pub fn set_view(&self, view: Option<&BinaryView>) {
122 let view_ptr = view.map(|v| v.handle).unwrap_or(std::ptr::null_mut());
123 unsafe { BNSetViewForFlowGraph(self.handle, view_ptr) }
124 }
125
126 pub fn lifted_il(&self) -> Option<Ref<LowLevelILRegularFunction>> {
127 self.function()?.lifted_il().ok()
128 }
129
130 pub fn low_level_il(&self) -> Option<Ref<LowLevelILRegularFunction>> {
131 unsafe {
132 let llil_ptr = BNGetFlowGraphLowLevelILFunction(self.handle);
133 match llil_ptr.is_null() {
134 false => Some(LowLevelILRegularFunction::ref_from_raw(llil_ptr)),
135 true => None,
136 }
137 }
138 }
139
140 pub fn medium_level_il(&self) -> Option<Ref<MediumLevelILFunction>> {
141 unsafe {
142 let mlil_ptr = BNGetFlowGraphMediumLevelILFunction(self.handle);
143 match mlil_ptr.is_null() {
144 false => Some(MediumLevelILFunction::ref_from_raw(mlil_ptr)),
145 true => None,
146 }
147 }
148 }
149
150 pub fn high_level_il(&self, full_ast: bool) -> Option<Ref<HighLevelILFunction>> {
151 unsafe {
152 let hlil_ptr = BNGetFlowGraphHighLevelILFunction(self.handle);
153 match hlil_ptr.is_null() {
154 false => Some(HighLevelILFunction::ref_from_raw(hlil_ptr, full_ast)),
155 true => None,
156 }
157 }
158 }
159
160 pub fn get_node(&self, i: usize) -> Option<Ref<FlowGraphNode>> {
161 let node_ptr = unsafe { BNGetFlowGraphNode(self.handle, i) };
162 if node_ptr.is_null() {
163 None
164 } else {
165 Some(unsafe { FlowGraphNode::ref_from_raw(node_ptr) })
166 }
167 }
168
169 pub fn get_node_count(&self) -> usize {
170 unsafe { BNGetFlowGraphNodeCount(self.handle) }
171 }
172
173 pub fn has_nodes(&self) -> bool {
174 unsafe { BNFlowGraphHasNodes(self.handle) }
175 }
176
177 pub fn size(&self) -> (i32, i32) {
179 let width = unsafe { BNGetFlowGraphWidth(self.handle) };
180 let height = unsafe { BNGetFlowGraphHeight(self.handle) };
181 (width, height)
182 }
183
184 pub fn node_margins(&self) -> (i32, i32) {
186 let horizontal = unsafe { BNGetHorizontalFlowGraphNodeMargin(self.handle) };
187 let vertical = unsafe { BNGetVerticalFlowGraphNodeMargin(self.handle) };
188 (horizontal, vertical)
189 }
190
191 pub fn set_node_margins(&self, horizontal: i32, vertical: i32) {
193 unsafe { BNSetFlowGraphNodeMargins(self.handle, horizontal, vertical) };
194 }
195
196 pub fn append(&self, node: &FlowGraphNode) -> usize {
197 unsafe { BNAddFlowGraphNode(self.handle, node.handle) }
198 }
199
200 pub fn replace(&self, index: usize, node: &FlowGraphNode) {
201 unsafe { BNReplaceFlowGraphNode(self.handle, index, node.handle) }
202 }
203
204 pub fn clear(&self) {
205 unsafe { BNClearFlowGraphNodes(self.handle) }
206 }
207
208 pub fn set_option(&self, option: FlowGraphOption, value: bool) {
209 unsafe { BNSetFlowGraphOption(self.handle, option, value) }
210 }
211
212 pub fn is_option_set(&self, option: FlowGraphOption) -> bool {
213 unsafe { BNIsFlowGraphOptionSet(self.handle, option) }
214 }
215
216 pub fn render_layers(&self) -> Array<CoreRenderLayer> {
218 let mut count: usize = 0;
219 unsafe {
220 let handles = BNGetFlowGraphRenderLayers(self.handle, &mut count);
221 Array::new(handles, count, ())
222 }
223 }
224
225 pub fn add_render_layer(&self, layer: &CoreRenderLayer) {
229 unsafe { BNAddFlowGraphRenderLayer(self.handle, layer.handle.as_ptr()) };
230 }
231
232 pub fn remove_render_layer(&self, layer: &CoreRenderLayer) {
234 unsafe { BNRemoveFlowGraphRenderLayer(self.handle, layer.handle.as_ptr()) };
235 }
236}
237
238unsafe impl RefCountable for FlowGraph {
239 unsafe fn inc_ref(handle: &Self) -> Ref<Self> {
240 Ref::new(Self {
241 handle: BNNewFlowGraphReference(handle.handle),
242 })
243 }
244
245 unsafe fn dec_ref(handle: &Self) {
246 BNFreeFlowGraph(handle.handle);
247 }
248}
249
250impl ToOwned for FlowGraph {
251 type Owned = Ref<Self>;
252
253 fn to_owned(&self) -> Self::Owned {
254 unsafe { RefCountable::inc_ref(self) }
255 }
256}