Skip to content

Commit dc3ed31

Browse files
committed
[Rust] Misc TypeLibrary API improvements
1 parent 6a3ed1b commit dc3ed31

3 files changed

Lines changed: 67 additions & 49 deletions

File tree

rust/src/binary_view.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2189,7 +2189,7 @@ pub trait BinaryViewExt: BinaryViewBase {
21892189
/// Note that the name actually inserted into the view may not match the name as it exists in
21902190
/// the type library in the event of a name conflict. To aid in this, the [`Type`] object
21912191
/// returned is a `NamedTypeReference` to the deconflicted name used.
2192-
fn import_type_library<T: Into<QualifiedName>>(
2192+
fn import_type_library_type<T: Into<QualifiedName>>(
21932193
&self,
21942194
name: T,
21952195
lib: Option<&TypeLibrary>,
@@ -2216,7 +2216,7 @@ pub trait BinaryViewExt: BinaryViewBase {
22162216
/// NOTE: If you are implementing a custom [`BinaryView`] and use this method to import object types,
22172217
/// you should then call [BinaryViewExt::record_imported_object_library] with the details of
22182218
/// where the object is located.
2219-
fn import_type_object<T: Into<QualifiedName>>(
2219+
fn import_type_library_object<T: Into<QualifiedName>>(
22202220
&self,
22212221
name: T,
22222222
lib: Option<&TypeLibrary>,

rust/src/types/library.rs

Lines changed: 64 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use binaryninjacore_sys::*;
22
use std::fmt::{Debug, Formatter};
33

44
use crate::rc::{Guard, RefCountable};
5+
use crate::types::TypeContainer;
56
use crate::{
67
architecture::CoreArchitecture,
78
metadata::Metadata,
@@ -13,6 +14,20 @@ use crate::{
1314
use std::path::Path;
1415
use std::ptr::NonNull;
1516

17+
// Used for doc comments
18+
#[allow(unused_imports)]
19+
use crate::binary_view::BinaryView;
20+
21+
// TODO: Introduce a FinalizedTypeLibrary that cannot be mutated, so we do not have APIs that are unusable.
22+
23+
/// A [`TypeLibrary`] is a collection of function symbols and their associated types and metadata that
24+
/// correspond to a shared library or are used in conjunction with a shared library. Type libraries
25+
/// are the main way external functions in a binary view are annotated and are crucial to allowing
26+
/// proper analysis of the binary.
27+
///
28+
/// Type libraries can share common types between them by forwarding named type references to a specified
29+
/// source type library. If a type library is made available to a view, it may also pull in other type
30+
/// libraries, it is important to not treat a type library as a complete source of information.
1631
#[repr(transparent)]
1732
pub struct TypeLibrary {
1833
handle: NonNull<BNTypeLibrary>,
@@ -32,7 +47,12 @@ impl TypeLibrary {
3247
&mut *self.handle.as_ptr()
3348
}
3449

35-
pub fn new_duplicated(&self) -> Ref<Self> {
50+
/// Duplicate the type library. This creates a new, non-finalized type library object that shares
51+
/// the same underlying name and architecture.
52+
///
53+
/// IMPORTANT: This does not *actually* duplicate the type library currently, you still need to
54+
/// copy over the named types, named objects, platforms, and metadata.
55+
pub fn duplicate(&self) -> Ref<Self> {
3656
unsafe { Self::ref_from_raw(NonNull::new(BNDuplicateTypeLibrary(self.as_raw())).unwrap()) }
3757
}
3858

@@ -50,21 +70,25 @@ impl TypeLibrary {
5070
unsafe { Array::new(result, count, ()) }
5171
}
5272

53-
/// Decompresses a type library file to a file on disk.
73+
/// Decompresses a type library file to a JSON file at the given `output_path`.
5474
pub fn decompress_to_file(path: &Path, output_path: &Path) -> bool {
5575
let path = path.to_cstr();
5676
let output = output_path.to_cstr();
5777
unsafe { BNTypeLibraryDecompressToFile(path.as_ptr(), output.as_ptr()) }
5878
}
5979

60-
/// Loads a finalized type library instance from file
80+
/// Loads a finalized type library instance from the given `path`.
81+
///
82+
/// The returned type library cannot be modified.
6183
pub fn load_from_file(path: &Path) -> Option<Ref<TypeLibrary>> {
6284
let path = path.to_cstr();
6385
let handle = unsafe { BNLoadTypeLibraryFromFile(path.as_ptr()) };
6486
NonNull::new(handle).map(|h| unsafe { TypeLibrary::ref_from_raw(h) })
6587
}
6688

67-
/// Saves a finalized type library instance to file
89+
/// Saves a type library at the given `path` on disk, overwriting any existing file.
90+
///
91+
/// The path must be writable, and the parent directory must exist.
6892
pub fn write_to_file(&self, path: &Path) -> bool {
6993
let path = path.to_cstr();
7094
unsafe { BNWriteTypeLibraryToFile(self.as_raw(), path.as_ptr()) }
@@ -92,21 +116,25 @@ impl TypeLibrary {
92116
NonNull::new(handle).map(|h| unsafe { TypeLibrary::ref_from_raw(h) })
93117
}
94118

95-
/// The Architecture this type library is associated with
119+
/// The [`CoreArchitecture`] this type library is associated with.
120+
///
121+
/// Type libraries will always have a single architecture associated with it. It can have multiple
122+
/// platforms associated with it, see [`TypeLibrary::platform_names`] for more detail.
96123
pub fn arch(&self) -> CoreArchitecture {
97124
let arch = unsafe { BNGetTypeLibraryArchitecture(self.as_raw()) };
98125
assert!(!arch.is_null());
99126
unsafe { CoreArchitecture::from_raw(arch) }
100127
}
101128

102-
/// The primary name associated with this type library
129+
/// The primary name associated with this type library, this will not be used for importing type
130+
/// libraries automatically into a binary view, that is the job of [`TypeLibrary::dependency_name`].
103131
pub fn name(&self) -> String {
104132
let result = unsafe { BNGetTypeLibraryName(self.as_raw()) };
105133
assert!(!result.is_null());
106134
unsafe { BnString::into_string(result) }
107135
}
108136

109-
/// Sets the name of a type library instance that has not been finalized
137+
/// Sets the name of a type library that has not been finalized.
110138
pub fn set_name(&self, value: &str) {
111139
let value = value.to_cstr();
112140
unsafe { BNSetTypeLibraryName(self.as_raw(), value.as_ptr()) }
@@ -136,13 +164,13 @@ impl TypeLibrary {
136164
unsafe { BnString::into_string(result) }
137165
}
138166

139-
/// Sets the GUID of a type library instance that has not been finalized
167+
/// Sets the GUID of a type library instance that has not been finalized.
140168
pub fn set_guid(&self, value: &str) {
141169
let value = value.to_cstr();
142170
unsafe { BNSetTypeLibraryGuid(self.as_raw(), value.as_ptr()) }
143171
}
144172

145-
/// A list of extra names that will be considered a match by [Platform::get_type_libraries_by_name]
173+
/// A list of extra names that will be considered a match by [`Platform::get_type_libraries_by_name`]
146174
pub fn alternate_names(&self) -> Array<BnString> {
147175
let mut count = 0;
148176
let result = unsafe { BNGetTypeLibraryAlternateNames(self.as_raw(), &mut count) };
@@ -170,76 +198,66 @@ impl TypeLibrary {
170198

171199
/// Associate a platform with a type library instance that has not been finalized.
172200
///
173-
/// This will cause the library to be searchable by [Platform::get_type_libraries_by_name]
201+
/// This will cause the library to be searchable by [`Platform::get_type_libraries_by_name`]
174202
/// when loaded.
175203
///
176-
/// This does not have side affects until finalization of the type library.
204+
/// This does not have side effects until finalization of the type library.
177205
pub fn add_platform(&self, plat: &Platform) {
178206
unsafe { BNAddTypeLibraryPlatform(self.as_raw(), plat.handle) }
179207
}
180208

181-
/// Clears the list of platforms associated with a type library instance that has not been finalized
209+
/// Clears the list of platforms associated with a type library instance that has not been finalized.
182210
pub fn clear_platforms(&self) {
183211
unsafe { BNClearTypeLibraryPlatforms(self.as_raw()) }
184212
}
185213

186-
/// Flags a newly created type library instance as finalized and makes it available for Platform and Architecture
187-
/// type library searches
214+
/// Flags a newly created type library instance as finalized and makes it available for Platform
215+
/// and Architecture type library searches.
188216
pub fn finalize(&self) -> bool {
189217
unsafe { BNFinalizeTypeLibrary(self.as_raw()) }
190218
}
191219

192-
/// Retrieves a metadata associated with the given key stored in the type library
220+
/// Retrieves the metadata associated with the given key stored in the type library.
193221
pub fn query_metadata(&self, key: &str) -> Option<Ref<Metadata>> {
194222
let key = key.to_cstr();
195223
let result = unsafe { BNTypeLibraryQueryMetadata(self.as_raw(), key.as_ptr()) };
196224
(!result.is_null()).then(|| unsafe { Metadata::ref_from_raw(result) })
197225
}
198226

199-
/// Stores an object for the given key in the current type library. Objects stored using
200-
/// `store_metadata` can be retrieved from any reference to the library. Objects stored are not arbitrary python
201-
/// objects! The values stored must be able to be held in a Metadata object. See [Metadata]
202-
/// for more information. Python objects could obviously be serialized using pickle but this intentionally
203-
/// a task left to the user since there is the potential security issues.
227+
/// Stores a [`Metadata`] object in the given key for the type library.
204228
///
205229
/// This is primarily intended as a way to store Platform specific information relevant to BinaryView implementations;
206-
/// for example the PE BinaryViewType uses type library metadata to retrieve ordinal information, when available.
207-
///
208-
/// * `key` - key value to associate the Metadata object with
209-
/// * `md` - object to store.
230+
/// for example, the PE BinaryViewType uses type library metadata to retrieve ordinal information, when available.
210231
pub fn store_metadata(&self, key: &str, md: &Metadata) {
211232
let key = key.to_cstr();
212233
unsafe { BNTypeLibraryStoreMetadata(self.as_raw(), key.as_ptr(), md.handle) }
213234
}
214235

215-
/// Removes the metadata associated with key from the current type library.
236+
/// Removes the metadata associated with key from the type library.
216237
pub fn remove_metadata(&self, key: &str) {
217238
let key = key.to_cstr();
218239
unsafe { BNTypeLibraryRemoveMetadata(self.as_raw(), key.as_ptr()) }
219240
}
220241

221-
/// Retrieves the metadata associated with the current type library.
242+
/// Retrieves the metadata associated with the type library.
222243
pub fn metadata(&self) -> Ref<Metadata> {
223244
let md_handle = unsafe { BNTypeLibraryGetMetadata(self.as_raw()) };
224245
assert!(!md_handle.is_null());
225246
unsafe { Metadata::ref_from_raw(md_handle) }
226247
}
227248

228-
// TODO: implement TypeContainer
229-
// /// Type Container for all TYPES within the Type Library. Objects are not included.
230-
// /// The Type Container's Platform will be the first platform associated with the Type Library.
231-
// pub fn type_container(&self) -> TypeContainer {
232-
// let result = unsafe{ BNGetTypeLibraryTypeContainer(self.as_raw())};
233-
// unsafe{TypeContainer::from_raw(NonNull::new(result).unwrap())}
234-
// }
249+
pub fn type_container(&self) -> TypeContainer {
250+
let result = unsafe { BNGetTypeLibraryTypeContainer(self.as_raw()) };
251+
unsafe { TypeContainer::from_raw(NonNull::new(result).unwrap()) }
252+
}
235253

236254
/// Directly inserts a named object into the type library's object store.
237-
/// This is not done recursively, so care should be taken that types referring to other types
238-
/// through NamedTypeReferences are already appropriately prepared.
239255
///
240-
/// To add types and objects from an existing BinaryView, it is recommended to use
241-
/// `export_object_to_library <binaryview.BinaryView.export_object_to_library>`, which will automatically pull in
242-
/// all referenced types and record additional dependencies as needed.
256+
/// Referenced types will not automatically be added, so make sure to add referenced types to the
257+
/// library or use [`TypeLibrary::add_type_source`] to mark the references originating source.
258+
///
259+
/// To add objects from a binary view, prefer using [`BinaryView::export_object_to_library`] which
260+
/// will automatically pull in all referenced types and record additional dependencies as needed.
243261
pub fn add_named_object(&self, name: QualifiedName, type_: &Type) {
244262
let mut raw_name = QualifiedName::into_raw(name);
245263
unsafe { BNAddTypeLibraryNamedObject(self.as_raw(), &mut raw_name, type_.handle) }
@@ -274,35 +292,35 @@ impl TypeLibrary {
274292
QualifiedName::free_raw(raw_name);
275293
}
276294

277-
/// Direct extracts a reference to a contained object -- when
278-
/// attempting to extract types from a library into a BinaryView, consider using
279-
/// `import_library_object <binaryview.BinaryView.import_library_object>` instead.
295+
/// Get the object (function) associated with the given name, if any.
296+
///
297+
/// Prefer [`BinaryView::import_type_library_object`] as it will recursively import types required.
280298
pub fn get_named_object(&self, name: QualifiedName) -> Option<Ref<Type>> {
281299
let mut raw_name = QualifiedName::into_raw(name);
282300
let t = unsafe { BNGetTypeLibraryNamedObject(self.as_raw(), &mut raw_name) };
283301
QualifiedName::free_raw(raw_name);
284302
(!t.is_null()).then(|| unsafe { Type::ref_from_raw(t) })
285303
}
286304

287-
/// Direct extracts a reference to a contained type -- when
288-
/// attempting to extract types from a library into a BinaryView, consider using
289-
/// `import_library_type <binaryview.BinaryView.import_library_type>` instead.
305+
/// Get the type associated with the given name, if any.
306+
///
307+
/// Prefer [`BinaryView::import_type_library_type`] as it will recursively import types required.
290308
pub fn get_named_type(&self, name: QualifiedName) -> Option<Ref<Type>> {
291309
let mut raw_name = QualifiedName::into_raw(name);
292310
let t = unsafe { BNGetTypeLibraryNamedType(self.as_raw(), &mut raw_name) };
293311
QualifiedName::free_raw(raw_name);
294312
(!t.is_null()).then(|| unsafe { Type::ref_from_raw(t) })
295313
}
296314

297-
/// A dict containing all named objects (functions, exported variables) provided by a type library
315+
/// The list of all named objects provided by a type library
298316
pub fn named_objects(&self) -> Array<QualifiedNameAndType> {
299317
let mut count = 0;
300318
let result = unsafe { BNGetTypeLibraryNamedObjects(self.as_raw(), &mut count) };
301319
assert!(!result.is_null());
302320
unsafe { Array::new(result, count, ()) }
303321
}
304322

305-
/// A dict containing all named types provided by a type library
323+
/// The list of all named types provided by a type library
306324
pub fn named_types(&self) -> Array<QualifiedNameAndType> {
307325
let mut count = 0;
308326
let result = unsafe { BNGetTypeLibraryNamedTypes(self.as_raw(), &mut count) };

rust/tests/type_library.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ fn test_applying_type_library() {
4747
// Type library types don't exist in the view until they are imported.
4848
// Adding the type library to the view will let you import types from it without necessarily knowing "where" they came from.
4949
let found_lib_type = view
50-
.import_type_library("SIP_ADD_NEWPROVIDER", None)
50+
.import_type_library_type("SIP_ADD_NEWPROVIDER", None)
5151
.expect("SIP_ADD_NEWPROVIDER exists");
5252
assert_eq!(found_lib_type.width(), 48);
5353
// Per docs type is returned as a NamedTypeReferenceClass.

0 commit comments

Comments
 (0)