summaryrefslogtreecommitdiff
path: root/rust/src
diff options
context:
space:
mode:
Diffstat (limited to 'rust/src')
-rw-r--r--rust/src/binary_view.rs87
-rw-r--r--rust/src/function.rs42
-rw-r--r--rust/src/workflow.rs104
3 files changed, 146 insertions, 87 deletions
diff --git a/rust/src/binary_view.rs b/rust/src/binary_view.rs
index 593c1c4b..4fb07ded 100644
--- a/rust/src/binary_view.rs
+++ b/rust/src/binary_view.rs
@@ -23,6 +23,10 @@
use binaryninjacore_sys::*;
+// Used for documentation
+#[allow(unused)]
+pub use crate::workflow::AnalysisContext;
+
use crate::architecture::{Architecture, CoreArchitecture};
use crate::base_detection::BaseAddressDetection;
use crate::basic_block::BasicBlock;
@@ -447,14 +451,29 @@ pub trait BinaryViewExt: BinaryViewBase {
}
}
+ /// Consults the [`Section`]'s current [`crate::section::Semantics`] to determine if the
+ /// offset has code semantics.
fn offset_has_code_semantics(&self, offset: u64) -> bool {
unsafe { BNIsOffsetCodeSemantics(self.as_ref().handle, offset) }
}
+ /// Check if the offset is within a [`Section`] with [`crate::section::Semantics::External`].
+ fn offset_has_extern_semantics(&self, offset: u64) -> bool {
+ unsafe { BNIsOffsetExternSemantics(self.as_ref().handle, offset) }
+ }
+
+ /// Consults the [`Section`]'s current [`crate::section::Semantics`] to determine if the
+ /// offset has writable semantics.
fn offset_has_writable_semantics(&self, offset: u64) -> bool {
unsafe { BNIsOffsetWritableSemantics(self.as_ref().handle, offset) }
}
+ /// Consults the [`Section`]'s current [`crate::section::Semantics`] to determine if the
+ /// offset has read only semantics.
+ fn offset_has_read_only_semantics(&self, offset: u64) -> bool {
+ unsafe { BNIsOffsetExternSemantics(self.as_ref().handle, offset) }
+ }
+
fn image_base(&self) -> u64 {
unsafe { BNGetImageBase(self.as_ref().handle) }
}
@@ -467,6 +486,9 @@ pub trait BinaryViewExt: BinaryViewBase {
unsafe { BNSetOriginalImageBase(self.as_ref().handle, image_base) }
}
+ /// The highest address in the view.
+ ///
+ /// NOTE: If operating within a [`Workflow`], consider using [`AnalysisContext::end`].
fn end(&self) -> u64 {
unsafe { BNGetEndOffset(self.as_ref().handle) }
}
@@ -2371,26 +2393,45 @@ impl BinaryViewBase for BinaryView {
unsafe { BNRemoveViewData(self.handle, offset, len as u64) }
}
+ /// Check if the offset is valid for the current view.
+ ///
+ /// NOTE: If operating within a [`Workflow`], consider using [`AnalysisContext::is_offset_valid`].
fn offset_valid(&self, offset: u64) -> bool {
unsafe { BNIsValidOffset(self.handle, offset) }
}
+ /// Check if the offset is readable for the current view.
+ ///
+ /// NOTE: If operating within a [`Workflow`], consider using [`AnalysisContext::is_offset_valid`].
fn offset_readable(&self, offset: u64) -> bool {
unsafe { BNIsOffsetReadable(self.handle, offset) }
}
+ /// Check if the offset is writable for the current view.
+ ///
+ /// NOTE: If operating within a [`Workflow`], consider using [`AnalysisContext::is_offset_writable`].
fn offset_writable(&self, offset: u64) -> bool {
unsafe { BNIsOffsetWritable(self.handle, offset) }
}
+ /// Check if the offset is executable for the current view.
+ ///
+ /// NOTE: If operating within a [`Workflow`], consider using [`AnalysisContext::is_offset_executable`].
fn offset_executable(&self, offset: u64) -> bool {
unsafe { BNIsOffsetExecutable(self.handle, offset) }
}
+ /// Check if the offset is backed by the original file and not added after the fact.
+ ///
+ /// NOTE: If operating within a [`Workflow`], consider using [`AnalysisContext::is_offset_backed_by_file`].
fn offset_backed_by_file(&self, offset: u64) -> bool {
unsafe { BNIsOffsetBackedByFile(self.handle, offset) }
}
+ /// Get the next valid offset after the provided `offset`, useful if you need to iterate over all
+ /// readable offsets in the view.
+ ///
+ /// NOTE: If operating within a [`Workflow`], consider using [`AnalysisContext::next_valid_offset`].
fn next_valid_offset_after(&self, offset: u64) -> u64 {
unsafe { BNGetNextValidOffset(self.handle, offset) }
}
@@ -2399,10 +2440,16 @@ impl BinaryViewBase for BinaryView {
unsafe { BNGetModification(self.handle, offset) }
}
+ /// The lowest address in the view.
+ ///
+ /// NOTE: If operating within a [`Workflow`], consider using [`AnalysisContext::start`].
fn start(&self) -> u64 {
unsafe { BNGetStartOffset(self.handle) }
}
+ /// The length of the view, lowest to highest address.
+ ///
+ /// NOTE: If operating within a [`Workflow`], consider using [`AnalysisContext::length`].
fn len(&self) -> u64 {
unsafe { BNGetViewLength(self.handle) }
}
@@ -2582,3 +2629,43 @@ unsafe impl CoreArrayProviderInner for StringReference {
Self::from(*raw)
}
}
+
+#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
+pub struct AddressRange {
+ pub start: u64,
+ pub end: u64,
+}
+
+impl From<BNAddressRange> for AddressRange {
+ fn from(raw: BNAddressRange) -> Self {
+ Self {
+ start: raw.start,
+ end: raw.end,
+ }
+ }
+}
+
+impl From<AddressRange> for BNAddressRange {
+ fn from(raw: AddressRange) -> Self {
+ Self {
+ start: raw.start,
+ end: raw.end,
+ }
+ }
+}
+
+impl CoreArrayProvider for AddressRange {
+ type Raw = BNAddressRange;
+ type Context = ();
+ type Wrapped<'a> = Self;
+}
+
+unsafe impl CoreArrayProviderInner for AddressRange {
+ unsafe fn free(raw: *mut Self::Raw, _count: usize, _context: &Self::Context) {
+ BNFreeAddressRanges(raw);
+ }
+
+ unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
+ Self::from(*raw)
+ }
+}
diff --git a/rust/src/function.rs b/rust/src/function.rs
index c0e00bd1..80de8e6d 100644
--- a/rust/src/function.rs
+++ b/rust/src/function.rs
@@ -38,6 +38,7 @@ pub use binaryninjacore_sys::BNFunctionUpdateType as FunctionUpdateType;
pub use binaryninjacore_sys::BNHighlightStandardColor as HighlightStandardColor;
use crate::architecture::RegisterId;
+use crate::binary_view::AddressRange;
use crate::confidence::Conf;
use crate::high_level_il::HighLevelILFunction;
use crate::language_representation::CoreLanguageRepresentationFunction;
@@ -373,7 +374,6 @@ impl Function {
unsafe {
let mut count = 0;
let addresses = BNGetFunctionAddressRanges(self.handle, &mut count);
-
Array::new(addresses, count, ())
}
}
@@ -2684,46 +2684,6 @@ impl PartialEq for Function {
}
}
-#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-pub struct AddressRange {
- pub start: u64,
- pub end: u64,
-}
-
-impl From<BNAddressRange> for AddressRange {
- fn from(raw: BNAddressRange) -> Self {
- Self {
- start: raw.start,
- end: raw.end,
- }
- }
-}
-
-impl From<AddressRange> for BNAddressRange {
- fn from(raw: AddressRange) -> Self {
- Self {
- start: raw.start,
- end: raw.end,
- }
- }
-}
-
-impl CoreArrayProvider for AddressRange {
- type Raw = BNAddressRange;
- type Context = ();
- type Wrapped<'a> = Self;
-}
-
-unsafe impl CoreArrayProviderInner for AddressRange {
- unsafe fn free(raw: *mut Self::Raw, _count: usize, _context: &Self::Context) {
- BNFreeAddressRanges(raw);
- }
-
- unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
- Self::from(*raw)
- }
-}
-
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct PerformanceInfo {
pub name: String,
diff --git a/rust/src/workflow.rs b/rust/src/workflow.rs
index 2fd02e09..adc8d4ba 100644
--- a/rust/src/workflow.rs
+++ b/rust/src/workflow.rs
@@ -1,14 +1,18 @@
use binaryninjacore_sys::*;
+// Needed for documentation.
+#[allow(unused)]
+use crate::binary_view::{memory_map::MemoryMap, BinaryViewBase, BinaryViewExt};
+
use crate::basic_block::BasicBlock;
-use crate::binary_view::BinaryView;
+use crate::binary_view::{AddressRange, BinaryView};
use crate::flowgraph::FlowGraph;
use crate::function::{Function, NativeBlock};
use crate::high_level_il::HighLevelILFunction;
use crate::low_level_il::{LowLevelILMutableFunction, LowLevelILRegularFunction};
use crate::medium_level_il::MediumLevelILFunction;
use crate::rc::{Array, CoreArrayProvider, CoreArrayProviderInner, Guard, Ref, RefCountable};
-use crate::segment::Segment;
+use crate::segment::{Segment, SegmentFlags};
use crate::string::{BnString, IntoCStr};
use std::ffi::c_char;
use std::ptr;
@@ -176,65 +180,87 @@ impl AnalysisContext {
}
}
- // Memory map access - lock-free access to cached MemoryMap
-
- /// Check if an offset is mapped in the cached memory map
- pub fn is_valid_offset(&self, offset: u64) -> bool {
+ /// Check if an offset is mapped in the cached [`MemoryMap`].
+ ///
+ /// NOTE: This is a lock-free alternative to [`BinaryView::offset_valid`].
+ pub fn is_offset_valid(&self, offset: u64) -> bool {
unsafe { BNAnalysisContextIsValidOffset(self.handle.as_ptr(), offset) }
}
- /// Check if an offset is readable in the cached memory map
+ /// Check if an offset is readable in the cached [`MemoryMap`].
+ ///
+ /// NOTE: This is a lock-free alternative to [`BinaryView::offset_readable`].
pub fn is_offset_readable(&self, offset: u64) -> bool {
unsafe { BNAnalysisContextIsOffsetReadable(self.handle.as_ptr(), offset) }
}
- /// Check if an offset is writable in the cached memory map
+ /// Check if an offset is writable in the cached [`MemoryMap`].
+ ///
+ /// NOTE: This is a lock-free alternative to [`BinaryView::offset_writable`].
pub fn is_offset_writable(&self, offset: u64) -> bool {
unsafe { BNAnalysisContextIsOffsetWritable(self.handle.as_ptr(), offset) }
}
- /// Check if an offset is executable in the cached memory map
+ /// Check if an offset is executable in the cached [`MemoryMap`].
+ ///
+ /// NOTE: This is a lock-free alternative to [`BinaryView::offset_executable`].
pub fn is_offset_executable(&self, offset: u64) -> bool {
unsafe { BNAnalysisContextIsOffsetExecutable(self.handle.as_ptr(), offset) }
}
- /// Check if an offset is backed by file in the cached memory map
+ /// Check if an offset is backed by file in the cached [`MemoryMap`].
+ ///
+ /// NOTE: This is a lock-free alternative to [`BinaryView::offset_backed_by_file`].
pub fn is_offset_backed_by_file(&self, offset: u64) -> bool {
unsafe { BNAnalysisContextIsOffsetBackedByFile(self.handle.as_ptr(), offset) }
}
- /// Get the start address from the cached memory map
- pub fn get_start(&self) -> u64 {
+ /// Get the start address (the lowest address) from the cached [`MemoryMap`].
+ ///
+ /// NOTE: This is a lock-free alternative to [`BinaryView::start`].
+ pub fn start(&self) -> u64 {
unsafe { BNAnalysisContextGetStart(self.handle.as_ptr()) }
}
- /// Get the end address from the cached memory map
- pub fn get_end(&self) -> u64 {
+ /// Get the end address (the highest address) from the cached [`MemoryMap`].
+ ///
+ /// NOTE: This is a lock-free alternative to [`BinaryViewBase::end`].
+ pub fn end(&self) -> u64 {
unsafe { BNAnalysisContextGetEnd(self.handle.as_ptr()) }
}
- /// Get the length of the cached memory map
- pub fn get_length(&self) -> u64 {
+ /// Get the length of the cached [`MemoryMap`].
+ ///
+ /// NOTE: This is a lock-free alternative to [`BinaryViewBase::len`].
+ pub fn length(&self) -> u64 {
unsafe { BNAnalysisContextGetLength(self.handle.as_ptr()) }
}
- /// Get the next valid offset after the given offset from the cached memory map
- pub fn get_next_valid_offset(&self, offset: u64) -> u64 {
+ /// Get the next valid offset after the given offset from the cached [`MemoryMap`].
+ ///
+ /// NOTE: This is a lock-free alternative to [`BinaryView::next_valid_offset_after`].
+ pub fn next_valid_offset(&self, offset: u64) -> u64 {
unsafe { BNAnalysisContextGetNextValidOffset(self.handle.as_ptr(), offset) }
}
- /// Get the next mapped address after the given address from the cached memory map
- pub fn get_next_mapped_address(&self, addr: u64, flags: u32) -> u64 {
- unsafe { BNAnalysisContextGetNextMappedAddress(self.handle.as_ptr(), addr, flags) }
+ /// Get the next mapped address after the given address from the cached [`MemoryMap`].
+ pub fn next_mapped_address(&self, addr: u64, flags: &SegmentFlags) -> u64 {
+ unsafe {
+ BNAnalysisContextGetNextMappedAddress(self.handle.as_ptr(), addr, flags.into_raw())
+ }
}
- /// Get the next backed address after the given address from the cached memory map
- pub fn get_next_backed_address(&self, addr: u64, flags: u32) -> u64 {
- unsafe { BNAnalysisContextGetNextBackedAddress(self.handle.as_ptr(), addr, flags) }
+ /// Get the next backed address after the given address from the cached [`MemoryMap`].
+ pub fn next_backed_address(&self, addr: u64, flags: &SegmentFlags) -> u64 {
+ unsafe {
+ BNAnalysisContextGetNextBackedAddress(self.handle.as_ptr(), addr, flags.into_raw())
+ }
}
- /// Get the segment containing the given address from the cached memory map
- pub fn get_segment_at(&self, addr: u64) -> Option<Ref<Segment>> {
+ /// Get the segment containing the given address from the cached [`MemoryMap`].
+ ///
+ /// NOTE: This is a lock-free alternative to [`BinaryView::segment_at`].
+ pub fn segment_at(&self, addr: u64) -> Option<Ref<Segment>> {
unsafe {
let result = BNAnalysisContextGetSegmentAt(self.handle.as_ptr(), addr);
if result.is_null() {
@@ -245,35 +271,21 @@ impl AnalysisContext {
}
}
- /// Get all mapped address ranges from the cached memory map
- pub fn get_mapped_address_ranges(&self) -> Vec<(u64, u64)> {
+ /// Get all mapped address ranges from the cached [`MemoryMap`].
+ pub fn mapped_address_ranges(&self) -> Array<AddressRange> {
unsafe {
let mut count = 0;
let ranges = BNAnalysisContextGetMappedAddressRanges(self.handle.as_ptr(), &mut count);
- let result = (0..count)
- .map(|i| {
- let range = *ranges.add(i);
- (range.start, range.end)
- })
- .collect();
- BNFreeAddressRanges(ranges);
- result
+ Array::new(ranges, count, ())
}
}
- /// Get all backed address ranges from the cached memory map
- pub fn get_backed_address_ranges(&self) -> Vec<(u64, u64)> {
+ /// Get all backed address ranges from the cached [`MemoryMap`].
+ pub fn backed_address_ranges(&self) -> Array<AddressRange> {
unsafe {
let mut count = 0;
let ranges = BNAnalysisContextGetBackedAddressRanges(self.handle.as_ptr(), &mut count);
- let result = (0..count)
- .map(|i| {
- let range = *ranges.add(i);
- (range.start, range.end)
- })
- .collect();
- BNFreeAddressRanges(ranges);
- result
+ Array::new(ranges, count, ())
}
}
}