HookId trait and types in libafl_qemu (#1796)

* libafl_qemu fix remove_hook

* libafl_qemu specialize hooks into separated types

* libafl_qemu generalize HookState to allow any HookId implementation

* fmt: external C qemu hook functions

---------

Co-authored-by: Andrea Fioraldi <andreafioraldi@gmail.com>
This commit is contained in:
Rubens Brandão 2024-02-01 06:55:55 -03:00 committed by GitHub
parent 13dd1cc4ec
commit c96d103b37
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 186 additions and 123 deletions

View File

@ -832,8 +832,45 @@ impl CPU {
}
}
#[derive(Clone, Copy, PartialEq, Debug)]
pub struct HookId(pub(crate) usize);
pub trait HookId {
fn remove(&self, invalidate_block: bool) -> bool;
}
macro_rules! create_hook_id {
($name:ident, $sys:ident, true) => {
paste::paste! {
#[derive(Clone, Copy, PartialEq, Debug)]
pub struct [<$name HookId>](pub(crate) usize);
impl HookId for [<$name HookId>] {
fn remove(&self, invalidate_block: bool) -> bool {
unsafe { libafl_qemu_sys::$sys(self.0, invalidate_block.into()) != 0 }
}
}
}
};
($name:ident, $sys:ident, false) => {
paste::paste! {
#[derive(Clone, Copy, PartialEq, Debug)]
pub struct [<$name HookId>](pub(crate) usize);
impl HookId for [<$name HookId>] {
fn remove(&self, _invalidate_block: bool) -> bool {
unsafe { libafl_qemu_sys::$sys(self.0) != 0 }
}
}
}
};
}
create_hook_id!(Instruction, libafl_qemu_remove_hook, true);
create_hook_id!(Backdoor, libafl_qemu_remove_backdoor_hook, true);
create_hook_id!(Edge, libafl_qemu_remove_edge_hook, true);
create_hook_id!(Block, libafl_qemu_remove_block_hook, true);
create_hook_id!(Read, libafl_qemu_remove_read_hook, true);
create_hook_id!(Write, libafl_qemu_remove_write_hook, true);
create_hook_id!(Cmp, libafl_qemu_remove_cmp_hook, true);
create_hook_id!(PreSyscall, libafl_qemu_remove_pre_syscall_hook, false);
create_hook_id!(PostSyscall, libafl_qemu_remove_post_syscall_hook, false);
create_hook_id!(NewThread, libafl_qemu_remove_new_thread_hook, false);
use std::pin::Pin;
@ -1347,7 +1384,7 @@ impl Emulator {
addr: GuestAddr,
callback: extern "C" fn(T, GuestAddr),
invalidate_block: bool,
) -> HookId {
) -> InstructionHookId {
unsafe {
let data: u64 = data.into().0;
let callback: extern "C" fn(u64, GuestAddr) = core::mem::transmute(callback);
@ -1357,13 +1394,13 @@ impl Emulator {
data,
i32::from(invalidate_block),
);
HookId(num)
InstructionHookId(num)
}
}
#[must_use]
pub fn remove_hook(&self, id: HookId, invalidate_block: bool) -> bool {
unsafe { libafl_qemu_sys::libafl_qemu_remove_hook(id.0, i32::from(invalidate_block)) != 0 }
pub fn remove_hook(&self, id: impl HookId, invalidate_block: bool) -> bool {
id.remove(invalidate_block)
}
#[must_use]
@ -1378,14 +1415,14 @@ impl Emulator {
data: T,
gen: Option<extern "C" fn(T, GuestAddr, GuestAddr) -> u64>,
exec: Option<extern "C" fn(T, u64)>,
) -> HookId {
) -> EdgeHookId {
unsafe {
let data: u64 = data.into().0;
let gen: Option<extern "C" fn(u64, GuestAddr, GuestAddr) -> u64> =
core::mem::transmute(gen);
let exec: Option<extern "C" fn(u64, u64)> = core::mem::transmute(exec);
let num = libafl_qemu_sys::libafl_add_edge_hook(gen, exec, data);
HookId(num)
EdgeHookId(num)
}
}
@ -1395,7 +1432,7 @@ impl Emulator {
gen: Option<extern "C" fn(T, GuestAddr) -> u64>,
post_gen: Option<extern "C" fn(T, GuestAddr, GuestUsize)>,
exec: Option<extern "C" fn(T, u64)>,
) -> HookId {
) -> BlockHookId {
unsafe {
let data: u64 = data.into().0;
let gen: Option<extern "C" fn(u64, GuestAddr) -> u64> = core::mem::transmute(gen);
@ -1403,7 +1440,7 @@ impl Emulator {
core::mem::transmute(post_gen);
let exec: Option<extern "C" fn(u64, u64)> = core::mem::transmute(exec);
let num = libafl_qemu_sys::libafl_add_block_hook(gen, post_gen, exec, data);
HookId(num)
BlockHookId(num)
}
}
@ -1416,7 +1453,7 @@ impl Emulator {
exec4: Option<extern "C" fn(T, u64, GuestAddr)>,
exec8: Option<extern "C" fn(T, u64, GuestAddr)>,
exec_n: Option<extern "C" fn(T, u64, GuestAddr, usize)>,
) -> HookId {
) -> ReadHookId {
unsafe {
let data: u64 = data.into().0;
let gen: Option<extern "C" fn(u64, GuestAddr, libafl_qemu_sys::MemOpIdx) -> u64> =
@ -1430,7 +1467,7 @@ impl Emulator {
let num = libafl_qemu_sys::libafl_add_read_hook(
gen, exec1, exec2, exec4, exec8, exec_n, data,
);
HookId(num)
ReadHookId(num)
}
}
@ -1444,7 +1481,7 @@ impl Emulator {
exec4: Option<extern "C" fn(T, u64, GuestAddr)>,
exec8: Option<extern "C" fn(T, u64, GuestAddr)>,
exec_n: Option<extern "C" fn(T, u64, GuestAddr, usize)>,
) -> HookId {
) -> WriteHookId {
unsafe {
let data: u64 = data.into().0;
let gen: Option<extern "C" fn(u64, GuestAddr, libafl_qemu_sys::MemOpIdx) -> u64> =
@ -1458,7 +1495,7 @@ impl Emulator {
let num = libafl_qemu_sys::libafl_add_write_hook(
gen, exec1, exec2, exec4, exec8, exec_n, data,
);
HookId(num)
WriteHookId(num)
}
}
@ -1470,7 +1507,7 @@ impl Emulator {
exec2: Option<extern "C" fn(T, u64, u16, u16)>,
exec4: Option<extern "C" fn(T, u64, u32, u32)>,
exec8: Option<extern "C" fn(T, u64, u64, u64)>,
) -> HookId {
) -> CmpHookId {
unsafe {
let data: u64 = data.into().0;
let gen: Option<extern "C" fn(u64, GuestAddr, usize) -> u64> =
@ -1480,7 +1517,7 @@ impl Emulator {
let exec4: Option<extern "C" fn(u64, u64, u32, u32)> = core::mem::transmute(exec4);
let exec8: Option<extern "C" fn(u64, u64, u64, u64)> = core::mem::transmute(exec8);
let num = libafl_qemu_sys::libafl_add_cmp_hook(gen, exec1, exec2, exec4, exec8, data);
HookId(num)
CmpHookId(num)
}
}
@ -1488,12 +1525,12 @@ impl Emulator {
&self,
data: T,
callback: extern "C" fn(T, GuestAddr),
) -> HookId {
) -> BackdoorHookId {
unsafe {
let data: u64 = data.into().0;
let callback: extern "C" fn(u64, GuestAddr) = core::mem::transmute(callback);
let num = libafl_qemu_sys::libafl_add_backdoor_hook(Some(callback), data);
HookId(num)
BackdoorHookId(num)
}
}
@ -1514,7 +1551,7 @@ impl Emulator {
GuestAddr,
GuestAddr,
) -> SyscallHookResult,
) -> HookId {
) -> PreSyscallHookId {
unsafe {
let data: u64 = data.into().0;
let callback: extern "C" fn(
@ -1530,7 +1567,7 @@ impl Emulator {
GuestAddr,
) -> libafl_qemu_sys::syshook_ret = core::mem::transmute(callback);
let num = libafl_qemu_sys::libafl_add_pre_syscall_hook(Some(callback), data);
HookId(num)
PreSyscallHookId(num)
}
}
@ -1552,7 +1589,7 @@ impl Emulator {
GuestAddr,
GuestAddr,
) -> GuestAddr,
) -> HookId {
) -> PostSyscallHookId {
unsafe {
let data: u64 = data.into().0;
let callback: extern "C" fn(
@ -1569,7 +1606,7 @@ impl Emulator {
GuestAddr,
) -> GuestAddr = core::mem::transmute(callback);
let num = libafl_qemu_sys::libafl_add_post_syscall_hook(Some(callback), data);
HookId(num)
PostSyscallHookId(num)
}
}
@ -1578,12 +1615,12 @@ impl Emulator {
&self,
data: T,
callback: extern "C" fn(T, tid: u32) -> bool,
) -> HookId {
) -> NewThreadHookId {
unsafe {
let data: u64 = data.into().0;
let callback: extern "C" fn(u64, u32) -> bool = core::mem::transmute(callback);
let num = libafl_qemu_sys::libafl_add_new_thread_hook(Some(callback), data);
HookId(num)
NewThreadHookId(num)
}
}

View File

@ -13,9 +13,11 @@ use libafl::{executors::hooks::inprocess::inprocess_get_state, inputs::UsesInput
pub use crate::emu::SyscallHookResult;
use crate::{
emu::{Emulator, FatPtr, HookId, MemAccessInfo, SKIP_EXEC_HOOK},
emu::{Emulator, FatPtr, MemAccessInfo, SKIP_EXEC_HOOK},
helper::QemuHelperTuple,
GuestAddr, GuestUsize,
BackdoorHookId, BlockHookId, CmpHookId, EdgeHookId, GuestAddr, GuestUsize, HookId,
InstructionHookId, NewThreadHookId, PostSyscallHookId, PreSyscallHookId, ReadHookId,
WriteHookId,
};
/*
@ -38,8 +40,8 @@ pub(crate) enum HookRepr {
Empty,
}
pub struct HookState<const N: usize> {
id: HookId,
pub struct HookState<const N: usize, H: HookId> {
id: H,
gen: HookRepr,
post_gen: HookRepr,
execs: [HookRepr; N],
@ -153,9 +155,9 @@ macro_rules! create_wrapper {
}
macro_rules! create_gen_wrapper {
($name:ident, ($($param:ident : $param_type:ty),*), $ret_type:ty, $execs:literal) => {
($name:ident, ($($param:ident : $param_type:ty),*), $ret_type:ty, $execs:literal, $hook_id:ident) => {
paste::paste! {
extern "C" fn [<$name _gen_hook_wrapper>]<QT, S>(hook: &mut HookState<{ $execs }>, $($param: $param_type),*) -> $ret_type
extern "C" fn [<$name _gen_hook_wrapper>]<QT, S>(hook: &mut HookState<{ $execs }, $hook_id>, $($param: $param_type),*) -> $ret_type
where
S: UsesInput,
QT: QemuHelperTuple<S>,
@ -183,9 +185,9 @@ macro_rules! create_gen_wrapper {
}
macro_rules! create_post_gen_wrapper {
($name:ident, ($($param:ident : $param_type:ty),*), $execs:literal) => {
($name:ident, ($($param:ident : $param_type:ty),*), $execs:literal, $hook_id:ident) => {
paste::paste! {
extern "C" fn [<$name _post_gen_hook_wrapper>]<QT, S>(hook: &mut HookState<{ $execs }>, $($param: $param_type),*)
extern "C" fn [<$name _post_gen_hook_wrapper>]<QT, S>(hook: &mut HookState<{ $execs }, $hook_id>, $($param: $param_type),*)
where
S: UsesInput,
QT: QemuHelperTuple<S>,
@ -213,9 +215,9 @@ macro_rules! create_post_gen_wrapper {
}
macro_rules! create_exec_wrapper {
($name:ident, ($($param:ident : $param_type:ty),*), $execidx:literal, $execs:literal) => {
($name:ident, ($($param:ident : $param_type:ty),*), $execidx:literal, $execs:literal, $hook_id:ident) => {
paste::paste! {
extern "C" fn [<$name _ $execidx _exec_hook_wrapper>]<QT, S>(hook: &mut HookState<{ $execs }>, $($param: $param_type),*)
extern "C" fn [<$name _ $execidx _exec_hook_wrapper>]<QT, S>(hook: &mut HookState<{ $execs }, $hook_id>, $($param: $param_type),*)
where
S: UsesInput,
QT: QemuHelperTuple<S>,
@ -240,13 +242,13 @@ macro_rules! create_exec_wrapper {
}
}
static mut GENERIC_HOOKS: Vec<(HookId, FatPtr)> = vec![];
static mut GENERIC_HOOKS: Vec<(InstructionHookId, FatPtr)> = vec![];
create_wrapper!(generic, (pc: GuestAddr));
static mut BACKDOOR_HOOKS: Vec<(HookId, FatPtr)> = vec![];
static mut BACKDOOR_HOOKS: Vec<(BackdoorHookId, FatPtr)> = vec![];
create_wrapper!(backdoor, (pc: GuestAddr));
#[cfg(emulation_mode = "usermode")]
static mut PRE_SYSCALL_HOOKS: Vec<(HookId, FatPtr)> = vec![];
static mut PRE_SYSCALL_HOOKS: Vec<(PreSyscallHookId, FatPtr)> = vec![];
#[cfg(emulation_mode = "usermode")]
create_wrapper!(pre_syscall, (sys_num: i32,
a0: GuestAddr,
@ -258,7 +260,7 @@ create_wrapper!(pre_syscall, (sys_num: i32,
a6: GuestAddr,
a7: GuestAddr), SyscallHookResult);
#[cfg(emulation_mode = "usermode")]
static mut POST_SYSCALL_HOOKS: Vec<(HookId, FatPtr)> = vec![];
static mut POST_SYSCALL_HOOKS: Vec<(PostSyscallHookId, FatPtr)> = vec![];
#[cfg(emulation_mode = "usermode")]
create_wrapper!(post_syscall, (res: GuestAddr, sys_num: i32,
a0: GuestAddr,
@ -270,41 +272,41 @@ create_wrapper!(post_syscall, (res: GuestAddr, sys_num: i32,
a6: GuestAddr,
a7: GuestAddr), GuestAddr);
#[cfg(emulation_mode = "usermode")]
static mut NEW_THREAD_HOOKS: Vec<(HookId, FatPtr)> = vec![];
static mut NEW_THREAD_HOOKS: Vec<(NewThreadHookId, FatPtr)> = vec![];
#[cfg(emulation_mode = "usermode")]
create_wrapper!(new_thread, (tid: u32), bool);
static mut EDGE_HOOKS: Vec<HookState<1>> = vec![];
create_gen_wrapper!(edge, (src: GuestAddr, dest: GuestAddr), u64, 1);
create_exec_wrapper!(edge, (id: u64), 0, 1);
static mut EDGE_HOOKS: Vec<HookState<1, EdgeHookId>> = vec![];
create_gen_wrapper!(edge, (src: GuestAddr, dest: GuestAddr), u64, 1, EdgeHookId);
create_exec_wrapper!(edge, (id: u64), 0, 1, EdgeHookId);
static mut BLOCK_HOOKS: Vec<HookState<1>> = vec![];
create_gen_wrapper!(block, (addr: GuestAddr), u64, 1);
create_post_gen_wrapper!(block, (addr: GuestAddr, len: GuestUsize), 1);
create_exec_wrapper!(block, (id: u64), 0, 1);
static mut BLOCK_HOOKS: Vec<HookState<1, BlockHookId>> = vec![];
create_gen_wrapper!(block, (addr: GuestAddr), u64, 1, BlockHookId);
create_post_gen_wrapper!(block, (addr: GuestAddr, len: GuestUsize), 1, BlockHookId);
create_exec_wrapper!(block, (id: u64), 0, 1, BlockHookId);
static mut READ_HOOKS: Vec<HookState<5>> = vec![];
create_gen_wrapper!(read, (pc: GuestAddr, info: MemAccessInfo), u64, 5);
create_exec_wrapper!(read, (id: u64, addr: GuestAddr), 0, 5);
create_exec_wrapper!(read, (id: u64, addr: GuestAddr), 1, 5);
create_exec_wrapper!(read, (id: u64, addr: GuestAddr), 2, 5);
create_exec_wrapper!(read, (id: u64, addr: GuestAddr), 3, 5);
create_exec_wrapper!(read, (id: u64, addr: GuestAddr, size: usize), 4, 5);
static mut READ_HOOKS: Vec<HookState<5, ReadHookId>> = vec![];
create_gen_wrapper!(read, (pc: GuestAddr, info: MemAccessInfo), u64, 5, ReadHookId);
create_exec_wrapper!(read, (id: u64, addr: GuestAddr), 0, 5, ReadHookId);
create_exec_wrapper!(read, (id: u64, addr: GuestAddr), 1, 5, ReadHookId);
create_exec_wrapper!(read, (id: u64, addr: GuestAddr), 2, 5, ReadHookId);
create_exec_wrapper!(read, (id: u64, addr: GuestAddr), 3, 5, ReadHookId);
create_exec_wrapper!(read, (id: u64, addr: GuestAddr, size: usize), 4, 5, ReadHookId);
static mut WRITE_HOOKS: Vec<HookState<5>> = vec![];
create_gen_wrapper!(write, (pc: GuestAddr, info: MemAccessInfo), u64, 5);
create_exec_wrapper!(write, (id: u64, addr: GuestAddr), 0, 5);
create_exec_wrapper!(write, (id: u64, addr: GuestAddr), 1, 5);
create_exec_wrapper!(write, (id: u64, addr: GuestAddr), 2, 5);
create_exec_wrapper!(write, (id: u64, addr: GuestAddr), 3, 5);
create_exec_wrapper!(write, (id: u64, addr: GuestAddr, size: usize), 4, 5);
static mut WRITE_HOOKS: Vec<HookState<5, WriteHookId>> = vec![];
create_gen_wrapper!(write, (pc: GuestAddr, info: MemAccessInfo), u64, 5, WriteHookId);
create_exec_wrapper!(write, (id: u64, addr: GuestAddr), 0, 5, WriteHookId);
create_exec_wrapper!(write, (id: u64, addr: GuestAddr), 1, 5, WriteHookId);
create_exec_wrapper!(write, (id: u64, addr: GuestAddr), 2, 5, WriteHookId);
create_exec_wrapper!(write, (id: u64, addr: GuestAddr), 3, 5, WriteHookId);
create_exec_wrapper!(write, (id: u64, addr: GuestAddr, size: usize), 4, 5, WriteHookId);
static mut CMP_HOOKS: Vec<HookState<4>> = vec![];
create_gen_wrapper!(cmp, (pc: GuestAddr, size: usize), u64, 4);
create_exec_wrapper!(cmp, (id: u64, v0: u8, v1: u8), 0, 4);
create_exec_wrapper!(cmp, (id: u64, v0: u16, v1: u16), 1, 4);
create_exec_wrapper!(cmp, (id: u64, v0: u32, v1: u32), 2, 4);
create_exec_wrapper!(cmp, (id: u64, v0: u64, v1: u64), 3, 4);
static mut CMP_HOOKS: Vec<HookState<4, CmpHookId>> = vec![];
create_gen_wrapper!(cmp, (pc: GuestAddr, size: usize), u64, 4, CmpHookId);
create_exec_wrapper!(cmp, (id: u64, v0: u8, v1: u8), 0, 4, CmpHookId);
create_exec_wrapper!(cmp, (id: u64, v0: u16, v1: u16), 1, 4, CmpHookId);
create_exec_wrapper!(cmp, (id: u64, v0: u32, v1: u32), 2, 4, CmpHookId);
create_exec_wrapper!(cmp, (id: u64, v0: u64, v1: u64), 3, 4, CmpHookId);
#[cfg(emulation_mode = "usermode")]
static mut CRASH_HOOKS: Vec<HookRepr> = vec![];
@ -422,7 +424,7 @@ where
extern "C" fn(*const (), pc: GuestAddr),
>,
invalidate_block: bool,
) -> HookId {
) -> InstructionHookId {
match hook {
Hook::Function(f) => self.instruction_function(addr, f, invalidate_block),
Hook::Closure(c) => self.instruction_closure(addr, c, invalidate_block),
@ -430,7 +432,7 @@ where
let z: *const () = ptr::null::<()>();
self.emulator.set_hook(z, addr, r, invalidate_block)
}
Hook::Empty => HookId(0), // TODO error type
Hook::Empty => InstructionHookId(0), // TODO error type
}
}
@ -439,7 +441,7 @@ where
addr: GuestAddr,
hook: fn(&mut Self, Option<&mut S>, GuestAddr),
invalidate_block: bool,
) -> HookId {
) -> InstructionHookId {
unsafe {
self.emulator.set_hook(
transmute(hook),
@ -455,10 +457,10 @@ where
addr: GuestAddr,
hook: Box<dyn for<'a> FnMut(&'a mut Self, Option<&'a mut S>, GuestAddr)>,
invalidate_block: bool,
) -> HookId {
) -> InstructionHookId {
unsafe {
let fat: FatPtr = transmute(hook);
GENERIC_HOOKS.push((HookId(0), fat));
GENERIC_HOOKS.push((InstructionHookId(0), fat));
let id = self.emulator.set_hook(
&mut ((*addr_of_mut!(GENERIC_HOOKS)).last_mut().unwrap().1),
addr,
@ -489,20 +491,24 @@ where
Box<dyn for<'a> FnMut(&'a mut Self, Option<&'a mut S>, u64)>,
extern "C" fn(*const (), id: u64),
>,
) -> HookId {
) -> EdgeHookId {
unsafe {
let gen = get_raw_hook!(
generation_hook,
edge_gen_hook_wrapper::<QT, S>,
extern "C" fn(&mut HookState<1>, src: GuestAddr, dest: GuestAddr) -> u64
extern "C" fn(
&mut HookState<1, EdgeHookId>,
src: GuestAddr,
dest: GuestAddr,
) -> u64
);
let exec = get_raw_hook!(
execution_hook,
edge_0_exec_hook_wrapper::<QT, S>,
extern "C" fn(&mut HookState<1>, id: u64)
extern "C" fn(&mut HookState<1, EdgeHookId>, id: u64)
);
EDGE_HOOKS.push(HookState {
id: HookId(0),
id: EdgeHookId(0),
gen: hook_to_repr!(generation_hook),
post_gen: HookRepr::Empty,
execs: [hook_to_repr!(execution_hook)],
@ -532,25 +538,29 @@ where
Box<dyn for<'a> FnMut(&'a mut Self, Option<&'a mut S>, u64)>,
extern "C" fn(*const (), id: u64),
>,
) -> HookId {
) -> BlockHookId {
unsafe {
let gen = get_raw_hook!(
generation_hook,
block_gen_hook_wrapper::<QT, S>,
extern "C" fn(&mut HookState<1>, pc: GuestAddr) -> u64
extern "C" fn(&mut HookState<1, BlockHookId>, pc: GuestAddr) -> u64
);
let postgen = get_raw_hook!(
post_generation_hook,
block_post_gen_hook_wrapper::<QT, S>,
extern "C" fn(&mut HookState<1>, pc: GuestAddr, block_length: GuestUsize)
extern "C" fn(
&mut HookState<1, BlockHookId>,
pc: GuestAddr,
block_length: GuestUsize,
)
);
let exec = get_raw_hook!(
execution_hook,
block_0_exec_hook_wrapper::<QT, S>,
extern "C" fn(&mut HookState<1>, id: u64)
extern "C" fn(&mut HookState<1, BlockHookId>, id: u64)
);
BLOCK_HOOKS.push(HookState {
id: HookId(0),
id: BlockHookId(0),
gen: hook_to_repr!(generation_hook),
post_gen: hook_to_repr!(post_generation_hook),
execs: [hook_to_repr!(execution_hook)],
@ -603,40 +613,44 @@ where
Box<dyn for<'a> FnMut(&'a mut Self, Option<&'a mut S>, u64, GuestAddr, usize)>,
extern "C" fn(*const (), id: u64, addr: GuestAddr, size: usize),
>,
) -> HookId {
) -> ReadHookId {
unsafe {
let gen = get_raw_hook!(
generation_hook,
read_gen_hook_wrapper::<QT, S>,
extern "C" fn(&mut HookState<5>, pc: GuestAddr, info: MemAccessInfo) -> u64
extern "C" fn(
&mut HookState<5, ReadHookId>,
pc: GuestAddr,
info: MemAccessInfo,
) -> u64
);
let exec1 = get_raw_hook!(
execution_hook_1,
read_0_exec_hook_wrapper::<QT, S>,
extern "C" fn(&mut HookState<5>, id: u64, addr: GuestAddr)
extern "C" fn(&mut HookState<5, ReadHookId>, id: u64, addr: GuestAddr)
);
let exec2 = get_raw_hook!(
execution_hook_2,
read_1_exec_hook_wrapper::<QT, S>,
extern "C" fn(&mut HookState<5>, id: u64, addr: GuestAddr)
extern "C" fn(&mut HookState<5, ReadHookId>, id: u64, addr: GuestAddr)
);
let exec4 = get_raw_hook!(
execution_hook_4,
read_2_exec_hook_wrapper::<QT, S>,
extern "C" fn(&mut HookState<5>, id: u64, addr: GuestAddr)
extern "C" fn(&mut HookState<5, ReadHookId>, id: u64, addr: GuestAddr)
);
let exec8 = get_raw_hook!(
execution_hook_8,
read_3_exec_hook_wrapper::<QT, S>,
extern "C" fn(&mut HookState<5>, id: u64, addr: GuestAddr)
extern "C" fn(&mut HookState<5, ReadHookId>, id: u64, addr: GuestAddr)
);
let execn = get_raw_hook!(
execution_hook_n,
read_4_exec_hook_wrapper::<QT, S>,
extern "C" fn(&mut HookState<5>, id: u64, addr: GuestAddr, size: usize)
extern "C" fn(&mut HookState<5, ReadHookId>, id: u64, addr: GuestAddr, size: usize)
);
READ_HOOKS.push(HookState {
id: HookId(0),
id: ReadHookId(0),
gen: hook_to_repr!(generation_hook),
post_gen: HookRepr::Empty,
execs: [
@ -701,40 +715,49 @@ where
Box<dyn for<'a> FnMut(&'a mut Self, Option<&'a mut S>, u64, GuestAddr, usize)>,
extern "C" fn(*const (), id: u64, addr: GuestAddr, size: usize),
>,
) -> HookId {
) -> WriteHookId {
unsafe {
let gen = get_raw_hook!(
generation_hook,
write_gen_hook_wrapper::<QT, S>,
extern "C" fn(&mut HookState<5>, pc: GuestAddr, info: MemAccessInfo) -> u64
extern "C" fn(
&mut HookState<5, WriteHookId>,
pc: GuestAddr,
info: MemAccessInfo,
) -> u64
);
let exec1 = get_raw_hook!(
execution_hook_1,
write_0_exec_hook_wrapper::<QT, S>,
extern "C" fn(&mut HookState<5>, id: u64, addr: GuestAddr)
extern "C" fn(&mut HookState<5, WriteHookId>, id: u64, addr: GuestAddr)
);
let exec2 = get_raw_hook!(
execution_hook_2,
write_1_exec_hook_wrapper::<QT, S>,
extern "C" fn(&mut HookState<5>, id: u64, addr: GuestAddr)
extern "C" fn(&mut HookState<5, WriteHookId>, id: u64, addr: GuestAddr)
);
let exec4 = get_raw_hook!(
execution_hook_4,
write_2_exec_hook_wrapper::<QT, S>,
extern "C" fn(&mut HookState<5>, id: u64, addr: GuestAddr)
extern "C" fn(&mut HookState<5, WriteHookId>, id: u64, addr: GuestAddr)
);
let exec8 = get_raw_hook!(
execution_hook_8,
write_3_exec_hook_wrapper::<QT, S>,
extern "C" fn(&mut HookState<5>, id: u64, addr: GuestAddr)
extern "C" fn(&mut HookState<5, WriteHookId>, id: u64, addr: GuestAddr)
);
let execn = get_raw_hook!(
execution_hook_n,
write_4_exec_hook_wrapper::<QT, S>,
extern "C" fn(&mut HookState<5>, id: u64, addr: GuestAddr, size: usize)
extern "C" fn(
&mut HookState<5, WriteHookId>,
id: u64,
addr: GuestAddr,
size: usize,
)
);
WRITE_HOOKS.push(HookState {
id: HookId(0),
id: WriteHookId(0),
gen: hook_to_repr!(generation_hook),
post_gen: HookRepr::Empty,
execs: [
@ -788,35 +811,35 @@ where
Box<dyn for<'a> FnMut(&'a mut Self, Option<&'a mut S>, u64, u64, u64)>,
extern "C" fn(*const (), id: u64, v0: u64, v1: u64),
>,
) -> HookId {
) -> CmpHookId {
unsafe {
let gen = get_raw_hook!(
generation_hook,
cmp_gen_hook_wrapper::<QT, S>,
extern "C" fn(&mut HookState<4>, pc: GuestAddr, size: usize) -> u64
extern "C" fn(&mut HookState<4, CmpHookId>, pc: GuestAddr, size: usize) -> u64
);
let exec1 = get_raw_hook!(
execution_hook_1,
cmp_0_exec_hook_wrapper::<QT, S>,
extern "C" fn(&mut HookState<4>, id: u64, v0: u8, v1: u8)
extern "C" fn(&mut HookState<4, CmpHookId>, id: u64, v0: u8, v1: u8)
);
let exec2 = get_raw_hook!(
execution_hook_2,
cmp_1_exec_hook_wrapper::<QT, S>,
extern "C" fn(&mut HookState<4>, id: u64, v0: u16, v1: u16)
extern "C" fn(&mut HookState<4, CmpHookId>, id: u64, v0: u16, v1: u16)
);
let exec4 = get_raw_hook!(
execution_hook_4,
cmp_2_exec_hook_wrapper::<QT, S>,
extern "C" fn(&mut HookState<4>, id: u64, v0: u32, v1: u32)
extern "C" fn(&mut HookState<4, CmpHookId>, id: u64, v0: u32, v1: u32)
);
let exec8 = get_raw_hook!(
execution_hook_8,
cmp_3_exec_hook_wrapper::<QT, S>,
extern "C" fn(&mut HookState<4>, id: u64, v0: u64, v1: u64)
extern "C" fn(&mut HookState<4, CmpHookId>, id: u64, v0: u64, v1: u64)
);
CMP_HOOKS.push(HookState {
id: HookId(0),
id: CmpHookId(0),
gen: hook_to_repr!(generation_hook),
post_gen: HookRepr::Empty,
execs: [
@ -846,7 +869,7 @@ where
Box<dyn for<'a> FnMut(&'a mut Self, Option<&'a mut S>, GuestAddr)>,
extern "C" fn(*const (), pc: GuestAddr),
>,
) -> HookId {
) -> BackdoorHookId {
match hook {
Hook::Function(f) => self.backdoor_function(f),
Hook::Closure(c) => self.backdoor_closure(c),
@ -854,11 +877,14 @@ where
let z: *const () = ptr::null::<()>();
self.emulator.add_backdoor_hook(z, r)
}
Hook::Empty => HookId(0), // TODO error type
Hook::Empty => BackdoorHookId(0), // TODO error type
}
}
pub fn backdoor_function(&self, hook: fn(&mut Self, Option<&mut S>, pc: GuestAddr)) -> HookId {
pub fn backdoor_function(
&self,
hook: fn(&mut Self, Option<&mut S>, pc: GuestAddr),
) -> BackdoorHookId {
unsafe {
self.emulator
.add_backdoor_hook(transmute(hook), func_backdoor_hook_wrapper::<QT, S>)
@ -868,10 +894,10 @@ where
pub fn backdoor_closure(
&self,
hook: Box<dyn for<'a> FnMut(&'a mut Self, Option<&'a mut S>, GuestAddr)>,
) -> HookId {
) -> BackdoorHookId {
unsafe {
let fat: FatPtr = transmute(hook);
BACKDOOR_HOOKS.push((HookId(0), fat));
BACKDOOR_HOOKS.push((BackdoorHookId(0), fat));
let id = self.emulator.add_backdoor_hook(
&mut ((*addr_of_mut!(BACKDOOR_HOOKS)).last_mut().unwrap().1),
closure_backdoor_hook_wrapper::<QT, S>,
@ -927,7 +953,7 @@ where
GuestAddr,
) -> SyscallHookResult,
>,
) -> HookId {
) -> PreSyscallHookId {
match hook {
Hook::Function(f) => self.syscalls_function(f),
Hook::Closure(c) => self.syscalls_closure(c),
@ -935,7 +961,7 @@ where
let z: *const () = ptr::null::<()>();
self.emulator.add_pre_syscall_hook(z, r)
}
Hook::Empty => HookId(0), // TODO error type
Hook::Empty => PreSyscallHookId(0), // TODO error type
}
}
@ -956,7 +982,7 @@ where
a6: GuestAddr,
a7: GuestAddr,
) -> SyscallHookResult,
) -> HookId {
) -> PreSyscallHookId {
unsafe {
self.emulator
.add_pre_syscall_hook(transmute(hook), func_pre_syscall_hook_wrapper::<QT, S>)
@ -982,10 +1008,10 @@ where
GuestAddr,
) -> SyscallHookResult,
>,
) -> HookId {
) -> PreSyscallHookId {
unsafe {
let fat: FatPtr = transmute(hook);
PRE_SYSCALL_HOOKS.push((HookId(0), fat));
PRE_SYSCALL_HOOKS.push((PreSyscallHookId(0), fat));
let id = self.emulator.add_pre_syscall_hook(
&mut ((*addr_of_mut!(PRE_SYSCALL_HOOKS)).last_mut().unwrap().1),
closure_pre_syscall_hook_wrapper::<QT, S>,
@ -1044,7 +1070,7 @@ where
GuestAddr,
) -> GuestAddr,
>,
) -> HookId {
) -> PostSyscallHookId {
match hook {
Hook::Function(f) => self.after_syscalls_function(f),
Hook::Closure(c) => self.after_syscalls_closure(c),
@ -1052,7 +1078,7 @@ where
let z: *const () = ptr::null::<()>();
self.emulator.add_post_syscall_hook(z, r)
}
Hook::Empty => HookId(0), // TODO error type
Hook::Empty => PostSyscallHookId(0), // TODO error type
}
}
@ -1074,7 +1100,7 @@ where
a6: GuestAddr,
a7: GuestAddr,
) -> GuestAddr,
) -> HookId {
) -> PostSyscallHookId {
unsafe {
self.emulator
.add_post_syscall_hook(transmute(hook), func_post_syscall_hook_wrapper::<QT, S>)
@ -1101,10 +1127,10 @@ where
GuestAddr,
) -> GuestAddr,
>,
) -> HookId {
) -> PostSyscallHookId {
unsafe {
let fat: FatPtr = transmute(hook);
POST_SYSCALL_HOOKS.push((HookId(0), fat));
POST_SYSCALL_HOOKS.push((PostSyscallHookId(0), fat));
let id = self.emulator.add_post_syscall_hook(
&mut ((*addr_of_mut!(POST_SYSCALL_HOOKS)).last_mut().unwrap().1),
closure_post_syscall_hook_wrapper::<QT, S>,
@ -1122,7 +1148,7 @@ where
Box<dyn for<'a> FnMut(&'a mut Self, Option<&'a mut S>, u32) -> bool>,
extern "C" fn(*const (), tid: u32) -> bool,
>,
) -> HookId {
) -> NewThreadHookId {
match hook {
Hook::Function(f) => self.thread_creation_function(f),
Hook::Closure(c) => self.thread_creation_closure(c),
@ -1130,7 +1156,7 @@ where
let z: *const () = ptr::null::<()>();
self.emulator.add_new_thread_hook(z, r)
}
Hook::Empty => HookId(0), // TODO error type
Hook::Empty => NewThreadHookId(0), // TODO error type
}
}
@ -1138,7 +1164,7 @@ where
pub fn thread_creation_function(
&self,
hook: fn(&mut Self, Option<&mut S>, tid: u32) -> bool,
) -> HookId {
) -> NewThreadHookId {
unsafe {
self.emulator
.add_new_thread_hook(transmute(hook), func_new_thread_hook_wrapper::<QT, S>)
@ -1149,10 +1175,10 @@ where
pub fn thread_creation_closure(
&self,
hook: Box<dyn for<'a> FnMut(&'a mut Self, Option<&'a mut S>, u32) -> bool>,
) -> HookId {
) -> NewThreadHookId {
unsafe {
let fat: FatPtr = transmute(hook);
NEW_THREAD_HOOKS.push((HookId(0), fat));
NEW_THREAD_HOOKS.push((NewThreadHookId(0), fat));
let id = self.emulator.add_new_thread_hook(
&mut (*addr_of_mut!(NEW_THREAD_HOOKS)).last_mut().unwrap().1,
closure_new_thread_hook_wrapper::<QT, S>,