summaryrefslogtreecommitdiff
path: root/rust/src
diff options
context:
space:
mode:
authorRubens Brandao <git@rubens.io>2024-04-17 07:23:15 -0300
committerRubens Brandao <git@rubens.io>2024-04-17 07:43:43 -0300
commit90040508478f4551eb303a5056026fd59bb0cdc6 (patch)
treeaea3cb4d3c0092505d9fd7b0a93b698806600442 /rust/src
parentf408eb32085956f7e29e0f15fd92aa4b72453370 (diff)
allow DataVariable and NameAndType to be transmutable
Diffstat (limited to 'rust/src')
-rw-r--r--rust/src/architecture.rs6
-rw-r--r--rust/src/binaryview.rs12
-rw-r--r--rust/src/debuginfo.rs12
-rw-r--r--rust/src/rc.rs1
-rw-r--r--rust/src/types.rs89
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()
}
}