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