1use binaryninjacore_sys::*;
24use std::fmt::{Debug, Formatter};
25
26use crate::{
27 calling_convention::CoreCallingConvention,
28 data_buffer::DataBuffer,
29 disassembly::InstructionTextToken,
30 ffi::INVALID_REGISTER,
31 function::{Function, Location, NativeBlock},
32 platform::Platform,
33 rc::*,
34 relocation::CoreRelocationHandler,
35 string::{IntoCStr, *},
36 types::{NameAndType, Type},
37 Endianness,
38};
39use std::collections::{HashMap, HashSet};
40use std::ops::Deref;
41use std::{
42 borrow::Borrow,
43 ffi::{c_char, c_void, CString},
44 hash::Hash,
45 mem::MaybeUninit,
46};
47
48use std::ptr::NonNull;
49
50use crate::function_recognizer::FunctionRecognizer;
51use crate::relocation::{CustomRelocationHandlerHandle, RelocationHandler};
52
53use crate::basic_block::BasicBlock;
54use crate::confidence::Conf;
55use crate::logger::Logger;
56use crate::low_level_il::expression::{LowLevelExpressionIndex, ValueExpr};
57use crate::low_level_il::lifting::{
58 get_default_flag_cond_llil, get_default_flag_write_llil, LowLevelILFlagWriteOp,
59};
60use crate::low_level_il::{LowLevelILMutableExpression, LowLevelILMutableFunction};
61
62pub mod basic_block;
63pub mod branches;
64pub mod flag;
65pub mod hook;
66pub mod instruction;
67pub mod intrinsic;
68pub mod register;
69
70pub use basic_block::*;
73pub use binaryninjacore_sys::BNLinearSweepAnalysisCapability as LinearSweepAnalysisCapability;
74pub use branches::*;
75pub use flag::*;
76pub use hook::{register_architecture_hook, ArchitectureHook};
77pub use instruction::*;
78pub use intrinsic::*;
79pub use register::*;
80
81pub trait Architecture: 'static + Sized + AsRef<CoreArchitecture> {
92 type Handle: Borrow<Self> + Clone;
93
94 type RegisterInfo: RegisterInfo<RegType = Self::Register>;
96
97 type Register: Register<InfoType = Self::RegisterInfo>;
99
100 type RegisterStackInfo: RegisterStackInfo<
104 RegType = Self::Register,
105 RegInfoType = Self::RegisterInfo,
106 RegStackType = Self::RegisterStack,
107 >;
108
109 type RegisterStack: RegisterStack<
114 InfoType = Self::RegisterStackInfo,
115 RegType = Self::Register,
116 RegInfoType = Self::RegisterInfo,
117 >;
118
119 type Flag: Flag<FlagClass = Self::FlagClass>;
124
125 type FlagWrite: FlagWrite<FlagType = Self::Flag, FlagClass = Self::FlagClass>;
133
134 type FlagClass: FlagClass;
142
143 type FlagGroup: FlagGroup<FlagType = Self::Flag, FlagClass = Self::FlagClass>;
151
152 type Intrinsic: Intrinsic;
153
154 fn endianness(&self) -> Endianness;
155 fn address_size(&self) -> usize;
156 fn default_integer_size(&self) -> usize;
157 fn instruction_alignment(&self) -> usize;
158
159 fn linear_sweep_initial_alignment(&self) -> usize {
161 self.instruction_alignment()
162 }
163
164 fn linear_sweep_analysis_capabilities(&self) -> u32 {
166 LinearSweepAnalysisCapability::BNLinearSweepCallTargetAnalysis as u32
167 | LinearSweepAnalysisCapability::BNLinearSweepGenericControlFlowAnalysis as u32
168 }
169
170 fn supports_standalone_instruction_decoding(&self) -> bool {
173 true
174 }
175
176 fn max_instr_len(&self) -> usize;
182
183 fn opcode_display_len(&self) -> usize {
186 self.max_instr_len()
187 }
188
189 fn associated_arch_by_addr(&self, _addr: &mut u64) -> CoreArchitecture {
195 *self.as_ref()
196 }
197
198 fn instruction_info(&self, data: &[u8], addr: u64) -> Option<InstructionInfo>;
203
204 fn instruction_text(
219 &self,
220 data: &[u8],
221 addr: u64,
222 ) -> Option<(usize, Vec<InstructionTextToken>)>;
223
224 fn instruction_text_with_context(
240 &self,
241 data: &[u8],
242 addr: u64,
243 _context: Option<NonNull<c_void>>,
244 ) -> Option<(usize, Vec<InstructionTextToken>)> {
245 self.instruction_text(data, addr)
246 }
247
248 fn instruction_llil(
254 &self,
255 data: &[u8],
256 addr: u64,
257 il: &LowLevelILMutableFunction,
258 ) -> Option<(usize, bool)>;
259
260 fn analyze_basic_blocks(
265 &self,
266 function: &mut Function,
267 context: &mut BasicBlockAnalysisContext,
268 ) {
269 unsafe {
270 BNArchitectureDefaultAnalyzeBasicBlocks(function.handle, context.handle);
271 }
272 }
273
274 fn lift_function(
275 &self,
276 function: LowLevelILMutableFunction,
277 context: &mut FunctionLifterContext,
278 ) -> bool {
279 unsafe { BNArchitectureDefaultLiftFunction(function.handle, context.handle) }
280 }
281
282 fn flag_write_llil<'a>(
292 &self,
293 flag: Self::Flag,
294 flag_write_type: Self::FlagWrite,
295 op: LowLevelILFlagWriteOp<Self::Register>,
296 il: &'a LowLevelILMutableFunction,
297 ) -> Option<LowLevelILMutableExpression<'a, ValueExpr>> {
298 let role = flag.role(flag_write_type.class());
299 Some(get_default_flag_write_llil(self, role, op, il))
300 }
301
302 fn flags_required_for_flag_condition(
307 &self,
308 _condition: FlagCondition,
309 _class: Option<Self::FlagClass>,
310 ) -> Vec<Self::Flag> {
311 Vec::new()
312 }
313
314 fn flag_cond_llil<'a>(
321 &self,
322 cond: FlagCondition,
323 class: Option<Self::FlagClass>,
324 il: &'a LowLevelILMutableFunction,
325 ) -> Option<LowLevelILMutableExpression<'a, ValueExpr>> {
326 Some(get_default_flag_cond_llil(self, cond, class, il))
327 }
328
329 fn flag_group_llil<'a>(
344 &self,
345 _group: Self::FlagGroup,
346 _il: &'a LowLevelILMutableFunction,
347 ) -> Option<LowLevelILMutableExpression<'a, ValueExpr>> {
348 None
349 }
350
351 fn registers_all(&self) -> Vec<Self::Register>;
352
353 fn register_from_id(&self, id: RegisterId) -> Option<Self::Register>;
354
355 fn registers_full_width(&self) -> Vec<Self::Register>;
356
357 fn registers_global(&self) -> Vec<Self::Register> {
359 Vec::new()
360 }
361
362 fn registers_system(&self) -> Vec<Self::Register> {
364 Vec::new()
365 }
366
367 fn stack_pointer_reg(&self) -> Option<Self::Register>;
368
369 fn link_reg(&self) -> Option<Self::Register> {
370 None
371 }
372
373 fn register_stacks(&self) -> Vec<Self::RegisterStack> {
379 Vec::new()
380 }
381
382 fn register_stack_from_id(&self, _id: RegisterStackId) -> Option<Self::RegisterStack> {
388 None
389 }
390
391 fn flags(&self) -> Vec<Self::Flag> {
403 Vec::new()
404 }
405
406 fn flag_from_id(&self, _id: FlagId) -> Option<Self::Flag> {
418 None
419 }
420
421 fn flag_write_types(&self) -> Vec<Self::FlagWrite> {
433 Vec::new()
434 }
435
436 fn flag_write_from_id(&self, _id: FlagWriteId) -> Option<Self::FlagWrite> {
448 None
449 }
450
451 fn flag_classes(&self) -> Vec<Self::FlagClass> {
462 Vec::new()
463 }
464
465 fn flag_class_from_id(&self, _id: FlagClassId) -> Option<Self::FlagClass> {
476 None
477 }
478
479 fn flag_groups(&self) -> Vec<Self::FlagGroup> {
490 Vec::new()
491 }
492
493 fn flag_group_from_id(&self, _id: FlagGroupId) -> Option<Self::FlagGroup> {
504 None
505 }
506
507 fn intrinsics(&self) -> Vec<Self::Intrinsic> {
513 Vec::new()
514 }
515
516 fn intrinsic_class(&self, id: IntrinsicId) -> BNIntrinsicClass {
518 match self.intrinsic_from_id(id) {
519 Some(intrinsic) => intrinsic.class(),
520 None => BNIntrinsicClass::GeneralIntrinsicClass,
521 }
522 }
523
524 fn intrinsic_from_id(&self, _id: IntrinsicId) -> Option<Self::Intrinsic> {
530 None
531 }
532
533 fn can_assemble(&self) -> bool {
537 false
538 }
539
540 fn assemble(&self, _code: &str, _addr: u64) -> Result<Vec<u8>, String> {
544 Err("Assemble unsupported".into())
545 }
546
547 fn is_never_branch_patch_available(&self, data: &[u8], addr: u64) -> bool {
551 self.is_invert_branch_patch_available(data, addr)
552 }
553
554 fn is_always_branch_patch_available(&self, _data: &[u8], _addr: u64) -> bool {
558 false
559 }
560
561 fn is_invert_branch_patch_available(&self, _data: &[u8], _addr: u64) -> bool {
565 false
566 }
567
568 fn is_skip_and_return_zero_patch_available(&self, data: &[u8], addr: u64) -> bool {
572 self.is_skip_and_return_value_patch_available(data, addr)
573 }
574
575 fn is_skip_and_return_value_patch_available(&self, _data: &[u8], _addr: u64) -> bool {
579 false
580 }
581
582 fn convert_to_nop(&self, _data: &mut [u8], _addr: u64) -> bool {
583 false
584 }
585
586 fn always_branch(&self, _data: &mut [u8], _addr: u64) -> bool {
590 false
591 }
592
593 fn invert_branch(&self, _data: &mut [u8], _addr: u64) -> bool {
597 false
598 }
599
600 fn skip_and_return_value(&self, _data: &mut [u8], _addr: u64, _value: u64) -> bool {
604 false
605 }
606
607 fn handle(&self) -> Self::Handle;
608}
609
610pub trait ArchitectureWithFunctionContext: Architecture {
611 type FunctionArchContext: Send + Sync + 'static;
612
613 fn instruction_text_with_typed_context(
614 &self,
615 data: &[u8],
616 addr: u64,
617 _context: Option<&Self::FunctionArchContext>,
618 ) -> Option<(usize, Vec<InstructionTextToken>)> {
619 self.instruction_text(data, addr)
620 }
621}
622
623pub struct FunctionLifterContext {
624 pub(crate) handle: *mut BNFunctionLifterContext,
625 pub function: Ref<LowLevelILMutableFunction>,
626 pub platform: Ref<Platform>,
627 pub logger: Ref<Logger>,
628 pub blocks: Vec<Ref<BasicBlock<NativeBlock>>>,
629 pub no_return_calls: HashSet<Location>,
630 pub contextual_returns: HashMap<Location, bool>,
631 pub inlined_remapping: HashMap<Location, Location>,
632 pub user_indirect_branches: HashMap<Location, HashSet<Location>>,
633 pub auto_indirect_branches: HashMap<Location, HashSet<Location>>,
634 pub inlined_calls: HashSet<u64>,
635}
636
637unsafe fn lifter_context_slice<'a, T>(ptr: *const T, len: usize) -> &'a [T] {
638 if len == 0 {
639 &[]
640 } else {
641 debug_assert!(!ptr.is_null());
642 unsafe { std::slice::from_raw_parts(ptr, len) }
643 }
644}
645
646impl FunctionLifterContext {
647 pub unsafe fn from_raw(
648 function: *mut BNLowLevelILFunction,
649 handle: *mut BNFunctionLifterContext,
650 ) -> Self {
651 Self::from_raw_with_arch(function, handle, None)
652 }
653
654 pub(crate) unsafe fn from_raw_with_arch(
655 function: *mut BNLowLevelILFunction,
656 handle: *mut BNFunctionLifterContext,
657 arch: Option<CoreArchitecture>,
658 ) -> Self {
659 debug_assert!(!function.is_null());
660 debug_assert!(!handle.is_null());
661 let flc_ref = &*handle;
662 let platform = unsafe { Platform::ref_from_raw(BNNewPlatformReference(flc_ref.platform)) };
663 let logger = unsafe { Logger::ref_from_raw(BNNewLoggerReference(flc_ref.logger)) };
664
665 let mut blocks = Vec::new();
666 for i in 0..flc_ref.basicBlockCount {
667 let block = unsafe {
668 Some(BasicBlock::ref_from_raw(
669 BNNewBasicBlockReference(*flc_ref.basicBlocks.add(i)),
670 NativeBlock::new(),
671 ))
672 };
673
674 blocks.push(block.unwrap());
675 }
676
677 let raw_no_return_calls: &[BNArchitectureAndAddress] =
678 lifter_context_slice(flc_ref.noReturnCalls, flc_ref.noReturnCallsCount);
679 let no_return_calls: HashSet<Location> =
680 raw_no_return_calls.iter().map(Location::from).collect();
681
682 let raw_contextual_return_locs: &[BNArchitectureAndAddress] = unsafe {
683 lifter_context_slice(
684 flc_ref.contextualFunctionReturnLocations,
685 flc_ref.contextualFunctionReturnCount,
686 )
687 };
688 let raw_contextual_return_vals: &[bool] = unsafe {
689 lifter_context_slice(
690 flc_ref.contextualFunctionReturnValues,
691 flc_ref.contextualFunctionReturnCount,
692 )
693 };
694 let contextual_returns: HashMap<Location, bool> = raw_contextual_return_locs
695 .iter()
696 .map(Location::from)
697 .zip(raw_contextual_return_vals.iter().copied())
698 .collect();
699
700 let inlined_remapping: HashMap<Location, Location> = {
701 let raw_inline_remap_locs: &[BNArchitectureAndAddress] = lifter_context_slice(
702 flc_ref.inlinedRemappingKeys,
703 flc_ref.inlinedRemappingEntryCount,
704 );
705
706 let raw_inline_remap_dests: &[BNArchitectureAndAddress] = lifter_context_slice(
707 flc_ref.inlinedRemappingValues,
708 flc_ref.inlinedRemappingEntryCount,
709 );
710
711 raw_inline_remap_locs
712 .iter()
713 .map(Location::from)
714 .zip(raw_inline_remap_dests.iter().map(Location::from))
715 .collect()
716 };
717
718 let mut user_indirect_branches: HashMap<Location, HashSet<Location>> = HashMap::new();
719 let mut auto_indirect_branches: HashMap<Location, HashSet<Location>> = HashMap::new();
720 for i in 0..flc_ref.indirectBranchesCount {
721 let entry = unsafe { *flc_ref.indirectBranches.add(i) };
722 let src = Location::new(
723 Some(CoreArchitecture::from_raw(entry.sourceArch)),
724 entry.sourceAddr,
725 );
726 let dest = Location::new(
727 Some(CoreArchitecture::from_raw(entry.destArch)),
728 entry.destAddr,
729 );
730 if entry.autoDefined {
731 auto_indirect_branches.entry(src).or_default().insert(dest);
732 } else {
733 user_indirect_branches.entry(src).or_default().insert(dest);
734 }
735 }
736
737 let inlined_calls: HashSet<u64> =
738 lifter_context_slice(flc_ref.inlinedCalls, flc_ref.inlinedCallsCount)
739 .iter()
740 .copied()
741 .collect();
742
743 FunctionLifterContext {
744 handle,
745 function: LowLevelILMutableFunction::ref_from_raw_with_arch(
746 BNNewLowLevelILFunctionReference(function),
747 arch,
748 ),
749 platform,
750 logger,
751 blocks,
752 no_return_calls,
753 contextual_returns,
754 inlined_remapping,
755 user_indirect_branches,
756 auto_indirect_branches,
757 inlined_calls,
758 }
759 }
760
761 pub fn prepare_block_translation(
762 &self,
763 func: &LowLevelILMutableFunction,
764 arch: &CoreArchitecture,
765 address: u64,
766 ) {
767 unsafe {
768 BNPrepareBlockTranslation(func.handle, arch.handle, address);
769 }
770 }
771
772 pub fn lifter_instruction_data(&self) -> Option<LifterInstructionData> {
775 let handle = unsafe { (*self.handle).lifterInstructionData };
776 if handle.is_null() {
777 None
778 } else {
779 Some(unsafe { LifterInstructionData::from_raw(handle) })
780 }
781 }
782
783 pub fn get_function_arch_context<A: ArchitectureWithFunctionContext>(
784 &self,
785 _arch: &A,
786 ) -> Option<&A::FunctionArchContext> {
787 unsafe {
788 let ptr = (*self.handle).functionArchContext;
789 if ptr.is_null() {
790 None
791 } else {
792 Some(&*(ptr as *const A::FunctionArchContext))
793 }
794 }
795 }
796}
797
798pub struct CoreArchitectureList(*mut *mut BNArchitecture, usize);
800
801impl Deref for CoreArchitectureList {
802 type Target = [CoreArchitecture];
803
804 fn deref(&self) -> &Self::Target {
805 unsafe { std::slice::from_raw_parts_mut(self.0 as *mut CoreArchitecture, self.1) }
806 }
807}
808
809impl Drop for CoreArchitectureList {
810 fn drop(&mut self) {
811 unsafe {
812 BNFreeArchitectureList(self.0);
813 }
814 }
815}
816
817#[derive(Copy, Clone, Eq, PartialEq, Hash)]
818pub struct CoreArchitecture {
819 pub(crate) handle: *mut BNArchitecture,
820}
821
822impl CoreArchitecture {
823 pub unsafe fn from_raw(handle: *mut BNArchitecture) -> Self {
825 debug_assert!(!handle.is_null());
826 CoreArchitecture { handle }
827 }
828
829 pub fn list_all() -> CoreArchitectureList {
830 let mut count: usize = 0;
831 let archs = unsafe { BNGetArchitectureList(&mut count) };
832
833 CoreArchitectureList(archs, count)
834 }
835
836 pub fn by_name(name: &str) -> Option<Self> {
837 let name = name.to_cstr();
838 let handle = unsafe { BNGetArchitectureByName(name.as_ptr()) };
839 match handle.is_null() {
840 false => Some(CoreArchitecture { handle }),
841 true => None,
842 }
843 }
844
845 pub fn name(&self) -> String {
846 unsafe { BnString::into_string(BNGetArchitectureName(self.handle)) }
847 }
848
849 pub fn register_stack_for_register(&self, reg: CoreRegister) -> Option<CoreRegisterStack> {
850 match unsafe { BNGetArchitectureRegisterStackForRegister(self.handle, reg.id().0) } {
851 INVALID_REGISTER => None,
852 reg_stack => CoreRegisterStack::new(*self, RegisterStackId::from(reg_stack)),
853 }
854 }
855}
856
857unsafe impl Send for CoreArchitecture {}
858unsafe impl Sync for CoreArchitecture {}
859
860impl AsRef<CoreArchitecture> for CoreArchitecture {
861 fn as_ref(&self) -> &Self {
862 self
863 }
864}
865
866impl Architecture for CoreArchitecture {
867 type Handle = Self;
868
869 type RegisterInfo = CoreRegisterInfo;
870 type Register = CoreRegister;
871 type RegisterStackInfo = CoreRegisterStackInfo;
872 type RegisterStack = CoreRegisterStack;
873 type Flag = CoreFlag;
874 type FlagWrite = CoreFlagWrite;
875 type FlagClass = CoreFlagClass;
876 type FlagGroup = CoreFlagGroup;
877 type Intrinsic = CoreIntrinsic;
878
879 fn endianness(&self) -> Endianness {
880 unsafe { BNGetArchitectureEndianness(self.handle) }
881 }
882
883 fn address_size(&self) -> usize {
884 unsafe { BNGetArchitectureAddressSize(self.handle) }
885 }
886
887 fn default_integer_size(&self) -> usize {
888 unsafe { BNGetArchitectureDefaultIntegerSize(self.handle) }
889 }
890
891 fn instruction_alignment(&self) -> usize {
892 unsafe { BNGetArchitectureInstructionAlignment(self.handle) }
893 }
894
895 fn linear_sweep_initial_alignment(&self) -> usize {
896 unsafe { BNGetArchitectureLinearSweepInitialAlignment(self.handle) }
897 }
898
899 fn linear_sweep_analysis_capabilities(&self) -> u32 {
900 unsafe { BNGetArchitectureLinearSweepAnalysisCapabilities(self.handle) }
901 }
902
903 fn supports_standalone_instruction_decoding(&self) -> bool {
904 unsafe { BNArchitectureSupportsStandaloneInstructionDecoding(self.handle) }
905 }
906
907 fn max_instr_len(&self) -> usize {
908 unsafe { BNGetArchitectureMaxInstructionLength(self.handle) }
909 }
910
911 fn opcode_display_len(&self) -> usize {
912 unsafe { BNGetArchitectureOpcodeDisplayLength(self.handle) }
913 }
914
915 fn associated_arch_by_addr(&self, addr: &mut u64) -> CoreArchitecture {
916 let handle = unsafe { BNGetAssociatedArchitectureByAddress(self.handle, addr) };
917 CoreArchitecture { handle }
918 }
919
920 fn instruction_info(&self, data: &[u8], addr: u64) -> Option<InstructionInfo> {
921 let mut info = BNInstructionInfo::default();
922 if unsafe { BNGetInstructionInfo(self.handle, data.as_ptr(), addr, data.len(), &mut info) }
923 {
924 Some(info.into())
925 } else {
926 None
927 }
928 }
929
930 fn instruction_text(
931 &self,
932 data: &[u8],
933 addr: u64,
934 ) -> Option<(usize, Vec<InstructionTextToken>)> {
935 let mut consumed = data.len();
936 let mut count: usize = 0;
937 let mut result: *mut BNInstructionTextToken = std::ptr::null_mut();
938
939 unsafe {
940 if BNGetInstructionText(
941 self.handle,
942 data.as_ptr(),
943 addr,
944 &mut consumed,
945 &mut result,
946 &mut count,
947 ) {
948 let instr_text_tokens = std::slice::from_raw_parts(result, count)
949 .iter()
950 .map(InstructionTextToken::from_raw)
951 .collect();
952 BNFreeInstructionText(result, count);
953 Some((consumed, instr_text_tokens))
954 } else {
955 None
956 }
957 }
958 }
959
960 fn instruction_text_with_context(
961 &self,
962 data: &[u8],
963 addr: u64,
964 context: Option<NonNull<c_void>>,
965 ) -> Option<(usize, Vec<InstructionTextToken>)> {
966 let mut consumed = data.len();
967 let mut count: usize = 0;
968 let mut result: *mut BNInstructionTextToken = std::ptr::null_mut();
969 let ctx_ptr: *mut c_void = context.map_or(std::ptr::null_mut(), |p| p.as_ptr());
970 unsafe {
971 if BNGetInstructionTextWithContext(
972 self.handle,
973 data.as_ptr(),
974 addr,
975 &mut consumed,
976 ctx_ptr,
977 &mut result,
978 &mut count,
979 ) {
980 let instr_text_tokens = std::slice::from_raw_parts(result, count)
981 .iter()
982 .map(InstructionTextToken::from_raw)
983 .collect();
984 BNFreeInstructionText(result, count);
985 Some((consumed, instr_text_tokens))
986 } else {
987 None
988 }
989 }
990 }
991
992 fn instruction_llil(
993 &self,
994 data: &[u8],
995 addr: u64,
996 il: &LowLevelILMutableFunction,
997 ) -> Option<(usize, bool)> {
998 let mut size = data.len();
999 let success = unsafe {
1000 BNGetInstructionLowLevelIL(
1001 self.handle,
1002 data.as_ptr(),
1003 addr,
1004 &mut size as *mut _,
1005 il.handle,
1006 )
1007 };
1008
1009 Some((size, success))
1010 }
1011
1012 fn analyze_basic_blocks(
1019 &self,
1020 function: &mut Function,
1021 context: &mut BasicBlockAnalysisContext,
1022 ) {
1023 unsafe {
1024 BNArchitectureAnalyzeBasicBlocks(self.handle, function.handle, context.handle);
1025 }
1026 }
1027
1028 fn lift_function(
1029 &self,
1030 function: LowLevelILMutableFunction,
1031 context: &mut FunctionLifterContext,
1032 ) -> bool {
1033 unsafe { BNArchitectureLiftFunction(self.handle, function.handle, context.handle) }
1034 }
1035
1036 fn flag_write_llil<'a>(
1037 &self,
1038 flag: Self::Flag,
1039 flag_write: Self::FlagWrite,
1040 op: LowLevelILFlagWriteOp<Self::Register>,
1041 il: &'a LowLevelILMutableFunction,
1042 ) -> Option<LowLevelILMutableExpression<'a, ValueExpr>> {
1043 let (size, operation) = op.size_and_op();
1044 let mut operands = op.raw_operands();
1045 let index = unsafe {
1046 BNGetArchitectureFlagWriteLowLevelIL(
1047 self.handle,
1048 operation,
1049 size,
1050 flag_write.id().0,
1051 flag.id().0,
1052 operands.as_mut_ptr(),
1053 operands.len(),
1054 il.handle,
1055 )
1056 };
1057 Some(LowLevelILMutableExpression::new(
1058 il,
1059 LowLevelExpressionIndex(index),
1060 ))
1061 }
1062
1063 fn flags_required_for_flag_condition(
1064 &self,
1065 condition: FlagCondition,
1066 class: Option<Self::FlagClass>,
1067 ) -> Vec<Self::Flag> {
1068 let class_id_raw = class.map(|c| c.id().0).unwrap_or(0);
1069
1070 unsafe {
1071 let mut count: usize = 0;
1072 let flags = BNGetArchitectureFlagsRequiredForFlagCondition(
1073 self.handle,
1074 condition,
1075 class_id_raw,
1076 &mut count,
1077 );
1078
1079 let ret = std::slice::from_raw_parts(flags, count)
1080 .iter()
1081 .map(|&id| FlagId::from(id))
1082 .filter_map(|flag| CoreFlag::new(*self, flag))
1083 .collect();
1084
1085 BNFreeRegisterList(flags);
1086
1087 ret
1088 }
1089 }
1090
1091 fn flag_cond_llil<'a>(
1092 &self,
1093 cond: FlagCondition,
1094 class: Option<Self::FlagClass>,
1095 il: &'a LowLevelILMutableFunction,
1096 ) -> Option<LowLevelILMutableExpression<'a, ValueExpr>> {
1097 let index = unsafe {
1098 BNGetArchitectureFlagConditionLowLevelIL(
1099 self.handle,
1100 cond,
1101 class.map_or(0, |class| class.id().0),
1102 il.handle,
1103 )
1104 };
1105 Some(LowLevelILMutableExpression::new(
1106 il,
1107 LowLevelExpressionIndex(index),
1108 ))
1109 }
1110
1111 fn flag_group_llil<'a>(
1112 &self,
1113 group: Self::FlagGroup,
1114 il: &'a LowLevelILMutableFunction,
1115 ) -> Option<LowLevelILMutableExpression<'a, ValueExpr>> {
1116 let index = unsafe {
1117 BNGetArchitectureSemanticFlagGroupLowLevelIL(self.handle, group.id().0, il.handle)
1118 };
1119 Some(LowLevelILMutableExpression::new(
1120 il,
1121 LowLevelExpressionIndex(index),
1122 ))
1123 }
1124
1125 fn registers_all(&self) -> Vec<CoreRegister> {
1126 unsafe {
1127 let mut count: usize = 0;
1128 let registers_raw = BNGetAllArchitectureRegisters(self.handle, &mut count);
1129
1130 let ret = std::slice::from_raw_parts(registers_raw, count)
1131 .iter()
1132 .map(|&id| RegisterId::from(id))
1133 .filter_map(|reg| CoreRegister::new(*self, reg))
1134 .collect();
1135
1136 BNFreeRegisterList(registers_raw);
1137
1138 ret
1139 }
1140 }
1141
1142 fn register_from_id(&self, id: RegisterId) -> Option<CoreRegister> {
1143 CoreRegister::new(*self, id)
1144 }
1145
1146 fn registers_full_width(&self) -> Vec<CoreRegister> {
1147 unsafe {
1148 let mut count: usize = 0;
1149 let registers_raw = BNGetFullWidthArchitectureRegisters(self.handle, &mut count);
1150
1151 let ret = std::slice::from_raw_parts(registers_raw, count)
1152 .iter()
1153 .map(|&id| RegisterId::from(id))
1154 .filter_map(|reg| CoreRegister::new(*self, reg))
1155 .collect();
1156
1157 BNFreeRegisterList(registers_raw);
1158
1159 ret
1160 }
1161 }
1162
1163 fn registers_global(&self) -> Vec<CoreRegister> {
1164 unsafe {
1165 let mut count: usize = 0;
1166 let registers_raw = BNGetArchitectureGlobalRegisters(self.handle, &mut count);
1167
1168 let ret = std::slice::from_raw_parts(registers_raw, count)
1169 .iter()
1170 .map(|&id| RegisterId::from(id))
1171 .filter_map(|reg| CoreRegister::new(*self, reg))
1172 .collect();
1173
1174 BNFreeRegisterList(registers_raw);
1175
1176 ret
1177 }
1178 }
1179
1180 fn registers_system(&self) -> Vec<CoreRegister> {
1181 unsafe {
1182 let mut count: usize = 0;
1183 let registers_raw = BNGetArchitectureSystemRegisters(self.handle, &mut count);
1184
1185 let ret = std::slice::from_raw_parts(registers_raw, count)
1186 .iter()
1187 .map(|&id| RegisterId::from(id))
1188 .filter_map(|reg| CoreRegister::new(*self, reg))
1189 .collect();
1190
1191 BNFreeRegisterList(registers_raw);
1192
1193 ret
1194 }
1195 }
1196
1197 fn stack_pointer_reg(&self) -> Option<CoreRegister> {
1198 match unsafe { BNGetArchitectureStackPointerRegister(self.handle) } {
1199 INVALID_REGISTER => None,
1200 reg => Some(CoreRegister::new(*self, reg.into())?),
1201 }
1202 }
1203
1204 fn link_reg(&self) -> Option<CoreRegister> {
1205 match unsafe { BNGetArchitectureLinkRegister(self.handle) } {
1206 INVALID_REGISTER => None,
1207 reg => Some(CoreRegister::new(*self, reg.into())?),
1208 }
1209 }
1210
1211 fn register_stacks(&self) -> Vec<CoreRegisterStack> {
1212 unsafe {
1213 let mut count: usize = 0;
1214 let reg_stacks_raw = BNGetAllArchitectureRegisterStacks(self.handle, &mut count);
1215
1216 let ret = std::slice::from_raw_parts(reg_stacks_raw, count)
1217 .iter()
1218 .map(|&id| RegisterStackId::from(id))
1219 .filter_map(|reg_stack| CoreRegisterStack::new(*self, reg_stack))
1220 .collect();
1221
1222 BNFreeRegisterList(reg_stacks_raw);
1223
1224 ret
1225 }
1226 }
1227
1228 fn register_stack_from_id(&self, id: RegisterStackId) -> Option<CoreRegisterStack> {
1229 CoreRegisterStack::new(*self, id)
1230 }
1231
1232 fn flags(&self) -> Vec<CoreFlag> {
1233 unsafe {
1234 let mut count: usize = 0;
1235 let flags_raw = BNGetAllArchitectureFlags(self.handle, &mut count);
1236
1237 let ret = std::slice::from_raw_parts(flags_raw, count)
1238 .iter()
1239 .map(|&id| FlagId::from(id))
1240 .filter_map(|flag| CoreFlag::new(*self, flag))
1241 .collect();
1242
1243 BNFreeRegisterList(flags_raw);
1244
1245 ret
1246 }
1247 }
1248
1249 fn flag_from_id(&self, id: FlagId) -> Option<CoreFlag> {
1250 CoreFlag::new(*self, id)
1251 }
1252
1253 fn flag_write_types(&self) -> Vec<CoreFlagWrite> {
1254 unsafe {
1255 let mut count: usize = 0;
1256 let flag_writes_raw = BNGetAllArchitectureFlagWriteTypes(self.handle, &mut count);
1257
1258 let ret = std::slice::from_raw_parts(flag_writes_raw, count)
1259 .iter()
1260 .map(|&id| FlagWriteId::from(id))
1261 .filter_map(|flag_write| CoreFlagWrite::new(*self, flag_write))
1262 .collect();
1263
1264 BNFreeRegisterList(flag_writes_raw);
1265
1266 ret
1267 }
1268 }
1269
1270 fn flag_write_from_id(&self, id: FlagWriteId) -> Option<CoreFlagWrite> {
1271 CoreFlagWrite::new(*self, id)
1272 }
1273
1274 fn flag_classes(&self) -> Vec<CoreFlagClass> {
1275 unsafe {
1276 let mut count: usize = 0;
1277 let flag_classes_raw = BNGetAllArchitectureSemanticFlagClasses(self.handle, &mut count);
1278
1279 let ret = std::slice::from_raw_parts(flag_classes_raw, count)
1280 .iter()
1281 .map(|&id| FlagClassId::from(id))
1282 .filter_map(|flag_class| CoreFlagClass::new(*self, flag_class))
1283 .collect();
1284
1285 BNFreeRegisterList(flag_classes_raw);
1286
1287 ret
1288 }
1289 }
1290
1291 fn flag_class_from_id(&self, id: FlagClassId) -> Option<CoreFlagClass> {
1292 CoreFlagClass::new(*self, id)
1293 }
1294
1295 fn flag_groups(&self) -> Vec<CoreFlagGroup> {
1296 unsafe {
1297 let mut count: usize = 0;
1298 let flag_groups_raw = BNGetAllArchitectureSemanticFlagGroups(self.handle, &mut count);
1299
1300 let ret = std::slice::from_raw_parts(flag_groups_raw, count)
1301 .iter()
1302 .map(|&id| FlagGroupId::from(id))
1303 .filter_map(|flag_group| CoreFlagGroup::new(*self, flag_group))
1304 .collect();
1305
1306 BNFreeRegisterList(flag_groups_raw);
1307
1308 ret
1309 }
1310 }
1311
1312 fn flag_group_from_id(&self, id: FlagGroupId) -> Option<CoreFlagGroup> {
1313 CoreFlagGroup::new(*self, id)
1314 }
1315
1316 fn intrinsics(&self) -> Vec<CoreIntrinsic> {
1317 unsafe {
1318 let mut count: usize = 0;
1319 let intrinsics_raw = BNGetAllArchitectureIntrinsics(self.handle, &mut count);
1320
1321 let intrinsics = std::slice::from_raw_parts_mut(intrinsics_raw, count)
1322 .iter()
1323 .map(|&id| IntrinsicId::from(id))
1324 .filter_map(|intrinsic| CoreIntrinsic::new(*self, intrinsic))
1325 .collect();
1326
1327 BNFreeRegisterList(intrinsics_raw);
1328
1329 intrinsics
1330 }
1331 }
1332
1333 fn intrinsic_class(&self, id: IntrinsicId) -> BNIntrinsicClass {
1334 unsafe { BNGetArchitectureIntrinsicClass(self.handle, id.0) }
1335 }
1336
1337 fn intrinsic_from_id(&self, id: IntrinsicId) -> Option<CoreIntrinsic> {
1338 CoreIntrinsic::new(*self, id)
1339 }
1340
1341 fn can_assemble(&self) -> bool {
1342 unsafe { BNCanArchitectureAssemble(self.handle) }
1343 }
1344
1345 fn assemble(&self, code: &str, addr: u64) -> Result<Vec<u8>, String> {
1346 let code = CString::new(code).map_err(|_| "Invalid encoding in code string".to_string())?;
1347
1348 let result = DataBuffer::new(&[]);
1349 let mut error_raw: *mut c_char = std::ptr::null_mut();
1351 let res = unsafe {
1352 BNAssemble(
1353 self.handle,
1354 code.as_ptr(),
1355 addr,
1356 result.as_raw(),
1357 &mut error_raw as *mut *mut c_char,
1358 )
1359 };
1360
1361 let error = raw_to_string(error_raw);
1362 unsafe {
1363 BNFreeString(error_raw);
1364 }
1365
1366 if res {
1367 Ok(result.get_data().to_vec())
1368 } else {
1369 Err(error.unwrap_or_else(|| "Assemble failed".into()))
1370 }
1371 }
1372
1373 fn is_never_branch_patch_available(&self, data: &[u8], addr: u64) -> bool {
1374 unsafe {
1375 BNIsArchitectureNeverBranchPatchAvailable(self.handle, data.as_ptr(), addr, data.len())
1376 }
1377 }
1378
1379 fn is_always_branch_patch_available(&self, data: &[u8], addr: u64) -> bool {
1380 unsafe {
1381 BNIsArchitectureAlwaysBranchPatchAvailable(self.handle, data.as_ptr(), addr, data.len())
1382 }
1383 }
1384
1385 fn is_invert_branch_patch_available(&self, data: &[u8], addr: u64) -> bool {
1386 unsafe {
1387 BNIsArchitectureInvertBranchPatchAvailable(self.handle, data.as_ptr(), addr, data.len())
1388 }
1389 }
1390
1391 fn is_skip_and_return_zero_patch_available(&self, data: &[u8], addr: u64) -> bool {
1392 unsafe {
1393 BNIsArchitectureSkipAndReturnZeroPatchAvailable(
1394 self.handle,
1395 data.as_ptr(),
1396 addr,
1397 data.len(),
1398 )
1399 }
1400 }
1401
1402 fn is_skip_and_return_value_patch_available(&self, data: &[u8], addr: u64) -> bool {
1403 unsafe {
1404 BNIsArchitectureSkipAndReturnValuePatchAvailable(
1405 self.handle,
1406 data.as_ptr(),
1407 addr,
1408 data.len(),
1409 )
1410 }
1411 }
1412
1413 fn convert_to_nop(&self, data: &mut [u8], addr: u64) -> bool {
1414 unsafe { BNArchitectureConvertToNop(self.handle, data.as_mut_ptr(), addr, data.len()) }
1415 }
1416
1417 fn always_branch(&self, data: &mut [u8], addr: u64) -> bool {
1418 unsafe { BNArchitectureAlwaysBranch(self.handle, data.as_mut_ptr(), addr, data.len()) }
1419 }
1420
1421 fn invert_branch(&self, data: &mut [u8], addr: u64) -> bool {
1422 unsafe { BNArchitectureInvertBranch(self.handle, data.as_mut_ptr(), addr, data.len()) }
1423 }
1424
1425 fn skip_and_return_value(&self, data: &mut [u8], addr: u64, value: u64) -> bool {
1426 unsafe {
1427 BNArchitectureSkipAndReturnValue(
1428 self.handle,
1429 data.as_mut_ptr(),
1430 addr,
1431 data.len(),
1432 value,
1433 )
1434 }
1435 }
1436
1437 fn handle(&self) -> CoreArchitecture {
1438 *self
1439 }
1440}
1441
1442impl Debug for CoreArchitecture {
1443 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1444 f.debug_struct("CoreArchitecture")
1445 .field("name", &self.name())
1446 .field("endianness", &self.endianness())
1447 .field("address_size", &self.address_size())
1448 .field("instruction_alignment", &self.instruction_alignment())
1449 .finish()
1450 }
1451}
1452
1453macro_rules! cc_func {
1454 ($get_name:ident, $get_api:ident, $set_name:ident, $set_api:ident) => {
1455 fn $get_name(&self) -> Option<Ref<CoreCallingConvention>> {
1456 let arch = self.as_ref();
1457
1458 unsafe {
1459 let cc = $get_api(arch.handle);
1460
1461 if cc.is_null() {
1462 None
1463 } else {
1464 Some(CoreCallingConvention::ref_from_raw(
1465 cc,
1466 self.as_ref().handle(),
1467 ))
1468 }
1469 }
1470 }
1471
1472 fn $set_name(&self, cc: &CoreCallingConvention) {
1473 let arch = self.as_ref();
1474
1475 assert!(
1476 cc.arch_handle.borrow().as_ref().handle == arch.handle,
1477 "use of calling convention with non-matching architecture!"
1478 );
1479
1480 unsafe {
1481 $set_api(arch.handle, cc.handle);
1482 }
1483 }
1484 };
1485}
1486
1487pub trait ArchitectureExt: Architecture {
1489 fn register_by_name(&self, name: &str) -> Option<Self::Register> {
1490 let name = name.to_cstr();
1491
1492 match unsafe { BNGetArchitectureRegisterByName(self.as_ref().handle, name.as_ptr()) } {
1493 INVALID_REGISTER => None,
1494 reg => self.register_from_id(reg.into()),
1495 }
1496 }
1497
1498 fn calling_convention_by_name(&self, name: &str) -> Option<Ref<CoreCallingConvention>> {
1499 let name = name.to_cstr();
1500 unsafe {
1501 let result = NonNull::new(BNGetArchitectureCallingConventionByName(
1502 self.as_ref().handle,
1503 name.as_ptr(),
1504 ))?;
1505 Some(CoreCallingConvention::ref_from_raw(
1506 result.as_ptr(),
1507 self.as_ref().handle(),
1508 ))
1509 }
1510 }
1511
1512 fn calling_conventions(&self) -> Array<CoreCallingConvention> {
1513 unsafe {
1514 let mut count = 0;
1515 let calling_convs =
1516 BNGetArchitectureCallingConventions(self.as_ref().handle, &mut count);
1517 Array::new(calling_convs, count, self.as_ref().handle())
1518 }
1519 }
1520
1521 cc_func!(
1522 get_default_calling_convention,
1523 BNGetArchitectureDefaultCallingConvention,
1524 set_default_calling_convention,
1525 BNSetArchitectureDefaultCallingConvention
1526 );
1527
1528 cc_func!(
1529 get_cdecl_calling_convention,
1530 BNGetArchitectureCdeclCallingConvention,
1531 set_cdecl_calling_convention,
1532 BNSetArchitectureCdeclCallingConvention
1533 );
1534
1535 cc_func!(
1536 get_stdcall_calling_convention,
1537 BNGetArchitectureStdcallCallingConvention,
1538 set_stdcall_calling_convention,
1539 BNSetArchitectureStdcallCallingConvention
1540 );
1541
1542 cc_func!(
1543 get_fastcall_calling_convention,
1544 BNGetArchitectureFastcallCallingConvention,
1545 set_fastcall_calling_convention,
1546 BNSetArchitectureFastcallCallingConvention
1547 );
1548
1549 fn standalone_platform(&self) -> Option<Ref<Platform>> {
1550 unsafe {
1551 let handle = BNGetArchitectureStandalonePlatform(self.as_ref().handle);
1552
1553 if handle.is_null() {
1554 return None;
1555 }
1556
1557 Some(Platform::ref_from_raw(handle))
1558 }
1559 }
1560
1561 fn relocation_handler(&self, view_name: &str) -> Option<Ref<CoreRelocationHandler>> {
1562 let view_name = match CString::new(view_name) {
1563 Ok(view_name) => view_name,
1564 Err(_) => return None,
1565 };
1566
1567 unsafe {
1568 let handle =
1569 BNArchitectureGetRelocationHandler(self.as_ref().handle, view_name.as_ptr());
1570
1571 if handle.is_null() {
1572 return None;
1573 }
1574
1575 Some(CoreRelocationHandler::ref_from_raw(handle))
1576 }
1577 }
1578
1579 fn register_relocation_handler<R, F>(&self, name: &str, func: F)
1580 where
1581 R: 'static
1582 + RelocationHandler<Handle = CustomRelocationHandlerHandle<R>>
1583 + Send
1584 + Sync
1585 + Sized,
1586 F: FnOnce(CustomRelocationHandlerHandle<R>, CoreRelocationHandler) -> R,
1587 {
1588 crate::relocation::register_relocation_handler(self.as_ref(), name, func);
1589 }
1590
1591 fn register_function_recognizer<R>(&self, recognizer: R)
1592 where
1593 R: 'static + FunctionRecognizer + Send + Sync + Sized,
1594 {
1595 crate::function_recognizer::register_arch_function_recognizer(self.as_ref(), recognizer);
1596 }
1597}
1598
1599impl<T: Architecture> ArchitectureExt for T {}
1600
1601pub fn register_architecture<A, F>(name: &str, func: F) -> &'static A
1605where
1606 A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync + Sized,
1607 F: FnOnce(CustomArchitectureHandle<A>, CoreArchitecture) -> A,
1608{
1609 register_architecture_impl(ArchitectureRegistration::New(name), func, |_| {})
1610}
1611
1612enum ArchitectureRegistration<'a> {
1613 New(&'a str),
1614 Hook(CoreArchitecture),
1615}
1616
1617fn register_architecture_impl<A, F, C>(
1618 registration: ArchitectureRegistration<'_>,
1619 func: F,
1620 customize: C,
1621) -> &'static A
1622where
1623 A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync + Sized,
1624 F: FnOnce(CustomArchitectureHandle<A>, CoreArchitecture) -> A,
1625 C: FnOnce(&mut BNCustomArchitecture),
1626{
1627 #[repr(C)]
1628 struct ArchitectureBuilder<A, F>
1629 where
1630 A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
1631 F: FnOnce(CustomArchitectureHandle<A>, CoreArchitecture) -> A,
1632 {
1633 arch: MaybeUninit<A>,
1634 func: Option<F>,
1635 }
1636
1637 extern "C" fn cb_init<A, F>(ctxt: *mut c_void, obj: *mut BNArchitecture)
1638 where
1639 A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
1640 F: FnOnce(CustomArchitectureHandle<A>, CoreArchitecture) -> A,
1641 {
1642 unsafe {
1643 let custom_arch = &mut *(ctxt as *mut ArchitectureBuilder<A, F>);
1644 let custom_arch_handle = CustomArchitectureHandle {
1645 handle: ctxt as *mut A,
1646 };
1647
1648 let create = custom_arch.func.take().unwrap();
1649 custom_arch
1650 .arch
1651 .write(create(custom_arch_handle, CoreArchitecture::from_raw(obj)));
1652 }
1653 }
1654
1655 extern "C" fn cb_endianness<A>(ctxt: *mut c_void) -> BNEndianness
1656 where
1657 A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
1658 {
1659 let custom_arch = unsafe { &*(ctxt as *mut A) };
1660 custom_arch.endianness()
1661 }
1662
1663 extern "C" fn cb_address_size<A>(ctxt: *mut c_void) -> usize
1664 where
1665 A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
1666 {
1667 let custom_arch = unsafe { &*(ctxt as *mut A) };
1668 custom_arch.address_size()
1669 }
1670
1671 extern "C" fn cb_default_integer_size<A>(ctxt: *mut c_void) -> usize
1672 where
1673 A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
1674 {
1675 let custom_arch = unsafe { &*(ctxt as *mut A) };
1676 custom_arch.default_integer_size()
1677 }
1678
1679 extern "C" fn cb_instruction_alignment<A>(ctxt: *mut c_void) -> usize
1680 where
1681 A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
1682 {
1683 let custom_arch = unsafe { &*(ctxt as *mut A) };
1684 custom_arch.instruction_alignment()
1685 }
1686
1687 extern "C" fn cb_linear_sweep_initial_alignment<A>(ctxt: *mut c_void) -> usize
1688 where
1689 A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
1690 {
1691 let custom_arch = unsafe { &*(ctxt as *mut A) };
1692 custom_arch.linear_sweep_initial_alignment()
1693 }
1694
1695 extern "C" fn cb_linear_sweep_analysis_capabilities<A>(ctxt: *mut c_void) -> u32
1696 where
1697 A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
1698 {
1699 let custom_arch = unsafe { &*(ctxt as *mut A) };
1700 custom_arch.linear_sweep_analysis_capabilities()
1701 }
1702
1703 extern "C" fn cb_max_instr_len<A>(ctxt: *mut c_void) -> usize
1704 where
1705 A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
1706 {
1707 let custom_arch = unsafe { &*(ctxt as *mut A) };
1708 custom_arch.max_instr_len()
1709 }
1710
1711 extern "C" fn cb_opcode_display_len<A>(ctxt: *mut c_void) -> usize
1712 where
1713 A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
1714 {
1715 let custom_arch = unsafe { &*(ctxt as *mut A) };
1716 custom_arch.opcode_display_len()
1717 }
1718
1719 extern "C" fn cb_associated_arch_by_addr<A>(
1720 ctxt: *mut c_void,
1721 addr: *mut u64,
1722 ) -> *mut BNArchitecture
1723 where
1724 A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
1725 {
1726 let custom_arch = unsafe { &*(ctxt as *mut A) };
1727 let addr = unsafe { &mut *addr };
1728
1729 custom_arch.associated_arch_by_addr(addr).handle
1730 }
1731
1732 extern "C" fn cb_instruction_info<A>(
1733 ctxt: *mut c_void,
1734 data: *const u8,
1735 addr: u64,
1736 len: usize,
1737 result: *mut BNInstructionInfo,
1738 ) -> bool
1739 where
1740 A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
1741 {
1742 let custom_arch = unsafe { &*(ctxt as *mut A) };
1743 let data = unsafe { std::slice::from_raw_parts(data, len) };
1744
1745 match custom_arch.instruction_info(data, addr) {
1746 Some(info) => {
1747 unsafe { *result = info.into() };
1749 true
1750 }
1751 None => false,
1752 }
1753 }
1754
1755 extern "C" fn cb_get_instruction_text<A>(
1756 ctxt: *mut c_void,
1757 data: *const u8,
1758 addr: u64,
1759 len: *mut usize,
1760 result: *mut *mut BNInstructionTextToken,
1761 count: *mut usize,
1762 ) -> bool
1763 where
1764 A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
1765 {
1766 let custom_arch = unsafe { &*(ctxt as *mut A) };
1767 let data = unsafe { std::slice::from_raw_parts(data, *len) };
1768 let result = unsafe { &mut *result };
1769
1770 let Some((res_size, res_tokens)) = custom_arch.instruction_text(data, addr) else {
1771 return false;
1772 };
1773
1774 let res_tokens: Box<[BNInstructionTextToken]> = res_tokens
1775 .into_iter()
1776 .map(InstructionTextToken::into_raw)
1777 .collect();
1778 unsafe {
1779 let res_tokens = Box::leak(res_tokens);
1781 *result = res_tokens.as_mut_ptr();
1782 *count = res_tokens.len();
1783 *len = res_size;
1784 }
1785 true
1786 }
1787
1788 pub unsafe extern "C" fn cb_get_instruction_text_with_context<A>(
1789 ctxt: *mut c_void,
1790 data: *const u8,
1791 addr: u64,
1792 len: *mut usize,
1793 context: *mut c_void,
1794 result: *mut *mut BNInstructionTextToken,
1795 count: *mut usize,
1796 ) -> bool
1797 where
1798 A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
1799 {
1800 let custom_arch = unsafe { &*(ctxt as *mut A) };
1801 let data = unsafe { std::slice::from_raw_parts(data, *len) };
1802 let result = unsafe { &mut *result };
1803 let context = NonNull::new(context);
1804
1805 let Some((res_size, res_tokens)) =
1806 custom_arch.instruction_text_with_context(data, addr, context)
1807 else {
1808 return false;
1809 };
1810
1811 let res_tokens: Box<[BNInstructionTextToken]> = res_tokens
1812 .into_iter()
1813 .map(InstructionTextToken::into_raw)
1814 .collect();
1815 unsafe {
1816 let res_tokens = Box::leak(res_tokens);
1818 *result = res_tokens.as_mut_ptr();
1819 *count = res_tokens.len();
1820 *len = res_size;
1821 }
1822 true
1823 }
1824
1825 extern "C" fn cb_free_instruction_text(tokens: *mut BNInstructionTextToken, count: usize) {
1826 unsafe {
1827 let raw_tokens = std::slice::from_raw_parts_mut(tokens, count);
1828 let boxed_tokens = Box::from_raw(raw_tokens);
1829 for token in boxed_tokens {
1830 InstructionTextToken::free_raw(token);
1831 }
1832 }
1833 }
1834
1835 extern "C" fn cb_instruction_llil<A>(
1836 ctxt: *mut c_void,
1837 data: *const u8,
1838 addr: u64,
1839 len: *mut usize,
1840 il: *mut BNLowLevelILFunction,
1841 ) -> bool
1842 where
1843 A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
1844 {
1845 let custom_arch = unsafe { &*(ctxt as *mut A) };
1846 let data = unsafe { std::slice::from_raw_parts(data, *len) };
1847 let lifter = unsafe {
1848 LowLevelILMutableFunction::from_raw_with_arch(il, Some(*custom_arch.as_ref()))
1849 };
1850
1851 match custom_arch.instruction_llil(data, addr, &lifter) {
1852 Some((res_len, res_value)) => {
1853 unsafe { *len = res_len };
1854 res_value
1855 }
1856 None => false,
1857 }
1858 }
1859
1860 extern "C" fn cb_supports_standalone_instruction_decoding<A>(ctxt: *mut c_void) -> bool
1861 where
1862 A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
1863 {
1864 let custom_arch = unsafe { &*(ctxt as *mut A) };
1865 custom_arch.supports_standalone_instruction_decoding()
1866 }
1867
1868 extern "C" fn cb_analyze_basic_blocks<A>(
1869 ctxt: *mut c_void,
1870 function: *mut BNFunction,
1871 context: *mut BNBasicBlockAnalysisContext,
1872 ) where
1873 A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
1874 {
1875 let custom_arch = unsafe { &*(ctxt as *mut A) };
1876 let mut function = unsafe { Function::from_raw(function) };
1877 let mut context: BasicBlockAnalysisContext =
1878 unsafe { BasicBlockAnalysisContext::from_raw(context) };
1879 custom_arch.analyze_basic_blocks(&mut function, &mut context);
1880 }
1881
1882 extern "C" fn cb_lift_function<A>(
1883 ctxt: *mut c_void,
1884 function: *mut BNLowLevelILFunction,
1885 context: *mut BNFunctionLifterContext,
1886 ) -> bool
1887 where
1888 A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
1889 {
1890 let custom_arch = unsafe { &*(ctxt as *mut A) };
1891 let llil = unsafe {
1892 LowLevelILMutableFunction::from_raw_with_arch(function, Some(*custom_arch.as_ref()))
1893 };
1894
1895 let mut ctx = unsafe {
1896 FunctionLifterContext::from_raw_with_arch(
1897 function,
1898 context,
1899 Some(*custom_arch.as_ref()),
1900 )
1901 };
1902 custom_arch.lift_function(llil, &mut ctx)
1903 }
1904
1905 extern "C" fn cb_reg_name<A>(ctxt: *mut c_void, reg: u32) -> *mut c_char
1906 where
1907 A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
1908 {
1909 let custom_arch = unsafe { &*(ctxt as *mut A) };
1910
1911 match custom_arch.register_from_id(reg.into()) {
1912 Some(reg) => BnString::into_raw(BnString::new(reg.name().as_ref())),
1913 None => BnString::into_raw(BnString::new("invalid_reg")),
1914 }
1915 }
1916
1917 extern "C" fn cb_flag_name<A>(ctxt: *mut c_void, flag: u32) -> *mut c_char
1918 where
1919 A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
1920 {
1921 let custom_arch = unsafe { &*(ctxt as *mut A) };
1922
1923 match custom_arch.flag_from_id(flag.into()) {
1924 Some(flag) => BnString::into_raw(BnString::new(flag.name().as_ref())),
1925 None => BnString::into_raw(BnString::new("invalid_flag")),
1926 }
1927 }
1928
1929 extern "C" fn cb_flag_write_name<A>(ctxt: *mut c_void, flag_write: u32) -> *mut c_char
1930 where
1931 A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
1932 {
1933 let custom_arch = unsafe { &*(ctxt as *mut A) };
1934
1935 match custom_arch.flag_write_from_id(flag_write.into()) {
1936 Some(flag_write) => BnString::into_raw(BnString::new(flag_write.name().as_ref())),
1937 None => BnString::into_raw(BnString::new("invalid_flag_write")),
1938 }
1939 }
1940
1941 extern "C" fn cb_semantic_flag_class_name<A>(ctxt: *mut c_void, class: u32) -> *mut c_char
1942 where
1943 A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
1944 {
1945 let custom_arch = unsafe { &*(ctxt as *mut A) };
1946
1947 match custom_arch.flag_class_from_id(class.into()) {
1948 Some(class) => BnString::into_raw(BnString::new(class.name().as_ref())),
1949 None => BnString::into_raw(BnString::new("invalid_flag_class")),
1950 }
1951 }
1952
1953 extern "C" fn cb_semantic_flag_group_name<A>(ctxt: *mut c_void, group: u32) -> *mut c_char
1954 where
1955 A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
1956 {
1957 let custom_arch = unsafe { &*(ctxt as *mut A) };
1958
1959 match custom_arch.flag_group_from_id(group.into()) {
1960 Some(group) => BnString::into_raw(BnString::new(group.name().as_ref())),
1961 None => BnString::into_raw(BnString::new("invalid_flag_group")),
1962 }
1963 }
1964
1965 extern "C" fn cb_registers_full_width<A>(ctxt: *mut c_void, count: *mut usize) -> *mut u32
1966 where
1967 A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
1968 {
1969 let custom_arch = unsafe { &*(ctxt as *mut A) };
1970 let mut regs: Box<[_]> = custom_arch
1971 .registers_full_width()
1972 .iter()
1973 .map(|r| r.id().0)
1974 .collect();
1975
1976 unsafe { *count = regs.len() };
1978 let regs_ptr = regs.as_mut_ptr();
1979 std::mem::forget(regs);
1980 regs_ptr
1981 }
1982
1983 extern "C" fn cb_registers_all<A>(ctxt: *mut c_void, count: *mut usize) -> *mut u32
1984 where
1985 A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
1986 {
1987 let custom_arch = unsafe { &*(ctxt as *mut A) };
1988 let mut regs: Box<[_]> = custom_arch
1989 .registers_all()
1990 .iter()
1991 .map(|r| r.id().0)
1992 .collect();
1993
1994 unsafe { *count = regs.len() };
1996 let regs_ptr = regs.as_mut_ptr();
1997 std::mem::forget(regs);
1998 regs_ptr
1999 }
2000
2001 extern "C" fn cb_registers_global<A>(ctxt: *mut c_void, count: *mut usize) -> *mut u32
2002 where
2003 A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
2004 {
2005 let custom_arch = unsafe { &*(ctxt as *mut A) };
2006 let mut regs: Box<[_]> = custom_arch
2007 .registers_global()
2008 .iter()
2009 .map(|r| r.id().0)
2010 .collect();
2011
2012 unsafe { *count = regs.len() };
2014 let regs_ptr = regs.as_mut_ptr();
2015 std::mem::forget(regs);
2016 regs_ptr
2017 }
2018
2019 extern "C" fn cb_registers_system<A>(ctxt: *mut c_void, count: *mut usize) -> *mut u32
2020 where
2021 A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
2022 {
2023 let custom_arch = unsafe { &*(ctxt as *mut A) };
2024 let mut regs: Box<[_]> = custom_arch
2025 .registers_system()
2026 .iter()
2027 .map(|r| r.id().0)
2028 .collect();
2029
2030 unsafe { *count = regs.len() };
2032 let regs_ptr = regs.as_mut_ptr();
2033 std::mem::forget(regs);
2034 regs_ptr
2035 }
2036
2037 extern "C" fn cb_flags<A>(ctxt: *mut c_void, count: *mut usize) -> *mut u32
2038 where
2039 A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
2040 {
2041 let custom_arch = unsafe { &*(ctxt as *mut A) };
2042 let mut flags: Box<[_]> = custom_arch.flags().iter().map(|f| f.id().0).collect();
2043
2044 unsafe { *count = flags.len() };
2046 let flags_ptr = flags.as_mut_ptr();
2047 std::mem::forget(flags);
2048 flags_ptr
2049 }
2050
2051 extern "C" fn cb_flag_write_types<A>(ctxt: *mut c_void, count: *mut usize) -> *mut u32
2052 where
2053 A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
2054 {
2055 let custom_arch = unsafe { &*(ctxt as *mut A) };
2056 let mut flag_writes: Box<[_]> = custom_arch
2057 .flag_write_types()
2058 .iter()
2059 .map(|f| f.id().0)
2060 .collect();
2061
2062 unsafe { *count = flag_writes.len() };
2064 let flags_ptr = flag_writes.as_mut_ptr();
2065 std::mem::forget(flag_writes);
2066 flags_ptr
2067 }
2068
2069 extern "C" fn cb_semantic_flag_classes<A>(ctxt: *mut c_void, count: *mut usize) -> *mut u32
2070 where
2071 A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
2072 {
2073 let custom_arch = unsafe { &*(ctxt as *mut A) };
2074 let mut flag_classes: Box<[_]> = custom_arch
2075 .flag_classes()
2076 .iter()
2077 .map(|f| f.id().0)
2078 .collect();
2079
2080 unsafe { *count = flag_classes.len() };
2082 let flags_ptr = flag_classes.as_mut_ptr();
2083 std::mem::forget(flag_classes);
2084 flags_ptr
2085 }
2086
2087 extern "C" fn cb_semantic_flag_groups<A>(ctxt: *mut c_void, count: *mut usize) -> *mut u32
2088 where
2089 A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
2090 {
2091 let custom_arch = unsafe { &*(ctxt as *mut A) };
2092 let mut flag_groups: Box<[_]> =
2093 custom_arch.flag_groups().iter().map(|f| f.id().0).collect();
2094
2095 unsafe { *count = flag_groups.len() };
2097 let flags_ptr = flag_groups.as_mut_ptr();
2098 std::mem::forget(flag_groups);
2099 flags_ptr
2100 }
2101
2102 extern "C" fn cb_flag_role<A>(ctxt: *mut c_void, flag: u32, class: u32) -> BNFlagRole
2103 where
2104 A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
2105 {
2106 let custom_arch = unsafe { &*(ctxt as *mut A) };
2107
2108 if let (Some(flag), class) = (
2109 custom_arch.flag_from_id(FlagId(flag)),
2110 custom_arch.flag_class_from_id(FlagClassId(class)),
2111 ) {
2112 flag.role(class)
2113 } else {
2114 FlagRole::SpecialFlagRole
2115 }
2116 }
2117
2118 extern "C" fn cb_flags_required_for_flag_cond<A>(
2119 ctxt: *mut c_void,
2120 cond: BNLowLevelILFlagCondition,
2121 class: u32,
2122 count: *mut usize,
2123 ) -> *mut u32
2124 where
2125 A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
2126 {
2127 let custom_arch = unsafe { &*(ctxt as *mut A) };
2128 let class = custom_arch.flag_class_from_id(FlagClassId(class));
2129 let mut flags: Box<[_]> = custom_arch
2130 .flags_required_for_flag_condition(cond, class)
2131 .iter()
2132 .map(|f| f.id().0)
2133 .collect();
2134
2135 unsafe { *count = flags.len() };
2137 let flags_ptr = flags.as_mut_ptr();
2138 std::mem::forget(flags);
2139 flags_ptr
2140 }
2141
2142 extern "C" fn cb_flags_required_for_semantic_flag_group<A>(
2143 ctxt: *mut c_void,
2144 group: u32,
2145 count: *mut usize,
2146 ) -> *mut u32
2147 where
2148 A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
2149 {
2150 let custom_arch = unsafe { &*(ctxt as *mut A) };
2151
2152 if let Some(group) = custom_arch.flag_group_from_id(FlagGroupId(group)) {
2153 let mut flags: Box<[_]> = group.flags_required().iter().map(|f| f.id().0).collect();
2154
2155 unsafe { *count = flags.len() };
2157 let flags_ptr = flags.as_mut_ptr();
2158 std::mem::forget(flags);
2159 flags_ptr
2160 } else {
2161 unsafe {
2162 *count = 0;
2163 }
2164 std::ptr::null_mut()
2165 }
2166 }
2167
2168 extern "C" fn cb_flag_conditions_for_semantic_flag_group<A>(
2169 ctxt: *mut c_void,
2170 group: u32,
2171 count: *mut usize,
2172 ) -> *mut BNFlagConditionForSemanticClass
2173 where
2174 A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
2175 {
2176 let custom_arch = unsafe { &*(ctxt as *mut A) };
2177
2178 if let Some(group) = custom_arch.flag_group_from_id(FlagGroupId(group)) {
2179 let flag_conditions = group.flag_conditions();
2180 let mut flags: Box<[_]> = flag_conditions
2181 .iter()
2182 .map(|(&class, &condition)| BNFlagConditionForSemanticClass {
2183 semanticClass: class.id().0,
2184 condition,
2185 })
2186 .collect();
2187
2188 unsafe { *count = flags.len() };
2190 let flags_ptr = flags.as_mut_ptr();
2191 std::mem::forget(flags);
2192 flags_ptr
2193 } else {
2194 unsafe {
2195 *count = 0;
2196 }
2197 std::ptr::null_mut()
2198 }
2199 }
2200
2201 extern "C" fn cb_free_flag_conditions_for_semantic_flag_group<A>(
2202 _ctxt: *mut c_void,
2203 conds: *mut BNFlagConditionForSemanticClass,
2204 count: usize,
2205 ) where
2206 A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
2207 {
2208 if conds.is_null() {
2209 return;
2210 }
2211
2212 unsafe {
2213 let flags_ptr = std::ptr::slice_from_raw_parts_mut(conds, count);
2214 let _flags = Box::from_raw(flags_ptr);
2215 }
2216 }
2217
2218 extern "C" fn cb_flags_written_by_write_type<A>(
2219 ctxt: *mut c_void,
2220 write_type: u32,
2221 count: *mut usize,
2222 ) -> *mut u32
2223 where
2224 A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
2225 {
2226 let custom_arch = unsafe { &*(ctxt as *mut A) };
2227
2228 if let Some(write_type) = custom_arch.flag_write_from_id(FlagWriteId(write_type)) {
2229 let mut flags_written: Box<[_]> = write_type
2230 .flags_written()
2231 .iter()
2232 .map(|f| f.id().0)
2233 .collect();
2234
2235 unsafe { *count = flags_written.len() };
2237 let flags_ptr = flags_written.as_mut_ptr();
2238 std::mem::forget(flags_written);
2239 flags_ptr
2240 } else {
2241 unsafe {
2242 *count = 0;
2243 }
2244 std::ptr::null_mut()
2245 }
2246 }
2247
2248 extern "C" fn cb_semantic_class_for_flag_write_type<A>(
2249 ctxt: *mut c_void,
2250 write_type: u32,
2251 ) -> u32
2252 where
2253 A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
2254 {
2255 let custom_arch = unsafe { &*(ctxt as *mut A) };
2256 custom_arch
2257 .flag_write_from_id(FlagWriteId(write_type))
2258 .map(|w| w.class())
2259 .and_then(|c| c.map(|c| c.id().0))
2260 .unwrap_or(0)
2261 }
2262
2263 extern "C" fn cb_flag_write_llil<A>(
2264 ctxt: *mut c_void,
2265 op: BNLowLevelILOperation,
2266 size: usize,
2267 flag_write: u32,
2268 flag: u32,
2269 operands_raw: *mut BNRegisterOrConstant,
2270 operand_count: usize,
2271 il: *mut BNLowLevelILFunction,
2272 ) -> usize
2273 where
2274 A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
2275 {
2276 let custom_arch = unsafe { &*(ctxt as *mut A) };
2277 let flag_write_type = custom_arch.flag_write_from_id(FlagWriteId(flag_write));
2278 let flag_value = custom_arch.flag_from_id(FlagId(flag));
2279 let operands = if operand_count == 0 {
2280 &[]
2281 } else {
2282 unsafe { std::slice::from_raw_parts(operands_raw, operand_count) }
2283 };
2284 let lifter = unsafe {
2285 LowLevelILMutableFunction::from_raw_with_arch(il, Some(*custom_arch.as_ref()))
2286 };
2287
2288 if let (Some(flag_write_type), Some(flag_value)) = (flag_write_type, flag_value) {
2289 let decoded_op = LowLevelILFlagWriteOp::from_op(custom_arch, size, op, operands);
2290 if let Some(expr) =
2291 custom_arch.flag_write_llil(flag_value, flag_write_type, decoded_op, &lifter)
2292 {
2293 return expr.index.0;
2295 }
2296
2297 let role = flag_value.role(flag_write_type.class());
2298
2299 unsafe {
2300 BNGetDefaultArchitectureFlagWriteLowLevelIL(
2301 custom_arch.as_ref().handle,
2302 op,
2303 size,
2304 role,
2305 operands_raw,
2306 operand_count,
2307 il,
2308 )
2309 }
2310 } else {
2311 lifter.unimplemented().index.0
2314 }
2315 }
2316
2317 extern "C" fn cb_flag_cond_llil<A>(
2318 ctxt: *mut c_void,
2319 cond: FlagCondition,
2320 class: u32,
2321 il: *mut BNLowLevelILFunction,
2322 ) -> usize
2323 where
2324 A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
2325 {
2326 let custom_arch = unsafe { &*(ctxt as *mut A) };
2327 let class = custom_arch.flag_class_from_id(FlagClassId(class));
2328
2329 let lifter = unsafe {
2330 LowLevelILMutableFunction::from_raw_with_arch(il, Some(*custom_arch.as_ref()))
2331 };
2332 if let Some(expr) = custom_arch.flag_cond_llil(cond, class, &lifter) {
2333 return expr.index.0;
2335 }
2336
2337 lifter.unimplemented().index.0
2338 }
2339
2340 extern "C" fn cb_flag_group_llil<A>(
2341 ctxt: *mut c_void,
2342 group: u32,
2343 il: *mut BNLowLevelILFunction,
2344 ) -> usize
2345 where
2346 A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
2347 {
2348 let custom_arch = unsafe { &*(ctxt as *mut A) };
2349 let lifter = unsafe {
2350 LowLevelILMutableFunction::from_raw_with_arch(il, Some(*custom_arch.as_ref()))
2351 };
2352
2353 if let Some(group) = custom_arch.flag_group_from_id(FlagGroupId(group)) {
2354 if let Some(expr) = custom_arch.flag_group_llil(group, &lifter) {
2355 return expr.index.0;
2357 }
2358 }
2359
2360 lifter.unimplemented().index.0
2361 }
2362
2363 extern "C" fn cb_free_register_list(_ctxt: *mut c_void, regs: *mut u32, count: usize) {
2364 if regs.is_null() {
2365 return;
2366 }
2367
2368 unsafe {
2369 let regs_ptr = std::ptr::slice_from_raw_parts_mut(regs, count);
2370 let _regs = Box::from_raw(regs_ptr);
2371 }
2372 }
2373
2374 extern "C" fn cb_register_info<A>(ctxt: *mut c_void, reg: u32, result: *mut BNRegisterInfo)
2375 where
2376 A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
2377 {
2378 let custom_arch = unsafe { &*(ctxt as *mut A) };
2379 let result = unsafe { &mut *result };
2380
2381 if let Some(reg) = custom_arch.register_from_id(RegisterId(reg)) {
2382 let info = reg.info();
2383
2384 result.fullWidthRegister = match info.parent() {
2385 Some(p) => p.id().0,
2386 None => reg.id().0,
2387 };
2388
2389 result.offset = info.offset();
2390 result.size = info.size();
2391 result.extend = info.implicit_extend().into();
2392 }
2393 }
2394
2395 extern "C" fn cb_stack_pointer<A>(ctxt: *mut c_void) -> u32
2396 where
2397 A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
2398 {
2399 let custom_arch = unsafe { &*(ctxt as *mut A) };
2400
2401 if let Some(reg) = custom_arch.stack_pointer_reg() {
2402 reg.id().0
2403 } else {
2404 INVALID_REGISTER
2405 }
2406 }
2407
2408 extern "C" fn cb_link_reg<A>(ctxt: *mut c_void) -> u32
2409 where
2410 A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
2411 {
2412 let custom_arch = unsafe { &*(ctxt as *mut A) };
2413
2414 if let Some(reg) = custom_arch.link_reg() {
2415 reg.id().0
2416 } else {
2417 INVALID_REGISTER
2418 }
2419 }
2420
2421 extern "C" fn cb_reg_stack_name<A>(ctxt: *mut c_void, stack: u32) -> *mut c_char
2422 where
2423 A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
2424 {
2425 let custom_arch = unsafe { &*(ctxt as *mut A) };
2426
2427 match custom_arch.register_stack_from_id(RegisterStackId(stack)) {
2428 Some(stack) => BnString::into_raw(BnString::new(stack.name().as_ref())),
2429 None => BnString::into_raw(BnString::new("invalid_reg_stack")),
2430 }
2431 }
2432
2433 extern "C" fn cb_reg_stacks<A>(ctxt: *mut c_void, count: *mut usize) -> *mut u32
2434 where
2435 A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
2436 {
2437 let custom_arch = unsafe { &*(ctxt as *mut A) };
2438 let mut regs: Box<[_]> = custom_arch
2439 .register_stacks()
2440 .iter()
2441 .map(|r| r.id().0)
2442 .collect();
2443
2444 unsafe { *count = regs.len() };
2446 let regs_ptr = regs.as_mut_ptr();
2447 std::mem::forget(regs);
2448 regs_ptr
2449 }
2450
2451 extern "C" fn cb_reg_stack_info<A>(
2452 ctxt: *mut c_void,
2453 stack: u32,
2454 result: *mut BNRegisterStackInfo,
2455 ) where
2456 A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
2457 {
2458 let custom_arch = unsafe { &*(ctxt as *mut A) };
2459 let result = unsafe { &mut *result };
2460
2461 if let Some(stack) = custom_arch.register_stack_from_id(RegisterStackId(stack)) {
2462 let info = stack.info();
2463
2464 let (reg, count) = info.storage_regs();
2465 result.firstStorageReg = reg.id().0;
2466 result.storageCount = count as u32;
2467
2468 if let Some((reg, count)) = info.top_relative_regs() {
2469 result.firstTopRelativeReg = reg.id().0;
2470 result.topRelativeCount = count as u32;
2471 } else {
2472 result.firstTopRelativeReg = INVALID_REGISTER;
2473 result.topRelativeCount = 0;
2474 }
2475
2476 result.stackTopReg = info.stack_top_reg().id().0;
2477 }
2478 }
2479
2480 extern "C" fn cb_intrinsic_class<A>(ctxt: *mut c_void, intrinsic: u32) -> BNIntrinsicClass
2481 where
2482 A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
2483 {
2484 let custom_arch = unsafe { &*(ctxt as *mut A) };
2485 custom_arch.intrinsic_class(IntrinsicId(intrinsic))
2486 }
2487
2488 extern "C" fn cb_intrinsic_name<A>(ctxt: *mut c_void, intrinsic: u32) -> *mut c_char
2489 where
2490 A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
2491 {
2492 let custom_arch = unsafe { &*(ctxt as *mut A) };
2493 match custom_arch.intrinsic_from_id(IntrinsicId(intrinsic)) {
2494 Some(intrinsic) => BnString::into_raw(BnString::new(intrinsic.name())),
2495 None => BnString::into_raw(BnString::new("invalid_intrinsic")),
2496 }
2497 }
2498
2499 extern "C" fn cb_intrinsics<A>(ctxt: *mut c_void, count: *mut usize) -> *mut u32
2500 where
2501 A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
2502 {
2503 let custom_arch = unsafe { &*(ctxt as *mut A) };
2504 let mut intrinsics: Box<[_]> = custom_arch.intrinsics().iter().map(|i| i.id().0).collect();
2505
2506 unsafe { *count = intrinsics.len() };
2508 let intrinsics_ptr = intrinsics.as_mut_ptr();
2509 std::mem::forget(intrinsics);
2510 intrinsics_ptr
2511 }
2512
2513 extern "C" fn cb_intrinsic_inputs<A>(
2514 ctxt: *mut c_void,
2515 intrinsic: u32,
2516 count: *mut usize,
2517 ) -> *mut BNNameAndType
2518 where
2519 A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
2520 {
2521 let custom_arch = unsafe { &*(ctxt as *mut A) };
2522
2523 let Some(intrinsic) = custom_arch.intrinsic_from_id(IntrinsicId(intrinsic)) else {
2524 unsafe {
2526 *count = 0;
2527 }
2528 return std::ptr::null_mut();
2529 };
2530
2531 let inputs = intrinsic.inputs();
2532 let raw_inputs: Box<[_]> = inputs.into_iter().map(NameAndType::into_raw).collect();
2534
2535 unsafe {
2537 *count = raw_inputs.len();
2538 }
2539
2540 if raw_inputs.is_empty() {
2541 std::ptr::null_mut()
2542 } else {
2543 Box::leak(raw_inputs).as_mut_ptr()
2545 }
2546 }
2547
2548 extern "C" fn cb_free_name_and_types<A>(
2549 _ctxt: *mut c_void,
2550 nt: *mut BNNameAndType,
2551 count: usize,
2552 ) where
2553 A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
2554 {
2555 if nt.is_null() {
2556 return;
2557 }
2558
2559 let nt_ptr = std::ptr::slice_from_raw_parts_mut(nt, count);
2561 let boxed_name_and_types = unsafe { Box::from_raw(nt_ptr) };
2563 for nt in boxed_name_and_types {
2564 NameAndType::free_raw(nt);
2565 }
2566 }
2567
2568 extern "C" fn cb_intrinsic_outputs<A>(
2569 ctxt: *mut c_void,
2570 intrinsic: u32,
2571 count: *mut usize,
2572 ) -> *mut BNTypeWithConfidence
2573 where
2574 A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
2575 {
2576 let custom_arch = unsafe { &*(ctxt as *mut A) };
2577
2578 let Some(intrinsic) = custom_arch.intrinsic_from_id(IntrinsicId(intrinsic)) else {
2579 unsafe {
2581 *count = 0;
2582 }
2583 return std::ptr::null_mut();
2584 };
2585
2586 let outputs = intrinsic.outputs();
2587 let raw_outputs: Box<[BNTypeWithConfidence]> = outputs
2588 .into_iter()
2589 .map(Conf::<Ref<Type>>::into_raw)
2591 .collect();
2592
2593 unsafe {
2595 *count = raw_outputs.len();
2596 }
2597
2598 if raw_outputs.is_empty() {
2599 std::ptr::null_mut()
2600 } else {
2601 Box::leak(raw_outputs).as_mut_ptr()
2603 }
2604 }
2605
2606 extern "C" fn cb_free_type_list<A>(
2607 ctxt: *mut c_void,
2608 tl: *mut BNTypeWithConfidence,
2609 count: usize,
2610 ) where
2611 A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
2612 {
2613 let _custom_arch = unsafe { &*(ctxt as *mut A) };
2614 if !tl.is_null() {
2615 let boxed_types =
2616 unsafe { Box::from_raw(std::ptr::slice_from_raw_parts_mut(tl, count)) };
2617 for ty in boxed_types {
2618 Conf::<Ref<Type>>::free_raw(ty);
2619 }
2620 }
2621 }
2622
2623 extern "C" fn cb_can_assemble<A>(ctxt: *mut c_void) -> bool
2624 where
2625 A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
2626 {
2627 let custom_arch = unsafe { &*(ctxt as *mut A) };
2628 custom_arch.can_assemble()
2629 }
2630
2631 extern "C" fn cb_assemble<A>(
2632 ctxt: *mut c_void,
2633 code: *const c_char,
2634 addr: u64,
2635 buffer: *mut BNDataBuffer,
2636 errors: *mut *mut c_char,
2637 ) -> bool
2638 where
2639 A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
2640 {
2641 let custom_arch = unsafe { &*(ctxt as *mut A) };
2642 let code = raw_to_string(code).unwrap_or("".into());
2643 let mut buffer = DataBuffer::from_raw(buffer);
2644
2645 let result = match custom_arch.assemble(&code, addr) {
2646 Ok(result) => {
2647 buffer.set_data(&result);
2648 unsafe {
2649 *errors = BnString::into_raw(BnString::new(""));
2650 }
2651 true
2652 }
2653 Err(result) => {
2654 unsafe {
2655 *errors = BnString::into_raw(BnString::new(result));
2656 }
2657 false
2658 }
2659 };
2660
2661 std::mem::forget(buffer);
2663
2664 result
2665 }
2666
2667 extern "C" fn cb_is_never_branch_patch_available<A>(
2668 ctxt: *mut c_void,
2669 data: *const u8,
2670 addr: u64,
2671 len: usize,
2672 ) -> bool
2673 where
2674 A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
2675 {
2676 let custom_arch = unsafe { &*(ctxt as *mut A) };
2677 let data = unsafe { std::slice::from_raw_parts(data, len) };
2678 custom_arch.is_never_branch_patch_available(data, addr)
2679 }
2680
2681 extern "C" fn cb_is_always_branch_patch_available<A>(
2682 ctxt: *mut c_void,
2683 data: *const u8,
2684 addr: u64,
2685 len: usize,
2686 ) -> bool
2687 where
2688 A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
2689 {
2690 let custom_arch = unsafe { &*(ctxt as *mut A) };
2691 let data = unsafe { std::slice::from_raw_parts(data, len) };
2692 custom_arch.is_always_branch_patch_available(data, addr)
2693 }
2694
2695 extern "C" fn cb_is_invert_branch_patch_available<A>(
2696 ctxt: *mut c_void,
2697 data: *const u8,
2698 addr: u64,
2699 len: usize,
2700 ) -> bool
2701 where
2702 A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
2703 {
2704 let custom_arch = unsafe { &*(ctxt as *mut A) };
2705 let data = unsafe { std::slice::from_raw_parts(data, len) };
2706 custom_arch.is_invert_branch_patch_available(data, addr)
2707 }
2708
2709 extern "C" fn cb_is_skip_and_return_zero_patch_available<A>(
2710 ctxt: *mut c_void,
2711 data: *const u8,
2712 addr: u64,
2713 len: usize,
2714 ) -> bool
2715 where
2716 A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
2717 {
2718 let custom_arch = unsafe { &*(ctxt as *mut A) };
2719 let data = unsafe { std::slice::from_raw_parts(data, len) };
2720 custom_arch.is_skip_and_return_zero_patch_available(data, addr)
2721 }
2722
2723 extern "C" fn cb_is_skip_and_return_value_patch_available<A>(
2724 ctxt: *mut c_void,
2725 data: *const u8,
2726 addr: u64,
2727 len: usize,
2728 ) -> bool
2729 where
2730 A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
2731 {
2732 let custom_arch = unsafe { &*(ctxt as *mut A) };
2733 let data = unsafe { std::slice::from_raw_parts(data, len) };
2734 custom_arch.is_skip_and_return_value_patch_available(data, addr)
2735 }
2736
2737 extern "C" fn cb_convert_to_nop<A>(
2738 ctxt: *mut c_void,
2739 data: *mut u8,
2740 addr: u64,
2741 len: usize,
2742 ) -> bool
2743 where
2744 A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
2745 {
2746 let custom_arch = unsafe { &*(ctxt as *mut A) };
2747 let data = unsafe { std::slice::from_raw_parts_mut(data, len) };
2748 custom_arch.convert_to_nop(data, addr)
2749 }
2750
2751 extern "C" fn cb_always_branch<A>(
2752 ctxt: *mut c_void,
2753 data: *mut u8,
2754 addr: u64,
2755 len: usize,
2756 ) -> bool
2757 where
2758 A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
2759 {
2760 let custom_arch = unsafe { &*(ctxt as *mut A) };
2761 let data = unsafe { std::slice::from_raw_parts_mut(data, len) };
2762 custom_arch.always_branch(data, addr)
2763 }
2764
2765 extern "C" fn cb_invert_branch<A>(
2766 ctxt: *mut c_void,
2767 data: *mut u8,
2768 addr: u64,
2769 len: usize,
2770 ) -> bool
2771 where
2772 A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
2773 {
2774 let custom_arch = unsafe { &*(ctxt as *mut A) };
2775 let data = unsafe { std::slice::from_raw_parts_mut(data, len) };
2776 custom_arch.invert_branch(data, addr)
2777 }
2778
2779 extern "C" fn cb_skip_and_return_value<A>(
2780 ctxt: *mut c_void,
2781 data: *mut u8,
2782 addr: u64,
2783 len: usize,
2784 val: u64,
2785 ) -> bool
2786 where
2787 A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
2788 {
2789 let custom_arch = unsafe { &*(ctxt as *mut A) };
2790 let data = unsafe { std::slice::from_raw_parts_mut(data, len) };
2791 custom_arch.skip_and_return_value(data, addr, val)
2792 }
2793
2794 let uninit_arch = ArchitectureBuilder {
2795 arch: MaybeUninit::zeroed(),
2796 func: Some(func),
2797 };
2798
2799 let raw = Box::into_raw(Box::new(uninit_arch));
2800 let mut custom_arch = BNCustomArchitecture {
2801 context: raw as *mut _,
2802 init: Some(cb_init::<A, F>),
2803 getEndianness: Some(cb_endianness::<A>),
2804 getAddressSize: Some(cb_address_size::<A>),
2805 getDefaultIntegerSize: Some(cb_default_integer_size::<A>),
2806 getInstructionAlignment: Some(cb_instruction_alignment::<A>),
2807 getMaxInstructionLength: Some(cb_max_instr_len::<A>),
2809 getOpcodeDisplayLength: Some(cb_opcode_display_len::<A>),
2811 getAssociatedArchitectureByAddress: Some(cb_associated_arch_by_addr::<A>),
2812 getInstructionInfo: Some(cb_instruction_info::<A>),
2813 getInstructionText: Some(cb_get_instruction_text::<A>),
2814 getInstructionTextWithContext: Some(cb_get_instruction_text_with_context::<A>),
2815 freeInstructionText: Some(cb_free_instruction_text),
2816 getInstructionLowLevelIL: Some(cb_instruction_llil::<A>),
2817 analyzeBasicBlocks: Some(cb_analyze_basic_blocks::<A>),
2818 liftFunction: Some(cb_lift_function::<A>),
2819 freeFunctionArchContext: None,
2820
2821 getRegisterName: Some(cb_reg_name::<A>),
2822 getFlagName: Some(cb_flag_name::<A>),
2823 getFlagWriteTypeName: Some(cb_flag_write_name::<A>),
2824 getSemanticFlagClassName: Some(cb_semantic_flag_class_name::<A>),
2825 getSemanticFlagGroupName: Some(cb_semantic_flag_group_name::<A>),
2826
2827 getFullWidthRegisters: Some(cb_registers_full_width::<A>),
2828 getAllRegisters: Some(cb_registers_all::<A>),
2829 getAllFlags: Some(cb_flags::<A>),
2830 getAllFlagWriteTypes: Some(cb_flag_write_types::<A>),
2831 getAllSemanticFlagClasses: Some(cb_semantic_flag_classes::<A>),
2832 getAllSemanticFlagGroups: Some(cb_semantic_flag_groups::<A>),
2833
2834 getFlagRole: Some(cb_flag_role::<A>),
2835 getFlagsRequiredForFlagCondition: Some(cb_flags_required_for_flag_cond::<A>),
2836
2837 getFlagsRequiredForSemanticFlagGroup: Some(cb_flags_required_for_semantic_flag_group::<A>),
2838 getFlagConditionsForSemanticFlagGroup: Some(
2839 cb_flag_conditions_for_semantic_flag_group::<A>,
2840 ),
2841 freeFlagConditionsForSemanticFlagGroup: Some(
2842 cb_free_flag_conditions_for_semantic_flag_group::<A>,
2843 ),
2844
2845 getFlagsWrittenByFlagWriteType: Some(cb_flags_written_by_write_type::<A>),
2846 getSemanticClassForFlagWriteType: Some(cb_semantic_class_for_flag_write_type::<A>),
2847
2848 getFlagWriteLowLevelIL: Some(cb_flag_write_llil::<A>),
2849 getFlagConditionLowLevelIL: Some(cb_flag_cond_llil::<A>),
2850 getSemanticFlagGroupLowLevelIL: Some(cb_flag_group_llil::<A>),
2851
2852 freeRegisterList: Some(cb_free_register_list),
2853 getRegisterInfo: Some(cb_register_info::<A>),
2854 getStackPointerRegister: Some(cb_stack_pointer::<A>),
2855 getLinkRegister: Some(cb_link_reg::<A>),
2856 getGlobalRegisters: Some(cb_registers_global::<A>),
2857 getSystemRegisters: Some(cb_registers_system::<A>),
2858
2859 getRegisterStackName: Some(cb_reg_stack_name::<A>),
2860 getAllRegisterStacks: Some(cb_reg_stacks::<A>),
2861 getRegisterStackInfo: Some(cb_reg_stack_info::<A>),
2862
2863 getIntrinsicClass: Some(cb_intrinsic_class::<A>),
2864 getIntrinsicName: Some(cb_intrinsic_name::<A>),
2865 getAllIntrinsics: Some(cb_intrinsics::<A>),
2866 getIntrinsicInputs: Some(cb_intrinsic_inputs::<A>),
2867 freeNameAndTypeList: Some(cb_free_name_and_types::<A>),
2868 getIntrinsicOutputs: Some(cb_intrinsic_outputs::<A>),
2869 freeTypeList: Some(cb_free_type_list::<A>),
2870
2871 canAssemble: Some(cb_can_assemble::<A>),
2872 assemble: Some(cb_assemble::<A>),
2873
2874 isNeverBranchPatchAvailable: Some(cb_is_never_branch_patch_available::<A>),
2875 isAlwaysBranchPatchAvailable: Some(cb_is_always_branch_patch_available::<A>),
2876 isInvertBranchPatchAvailable: Some(cb_is_invert_branch_patch_available::<A>),
2877 isSkipAndReturnZeroPatchAvailable: Some(cb_is_skip_and_return_zero_patch_available::<A>),
2878 isSkipAndReturnValuePatchAvailable: Some(cb_is_skip_and_return_value_patch_available::<A>),
2879
2880 convertToNop: Some(cb_convert_to_nop::<A>),
2881 alwaysBranch: Some(cb_always_branch::<A>),
2882 invertBranch: Some(cb_invert_branch::<A>),
2883 skipAndReturnValue: Some(cb_skip_and_return_value::<A>),
2884 getLinearSweepInitialAlignment: Some(cb_linear_sweep_initial_alignment::<A>),
2885 getLinearSweepAnalysisCapabilities: Some(cb_linear_sweep_analysis_capabilities::<A>),
2886 supportsStandaloneInstructionDecoding: Some(
2887 cb_supports_standalone_instruction_decoding::<A>,
2888 ),
2889 };
2890
2891 customize(&mut custom_arch);
2892
2893 unsafe {
2894 match registration {
2895 ArchitectureRegistration::Hook(base) => {
2896 let previous = BNRegisterArchitectureHook(base.handle, &mut custom_arch);
2899 assert!(!previous.is_null());
2900 cb_init::<A, F>(raw.cast(), previous);
2901 BNFinalizeArchitectureHook(base.handle);
2904 }
2905 ArchitectureRegistration::New(name) => {
2906 let name = name.to_cstr();
2907 let res = BNRegisterArchitecture(name.as_ptr(), &mut custom_arch);
2908 assert!(!res.is_null());
2909 }
2910 }
2911
2912 (*raw).arch.assume_init_mut()
2913 }
2914}
2915
2916pub fn register_architecture_with_function_context<A, F>(name: &str, func: F) -> &'static A
2917where
2918 A: 'static
2919 + ArchitectureWithFunctionContext<Handle = CustomArchitectureHandle<A>>
2920 + Send
2921 + Sync
2922 + Sized,
2923 F: FnOnce(CustomArchitectureHandle<A>, CoreArchitecture) -> A,
2924{
2925 unsafe extern "C" fn cb_free_function_arch_context_typed<A>(
2926 _ctxt: *mut c_void,
2927 context: *mut c_void,
2928 ) where
2929 A: 'static
2930 + ArchitectureWithFunctionContext<Handle = CustomArchitectureHandle<A>>
2931 + Send
2932 + Sync,
2933 {
2934 if context.is_null() {
2935 return;
2936 }
2937 let _ = unsafe { Box::from_raw(context as *mut A::FunctionArchContext) };
2940 }
2941
2942 unsafe extern "C" fn cb_get_instruction_text_with_context_typed<A>(
2943 ctxt: *mut c_void,
2944 data: *const u8,
2945 addr: u64,
2946 len: *mut usize,
2947 context: *mut c_void,
2948 result: *mut *mut BNInstructionTextToken,
2949 count: *mut usize,
2950 ) -> bool
2951 where
2952 A: 'static
2953 + ArchitectureWithFunctionContext<Handle = CustomArchitectureHandle<A>>
2954 + Send
2955 + Sync,
2956 {
2957 let custom_arch = unsafe { &*(ctxt as *mut A) };
2958 let data = unsafe { std::slice::from_raw_parts(data, *len) };
2959 let result = unsafe { &mut *result };
2960 let typed_context: Option<&A::FunctionArchContext> = if context.is_null() {
2961 None
2962 } else {
2963 Some(unsafe { &*(context as *const A::FunctionArchContext) })
2964 };
2965
2966 let Some((res_size, res_tokens)) =
2967 custom_arch.instruction_text_with_typed_context(data, addr, typed_context)
2968 else {
2969 return false;
2970 };
2971
2972 let res_tokens: Box<[BNInstructionTextToken]> = res_tokens
2973 .into_iter()
2974 .map(InstructionTextToken::into_raw)
2975 .collect();
2976 unsafe {
2977 let res_tokens = Box::leak(res_tokens);
2978 *result = res_tokens.as_mut_ptr();
2979 *count = res_tokens.len();
2980 *len = res_size;
2981 }
2982 true
2983 }
2984
2985 register_architecture_impl(ArchitectureRegistration::New(name), func, |custom_arch| {
2986 custom_arch.freeFunctionArchContext = Some(cb_free_function_arch_context_typed::<A>);
2987 custom_arch.getInstructionTextWithContext =
2988 Some(cb_get_instruction_text_with_context_typed::<A>);
2989 })
2990}
2991
2992#[derive(Debug)]
2993pub struct CustomArchitectureHandle<A>
2994where
2995 A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync,
2996{
2997 handle: *mut A,
2998}
2999
3000unsafe impl<A> Send for CustomArchitectureHandle<A> where
3001 A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync
3002{
3003}
3004
3005unsafe impl<A> Sync for CustomArchitectureHandle<A> where
3006 A: 'static + Architecture<Handle = CustomArchitectureHandle<A>> + Send + Sync
3007{
3008}
3009
3010impl<A> Clone for CustomArchitectureHandle<A>
3011where
3012 A: 'static + Architecture<Handle = Self> + Send + Sync,
3013{
3014 fn clone(&self) -> Self {
3015 *self
3016 }
3017}
3018
3019impl<A> Copy for CustomArchitectureHandle<A> where
3020 A: 'static + Architecture<Handle = Self> + Send + Sync
3021{
3022}
3023
3024impl<A> Borrow<A> for CustomArchitectureHandle<A>
3025where
3026 A: 'static + Architecture<Handle = Self> + Send + Sync,
3027{
3028 fn borrow(&self) -> &A {
3029 unsafe { &*self.handle }
3030 }
3031}