Skip to content

Commit cd67472

Browse files
committed
[Rust] Clarify and expand on the current set of queryable offset properties
Now that we have more duplicate API's we need to clarify and cross link between them to help alleviate the confusion for readers.
1 parent 979ba31 commit cd67472

File tree

3 files changed

+146
-87
lines changed

3 files changed

+146
-87
lines changed

rust/src/binary_view.rs

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@
2323
2424
use binaryninjacore_sys::*;
2525

26+
// Used for documentation
27+
#[allow(unused)]
28+
pub use crate::workflow::AnalysisContext;
29+
2630
use crate::architecture::{Architecture, CoreArchitecture};
2731
use crate::base_detection::BaseAddressDetection;
2832
use crate::basic_block::BasicBlock;
@@ -447,14 +451,29 @@ pub trait BinaryViewExt: BinaryViewBase {
447451
}
448452
}
449453

454+
/// Consults the [`Section`]'s current [`crate::section::Semantics`] to determine if the
455+
/// offset has code semantics.
450456
fn offset_has_code_semantics(&self, offset: u64) -> bool {
451457
unsafe { BNIsOffsetCodeSemantics(self.as_ref().handle, offset) }
452458
}
453459

460+
/// Check if the offset is within a [`Section`] with [`crate::section::Semantics::External`].
461+
fn offset_has_extern_semantics(&self, offset: u64) -> bool {
462+
unsafe { BNIsOffsetExternSemantics(self.as_ref().handle, offset) }
463+
}
464+
465+
/// Consults the [`Section`]'s current [`crate::section::Semantics`] to determine if the
466+
/// offset has writable semantics.
454467
fn offset_has_writable_semantics(&self, offset: u64) -> bool {
455468
unsafe { BNIsOffsetWritableSemantics(self.as_ref().handle, offset) }
456469
}
457470

471+
/// Consults the [`Section`]'s current [`crate::section::Semantics`] to determine if the
472+
/// offset has read only semantics.
473+
fn offset_has_read_only_semantics(&self, offset: u64) -> bool {
474+
unsafe { BNIsOffsetExternSemantics(self.as_ref().handle, offset) }
475+
}
476+
458477
fn image_base(&self) -> u64 {
459478
unsafe { BNGetImageBase(self.as_ref().handle) }
460479
}
@@ -467,6 +486,9 @@ pub trait BinaryViewExt: BinaryViewBase {
467486
unsafe { BNSetOriginalImageBase(self.as_ref().handle, image_base) }
468487
}
469488

489+
/// The highest address in the view.
490+
///
491+
/// NOTE: If operating within a [`Workflow`], consider using [`AnalysisContext::end`].
470492
fn end(&self) -> u64 {
471493
unsafe { BNGetEndOffset(self.as_ref().handle) }
472494
}
@@ -2371,26 +2393,45 @@ impl BinaryViewBase for BinaryView {
23712393
unsafe { BNRemoveViewData(self.handle, offset, len as u64) }
23722394
}
23732395

2396+
/// Check if the offset is valid for the current view.
2397+
///
2398+
/// NOTE: If operating within a [`Workflow`], consider using [`AnalysisContext::is_offset_valid`].
23742399
fn offset_valid(&self, offset: u64) -> bool {
23752400
unsafe { BNIsValidOffset(self.handle, offset) }
23762401
}
23772402

2403+
/// Check if the offset is readable for the current view.
2404+
///
2405+
/// NOTE: If operating within a [`Workflow`], consider using [`AnalysisContext::is_offset_valid`].
23782406
fn offset_readable(&self, offset: u64) -> bool {
23792407
unsafe { BNIsOffsetReadable(self.handle, offset) }
23802408
}
23812409

2410+
/// Check if the offset is writable for the current view.
2411+
///
2412+
/// NOTE: If operating within a [`Workflow`], consider using [`AnalysisContext::is_offset_writable`].
23822413
fn offset_writable(&self, offset: u64) -> bool {
23832414
unsafe { BNIsOffsetWritable(self.handle, offset) }
23842415
}
23852416

2417+
/// Check if the offset is executable for the current view.
2418+
///
2419+
/// NOTE: If operating within a [`Workflow`], consider using [`AnalysisContext::is_offset_executable`].
23862420
fn offset_executable(&self, offset: u64) -> bool {
23872421
unsafe { BNIsOffsetExecutable(self.handle, offset) }
23882422
}
23892423

2424+
/// Check if the offset is backed by the original file and not added after the fact.
2425+
///
2426+
/// NOTE: If operating within a [`Workflow`], consider using [`AnalysisContext::is_offset_backed_by_file`].
23902427
fn offset_backed_by_file(&self, offset: u64) -> bool {
23912428
unsafe { BNIsOffsetBackedByFile(self.handle, offset) }
23922429
}
23932430

