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_width(&self, width: usize) -> &Self {
130 unsafe { BNTypeBuilderSetWidth(self.handle, width) }
131 self
132 }
133
134 pub fn set_alignment(&self, alignment: usize) -> &Self {
138 unsafe { BNTypeBuilderSetAlignment(self.handle, alignment) }
139 self
140 }
141
142 pub fn set_pointer_base(&self, base_type: PointerBaseType, base_offset: i64) -> &Self {
143 unsafe { BNSetTypeBuilderPointerBase(self.handle, base_type, base_offset) }
144 self
145 }
146
147 pub fn set_child_type<'a, T: Into<Conf<&'a Type>>>(&self, ty: T) -> &Self {
148 let mut type_with_confidence = Conf::<&Type>::into_raw(ty.into());
149 unsafe { BNTypeBuilderSetChildType(self.handle, &mut type_with_confidence) };
150 self
151 }
152
153 pub fn set_target<'a, T: Into<Conf<&'a Type>>>(&self, ty: T) -> &Self {
155 self.set_child_type(ty)
156 }
157
158 pub fn set_element_type<'a, T: Into<Conf<&'a Type>>>(&self, ty: T) -> &Self {
160 self.set_child_type(ty)
161 }
162
163 pub fn set_return_value<'a, T: Into<Conf<&'a Type>>>(&self, ty: T) -> &Self {
165 self.set_child_type(ty)
166 }
167
168 pub fn set_signed<T: Into<Conf<bool>>>(&self, value: T) -> &Self {
169 let mut bool_with_confidence = value.into().into();
170 unsafe { BNTypeBuilderSetSigned(self.handle, &mut bool_with_confidence) };
171 self
172 }
173
174 pub fn type_class(&self) -> TypeClass {
177 unsafe { BNGetTypeBuilderClass(self.handle) }
178 }
179
180 pub fn width(&self) -> u64 {
181 unsafe { BNGetTypeBuilderWidth(self.handle) }
182 }
183
184 pub fn alignment(&self) -> usize {
185 unsafe { BNGetTypeBuilderAlignment(self.handle) }
186 }
187
188 pub fn is_signed(&self) -> Conf<bool> {
189 unsafe { BNIsTypeBuilderSigned(self.handle).into() }
190 }
191
192 pub fn is_const(&self) -> Conf<bool> {
193 unsafe { BNIsTypeBuilderConst(self.handle).into() }
194 }
195
196 pub fn is_volatile(&self) -> Conf<bool> {
197 unsafe { BNIsTypeBuilderVolatile(self.handle).into() }
198 }
199
200 pub fn is_floating_point(&self) -> bool {
201 unsafe { BNIsTypeBuilderFloatingPoint(self.handle) }
202 }
203
204 pub fn child_type(&self) -> Option<Conf<Ref<Type>>> {
205 let raw_target = unsafe { BNGetTypeBuilderChildType(self.handle) };
206 match raw_target.type_.is_null() {
207 false => Some(Conf::<Ref<Type>>::from_owned_raw(raw_target)),
208 true => None,
209 }
210 }
211
212 pub fn target(&self) -> Option<Conf<Ref<Type>>> {
214 self.child_type()
215 }
216
217 pub fn element_type(&self) -> Option<Conf<Ref<Type>>> {
219 self.child_type()
220 }
221
222 pub fn return_value(&self) -> Option<Conf<Ref<Type>>> {
224 self.child_type()
225 }
226
227 pub fn calling_convention(&self) -> Option<Conf<Ref<CoreCallingConvention>>> {
228 let raw_convention_confidence = unsafe { BNGetTypeBuilderCallingConvention(self.handle) };
229 match raw_convention_confidence.convention.is_null() {
230 false => Some(Conf::<Ref<CoreCallingConvention>>::from_owned_raw(
231 raw_convention_confidence,
232 )),
233 true => None,
234 }
235 }
236
237 pub fn parameters(&self) -> Option<Vec<FunctionParameter>> {
238 unsafe {
239 let mut count = 0;
240 let raw_parameters_ptr = BNGetTypeBuilderParameters(self.handle, &mut count);
241 match raw_parameters_ptr.is_null() {
242 false => {
243 let raw_parameters = std::slice::from_raw_parts(raw_parameters_ptr, count);
244 let parameters = raw_parameters
245 .iter()
246 .map(FunctionParameter::from_raw)
247 .collect();
248 BNFreeTypeParameterList(raw_parameters_ptr, count);
249 Some(parameters)
250 }
251 true => None,
252 }
253 }
254 }
255
256 pub fn has_variable_arguments(&self) -> Conf<bool> {
257 unsafe { BNTypeBuilderHasVariableArguments(self.handle).into() }
258 }
259
260 pub fn can_return(&self) -> Conf<bool> {
261 unsafe { BNFunctionTypeBuilderCanReturn(self.handle).into() }
262 }
263
264 pub fn pure(&self) -> Conf<bool> {
265 unsafe { BNIsTypeBuilderPure(self.handle).into() }
266 }
267
268 pub fn get_structure(&self) -> Option<Ref<Structure>> {
271 let raw_struct_ptr = unsafe { BNGetTypeBuilderStructure(self.handle) };
272 match raw_struct_ptr.is_null() {
273 false => Some(unsafe { Structure::ref_from_raw(raw_struct_ptr) }),
274 true => None,
275 }
276 }
277
278 pub fn get_enumeration(&self) -> Option<Ref<Enumeration>> {
281 let raw_enum_ptr = unsafe { BNGetTypeBuilderEnumeration(self.handle) };
282 match raw_enum_ptr.is_null() {
283 false => Some(unsafe { Enumeration::ref_from_raw(raw_enum_ptr) }),
284 true => None,
285 }
286 }
287
288 pub fn get_named_type_reference(&self) -> Option<Ref<NamedTypeReference>> {
291 let raw_type_ref_ptr = unsafe { BNGetTypeBuilderNamedTypeReference(self.handle) };
292 match raw_type_ref_ptr.is_null() {
293 false => Some(unsafe { NamedTypeReference::ref_from_raw(raw_type_ref_ptr) }),
294 true => None,
295 }
296 }
297
298 pub fn count(&self) -> u64 {
299 unsafe { BNGetTypeBuilderElementCount(self.handle) }
300 }
301
302 pub fn offset(&self) -> u64 {
303 unsafe { BNGetTypeBuilderOffset(self.handle) }
304 }
305
306 pub fn stack_adjustment(&self) -> Conf<i64> {
307 unsafe { BNGetTypeBuilderStackAdjustment(self.handle).into() }
308 }
309
310 pub fn pointer_base_type(&self) -> PointerBaseType {
311 unsafe { BNTypeBuilderGetPointerBaseType(self.handle) }
312 }
313
314 pub fn pointer_base_offset(&self) -> i64 {
315 unsafe { BNTypeBuilderGetPointerBaseOffset(self.handle) }
316 }
317
318 pub fn void() -> Self {
323 unsafe { Self::from_raw(BNCreateVoidTypeBuilder()) }
324 }
325
326 pub fn bool() -> Self {
328 unsafe { Self::from_raw(BNCreateBoolTypeBuilder()) }
329 }
330
331 pub fn char() -> Self {
333 Self::int(1, true)
334 }
335
336 pub fn int(width: usize, is_signed: bool) -> Self {
338 let mut is_signed = Conf::new(is_signed, MAX_CONFIDENCE).into();
339
340 unsafe {
341 Self::from_raw(BNCreateIntegerTypeBuilder(
342 width,
343 &mut is_signed,
344 c"".as_ptr() as _,
345 ))
346 }
347 }
348
349 pub fn named_int(width: usize, is_signed: bool, alt_name: &str) -> Self {
352 let mut is_signed = Conf::new(is_signed, MAX_CONFIDENCE).into();
353 let alt_name = alt_name.to_cstr();
354
355 unsafe {
356 Self::from_raw(BNCreateIntegerTypeBuilder(
357 width,
358 &mut is_signed,
359 alt_name.as_ref().as_ptr() as _,
360 ))
361 }
362 }
363
364 pub fn float(width: usize) -> Self {
366 unsafe { Self::from_raw(BNCreateFloatTypeBuilder(width, c"".as_ptr())) }
367 }
368
369 pub fn named_float(width: usize, alt_name: &str) -> Self {
371 let alt_name = alt_name.to_cstr();
372 unsafe { Self::from_raw(BNCreateFloatTypeBuilder(width, alt_name.as_ptr())) }
373 }
374
375 pub fn array<'a, T: Into<Conf<&'a Type>>>(ty: T, count: u64) -> Self {
377 let owned_raw_ty = Conf::<&Type>::into_raw(ty.into());
378 unsafe { Self::from_raw(BNCreateArrayTypeBuilder(&owned_raw_ty, count)) }
379 }
380
381 pub fn enumeration<T: Into<Conf<bool>>>(
389 enumeration: &Enumeration,
390 width: NonZeroUsize,
391 is_signed: T,
392 ) -> Self {
393 unsafe {
394 Self::from_raw(BNCreateEnumerationTypeBuilder(
395 std::ptr::null_mut(),
397 enumeration.handle,
398 width.get(),
399 &mut is_signed.into().into(),
400 ))
401 }
402 }
403
404 pub fn structure(structure_type: &Structure) -> Self {
406 unsafe { Self::from_raw(BNCreateStructureTypeBuilder(structure_type.handle)) }
407 }
408
409 pub fn named_type(type_reference: &NamedTypeReference) -> Self {
411 let mut is_const = Conf::new(false, MIN_CONFIDENCE).into();
412 let mut is_volatile = Conf::new(false, MIN_CONFIDENCE).into();
413 unsafe {
414 Self::from_raw(BNCreateNamedTypeReferenceBuilder(
415 type_reference.handle,
416 0,
417 1,
418 &mut is_const,
419 &mut is_volatile,
420 ))
421 }
422 }
423
424 pub fn named_type_from_type<T: Into<QualifiedName>>(name: T, t: &Type) -> Self {
426 let mut raw_name = QualifiedName::into_raw(name.into());
427 let id = c"";
428
429 let result = unsafe {
430 Self::from_raw(BNCreateNamedTypeReferenceBuilderFromTypeAndId(
431 id.as_ptr() as *mut _,
432 &mut raw_name,
433 t.handle,
434 ))
435 };
436 QualifiedName::free_raw(raw_name);
437 result
438 }
439
440 pub fn pointer<'a, A: Architecture, T: Into<Conf<&'a Type>>>(arch: &A, ty: T) -> Self {
444 Self::pointer_with_options(arch, ty, false, false, None)
445 }
446
447 pub fn const_pointer<'a, A: Architecture, T: Into<Conf<&'a Type>>>(arch: &A, ty: T) -> Self {
449 Self::pointer_with_options(arch, ty, true, false, None)
450 }
451
452 pub fn pointer_with_options<'a, A: Architecture, T: Into<Conf<&'a Type>>>(
453 arch: &A,
454 ty: T,
455 is_const: bool,
456 is_volatile: bool,
457 ref_type: Option<ReferenceType>,
458 ) -> Self {
459 let arch_ptr_size = arch.address_size();
460 Self::pointer_of_width(ty, arch_ptr_size, is_const, is_volatile, ref_type)
461 }
462
463 pub fn pointer_of_width<'a, T: Into<Conf<&'a Type>>>(
464 ty: T,
465 size: usize,
466 is_const: bool,
467 is_volatile: bool,
468 ref_type: Option<ReferenceType>,
469 ) -> Self {
470 let mut is_const = Conf::new(is_const, MAX_CONFIDENCE).into();
471 let mut is_volatile = Conf::new(is_volatile, MAX_CONFIDENCE).into();
472 let owned_raw_ty = Conf::<&Type>::into_raw(ty.into());
473 unsafe {
474 Self::from_raw(BNCreatePointerTypeBuilderOfWidth(
475 size,
476 &owned_raw_ty,
477 &mut is_const,
478 &mut is_volatile,
479 ref_type.unwrap_or(ReferenceType::PointerReferenceType),
480 ))
481 }
482 }
483}
484
485impl Display for TypeBuilder {
486 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
487 write!(f, "{}", unsafe {
488 BnString::into_string(BNGetTypeBuilderString(self.handle, std::ptr::null_mut()))
489 })
490 }
491}
492
493impl Drop for TypeBuilder {
494 fn drop(&mut self) {
495 unsafe { BNFreeTypeBuilder(self.handle) };
496 }
497}
498
499#[repr(transparent)]
535pub struct Type {
536 pub handle: *mut BNType,
537}
538
539impl Type {
540 pub unsafe fn from_raw(handle: *mut BNType) -> Self {
541 debug_assert!(!handle.is_null());
542 Self { handle }
543 }
544
545 pub unsafe fn ref_from_raw(handle: *mut BNType) -> Ref<Self> {
546 debug_assert!(!handle.is_null());
547 Ref::new(Self { handle })
548 }
549
550 pub fn to_builder(&self) -> TypeBuilder {
551 TypeBuilder::new(self)
552 }
553
554 pub fn type_class(&self) -> TypeClass {
555 unsafe { BNGetTypeClass(self.handle) }
556 }
557
558 pub fn width(&self) -> u64 {
562 unsafe { BNGetTypeWidth(self.handle) }
563 }
564
565 pub fn alignment(&self) -> usize {
566 unsafe { BNGetTypeAlignment(self.handle) }
567 }
568
569 pub fn is_signed(&self) -> Conf<bool> {
570 unsafe { BNIsTypeSigned(self.handle).into() }
571 }
572
573 pub fn is_const(&self) -> Conf<bool> {
574 unsafe { BNIsTypeConst(self.handle).into() }
575 }
576
577 pub fn is_volatile(&self) -> Conf<bool> {
578 unsafe { BNIsTypeVolatile(self.handle).into() }
579 }
580
581 pub fn is_floating_point(&self) -> bool {
582 unsafe { BNIsTypeFloatingPoint(self.handle) }
583 }
584
585 pub fn child_type(&self) -> Option<Conf<Ref<Type>>> {
586 let raw_target = unsafe { BNGetChildType(self.handle) };
587 match raw_target.type_.is_null() {
588 false => Some(Conf::<Ref<Type>>::from_owned_raw(raw_target)),
589 true => None,
590 }
591 }
592
593 pub fn target(&self) -> Option<Conf<Ref<Type>>> {
595 self.child_type()
596 }
597
598 pub fn element_type(&self) -> Option<Conf<Ref<Type>>> {
600 self.child_type()
601 }
602
603 pub fn return_value(&self) -> Option<Conf<Ref<Type>>> {
605 self.child_type()
606 }
607
608 pub fn calling_convention(&self) -> Option<Conf<Ref<CoreCallingConvention>>> {
609 let convention_confidence = unsafe { BNGetTypeCallingConvention(self.handle) };
610 match convention_confidence.convention.is_null() {
611 false => Some(Conf::<Ref<CoreCallingConvention>>::from_owned_raw(
612 convention_confidence,
613 )),
614 true => None,
615 }
616 }
617
618 pub fn parameters(&self) -> Option<Vec<FunctionParameter>> {
619 unsafe {
620 let mut count = 0;
621 let raw_parameters_ptr = BNGetTypeParameters(self.handle, &mut count);
622 match raw_parameters_ptr.is_null() {
623 false => {
624 let raw_parameters = std::slice::from_raw_parts(raw_parameters_ptr, count);
625 let parameters = raw_parameters
626 .iter()
627 .map(FunctionParameter::from_raw)
628 .collect();
629 BNFreeTypeParameterList(raw_parameters_ptr, count);
630 Some(parameters)
631 }
632 true => None,
633 }
634 }
635 }
636
637 pub fn has_variable_arguments(&self) -> Conf<bool> {
638 unsafe { BNTypeHasVariableArguments(self.handle).into() }
639 }
640
641 pub fn can_return(&self) -> Conf<bool> {
642 unsafe { BNFunctionTypeCanReturn(self.handle).into() }
643 }
644
645 pub fn pure(&self) -> Conf<bool> {
646 unsafe { BNIsTypePure(self.handle).into() }
647 }
648
649 pub fn get_structure(&self) -> Option<Ref<Structure>> {
652 let raw_struct_ptr = unsafe { BNGetTypeStructure(self.handle) };
653 match raw_struct_ptr.is_null() {
654 false => Some(unsafe { Structure::ref_from_raw(raw_struct_ptr) }),
655 true => None,
656 }
657 }
658
659 pub fn get_enumeration(&self) -> Option<Ref<Enumeration>> {
662 let raw_enum_ptr = unsafe { BNGetTypeEnumeration(self.handle) };
663 match raw_enum_ptr.is_null() {
664 false => Some(unsafe { Enumeration::ref_from_raw(raw_enum_ptr) }),
665 true => None,
666 }
667 }
668
669 pub fn get_named_type_reference(&self) -> Option<Ref<NamedTypeReference>> {
672 let raw_type_ref_ptr = unsafe { BNGetTypeNamedTypeReference(self.handle) };
673 match raw_type_ref_ptr.is_null() {
674 false => Some(unsafe { NamedTypeReference::ref_from_raw(raw_type_ref_ptr) }),
675 true => None,
676 }
677 }
678
679 pub fn count(&self) -> u64 {
680 unsafe { BNGetTypeElementCount(self.handle) }
681 }
682
683 pub fn offset(&self) -> u64 {
684 unsafe { BNGetTypeOffset(self.handle) }
685 }
686
687 pub fn stack_adjustment(&self) -> Conf<i64> {
688 unsafe { BNGetTypeStackAdjustment(self.handle).into() }
689 }
690
691 pub fn registered_name(&self) -> Option<Ref<NamedTypeReference>> {
692 let raw_type_ref_ptr = unsafe { BNGetRegisteredTypeName(self.handle) };
693 match raw_type_ref_ptr.is_null() {
694 false => Some(unsafe { NamedTypeReference::ref_from_raw(raw_type_ref_ptr) }),
695 true => None,
696 }
697 }
698
699 pub fn pointer_base_type(&self) -> BNPointerBaseType {
700 unsafe { BNTypeGetPointerBaseType(self.handle) }
701 }
702
703 pub fn pointer_base_offset(&self) -> i64 {
704 unsafe { BNTypeGetPointerBaseOffset(self.handle) }
705 }
706
707 pub fn void() -> Ref<Self> {
711 unsafe { Self::ref_from_raw(BNCreateVoidType()) }
712 }
713
714 pub fn bool() -> Ref<Self> {
715 unsafe { Self::ref_from_raw(BNCreateBoolType()) }
716 }
717
718 pub fn char() -> Ref<Self> {
719 Self::int(1, true)
720 }
721
722 pub fn wide_char(width: usize) -> Ref<Self> {
723 unsafe { Self::ref_from_raw(BNCreateWideCharType(width, c"".as_ptr())) }
724 }
725
726 pub fn int(width: usize, is_signed: bool) -> Ref<Self> {
727 let mut is_signed = Conf::new(is_signed, MAX_CONFIDENCE).into();
728 unsafe { Self::ref_from_raw(BNCreateIntegerType(width, &mut is_signed, c"".as_ptr())) }
729 }
730
731 pub fn named_int(width: usize, is_signed: bool, alt_name: &str) -> Ref<Self> {
732 let mut is_signed = Conf::new(is_signed, MAX_CONFIDENCE).into();
733 let alt_name = alt_name.to_cstr();
734
735 unsafe {
736 Self::ref_from_raw(BNCreateIntegerType(
737 width,
738 &mut is_signed,
739 alt_name.as_ptr(),
740 ))
741 }
742 }
743
744 pub fn float(width: usize) -> Ref<Self> {
745 unsafe { Self::ref_from_raw(BNCreateFloatType(width, c"".as_ptr())) }
746 }
747
748 pub fn named_float(width: usize, alt_name: &str) -> Ref<Self> {
749 let alt_name = alt_name.to_cstr();
750 unsafe { Self::ref_from_raw(BNCreateFloatType(width, alt_name.as_ptr())) }
751 }
752
753 pub fn array<'a, T: Into<Conf<&'a Type>>>(ty: T, count: u64) -> Ref<Self> {
754 let owned_raw_ty = Conf::<&Type>::into_raw(ty.into());
755 unsafe { Self::ref_from_raw(BNCreateArrayType(&owned_raw_ty, count)) }
756 }
757
758 pub fn enumeration<T: Into<Conf<bool>>>(
764 enumeration: &Enumeration,
765 width: NonZeroUsize,
766 is_signed: T,
767 ) -> Ref<Self> {
768 unsafe {
769 Self::ref_from_raw(BNCreateEnumerationType(
770 std::ptr::null_mut(),
772 enumeration.handle,
773 width.get(),
774 &mut is_signed.into().into(),
775 ))
776 }
777 }
778
779 pub fn structure(structure: &Structure) -> Ref<Self> {
780 unsafe { Self::ref_from_raw(BNCreateStructureType(structure.handle)) }
781 }
782
783 pub fn named_type(type_reference: &NamedTypeReference) -> Ref<Self> {
784 let mut is_const = Conf::new(false, MIN_CONFIDENCE).into();
785 let mut is_volatile = Conf::new(false, MIN_CONFIDENCE).into();
786 unsafe {
787 Self::ref_from_raw(BNCreateNamedTypeReference(
788 type_reference.handle,
789 0,
790 1,
791 &mut is_const,
792 &mut is_volatile,
793 ))
794 }
795 }
796
797 pub fn named_type_from_type<T: Into<QualifiedName>>(name: T, t: &Type) -> Ref<Self> {
798 let mut raw_name = QualifiedName::into_raw(name.into());
799 let id = c"";
801
802 let result = unsafe {
803 Self::ref_from_raw(BNCreateNamedTypeReferenceFromTypeAndId(
804 id.as_ptr(),
805 &mut raw_name,
806 t.handle,
807 ))
808 };
809 QualifiedName::free_raw(raw_name);
810 result
811 }
812
813 pub fn function<'a, T: Into<Conf<&'a Type>>>(
815 return_type: T,
816 parameters: Vec<FunctionParameter>,
817 variable_arguments: bool,
818 ) -> Ref<Self> {
819 let mut owned_raw_return_type = Conf::<&Type>::into_raw(return_type.into());
820 let mut variable_arguments = Conf::new(variable_arguments, MAX_CONFIDENCE).into();
821 let mut can_return = Conf::new(true, MIN_CONFIDENCE).into();
822 let mut pure = Conf::new(false, MIN_CONFIDENCE).into();
823
824 let mut raw_calling_convention: BNCallingConventionWithConfidence =
825 BNCallingConventionWithConfidence {
826 convention: std::ptr::null_mut(),
827 confidence: MIN_CONFIDENCE,
828 };
829
830 let mut stack_adjust = Conf::new(0, MIN_CONFIDENCE).into();
831 let mut raw_parameters = parameters
832 .into_iter()
833 .map(FunctionParameter::into_raw)
834 .collect::<Vec<_>>();
835 let reg_stack_adjust_regs = std::ptr::null_mut();
836 let reg_stack_adjust_values = std::ptr::null_mut();
837
838 let mut return_regs: BNRegisterSetWithConfidence = BNRegisterSetWithConfidence {
839 regs: std::ptr::null_mut(),
840 count: 0,
841 confidence: 0,
842 };
843
844 let result = unsafe {
845 Self::ref_from_raw(BNCreateFunctionType(
846 &mut owned_raw_return_type,
847 &mut raw_calling_convention,
848 raw_parameters.as_mut_ptr(),
849 raw_parameters.len(),
850 &mut variable_arguments,
851 &mut can_return,
852 &mut stack_adjust,
853 reg_stack_adjust_regs,
854 reg_stack_adjust_values,
855 0,
856 &mut return_regs,
857 BNNameType::NoNameType,
858 &mut pure,
859 ))
860 };
861
862 for raw_param in raw_parameters {
863 FunctionParameter::free_raw(raw_param);
864 }
865
866 result
867 }
868
869 pub fn function_with_opts<
871 'a,
872 T: Into<Conf<&'a Type>>,
873 C: Into<Conf<Ref<CoreCallingConvention>>>,
874 >(
875 return_type: T,
876 parameters: &[FunctionParameter],
877 variable_arguments: bool,
878 calling_convention: C,
879 stack_adjust: Conf<i64>,
880 ) -> Ref<Self> {
881 let mut owned_raw_return_type = Conf::<&Type>::into_raw(return_type.into());
882 let mut variable_arguments = Conf::new(variable_arguments, MAX_CONFIDENCE).into();
883 let mut can_return = Conf::new(true, MIN_CONFIDENCE).into();
884 let mut pure = Conf::new(false, MIN_CONFIDENCE).into();
885
886 let mut owned_raw_calling_convention =
887 Conf::<Ref<CoreCallingConvention>>::into_owned_raw(&calling_convention.into());
888
889 let mut stack_adjust = stack_adjust.into();
890 let mut raw_parameters = parameters
891 .iter()
892 .cloned()
893 .map(FunctionParameter::into_raw)
894 .collect::<Vec<_>>();
895
896 let reg_stack_adjust_regs = std::ptr::null_mut();
898 let reg_stack_adjust_values = std::ptr::null_mut();
899
900 let mut return_regs: BNRegisterSetWithConfidence = BNRegisterSetWithConfidence {
901 regs: std::ptr::null_mut(),
902 count: 0,
903 confidence: 0,
904 };
905
906 let result = unsafe {
907 Self::ref_from_raw(BNCreateFunctionType(
908 &mut owned_raw_return_type,
909 &mut owned_raw_calling_convention,
910 raw_parameters.as_mut_ptr(),
911 raw_parameters.len(),
912 &mut variable_arguments,
913 &mut can_return,
914 &mut stack_adjust,
915 reg_stack_adjust_regs,
916 reg_stack_adjust_values,
917 0,
918 &mut return_regs,
919 BNNameType::NoNameType,
920 &mut pure,
921 ))
922 };
923
924 for raw_param in raw_parameters {
925 FunctionParameter::free_raw(raw_param);
926 }
927
928 result
929 }
930
931 pub fn pointer<'a, A: Architecture, T: Into<Conf<&'a Type>>>(arch: &A, ty: T) -> Ref<Self> {
932 Self::pointer_with_options(arch, ty, false, false, None)
933 }
934
935 pub fn const_pointer<'a, A: Architecture, T: Into<Conf<&'a Type>>>(
936 arch: &A,
937 ty: T,
938 ) -> Ref<Self> {
939 Self::pointer_with_options(arch, ty, true, false, None)
940 }
941
942 pub fn pointer_with_options<'a, A: Architecture, T: Into<Conf<&'a Type>>>(
943 arch: &A,
944 ty: T,
945 is_const: bool,
946 is_volatile: bool,
947 ref_type: Option<ReferenceType>,
948 ) -> Ref<Self> {
949 let arch_pointer_size = arch.address_size();
950 Self::pointer_of_width(ty, arch_pointer_size, is_const, is_volatile, ref_type)
951 }
952
953 pub fn pointer_of_width<'a, T: Into<Conf<&'a Type>>>(
954 ty: T,
955 size: usize,
956 is_const: bool,
957 is_volatile: bool,
958 ref_type: Option<ReferenceType>,
959 ) -> Ref<Self> {
960 let mut is_const = Conf::new(is_const, MAX_CONFIDENCE).into();
961 let mut is_volatile = Conf::new(is_volatile, MAX_CONFIDENCE).into();
962 let owned_raw_ty = Conf::<&Type>::into_raw(ty.into());
963 unsafe {
964 Self::ref_from_raw(BNCreatePointerTypeOfWidth(
965 size,
966 &owned_raw_ty,
967 &mut is_const,
968 &mut is_volatile,
969 ref_type.unwrap_or(ReferenceType::PointerReferenceType),
970 ))
971 }
972 }
973
974 pub fn generate_auto_demangled_type_id<T: Into<QualifiedName>>(name: T) -> String {
975 let mut raw_name = QualifiedName::into_raw(name.into());
976 let type_id =
977 unsafe { BnString::into_string(BNGenerateAutoDemangledTypeId(&mut raw_name)) };
978 QualifiedName::free_raw(raw_name);
979 type_id
980 }
981}
982
983impl Display for Type {
984 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
985 write!(f, "{}", unsafe {
986 BnString::into_string(BNGetTypeString(
987 self.handle,
988 std::ptr::null_mut(),
989 BNTokenEscapingType::NoTokenEscapingType,
990 ))
991 })
992 }
993}
994
995impl Debug for Type {
996 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
997 f.debug_struct("Type")
1002 .field("type_class", &self.type_class())
1003 .field("width", &self.width())
1004 .field("alignment", &self.alignment())
1005 .field("is_signed", &self.is_signed())
1006 .field("is_const", &self.is_const())
1007 .field("is_volatile", &self.is_volatile())
1008 .field("child_type", &self.child_type())
1009 .field("calling_convention", &self.calling_convention())
1010 .field("parameters", &self.parameters())
1011 .field("has_variable_arguments", &self.has_variable_arguments())
1012 .field("can_return", &self.can_return())
1013 .field("pure", &self.pure())
1014 .field("get_structure", &self.get_structure())
1015 .field("get_enumeration", &self.get_enumeration())
1016 .field("get_named_type_reference", &self.get_named_type_reference())
1017 .field("count", &self.count())
1018 .field("offset", &self.offset())
1019 .field("stack_adjustment", &self.stack_adjustment())
1020 .field("registered_name", &self.registered_name())
1021 .finish()
1022 }
1023}
1024
1025impl PartialEq for Type {
1026 fn eq(&self, other: &Self) -> bool {
1027 unsafe { BNTypesEqual(self.handle, other.handle) }
1028 }
1029}
1030
1031impl Eq for Type {}
1032
1033impl Hash for Type {
1034 fn hash<H: Hasher>(&self, state: &mut H) {
1035 self.handle.hash(state);
1036 }
1037}
1038
1039unsafe impl Send for Type {}
1040unsafe impl Sync for Type {}
1041
1042unsafe impl RefCountable for Type {
1043 unsafe fn inc_ref(handle: &Self) -> Ref<Self> {
1044 Self::ref_from_raw(BNNewTypeReference(handle.handle))
1045 }
1046
1047 unsafe fn dec_ref(handle: &Self) {
1048 BNFreeType(handle.handle);
1049 }
1050}
1051
1052impl ToOwned for Type {
1053 type Owned = Ref<Self>;
1054
1055 fn to_owned(&self) -> Self::Owned {
1056 unsafe { RefCountable::inc_ref(self) }
1057 }
1058}
1059
1060impl CoreArrayProvider for Type {
1061 type Raw = *mut BNType;
1062 type Context = ();
1063 type Wrapped<'a> = &'a Self;
1064}
1065
1066unsafe impl CoreArrayProviderInner for Type {
1067 unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
1068 BNFreeTypeList(raw, count)
1069 }
1070
1071 unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
1072 std::mem::transmute(raw)
1074 }
1075}
1076
1077#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1078pub struct FunctionParameter {
1079 pub ty: Conf<Ref<Type>>,
1080 pub name: String,
1081 pub location: Option<Variable>,
1082}
1083
1084impl FunctionParameter {
1085 pub(crate) fn from_raw(value: &BNFunctionParameter) -> Self {
1086 let name = if value.name.is_null() {
1089 if value.location.type_ == VariableSourceType::RegisterVariableSourceType {
1090 format!("reg_{}", value.location.storage)
1091 } else if value.location.type_ == VariableSourceType::StackVariableSourceType {
1092 format!("arg_{}", value.location.storage)
1093 } else {
1094 String::new()
1095 }
1096 } else {
1097 raw_to_string(value.name as *const _).unwrap()
1098 };
1099
1100 Self {
1101 ty: Conf::new(
1102 unsafe { Type::from_raw(value.type_).to_owned() },
1103 value.typeConfidence,
1104 ),
1105 name,
1106 location: match value.defaultLocation {
1107 false => Some(Variable::from(value.location)),
1108 true => None,
1109 },
1110 }
1111 }
1112
1113 #[allow(unused)]
1114 pub(crate) fn from_owned_raw(value: BNFunctionParameter) -> Self {
1115 let owned = Self::from_raw(&value);
1116 Self::free_raw(value);
1117 owned
1118 }
1119
1120 pub(crate) fn into_raw(value: Self) -> BNFunctionParameter {
1121 let bn_name = BnString::new(value.name);
1122 BNFunctionParameter {
1123 name: BnString::into_raw(bn_name),
1124 type_: unsafe { Ref::into_raw(value.ty.contents) }.handle,
1125 typeConfidence: value.ty.confidence,
1126 defaultLocation: value.location.is_none(),
1127 location: value.location.map(Into::into).unwrap_or_default(),
1128 }
1129 }
1130
1131 pub(crate) fn free_raw(value: BNFunctionParameter) {
1132 unsafe { BnString::free_raw(value.name) };
1133 let _ = unsafe { Type::ref_from_raw(value.type_) };
1134 }
1135
1136 pub fn new<T: Into<Conf<Ref<Type>>>>(ty: T, name: String, location: Option<Variable>) -> Self {
1137 Self {
1138 ty: ty.into(),
1139 name,
1140 location,
1141 }
1142 }
1143}
1144
1145#[derive(PartialEq, Eq, Hash)]
1146pub struct NamedTypeReference {
1147 pub(crate) handle: *mut BNNamedTypeReference,
1148}
1149
1150impl NamedTypeReference {
1151 pub(crate) unsafe fn from_raw(handle: *mut BNNamedTypeReference) -> Self {
1152 debug_assert!(!handle.is_null());
1153 Self { handle }
1154 }
1155
1156 pub(crate) unsafe fn ref_from_raw(handle: *mut BNNamedTypeReference) -> Ref<Self> {
1157 debug_assert!(!handle.is_null());
1158 Ref::new(Self { handle })
1159 }
1160
1161 pub fn new<T: Into<QualifiedName>>(type_class: NamedTypeReferenceClass, name: T) -> Ref<Self> {
1167 let mut raw_name = QualifiedName::into_raw(name.into());
1168 let result = unsafe {
1169 Self::ref_from_raw(BNCreateNamedType(
1170 type_class,
1171 std::ptr::null(),
1172 &mut raw_name,
1173 ))
1174 };
1175 QualifiedName::free_raw(raw_name);
1176 result
1177 }
1178
1179 pub fn new_with_id<T: Into<QualifiedName>>(
1185 type_class: NamedTypeReferenceClass,
1186 type_id: &str,
1187 name: T,
1188 ) -> Ref<Self> {
1189 let type_id = type_id.to_cstr();
1190 let mut raw_name = QualifiedName::into_raw(name.into());
1191 let result = unsafe {
1192 Self::ref_from_raw(BNCreateNamedType(
1193 type_class,
1194 type_id.as_ref().as_ptr() as _,
1195 &mut raw_name,
1196 ))
1197 };
1198 QualifiedName::free_raw(raw_name);
1199 result
1200 }
1201
1202 pub fn name(&self) -> QualifiedName {
1203 let raw_name = unsafe { BNGetTypeReferenceName(self.handle) };
1204 QualifiedName::from_owned_raw(raw_name)
1205 }
1206
1207 pub fn id(&self) -> String {
1208 unsafe { BnString::into_string(BNGetTypeReferenceId(self.handle)) }
1209 }
1210
1211 pub fn class(&self) -> NamedTypeReferenceClass {
1212 unsafe { BNGetTypeReferenceClass(self.handle) }
1213 }
1214
1215 fn target_helper(&self, bv: &BinaryView, visited: &mut HashSet<String>) -> Option<Ref<Type>> {
1216 let ty = bv.type_by_id(&self.id())?;
1217 match ty.type_class() {
1218 TypeClass::NamedTypeReferenceClass => {
1219 let ntr = ty
1221 .get_named_type_reference()
1222 .expect("NTR type class should always have a valid NTR");
1223 match visited.insert(ntr.id()) {
1224 true => ntr.target_helper(bv, visited),
1225 false => None,
1227 }
1228 }
1229 _ => Some(ty),
1231 }
1232 }
1233
1234 pub fn target(&self, bv: &BinaryView) -> Option<Ref<Type>> {
1238 self.target_helper(bv, &mut HashSet::new())
1239 }
1240}
1241
1242impl ToOwned for NamedTypeReference {
1243 type Owned = Ref<Self>;
1244
1245 fn to_owned(&self) -> Self::Owned {
1246 unsafe { RefCountable::inc_ref(self) }
1247 }
1248}
1249
1250unsafe impl RefCountable for NamedTypeReference {
1251 unsafe fn inc_ref(handle: &Self) -> Ref<Self> {
1252 Self::ref_from_raw(BNNewNamedTypeReference(handle.handle))
1253 }
1254
1255 unsafe fn dec_ref(handle: &Self) {
1256 BNFreeNamedTypeReference(handle.handle)
1257 }
1258}
1259
1260impl Debug for NamedTypeReference {
1261 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1262 write!(f, "{} (id: {})", self.name(), self.id())
1263 }
1264}
1265
1266#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1267pub struct QualifiedNameAndType {
1268 pub name: QualifiedName,
1269 pub ty: Ref<Type>,
1270}
1271
1272impl QualifiedNameAndType {
1273 pub(crate) fn from_raw(value: &BNQualifiedNameAndType) -> Self {
1274 Self {
1275 name: QualifiedName::from_raw(&value.name),
1276 ty: unsafe { Type::from_raw(value.type_).to_owned() },
1277 }
1278 }
1279
1280 pub(crate) fn from_owned_raw(value: BNQualifiedNameAndType) -> Self {
1281 let owned = Self::from_raw(&value);
1282 Self::free_raw(value);
1283 owned
1284 }
1285
1286 pub(crate) fn into_raw(value: Self) -> BNQualifiedNameAndType {
1287 BNQualifiedNameAndType {
1288 name: QualifiedName::into_raw(value.name),
1289 type_: unsafe { Ref::into_raw(value.ty).handle },
1290 }
1291 }
1292
1293 pub(crate) fn free_raw(value: BNQualifiedNameAndType) {
1294 QualifiedName::free_raw(value.name);
1295 let _ = unsafe { Type::ref_from_raw(value.type_) };
1296 }
1297
1298 pub fn new(name: QualifiedName, ty: Ref<Type>) -> Self {
1299 Self { name, ty }
1300 }
1301}
1302
1303impl<T> From<(T, Ref<Type>)> for QualifiedNameAndType
1304where
1305 T: Into<QualifiedName>,
1306{
1307 fn from(value: (T, Ref<Type>)) -> Self {
1308 Self {
1309 name: value.0.into(),
1310 ty: value.1,
1311 }
1312 }
1313}
1314
1315impl<T> From<(T, &Type)> for QualifiedNameAndType
1316where
1317 T: Into<QualifiedName>,
1318{
1319 fn from(value: (T, &Type)) -> Self {
1320 let ty = value.1.to_owned();
1321 Self {
1322 name: value.0.into(),
1323 ty,
1324 }
1325 }
1326}
1327
1328impl CoreArrayProvider for QualifiedNameAndType {
1329 type Raw = BNQualifiedNameAndType;
1330 type Context = ();
1331 type Wrapped<'a> = Self;
1332}
1333
1334unsafe impl CoreArrayProviderInner for QualifiedNameAndType {
1335 unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
1336 BNFreeTypeAndNameList(raw, count);
1337 }
1338
1339 unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
1340 QualifiedNameAndType::from_raw(raw)
1341 }
1342}
1343
1344#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1345pub struct QualifiedNameTypeAndId {
1346 pub name: QualifiedName,
1347 pub ty: Ref<Type>,
1348 pub id: String,
1349}
1350
1351impl QualifiedNameTypeAndId {
1352 pub(crate) fn from_raw(value: &BNQualifiedNameTypeAndId) -> Self {
1353 Self {
1354 name: QualifiedName::from_raw(&value.name),
1355 ty: unsafe { Type::from_raw(value.type_) }.to_owned(),
1356 id: raw_to_string(value.id).unwrap(),
1357 }
1358 }
1359
1360 #[allow(unused)]
1361 pub(crate) fn from_owned_raw(value: BNQualifiedNameTypeAndId) -> Self {
1362 let owned = Self::from_raw(&value);
1363 Self::free_raw(value);
1364 owned
1365 }
1366
1367 pub(crate) fn into_raw(value: Self) -> BNQualifiedNameTypeAndId {
1368 let bn_id = BnString::new(value.id);
1369 BNQualifiedNameTypeAndId {
1370 name: QualifiedName::into_raw(value.name),
1371 id: BnString::into_raw(bn_id),
1372 type_: unsafe { Ref::into_raw(value.ty) }.handle,
1373 }
1374 }
1375
1376 pub(crate) fn free_raw(value: BNQualifiedNameTypeAndId) {
1377 QualifiedName::free_raw(value.name);
1378 let _ = unsafe { Type::ref_from_raw(value.type_) };
1379 let _ = unsafe { BnString::from_raw(value.id) };
1380 }
1381}
1382
1383impl CoreArrayProvider for QualifiedNameTypeAndId {
1384 type Raw = BNQualifiedNameTypeAndId;
1385 type Context = ();
1386 type Wrapped<'a> = QualifiedNameTypeAndId;
1387}
1388
1389unsafe impl CoreArrayProviderInner for QualifiedNameTypeAndId {
1390 unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
1391 BNFreeTypeIdList(raw, count);
1392 }
1393
1394 unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
1395 QualifiedNameTypeAndId::from_raw(raw)
1396 }
1397}
1398
1399#[derive(Debug, Clone, Eq, PartialEq, Hash)]
1404pub struct NameAndType {
1405 pub name: String,
1406 pub ty: Conf<Ref<Type>>,
1407}
1408
1409impl NameAndType {
1410 pub(crate) fn from_raw(value: &BNNameAndType) -> Self {
1411 Self {
1412 name: raw_to_string(value.name as *mut _).unwrap(),
1414 ty: Conf::new(
1415 unsafe { Type::from_raw(value.type_).to_owned() },
1416 value.typeConfidence,
1417 ),
1418 }
1419 }
1420
1421 #[allow(unused)]
1422 pub(crate) fn from_owned_raw(value: BNNameAndType) -> Self {
1423 let owned = Self::from_raw(&value);
1424 Self::free_raw(value);
1425 owned
1426 }
1427
1428 pub(crate) fn into_raw(value: Self) -> BNNameAndType {
1429 let bn_name = BnString::new(value.name);
1430 BNNameAndType {
1431 name: BnString::into_raw(bn_name),
1432 type_: unsafe { Ref::into_raw(value.ty.contents) }.handle,
1433 typeConfidence: value.ty.confidence,
1434 }
1435 }
1436
1437 pub(crate) fn free_raw(value: BNNameAndType) {
1438 unsafe { BnString::free_raw(value.name) };
1439 let _ = unsafe { Type::ref_from_raw(value.type_) };
1440 }
1441
1442 pub fn new(name: impl Into<String>, ty: Conf<Ref<Type>>) -> Self {
1443 Self {
1444 name: name.into(),
1445 ty,
1446 }
1447 }
1448}
1449
1450impl CoreArrayProvider for NameAndType {
1451 type Raw = BNNameAndType;
1452 type Context = ();
1453 type Wrapped<'a> = Self;
1454}
1455
1456unsafe impl CoreArrayProviderInner for NameAndType {
1457 unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
1458 BNFreeNameAndTypeList(raw, count);
1459 }
1460
1461 unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
1462 NameAndType::from_raw(raw)
1463 }
1464}