diff options
| author | Rubens Brandao <git@rubens.io> | 2024-04-17 07:23:15 -0300 |
|---|---|---|
| committer | Rubens Brandao <git@rubens.io> | 2024-04-17 07:43:43 -0300 |
| commit | 90040508478f4551eb303a5056026fd59bb0cdc6 (patch) | |
| tree | aea3cb4d3c0092505d9fd7b0a93b698806600442 /rust/src | |
| parent | f408eb32085956f7e29e0f15fd92aa4b72453370 (diff) | |
allow DataVariable and NameAndType to be transmutable
Diffstat (limited to 'rust/src')
| -rw-r--r-- | rust/src/architecture.rs | 6 | ||||
| -rw-r--r-- | rust/src/binaryview.rs | 12 | ||||
| -rw-r--r-- | rust/src/debuginfo.rs | 12 | ||||
| -rw-r--r-- | rust/src/rc.rs | 1 | ||||
| -rw-r--r-- | rust/src/types.rs | 89 |
5 files changed, 77 insertions, 43 deletions
diff --git a/rust/src/architecture.rs b/rust/src/architecture.rs index 9a7b3e72..82df7441 100644 --- a/rust/src/architecture.rs +++ b/rust/src/architecture.rs @@ -313,7 +313,7 @@ pub trait Intrinsic: Sized + Clone + Copy { fn id(&self) -> u32; /// Reeturns the list of the input names and types for this intrinsic. - fn inputs(&self) -> Vec<NameAndType<String>>; + fn inputs(&self) -> Vec<NameAndType>; /// Returns the list of the output types for this intrinsic. fn outputs(&self) -> Vec<Conf<Ref<Type>>>; @@ -650,7 +650,7 @@ impl Intrinsic for UnusedIntrinsic { fn id(&self) -> u32 { unreachable!() } - fn inputs(&self) -> Vec<NameAndType<String>> { + fn inputs(&self) -> Vec<NameAndType> { unreachable!() } fn outputs(&self) -> Vec<Conf<Ref<Type>>> { @@ -992,7 +992,7 @@ impl Intrinsic for crate::architecture::CoreIntrinsic { self.1 } - fn inputs(&self) -> Vec<NameAndType<String>> { + fn inputs(&self) -> Vec<NameAndType> { let mut count: usize = 0; unsafe { diff --git a/rust/src/binaryview.rs b/rust/src/binaryview.rs index 52d688b8..bcb3f57f 100644 --- a/rust/src/binaryview.rs +++ b/rust/src/binaryview.rs @@ -576,14 +576,22 @@ pub trait BinaryViewExt: BinaryViewBase { fn define_auto_data_var(&self, dv: DataVariable) { unsafe { - BNDefineDataVariable(self.as_ref().handle, dv.address, &mut dv.t.into()); + BNDefineDataVariable( + self.as_ref().handle, + dv.address(), + &mut dv.type_with_confidence().into(), + ); } } /// You likely would also like to call [`Self::define_user_symbol`] to bind this data variable with a name fn define_user_data_var(&self, dv: DataVariable) { unsafe { - BNDefineUserDataVariable(self.as_ref().handle, dv.address, &mut dv.t.into()); + BNDefineUserDataVariable( + self.as_ref().handle, + dv.address(), + &mut dv.type_with_confidence().into(), + ); } } diff --git a/rust/src/debuginfo.rs b/rust/src/debuginfo.rs index ab4f8f6b..7bb5e36f 100644 --- a/rust/src/debuginfo.rs +++ b/rust/src/debuginfo.rs @@ -376,7 +376,7 @@ impl DebugInfo { } /// Returns a generator of all types provided by a named DebugInfoParser - pub fn types_by_name<S: BnStrCompatible>(&self, parser_name: S) -> Vec<NameAndType<String>> { + pub fn types_by_name<S: BnStrCompatible>(&self, parser_name: S) -> Vec<NameAndType> { let parser_name = parser_name.into_bytes_with_nul(); let mut count: usize = 0; @@ -387,10 +387,10 @@ impl DebugInfo { &mut count, ) }; - let result: Vec<NameAndType<String>> = unsafe { + let result: Vec<NameAndType> = unsafe { slice::from_raw_parts_mut(debug_types_ptr, count) .iter() - .map(NameAndType::<String>::from_raw) + .map(NameAndType::from_raw) .collect() }; @@ -399,13 +399,13 @@ impl DebugInfo { } /// A generator of all types provided by DebugInfoParsers - pub fn types(&self) -> Vec<NameAndType<String>> { + pub fn types(&self) -> Vec<NameAndType> { let mut count: usize = 0; let debug_types_ptr = unsafe { BNGetDebugTypes(self.handle, ptr::null_mut(), &mut count) }; - let result: Vec<NameAndType<String>> = unsafe { + let result: Vec<NameAndType> = unsafe { slice::from_raw_parts_mut(debug_types_ptr, count) .iter() - .map(NameAndType::<String>::from_raw) + .map(NameAndType::from_raw) .collect() }; diff --git a/rust/src/rc.rs b/rust/src/rc.rs index cdcae179..91e51565 100644 --- a/rust/src/rc.rs +++ b/rust/src/rc.rs @@ -43,6 +43,7 @@ pub unsafe trait RefCountable: ToOwned<Owned = Ref<Self>> + Sized { // Represents an 'owned' reference tracked by the core // that we are responsible for cleaning up once we're // done with the encapsulated value. +#[repr(transparent)] pub struct Ref<T: RefCountable> { contents: T, } diff --git a/rust/src/types.rs b/rust/src/types.rs index 8f14cf00..eb629503 100644 --- a/rust/src/types.rs +++ b/rust/src/types.rs @@ -56,6 +56,8 @@ pub type MemberScope = BNMemberScope; //////////////// // Confidence +/// Compatible with the `BNType*WithConfidence` types +#[repr(C)] pub struct Conf<T> { pub contents: T, pub confidence: u8, @@ -698,6 +700,7 @@ impl Drop for TypeBuilder { ////////// // Type +#[repr(transparent)] pub struct Type { pub(crate) handle: *mut BNType, } @@ -2447,12 +2450,10 @@ unsafe impl<'a> CoreArrayWrapper<'a> for QualifiedNameTypeAndId { ////////////////////////// // NameAndType -pub struct NameAndType<S: BnStrCompatible> { - pub name: S, - pub t: Conf<Ref<Type>>, -} +#[repr(transparent)] +pub struct NameAndType(pub(crate) BNNameAndType); -impl NameAndType<String> { +impl NameAndType { pub(crate) fn from_raw(raw: &BNNameAndType) -> Self { Self::new( raw_to_string(raw.name).unwrap(), @@ -2462,43 +2463,56 @@ impl NameAndType<String> { } } -impl<S: BnStrCompatible> NameAndType<S> { - pub fn new(name: S, t: &Ref<Type>, confidence: u8) -> Self { - Self { - name, - t: Conf::new(t.clone(), confidence), - } +impl NameAndType { + pub fn new<S: BnStrCompatible>(name: S, t: &Ref<Type>, confidence: u8) -> Self { + Self(BNNameAndType { + name: unsafe { BNAllocString(name.into_bytes_with_nul().as_ref().as_ptr() as *mut _) }, + type_: unsafe { Ref::into_raw(t.to_owned()).handle }, + typeConfidence: confidence, + }) } pub(crate) fn into_raw(self) -> BNNameAndType { - let t = self.t.clone(); - let res = BNNameAndType { - name: BnString::new(self.name).into_raw(), - type_: t.contents.handle, - typeConfidence: self.t.confidence, - }; - mem::forget(t); - res + self.0 } - pub fn type_with_confidence(&self) -> Conf<Ref<Type>> { - self.t.clone() + pub fn name(&self) -> &str { + let c_str = unsafe { CStr::from_ptr(self.0.name) }; + c_str.to_str().unwrap() + } + + pub fn t(&self) -> &Type { + unsafe { mem::transmute::<_, &Type>(&self.0.type_) } + } + + pub fn type_with_confidence(&self) -> &Conf<Type> { + // the struct BNNameAndType contains a Conf inside of it, so this is safe + unsafe { mem::transmute::<_, &Conf<Type>>(&self.0.type_) } + } +} + +impl Drop for NameAndType { + fn drop(&mut self) { + unsafe { + BNFreeString(self.0.name); + BNFreeType(self.0.type_); + } } } -impl<S: BnStrCompatible> CoreArrayProvider for NameAndType<S> { +impl CoreArrayProvider for NameAndType { type Raw = BNNameAndType; type Context = (); } -unsafe impl<S: BnStrCompatible> CoreOwnedArrayProvider for NameAndType<S> { +unsafe impl CoreOwnedArrayProvider for NameAndType { unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) { BNFreeNameAndTypeList(raw, count); } } -unsafe impl<'a, S: 'a + BnStrCompatible> CoreArrayWrapper<'a> for NameAndType<S> { - type Wrapped = &'a NameAndType<S>; +unsafe impl<'a> CoreArrayWrapper<'a> for NameAndType { + type Wrapped = &'a NameAndType; unsafe fn wrap_raw(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped { mem::transmute(raw) @@ -2508,11 +2522,8 @@ unsafe impl<'a, S: 'a + BnStrCompatible> CoreArrayWrapper<'a> for NameAndType<S> ////////////////// // DataVariable -pub struct DataVariable { - pub address: u64, - pub t: Conf<Ref<Type>>, - pub auto_discovered: bool, -} +#[repr(transparent)] +pub struct DataVariable(pub(crate) BNDataVariable); // impl DataVariable { // pub(crate) fn from_raw(var: &BNDataVariable) -> Self { @@ -2525,12 +2536,26 @@ pub struct DataVariable { // } impl DataVariable { + pub fn address(&self) -> u64 { + self.0.address + } + + pub fn auto_discovered(&self) -> &bool { + unsafe { mem::transmute(&self.0.autoDiscovered) } + } + + pub fn t(&self) -> &Type { + unsafe { mem::transmute(&self.0.type_) } + } + pub fn type_with_confidence(&self) -> Conf<Ref<Type>> { - Conf::new(self.t.contents.clone(), self.t.confidence) + // if it was not for the `autoDiscovered: bool` between `type_` and + // `typeConfidence` this could have being a reference, like NameAndType + Conf::new(self.t().to_owned(), self.0.typeConfidence) } pub fn symbol(&self, bv: &BinaryView) -> Option<Ref<Symbol>> { - bv.symbol_by_address(self.address).ok() + bv.symbol_by_address(self.0.address).ok() } } |
