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
1527pub mod archive;
1628pub 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+
496515impl 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