Skip to content

Commit cf8379e

Browse files
committed
[Rust] Misc documentation and internal cleanup of types module
1 parent 768e9d2 commit cf8379e

File tree

1 file changed

+82
-95
lines changed

1 file changed

+82
-95
lines changed

rust/src/types.rs

Lines changed: 82 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,18 @@
1111
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
14+
//! The model for representing types in Binary Ninja.
15+
//!
16+
//! [`Type`]'s are fundamental to analysis. With types, you can influence how decompilation resolves accesses,
17+
//! renders data, and tell the analysis of properties such as volatility and constness.
18+
//!
19+
//! Types are typically stored within a [`BinaryView`], [`TypeArchive`] or a [`TypeLibrary`].
20+
//!
21+
//! Types can be created using the [`TypeBuilder`] or one of the convenience functions. Another way
22+
//! to create a type is with a [`TypeParser`] if you have C type definitions.
23+
//!
24+
//! Some interfaces may expect to be passed a [`TypeContainer`] which itself does not store any type
25+
//! information, rather a generic interface to query for types by name or by id.
1426
1527
pub mod archive;
1628
pub mod container;
@@ -80,13 +92,11 @@ impl TypeBuilder {
8092
Self { handle }
8193
}
8294

83-
// Chainable terminal
95+
/// Turn the [`TypeBuilder`] into a [`Type`].
8496
pub fn finalize(&self) -> Ref<Type> {
8597
unsafe { Type::ref_from_raw(BNFinalizeTypeBuilder(self.handle)) }
8698
}
8799