2431+
/// Get the next valid offset after the provided `offset`, useful if you need to iterate over all
2432+
/// readable offsets in the view.
2433+
///
2434+
/// NOTE: If operating within a [`Workflow`], consider using [`AnalysisContext::next_valid_offset`].
23942435
fn next_valid_offset_after(&self, offset: u64) -> u64 {
23952436
unsafe { BNGetNextValidOffset(self.handle, offset) }
23962437
}
@@ -2399,10 +2440,16 @@ impl BinaryViewBase for BinaryView {
23992440
unsafe { BNGetModification(self.handle, offset) }
24002441
}
24012442

2443+
/// The lowest address in the view.
2444+
///
2445+
/// NOTE: If operating within a [`Workflow`], consider using [`AnalysisContext::start`].
24022446
fn start(&self) -> u64 {
24032447
unsafe { BNGetStartOffset(self.handle) }
24042448
}
24052449

2450+
/// The length of the view, lowest to highest address.
2451+
///
2452+
/// NOTE: If operating within a [`Workflow`], consider using [`AnalysisContext::length`].
24062453
fn len(&self) -> u64 {
24072454
unsafe { BNGetViewLength(self.handle) }
24082455
}
@@ -2582,3 +2629,43 @@ unsafe impl CoreArrayProviderInner for StringReference {
25822629
Self::from(*raw)
25832630
}
25842631
}
2632+
2633+
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
2634+
pub struct AddressRange {
2635+
pub start: u64,
2636+
pub end: u64,
2637+
}
2638+
2639+
impl From<BNAddressRange> for AddressRange {
2640+
fn from(raw: BNAddressRange) -> Self {
2641+
Self {
2642+
start: raw.start,
2643+
end: raw.end,
2644+
}
2645+
}
2646+
}
2647+
2648+
impl From<AddressRange> for BNAddressRange {
2649+
fn from(raw: AddressRange) -> Self {
2650+
Self {
2651+
start: raw.start,
2652+
end: raw.end,
2653+
}
2654+
}
2655+
}
2656+
2657+
impl CoreArrayProvider for AddressRange {
2658+
type Raw = BNAddressRange;
2659+
type Context = ();
2660+
type Wrapped<'a> = Self;
2661+
}
2662+
2663+
unsafe impl CoreArrayProviderInner for AddressRange {
2664+
unsafe fn free(raw: *mut Self::Raw, _count: usize, _context: &Self::Context) {
2665+
BNFreeAddressRanges(raw);
2666+
}
2667+
2668+
unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
2669+
Self::from(*raw)
2670+
}
2671+
}

rust/src/function.rs

Lines changed: 1 addition & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ pub use binaryninjacore_sys::BNFunctionUpdateType as FunctionUpdateType;
3838
pub use binaryninjacore_sys::BNHighlightStandardColor as HighlightStandardColor;
3939

4040
use crate::architecture::RegisterId;
41+
use crate::binary_view::AddressRange;
4142
use crate::confidence::Conf;
4243
use crate::high_level_il::HighLevelILFunction;
4344
use crate::language_representation::CoreLanguageRepresentationFunction;
@@ -373,7 +374,6 @@ impl Function {
373374
unsafe {
374375
let mut count = 0;
375376
let addresses = BNGetFunctionAddressRanges(self.handle, &mut count);
376-
377377
Array::new(addresses, count, ())
378378
}
379379
}
@@ -2684,46 +2684,6 @@ impl PartialEq for Function {
26842684
}
26852685
}
26862686

