diff options
Diffstat (limited to 'rust/src')
| -rw-r--r-- | rust/src/binary_view.rs | 87 | ||||
| -rw-r--r-- | rust/src/function.rs | 42 | ||||
| -rw-r--r-- | rust/src/workflow.rs | 104 |
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, ()) } } } |
