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