2687-
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
2688-
pub struct AddressRange {
2689-
pub start: u64,
2690-
pub end: u64,
2691-
}
2692-
2693-
impl From<BNAddressRange> for AddressRange {
2694-
fn from(raw: BNAddressRange) -> Self {
2695-
Self {
2696-
start: raw.start,
2697-
end: raw.end,
2698-
}
2699-
}
2700-
}
2701-
2702-
impl From<AddressRange> for BNAddressRange {
2703-
fn from(raw: AddressRange) -> Self {
2704-
Self {
2705-
start: raw.start,
2706-
end: raw.end,
2707-
}
2708-
}
2709-
}
2710-
2711-
impl CoreArrayProvider for AddressRange {
2712-
type Raw = BNAddressRange;
2713-
type Context = ();
2714-
type Wrapped<'a> = Self;
2715-
}
2716-
2717-
unsafe impl CoreArrayProviderInner for AddressRange {
2718-
unsafe fn free(raw: *mut Self::Raw, _count: usize, _context: &Self::Context) {
2719-
BNFreeAddressRanges(raw);
2720-
}
2721-
2722-
unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
2723-
Self::from(*raw)
2724-
}
2725-
}
2726-
27272687
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
27282688
pub struct PerformanceInfo {
27292689
pub name: String,

rust/src/workflow.rs

Lines changed: 58 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,18 @@
11
use binaryninjacore_sys::*;
22

3+
// Needed for documentation.
4+
#[allow(unused)]
5+
use crate::binary_view::{memory_map::MemoryMap, BinaryViewBase, BinaryViewExt};
6+
37
use crate::basic_block::BasicBlock;
4-
use crate::binary_view::BinaryView;
8+
use crate::binary_view::{AddressRange, BinaryView};
59
use crate::flowgraph::FlowGraph;
610
use crate::function::{Function, NativeBlock};
711
use crate::high_level_il::HighLevelILFunction;
812
use crate::low_level_il::{LowLevelILMutableFunction, LowLevelILRegularFunction};
913
use crate::medium_level_il::MediumLevelILFunction;
1014
use crate::rc::{Array, CoreArrayProvider, CoreArrayProviderInner, Guard, Ref, RefCountable};
11-
use crate::segment::Segment;
15+
use crate::segment::{Segment, SegmentFlags};
1216
use crate::string::{BnString, IntoCStr};
1317
use std::ffi::c_char;
1418
use std::ptr;
@@ -176,65 +180,87 @@ impl AnalysisContext {
176180
}
177181
}
178182

