Skip to content

Commit 9cf8f1a

Browse files
committed
Flowgraph improvements for Rust API
1 parent aa04173 commit 9cf8f1a

File tree

2 files changed

+102
-16
lines changed

2 files changed

+102
-16
lines changed

rust/examples/flowgraph.rs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use binaryninja::{
1515
pub struct GraphPrinter;
1616

1717
impl GraphPrinter {
18-
pub fn print_graph(&self, _view: &BinaryView, graph: &FlowGraph) {
18+
pub fn print_graph(&self, graph: &FlowGraph) {
1919
println!("Printing flow graph:");
2020
for node in &graph.nodes() {
2121
// Print all disassembly lines in the node
@@ -60,24 +60,24 @@ impl InteractionHandler for GraphPrinter {
6060
false
6161
}
6262

63-
fn show_plain_text_report(&mut self, _view: &BinaryView, title: &str, contents: &str) {
63+
fn show_plain_text_report(&mut self, _view: Option<&BinaryView>, title: &str, contents: &str) {
6464
println!("Plain text report");
6565
println!("Title: {}", title);
6666
println!("Contents: {}", contents);
6767
}
6868

69-
fn show_graph_report(&mut self, view: &BinaryView, title: &str, graph: &FlowGraph) {
69+
fn show_graph_report(&mut self, _view: Option<&BinaryView>, title: &str, graph: &FlowGraph) {
7070
println!("Graph report");
7171
println!("Title: {}", title);
72-
self.print_graph(view, graph);
72+
self.print_graph(graph);
7373
}
7474

7575
fn get_form_input(&mut self, _form: &mut Form) -> bool {
7676
false
7777
}
7878
}
7979

80-
fn test_graph(view: &BinaryView) {
80+
fn test_graph() {
8181
let graph = FlowGraph::new();
8282

8383
let disassembly_lines_a = vec![DisassemblyTextLine::new(vec![
@@ -110,7 +110,7 @@ fn test_graph(view: &BinaryView) {
110110
EdgeStyle::default(),
111111
);
112112

113-
view.show_graph_report("Rust Graph Title", &graph);
113+
graph.show("Rust Example Graph");
114114
}
115115

116116
fn main() {
@@ -127,10 +127,11 @@ fn main() {
127127
// Register the interaction handler so we can see the graph report headlessly.
128128
register_interaction_handler(GraphPrinter);
129129

130-
test_graph(&bv);
130+
test_graph();
131131

132132
for func in bv.functions().iter().take(5) {
133133
let graph = func.create_graph(FunctionViewType::MediumLevelIL, None);
134+
// TODO: Why are the nodes empty? Python its empty until its shown...
134135
assert!(!graph.nodes().is_empty());
135136
let func_name = func.symbol().short_name();
136137
let title = func_name.to_string_lossy();

rust/src/flowgraph.rs

Lines changed: 94 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ use crate::render_layer::CoreRenderLayer;
2525
pub mod edge;
2626
pub mod node;
2727

28+
use crate::binary_view::BinaryView;
29+
use crate::function::Function;
30+
use crate::string::IntoCStr;
2831
pub use edge::EdgeStyle;
2932
pub use edge::FlowGraphEdge;
3033
pub use node::FlowGraphNode;
@@ -52,38 +55,101 @@ impl FlowGraph {
5255
unsafe { FlowGraph::ref_from_raw(BNCreateFlowGraph()) }
5356
}
5457

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+
/// Whether flow graph layout is complete.
87+
pub fn is_layout_complete(&self) -> bool {
88+
unsafe { BNIsFlowGraphLayoutComplete(self.handle) }
89+
}
90+
5591
pub fn nodes(&self) -> Array<FlowGraphNode> {
5692
let mut count: usize = 0;
5793
let nodes_ptr = unsafe { BNGetFlowGraphNodes(self.handle, &mut count as *mut usize) };
5894
unsafe { Array::new(nodes_ptr, count, ()) }
5995
}
6096

61-
pub fn low_level_il(&self) -> Result<Ref<LowLevelILRegularFunction>, ()> {
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 low_level_il(&self) -> Option<Ref<LowLevelILRegularFunction>> {
62128
unsafe {
63129
let llil_ptr = BNGetFlowGraphLowLevelILFunction(self.handle);
64130
match llil_ptr.is_null() {
65-
false => Ok(LowLevelILRegularFunction::ref_from_raw(llil_ptr)),
66-
true => Err(()),
131+
false => Some(LowLevelILRegularFunction::ref_from_raw(llil_ptr)),
132+
true => None,
67133
}
68134
}
69135
}
70136

71-
pub fn medium_level_il(&self) -> Result<Ref<MediumLevelILFunction>, ()> {
137+
pub fn medium_level_il(&self) -> Option<Ref<MediumLevelILFunction>> {
72138
unsafe {
73139
let mlil_ptr = BNGetFlowGraphMediumLevelILFunction(self.handle);
74140
match mlil_ptr.is_null() {
75-
false => Ok(MediumLevelILFunction::ref_from_raw(mlil_ptr)),
76-
true => Err(()),
141+
false => Some(MediumLevelILFunction::ref_from_raw(mlil_ptr)),
142+
true => None,
77143
}
78144
}
79145
}
80146

81-
pub fn high_level_il(&self, full_ast: bool) -> Result<Ref<HighLevelILFunction>, ()> {
147+
pub fn high_level_il(&self, full_ast: bool) -> Option<Ref<HighLevelILFunction>> {
82148
unsafe {
83149
let hlil_ptr = BNGetFlowGraphHighLevelILFunction(self.handle);
84150
match hlil_ptr.is_null() {
85-
false => Ok(HighLevelILFunction::ref_from_raw(hlil_ptr, full_ast)),
86-
true => Err(()),
151+
false => Some(HighLevelILFunction::ref_from_raw(hlil_ptr, full_ast)),
152+
true => None,
87153
}
88154
}
89155
}
@@ -105,6 +171,25 @@ impl FlowGraph {
105171
unsafe { BNFlowGraphHasNodes(self.handle) }
106172
}
107173

174+
/// Returns the graph size in width, height form.
175+
pub fn size(&self) -> (i32, i32) {
176+
let width = unsafe { BNGetFlowGraphWidth(self.handle) };
177+
let height = unsafe { BNGetFlowGraphHeight(self.handle) };
178+
(width, height)
179+
}
180+
181+
/// Returns the graph margins between nodes.
182+
pub fn node_margins(&self) -> (i32, i32) {
183+
let horizontal = unsafe { BNGetHorizontalFlowGraphNodeMargin(self.handle) };
184+
let vertical = unsafe { BNGetVerticalFlowGraphNodeMargin(self.handle) };
185+
(horizontal, vertical)
186+
}
187+
188+
/// Sets the graph margins between nodes.
189+
pub fn set_node_margins(&self, horizontal: i32, vertical: i32) {
190+
unsafe { BNSetFlowGraphNodeMargins(self.handle, horizontal, vertical) };
191+
}
192+
108193
pub fn append(&self, node: &FlowGraphNode) -> usize {
109194
unsafe { BNAddFlowGraphNode(self.handle, node.handle) }
110195
}

0 commit comments

Comments
 (0)