Skip to content

Commit 0593056

Browse files
emesareCouleeApps
authored andcommitted
Add Render Layer API to Rust
# Conflicts: # rust/src/flowgraph.rs
1 parent 9099142 commit 0593056

File tree

13 files changed

+745
-69
lines changed

13 files changed

+745
-69
lines changed

rust/src/basic_block.rs

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use crate::BranchType;
1919
use binaryninjacore_sys::*;
2020
use std::fmt;
2121
use std::fmt::Debug;
22+
use std::hash::{Hash, Hasher};
2223

2324
enum EdgeDirection {
2425
Incoming,
@@ -97,7 +98,14 @@ pub trait BlockContext: Clone + Sync + Send + Sized {
9798
fn iter(&self, block: &BasicBlock<Self>) -> Self::Iter;
9899
}
99100

100-
#[derive(PartialEq, Eq, Hash)]
101+
#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy, PartialOrd, Ord)]
102+
pub enum BasicBlockType {
103+
Native,
104+
LowLevelIL,
105+
MediumLevelIL,
106+
HighLevelIL,
107+
}
108+
101109
pub struct BasicBlock<C: BlockContext> {
102110
pub(crate) handle: *mut BNBasicBlock,
103111
context: C,
@@ -127,6 +135,19 @@ impl<C: BlockContext> BasicBlock<C> {
127135
}
128136
}
129137

138+
pub fn block_type(&self) -> BasicBlockType {
139+
if unsafe { !BNIsILBasicBlock(self.handle) } {
140+
BasicBlockType::Native
141+
} else if unsafe { BNIsLowLevelILBasicBlock(self.handle) } {
142+
BasicBlockType::LowLevelIL
143+
} else if unsafe { BNIsMediumLevelILBasicBlock(self.handle) } {
144+
BasicBlockType::MediumLevelIL
145+
} else {
146+
// We checked all other IL levels, so this is safe.
147+
BasicBlockType::HighLevelIL
148+
}
149+
}
150+
130151
pub fn iter(&self) -> C::Iter {
131152
self.context.iter(self)
132153
}
@@ -194,7 +215,7 @@ impl<C: BlockContext> BasicBlock<C> {
194215
if block.is_null() {
195216
return None;
196217
}
197-
Some(Ref::new(BasicBlock::from_raw(block, self.context.clone())))
218+
Some(BasicBlock::ref_from_raw(block, self.context.clone()))
198219
}
199220
}
200221

@@ -237,6 +258,24 @@ impl<C: BlockContext> BasicBlock<C> {
237258
// TODO iterated dominance frontier
238259
}
239260

