diff options
| author | Mason Reed <mason@vector35.com> | 2025-07-13 17:34:02 -0400 |
|---|---|---|
| committer | Mason Reed <mason@vector35.com> | 2025-07-15 12:34:43 -0400 |
| commit | bd1b6b8a1a75df296da5c7afa8107ba301c9cd8e (patch) | |
| tree | b0155db15147c9d91da10519ee72eb87560ba2d4 /rust/src/binary_view.rs | |
| parent | fa3c81fd9b4287792c3e3d534a7d237d6005cb5f (diff) | |
[Rust] Add `BinaryView::search` and friends
Diffstat (limited to 'rust/src/binary_view.rs')
| -rw-r--r-- | rust/src/binary_view.rs | 197 |
1 files changed, 196 insertions, 1 deletions
diff --git a/rust/src/binary_view.rs b/rust/src/binary_view.rs index 73c3a2ab..2db833c4 100644 --- a/rust/src/binary_view.rs +++ b/rust/src/binary_view.rs @@ -34,7 +34,7 @@ use crate::external_library::{ExternalLibrary, ExternalLocation}; use crate::file_accessor::{Accessor, FileAccessor}; use crate::file_metadata::FileMetadata; use crate::flowgraph::FlowGraph; -use crate::function::{Function, NativeBlock}; +use crate::function::{Function, FunctionViewType, NativeBlock}; use crate::linear_view::{LinearDisassemblyLine, LinearViewCursor}; use crate::metadata::Metadata; use crate::platform::Platform; @@ -66,8 +66,11 @@ use std::{result, slice}; pub mod memory_map; pub mod reader; +pub mod search; pub mod writer; +use crate::binary_view::search::SearchQuery; +use crate::disassembly::DisassemblySettings; use crate::workflow::Workflow; pub use memory_map::MemoryMap; pub use reader::BinaryReader; @@ -78,6 +81,7 @@ pub type BinaryViewEventType = BNBinaryViewEventType; pub type AnalysisState = BNAnalysisState; pub type ModificationStatus = BNModificationStatus; pub type StringType = BNStringType; +pub type FindFlag = BNFindFlag; #[allow(clippy::len_without_is_empty)] pub trait BinaryViewBase: AsRef<BinaryView> { @@ -230,6 +234,197 @@ pub trait BinaryViewExt: BinaryViewBase { read_size } + /// Search the view using the query options. + fn search<C: FnMut(u64, &DataBuffer) -> bool>(&self, query: &SearchQuery, on_match: C) -> bool { + self.search_with_progress(query, on_match, NoProgressCallback) + } + + /// Search the view using the query options. + fn search_with_progress<P: ProgressCallback, C: FnMut(u64, &DataBuffer) -> bool>( + &self, + query: &SearchQuery, + mut on_match: C, + mut progress: P, + ) -> bool { + unsafe extern "C" fn cb_on_match<C: FnMut(u64, &DataBuffer) -> bool>( + ctx: *mut c_void, + offset: u64, + data: *mut BNDataBuffer, + ) -> bool { + let f = ctx as *mut C; + let buffer = DataBuffer::from_raw(data); + (*f)(offset, &buffer) + } + + let query = query.to_json().to_cstr(); + unsafe { + BNSearch( + self.as_ref().handle, + query.as_ptr(), + &mut progress as *mut P as *mut c_void, + Some(P::cb_progress_callback), + &mut on_match as *const C as *mut c_void, + Some(cb_on_match::<C>), + ) + } + } + + fn find_next_data(&self, start: u64, end: u64, data: &DataBuffer) -> Option<u64> { + self.find_next_data_with_opts( + start, + end, + data, + FindFlag::FindCaseInsensitive, + NoProgressCallback, + ) + } + + /// # Warning + /// + /// This function is likely to be changed to take in a "query" structure. Or deprecated entirely. + fn find_next_data_with_opts<P: ProgressCallback>( + &self, + start: u64, + end: u64, + data: &DataBuffer, + flag: FindFlag, + mut progress: P, + ) -> Option<u64> { + let mut result: u64 = 0; + let found = unsafe { + BNFindNextDataWithProgress( + self.as_ref().handle, + start, + end, + data.as_raw(), + &mut result, + flag, + &mut progress as *mut P as *mut c_void, + Some(P::cb_progress_callback), + ) + }; + + if found { + Some(result) + } else { + None + } + } + + fn find_next_constant( + &self, + start: u64, + end: u64, + constant: u64, + view_type: FunctionViewType, + ) -> Option<u64> { + // TODO: What are the best "default" settings? + let settings = DisassemblySettings::new(); + self.find_next_constant_with_opts( + start, + end, + constant, + &settings, + view_type, + NoProgressCallback, + ) + } + + /// # Warning + /// + /// This function is likely to be changed to take in a "query" structure. + fn find_next_constant_with_opts<P: ProgressCallback>( + &self, + start: u64, + end: u64, + constant: u64, + disasm_settings: &DisassemblySettings, + view_type: FunctionViewType, + mut progress: P, + ) -> Option<u64> { + let mut result: u64 = 0; + let raw_view_type = FunctionViewType::into_raw(view_type); + let found = unsafe { + BNFindNextConstantWithProgress( + self.as_ref().handle, + start, + end, + constant, + &mut result, + disasm_settings.handle, + raw_view_type, + &mut progress as *mut P as *mut c_void, + Some(P::cb_progress_callback), + ) + }; + FunctionViewType::free_raw(raw_view_type); + + if found { + Some(result) + } else { + None + } + } + + fn find_next_text( + &self, + start: u64, + end: u64, + text: &str, + view_type: FunctionViewType, + ) -> Option<u64> { + // TODO: What are the best "default" settings? + let settings = DisassemblySettings::new(); + self.find_next_text_with_opts( + start, + end, + text, + &settings, + FindFlag::FindCaseInsensitive, + view_type, + NoProgressCallback, + ) + } + + /// # Warning + /// + /// This function is likely to be changed to take in a "query" structure. + fn find_next_text_with_opts<P: ProgressCallback>( + &self, + start: u64, + end: u64, + text: &str, + disasm_settings: &DisassemblySettings, + flag: FindFlag, + view_type: FunctionViewType, + mut progress: P, + ) -> Option<u64> { + let text = text.to_cstr(); + let raw_view_type = FunctionViewType::into_raw(view_type); + let mut result: u64 = 0; + let found = unsafe { + BNFindNextTextWithProgress( + self.as_ref().handle, + start, + end, + text.as_ptr(), + &mut result, + disasm_settings.handle, + flag, + raw_view_type, + &mut progress as *mut P as *mut c_void, + Some(P::cb_progress_callback), + ) + }; + FunctionViewType::free_raw(raw_view_type); + + if found { + Some(result) + } else { + None + } + } + fn notify_data_written(&self, offset: u64, len: usize) { unsafe { BNNotifyDataWritten(self.as_ref().handle, offset, len); |
