diff options
| author | Mason Reed <mason@vector35.com> | 2025-12-11 15:47:56 -0500 |
|---|---|---|
| committer | Mason Reed <35282038+emesare@users.noreply.github.com> | 2025-12-15 19:29:56 -0500 |
| commit | 479ad6d05402f1c611a6f300674b52483413aa12 (patch) | |
| tree | 6c95e3912a698e5185f715d91eeb32d2fdfe76f6 | |
| parent | ca0e32efb1e5b9eba157e9fd2eef178d9367c578 (diff) | |
[Rust] Misc documentation and internal cleanup of types module
| -rw-r--r-- | rust/src/types.rs | 177 |
1 files changed, 82 insertions, 95 deletions
diff --git a/rust/src/types.rs b/rust/src/types.rs index cfdc865b..cf7b6f1a 100644 --- a/rust/src/types.rs +++ b/rust/src/types.rs @@ -11,6 +11,18 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. +//! The model for representing types in Binary Ninja. +//! +//! [`Type`]'s are fundamental to analysis. With types, you can influence how decompilation resolves accesses, +//! renders data, and tell the analysis of properties such as volatility and constness. +//! +//! Types are typically stored within a [`BinaryView`], [`TypeArchive`] or a [`TypeLibrary`]. +//! +//! Types can be created using the [`TypeBuilder`] or one of the convenience functions. Another way +//! to create a type is with a [`TypeParser`] if you have C type definitions. +//! +//! Some interfaces may expect to be passed a [`TypeContainer`] which itself does not store any type +//! information, rather a generic interface to query for types by name or by id. pub mod archive; pub mod container; @@ -80,13 +92,11 @@ impl TypeBuilder { Self { handle } } - // Chainable terminal + /// Turn the [`TypeBuilder`] into a [`Type`]. pub fn finalize(&self) -> Ref<Type> { unsafe { Type::ref_from_raw(BNFinalizeTypeBuilder(self.handle)) } } - // Settable properties - pub fn set_can_return<T: Into<Conf<bool>>>(&self, value: T) -> &Self { let mut bool_with_confidence = value.into().into(); unsafe { BNSetFunctionTypeBuilderCanReturn(self.handle, &mut bool_with_confidence) }; @@ -284,18 +294,22 @@ impl TypeBuilder { // TODO : This and properties // pub fn tokens(&self) -> ? {} + /// Create a void [`TypeBuilder`]. Analogous to [`Type::void`]. pub fn void() -> Self { unsafe { Self::from_raw(BNCreateVoidTypeBuilder()) } } + /// Create a bool [`TypeBuilder`]. Analogous to [`Type::bool`]. pub fn bool() -> Self { unsafe { Self::from_raw(BNCreateBoolTypeBuilder()) } } + /// Create a signed one byte integer [`TypeBuilder`]. Analogous to [`Type::char`]. pub fn char() -> Self { Self::int(1, true) } + /// Create an integer [`TypeBuilder`] with the given width and signedness. Analogous to [`Type::int`]. pub fn int(width: usize, is_signed: bool) -> Self { let mut is_signed = Conf::new(is_signed, MAX_CONFIDENCE).into(); @@ -303,15 +317,16 @@ impl TypeBuilder { Self::from_raw(BNCreateIntegerTypeBuilder( width, &mut is_signed, - BnString::new("").as_ptr() as *mut _, + c"".as_ptr() as _, )) } } + /// Create an integer [`TypeBuilder`] with the given width and signedness and an alternative name. + /// Analogous to [`Type::named_int`]. pub fn named_int(width: usize, is_signed: bool, alt_name: &str) -> Self { let mut is_signed = Conf::new(is_signed, MAX_CONFIDENCE).into(); - // let alt_name = BnString::new(alt_name); - let alt_name = alt_name.to_cstr(); // This segfaulted once, so the above version is there if we need to change to it, but in theory this is copied into a `const string&` on the C++ side; I'm just not 100% confident that a constant reference copies data + let alt_name = alt_name.to_cstr(); unsafe { Self::from_raw(BNCreateIntegerTypeBuilder( @@ -322,20 +337,25 @@ impl TypeBuilder { } } + /// Create a float [`TypeBuilder`] with the given width. Analogous to [`Type::float`]. pub fn float(width: usize) -> Self { unsafe { Self::from_raw(BNCreateFloatTypeBuilder(width, c"".as_ptr())) } } + /// Create a float [`TypeBuilder`] with the given width and alternative name. Analogous to [`Type::named_float`]. pub fn named_float(width: usize, alt_name: &str) -> Self { let alt_name = alt_name.to_cstr(); unsafe { Self::from_raw(BNCreateFloatTypeBuilder(width, alt_name.as_ptr())) } } + /// Create an array [`TypeBuilder`] with the given element type and count. Analogous to [`Type::array`]. pub fn array<'a, T: Into<Conf<&'a Type>>>(ty: T, count: u64) -> Self { let owned_raw_ty = Conf::<&Type>::into_raw(ty.into()); unsafe { Self::from_raw(BNCreateArrayTypeBuilder(&owned_raw_ty, count)) } } + /// Create an enumeration [`TypeBuilder`] with the given width and signedness. Analogous to [`Type::enumeration`]. + /// /// ## NOTE /// /// The C/C++ APIs require an associated architecture, but in the core we only query the default_int_size if the given width is 0. @@ -357,10 +377,12 @@ impl TypeBuilder { } } + /// Create a structure [`TypeBuilder`]. Analogous to [`Type::structure`]. pub fn structure(structure_type: &Structure) -> Self { unsafe { Self::from_raw(BNCreateStructureTypeBuilder(structure_type.handle)) } } + /// Create a named type reference [`TypeBuilder`]. Analogous to [`Type::named_type`]. pub fn named_type(type_reference: NamedTypeReference) -> Self { let mut is_const = Conf::new(false, MIN_CONFIDENCE).into(); let mut is_volatile = Conf::new(false, MIN_CONFIDENCE).into(); @@ -375,6 +397,7 @@ impl TypeBuilder { } } + /// Create a named type reference [`TypeBuilder`] from a type and name. Analogous to [`Type::named_type_from_type`]. pub fn named_type_from_type<T: Into<QualifiedName>>(name: T, t: &Type) -> Self { let mut raw_name = QualifiedName::into_raw(name.into()); let id = c""; @@ -392,60 +415,30 @@ impl TypeBuilder { // TODO : BNCreateFunctionTypeBuilder + /// Create a pointer [`TypeBuilder`] with the given target type. Analogous to [`Type::pointer`]. pub fn pointer<'a, A: Architecture, T: Into<Conf<&'a Type>>>(arch: &A, ty: T) -> Self { - let mut is_const = Conf::new(false, MIN_CONFIDENCE).into(); - let mut is_volatile = Conf::new(false, MIN_CONFIDENCE).into(); - let owned_raw_ty = Conf::<&Type>::into_raw(ty.into()); - unsafe { - Self::from_raw(BNCreatePointerTypeBuilder( - arch.as_ref().handle, - &owned_raw_ty, - &mut is_const, - &mut is_volatile, - ReferenceType::PointerReferenceType, - )) - } + Self::pointer_with_options(arch, ty, false, false, None) } + /// Create a const pointer [`TypeBuilder`] with the given target type. Analogous to [`Type::const_pointer`]. pub fn const_pointer<'a, A: Architecture, T: Into<Conf<&'a Type>>>(arch: &A, ty: T) -> Self { - let mut is_const = Conf::new(true, MAX_CONFIDENCE).into(); - let mut is_volatile = Conf::new(false, MIN_CONFIDENCE).into(); - let owned_raw_ty = Conf::<&Type>::into_raw(ty.into()); - unsafe { - Self::from_raw(BNCreatePointerTypeBuilder( - arch.as_ref().handle, - &owned_raw_ty, - &mut is_const, - &mut is_volatile, - ReferenceType::PointerReferenceType, - )) - } + Self::pointer_with_options(arch, ty, true, false, None) } - pub fn pointer_of_width<'a, T: Into<Conf<&'a Type>>>( + pub fn pointer_with_options<'a, A: Architecture, T: Into<Conf<&'a Type>>>( + arch: &A, ty: T, - size: usize, is_const: bool, is_volatile: bool, ref_type: Option<ReferenceType>, ) -> Self { - let mut is_const = Conf::new(is_const, MAX_CONFIDENCE).into(); - let mut is_volatile = Conf::new(is_volatile, MAX_CONFIDENCE).into(); - let owned_raw_ty = Conf::<&Type>::into_raw(ty.into()); - unsafe { - Self::from_raw(BNCreatePointerTypeBuilderOfWidth( - size, - &owned_raw_ty, - &mut is_const, - &mut is_volatile, - ref_type.unwrap_or(ReferenceType::PointerReferenceType), - )) - } + let arch_ptr_size = arch.address_size(); + Self::pointer_of_width(ty, arch_ptr_size, is_const, is_volatile, ref_type) } - pub fn pointer_with_options<'a, A: Architecture, T: Into<Conf<&'a Type>>>( - arch: &A, + pub fn pointer_of_width<'a, T: Into<Conf<&'a Type>>>( ty: T, + size: usize, is_const: bool, is_volatile: bool, ref_type: Option<ReferenceType>, @@ -454,8 +447,8 @@ impl TypeBuilder { let mut is_volatile = Conf::new(is_volatile, MAX_CONFIDENCE).into(); let owned_raw_ty = Conf::<&Type>::into_raw(ty.into()); unsafe { - Self::from_raw(BNCreatePointerTypeBuilder( - arch.as_ref().handle, + Self::from_raw(BNCreatePointerTypeBuilderOfWidth( + size, &owned_raw_ty, &mut is_const, &mut is_volatile, @@ -479,11 +472,32 @@ impl Drop for TypeBuilder { } } -#[repr(transparent)] -pub struct Type { - pub handle: *mut BNType, -} - +/// The core model for types in Binary Ninja. +/// +/// A [`Type`] is how we model the storage of a [`Variable`] or [`crate::variable::DataVariable`] as +/// well as propagate information such as the constness of a variable. Types are also used to declare +/// function signatures, such as the [`FunctionParameter`]'s and return type. +/// +/// Types are immutable. To change a type, you must create a new one either using [`TypeBuilder`] or +/// one of the helper functions: +/// +/// - [`Type::void`] +/// - [`Type::bool`] +/// - [`Type::char`] +/// - [`Type::wide_char`] +/// - [`Type::int`], [`Type::named_int`] +/// - [`Type::float`], [`Type::named_float`] +/// - [`Type::array`] +/// - [`Type::enumeration`] +/// - [`Type::structure`] +/// - [`Type::named_type`], [`Type::named_type_from_type`] +/// - [`Type::function`], [`Type::function_with_opts`] +/// - [`Type::pointer`], [`Type::const_pointer`], [`Type::pointer_of_width`], [`Type::pointer_with_options`] +/// +/// # Example +/// +/// As an example, defining a _named_ type within a [`BinaryView`]: +/// /// ```no_run /// # use crate::binaryninja::binary_view::BinaryViewExt; /// # use binaryninja::types::Type; @@ -493,6 +507,11 @@ pub struct Type { /// bv.define_user_type("int_1", &my_custom_type_1); /// bv.define_user_type("int_2", &my_custom_type_2); /// ``` +#[repr(transparent)] +pub struct Type { + pub handle: *mut BNType, +} + impl Type { pub unsafe fn from_raw(handle: *mut BNType) -> Self { debug_assert!(!handle.is_null()); @@ -885,62 +904,30 @@ impl Type { } pub fn pointer<'a, A: Architecture, T: Into<Conf<&'a Type>>>(arch: &A, ty: T) -> Ref<Self> { - let mut is_const = Conf::new(false, MIN_CONFIDENCE).into(); - let mut is_volatile = Conf::new(false, MIN_CONFIDENCE).into(); - let owned_raw_ty = Conf::<&Type>::into_raw(ty.into()); - unsafe { - Self::ref_from_raw(BNCreatePointerType( - arch.as_ref().handle, - &owned_raw_ty, - &mut is_const, - &mut is_volatile, - ReferenceType::PointerReferenceType, - )) - } + Self::pointer_with_options(arch, ty, false, false, None) } pub fn const_pointer<'a, A: Architecture, T: Into<Conf<&'a Type>>>( arch: &A, ty: T, ) -> Ref<Self> { - let mut is_const = Conf::new(true, MAX_CONFIDENCE).into(); - let mut is_volatile = Conf::new(false, MIN_CONFIDENCE).into(); - let owned_raw_ty = Conf::<&Type>::into_raw(ty.into()); - unsafe { - Self::ref_from_raw(BNCreatePointerType( - arch.as_ref().handle, - &owned_raw_ty, - &mut is_const, - &mut is_volatile, - ReferenceType::PointerReferenceType, - )) - } + Self::pointer_with_options(arch, ty, true, false, None) } - pub fn pointer_of_width<'a, T: Into<Conf<&'a Type>>>( + pub fn pointer_with_options<'a, A: Architecture, T: Into<Conf<&'a Type>>>( + arch: &A, ty: T, - size: usize, is_const: bool, is_volatile: bool, ref_type: Option<ReferenceType>, ) -> Ref<Self> { - let mut is_const = Conf::new(is_const, MAX_CONFIDENCE).into(); - let mut is_volatile = Conf::new(is_volatile, MAX_CONFIDENCE).into(); - let owned_raw_ty = Conf::<&Type>::into_raw(ty.into()); - unsafe { - Self::ref_from_raw(BNCreatePointerTypeOfWidth( - size, - &owned_raw_ty, - &mut is_const, - &mut is_volatile, - ref_type.unwrap_or(ReferenceType::PointerReferenceType), - )) - } + let arch_pointer_size = arch.address_size(); + Self::pointer_of_width(ty, arch_pointer_size, is_const, is_volatile, ref_type) } - pub fn pointer_with_options<'a, A: Architecture, T: Into<Conf<&'a Type>>>( - arch: &A, + pub fn pointer_of_width<'a, T: Into<Conf<&'a Type>>>( ty: T, + size: usize, is_const: bool, is_volatile: bool, ref_type: Option<ReferenceType>, @@ -949,8 +936,8 @@ impl Type { let mut is_volatile = Conf::new(is_volatile, MAX_CONFIDENCE).into(); let owned_raw_ty = Conf::<&Type>::into_raw(ty.into()); unsafe { - Self::ref_from_raw(BNCreatePointerType( - arch.as_ref().handle, + Self::ref_from_raw(BNCreatePointerTypeOfWidth( + size, &owned_raw_ty, &mut is_const, &mut is_volatile, |
