Skip to content

Commit ee1010d

Browse files
committed
Add Render Layer API to Rust
1 parent 1869875 commit ee1010d

File tree

13 files changed

+703
-70
lines changed

13 files changed

+703
-70
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: 65 additions & 6 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 crate::disassembly::DisassemblyTextLine;
1718
use binaryninjacore_sys::*;
1819
use std::slice;
19-
use crate::disassembly::DisassemblyTextLine;
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,15 +39,19 @@ 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()) }
4248
}
4349

4450
pub fn nodes<'a>(&self) -> Vec<Ref<FlowGraphNode<'a>>> {
4551
let mut count: usize = 0;
46-
let mut nodes_ptr = unsafe { BNGetFlowGraphNodes(self.handle, &mut count as *mut usize) };
52+
let nodes_ptr = unsafe { BNGetFlowGraphNodes(self.handle, &mut count as *mut usize) };
4753

48-
let mut nodes = unsafe { slice::from_raw_parts_mut(nodes_ptr, count) };
54+
let nodes = unsafe { slice::from_raw_parts_mut(nodes_ptr, count) };
4955

5056
let mut result = vec![];
5157
result.reserve(count);
@@ -131,8 +137,37 @@ impl<'a> FlowGraphNode<'a> {
131137
}
132138
}
133139

134-
pub fn new(graph: &FlowGraph) -> Self {
135-
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, ()) }
136171
}
137172

138173
pub fn set_lines(&self, lines: impl IntoIterator<Item = DisassemblyTextLine>) {
@@ -149,6 +184,30 @@ impl<'a> FlowGraphNode<'a> {
149184
}
150185
}
151186

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+
152211
pub fn add_outgoing_edge(
153212
&self,
154213
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)