summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRubens Brandao <git@rubens.io>2024-06-13 13:35:19 -0300
committerKyle Martin <krm504@nyu.edu>2024-07-09 18:45:30 -0400
commit66cb34c9b6fc3620cc60faf8ce964b255608b69e (patch)
tree0a3f73c7383753ab26947433e46ca5c56d3d2bf7
parent273fa764cee0e0b972546bbc460e802879b109f8 (diff)
implement rust TypeLibrary
-rw-r--r--rust/src/binaryview.rs214
-rw-r--r--rust/src/lib.rs1
-rw-r--r--rust/src/platform.rs10
-rw-r--r--rust/src/typelibrary.rs362
4 files changed, 578 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 {}
diff --git a/rust/src/lib.rs b/rust/src/lib.rs
index 8cd6ba60..0eb0653c 100644
--- a/rust/src/lib.rs
+++ b/rust/src/lib.rs
@@ -166,6 +166,7 @@ pub mod string;
pub mod symbol;
pub mod tags;
pub mod templatesimplifier;
+pub mod typelibrary;
pub mod typearchive;
pub mod types;
diff --git a/rust/src/platform.rs b/rust/src/platform.rs
index 11f76284..4e31a0a2 100644
--- a/rust/src/platform.rs
+++ b/rust/src/platform.rs
@@ -23,6 +23,7 @@ use crate::{
callingconvention::CallingConvention,
rc::*,
string::*,
+ typelibrary::TypeLibrary,
types::{QualifiedName, QualifiedNameAndType, Type},
};
@@ -163,6 +164,15 @@ impl Platform {
unsafe { CoreArchitecture::from_raw(BNGetPlatformArchitecture(self.handle)) }
}
+ pub fn get_type_libraries_by_name(&self, name: &QualifiedName) -> Array<TypeLibrary> {
+ let mut count = 0;
+ let result = unsafe {
+ BNGetPlatformTypeLibrariesByName(self.handle, &name.0 as *const _ as *mut _, &mut count)
+ };
+ assert!(!result.is_null());
+ unsafe { Array::new(result, count, ()) }
+ }
+
pub fn register_os<S: BnStrCompatible>(&self, os: S) {
let os = os.into_bytes_with_nul();
diff --git a/rust/src/typelibrary.rs b/rust/src/typelibrary.rs
new file mode 100644
index 00000000..79cb6569
--- /dev/null
+++ b/rust/src/typelibrary.rs
@@ -0,0 +1,362 @@
+use binaryninjacore_sys::*;
+
+use core::{ffi, mem, ptr};
+
+use crate::{
+ architecture::CoreArchitecture,
+ metadata::Metadata,
+ platform::Platform,
+ rc::{Array, CoreArrayProvider, CoreArrayProviderInner, Ref},
+ string::{BnStrCompatible, BnString},
+ types::{QualifiedName, QualifiedNameAndType, Type},
+};
+
+pub struct TypeLibrary {
+ handle: ptr::NonNull<BNTypeLibrary>,
+}
+
+impl TypeLibrary {
+ pub(crate) unsafe fn from_raw(handle: ptr::NonNull<BNTypeLibrary>) -> Self {
+ Self { handle }
+ }
+
+ pub(crate) unsafe fn ref_from_raw(handle: &*mut BNTypeLibrary) -> &Self {
+ assert!(!handle.is_null());
+ mem::transmute(handle)
+ }
+
+ #[allow(clippy::mut_from_ref)]
+ pub(crate) unsafe fn as_raw(&self) -> &mut BNTypeLibrary {
+ &mut *self.handle.as_ptr()
+ }
+
+ pub fn new_reference(&self) -> Self {
+ unsafe {
+ Self::from_raw(ptr::NonNull::new(BNNewTypeLibraryReference(self.as_raw())).unwrap())
+ }
+ }
+
+ pub fn new_duplicated(&self) -> Self {
+ unsafe { Self::from_raw(ptr::NonNull::new(BNDuplicateTypeLibrary(self.as_raw())).unwrap()) }
+ }
+
+ /// Creates an empty type library object with a random GUID and the provided name.
+ pub fn new<S: BnStrCompatible>(arch: CoreArchitecture, name: S) -> TypeLibrary {
+ let name = name.into_bytes_with_nul();
+ let new_lib =
+ unsafe { BNNewTypeLibrary(arch.0, name.as_ref().as_ptr() as *const ffi::c_char) };
+ unsafe { TypeLibrary::from_raw(ptr::NonNull::new(new_lib).unwrap()) }
+ }
+
+ pub fn all(arch: CoreArchitecture) -> Array<TypeLibrary> {
+ let mut count = 0;
+ let result = unsafe { BNGetArchitectureTypeLibraries(arch.0, &mut count) };
+ assert!(!result.is_null());
+ unsafe { Array::new(result, count, ()) }
+ }
+
+ /// Decompresses a type library file to a file on disk.
+ pub fn decompress_to_file<P: BnStrCompatible, O: BnStrCompatible>(path: P, output: O) -> bool {
+ let path = path.into_bytes_with_nul();
+ let output = output.into_bytes_with_nul();
+ unsafe {
+ BNTypeLibraryDecompressToFile(
+ path.as_ref().as_ptr() as *const ffi::c_char,
+ output.as_ref().as_ptr() as *const ffi::c_char,
+ )
+ }
+ }
+
+ /// Loads a finalized type library instance from file
+ pub fn load_from_file<S: BnStrCompatible>(path: S) -> Option<TypeLibrary> {
+ let path = path.into_bytes_with_nul();
+ let handle =
+ unsafe { BNLoadTypeLibraryFromFile(path.as_ref().as_ptr() as *const ffi::c_char) };
+ ptr::NonNull::new(handle).map(|h| unsafe { TypeLibrary::from_raw(h) })
+ }
+
+ /// Saves a finalized type library instance to file
+ pub fn write_to_file<S: BnStrCompatible>(&self, path: S) {
+ let path = path.into_bytes_with_nul();
+ unsafe {
+ BNWriteTypeLibraryToFile(self.as_raw(), path.as_ref().as_ptr() as *const ffi::c_char)
+ }
+ }
+
+ /// Looks up the first type library found with a matching name. Keep in mind that names are not
+ /// necessarily unique.
+ pub fn from_name<S: BnStrCompatible>(arch: CoreArchitecture, name: S) -> Option<TypeLibrary> {
+ let name = name.into_bytes_with_nul();
+ let handle = unsafe {
+ BNLookupTypeLibraryByName(arch.0, name.as_ref().as_ptr() as *const ffi::c_char)
+ };
+ ptr::NonNull::new(handle).map(|h| unsafe { TypeLibrary::from_raw(h) })
+ }
+
+ /// Attempts to grab a type library associated with the provided Architecture and GUID pair
+ pub fn from_guid<S: BnStrCompatible>(arch: CoreArchitecture, guid: S) -> Option<TypeLibrary> {
+ let guid = guid.into_bytes_with_nul();
+ let handle = unsafe {
+ BNLookupTypeLibraryByGuid(arch.0, guid.as_ref().as_ptr() as *const ffi::c_char)
+ };
+ ptr::NonNull::new(handle).map(|h| unsafe { TypeLibrary::from_raw(h) })
+ }
+
+ /// The Architecture this type library is associated with
+ pub fn arch(&self) -> CoreArchitecture {
+ let arch = unsafe { BNGetTypeLibraryArchitecture(self.as_raw()) };
+ assert!(!arch.is_null());
+ CoreArchitecture(arch)
+ }
+
+ /// The primary name associated with this type library
+ pub fn name(&self) -> Option<BnString> {
+ let result = unsafe { BNGetTypeLibraryName(self.as_raw()) };
+ (!result.is_null()).then(|| unsafe { BnString::from_raw(result) })
+ }
+
+ /// Sets the name of a type library instance that has not been finalized
+ pub fn set_name<S: BnStrCompatible>(&self, value: S) {
+ let value = value.into_bytes_with_nul();
+ unsafe {
+ BNSetTypeLibraryName(self.as_raw(), value.as_ref().as_ptr() as *const ffi::c_char)
+ }
+ }
+
+ /// The `dependency_name` of a library is the name used to record dependencies across
+ /// type libraries. This allows, for example, a library with the name "musl_libc" to have
+ /// dependencies on it recorded as "libc_generic", allowing a type library to be used across
+ /// multiple platforms where each has a specific libc that also provides the name "libc_generic"
+ /// as an `alternate_name`.
+ pub fn dependency_name(&self) -> Option<BnString> {
+ let result = unsafe { BNGetTypeLibraryDependencyName(self.as_raw()) };
+ (!result.is_null()).then(|| unsafe { BnString::from_raw(result) })
+ }
+
+ /// Sets the dependency name of a type library instance that has not been finalized
+ pub fn set_dependency_name<S: BnStrCompatible>(&self, value: S) {
+ let value = value.into_bytes_with_nul();
+ unsafe {
+ BNSetTypeLibraryDependencyName(
+ self.as_raw(),
+ value.as_ref().as_ptr() as *const ffi::c_char,
+ )
+ }
+ }
+
+ /// Returns the GUID associated with the type library
+ pub fn guid(&self) -> Option<BnString> {
+ let result = unsafe { BNGetTypeLibraryGuid(self.as_raw()) };
+ (!result.is_null()).then(|| unsafe { BnString::from_raw(result) })
+ }
+
+ /// Sets the GUID of a type library instance that has not been finalized
+ pub fn set_guid<S: BnStrCompatible>(&self, value: S) {
+ let value = value.into_bytes_with_nul();
+ unsafe {
+ BNSetTypeLibraryGuid(self.as_raw(), value.as_ref().as_ptr() as *const ffi::c_char)
+ }
+ }
+
+ /// A list of extra names that will be considered a match by [Platform::get_type_libraries_by_name]
+ pub fn alternate_names(&self) -> Array<BnString> {
+ let mut count = 0;
+ let result = unsafe { BNGetTypeLibraryAlternateNames(self.as_raw(), &mut count) };
+ assert!(!result.is_null());
+ unsafe { Array::new(result, count, ()) }
+ }
+
+ /// Adds an extra name to this type library used during library lookups and dependency resolution
+ pub fn add_alternate_name<S: BnStrCompatible>(&self, value: S) {
+ let value = value.into_bytes_with_nul();
+ unsafe {
+ BNAddTypeLibraryAlternateName(
+ self.as_raw(),
+ value.as_ref().as_ptr() as *const ffi::c_char,
+ )
+ }
+ }
+
+ /// Returns a list of all platform names that this type library will register with during platform
+ /// type registration.
+ ///
+ /// This returns strings, not Platform objects, as type libraries can be distributed with support for
+ /// Platforms that may not be present.
+ pub fn platform_names(&self) -> Array<BnString> {
+ let mut count = 0;
+ let result = unsafe { BNGetTypeLibraryPlatforms(self.as_raw(), &mut count) };
+ assert!(!result.is_null());
+ unsafe { Array::new(result, count, ()) }
+ }
+
+ /// Associate a platform with a type library instance that has not been finalized.
+ ///
+ /// This will cause the library to be searchable by [Platform::get_type_libraries_by_name]
+ /// when loaded.
+ ///
+ /// This does not have side affects until finalization of the type library.
+ pub fn add_platform(&self, plat: &Platform) {
+ unsafe { BNAddTypeLibraryPlatform(self.as_raw(), plat.handle) }
+ }
+
+ /// Clears the list of platforms associated with a type library instance that has not been finalized
+ pub fn clear_platforms(&self) {
+ unsafe { BNClearTypeLibraryPlatforms(self.as_raw()) }
+ }
+
+ /// Flags a newly created type library instance as finalized and makes it available for Platform and Architecture
+ /// type library searches
+ pub fn finalize(&self) -> bool {
+ unsafe { BNFinalizeTypeLibrary(self.as_raw()) }
+ }
+
+ /// Retrieves a metadata associated with the given key stored in the type library
+ pub fn query_metadata<S: BnStrCompatible>(&self, key: S) -> Option<Metadata> {
+ let key = key.into_bytes_with_nul();
+ let result = unsafe {
+ BNTypeLibraryQueryMetadata(self.as_raw(), key.as_ref().as_ptr() as *const ffi::c_char)
+ };
+ (!result.is_null()).then(|| unsafe { Metadata::from_raw(result) })
+ }
+
+ /// Stores an object for the given key in the current type library. Objects stored using
+ /// `store_metadata` can be retrieved from any reference to the library. Objects stored are not arbitrary python
+ /// objects! The values stored must be able to be held in a Metadata object. See [Metadata]
+ /// for more information. Python objects could obviously be serialized using pickle but this intentionally
+ /// a task left to the user since there is the potential security issues.
+ ///
+ /// This is primarily intended as a way to store Platform specific information relevant to BinaryView implementations;
+ /// for example the PE BinaryViewType uses type library metadata to retrieve ordinal information, when available.
+ ///
+ /// * `key` - key value to associate the Metadata object with
+ /// * `md` - object to store.
+ pub fn store_metadata<S: BnStrCompatible>(&self, key: S, md: &Metadata) {
+ let key = key.into_bytes_with_nul();
+ unsafe {
+ BNTypeLibraryStoreMetadata(
+ self.as_raw(),
+ key.as_ref().as_ptr() as *const ffi::c_char,
+ md.handle,
+ )
+ }
+ }
+
+ /// Removes the metadata associated with key from the current type library.
+ pub fn remove_metadata<S: BnStrCompatible>(&self, key: S) {
+ let key = key.into_bytes_with_nul();
+ unsafe {
+ BNTypeLibraryRemoveMetadata(self.as_raw(), key.as_ref().as_ptr() as *const ffi::c_char)
+ }
+ }
+
+ /// Retrieves the metadata associated with the current type library.
+ pub fn metadata(&self) -> Metadata {
+ let md_handle = unsafe { BNTypeLibraryGetMetadata(self.as_raw()) };
+ assert!(!md_handle.is_null());
+ unsafe { Metadata::from_raw(md_handle) }
+ }
+
+ // TODO: implement TypeContainer
+ // /// Type Container for all TYPES within the Type Library. Objects are not included.
+ // /// The Type Container's Platform will be the first platform associated with the Type Library.
+ // pub fn type_container(&self) -> TypeContainer {
+ // let result = unsafe{ BNGetTypeLibraryTypeContainer(self.as_raw())};
+ // unsafe{TypeContainer::from_raw(ptr::NonNull::new(result).unwrap())}
+ // }
+
+ /// Directly inserts a named object into the type library's object store.
+ /// This is not done recursively, so care should be taken that types referring to other types
+ /// through NamedTypeReferences are already appropriately prepared.
+ ///
+ /// To add types and objects from an existing BinaryView, it is recommended to use
+ /// `export_object_to_library <binaryview.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) {
+ unsafe {
+ BNAddTypeLibraryNamedObject(self.as_raw(), &name.0 as *const _ as *mut _, type_.handle)
+ }
+ }
+
+ /// Directly inserts a named object into the type library's object store.
+ /// This is not done recursively, so care should be taken that types referring to other types
+ /// through NamedTypeReferences are already appropriately prepared.
+ ///
+ /// To add types and objects from an existing BinaryView, it is recommended to use
+ /// `export_type_to_library <binaryview.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: &QualifiedNameAndType, type_: &Type) {
+ unsafe {
+ BNAddTypeLibraryNamedType(self.as_raw(), &name.0 as *const _ as *mut _, type_.handle)
+ }
+ }
+
+ /// Manually flag NamedTypeReferences to the given QualifiedName as originating from another source
+ /// TypeLibrary with the given dependency name.
+ ///
+ /// .. warning:: Use this api with extreme caution.
+ pub fn add_type_source<S: BnStrCompatible>(&self, name: &QualifiedName, source: S) {
+ let source = source.into_bytes_with_nul();
+ unsafe {
+ BNAddTypeLibraryNamedTypeSource(
+ self.as_raw(),
+ &name.0 as *const _ as *mut _,
+ source.as_ref().as_ptr() as *const ffi::c_char,
+ )
+ }
+ }
+
+ /// Direct extracts a reference to a contained object -- when
+ /// attempting to extract types from a library into a BinaryView, consider using
+ /// `import_library_object <binaryview.BinaryView.import_library_object>` instead.
+ pub fn get_named_object(&self, name: &QualifiedName) -> Option<Ref<Type>> {
+ let t =
+ unsafe { BNGetTypeLibraryNamedObject(self.as_raw(), &name.0 as *const _ as *mut _) };
+ (!t.is_null()).then(|| unsafe { Type::ref_from_raw(t) })
+ }
+
+ /// Direct extracts a reference to a contained type -- when
+ /// attempting to extract types from a library into a BinaryView, consider using
+ /// `import_library_type <binaryview.BinaryView.import_library_type>` instead.
+ pub fn get_named_type(&self, name: &QualifiedName) -> Option<Ref<Type>> {
+ let t = unsafe { BNGetTypeLibraryNamedType(self.as_raw(), &name.0 as *const _ as *mut _) };
+ (!t.is_null()).then(|| unsafe { Type::ref_from_raw(t) })
+ }
+
+ /// A dict containing all named objects (functions, exported variables) provided by a type library
+ pub fn named_objects(&self) -> Array<QualifiedNameAndType> {
+ let mut count = 0;
+ let result = unsafe { BNGetTypeLibraryNamedObjects(self.as_raw(), &mut count) };
+ assert!(!result.is_null());
+ unsafe { Array::new(result, count, ()) }
+ }
+
+ /// A dict containing all named types provided by a type library
+ pub fn named_types(&self) -> Array<QualifiedNameAndType> {
+ let mut count = 0;
+ let result = unsafe { BNGetTypeLibraryNamedTypes(self.as_raw(), &mut count) };
+ assert!(!result.is_null());
+ unsafe { Array::new(result, count, ()) }
+ }
+}
+
+impl Drop for TypeLibrary {
+ fn drop(&mut self) {
+ unsafe { BNFreeTypeLibrary(self.as_raw()) }
+ }
+}
+
+impl CoreArrayProvider for TypeLibrary {
+ type Raw = *mut BNTypeLibrary;
+ type Context = ();
+ type Wrapped<'a> = &'a Self;
+}
+
+unsafe impl CoreArrayProviderInner for TypeLibrary {
+ unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
+ BNFreeTypeLibraryList(raw, count)
+ }
+
+ unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
+ Self::ref_from_raw(raw)
+ }
+}