binaryninja/flowgraph/
node.rs1use crate::architecture::BranchType;
4use crate::basic_block::{BasicBlock, BlockContext};
5use crate::disassembly::DisassemblyTextLine;
6use crate::flowgraph::edge::{EdgeStyle, FlowGraphEdge, Point};
7use crate::flowgraph::FlowGraph;
8use crate::function::HighlightColor;
9use crate::rc::{Array, CoreArrayProvider, CoreArrayProviderInner, Ref, RefCountable};
10use binaryninjacore_sys::*;
11use std::fmt::{Debug, Formatter};
12use std::hash::Hash;
13
14#[allow(unused)]
16use crate::flowgraph::layout::FlowGraphLayout;
17
18#[repr(transparent)]
24#[derive(PartialEq, Eq, Hash)]
25pub struct FlowGraphNode {
26 pub(crate) handle: *mut BNFlowGraphNode,
27}
28
29impl FlowGraphNode {
30 pub(crate) unsafe fn from_raw(raw: *mut BNFlowGraphNode) -> Self {
31 Self { handle: raw }
32 }
33
34 pub(crate) unsafe fn ref_from_raw(raw: *mut BNFlowGraphNode) -> Ref<Self> {
35 Ref::new(Self { handle: raw })
36 }
37
38 pub fn new(graph: &FlowGraph) -> Ref<Self> {
39 unsafe { FlowGraphNode::ref_from_raw(BNCreateFlowGraphNode(graph.handle)) }
40 }
41
42 pub fn basic_block<C: BlockContext>(&self, context: C) -> Option<Ref<BasicBlock<C>>> {
43 let block_ptr = unsafe { BNGetFlowGraphBasicBlock(self.handle) };
44 if block_ptr.is_null() {
45 return None;
46 }
47 Some(unsafe { BasicBlock::ref_from_raw(block_ptr, context) })
48 }
49
50 pub fn set_basic_block<C: BlockContext>(&self, block: Option<&BasicBlock<C>>) {
51 match block {
52 Some(block) => unsafe { BNSetFlowGraphBasicBlock(self.handle, block.handle) },
53 None => unsafe { BNSetFlowGraphBasicBlock(self.handle, std::ptr::null_mut()) },
54 }
55 }
56
57 pub fn lines(&self) -> Array<DisassemblyTextLine> {
58 let mut count = 0;
59 let result = unsafe { BNGetFlowGraphNodeLines(self.handle, &mut count) };
60 assert!(!result.is_null());
61 unsafe { Array::new(result, count, ()) }
62 }
63
64 pub fn set_lines(&self, lines: impl IntoIterator<Item = DisassemblyTextLine>) {
65 let mut raw_lines: Vec<BNDisassemblyTextLine> = lines
67 .into_iter()
68 .map(DisassemblyTextLine::into_raw)
69 .collect();
70 unsafe {
71 BNSetFlowGraphNodeLines(self.handle, raw_lines.as_mut_ptr(), raw_lines.len());
72 for raw_line in raw_lines {
73 DisassemblyTextLine::free_raw(raw_line);
74 }
75 }
76 }
77
78 pub fn position(&self) -> (i32, i32) {
80 let pos_x = unsafe { BNGetFlowGraphNodeX(self.handle) };
81 let pos_y = unsafe { BNGetFlowGraphNodeY(self.handle) };
82 (pos_x, pos_y)
83 }
84
85 pub fn size(&self) -> (i32, i32) {
87 let w = unsafe { BNGetFlowGraphNodeWidth(self.handle) };
88 let h = unsafe { BNGetFlowGraphNodeHeight(self.handle) };
89 (w, h)
90 }
91
92 pub fn set_position(&self, x: i32, y: i32) {
94 unsafe { BNFlowGraphNodeSetX(self.handle, x) };
95 unsafe { BNFlowGraphNodeSetY(self.handle, y) };
96 }
97
98 pub fn highlight_color(&self) -> HighlightColor {
99 let raw = unsafe { BNGetFlowGraphNodeHighlight(self.handle) };
100 HighlightColor::from(raw)
101 }
102
103 pub fn set_highlight_color(&self, highlight: HighlightColor) {
104 unsafe { BNSetFlowGraphNodeHighlight(self.handle, highlight.into()) };
105 }
106
107 pub fn incoming_edges(&self) -> Array<FlowGraphEdge> {
109 let mut count = 0;
110 let result = unsafe { BNGetFlowGraphNodeIncomingEdges(self.handle, &mut count) };
111 assert!(!result.is_null());
112 unsafe { Array::new(result, count, ()) }
113 }
114
115 pub fn outgoing_edges(&self) -> Array<FlowGraphEdge> {
117 let mut count = 0;
118 let result = unsafe { BNGetFlowGraphNodeOutgoingEdges(self.handle, &mut count) };
119 assert!(!result.is_null());
120 unsafe { Array::new(result, count, ()) }
121 }
122
123 pub fn add_outgoing_edge(
125 &self,
126 type_: BranchType,
127 target: &FlowGraphNode,
128 edge_style: EdgeStyle,
129 ) {
130 unsafe {
131 BNAddFlowGraphNodeOutgoingEdge(self.handle, type_, target.handle, edge_style.into())
132 }
133 }
134
135 pub fn set_outgoing_edge_points(&self, edge_idx: usize, points: &[Point]) {
141 let mut points_raw: Vec<BNPoint> = points.iter().map(|p| (*p).into()).collect();
142 unsafe {
143 BNFlowGraphNodeSetOutgoingEdgePoints(
144 self.handle,
145 edge_idx,
146 points_raw.as_mut_ptr(),
147 points.len(),
148 )
149 };
150 }
151
152 pub fn set_visibility_region(&self, x: i32, y: i32, w: i32, h: i32) {
162 unsafe { BNFlowGraphNodeSetVisibilityRegion(self.handle, x, y, w, h) };
163 }
164}
165
166impl Debug for FlowGraphNode {
167 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
168 f.debug_struct("FlowGraphNode")
169 .field("lines", &self.lines().to_vec())
170 .finish()
171 }
172}
173
174unsafe impl RefCountable for FlowGraphNode {
175 unsafe fn inc_ref(handle: &Self) -> Ref<Self> {
176 Ref::new(Self {
177 handle: BNNewFlowGraphNodeReference(handle.handle),
178 })
179 }
180
181 unsafe fn dec_ref(handle: &Self) {
182 BNFreeFlowGraphNode(handle.handle);
183 }
184}
185
186impl ToOwned for FlowGraphNode {
187 type Owned = Ref<Self>;
188
189 fn to_owned(&self) -> Self::Owned {
190 unsafe { RefCountable::inc_ref(self) }
191 }
192}
193
194impl CoreArrayProvider for FlowGraphNode {
195 type Raw = *mut BNFlowGraphNode;
196 type Context = ();
197 type Wrapped<'a> = FlowGraphNode;
198}
199
200unsafe impl CoreArrayProviderInner for FlowGraphNode {
201 unsafe fn free(raw: *mut Self::Raw, count: usize, _: &Self::Context) {
202 BNFreeFlowGraphNodeList(raw, count);
203 }
204
205 unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
206 Self::from_raw(*raw)
207 }
208}