summaryrefslogtreecommitdiff
path: root/rust/src
diff options
context:
space:
mode:
authorMason Reed <mason@vector35.com>2026-04-21 18:10:51 -0700
committerMason Reed <35282038+emesare@users.noreply.github.com>2026-05-10 17:13:08 -0700
commitc4ba6d79ae3b96d56cc6b3744e7c64e004ecd161 (patch)
tree5762fc3ff58b57caec5f42176faf6635c464b4f3 /rust/src
parent8269a8ac29e59c7949af753dac5c1f36bb700903 (diff)
[Rust] Refactor `binary_view` module
- Remove the "viral" `BinaryViewExt` trait and its blanket impl - Split up the binary view type from the custom trait impl - Simplify and fix bugs regarding custom binary view initialization - Rewrite Minidump binary view example, parses the PE headers to create proper sections now - Add some extra documentation - Add unit test for custom binary view
Diffstat (limited to 'rust/src')
-rw-r--r--rust/src/binary_view.rs1913
-rw-r--r--rust/src/binary_view/writer.rs2
-rw-r--r--rust/src/collaboration/file.rs2
-rw-r--r--rust/src/collaboration/project.rs5
-rw-r--r--rust/src/collaboration/snapshot.rs2
-rw-r--r--rust/src/collaboration/sync.rs4
-rw-r--r--rust/src/component.rs2
-rw-r--r--rust/src/custom_binary_view.rs961
-rw-r--r--rust/src/debuginfo.rs1
-rw-r--r--rust/src/ffi.rs1
-rw-r--r--rust/src/file_metadata.rs5
-rw-r--r--rust/src/function.rs6
-rw-r--r--rust/src/lib.rs1
-rw-r--r--rust/src/platform.rs2
-rw-r--r--rust/src/section.rs1
-rw-r--r--rust/src/segment.rs4
-rw-r--r--rust/src/types.rs3
-rw-r--r--rust/src/types/library.rs10
-rw-r--r--rust/src/types/structure.rs9
-rw-r--r--rust/src/workflow.rs2
20 files changed, 1335 insertions, 1601 deletions
diff --git a/rust/src/binary_view.rs b/rust/src/binary_view.rs
index b65367a2..8d49e55e 100644
--- a/rust/src/binary_view.rs
+++ b/rust/src/binary_view.rs
@@ -13,6 +13,8 @@
// limitations under the License.
//! A view on binary data and queryable interface of a binary files analysis.
+//!
+//! The main analysis object is [`BinaryView`], and custom implementations can be implemented with [`CustomBinaryView`].
use binaryninjacore_sys::*;
@@ -57,11 +59,11 @@ use crate::workflow::Workflow;
use crate::{Endianness, BN_FULL_CONFIDENCE};
use std::collections::{BTreeMap, HashMap};
use std::ffi::{c_char, c_void, CString};
-use std::fmt::{Display, Formatter};
+use std::fmt::{Debug, Display, Formatter};
+use std::mem::MaybeUninit;
use std::ops::Range;
use std::path::{Path, PathBuf};
use std::ptr::NonNull;
-use std::{result, slice};
pub mod memory_map;
pub mod reader;
@@ -72,15 +74,377 @@ pub use memory_map::{MemoryMap, MemoryRegionInfo, ResolvedRange};
pub use reader::BinaryReader;
pub use writer::BinaryWriter;
-pub type Result<R> = result::Result<R, ()>;
pub type BinaryViewEventType = BNBinaryViewEventType;
pub type AnalysisState = BNAnalysisState;
pub type ModificationStatus = BNModificationStatus;
pub type StringType = BNStringType;
pub type FindFlag = BNFindFlag;
+/// Registers a new binary view type.
+pub fn register_binary_view_type<T>(view_type: T) -> (&'static T, BinaryViewType)
+where
+ T: CustomBinaryViewType,
+{
+ let name = T::NAME.to_cstr();
+ let long_name = T::LONG_NAME.to_cstr();
+ let leaked_type = Box::leak(Box::new(view_type));
+
+ let result = unsafe {
+ BNRegisterBinaryViewType(
+ name.as_ref().as_ptr() as *const _,
+ long_name.as_ref().as_ptr() as *const _,
+ &mut BNCustomBinaryViewType {
+ context: leaked_type as *mut _ as *mut std::os::raw::c_void,
+ create: Some(cb_create::<T>),
+ parse: Some(cb_parse::<T>),
+ isValidForData: Some(cb_valid::<T>),
+ isDeprecated: Some(cb_deprecated::<T>),
+ isForceLoadable: Some(cb_force_loadable::<T>),
+ getLoadSettingsForData: Some(cb_load_settings::<T>),
+ hasNoInitialContent: Some(cb_has_no_initial_content::<T>),
+ },
+ )
+ };
+
+ assert!(
+ !result.is_null(),
+ "BNRegisterBinaryViewType always returns a non-null handle"
+ );
+ let core_view_type = unsafe { BinaryViewType::from_raw(result) };
+ (leaked_type, core_view_type)
+}
+
+/// Interface for creating custom binary views of a given type, analogous to [`BinaryViewType`].
+pub trait CustomBinaryViewType: 'static + Sync {
+ /// The associated [`BinaryViewBase`] for which this type creates with [`CustomBinaryViewType::create_binary_view`].
+ type CustomBinaryView: CustomBinaryView;
+
+ /// The name of the binary view type.
+ const NAME: &'static str;
+
+ /// The longer name of the binary view type, defaults to [`CustomBinaryViewType::NAME`].
+ const LONG_NAME: &'static str = Self::NAME;
+
+ /// Is this [`CustomBinaryViewType`] deprecated and should not be used?
+ ///
+ /// We specify this such that the view type may still be used by existing databases, but not
+ /// newly created views.
+ const DEPRECATED: bool = false;
+
+ /// Is this [`CustomBinaryViewType`] able to be loaded forcefully?
+ ///
+ /// If so, it will be shown in the drop-down when a user opens a file with options.
+ const FORCE_LOADABLE: bool = false;
+
+ /// Do instances of this [`CustomBinaryViewType`] start with no loaded content?
+ ///
+ /// When true, the view has no meaningful default state: the user must make a
+ /// selection (e.g. load images from a shared cache) before any content exists.
+ ///
+ /// Callers can use this to suppress restoring the previously saved view state for
+ /// files not being loaded from a database, since a saved layout would reference
+ /// content that isn't available on reopening.
+ const HAS_NO_INITIAL_CONTENT: bool = false;
+
+ /// Constructs the custom binary view instance.
+ fn create_binary_view(&self, data: &BinaryView) -> Result<Self::CustomBinaryView, ()>;
+
+ /// Constructs the custom binary view instance to be used for configuration.
+ ///
+ /// This is the path that is used when opening a binary with "Open With Options", and is what populates
+ /// the sections and segments of the dialog along with settings like the image base (start) address.
+ ///
+ /// The default implementation for this will construct a new instance identical to that of [`CustomBinaryViewType::create_binary_view`].
+ ///
+ /// Overriding this is encouraged as you can skip actually applying data to the view such as functions,
+ /// symbols, and other data not required for configuration, especially because this binary view is created
+ /// only temporarily and will be discarded after configuration is complete.
+ fn create_binary_view_for_parse(
+ &self,
+ data: &BinaryView,
+ ) -> Result<Self::CustomBinaryView, ()> {
+ self.create_binary_view(data)
+ }
+
+ /// Is this [`BinaryViewType`] valid for the given the raw [`BinaryView`]?
+ ///
+ /// Typical implementations will read the magic bytes (e.g. 'MZ'), this is a performance-sensitive
+ /// path so prefer inexpensive checks rather than comprehensive ones.
+ fn is_valid_for(&self, data: &BinaryView) -> bool;
+
+ fn load_settings_for_data(&self, _data: &BinaryView) -> Ref<Settings> {
+ Settings::new()
+ }
+}
+
+/// A [`BinaryViewType`] acts as a factory for [`BinaryView`] objects.
+///
+/// Each file format will have its own type, such as PE, ELF, or Mach-O.
+///
+/// Custom view types can be implemented using [`CustomBinaryViewType`].
+#[derive(Copy, Clone, PartialEq, Eq, Hash)]
+pub struct BinaryViewType {
+ pub handle: *mut BNBinaryViewType,
+}
+
+impl BinaryViewType {
+ pub(crate) unsafe fn from_raw(handle: *mut BNBinaryViewType) -> Self {
+ debug_assert!(!handle.is_null());
+ Self { handle }
+ }
+
+ pub fn list_all() -> Array<BinaryViewType> {
+ unsafe {
+ let mut count: usize = 0;
+ let types = BNGetBinaryViewTypes(&mut count as *mut _);
+ Array::new(types, count, ())
+ }
+ }
+
+ /// Enumerates all view types and checks to see if the given raw [`BinaryView`] is valid,
+ /// returning only those that are.
+ pub fn valid_types_for_data(data: &BinaryView) -> Array<BinaryViewType> {
+ unsafe {
+ let mut count: usize = 0;
+ let types = BNGetBinaryViewTypesForData(data.handle, &mut count as *mut _);
+ Array::new(types, count, ())
+ }
+ }
+
+ /// Looks up a binary view type by its name (_not_ the long name).
+ pub fn by_name(name: &str) -> Option<Self> {
+ let bytes = name.to_cstr();
+ let handle = unsafe { BNGetBinaryViewTypeByName(bytes.as_ref().as_ptr() as *const _) };
+ if handle.is_null() {
+ None
+ } else {
+ Some(unsafe { BinaryViewType::from_raw(handle) })
+ }
+ }
+
+ /// The given name for the binary view type.
+ pub fn name(&self) -> String {
+ unsafe { BnString::into_string(BNGetBinaryViewTypeName(self.handle)) }
+ }
+
+ /// The given long name for the binary view type.
+ pub fn long_name(&self) -> String {
+ unsafe { BnString::into_string(BNGetBinaryViewTypeLongName(self.handle)) }
+ }
+
+ /// Register an architecture for selection via the `id` and `endianness`.
+ ///
+ /// If you need to peak at the [`BinaryView`] to determine the architecture, use [`BinaryViewType::register_platform_recognizer`]
+ /// instead of this.
+ pub fn register_arch<A: Architecture>(&self, id: u32, endianness: Endianness, arch: &A) {
+ unsafe {
+ BNRegisterArchitectureForViewType(self.handle, id, endianness, arch.as_ref().handle);
+ }
+ }
+
+ /// Register a platform for selection via the `id`.
+ ///
+ /// If you need to peak at the [`BinaryView`] to determine the platform, use [`BinaryViewType::register_platform_recognizer`]
+ /// instead of this.
+ pub fn register_platform(&self, id: u32, plat: &Platform) {
+ let arch = plat.arch();
+ unsafe {
+ BNRegisterPlatformForViewType(self.handle, id, arch.handle, plat.handle);
+ }
+ }
+
+ /// Expanded identification of [`Platform`] for [`BinaryViewType`]'s. Supersedes [`BinaryViewType::register_arch`]
+ /// and [`BinaryViewType::register_platform`], as these have certain edge cases (overloaded elf families, for example)
+ /// that can't be represented.
+ ///
+ /// The callback returns a [`Platform`] object or `None` (failure), and most recently added callbacks are called first
+ /// to allow plugins to override any default behaviors. When a callback returns a platform, architecture will be
+ /// derived from the identified platform.
+ ///
+ /// The [`BinaryView`] is the *parent* view (usually 'Raw') that the [`BinaryView`] is being created for. This
+ /// means that generally speaking, the callbacks need to be aware of the underlying file format. However, the
+ /// [`BinaryView`] implementation may have created data variables in the 'Raw' view by the time the callback is invoked.
+ /// Behavior regarding when this callback is invoked and what has been made available in the [`BinaryView`] passed as an
+ /// argument to the callback is up to the discretion of the [`BinaryView`] implementation.
+ ///
+ /// The `id` ind `endian` arguments are used as a filter to determine which registered [`Platform`] recognizer callbacks
+ /// are invoked.
+ ///
+ /// Support for this API tentatively requires explicit support in the [`BinaryView`] implementation.
+ pub fn register_platform_recognizer<R>(&self, id: u32, endian: Endianness, recognizer: R)
+ where
+ R: 'static + Fn(&BinaryView, &Metadata) -> Option<Ref<Platform>> + Send + Sync,
+ {
+ #[repr(C)]
+ struct PlatformRecognizerHandlerContext<R>
+ where
+ R: 'static + Fn(&BinaryView, &Metadata) -> Option<Ref<Platform>> + Send + Sync,
+ {
+ recognizer: R,
+ }
+
+ extern "C" fn cb_recognize_low_level_il<R>(
+ ctxt: *mut std::os::raw::c_void,
+ bv: *mut BNBinaryView,
+ metadata: *mut BNMetadata,
+ ) -> *mut BNPlatform
+ where
+ R: 'static + Fn(&BinaryView, &Metadata) -> Option<Ref<Platform>> + Send + Sync,
+ {
+ let context = unsafe { &*(ctxt as *mut PlatformRecognizerHandlerContext<R>) };
+ let bv = unsafe { BinaryView::from_raw(bv).to_owned() };
+ let metadata = unsafe { Metadata::from_raw(metadata).to_owned() };
+ match (context.recognizer)(&bv, &metadata) {
+ Some(plat) => unsafe { Ref::into_raw(plat).handle },
+ None => std::ptr::null_mut(),
+ }
+ }
+
+ let recognizer = PlatformRecognizerHandlerContext { recognizer };
+ let raw = Box::into_raw(Box::new(recognizer));
+ unsafe {
+ BNRegisterPlatformRecognizerForViewType(
+ self.handle,
+ id as u64,
+ endian,
+ Some(cb_recognize_low_level_il::<R>),
+ raw as *mut std::os::raw::c_void,
+ )
+ }
+ }
+
+ /// Creates a new instance of the binary view for this given type, constructed with `data` as
+ /// the parent view.
+ ///
+ /// This will also call the initialization routine for the view, after calling this you should
+ /// be able to use the view as normal and ready to start analysis with [`BinaryView::update_analysis`].
+ pub fn create(&self, data: &BinaryView) -> Result<Ref<BinaryView>, ()> {
+ let handle = unsafe { BNCreateBinaryViewOfType(self.handle, data.handle) };
+ if handle.is_null() {
+ // TODO: Proper Result, possibly introduce BNSetError to populate.
+ return Err(());
+ }
+ unsafe { Ok(BinaryView::ref_from_raw(handle)) }
+ }
+
+ /// Creates a new instance of the binary view for parsing, this is a "specialize" version of the
+ /// regular [`BinaryViewType::create`] and is expected to be used when you only want to have the
+ /// view parsed and populated with information required for configuration, like with open with options.
+ pub fn parse(&self, data: &BinaryView) -> Result<Ref<BinaryView>, ()> {
+ let handle = unsafe { BNParseBinaryViewOfType(self.handle, data.handle) };
+ if handle.is_null() {
+ // TODO: Proper Result, possibly introduce BNSetError to populate.
+ return Err(());
+ }
+ unsafe { Ok(BinaryView::ref_from_raw(handle)) }
+ }
+
+ /// Is this [`BinaryViewType`] valid for the given the raw [`BinaryView`]?
+ ///
+ /// Typical implementations will read the magic bytes (e.g. 'MZ'), this is a performance-sensitive
+ /// path so prefer inexpensive checks rather than comprehensive ones.
+ pub fn is_valid_for(&self, data: &BinaryView) -> bool {
+ unsafe { BNIsBinaryViewTypeValidForData(self.handle, data.handle) }
+ }
+
+ /// Is this [`BinaryViewType`] deprecated and should not be used?
+ ///
+ /// We specify this such that the view type may still be used by existing databases, but not
+ /// newly created views.
+ pub fn is_deprecated(&self) -> bool {
+ unsafe { BNIsBinaryViewTypeDeprecated(self.handle) }
+ }
+
+ /// Is this [`BinaryViewType`] able to be loaded forcefully?
+ ///
+ /// If so, it will be shown in the drop-down when a user opens a file with options.
+ pub fn is_force_loadable(&self) -> bool {
+ unsafe { BNIsBinaryViewTypeForceLoadable(self.handle) }
+ }
+
+ /// Do instances of this [`BinaryViewType`] start with no loaded content?
+ ///
+ /// When true, the view has no meaningful default state: the user must make a
+ /// selection (e.g. load images from a shared cache) before any content exists.
+ ///
+ /// Callers can use this to suppress restoring the previously saved view state for
+ /// files not being loaded from a database, since a saved layout would reference
+ /// content that isn't available on reopening.
+ pub fn has_no_initial_content(&self) -> bool {
+ unsafe { BNBinaryViewTypeHasNoInitialContent(self.handle) }
+ }
+
+ pub fn load_settings_for_data(&self, data: &BinaryView) -> Option<Ref<Settings>> {
+ let settings_handle =
+ unsafe { BNGetBinaryViewLoadSettingsForData(self.handle, data.handle) };
+
+ if settings_handle.is_null() {
+ None
+ } else {
+ unsafe { Some(Settings::ref_from_raw(settings_handle)) }
+ }
+ }
+}
+
+impl Debug for BinaryViewType {
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
+ f.debug_struct("BinaryViewType")
+ .field("name", &self.name())
+ .field("long_name", &self.long_name())
+ .finish()
+ }
+}
+
+impl CoreArrayProvider for BinaryViewType {
+ type Raw = *mut BNBinaryViewType;
+ type Context = ();
+ type Wrapped<'a> = Guard<'a, BinaryViewType>;
+}
+
+unsafe impl CoreArrayProviderInner for BinaryViewType {
+ unsafe fn free(raw: *mut Self::Raw, _count: usize, _context: &Self::Context) {
+ BNFreeBinaryViewTypeList(raw);
+ }
+
+ unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
+ Guard::new(BinaryViewType::from_raw(*raw), &())
+ }
+}
+
+unsafe impl Send for BinaryViewType {}
+unsafe impl Sync for BinaryViewType {}
+
+/// Implemented for custom views, responsible for setting up the view state once the binary is open.
+pub trait CustomBinaryView: BinaryViewBase {
+ /// Initializes the opened binary view state.
+ ///
+ /// Use this to populate the [`BinaryView`] with sections, segments, and other view data.
+ ///
+ /// NOTE: You must add **at least** one segment to the view, otherwise calls to [`BinaryViewType::create`]
+ /// will fail.
+ ///
+ /// NOTE: This will be called on every subsequent open of a database, any view data applied here
+ /// should be expected to be regenerated on every open.
+ fn initialize(&mut self, view: &BinaryView) -> bool;
+
+ /// Called after deserialization of the current database snapshot has completed and all the
+ /// view data inside that snapshot has been applied to the view (like sections and segments).
+ ///
+ /// Useful if you need to regenerate temporary data based on the view state.
+ fn on_after_snapshot_data_applied(&mut self) {}
+}
+
+/// Wrapper around `C` when being passed to the custom view constructor so that we have the core
+/// view available to [`CustomBinaryView::initialize`], called from [`cb_init`].
+struct CustomBinaryViewContext<C: CustomBinaryView> {
+ // This is not ref-counted because we do not want to impact the lifetime of the core view, the lifetime
+ // of which is already bound to the lifetime of the custom view (to be freed when the custom view is freed).
+ core_view: MaybeUninit<BinaryView>,
+ view: C,
+}
+
#[allow(clippy::len_without_is_empty)]
-pub trait BinaryViewBase: AsRef<BinaryView> {
+pub trait BinaryViewBase {
fn read(&self, _buf: &mut [u8], _offset: u64) -> usize {
0
}
@@ -100,10 +464,7 @@ pub trait BinaryViewBase: AsRef<BinaryView> {
/// Check if the offset is valid for the current view.
fn offset_valid(&self, offset: u64) -> bool {
let mut buf = [0u8; 1];
-
- // don't use self.read so that if segments were used we
- // check against those as well
- self.as_ref().read(&mut buf[..], offset) == buf.len()
+ self.read(&mut buf[..], offset) == buf.len()
}
/// Check if the offset is readable for the current view.
@@ -129,8 +490,7 @@ pub trait BinaryViewBase: AsRef<BinaryView> {
/// Get the next valid offset after the provided `offset`, useful if you need to iterate over all
/// readable offsets in the view.
fn next_valid_offset_after(&self, offset: u64) -> u64 {
- let start = self.as_ref().start();
-
+ let start = self.start();
if offset < start {
start
} else {
@@ -158,18 +518,20 @@ pub trait BinaryViewBase: AsRef<BinaryView> {
}
fn relocatable(&self) -> bool {
- true
+ false
+ }
+
+ fn entry_point(&self) -> u64 {
+ 0
}
- fn entry_point(&self) -> u64;
fn default_endianness(&self) -> Endianness;
+
fn address_size(&self) -> usize;
+ // TODO: Needs to take file accessor?
fn save(&self) -> bool {
- self.as_ref()
- .parent_view()
- .map(|view| view.save())
- .unwrap_or(false)
+ false
}
}
@@ -241,33 +603,214 @@ impl From<BNAnalysisProgress> for AnalysisProgress {
}
}
-pub trait BinaryViewExt: BinaryViewBase {
- fn file(&self) -> Ref<FileMetadata> {
+/// Represents the "whole view" of the binary and its analysis.
+///
+/// Analysis information:
+///
+/// - [`BinaryView::functions`]
+/// - [`BinaryView::data_variables`]
+/// - [`BinaryView::strings`]
+///
+/// Annotation information:
+///
+/// - [`BinaryView::symbols`]
+/// - [`BinaryView::tags_all_scopes`]
+/// - [`BinaryView::comments`]
+///
+/// Data representation and binary information:
+///
+/// - [`BinaryView::types`]
+/// - [`BinaryView::segments`]
+/// - [`BinaryView::sections`]
+///
+/// # Cleaning up
+///
+/// [`BinaryView`] has a cyclic relationship with the associated [`FileMetadata`], each holds a strong
+/// reference to one another, so to properly clean up/free the [`BinaryView`], you must manually close the
+/// file using [`FileMetadata::close`], this is not fixable in the general case, until [`FileMetadata`]
+/// has only a weak reference to the [`BinaryView`].
+#[derive(PartialEq, Eq, Hash)]
+pub struct BinaryView {
+ pub handle: *mut BNBinaryView,
+}
+
+impl BinaryView {
+ pub unsafe fn from_raw(handle: *mut BNBinaryView) -> Self {
+ debug_assert!(!handle.is_null());
+ Self { handle }
+ }
+
+ pub(crate) unsafe fn ref_from_raw(handle: *mut BNBinaryView) -> Ref<Self> {
+ debug_assert!(!handle.is_null());
+ Ref::new(Self { handle })
+ }
+
+ /// Create a core instance of the [`CustomBinaryView`].
+ pub fn from_custom<C: CustomBinaryView>(
+ view_type_name: &str,
+ file: &FileMetadata,
+ parent_view: &BinaryView,
+ view: C,
+ ) -> Result<Ref<Self>, ()> {
+ let type_name = view_type_name.to_cstr();
+ // We need to pass the core BinaryView when initializing the custom view state with [`CustomBinaryView::initialize`],
+ // and to do that we need to store the returned core view handle after creating the custom view.
+ let custom_context = CustomBinaryViewContext {
+ core_view: MaybeUninit::uninit(),
+ view,
+ };
+ // We leak to be freed in `cb_free_object`.
+ let leaked_view = Box::leak(Box::new(custom_context));
+ let handle = unsafe {
+ BNCreateCustomBinaryView(
+ type_name.as_ptr(),
+ file.handle,
+ parent_view.handle,
+ &mut BNCustomBinaryView {
+ context: leaked_view as *mut CustomBinaryViewContext<C> as *mut _,
+ init: Some(cb_init::<C>),
+ freeObject: Some(cb_free_object::<C>),
+ externalRefTaken: None,
+ externalRefReleased: None,
+ read: Some(cb_read::<C>),
+ write: Some(cb_write::<C>),
+ insert: Some(cb_insert::<C>),
+ remove: Some(cb_remove::<C>),
+ getModification: Some(cb_modification::<C>),
+ isValidOffset: Some(cb_offset_valid::<C>),
+ isOffsetReadable: Some(cb_offset_readable::<C>),
+ isOffsetWritable: Some(cb_offset_writable::<C>),
+ isOffsetExecutable: Some(cb_offset_executable::<C>),
+ isOffsetBackedByFile: Some(cb_offset_backed_by_file::<C>),
+ getNextValidOffset: Some(cb_next_valid_offset::<C>),
+ getStart: Some(cb_start::<C>),
+ getLength: Some(cb_length::<C>),
+ getEntryPoint: Some(cb_entry_point::<C>),
+ isExecutable: Some(cb_executable::<C>),
+ getDefaultEndianness: Some(cb_endianness::<C>),
+ isRelocatable: Some(cb_relocatable::<C>),
+ getAddressSize: Some(cb_address_size::<C>),
+ save: Some(cb_save::<C>),
+ onAfterSnapshotDataApplied: Some(cb_on_after_snapshot_data_applied::<C>),
+ },
+ )
+ };
+ if handle.is_null() {
+ // We need to free the custom context manually.
+ let _ = unsafe { Box::from_raw(leaked_view) };
+ return Err(());
+ }
+ leaked_view.core_view = unsafe { MaybeUninit::new(BinaryView::from_raw(handle)) };
+ unsafe { Ok(Ref::new(Self { handle })) }
+ }
+
+ /// Construct the raw binary view from the given metadata.
+ ///
+ /// Before calling this, make sure you have a valid file path set for the [`FileMetadata`]. It is
+ /// required that the [`FileMetadata::file_path`] exist in the local filesystem.
+ pub fn from_metadata(meta: &FileMetadata) -> Result<Ref<Self>, ()> {
+ if !meta.file_path().exists() {
+ return Err(());
+ }
+ let file = meta.file_path().to_cstr();
+ let handle =
+ unsafe { BNCreateBinaryDataViewFromFilename(meta.handle, file.as_ptr() as *mut _) };
+ if handle.is_null() {
+ return Err(());
+ }
+ unsafe { Ok(Ref::new(Self { handle })) }
+ }
+
+ /// Construct the raw binary view from the given `file_path` and metadata.
+ ///
+ /// This will implicitly set the metadata file path and then construct the view. If the metadata
+ /// already has the desired file path, use [`BinaryView::from_metadata`] instead.
+ pub fn from_path(meta: &FileMetadata, file_path: impl AsRef<Path>) -> Result<Ref<Self>, ()> {
+ meta.set_file_path(file_path.as_ref());
+ Self::from_metadata(meta)
+ }
+
+ // TODO: Provide an API that manages the lifetime of the accessor and the view.
+ /// Construct the raw binary view from the given `accessor` and metadata.
+ ///
+ /// It is the responsibility of the caller to keep the accessor alive for the lifetime of the view;
+ /// because of this, we mark the function as unsafe.
+ pub unsafe fn from_accessor<A: Accessor>(
+ meta: &FileMetadata,
+ accessor: &mut FileAccessor<A>,
+ ) -> Result<Ref<Self>, ()> {
+ let handle = unsafe { BNCreateBinaryDataViewFromFile(meta.handle, &mut accessor.raw) };
+ if handle.is_null() {
+ return Err(());
+ }
+ unsafe { Ok(Ref::new(Self { handle })) }
+ }
+
+ /// Construct the raw binary view from the given `data` and metadata.
+ ///
+ /// The data will be copied into the view, so the caller does not need to keep the data alive.
+ pub fn from_data(meta: &FileMetadata, data: &[u8]) -> Ref<Self> {
+ let handle = unsafe {
+ BNCreateBinaryDataViewFromData(meta.handle, data.as_ptr() as *mut _, data.len())
+ };
+ assert!(
+ !handle.is_null(),
+ "BNCreateBinaryDataViewFromData should always succeed"
+ );
+ unsafe { Ref::new(Self { handle }) }
+ }
+
+ /// Save the original binary file to the provided `file_path` along with any modifications.
+ ///
+ /// WARNING: Currently, there is a possibility to deadlock if the analysis has queued up a main thread action
+ /// that tries to take the [`FileMetadata`] lock of the current view and is executed while we
+ /// are executing in this function.
+ ///
+ /// To avoid the above issue, use [`crate::main_thread::execute_on_main_thread_and_wait`] to verify there
+ /// are no queued up main thread actions.
+ pub fn save_to_path(&self, file_path: impl AsRef<Path>) -> bool {
+ let file = file_path.as_ref().to_cstr();
+ unsafe { BNSaveToFilename(self.handle, file.as_ptr() as *mut _) }
+ }
+
+ /// Save the original binary file to the provided [`FileAccessor`] along with any modifications.
+ ///
+ /// WARNING: Currently, there is a possibility to deadlock if the analysis has queued up a main thread action
+ /// that tries to take the [`FileMetadata`] lock of the current view and is executed while we
+ /// are executing in this function.
+ ///
+ /// To avoid the above issue, use [`crate::main_thread::execute_on_main_thread_and_wait`] to verify there
+ /// are no queued up main thread actions.
+ pub fn save_to_accessor<A: Accessor>(&self, file: &mut FileAccessor<A>) -> bool {
+ unsafe { BNSaveToFile(self.handle, &mut file.raw) }
+ }
+
+ pub fn file(&self) -> Ref<FileMetadata> {
unsafe {
- let raw = BNGetFileForView(self.as_ref().handle);
+ let raw = BNGetFileForView(self.handle);
FileMetadata::ref_from_raw(raw)
}
}
- fn parent_view(&self) -> Option<Ref<BinaryView>> {
- let raw_view_ptr = unsafe { BNGetParentView(self.as_ref().handle) };
+ pub fn parent_view(&self) -> Option<Ref<BinaryView>> {
+ let raw_view_ptr = unsafe { BNGetParentView(self.handle) };
match raw_view_ptr.is_null() {
false => Some(unsafe { BinaryView::ref_from_raw(raw_view_ptr) }),
true => None,
}
}
- fn raw_view(&self) -> Option<Ref<BinaryView>> {
+ pub fn raw_view(&self) -> Option<Ref<BinaryView>> {
self.file().view_of_type("Raw")
}
- fn view_type(&self) -> String {
- let ptr: *mut c_char = unsafe { BNGetViewType(self.as_ref().handle) };
+ pub fn view_type(&self) -> String {
+ let ptr: *mut c_char = unsafe { BNGetViewType(self.handle) };
unsafe { BnString::into_string(ptr) }
}
/// Reads up to `len` bytes from address `offset`
- fn read_vec(&self, offset: u64, len: usize) -> Vec<u8> {
+ pub fn read_vec(&self, offset: u64, len: usize) -> Vec<u8> {
let mut ret = vec![0; len];
let size = self.read(&mut ret, offset);
ret.truncate(size);
@@ -275,7 +818,7 @@ pub trait BinaryViewExt: BinaryViewBase {
}
/// Appends up to `len` bytes from address `offset` into `dest`
- fn read_into_vec(&self, dest: &mut Vec<u8>, offset: u64, len: usize) -> usize {
+ pub fn read_into_vec(&self, dest: &mut Vec<u8>, offset: u64, len: usize) -> usize {
let starting_len = dest.len();
dest.resize(starting_len + len, 0);
let read_size = self.read(&mut dest[starting_len..], offset);
@@ -284,7 +827,7 @@ pub trait BinaryViewExt: BinaryViewBase {
}
/// Reads up to `len` bytes from the address `offset` returning a `CString` if available.
- fn read_c_string_at(&self, offset: u64, len: usize) -> Option<CString> {
+ pub fn read_c_string_at(&self, offset: u64, len: usize) -> Option<CString> {
let mut buf = vec![0; len];
let size = self.read(&mut buf, offset);
let string = CString::new(buf[..size].to_vec()).ok()?;
@@ -292,7 +835,7 @@ pub trait BinaryViewExt: BinaryViewBase {
}
/// Reads up to `len` bytes from the address `offset` returning a `String` if available.
- fn read_utf8_string_at(&self, offset: u64, len: usize) -> Option<String> {
+ pub fn read_utf8_string_at(&self, offset: u64, len: usize) -> Option<String> {
let mut buf = vec![0; len];
let size = self.read(&mut buf, offset);
let string = String::from_utf8(buf[..size].to_vec()).ok()?;
@@ -302,14 +845,18 @@ pub trait BinaryViewExt: BinaryViewBase {
/// Search the view using the query options.
///
/// In the `on_match` callback return `false` to stop searching.
- fn search<C: FnMut(u64, &DataBuffer) -> bool>(&self, query: &SearchQuery, on_match: C) -> bool {
+ pub 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.
///
/// In the `on_match` callback return `false` to stop searching.
- fn search_with_progress<P: ProgressCallback, C: FnMut(u64, &DataBuffer) -> bool>(
+ pub fn search_with_progress<P: ProgressCallback, C: FnMut(u64, &DataBuffer) -> bool>(
&self,
query: &SearchQuery,
mut on_match: C,
@@ -328,7 +875,7 @@ pub trait BinaryViewExt: BinaryViewBase {
let query = query.to_json().to_cstr();
unsafe {
BNSearch(
- self.as_ref().handle,
+ self.handle,
query.as_ptr(),
&mut progress as *mut P as *mut c_void,
Some(P::cb_progress_callback),
@@ -338,7 +885,7 @@ pub trait BinaryViewExt: BinaryViewBase {
}
}
- fn find_next_data(&self, start: u64, end: u64, data: &DataBuffer) -> Option<u64> {
+ pub fn find_next_data(&self, start: u64, end: u64, data: &DataBuffer) -> Option<u64> {
self.find_next_data_with_opts(
start,
end,
@@ -351,7 +898,7 @@ pub trait BinaryViewExt: BinaryViewBase {
/// # 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>(
+ pub fn find_next_data_with_opts<P: ProgressCallback>(
&self,
start: u64,
end: u64,
@@ -362,7 +909,7 @@ pub trait BinaryViewExt: BinaryViewBase {
let mut result: u64 = 0;
let found = unsafe {
BNFindNextDataWithProgress(
- self.as_ref().handle,
+ self.handle,
start,
end,
data.as_raw(),
@@ -380,7 +927,7 @@ pub trait BinaryViewExt: BinaryViewBase {
}
}
- fn find_next_constant(
+ pub fn find_next_constant(
&self,
start: u64,
end: u64,
@@ -402,7 +949,7 @@ pub trait BinaryViewExt: BinaryViewBase {
/// # Warning
///
/// This function is likely to be changed to take in a "query" structure.
- fn find_next_constant_with_opts<P: ProgressCallback>(
+ pub fn find_next_constant_with_opts<P: ProgressCallback>(
&self,
start: u64,
end: u64,
@@ -415,7 +962,7 @@ pub trait BinaryViewExt: BinaryViewBase {
let raw_view_type = FunctionViewType::into_raw(view_type);
let found = unsafe {
BNFindNextConstantWithProgress(
- self.as_ref().handle,
+ self.handle,
start,
end,
constant,
@@ -435,7 +982,7 @@ pub trait BinaryViewExt: BinaryViewBase {
}
}
- fn find_next_text(
+ pub fn find_next_text(
&self,
start: u64,
end: u64,
@@ -458,7 +1005,7 @@ pub trait BinaryViewExt: BinaryViewBase {
/// # Warning
///
/// This function is likely to be changed to take in a "query" structure.
- fn find_next_text_with_opts<P: ProgressCallback>(
+ pub fn find_next_text_with_opts<P: ProgressCallback>(
&self,
start: u64,
end: u64,
@@ -473,7 +1020,7 @@ pub trait BinaryViewExt: BinaryViewBase {
let mut result: u64 = 0;
let found = unsafe {
BNFindNextTextWithProgress(
- self.as_ref().handle,
+ self.handle,
start,
end,
text.as_ptr(),
@@ -494,75 +1041,75 @@ pub trait BinaryViewExt: BinaryViewBase {
}
}
- fn notify_data_written(&self, offset: u64, len: usize) {
+ pub fn notify_data_written(&self, offset: u64, len: usize) {
unsafe {
- BNNotifyDataWritten(self.as_ref().handle, offset, len);
+ BNNotifyDataWritten(self.handle, offset, len);
}
}
- fn notify_data_inserted(&self, offset: u64, len: usize) {
+ pub fn notify_data_inserted(&self, offset: u64, len: usize) {
unsafe {
- BNNotifyDataInserted(self.as_ref().handle, offset, len);
+ BNNotifyDataInserted(self.handle, offset, len);
}
}
- fn notify_data_removed(&self, offset: u64, len: usize) {
+ pub fn notify_data_removed(&self, offset: u64, len: usize) {
unsafe {
- BNNotifyDataRemoved(self.as_ref().handle, offset, len as u64);
+ BNNotifyDataRemoved(self.handle, offset, len as u64);
}
}
/// 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) }
+ pub fn offset_has_code_semantics(&self, offset: u64) -> bool {
+ unsafe { BNIsOffsetCodeSemantics(self.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) }
+ pub fn offset_has_extern_semantics(&self, offset: u64) -> bool {
+ unsafe { BNIsOffsetExternSemantics(self.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) }
+ pub fn offset_has_writable_semantics(&self, offset: u64) -> bool {
+ unsafe { BNIsOffsetWritableSemantics(self.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 { BNIsOffsetReadOnlySemantics(self.as_ref().handle, offset) }
+ pub fn offset_has_read_only_semantics(&self, offset: u64) -> bool {
+ unsafe { BNIsOffsetReadOnlySemantics(self.handle, offset) }
}
- fn image_base(&self) -> u64 {
- unsafe { BNGetImageBase(self.as_ref().handle) }
+ pub fn image_base(&self) -> u64 {
+ unsafe { BNGetImageBase(self.handle) }
}
- fn original_image_base(&self) -> u64 {
- unsafe { BNGetOriginalImageBase(self.as_ref().handle) }
+ pub fn original_image_base(&self) -> u64 {
+ unsafe { BNGetOriginalImageBase(self.handle) }
}
- fn set_original_image_base(&self, image_base: u64) {
- unsafe { BNSetOriginalImageBase(self.as_ref().handle, image_base) }
+ pub fn set_original_image_base(&self, image_base: u64) {
+ unsafe { BNSetOriginalImageBase(self.handle, image_base) }
}
/// The highest address in the view.
- fn end(&self) -> u64 {
- unsafe { BNGetEndOffset(self.as_ref().handle) }
+ pub fn end(&self) -> u64 {
+ unsafe { BNGetEndOffset(self.handle) }
}
- fn add_analysis_option(&self, name: &str) {
+ pub fn add_analysis_option(&self, name: &str) {
let name = name.to_cstr();
- unsafe { BNAddAnalysisOption(self.as_ref().handle, name.as_ptr()) }
+ unsafe { BNAddAnalysisOption(self.handle, name.as_ptr()) }
}
- fn has_initial_analysis(&self) -> bool {
- unsafe { BNHasInitialAnalysis(self.as_ref().handle) }
+ pub fn has_initial_analysis(&self) -> bool {
+ unsafe { BNHasInitialAnalysis(self.handle) }
}
- fn set_analysis_hold(&self, enable: bool) {
- unsafe { BNSetAnalysisHold(self.as_ref().handle, enable) }
+ pub fn set_analysis_hold(&self, enable: bool) {
+ unsafe { BNSetAnalysisHold(self.handle, enable) }
}
/// Runs the analysis pipeline, analyzing any data that has been marked for updates.
@@ -571,11 +1118,11 @@ pub trait BinaryViewExt: BinaryViewBase {
/// - [`Function::mark_updates_required`]
/// - [`Function::mark_caller_updates_required`]
///
- /// NOTE: This is a **non-blocking** call, use [`BinaryViewExt::update_analysis_and_wait`] if you
+ /// NOTE: This is a **non-blocking** call, use [`BinaryView::update_analysis_and_wait`] if you
/// require analysis to have completed before moving on.
- fn update_analysis(&self) {
+ pub fn update_analysis(&self) {
unsafe {
- BNUpdateAnalysis(self.as_ref().handle);
+ BNUpdateAnalysis(self.handle);
}
}
@@ -585,47 +1132,47 @@ pub trait BinaryViewExt: BinaryViewBase {
/// - [`Function::mark_updates_required`]
/// - [`Function::mark_caller_updates_required`]
///
- /// NOTE: This is a **blocking** call, use [`BinaryViewExt::update_analysis`] if you do not
+ /// NOTE: This is a **blocking** call, use [`BinaryView::update_analysis`] if you do not
/// need to wait for the analysis update to finish.
- fn update_analysis_and_wait(&self) {
+ pub fn update_analysis_and_wait(&self) {
unsafe {
- BNUpdateAnalysisAndWait(self.as_ref().handle);
+ BNUpdateAnalysisAndWait(self.handle);
}
}
/// Causes **all** functions to be reanalyzed.
///
- /// Use [`BinaryViewExt::update_analysis`] or [`BinaryViewExt::update_analysis_and_wait`] instead
+ /// Use [`BinaryView::update_analysis`] or [`BinaryView::update_analysis_and_wait`] instead
/// if you want to incrementally update analysis.
///
/// NOTE: This function does not wait for the analysis to finish.
- fn reanalyze(&self) {
+ pub fn reanalyze(&self) {
unsafe {
- BNReanalyzeAllFunctions(self.as_ref().handle);
+ BNReanalyzeAllFunctions(self.handle);
}
}
- fn abort_analysis(&self) {
- unsafe { BNAbortAnalysis(self.as_ref().handle) }
+ pub fn abort_analysis(&self) {
+ unsafe { BNAbortAnalysis(self.handle) }
}
- fn analysis_is_aborted(&self) -> bool {
- unsafe { BNAnalysisIsAborted(self.as_ref().handle) }
+ pub fn analysis_is_aborted(&self) -> bool {
+ unsafe { BNAnalysisIsAborted(self.handle) }
}
- fn workflow(&self) -> Ref<Workflow> {
+ pub fn workflow(&self) -> Ref<Workflow> {
unsafe {
- let raw_ptr = BNGetWorkflowForBinaryView(self.as_ref().handle);
+ let raw_ptr = BNGetWorkflowForBinaryView(self.handle);
let nonnull = NonNull::new(raw_ptr).expect("All views must have a workflow");
Workflow::ref_from_raw(nonnull)
}
}
- fn analysis_info(&self) -> AnalysisInfo {
- let info_ptr = unsafe { BNGetAnalysisInfo(self.as_ref().handle) };
+ pub fn analysis_info(&self) -> AnalysisInfo {
+ let info_ptr = unsafe { BNGetAnalysisInfo(self.handle) };
assert!(!info_ptr.is_null());
let info = unsafe { *info_ptr };
- let active_infos = unsafe { slice::from_raw_parts(info.activeInfo, info.count) };
+ let active_infos = unsafe { std::slice::from_raw_parts(info.activeInfo, info.count) };
let mut active_info_list = vec![];
for active_info in active_infos {
@@ -648,14 +1195,14 @@ pub trait BinaryViewExt: BinaryViewBase {
result
}
- fn analysis_progress(&self) -> AnalysisProgress {
- let progress_raw = unsafe { BNGetAnalysisProgress(self.as_ref().handle) };
+ pub fn analysis_progress(&self) -> AnalysisProgress {
+ let progress_raw = unsafe { BNGetAnalysisProgress(self.handle) };
AnalysisProgress::from(progress_raw)
}
- fn default_arch(&self) -> Option<CoreArchitecture> {
+ pub fn default_arch(&self) -> Option<CoreArchitecture> {
unsafe {
- let raw = BNGetDefaultArchitecture(self.as_ref().handle);
+ let raw = BNGetDefaultArchitecture(self.handle);
if raw.is_null() {
return None;
@@ -665,15 +1212,15 @@ pub trait BinaryViewExt: BinaryViewBase {
}
}
- fn set_default_arch<A: Architecture>(&self, arch: &A) {
+ pub fn set_default_arch<A: Architecture>(&self, arch: &A) {
unsafe {
- BNSetDefaultArchitecture(self.as_ref().handle, arch.as_ref().handle);
+ BNSetDefaultArchitecture(self.handle, arch.as_ref().handle);
}
}
- fn default_platform(&self) -> Option<Ref<Platform>> {
+ pub fn default_platform(&self) -> Option<Ref<Platform>> {
unsafe {
- let raw = BNGetDefaultPlatform(self.as_ref().handle);
+ let raw = BNGetDefaultPlatform(self.handle);
if raw.is_null() {
return None;
@@ -683,22 +1230,22 @@ pub trait BinaryViewExt: BinaryViewBase {
}
}
- fn set_default_platform(&self, plat: &Platform) {
+ pub fn set_default_platform(&self, plat: &Platform) {
unsafe {
- BNSetDefaultPlatform(self.as_ref().handle, plat.handle);
+ BNSetDefaultPlatform(self.handle, plat.handle);
}
}
- fn base_address_detection(&self) -> Option<BaseAddressDetection> {
+ pub fn base_address_detection(&self) -> Option<BaseAddressDetection> {
unsafe {
- let handle = BNCreateBaseAddressDetection(self.as_ref().handle);
+ let handle = BNCreateBaseAddressDetection(self.handle);
NonNull::new(handle).map(|base| BaseAddressDetection::from_raw(base))
}
}
- fn instruction_len<A: Architecture>(&self, arch: &A, addr: u64) -> Option<usize> {
+ pub fn instruction_len<A: Architecture>(&self, arch: &A, addr: u64) -> Option<usize> {
unsafe {
- let size = BNGetInstructionLength(self.as_ref().handle, arch.as_ref().handle, addr);
+ let size = BNGetInstructionLength(self.handle, arch.as_ref().handle, addr);
if size > 0 {
Some(size)
@@ -708,10 +1255,9 @@ pub trait BinaryViewExt: BinaryViewBase {
}
}
- fn symbol_by_address(&self, addr: u64) -> Option<Ref<Symbol>> {
+ pub fn symbol_by_address(&self, addr: u64) -> Option<Ref<Symbol>> {
unsafe {
- let raw_sym_ptr =
- BNGetSymbolByAddress(self.as_ref().handle, addr, std::ptr::null_mut());
+ let raw_sym_ptr = BNGetSymbolByAddress(self.handle, addr, std::ptr::null_mut());
match raw_sym_ptr.is_null() {
false => Some(Symbol::ref_from_raw(raw_sym_ptr)),
true => None,
@@ -719,15 +1265,12 @@ pub trait BinaryViewExt: BinaryViewBase {
}
}
- fn symbol_by_raw_name(&self, raw_name: impl IntoCStr) -> Option<Ref<Symbol>> {
+ pub fn symbol_by_raw_name(&self, raw_name: impl IntoCStr) -> Option<Ref<Symbol>> {
let raw_name = raw_name.to_cstr();
unsafe {
- let raw_sym_ptr = BNGetSymbolByRawName(
- self.as_ref().handle,
- raw_name.as_ptr(),
- std::ptr::null_mut(),
- );
+ let raw_sym_ptr =
+ BNGetSymbolByRawName(self.handle, raw_name.as_ptr(), std::ptr::null_mut());
match raw_sym_ptr.is_null() {
false => Some(Symbol::ref_from_raw(raw_sym_ptr)),
true => None,
@@ -735,22 +1278,22 @@ pub trait BinaryViewExt: BinaryViewBase {
}
}
- fn symbols(&self) -> Array<Symbol> {
+ pub fn symbols(&self) -> Array<Symbol> {
unsafe {
let mut count = 0;
- let handles = BNGetSymbols(self.as_ref().handle, &mut count, std::ptr::null_mut());
+ let handles = BNGetSymbols(self.handle, &mut count, std::ptr::null_mut());
Array::new(handles, count, ())
}
}
- fn symbols_by_name(&self, name: impl IntoCStr) -> Array<Symbol> {
+ pub fn symbols_by_name(&self, name: impl IntoCStr) -> Array<Symbol> {
let raw_name = name.to_cstr();
unsafe {
let mut count = 0;
let handles = BNGetSymbolsByName(
- self.as_ref().handle,
+ self.handle,
raw_name.as_ptr(),
&mut count,
std::ptr::null_mut(),
@@ -760,12 +1303,12 @@ pub trait BinaryViewExt: BinaryViewBase {
}
}
- fn symbols_in_range(&self, range: Range<u64>) -> Array<Symbol> {
+ pub fn symbols_in_range(&self, range: Range<u64>) -> Array<Symbol> {
unsafe {
let mut count = 0;
let len = range.end.wrapping_sub(range.start);
let handles = BNGetSymbolsInRange(
- self.as_ref().handle,
+ self.handle,
range.start,
len,
&mut count,
@@ -776,26 +1319,22 @@ pub trait BinaryViewExt: BinaryViewBase {
}
}
- fn symbols_of_type(&self, ty: SymbolType) -> Array<Symbol> {
+ pub fn symbols_of_type(&self, ty: SymbolType) -> Array<Symbol> {
unsafe {
let mut count = 0;
- let handles = BNGetSymbolsOfType(
- self.as_ref().handle,
- ty.into(),
- &mut count,
- std::ptr::null_mut(),
- );
+ let handles =
+ BNGetSymbolsOfType(self.handle, ty.into(), &mut count, std::ptr::null_mut());
Array::new(handles, count, ())
}
}
- fn symbols_of_type_in_range(&self, ty: SymbolType, range: Range<u64>) -> Array<Symbol> {
+ pub fn symbols_of_type_in_range(&self, ty: SymbolType, range: Range<u64>) -> Array<Symbol> {
unsafe {
let mut count = 0;
let len = range.end.wrapping_sub(range.start);
let handles = BNGetSymbolsOfTypeInRange(
- self.as_ref().handle,
+ self.handle,
ty.into(),
range.start,
len,
@@ -807,18 +1346,21 @@ pub trait BinaryViewExt: BinaryViewBase {
}
}
- fn define_auto_symbol(&self, sym: &Symbol) {
+ pub fn define_auto_symbol(&self, sym: &Symbol) {
unsafe {
- BNDefineAutoSymbol(self.as_ref().handle, sym.handle);
+ BNDefineAutoSymbol(self.handle, sym.handle);
}
}
- fn define_auto_symbol_with_type<'a, T: Into<Option<&'a Type>>>(
+ /// Defines the symbol as well as the analysis object associated with the given symbol type, such as
+ /// the data variable for a [`SymbolType::Data`], or the function for a [`SymbolType::Function`].
+ /// Returns the symbol, as it was applied to the binary view.
+ pub fn define_auto_symbol_with_type<'a, T: Into<Option<&'a Type>>>(
&self,
sym: &Symbol,
plat: &Platform,
ty: T,
- ) -> Result<Ref<Symbol>> {
+ ) -> Ref<Symbol> {
let mut type_with_conf = BNTypeWithConfidence {
type_: if let Some(t) = ty.into() {
t.handle
@@ -830,50 +1372,50 @@ pub trait BinaryViewExt: BinaryViewBase {
unsafe {
let raw_sym = BNDefineAutoSymbolAndVariableOrFunction(
- self.as_ref().handle,
+ self.handle,
plat.handle,
sym.handle,
&mut type_with_conf,
);
-
- if raw_sym.is_null() {
- return Err(());
- }
-
- Ok(Symbol::ref_from_raw(raw_sym))
+ // We should always get the symbol back as it is defined.
+ debug_assert!(
+ !raw_sym.is_null(),
+ "BNDefineAutoSymbolAndVariableOrFunction should not return null"
+ );
+ Symbol::ref_from_raw(raw_sym)
}
}
- fn undefine_auto_symbol(&self, sym: &Symbol) {
+ pub fn undefine_auto_symbol(&self, sym: &Symbol) {
unsafe {
- BNUndefineAutoSymbol(self.as_ref().handle, sym.handle);
+ BNUndefineAutoSymbol(self.handle, sym.handle);
}
}
- fn define_user_symbol(&self, sym: &Symbol) {
+ pub fn define_user_symbol(&self, sym: &Symbol) {
unsafe {
- BNDefineUserSymbol(self.as_ref().handle, sym.handle);
+ BNDefineUserSymbol(self.handle, sym.handle);
}
}
- fn undefine_user_symbol(&self, sym: &Symbol) {
+ pub fn undefine_user_symbol(&self, sym: &Symbol) {
unsafe {
- BNUndefineUserSymbol(self.as_ref().handle, sym.handle);
+ BNUndefineUserSymbol(self.handle, sym.handle);
}
}
- fn data_variables(&self) -> Array<DataVariable> {
+ pub fn data_variables(&self) -> Array<DataVariable> {
unsafe {
let mut count = 0;
- let vars = BNGetDataVariables(self.as_ref().handle, &mut count);
+ let vars = BNGetDataVariables(self.handle, &mut count);
Array::new(vars, count, ())
}
}
- fn data_variable_at_address(&self, addr: u64) -> Option<DataVariable> {
+ pub fn data_variable_at_address(&self, addr: u64) -> Option<DataVariable> {
let mut dv = BNDataVariable::default();
unsafe {
- if BNGetDataVariableAtAddress(self.as_ref().handle, addr, &mut dv) {
+ if BNGetDataVariableAtAddress(self.handle, addr, &mut dv) {
Some(DataVariable::from_owned_raw(dv))
} else {
None
@@ -881,34 +1423,34 @@ pub trait BinaryViewExt: BinaryViewBase {
}
}
- fn define_auto_data_var<'a, T: Into<Conf<&'a Type>>>(&self, addr: u64, ty: T) {
+ pub fn define_auto_data_var<'a, T: Into<Conf<&'a Type>>>(&self, addr: u64, ty: T) {
let mut owned_raw_ty = Conf::<&Type>::into_raw(ty.into());
unsafe {
- BNDefineDataVariable(self.as_ref().handle, addr, &mut owned_raw_ty);
+ BNDefineDataVariable(self.handle, addr, &mut owned_raw_ty);
}
}
- /// You likely would also like to call [`BinaryViewExt::define_user_symbol`] to bind this data variable with a name
- fn define_user_data_var<'a, T: Into<Conf<&'a Type>>>(&self, addr: u64, ty: T) {
+ /// You likely would also like to call [`BinaryView::define_user_symbol`] to bind this data variable with a name
+ pub fn define_user_data_var<'a, T: Into<Conf<&'a Type>>>(&self, addr: u64, ty: T) {
let mut owned_raw_ty = Conf::<&Type>::into_raw(ty.into());
unsafe {
- BNDefineUserDataVariable(self.as_ref().handle, addr, &mut owned_raw_ty);
+ BNDefineUserDataVariable(self.handle, addr, &mut owned_raw_ty);
}
}
- fn undefine_auto_data_var(&self, addr: u64, blacklist: Option<bool>) {
+ pub fn undefine_auto_data_var(&self, addr: u64, blacklist: Option<bool>) {
unsafe {
- BNUndefineDataVariable(self.as_ref().handle, addr, blacklist.unwrap_or(true));
+ BNUndefineDataVariable(self.handle, addr, blacklist.unwrap_or(true));
}
}
- fn undefine_user_data_var(&self, addr: u64) {
+ pub fn undefine_user_data_var(&self, addr: u64) {
unsafe {
- BNUndefineUserDataVariable(self.as_ref().handle, addr);
+ BNUndefineUserDataVariable(self.handle, addr);
}
}
- fn define_auto_type<T: Into<QualifiedName>>(
+ pub fn define_auto_type<T: Into<QualifiedName>>(
&self,
name: T,
source: &str,
@@ -919,13 +1461,13 @@ pub trait BinaryViewExt: BinaryViewBase {
let name_handle = unsafe {
let id_str =
BNGenerateAutoTypeId(source_str.as_ref().as_ptr() as *const _, &mut raw_name);
- BNDefineAnalysisType(self.as_ref().handle, id_str, &mut raw_name, type_obj.handle)
+ BNDefineAnalysisType(self.handle, id_str, &mut raw_name, type_obj.handle)
};
QualifiedName::free_raw(raw_name);
QualifiedName::from_owned_raw(name_handle)
}
- fn define_auto_type_with_id<T: Into<QualifiedName>>(
+ pub fn define_auto_type_with_id<T: Into<QualifiedName>>(
&self,
name: T,
id: &str,
@@ -935,7 +1477,7 @@ pub trait BinaryViewExt: BinaryViewBase {
let id_str = id.to_cstr();
let result_raw_name = unsafe {
BNDefineAnalysisType(
- self.as_ref().handle,
+ self.handle,
id_str.as_ref().as_ptr() as *const _,
&mut raw_name,
type_obj.handle,
@@ -945,13 +1487,16 @@ pub trait BinaryViewExt: BinaryViewBase {
QualifiedName::from_owned_raw(result_raw_name)
}
- fn define_user_type<T: Into<QualifiedName>>(&self, name: T, type_obj: &Type) {
+ pub fn define_user_type<T: Into<QualifiedName>>(&self, name: T, type_obj: &Type) {
let mut raw_name = QualifiedName::into_raw(name.into());
- unsafe { BNDefineUserAnalysisType(self.as_ref().handle, &mut raw_name, type_obj.handle) }
+ unsafe { BNDefineUserAnalysisType(self.handle, &mut raw_name, type_obj.handle) }
QualifiedName::free_raw(raw_name);
}
- fn define_auto_types<T, I>(&self, names_sources_and_types: T) -> HashMap<String, QualifiedName>
+ pub fn define_auto_types<T, I>(
+ &self,
+ names_sources_and_types: T,
+ ) -> HashMap<String, QualifiedName>
where
T: Iterator<Item = I>,
I: Into<QualifiedNameTypeAndId>,
@@ -959,7 +1504,7 @@ pub trait BinaryViewExt: BinaryViewBase {
self.define_auto_types_with_progress(names_sources_and_types, NoProgressCallback)
}
- fn define_auto_types_with_progress<T, I, P>(
+ pub fn define_auto_types_with_progress<T, I, P>(
&self,
names_sources_and_types: T,
mut progress: P,
@@ -978,7 +1523,7 @@ pub trait BinaryViewExt: BinaryViewBase {
let result_count = unsafe {
BNDefineAnalysisTypes(
- self.as_ref().handle,
+ self.handle,
types.as_mut_ptr(),
types.len(),
Some(P::cb_progress_callback),
@@ -1001,7 +1546,7 @@ pub trait BinaryViewExt: BinaryViewBase {
.collect()
}
- fn define_user_types<T, I>(&self, names_and_types: T)
+ pub fn define_user_types<T, I>(&self, names_and_types: T)
where
T: Iterator<Item = I>,
I: Into<QualifiedNameAndType>,
@@ -1009,7 +1554,7 @@ pub trait BinaryViewExt: BinaryViewBase {
self.define_user_types_with_progress(names_and_types, NoProgressCallback);
}
- fn define_user_types_with_progress<T, I, P>(&self, names_and_types: T, mut progress: P)
+ pub fn define_user_types_with_progress<T, I, P>(&self, names_and_types: T, mut progress: P)
where
T: Iterator<Item = I>,
I: Into<QualifiedNameAndType>,
@@ -1022,7 +1567,7 @@ pub trait BinaryViewExt: BinaryViewBase {
unsafe {
BNDefineUserAnalysisTypes(
- self.as_ref().handle,
+ self.handle,
types.as_mut_ptr(),
types.len(),
Some(P::cb_progress_callback),
@@ -1035,39 +1580,39 @@ pub trait BinaryViewExt: BinaryViewBase {
}
}
- fn undefine_auto_type(&self, id: &str) {
+ pub fn undefine_auto_type(&self, id: &str) {
let id_str = id.to_cstr();
unsafe {
- BNUndefineAnalysisType(self.as_ref().handle, id_str.as_ref().as_ptr() as *const _);
+ BNUndefineAnalysisType(self.handle, id_str.as_ref().as_ptr() as *const _);
}
}
- fn undefine_user_type<T: Into<QualifiedName>>(&self, name: T) {
+ pub fn undefine_user_type<T: Into<QualifiedName>>(&self, name: T) {
let mut raw_name = QualifiedName::into_raw(name.into());
- unsafe { BNUndefineUserAnalysisType(self.as_ref().handle, &mut raw_name) }
+ unsafe { BNUndefineUserAnalysisType(self.handle, &mut raw_name) }
QualifiedName::free_raw(raw_name);
}
- fn types(&self) -> Array<QualifiedNameAndType> {
+ pub fn types(&self) -> Array<QualifiedNameAndType> {
unsafe {
let mut count = 0usize;
- let types = BNGetAnalysisTypeList(self.as_ref().handle, &mut count);
+ let types = BNGetAnalysisTypeList(self.handle, &mut count);
Array::new(types, count, ())
}
}
- fn dependency_sorted_types(&self) -> Array<QualifiedNameAndType> {
+ pub fn dependency_sorted_types(&self) -> Array<QualifiedNameAndType> {
unsafe {
let mut count = 0usize;
- let types = BNGetAnalysisDependencySortedTypeList(self.as_ref().handle, &mut count);
+ let types = BNGetAnalysisDependencySortedTypeList(self.handle, &mut count);
Array::new(types, count, ())
}
}
- fn type_by_name<T: Into<QualifiedName>>(&self, name: T) -> Option<Ref<Type>> {
+ pub fn type_by_name<T: Into<QualifiedName>>(&self, name: T) -> Option<Ref<Type>> {
let mut raw_name = QualifiedName::into_raw(name.into());
unsafe {
- let type_handle = BNGetAnalysisTypeByName(self.as_ref().handle, &mut raw_name);
+ let type_handle = BNGetAnalysisTypeByName(self.handle, &mut raw_name);
QualifiedName::free_raw(raw_name);
if type_handle.is_null() {
return None;
@@ -1076,9 +1621,9 @@ pub trait BinaryViewExt: BinaryViewBase {
}
}
- fn type_by_ref(&self, ref_: &NamedTypeReference) -> Option<Ref<Type>> {
+ pub fn type_by_ref(&self, ref_: &NamedTypeReference) -> Option<Ref<Type>> {
unsafe {
- let type_handle = BNGetAnalysisTypeByRef(self.as_ref().handle, ref_.handle);
+ let type_handle = BNGetAnalysisTypeByRef(self.handle, ref_.handle);
if type_handle.is_null() {
return None;
}
@@ -1086,10 +1631,10 @@ pub trait BinaryViewExt: BinaryViewBase {
}
}
- fn type_by_id(&self, id: &str) -> Option<Ref<Type>> {
+ pub fn type_by_id(&self, id: &str) -> Option<Ref<Type>> {
let id_str = id.to_cstr();
unsafe {
- let type_handle = BNGetAnalysisTypeById(self.as_ref().handle, id_str.as_ptr());
+ let type_handle = BNGetAnalysisTypeById(self.handle, id_str.as_ptr());
if type_handle.is_null() {
return None;
}
@@ -1097,10 +1642,10 @@ pub trait BinaryViewExt: BinaryViewBase {
}
}
- fn type_name_by_id(&self, id: &str) -> Option<QualifiedName> {
+ pub fn type_name_by_id(&self, id: &str) -> Option<QualifiedName> {
let id_str = id.to_cstr();
unsafe {
- let name_handle = BNGetAnalysisTypeNameById(self.as_ref().handle, id_str.as_ptr());
+ let name_handle = BNGetAnalysisTypeNameById(self.handle, id_str.as_ptr());
let name = QualifiedName::from_owned_raw(name_handle);
// The core will return an empty qualified name if no type name was found.
match name.items.is_empty() {
@@ -1110,10 +1655,10 @@ pub trait BinaryViewExt: BinaryViewBase {
}
}
- fn type_id_by_name<T: Into<QualifiedName>>(&self, name: T) -> Option<String> {
+ pub fn type_id_by_name<T: Into<QualifiedName>>(&self, name: T) -> Option<String> {
let mut raw_name = QualifiedName::into_raw(name.into());
unsafe {
- let id_cstr = BNGetAnalysisTypeId(self.as_ref().handle, &mut raw_name);
+ let id_cstr = BNGetAnalysisTypeId(self.handle, &mut raw_name);
QualifiedName::free_raw(raw_name);
let id = BnString::into_string(id_cstr);
match id.is_empty() {
@@ -1123,24 +1668,24 @@ pub trait BinaryViewExt: BinaryViewBase {
}
}
- fn is_type_auto_defined<T: Into<QualifiedName>>(&self, name: T) -> bool {
+ pub fn is_type_auto_defined<T: Into<QualifiedName>>(&self, name: T) -> bool {
let mut raw_name = QualifiedName::into_raw(name.into());
- let result = unsafe { BNIsAnalysisTypeAutoDefined(self.as_ref().handle, &mut raw_name) };
+ let result = unsafe { BNIsAnalysisTypeAutoDefined(self.handle, &mut raw_name) };
QualifiedName::free_raw(raw_name);
result
}
- fn segments(&self) -> Array<Segment> {
+ pub fn segments(&self) -> Array<Segment> {
unsafe {
let mut count = 0;
- let raw_segments = BNGetSegments(self.as_ref().handle, &mut count);
+ let raw_segments = BNGetSegments(self.handle, &mut count);
Array::new(raw_segments, count, ())
}
}
- fn segment_at(&self, addr: u64) -> Option<Ref<Segment>> {
+ pub fn segment_at(&self, addr: u64) -> Option<Ref<Segment>> {
unsafe {
- let raw_seg = BNGetSegmentAt(self.as_ref().handle, addr);
+ let raw_seg = BNGetSegmentAt(self.handle, addr);
match raw_seg.is_null() {
false => Some(Segment::ref_from_raw(raw_seg)),
true => None,
@@ -1150,24 +1695,24 @@ pub trait BinaryViewExt: BinaryViewBase {
/// Adds a segment to the view.
///
- /// NOTE: Consider using [BinaryViewExt::begin_bulk_add_segments] and [BinaryViewExt::end_bulk_add_segments]
+ /// NOTE: Consider using [BinaryView::begin_bulk_add_segments] and [BinaryView::end_bulk_add_segments]
/// if you plan on adding a number of segments all at once, to avoid unnecessary MemoryMap updates.
- fn add_segment(&self, segment: SegmentBuilder) {
+ pub fn add_segment(&self, segment: SegmentBuilder) {
segment.create(self.as_ref());
}
// TODO: Replace with BulkModify guard.
/// Start adding segments in bulk. Useful for adding large numbers of segments.
///
- /// After calling this any call to [BinaryViewExt::add_segment] will be uncommitted until a call to
- /// [BinaryViewExt::end_bulk_add_segments]
+ /// After calling this any call to [BinaryView::add_segment] will be uncommitted until a call to
+ /// [BinaryView::end_bulk_add_segments]
///
- /// If you wish to discard the uncommitted segments you can call [BinaryViewExt::cancel_bulk_add_segments].
+ /// If you wish to discard the uncommitted segments you can call [BinaryView::cancel_bulk_add_segments].
///
- /// NOTE: This **must** be paired with a later call to [BinaryViewExt::end_bulk_add_segments] or
- /// [BinaryViewExt::cancel_bulk_add_segments], otherwise segments added after this call will stay uncommitted.
- fn begin_bulk_add_segments(&self) {
- unsafe { BNBeginBulkAddSegments(self.as_ref().handle) }
+ /// NOTE: This **must** be paired with a later call to [BinaryView::end_bulk_add_segments] or
+ /// [BinaryView::cancel_bulk_add_segments], otherwise segments added after this call will stay uncommitted.
+ pub fn begin_bulk_add_segments(&self) {
+ unsafe { BNBeginBulkAddSegments(self.handle) }
}
// TODO: Replace with BulkModify guard.
@@ -1175,8 +1720,8 @@ pub trait BinaryViewExt: BinaryViewBase {
///
/// NOTE: This **must** be paired with a prior call to [Self::begin_bulk_add_segments], otherwise this
/// does nothing and segments are added individually.
- fn end_bulk_add_segments(&self) {
- unsafe { BNEndBulkAddSegments(self.as_ref().handle) }
+ pub fn end_bulk_add_segments(&self) {
+ unsafe { BNEndBulkAddSegments(self.handle) }
}
// TODO: Replace with BulkModify guard.
@@ -1186,35 +1731,35 @@ pub trait BinaryViewExt: BinaryViewBase {
/// and [Self::end_bulk_add_segments], where the latter will commit the segments
/// which have been added since [Self::begin_bulk_add_segments], this function
/// will discard them so that they do not get added to the view.
- fn cancel_bulk_add_segments(&self) {
- unsafe { BNCancelBulkAddSegments(self.as_ref().handle) }
+ pub fn cancel_bulk_add_segments(&self) {
+ unsafe { BNCancelBulkAddSegments(self.handle) }
}
- fn add_section(&self, section: SectionBuilder) {
+ pub fn add_section(&self, section: SectionBuilder) {
section.create(self.as_ref());
}
- fn remove_auto_section(&self, name: impl IntoCStr) {
+ pub fn remove_auto_section(&self, name: impl IntoCStr) {
let raw_name = name.to_cstr();
let raw_name_ptr = raw_name.as_ptr();
unsafe {
- BNRemoveAutoSection(self.as_ref().handle, raw_name_ptr);
+ BNRemoveAutoSection(self.handle, raw_name_ptr);
}
}
- fn remove_user_section(&self, name: impl IntoCStr) {
+ pub fn remove_user_section(&self, name: impl IntoCStr) {
let raw_name = name.to_cstr();
let raw_name_ptr = raw_name.as_ptr();
unsafe {
- BNRemoveUserSection(self.as_ref().handle, raw_name_ptr);
+ BNRemoveUserSection(self.handle, raw_name_ptr);
}
}
- fn section_by_name(&self, name: impl IntoCStr) -> Option<Ref<Section>> {
+ pub fn section_by_name(&self, name: impl IntoCStr) -> Option<Ref<Section>> {
unsafe {
let raw_name = name.to_cstr();
let name_ptr = raw_name.as_ptr();
- let raw_section_ptr = BNGetSectionByName(self.as_ref().handle, name_ptr);
+ let raw_section_ptr = BNGetSectionByName(self.handle, name_ptr);
match raw_section_ptr.is_null() {
false => Some(Section::ref_from_raw(raw_section_ptr)),
true => None,
@@ -1222,42 +1767,42 @@ pub trait BinaryViewExt: BinaryViewBase {
}
}
- fn sections(&self) -> Array<Section> {
+ pub fn sections(&self) -> Array<Section> {
unsafe {
let mut count = 0;
- let sections = BNGetSections(self.as_ref().handle, &mut count);
+ let sections = BNGetSections(self.handle, &mut count);
Array::new(sections, count, ())
}
}
- fn sections_at(&self, addr: u64) -> Array<Section> {
+ pub fn sections_at(&self, addr: u64) -> Array<Section> {
unsafe {
let mut count = 0;
- let sections = BNGetSectionsAt(self.as_ref().handle, addr, &mut count);
+ let sections = BNGetSectionsAt(self.handle, addr, &mut count);
Array::new(sections, count, ())
}
}
- fn memory_map(&self) -> MemoryMap {
+ pub fn memory_map(&self) -> MemoryMap {
MemoryMap::new(self.as_ref().to_owned())
}
/// Add an auto function at the given `address` with the views default platform.
///
- /// Use [`BinaryViewExt::add_auto_function_with_platform`] if you wish to specify a platform.
+ /// Use [`BinaryView::add_auto_function_with_platform`] if you wish to specify a platform.
///
/// NOTE: The default platform **must** be set for this view!
- fn add_auto_function(&self, address: u64) -> Option<Ref<Function>> {
+ pub fn add_auto_function(&self, address: u64) -> Option<Ref<Function>> {
let platform = self.default_platform()?;
self.add_auto_function_with_platform(address, &platform)
}
/// Add an auto function at the given `address` with the `platform`.
///
- /// Use [`BinaryViewExt::add_auto_function_ext`] if you wish to specify a function type.
+ /// Use [`BinaryView::add_auto_function_ext`] if you wish to specify a function type.
///
/// NOTE: If the view's default platform is not set, this will set it to `platform`.
- fn add_auto_function_with_platform(
+ pub fn add_auto_function_with_platform(
&self,
address: u64,
platform: &Platform,
@@ -1268,7 +1813,7 @@ pub trait BinaryViewExt: BinaryViewBase {
/// Add an auto function at the given `address` with the `platform` and function type.
///
/// NOTE: If the view's default platform is not set, this will set it to `platform`.
- fn add_auto_function_ext(
+ pub fn add_auto_function_ext(
&self,
address: u64,
platform: &Platform,
@@ -1280,13 +1825,8 @@ pub trait BinaryViewExt: BinaryViewBase {
None => std::ptr::null_mut(),
};
- let handle = BNAddFunctionForAnalysis(
- self.as_ref().handle,
- platform.handle,
- address,
- true,
- func_type,
- );
+ let handle =
+ BNAddFunctionForAnalysis(self.handle, platform.handle, address, true, func_type);
if handle.is_null() {
return None;
@@ -1300,21 +1840,21 @@ pub trait BinaryViewExt: BinaryViewBase {
///
/// Pass `true` for `update_refs` to update all references of the function.
///
- /// NOTE: Unlike [`BinaryViewExt::remove_user_function`], this will NOT prohibit the function from
- /// being re-added in the future, use [`BinaryViewExt::remove_user_function`] to blacklist the
+ /// NOTE: Unlike [`BinaryView::remove_user_function`], this will NOT prohibit the function from
+ /// being re-added in the future, use [`BinaryView::remove_user_function`] to blacklist the
/// function from being automatically created.
- fn remove_auto_function(&self, func: &Function, update_refs: bool) {
+ pub fn remove_auto_function(&self, func: &Function, update_refs: bool) {
unsafe {
- BNRemoveAnalysisFunction(self.as_ref().handle, func.handle, update_refs);
+ BNRemoveAnalysisFunction(self.handle, func.handle, update_refs);
}
}
/// Add a user function at the given `address` with the views default platform.
///
- /// Use [`BinaryViewExt::add_user_function_with_platform`] if you wish to specify a platform.
+ /// Use [`BinaryView::add_user_function_with_platform`] if you wish to specify a platform.
///
/// NOTE: The default platform **must** be set for this view!
- fn add_user_function(&self, addr: u64) -> Option<Ref<Function>> {
+ pub fn add_user_function(&self, addr: u64) -> Option<Ref<Function>> {
let platform = self.default_platform()?;
self.add_user_function_with_platform(addr, &platform)
}
@@ -1322,13 +1862,13 @@ pub trait BinaryViewExt: BinaryViewBase {
/// Add an auto function at the given `address` with the `platform`.
///
/// NOTE: If the view's default platform is not set, this will set it to `platform`.
- fn add_user_function_with_platform(
+ pub fn add_user_function_with_platform(
&self,
addr: u64,
platform: &Platform,
) -> Option<Ref<Function>> {
unsafe {
- let func = BNCreateUserFunction(self.as_ref().handle, platform.handle, addr);
+ let func = BNCreateUserFunction(self.handle, platform.handle, addr);
if func.is_null() {
return None;
}
@@ -1338,19 +1878,19 @@ pub trait BinaryViewExt: BinaryViewBase {
/// Removes the function from the view and blacklists it from being created automatically.
///
- /// NOTE: If you call [`BinaryViewExt::add_user_function`], it will override the blacklist.
- fn remove_user_function(&self, func: &Function) {
- unsafe { BNRemoveUserFunction(self.as_ref().handle, func.handle) }
+ /// NOTE: If you call [`BinaryView::add_user_function`], it will override the blacklist.
+ pub fn remove_user_function(&self, func: &Function) {
+ unsafe { BNRemoveUserFunction(self.handle, func.handle) }
}
- fn has_functions(&self) -> bool {
- unsafe { BNHasFunctions(self.as_ref().handle) }
+ pub fn has_functions(&self) -> bool {
+ unsafe { BNHasFunctions(self.handle) }
}
/// Add an entry point at the given `address` with the view's default platform.
///
/// NOTE: The default platform **must** be set for this view!
- fn add_entry_point(&self, addr: u64) {
+ pub fn add_entry_point(&self, addr: u64) {
if let Some(platform) = self.default_platform() {
self.add_entry_point_with_platform(addr, &platform);
}
@@ -1359,15 +1899,15 @@ pub trait BinaryViewExt: BinaryViewBase {
/// Add an entry point at the given `address` with the `platform`.
///
/// NOTE: If the view's default platform is not set, this will set it to `platform`.
- fn add_entry_point_with_platform(&self, addr: u64, platform: &Platform) {
+ pub fn add_entry_point_with_platform(&self, addr: u64, platform: &Platform) {
unsafe {
- BNAddEntryPointForAnalysis(self.as_ref().handle, platform.handle, addr);
+ BNAddEntryPointForAnalysis(self.handle, platform.handle, addr);
}
}
- fn entry_point_function(&self) -> Option<Ref<Function>> {
+ pub fn entry_point_function(&self) -> Option<Ref<Function>> {
unsafe {
- let raw_func_ptr = BNGetAnalysisEntryPoint(self.as_ref().handle);
+ let raw_func_ptr = BNGetAnalysisEntryPoint(self.handle);
match raw_func_ptr.is_null() {
false => Some(Function::ref_from_raw(raw_func_ptr)),
true => None,
@@ -1380,41 +1920,39 @@ pub trait BinaryViewExt: BinaryViewBase {
///
/// We see `entry_functions` as good starting points for analysis, these functions normally don't
/// have internal references. Exported functions in a dll/so file are not included.
- fn entry_point_functions(&self) -> Array<Function> {
+ pub fn entry_point_functions(&self) -> Array<Function> {
unsafe {
let mut count = 0;
- let functions = BNGetAllEntryFunctions(self.as_ref().handle, &mut count);
+ let functions = BNGetAllEntryFunctions(self.handle, &mut count);
Array::new(functions, count, ())
}
}
- fn functions(&self) -> Array<Function> {
+ pub fn functions(&self) -> Array<Function> {
unsafe {
let mut count = 0;
- let functions = BNGetAnalysisFunctionList(self.as_ref().handle, &mut count);
+ let functions = BNGetAnalysisFunctionList(self.handle, &mut count);
Array::new(functions, count, ())
}
}
/// List of functions *starting* at `addr`
- fn functions_at(&self, addr: u64) -> Array<Function> {
+ pub fn functions_at(&self, addr: u64) -> Array<Function> {
unsafe {
let mut count = 0;
- let functions =
- BNGetAnalysisFunctionsForAddress(self.as_ref().handle, addr, &mut count);
+ let functions = BNGetAnalysisFunctionsForAddress(self.handle, addr, &mut count);
Array::new(functions, count, ())
}
}
/// List of functions containing `addr`
- fn functions_containing(&self, addr: u64) -> Array<Function> {
+ pub fn functions_containing(&self, addr: u64) -> Array<Function> {
unsafe {
let mut count = 0;
- let functions =
- BNGetAnalysisFunctionsContainingAddress(self.as_ref().handle, addr, &mut count);
+ let functions = BNGetAnalysisFunctionsContainingAddress(self.handle, addr, &mut count);
Array::new(functions, count, ())
}
@@ -1429,7 +1967,7 @@ pub trait BinaryViewExt: BinaryViewBase {
/// # Params
/// - `name`: Name that the function should have
/// - `plat`: Optional platform that the function should be defined for. Defaults to all platforms if `None` passed.
- fn functions_by_name(
+ pub fn functions_by_name(
&self,
name: impl IntoCStr,
plat: Option<&Platform>,
@@ -1459,9 +1997,9 @@ pub trait BinaryViewExt: BinaryViewBase {
functions
}
- fn function_at(&self, platform: &Platform, addr: u64) -> Option<Ref<Function>> {
+ pub fn function_at(&self, platform: &Platform, addr: u64) -> Option<Ref<Function>> {
unsafe {
- let raw_func_ptr = BNGetAnalysisFunction(self.as_ref().handle, platform.handle, addr);
+ let raw_func_ptr = BNGetAnalysisFunction(self.handle, platform.handle, addr);
match raw_func_ptr.is_null() {
false => Some(Function::ref_from_raw(raw_func_ptr)),
true => None,
@@ -1469,42 +2007,42 @@ pub trait BinaryViewExt: BinaryViewBase {
}
}
- fn function_start_before(&self, addr: u64) -> u64 {
- unsafe { BNGetPreviousFunctionStartBeforeAddress(self.as_ref().handle, addr) }
+ pub fn function_start_before(&self, addr: u64) -> u64 {
+ unsafe { BNGetPreviousFunctionStartBeforeAddress(self.handle, addr) }
}
- fn function_start_after(&self, addr: u64) -> u64 {
- unsafe { BNGetNextFunctionStartAfterAddress(self.as_ref().handle, addr) }
+ pub fn function_start_after(&self, addr: u64) -> u64 {
+ unsafe { BNGetNextFunctionStartAfterAddress(self.handle, addr) }
}
- fn basic_blocks_containing(&self, addr: u64) -> Array<BasicBlock<NativeBlock>> {
+ pub fn basic_blocks_containing(&self, addr: u64) -> Array<BasicBlock<NativeBlock>> {
unsafe {
let mut count = 0;
- let blocks = BNGetBasicBlocksForAddress(self.as_ref().handle, addr, &mut count);
+ let blocks = BNGetBasicBlocksForAddress(self.handle, addr, &mut count);
Array::new(blocks, count, NativeBlock::new())
}
}
- fn basic_blocks_starting_at(&self, addr: u64) -> Array<BasicBlock<NativeBlock>> {
+ pub fn basic_blocks_starting_at(&self, addr: u64) -> Array<BasicBlock<NativeBlock>> {
unsafe {
let mut count = 0;
- let blocks = BNGetBasicBlocksStartingAtAddress(self.as_ref().handle, addr, &mut count);
+ let blocks = BNGetBasicBlocksStartingAtAddress(self.handle, addr, &mut count);
Array::new(blocks, count, NativeBlock::new())
}
}
- fn is_new_auto_function_analysis_suppressed(&self) -> bool {
- unsafe { BNGetNewAutoFunctionAnalysisSuppressed(self.as_ref().handle) }
+ pub fn is_new_auto_function_analysis_suppressed(&self) -> bool {
+ unsafe { BNGetNewAutoFunctionAnalysisSuppressed(self.handle) }
}
- fn set_new_auto_function_analysis_suppressed(&self, suppress: bool) {
+ pub fn set_new_auto_function_analysis_suppressed(&self, suppress: bool) {
unsafe {
- BNSetNewAutoFunctionAnalysisSuppressed(self.as_ref().handle, suppress);
+ BNSetNewAutoFunctionAnalysisSuppressed(self.handle, suppress);
}
}
// TODO: Should this instead be implemented on [`Function`] considering `src_func`? `Location` is local to the source function.
- fn should_skip_target_analysis(
+ pub fn should_skip_target_analysis(
&self,
src_loc: impl Into<Location>,
src_func: &Function,
@@ -1515,7 +2053,7 @@ pub trait BinaryViewExt: BinaryViewBase {
let target = target.into();
unsafe {
BNShouldSkipTargetAnalysis(
- self.as_ref().handle,
+ self.handle,
&mut src_loc.into(),
src_func.handle,
src_end,
@@ -1524,8 +2062,8 @@ pub trait BinaryViewExt: BinaryViewBase {
}
}
- fn read_buffer(&self, offset: u64, len: usize) -> Option<DataBuffer> {
- let read_buffer = unsafe { BNReadViewBuffer(self.as_ref().handle, offset, len) };
+ pub fn read_buffer(&self, offset: u64, len: usize) -> Option<DataBuffer> {
+ let read_buffer = unsafe { BNReadViewBuffer(self.handle, offset, len) };
if read_buffer.is_null() {
None
} else {
@@ -1533,37 +2071,37 @@ pub trait BinaryViewExt: BinaryViewBase {
}
}
- fn debug_info(&self) -> Ref<DebugInfo> {
- unsafe { DebugInfo::ref_from_raw(BNGetDebugInfo(self.as_ref().handle)) }
+ pub fn debug_info(&self) -> Ref<DebugInfo> {
+ unsafe { DebugInfo::ref_from_raw(BNGetDebugInfo(self.handle)) }
}
- fn set_debug_info(&self, debug_info: &DebugInfo) {
- unsafe { BNSetDebugInfo(self.as_ref().handle, debug_info.handle) }
+ pub fn set_debug_info(&self, debug_info: &DebugInfo) {
+ unsafe { BNSetDebugInfo(self.handle, debug_info.handle) }
}
- fn apply_debug_info(&self, debug_info: &DebugInfo) {
- unsafe { BNApplyDebugInfo(self.as_ref().handle, debug_info.handle) }
+ pub fn apply_debug_info(&self, debug_info: &DebugInfo) {
+ unsafe { BNApplyDebugInfo(self.handle, debug_info.handle) }
}
- fn show_plaintext_report(&self, title: &str, plaintext: &str) {
+ pub fn show_plaintext_report(&self, title: &str, plaintext: &str) {
let title = title.to_cstr();
let plaintext = plaintext.to_cstr();
unsafe {
BNShowPlainTextReport(
- self.as_ref().handle,
+ self.handle,
title.as_ref().as_ptr() as *mut _,
plaintext.as_ref().as_ptr() as *mut _,
)
}
}
- fn show_markdown_report(&self, title: &str, contents: &str, plaintext: &str) {
+ pub fn show_markdown_report(&self, title: &str, contents: &str, plaintext: &str) {
let title = title.to_cstr();
let contents = contents.to_cstr();
let plaintext = plaintext.to_cstr();
unsafe {
BNShowMarkdownReport(
- self.as_ref().handle,
+ self.handle,
title.as_ref().as_ptr() as *mut _,
contents.as_ref().as_ptr() as *mut _,
plaintext.as_ref().as_ptr() as *mut _,
@@ -1571,13 +2109,13 @@ pub trait BinaryViewExt: BinaryViewBase {
}
}
- fn show_html_report(&self, title: &str, contents: &str, plaintext: &str) {
+ pub fn show_html_report(&self, title: &str, contents: &str, plaintext: &str) {
let title = title.to_cstr();
let contents = contents.to_cstr();
let plaintext = plaintext.to_cstr();
unsafe {
BNShowHTMLReport(
- self.as_ref().handle,
+ self.handle,
title.as_ref().as_ptr() as *mut _,
contents.as_ref().as_ptr() as *mut _,
plaintext.as_ref().as_ptr() as *mut _,
@@ -1585,60 +2123,54 @@ pub trait BinaryViewExt: BinaryViewBase {
}
}
- fn show_graph_report(&self, raw_name: &str, graph: &FlowGraph) {
+ pub fn show_graph_report(&self, raw_name: &str, graph: &FlowGraph) {
let raw_name = raw_name.to_cstr();
unsafe {
- BNShowGraphReport(self.as_ref().handle, raw_name.as_ptr(), graph.handle);
+ BNShowGraphReport(self.handle, raw_name.as_ptr(), graph.handle);
}
}
- fn load_settings(&self, view_type_name: &str) -> Result<Ref<Settings>> {
+ pub fn load_settings(&self, view_type_name: &str) -> Option<Ref<Settings>> {
let view_type_name = view_type_name.to_cstr();
let settings_handle =
- unsafe { BNBinaryViewGetLoadSettings(self.as_ref().handle, view_type_name.as_ptr()) };
-
- if settings_handle.is_null() {
- Err(())
- } else {
- Ok(unsafe { Settings::ref_from_raw(settings_handle) })
+ unsafe { BNBinaryViewGetLoadSettings(self.handle, view_type_name.as_ptr()) };
+ match settings_handle.is_null() {
+ true => None,
+ false => Some(unsafe { Settings::ref_from_raw(settings_handle) }),
}
}
- fn set_load_settings(&self, view_type_name: &str, settings: &Settings) {
+ pub fn set_load_settings(&self, view_type_name: &str, settings: &Settings) {
let view_type_name = view_type_name.to_cstr();
unsafe {
- BNBinaryViewSetLoadSettings(
- self.as_ref().handle,
- view_type_name.as_ptr(),
- settings.handle,
- )
+ BNBinaryViewSetLoadSettings(self.handle, view_type_name.as_ptr(), settings.handle)
};
}
- /// Creates a new [TagType] and adds it to the view.
+ /// Creates a new [`TagType`] and adds it to the view.
///
/// # Arguments
/// * `name` - the name for the tag
/// * `icon` - the icon (recommended 1 emoji or 2 chars) for the tag
- fn create_tag_type(&self, name: &str, icon: &str) -> Ref<TagType> {
- let tag_type = TagType::create(self.as_ref(), name, icon);
+ pub fn create_tag_type(&self, name: &str, icon: &str) -> Ref<TagType> {
+ let tag_type = TagType::create(self, name, icon);
unsafe {
- BNAddTagType(self.as_ref().handle, tag_type.handle);
+ BNAddTagType(self.handle, tag_type.handle);
}
tag_type
}
/// Removes a [TagType] and all tags that use it
- fn remove_tag_type(&self, tag_type: &TagType) {
- unsafe { BNRemoveTagType(self.as_ref().handle, tag_type.handle) }
+ pub fn remove_tag_type(&self, tag_type: &TagType) {
+ unsafe { BNRemoveTagType(self.handle, tag_type.handle) }
}
/// Get a tag type by its name.
- fn tag_type_by_name(&self, name: &str) -> Option<Ref<TagType>> {
+ pub fn tag_type_by_name(&self, name: &str) -> Option<Ref<TagType>> {
let name = name.to_cstr();
unsafe {
- let handle = BNGetTagType(self.as_ref().handle, name.as_ptr());
+ let handle = BNGetTagType(self.handle, name.as_ptr());
if handle.is_null() {
return None;
}
@@ -1647,29 +2179,29 @@ pub trait BinaryViewExt: BinaryViewBase {
}
/// Get all tags in all scopes
- fn tags_all_scopes(&self) -> Array<TagReference> {
+ pub fn tags_all_scopes(&self) -> Array<TagReference> {
let mut count = 0;
unsafe {
- let tag_references = BNGetAllTagReferences(self.as_ref().handle, &mut count);
+ let tag_references = BNGetAllTagReferences(self.handle, &mut count);
Array::new(tag_references, count, ())
}
}
/// Get all tag types present for the view
- fn tag_types(&self) -> Array<TagType> {
+ pub fn tag_types(&self) -> Array<TagType> {
let mut count = 0;
unsafe {
- let tag_types_raw = BNGetTagTypes(self.as_ref().handle, &mut count);
+ let tag_types_raw = BNGetTagTypes(self.handle, &mut count);
Array::new(tag_types_raw, count, ())
}
}
/// Get all tag references of a specific type
- fn tags_by_type(&self, tag_type: &TagType) -> Array<TagReference> {
+ pub fn tags_by_type(&self, tag_type: &TagType) -> Array<TagReference> {
let mut count = 0;
unsafe {
let tag_references =
- BNGetAllTagReferencesOfType(self.as_ref().handle, tag_type.handle, &mut count);
+ BNGetAllTagReferencesOfType(self.handle, tag_type.handle, &mut count);
Array::new(tag_references, count, ())
}
}
@@ -1677,10 +2209,10 @@ pub trait BinaryViewExt: BinaryViewBase {
/// Get a tag by its id.
///
/// Note this does not tell you anything about where it is used.
- fn tag_by_id(&self, id: &str) -> Option<Ref<Tag>> {
+ pub fn tag_by_id(&self, id: &str) -> Option<Ref<Tag>> {
let id = id.to_cstr();
unsafe {
- let handle = BNGetTag(self.as_ref().handle, id.as_ptr());
+ let handle = BNGetTag(self.handle, id.as_ptr());
if handle.is_null() {
return None;
}
@@ -1691,55 +2223,54 @@ pub trait BinaryViewExt: BinaryViewBase {
/// Creates and adds a tag to an address
///
/// User tag creations will be added to the undo buffer
- fn add_tag(&self, addr: u64, t: &TagType, data: &str, user: bool) {
+ pub fn add_tag(&self, addr: u64, t: &TagType, data: &str, user: bool) {
let tag = Tag::new(t, data);
- unsafe { BNAddTag(self.as_ref().handle, tag.handle, user) }
+ unsafe { BNAddTag(self.handle, tag.handle, user) }
if user {
- unsafe { BNAddUserDataTag(self.as_ref().handle, addr, tag.handle) }
+ unsafe { BNAddUserDataTag(self.handle, addr, tag.handle) }
} else {
- unsafe { BNAddAutoDataTag(self.as_ref().handle, addr, tag.handle) }
+ unsafe { BNAddAutoDataTag(self.handle, addr, tag.handle) }
}
}
/// removes a Tag object at a data address.
- fn remove_auto_data_tag(&self, addr: u64, tag: &Tag) {
- unsafe { BNRemoveAutoDataTag(self.as_ref().handle, addr, tag.handle) }
+ pub fn remove_auto_data_tag(&self, addr: u64, tag: &Tag) {
+ unsafe { BNRemoveAutoDataTag(self.handle, addr, tag.handle) }
}
/// removes a Tag object at a data address.
/// Since this removes a user tag, it will be added to the current undo buffer.
- fn remove_user_data_tag(&self, addr: u64, tag: &Tag) {
- unsafe { BNRemoveUserDataTag(self.as_ref().handle, addr, tag.handle) }
+ pub fn remove_user_data_tag(&self, addr: u64, tag: &Tag) {
+ unsafe { BNRemoveUserDataTag(self.handle, addr, tag.handle) }
}
/// Retrieves a list of comment addresses, the comments themselves can then be queried with
- /// the function [`BinaryViewExt::comment_at`].
+ /// the function [`BinaryView::comment_at`].
///
/// If you would rather retrieve the contents of **all** comments at once you can do so with
- /// the helper function [`BinaryViewExt::comments`].
- fn comment_references(&self) -> Array<CommentReference> {
+ /// the helper function [`BinaryView::comments`].
+ pub fn comment_references(&self) -> Array<CommentReference> {
let mut count = 0;
- let addresses_raw =
- unsafe { BNGetGlobalCommentedAddresses(self.as_ref().handle, &mut count) };
+ let addresses_raw = unsafe { BNGetGlobalCommentedAddresses(self.handle, &mut count) };
unsafe { Array::new(addresses_raw, count, ()) }
}
/// Retrieves a map of comment addresses to their contents.
///
/// This is a helper function that eagerly reads the contents of all comments within the
- /// view, use [`BinaryViewExt::comment_references`] instead if you do not wish to read all the comments.
- fn comments(&self) -> BTreeMap<u64, String> {
+ /// view, use [`BinaryView::comment_references`] instead if you do not wish to read all the comments.
+ pub fn comments(&self) -> BTreeMap<u64, String> {
self.comment_references()
.iter()
.filter_map(|cmt_ref| Some((cmt_ref.start, self.comment_at(cmt_ref.start)?)))
.collect()
}
- fn comment_at(&self, addr: u64) -> Option<String> {
+ pub fn comment_at(&self, addr: u64) -> Option<String> {
unsafe {
- let comment_raw = BNGetGlobalCommentForAddress(self.as_ref().handle, addr);
+ let comment_raw = BNGetGlobalCommentForAddress(self.handle, addr);
match comment_raw.is_null() {
false => Some(BnString::into_string(comment_raw)),
true => None,
@@ -1751,9 +2282,9 @@ pub trait BinaryViewExt: BinaryViewBase {
///
/// NOTE: This is different from setting a comment at the function-level. To set a comment in a
/// function use [`Function::set_comment_at`]
- fn set_comment_at(&self, addr: u64, comment: &str) {
+ pub fn set_comment_at(&self, addr: u64, comment: &str) {
let comment_raw = comment.to_cstr();
- unsafe { BNSetGlobalCommentForAddress(self.as_ref().handle, addr, comment_raw.as_ptr()) }
+ unsafe { BNSetGlobalCommentForAddress(self.handle, addr, comment_raw.as_ptr()) }
}
/// Retrieves a list of the next disassembly lines.
@@ -1764,7 +2295,7 @@ pub trait BinaryViewExt: BinaryViewBase {
///
/// # Arguments
/// * `pos` - Position to retrieve linear disassembly lines from
- fn get_next_linear_disassembly_lines(
+ pub fn get_next_linear_disassembly_lines(
&self,
pos: &mut LinearViewCursor,
) -> Array<LinearDisassemblyLine> {
@@ -1788,7 +2319,7 @@ pub trait BinaryViewExt: BinaryViewBase {
///
/// # Arguments
/// * `pos` - Position to retrieve linear disassembly lines relative to
- fn get_previous_linear_disassembly_lines(
+ pub fn get_previous_linear_disassembly_lines(
&self,
pos: &mut LinearViewCursor,
) -> Array<LinearDisassemblyLine> {
@@ -1804,10 +2335,10 @@ pub trait BinaryViewExt: BinaryViewBase {
result
}
- fn query_metadata(&self, key: &str) -> Option<Ref<Metadata>> {
+ pub fn query_metadata(&self, key: &str) -> Option<Ref<Metadata>> {
let key = key.to_cstr();
let value: *mut BNMetadata =
- unsafe { BNBinaryViewQueryMetadata(self.as_ref().handle, key.as_ptr()) };
+ unsafe { BNBinaryViewQueryMetadata(self.handle, key.as_ptr()) };
if value.is_null() {
None
} else {
@@ -1818,50 +2349,45 @@ pub trait BinaryViewExt: BinaryViewBase {
/// Retrieve the metadata as the type `T`.
///
/// Fails if the metadata does not exist, or if the metadata failed to coerce to type `T`.
- fn get_metadata<T>(&self, key: &str) -> Option<Result<T>>
+ pub fn get_metadata<T>(&self, key: &str) -> Option<T>
where
T: for<'a> TryFrom<&'a Metadata>,
{
self.query_metadata(key)
- .map(|md| T::try_from(md.as_ref()).map_err(|_| ()))
+ .and_then(|md| T::try_from(md.as_ref()).ok())
}
- fn store_metadata<V>(&self, key: &str, value: V, is_auto: bool)
+ pub fn store_metadata<V>(&self, key: &str, value: V, is_auto: bool)
where
V: Into<Ref<Metadata>>,
{
let md = value.into();
let key = key.to_cstr();
unsafe {
- BNBinaryViewStoreMetadata(
- self.as_ref().handle,
- key.as_ptr(),
- md.as_ref().handle,
- is_auto,
- )
+ BNBinaryViewStoreMetadata(self.handle, key.as_ptr(), md.as_ref().handle, is_auto)
};
}
- fn remove_metadata(&self, key: &str) {
+ pub fn remove_metadata(&self, key: &str) {
let key = key.to_cstr();
- unsafe { BNBinaryViewRemoveMetadata(self.as_ref().handle, key.as_ptr()) };
+ unsafe { BNBinaryViewRemoveMetadata(self.handle, key.as_ptr()) };
}
/// Retrieves a list of [CodeReference]s pointing to a given address.
- fn code_refs_to_addr(&self, addr: u64) -> Array<CodeReference> {
+ pub fn code_refs_to_addr(&self, addr: u64) -> Array<CodeReference> {
unsafe {
let mut count = 0;
- let handle = BNGetCodeReferences(self.as_ref().handle, addr, &mut count, false, 0);
+ let handle = BNGetCodeReferences(self.handle, addr, &mut count, false, 0);
Array::new(handle, count, ())
}
}
/// Retrieves a list of [CodeReference]s pointing into a given [Range].
- fn code_refs_into_range(&self, range: Range<u64>) -> Array<CodeReference> {
+ pub fn code_refs_into_range(&self, range: Range<u64>) -> Array<CodeReference> {
unsafe {
let mut count = 0;
let handle = BNGetCodeReferencesInRange(
- self.as_ref().handle,
+ self.handle,
range.start,
range.end - range.start,
&mut count,
@@ -1873,14 +2399,13 @@ pub trait BinaryViewExt: BinaryViewBase {
}
/// Retrieves a list of addresses pointed to by a given address.
- fn code_refs_from_addr(&self, addr: u64, func: Option<&Function>) -> Vec<u64> {
+ pub fn code_refs_from_addr(&self, addr: u64, func: Option<&Function>) -> Vec<u64> {
unsafe {
let mut count = 0;
let code_ref =
CodeReference::new(addr, func.map(|f| f.to_owned()), func.map(|f| f.arch()));
let mut raw_code_ref = CodeReference::into_owned_raw(&code_ref);
- let addresses =
- BNGetCodeReferencesFrom(self.as_ref().handle, &mut raw_code_ref, &mut count);
+ let addresses = BNGetCodeReferencesFrom(self.handle, &mut raw_code_ref, &mut count);
let res = std::slice::from_raw_parts(addresses, count).to_vec();
BNFreeAddressList(addresses);
res
@@ -1888,20 +2413,20 @@ pub trait BinaryViewExt: BinaryViewBase {
}
/// Retrieves a list of [DataReference]s pointing to a given address.
- fn data_refs_to_addr(&self, addr: u64) -> Array<DataReference> {
+ pub fn data_refs_to_addr(&self, addr: u64) -> Array<DataReference> {
unsafe {
let mut count = 0;
- let handle = BNGetDataReferences(self.as_ref().handle, addr, &mut count, false, 0);
+ let handle = BNGetDataReferences(self.handle, addr, &mut count, false, 0);
Array::new(handle, count, ())
}
}
/// Retrieves a list of [DataReference]s pointing into a given [Range].
- fn data_refs_into_range(&self, range: Range<u64>) -> Array<DataReference> {
+ pub fn data_refs_into_range(&self, range: Range<u64>) -> Array<DataReference> {
unsafe {
let mut count = 0;
let handle = BNGetDataReferencesInRange(
- self.as_ref().handle,
+ self.handle,
range.start,
range.end - range.start,
&mut count,
@@ -1913,60 +2438,56 @@ pub trait BinaryViewExt: BinaryViewBase {
}
/// Retrieves a list of [DataReference]s originating from a given address.
- fn data_refs_from_addr(&self, addr: u64) -> Array<DataReference> {
+ pub fn data_refs_from_addr(&self, addr: u64) -> Array<DataReference> {
unsafe {
let mut count = 0;
- let handle = BNGetDataReferencesFrom(self.as_ref().handle, addr, &mut count);
+ let handle = BNGetDataReferencesFrom(self.handle, addr, &mut count);
Array::new(handle, count, ())
}
}
/// Retrieves a list of [CodeReference]s for locations in code that use a given named type.
- fn code_refs_using_type_name<T: Into<QualifiedName>>(&self, name: T) -> Array<CodeReference> {
+ pub fn code_refs_using_type_name<T: Into<QualifiedName>>(
+ &self,
+ name: T,
+ ) -> Array<CodeReference> {
let mut raw_name = QualifiedName::into_raw(name.into());
unsafe {
let mut count = 0;
- let handle = BNGetCodeReferencesForType(
- self.as_ref().handle,
- &mut raw_name,
- &mut count,
- false,
- 0,
- );
+ let handle =
+ BNGetCodeReferencesForType(self.handle, &mut raw_name, &mut count, false, 0);
QualifiedName::free_raw(raw_name);
Array::new(handle, count, ())
}
}
/// Retrieves a list of [DataReference]s for locations in data that use a given named type.
- fn data_refs_using_type_name<T: Into<QualifiedName>>(&self, name: T) -> Array<DataReference> {
+ pub fn data_refs_using_type_name<T: Into<QualifiedName>>(
+ &self,
+ name: T,
+ ) -> Array<DataReference> {
let mut raw_name = QualifiedName::into_raw(name.into());
unsafe {
let mut count = 0;
- let handle = BNGetDataReferencesForType(
- self.as_ref().handle,
- &mut raw_name,
- &mut count,
- false,
- 0,
- );
+ let handle =
+ BNGetDataReferencesForType(self.handle, &mut raw_name, &mut count, false, 0);
QualifiedName::free_raw(raw_name);
Array::new(handle, count, ())
}
}
- fn relocations_at(&self, addr: u64) -> Array<Relocation> {
+ pub fn relocations_at(&self, addr: u64) -> Array<Relocation> {
unsafe {
let mut count = 0;
- let handle = BNGetRelocationsAt(self.as_ref().handle, addr, &mut count);
+ let handle = BNGetRelocationsAt(self.handle, addr, &mut count);
Array::new(handle, count, ())
}
}
- fn relocation_ranges(&self) -> Vec<Range<u64>> {
+ pub fn relocation_ranges(&self) -> Vec<Range<u64>> {
let ranges = unsafe {
let mut count = 0;
- let reloc_ranges_ptr = BNGetRelocationRanges(self.as_ref().handle, &mut count);
+ let reloc_ranges_ptr = BNGetRelocationRanges(self.handle, &mut count);
let ranges = std::slice::from_raw_parts(reloc_ranges_ptr, count).to_vec();
BNFreeRelocationRanges(reloc_ranges_ptr);
ranges
@@ -1982,64 +2503,62 @@ pub trait BinaryViewExt: BinaryViewBase {
.collect()
}
- fn component_by_guid(&self, guid: &str) -> Option<Ref<Component>> {
+ pub fn component_by_guid(&self, guid: &str) -> Option<Ref<Component>> {
let name = guid.to_cstr();
- let result = unsafe { BNGetComponentByGuid(self.as_ref().handle, name.as_ptr()) };
+ let result = unsafe { BNGetComponentByGuid(self.handle, name.as_ptr()) };
NonNull::new(result).map(|h| unsafe { Component::ref_from_raw(h) })
}
- fn root_component(&self) -> Option<Ref<Component>> {
- let result = unsafe { BNGetRootComponent(self.as_ref().handle) };
+ pub fn root_component(&self) -> Option<Ref<Component>> {
+ let result = unsafe { BNGetRootComponent(self.handle) };
NonNull::new(result).map(|h| unsafe { Component::ref_from_raw(h) })
}
- fn component_by_path(&self, path: &str) -> Option<Ref<Component>> {
+ pub fn component_by_path(&self, path: &str) -> Option<Ref<Component>> {
let path = path.to_cstr();
- let result = unsafe { BNGetComponentByPath(self.as_ref().handle, path.as_ptr()) };
+ let result = unsafe { BNGetComponentByPath(self.handle, path.as_ptr()) };
NonNull::new(result).map(|h| unsafe { Component::ref_from_raw(h) })
}
- fn remove_component(&self, component: &Component) -> bool {
- unsafe { BNRemoveComponent(self.as_ref().handle, component.handle.as_ptr()) }
+ pub fn remove_component(&self, component: &Component) -> bool {
+ unsafe { BNRemoveComponent(self.handle, component.handle.as_ptr()) }
}
- fn remove_component_by_guid(&self, guid: &str) -> bool {
+ pub fn remove_component_by_guid(&self, guid: &str) -> bool {
let path = guid.to_cstr();
- unsafe { BNRemoveComponentByGuid(self.as_ref().handle, path.as_ptr()) }
+ unsafe { BNRemoveComponentByGuid(self.handle, path.as_ptr()) }
}
- fn data_variable_parent_components(&self, data_variable: &DataVariable) -> Array<Component> {
+ pub fn data_variable_parent_components(
+ &self,
+ data_variable: &DataVariable,
+ ) -> Array<Component> {
let mut count = 0;
let result = unsafe {
- BNGetDataVariableParentComponents(
- self.as_ref().handle,
- data_variable.address,
- &mut count,
- )
+ BNGetDataVariableParentComponents(self.handle, data_variable.address, &mut count)
};
unsafe { Array::new(result, count, ()) }
}
- fn external_libraries(&self) -> Array<ExternalLibrary> {
+ pub fn external_libraries(&self) -> Array<ExternalLibrary> {
let mut count = 0;
- let result = unsafe { BNBinaryViewGetExternalLibraries(self.as_ref().handle, &mut count) };
+ let result = unsafe { BNBinaryViewGetExternalLibraries(self.handle, &mut count) };
unsafe { Array::new(result, count, ()) }
}
- fn external_library(&self, name: &str) -> Option<Ref<ExternalLibrary>> {
+ pub fn external_library(&self, name: &str) -> Option<Ref<ExternalLibrary>> {
let name_ptr = name.to_cstr();
- let result =
- unsafe { BNBinaryViewGetExternalLibrary(self.as_ref().handle, name_ptr.as_ptr()) };
+ let result = unsafe { BNBinaryViewGetExternalLibrary(self.handle, name_ptr.as_ptr()) };
let result_ptr = NonNull::new(result)?;
Some(unsafe { ExternalLibrary::ref_from_raw(result_ptr) })
}
- fn remove_external_library(&self, name: &str) {
+ pub fn remove_external_library(&self, name: &str) {
let name_ptr = name.to_cstr();
- unsafe { BNBinaryViewRemoveExternalLibrary(self.as_ref().handle, name_ptr.as_ptr()) };
+ unsafe { BNBinaryViewRemoveExternalLibrary(self.handle, name_ptr.as_ptr()) };
}
- fn add_external_library(
+ pub fn add_external_library(
&self,
name: &str,
backing_file: Option<&ProjectFile>,
@@ -2048,7 +2567,7 @@ pub trait BinaryViewExt: BinaryViewBase {
let name_ptr = name.to_cstr();
let result = unsafe {
BNBinaryViewAddExternalLibrary(
- self.as_ref().handle,
+ self.handle,
name_ptr.as_ptr(),
backing_file
.map(|b| b.handle.as_ptr())
@@ -2059,29 +2578,28 @@ pub trait BinaryViewExt: BinaryViewBase {
NonNull::new(result).map(|h| unsafe { ExternalLibrary::ref_from_raw(h) })
}
- fn external_locations(&self) -> Array<ExternalLocation> {
+ pub fn external_locations(&self) -> Array<ExternalLocation> {
let mut count = 0;
- let result = unsafe { BNBinaryViewGetExternalLocations(self.as_ref().handle, &mut count) };
+ let result = unsafe { BNBinaryViewGetExternalLocations(self.handle, &mut count) };
unsafe { Array::new(result, count, ()) }
}
- fn external_location_from_symbol(&self, symbol: &Symbol) -> Option<Ref<ExternalLocation>> {
- let result =
- unsafe { BNBinaryViewGetExternalLocation(self.as_ref().handle, symbol.handle) };
+ pub fn external_location_from_symbol(&self, symbol: &Symbol) -> Option<Ref<ExternalLocation>> {
+ let result = unsafe { BNBinaryViewGetExternalLocation(self.handle, symbol.handle) };
let result_ptr = NonNull::new(result)?;
Some(unsafe { ExternalLocation::ref_from_raw(result_ptr) })
}
- fn remove_external_location(&self, location: &ExternalLocation) {
+ pub fn remove_external_location(&self, location: &ExternalLocation) {
self.remove_external_location_from_symbol(&location.source_symbol())
}
- fn remove_external_location_from_symbol(&self, symbol: &Symbol) {
- unsafe { BNBinaryViewRemoveExternalLocation(self.as_ref().handle, symbol.handle) };
+ pub fn remove_external_location_from_symbol(&self, symbol: &Symbol) {
+ unsafe { BNBinaryViewRemoveExternalLocation(self.handle, symbol.handle) };
}
// TODO: This is awful, rewrite this.
- fn add_external_location(
+ pub fn add_external_location(
&self,
symbol: &Symbol,
library: &ExternalLibrary,
@@ -2095,7 +2613,7 @@ pub trait BinaryViewExt: BinaryViewBase {
.unwrap_or(std::ptr::null_mut());
let result = unsafe {
BNBinaryViewAddExternalLocation(
- self.as_ref().handle,
+ self.handle,
symbol.handle,
library.handle.as_ptr(),
target_symbol_name.as_ptr(),
@@ -2109,17 +2627,16 @@ pub trait BinaryViewExt: BinaryViewBase {
/// Type container for all types (user and auto) in the Binary View.
///
/// NOTE: Modifying an auto type will promote it to a user type.
- fn type_container(&self) -> TypeContainer {
- let type_container_ptr =
- NonNull::new(unsafe { BNGetAnalysisTypeContainer(self.as_ref().handle) });
+ pub fn type_container(&self) -> TypeContainer {
+ let type_container_ptr = NonNull::new(unsafe { BNGetAnalysisTypeContainer(self.handle) });
// NOTE: I have no idea how this isn't a UAF, see the note in `TypeContainer::from_raw`
unsafe { TypeContainer::from_raw(type_container_ptr.unwrap()) }
}
/// Type container for user types in the Binary View.
- fn user_type_container(&self) -> TypeContainer {
+ pub fn user_type_container(&self) -> TypeContainer {
let type_container_ptr =
- NonNull::new(unsafe { BNGetAnalysisUserTypeContainer(self.as_ref().handle) });
+ NonNull::new(unsafe { BNGetAnalysisUserTypeContainer(self.handle) });
// NOTE: I have no idea how this isn't a UAF, see the note in `TypeContainer::from_raw`
unsafe { TypeContainer::from_raw(type_container_ptr.unwrap()) }.clone()
}
@@ -2127,39 +2644,39 @@ pub trait BinaryViewExt: BinaryViewBase {
/// Type container for auto types in the Binary View.
///
/// NOTE: Unlike [`Self::type_container`] modification of auto types will **NOT** promote it to a user type.
- fn auto_type_container(&self) -> TypeContainer {
+ pub fn auto_type_container(&self) -> TypeContainer {
let type_container_ptr =
- NonNull::new(unsafe { BNGetAnalysisAutoTypeContainer(self.as_ref().handle) });
+ NonNull::new(unsafe { BNGetAnalysisAutoTypeContainer(self.handle) });
// NOTE: I have no idea how this isn't a UAF, see the note in `TypeContainer::from_raw`
unsafe { TypeContainer::from_raw(type_container_ptr.unwrap()) }
}
- fn type_libraries(&self) -> Array<TypeLibrary> {
+ pub fn type_libraries(&self) -> Array<TypeLibrary> {
let mut count = 0;
- let result = unsafe { BNGetBinaryViewTypeLibraries(self.as_ref().handle, &mut count) };
+ let result = unsafe { BNGetBinaryViewTypeLibraries(self.handle, &mut count) };
unsafe { Array::new(result, count, ()) }
}
/// Make the contents of a type library available for type/import resolution
- fn add_type_library(&self, library: &TypeLibrary) {
- unsafe { BNAddBinaryViewTypeLibrary(self.as_ref().handle, library.as_raw()) }
+ pub fn add_type_library(&self, library: &TypeLibrary) {
+ unsafe { BNAddBinaryViewTypeLibrary(self.handle, library.as_raw()) }
}
- fn type_library_by_name(&self, name: &str) -> Option<Ref<TypeLibrary>> {
+ pub fn type_library_by_name(&self, name: &str) -> Option<Ref<TypeLibrary>> {
let name = name.to_cstr();
- let result = unsafe { BNGetBinaryViewTypeLibrary(self.as_ref().handle, name.as_ptr()) };
+ let result = unsafe { BNGetBinaryViewTypeLibrary(self.handle, name.as_ptr()) };
NonNull::new(result).map(|h| unsafe { TypeLibrary::ref_from_raw(h) })
}
/// Should be called by custom [`BinaryView`] implementations when they have successfully
/// imported an object from a type library (eg a symbol's type). Values recorded with this
- /// function will then be queryable via [`BinaryViewExt::lookup_imported_object_library`].
+ /// function will then be queryable via [`BinaryView::lookup_imported_object_library`].
///
/// * `lib` - Type Library containing the imported type
/// * `name` - Name of the object in the type library
/// * `addr` - address of symbol at import site
/// * `platform` - Platform of symbol at import site
- fn record_imported_object_library<T: Into<QualifiedName>>(
+ pub fn record_imported_object_library<T: Into<QualifiedName>>(
&self,
lib: &TypeLibrary,
name: T,
@@ -2169,7 +2686,7 @@ pub trait BinaryViewExt: BinaryViewBase {
let mut raw_name = QualifiedName::into_raw(name.into());
unsafe {
BNBinaryViewRecordImportedObjectLibrary(
- self.as_ref().handle,
+ self.handle,
platform.handle,
addr,
lib.as_raw(),
@@ -2189,7 +2706,7 @@ pub trait BinaryViewExt: BinaryViewBase {
/// Note that the name actually inserted into the view may not match the name as it exists in
/// the type library in the event of a name conflict. To aid in this, the [`Type`] object
/// returned is a `NamedTypeReference` to the deconflicted name used.
- fn import_type_library_type<T: Into<QualifiedName>>(
+ pub fn import_type_library_type<T: Into<QualifiedName>>(
&self,
name: T,
lib: Option<&TypeLibrary>,
@@ -2199,9 +2716,8 @@ pub trait BinaryViewExt: BinaryViewBase {
.map(|l| unsafe { l.as_raw() } as *mut _)
.unwrap_or(std::ptr::null_mut());
let mut raw_name = QualifiedName::into_raw(name.into());
- let result = unsafe {
- BNBinaryViewImportTypeLibraryType(self.as_ref().handle, &mut lib_ref, &mut raw_name)
- };
+ let result =
+ unsafe { BNBinaryViewImportTypeLibraryType(self.handle, &mut lib_ref, &mut raw_name) };
QualifiedName::free_raw(raw_name);
(!result.is_null()).then(|| unsafe { Type::ref_from_raw(result) })
}
@@ -2214,9 +2730,9 @@ pub trait BinaryViewExt: BinaryViewBase {
/// libraries are lazily resolved when references to types provided by them are first encountered.
///
/// NOTE: If you are implementing a custom [`BinaryView`] and use this method to import object types,
- /// you should then call [BinaryViewExt::record_imported_object_library] with the details of
+ /// you should then call [BinaryView::record_imported_object_library] with the details of
/// where the object is located.
- fn import_type_library_object<T: Into<QualifiedName>>(
+ pub fn import_type_library_object<T: Into<QualifiedName>>(
&self,
name: T,
lib: Option<&TypeLibrary>,
@@ -2227,17 +2743,16 @@ pub trait BinaryViewExt: BinaryViewBase {
.unwrap_or(std::ptr::null_mut());
let mut raw_name = QualifiedName::into_raw(name.into());
let result = unsafe {
- BNBinaryViewImportTypeLibraryObject(self.as_ref().handle, &mut lib_ref, &mut raw_name)
+ BNBinaryViewImportTypeLibraryObject(self.handle, &mut lib_ref, &mut raw_name)
};
QualifiedName::free_raw(raw_name);
(!result.is_null()).then(|| unsafe { Type::ref_from_raw(result) })
}
/// Recursively imports a [`Type`] given its GUID from available type libraries.
- fn import_type_by_guid(&self, guid: &str) -> Option<Ref<Type>> {
+ pub fn import_type_by_guid(&self, guid: &str) -> Option<Ref<Type>> {
let guid = guid.to_cstr();
- let result =
- unsafe { BNBinaryViewImportTypeLibraryTypeByGuid(self.as_ref().handle, guid.as_ptr()) };
+ let result = unsafe { BNBinaryViewImportTypeLibraryTypeByGuid(self.handle, guid.as_ptr()) };
(!result.is_null()).then(|| unsafe { Type::ref_from_raw(result) })
}
@@ -2245,7 +2760,7 @@ pub trait BinaryViewExt: BinaryViewBase {
///
/// As other referenced types are encountered, they are either copied into the destination type library or
/// else the type library that provided the referenced type is added as a dependency for the destination library.
- fn export_type_to_library<T: Into<QualifiedName>>(
+ pub fn export_type_to_library<T: Into<QualifiedName>>(
&self,
lib: &TypeLibrary,
name: T,
@@ -2254,7 +2769,7 @@ pub trait BinaryViewExt: BinaryViewBase {
let mut raw_name = QualifiedName::into_raw(name.into());
unsafe {
BNBinaryViewExportTypeToTypeLibrary(
- self.as_ref().handle,
+ self.handle,
lib.as_raw(),
&mut raw_name,
type_obj.handle,
@@ -2267,7 +2782,7 @@ pub trait BinaryViewExt: BinaryViewBase {
///
/// As other referenced types are encountered, they are either copied into the destination type library or
/// else the type library that provided the referenced type is added as a dependency for the destination library.
- fn export_object_to_library<T: Into<QualifiedName>>(
+ pub fn export_object_to_library<T: Into<QualifiedName>>(
&self,
lib: &TypeLibrary,
name: T,
@@ -2276,7 +2791,7 @@ pub trait BinaryViewExt: BinaryViewBase {
let mut raw_name = QualifiedName::into_raw(name.into());
unsafe {
BNBinaryViewExportObjectToTypeLibrary(
- self.as_ref().handle,
+ self.handle,
lib.as_raw(),
&mut raw_name,
type_obj.handle,
@@ -2290,7 +2805,7 @@ pub trait BinaryViewExt: BinaryViewBase {
///
/// * `addr` - address of symbol at import site
/// * `platform` - Platform of symbol at import site
- fn lookup_imported_object_library(
+ pub fn lookup_imported_object_library(
&self,
addr: u64,
platform: &Platform,
@@ -2299,7 +2814,7 @@ pub trait BinaryViewExt: BinaryViewBase {
let mut result_name = BNQualifiedName::default();
let success = unsafe {
BNBinaryViewLookupImportedObjectLibrary(
- self.as_ref().handle,
+ self.handle,
platform.handle,
addr,
&mut result_lib,
@@ -2317,7 +2832,7 @@ pub trait BinaryViewExt: BinaryViewBase {
/// Gives you details of from which type library and name a given type in the analysis was imported.
///
/// * `name` - Name of type in analysis
- fn lookup_imported_type_library<T: Into<QualifiedName>>(
+ pub fn lookup_imported_type_library<T: Into<QualifiedName>>(
&self,
name: T,
) -> Option<(Ref<TypeLibrary>, QualifiedName)> {
@@ -2326,7 +2841,7 @@ pub trait BinaryViewExt: BinaryViewBase {
let mut result_name = BNQualifiedName::default();
let success = unsafe {
BNBinaryViewLookupImportedTypeLibrary(
- self.as_ref().handle,
+ self.handle,
&raw_name,
&mut result_lib,
&mut result_name,
@@ -2349,15 +2864,15 @@ pub trait BinaryViewExt: BinaryViewBase {
///
/// Some helpers for reading strings are available:
///
- /// - [`BinaryViewExt::read_c_string_at`]
- /// - [`BinaryViewExt::read_utf8_string_at`]
+ /// - [`BinaryView::read_c_string_at`]
+ /// - [`BinaryView::read_utf8_string_at`]
///
/// NOTE: This returns discovered strings and is therefore governed by `analysis.limits.minStringLength`
/// and other settings.
- fn strings(&self) -> Array<StringReference> {
+ pub fn strings(&self) -> Array<StringReference> {
unsafe {
let mut count = 0;
- let strings = BNGetStrings(self.as_ref().handle, &mut count);
+ let strings = BNGetStrings(self.handle, &mut count);
Array::new(strings, count, ())
}
}
@@ -2370,14 +2885,14 @@ pub trait BinaryViewExt: BinaryViewBase {
///
/// Some helpers for reading strings are available:
///
- /// - [`BinaryViewExt::read_c_string_at`]
- /// - [`BinaryViewExt::read_utf8_string_at`]
+ /// - [`BinaryView::read_c_string_at`]
+ /// - [`BinaryView::read_utf8_string_at`]
///
/// NOTE: This returns discovered strings and is therefore governed by `analysis.limits.minStringLength`
/// and other settings.
- fn string_at(&self, addr: u64) -> Option<StringReference> {
+ pub fn string_at(&self, addr: u64) -> Option<StringReference> {
let mut str_ref = BNStringReference::default();
- let success = unsafe { BNGetStringAtAddress(self.as_ref().handle, addr, &mut str_ref) };
+ let success = unsafe { BNGetStringAtAddress(self.handle, addr, &mut str_ref) };
if success {
Some(str_ref.into())
} else {
@@ -2393,16 +2908,16 @@ pub trait BinaryViewExt: BinaryViewBase {
///
/// Some helpers for reading strings are available:
///
- /// - [`BinaryViewExt::read_c_string_at`]
- /// - [`BinaryViewExt::read_utf8_string_at`]
+ /// - [`BinaryView::read_c_string_at`]
+ /// - [`BinaryView::read_utf8_string_at`]
///
/// NOTE: This returns discovered strings and is therefore governed by `analysis.limits.minStringLength`
/// and other settings.
- fn strings_in_range(&self, range: Range<u64>) -> Array<StringReference> {
+ pub fn strings_in_range(&self, range: Range<u64>) -> Array<StringReference> {
unsafe {
let mut count = 0;
let strings = BNGetStringsInRange(
- self.as_ref().handle,
+ self.handle,
range.start,
range.end - range.start,
&mut count,
@@ -2413,14 +2928,13 @@ pub trait BinaryViewExt: BinaryViewBase {
/// Retrieve the attached type archives as their [`TypeArchiveId`].
///
- /// Using the returned id you can retrieve the [`TypeArchive`] with [`BinaryViewExt::type_archive_by_id`].
- fn attached_type_archives(&self) -> Vec<TypeArchiveId> {
+ /// Using the returned id you can retrieve the [`TypeArchive`] with [`BinaryView::type_archive_by_id`].
+ pub fn attached_type_archives(&self) -> Vec<TypeArchiveId> {
let mut ids: *mut *mut c_char = std::ptr::null_mut();
let mut paths: *mut *mut c_char = std::ptr::null_mut();
- let count =
- unsafe { BNBinaryViewGetTypeArchives(self.as_ref().handle, &mut ids, &mut paths) };
- // We discard the path here, you can retrieve it later with [`BinaryViewExt::type_archive_path_by_id`],
- // this is so we can simplify the return type which will commonly just want to query through to the type
+ let count = unsafe { BNBinaryViewGetTypeArchives(self.handle, &mut ids, &mut paths) };
+ // We discard the path here, you can retrieve it later with [`BinaryView::type_archive_path_by_id`].
+ // This is so we can simplify the return type which will commonly just want to query through to the type
// archive itself.
let _path_list = unsafe { Array::<BnString>::new(paths, count, ()) };
let id_list = unsafe { Array::<BnString>::new(ids, count, ()) };
@@ -2433,17 +2947,17 @@ pub trait BinaryViewExt: BinaryViewBase {
/// Look up a connected [`TypeArchive`] by its `id`.
///
/// NOTE: A [`TypeArchive`] can be attached but not connected, returning `None`.
- fn type_archive_by_id(&self, id: &TypeArchiveId) -> Option<Ref<TypeArchive>> {
+ pub fn type_archive_by_id(&self, id: &TypeArchiveId) -> Option<Ref<TypeArchive>> {
let id = id.0.as_str().to_cstr();
- let result = unsafe { BNBinaryViewGetTypeArchive(self.as_ref().handle, id.as_ptr()) };
+ let result = unsafe { BNBinaryViewGetTypeArchive(self.handle, id.as_ptr()) };
let result_ptr = NonNull::new(result)?;
Some(unsafe { TypeArchive::ref_from_raw(result_ptr) })
}
/// Look up the path for an attached (but not necessarily connected) [`TypeArchive`] by its `id`.
- fn type_archive_path_by_id(&self, id: &TypeArchiveId) -> Option<PathBuf> {
+ pub fn type_archive_path_by_id(&self, id: &TypeArchiveId) -> Option<PathBuf> {
let id = id.0.as_str().to_cstr();
- let result = unsafe { BNBinaryViewGetTypeArchivePath(self.as_ref().handle, id.as_ptr()) };
+ let result = unsafe { BNBinaryViewGetTypeArchivePath(self.handle, id.as_ptr()) };
if result.is_null() {
return None;
}
@@ -2452,132 +2966,6 @@ pub trait BinaryViewExt: BinaryViewBase {
}
}
-impl<T: BinaryViewBase> BinaryViewExt for T {}
-
-/// Represents the "whole view" of the binary and its analysis.
-///
-/// Analysis information:
-///
-/// - [`BinaryViewExt::functions`]
-/// - [`BinaryViewExt::data_variables`]
-/// - [`BinaryViewExt::strings`]
-///
-/// Annotation information:
-///
-/// - [`BinaryViewExt::symbols`]
-/// - [`BinaryViewExt::tags_all_scopes`]
-/// - [`BinaryViewExt::comments`]
-///
-/// Data representation and binary information:
-///
-/// - [`BinaryViewExt::types`]
-/// - [`BinaryViewExt::segments`]
-/// - [`BinaryViewExt::sections`]
-///
-/// # Cleaning up
-///
-/// [`BinaryView`] has a cyclic relationship with the associated [`FileMetadata`], each holds a strong
-/// reference to one another, so to properly clean up/free the [`BinaryView`], you must manually close the
-/// file using [`FileMetadata::close`], this is not fixable in the general case, until [`FileMetadata`]
-/// has only a weak reference to the [`BinaryView`].
-#[derive(PartialEq, Eq, Hash)]
-pub struct BinaryView {
- pub handle: *mut BNBinaryView,
-}
-
-impl BinaryView {
- pub unsafe fn from_raw(handle: *mut BNBinaryView) -> Self {
- debug_assert!(!handle.is_null());
- Self { handle }
- }
-
- pub(crate) unsafe fn ref_from_raw(handle: *mut BNBinaryView) -> Ref<Self> {
- debug_assert!(!handle.is_null());
- Ref::new(Self { handle })
- }
-
- /// Construct the raw binary view from the given metadata.
- ///
- /// Before calling this, make sure you have a valid file path set for the [`FileMetadata`]. It is
- /// required that the [`FileMetadata::file_path`] exist in the local filesystem.
- pub fn from_metadata(meta: &FileMetadata) -> Result<Ref<Self>> {
- if !meta.file_path().exists() {
- return Err(());
- }
- let file = meta.file_path().to_cstr();
- let handle =
- unsafe { BNCreateBinaryDataViewFromFilename(meta.handle, file.as_ptr() as *mut _) };
- if handle.is_null() {
- return Err(());
- }
- unsafe { Ok(Ref::new(Self { handle })) }
- }
-
- /// Construct the raw binary view from the given `file_path` and metadata.
- ///
- /// This will implicitly set the metadata file path and then construct the view. If the metadata
- /// already has the desired file path, use [`BinaryView::from_metadata`] instead.
- pub fn from_path(meta: &FileMetadata, file_path: impl AsRef<Path>) -> Result<Ref<Self>> {
- meta.set_file_path(file_path.as_ref());
- Self::from_metadata(meta)
- }
-
- // TODO: Provide an API that manages the lifetime of the accessor and the view.
- /// Construct the raw binary view from the given `accessor` and metadata.
- ///
- /// It is the responsibility of the caller to keep the accessor alive for the lifetime of the view;
- /// because of this, we mark the function as unsafe.
- pub unsafe fn from_accessor<A: Accessor>(
- meta: &FileMetadata,
- accessor: &mut FileAccessor<A>,
- ) -> Result<Ref<Self>> {
- let handle = unsafe { BNCreateBinaryDataViewFromFile(meta.handle, &mut accessor.raw) };
- if handle.is_null() {
- return Err(());
- }
- unsafe { Ok(Ref::new(Self { handle })) }
- }
-
- /// Construct the raw binary view from the given `data` and metadata.
- ///
- /// The data will be copied into the view, so the caller does not need to keep the data alive.
- pub fn from_data(meta: &FileMetadata, data: &[u8]) -> Ref<Self> {
- let handle = unsafe {
- BNCreateBinaryDataViewFromData(meta.handle, data.as_ptr() as *mut _, data.len())
- };
- assert!(
- !handle.is_null(),
- "BNCreateBinaryDataViewFromData should always succeed"
- );
- unsafe { Ref::new(Self { handle }) }
- }
-
- /// Save the original binary file to the provided `file_path` along with any modifications.
- ///
- /// WARNING: Currently there is a possibility to deadlock if the analysis has queued up a main thread action
- /// that tries to take the [`FileMetadata`] lock of the current view, and is executed while we
- /// are executing in this function.
- ///
- /// To avoid the above issue use [`crate::main_thread::execute_on_main_thread_and_wait`] to verify there
- /// are no queued up main thread actions.
- pub fn save_to_path(&self, file_path: impl AsRef<Path>) -> bool {
- let file = file_path.as_ref().to_cstr();
- unsafe { BNSaveToFilename(self.handle, file.as_ptr() as *mut _) }
- }
-
- /// Save the original binary file to the provided [`FileAccessor`] along with any modifications.
- ///
- /// WARNING: Currently there is a possibility to deadlock if the analysis has queued up a main thread action
- /// that tries to take the [`FileMetadata`] lock of the current view, and is executed while we
- /// are executing in this function.
- ///
- /// To avoid the above issue use [`crate::main_thread::execute_on_main_thread_and_wait`] to verify there
- /// are no queued up main thread actions.
- pub fn save_to_accessor<A: Accessor>(&self, file: &mut FileAccessor<A>) -> bool {
- unsafe { BNSaveToFile(self.handle, &mut file.raw) }
- }
-}
-
impl BinaryViewBase for BinaryView {
fn read(&self, buf: &mut [u8], offset: u64) -> usize {
unsafe { BNReadViewData(self.handle, buf.as_mut_ptr() as *mut _, offset, buf.len()) }
@@ -2749,7 +3137,7 @@ where
Handler: BinaryViewEventHandler,
{
unsafe extern "C" fn on_event<Handler: BinaryViewEventHandler>(
- ctx: *mut ::std::os::raw::c_void,
+ ctx: *mut c_void,
view: *mut BNBinaryView,
) {
ffi_wrap!("EventHandler::on_event", {
@@ -2762,11 +3150,7 @@ where
let raw = Box::into_raw(boxed);
unsafe {
- BNRegisterBinaryViewEvent(
- event_type,
- Some(on_event::<Handler>),
- raw as *mut ::std::os::raw::c_void,
- );
+ BNRegisterBinaryViewEvent(event_type, Some(on_event::<Handler>), raw as *mut c_void);
}
}
@@ -2879,3 +3263,318 @@ unsafe impl CoreArrayProviderInner for AddressRange {
Self::from(*raw)
}
}
+
+extern "C" fn cb_valid<T>(ctxt: *mut c_void, data: *mut BNBinaryView) -> bool
+where
+ T: CustomBinaryViewType,
+{
+ let view_type = unsafe { &*(ctxt as *mut T) };
+ let data = unsafe { BinaryView::ref_from_raw(BNNewViewReference(data)) };
+ let _span = ffi_span!("CustomBinaryViewType::is_valid_for", data);
+ view_type.is_valid_for(&data)
+}
+
+extern "C" fn cb_deprecated<T>(_ctxt: *mut c_void) -> bool
+where
+ T: CustomBinaryViewType,
+{
+ T::DEPRECATED
+}
+
+extern "C" fn cb_force_loadable<T>(_ctxt: *mut c_void) -> bool
+where
+ T: CustomBinaryViewType,
+{
+ T::FORCE_LOADABLE
+}
+
+extern "C" fn cb_has_no_initial_content<T>(_ctxt: *mut c_void) -> bool
+where
+ T: CustomBinaryViewType,
+{
+ T::HAS_NO_INITIAL_CONTENT
+}
+
+extern "C" fn cb_create<T>(ctxt: *mut c_void, data: *mut BNBinaryView) -> *mut BNBinaryView
+where
+ T: CustomBinaryViewType,
+{
+ ffi_wrap!("CustomBinaryViewType::create", unsafe {
+ let view_type = &*(ctxt as *mut T);
+ let data = BinaryView::from_raw(data);
+ let _span = ffi_span!("CustomBinaryViewType::create", data);
+ match view_type.create_binary_view(&data) {
+ Ok(custom_view) => {
+ match BinaryView::from_custom(T::NAME, &data.file(), &data, custom_view) {
+ Ok(custom_view) => Ref::into_raw(custom_view).handle,
+ Err(_) => std::ptr::null_mut(),
+ }
+ }
+ Err(_) => std::ptr::null_mut(),
+ }
+ })
+}
+
+extern "C" fn cb_parse<T>(ctxt: *mut c_void, data: *mut BNBinaryView) -> *mut BNBinaryView
+where
+ T: CustomBinaryViewType,
+{
+ ffi_wrap!("CustomBinaryViewType::parse", unsafe {
+ let view_type = &*(ctxt as *mut T);
+ let data = BinaryView::from_raw(data);
+ let _span = ffi_span!("CustomBinaryViewType::parse", data);
+ match view_type.create_binary_view_for_parse(&data) {
+ Ok(custom_view) => {
+ match BinaryView::from_custom(T::NAME, &data.file(), &data, custom_view) {
+ Ok(custom_view) => Ref::into_raw(custom_view).handle,
+ Err(_) => std::ptr::null_mut(),
+ }
+ }
+ Err(_) => std::ptr::null_mut(),
+ }
+ })
+}
+
+extern "C" fn cb_load_settings<T>(ctxt: *mut c_void, data: *mut BNBinaryView) -> *mut BNSettings
+where
+ T: CustomBinaryViewType,
+{
+ ffi_wrap!("CustomBinaryViewType::load_settings", unsafe {
+ let view_type = &*(ctxt as *mut T);
+ let data = BinaryView::from_raw(data);
+
+ let _span = ffi_span!("CustomBinaryViewType::load_settings", data);
+ let settings = view_type.load_settings_for_data(&data);
+ Ref::into_raw(settings).handle
+ })
+}
+
+extern "C" fn cb_init<C>(ctxt: *mut c_void) -> bool
+where
+ C: CustomBinaryView,
+{
+ ffi_wrap!("BinaryViewBase::init", unsafe {
+ let context = &mut *(ctxt as *mut CustomBinaryViewContext<C>);
+ // SAFETY: The core view has been initialized by [`BinaryView::from_custom`], so it should be valid.
+ // SAFETY: The custom view is not being touched by anything else at the point this function is called,
+ // so it should be safe to mutably borrow it.
+ context.view.initialize(context.core_view.assume_init_ref())
+ })
+}
+
+extern "C" fn cb_on_after_snapshot_data_applied<C>(ctxt: *mut c_void)
+where
+ C: CustomBinaryView,
+{
+ ffi_wrap!("BinaryViewBase::onAfterSnapshotDataApplied", unsafe {
+ let context = &mut *(ctxt as *mut CustomBinaryViewContext<C>);
+ // SAFETY: The custom view is not being touched by anything else at the point this function is called,
+ // so it should be safe to mutably borrow it.
+ context.view.on_after_snapshot_data_applied();
+ })
+}
+
+extern "C" fn cb_free_object<C>(ctxt: *mut c_void)
+where
+ C: CustomBinaryView,
+{
+ ffi_wrap!("BinaryViewBase::freeObject", unsafe {
+ let context = ctxt as *mut CustomBinaryViewContext<C>;
+ let _context = Box::from_raw(context);
+ })
+}
+
+extern "C" fn cb_read<C>(ctxt: *mut c_void, dest: *mut c_void, offset: u64, len: usize) -> usize
+where
+ C: CustomBinaryView,
+{
+ ffi_wrap!("BinaryViewBase::read", unsafe {
+ let context = &*(ctxt as *mut CustomBinaryViewContext<C>);
+ let dest = std::slice::from_raw_parts_mut(dest as *mut u8, len);
+ context.view.read(dest, offset)
+ })
+}
+
+extern "C" fn cb_write<C>(ctxt: *mut c_void, offset: u64, src: *const c_void, len: usize) -> usize
+where
+ C: CustomBinaryView,
+{
+ ffi_wrap!("BinaryViewBase::write", unsafe {
+ let context = &*(ctxt as *mut CustomBinaryViewContext<C>);
+ let src = std::slice::from_raw_parts(src as *const u8, len);
+ context.view.write(offset, src)
+ })
+}
+
+extern "C" fn cb_insert<C>(ctxt: *mut c_void, offset: u64, src: *const c_void, len: usize) -> usize
+where
+ C: CustomBinaryView,
+{
+ ffi_wrap!("BinaryViewBase::insert", unsafe {
+ let context = &*(ctxt as *mut CustomBinaryViewContext<C>);
+ let src = std::slice::from_raw_parts(src as *const u8, len);
+ context.view.insert(offset, src)
+ })
+}
+
+extern "C" fn cb_remove<C>(ctxt: *mut c_void, offset: u64, len: u64) -> usize
+where
+ C: CustomBinaryView,
+{
+ ffi_wrap!("BinaryViewBase::remove", unsafe {
+ let context = &*(ctxt as *mut CustomBinaryViewContext<C>);
+ context.view.remove(offset, len as usize)
+ })
+}
+
+extern "C" fn cb_modification<C>(ctxt: *mut c_void, offset: u64) -> ModificationStatus
+where
+ C: CustomBinaryView,
+{
+ ffi_wrap!("BinaryViewBase::modification_status", unsafe {
+ let context = &*(ctxt as *mut CustomBinaryViewContext<C>);
+ context.view.modification_status(offset)
+ })
+}
+
+extern "C" fn cb_offset_valid<C>(ctxt: *mut c_void, offset: u64) -> bool
+where
+ C: CustomBinaryView,
+{
+ ffi_wrap!("BinaryViewBase::offset_valid", unsafe {
+ let context = &*(ctxt as *mut CustomBinaryViewContext<C>);
+ context.view.offset_valid(offset)
+ })
+}
+
+extern "C" fn cb_offset_readable<C>(ctxt: *mut c_void, offset: u64) -> bool
+where
+ C: CustomBinaryView,
+{
+ ffi_wrap!("BinaryViewBase::readable", unsafe {
+ let context = &*(ctxt as *mut CustomBinaryViewContext<C>);
+ context.view.offset_readable(offset)
+ })
+}
+
+extern "C" fn cb_offset_writable<C>(ctxt: *mut c_void, offset: u64) -> bool
+where
+ C: CustomBinaryView,
+{
+ ffi_wrap!("BinaryViewBase::writable", unsafe {
+ let context = &*(ctxt as *mut CustomBinaryViewContext<C>);
+ context.view.offset_writable(offset)
+ })
+}
+
+extern "C" fn cb_offset_executable<C>(ctxt: *mut c_void, offset: u64) -> bool
+where
+ C: CustomBinaryView,
+{
+ ffi_wrap!("BinaryViewBase::offset_executable", unsafe {
+ let context = &*(ctxt as *mut CustomBinaryViewContext<C>);
+ context.view.offset_executable(offset)
+ })
+}
+
+extern "C" fn cb_offset_backed_by_file<C>(ctxt: *mut c_void, offset: u64) -> bool
+where
+ C: CustomBinaryView,
+{
+ ffi_wrap!("BinaryViewBase::offset_backed_by_file", unsafe {
+ let context = &*(ctxt as *mut CustomBinaryViewContext<C>);
+ context.view.offset_backed_by_file(offset)
+ })
+}
+
+extern "C" fn cb_next_valid_offset<C>(ctxt: *mut c_void, offset: u64) -> u64
+where
+ C: CustomBinaryView,
+{
+ ffi_wrap!("BinaryViewBase::next_valid_offset_after", unsafe {
+ let context = &*(ctxt as *mut CustomBinaryViewContext<C>);
+ context.view.next_valid_offset_after(offset)
+ })
+}
+
+extern "C" fn cb_start<C>(ctxt: *mut c_void) -> u64
+where
+ C: CustomBinaryView,
+{
+ ffi_wrap!("BinaryViewBase::start", unsafe {
+ let context = &*(ctxt as *mut CustomBinaryViewContext<C>);
+ context.view.start()
+ })
+}
+
+extern "C" fn cb_length<C>(ctxt: *mut c_void) -> u64
+where
+ C: CustomBinaryView,
+{
+ ffi_wrap!("BinaryViewBase::len", unsafe {
+ let context = &*(ctxt as *mut CustomBinaryViewContext<C>);
+ context.view.len()
+ })
+}
+
+extern "C" fn cb_entry_point<C>(ctxt: *mut c_void) -> u64
+where
+ C: CustomBinaryView,
+{
+ ffi_wrap!("BinaryViewBase::entry_point", unsafe {
+ let context = &*(ctxt as *mut CustomBinaryViewContext<C>);
+ context.view.entry_point()
+ })
+}
+
+extern "C" fn cb_executable<C>(ctxt: *mut c_void) -> bool
+where
+ C: CustomBinaryView,
+{
+ ffi_wrap!("BinaryViewBase::executable", unsafe {
+ let context = &*(ctxt as *mut CustomBinaryViewContext<C>);
+ context.view.executable()
+ })
+}
+
+extern "C" fn cb_endianness<C>(ctxt: *mut c_void) -> Endianness
+where
+ C: CustomBinaryView,
+{
+ ffi_wrap!("BinaryViewBase::default_endianness", unsafe {
+ let context = &*(ctxt as *mut CustomBinaryViewContext<C>);
+ context.view.default_endianness()
+ })
+}
+
+extern "C" fn cb_relocatable<C>(ctxt: *mut c_void) -> bool
+where
+ C: CustomBinaryView,
+{
+ ffi_wrap!("BinaryViewBase::relocatable", unsafe {
+ let context = &*(ctxt as *mut CustomBinaryViewContext<C>);
+ context.view.relocatable()
+ })
+}
+
+extern "C" fn cb_address_size<C>(ctxt: *mut c_void) -> usize
+where
+ C: CustomBinaryView,
+{
+ ffi_wrap!("BinaryViewBase::address_size", unsafe {
+ let context = &*(ctxt as *mut CustomBinaryViewContext<C>);
+ context.view.address_size()
+ })
+}
+
+extern "C" fn cb_save<C>(ctxt: *mut c_void, _file: *mut BNFileAccessor) -> bool
+where
+ C: CustomBinaryView,
+{
+ ffi_wrap!("BinaryViewBase::save", unsafe {
+ let context = &*(ctxt as *mut CustomBinaryViewContext<C>);
+ // TODO: Need to pass file accessor to save to.
+ // let file = FileAccessor::from_raw(file);
+ context.view.save()
+ })
+}
diff --git a/rust/src/binary_view/writer.rs b/rust/src/binary_view/writer.rs
index 512418e4..57f431fe 100644
--- a/rust/src/binary_view/writer.rs
+++ b/rust/src/binary_view/writer.rs
@@ -17,7 +17,7 @@
use binaryninjacore_sys::*;
use std::fmt::Debug;
-use crate::binary_view::{BinaryView, BinaryViewBase, BinaryViewExt};
+use crate::binary_view::{BinaryView, BinaryViewBase};
use crate::Endianness;
use crate::rc::Ref;
diff --git a/rust/src/collaboration/file.rs b/rust/src/collaboration/file.rs
index dbe2b8b9..84860dd8 100644
--- a/rust/src/collaboration/file.rs
+++ b/rust/src/collaboration/file.rs
@@ -11,7 +11,7 @@ use super::{
Remote, RemoteFolder, RemoteProject, RemoteSnapshot,
};
-use crate::binary_view::{BinaryView, BinaryViewExt};
+use crate::binary_view::BinaryView;
use crate::database::Database;
use crate::file_metadata::FileMetadata;
use crate::progress::{NoProgressCallback, ProgressCallback, SplitProgressBuilder};
diff --git a/rust/src/collaboration/project.rs b/rust/src/collaboration/project.rs
index 3a24ea8b..8ee53f6a 100644
--- a/rust/src/collaboration/project.rs
+++ b/rust/src/collaboration/project.rs
@@ -8,11 +8,10 @@ use binaryninjacore_sys::*;
use super::{
sync, CollaborationPermissionLevel, NameChangeset, Permission, Remote, RemoteFile,
- RemoteFileType, RemoteFolder,
+ RemoteFileType, RemoteFolder, RemoteUser,
};
-use crate::binary_view::{BinaryView, BinaryViewExt};
-use crate::collaboration::RemoteUser;
+use crate::binary_view::BinaryView;
use crate::database::Database;
use crate::file_metadata::FileMetadata;
use crate::progress::{NoProgressCallback, ProgressCallback};
diff --git a/rust/src/collaboration/snapshot.rs b/rust/src/collaboration/snapshot.rs
index 203d8677..3e99805d 100644
--- a/rust/src/collaboration/snapshot.rs
+++ b/rust/src/collaboration/snapshot.rs
@@ -3,7 +3,7 @@ use std::ptr::NonNull;
use std::time::SystemTime;
use super::{sync, Remote, RemoteFile, RemoteProject};
-use crate::binary_view::{BinaryView, BinaryViewExt};
+use crate::binary_view::BinaryView;
use crate::collaboration::undo::{RemoteUndoEntry, RemoteUndoEntryId};
use crate::database::snapshot::Snapshot;
use crate::progress::{NoProgressCallback, ProgressCallback};
diff --git a/rust/src/collaboration/sync.rs b/rust/src/collaboration/sync.rs
index 72c57a46..1bf9c010 100644
--- a/rust/src/collaboration/sync.rs
+++ b/rust/src/collaboration/sync.rs
@@ -6,7 +6,7 @@ use std::ffi::{c_char, c_void};
use std::path::{Path, PathBuf};
use std::ptr::NonNull;
-use crate::binary_view::{BinaryView, BinaryViewExt};
+use crate::binary_view::BinaryView;
use crate::database::{snapshot::Snapshot, Database};
use crate::file_metadata::FileMetadata;
use crate::progress::{NoProgressCallback, ProgressCallback};
@@ -138,7 +138,7 @@ pub fn get_remote_for_local_database(database: &Database) -> Result<Option<Ref<R
.ok_or(())
}
-/// Get the Remote for a BinaryView
+/// Get the [`Remote`] for the given [`BinaryView`].
pub fn get_remote_for_binary_view(bv: &BinaryView) -> Result<Option<Ref<Remote>>, ()> {
let Some(db) = bv.file().database() else {
return Ok(None);
diff --git a/rust/src/component.rs b/rust/src/component.rs
index f038d5c3..c99081fa 100644
--- a/rust/src/component.rs
+++ b/rust/src/component.rs
@@ -1,4 +1,4 @@
-use crate::binary_view::{BinaryView, BinaryViewExt};
+use crate::binary_view::BinaryView;
use crate::function::Function;
use crate::rc::{Array, CoreArrayProvider, CoreArrayProviderInner, Guard, Ref, RefCountable};
use crate::string::{BnString, IntoCStr};
diff --git a/rust/src/custom_binary_view.rs b/rust/src/custom_binary_view.rs
deleted file mode 100644
index 84f39171..00000000
--- a/rust/src/custom_binary_view.rs
+++ /dev/null
@@ -1,961 +0,0 @@
-// Copyright 2021-2026 Vector 35 Inc.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-//! An interface for providing your own [BinaryView]s to Binary Ninja.
-
-use binaryninjacore_sys::*;
-
-pub use binaryninjacore_sys::BNModificationStatus as ModificationStatus;
-
-use std::fmt::Debug;
-use std::marker::PhantomData;
-use std::mem::MaybeUninit;
-use std::os::raw::c_void;
-use std::ptr;
-use std::slice;
-
-use crate::architecture::Architecture;
-use crate::binary_view::{BinaryView, BinaryViewBase, BinaryViewExt, Result};
-use crate::metadata::Metadata;
-use crate::platform::Platform;
-use crate::rc::*;
-use crate::settings::Settings;
-use crate::string::*;
-use crate::Endianness;
-
-/// Registers a custom `BinaryViewType` with the core.
-///
-/// The `constructor` argument is called immediately after successful registration of the type with
-/// the core. The `BinaryViewType` argument passed to `constructor` is the object that the
-/// `AsRef<BinaryViewType>`
-/// implementation of the `CustomBinaryViewType` must return.
-pub fn register_view_type<T, F>(name: &str, long_name: &str, constructor: F) -> &'static T
-where
- T: CustomBinaryViewType,
- F: FnOnce(BinaryViewType) -> T,
-{
- extern "C" fn cb_valid<T>(ctxt: *mut c_void, data: *mut BNBinaryView) -> bool
- where
- T: CustomBinaryViewType,
- {
- let view_type = unsafe { &*(ctxt as *mut T) };
- let data = unsafe { BinaryView::ref_from_raw(BNNewViewReference(data)) };
- let _span = ffi_span!("BinaryViewTypeBase::is_valid_for", data);
- view_type.is_valid_for(&data)
- }
-
- extern "C" fn cb_deprecated<T>(ctxt: *mut c_void) -> bool
- where
- T: CustomBinaryViewType,
- {
- ffi_wrap!("BinaryViewTypeBase::is_deprecated", unsafe {
- let view_type = &*(ctxt as *mut T);
- view_type.is_deprecated()
- })
- }
-
- extern "C" fn cb_force_loadable<T>(ctxt: *mut c_void) -> bool
- where
- T: CustomBinaryViewType,
- {
- ffi_wrap!("BinaryViewTypeBase::is_force_loadable", unsafe {
- let view_type = &*(ctxt as *mut T);
- view_type.is_force_loadable()
- })
- }
-
- extern "C" fn cb_has_no_initial_content<T>(ctxt: *mut c_void) -> bool
- where
- T: CustomBinaryViewType,
- {
- ffi_wrap!("BinaryViewTypeBase::has_no_initial_content", unsafe {
- let view_type = &*(ctxt as *mut T);
- view_type.has_no_initial_content()
- })
- }
-
- extern "C" fn cb_create<T>(ctxt: *mut c_void, data: *mut BNBinaryView) -> *mut BNBinaryView
- where
- T: CustomBinaryViewType,
- {
- ffi_wrap!("BinaryViewTypeBase::create", unsafe {
- let view_type = &*(ctxt as *mut T);
- let data = BinaryView::ref_from_raw(BNNewViewReference(data));
-
- let builder = CustomViewBuilder {
- view_type,
- actual_parent: &data,
- };
-
- let _span = ffi_span!("BinaryViewTypeBase::create", data);
- match view_type.create_custom_view(&data, builder) {
- Ok(bv) => {
- // force a leak of the Ref; failure to do this would result
- // in the refcount going to 0 in the process of returning it
- // to the core -- we're transferring ownership of the Ref here
- Ref::into_raw(bv.handle).handle
- }
- Err(_) => ptr::null_mut(),
- }
- })
- }
-
- extern "C" fn cb_parse<T>(ctxt: *mut c_void, data: *mut BNBinaryView) -> *mut BNBinaryView
- where
- T: CustomBinaryViewType,
- {
- ffi_wrap!("BinaryViewTypeBase::parse", unsafe {
- let view_type = &*(ctxt as *mut T);
- let data = BinaryView::ref_from_raw(BNNewViewReference(data));
-
- let builder = CustomViewBuilder {
- view_type,
- actual_parent: &data,
- };
-
- let _span = ffi_span!("BinaryViewTypeBase::parse", data);
- match view_type.parse_custom_view(&data, builder) {
- Ok(bv) => {
- // force a leak of the Ref; failure to do this would result
- // in the refcount going to 0 in the process of returning it
- // to the core -- we're transferring ownership of the Ref here
- Ref::into_raw(bv.handle).handle
- }
- Err(_) => ptr::null_mut(),
- }
- })
- }
-
- extern "C" fn cb_load_settings<T>(ctxt: *mut c_void, data: *mut BNBinaryView) -> *mut BNSettings
- where
- T: CustomBinaryViewType,
- {
- ffi_wrap!("BinaryViewTypeBase::load_settings", unsafe {
- let view_type = &*(ctxt as *mut T);
- let data = BinaryView::ref_from_raw(BNNewViewReference(data));
-
- let _span = ffi_span!("BinaryViewTypeBase::load_settings", data);
- match view_type.load_settings_for_data(&data) {
- Some(settings) => Ref::into_raw(settings).handle,
- None => ptr::null_mut() as *mut _,
- }
- })
- }
-
- let name = name.to_cstr();
- let name_ptr = name.as_ptr();
-
- let long_name = long_name.to_cstr();
- let long_name_ptr = long_name.as_ptr();
-
- let ctxt = Box::leak(Box::new(MaybeUninit::zeroed()));
-
- let mut bn_obj = BNCustomBinaryViewType {
- context: ctxt.as_mut_ptr() as *mut _,
- create: Some(cb_create::<T>),
- parse: Some(cb_parse::<T>),
- isValidForData: Some(cb_valid::<T>),
- isDeprecated: Some(cb_deprecated::<T>),
- isForceLoadable: Some(cb_force_loadable::<T>),
- getLoadSettingsForData: Some(cb_load_settings::<T>),
- hasNoInitialContent: Some(cb_has_no_initial_content::<T>),
- };
-
- unsafe {
- let handle = BNRegisterBinaryViewType(name_ptr, long_name_ptr, &mut bn_obj as *mut _);
- if handle.is_null() {
- // avoid leaking the space allocated for the type, but also
- // avoid running its Drop impl (if any -- not that there should
- // be one since view types live for the life of the process) as
- // MaybeUninit suppress the Drop implementation of it's inner type
- drop(Box::from_raw(ctxt));
- panic!("bvt registration failed");
- }
-
- ctxt.write(constructor(BinaryViewType { handle }));
- ctxt.assume_init_mut()
- }
-}
-
-pub trait BinaryViewTypeBase: AsRef<BinaryViewType> {
- /// Is this [`BinaryViewType`] valid for the given the raw [`BinaryView`]?
- ///
- /// Typical implementations will read the magic bytes (e.g. 'MZ'), this is a performance-sensitive
- /// path so prefer inexpensive checks rather than comprehensive ones.
- fn is_valid_for(&self, data: &BinaryView) -> bool;
-
- /// Is this [`BinaryViewType`] deprecated and should not be used?
- ///
- /// We specify this such that the view type may still be used by existing databases, but not
- /// newly created views.
- fn is_deprecated(&self) -> bool {
- false
- }
-
- /// Is this [`BinaryViewType`] able to be loaded forcefully?
- ///
- /// If so, it will be shown in the drop-down when a user opens a file with options.
- fn is_force_loadable(&self) -> bool {
- false
- }
-
- /// Do instances of this [`BinaryViewType`] start with no loaded content?
- ///
- /// When true, the view has no meaningful default state: the user must make a
- /// selection (e.g. load images from a shared cache) before any content exists.
- /// Callers can use this to suppress restoring previously-saved view state for
- /// files not being loaded from a database, since a saved layout would reference
- /// content that isn't available on reopen.
- fn has_no_initial_content(&self) -> bool {
- false
- }
-
- fn default_load_settings_for_data(&self, data: &BinaryView) -> Option<Ref<Settings>> {
- let settings_handle =
- unsafe { BNGetBinaryViewDefaultLoadSettingsForData(self.as_ref().handle, data.handle) };
-
- if settings_handle.is_null() {
- None
- } else {
- unsafe { Some(Settings::ref_from_raw(settings_handle)) }
- }
- }
-
- fn load_settings_for_data(&self, _data: &BinaryView) -> Option<Ref<Settings>> {
- None
- }
-}
-
-pub trait BinaryViewTypeExt: BinaryViewTypeBase {
- fn name(&self) -> String {
- unsafe { BnString::into_string(BNGetBinaryViewTypeName(self.as_ref().handle)) }
- }
-
- fn long_name(&self) -> String {
- unsafe { BnString::into_string(BNGetBinaryViewTypeLongName(self.as_ref().handle)) }
- }
-
- fn register_arch<A: Architecture>(&self, id: u32, endianness: Endianness, arch: &A) {
- unsafe {
- BNRegisterArchitectureForViewType(
- self.as_ref().handle,
- id,
- endianness,
- arch.as_ref().handle,
- );
- }
- }
-
- fn register_platform(&self, id: u32, plat: &Platform) {
- let arch = plat.arch();
-
- unsafe {
- BNRegisterPlatformForViewType(self.as_ref().handle, id, arch.handle, plat.handle);
- }
- }
-
- /// Expanded identification of [`Platform`] for [`BinaryViewType`]'s. Supersedes [`BinaryViewTypeExt::register_arch`]
- /// and [`BinaryViewTypeExt::register_platform`], as these have certain edge cases (overloaded elf families, for example)
- /// that can't be represented.
- ///
- /// The callback returns a [`Platform`] object or `None` (failure), and most recently added callbacks are called first
- /// to allow plugins to override any default behaviors. When a callback returns a platform, architecture will be
- /// derived from the identified platform.
- ///
- /// The [`BinaryView`] is the *parent* view (usually 'Raw') that the [`BinaryView`] is being created for. This
- /// means that generally speaking the callbacks need to be aware of the underlying file format, however the
- /// [`BinaryView`] implementation may have created datavars in the 'Raw' view by the time the callback is invoked.
- /// Behavior regarding when this callback is invoked and what has been made available in the [`BinaryView`] passed as an
- /// argument to the callback is up to the discretion of the [`BinaryView`] implementation.
- ///
- /// The `id` ind `endian` arguments are used as a filter to determine which registered [`Platform`] recognizer callbacks
- /// are invoked.
- ///
- /// Support for this API tentatively requires explicit support in the [`BinaryView`] implementation.
- fn register_platform_recognizer<R>(&self, id: u32, endian: Endianness, recognizer: R)
- where
- R: 'static + Fn(&BinaryView, &Metadata) -> Option<Ref<Platform>> + Send + Sync,
- {
- #[repr(C)]
- struct PlatformRecognizerHandlerContext<R>
- where
- R: 'static + Fn(&BinaryView, &Metadata) -> Option<Ref<Platform>> + Send + Sync,
- {
- recognizer: R,
- }
-
- extern "C" fn cb_recognize_low_level_il<R>(
- ctxt: *mut c_void,
- bv: *mut BNBinaryView,
- metadata: *mut BNMetadata,
- ) -> *mut BNPlatform
- where
- R: 'static + Fn(&BinaryView, &Metadata) -> Option<Ref<Platform>> + Send + Sync,
- {
- let context = unsafe { &*(ctxt as *mut PlatformRecognizerHandlerContext<R>) };
- let bv = unsafe { BinaryView::from_raw(bv).to_owned() };
- let metadata = unsafe { Metadata::from_raw(metadata).to_owned() };
- match (context.recognizer)(&bv, &metadata) {
- Some(plat) => unsafe { Ref::into_raw(plat).handle },
- None => std::ptr::null_mut(),
- }
- }
-
- let recognizer = PlatformRecognizerHandlerContext { recognizer };
- // TODO: Currently we leak `recognizer`.
- let raw = Box::into_raw(Box::new(recognizer));
-
- unsafe {
- BNRegisterPlatformRecognizerForViewType(
- self.as_ref().handle,
- id as u64,
- endian,
- Some(cb_recognize_low_level_il::<R>),
- raw as *mut c_void,
- )
- }
- }
-
- fn open(&self, data: &BinaryView) -> Result<Ref<BinaryView>> {
- let handle = unsafe { BNCreateBinaryViewOfType(self.as_ref().handle, data.handle) };
-
- if handle.is_null() {
- // TODO: Proper Result, possibly introduce BNSetError to populate.
- return Err(());
- }
-
- unsafe { Ok(BinaryView::ref_from_raw(handle)) }
- }
-
- fn parse(&self, data: &BinaryView) -> Result<Ref<BinaryView>> {
- let handle = unsafe { BNParseBinaryViewOfType(self.as_ref().handle, data.handle) };
-
- if handle.is_null() {
- // TODO: Proper Result, possibly introduce BNSetError to populate.
- return Err(());
- }
-
- unsafe { Ok(BinaryView::ref_from_raw(handle)) }
- }
-}
-
-impl<T: BinaryViewTypeBase> BinaryViewTypeExt for T {}
-
-/// A [`BinaryViewType`] acts as a factory for [`BinaryView`] objects.
-///
-/// Each file format will have its own type, such as PE, ELF, or Mach-O.
-#[derive(Copy, Clone, PartialEq, Eq, Hash)]
-pub struct BinaryViewType {
- pub handle: *mut BNBinaryViewType,
-}
-
-impl BinaryViewType {
- pub(crate) unsafe fn from_raw(handle: *mut BNBinaryViewType) -> Self {
- debug_assert!(!handle.is_null());
- Self { handle }
- }
-
- pub fn list_all() -> Array<BinaryViewType> {
- unsafe {
- let mut count: usize = 0;
- let types = BNGetBinaryViewTypes(&mut count as *mut _);
- Array::new(types, count, ())
- }
- }
-
- /// Enumerates all view types and checks to see if the given raw [`BinaryView`] is valid,
- /// returning only those that are.
- pub fn valid_types_for_data(data: &BinaryView) -> Array<BinaryViewType> {
- unsafe {
- let mut count: usize = 0;
- let types = BNGetBinaryViewTypesForData(data.handle, &mut count as *mut _);
- Array::new(types, count, ())
- }
- }
-
- /// Looks up a BinaryViewType by its short name
- pub fn by_name(name: &str) -> Result<Self> {
- let bytes = name.to_cstr();
- let handle = unsafe { BNGetBinaryViewTypeByName(bytes.as_ref().as_ptr() as *const _) };
- match handle.is_null() {
- false => Ok(unsafe { BinaryViewType::from_raw(handle) }),
- true => Err(()),
- }
- }
-}
-
-impl BinaryViewTypeBase for BinaryViewType {
- fn is_valid_for(&self, data: &BinaryView) -> bool {
- unsafe { BNIsBinaryViewTypeValidForData(self.handle, data.handle) }
- }
-
- fn is_deprecated(&self) -> bool {
- unsafe { BNIsBinaryViewTypeDeprecated(self.handle) }
- }
-
- fn is_force_loadable(&self) -> bool {
- unsafe { BNIsBinaryViewTypeForceLoadable(self.handle) }
- }
-
- fn has_no_initial_content(&self) -> bool {
- unsafe { BNBinaryViewTypeHasNoInitialContent(self.handle) }
- }
-
- fn load_settings_for_data(&self, data: &BinaryView) -> Option<Ref<Settings>> {
- let settings_handle =
- unsafe { BNGetBinaryViewLoadSettingsForData(self.handle, data.handle) };
-
- if settings_handle.is_null() {
- None
- } else {
- unsafe { Some(Settings::ref_from_raw(settings_handle)) }
- }
- }
-}
-
-impl Debug for BinaryViewType {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- f.debug_struct("BinaryViewType")
- .field("name", &self.name())
- .field("long_name", &self.long_name())
- .finish()
- }
-}
-
-impl CoreArrayProvider for BinaryViewType {
- type Raw = *mut BNBinaryViewType;
- type Context = ();
- type Wrapped<'a> = Guard<'a, BinaryViewType>;
-}
-
-unsafe impl CoreArrayProviderInner for BinaryViewType {
- unsafe fn free(raw: *mut Self::Raw, _count: usize, _context: &Self::Context) {
- BNFreeBinaryViewTypeList(raw);
- }
-
- unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
- Guard::new(BinaryViewType::from_raw(*raw), &())
- }
-}
-
-impl AsRef<BinaryViewType> for BinaryViewType {
- fn as_ref(&self) -> &Self {
- self
- }
-}
-
-unsafe impl Send for BinaryViewType {}
-unsafe impl Sync for BinaryViewType {}
-
-pub trait CustomBinaryViewType: 'static + BinaryViewTypeBase + Sync {
- fn create_custom_view<'builder>(
- &self,
- data: &BinaryView,
- builder: CustomViewBuilder<'builder, Self>,
- ) -> Result<CustomView<'builder>>;
-
- fn parse_custom_view<'builder>(
- &self,
- data: &BinaryView,
- builder: CustomViewBuilder<'builder, Self>,
- ) -> Result<CustomView<'builder>> {
- // TODO: Check to make sure data.type_name is not Self::type_name ?
- self.create_custom_view(data, builder)
- }
-}
-
-/// Represents a request from the core to instantiate a custom BinaryView
-pub struct CustomViewBuilder<'a, T: CustomBinaryViewType + ?Sized> {
- view_type: &'a T,
- actual_parent: &'a BinaryView,
-}
-
-pub unsafe trait CustomBinaryView: 'static + BinaryViewBase + Sync + Sized {
- type Args: Send;
-
- fn new(handle: &BinaryView, args: &Self::Args) -> Result<Self>;
- fn init(&mut self, args: Self::Args) -> Result<()>;
- fn on_after_snapshot_data_applied(&mut self) {}
-}
-
-/// Represents a partially initialized custom `BinaryView` that should be returned to the core
-/// from the `create_custom_view` method of a `CustomBinaryViewType`.
-#[must_use]
-pub struct CustomView<'builder> {
- // this object can't actually be treated like a real
- // BinaryView as it isn't fully initialized until the
- // core receives it from the BNCustomBinaryViewType::create
- // callback.
- handle: Ref<BinaryView>,
- _builder: PhantomData<&'builder ()>,
-}
-
-impl<'a, T: CustomBinaryViewType> CustomViewBuilder<'a, T> {
- /// Begins creating a custom BinaryView.
- ///
- /// This function may only be called from the `create_custom_view` function of a
- /// `CustomBinaryViewType`.
- ///
- /// `parent` specifies the view that the core will treat as the parent view, that
- /// Segments created against the created view will be backed by `parent`. It will
- /// usually be (but is not required to be) the `data` argument of the `create_custom_view`
- /// callback.
- ///
- /// `constructor` will not be called until well after the value returned by this function
- /// has been returned by `create_custom_view` callback to the core, and may not ever
- /// be called if the value returned by this function is dropped or leaked.
- ///
- /// # Errors
- ///
- /// This function will fail if the `FileMetadata` object associated with the *expected* parent
- /// (i.e., the `data` argument passed to the `create_custom_view` function) already has an
- /// associated `BinaryView` of the same `CustomBinaryViewType`. Multiple `BinaryView` objects
- /// of the same `BinaryViewType` belonging to the same `FileMetadata` object is prohibited and
- /// can cause strange, delayed segmentation faults.
- ///
- /// # Safety
- ///
- /// `constructor` should avoid doing anything with the object it returns, especially anything
- /// that would cause the core to invoke any of the `BinaryViewBase` methods. The core isn't
- /// going to consider the object fully initialized until after that callback has run.
- ///
- /// The `BinaryView` argument passed to the constructor function is the object that is expected
- /// to be returned by the `AsRef<BinaryView>` implementation required by the `BinaryViewBase` trait.
- /// TODO FIXME whelp this is broke going to need 2 init callbacks
- pub fn create<V>(self, parent: &BinaryView, view_args: V::Args) -> Result<CustomView<'a>>
- where
- V: CustomBinaryView,
- {
- let file = self.actual_parent.file();
- let view_type = self.view_type;
-
- let view_name = view_type.name();
-
- if let Some(bv) = file.view_of_type(&view_name) {
- // while it seems to work most of the time, you can get really unlucky
- // if a free of the existing view of the same type kicks off while
- // BNCreateBinaryViewOfType is still running. the freeObject callback
- // will run for the new view before we've even finished initializing,
- // and that's all she wrote.
- //
- // even if we deal with it gracefully in cb_free_object,
- // BNCreateBinaryViewOfType is still going to crash, so we're just
- // going to try and stop this from happening in the first place.
- tracing::error!(
- "attempt to create duplicate view of type '{}' (existing: {:?})",
- view_name,
- bv.handle
- );
-
- return Err(());
- }
-
- // struct representing the context of a BNCustomBinaryView. Can be safely
- // dropped at any moment.
- struct CustomViewContext<V>
- where
- V: CustomBinaryView,
- {
- raw_handle: *mut BNBinaryView,
- state: CustomViewContextState<V>,
- }
-
- enum CustomViewContextState<V>
- where
- V: CustomBinaryView,
- {
- Uninitialized { args: V::Args },
- Initialized { view: V },
- // dummy state, used as a helper to change states, only happen if the
- // `new` or `init` function fails.
- None,
- }
-
- impl<V: CustomBinaryView> CustomViewContext<V> {
- fn assume_init_ref(&self) -> &V {
- let CustomViewContextState::Initialized { view } = &self.state else {
- panic!("CustomViewContextState in invalid state");
- };
- view
- }
- }
-
- extern "C" fn cb_init<V>(ctxt: *mut c_void) -> bool
- where
- V: CustomBinaryView,
- {
- ffi_wrap!("BinaryViewBase::init", unsafe {
- let context = &mut *(ctxt as *mut CustomViewContext<V>);
- let handle = BinaryView::ref_from_raw(context.raw_handle);
-
- // take the uninitialized state and use the args to call init
- let mut state = CustomViewContextState::None;
- core::mem::swap(&mut context.state, &mut state);
- let CustomViewContextState::Uninitialized { args } = state else {
- panic!("CustomViewContextState in invalid state");
- };
- match V::new(handle.as_ref(), &args) {
- Ok(mut view) => match view.init(args) {
- Ok(_) => {
- // put the initialized state
- context.state = CustomViewContextState::Initialized { view };
- true
- }
- Err(_) => {
- tracing::error!(
- "CustomBinaryView::init failed; custom view returned Err"
- );
- false
- }
- },
- Err(_) => {
- tracing::error!("CustomBinaryView::new failed; custom view returned Err");
- false
- }
- }
- })
- }
-
- extern "C" fn cb_on_after_snapshot_data_applied<V>(ctxt: *mut c_void)
- where
- V: CustomBinaryView,
- {
- ffi_wrap!("BinaryViewBase::onAfterSnapshotDataApplied", unsafe {
- let context = &mut *(ctxt as *mut CustomViewContext<V>);
- if let CustomViewContextState::Initialized { view } = &mut context.state {
- view.on_after_snapshot_data_applied();
- }
- })
- }
-
- extern "C" fn cb_free_object<V>(ctxt: *mut c_void)
- where
- V: CustomBinaryView,
- {
- ffi_wrap!("BinaryViewBase::freeObject", unsafe {
- let context = ctxt as *mut CustomViewContext<V>;
- let context = Box::from_raw(context);
-
- if context.raw_handle.is_null() {
- // being called here is essentially a guarantee that BNCreateBinaryViewOfType
- // is above above us on the call stack somewhere -- no matter what we do, a crash
- // is pretty much certain at this point.
- //
- // this has been observed when two views of the same BinaryViewType are created
- // against the same BNFileMetaData object, and one of the views gets freed while
- // the second one is being initialized -- somehow the partially initialized one
- // gets freed before BNCreateBinaryViewOfType returns.
- //
- // multiples views of the same BinaryViewType in a BNFileMetaData object are
- // prohibited, so an API contract was violated in order to get here.
- //
- // if we're here, it's too late to do anything about it, though we can at least not
- // run the destructor on the custom view since that memory is uninitialized.
- tracing::error!(
- "BinaryViewBase::freeObject called on partially initialized object! crash imminent!"
- );
- } else if matches!(
- &context.state,
- CustomViewContextState::None | CustomViewContextState::Uninitialized { .. }
- ) {
- // making it here means somebody went out of their way to leak a BinaryView
- // after calling BNCreateCustomView and never gave the BNBinaryView handle
- // to the core (which would have called cb_init)
- //
- // the result is a half-initialized BinaryView that the core will happily hand out
- // references to via BNGetFileViewofType even though it was never initialized
- // all the way.
- //
- // TODO update when this corner case gets fixed in the core?
- //
- // we can't do anything to prevent this, but we can at least have the crash
- // not be our fault.
- tracing::error!("BinaryViewBase::freeObject called on leaked/never initialized custom view!");
- }
- })
- }
-
- extern "C" fn cb_read<V>(
- ctxt: *mut c_void,
- dest: *mut c_void,
- offset: u64,
- len: usize,
- ) -> usize
- where
- V: CustomBinaryView,
- {
- ffi_wrap!("BinaryViewBase::read", unsafe {
- let context = &*(ctxt as *mut CustomViewContext<V>);
- let dest = slice::from_raw_parts_mut(dest as *mut u8, len);
- context.assume_init_ref().read(dest, offset)
- })
- }
-
- extern "C" fn cb_write<V>(
- ctxt: *mut c_void,
- offset: u64,
- src: *const c_void,
- len: usize,
- ) -> usize
- where
- V: CustomBinaryView,
- {
- ffi_wrap!("BinaryViewBase::write", unsafe {
- let context = &*(ctxt as *mut CustomViewContext<V>);
- let src = slice::from_raw_parts(src as *const u8, len);
- context.assume_init_ref().write(offset, src)
- })
- }
-
- extern "C" fn cb_insert<V>(
- ctxt: *mut c_void,
- offset: u64,
- src: *const c_void,
- len: usize,
- ) -> usize
- where
- V: CustomBinaryView,
- {
- ffi_wrap!("BinaryViewBase::insert", unsafe {
- let context = &*(ctxt as *mut CustomViewContext<V>);
- let src = slice::from_raw_parts(src as *const u8, len);
- context.assume_init_ref().insert(offset, src)
- })
- }
-
- extern "C" fn cb_remove<V>(ctxt: *mut c_void, offset: u64, len: u64) -> usize
- where
- V: CustomBinaryView,
- {
- ffi_wrap!("BinaryViewBase::remove", unsafe {
- let context = &*(ctxt as *mut CustomViewContext<V>);
- context.assume_init_ref().remove(offset, len as usize)
- })
- }
-
- extern "C" fn cb_modification<V>(ctxt: *mut c_void, offset: u64) -> ModificationStatus
- where
- V: CustomBinaryView,
- {
- ffi_wrap!("BinaryViewBase::modification_status", unsafe {
- let context = &*(ctxt as *mut CustomViewContext<V>);
- context.assume_init_ref().modification_status(offset)
- })
- }
-
- extern "C" fn cb_offset_valid<V>(ctxt: *mut c_void, offset: u64) -> bool
- where
- V: CustomBinaryView,
- {
- ffi_wrap!("BinaryViewBase::offset_valid", unsafe {
- let context = &*(ctxt as *mut CustomViewContext<V>);
- context.assume_init_ref().offset_valid(offset)
- })
- }
-
- extern "C" fn cb_offset_readable<V>(ctxt: *mut c_void, offset: u64) -> bool
- where
- V: CustomBinaryView,
- {
- ffi_wrap!("BinaryViewBase::readable", unsafe {
- let context = &*(ctxt as *mut CustomViewContext<V>);
- context.assume_init_ref().offset_readable(offset)
- })
- }
-
- extern "C" fn cb_offset_writable<V>(ctxt: *mut c_void, offset: u64) -> bool
- where
- V: CustomBinaryView,
- {
- ffi_wrap!("BinaryViewBase::writable", unsafe {
- let context = &*(ctxt as *mut CustomViewContext<V>);
- context.assume_init_ref().offset_writable(offset)
- })
- }
-
- extern "C" fn cb_offset_executable<V>(ctxt: *mut c_void, offset: u64) -> bool
- where
- V: CustomBinaryView,
- {
- ffi_wrap!("BinaryViewBase::offset_executable", unsafe {
- let context = &*(ctxt as *mut CustomViewContext<V>);
- context.assume_init_ref().offset_executable(offset)
- })
- }
-
- extern "C" fn cb_offset_backed_by_file<V>(ctxt: *mut c_void, offset: u64) -> bool
- where
- V: CustomBinaryView,
- {
- ffi_wrap!("BinaryViewBase::offset_backed_by_file", unsafe {
- let context = &*(ctxt as *mut CustomViewContext<V>);
- context.assume_init_ref().offset_backed_by_file(offset)
- })
- }
-
- extern "C" fn cb_next_valid_offset<V>(ctxt: *mut c_void, offset: u64) -> u64
- where
- V: CustomBinaryView,
- {
- ffi_wrap!("BinaryViewBase::next_valid_offset_after", unsafe {
- let context = &*(ctxt as *mut CustomViewContext<V>);
- context.assume_init_ref().next_valid_offset_after(offset)
- })
- }
-
- extern "C" fn cb_start<V>(ctxt: *mut c_void) -> u64
- where
- V: CustomBinaryView,
- {
- ffi_wrap!("BinaryViewBase::start", unsafe {
- let context = &*(ctxt as *mut CustomViewContext<V>);
- context.assume_init_ref().start()
- })
- }
-
- extern "C" fn cb_length<V>(ctxt: *mut c_void) -> u64
- where
- V: CustomBinaryView,
- {
- ffi_wrap!("BinaryViewBase::len", unsafe {
- let context = &*(ctxt as *mut CustomViewContext<V>);
- context.assume_init_ref().len()
- })
- }
-
- extern "C" fn cb_entry_point<V>(ctxt: *mut c_void) -> u64
- where
- V: CustomBinaryView,
- {
- ffi_wrap!("BinaryViewBase::entry_point", unsafe {
- let context = &*(ctxt as *mut CustomViewContext<V>);
- context.assume_init_ref().entry_point()
- })
- }
-
- extern "C" fn cb_executable<V>(ctxt: *mut c_void) -> bool
- where
- V: CustomBinaryView,
- {
- ffi_wrap!("BinaryViewBase::executable", unsafe {
- let context = &*(ctxt as *mut CustomViewContext<V>);
- context.assume_init_ref().executable()
- })
- }
-
- extern "C" fn cb_endianness<V>(ctxt: *mut c_void) -> Endianness
- where
- V: CustomBinaryView,
- {
- ffi_wrap!("BinaryViewBase::default_endianness", unsafe {
- let context = &*(ctxt as *mut CustomViewContext<V>);
-
- context.assume_init_ref().default_endianness()
- })
- }
-
- extern "C" fn cb_relocatable<V>(ctxt: *mut c_void) -> bool
- where
- V: CustomBinaryView,
- {
- ffi_wrap!("BinaryViewBase::relocatable", unsafe {
- let context = &*(ctxt as *mut CustomViewContext<V>);
-
- context.assume_init_ref().relocatable()
- })
- }
-
- extern "C" fn cb_address_size<V>(ctxt: *mut c_void) -> usize
- where
- V: CustomBinaryView,
- {
- ffi_wrap!("BinaryViewBase::address_size", unsafe {
- let context = &*(ctxt as *mut CustomViewContext<V>);
-
- context.assume_init_ref().address_size()
- })
- }
-
- extern "C" fn cb_save<V>(ctxt: *mut c_void, _fa: *mut BNFileAccessor) -> bool
- where
- V: CustomBinaryView,
- {
- ffi_wrap!("BinaryViewBase::save", unsafe {
- let _context = &*(ctxt as *mut CustomViewContext<V>);
- false
- })
- }
-
- let ctxt = Box::new(CustomViewContext::<V> {
- raw_handle: ptr::null_mut(),
- state: CustomViewContextState::Uninitialized { args: view_args },
- });
-
- let ctxt = Box::into_raw(ctxt);
-
- let mut bn_obj = BNCustomBinaryView {
- context: ctxt as *mut _,
- init: Some(cb_init::<V>),
- freeObject: Some(cb_free_object::<V>),
- externalRefTaken: None,
- externalRefReleased: None,
- read: Some(cb_read::<V>),
- write: Some(cb_write::<V>),
- insert: Some(cb_insert::<V>),
- remove: Some(cb_remove::<V>),
- getModification: Some(cb_modification::<V>),
- isValidOffset: Some(cb_offset_valid::<V>),
- isOffsetReadable: Some(cb_offset_readable::<V>),
- isOffsetWritable: Some(cb_offset_writable::<V>),
- isOffsetExecutable: Some(cb_offset_executable::<V>),
- isOffsetBackedByFile: Some(cb_offset_backed_by_file::<V>),
- getNextValidOffset: Some(cb_next_valid_offset::<V>),
- getStart: Some(cb_start::<V>),
- getLength: Some(cb_length::<V>),
- getEntryPoint: Some(cb_entry_point::<V>),
- isExecutable: Some(cb_executable::<V>),
- getDefaultEndianness: Some(cb_endianness::<V>),
- isRelocatable: Some(cb_relocatable::<V>),
- getAddressSize: Some(cb_address_size::<V>),
- save: Some(cb_save::<V>),
- onAfterSnapshotDataApplied: Some(cb_on_after_snapshot_data_applied::<V>),
- };
-
- let view_name = view_name.to_cstr();
- unsafe {
- let res = BNCreateCustomBinaryView(
- view_name.as_ptr(),
- file.handle,
- parent.handle,
- &mut bn_obj,
- );
- assert!(
- !res.is_null(),
- "BNCreateCustomBinaryView cannot return null"
- );
- (*ctxt).raw_handle = res;
- Ok(CustomView {
- handle: BinaryView::ref_from_raw(res),
- _builder: PhantomData,
- })
- }
- }
-
- pub fn wrap_existing(self, wrapped_view: Ref<BinaryView>) -> Result<CustomView<'a>> {
- Ok(CustomView {
- handle: wrapped_view,
- _builder: PhantomData,
- })
- }
-}
diff --git a/rust/src/debuginfo.rs b/rust/src/debuginfo.rs
index f4cee4ff..2710537f 100644
--- a/rust/src/debuginfo.rs
+++ b/rust/src/debuginfo.rs
@@ -62,7 +62,6 @@
//! `DebugInfo` will then be automatically applied to binary views that contain debug information (via the setting `analysis.debugInfo.internal`), binary views that provide valid external debug info files (`analysis.debugInfo.external`), or manually fetched/applied as below:
//! ```no_run
//! # use binaryninja::debuginfo::DebugInfoParser;
-//! # use binaryninja::binary_view::BinaryViewExt;
//! let bv = binaryninja::load("example").unwrap();
//! let valid_parsers = DebugInfoParser::parsers_for_view(&bv);
//! let parser = valid_parsers.get(0);
diff --git a/rust/src/ffi.rs b/rust/src/ffi.rs
index d1c63216..45d142bf 100644
--- a/rust/src/ffi.rs
+++ b/rust/src/ffi.rs
@@ -34,7 +34,6 @@ pub(crate) fn time_from_bn(timestamp: u64) -> SystemTime {
#[macro_export]
macro_rules! ffi_span {
($name:expr, $bv:expr) => {{
- use $crate::binary_view::BinaryViewExt;
#[allow(unused_imports)]
use $crate::file_metadata::FileMetadata;
::tracing::info_span!($name, session_id = $bv.file().session_id().0).entered()
diff --git a/rust/src/file_metadata.rs b/rust/src/file_metadata.rs
index b58daa55..7b8a60fd 100644
--- a/rust/src/file_metadata.rs
+++ b/rust/src/file_metadata.rs
@@ -30,7 +30,7 @@ use crate::project::file::ProjectFile;
use std::ptr::NonNull;
#[allow(unused_imports)]
-use crate::custom_binary_view::BinaryViewType;
+use crate::binary_view::BinaryViewType;
new_id_type!(SessionId, usize);
@@ -472,6 +472,9 @@ impl FileMetadata {
/// The [`BinaryViewType`]s associated with this file.
///
/// For example, opening a PE binary will have the following: "Raw", "PE".
+ ///
+ /// Because the type may not have been registered, and the actual [`BinaryViewType`] is not available,
+ /// we instead return the name of the view type.
pub fn view_types(&self) -> Array<BnString> {
let mut count = 0;
unsafe {
diff --git a/rust/src/function.rs b/rust/src/function.rs
index c19e2107..90432af6 100644
--- a/rust/src/function.rs
+++ b/rust/src/function.rs
@@ -17,7 +17,7 @@ use binaryninjacore_sys::*;
use crate::{
architecture::{Architecture, CoreArchitecture, CoreRegister, Register},
basic_block::{BasicBlock, BlockContext},
- binary_view::{BinaryView, BinaryViewExt},
+ binary_view::BinaryView,
calling_convention::CoreCallingConvention,
component::Component,
disassembly::{DisassemblySettings, DisassemblyTextLine},
@@ -1157,7 +1157,7 @@ impl Function {
/// Function.add_tag, you'll create an "address tag". These are good for labeling
/// specific instructions.
///
- /// For tagging arbitrary data, consider [BinaryViewExt::add_tag].
+ /// For tagging arbitrary data, consider [BinaryView::add_tag].
///
/// * `tag_type_name` - The name of the tag type for this Tag.
/// * `data` - Additional data for the Tag.
@@ -1167,7 +1167,7 @@ impl Function {
/// # Example
///
/// ```no_run
- /// # use binaryninja::binary_view::{BinaryView, BinaryViewExt};
+ /// # use binaryninja::binary_view::BinaryView;
/// # use binaryninja::function::Function;
/// # let fun: Function = todo!();
/// # let bv: BinaryView = todo!();
diff --git a/rust/src/lib.rs b/rust/src/lib.rs
index 5f23a9f6..f420fa30 100644
--- a/rust/src/lib.rs
+++ b/rust/src/lib.rs
@@ -37,7 +37,6 @@ pub mod collaboration;
pub mod command;
pub mod component;
pub mod confidence;
-pub mod custom_binary_view;
pub mod data_buffer;
pub mod data_notification;
pub mod data_renderer;
diff --git a/rust/src/platform.rs b/rust/src/platform.rs
index bf135fae..e70e1277 100644
--- a/rust/src/platform.rs
+++ b/rust/src/platform.rs
@@ -176,7 +176,7 @@ impl Platform {
pub fn type_container(&self) -> TypeContainer {
let type_container_ptr = NonNull::new(unsafe { BNGetPlatformTypeContainer(self.handle) });
// NOTE: I have no idea how this isn't a UAF, see the note in `TypeContainer::from_raw`
- // TODO: We are cloning here for platforms but we dont need to do this for [BinaryViewExt::type_container]
+ // TODO: We are cloning here for platforms but we dont need to do this for [BinaryView::type_container]
// TODO: Why does this require that we, construct a TypeContainer, duplicate the type container, then drop the original.
unsafe { TypeContainer::from_raw(type_container_ptr.unwrap()) }
}
diff --git a/rust/src/section.rs b/rust/src/section.rs
index 7668f548..ee7e0ec7 100644
--- a/rust/src/section.rs
+++ b/rust/src/section.rs
@@ -81,7 +81,6 @@ impl Section {
///
/// ```no_run
/// # use binaryninja::section::Section;
- /// # use binaryninja::binary_view::BinaryViewExt;
/// let bv = binaryninja::load("example").unwrap();
/// bv.add_section(Section::builder("example".to_string(), 0..1024).align(4).entry_size(4))
/// ```
diff --git a/rust/src/segment.rs b/rust/src/segment.rs
index 348d8f67..a042d1fd 100644
--- a/rust/src/segment.rs
+++ b/rust/src/segment.rs
@@ -41,6 +41,9 @@ impl SegmentBuilder {
}
}
+ /// The range of the data in the parent binary view.
+ ///
+ /// If this is not specified, then the segment is "unbacked" and will contain no data.
pub fn parent_backing(mut self, parent_backing: Range<u64>) -> Self {
self.parent_backing = Some(parent_backing);
self
@@ -107,7 +110,6 @@ impl Segment {
///
/// ```no_run
/// # use binaryninja::segment::{Segment, SegmentFlags};
- /// # use binaryninja::binary_view::BinaryViewExt;
/// let bv = binaryninja::load("example").unwrap();
/// let segment_flags = SegmentFlags::new().writable(true).readable(true);
/// bv.add_segment(Segment::builder(0..0x1000).flags(segment_flags))
diff --git a/rust/src/types.rs b/rust/src/types.rs
index 65e50040..f45d93bc 100644
--- a/rust/src/types.rs
+++ b/rust/src/types.rs
@@ -36,7 +36,7 @@ use binaryninjacore_sys::*;
use crate::{
architecture::Architecture,
- binary_view::{BinaryView, BinaryViewExt},
+ binary_view::BinaryView,
calling_convention::CoreCallingConvention,
rc::*,
string::{BnString, IntoCStr},
@@ -643,7 +643,6 @@ impl Drop for TypeBuilder {
/// As an example, defining a _named_ type within a [`BinaryView`]:
///
/// ```no_run
-/// # use crate::binaryninja::binary_view::BinaryViewExt;
/// # use binaryninja::types::Type;
/// let bv = binaryninja::load("example.bin").unwrap();
/// let my_custom_type_1 = Type::named_int(5, false, "my_w");
diff --git a/rust/src/types/library.rs b/rust/src/types/library.rs
index 8743b896..9b543362 100644
--- a/rust/src/types/library.rs
+++ b/rust/src/types/library.rs
@@ -17,8 +17,6 @@ use std::ptr::NonNull;
// Used for doc comments
#[allow(unused_imports)]
use crate::binary_view::BinaryView;
-#[allow(unused_imports)]
-use crate::binary_view::BinaryViewExt;
// TODO: Introduce a FinalizedTypeLibrary that cannot be mutated, so we do not have APIs that are unusable.
@@ -261,7 +259,7 @@ impl TypeLibrary {
/// Referenced types will not automatically be added, so make sure to add referenced types to the
/// library or use [`TypeLibrary::add_type_source`] to mark the references originating source.
///
- /// To add objects from a binary view, prefer using [`BinaryViewExt::export_object_to_library`] which
+ /// To add objects from a binary view, prefer using [`BinaryView::export_object_to_library`] which
/// will automatically pull in all referenced types and record additional dependencies as needed.
pub fn add_named_object(&self, name: QualifiedName, type_: &Type) {
let mut raw_name = QualifiedName::into_raw(name);
@@ -280,7 +278,7 @@ impl TypeLibrary {
/// Referenced types will not automatically be added, so make sure to add referenced types to the
/// library or use [`TypeLibrary::add_type_source`] to mark the references originating source.
///
- /// To add types from a binary view, prefer using [`BinaryViewExt::export_type_to_library`] which
+ /// To add types from a binary view, prefer using [`BinaryView::export_type_to_library`] which
/// will automatically pull in all referenced types and record additional dependencies as needed.
pub fn add_named_type(&self, name: QualifiedName, type_: &Type) {
let mut raw_name = QualifiedName::into_raw(name);
@@ -320,7 +318,7 @@ impl TypeLibrary {
/// Get the object (function) associated with the given name, if any.
///
- /// Prefer [`BinaryViewExt::import_type_library_object`] as it will recursively import types required.
+ /// Prefer [`BinaryView::import_type_library_object`] as it will recursively import types required.
pub fn get_named_object(&self, name: QualifiedName) -> Option<Ref<Type>> {
let mut raw_name = QualifiedName::into_raw(name);
let t = unsafe { BNGetTypeLibraryNamedObject(self.as_raw(), &mut raw_name) };
@@ -330,7 +328,7 @@ impl TypeLibrary {
/// Get the type associated with the given name, if any.
///
- /// Prefer [`BinaryViewExt::import_type_library_type`] as it will recursively import types required.
+ /// Prefer [`BinaryView::import_type_library_type`] as it will recursively import types required.
pub fn get_named_type(&self, name: QualifiedName) -> Option<Ref<Type>> {
let mut raw_name = QualifiedName::into_raw(name);
let t = unsafe { BNGetTypeLibraryNamedType(self.as_raw(), &mut raw_name) };
diff --git a/rust/src/types/structure.rs b/rust/src/types/structure.rs
index 3b609287..6dd8048a 100644
--- a/rust/src/types/structure.rs
+++ b/rust/src/types/structure.rs
@@ -7,9 +7,9 @@ use crate::types::{
use binaryninjacore_sys::*;
use std::fmt::{Debug, Formatter};
-// Needed for doc comments
+// Used for documentation purposes.
#[allow(unused)]
-use crate::binary_view::BinaryViewExt;
+use crate::binary_view::BinaryView;
#[derive(PartialEq, Eq, Hash)]
pub struct StructureBuilder {
@@ -18,7 +18,6 @@ pub struct StructureBuilder {
/// ```no_run
/// // Includes
-/// # use binaryninja::binary_view::BinaryViewExt;
/// use binaryninja::types::{MemberAccess, MemberScope, Structure, StructureBuilder, Type};
///
/// // Types to use in the members
@@ -349,7 +348,7 @@ impl Structure {
///
/// We must pass a [`TypeContainer`] here so that we can resolve base structure members, as they
/// are treated as members through this function. Typically, you get the [`TypeContainer`]
- /// through the binary view with [`BinaryViewExt::type_container`].
+ /// through the binary view with [`BinaryView::type_container`].
pub fn members_at_offset(
&self,
container: &TypeContainer,
@@ -382,7 +381,7 @@ impl Structure {
/// Returns the list of all structure members, including inherited ones.
///
/// Because we must traverse through base structures, we have to provide the [`TypeContainer`];
- /// in most cases it is ok to provide the binary views container via [`BinaryViewExt::type_container`].
+ /// in most cases it is ok to provide the binary views container via [`BinaryView::type_container`].
pub fn members_including_inherited(
&self,
container: &TypeContainer,
diff --git a/rust/src/workflow.rs b/rust/src/workflow.rs
index e53e0001..72d02237 100644
--- a/rust/src/workflow.rs
+++ b/rust/src/workflow.rs
@@ -2,7 +2,7 @@ use binaryninjacore_sys::*;
// Needed for documentation.
#[allow(unused)]
-use crate::binary_view::{memory_map::MemoryMap, BinaryViewBase, BinaryViewExt};
+use crate::binary_view::{memory_map::MemoryMap, BinaryViewBase};
use crate::basic_block::BasicBlock;
use crate::binary_view::BinaryView;