use crate::abi::{BpInsertError, PhysAddr};
mod generated {
#![allow(non_camel_case_types, non_upper_case_globals, dead_code)]
include!("generated.rs");
}
pub use generated::*;
impl BreakpointsVtable {
pub const ABSENT: BreakpointsVtable =
BreakpointsVtable { insert: None, remove: None, query: None };
}
pub type BpFn<T, C> = extern "C" fn(&mut T, &mut C, PhysAddr);
impl BreakpointsRef {
pub fn insert<T, C>(
&self,
pa: PhysAddr,
obj: &mut T,
handler: BpFn<T, C>,
) -> Result<(), BpInsertError> {
let handler: BpHandler = unsafe { core::mem::transmute(handler) };
let obj = core::ptr::from_mut(obj).cast();
let insert = unsafe { (*self.vtable).insert }
.expect("the breakpoints `.so` populates every BreakpointsVtable fn");
let rc = unsafe { insert(*self, pa.0, obj, handler) };
(rc == 0)
.then_some(())
.ok_or(BpInsertError::DuplicateOwner(pa))
}
pub fn remove<T>(&self, pa: PhysAddr, obj: &mut T) {
let Some(remove) = (unsafe { (*self.vtable).remove }) else {
return;
};
unsafe { remove(*self, pa.0, core::ptr::from_mut(obj).cast()) };
}
pub fn query(&self, pa: u64) -> Option<bool> {
let query = unsafe { (*self.vtable).query }?;
Some(unsafe { query(*self, pa) } != 0)
}
}