binaryninja/flowgraph/
node.rs1use crate::architecture::BranchType;
2use crate::basic_block::{BasicBlock, BlockContext};
3use crate::disassembly::DisassemblyTextLine;
4use crate::flowgraph::edge::{EdgeStyle, FlowGraphEdge};
5use crate::flowgraph::FlowGraph;
6use crate::function::HighlightColor;
7use crate::rc::{Array, CoreArrayProvider, CoreArrayProviderInner, Guard, Ref, RefCountable};
8use binaryninjacore_sys::*;
9use std::fmt::{Debug, Formatter};
10
11#[derive(PartialEq, Eq, Hash)]
12pub struct FlowGraphNode {
13 pub(crate) handle: *mut BNFlowGraphNode,
14}
15
16impl FlowGraphNode {
17 pub(crate) unsafe fn from_raw(raw: *mut BNFlowGraphNode) -> Self {
18 Self { handle: raw }
19 }
20
21 pub(crate) unsafe fn ref_from_raw(raw: *mut BNFlowGraphNode) -> Ref<Self> {
22 Ref::new(Self { handle: raw })
23 }
24
25 pub fn new(graph: &FlowGraph) -> Ref<Self> {
26 unsafe { FlowGraphNode::ref_from_raw(BNCreateFlowGraphNode(graph.handle)) }
27 }
28
29 pub fn basic_block<C: BlockContext>(&self, context: C) -> Option<Ref<BasicBlock<C>>> {
30 let block_ptr = unsafe { BNGetFlowGraphBasicBlock(self.handle) };
31 if block_ptr.is_null() {
32 return None;
33 }
34 Some(unsafe { BasicBlock::ref_from_raw(block_ptr, context) })
35 }
36
37 pub fn set_basic_block<C: BlockContext>(&self, block: Option<&BasicBlock<C>>) {
38 match block {
39 Some(block) => unsafe { BNSetFlowGraphBasicBlock(self.handle, block.handle) },
40 None => unsafe { BNSetFlowGraphBasicBlock(self.handle, std::ptr::null_mut()) },
41 }
42 }
43
44 pub fn lines(&self) -> Array<DisassemblyTextLine> {
45 let mut count = 0;
46 let result = unsafe { BNGetFlowGraphNodeLines(self.handle, &mut count) };
47 assert!(!result.is_null());
48 unsafe { Array::new(result, count, ()) }
49 }
50
51 pub fn set_lines(&self, lines: impl IntoIterator<Item = DisassemblyTextLine>) {
52 let mut raw_lines: Vec<BNDisassemblyTextLine> = lines
54 .into_iter()
55 .map(DisassemblyTextLine::into_raw)
56 .collect();
57 unsafe {
58 BNSetFlowGraphNodeLines(self.handle, raw_lines.as_mut_ptr(), raw_lines.len());
59 for raw_line in raw_lines {
60 DisassemblyTextLine::free_raw(raw_line);
61 }
62 }
63 }
64
65 pub fn position(&self) -> (i32, i32) {
67 let pos_x = unsafe { BNGetFlowGraphNodeX(self.handle) };
68 let pos_y = unsafe { BNGetFlowGraphNodeY(self.handle) };
69 (pos_x, pos_y)
70 }
71
72 pub fn set_position(&self, x: i32, y: i32) {
74 unsafe { BNFlowGraphNodeSetX(self.handle, x) };
75 unsafe { BNFlowGraphNodeSetY(self.handle, y) };
76 }
77
78 pub fn highlight_color(&self) -> HighlightColor {
79 let raw = unsafe { BNGetFlowGraphNodeHighlight(self.handle) };
80 HighlightColor::from(raw)
81 }
82
83 pub fn set_highlight_color(&self, highlight: HighlightColor) {
84 unsafe { BNSetFlowGraphNodeHighlight(self.handle, highlight.into()) };
85 }
86
87 pub fn incoming_edges(&self) -> Array<FlowGraphEdge> {
88 let mut count = 0;
89 let result = unsafe { BNGetFlowGraphNodeIncomingEdges(self.handle, &mut count) };
90 assert!(!result.is_null());
91 unsafe { Array::new(result, count, ()) }
92 }
93
94 pub fn outgoing_edges(&self) -> Array<FlowGraphEdge> {
95 let mut count = 0;
96 let result = unsafe { BNGetFlowGraphNodeOutgoingEdges(self.handle, &mut count) };
97 assert!(!result.is_null());
98 unsafe { Array::new(result, count, ()) }
99 }
100
101 pub fn add_outgoing_edge(
103 &self,
104 type_: BranchType,
105 target: &FlowGraphNode,
106 edge_style: EdgeStyle,
107 ) {
108 unsafe {
109 BNAddFlowGraphNodeOutgoingEdge(self.handle, type_, target.handle, edge_style.into())
110 }
111 }
112}
113
114impl Debug for FlowGraphNode {
115 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
116 f.debug_struct("FlowGraphNode")
117 .field("lines", &self.lines().to_vec())
118 .finish()
119 }
120}
121
122unsafe impl RefCountable for FlowGraphNode {
123 unsafe fn inc_ref(handle: &Self) -> Ref<Self> {
124 Ref::new(Self {
125 handle: BNNewFlowGraphNodeReference(handle.handle),
126 })
127 }
128
129 unsafe fn dec_ref(handle: &Self) {
130 BNFreeFlowGraphNode(handle.handle);
131 }
132}
133
134impl ToOwned for FlowGraphNode {
135 type Owned = Ref<Self>;
136
137 fn to_owned(&self) -> Self::Owned {
138 unsafe { RefCountable::inc_ref(self) }
139 }
140}
141
142impl CoreArrayProvider for FlowGraphNode {
143 type Raw = *mut BNFlowGraphNode;
144 type Context = ();
145 type Wrapped<'a> = Guard<'a, FlowGraphNode>;
146}
147
148unsafe impl CoreArrayProviderInner for FlowGraphNode {
149 unsafe fn free(raw: *mut Self::Raw, count: usize, _: &Self::Context) {
150 BNFreeFlowGraphNodeList(raw, count);
151 }
152
153 unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, context: &'a Self::Context) -> Self::Wrapped<'a> {
154 Guard::new(Self::from_raw(*raw), context)
155 }
156}