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