unicorn_engine/
hook.rs

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
19/// # Safety
20///
21/// This function is unsafe because it dereferences the `user_data` pointer.
22pub extern "C" fn mmio_read_callback_proxy<D, F>(
23    uc: *mut uc_engine,
24    offset: u64,
25    size: u32,
26    // user_data: *mut UcHook<D, F>,
27    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
40/// # Safety
41///
42/// This function is unsafe because it dereferences the `user_data` pointer.
43pub 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
60/// # Safety
61///
62/// This function is unsafe because it dereferences the `user_data` pointer.
63pub 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
79/// # Safety
80///
81/// This function is unsafe because it dereferences the `user_data` pointer.
82pub 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
98/// # Safety
99///
100/// This function is unsafe because it dereferences the `user_data` pointer.
101pub 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
120/// # Safety
121///
122/// This function is unsafe because it dereferences the `user_data` pointer.
123pub 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
138/// # Safety
139///
140/// This function is unsafe because it dereferences the `user_data` pointer.
141pub 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
158/// # Safety
159///
160/// This function is unsafe because it dereferences the `user_data` pointer.
161pub 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
176/// # Safety
177///
178/// This function is unsafe because it dereferences the `user_data` pointer.
179pub 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
196/// # Safety
197///
198/// This function is unsafe because it dereferences the `user_data` pointer.
199pub 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/// # Safety
212///
213/// This function is unsafe because it dereferences the `user_data` pointer.
214#[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
233/// # Safety
234///
235/// This function is unsafe because it dereferences the `user_data` pointer.
236pub 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
259/// # Safety
260///
261/// This function is unsafe because it dereferences the `user_data` pointer.
262pub 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
280/// # Safety
281///
282/// This function is unsafe because it dereferences the `user_data` pointer.
283pub 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}