1#![allow(non_camel_case_types)]
2
3use alloc::rc::Weak;
4use core::{cell::UnsafeCell, ffi::c_void};
5
6pub use unicorn_engine_sys::{self as sys, uc_context, uc_engine, uc_hook};
7
8use crate::{Unicorn, UnicornInner};
9
10pub struct UcHook<'a, D: 'a, F: 'a> {
11 pub callback: F,
12 pub uc: Weak<UnsafeCell<UnicornInner<'a, D>>>,
13}
14
15pub trait IsUcHook<'a> {}
16
17impl<'a, D, F> IsUcHook<'a> for UcHook<'a, D, F> {}
18
19pub extern "C" fn mmio_read_callback_proxy<D, F>(
23 uc: *mut uc_engine,
24 offset: u64,
25 size: u32,
26 user_data: *mut c_void,
28) -> u64
29where
30 F: FnMut(&mut crate::Unicorn<D>, u64, usize) -> u64,
31{
32 let user_data = unsafe { &mut *user_data.cast::<UcHook<D, F>>() };
33 let mut user_data_uc = Unicorn {
34 inner: user_data.uc.upgrade().unwrap(),
35 };
36 debug_assert_eq!(uc, user_data_uc.get_handle());
37 (user_data.callback)(&mut user_data_uc, offset, size as usize)
38}
39
40pub unsafe extern "C" fn mmio_write_callback_proxy<D, F>(
44 uc: *mut uc_engine,
45 offset: u64,
46 size: u32,
47 value: u64,
48 user_data: *mut c_void,
49) where
50 F: FnMut(&mut crate::Unicorn<D>, u64, usize, u64),
51{
52 let user_data = unsafe { &mut *user_data.cast::<UcHook<D, F>>() };
53 let mut user_data_uc = Unicorn {
54 inner: user_data.uc.upgrade().unwrap(),
55 };
56 debug_assert_eq!(uc, user_data_uc.get_handle());
57 (user_data.callback)(&mut user_data_uc, offset, size as usize, value);
58}
59
60pub unsafe extern "C" fn code_hook_proxy<D, F>(
64 uc: *mut uc_engine,
65 address: u64,
66 size: u32,
67 user_data: *mut UcHook<D, F>,
68) where
69 F: FnMut(&mut crate::Unicorn<D>, u64, u32),
70{
71 let user_data = unsafe { &mut *user_data };
72 let mut user_data_uc = Unicorn {
73 inner: user_data.uc.upgrade().unwrap(),
74 };
75 debug_assert_eq!(uc, user_data_uc.get_handle());
76 (user_data.callback)(&mut user_data_uc, address, size);
77}
78
79pub unsafe extern "C" fn block_hook_proxy<D, F>(
83 uc: *mut uc_engine,
84 address: u64,
85 size: u32,
86 user_data: *mut UcHook<D, F>,
87) where
88 F: FnMut(&mut crate::Unicorn<D>, u64, u32),
89{
90 let user_data = unsafe { &mut *user_data };
91 let mut user_data_uc = Unicorn {
92 inner: user_data.uc.upgrade().unwrap(),
93 };
94 debug_assert_eq!(uc, user_data_uc.get_handle());
95 (user_data.callback)(&mut user_data_uc, address, size);
96}
97
98pub unsafe extern "C" fn mem_hook_proxy<D, F>(
102 uc: *mut uc_engine,
103 mem_type: sys::MemType,
104 address: u64,
105 size: u32,
106 value: i64,
107 user_data: *mut UcHook<D, F>,
108) -> bool
109where
110 F: FnMut(&mut crate::Unicorn<D>, sys::MemType, u64, usize, i64) -> bool,
111{
112 let user_data = unsafe { &mut *user_data };
113 let mut user_data_uc = Unicorn {
114 inner: user_data.uc.upgrade().unwrap(),
115 };
116 debug_assert_eq!(uc, user_data_uc.get_handle());
117 (user_data.callback)(&mut user_data_uc, mem_type, address, size as usize, value)
118}
119
120pub unsafe extern "C" fn intr_hook_proxy<D, F>(
124 uc: *mut uc_engine,
125 value: u32,
126 user_data: *mut UcHook<D, F>,
127) where
128 F: FnMut(&mut crate::Unicorn<D>, u32),
129{
130 let user_data = unsafe { &mut *user_data };
131 let mut user_data_uc = Unicorn {
132 inner: user_data.uc.upgrade().unwrap(),
133 };
134 debug_assert_eq!(uc, user_data_uc.get_handle());
135 (user_data.callback)(&mut user_data_uc, value);
136}
137
138pub unsafe extern "C" fn insn_in_hook_proxy<D, F>(
142 uc: *mut uc_engine,
143 port: u32,
144 size: usize,
145 user_data: *mut UcHook<D, F>,
146) -> u32
147where
148 F: FnMut(&mut crate::Unicorn<D>, u32, usize) -> u32,
149{
150 let user_data = unsafe { &mut *user_data };
151 let mut user_data_uc = Unicorn {
152 inner: user_data.uc.upgrade().unwrap(),
153 };
154 debug_assert_eq!(uc, user_data_uc.get_handle());
155 (user_data.callback)(&mut user_data_uc, port, size)
156}
157
158pub unsafe extern "C" fn insn_invalid_hook_proxy<D, F>(
162 uc: *mut uc_engine,
163 user_data: *mut UcHook<D, F>,
164) -> bool
165where
166 F: FnMut(&mut crate::Unicorn<D>) -> bool,
167{
168 let user_data = unsafe { &mut *user_data };
169 let mut user_data_uc = Unicorn {
170 inner: user_data.uc.upgrade().unwrap(),
171 };
172 debug_assert_eq!(uc, user_data_uc.get_handle());
173 (user_data.callback)(&mut user_data_uc)
174}
175
176pub unsafe extern "C" fn insn_out_hook_proxy<D, F>(
180 uc: *mut uc_engine,
181 port: u32,
182 size: usize,
183 value: u32,
184 user_data: *mut UcHook<D, F>,
185) where
186 F: FnMut(&mut crate::Unicorn<D>, u32, usize, u32),
187{
188 let user_data = unsafe { &mut *user_data };
189 let mut user_data_uc = Unicorn {
190 inner: user_data.uc.upgrade().unwrap(),
191 };
192 debug_assert_eq!(uc, user_data_uc.get_handle());
193 (user_data.callback)(&mut user_data_uc, port, size, value);
194}
195
196pub unsafe extern "C" fn insn_sys_hook_proxy<D, F>(uc: *mut uc_engine, user_data: *mut UcHook<D, F>)
200where
201 F: FnMut(&mut crate::Unicorn<D>),
202{
203 let user_data = unsafe { &mut *user_data };
204 let mut user_data_uc = Unicorn {
205 inner: user_data.uc.upgrade().unwrap(),
206 };
207 debug_assert_eq!(uc, user_data_uc.get_handle());
208 (user_data.callback)(&mut user_data_uc);
209}
210
211#[cfg(feature = "arch_aarch64")]
215pub unsafe extern "C" fn insn_sys_hook_proxy_arm64<D, F>(
216 uc: *mut uc_engine,
217 reg: sys::RegisterARM64,
218 cp_reg: *const sys::RegisterARM64CP,
219 user_data: *mut UcHook<D, F>,
220) -> bool
221where
222 F: FnMut(&mut crate::Unicorn<D>, sys::RegisterARM64, &sys::RegisterARM64CP) -> bool,
223{
224 let user_data = unsafe { &mut *user_data };
225 let mut user_data_uc = Unicorn {
226 inner: user_data.uc.upgrade().unwrap(),
227 };
228 debug_assert_eq!(uc, user_data_uc.get_handle());
229 let cp_reg = unsafe { cp_reg.as_ref() }.unwrap();
230 (user_data.callback)(&mut user_data_uc, reg, cp_reg)
231}
232
233pub unsafe extern "C" fn tlb_lookup_hook_proxy<D, F>(
237 uc: *mut uc_engine,
238 vaddr: u64,
239 mem_type: sys::MemType,
240 result: *mut sys::TlbEntry,
241 user_data: *mut UcHook<D, F>,
242) -> bool
243where
244 F: FnMut(&mut crate::Unicorn<D>, u64, sys::MemType) -> Option<sys::TlbEntry>,
245{
246 let user_data = unsafe { &mut *user_data };
247 let mut user_data_uc = Unicorn {
248 inner: user_data.uc.upgrade().unwrap(),
249 };
250 debug_assert_eq!(uc, user_data_uc.get_handle());
251 let r = (user_data.callback)(&mut user_data_uc, vaddr, mem_type);
252 if let Some(ref e) = r {
253 let ref_result: &mut sys::TlbEntry = unsafe { &mut *result };
254 *ref_result = *e;
255 }
256 r.is_some()
257}
258
259pub unsafe extern "C" fn tcg_proxy<D, F>(
263 uc: *mut uc_engine,
264 addr: u64,
265 arg1: u64,
266 arg2: u64,
267 size: u32,
268 user_data: *mut UcHook<D, F>,
269) where
270 F: FnMut(&mut Unicorn<D>, u64, u64, u64, usize),
271{
272 let user_data = unsafe { &mut *user_data };
273 let mut user_data_uc = Unicorn {
274 inner: user_data.uc.upgrade().unwrap(),
275 };
276 debug_assert_eq!(uc, user_data_uc.get_handle());
277 (user_data.callback)(&mut user_data_uc, addr, arg1, arg2, size as usize);
278}
279
280pub unsafe extern "C" fn edge_gen_hook_proxy<D, F>(
284 uc: *mut uc_engine,
285 cur_tb: *mut sys::TranslationBlock,
286 prev_tb: *mut sys::TranslationBlock,
287 user_data: *mut UcHook<D, F>,
288) where
289 F: FnMut(&mut Unicorn<D>, &mut sys::TranslationBlock, &mut sys::TranslationBlock),
290{
291 let user_data = unsafe { &mut *user_data };
292 let mut user_data_uc = Unicorn {
293 inner: user_data.uc.upgrade().unwrap(),
294 };
295 debug_assert_eq!(uc, user_data_uc.get_handle());
296 (user_data.callback)(&mut user_data_uc, unsafe { &mut *cur_tb }, unsafe {
297 &mut *prev_tb
298 });
299}