diff --git a/rust/examples/dwarf/dwarf_export/src/lib.rs b/rust/examples/dwarf/dwarf_export/src/lib.rs index 7143f6dd9..ef71f1ae7 100644 --- a/rust/examples/dwarf/dwarf_export/src/lib.rs +++ b/rust/examples/dwarf/dwarf_export/src/lib.rs @@ -551,7 +551,7 @@ fn export_data_vars( dwarf.unit.get_mut(var_die_uid).set( gimli::DW_AT_name, AttributeValue::String( - format!("data_{:x}", data_variable.address) + format!("data_{:x}", data_variable.address()) .as_bytes() .to_vec(), ), @@ -559,15 +559,15 @@ fn export_data_vars( } let mut variable_location = Expression::new(); - variable_location.op_addr(Address::Constant(data_variable.address)); + variable_location.op_addr(Address::Constant(data_variable.address())); dwarf.unit.get_mut(var_die_uid).set( gimli::DW_AT_location, AttributeValue::Exprloc(variable_location), ); if let Some(target_die_uid) = export_type( - format!("{}", data_variable.t.contents), - data_variable.t.contents.as_ref(), + format!("{}", data_variable.t()), + data_variable.t(), bv, defined_types, dwarf, diff --git a/rust/examples/dwarf/shared/src/lib.rs b/rust/examples/dwarf/shared/src/lib.rs index 718dcb8cd..7712ff3b3 100644 --- a/rust/examples/dwarf/shared/src/lib.rs +++ b/rust/examples/dwarf/shared/src/lib.rs @@ -88,11 +88,11 @@ pub fn create_section_reader<'a, Endian: 'a + Endianity>( if let Some(data_var) = view .data_variables() .iter() - .find(|var| var.address == symbol.address()) + .find(|var| var.address() == symbol.address()) { // TODO : This should eventually be wrapped by some DataView sorta thingy thing, like how python does it - let data_type = data_var.type_with_confidence().contents; - let data = view.read_vec(data_var.address, data_type.width() as usize); + let data_type = data_var.t(); + let data = view.read_vec(data_var.address(), data_type.width() as usize); let element_type = data_type.element_type().unwrap().contents; if let Some(current_section_header) = data diff --git a/rust/src/architecture.rs b/rust/src/architecture.rs index 9a7b3e723..9b5b36b48 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>; + fn inputs(&self) -> Vec>; /// Returns the list of the output types for this intrinsic. fn outputs(&self) -> Vec>>; @@ -650,7 +650,7 @@ impl Intrinsic for UnusedIntrinsic { fn id(&self) -> u32 { unreachable!() } - fn inputs(&self) -> Vec> { + fn inputs(&self) -> Vec> { unreachable!() } fn outputs(&self) -> Vec>> { @@ -992,7 +992,7 @@ impl Intrinsic for crate::architecture::CoreIntrinsic { self.1 } - fn inputs(&self) -> Vec> { + fn inputs(&self) -> Vec> { let mut count: usize = 0; unsafe { @@ -1172,7 +1172,7 @@ impl Architecture for CoreArchitecture { } } } - + fn instruction_llil( &self, data: &[u8], @@ -2424,7 +2424,7 @@ where let inputs = intrinsic.inputs(); let mut res = Vec::with_capacity(inputs.len()); for input in inputs { - res.push(input.into_raw()); + res.push(unsafe { Ref::into_raw(input) }.into_raw()); } unsafe { diff --git a/rust/src/binaryview.rs b/rust/src/binaryview.rs index 52d688b84..33fd98813 100644 --- a/rust/src/binaryview.rs +++ b/rust/src/binaryview.rs @@ -574,16 +574,24 @@ pub trait BinaryViewExt: BinaryViewBase { } } - fn define_auto_data_var(&self, dv: DataVariable) { + 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) { + 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 ab4f8f6b3..32db7ebb3 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(&self, parser_name: S) -> Vec> { + pub fn types_by_name(&self, parser_name: S) -> Vec> { 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> = unsafe { + let result: Vec> = unsafe { slice::from_raw_parts_mut(debug_types_ptr, count) .iter() - .map(NameAndType::::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> { + pub fn types(&self) -> Vec> { let mut count: usize = 0; let debug_types_ptr = unsafe { BNGetDebugTypes(self.handle, ptr::null_mut(), &mut count) }; - let result: Vec> = unsafe { + let result: Vec> = unsafe { slice::from_raw_parts_mut(debug_types_ptr, count) .iter() - .map(NameAndType::::from_raw) + .map(NameAndType::from_raw) .collect() }; diff --git a/rust/src/types.rs b/rust/src/types.rs index 8f14cf00e..9fcd9d45f 100644 --- a/rust/src/types.rs +++ b/rust/src/types.rs @@ -56,6 +56,7 @@ pub type MemberScope = BNMemberScope; //////////////// // Confidence +/// Compatible with the `BNType*WithConfidence` types pub struct Conf { pub contents: T, pub confidence: u8, @@ -698,6 +699,7 @@ impl Drop for TypeBuilder { ////////// // Type +#[repr(transparent)] pub struct Type { pub(crate) handle: *mut BNType, } @@ -2447,13 +2449,11 @@ unsafe impl<'a> CoreArrayWrapper<'a> for QualifiedNameTypeAndId { ////////////////////////// // NameAndType -pub struct NameAndType { - pub name: S, - pub t: Conf>, -} +#[repr(transparent)] +pub struct NameAndType(pub(crate) BNNameAndType); -impl NameAndType { - pub(crate) fn from_raw(raw: &BNNameAndType) -> Self { +impl NameAndType { + pub(crate) fn from_raw(raw: &BNNameAndType) -> Ref { Self::new( raw_to_string(raw.name).unwrap(), unsafe { &Type::ref_from_raw(raw.type_) }, @@ -2462,43 +2462,73 @@ impl NameAndType { } } -impl NameAndType { - pub fn new(name: S, t: &Ref, confidence: u8) -> Self { - Self { - name, - t: Conf::new(t.clone(), confidence), +impl NameAndType { + pub fn new(name: S, t: &Type, confidence: u8) -> Ref { + unsafe { + Ref::new(Self(BNNameAndType { + name: BNAllocString(name.into_bytes_with_nul().as_ref().as_ptr() as *mut _), + type_: 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> { - 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> { + Conf::new(self.t(), self.0.typeConfidence) + } +} + +impl ToOwned for NameAndType { + type Owned = Ref; + + fn to_owned(&self) -> Self::Owned { + unsafe { RefCountable::inc_ref(self) } + } +} + +unsafe impl RefCountable for NameAndType { + unsafe fn inc_ref(handle: &Self) -> Ref { + Self::new( + CStr::from_ptr(handle.0.name), + handle.t(), + handle.type_with_confidence().confidence, + ) + } + + unsafe fn dec_ref(handle: &Self) { + unsafe { + BNFreeString(handle.0.name); + RefCountable::dec_ref(handle.t()); + } } } -impl CoreArrayProvider for NameAndType { +impl CoreArrayProvider for NameAndType { type Raw = BNNameAndType; type Context = (); } -unsafe impl CoreOwnedArrayProvider for NameAndType { +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 { - type Wrapped = &'a NameAndType; +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,29 +2538,61 @@ unsafe impl<'a, S: 'a + BnStrCompatible> CoreArrayWrapper<'a> for NameAndType ////////////////// // DataVariable -pub struct DataVariable { - pub address: u64, - pub t: Conf>, - pub auto_discovered: bool, -} +#[repr(transparent)] +pub struct DataVariable(pub(crate) BNDataVariable); // impl DataVariable { // pub(crate) fn from_raw(var: &BNDataVariable) -> Self { -// Self { -// address: var.address, -// t: Conf::new(unsafe { Type::ref_from_raw(var.type_) }, var.typeConfidence), -// auto_discovered: var.autoDiscovered, -// } +// let var = DataVariable(*var); +// Self(BNDataVariable { +// type_: unsafe { Ref::into_raw(var.t().to_owned()).handle }, +// ..var.0 +// }) // } // } impl DataVariable { - pub fn type_with_confidence(&self) -> Conf> { - Conf::new(self.t.contents.clone(), self.t.confidence) + pub fn address(&self) -> u64 { + self.0.address + } + + pub fn auto_discovered(&self) -> bool { + self.0.autoDiscovered + } + + pub fn t(&self) -> &Type { + unsafe { mem::transmute(&self.0.type_) } + } + + pub fn type_with_confidence(&self) -> Conf<&Type> { + Conf::new(self.t(), self.0.typeConfidence) } pub fn symbol(&self, bv: &BinaryView) -> Option> { - bv.symbol_by_address(self.address).ok() + bv.symbol_by_address(self.0.address).ok() + } +} + +impl ToOwned for DataVariable { + type Owned = Ref; + + fn to_owned(&self) -> Self::Owned { + unsafe { RefCountable::inc_ref(self) } + } +} + +unsafe impl RefCountable for DataVariable { + unsafe fn inc_ref(handle: &Self) -> Ref { + unsafe { + Ref::new(Self(BNDataVariable { + type_: Ref::into_raw(handle.t().to_owned()).handle, + ..handle.0 + })) + } + } + + unsafe fn dec_ref(handle: &Self) { + unsafe { BNFreeType(handle.0.type_) } } }