summaryrefslogtreecommitdiff
path: root/rust/src/binaryview.rs
diff options
context:
space:
mode:
Diffstat (limited to 'rust/src/binaryview.rs')
-rw-r--r--rust/src/binaryview.rs214
1 files changed, 205 insertions, 9 deletions
diff --git a/rust/src/binaryview.rs b/rust/src/binaryview.rs
index 7da5a744..83249309 100644
--- a/rust/src/binaryview.rs
+++ b/rust/src/binaryview.rs
@@ -23,15 +23,11 @@ pub use binaryninjacore_sys::BNAnalysisState as AnalysisState;
pub use binaryninjacore_sys::BNModificationStatus as ModificationStatus;
use std::collections::HashMap;
-use std::ffi::c_void;
+use std::ffi::{c_char, c_void};
use std::ops::Range;
-use std::os::raw::c_char;
-use std::ptr;
-use std::result;
-use std::{ops, slice};
+use std::{ops, ptr, result, slice};
-use crate::architecture::Architecture;
-use crate::architecture::CoreArchitecture;
+use crate::architecture::{Architecture, CoreArchitecture};
use crate::basicblock::BasicBlock;
use crate::component::{Component, ComponentBuilder, IntoComponentGuid};
use crate::databuffer::DataBuffer;
@@ -40,8 +36,7 @@ use crate::fileaccessor::FileAccessor;
use crate::filemetadata::FileMetadata;
use crate::flowgraph::FlowGraph;
use crate::function::{Function, NativeBlock};
-use crate::linearview::LinearDisassemblyLine;
-use crate::linearview::LinearViewCursor;
+use crate::linearview::{LinearDisassemblyLine, LinearViewCursor};
use crate::metadata::Metadata;
use crate::platform::Platform;
use crate::relocation::Relocation;
@@ -50,6 +45,7 @@ use crate::segment::{Segment, SegmentBuilder};
use crate::settings::Settings;
use crate::symbol::{Symbol, SymbolType};
use crate::tags::{Tag, TagType};
+use crate::typelibrary::TypeLibrary;
use crate::types::{
Conf, DataVariable, NamedTypeReference, QualifiedName, QualifiedNameAndType, Type,
};
@@ -1429,6 +1425,206 @@ pub trait BinaryViewExt: BinaryViewBase {
};
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()) }
+ }
+
+ fn type_library_by_name<S: BnStrCompatible>(&self, name: S) -> Option<TypeLibrary> {
+ let name = name.into_bytes_with_nul();
+ let result = unsafe {
+ BNGetBinaryViewTypeLibrary(
+ self.as_ref().handle,
+ name.as_ref().as_ptr() as *const core::ffi::c_char,
+ )
+ };
+ core::ptr::NonNull::new(result).map(|h| unsafe { TypeLibrary::from_raw(h) })
+ }
+
+ /// Should be called by custom py:py:class:`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].
+ ///
+ /// * `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(
+ &self,
+ lib: &TypeLibrary,
+ name: &QualifiedName,
+ addr: u64,
+ platform: &Platform,
+ ) {
+ unsafe {
+ BNBinaryViewRecordImportedObjectLibrary(
+ self.as_ref().handle,
+ platform.handle,
+ addr,
+ lib.as_raw(),
+ &name.0 as *const _ as *mut _,
+ )
+ }
+ }
+
+ /// Recursively imports a type from the specified type library, or, if
+ /// no library was explicitly provided, the first type library associated with the current [BinaryView]
+ /// that provides the name requested.
+ ///
+ /// This may have the impact of loading other type libraries as dependencies on other type libraries are lazily resolved
+ /// when references to types provided by them are first encountered.
+ ///
+ /// 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(
+ &self,
+ name: &QualifiedName,
+ mut lib: Option<TypeLibrary>,
+ ) -> Option<Ref<Type>> {
+ let mut lib_ref = lib
+ .as_mut()
+ .map(|l| unsafe { l.as_raw() } as *mut _)
+ .unwrap_or(ptr::null_mut());
+ let result = unsafe {
+ BNBinaryViewImportTypeLibraryType(
+ self.as_ref().handle,
+ &mut lib_ref,
+ &name.0 as *const _ as *mut _,
+ )
+ };
+ (!result.is_null()).then(|| unsafe { Type::ref_from_raw(result) })
+ }
+
+ /// Recursively imports an object from the specified type library, or, if
+ /// no library was explicitly provided, the first type library associated with the current [BinaryView]
+ /// that provides the name requested.
+ ///
+ /// This may have the impact of loading other type libraries as dependencies on other type 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 where the object is located.
+ fn import_type_object(
+ &self,
+ name: &QualifiedName,
+ mut lib: Option<TypeLibrary>,
+ ) -> Option<Ref<Type>> {
+ let mut lib_ref = lib
+ .as_mut()
+ .map(|l| unsafe { l.as_raw() } as *mut _)
+ .unwrap_or(ptr::null_mut());
+ let result = unsafe {
+ BNBinaryViewImportTypeLibraryObject(
+ self.as_ref().handle,
+ &mut lib_ref,
+ &name.0 as *const _ as *mut _,
+ )
+ };
+ (!result.is_null()).then(|| unsafe { Type::ref_from_raw(result) })
+ }
+
+ /// Recursively imports a type interface given its GUID.
+ ///
+ /// .. note:: To support this type of lookup a type library must have
+ /// contain a metadata key called "type_guids" which is a map
+ /// Dict[string_guid, string_type_name] or
+ /// Dict[string_guid, Tuple[string_type_name, type_library_name]]
+ fn import_type_by_guid<S: BnStrCompatible>(&self, guid: S) -> Option<Ref<Type>> {
+ let guid = guid.into_bytes_with_nul();
+ let result = unsafe {
+ BNBinaryViewImportTypeLibraryTypeByGuid(
+ self.as_ref().handle,
+ guid.as_ref().as_ptr() as *const c_char,
+ )
+ };
+ (!result.is_null()).then(|| unsafe { Type::ref_from_raw(result) })
+ }
+
+ /// Recursively exports `type_obj` into `lib` as a type with name `name`
+ ///
+ /// 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(&self, lib: &TypeLibrary, name: &QualifiedName, type_obj: &Type) {
+ unsafe {
+ BNBinaryViewExportTypeToTypeLibrary(
+ self.as_ref().handle,
+ lib.as_raw(),
+ &name.0 as *const _ as *mut _,
+ type_obj.handle,
+ )
+ }
+ }
+
+ /// Recursively exports `type_obj` into `lib` as a type with name `name`
+ ///
+ /// 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(&self, lib: &TypeLibrary, name: &QualifiedName, type_obj: &Type) {
+ unsafe {
+ BNBinaryViewExportObjectToTypeLibrary(
+ self.as_ref().handle,
+ lib.as_raw(),
+ &name.0 as *const _ as *mut _,
+ type_obj.handle,
+ )
+ }
+ }
+
+ /// Gives you details of which type library and name was used to determine
+ /// the type of a symbol at a given address
+ ///
+ /// * `addr` - address of symbol at import site
+ /// * `platform` - Platform of symbol at import site
+ fn lookup_imported_object_library(
+ &self,
+ addr: u64,
+ platform: &Platform,
+ ) -> Option<(TypeLibrary, QualifiedName)> {
+ let mut result_lib = ptr::null_mut();
+ let mut result_name = Default::default();
+ let success = unsafe {
+ BNBinaryViewLookupImportedObjectLibrary(
+ self.as_ref().handle,
+ platform.handle,
+ addr,
+ &mut result_lib,
+ &mut result_name,
+ )
+ };
+ if !success {
+ return None;
+ }
+ let lib = unsafe { TypeLibrary::from_raw(ptr::NonNull::new(result_lib)?) };
+ let name = QualifiedName(result_name);
+ Some((lib, name))
+ }
+
+ /// 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(
+ &self,
+ name: &QualifiedNameAndType,
+ ) -> Option<(TypeLibrary, QualifiedName)> {
+ let mut result_lib = ptr::null_mut();
+ let mut result_name = Default::default();
+ let success = unsafe {
+ BNBinaryViewLookupImportedTypeLibrary(
+ self.as_ref().handle,
+ &name.0 as *const _ as *mut _,
+ &mut result_lib,
+ &mut result_name,
+ )
+ };
+ if !success {
+ return None;
+ }
+ let lib = unsafe { TypeLibrary::from_raw(ptr::NonNull::new(result_lib)?) };
+ let name = QualifiedName(result_name);
+ Some((lib, name))
+ }
}
impl<T: BinaryViewBase> BinaryViewExt for T {}