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