88-
// Settable properties
89-
90100
pub fn set_can_return<T: Into<Conf<bool>>>(&self, value: T) -> &Self {
91101
let mut bool_with_confidence = value.into().into();
92102
unsafe { BNSetFunctionTypeBuilderCanReturn(self.handle, &mut bool_with_confidence) };
@@ -284,34 +294,39 @@ impl TypeBuilder {
284294
// TODO : This and properties
285295
// pub fn tokens(&self) -> ? {}
286296

297+
/// Create a void [`TypeBuilder`]. Analogous to [`Type::void`].
287298
pub fn void() -> Self {
288299
unsafe { Self::from_raw(BNCreateVoidTypeBuilder()) }
289300
}
290301

302+
/// Create a bool [`TypeBuilder`]. Analogous to [`Type::bool`].
291303
pub fn bool() -> Self {
292304
unsafe { Self::from_raw(BNCreateBoolTypeBuilder()) }
293305
}
294306

307+
/// Create a signed one byte integer [`TypeBuilder`]. Analogous to [`Type::char`].
295308
pub fn char() -> Self {
296309
Self::int(1, true)
297310
}
298311

312+
/// Create an integer [`TypeBuilder`] with the given width and signedness. Analogous to [`Type::int`].
299313
pub fn int(width: usize, is_signed: bool) -> Self {
300314
let mut is_signed = Conf::new(is_signed, MAX_CONFIDENCE).into();
301315

302316
unsafe {
303317
Self::from_raw(BNCreateIntegerTypeBuilder(
304318
width,
305319
&mut is_signed,
306-
BnString::new("").as_ptr() as *mut _,
320+
c"".as_ptr() as _,
307321
))
308322
}
309323
}
310324

325+
/// Create an integer [`TypeBuilder`] with the given width and signedness and an alternative name.
326+
/// Analogous to [`Type::named_int`].
311327
pub fn named_int(width: usize, is_signed: bool, alt_name: &str) -> Self {
312328
let mut is_signed = Conf::new(is_signed, MAX_CONFIDENCE).into();
313-
// let alt_name = BnString::new(alt_name);
314-
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
329+
let alt_name = alt_name.to_cstr();
315330

316331
unsafe {
317332
Self::from_raw(BNCreateIntegerTypeBuilder(
@@ -322,20 +337,25 @@ impl TypeBuilder {
322337
}
323338
}
324339

340+
/// Create a float [`TypeBuilder`] with the given width. Analogous to [`Type::float`].
325341
pub fn float(width: usize) -> Self {
326342
unsafe { Self::from_raw(BNCreateFloatTypeBuilder(width, c"".as_ptr())) }
327343
}
328344

345+
/// Create a float [`TypeBuilder`] with the given width and alternative name. Analogous to [`Type::named_float`].
329346
pub fn named_float(width: usize, alt_name: &str) -> Self {
330347
let alt_name = alt_name.to_cstr();
331348
unsafe { Self::from_raw(BNCreateFloatTypeBuilder(width, alt_name.as_ptr())) }
332349
}
333350

351+
/// Create an array [`TypeBuilder`] with the given element type and count. Analogous to [`Type::array`].
334352
pub fn array<'a, T: Into<Conf<&'a Type>>>(ty: T, count: u64) -> Self {
335353
let owned_raw_ty = Conf::<&Type>::into_raw(ty.into());
336354
unsafe { Self::from_raw(BNCreateArrayTypeBuilder(&owned_raw_ty, count)) }
337355
}
338356

357+
/// Create an enumeration [`TypeBuilder`] with the given width and signedness. Analogous to [`Type::enumeration`].
358+
///
339359
/// ## NOTE
340360
///
341361
/// 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 {
357377
}
358378
}
359379

380+
/// Create a structure [`TypeBuilder`]. Analogous to [`Type::structure`].
360381
pub fn structure(structure_type: &Structure) -> Self {
361382
unsafe { Self::from_raw(BNCreateStructureTypeBuilder(structure_type.handle)) }
362383
}
363384

385+
/// Create a named type reference [`TypeBuilder`]. Analogous to [`Type::named_type`].
364386
pub fn named_type(type_reference: NamedTypeReference) -> Self {
365387
let mut is_const = Conf::new(false, MIN_CONFIDENCE).into();
366388
let mut is_volatile = Conf::new(false, MIN_CONFIDENCE).into();
@@ -375,6 +397,7 @@ impl TypeBuilder {
375397
}
376398
}
377399

400+
/// Create a named type reference [`TypeBuilder`] from a type and name. Analogous to [`Type::named_type_from_type`].
378401
pub fn named_type_from_type<T: Into<QualifiedName>>(name: T, t: &Type) -> Self {
379402
let mut raw_name = QualifiedName::into_raw(name.into());
380403
let id = c"";
@@ -392,60 +415,30 @@ impl TypeBuilder {
392415

393416
// TODO : BNCreateFunctionTypeBuilder
394417

418+
/// Create a pointer [`TypeBuilder`] with the given target type. Analogous to [`Type::pointer`].
395419
pub fn pointer<'a, A: Architecture, T: Into<Conf<&'a Type>>>(arch: &A, ty: T) -> Self {
396-
let mut is_const = Conf::new(false, MIN_CONFIDENCE).into();
397-
let mut is_volatile = Conf::new(false, MIN_CONFIDENCE).into();
398-
let owned_raw_ty = Conf::<&Type>::into_raw(ty.into());
399-
unsafe {
400-
Self::from_raw(BNCreatePointerTypeBuilder(
401-
arch.as_ref().handle,
402-
&owned_raw_ty,
403-
&mut is_const,
404-
&mut is_volatile,
405-
ReferenceType::PointerReferenceType,
406-
))
407-
}
420+
Self::pointer_with_options(arch, ty, false, false, None)
408421
}
409422

423+
/// Create a const pointer [`TypeBuilder`] with the given target type. Analogous to [`Type::const_pointer`].
410424
pub fn const_pointer<'a, A: Architecture, T: Into<Conf<&'a Type>>>(arch: &A, ty: T) -> Self {
411-
let mut is_const = Conf::new(true, MAX_CONFIDENCE).into();
412-
let mut is_volatile = Conf::new(false, MIN_CONFIDENCE).into();
413-
let owned_raw_ty = Conf::<&Type>::into_raw(ty.into());
414-
unsafe {
415-
Self::from_raw(BNCreatePointerTypeBuilder(
416-
arch.as_ref().handle,
417-
&owned_raw_ty,
418-
&mut is_const,
419-
&mut is_volatile,
420-
ReferenceType::PointerReferenceType,
421-
))
422-
}
425+
Self::pointer_with_options(arch, ty, true, false, None)
423426
}
424427

425-
pub fn pointer_of_width<'a, T: Into<Conf<&'a Type>>>(
428+
pub fn pointer_with_options<'a, A: Architecture, T: Into<Conf<&'a Type>>>(
429+
arch: &A,
426430
ty: T,
427-
size: usize,
428431
is_const: bool,
429432
is_volatile: bool,
430433
ref_type: Option<ReferenceType>,
431434
) -> Self {
432-
let mut is_const = Conf::new(is_const, MAX_CONFIDENCE).into();
433-
let mut is_volatile = Conf::new(is_volatile, MAX_CONFIDENCE).into();
434-
let owned_raw_ty = Conf::<&Type>::into_raw(ty.into());
435-
unsafe {
436-
Self::from_raw(BNCreatePointerTypeBuilderOfWidth(
437-
size,
438-
&owned_raw_ty,
439-
&mut is_const,
440-
&mut is_volatile,
441-
ref_type.unwrap_or(ReferenceType::PointerReferenceType),
442-
))
443-
}
435+
let arch_ptr_size = arch.address_size();
436+
Self::pointer_of_width(ty, arch_ptr_size, is_const, is_volatile, ref_type)
444437
}
445438

446-
pub fn pointer_with_options<'a, A: Architecture, T: Into<Conf<&'a Type>>>(
447-
arch: &A,
439+
pub fn pointer_of_width<'a, T: Into<Conf<&'a Type>>>(
448440
ty: T,
441+
size: usize,
449442
is_const: bool,
450443
is_volatile: bool,
451444
ref_type: Option<ReferenceType>,
@@ -454,8 +447,8 @@ impl TypeBuilder {
454447
let mut is_volatile = Conf::new(is_volatile, MAX_CONFIDENCE).into();
455448
let owned_raw_ty = Conf::<&Type>::into_raw(ty.into());
456449
unsafe {
457-
Self::from_raw(BNCreatePointerTypeBuilder(
458-
arch.as_ref().handle,
450+
Self::from_raw(BNCreatePointerTypeBuilderOfWidth(
451+
size,
459452
&owned_raw_ty,
460453
&mut is_const,
461454
&mut is_volatile,
@@ -479,11 +472,32 @@ impl Drop for TypeBuilder {
479472
}
480473
}
481474

482-
#[repr(transparent)]
483-
pub struct Type {
484-
pub handle: *mut BNType,
485-
}
486-
475+
/// The core model for types in Binary Ninja.
476+
///
477+
/// A [`Type`] is how we model the storage of a [`Variable`] or [`crate::variable::DataVariable`] as
478+
/// well as propagate information such as the constness of a variable. Types are also used to declare
479+
/// function signatures, such as the [`FunctionParameter`]'s and return type.
480+
///
481+
/// Types are immutable. To change a type, you must create a new one either using [`TypeBuilder`] or
482+
/// one of the helper functions:
483+
///
484+
/// - [`Type::void`]
485+
/// - [`Type::bool`]
486+
/// - [`Type::char`]
487+
/// - [`Type::wide_char`]
488+
/// - [`Type::int`], [`Type::named_int`]
489+
/// - [`Type::float`], [`Type::named_float`]
490+
/// - [`Type::array`]
491+
/// - [`Type::enumeration`]
492+
/// - [`Type::structure`]
493+
/// - [`Type::named_type`], [`Type::named_type_from_type`]
494+
/// - [`Type::function`], [`Type::function_with_opts`]
495+
/// - [`Type::pointer`], [`Type::const_pointer`], [`Type::pointer_of_width`], [`Type::pointer_with_options`]
496+
///
497+
/// # Example
498+
///
499+
/// As an example, defining a _named_ type within a [`BinaryView`]:
500+
///
487501
/// ```no_run
488502
/// # use crate::binaryninja::binary_view::BinaryViewExt;
489503
/// # use binaryninja::types::Type;
@@ -493,6 +507,11 @@ pub struct Type {
493507
/// bv.define_user_type("int_1", &my_custom_type_1);
494508
/// bv.define_user_type("int_2", &my_custom_type_2);
495509
/// ```
510+
#[repr(transparent)]
511+
pub struct Type {
512+
pub handle: *mut BNType,
513+
}
514+
496515
impl Type {
497516
pub unsafe fn from_raw(handle: *mut BNType) -> Self {
498517
debug_assert!(!handle.is_null());
@@ -885,62 +904,30 @@ impl Type {
885904
}
886905

887906
pub fn pointer<'a, A: Architecture, T: Into<Conf<&'a Type>>>(arch: &A, ty: T) -> Ref<Self> {
888-
let mut is_const = Conf::new(false, MIN_CONFIDENCE).into();
889-
let mut is_volatile = Conf::new(false, MIN_CONFIDENCE).into();
890-
let owned_raw_ty = Conf::<&Type>::into_raw(ty.into());
891-
unsafe {
892-
Self::ref_from_raw(BNCreatePointerType(
893-
arch.as_ref().handle,
894-
&owned_raw_ty,
895-
&mut is_const,
896-
&mut is_volatile,
897-
ReferenceType::PointerReferenceType,
898-
))
899-
}
907+
Self::pointer_with_options(arch, ty, false, false, None)
900908
}
901909

902910
pub fn const_pointer<'a, A: Architecture, T: Into<Conf<&'a Type>>>(
903911
arch: &A,
904912
ty: T,
905913
) -> Ref<Self> {
906-
let mut is_const = Conf::new(true, MAX_CONFIDENCE).into();
907-
let mut is_volatile = Conf::new(false, MIN_CONFIDENCE).into();
908-
let owned_raw_ty = Conf::<&Type>::into_raw(ty.into());
909-
unsafe {
910-
Self::ref_from_raw(BNCreatePointerType(
911-
arch.as_ref().handle,
912-
&owned_raw_ty,
913-
&mut is_const,
914-
&mut is_volatile,
915-
ReferenceType::PointerReferenceType,
916-
))
917-
}
914+
Self::pointer_with_options(arch, ty, true, false, None)
918915
}
919916

920-
pub fn pointer_of_width<'a, T: Into<Conf<&'a Type>>>(
917+
pub fn pointer_with_options<'a, A: Architecture, T: Into<Conf<&'a Type>>>(
918+
arch: &A,
921919
ty: T,
922-
size: usize,
923920
is_const: bool,
924921
is_volatile: bool,
925922
ref_type: Option<ReferenceType>,
926923
) -> Ref<Self> {
927-
let mut is_const = Conf::new(is_const, MAX_CONFIDENCE).into();
928-
let mut is_volatile = Conf::new(is_volatile, MAX_CONFIDENCE).into();
929-
let owned_raw_ty = Conf::<&Type>::into_raw(ty.into());
930-
unsafe {
931-
Self::ref_from_raw(BNCreatePointerTypeOfWidth(
932-
size,
933-
&owned_raw_ty,
934-
&mut is_const,
935-
&mut is_volatile,
936-
ref_type.unwrap_or(ReferenceType::PointerReferenceType),
937-
))
938-
}
924+
let arch_pointer_size = arch.address_size();
925+
Self::pointer_of_width(ty, arch_pointer_size, is_const, is_volatile, ref_type)
939926
}
940927

941-
pub fn pointer_with_options<'a, A: Architecture, T: Into<Conf<&'a Type>>>(
942-
arch: &A,
928+
pub fn pointer_of_width<'a, T: Into<Conf<&'a Type>>>(
943929
ty: T,
930+
size: usize,
944931
is_const: bool,
945932
is_volatile: bool,
946933
ref_type: Option<ReferenceType>,
@@ -949,8 +936,8 @@ impl Type {
949936
let mut is_volatile = Conf::new(is_volatile, MAX_CONFIDENCE).into();
950937
let owned_raw_ty = Conf::<&Type>::into_raw(ty.into());
951938
unsafe {
952-
Self::ref_from_raw(BNCreatePointerType(
953-
arch.as_ref().handle,
939+
Self::ref_from_raw(BNCreatePointerTypeOfWidth(
940+
size,
954941
&owned_raw_ty,
955942
&mut is_const,
956943
&mut is_volatile,

0 commit comments

Comments
 (0)