Skip to content

Commit 7818772

Browse files
committed
[Rust] Make TypeLibrary ref counted
And some other misc cleanup
1 parent d79b019 commit 7818772

File tree

2 files changed

+57
-92
lines changed

2 files changed

+57
-92
lines changed

rust/src/binary_view.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1634,10 +1634,10 @@ pub trait BinaryViewExt: BinaryViewBase {
16341634
unsafe { BNAddBinaryViewTypeLibrary(self.as_ref().handle, library.as_raw()) }
16351635
}
16361636

1637-
fn type_library_by_name(&self, name: &str) -> Option<TypeLibrary> {
1637+
fn type_library_by_name(&self, name: &str) -> Option<Ref<TypeLibrary>> {
16381638
let name = name.to_cstr();
16391639
let result = unsafe { BNGetBinaryViewTypeLibrary(self.as_ref().handle, name.as_ptr()) };
1640-
NonNull::new(result).map(|h| unsafe { TypeLibrary::from_raw(h) })
1640+
NonNull::new(result).map(|h| unsafe { TypeLibrary::ref_from_raw(h) })
16411641
}
16421642

16431643
/// Should be called by custom py:py:class:`BinaryView` implementations
@@ -1782,7 +1782,7 @@ pub trait BinaryViewExt: BinaryViewBase {
17821782
&self,
17831783
addr: u64,
17841784
platform: &Platform,
1785-
) -> Option<(TypeLibrary, QualifiedName)> {
1785+
) -> Option<(Ref<TypeLibrary>, QualifiedName)> {
17861786
let mut result_lib = std::ptr::null_mut();
17871787
let mut result_name = BNQualifiedName::default();
17881788
let success = unsafe {
@@ -1797,7 +1797,7 @@ pub trait BinaryViewExt: BinaryViewBase {
17971797
if !success {
17981798
return None;
17991799
}
1800-
let lib = unsafe { TypeLibrary::from_raw(NonNull::new(result_lib)?) };
1800+
let lib = unsafe { TypeLibrary::ref_from_raw(NonNull::new(result_lib)?) };
18011801
let name = QualifiedName::from_owned_raw(result_name);
18021802
Some((lib, name))
18031803
}
@@ -1808,7 +1808,7 @@ pub trait BinaryViewExt: BinaryViewBase {
18081808
fn lookup_imported_type_library<T: Into<QualifiedName>>(
18091809
&self,
18101810
name: T,
1811-
) -> Option<(TypeLibrary, QualifiedName)> {
1811+
) -> Option<(Ref<TypeLibrary>, QualifiedName)> {
18121812
let raw_name = QualifiedName::into_raw(name.into());
18131813
let mut result_lib = std::ptr::null_mut();
18141814
let mut result_name = BNQualifiedName::default();
@@ -1824,7 +1824,7 @@ pub trait BinaryViewExt: BinaryViewBase {
18241824
if !success {
18251825
return None;
18261826
}
1827-
let lib = unsafe { TypeLibrary::from_raw(NonNull::new(result_lib)?) };
1827+
let lib = unsafe { TypeLibrary::ref_from_raw(NonNull::new(result_lib)?) };
18281828
let name = QualifiedName::from_owned_raw(result_name);
18291829
Some((lib, name))
18301830
}

rust/src/type_library.rs

Lines changed: 51 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use binaryninjacore_sys::*;
22

3+
use crate::rc::{Guard, RefCountable};
34
use crate::{
45
architecture::CoreArchitecture,
56
metadata::Metadata,
@@ -8,45 +9,37 @@ use crate::{
89
string::{BnString, IntoCStr},
910
types::{QualifiedName, QualifiedNameAndType, Type},
1011
};
11-
use core::{ffi, mem, ptr};
1212
use std::path::Path;
13+
use std::ptr::NonNull;
1314

1415
#[repr(transparent)]
1516
pub struct TypeLibrary {
16-
handle: ptr::NonNull<BNTypeLibrary>,
17+
handle: NonNull<BNTypeLibrary>,
1718
}
1819

1920
impl TypeLibrary {
20-
pub(crate) unsafe fn from_raw(handle: ptr::NonNull<BNTypeLibrary>) -> Self {
21+
pub(crate) unsafe fn from_raw(handle: NonNull<BNTypeLibrary>) -> Self {
2122
Self { handle }
2223
}
2324

24-
pub(crate) unsafe fn ref_from_raw(handle: &*mut BNTypeLibrary) -> &Self {
25-
assert!(!handle.is_null());
26-
mem::transmute(handle)
25+
pub(crate) unsafe fn ref_from_raw(handle: NonNull<BNTypeLibrary>) -> Ref<Self> {
26+
Ref::new(Self { handle })
2727
}
2828

2929
#[allow(clippy::mut_from_ref)]
3030
pub(crate) unsafe fn as_raw(&self) -> &mut BNTypeLibrary {
3131
&mut *self.handle.as_ptr()
3232
}
3333

34-
pub fn new_reference(&self) -> Self {
35-
unsafe {
36-
Self::from_raw(ptr::NonNull::new(BNNewTypeLibraryReference(self.as_raw())).unwrap())
37-
}
38-
}
39-
40-
pub fn new_duplicated(&self) -> Self {
41-
unsafe { Self::from_raw(ptr::NonNull::new(BNDuplicateTypeLibrary(self.as_raw())).unwrap()) }
34+
pub fn new_duplicated(&self) -> Ref<Self> {
35+
unsafe { Self::ref_from_raw(NonNull::new(BNDuplicateTypeLibrary(self.as_raw())).unwrap()) }
4236
}
4337

4438
/// Creates an empty type library object with a random GUID and the provided name.
45-
pub fn new(arch: CoreArchitecture, name: &str) -> TypeLibrary {
39+
pub fn new(arch: CoreArchitecture, name: &str) -> Ref<TypeLibrary> {
4640
let name = name.to_cstr();
47-
let new_lib =
48-
unsafe { BNNewTypeLibrary(arch.handle, name.as_ref().as_ptr() as *const ffi::c_char) };
49-
unsafe { TypeLibrary::from_raw(ptr::NonNull::new(new_lib).unwrap()) }
41+
let new_lib = unsafe { BNNewTypeLibrary(arch.handle, name.as_ptr()) };
42+
unsafe { TypeLibrary::ref_from_raw(NonNull::new(new_lib).unwrap()) }
5043
}
5144

5245
pub fn all(arch: CoreArchitecture) -> Array<TypeLibrary> {
@@ -60,47 +53,35 @@ impl TypeLibrary {
6053
pub fn decompress_to_file(path: &Path, output_path: &Path) -> bool {
6154
let path = path.to_cstr();
6255
let output = output_path.to_cstr();
63-
unsafe {
64-
BNTypeLibraryDecompressToFile(
65-
path.as_ref().as_ptr() as *const ffi::c_char,
66-
output.as_ref().as_ptr() as *const ffi::c_char,
67-
)
68-
}
56+
unsafe { BNTypeLibraryDecompressToFile(path.as_ptr(), output.as_ptr()) }
6957
}
7058

7159
/// Loads a finalized type library instance from file
72-
pub fn load_from_file(path: &Path) -> Option<TypeLibrary> {
60+
pub fn load_from_file(path: &Path) -> Option<Ref<TypeLibrary>> {
7361
let path = path.to_cstr();
74-
let handle =
75-
unsafe { BNLoadTypeLibraryFromFile(path.as_ref().as_ptr() as *const ffi::c_char) };
76-
ptr::NonNull::new(handle).map(|h| unsafe { TypeLibrary::from_raw(h) })
62+
let handle = unsafe { BNLoadTypeLibraryFromFile(path.as_ptr()) };
63+
NonNull::new(handle).map(|h| unsafe { TypeLibrary::ref_from_raw(h) })
7764
}
7865

7966
/// Saves a finalized type library instance to file
8067
pub fn write_to_file(&self, path: &Path) -> bool {
8168
let path = path.to_cstr();
82-
unsafe {
83-
BNWriteTypeLibraryToFile(self.as_raw(), path.as_ref().as_ptr() as *const ffi::c_char)
84-
}
69+
unsafe { BNWriteTypeLibraryToFile(self.as_raw(), path.as_ptr()) }
8570
}
8671

8772
/// Looks up the first type library found with a matching name. Keep in mind that names are not
8873
/// necessarily unique.
89-
pub fn from_name(arch: CoreArchitecture, name: &str) -> Option<TypeLibrary> {
74+
pub fn from_name(arch: CoreArchitecture, name: &str) -> Option<Ref<TypeLibrary>> {
9075
let name = name.to_cstr();
91-
let handle = unsafe {
92-
BNLookupTypeLibraryByName(arch.handle, name.as_ref().as_ptr() as *const ffi::c_char)
93-
};
94-
ptr::NonNull::new(handle).map(|h| unsafe { TypeLibrary::from_raw(h) })
76+
let handle = unsafe { BNLookupTypeLibraryByName(arch.handle, name.as_ptr()) };
77+
NonNull::new(handle).map(|h| unsafe { TypeLibrary::ref_from_raw(h) })
9578
}
9679

9780
/// Attempts to grab a type library associated with the provided Architecture and GUID pair
98-
pub fn from_guid(arch: CoreArchitecture, guid: &str) -> Option<TypeLibrary> {
81+
pub fn from_guid(arch: CoreArchitecture, guid: &str) -> Option<Ref<TypeLibrary>> {
9982
let guid = guid.to_cstr();
100-
let handle = unsafe {
101-
BNLookupTypeLibraryByGuid(arch.handle, guid.as_ref().as_ptr() as *const ffi::c_char)
102-
};
103-
ptr::NonNull::new(handle).map(|h| unsafe { TypeLibrary::from_raw(h) })
83+
let handle = unsafe { BNLookupTypeLibraryByGuid(arch.handle, guid.as_ptr()) };
84+
NonNull::new(handle).map(|h| unsafe { TypeLibrary::ref_from_raw(h) })
10485
}
10586

10687
/// The Architecture this type library is associated with
@@ -119,9 +100,7 @@ impl TypeLibrary {
119100
/// Sets the name of a type library instance that has not been finalized
120101
pub fn set_name(&self, value: &str) {
121102
let value = value.to_cstr();
122-
unsafe {
123-
BNSetTypeLibraryName(self.as_raw(), value.as_ref().as_ptr() as *const ffi::c_char)
124-
}
103+
unsafe { BNSetTypeLibraryName(self.as_raw(), value.as_ptr()) }
125104
}
126105

127106
/// The `dependency_name` of a library is the name used to record dependencies across
@@ -137,12 +116,7 @@ impl TypeLibrary {
137116
/// Sets the dependency name of a type library instance that has not been finalized
138117
pub fn set_dependency_name(&self, value: &str) {
139118
let value = value.to_cstr();
140-
unsafe {
141-
BNSetTypeLibraryDependencyName(
142-
self.as_raw(),
143-
value.as_ref().as_ptr() as *const ffi::c_char,
144-
)
145-
}
119+
unsafe { BNSetTypeLibraryDependencyName(self.as_raw(), value.as_ptr()) }
146120
}
147121

148122
/// Returns the GUID associated with the type library
@@ -154,9 +128,7 @@ impl TypeLibrary {
154128
/// Sets the GUID of a type library instance that has not been finalized
155129
pub fn set_guid(&self, value: &str) {
156130
let value = value.to_cstr();
157-
unsafe {
158-
BNSetTypeLibraryGuid(self.as_raw(), value.as_ref().as_ptr() as *const ffi::c_char)
159-
}
131+
unsafe { BNSetTypeLibraryGuid(self.as_raw(), value.as_ptr()) }
160132
}
161133

162134
/// A list of extra names that will be considered a match by [Platform::get_type_libraries_by_name]
@@ -170,12 +142,7 @@ impl TypeLibrary {
170142
/// Adds an extra name to this type library used during library lookups and dependency resolution
171143
pub fn add_alternate_name(&self, value: &str) {
172144
let value = value.to_cstr();
173-
unsafe {
174-
BNAddTypeLibraryAlternateName(
175-
self.as_raw(),
176-
value.as_ref().as_ptr() as *const ffi::c_char,
177-
)
178-
}
145+
unsafe { BNAddTypeLibraryAlternateName(self.as_raw(), value.as_ptr()) }
179146
}
180147

181148
/// Returns a list of all platform names that this type library will register with during platform
@@ -214,9 +181,7 @@ impl TypeLibrary {
214181
/// Retrieves a metadata associated with the given key stored in the type library
215182
pub fn query_metadata(&self, key: &str) -> Option<Metadata> {
216183
let key = key.to_cstr();
217-
let result = unsafe {
218-
BNTypeLibraryQueryMetadata(self.as_raw(), key.as_ref().as_ptr() as *const ffi::c_char)
219-
};
184+
let result = unsafe { BNTypeLibraryQueryMetadata(self.as_raw(), key.as_ptr()) };
220185
(!result.is_null()).then(|| unsafe { Metadata::from_raw(result) })
221186
}
222187

@@ -233,21 +198,13 @@ impl TypeLibrary {
233198
/// * `md` - object to store.
234199
pub fn store_metadata(&self, key: &str, md: &Metadata) {
235200
let key = key.to_cstr();
236-
unsafe {
237-
BNTypeLibraryStoreMetadata(
238-
self.as_raw(),
239-
key.as_ref().as_ptr() as *const ffi::c_char,
240-
md.handle,
241-
)
242-
}
201+
unsafe { BNTypeLibraryStoreMetadata(self.as_raw(), key.as_ptr(), md.handle) }
243202
}
244203

245204
/// Removes the metadata associated with key from the current type library.
246205
pub fn remove_metadata(&self, key: &str) {
247206
let key = key.to_cstr();
248-
unsafe {
249-
BNTypeLibraryRemoveMetadata(self.as_raw(), key.as_ref().as_ptr() as *const ffi::c_char)
250-
}
207+
unsafe { BNTypeLibraryRemoveMetadata(self.as_raw(), key.as_ptr()) }
251208
}
252209

253210
/// Retrieves the metadata associated with the current type library.
@@ -262,7 +219,7 @@ impl TypeLibrary {
262219
// /// The Type Container's Platform will be the first platform associated with the Type Library.
263220
// pub fn type_container(&self) -> TypeContainer {
264221
// let result = unsafe{ BNGetTypeLibraryTypeContainer(self.as_raw())};
265-
// unsafe{TypeContainer::from_raw(ptr::NonNull::new(result).unwrap())}
222+
// unsafe{TypeContainer::from_raw(NonNull::new(result).unwrap())}
266223
// }
267224

268225
/// Directly inserts a named object into the type library's object store.
@@ -302,13 +259,7 @@ impl TypeLibrary {
302259
pub fn add_type_source(&self, name: QualifiedName, source: &str) {
303260
let source = source.to_cstr();
304261
let mut raw_name = QualifiedName::into_raw(name);
305-
unsafe {
306-
BNAddTypeLibraryNamedTypeSource(
307-
self.as_raw(),
308-
&mut raw_name,
309-
source.as_ref().as_ptr() as *const ffi::c_char,
310-
)
311-
}
262+
unsafe { BNAddTypeLibraryNamedTypeSource(self.as_raw(), &mut raw_name, source.as_ptr()) }
312263
QualifiedName::free_raw(raw_name);
313264
}
314265

@@ -349,24 +300,38 @@ impl TypeLibrary {
349300
}
350301
}
351302

352-
impl Drop for TypeLibrary {
353-
fn drop(&mut self) {
354-
unsafe { BNFreeTypeLibrary(self.as_raw()) }
303+
unsafe impl RefCountable for TypeLibrary {
304+
unsafe fn inc_ref(handle: &Self) -> Ref<Self> {
305+
Ref::new(Self {
306+
handle: NonNull::new(BNNewTypeLibraryReference(handle.handle.as_ptr())).unwrap(),
307+
})
308+
}
309+
310+
unsafe fn dec_ref(handle: &Self) {
311+
BNFreeTypeLibrary(handle.handle.as_ptr());
312+
}
313+
}
314+
315+
impl ToOwned for TypeLibrary {
316+
type Owned = Ref<Self>;
317+
318+
fn to_owned(&self) -> Self::Owned {
319+
unsafe { RefCountable::inc_ref(self) }
355320
}
356321
}
357322

358323
impl CoreArrayProvider for TypeLibrary {
359324
type Raw = *mut BNTypeLibrary;
360325
type Context = ();
361-
type Wrapped<'a> = &'a Self;
326+
type Wrapped<'a> = Guard<'a, Self>;
362327
}
363328

364329
unsafe impl CoreArrayProviderInner for TypeLibrary {
365330
unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
366331
BNFreeTypeLibraryList(raw, count)
367332
}
368333

369-
unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
370-
Self::ref_from_raw(raw)
334+
unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, context: &'a Self::Context) -> Self::Wrapped<'a> {
335+
Guard::new(Self::from_raw(NonNull::new(*raw).unwrap()), context)
371336
}
372337
}

0 commit comments

Comments
 (0)