Support to pass unicorn handle to rust through FFI

This commit is contained in:
Bet4 2022-01-21 22:37:15 +08:00
parent 5f89981a3c
commit 2977c9ca47
2 changed files with 43 additions and 1 deletions

View File

@ -128,6 +128,7 @@ impl<'a> MmioCallbackScope<'a> {
pub struct UnicornInner<'a, D> {
pub uc: uc_handle,
pub ffi: bool,
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>)>,
@ -139,7 +140,7 @@ pub struct UnicornInner<'a, D> {
/// Drop UC
impl<'a, D> Drop for UnicornInner<'a, D> {
fn drop(&mut self) {
if !self.uc.is_null() {
if !self.ffi && !self.uc.is_null() {
unsafe { ffi::uc_close(self.uc) };
}
self.uc = ptr::null_mut();
@ -157,6 +158,27 @@ impl<'a> Unicorn<'a, ()> {
pub fn new(arch: Arch, mode: Mode) -> Result<Unicorn<'a, ()>, uc_error> {
Self::new_with_data(arch, mode, ())
}
pub fn new_with_handle(handle: uc_handle) -> Result<Unicorn<'a, ()>, uc_error> {
if handle == ptr::null_mut() {
return Err(uc_error::HANDLE);
}
let mut arch: libc::size_t = Default::default();
let err = unsafe { ffi::uc_query(handle, Query::ARCH, &mut arch) };
if err != uc_error::OK {
return Err(err);
}
Ok(Unicorn {
inner: Rc::new(UnsafeCell::from(UnicornInner {
uc: handle,
ffi: true,
arch: arch.try_into()?,
data: (),
hooks: vec![],
mmio_callbacks: vec![],
})),
})
}
}
impl<'a, D> Unicorn<'a, D>
@ -172,6 +194,7 @@ where
Ok(Unicorn {
inner: Rc::new(UnsafeCell::from(UnicornInner {
uc: handle,
ffi: false,
arch,
data,
hooks: vec![],

View File

@ -131,6 +131,25 @@ pub enum Arch {
MAX = 9,
}
impl TryFrom<usize> for Arch {
type Error = uc_error;
fn try_from(v: usize) -> Result<Self, Self::Error> {
match v {
x if x == Self::ARM as usize => Ok(Self::ARM),
x if x == Self::ARM64 as usize => Ok(Self::ARM64),
x if x == Self::MIPS as usize => Ok(Self::MIPS),
x if x == Self::X86 as usize => Ok(Self::X86),
x if x == Self::PPC as usize => Ok(Self::PPC),
x if x == Self::SPARC as usize => Ok(Self::SPARC),
x if x == Self::M68K as usize => Ok(Self::M68K),
x if x == Self::RISCV as usize => Ok(Self::RISCV),
x if x == Self::MAX as usize => Ok(Self::MAX),
_ => Err(uc_error::ARCH),
}
}
}
bitflags! {
#[repr(C)]
pub struct Mode: i32 {