1pub mod archive;
28pub mod container;
29pub mod enumeration;
30pub mod library;
31pub mod parser;
32pub mod printer;
33pub mod structure;
34
35use binaryninjacore_sys::*;
36
37use crate::{
38 architecture::Architecture,
39 binary_view::{BinaryView, BinaryViewExt},
40 calling_convention::CoreCallingConvention,
41 rc::*,
42 string::{BnString, IntoCStr},
43};
44
45use crate::confidence::{Conf, MAX_CONFIDENCE, MIN_CONFIDENCE};
46use crate::string::raw_to_string;
47use crate::variable::{Variable, VariableSourceType};
48use std::num::NonZeroUsize;
49use std::{
50 collections::HashSet,
51 fmt::{Debug, Display, Formatter},
52 hash::{Hash, Hasher},
53 iter::IntoIterator,
54};
55
56pub use archive::{TypeArchive, TypeArchiveId, TypeArchiveSnapshotId};
57pub use container::TypeContainer;
58pub use enumeration::{Enumeration, EnumerationBuilder, EnumerationMember};
59pub use library::TypeLibrary;
60pub use parser::{
61 CoreTypeParser, ParsedType, TypeParser, TypeParserError, TypeParserErrorSeverity,
62 TypeParserResult,
63};
64pub use printer::{CoreTypePrinter, TypePrinter};
65pub use structure::{
66 BaseStructure, InheritedStructureMember, Structure, StructureBuilder, StructureMember,
67};
68
69#[deprecated(note = "Use crate::qualified_name::QualifiedName instead")]
70pub use crate::qualified_name::QualifiedName;
72
73pub type StructureType = BNStructureVariant;
74pub type ReferenceType = BNReferenceType;
75pub type TypeClass = BNTypeClass;
76pub type NamedTypeReferenceClass = BNNamedTypeReferenceClass;
77pub type MemberAccess = BNMemberAccess;
78pub type MemberScope = BNMemberScope;
79pub type IntegerDisplayType = BNIntegerDisplayType;
80pub type PointerBaseType = BNPointerBaseType;
81
82#[derive(PartialEq, Eq, Hash)]
83pub struct TypeBuilder {
84 pub(crate) handle: *mut BNTypeBuilder,
85}
86
87impl TypeBuilder {
88 pub fn new(t: &Type) -> Self {
89 unsafe { Self::from_raw(BNCreateTypeBuilderFromType(t.handle)) }
90 }
91
92 pub(crate) unsafe fn from_raw(handle: *mut BNTypeBuilder) -> Self {
93 debug_assert!(!handle.is_null());
94 Self { handle }
95 }
96
97 pub fn finalize(&self) -> Ref<Type> {
99 unsafe { Type::ref_from_raw(BNFinalizeTypeBuilder(self.handle)) }
100 }
101
102 pub fn set_can_return<T: Into<Conf<bool>>>(&self, value: T) -> &Self {
103 let mut bool_with_confidence = value.into().into();
104 unsafe { BNSetFunctionTypeBuilderCanReturn(self.handle, &mut bool_with_confidence) };
105 self
106 }
107
108 pub fn set_pure<T: Into<Conf<bool>>>(&self, value: T) -> &Self {
109 let mut bool_with_confidence = value.into().into();
110 unsafe { BNSetTypeBuilderPure(self.handle, &mut bool_with_confidence) };
111 self
112 }
113
114 pub fn set_const<T: Into<Conf<bool>>>(&self, value: T) -> &Self {
115 let mut bool_with_confidence = value.into().into();
116 unsafe { BNTypeBuilderSetConst(self.handle, &mut bool_with_confidence) };
117 self
118 }
119
120 pub fn set_volatile<T: Into<Conf<bool>>>(&self, value: T) -> &Self {
121 let mut bool_with_confidence = value.into().into();
122 unsafe { BNTypeBuilderSetVolatile(self.handle, &mut bool_with_confidence) };
123 self
124 }
125
126 pub fn set_pointer_base(&self, base_type: PointerBaseType, base_offset: i64) -> &Self {
127 unsafe { BNSetTypeBuilderPointerBase(self.handle, base_type, base_offset) }
128 self
129 }
130
131 pub fn set_child_type<'a, T: Into<Conf<&'a Type>>>(&self, ty: T) -> &Self {
132 let mut type_with_confidence = Conf::<&Type>::into_raw(ty.into());
133 unsafe { BNTypeBuilderSetChildType(self.handle, &mut type_with_confidence) };
134 self
135 }
136
137 pub fn set_target<'a, T: Into<Conf<&'a Type>>>(&self, ty: T) -> &Self {
139 self.set_child_type(ty)
140 }
141
142 pub fn set_element_type<'a, T: Into<Conf<&'a Type>>>(&self, ty: T) -> &Self {
144 self.set_child_type(ty)
145 }
146
147 pub fn set_return_value<'a, T: Into<Conf<&'a Type>>>(&self, ty: T) -> &Self {
149 self.set_child_type(ty)
150 }
151
152 pub fn set_signed<T: Into<Conf<bool>>>(&self, value: T) -> &Self {
153 let mut bool_with_confidence = value.into().into();
154 unsafe { BNTypeBuilderSetSigned(self.handle, &mut bool_with_confidence) };
155 self
156 }
157
158 pub fn type_class(&self) -> TypeClass {
161 unsafe { BNGetTypeBuilderClass(self.handle) }
162 }
163
164 pub fn width(&self) -> u64 {
165 unsafe { BNGetTypeBuilderWidth(self.handle) }
166 }
167
168 pub fn alignment(&self) -> usize {
169 unsafe { BNGetTypeBuilderAlignment(self.handle) }
170 }
171
172 pub fn is_signed(&self) -> Conf<bool> {
173 unsafe { BNIsTypeBuilderSigned(self.handle).into() }
174 }
175
176 pub fn is_const(&self) -> Conf<bool> {
177 unsafe { BNIsTypeBuilderConst(self.handle).into() }
178 }
179
180 pub fn is_volatile(&self) -> Conf<bool> {
181 unsafe { BNIsTypeBuilderVolatile(self.handle).into() }
182 }
183
184 pub fn is_floating_point(&self) -> bool {
185 unsafe { BNIsTypeBuilderFloatingPoint(self.handle) }
186 }
187
188 pub fn child_type(&self) -> Option<Conf<Ref<Type>>> {
189 let raw_target = unsafe { BNGetTypeBuilderChildType(self.handle) };
190 match raw_target.type_.is_null() {
191 false => Some(Conf::<Ref<Type>>::from_owned_raw(raw_target)),
192 true => None,
193 }
194 }
195
196 pub fn target(&self) -> Option<Conf<Ref<Type>>> {
198 self.child_type()
199 }
200
201 pub fn element_type(&self) -> Option<Conf<Ref<Type>>> {
203 self.child_type()
204 }
205
206 pub fn return_value(&self) -> Option<Conf<Ref<Type>>> {
208 self.child_type()
209 }
210
211 pub fn calling_convention(&self) -> Option<Conf<Ref<CoreCallingConvention>>> {
212 let raw_convention_confidence = unsafe { BNGetTypeBuilderCallingConvention(self.handle) };
213 match raw_convention_confidence.convention.is_null() {
214 false => Some(Conf::<Ref<CoreCallingConvention>>::from_owned_raw(
215 raw_convention_confidence,
216 )),
217 true => None,
218 }
219 }
220
221 pub fn parameters(&self) -> Option<Vec<FunctionParameter>> {
222 unsafe {
223 let mut count = 0;
224 let raw_parameters_ptr = BNGetTypeBuilderParameters(self.handle, &mut count);
225 match raw_parameters_ptr.is_null() {
226 false => {
227 let raw_parameters = std::slice::from_raw_parts(raw_parameters_ptr, count);
228 let parameters = raw_parameters
229 .iter()
230 .map(FunctionParameter::from_raw)
231 .collect();
232 BNFreeTypeParameterList(raw_parameters_ptr, count);
233 Some(parameters)
234 }
235 true => None,
236 }
237 }
238 }
239
240 pub fn has_variable_arguments(&self) -> Conf<bool> {
241 unsafe { BNTypeBuilderHasVariableArguments(self.handle).into() }
242 }
243
244 pub fn can_return(&self) -> Conf<bool> {
245 unsafe { BNFunctionTypeBuilderCanReturn(self.handle).into() }
246 }
247
248 pub fn pure(&self) -> Conf<bool> {
249 unsafe { BNIsTypeBuilderPure(self.handle).into() }
250 }
251
252 pub fn get_structure(&self) -> Option<Ref<Structure>> {
255 let raw_struct_ptr = unsafe { BNGetTypeBuilderStructure(self.handle) };
256 match raw_struct_ptr.is_null() {
257 false => Some(unsafe { Structure::ref_from_raw(raw_struct_ptr) }),
258 true => None,
259 }
260 }
261
262 pub fn get_enumeration(&self) -> Option<Ref<Enumeration>> {
265 let raw_enum_ptr = unsafe { BNGetTypeBuilderEnumeration(self.handle) };
266 match raw_enum_ptr.is_null() {
267 false => Some(unsafe { Enumeration::ref_from_raw(raw_enum_ptr) }),
268 true => None,
269 }
270 }
271
272 pub fn get_named_type_reference(&self) -> Option<Ref<NamedTypeReference>> {
275 let raw_type_ref_ptr = unsafe { BNGetTypeBuilderNamedTypeReference(self.handle) };
276 match raw_type_ref_ptr.is_null() {
277 false => Some(unsafe { NamedTypeReference::ref_from_raw(raw_type_ref_ptr) }),
278 true => None,
279 }
280 }
281
282 pub fn count(&self) -> u64 {
283 unsafe { BNGetTypeBuilderElementCount(self.handle) }
284 }
285
286 pub fn offset(&self) -> u64 {
287 unsafe { BNGetTypeBuilderOffset(self.handle) }
288 }
289
290 pub fn stack_adjustment(&self) -> Conf<i64> {
291 unsafe { BNGetTypeBuilderStackAdjustment(self.handle).into() }
292 }
293
294 pub fn pointer_base_type(&self) -> PointerBaseType {
295 unsafe { BNTypeBuilderGetPointerBaseType(self.handle) }
296 }
297
298 pub fn pointer_base_offset(&self) -> i64 {
299 unsafe { BNTypeBuilderGetPointerBaseOffset(self.handle) }
300 }
301
302 pub fn void() -> Self {
307 unsafe { Self::from_raw(BNCreateVoidTypeBuilder()) }
308 }
309
310 pub fn bool() -> Self {
312 unsafe { Self::from_raw(BNCreateBoolTypeBuilder()) }
313 }
314
315 pub fn char() -> Self {
317 Self::int(1, true)
318 }
319
320 pub fn int(width: usize, is_signed: bool) -> Self {
322 let mut is_signed = Conf::new(is_signed, MAX_CONFIDENCE).into();
323
324 unsafe {
325 Self::from_raw(BNCreateIntegerTypeBuilder(
326 width,
327 &mut is_signed,
328 c"".as_ptr() as _,
329 ))
330 }
331 }
332
333 pub fn named_int(width: usize, is_signed: bool, alt_name: &str) -> Self {
336 let mut is_signed = Conf::new(is_signed, MAX_CONFIDENCE).into();
337 let alt_name = alt_name.to_cstr();
338
339 unsafe {
340 Self::from_raw(BNCreateIntegerTypeBuilder(
341 width,
342 &mut is_signed,
343 alt_name.as_ref().as_ptr() as _,
344 ))
345 }
346 }
347
348 pub fn float(width: usize) -> Self {
350 unsafe { Self::from_raw(BNCreateFloatTypeBuilder(width, c"".as_ptr())) }
351 }
352
353 pub fn named_float(width: usize, alt_name: &str) -> Self {
355 let alt_name = alt_name.to_cstr();
356 unsafe { Self::from_raw(BNCreateFloatTypeBuilder(width, alt_name.as_ptr())) }
357 }
358
359 pub fn array<'a, T: Into<Conf<&'a Type>>>(ty: T, count: u64) -> Self {
361 let owned_raw_ty = Conf::<&Type>::into_raw(ty.into());
362 unsafe { Self::from_raw(BNCreateArrayTypeBuilder(&owned_raw_ty, count)) }
363 }
364
365 pub fn enumeration<T: Into<Conf<bool>>>(
373 enumeration: &Enumeration,
374 width: NonZeroUsize,
375 is_signed: T,
376 ) -> Self {
377 unsafe {
378 Self::from_raw(BNCreateEnumerationTypeBuilder(
379 std::ptr::null_mut(),
381 enumeration.handle,
382 width.get(),
383 &mut is_signed.into().into(),
384 ))
385 }
386 }
387
388 pub fn structure(structure_type: &Structure) -> Self {
390 unsafe { Self::from_raw(BNCreateStructureTypeBuilder(structure_type.handle)) }
391 }
392
393 pub fn named_type(type_reference: NamedTypeReference) -> Self {
395 let mut is_const = Conf::new(false, MIN_CONFIDENCE).into();
396 let mut is_volatile = Conf::new(false, MIN_CONFIDENCE).into();
397 unsafe {
398 Self::from_raw(BNCreateNamedTypeReferenceBuilder(
399 type_reference.handle,
400 0,
401 1,
402 &mut is_const,
403 &mut is_volatile,
404 ))
405 }
406 }
407
408 pub fn named_type_from_type<T: Into<QualifiedName>>(name: T, t: &Type) -> Self {
410 let mut raw_name = QualifiedName::into_raw(name.into());
411 let id = c"";
412
413 let result = unsafe {
414 Self::from_raw(BNCreateNamedTypeReferenceBuilderFromTypeAndId(
415 id.as_ptr() as *mut _,
416 &mut raw_name,
417 t.handle,
418 ))
419 };
420 QualifiedName::free_raw(raw_name);
421 result
422 }
423
424 pub fn pointer<'a, A: Architecture, T: Into<Conf<&'a Type>>>(arch: &A, ty: T) -> Self {
428 Self::pointer_with_options(arch, ty, false, false, None)
429 }
430
431 pub fn const_pointer<'a, A: Architecture, T: Into<Conf<&'a Type>>>(arch: &A, ty: T) -> Self {
433 Self::pointer_with_options(arch, ty, true, false, None)
434 }
435
436 pub fn pointer_with_options<'a, A: Architecture, T: Into<Conf<&'a Type>>>(
437 arch: &A,
438 ty: T,
439 is_const: bool,
440 is_volatile: bool,
441 ref_type: Option<ReferenceType>,
442 ) -> Self {
443 let arch_ptr_size = arch.address_size();
444 Self::pointer_of_width(ty, arch_ptr_size, is_const, is_volatile, ref_type)
445 }
446
447 pub fn pointer_of_width<'a, T: Into<Conf<&'a Type>>>(
448 ty: T,
449 size: usize,
450 is_const: bool,
451 is_volatile: bool,
452 ref_type: Option<ReferenceType>,
453 ) -> Self {
454 let mut is_const = Conf::new(is_const, MAX_CONFIDENCE).into();
455 let mut is_volatile = Conf::new(is_volatile, MAX_CONFIDENCE).into();
456 let owned_raw_ty = Conf::<&Type>::into_raw(ty.into());
457 unsafe {
458 Self::from_raw(BNCreatePointerTypeBuilderOfWidth(
459 size,
460 &owned_raw_ty,
461 &mut is_const,
462 &mut is_volatile,
463 ref_type.unwrap_or(ReferenceType::PointerReferenceType),
464 ))
465 }
466 }
467}
468
469impl Display for TypeBuilder {
470 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
471 write!(f, "{}", unsafe {
472 BnString::into_string(BNGetTypeBuilderString(self.handle, std::ptr::null_mut()))
473 })
474 }
475}
476
477impl Drop for TypeBuilder {
478 fn drop(&mut self) {
479 unsafe { BNFreeTypeBuilder(self.handle) };
480 }
481}
482
483#[repr(transparent)]
519pub struct Type {
520 pub handle: *mut BNType,
521}
522
523impl Type {
524 pub unsafe fn from_raw(handle: *mut BNType) -> Self {
525 debug_assert!(!handle.is_null());
526 Self { handle }
527 }
528
529 pub unsafe fn ref_from_raw(handle: *mut BNType) -> Ref<Self> {
530 debug_assert!(!handle.is_null());
531 Ref::new(Self { handle })
532 }
533
534 pub fn to_builder(&self) -> TypeBuilder {
535 TypeBuilder::new(self)
536 }
537
538 pub fn type_class(&self) -> TypeClass {
539 unsafe { BNGetTypeClass(self.handle) }
540 }
541
542 pub fn width(&self) -> u64 {
545 unsafe { BNGetTypeWidth(self.handle) }
546 }
547
548 pub fn alignment(&self) -> usize {
549 unsafe { BNGetTypeAlignment(self.handle) }
550 }
551
552 pub fn is_signed(&self) -> Conf<bool> {
553 unsafe { BNIsTypeSigned(self.handle).into() }
554 }
555
556 pub fn is_const(&self) -> Conf<bool> {
557 unsafe { BNIsTypeConst(self.handle).into() }
558 }
559
560 pub fn is_volatile(&self) -> Conf<bool> {
561 unsafe { BNIsTypeVolatile(self.handle).into() }
562 }
563
564 pub fn is_floating_point(&self) -> bool {
565 unsafe { BNIsTypeFloatingPoint(self.handle) }
566 }
567
568 pub fn child_type(&self) -> Option<Conf<Ref<Type>>> {
569 let raw_target = unsafe { BNGetChildType(self.handle) };
570 match raw_target.type_.is_null() {
571 false => Some(Conf::<Ref<Type>>::from_owned_raw(raw_target)),
572 true => None,
573 }
574 }
575
576 pub fn target(&self) -> Option<Conf<Ref<Type>>> {
578 self.child_type()
579 }
580
581 pub fn element_type(&self) -> Option<Conf<Ref<Type>>> {
583 self.child_type()
584 }
585
586 pub fn return_value(&self) -> Option<Conf<Ref<Type>>> {
588 self.child_type()
589 }
590
591 pub fn calling_convention(&self) -> Option<Conf<Ref<CoreCallingConvention>>> {
592 let convention_confidence = unsafe { BNGetTypeCallingConvention(self.handle) };
593 match convention_confidence.convention.is_null() {
594 false => Some(Conf::<Ref<CoreCallingConvention>>::from_owned_raw(
595 convention_confidence,
596 )),
597 true => None,
598 }
599 }
600
601 pub fn parameters(&self) -> Option<Vec<FunctionParameter>> {
602 unsafe {
603 let mut count = 0;
604 let raw_parameters_ptr = BNGetTypeParameters(self.handle, &mut count);
605 match raw_parameters_ptr.is_null() {
606 false => {
607 let raw_parameters = std::slice::from_raw_parts(raw_parameters_ptr, count);
608 let parameters = raw_parameters
609 .iter()
610 .map(FunctionParameter::from_raw)
611 .collect();
612 BNFreeTypeParameterList(raw_parameters_ptr, count);
613 Some(parameters)
614 }
615 true => None,
616 }
617 }
618 }
619
620 pub fn has_variable_arguments(&self) -> Conf<bool> {
621 unsafe { BNTypeHasVariableArguments(self.handle).into() }
622 }
623
624 pub fn can_return(&self) -> Conf<bool> {
625 unsafe { BNFunctionTypeCanReturn(self.handle).into() }
626 }
627
628 pub fn pure(&self) -> Conf<bool> {
629 unsafe { BNIsTypePure(self.handle).into() }
630 }
631
632 pub fn get_structure(&self) -> Option<Ref<Structure>> {
635 let raw_struct_ptr = unsafe { BNGetTypeStructure(self.handle) };
636 match raw_struct_ptr.is_null() {
637 false => Some(unsafe { Structure::ref_from_raw(raw_struct_ptr) }),
638 true => None,
639 }
640 }
641
642 pub fn get_enumeration(&self) -> Option<Ref<Enumeration>> {
645 let raw_enum_ptr = unsafe { BNGetTypeEnumeration(self.handle) };
646 match raw_enum_ptr.is_null() {
647 false => Some(unsafe { Enumeration::ref_from_raw(raw_enum_ptr) }),
648 true => None,
649 }
650 }
651
652 pub fn get_named_type_reference(&self) -> Option<Ref<NamedTypeReference>> {
655 let raw_type_ref_ptr = unsafe { BNGetTypeNamedTypeReference(self.handle) };
656 match raw_type_ref_ptr.is_null() {
657 false => Some(unsafe { NamedTypeReference::ref_from_raw(raw_type_ref_ptr) }),
658 true => None,
659 }
660 }
661
662 pub fn count(&self) -> u64 {
663 unsafe { BNGetTypeElementCount(self.handle) }
664 }
665
666 pub fn offset(&self) -> u64 {
667 unsafe { BNGetTypeOffset(self.handle) }
668 }
669
670 pub fn stack_adjustment(&self) -> Conf<i64> {
671 unsafe { BNGetTypeStackAdjustment(self.handle).into() }
672 }
673
674 pub fn registered_name(&self) -> Option<Ref<NamedTypeReference>> {
675 let raw_type_ref_ptr = unsafe { BNGetRegisteredTypeName(self.handle) };
676 match raw_type_ref_ptr.is_null() {
677 false => Some(unsafe { NamedTypeReference::ref_from_raw(raw_type_ref_ptr) }),
678 true => None,
679 }
680 }
681
682 pub fn pointer_base_type(&self) -> BNPointerBaseType {
683 unsafe { BNTypeGetPointerBaseType(self.handle) }
684 }
685
686 pub fn pointer_base_offset(&self) -> i64 {
687 unsafe { BNTypeGetPointerBaseOffset(self.handle) }
688 }
689
690 pub fn void() -> Ref<Self> {
694 unsafe { Self::ref_from_raw(BNCreateVoidType()) }
695 }
696
697 pub fn bool() -> Ref<Self> {
698 unsafe { Self::ref_from_raw(BNCreateBoolType()) }
699 }
700
701 pub fn char() -> Ref<Self> {
702 Self::int(1, true)
703 }
704
705 pub fn wide_char(width: usize) -> Ref<Self> {
706 unsafe { Self::ref_from_raw(BNCreateWideCharType(width, c"".as_ptr())) }
707 }
708
709 pub fn int(width: usize, is_signed: bool) -> Ref<Self> {
710 let mut is_signed = Conf::new(is_signed, MAX_CONFIDENCE).into();
711 unsafe { Self::ref_from_raw(BNCreateIntegerType(width, &mut is_signed, c"".as_ptr())) }
712 }
713
714 pub fn named_int(width: usize, is_signed: bool, alt_name: &str) -> Ref<Self> {
715 let mut is_signed = Conf::new(is_signed, MAX_CONFIDENCE).into();
716 let alt_name = alt_name.to_cstr();
717
718 unsafe {
719 Self::ref_from_raw(BNCreateIntegerType(
720 width,
721 &mut is_signed,
722 alt_name.as_ptr(),
723 ))
724 }
725 }
726
727 pub fn float(width: usize) -> Ref<Self> {
728 unsafe { Self::ref_from_raw(BNCreateFloatType(width, c"".as_ptr())) }
729 }
730
731 pub fn named_float(width: usize, alt_name: &str) -> Ref<Self> {
732 let alt_name = alt_name.to_cstr();
733 unsafe { Self::ref_from_raw(BNCreateFloatType(width, alt_name.as_ptr())) }
734 }
735
736 pub fn array<'a, T: Into<Conf<&'a Type>>>(ty: T, count: u64) -> Ref<Self> {
737 let owned_raw_ty = Conf::<&Type>::into_raw(ty.into());
738 unsafe { Self::ref_from_raw(BNCreateArrayType(&owned_raw_ty, count)) }
739 }
740
741 pub fn enumeration<T: Into<Conf<bool>>>(
747 enumeration: &Enumeration,
748 width: NonZeroUsize,
749 is_signed: T,
750 ) -> Ref<Self> {
751 unsafe {
752 Self::ref_from_raw(BNCreateEnumerationType(
753 std::ptr::null_mut(),
755 enumeration.handle,
756 width.get(),
757 &mut is_signed.into().into(),
758 ))
759 }
760 }
761
762 pub fn structure(structure: &Structure) -> Ref<Self> {
763 unsafe { Self::ref_from_raw(BNCreateStructureType(structure.handle)) }
764 }
765
766 pub fn named_type(type_reference: &NamedTypeReference) -> Ref<Self> {
767 let mut is_const = Conf::new(false, MIN_CONFIDENCE).into();
768 let mut is_volatile = Conf::new(false, MIN_CONFIDENCE).into();
769 unsafe {
770 Self::ref_from_raw(BNCreateNamedTypeReference(
771 type_reference.handle,
772 0,
773 1,
774 &mut is_const,
775 &mut is_volatile,
776 ))
777 }
778 }
779
780 pub fn named_type_from_type<T: Into<QualifiedName>>(name: T, t: &Type) -> Ref<Self> {
781 let mut raw_name = QualifiedName::into_raw(name.into());
782 let id = c"";
784
785 let result = unsafe {
786 Self::ref_from_raw(BNCreateNamedTypeReferenceFromTypeAndId(
787 id.as_ptr(),
788 &mut raw_name,
789 t.handle,
790 ))
791 };
792 QualifiedName::free_raw(raw_name);
793 result
794 }
795
796 pub fn function<'a, T: Into<Conf<&'a Type>>>(
798 return_type: T,
799 parameters: Vec<FunctionParameter>,
800 variable_arguments: bool,
801 ) -> Ref<Self> {
802 let mut owned_raw_return_type = Conf::<&Type>::into_raw(return_type.into());
803 let mut variable_arguments = Conf::new(variable_arguments, MAX_CONFIDENCE).into();
804 let mut can_return = Conf::new(true, MIN_CONFIDENCE).into();
805 let mut pure = Conf::new(false, MIN_CONFIDENCE).into();
806
807 let mut raw_calling_convention: BNCallingConventionWithConfidence =
808 BNCallingConventionWithConfidence {
809 convention: std::ptr::null_mut(),
810 confidence: MIN_CONFIDENCE,
811 };
812
813 let mut stack_adjust = Conf::new(0, MIN_CONFIDENCE).into();
814 let mut raw_parameters = parameters
815 .into_iter()
816 .map(FunctionParameter::into_raw)
817 .collect::<Vec<_>>();
818 let reg_stack_adjust_regs = std::ptr::null_mut();
819 let reg_stack_adjust_values = std::ptr::null_mut();
820
821 let mut return_regs: BNRegisterSetWithConfidence = BNRegisterSetWithConfidence {
822 regs: std::ptr::null_mut(),
823 count: 0,
824 confidence: 0,
825 };
826
827 let result = unsafe {
828 Self::ref_from_raw(BNCreateFunctionType(
829 &mut owned_raw_return_type,
830 &mut raw_calling_convention,
831 raw_parameters.as_mut_ptr(),
832 raw_parameters.len(),
833 &mut variable_arguments,
834 &mut can_return,
835 &mut stack_adjust,
836 reg_stack_adjust_regs,
837 reg_stack_adjust_values,
838 0,
839 &mut return_regs,
840 BNNameType::NoNameType,
841 &mut pure,
842 ))
843 };
844
845 for raw_param in raw_parameters {
846 FunctionParameter::free_raw(raw_param);
847 }
848
849 result
850 }
851
852 pub fn function_with_opts<
854 'a,
855 T: Into<Conf<&'a Type>>,
856 C: Into<Conf<Ref<CoreCallingConvention>>>,
857 >(
858 return_type: T,
859 parameters: &[FunctionParameter],
860 variable_arguments: bool,
861 calling_convention: C,
862 stack_adjust: Conf<i64>,
863 ) -> Ref<Self> {
864 let mut owned_raw_return_type = Conf::<&Type>::into_raw(return_type.into());
865 let mut variable_arguments = Conf::new(variable_arguments, MAX_CONFIDENCE).into();
866 let mut can_return = Conf::new(true, MIN_CONFIDENCE).into();
867 let mut pure = Conf::new(false, MIN_CONFIDENCE).into();
868
869 let mut owned_raw_calling_convention =
870 Conf::<Ref<CoreCallingConvention>>::into_owned_raw(&calling_convention.into());
871
872 let mut stack_adjust = stack_adjust.into();
873 let mut raw_parameters = parameters
874 .iter()
875 .cloned()
876 .map(FunctionParameter::into_raw)
877 .collect::<Vec<_>>();
878
879 let reg_stack_adjust_regs = std::ptr::null_mut();
881 let reg_stack_adjust_values = std::ptr::null_mut();
882
883 let mut return_regs: BNRegisterSetWithConfidence = BNRegisterSetWithConfidence {
884 regs: std::ptr::null_mut(),
885 count: 0,
886 confidence: 0,
887 };
888
889 let result = unsafe {
890 Self::ref_from_raw(BNCreateFunctionType(
891 &mut owned_raw_return_type,
892 &mut owned_raw_calling_convention,
893 raw_parameters.as_mut_ptr(),
894 raw_parameters.len(),
895 &mut variable_arguments,
896 &mut can_return,
897 &mut stack_adjust,
898 reg_stack_adjust_regs,
899 reg_stack_adjust_values,
900 0,
901 &mut return_regs,
902 BNNameType::NoNameType,
903 &mut pure,
904 ))
905 };
906
907 for raw_param in raw_parameters {
908 FunctionParameter::free_raw(raw_param);
909 }
910
911 result
912 }
913
914 pub fn pointer<'a, A: Architecture, T: Into<Conf<&'a Type>>>(arch: &A, ty: T) -> Ref<Self> {
915 Self::pointer_with_options(arch, ty, false, false, None)
916 }
917
918 pub fn const_pointer<'a, A: Architecture, T: Into<Conf<&'a Type>>>(
919 arch: &A,
920 ty: T,
921 ) -> Ref<Self> {
922 Self::pointer_with_options(arch, ty, true, false, None)
923 }
924
925 pub fn pointer_with_options<'a, A: Architecture, T: Into<Conf<&'a Type>>>(
926 arch: &A,
927 ty: T,
928 is_const: bool,
929 is_volatile: bool,
930 ref_type: Option<ReferenceType>,
931 ) -> Ref<Self> {
932 let arch_pointer_size = arch.address_size();
933 Self::pointer_of_width(ty, arch_pointer_size, is_const, is_volatile, ref_type)
934 }
935
936 pub fn pointer_of_width<'a, T: Into<Conf<&'a Type>>>(
937 ty: T,
938 size: usize,
939 is_const: bool,
940 is_volatile: bool,
941 ref_type: Option<ReferenceType>,
942 ) -> Ref<Self> {
943 let mut is_const = Conf::new(is_const, MAX_CONFIDENCE).into();
944 let mut is_volatile = Conf::new(is_volatile, MAX_CONFIDENCE).into();
945 let owned_raw_ty = Conf::<&Type>::into_raw(ty.into());
946 unsafe {
947 Self::ref_from_raw(BNCreatePointerTypeOfWidth(
948 size,
949 &owned_raw_ty,
950 &mut is_const,
951 &mut is_volatile,
952 ref_type.unwrap_or(ReferenceType::PointerReferenceType),
953 ))
954 }
955 }
956
957 pub fn generate_auto_demangled_type_id<T: Into<QualifiedName>>(name: T) -> String {
958 let mut raw_name = QualifiedName::into_raw(name.into());
959 let type_id =
960 unsafe { BnString::into_string(BNGenerateAutoDemangledTypeId(&mut raw_name)) };
961 QualifiedName::free_raw(raw_name);
962 type_id
963 }
964}
965
966impl Display for Type {
967 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
968 write!(f, "{}", unsafe {
969 BnString::into_string(BNGetTypeString(
970 self.handle,
971 std::ptr::null_mut(),
972 BNTokenEscapingType::NoTokenEscapingType,
973 ))
974 })
975 }
976}
977
978impl Debug for Type {
979 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
980 f.debug_struct("Type")
985 .field("type_class", &self.type_class())
986 .field("width", &self.width())
987 .field("alignment", &self.alignment())
988 .field("is_signed", &self.is_signed())
989 .field("is_const", &self.is_const())
990 .field("is_volatile", &self.is_volatile())
991 .field("child_type", &self.child_type())
992 .field("calling_convention", &self.calling_convention())
993 .field("parameters", &self.parameters())
994 .field("has_variable_arguments", &self.has_variable_arguments())
995 .field("can_return", &self.can_return())
996 .field("pure", &self.pure())
997 .field("get_structure", &self.get_structure())
998 .field("get_enumeration", &self.get_enumeration())
999 .field("get_named_type_reference", &self.get_named_type_reference())
1000 .field("count", &self.count())
1001 .field("offset", &self.offset())
1002 .field("stack_adjustment", &self.stack_adjustment())
1003 .field("registered_name", &self.registered_name())
1004 .finish()
1005 }
1006}
1007
1008impl PartialEq for Type {
1009 fn eq(&self, other: &Self) -> bool {
1010 unsafe { BNTypesEqual(self.handle, other.handle) }
1011 }
1012}
1013
1014impl Eq for Type {}
1015
1016impl Hash for Type {
1017 fn hash<H: Hasher>(&self, state: &mut H) {
1018 self.handle.hash(state);
1019 }
1020}
1021
1022unsafe impl Send for Type {}
1023unsafe impl Sync for Type {}
1024
1025unsafe impl RefCountable for Type {
1026 unsafe fn inc_ref(handle: &Self) -> Ref<Self> {
1027 Self::ref_from_raw(BNNewTypeReference(handle.handle))
1028 }
1029
1030 unsafe fn dec_ref(handle: &Self) {
1031 BNFreeType(handle.handle);
1032 }
1033}
1034
1035impl ToOwned for Type {
1036 type Owned = Ref<Self>;
1037
1038 fn to_owned(&self) -> Self::Owned {
1039 unsafe { RefCountable::inc_ref(self) }
1040 }
1041}
1042
1043impl CoreArrayProvider for Type {
1044 type Raw = *mut BNType;
1045 type Context = ();
1046 type Wrapped<'a> = &'a Self;
1047}
1048
1049unsafe impl CoreArrayProviderInner for Type {
1050 unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
1051 BNFreeTypeList(raw, count)
1052 }
1053
1054 unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
1055 std::mem::transmute(raw)
1057 }
1058}
1059
1060#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1061pub struct FunctionParameter {
1062 pub ty: Conf<Ref<Type>>,
1063 pub name: String,
1064 pub location: Option<Variable>,
1065}
1066
1067impl FunctionParameter {
1068 pub(crate) fn from_raw(value: &BNFunctionParameter) -> Self {
1069 let name = if value.name.is_null() {
1072 if value.location.type_ == VariableSourceType::RegisterVariableSourceType {
1073 format!("reg_{}", value.location.storage)
1074 } else if value.location.type_ == VariableSourceType::StackVariableSourceType {
1075 format!("arg_{}", value.location.storage)
1076 } else {
1077 String::new()
1078 }
1079 } else {
1080 raw_to_string(value.name as *const _).unwrap()
1081 };
1082
1083 Self {
1084 ty: Conf::new(
1085 unsafe { Type::from_raw(value.type_).to_owned() },
1086 value.typeConfidence,
1087 ),
1088 name,
1089 location: match value.defaultLocation {
1090 false => Some(Variable::from(value.location)),
1091 true => None,
1092 },
1093 }
1094 }
1095
1096 #[allow(unused)]
1097 pub(crate) fn from_owned_raw(value: BNFunctionParameter) -> Self {
1098 let owned = Self::from_raw(&value);
1099 Self::free_raw(value);
1100 owned
1101 }
1102
1103 pub(crate) fn into_raw(value: Self) -> BNFunctionParameter {
1104 let bn_name = BnString::new(value.name);
1105 BNFunctionParameter {
1106 name: BnString::into_raw(bn_name),
1107 type_: unsafe { Ref::into_raw(value.ty.contents) }.handle,
1108 typeConfidence: value.ty.confidence,
1109 defaultLocation: value.location.is_none(),
1110 location: value.location.map(Into::into).unwrap_or_default(),
1111 }
1112 }
1113
1114 pub(crate) fn free_raw(value: BNFunctionParameter) {
1115 unsafe { BnString::free_raw(value.name) };
1116 let _ = unsafe { Type::ref_from_raw(value.type_) };
1117 }
1118
1119 pub fn new<T: Into<Conf<Ref<Type>>>>(ty: T, name: String, location: Option<Variable>) -> Self {
1120 Self {
1121 ty: ty.into(),
1122 name,
1123 location,
1124 }
1125 }
1126}
1127
1128#[derive(PartialEq, Eq, Hash)]
1129pub struct NamedTypeReference {
1130 pub(crate) handle: *mut BNNamedTypeReference,
1131}
1132
1133impl NamedTypeReference {
1134 pub(crate) unsafe fn from_raw(handle: *mut BNNamedTypeReference) -> Self {
1135 debug_assert!(!handle.is_null());
1136 Self { handle }
1137 }
1138
1139 pub(crate) unsafe fn ref_from_raw(handle: *mut BNNamedTypeReference) -> Ref<Self> {
1140 debug_assert!(!handle.is_null());
1141 Ref::new(Self { handle })
1142 }
1143
1144 pub fn new<T: Into<QualifiedName>>(type_class: NamedTypeReferenceClass, name: T) -> Ref<Self> {
1150 let mut raw_name = QualifiedName::into_raw(name.into());
1151 let result = unsafe {
1152 Self::ref_from_raw(BNCreateNamedType(
1153 type_class,
1154 std::ptr::null(),
1155 &mut raw_name,
1156 ))
1157 };
1158 QualifiedName::free_raw(raw_name);
1159 result
1160 }
1161
1162 pub fn new_with_id<T: Into<QualifiedName>>(
1168 type_class: NamedTypeReferenceClass,
1169 type_id: &str,
1170 name: T,
1171 ) -> Ref<Self> {
1172 let type_id = type_id.to_cstr();
1173 let mut raw_name = QualifiedName::into_raw(name.into());
1174 let result = unsafe {
1175 Self::ref_from_raw(BNCreateNamedType(
1176 type_class,
1177 type_id.as_ref().as_ptr() as _,
1178 &mut raw_name,
1179 ))
1180 };
1181 QualifiedName::free_raw(raw_name);
1182 result
1183 }
1184
1185 pub fn name(&self) -> QualifiedName {
1186 let raw_name = unsafe { BNGetTypeReferenceName(self.handle) };
1187 QualifiedName::from_owned_raw(raw_name)
1188 }
1189
1190 pub fn id(&self) -> String {
1191 unsafe { BnString::into_string(BNGetTypeReferenceId(self.handle)) }
1192 }
1193
1194 pub fn class(&self) -> NamedTypeReferenceClass {
1195 unsafe { BNGetTypeReferenceClass(self.handle) }
1196 }
1197
1198 fn target_helper(&self, bv: &BinaryView, visited: &mut HashSet<String>) -> Option<Ref<Type>> {
1199 let ty = bv.type_by_id(&self.id())?;
1200 match ty.type_class() {
1201 TypeClass::NamedTypeReferenceClass => {
1202 let ntr = ty
1204 .get_named_type_reference()
1205 .expect("NTR type class should always have a valid NTR");
1206 match visited.insert(ntr.id()) {
1207 true => ntr.target_helper(bv, visited),
1208 false => None,
1210 }
1211 }
1212 _ => Some(ty),
1214 }
1215 }
1216
1217 pub fn target(&self, bv: &BinaryView) -> Option<Ref<Type>> {
1221 self.target_helper(bv, &mut HashSet::new())
1222 }
1223}
1224
1225impl ToOwned for NamedTypeReference {
1226 type Owned = Ref<Self>;
1227
1228 fn to_owned(&self) -> Self::Owned {
1229 unsafe { RefCountable::inc_ref(self) }
1230 }
1231}
1232
1233unsafe impl RefCountable for NamedTypeReference {
1234 unsafe fn inc_ref(handle: &Self) -> Ref<Self> {
1235 Self::ref_from_raw(BNNewNamedTypeReference(handle.handle))
1236 }
1237
1238 unsafe fn dec_ref(handle: &Self) {
1239 BNFreeNamedTypeReference(handle.handle)
1240 }
1241}
1242
1243impl Debug for NamedTypeReference {
1244 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1245 write!(f, "{} (id: {})", self.name(), self.id())
1246 }
1247}
1248
1249#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1250pub struct QualifiedNameAndType {
1251 pub name: QualifiedName,
1252 pub ty: Ref<Type>,
1253}
1254
1255impl QualifiedNameAndType {
1256 pub(crate) fn from_raw(value: &BNQualifiedNameAndType) -> Self {
1257 Self {
1258 name: QualifiedName::from_raw(&value.name),
1259 ty: unsafe { Type::from_raw(value.type_).to_owned() },
1260 }
1261 }
1262
1263 pub(crate) fn from_owned_raw(value: BNQualifiedNameAndType) -> Self {
1264 let owned = Self::from_raw(&value);
1265 Self::free_raw(value);
1266 owned
1267 }
1268
1269 pub(crate) fn into_raw(value: Self) -> BNQualifiedNameAndType {
1270 BNQualifiedNameAndType {
1271 name: QualifiedName::into_raw(value.name),
1272 type_: unsafe { Ref::into_raw(value.ty).handle },
1273 }
1274 }
1275
1276 pub(crate) fn free_raw(value: BNQualifiedNameAndType) {
1277 QualifiedName::free_raw(value.name);
1278 let _ = unsafe { Type::ref_from_raw(value.type_) };
1279 }
1280
1281 pub fn new(name: QualifiedName, ty: Ref<Type>) -> Self {
1282 Self { name, ty }
1283 }
1284}
1285
1286impl<T> From<(T, Ref<Type>)> for QualifiedNameAndType
1287where
1288 T: Into<QualifiedName>,
1289{
1290 fn from(value: (T, Ref<Type>)) -> Self {
1291 Self {
1292 name: value.0.into(),
1293 ty: value.1,
1294 }
1295 }
1296}
1297
1298impl<T> From<(T, &Type)> for QualifiedNameAndType
1299where
1300 T: Into<QualifiedName>,
1301{
1302 fn from(value: (T, &Type)) -> Self {
1303 let ty = value.1.to_owned();
1304 Self {
1305 name: value.0.into(),
1306 ty,
1307 }
1308 }
1309}
1310
1311impl CoreArrayProvider for QualifiedNameAndType {
1312 type Raw = BNQualifiedNameAndType;
1313 type Context = ();
1314 type Wrapped<'a> = Self;
1315}
1316
1317unsafe impl CoreArrayProviderInner for QualifiedNameAndType {
1318 unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
1319 BNFreeTypeAndNameList(raw, count);
1320 }
1321
1322 unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
1323 QualifiedNameAndType::from_raw(raw)
1324 }
1325}
1326
1327#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1328pub struct QualifiedNameTypeAndId {
1329 pub name: QualifiedName,
1330 pub ty: Ref<Type>,
1331 pub id: String,
1332}
1333
1334impl QualifiedNameTypeAndId {
1335 pub(crate) fn from_raw(value: &BNQualifiedNameTypeAndId) -> Self {
1336 Self {
1337 name: QualifiedName::from_raw(&value.name),
1338 ty: unsafe { Type::from_raw(value.type_) }.to_owned(),
1339 id: raw_to_string(value.id).unwrap(),
1340 }
1341 }
1342
1343 #[allow(unused)]
1344 pub(crate) fn from_owned_raw(value: BNQualifiedNameTypeAndId) -> Self {
1345 let owned = Self::from_raw(&value);
1346 Self::free_raw(value);
1347 owned
1348 }
1349
1350 pub(crate) fn into_raw(value: Self) -> BNQualifiedNameTypeAndId {
1351 let bn_id = BnString::new(value.id);
1352 BNQualifiedNameTypeAndId {
1353 name: QualifiedName::into_raw(value.name),
1354 id: BnString::into_raw(bn_id),
1355 type_: unsafe { Ref::into_raw(value.ty) }.handle,
1356 }
1357 }
1358
1359 pub(crate) fn free_raw(value: BNQualifiedNameTypeAndId) {
1360 QualifiedName::free_raw(value.name);
1361 let _ = unsafe { Type::ref_from_raw(value.type_) };
1362 let _ = unsafe { BnString::from_raw(value.id) };
1363 }
1364}
1365
1366impl CoreArrayProvider for QualifiedNameTypeAndId {
1367 type Raw = BNQualifiedNameTypeAndId;
1368 type Context = ();
1369 type Wrapped<'a> = QualifiedNameTypeAndId;
1370}
1371
1372unsafe impl CoreArrayProviderInner for QualifiedNameTypeAndId {
1373 unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
1374 BNFreeTypeIdList(raw, count);
1375 }
1376
1377 unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
1378 QualifiedNameTypeAndId::from_raw(raw)
1379 }
1380}
1381
1382#[derive(Debug, Clone, Eq, PartialEq, Hash)]
1387pub struct NameAndType {
1388 pub name: String,
1389 pub ty: Conf<Ref<Type>>,
1390}
1391
1392impl NameAndType {
1393 pub(crate) fn from_raw(value: &BNNameAndType) -> Self {
1394 Self {
1395 name: raw_to_string(value.name as *mut _).unwrap(),
1397 ty: Conf::new(
1398 unsafe { Type::from_raw(value.type_).to_owned() },
1399 value.typeConfidence,
1400 ),
1401 }
1402 }
1403
1404 #[allow(unused)]
1405 pub(crate) fn from_owned_raw(value: BNNameAndType) -> Self {
1406 let owned = Self::from_raw(&value);
1407 Self::free_raw(value);
1408 owned
1409 }
1410
1411 pub(crate) fn into_raw(value: Self) -> BNNameAndType {
1412 let bn_name = BnString::new(value.name);
1413 BNNameAndType {
1414 name: BnString::into_raw(bn_name),
1415 type_: unsafe { Ref::into_raw(value.ty.contents) }.handle,
1416 typeConfidence: value.ty.confidence,
1417 }
1418 }
1419
1420 pub(crate) fn free_raw(value: BNNameAndType) {
1421 unsafe { BnString::free_raw(value.name) };
1422 let _ = unsafe { Type::ref_from_raw(value.type_) };
1423 }
1424
1425 pub fn new(name: impl Into<String>, ty: Conf<Ref<Type>>) -> Self {
1426 Self {
1427 name: name.into(),
1428 ty,
1429 }
1430 }
1431}
1432
1433impl CoreArrayProvider for NameAndType {
1434 type Raw = BNNameAndType;
1435 type Context = ();
1436 type Wrapped<'a> = Self;
1437}
1438
1439unsafe impl CoreArrayProviderInner for NameAndType {
1440 unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
1441 BNFreeNameAndTypeList(raw, count);
1442 }
1443
1444 unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
1445 NameAndType::from_raw(raw)
1446 }
1447}