binaryninja/architecture/
hook.rs1use super::*;
18
19macro_rules! architecture_hook {
21 ($(fn $name:ident $(<$lt:lifetime>)? ($($arg:ident: $ty:ty),* $(,)?) -> $ret:ty;)*) => {
22 pub trait ArchitectureHook: Send + Sync + 'static {
37 $(
38 #[doc = concat!("See [`Architecture::", stringify!($name), "`].")]
39 fn $name $(<$lt>)? (&self, base: &CoreArchitecture, $($arg: $ty),*) -> $ret {
40 base.$name($($arg),*)
41 }
42 )*
43 }
44
45 impl<H: ArchitectureHook> Architecture for HookArchitecture<H> {
46 type Handle = CustomArchitectureHandle<Self>;
47 type RegisterInfo = CoreRegisterInfo;
48 type Register = CoreRegister;
49 type RegisterStackInfo = CoreRegisterStackInfo;
50 type RegisterStack = CoreRegisterStack;
51 type Flag = CoreFlag;
52 type FlagWrite = CoreFlagWrite;
53 type FlagClass = CoreFlagClass;
54 type FlagGroup = CoreFlagGroup;
55 type Intrinsic = CoreIntrinsic;
56
57 $(
58 fn $name $(<$lt>)? (&self, $($arg: $ty),*) -> $ret {
59 self.hook.$name(&self.base, $($arg),*)
60 }
61 )*
62
63 fn handle(&self) -> Self::Handle {
64 self.handle
65 }
66 }
67 };
68}
69
70architecture_hook! {
71 fn endianness() -> Endianness;
72 fn address_size() -> usize;
73 fn default_integer_size() -> usize;
74 fn instruction_alignment() -> usize;
75 fn linear_sweep_initial_alignment() -> usize;
76 fn linear_sweep_analysis_capabilities() -> u32;
77 fn max_instr_len() -> usize;
78 fn opcode_display_len() -> usize;
79 fn associated_arch_by_addr(addr: &mut u64) -> CoreArchitecture;
80 fn instruction_info(data: &[u8], addr: u64) -> Option<InstructionInfo>;
81 fn instruction_text(data: &[u8], addr: u64) -> Option<(usize, Vec<InstructionTextToken>)>;
82 fn instruction_text_with_context(
83 data: &[u8],
84 addr: u64,
85 context: Option<NonNull<c_void>>,
86 ) -> Option<(usize, Vec<InstructionTextToken>)>;
87 fn instruction_llil(
88 data: &[u8],
89 addr: u64,
90 il: &LowLevelILMutableFunction,
91 ) -> Option<(usize, bool)>;
92 fn analyze_basic_blocks(function: &mut Function, context: &mut BasicBlockAnalysisContext) -> ();
93 fn lift_function(
94 function: LowLevelILMutableFunction,
95 context: &mut FunctionLifterContext,
96 ) -> bool;
97 fn flag_write_llil<'a>(
98 flag: CoreFlag,
99 flag_write_type: CoreFlagWrite,
100 op: LowLevelILFlagWriteOp<CoreRegister>,
101 il: &'a LowLevelILMutableFunction,
102 ) -> Option<LowLevelILMutableExpression<'a, ValueExpr>>;
103 fn flags_required_for_flag_condition(
104 condition: FlagCondition,
105 class: Option<CoreFlagClass>,
106 ) -> Vec<CoreFlag>;
107 fn flag_cond_llil<'a>(
108 cond: FlagCondition,
109 class: Option<CoreFlagClass>,
110 il: &'a LowLevelILMutableFunction,
111 ) -> Option<LowLevelILMutableExpression<'a, ValueExpr>>;
112 fn flag_group_llil<'a>(
113 group: CoreFlagGroup,
114 il: &'a LowLevelILMutableFunction,
115 ) -> Option<LowLevelILMutableExpression<'a, ValueExpr>>;
116 fn registers_all() -> Vec<CoreRegister>;
117 fn register_from_id(id: RegisterId) -> Option<CoreRegister>;
118 fn registers_full_width() -> Vec<CoreRegister>;
119 fn registers_global() -> Vec<CoreRegister>;
120 fn registers_system() -> Vec<CoreRegister>;
121 fn stack_pointer_reg() -> Option<CoreRegister>;
122 fn link_reg() -> Option<CoreRegister>;
123 fn register_stacks() -> Vec<CoreRegisterStack>;
124 fn register_stack_from_id(id: RegisterStackId) -> Option<CoreRegisterStack>;
125 fn flags() -> Vec<CoreFlag>;
126 fn flag_from_id(id: FlagId) -> Option<CoreFlag>;
127 fn flag_write_types() -> Vec<CoreFlagWrite>;
128 fn flag_write_from_id(id: FlagWriteId) -> Option<CoreFlagWrite>;
129 fn flag_classes() -> Vec<CoreFlagClass>;
130 fn flag_class_from_id(id: FlagClassId) -> Option<CoreFlagClass>;
131 fn flag_groups() -> Vec<CoreFlagGroup>;
132 fn flag_group_from_id(id: FlagGroupId) -> Option<CoreFlagGroup>;
133 fn intrinsics() -> Vec<CoreIntrinsic>;
134 fn intrinsic_class(id: IntrinsicId) -> BNIntrinsicClass;
135 fn intrinsic_from_id(id: IntrinsicId) -> Option<CoreIntrinsic>;
136 fn can_assemble() -> bool;
137 fn assemble(code: &str, addr: u64) -> Result<Vec<u8>, String>;
138 fn is_never_branch_patch_available(data: &[u8], addr: u64) -> bool;
139 fn is_always_branch_patch_available(data: &[u8], addr: u64) -> bool;
140 fn is_invert_branch_patch_available(data: &[u8], addr: u64) -> bool;
141 fn is_skip_and_return_zero_patch_available(data: &[u8], addr: u64) -> bool;
142 fn is_skip_and_return_value_patch_available(data: &[u8], addr: u64) -> bool;
143 fn convert_to_nop(data: &mut [u8], addr: u64) -> bool;
144 fn always_branch(data: &mut [u8], addr: u64) -> bool;
145 fn invert_branch(data: &mut [u8], addr: u64) -> bool;
146 fn skip_and_return_value(data: &mut [u8], addr: u64, value: u64) -> bool;
147}
148
149struct HookArchitecture<H: ArchitectureHook> {
150 hook: H,
151 base: CoreArchitecture,
152 handle: CustomArchitectureHandle<Self>,
153}
154
155impl<H: ArchitectureHook> AsRef<CoreArchitecture> for HookArchitecture<H> {
156 fn as_ref(&self) -> &CoreArchitecture {
157 &self.base
158 }
159}
160
161pub fn register_architecture_hook<H: ArchitectureHook>(
189 base: CoreArchitecture,
190 hook: H,
191) -> &'static H {
192 unsafe extern "C" fn free_function_arch_context<H: ArchitectureHook>(
193 context: *mut c_void,
194 function_context: *mut c_void,
195 ) {
196 let arch = unsafe { &*context.cast::<HookArchitecture<H>>() };
197 unsafe { BNArchitectureFreeFunctionArchContext(arch.base.handle, function_context) };
200 }
201
202 let registered = super::register_architecture_impl(
203 ArchitectureRegistration::Hook(base),
204 |handle, base| HookArchitecture { hook, base, handle },
205 |callbacks| {
206 callbacks.freeFunctionArchContext = Some(free_function_arch_context::<H>);
207 },
208 );
209 ®istered.hook
210}