Add map_mmio to rust bindings
This commit is contained in:
@ -81,6 +81,8 @@ pub struct UnicornInner<'a, D> {
|
||||
pub arch: Arch,
|
||||
/// to keep ownership over the hook for this uc instance's lifetime
|
||||
pub hooks: Vec<(ffi::uc_hook, Box<dyn ffi::IsUcHook<'a> + 'a>)>,
|
||||
/// To keep ownership over the mmio callbacks for this uc instance's lifetime
|
||||
pub mmio_callbacks: Vec<(Option<Box<dyn ffi::IsUcHook<'a> + 'a>>, Option<Box<dyn ffi::IsUcHook<'a> + 'a>>)>,
|
||||
pub data: D,
|
||||
}
|
||||
|
||||
@ -123,6 +125,7 @@ where
|
||||
arch,
|
||||
data,
|
||||
hooks: vec![],
|
||||
mmio_callbacks: vec![],
|
||||
})),
|
||||
})
|
||||
} else {
|
||||
@ -262,6 +265,99 @@ impl<'a, D> Unicorn<'a, D> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Map in am MMIO region backed by callbacks.
|
||||
///
|
||||
/// `address` must be aligned to 4kb or this will return `Error::ARG`.
|
||||
/// `size` must be a multiple of 4kb or this will return `Error::ARG`.
|
||||
pub fn mmio_map<R: 'a, W: 'a>(
|
||||
&mut self,
|
||||
address: u64,
|
||||
size: libc::size_t,
|
||||
read_callback: Option<R>,
|
||||
write_callback: Option<W>,
|
||||
) -> Result<(), uc_error>
|
||||
where
|
||||
R: FnMut(&mut Unicorn<D>, u64, usize) -> u64,
|
||||
W: FnMut(&mut Unicorn<D>, u64, usize, u64),
|
||||
{
|
||||
let mut read_data = read_callback.map( |c| {
|
||||
Box::new(ffi::UcHook {
|
||||
callback: c,
|
||||
uc: Unicorn {
|
||||
inner: self.inner.clone(),
|
||||
},
|
||||
})
|
||||
});
|
||||
let mut write_data = write_callback.map( |c| {
|
||||
Box::new(ffi::UcHook {
|
||||
callback: c,
|
||||
uc: Unicorn {
|
||||
inner: self.inner.clone(),
|
||||
},
|
||||
})
|
||||
});
|
||||
|
||||
let err = unsafe {
|
||||
ffi::uc_mmio_map(
|
||||
self.inner().uc,
|
||||
address,
|
||||
size,
|
||||
ffi::mmio_read_callback_proxy::<D, R> as _,
|
||||
match read_data {
|
||||
Some(ref mut d) => d.as_mut() as *mut _ as _,
|
||||
None => ptr::null_mut(),
|
||||
},
|
||||
ffi::mmio_write_callback_proxy::<D, W> as _,
|
||||
match write_data {
|
||||
Some(ref mut d) => d.as_mut() as *mut _ as _,
|
||||
None => ptr::null_mut(),
|
||||
},
|
||||
)
|
||||
};
|
||||
|
||||
if err == uc_error::OK {
|
||||
let rd = read_data.map( |c| c as Box<dyn ffi::IsUcHook> );
|
||||
let wd = write_data.map( |c| c as Box<dyn ffi::IsUcHook> );
|
||||
self.inner_mut().mmio_callbacks.push((rd, wd));
|
||||
|
||||
Ok(())
|
||||
} else {
|
||||
Err(err)
|
||||
}
|
||||
}
|
||||
|
||||
/// Map in a read-only MMIO region backed by a callback.
|
||||
///
|
||||
/// `address` must be aligned to 4kb or this will return `Error::ARG`.
|
||||
/// `size` must be a multiple of 4kb or this will return `Error::ARG`.
|
||||
pub fn mmio_map_ro<F: 'a>(
|
||||
&mut self,
|
||||
address: u64,
|
||||
size: libc::size_t,
|
||||
callback: F,
|
||||
) -> Result<(), uc_error>
|
||||
where
|
||||
F: FnMut(&mut Unicorn<D>, u64, usize) -> u64,
|
||||
{
|
||||
self.mmio_map(address, size, Some(callback), None::<fn(&mut Unicorn<D>, u64, usize, u64)>)
|
||||
}
|
||||
|
||||
/// Map in a write-only MMIO region backed by a callback.
|
||||
///
|
||||
/// `address` must be aligned to 4kb or this will return `Error::ARG`.
|
||||
/// `size` must be a multiple of 4kb or this will return `Error::ARG`.
|
||||
pub fn mmio_map_wo<F: 'a>(
|
||||
&mut self,
|
||||
address: u64,
|
||||
size: libc::size_t,
|
||||
callback: F,
|
||||
) -> Result<(), uc_error>
|
||||
where
|
||||
F: FnMut(&mut Unicorn<D>, u64, usize, u64),
|
||||
{
|
||||
self.mmio_map(address, size, None::<fn(&mut Unicorn<D>, u64, usize) -> u64>, Some(callback))
|
||||
}
|
||||
|
||||
/// Unmap a memory region.
|
||||
///
|
||||
/// `address` must be aligned to 4kb or this will return `Error::ARG`.
|
||||
|
Reference in New Issue
Block a user