panda/callbacks/
closure.rs1use std::{
2 collections::HashMap,
3 ffi::c_void,
4 sync::{
5 atomic::{AtomicU64, Ordering},
6 RwLock,
7 },
8};
9
10use once_cell::sync::OnceCell;
11
12use crate::sys::{hwaddr, target_ptr_t, CPUState, MachineState, Monitor, TranslationBlock};
13use crate::{sys, PluginHandle};
14
15#[repr(transparent)]
58#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
59pub struct Callback(u64);
60
61static CURRENT_CALLBACK_ID: AtomicU64 = AtomicU64::new(0);
62
63impl Callback {
64 pub fn new() -> Self {
67 Self(CURRENT_CALLBACK_ID.fetch_add(1, Ordering::SeqCst))
68 }
69
70 pub fn enable(&self) {
72 let callbacks = CALLBACKS.read().unwrap();
73 if let Some(callback) = callbacks.get(&self.0) {
74 unsafe {
75 sys::panda_enable_callback_with_context(
76 get_plugin_ref(),
77 callback.cb_kind,
78 callback.trampoline,
79 callback.closure_ref as *mut c_void,
80 );
81 }
82 }
83 }
84
85 pub fn disable(&self) {
87 let callbacks = CALLBACKS.read().unwrap();
88
89 if let Some(callback) = callbacks.get(&self.0) {
90 unsafe {
91 sys::panda_disable_callback_with_context(
92 get_plugin_ref(),
93 callback.cb_kind,
94 callback.trampoline,
95 callback.closure_ref as *mut c_void,
96 );
97 }
98 }
99 }
100}
101
102struct ClosureCallback {
103 closure_ref: *mut *mut c_void,
104 cb_kind: sys::panda_cb_type,
105 trampoline: sys::panda_cb_with_context,
106 drop_fn: unsafe fn(*mut *mut c_void),
107}
108
109unsafe impl Sync for ClosureCallback {}
110unsafe impl Send for ClosureCallback {}
111
112lazy_static::lazy_static! {
113 static ref CALLBACKS: RwLock<HashMap<u64, ClosureCallback>> = RwLock::new(HashMap::new());
114}
115
116static PLUGIN_REF: OnceCell<u64> = OnceCell::new();
117
118#[doc(hidden)]
119pub fn set_plugin_ref(plugin: *mut PluginHandle) {
120 let _ = PLUGIN_REF.set(plugin as u64);
121}
122
123fn get_plugin_ref() -> *mut c_void {
124 *PLUGIN_REF.get_or_init(|| &PLUGIN_REF as *const _ as u64) as _
125}
126
127fn install_closure_callback(id: u64, callback: ClosureCallback) {
128 unsafe {
129 sys::panda_register_callback_with_context(
130 get_plugin_ref(),
131 callback.cb_kind,
132 callback.trampoline,
133 callback.closure_ref as *mut c_void,
134 );
135 }
136
137 CALLBACKS.write().unwrap().insert(id, callback);
138}
139
140impl std::ops::Drop for ClosureCallback {
141 fn drop(&mut self) {
142 unsafe { (self.drop_fn)(self.closure_ref) }
143 }
144}
145
146panda_macros::define_closure_callbacks!();