261+
impl<C: BlockContext> Hash for BasicBlock<C> {
262+
fn hash<H: Hasher>(&self, state: &mut H) {
263+
self.function().hash(state);
264+
self.block_type().hash(state);
265+
state.write_usize(self.index());
266+
}
267+
}
268+
269+
impl<C: BlockContext> PartialEq for BasicBlock<C> {
270+
fn eq(&self, other: &Self) -> bool {
271+
self.function() == other.function()
272+
&& self.index() == other.index()
273+
&& self.block_type() == other.block_type()
274+
}
275+
}
276+
277+
impl<C: BlockContext> Eq for BasicBlock<C> {}
278+
240279
impl<C: BlockContext> IntoIterator for &BasicBlock<C> {
241280
type Item = C::Instruction;
242281
type IntoIter = C::Iter;

rust/src/binary_view.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1209,17 +1209,17 @@ pub trait BinaryViewExt: BinaryViewBase {
12091209

12101210
/// Retrieves a list of the next disassembly lines.
12111211
///
1212-
/// `get_next_linear_disassembly_lines` retrieves an [Array] over [LinearDisassemblyLine] objects for the
1213-
/// next disassembly lines, and updates the [LinearViewCursor] passed in. This function can be called
1212+
/// Retrieves an [`Array`] over [`LinearDisassemblyLine`] objects for the
1213+
/// next disassembly lines, and updates the [`LinearViewCursor`] passed in. This function can be called
12141214
/// repeatedly to get more lines of linear disassembly.
12151215
///
12161216
/// # Arguments
12171217
/// * `pos` - Position to retrieve linear disassembly lines from
12181218
fn get_next_linear_disassembly_lines(
12191219
&self,
12201220
pos: &mut LinearViewCursor,
1221-
) -> Array<LinearDisassemblyLine> {
1222-
let mut result = unsafe { Array::new(std::ptr::null_mut(), 0, ()) };
1221+
) -> Array<LinearDisassemblyLine<NativeBlock>> {
1222+
let mut result = unsafe { Array::new(std::ptr::null_mut(), 0, NativeBlock::new()) };
12231223

12241224
while result.is_empty() {
12251225
result = pos.lines();
@@ -1242,8 +1242,8 @@ pub trait BinaryViewExt: BinaryViewBase {
12421242
fn get_previous_linear_disassembly_lines(
12431243
&self,
12441244
pos: &mut LinearViewCursor,
1245-
) -> Array<LinearDisassemblyLine> {
1246-
let mut result = unsafe { Array::new(std::ptr::null_mut(), 0, ()) };
1245+
) -> Array<LinearDisassemblyLine<NativeBlock>> {
1246+
let mut result = unsafe { Array::new(std::ptr::null_mut(), 0, NativeBlock::new()) };
12471247
while result.is_empty() {
12481248
if !pos.previous() {
12491249
return result;

rust/src/collaboration/sync.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -701,7 +701,7 @@ pub fn is_type_archive_snapshot_ignored<S: BnStrCompatible>(
701701
pub fn download_type_archive<S: BnStrCompatible>(
702702
file: &RemoteFile,
703703
location: S,
704-
) -> Result<Option<TypeArchive>, ()> {
704+
) -> Result<Option<Ref<TypeArchive>>, ()> {
705705
download_type_archive_with_progress(file, location, NoProgressCallback)
706706
}
707707

@@ -711,7 +711,7 @@ pub fn download_type_archive_with_progress<S: BnStrCompatible, F: ProgressCallba
711711
file: &RemoteFile,
712712
location: S,
713713
mut progress: F,
714-
) -> Result<Option<TypeArchive>, ()> {
714+
) -> Result<Option<Ref<TypeArchive>>, ()> {
715715
let mut value = std::ptr::null_mut();
716716
let db_path = location.into_bytes_with_nul();
717717
let success = unsafe {
@@ -724,7 +724,7 @@ pub fn download_type_archive_with_progress<S: BnStrCompatible, F: ProgressCallba
724724
)
725725
};
726726
success
727-
.then(|| NonNull::new(value).map(|handle| unsafe { TypeArchive::from_raw(handle) }))
727+
.then(|| NonNull::new(value).map(|handle| unsafe { TypeArchive::ref_from_raw(handle) }))
728728
.ok_or(())
729729
}
730730

rust/src/disassembly.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ pub type DisassemblyOption = BNDisassemblyOption;
3030
pub type InstructionTextTokenType = BNInstructionTextTokenType;
3131
pub type StringType = BNStringType;
3232

33-
#[derive(Clone, PartialEq, Debug, Default)]
33+
#[derive(Clone, PartialEq, Debug, Default, Eq)]
3434
pub struct DisassemblyTextLine {
3535
pub address: u64,
3636
pub instruction_index: usize,
@@ -234,7 +234,7 @@ impl DisassemblyTextLineTypeInfo {
234234
}
235235
}
236236

237-
#[derive(Debug, Clone, PartialEq)]
237+
#[derive(Debug, Clone, PartialEq, Eq)]
238238
pub struct InstructionTextToken {
239239
pub address: u64,
240240
pub text: String,
@@ -882,6 +882,8 @@ impl From<InstructionTextTokenKind> for BNInstructionTextTokenType {
882882
}
883883
}
884884

885+
impl Eq for InstructionTextTokenKind {}
886+
885887
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
886888
pub enum InstructionTextTokenContext {
887889
Normal,

rust/src/flowgraph.rs

Lines changed: 107 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,14 @@
1414

1515
//! Interfaces for creating and displaying pretty CFGs in Binary Ninja.
1616
17-
use binaryninjacore_sys::*;
18-
1917
use crate::disassembly::DisassemblyTextLine;
18+
use binaryninjacore_sys::*;
19+
use std::slice;
2020

2121
use crate::rc::*;
2222

23+
use crate::basic_block::{BasicBlock, BlockContext};
24+
use crate::function::HighlightColor;
2325
use std::marker::PhantomData;
2426

2527
pub type BranchType = BNBranchType;
@@ -37,14 +39,61 @@ impl FlowGraph {
3739
Self { handle: raw }
3840
}
3941

42+
pub(crate) unsafe fn ref_from_raw(raw: *mut BNFlowGraph) -> Ref<Self> {
43+
Ref::new(Self { handle: raw })
44+
}
45+
4046
pub fn new() -> Ref<Self> {
41-
unsafe { Ref::new(FlowGraph::from_raw(BNCreateFlowGraph())) }
47+
unsafe { FlowGraph::ref_from_raw(BNCreateFlowGraph()) }
48+
}
49+
50+
pub fn nodes<'a>(&self) -> Vec<Ref<FlowGraphNode<'a>>> {
51+
let mut count: usize = 0;
52+
let nodes_ptr = unsafe { BNGetFlowGraphNodes(self.handle, &mut count as *mut usize) };
53+
54+
let nodes = unsafe { slice::from_raw_parts_mut(nodes_ptr, count) };
55+
56+
let mut result = vec![];
57+
result.reserve(count);
58+
59+
for i in 0..count {
60+
result.push(unsafe { RefCountable::inc_ref(&FlowGraphNode::from_raw(nodes[i])) });
61+
}
62+
63+
unsafe { BNFreeFlowGraphNodeList(nodes_ptr, count) };
64+
65+
result
66+
}
67+
68+
pub fn get_node<'a>(&self, i: usize) -> Option<Ref<FlowGraphNode<'a>>> {
69+
let node_ptr = unsafe { BNGetFlowGraphNode(self.handle, i) };
70+
if node_ptr.is_null() {
71+
None
72+
} else {
73+
Some(unsafe { Ref::new(FlowGraphNode::from_raw(node_ptr)) })
74+
}
75+
}
76+
77+
pub fn get_node_count(&self) -> usize {
78+
unsafe { BNGetFlowGraphNodeCount(self.handle) }
79+
}
80+
81+
pub fn has_nodes(&self) -> bool {
82+
unsafe { BNFlowGraphHasNodes(self.handle) }
4283
}
4384

4485
pub fn append(&self, node: &FlowGraphNode) -> usize {
4586
unsafe { BNAddFlowGraphNode(self.handle, node.handle) }
4687
}
4788

89+
pub fn replace(&self, index: usize, node: &FlowGraphNode) {
90+
unsafe { BNReplaceFlowGraphNode(self.handle, index, node.handle) }
91+
}
92+
93+
pub fn clear(&self) {
94+
unsafe { BNClearFlowGraphNodes(self.handle) }
95+
}
96+
4897
pub fn set_option(&self, option: FlowGraphOption, value: bool) {
4998
unsafe { BNSetFlowGraphOption(self.handle, option, value) }
5099
}
@@ -88,8 +137,37 @@ impl<'a> FlowGraphNode<'a> {
88137
}
89138
}
90139

91-
pub fn new(graph: &FlowGraph) -> Self {
92-
unsafe { FlowGraphNode::from_raw(BNCreateFlowGraphNode(graph.handle)) }
140+
pub(crate) unsafe fn ref_from_raw(raw: *mut BNFlowGraphNode) -> Ref<Self> {
141+
Ref::new(Self {
142+
handle: raw,
143+
_data: PhantomData,
144+
})
145+
}
146+
147+
pub fn new(graph: &FlowGraph) -> Ref<Self> {
148+
unsafe { FlowGraphNode::ref_from_raw(BNCreateFlowGraphNode(graph.handle)) }
149+
}
150+
151+
pub fn basic_block<C: BlockContext>(&self, context: C) -> Option<Ref<BasicBlock<C>>> {
152+
let block_ptr = unsafe { BNGetFlowGraphBasicBlock(self.handle) };
153+
if block_ptr.is_null() {
154+
return None;
155+
}
156+
Some(unsafe { BasicBlock::ref_from_raw(block_ptr, context) })
157+
}
158+
159+
pub fn set_basic_block<C: BlockContext>(&self, block: Option<&BasicBlock<C>>) {
160+
match block {
161+
Some(block) => unsafe { BNSetFlowGraphBasicBlock(self.handle, block.handle) },
162+
None => unsafe { BNSetFlowGraphBasicBlock(self.handle, std::ptr::null_mut()) },
163+
}
164+
}
165+
166+
pub fn lines(&self) -> Array<DisassemblyTextLine> {
167+
let mut count = 0;
168+
let result = unsafe { BNGetFlowGraphNodeLines(self.handle, &mut count) };
169+
assert!(!result.is_null());
170+
unsafe { Array::new(result, count, ()) }
93171
}
94172

95173
pub fn set_lines(&self, lines: impl IntoIterator<Item = DisassemblyTextLine>) {
@@ -106,6 +184,30 @@ impl<'a> FlowGraphNode<'a> {
106184
}
107185
}
108186

187+
/// Returns the graph position of the node in X, Y form.
188+
pub fn position(&self) -> (i32, i32) {
189+
let pos_x = unsafe { BNGetFlowGraphNodeX(self.handle) };
190+
let pos_y = unsafe { BNGetFlowGraphNodeY(self.handle) };
191+
(pos_x, pos_y)
192+
}
193+
194+
/// Sets the graph position of the node.
195+
pub fn set_position(&self, x: i32, y: i32) {
196+
unsafe { BNFlowGraphNodeSetX(self.handle, x) };
197+
unsafe { BNFlowGraphNodeSetX(self.handle, y) };
198+
}
199+
200+
pub fn highlight_color(&self) -> HighlightColor {
201+
let raw = unsafe { BNGetFlowGraphNodeHighlight(self.handle) };
202+
HighlightColor::from(raw)
203+
}
204+
205+
pub fn set_highlight_color(&self, highlight: HighlightColor) {
206+
unsafe { BNSetFlowGraphNodeHighlight(self.handle, highlight.into()) };
207+
}
208+
209+
// TODO: Add getters and setters for edges
210+
109211
pub fn add_outgoing_edge(
110212
&self,
111213
type_: BranchType,

rust/src/function.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ impl Iterator for NativeBlockIter {
128128
}
129129
}
130130

131-
#[derive(Clone)]
131+
#[derive(Clone, Debug, PartialEq, Eq)]
132132
pub struct NativeBlock {
133133
_priv: (),
134134
}
@@ -2346,7 +2346,7 @@ impl Function {
23462346
/// Flow graph of unresolved stack adjustments
23472347
pub fn unresolved_stack_adjustment_graph(&self) -> Option<Ref<FlowGraph>> {
23482348
let graph = unsafe { BNGetUnresolvedStackAdjustmentGraph(self.handle) };
2349-
(!graph.is_null()).then(|| unsafe { Ref::new(FlowGraph::from_raw(graph)) })
2349+
(!graph.is_null()).then(|| unsafe { FlowGraph::ref_from_raw(graph) })
23502350
}
23512351

23522352
pub fn create_graph(
@@ -2358,7 +2358,7 @@ impl Function {
23582358
let raw_view_type = FunctionViewType::into_raw(view_type);
23592359
let result = unsafe { BNCreateFunctionGraph(self.handle, raw_view_type, settings_raw) };
23602360
FunctionViewType::free_raw(raw_view_type);
2361-
unsafe { Ref::new(FlowGraph::from_raw(result)) }
2361+
unsafe { FlowGraph::ref_from_raw(result) }
23622362
}
23632363

23642364
pub fn parent_components(&self) -> Array<Component> {

rust/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ pub mod project;
6868
pub mod rc;
6969
pub mod references;
7070
pub mod relocation;
71+
pub mod render_layer;
7172
pub mod section;
7273
pub mod segment;
7374
pub mod settings;

0 commit comments

Comments
 (0)