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, Register, RegisterId},
39 binary_view::BinaryView,
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 set_integer_display_type(&self, display_type: IntegerDisplayType) -> &Self {
175 unsafe { BNSetIntegerTypeDisplayType(self.handle, display_type) };
176 self
177 }
178
179 pub fn type_class(&self) -> TypeClass {
182 unsafe { BNGetTypeBuilderClass(self.handle) }
183 }
184
185 pub fn width(&self) -> u64 {
186 unsafe { BNGetTypeBuilderWidth(self.handle) }
187 }
188
189 pub fn alignment(&self) -> usize {
190 unsafe { BNGetTypeBuilderAlignment(self.handle) }
191 }
192
193 pub fn is_signed(&self) -> Conf<bool> {
194 unsafe { BNIsTypeBuilderSigned(self.handle).into() }
195 }
196
197 pub fn integer_display_type(&self) -> IntegerDisplayType {
198 self.finalize().integer_display_type()
199 }
200
201 pub fn is_const(&self) -> Conf<bool> {
202 unsafe { BNIsTypeBuilderConst(self.handle).into() }
203 }
204
205 pub fn is_volatile(&self) -> Conf<bool> {
206 unsafe { BNIsTypeBuilderVolatile(self.handle).into() }
207 }
208
209 pub fn is_floating_point(&self) -> bool {
210 unsafe { BNIsTypeBuilderFloatingPoint(self.handle) }
211 }
212
213 pub fn child_type(&self) -> Option<Conf<Ref<Type>>> {
214 let raw_target = unsafe { BNGetTypeBuilderChildType(self.handle) };
215 match raw_target.type_.is_null() {
216 false => Some(Conf::<Ref<Type>>::from_owned_raw(raw_target)),
217 true => None,
218 }
219 }
220
221 pub fn target(&self) -> Option<Conf<Ref<Type>>> {
223 self.child_type()
224 }
225
226 pub fn element_type(&self) -> Option<Conf<Ref<Type>>> {
228 self.child_type()
229 }
230
231 pub fn return_value(&self) -> Option<Conf<Ref<Type>>> {
233 self.child_type()
234 }
235
236 pub fn calling_convention(&self) -> Option<Conf<Ref<CoreCallingConvention>>> {
237 let raw_convention_confidence = unsafe { BNGetTypeBuilderCallingConvention(self.handle) };
238 match raw_convention_confidence.convention.is_null() {
239 false => Some(Conf::<Ref<CoreCallingConvention>>::from_owned_raw(
240 raw_convention_confidence,
241 )),
242 true => None,
243 }
244 }
245
246 pub fn parameters(&self) -> Option<Vec<FunctionParameter>> {
247 unsafe {
248 let mut count = 0;
249 let raw_parameters_ptr = BNGetTypeBuilderParameters(self.handle, &mut count);
250 match raw_parameters_ptr.is_null() {
251 false => {
252 let raw_parameters = std::slice::from_raw_parts(raw_parameters_ptr, count);
253 let parameters = raw_parameters
254 .iter()
255 .map(FunctionParameter::from_raw)
256 .collect();
257 BNFreeTypeParameterList(raw_parameters_ptr, count);
258 Some(parameters)
259 }
260 true => None,
261 }
262 }
263 }
264
265 pub fn has_variable_arguments(&self) -> Conf<bool> {
266 unsafe { BNTypeBuilderHasVariableArguments(self.handle).into() }
267 }
268
269 pub fn can_return(&self) -> Conf<bool> {
270 unsafe { BNFunctionTypeBuilderCanReturn(self.handle).into() }
271 }
272
273 pub fn pure(&self) -> Conf<bool> {
274 unsafe { BNIsTypeBuilderPure(self.handle).into() }
275 }
276
277 pub fn get_structure(&self) -> Option<Ref<Structure>> {
280 let raw_struct_ptr = unsafe { BNGetTypeBuilderStructure(self.handle) };
281 match raw_struct_ptr.is_null() {
282 false => Some(unsafe { Structure::ref_from_raw(raw_struct_ptr) }),
283 true => None,
284 }
285 }
286
287 pub fn get_enumeration(&self) -> Option<Ref<Enumeration>> {
290 let raw_enum_ptr = unsafe { BNGetTypeBuilderEnumeration(self.handle) };
291 match raw_enum_ptr.is_null() {
292 false => Some(unsafe { Enumeration::ref_from_raw(raw_enum_ptr) }),
293 true => None,
294 }
295 }
296
297 pub fn get_named_type_reference(&self) -> Option<Ref<NamedTypeReference>> {
300 let raw_type_ref_ptr = unsafe { BNGetTypeBuilderNamedTypeReference(self.handle) };
301 match raw_type_ref_ptr.is_null() {
302 false => Some(unsafe { NamedTypeReference::ref_from_raw(raw_type_ref_ptr) }),
303 true => None,
304 }
305 }
306
307 pub fn count(&self) -> u64 {
308 unsafe { BNGetTypeBuilderElementCount(self.handle) }
309 }
310
311 pub fn offset(&self) -> u64 {
312 unsafe { BNGetTypeBuilderOffset(self.handle) }
313 }
314
315 pub fn stack_adjustment(&self) -> Conf<i64> {
316 unsafe { BNGetTypeBuilderStackAdjustment(self.handle).into() }
317 }
318
319 pub fn pointer_base_type(&self) -> PointerBaseType {
320 unsafe { BNTypeBuilderGetPointerBaseType(self.handle) }
321 }
322
323 pub fn pointer_base_offset(&self) -> i64 {
324 unsafe { BNTypeBuilderGetPointerBaseOffset(self.handle) }
325 }
326
327 pub fn void() -> Self {
332 unsafe { Self::from_raw(BNCreateVoidTypeBuilder()) }
333 }
334
335 pub fn bool() -> Self {
337 unsafe { Self::from_raw(BNCreateBoolTypeBuilder()) }
338 }
339
340 pub fn char() -> Self {
342 Self::int(1, true)
343 }
344
345 pub fn int(width: usize, is_signed: bool) -> Self {
347 let mut is_signed = Conf::new(is_signed, MAX_CONFIDENCE).into();
348
349 unsafe {
350 Self::from_raw(BNCreateIntegerTypeBuilder(
351 width,
352 &mut is_signed,
353 c"".as_ptr() as _,
354 ))
355 }
356 }
357
358 pub fn named_int(width: usize, is_signed: bool, alt_name: &str) -> Self {
361 let mut is_signed = Conf::new(is_signed, MAX_CONFIDENCE).into();
362 let alt_name = alt_name.to_cstr();
363
364 unsafe {
365 Self::from_raw(BNCreateIntegerTypeBuilder(
366 width,
367 &mut is_signed,
368 alt_name.as_ref().as_ptr() as _,
369 ))
370 }
371 }
372
373 pub fn float(width: usize) -> Self {
375 unsafe { Self::from_raw(BNCreateFloatTypeBuilder(width, c"".as_ptr())) }
376 }
377
378 pub fn named_float(width: usize, alt_name: &str) -> Self {
380 let alt_name = alt_name.to_cstr();
381 unsafe { Self::from_raw(BNCreateFloatTypeBuilder(width, alt_name.as_ptr())) }
382 }
383
384 pub fn array<'a, T: Into<Conf<&'a Type>>>(ty: T, count: u64) -> Self {
386 let owned_raw_ty = Conf::<&Type>::into_raw(ty.into());
387 unsafe { Self::from_raw(BNCreateArrayTypeBuilder(&owned_raw_ty, count)) }
388 }
389
390 pub fn enumeration<T: Into<Conf<bool>>>(
398 enumeration: &Enumeration,
399 width: NonZeroUsize,
400 is_signed: T,
401 ) -> Self {
402 unsafe {
403 Self::from_raw(BNCreateEnumerationTypeBuilder(
404 std::ptr::null_mut(),
406 enumeration.handle,
407 width.get(),
408 &mut is_signed.into().into(),
409 ))
410 }
411 }
412
413 pub fn structure(structure_type: &Structure) -> Self {
415 unsafe { Self::from_raw(BNCreateStructureTypeBuilder(structure_type.handle)) }
416 }
417
418 pub fn named_type(type_reference: &NamedTypeReference) -> Self {
420 let mut is_const = Conf::new(false, MIN_CONFIDENCE).into();
421 let mut is_volatile = Conf::new(false, MIN_CONFIDENCE).into();
422 unsafe {
423 Self::from_raw(BNCreateNamedTypeReferenceBuilder(
424 type_reference.handle,
425 0,
426 1,
427 &mut is_const,
428 &mut is_volatile,
429 ))
430 }
431 }
432
433 pub fn named_type_from_type<T: Into<QualifiedName>>(name: T, t: &Type) -> Self {
435 let mut raw_name = QualifiedName::into_raw(name.into());
436 let id = c"";
437
438 let result = unsafe {
439 Self::from_raw(BNCreateNamedTypeReferenceBuilderFromTypeAndId(
440 id.as_ptr() as *mut _,
441 &mut raw_name,
442 t.handle,
443 ))
444 };
445 QualifiedName::free_raw(raw_name);
446 result
447 }
448
449 pub fn function<T: Into<ReturnValue>>(
453 return_value: T,
454 parameters: Vec<FunctionParameter>,
455 variable_arguments: bool,
456 ) -> Self {
457 let mut owned_raw_return_value = ReturnValue::into_rust_raw(&return_value.into());
458 let mut variable_arguments = Conf::new(variable_arguments, MAX_CONFIDENCE).into();
459 let mut can_return = Conf::new(true, MIN_CONFIDENCE).into();
460 let mut pure = Conf::new(false, MIN_CONFIDENCE).into();
461
462 let mut raw_calling_convention: BNCallingConventionWithConfidence =
463 BNCallingConventionWithConfidence {
464 convention: std::ptr::null_mut(),
465 confidence: MIN_CONFIDENCE,
466 };
467
468 let mut stack_adjust = Conf::new(0, MIN_CONFIDENCE).into();
469 let mut raw_parameters = parameters
470 .into_iter()
471 .map(FunctionParameter::into_raw)
472 .collect::<Vec<_>>();
473 let reg_stack_adjust_regs = std::ptr::null_mut();
474 let reg_stack_adjust_values = std::ptr::null_mut();
475
476 let result = unsafe {
477 Self::from_raw(BNCreateFunctionTypeBuilder(
478 &mut owned_raw_return_value,
479 &mut raw_calling_convention,
480 raw_parameters.as_mut_ptr(),
481 raw_parameters.len(),
482 &mut variable_arguments,
483 &mut can_return,
484 &mut stack_adjust,
485 reg_stack_adjust_regs,
486 reg_stack_adjust_values,
487 0,
488 BNNameType::NoNameType,
489 &mut pure,
490 ))
491 };
492
493 for raw_param in raw_parameters {
494 FunctionParameter::free_raw(raw_param);
495 }
496
497 result
498 }
499
500 pub fn function_with_opts<T: Into<ReturnValue>, C: Into<Conf<Ref<CoreCallingConvention>>>>(
504 return_value: T,
505 parameters: &[FunctionParameter],
506 variable_arguments: bool,
507 calling_convention: C,
508 stack_adjust: Conf<i64>,
509 ) -> Self {
510 let mut owned_raw_return_value = ReturnValue::into_rust_raw(&return_value.into());
511 let mut variable_arguments = Conf::new(variable_arguments, MAX_CONFIDENCE).into();
512 let mut can_return = Conf::new(true, MIN_CONFIDENCE).into();
513 let mut pure = Conf::new(false, MIN_CONFIDENCE).into();
514
515 let mut owned_raw_calling_convention =
516 Conf::<Ref<CoreCallingConvention>>::into_owned_raw(&calling_convention.into());
517
518 let mut stack_adjust = stack_adjust.into();
519 let mut raw_parameters = parameters
520 .iter()
521 .cloned()
522 .map(FunctionParameter::into_raw)
523 .collect::<Vec<_>>();
524
525 let reg_stack_adjust_regs = std::ptr::null_mut();
527 let reg_stack_adjust_values = std::ptr::null_mut();
528
529 let result = unsafe {
530 Self::from_raw(BNCreateFunctionTypeBuilder(
531 &mut owned_raw_return_value,
532 &mut owned_raw_calling_convention,
533 raw_parameters.as_mut_ptr(),
534 raw_parameters.len(),
535 &mut variable_arguments,
536 &mut can_return,
537 &mut stack_adjust,
538 reg_stack_adjust_regs,
539 reg_stack_adjust_values,
540 0,
541 BNNameType::NoNameType,
542 &mut pure,
543 ))
544 };
545
546 for raw_param in raw_parameters {
547 FunctionParameter::free_raw(raw_param);
548 }
549
550 result
551 }
552
553 pub fn pointer<'a, A: Architecture, T: Into<Conf<&'a Type>>>(arch: &A, ty: T) -> Self {
555 Self::pointer_with_options(arch, ty, false, false, None)
556 }
557
558 pub fn const_pointer<'a, A: Architecture, T: Into<Conf<&'a Type>>>(arch: &A, ty: T) -> Self {
560 Self::pointer_with_options(arch, ty, true, false, None)
561 }
562
563 pub fn pointer_with_options<'a, A: Architecture, T: Into<Conf<&'a Type>>>(
564 arch: &A,
565 ty: T,
566 is_const: bool,
567 is_volatile: bool,
568 ref_type: Option<ReferenceType>,
569 ) -> Self {
570 let arch_ptr_size = arch.address_size();
571 Self::pointer_of_width(ty, arch_ptr_size, is_const, is_volatile, ref_type)
572 }
573
574 pub fn pointer_of_width<'a, T: Into<Conf<&'a Type>>>(
575 ty: T,
576 size: usize,
577 is_const: bool,
578 is_volatile: bool,
579 ref_type: Option<ReferenceType>,
580 ) -> Self {
581 let mut is_const = Conf::new(is_const, MAX_CONFIDENCE).into();
582 let mut is_volatile = Conf::new(is_volatile, MAX_CONFIDENCE).into();
583 let owned_raw_ty = Conf::<&Type>::into_raw(ty.into());
584 unsafe {
585 Self::from_raw(BNCreatePointerTypeBuilderOfWidth(
586 size,
587 &owned_raw_ty,
588 &mut is_const,
589 &mut is_volatile,
590 ref_type.unwrap_or(ReferenceType::PointerReferenceType),
591 ))
592 }
593 }
594}
595
596impl Display for TypeBuilder {
597 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
598 write!(f, "{}", unsafe {
599 BnString::into_string(BNGetTypeBuilderString(self.handle, std::ptr::null_mut()))
600 })
601 }
602}
603
604impl Drop for TypeBuilder {
605 fn drop(&mut self) {
606 unsafe { BNFreeTypeBuilder(self.handle) };
607 }
608}
609
610#[repr(transparent)]
645pub struct Type {
646 pub handle: *mut BNType,
647}
648
649impl Type {
650 pub unsafe fn from_raw(handle: *mut BNType) -> Self {
651 debug_assert!(!handle.is_null());
652 Self { handle }
653 }
654
655 pub unsafe fn ref_from_raw(handle: *mut BNType) -> Ref<Self> {
656 debug_assert!(!handle.is_null());
657 Ref::new(Self { handle })
658 }
659
660 pub fn to_builder(&self) -> TypeBuilder {
661 TypeBuilder::new(self)
662 }
663
664 pub fn type_class(&self) -> TypeClass {
665 unsafe { BNGetTypeClass(self.handle) }
666 }
667
668 pub fn width(&self) -> u64 {
672 unsafe { BNGetTypeWidth(self.handle) }
673 }
674
675 pub fn alignment(&self) -> usize {
676 unsafe { BNGetTypeAlignment(self.handle) }
677 }
678
679 pub fn is_signed(&self) -> Conf<bool> {
680 unsafe { BNIsTypeSigned(self.handle).into() }
681 }
682
683 pub fn integer_display_type(&self) -> IntegerDisplayType {
684 unsafe { BNGetIntegerTypeDisplayType(self.handle) }
685 }
686
687 pub fn is_const(&self) -> Conf<bool> {
688 unsafe { BNIsTypeConst(self.handle).into() }
689 }
690
691 pub fn is_volatile(&self) -> Conf<bool> {
692 unsafe { BNIsTypeVolatile(self.handle).into() }
693 }
694
695 pub fn is_floating_point(&self) -> bool {
696 unsafe { BNIsTypeFloatingPoint(self.handle) }
697 }
698
699 pub fn child_type(&self) -> Option<Conf<Ref<Type>>> {
700 let raw_target = unsafe { BNGetChildType(self.handle) };
701 match raw_target.type_.is_null() {
702 false => Some(Conf::<Ref<Type>>::from_owned_raw(raw_target)),
703 true => None,
704 }
705 }
706
707 pub fn target(&self) -> Option<Conf<Ref<Type>>> {
709 self.child_type()
710 }
711
712 pub fn element_type(&self) -> Option<Conf<Ref<Type>>> {
714 self.child_type()
715 }
716
717 pub fn return_value(&self) -> Option<Conf<Ref<Type>>> {
719 self.child_type()
720 }
721
722 pub fn calling_convention(&self) -> Option<Conf<Ref<CoreCallingConvention>>> {
723 let convention_confidence = unsafe { BNGetTypeCallingConvention(self.handle) };
724 match convention_confidence.convention.is_null() {
725 false => Some(Conf::<Ref<CoreCallingConvention>>::from_owned_raw(
726 convention_confidence,
727 )),
728 true => None,
729 }
730 }
731
732 pub fn parameters(&self) -> Option<Vec<FunctionParameter>> {
733 unsafe {
734 let mut count = 0;
735 let raw_parameters_ptr = BNGetTypeParameters(self.handle, &mut count);
736 match raw_parameters_ptr.is_null() {
737 false => {
738 let raw_parameters = std::slice::from_raw_parts(raw_parameters_ptr, count);
739 let parameters = raw_parameters
740 .iter()
741 .map(FunctionParameter::from_raw)
742 .collect();
743 BNFreeTypeParameterList(raw_parameters_ptr, count);
744 Some(parameters)
745 }
746 true => None,
747 }
748 }
749 }
750
751 pub fn has_variable_arguments(&self) -> Conf<bool> {
752 unsafe { BNTypeHasVariableArguments(self.handle).into() }
753 }
754
755 pub fn can_return(&self) -> Conf<bool> {
756 unsafe { BNFunctionTypeCanReturn(self.handle).into() }
757 }
758
759 pub fn pure(&self) -> Conf<bool> {
760 unsafe { BNIsTypePure(self.handle).into() }
761 }
762
763 pub fn get_structure(&self) -> Option<Ref<Structure>> {
766 let raw_struct_ptr = unsafe { BNGetTypeStructure(self.handle) };
767 match raw_struct_ptr.is_null() {
768 false => Some(unsafe { Structure::ref_from_raw(raw_struct_ptr) }),
769 true => None,
770 }
771 }
772
773 pub fn get_enumeration(&self) -> Option<Ref<Enumeration>> {
776 let raw_enum_ptr = unsafe { BNGetTypeEnumeration(self.handle) };
777 match raw_enum_ptr.is_null() {
778 false => Some(unsafe { Enumeration::ref_from_raw(raw_enum_ptr) }),
779 true => None,
780 }
781 }
782
783 pub fn get_named_type_reference(&self) -> Option<Ref<NamedTypeReference>> {
786 let raw_type_ref_ptr = unsafe { BNGetTypeNamedTypeReference(self.handle) };
787 match raw_type_ref_ptr.is_null() {
788 false => Some(unsafe { NamedTypeReference::ref_from_raw(raw_type_ref_ptr) }),
789 true => None,
790 }
791 }
792
793 pub fn count(&self) -> u64 {
794 unsafe { BNGetTypeElementCount(self.handle) }
795 }
796
797 pub fn offset(&self) -> u64 {
798 unsafe { BNGetTypeOffset(self.handle) }
799 }
800
801 pub fn stack_adjustment(&self) -> Conf<i64> {
802 unsafe { BNGetTypeStackAdjustment(self.handle).into() }
803 }
804
805 pub fn registered_name(&self) -> Option<Ref<NamedTypeReference>> {
806 let raw_type_ref_ptr = unsafe { BNGetRegisteredTypeName(self.handle) };
807 match raw_type_ref_ptr.is_null() {
808 false => Some(unsafe { NamedTypeReference::ref_from_raw(raw_type_ref_ptr) }),
809 true => None,
810 }
811 }
812
813 pub fn pointer_base_type(&self) -> BNPointerBaseType {
814 unsafe { BNTypeGetPointerBaseType(self.handle) }
815 }
816
817 pub fn pointer_base_offset(&self) -> i64 {
818 unsafe { BNTypeGetPointerBaseOffset(self.handle) }
819 }
820
821 pub fn void() -> Ref<Self> {
825 unsafe { Self::ref_from_raw(BNCreateVoidType()) }
826 }
827
828 pub fn bool() -> Ref<Self> {
829 unsafe { Self::ref_from_raw(BNCreateBoolType()) }
830 }
831
832 pub fn char() -> Ref<Self> {
833 Self::int(1, true)
834 }
835
836 pub fn wide_char(width: usize) -> Ref<Self> {
837 unsafe { Self::ref_from_raw(BNCreateWideCharType(width, c"".as_ptr())) }
838 }
839
840 pub fn int(width: usize, is_signed: bool) -> Ref<Self> {
841 let mut is_signed = Conf::new(is_signed, MAX_CONFIDENCE).into();
842 unsafe { Self::ref_from_raw(BNCreateIntegerType(width, &mut is_signed, c"".as_ptr())) }
843 }
844
845 pub fn named_int(width: usize, is_signed: bool, alt_name: &str) -> Ref<Self> {
846 let mut is_signed = Conf::new(is_signed, MAX_CONFIDENCE).into();
847 let alt_name = alt_name.to_cstr();
848
849 unsafe {
850 Self::ref_from_raw(BNCreateIntegerType(
851 width,
852 &mut is_signed,
853 alt_name.as_ptr(),
854 ))
855 }
856 }
857
858 pub fn float(width: usize) -> Ref<Self> {
859 unsafe { Self::ref_from_raw(BNCreateFloatType(width, c"".as_ptr())) }
860 }
861
862 pub fn named_float(width: usize, alt_name: &str) -> Ref<Self> {
863 let alt_name = alt_name.to_cstr();
864 unsafe { Self::ref_from_raw(BNCreateFloatType(width, alt_name.as_ptr())) }
865 }
866
867 pub fn array<'a, T: Into<Conf<&'a Type>>>(ty: T, count: u64) -> Ref<Self> {
868 let owned_raw_ty = Conf::<&Type>::into_raw(ty.into());
869 unsafe { Self::ref_from_raw(BNCreateArrayType(&owned_raw_ty, count)) }
870 }
871
872 pub fn enumeration<T: Into<Conf<bool>>>(
878 enumeration: &Enumeration,
879 width: NonZeroUsize,
880 is_signed: T,
881 ) -> Ref<Self> {
882 unsafe {
883 Self::ref_from_raw(BNCreateEnumerationType(
884 std::ptr::null_mut(),
886 enumeration.handle,
887 width.get(),
888 &mut is_signed.into().into(),
889 ))
890 }
891 }
892
893 pub fn structure(structure: &Structure) -> Ref<Self> {
894 unsafe { Self::ref_from_raw(BNCreateStructureType(structure.handle)) }
895 }
896
897 pub fn named_type(type_reference: &NamedTypeReference) -> Ref<Self> {
898 let mut is_const = Conf::new(false, MIN_CONFIDENCE).into();
899 let mut is_volatile = Conf::new(false, MIN_CONFIDENCE).into();
900 unsafe {
901 Self::ref_from_raw(BNCreateNamedTypeReference(
902 type_reference.handle,
903 0,
904 1,
905 &mut is_const,
906 &mut is_volatile,
907 ))
908 }
909 }
910
911 pub fn named_type_from_type<T: Into<QualifiedName>>(name: T, t: &Type) -> Ref<Self> {
912 let mut raw_name = QualifiedName::into_raw(name.into());
913 let id = c"";
915
916 let result = unsafe {
917 Self::ref_from_raw(BNCreateNamedTypeReferenceFromTypeAndId(
918 id.as_ptr(),
919 &mut raw_name,
920 t.handle,
921 ))
922 };
923 QualifiedName::free_raw(raw_name);
924 result
925 }
926
927 pub fn function<T: Into<ReturnValue>>(
929 return_value: T,
930 parameters: Vec<FunctionParameter>,
931 variable_arguments: bool,
932 ) -> Ref<Self> {
933 let mut owned_raw_return_value = ReturnValue::into_rust_raw(&return_value.into());
934 let mut variable_arguments = Conf::new(variable_arguments, MAX_CONFIDENCE).into();
935 let mut can_return = Conf::new(true, MIN_CONFIDENCE).into();
936 let mut pure = Conf::new(false, MIN_CONFIDENCE).into();
937
938 let mut raw_calling_convention: BNCallingConventionWithConfidence =
939 BNCallingConventionWithConfidence {
940 convention: std::ptr::null_mut(),
941 confidence: MIN_CONFIDENCE,
942 };
943
944 let mut stack_adjust = Conf::new(0, MIN_CONFIDENCE).into();
945 let mut raw_parameters = parameters
946 .into_iter()
947 .map(FunctionParameter::into_raw)
948 .collect::<Vec<_>>();
949 let reg_stack_adjust_regs = std::ptr::null_mut();
950 let reg_stack_adjust_values = std::ptr::null_mut();
951
952 let result = unsafe {
953 Self::ref_from_raw(BNCreateFunctionType(
954 &mut owned_raw_return_value,
955 &mut raw_calling_convention,
956 raw_parameters.as_mut_ptr(),
957 raw_parameters.len(),
958 &mut variable_arguments,
959 &mut can_return,
960 &mut stack_adjust,
961 reg_stack_adjust_regs,
962 reg_stack_adjust_values,
963 0,
964 BNNameType::NoNameType,
965 &mut pure,
966 ))
967 };
968
969 ReturnValue::free_rust_raw(owned_raw_return_value);
970 for raw_param in raw_parameters {
971 FunctionParameter::free_raw(raw_param);
972 }
973
974 result
975 }
976
977 pub fn function_with_opts<T: Into<ReturnValue>, C: Into<Conf<Ref<CoreCallingConvention>>>>(
979 return_value: T,
980 parameters: &[FunctionParameter],
981 variable_arguments: bool,
982 calling_convention: C,
983 stack_adjust: Conf<i64>,
984 ) -> Ref<Self> {
985 let mut owned_raw_return_value = ReturnValue::into_rust_raw(&return_value.into());
986 let mut variable_arguments = Conf::new(variable_arguments, MAX_CONFIDENCE).into();
987 let mut can_return = Conf::new(true, MIN_CONFIDENCE).into();
988 let mut pure = Conf::new(false, MIN_CONFIDENCE).into();
989
990 let mut owned_raw_calling_convention =
991 Conf::<Ref<CoreCallingConvention>>::into_owned_raw(&calling_convention.into());
992
993 let mut stack_adjust = stack_adjust.into();
994 let mut raw_parameters = parameters
995 .iter()
996 .cloned()
997 .map(FunctionParameter::into_raw)
998 .collect::<Vec<_>>();
999
1000 let reg_stack_adjust_regs = std::ptr::null_mut();
1002 let reg_stack_adjust_values = std::ptr::null_mut();
1003
1004 let result = unsafe {
1005 Self::ref_from_raw(BNCreateFunctionType(
1006 &mut owned_raw_return_value,
1007 &mut owned_raw_calling_convention,
1008 raw_parameters.as_mut_ptr(),
1009 raw_parameters.len(),
1010 &mut variable_arguments,
1011 &mut can_return,
1012 &mut stack_adjust,
1013 reg_stack_adjust_regs,
1014 reg_stack_adjust_values,
1015 0,
1016 BNNameType::NoNameType,
1017 &mut pure,
1018 ))
1019 };
1020
1021 ReturnValue::free_rust_raw(owned_raw_return_value);
1022 for raw_param in raw_parameters {
1023 FunctionParameter::free_raw(raw_param);
1024 }
1025
1026 result
1027 }
1028
1029 pub fn pointer<'a, A: Architecture, T: Into<Conf<&'a Type>>>(arch: &A, ty: T) -> Ref<Self> {
1030 Self::pointer_with_options(arch, ty, false, false, None)
1031 }
1032
1033 pub fn const_pointer<'a, A: Architecture, T: Into<Conf<&'a Type>>>(
1034 arch: &A,
1035 ty: T,
1036 ) -> Ref<Self> {
1037 Self::pointer_with_options(arch, ty, true, false, None)
1038 }
1039
1040 pub fn pointer_with_options<'a, A: Architecture, T: Into<Conf<&'a Type>>>(
1041 arch: &A,
1042 ty: T,
1043 is_const: bool,
1044 is_volatile: bool,
1045 ref_type: Option<ReferenceType>,
1046 ) -> Ref<Self> {
1047 let arch_pointer_size = arch.address_size();
1048 Self::pointer_of_width(ty, arch_pointer_size, is_const, is_volatile, ref_type)
1049 }
1050
1051 pub fn pointer_of_width<'a, T: Into<Conf<&'a Type>>>(
1052 ty: T,
1053 size: usize,
1054 is_const: bool,
1055 is_volatile: bool,
1056 ref_type: Option<ReferenceType>,
1057 ) -> Ref<Self> {
1058 let mut is_const = Conf::new(is_const, MAX_CONFIDENCE).into();
1059 let mut is_volatile = Conf::new(is_volatile, MAX_CONFIDENCE).into();
1060 let owned_raw_ty = Conf::<&Type>::into_raw(ty.into());
1061 unsafe {
1062 Self::ref_from_raw(BNCreatePointerTypeOfWidth(
1063 size,
1064 &owned_raw_ty,
1065 &mut is_const,
1066 &mut is_volatile,
1067 ref_type.unwrap_or(ReferenceType::PointerReferenceType),
1068 ))
1069 }
1070 }
1071
1072 pub fn generate_auto_demangled_type_id<T: Into<QualifiedName>>(name: T) -> String {
1073 let mut raw_name = QualifiedName::into_raw(name.into());
1074 let type_id =
1075 unsafe { BnString::into_string(BNGenerateAutoDemangledTypeId(&mut raw_name)) };
1076 QualifiedName::free_raw(raw_name);
1077 type_id
1078 }
1079
1080 pub fn deref_named_type_reference(&self, view: &BinaryView) -> Ref<Type> {
1081 unsafe { Self::ref_from_raw(BNDerefNamedTypeReference(view.handle, self.handle)) }
1082 }
1083}
1084
1085impl Display for Type {
1086 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1087 write!(f, "{}", unsafe {
1088 BnString::into_string(BNGetTypeString(
1089 self.handle,
1090 std::ptr::null_mut(),
1091 BNTokenEscapingType::NoTokenEscapingType,
1092 ))
1093 })
1094 }
1095}
1096
1097impl Debug for Type {
1098 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1099 f.debug_struct("Type")
1104 .field("type_class", &self.type_class())
1105 .field("width", &self.width())
1106 .field("alignment", &self.alignment())
1107 .field("is_signed", &self.is_signed())
1108 .field("is_const", &self.is_const())
1109 .field("is_volatile", &self.is_volatile())
1110 .field("child_type", &self.child_type())
1111 .field("calling_convention", &self.calling_convention())
1112 .field("parameters", &self.parameters())
1113 .field("has_variable_arguments", &self.has_variable_arguments())
1114 .field("can_return", &self.can_return())
1115 .field("pure", &self.pure())
1116 .field("get_structure", &self.get_structure())
1117 .field("get_enumeration", &self.get_enumeration())
1118 .field("get_named_type_reference", &self.get_named_type_reference())
1119 .field("count", &self.count())
1120 .field("offset", &self.offset())
1121 .field("stack_adjustment", &self.stack_adjustment())
1122 .field("registered_name", &self.registered_name())
1123 .finish()
1124 }
1125}
1126
1127impl PartialEq for Type {
1128 fn eq(&self, other: &Self) -> bool {
1129 unsafe { BNTypesEqual(self.handle, other.handle) }
1130 }
1131}
1132
1133impl Eq for Type {}
1134
1135impl Hash for Type {
1136 fn hash<H: Hasher>(&self, state: &mut H) {
1137 self.handle.hash(state);
1138 }
1139}
1140
1141unsafe impl Send for Type {}
1142unsafe impl Sync for Type {}
1143
1144unsafe impl RefCountable for Type {
1145 unsafe fn inc_ref(handle: &Self) -> Ref<Self> {
1146 Self::ref_from_raw(BNNewTypeReference(handle.handle))
1147 }
1148
1149 unsafe fn dec_ref(handle: &Self) {
1150 BNFreeType(handle.handle);
1151 }
1152}
1153
1154impl ToOwned for Type {
1155 type Owned = Ref<Self>;
1156
1157 fn to_owned(&self) -> Self::Owned {
1158 unsafe { RefCountable::inc_ref(self) }
1159 }
1160}
1161
1162impl CoreArrayProvider for Type {
1163 type Raw = *mut BNType;
1164 type Context = ();
1165 type Wrapped<'a> = &'a Self;
1166}
1167
1168unsafe impl CoreArrayProviderInner for Type {
1169 unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
1170 BNFreeTypeList(raw, count)
1171 }
1172
1173 unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
1174 std::mem::transmute(raw)
1176 }
1177}
1178
1179#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1180pub struct ValueLocationComponent {
1181 pub variable: Variable,
1182 pub offset: i64,
1183 pub size: Option<u64>,
1184}
1185
1186impl ValueLocationComponent {
1187 pub(crate) fn from_raw(value: &BNValueLocationComponent) -> Self {
1188 let variable = Variable::from(&value.variable);
1189 let size = if value.sizeValid {
1190 Some(value.size)
1191 } else {
1192 None
1193 };
1194 Self {
1195 variable,
1196 offset: value.offset,
1197 size,
1198 }
1199 }
1200
1201 pub(crate) fn into_raw(value: &Self) -> BNValueLocationComponent {
1202 BNValueLocationComponent {
1203 variable: value.variable.into(),
1204 offset: value.offset,
1205 sizeValid: value.size.is_some(),
1206 size: value.size.unwrap_or(0),
1207 }
1208 }
1209}
1210
1211#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1212pub struct ValueLocation {
1213 pub components: Vec<ValueLocationComponent>,
1214 pub indirect: bool,
1215 pub returned_pointer: Option<Variable>,
1216}
1217
1218impl ValueLocation {
1219 pub fn from_variable(var: Variable) -> Self {
1220 Self {
1221 components: vec![ValueLocationComponent {
1222 variable: var,
1223 offset: 0,
1224 size: None,
1225 }],
1226 indirect: false,
1227 returned_pointer: None,
1228 }
1229 }
1230
1231 pub fn from_register(reg: impl Register) -> Self {
1232 Self::from_variable(Variable::from_register(reg))
1233 }
1234
1235 pub fn from_register_id(reg: RegisterId) -> Self {
1236 Self::from_variable(Variable::from_register_id(reg))
1237 }
1238
1239 pub fn from_stack_offset(offset: i64) -> Self {
1240 Self::from_variable(Variable::from_stack_offset(offset))
1241 }
1242
1243 pub fn is_valid(&self) -> bool {
1244 !self.components.is_empty()
1245 }
1246
1247 pub fn variable_for_return_value(&self) -> Option<Variable> {
1248 let value_raw = Self::into_rust_raw(self);
1249 let mut var_raw = BNVariable::default();
1250 let valid = unsafe { BNGetValueLocationVariableForReturnValue(&value_raw, &mut var_raw) };
1251 Self::free_rust_raw(value_raw);
1252 if valid {
1253 Some(var_raw.into())
1254 } else {
1255 None
1256 }
1257 }
1258
1259 pub fn variable_for_parameter(&self, idx: usize) -> Option<Variable> {
1260 let value_raw = Self::into_rust_raw(self);
1261 let mut var_raw = BNVariable::default();
1262 let valid =
1263 unsafe { BNGetValueLocationVariableForParameter(&value_raw, &mut var_raw, idx) };
1264 Self::free_rust_raw(value_raw);
1265 if valid {
1266 Some(var_raw.into())
1267 } else {
1268 None
1269 }
1270 }
1271
1272 pub(crate) fn from_raw(loc: &BNValueLocation) -> Self {
1273 let components_raw: &[BNValueLocationComponent] =
1274 unsafe { crate::ffi::slice_from_raw_parts(loc.components, loc.count) };
1275 Self {
1276 components: components_raw
1277 .iter()
1278 .map(ValueLocationComponent::from_raw)
1279 .collect(),
1280 indirect: loc.indirect,
1281 returned_pointer: if loc.returnedPointerValid {
1282 Some(Variable::from(&loc.returnedPointer))
1283 } else {
1284 None
1285 },
1286 }
1287 }
1288
1289 pub fn into_rust_raw(value: &Self) -> BNValueLocation {
1290 let components: Box<[BNValueLocationComponent]> = value
1291 .components
1292 .iter()
1293 .map(ValueLocationComponent::into_raw)
1294 .collect();
1295 BNValueLocation {
1296 count: components.len(),
1297 components: Box::leak(components).as_mut_ptr(),
1298 indirect: value.indirect,
1299 returnedPointerValid: value.returned_pointer.is_some(),
1300 returnedPointer: if let Some(ptr) = value.returned_pointer {
1301 ptr.into()
1302 } else {
1303 Variable::new(VariableSourceType::RegisterVariableSourceType, 0, 0).into()
1304 },
1305 }
1306 }
1307
1308 pub fn free_rust_raw(value: BNValueLocation) {
1310 let raw_components =
1311 unsafe { std::slice::from_raw_parts_mut(value.components, value.count) };
1312 let _ = unsafe { Box::from_raw(raw_components) };
1313 }
1314}
1315
1316impl From<Variable> for ValueLocation {
1317 fn from(value: Variable) -> Self {
1318 ValueLocation {
1319 components: vec![ValueLocationComponent {
1320 variable: value,
1321 offset: 0,
1322 size: None,
1323 }],
1324 indirect: false,
1325 returned_pointer: None,
1326 }
1327 }
1328}
1329
1330#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1331pub struct ReturnValue {
1332 pub ty: Conf<Ref<Type>>,
1333 pub location: Option<Conf<ValueLocation>>,
1334}
1335
1336impl ReturnValue {
1337 pub(crate) fn from_raw(value: &BNReturnValue) -> Self {
1338 Self {
1339 ty: Conf::new(
1340 unsafe { Type::from_raw(value.type_).to_owned() },
1341 value.typeConfidence,
1342 ),
1343 location: match value.defaultLocation {
1344 false => Some(Conf::new(
1345 ValueLocation::from_raw(&value.location),
1346 value.locationConfidence,
1347 )),
1348 true => None,
1349 },
1350 }
1351 }
1352
1353 pub(crate) fn from_owned_core_raw(mut value: BNReturnValue) -> Self {
1355 let owned = Self::from_raw(&value);
1356 Self::free_core_raw(&mut value);
1357 owned
1358 }
1359
1360 pub(crate) fn into_rust_raw(value: &Self) -> BNReturnValue {
1361 BNReturnValue {
1362 type_: unsafe { Ref::into_raw(value.ty.contents.clone()) }.handle,
1363 typeConfidence: value.ty.confidence,
1364 defaultLocation: value.location.is_none(),
1365 location: ValueLocation::into_rust_raw(
1366 value
1367 .location
1368 .as_ref()
1369 .map(|v| &v.contents)
1370 .unwrap_or(&ValueLocation {
1371 components: Vec::new(),
1372 indirect: false,
1373 returned_pointer: None,
1374 }),
1375 ),
1376 locationConfidence: value.location.as_ref().map(|v| v.confidence).unwrap_or(0),
1377 }
1378 }
1379
1380 pub(crate) fn free_core_raw(value: &mut BNReturnValue) {
1382 unsafe { BNFreeReturnValue(value) }
1383 }
1384
1385 pub(crate) fn free_rust_raw(value: BNReturnValue) {
1387 let _ = unsafe { Type::ref_from_raw(value.type_) };
1388 ValueLocation::free_rust_raw(value.location);
1389 }
1390}
1391
1392impl From<Ref<Type>> for ReturnValue {
1393 fn from(value: Ref<Type>) -> ReturnValue {
1394 ReturnValue {
1395 ty: value.into(),
1396 location: None,
1397 }
1398 }
1399}
1400
1401impl From<&Ref<Type>> for ReturnValue {
1402 fn from(value: &Ref<Type>) -> ReturnValue {
1403 ReturnValue {
1404 ty: value.clone().into(),
1405 location: None,
1406 }
1407 }
1408}
1409
1410impl From<&Type> for ReturnValue {
1411 fn from(value: &Type) -> ReturnValue {
1412 ReturnValue {
1413 ty: value.to_owned().into(),
1414 location: None,
1415 }
1416 }
1417}
1418
1419impl From<Conf<Ref<Type>>> for ReturnValue {
1420 fn from(value: Conf<Ref<Type>>) -> ReturnValue {
1421 ReturnValue {
1422 ty: value,
1423 location: None,
1424 }
1425 }
1426}
1427
1428impl From<&Conf<Ref<Type>>> for ReturnValue {
1429 fn from(value: &Conf<Ref<Type>>) -> ReturnValue {
1430 ReturnValue {
1431 ty: value.clone(),
1432 location: None,
1433 }
1434 }
1435}
1436
1437#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1438pub enum ValueLocationSource {
1439 Default,
1440 PassByValue,
1441 PassByReference,
1442 Custom(ValueLocation),
1443}
1444
1445impl From<Option<ValueLocation>> for ValueLocationSource {
1446 fn from(loc: Option<ValueLocation>) -> Self {
1447 match loc {
1448 Some(loc) => ValueLocationSource::Custom(loc),
1449 None => ValueLocationSource::Default,
1450 }
1451 }
1452}
1453
1454#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1455pub struct FunctionParameter {
1456 pub ty: Conf<Ref<Type>>,
1457 pub name: String,
1458 pub location: ValueLocationSource,
1459}
1460
1461impl FunctionParameter {
1462 pub(crate) fn from_raw(value: &BNFunctionParameter) -> Self {
1463 let name = if value.name.is_null() {
1466 String::new()
1467 } else {
1468 raw_to_string(value.name as *const _).unwrap()
1469 };
1470
1471 Self {
1472 ty: Conf::new(
1473 unsafe { Type::from_raw(value.type_).to_owned() },
1474 value.typeConfidence,
1475 ),
1476 name,
1477 location: match value.locationSource {
1478 BNValueLocationSource::DefaultLocationSource => ValueLocationSource::Default,
1479 BNValueLocationSource::PassByValueLocationSource => {
1480 ValueLocationSource::PassByValue
1481 }
1482 BNValueLocationSource::PassByReferenceLocationSource => {
1483 ValueLocationSource::PassByReference
1484 }
1485 BNValueLocationSource::CustomLocationSource => {
1486 ValueLocationSource::Custom(ValueLocation::from_raw(&value.location))
1487 }
1488 },
1489 }
1490 }
1491
1492 #[allow(unused)]
1493 pub(crate) fn from_owned_raw(value: BNFunctionParameter) -> Self {
1494 let owned = Self::from_raw(&value);
1495 Self::free_raw(value);
1496 owned
1497 }
1498
1499 pub(crate) fn into_raw(value: Self) -> BNFunctionParameter {
1500 let bn_name = BnString::new(value.name);
1501 BNFunctionParameter {
1502 name: BnString::into_raw(bn_name),
1503 type_: unsafe { Ref::into_raw(value.ty.contents) }.handle,
1504 typeConfidence: value.ty.confidence,
1505 locationSource: match value.location {
1506 ValueLocationSource::Default => BNValueLocationSource::DefaultLocationSource,
1507 ValueLocationSource::PassByValue => {
1508 BNValueLocationSource::PassByValueLocationSource
1509 }
1510 ValueLocationSource::PassByReference => {
1511 BNValueLocationSource::PassByReferenceLocationSource
1512 }
1513 ValueLocationSource::Custom(_) => BNValueLocationSource::CustomLocationSource,
1514 },
1515 location: match &value.location {
1516 ValueLocationSource::Custom(loc) => ValueLocation::into_rust_raw(loc),
1517 _ => ValueLocation::into_rust_raw(&ValueLocation {
1518 components: Vec::new(),
1519 indirect: false,
1520 returned_pointer: None,
1521 }),
1522 },
1523 }
1524 }
1525
1526 pub(crate) fn free_raw(value: BNFunctionParameter) {
1527 unsafe { BnString::free_raw(value.name) };
1528 let _ = unsafe { Type::ref_from_raw(value.type_) };
1529 ValueLocation::free_rust_raw(value.location);
1530 }
1531
1532 pub fn new<T: Into<Conf<Ref<Type>>>>(
1533 ty: T,
1534 name: String,
1535 location: impl Into<ValueLocationSource>,
1536 ) -> Self {
1537 Self {
1538 ty: ty.into(),
1539 name,
1540 location: location.into(),
1541 }
1542 }
1543}
1544
1545#[derive(PartialEq, Eq, Hash)]
1546pub struct NamedTypeReference {
1547 pub(crate) handle: *mut BNNamedTypeReference,
1548}
1549
1550impl NamedTypeReference {
1551 pub(crate) unsafe fn from_raw(handle: *mut BNNamedTypeReference) -> Self {
1552 debug_assert!(!handle.is_null());
1553 Self { handle }
1554 }
1555
1556 pub(crate) unsafe fn ref_from_raw(handle: *mut BNNamedTypeReference) -> Ref<Self> {
1557 debug_assert!(!handle.is_null());
1558 Ref::new(Self { handle })
1559 }
1560
1561 pub fn new<T: Into<QualifiedName>>(type_class: NamedTypeReferenceClass, name: T) -> Ref<Self> {
1567 let mut raw_name = QualifiedName::into_raw(name.into());
1568 let result = unsafe {
1569 Self::ref_from_raw(BNCreateNamedType(
1570 type_class,
1571 std::ptr::null(),
1572 &mut raw_name,
1573 ))
1574 };
1575 QualifiedName::free_raw(raw_name);
1576 result
1577 }
1578
1579 pub fn new_with_id<T: Into<QualifiedName>>(
1585 type_class: NamedTypeReferenceClass,
1586 type_id: &str,
1587 name: T,
1588 ) -> Ref<Self> {
1589 let type_id = type_id.to_cstr();
1590 let mut raw_name = QualifiedName::into_raw(name.into());
1591 let result = unsafe {
1592 Self::ref_from_raw(BNCreateNamedType(
1593 type_class,
1594 type_id.as_ref().as_ptr() as _,
1595 &mut raw_name,
1596 ))
1597 };
1598 QualifiedName::free_raw(raw_name);
1599 result
1600 }
1601
1602 pub fn name(&self) -> QualifiedName {
1603 let raw_name = unsafe { BNGetTypeReferenceName(self.handle) };
1604 QualifiedName::from_owned_raw(raw_name)
1605 }
1606
1607 pub fn id(&self) -> String {
1608 unsafe { BnString::into_string(BNGetTypeReferenceId(self.handle)) }
1609 }
1610
1611 pub fn class(&self) -> NamedTypeReferenceClass {
1612 unsafe { BNGetTypeReferenceClass(self.handle) }
1613 }
1614
1615 fn target_helper(&self, bv: &BinaryView, visited: &mut HashSet<String>) -> Option<Ref<Type>> {
1616 let ty = bv.type_by_id(&self.id())?;
1617 match ty.type_class() {
1618 TypeClass::NamedTypeReferenceClass => {
1619 let ntr = ty
1621 .get_named_type_reference()
1622 .expect("NTR type class should always have a valid NTR");
1623 match visited.insert(ntr.id()) {
1624 true => ntr.target_helper(bv, visited),
1625 false => None,
1627 }
1628 }
1629 _ => Some(ty),
1631 }
1632 }
1633
1634 pub fn target(&self, bv: &BinaryView) -> Option<Ref<Type>> {
1638 self.target_helper(bv, &mut HashSet::new())
1639 }
1640}
1641
1642impl ToOwned for NamedTypeReference {
1643 type Owned = Ref<Self>;
1644
1645 fn to_owned(&self) -> Self::Owned {
1646 unsafe { RefCountable::inc_ref(self) }
1647 }
1648}
1649
1650unsafe impl RefCountable for NamedTypeReference {
1651 unsafe fn inc_ref(handle: &Self) -> Ref<Self> {
1652 Self::ref_from_raw(BNNewNamedTypeReference(handle.handle))
1653 }
1654
1655 unsafe fn dec_ref(handle: &Self) {
1656 BNFreeNamedTypeReference(handle.handle)
1657 }
1658}
1659
1660impl Debug for NamedTypeReference {
1661 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1662 write!(f, "{} (id: {})", self.name(), self.id())
1663 }
1664}
1665
1666#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1667pub struct QualifiedNameAndType {
1668 pub name: QualifiedName,
1669 pub ty: Ref<Type>,
1670}
1671
1672impl QualifiedNameAndType {
1673 pub(crate) fn from_raw(value: &BNQualifiedNameAndType) -> Self {
1674 Self {
1675 name: QualifiedName::from_raw(&value.name),
1676 ty: unsafe { Type::from_raw(value.type_).to_owned() },
1677 }
1678 }
1679
1680 pub(crate) fn from_owned_raw(value: BNQualifiedNameAndType) -> Self {
1681 let owned = Self::from_raw(&value);
1682 Self::free_raw(value);
1683 owned
1684 }
1685
1686 pub(crate) fn into_raw(value: Self) -> BNQualifiedNameAndType {
1687 BNQualifiedNameAndType {
1688 name: QualifiedName::into_raw(value.name),
1689 type_: unsafe { Ref::into_raw(value.ty).handle },
1690 }
1691 }
1692
1693 pub(crate) fn free_raw(value: BNQualifiedNameAndType) {
1694 QualifiedName::free_raw(value.name);
1695 let _ = unsafe { Type::ref_from_raw(value.type_) };
1696 }
1697
1698 pub fn new(name: QualifiedName, ty: Ref<Type>) -> Self {
1699 Self { name, ty }
1700 }
1701}
1702
1703impl<T> From<(T, Ref<Type>)> for QualifiedNameAndType
1704where
1705 T: Into<QualifiedName>,
1706{
1707 fn from(value: (T, Ref<Type>)) -> Self {
1708 Self {
1709 name: value.0.into(),
1710 ty: value.1,
1711 }
1712 }
1713}
1714
1715impl<T> From<(T, &Type)> for QualifiedNameAndType
1716where
1717 T: Into<QualifiedName>,
1718{
1719 fn from(value: (T, &Type)) -> Self {
1720 let ty = value.1.to_owned();
1721 Self {
1722 name: value.0.into(),
1723 ty,
1724 }
1725 }
1726}
1727
1728impl CoreArrayProvider for QualifiedNameAndType {
1729 type Raw = BNQualifiedNameAndType;
1730 type Context = ();
1731 type Wrapped<'a> = Self;
1732}
1733
1734unsafe impl CoreArrayProviderInner for QualifiedNameAndType {
1735 unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
1736 BNFreeTypeAndNameList(raw, count);
1737 }
1738
1739 unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
1740 QualifiedNameAndType::from_raw(raw)
1741 }
1742}
1743
1744#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1745pub struct QualifiedNameTypeAndId {
1746 pub name: QualifiedName,
1747 pub ty: Ref<Type>,
1748 pub id: String,
1749}
1750
1751impl QualifiedNameTypeAndId {
1752 pub(crate) fn from_raw(value: &BNQualifiedNameTypeAndId) -> Self {
1753 Self {
1754 name: QualifiedName::from_raw(&value.name),
1755 ty: unsafe { Type::from_raw(value.type_) }.to_owned(),
1756 id: raw_to_string(value.id).unwrap(),
1757 }
1758 }
1759
1760 #[allow(unused)]
1761 pub(crate) fn from_owned_raw(value: BNQualifiedNameTypeAndId) -> Self {
1762 let owned = Self::from_raw(&value);
1763 Self::free_raw(value);
1764 owned
1765 }
1766
1767 pub(crate) fn into_raw(value: Self) -> BNQualifiedNameTypeAndId {
1768 let bn_id = BnString::new(value.id);
1769 BNQualifiedNameTypeAndId {
1770 name: QualifiedName::into_raw(value.name),
1771 id: BnString::into_raw(bn_id),
1772 type_: unsafe { Ref::into_raw(value.ty) }.handle,
1773 }
1774 }
1775
1776 pub(crate) fn free_raw(value: BNQualifiedNameTypeAndId) {
1777 QualifiedName::free_raw(value.name);
1778 let _ = unsafe { Type::ref_from_raw(value.type_) };
1779 let _ = unsafe { BnString::from_raw(value.id) };
1780 }
1781}
1782
1783impl CoreArrayProvider for QualifiedNameTypeAndId {
1784 type Raw = BNQualifiedNameTypeAndId;
1785 type Context = ();
1786 type Wrapped<'a> = QualifiedNameTypeAndId;
1787}
1788
1789unsafe impl CoreArrayProviderInner for QualifiedNameTypeAndId {
1790 unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
1791 BNFreeTypeIdList(raw, count);
1792 }
1793
1794 unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
1795 QualifiedNameTypeAndId::from_raw(raw)
1796 }
1797}
1798
1799#[derive(Debug, Clone, Eq, PartialEq, Hash)]
1804pub struct NameAndType {
1805 pub name: String,
1806 pub ty: Conf<Ref<Type>>,
1807}
1808
1809impl NameAndType {
1810 pub(crate) fn from_raw(value: &BNNameAndType) -> Self {
1811 Self {
1812 name: raw_to_string(value.name as *mut _).unwrap(),
1814 ty: Conf::new(
1815 unsafe { Type::from_raw(value.type_).to_owned() },
1816 value.typeConfidence,
1817 ),
1818 }
1819 }
1820
1821 #[allow(unused)]
1822 pub(crate) fn from_owned_raw(value: BNNameAndType) -> Self {
1823 let owned = Self::from_raw(&value);
1824 Self::free_raw(value);
1825 owned
1826 }
1827
1828 pub(crate) fn into_raw(value: Self) -> BNNameAndType {
1829 let bn_name = BnString::new(value.name);
1830 BNNameAndType {
1831 name: BnString::into_raw(bn_name),
1832 type_: unsafe { Ref::into_raw(value.ty.contents) }.handle,
1833 typeConfidence: value.ty.confidence,
1834 }
1835 }
1836
1837 pub(crate) fn free_raw(value: BNNameAndType) {
1838 unsafe { BnString::free_raw(value.name) };
1839 let _ = unsafe { Type::ref_from_raw(value.type_) };
1840 }
1841
1842 pub fn new(name: impl Into<String>, ty: Conf<Ref<Type>>) -> Self {
1843 Self {
1844 name: name.into(),
1845 ty,
1846 }
1847 }
1848}
1849
1850impl CoreArrayProvider for NameAndType {
1851 type Raw = BNNameAndType;
1852 type Context = ();
1853 type Wrapped<'a> = Self;
1854}
1855
1856unsafe impl CoreArrayProviderInner for NameAndType {
1857 unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
1858 BNFreeNameAndTypeList(raw, count);
1859 }
1860
1861 unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
1862 NameAndType::from_raw(raw)
1863 }
1864}