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