summaryrefslogtreecommitdiff
path: root/rust/examples
diff options
context:
space:
mode:
authorMason Reed <mason@vector35.com>2025-05-08 21:39:12 -0400
committerMason Reed <35282038+emesare@users.noreply.github.com>2025-05-12 17:45:24 -0400
commitadbd39ab7c3d4e67e8709af43176e60f31141ba8 (patch)
treec6c937ae1561d5b7cd8f2925ef44b5091c6a86dc /rust/examples
parent38fa66115c00ead8dcc38ec5c5451d3ce4444ab8 (diff)
[Rust] Flow graph API improvements
- Fixed some misc bugs - Added real FlowGraphEdge type - Added accessors for node edges - Added interaction handler to the flow graph example to dump the flow graph to stdin - Split out the flow graph API into smaller files
Diffstat (limited to 'rust/examples')
-rw-r--r--rust/examples/flowgraph.rs89
1 files changed, 86 insertions, 3 deletions
diff --git a/rust/examples/flowgraph.rs b/rust/examples/flowgraph.rs
index 6666b7fb..515d52fe 100644
--- a/rust/examples/flowgraph.rs
+++ b/rust/examples/flowgraph.rs
@@ -1,9 +1,82 @@
+use binaryninja::flowgraph::edge::EdgeStyle;
+use binaryninja::flowgraph::FlowGraphNode;
+use binaryninja::function::FunctionViewType;
+use binaryninja::interaction::form::Form;
+use binaryninja::interaction::handler::{
+ register_interaction_handler, InteractionHandler, InteractionHandlerTask,
+};
+use binaryninja::interaction::{MessageBoxButtonResult, MessageBoxButtonSet, MessageBoxIcon};
use binaryninja::{
binary_view::{BinaryView, BinaryViewExt},
disassembly::{DisassemblyTextLine, InstructionTextToken, InstructionTextTokenKind},
- flowgraph::{BranchType, EdgePenStyle, EdgeStyle, FlowGraph, FlowGraphNode, ThemeColor},
+ flowgraph::{BranchType, EdgePenStyle, FlowGraph, ThemeColor},
};
+pub struct GraphPrinter;
+
+impl GraphPrinter {
+ pub fn print_graph(&self, _view: &BinaryView, graph: &FlowGraph) {
+ println!("Printing flow graph:");
+ for node in &graph.nodes() {
+ // Print all disassembly lines in the node
+ println!("Node @ {:?}:", node.position());
+ println!("------------------");
+ println!("Disassembly lines:");
+ for line in &node.lines() {
+ println!(" {}", line);
+ }
+
+ // Print outgoing edges
+ println!("Outgoing edges:");
+ for edge in &node.outgoing_edges() {
+ println!(" {:?} => {:?}", edge.branch_type, edge.target.position());
+ }
+ println!("------------------");
+ }
+ }
+}
+
+impl InteractionHandler for GraphPrinter {
+ fn show_message_box(
+ &mut self,
+ _title: &str,
+ _text: &str,
+ _buttons: MessageBoxButtonSet,
+ _icon: MessageBoxIcon,
+ ) -> MessageBoxButtonResult {
+ MessageBoxButtonResult::CancelButton
+ }
+
+ fn open_url(&mut self, _url: &str) -> bool {
+ false
+ }
+
+ fn run_progress_dialog(
+ &mut self,
+ _title: &str,
+ _can_cancel: bool,
+ _task: &InteractionHandlerTask,
+ ) -> bool {
+ false
+ }
+
+ fn show_plain_text_report(&mut self, _view: &BinaryView, title: &str, contents: &str) {
+ println!("Plain text report");
+ println!("Title: {}", title);
+ println!("Contents: {}", contents);
+ }
+
+ fn show_graph_report(&mut self, view: &BinaryView, title: &str, graph: &FlowGraph) {
+ println!("Graph report");
+ println!("Title: {}", title);
+ self.print_graph(view, graph);
+ }
+
+ fn get_form_input(&mut self, _form: &mut Form) -> bool {
+ false
+ }
+}
+
fn test_graph(view: &BinaryView) {
let graph = FlowGraph::new();
@@ -15,8 +88,10 @@ fn test_graph(view: &BinaryView) {
let node_a = FlowGraphNode::new(&graph);
node_a.set_lines(disassembly_lines_a);
+ node_a.set_position(1337, 7331);
let node_b = FlowGraphNode::new(&graph);
+ node_b.set_position(100, 200);
let disassembly_lines_b = vec![DisassemblyTextLine::new(vec![
InstructionTextToken::new("Li", InstructionTextTokenKind::Text),
InstructionTextToken::new("ne", InstructionTextTokenKind::Text),
@@ -49,8 +124,16 @@ fn main() {
.load("/bin/cat")
.expect("Couldn't open `/bin/cat`");
- // TODO: Register BNInteractionHandlerCallbacks with showGraphReport pointing at our function
- // TODO: Idea: register showGraphReport that dumps a dotgraph to stdin
+ // Register the interaction handler so we can see the graph report headlessly.
+ register_interaction_handler(GraphPrinter);
test_graph(&bv);
+
+ for func in bv.functions().iter().take(5) {
+ let graph = func.create_graph(FunctionViewType::MediumLevelIL, None);
+ assert!(!graph.nodes().is_empty());
+ let func_name = func.symbol().short_name();
+ let title = func_name.to_string_lossy();
+ bv.show_graph_report(&title, &graph);
+ }
}