179-
// Memory map access - lock-free access to cached MemoryMap
180-
181-
/// Check if an offset is mapped in the cached memory map
182-
pub fn is_valid_offset(&self, offset: u64) -> bool {
183+
/// Check if an offset is mapped in the cached [`MemoryMap`].
184+
///
185+
/// NOTE: This is a lock-free alternative to [`BinaryView::offset_valid`].
186+
pub fn is_offset_valid(&self, offset: u64) -> bool {
183187
unsafe { BNAnalysisContextIsValidOffset(self.handle.as_ptr(), offset) }
184188
}
185189

186-
/// Check if an offset is readable in the cached memory map
190+
/// Check if an offset is readable in the cached [`MemoryMap`].
191+
///
192+
/// NOTE: This is a lock-free alternative to [`BinaryView::offset_readable`].
187193
pub fn is_offset_readable(&self, offset: u64) -> bool {
188194
unsafe { BNAnalysisContextIsOffsetReadable(self.handle.as_ptr(), offset) }
189195
}
190196

191-
/// Check if an offset is writable in the cached memory map
197+
/// Check if an offset is writable in the cached [`MemoryMap`].
198+
///
199+
/// NOTE: This is a lock-free alternative to [`BinaryView::offset_writable`].
192200
pub fn is_offset_writable(&self, offset: u64) -> bool {
193201
unsafe { BNAnalysisContextIsOffsetWritable(self.handle.as_ptr(), offset) }
194202
}
195203

196-
/// Check if an offset is executable in the cached memory map
204+
/// Check if an offset is executable in the cached [`MemoryMap`].
205+
///
206+
/// NOTE: This is a lock-free alternative to [`BinaryView::offset_executable`].
197207
pub fn is_offset_executable(&self, offset: u64) -> bool {
198208
unsafe { BNAnalysisContextIsOffsetExecutable(self.handle.as_ptr(), offset) }
199209
}
200210

201-
/// Check if an offset is backed by file in the cached memory map
211+
/// Check if an offset is backed by file in the cached [`MemoryMap`].
212+
///
213+
/// NOTE: This is a lock-free alternative to [`BinaryView::offset_backed_by_file`].
202214
pub fn is_offset_backed_by_file(&self, offset: u64) -> bool {
203215
unsafe { BNAnalysisContextIsOffsetBackedByFile(self.handle.as_ptr(), offset) }
204216
}
205217

206-
/// Get the start address from the cached memory map
207-
pub fn get_start(&self) -> u64 {
218+
/// Get the start address (the lowest address) from the cached [`MemoryMap`].
219+
///
220+
/// NOTE: This is a lock-free alternative to [`BinaryView::start`].
221+
pub fn start(&self) -> u64 {
208222
unsafe { BNAnalysisContextGetStart(self.handle.as_ptr()) }
209223
}
210224

211-
/// Get the end address from the cached memory map
212-
pub fn get_end(&self) -> u64 {
225+
/// Get the end address (the highest address) from the cached [`MemoryMap`].
226+
///
227+
/// NOTE: This is a lock-free alternative to [`BinaryViewBase::end`].
228+
pub fn end(&self) -> u64 {
213229
unsafe { BNAnalysisContextGetEnd(self.handle.as_ptr()) }
214230
}
215231

216-
/// Get the length of the cached memory map
217-
pub fn get_length(&self) -> u64 {
232+
/// Get the length of the cached [`MemoryMap`].
233+
///
234+
/// NOTE: This is a lock-free alternative to [`BinaryViewBase::len`].
235+
pub fn length(&self) -> u64 {
218236
unsafe { BNAnalysisContextGetLength(self.handle.as_ptr()) }
219237
}
220238

221-
/// Get the next valid offset after the given offset from the cached memory map
222-
pub fn get_next_valid_offset(&self, offset: u64) -> u64 {
239+
/// Get the next valid offset after the given offset from the cached [`MemoryMap`].
240+
///
241+
/// NOTE: This is a lock-free alternative to [`BinaryView::next_valid_offset_after`].
242+
pub fn next_valid_offset(&self, offset: u64) -> u64 {
223243
unsafe { BNAnalysisContextGetNextValidOffset(self.handle.as_ptr(), offset) }
224244
}
225245

226-
/// Get the next mapped address after the given address from the cached memory map
227-
pub fn get_next_mapped_address(&self, addr: u64, flags: u32) -> u64 {
228-
unsafe { BNAnalysisContextGetNextMappedAddress(self.handle.as_ptr(), addr, flags) }
246+
/// Get the next mapped address after the given address from the cached [`MemoryMap`].
247+
pub fn next_mapped_address(&self, addr: u64, flags: &SegmentFlags) -> u64 {
248+
unsafe {
249+
BNAnalysisContextGetNextMappedAddress(self.handle.as_ptr(), addr, flags.into_raw())
250+
}
229251
}
230252

231-
/// Get the next backed address after the given address from the cached memory map
232-
pub fn get_next_backed_address(&self, addr: u64, flags: u32) -> u64 {
233-
unsafe { BNAnalysisContextGetNextBackedAddress(self.handle.as_ptr(), addr, flags) }
253+
/// Get the next backed address after the given address from the cached [`MemoryMap`].
254+
pub fn next_backed_address(&self, addr: u64, flags: &SegmentFlags) -> u64 {
255+
unsafe {
256+
BNAnalysisContextGetNextBackedAddress(self.handle.as_ptr(), addr, flags.into_raw())
257+
}
234258
}
235259

236-
/// Get the segment containing the given address from the cached memory map
237-
pub fn get_segment_at(&self, addr: u64) -> Option<Ref<Segment>> {
260+
/// Get the segment containing the given address from the cached [`MemoryMap`].
261+
///
262+
/// NOTE: This is a lock-free alternative to [`BinaryView::segment_at`].
263+
pub fn segment_at(&self, addr: u64) -> Option<Ref<Segment>> {
238264
unsafe {
239265
let result = BNAnalysisContextGetSegmentAt(self.handle.as_ptr(), addr);
240266
if result.is_null() {
@@ -245,35 +271,21 @@ impl AnalysisContext {
245271
}
246272
}
247273

248-
/// Get all mapped address ranges from the cached memory map
249-
pub fn get_mapped_address_ranges(&self) -> Vec<(u64, u64)> {
274+
/// Get all mapped address ranges from the cached [`MemoryMap`].
275+
pub fn mapped_address_ranges(&self) -> Array<AddressRange> {
250276
unsafe {
251277
let mut count = 0;
252278
let ranges = BNAnalysisContextGetMappedAddressRanges(self.handle.as_ptr(), &mut count);
253-
let result = (0..count)
254-
.map(|i| {
255-
let range = *ranges.add(i);
256-
(range.start, range.end)
257-
})
258-
.collect();
259-
BNFreeAddressRanges(ranges);
260-
result
279+
Array::new(ranges, count, ())
261280
}
262281
}
263282

264-
/// Get all backed address ranges from the cached memory map
265-
pub fn get_backed_address_ranges(&self) -> Vec<(u64, u64)> {
283+
/// Get all backed address ranges from the cached [`MemoryMap`].
284+
pub fn backed_address_ranges(&self) -> Array<AddressRange> {
266285
unsafe {
267286
let mut count = 0;
268287
let ranges = BNAnalysisContextGetBackedAddressRanges(self.handle.as_ptr(), &mut count);
269-
let result = (0..count)
270-
.map(|i| {
271-
let range = *ranges.add(i);
272-
(range.start, range.end)
273-
})
274-
.collect();
275-
BNFreeAddressRanges(ranges);
276-
result
288+
Array::new(ranges, count, ())
277289
}
278290
}
279291
}

0 commit comments

Comments
 (0)