diff --git a/libafl_qemu/src/command/mod.rs b/libafl_qemu/src/command/mod.rs index ae87cfcc3f..87402a7794 100644 --- a/libafl_qemu/src/command/mod.rs +++ b/libafl_qemu/src/command/mod.rs @@ -452,8 +452,8 @@ where // Unleash hooks if locked if emu.driver_mut().unlock_hooks() { // Prepare hooks - emu.modules_mut().first_exec_all(state); - emu.modules_mut().pre_exec_all(state, input); + emu.modules_mut().first_exec_all(qemu, state); + emu.modules_mut().pre_exec_all(qemu, state, input); } // Auto page filtering if option is enabled diff --git a/libafl_qemu/src/emu/builder.rs b/libafl_qemu/src/emu/builder.rs index 423e2ae128..e38be3cdfb 100644 --- a/libafl_qemu/src/emu/builder.rs +++ b/libafl_qemu/src/emu/builder.rs @@ -12,8 +12,8 @@ use crate::{ command::{CommandManager, NopCommandManager, StdCommandManager}, config::QemuConfig, modules::{EmulatorModule, EmulatorModuleTuple}, - Emulator, EmulatorHooks, NopEmulatorDriver, NopSnapshotManager, Qemu, QemuHooks, QemuInitError, - QemuParams, StdEmulatorDriver, StdSnapshotManager, + Emulator, EmulatorHooks, EmulatorModules, NopEmulatorDriver, NopSnapshotManager, Qemu, + QemuHooks, QemuInitError, QemuParams, StdEmulatorDriver, StdSnapshotManager, }; #[derive(Clone, Debug)] @@ -111,17 +111,23 @@ where { let qemu_parameters = self.qemu_parameters.ok_or(QemuInitError::EmptyArgs)?; - let mut emulator_hooks = unsafe { EmulatorHooks::new(QemuHooks::get_unchecked()) }; + let emulator_hooks = unsafe { EmulatorHooks::new(QemuHooks::get_unchecked()) }; - self.modules.pre_qemu_init_all(&mut emulator_hooks); + let mut emulator_modules = EmulatorModules::new(emulator_hooks, self.modules); + + // TODO: fix things there properly. The biggest issue being that it creates 2 mut ref to the module with the callback being called + unsafe { + emulator_modules + .modules_mut() + .pre_qemu_init_all(EmulatorModules::::emulator_modules_mut_unchecked()); + } let qemu = Qemu::init(qemu_parameters)?; unsafe { Ok(Emulator::new_with_qemu( qemu, - emulator_hooks, - self.modules, + emulator_modules, self.driver, self.snapshot_manager, self.command_manager, diff --git a/libafl_qemu/src/emu/drivers.rs b/libafl_qemu/src/emu/drivers.rs index 0fe0c6f161..18d380e9a7 100644 --- a/libafl_qemu/src/emu/drivers.rs +++ b/libafl_qemu/src/emu/drivers.rs @@ -54,7 +54,7 @@ where /// Just before calling user's harness for the first time. /// Called only once fn first_harness_exec(emulator: &mut Emulator, state: &mut S) { - emulator.modules.first_exec_all(state); + emulator.modules.first_exec_all(emulator.qemu, state); } /// Just before calling user's harness @@ -63,7 +63,7 @@ where state: &mut S, input: &S::Input, ) { - emulator.modules.pre_exec_all(state, input); + emulator.modules.pre_exec_all(emulator.qemu, state, input); } /// Just after returning from user's harness @@ -78,7 +78,7 @@ where { emulator .modules - .post_exec_all(state, input, observers, exit_kind); + .post_exec_all(emulator.qemu, state, input, observers, exit_kind); } /// Just before entering QEMU @@ -169,7 +169,7 @@ where { fn first_harness_exec(emulator: &mut Emulator, state: &mut S) { if !emulator.driver.hooks_locked { - emulator.modules.first_exec_all(state); + emulator.modules.first_exec_all(emulator.qemu, state); } } @@ -179,7 +179,7 @@ where input: &S::Input, ) { if !emulator.driver.hooks_locked { - emulator.modules.pre_exec_all(state, input); + emulator.modules.pre_exec_all(emulator.qemu, state, input); } let input_location = { emulator.driver.input_location.get().cloned() }; @@ -206,7 +206,7 @@ where if !emulator.driver.hooks_locked { emulator .modules - .post_exec_all(state, input, observers, exit_kind); + .post_exec_all(emulator.qemu, state, input, observers, exit_kind); } } diff --git a/libafl_qemu/src/emu/hooks.rs b/libafl_qemu/src/emu/hooks.rs index bb07522b60..61e3759ca9 100644 --- a/libafl_qemu/src/emu/hooks.rs +++ b/libafl_qemu/src/emu/hooks.rs @@ -3,7 +3,7 @@ use std::{fmt::Debug, marker::PhantomData, mem::transmute, pin::Pin, ptr}; use libafl::{executors::ExitKind, inputs::UsesInput, observers::ObserversTuple}; -use libafl_qemu_sys::{CPUArchStatePtr, CPUStatePtr, FatPtr, GuestAddr, GuestUsize, TCGTemp}; +use libafl_qemu_sys::{CPUStatePtr, FatPtr, GuestAddr, GuestUsize, TCGTemp}; #[cfg(feature = "usermode")] use crate::qemu::{ @@ -37,9 +37,15 @@ use crate::{ ReadExecNHook, ReadGenHook, ReadHookId, TcgHookState, WriteExecHook, WriteExecNHook, WriteGenHook, WriteHookId, }, - CpuPostRunHook, CpuPreRunHook, CpuRunHookId, HookState, MemAccessInfo, Qemu, + CpuPostRunHook, CpuPreRunHook, CpuRunHookId, HookState, MemAccessInfo, NewThreadHookFn, Qemu, }; +/// Get a C-compatible function pointer from the input hook. +/// If the hook was already a c function, nothing is done. +/// +/// h: input hook +/// replacement: C-compatible function to call when C side should call the hook +/// fntype: type used to cast h into replacement macro_rules! get_raw_hook { ($h:expr, $replacement:expr, $fntype:ty) => { match $h { @@ -100,7 +106,6 @@ pub struct EmulatorModules where S: UsesInput, { - qemu: Qemu, modules: Pin>, hooks: EmulatorHooks, phantom: PhantomData, @@ -679,10 +684,7 @@ where } } - pub fn backdoor_function( - &self, - hook: fn(&mut EmulatorModules, Option<&mut S>, cpu: CPUArchStatePtr, pc: GuestAddr), - ) -> BackdoorHookId { + pub fn backdoor_function(&self, hook: BackdoorHookFn) -> BackdoorHookId { unsafe { self.qemu_hooks .add_backdoor_hook(transmute(hook), func_backdoor_hook_wrapper::) @@ -715,15 +717,7 @@ where } } - pub fn thread_creation_function( - &mut self, - hook: fn( - &mut EmulatorModules, - Option<&mut S>, - env: CPUArchStatePtr, - tid: u32, - ) -> bool, - ) -> NewThreadHookId { + pub fn thread_creation_function(&mut self, hook: NewThreadHookFn) -> NewThreadHookId { unsafe { self.qemu_hooks .add_new_thread_hook(transmute(hook), func_new_thread_hook_wrapper::) @@ -965,7 +959,7 @@ where pub fn instruction_function( &mut self, addr: GuestAddr, - hook: fn(&mut EmulatorModules, Option<&mut S>, GuestAddr), + hook: InstructionHookFn, invalidate_block: bool, ) -> InstructionHookId { self.hooks @@ -1076,15 +1070,7 @@ where self.hooks.thread_creation(hook) } - pub fn thread_creation_function( - &mut self, - hook: fn( - &mut EmulatorModules, - Option<&mut S>, - env: CPUArchStatePtr, - tid: u32, - ) -> bool, - ) -> NewThreadHookId { + pub fn thread_creation_function(&mut self, hook: NewThreadHookFn) -> NewThreadHookId { self.hooks.thread_creation_function(hook) } @@ -1101,13 +1087,8 @@ where ET: EmulatorModuleTuple, S: UsesInput + Unpin, { - pub(super) fn new( - qemu: Qemu, - emulator_hooks: EmulatorHooks, - modules: ET, - ) -> Pin> { + pub(super) fn new(emulator_hooks: EmulatorHooks, modules: ET) -> Pin> { let mut modules = Box::pin(Self { - qemu, modules: Box::pin(modules), hooks: emulator_hooks, phantom: PhantomData, @@ -1130,35 +1111,41 @@ where modules } - pub fn post_qemu_init_all(&mut self) { + /// Run post-QEMU init module callbacks. + pub unsafe fn post_qemu_init_all(&mut self, qemu: Qemu) { // We give access to EmulatorModuleTuple during init, the compiler complains (for good reasons) // TODO: We should find a way to be able to check for a module without giving full access to the tuple. unsafe { self.modules_mut() - .post_qemu_init_all(Self::emulator_modules_mut_unchecked()); + .post_qemu_init_all(qemu, Self::emulator_modules_mut_unchecked()); } } - pub fn first_exec_all(&mut self, state: &mut S) { + pub fn first_exec_all(&mut self, qemu: Qemu, state: &mut S) { // # Safety // We assume that the emulator was initialized correctly unsafe { self.modules_mut() - .first_exec_all(Self::emulator_modules_mut_unchecked(), state); + .first_exec_all(qemu, Self::emulator_modules_mut_unchecked(), state); } } - pub fn pre_exec_all(&mut self, state: &mut S, input: &S::Input) { + pub fn pre_exec_all(&mut self, qemu: Qemu, state: &mut S, input: &S::Input) { // # Safety // We assume that the emulator was initialized correctly unsafe { - self.modules_mut() - .pre_exec_all(Self::emulator_modules_mut_unchecked(), state, input); + self.modules_mut().pre_exec_all( + qemu, + Self::emulator_modules_mut_unchecked(), + state, + input, + ); } } pub fn post_exec_all( &mut self, + qemu: Qemu, state: &mut S, input: &S::Input, observers: &mut OT, @@ -1168,6 +1155,7 @@ where { unsafe { self.modules_mut().post_exec_all( + qemu, Self::emulator_modules_mut_unchecked(), state, input, @@ -1199,11 +1187,6 @@ impl EmulatorModules where S: UsesInput, { - #[must_use] - pub fn qemu(&self) -> Qemu { - self.qemu - } - #[must_use] pub fn modules(&self) -> &ET { self.modules.as_ref().get_ref() diff --git a/libafl_qemu/src/emu/mod.rs b/libafl_qemu/src/emu/mod.rs index 0fcf92e3f6..e3e140c0cf 100644 --- a/libafl_qemu/src/emu/mod.rs +++ b/libafl_qemu/src/emu/mod.rs @@ -329,17 +329,22 @@ where snapshot_manager: SM, command_manager: CM, ) -> Result { - let mut emulator_hooks = unsafe { EmulatorHooks::new(QemuHooks::get_unchecked()) }; + let emulator_hooks = unsafe { EmulatorHooks::new(QemuHooks::get_unchecked()) }; + let mut emulator_modules = EmulatorModules::new(emulator_hooks, modules); - modules.pre_qemu_init_all(&mut emulator_hooks); + // TODO: fix things there properly. The biggest issue being that it creates 2 mut ref to the module with the callback being called + unsafe { + emulator_modules + .modules_mut() + .pre_qemu_init_all(EmulatorModules::::emulator_modules_mut_unchecked()); + } let qemu = Qemu::init(qemu_args)?; unsafe { Ok(Self::new_with_qemu( qemu, - emulator_hooks, - modules, + emulator_modules, driver, snapshot_manager, command_manager, @@ -352,17 +357,16 @@ where /// /// # Safety /// - /// pre-init qemu hooks should be run by then. + /// pre-init qemu hooks should be run before calling this. pub(crate) unsafe fn new_with_qemu( qemu: Qemu, - emulator_hooks: EmulatorHooks, - modules: ET, + emulator_modules: Pin>>, driver: ED, snapshot_manager: SM, command_manager: CM, ) -> Self { let mut emulator = Emulator { - modules: EmulatorModules::new(qemu, emulator_hooks, modules), + modules: emulator_modules, command_manager, snapshot_manager, driver, @@ -371,7 +375,7 @@ where qemu, }; - emulator.modules.post_qemu_init_all(); + emulator.modules.post_qemu_init_all(qemu); emulator } diff --git a/libafl_qemu/src/modules/calls.rs b/libafl_qemu/src/modules/calls.rs index 1e280a0720..951f51e97f 100644 --- a/libafl_qemu/src/modules/calls.rs +++ b/libafl_qemu/src/modules/calls.rs @@ -243,6 +243,7 @@ where } fn on_ret( + qemu: Qemu, emulator_modules: &mut EmulatorModules, state: Option<&mut S>, pc: GuestAddr, @@ -250,7 +251,7 @@ where S: Unpin + UsesInput, ET: EmulatorModuleTuple, { - let ret_addr: GuestAddr = emulator_modules.qemu().read_return_address().unwrap(); + let ret_addr: GuestAddr = qemu.read_return_address().unwrap(); // log::info!("RET @ 0x{:#x}", ret_addr); @@ -270,6 +271,7 @@ where } fn gen_blocks_calls( + qemu: Qemu, emulator_modules: &mut EmulatorModules, _state: Option<&mut S>, pc: GuestAddr, @@ -292,8 +294,6 @@ where .unwrap(); } - let qemu = emulator_modules.qemu(); - let mut call_addrs: Vec<(GuestAddr, usize)> = Vec::new(); let mut ret_addrs: Vec = Vec::new(); @@ -362,7 +362,10 @@ where for (call_addr, call_len) in call_addrs { // TODO do not use a closure, find a more efficient way to pass call_len let call_cb = Box::new( - move |emulator_modules: &mut EmulatorModules, state: Option<&mut S>, pc| { + move |_qemu: Qemu, + emulator_modules: &mut EmulatorModules, + state: Option<&mut S>, + pc| { // eprintln!("CALL @ 0x{:#x}", pc + call_len); let mut collectors = if let Some(h) = emulator_modules.get_mut::() { h.collectors.take() @@ -399,7 +402,7 @@ where #[cfg(feature = "systemmode")] type ModulePageFilter = NopPageFilter; - fn post_qemu_init(&self, emulator_modules: &mut EmulatorModules) + fn post_qemu_init(&self, _qemu: Qemu, emulator_modules: &mut EmulatorModules) where ET: EmulatorModuleTuple, { @@ -412,21 +415,20 @@ where fn pre_exec( &mut self, - emulator_modules: &mut EmulatorModules, + qemu: Qemu, + _emulator_modules: &mut EmulatorModules, _state: &mut S, input: &S::Input, ) where ET: EmulatorModuleTuple, { - self.collectors - .as_mut() - .unwrap() - .pre_exec_all(emulator_modules.qemu(), input); + self.collectors.as_mut().unwrap().pre_exec_all(qemu, input); } fn post_exec( &mut self, - emulator_modules: &mut EmulatorModules, + qemu: Qemu, + _emulator_modules: &mut EmulatorModules, _state: &mut S, input: &S::Input, observers: &mut OT, @@ -435,12 +437,10 @@ where OT: ObserversTuple, ET: EmulatorModuleTuple, { - self.collectors.as_mut().unwrap().post_exec_all( - emulator_modules.qemu(), - input, - observers, - exit_kind, - ); + self.collectors + .as_mut() + .unwrap() + .post_exec_all(qemu, input, observers, exit_kind); } fn address_filter(&self) -> &Self::ModuleAddressFilter { diff --git a/libafl_qemu/src/modules/cmplog.rs b/libafl_qemu/src/modules/cmplog.rs index b595971374..69ec5cb605 100644 --- a/libafl_qemu/src/modules/cmplog.rs +++ b/libafl_qemu/src/modules/cmplog.rs @@ -14,11 +14,12 @@ use serde::{Deserialize, Serialize}; #[cfg(feature = "systemmode")] use crate::modules::{NopPageFilter, NOP_PAGE_FILTER}; #[cfg(feature = "usermode")] -use crate::{capstone, qemu::ArchExtras, CallingConvention, Qemu}; +use crate::{capstone, qemu::ArchExtras, CallingConvention}; use crate::{ emu::EmulatorModules, modules::{hash_me, AddressFilter, EmulatorModule, EmulatorModuleTuple, StdAddressFilter}, qemu::Hook, + Qemu, }; #[cfg_attr( @@ -74,8 +75,12 @@ where #[cfg(feature = "systemmode")] type ModulePageFilter = NopPageFilter; - fn first_exec(&mut self, emulator_modules: &mut EmulatorModules, _state: &mut S) - where + fn first_exec( + &mut self, + _qemu: Qemu, + emulator_modules: &mut EmulatorModules, + _state: &mut S, + ) where ET: EmulatorModuleTuple, { emulator_modules.cmps( @@ -139,8 +144,12 @@ where const HOOKS_DO_SIDE_EFFECTS: bool = false; - fn first_exec(&mut self, emulator_modules: &mut EmulatorModules, _state: &mut S) - where + fn first_exec( + &mut self, + _qemu: Qemu, + emulator_modules: &mut EmulatorModules, + _state: &mut S, + ) where ET: EmulatorModuleTuple, { emulator_modules.cmps( @@ -172,6 +181,7 @@ where } pub fn gen_unique_cmp_ids( + _qemu: Qemu, emulator_modules: &mut EmulatorModules, state: Option<&mut S>, pc: GuestAddr, @@ -203,6 +213,7 @@ where } pub fn gen_hashed_cmp_ids( + _qemu: Qemu, emulator_modules: &mut EmulatorModules, _state: Option<&mut S>, pc: GuestAddr, @@ -296,6 +307,7 @@ impl CmpLogRoutinesModule { } fn gen_blocks_calls( + qemu: Qemu, emulator_modules: &mut EmulatorModules, _state: Option<&mut S>, pc: GuestAddr, @@ -318,8 +330,6 @@ impl CmpLogRoutinesModule { .unwrap(); } - let qemu = emulator_modules.qemu(); - if let Some(h) = emulator_modules.get::() { #[allow(unused_mut)] let mut code = { @@ -391,8 +401,12 @@ where #[cfg(feature = "systemmode")] type ModulePageFilter = NopPageFilter; - fn first_exec(&mut self, emulator_modules: &mut EmulatorModules, _state: &mut S) - where + fn first_exec( + &mut self, + _qemu: Qemu, + emulator_modules: &mut EmulatorModules, + _state: &mut S, + ) where ET: EmulatorModuleTuple, { emulator_modules.blocks( diff --git a/libafl_qemu/src/modules/drcov.rs b/libafl_qemu/src/modules/drcov.rs index e40d3dda0e..9621202328 100644 --- a/libafl_qemu/src/modules/drcov.rs +++ b/libafl_qemu/src/modules/drcov.rs @@ -13,6 +13,7 @@ use crate::{ emu::EmulatorModules, modules::{AddressFilter, EmulatorModule, EmulatorModuleTuple, NopAddressFilter}, qemu::Hook, + Qemu, }; static DRCOV_IDS: Mutex>> = Mutex::new(None); @@ -264,7 +265,7 @@ where #[cfg(feature = "systemmode")] type ModulePageFilter = NopPageFilter; - fn post_qemu_init(&self, emulator_modules: &mut EmulatorModules) + fn post_qemu_init(&self, _qemu: Qemu, emulator_modules: &mut EmulatorModules) where ET: EmulatorModuleTuple, { @@ -276,15 +277,17 @@ where } #[cfg(feature = "usermode")] - fn first_exec(&mut self, emulator_modules: &mut EmulatorModules, _state: &mut S) - where + fn first_exec( + &mut self, + qemu: Qemu, + _emulator_modules: &mut EmulatorModules, + _state: &mut S, + ) where ET: EmulatorModuleTuple, { if self.module_mapping.is_none() { log::info!("Auto-filling module mapping for DrCov module from QEMU mapping."); - let qemu = emulator_modules.qemu(); - let mut module_mapping: RangeMap = RangeMap::new(); #[allow(clippy::unnecessary_cast)] // for GuestAddr -> u64 @@ -307,8 +310,12 @@ where } #[cfg(feature = "systemmode")] - fn first_exec(&mut self, _emulator_modules: &mut EmulatorModules, _state: &mut S) - where + fn first_exec( + &mut self, + _qemu: Qemu, + _emulator_modules: &mut EmulatorModules, + _state: &mut S, + ) where ET: EmulatorModuleTuple, { assert!( @@ -319,6 +326,7 @@ where fn post_exec( &mut self, + _qemu: Qemu, _emulator_modules: &mut EmulatorModules, _state: &mut S, _input: &S::Input, @@ -359,6 +367,7 @@ where } pub fn gen_unique_block_ids( + _qemu: Qemu, emulator_modules: &mut EmulatorModules, state: Option<&mut S>, pc: GuestAddr, @@ -408,6 +417,7 @@ where } pub fn gen_block_lengths( + _qemu: Qemu, emulator_modules: &mut EmulatorModules, _state: Option<&mut S>, pc: GuestAddr, @@ -430,6 +440,7 @@ pub fn gen_block_lengths( } pub fn exec_trace_block( + _qemu: Qemu, emulator_modules: &mut EmulatorModules, _state: Option<&mut S>, id: u64, diff --git a/libafl_qemu/src/modules/edges/helpers.rs b/libafl_qemu/src/modules/edges/helpers.rs index 760fce7272..e4de6642b4 100644 --- a/libafl_qemu/src/modules/edges/helpers.rs +++ b/libafl_qemu/src/modules/edges/helpers.rs @@ -60,7 +60,7 @@ mod generators { }; use crate::{ modules::{hash_me, AddressFilter, EdgeCoverageModule, EmulatorModuleTuple, PageFilter}, - EmulatorModules, + EmulatorModules, Qemu, }; fn get_mask() -> usize { @@ -78,6 +78,7 @@ mod generators { } pub fn gen_unique_edge_ids( + qemu: Qemu, emulator_modules: &mut EmulatorModules, state: Option<&mut S>, src: GuestAddr, @@ -108,10 +109,7 @@ mod generators { #[cfg(feature = "systemmode")] { - let paging_id = emulator_modules - .qemu() - .current_cpu() - .and_then(|cpu| cpu.current_paging_id()); + let paging_id = qemu.current_cpu().and_then(|cpu| cpu.current_paging_id()); if !module.must_instrument(src, paging_id) && !module.must_instrument(dest, paging_id) @@ -157,6 +155,7 @@ mod generators { #[allow(clippy::unnecessary_cast)] pub fn gen_hashed_edge_ids( + qemu: Qemu, emulator_modules: &mut EmulatorModules, _state: Option<&mut S>, src: GuestAddr, @@ -179,10 +178,7 @@ mod generators { #[cfg(feature = "systemmode")] { - let paging_id = emulator_modules - .qemu() - .current_cpu() - .and_then(|cpu| cpu.current_paging_id()); + let paging_id = qemu.current_cpu().and_then(|cpu| cpu.current_paging_id()); if !module.must_instrument(src, paging_id) && !module.must_instrument(dest, paging_id) @@ -211,6 +207,7 @@ mod generators { #[allow(clippy::unnecessary_cast)] pub fn gen_hashed_block_ids( + qemu: Qemu, emulator_modules: &mut EmulatorModules, _state: Option<&mut S>, pc: GuestAddr, @@ -234,10 +231,7 @@ mod generators { } #[cfg(feature = "systemmode")] { - let page_id = emulator_modules - .qemu() - .current_cpu() - .and_then(|cpu| cpu.current_paging_id()); + let page_id = qemu.current_cpu().and_then(|cpu| cpu.current_paging_id()); if !module.must_instrument(pc, page_id) { return None; diff --git a/libafl_qemu/src/modules/edges/mod.rs b/libafl_qemu/src/modules/edges/mod.rs index db2538ca7e..1b9cb4026a 100644 --- a/libafl_qemu/src/modules/edges/mod.rs +++ b/libafl_qemu/src/modules/edges/mod.rs @@ -9,6 +9,7 @@ use libafl_qemu_sys::GuestPhysAddr; use crate::{ emu::EmulatorModules, modules::{AddressFilter, EmulatorModule, EmulatorModuleTuple, PageFilter}, + Qemu, }; mod helpers; @@ -327,8 +328,12 @@ where type ModulePageFilter = PF; const HOOKS_DO_SIDE_EFFECTS: bool = V::DO_SIDE_EFFECTS; - fn first_exec(&mut self, emulator_modules: &mut EmulatorModules, _state: &mut S) - where + fn first_exec( + &mut self, + _qemu: Qemu, + emulator_modules: &mut EmulatorModules, + _state: &mut S, + ) where ET: EmulatorModuleTuple, { if self.use_hitcounts { diff --git a/libafl_qemu/src/modules/mod.rs b/libafl_qemu/src/modules/mod.rs index 04b80a84ee..06dea61e09 100644 --- a/libafl_qemu/src/modules/mod.rs +++ b/libafl_qemu/src/modules/mod.rs @@ -40,7 +40,7 @@ pub mod drcov; #[cfg(not(cpu_target = "hexagon"))] pub use drcov::{DrCovMetadata, DrCovModule, DrCovModuleBuilder}; -use crate::{emu::EmulatorModules, EmulatorHooks, Qemu}; +use crate::{emu::EmulatorModules, Qemu}; /// A module for `libafl_qemu`. // TODO remove 'static when specialization will be stable @@ -58,7 +58,7 @@ where /// Hook run **before** QEMU is initialized. /// This is always run when Emulator gets initialized, in any case. /// Install here hooks that should be alive for the whole execution of the VM, even before QEMU gets initialized. - fn pre_qemu_init(&self, _emulator_hooks: &mut EmulatorHooks) + fn pre_qemu_init(&self, _emulator_modules: &mut EmulatorModules) where ET: EmulatorModuleTuple, { @@ -67,7 +67,7 @@ where /// Hook run **after** QEMU is initialized. /// This is always run when Emulator gets initialized, in any case. /// Install here hooks that should be alive for the whole execution of the VM, after QEMU gets initialized. - fn post_qemu_init(&self, _emulator_modules: &mut EmulatorModules) + fn post_qemu_init(&self, _qemu: Qemu, _emulator_modules: &mut EmulatorModules) where ET: EmulatorModuleTuple, { @@ -77,8 +77,12 @@ where /// This call can be delayed to the point at which fuzzing is supposed to start. /// It is mostly used to avoid running hooks during VM initialization, either /// because it is useless or it would produce wrong results. - fn first_exec(&mut self, _emulator_modules: &mut EmulatorModules, _state: &mut S) - where + fn first_exec( + &mut self, + _qemu: Qemu, + _emulator_modules: &mut EmulatorModules, + _state: &mut S, + ) where ET: EmulatorModuleTuple, { } @@ -87,6 +91,7 @@ where /// On the first run, it is executed after [`Self::first_exec`]. fn pre_exec( &mut self, + _qemu: Qemu, _emulator_modules: &mut EmulatorModules, _state: &mut S, _input: &S::Input, @@ -98,6 +103,7 @@ where /// Run after a fuzzing run ends. fn post_exec( &mut self, + _qemu: Qemu, _emulator_modules: &mut EmulatorModules, _state: &mut S, _input: &S::Input, @@ -146,20 +152,25 @@ where { const HOOKS_DO_SIDE_EFFECTS: bool; - fn pre_qemu_init_all(&self, _emulator_hooks: &mut EmulatorHooks) + fn pre_qemu_init_all(&self, emulator_modules: &mut EmulatorModules) where ET: EmulatorModuleTuple; - fn post_qemu_init_all(&self, _emulator_modules: &mut EmulatorModules) + fn post_qemu_init_all(&self, qemu: Qemu, emulator_modules: &mut EmulatorModules) where ET: EmulatorModuleTuple; - fn first_exec_all(&mut self, emulator_modules: &mut EmulatorModules, state: &mut S) - where + fn first_exec_all( + &mut self, + qemu: Qemu, + emulator_modules: &mut EmulatorModules, + state: &mut S, + ) where ET: EmulatorModuleTuple; fn pre_exec_all( &mut self, + qemu: Qemu, emulator_modules: &mut EmulatorModules, state: &mut S, input: &S::Input, @@ -168,6 +179,7 @@ where fn post_exec_all( &mut self, + qemu: Qemu, emulator_modules: &mut EmulatorModules, state: &mut S, input: &S::Input, @@ -195,30 +207,35 @@ where impl EmulatorModuleTuple for () where - S: UsesInput, + S: UsesInput + Unpin, { const HOOKS_DO_SIDE_EFFECTS: bool = false; - fn pre_qemu_init_all(&self, _emulator_hooks: &mut EmulatorHooks) + fn pre_qemu_init_all(&self, _emulator_modules: &mut EmulatorModules) where ET: EmulatorModuleTuple, { } - fn post_qemu_init_all(&self, _emulator_modules: &mut EmulatorModules) + fn post_qemu_init_all(&self, _qemu: Qemu, _emulator_modules: &mut EmulatorModules) where ET: EmulatorModuleTuple, { } - fn first_exec_all(&mut self, _emulator_modules: &mut EmulatorModules, _state: &mut S) - where + fn first_exec_all( + &mut self, + _qemu: Qemu, + _emulator_modules: &mut EmulatorModules, + _state: &mut S, + ) where ET: EmulatorModuleTuple, { } fn pre_exec_all( &mut self, + _qemu: Qemu, _emulator_modules: &mut EmulatorModules, _state: &mut S, _input: &S::Input, @@ -229,6 +246,7 @@ where fn post_exec_all( &mut self, + _qemu: Qemu, _emulator_modules: &mut EmulatorModules, _state: &mut S, _input: &S::Input, @@ -258,44 +276,50 @@ where { const HOOKS_DO_SIDE_EFFECTS: bool = Head::HOOKS_DO_SIDE_EFFECTS || Tail::HOOKS_DO_SIDE_EFFECTS; - fn pre_qemu_init_all(&self, emulator_hooks: &mut EmulatorHooks) + fn pre_qemu_init_all(&self, emulator_modules: &mut EmulatorModules) where ET: EmulatorModuleTuple, { - self.0.pre_qemu_init(emulator_hooks); - self.1.pre_qemu_init_all(emulator_hooks); + self.0.pre_qemu_init(emulator_modules); + self.1.pre_qemu_init_all(emulator_modules); } - fn post_qemu_init_all(&self, emulator_modules: &mut EmulatorModules) + fn post_qemu_init_all(&self, qemu: Qemu, emulator_modules: &mut EmulatorModules) where ET: EmulatorModuleTuple, { - self.0.post_qemu_init(emulator_modules); - self.1.post_qemu_init_all(emulator_modules); + self.0.post_qemu_init(qemu, emulator_modules); + self.1.post_qemu_init_all(qemu, emulator_modules); } - fn first_exec_all(&mut self, emulator_modules: &mut EmulatorModules, state: &mut S) - where + fn first_exec_all( + &mut self, + qemu: Qemu, + emulator_modules: &mut EmulatorModules, + state: &mut S, + ) where ET: EmulatorModuleTuple, { - self.0.first_exec(emulator_modules, state); - self.1.first_exec_all(emulator_modules, state); + self.0.first_exec(qemu, emulator_modules, state); + self.1.first_exec_all(qemu, emulator_modules, state); } fn pre_exec_all( &mut self, + qemu: Qemu, emulator_modules: &mut EmulatorModules, state: &mut S, input: &S::Input, ) where ET: EmulatorModuleTuple, { - self.0.pre_exec(emulator_modules, state, input); - self.1.pre_exec_all(emulator_modules, state, input); + self.0.pre_exec(qemu, emulator_modules, state, input); + self.1.pre_exec_all(qemu, emulator_modules, state, input); } fn post_exec_all( &mut self, + qemu: Qemu, emulator_modules: &mut EmulatorModules, state: &mut S, input: &S::Input, @@ -306,9 +330,9 @@ where ET: EmulatorModuleTuple, { self.0 - .post_exec(emulator_modules, state, input, observers, exit_kind); + .post_exec(qemu, emulator_modules, state, input, observers, exit_kind); self.1 - .post_exec_all(emulator_modules, state, input, observers, exit_kind); + .post_exec_all(qemu, emulator_modules, state, input, observers, exit_kind); } unsafe fn on_crash_all(&mut self) { diff --git a/libafl_qemu/src/qemu/hooks.rs b/libafl_qemu/src/qemu/hooks.rs index 4165742d17..97cc83e96c 100644 --- a/libafl_qemu/src/qemu/hooks.rs +++ b/libafl_qemu/src/qemu/hooks.rs @@ -100,16 +100,16 @@ impl Hook { } } -macro_rules! create_wrapper { +macro_rules! create_pre_init_wrapper { ($name:ident, ($($param:ident : $param_type:ty),*)) => { paste::paste! { - pub extern "C" fn [](hook: &mut c_void, $($param: $param_type),*) + pub extern "C" fn [](hook: &mut (), $($param: $param_type),*) where S: UsesInput + Unpin, { unsafe { let modules = EmulatorModules::::emulator_modules_mut_unchecked(); - let func: fn(&mut EmulatorModules, Option<&mut S>, $($param_type),*) = transmute(ptr::from_mut::(hook)); + let func: fn(&mut EmulatorModules, Option<&mut S>, $($param_type),*) = transmute(ptr::from_mut::<()>(hook)); func(modules, inprocess_get_state::(), $($param),*); } } @@ -128,13 +128,13 @@ macro_rules! create_wrapper { }; ($name:ident, ($($param:ident : $param_type:ty),*), $ret_type:ty) => { paste::paste! { - pub extern "C" fn [](hook: &mut c_void, $($param: $param_type),*) -> $ret_type + pub extern "C" fn [](hook: &mut (), $($param: $param_type),*) -> $ret_type where S: UsesInput + Unpin, { unsafe { let modules = EmulatorModules::::emulator_modules_mut_unchecked(); - let func: fn(&mut EmulatorModules, Option<&mut S>, $($param_type),*) -> $ret_type= transmute(ptr::from_mut::(hook)); + let func: fn(&mut EmulatorModules, Option<&mut S>, $($param_type),*) -> $ret_type= transmute(ptr::from_mut::<()>(hook)); func(modules, inprocess_get_state::(), $($param),*) } } @@ -153,6 +153,63 @@ macro_rules! create_wrapper { }; } +macro_rules! create_wrapper { + ($name:ident, ($($param:ident : $param_type:ty),*)) => { + paste::paste! { + pub extern "C" fn [](hook: &mut (), $($param: $param_type),*) + where + S: UsesInput + Unpin, + { + unsafe { + let qemu = Qemu::get_unchecked(); + let modules = EmulatorModules::::emulator_modules_mut_unchecked(); + let func: fn(Qemu, &mut EmulatorModules, Option<&mut S>, $($param_type),*) = transmute(ptr::from_mut::<()>(hook)); + func(qemu, modules, inprocess_get_state::(), $($param),*); + } + } + + pub extern "C" fn [](hook: &mut FatPtr, $($param: $param_type),*) + where + S: Unpin + UsesInput, + { + unsafe { + let qemu = Qemu::get_unchecked(); + let modules = EmulatorModules::::emulator_modules_mut_unchecked(); + let func: &mut Box, Option<&mut S>, $($param_type),*)> = &mut *(ptr::from_mut::(hook) as *mut Box, Option<&mut S>, $($param_type),*)>); + func(qemu, modules, inprocess_get_state::(), $($param),*); + } + } + } + }; + ($name:ident, ($($param:ident : $param_type:ty),*), $ret_type:ty) => { + paste::paste! { + pub extern "C" fn [](hook: &mut (), $($param: $param_type),*) -> $ret_type + where + S: UsesInput + Unpin, + { + unsafe { + let qemu = Qemu::get_unchecked(); + let modules = EmulatorModules::::emulator_modules_mut_unchecked(); + let func: fn(Qemu, &mut EmulatorModules, Option<&mut S>, $($param_type),*) -> $ret_type= transmute(ptr::from_mut::<()>(hook)); + func(qemu, modules, inprocess_get_state::(), $($param),*) + } + } + + pub extern "C" fn [](hook: &mut FatPtr, $($param: $param_type),*) -> $ret_type + where + S: UsesInput + Unpin, + { + unsafe { + let qemu = Qemu::get_unchecked(); + let modules = EmulatorModules::::emulator_modules_mut_unchecked(); + let func: &mut Box, Option<&mut S>, $($param_type),*) -> $ret_type> = &mut *(ptr::from_mut::(hook) as *mut Box, Option<&mut S>, $($param_type),*) -> $ret_type>); + func(qemu, modules, inprocess_get_state::(), $($param),*) + } + } + } + }; +} + macro_rules! create_pre_exec_wrapper { ($name:ident, ($($param:ident : $param_type:ty),*), $hook_id:ident) => { paste::paste! { @@ -161,21 +218,22 @@ macro_rules! create_pre_exec_wrapper { S: UsesInput + Unpin, { unsafe { + let qemu = Qemu::get_unchecked(); let modules = EmulatorModules::::emulator_modules_mut_unchecked(); match &mut hook.pre_run { HookRepr::Function(ptr) => { - let func: fn(&mut EmulatorModules, Option<&mut S>, $($param_type),*) = + let func: fn(Qemu, &mut EmulatorModules, Option<&mut S>, $($param_type),*) = transmute(*ptr); - func(modules, inprocess_get_state::(), $($param),*) + func(qemu, modules, inprocess_get_state::(), $($param),*) } HookRepr::Closure(ptr) => { let func: &mut Box< - dyn FnMut(&mut EmulatorModules, Option<&mut S>, $($param_type),*), + dyn FnMut(Qemu, &mut EmulatorModules, Option<&mut S>, $($param_type),*), > = &mut *(ptr::from_mut::(ptr) as *mut Box< - dyn FnMut(&mut EmulatorModules, Option<&mut S>, $($param_type),*), + dyn FnMut(Qemu, &mut EmulatorModules, Option<&mut S>, $($param_type),*), >); - func(modules, inprocess_get_state::(), $($param),*) + func(qemu, modules, inprocess_get_state::(), $($param),*) } _ => (), } @@ -193,21 +251,22 @@ macro_rules! create_post_exec_wrapper { S: UsesInput + Unpin, { unsafe { + let qemu = Qemu::get_unchecked(); let modules = EmulatorModules::::emulator_modules_mut_unchecked(); match &mut hook.post_run { HookRepr::Function(ptr) => { - let func: fn(&mut EmulatorModules, Option<&mut S>, $($param_type),*) = + let func: fn(Qemu, &mut EmulatorModules, Option<&mut S>, $($param_type),*) = transmute(*ptr); - func(modules, inprocess_get_state::(), $($param),*); + func(qemu, modules, inprocess_get_state::(), $($param),*); } HookRepr::Closure(ptr) => { let func: &mut Box< - dyn FnMut(&mut EmulatorModules, Option<&mut S>, $($param_type),*), + dyn FnMut(Qemu, &mut EmulatorModules, Option<&mut S>, $($param_type),*), > = &mut *(ptr::from_mut::(ptr) as *mut Box< - dyn FnMut(&mut EmulatorModules, Option<&mut S>, $($param_type),*), + dyn FnMut(Qemu, &mut EmulatorModules, Option<&mut S>, $($param_type),*), >); - func(modules, inprocess_get_state::(), $($param),*); + func(qemu, modules, inprocess_get_state::(), $($param),*); } _ => (), } @@ -225,19 +284,20 @@ macro_rules! create_gen_wrapper { S: UsesInput + Unpin, { unsafe { + let qemu = Qemu::get_unchecked(); let modules = EmulatorModules::::emulator_modules_mut_unchecked(); match &mut hook.gen { HookRepr::Function(ptr) => { - let func: fn(&mut EmulatorModules, Option<&mut S>, $($param_type),*) -> Option<$ret_type> = + let func: fn(Qemu, &mut EmulatorModules, Option<&mut S>, $($param_type),*) -> Option<$ret_type> = transmute(*ptr); - func(modules, inprocess_get_state::(), $($param),*).map_or(SKIP_EXEC_HOOK, |id| id) + func(qemu, modules, inprocess_get_state::(), $($param),*).map_or(SKIP_EXEC_HOOK, |id| id) } HookRepr::Closure(ptr) => { let func: &mut Box< - dyn FnMut(&mut EmulatorModules, Option<&mut S>, $($param_type),*) -> Option<$ret_type>, - > = &mut *(ptr::from_mut::(ptr) as *mut Box, Option<&mut S>, $($param_type),*) -> Option<$ret_type>>); - func(modules, inprocess_get_state::(), $($param),*).map_or(SKIP_EXEC_HOOK, |id| id) + dyn FnMut(Qemu, &mut EmulatorModules, Option<&mut S>, $($param_type),*) -> Option<$ret_type>, + > = &mut *(ptr::from_mut::(ptr) as *mut Box, Option<&mut S>, $($param_type),*) -> Option<$ret_type>>); + func(qemu, modules, inprocess_get_state::(), $($param),*).map_or(SKIP_EXEC_HOOK, |id| id) } _ => 0, } @@ -255,18 +315,20 @@ macro_rules! create_post_gen_wrapper { S: UsesInput + Unpin, { unsafe { + let qemu = Qemu::get_unchecked(); let modules = EmulatorModules::::emulator_modules_mut_unchecked(); + match &mut hook.post_gen { HookRepr::Function(ptr) => { - let func: fn(&mut EmulatorModules, Option<&mut S>, $($param_type),*) = + let func: fn(Qemu, &mut EmulatorModules, Option<&mut S>, $($param_type),*) = transmute(*ptr); - func(modules, inprocess_get_state::(), $($param),*); + func(qemu, modules, inprocess_get_state::(), $($param),*); } HookRepr::Closure(ptr) => { let func: &mut Box< - dyn FnMut(&mut EmulatorModules, Option<&mut S>, $($param_type),*), - > = &mut *(ptr::from_mut::(ptr) as *mut Box, Option<&mut S>, $($param_type),*)>); - func(modules, inprocess_get_state::(), $($param),*); + dyn FnMut(Qemu, &mut EmulatorModules, Option<&mut S>, $($param_type),*), + > = &mut *(ptr::from_mut::(ptr) as *mut Box, Option<&mut S>, $($param_type),*)>); + func(qemu, modules, inprocess_get_state::(), $($param),*); } _ => (), } @@ -284,16 +346,18 @@ macro_rules! create_exec_wrapper { S: UsesInput + Unpin, { unsafe { + let qemu = Qemu::get_unchecked(); let modules = EmulatorModules::::emulator_modules_mut_unchecked(); + match &mut hook.execs[$execidx] { HookRepr::Function(ptr) => { - let func: fn(&mut EmulatorModules, Option<&mut S>, $($param_type),*) = transmute(*ptr); - func(modules, inprocess_get_state::(), $($param),*); + let func: fn(Qemu, &mut EmulatorModules, Option<&mut S>, $($param_type),*) = transmute(*ptr); + func(qemu, modules, inprocess_get_state::(), $($param),*); } HookRepr::Closure(ptr) => { - let func: &mut Box, Option<&mut S>, $($param_type),*)> = - &mut *(ptr::from_mut::(ptr) as *mut Box, Option<&mut S>, $($param_type),*)>); - func(modules, inprocess_get_state::(), $($param),*); + let func: &mut Box, Option<&mut S>, $($param_type),*)> = + &mut *(ptr::from_mut::(ptr) as *mut Box, Option<&mut S>, $($param_type),*)>); + func(qemu, modules, inprocess_get_state::(), $($param),*); } _ => (), } @@ -359,8 +423,8 @@ macro_rules! create_hook_types { // Instruction hook wrappers create_hook_types!( Instruction, - fn(&mut EmulatorModules, Option<&mut S>, GuestAddr), - Box FnMut(&'a mut EmulatorModules, Option<&'a mut S>, GuestAddr)>, + fn(Qemu, &mut EmulatorModules, Option<&mut S>, GuestAddr), + Box FnMut(Qemu, &'a mut EmulatorModules, Option<&'a mut S>, GuestAddr)>, extern "C" fn(*const (), pc: GuestAddr) ); create_hook_id!(Instruction, libafl_qemu_remove_instruction_hook, true); @@ -369,9 +433,9 @@ create_wrapper!(instruction, (pc: GuestAddr)); // Backdoor hook wrappers create_hook_types!( Backdoor, - fn(&mut EmulatorModules, Option<&mut S>, cpu: CPUArchStatePtr, GuestAddr), - Box FnMut(&'a mut EmulatorModules, Option<&'a mut S>, GuestAddr)>, - extern "C" fn(*const (), cpu: CPUArchStatePtr, pc: GuestAddr) + fn(Qemu, &mut EmulatorModules, Option<&mut S>, cpu: CPUArchStatePtr, GuestAddr), + Box FnMut(Qemu, &'a mut EmulatorModules, Option<&'a mut S>, GuestAddr)>, + extern "C" fn(libafl_qemu_opaque: *const (), cpu: CPUArchStatePtr, pc: GuestAddr) ); create_hook_id!(Backdoor, libafl_qemu_remove_backdoor_hook, true); create_wrapper!(backdoor, (cpu: CPUArchStatePtr, pc: GuestAddr)); @@ -381,6 +445,7 @@ create_wrapper!(backdoor, (cpu: CPUArchStatePtr, pc: GuestAddr)); create_hook_types!( PreSyscall, fn( + Qemu, &mut EmulatorModules, Option<&mut S>, sys_num: i32, @@ -395,6 +460,7 @@ create_hook_types!( ) -> SyscallHookResult, Box< dyn for<'a> FnMut( + Qemu, &'a mut EmulatorModules, Option<&'a mut S>, i32, @@ -409,6 +475,7 @@ create_hook_types!( ) -> SyscallHookResult, >, extern "C" fn( + Qemu, *const (), i32, GuestAddr, @@ -445,6 +512,7 @@ create_wrapper!( create_hook_types!( PostSyscall, fn( + Qemu, &mut EmulatorModules, Option<&mut S>, res: GuestAddr, @@ -460,6 +528,7 @@ create_hook_types!( ) -> GuestAddr, Box< dyn for<'a> FnMut( + Qemu, &'a mut EmulatorModules, Option<&mut S>, GuestAddr, @@ -475,6 +544,7 @@ create_hook_types!( ) -> GuestAddr, >, extern "C" fn( + Qemu, *const (), GuestAddr, i32, @@ -520,23 +590,23 @@ create_hook_types!( u32, ) -> bool, >, - extern "C" fn(*const (), env: CPUArchStatePtr, tid: u32) -> bool + extern "C" fn(libafl_qemu_opaque: *const (), env: CPUArchStatePtr, tid: u32) -> bool ); create_hook_id!(NewThread, libafl_qemu_remove_new_thread_hook, false); -create_wrapper!(new_thread, (env: CPUArchStatePtr, tid: u32), bool); +create_pre_init_wrapper!(new_thread, (env: CPUArchStatePtr, tid: u32), bool); // CPU Run hook wrappers create_hook_types!( CpuPreRun, - fn(&mut EmulatorModules, Option<&mut S>, cpu: CPUStatePtr), - Box FnMut(&'a mut EmulatorModules, Option<&'a mut S>, CPUStatePtr)>, - extern "C" fn(*const (), cpu: CPUStatePtr) + fn(Qemu, &mut EmulatorModules, Option<&mut S>, cpu: CPUStatePtr), + Box FnMut(Qemu, &'a mut EmulatorModules, Option<&'a mut S>, CPUStatePtr)>, + extern "C" fn(libafl_qemu_opaque: *const (), cpu: CPUStatePtr) ); create_hook_types!( CpuPostRun, - fn(&mut EmulatorModules, Option<&mut S>, cpu: CPUStatePtr), - Box FnMut(&'a mut EmulatorModules, Option<&'a mut S>, CPUStatePtr)>, - extern "C" fn(*const (), cpu: CPUStatePtr) + fn(Qemu, &mut EmulatorModules, Option<&mut S>, cpu: CPUStatePtr), + Box FnMut(Qemu, &'a mut EmulatorModules, Option<&'a mut S>, CPUStatePtr)>, + extern "C" fn(libafl_qemu_opaque: *const (), cpu: CPUStatePtr) ); create_hook_id!(CpuRun, libafl_qemu_remove_cpu_run_hook, false); create_pre_exec_wrapper!(cpu_run, (cpu: CPUStatePtr), CpuRunHookId); @@ -546,22 +616,29 @@ create_wrapper!(cpu_run, (cpu: CPUStatePtr)); // Edge hook wrappers create_hook_types!( EdgeGen, - fn(&mut EmulatorModules, Option<&mut S>, src: GuestAddr, dest: GuestAddr) -> Option, + fn( + Qemu, + &mut EmulatorModules, + Option<&mut S>, + src: GuestAddr, + dest: GuestAddr, + ) -> Option, Box< dyn for<'a> FnMut( + Qemu, &'a mut EmulatorModules, Option<&'a mut S>, GuestAddr, GuestAddr, ) -> Option, >, - extern "C" fn(*const (), src: GuestAddr, dest: GuestAddr) -> u64 + extern "C" fn(libafl_qemu_opaque: *const (), src: GuestAddr, dest: GuestAddr) -> u64 ); create_hook_types!( EdgeExec, - fn(&mut EmulatorModules, Option<&mut S>, id: u64), - Box FnMut(&'a mut EmulatorModules, Option<&'a mut S>, u64)>, - unsafe extern "C" fn(*const (), id: u64) + fn(Qemu, &mut EmulatorModules, Option<&mut S>, id: u64), + Box FnMut(Qemu, &'a mut EmulatorModules, Option<&'a mut S>, u64)>, + unsafe extern "C" fn(libafl_qemu_opaque: *const (), id: u64) ); create_hook_id!(Edge, libafl_qemu_remove_edge_hook, true); create_gen_wrapper!(edge, (src: GuestAddr, dest: GuestAddr), u64, 1, EdgeHookId); @@ -570,27 +647,36 @@ create_exec_wrapper!(edge, (id: u64), 0, 1, EdgeHookId); // Block hook wrappers create_hook_types!( BlockGen, - fn(&mut EmulatorModules, Option<&mut S>, pc: GuestAddr) -> Option, + fn(Qemu, &mut EmulatorModules, Option<&mut S>, pc: GuestAddr) -> Option, Box< dyn for<'a> FnMut( + Qemu, &'a mut EmulatorModules, Option<&'a mut S>, GuestAddr, ) -> Option, >, - unsafe extern "C" fn(*const (), pc: GuestAddr) -> u64 + unsafe extern "C" fn(libafl_qemu_opaque: *const (), pc: GuestAddr) -> u64 ); create_hook_types!( BlockPostGen, - fn(&mut EmulatorModules, Option<&mut S>, pc: GuestAddr, block_length: GuestUsize), - Box FnMut(&'a mut EmulatorModules, Option<&mut S>, GuestAddr, GuestUsize)>, - unsafe extern "C" fn(*const (), pc: GuestAddr, block_length: GuestUsize) + fn(Qemu, &mut EmulatorModules, Option<&mut S>, pc: GuestAddr, block_length: GuestUsize), + Box< + dyn for<'a> FnMut( + Qemu, + &'a mut EmulatorModules, + Option<&mut S>, + GuestAddr, + GuestUsize, + ), + >, + unsafe extern "C" fn(libafl_qemu_opaque: *const (), pc: GuestAddr, block_length: GuestUsize) ); create_hook_types!( BlockExec, - fn(&mut EmulatorModules, Option<&mut S>, id: u64), - Box FnMut(&'a mut EmulatorModules, Option<&'a mut S>, u64)>, - unsafe extern "C" fn(*const (), id: u64) + fn(Qemu, &mut EmulatorModules, Option<&mut S>, id: u64), + Box FnMut(Qemu, &'a mut EmulatorModules, Option<&'a mut S>, u64)>, + unsafe extern "C" fn(libafl_qemu_opaque: *const (), id: u64) ); create_hook_id!(Block, libafl_qemu_remove_block_hook, true); @@ -602,7 +688,8 @@ create_exec_wrapper!(block, (id: u64), 0, 1, BlockHookId); create_hook_types!( ReadGen, fn( - qemu_modules: &mut EmulatorModules, + Qemu, + emulator_modules: &mut EmulatorModules, Option<&mut S>, pc: GuestAddr, addr: *mut TCGTemp, @@ -610,6 +697,7 @@ create_hook_types!( ) -> Option, Box< dyn for<'a> FnMut( + Qemu, &'a mut EmulatorModules, Option<&'a mut S>, GuestAddr, @@ -617,21 +705,33 @@ create_hook_types!( MemAccessInfo, ) -> Option, >, - unsafe extern "C" fn(*const (), pc: GuestAddr, addr: *mut TCGTemp, info: MemAccessInfo) -> u64 + unsafe extern "C" fn( + libafl_qemu_opaque: *const (), + pc: GuestAddr, + addr: *mut TCGTemp, + info: MemAccessInfo, + ) -> u64 ); create_hook_types!( ReadExec, - fn(&mut EmulatorModules, Option<&mut S>, id: u64, addr: GuestAddr), - Box FnMut(&'a mut EmulatorModules, Option<&'a mut S>, u64, GuestAddr)>, - unsafe extern "C" fn(*const (), id: u64, addr: GuestAddr) + fn(Qemu, &mut EmulatorModules, Option<&mut S>, id: u64, addr: GuestAddr), + Box FnMut(Qemu, &'a mut EmulatorModules, Option<&'a mut S>, u64, GuestAddr)>, + unsafe extern "C" fn(libafl_qemu_opaque: *const (), id: u64, addr: GuestAddr) ); create_hook_types!( ReadExecN, - fn(&mut EmulatorModules, Option<&mut S>, id: u64, addr: GuestAddr, size: usize), + fn(Qemu, &mut EmulatorModules, Option<&mut S>, id: u64, addr: GuestAddr, size: usize), Box< - dyn for<'a> FnMut(&'a mut EmulatorModules, Option<&'a mut S>, u64, GuestAddr, usize), + dyn for<'a> FnMut( + Qemu, + &'a mut EmulatorModules, + Option<&'a mut S>, + u64, + GuestAddr, + usize, + ), >, - unsafe extern "C" fn(*const (), id: u64, addr: GuestAddr, size: usize) + unsafe extern "C" fn(libafl_qemu_opaque: *const (), id: u64, addr: GuestAddr, size: usize) ); create_hook_id!(Read, libafl_qemu_remove_read_hook, true); create_gen_wrapper!(read, (pc: GuestAddr, addr: *mut TCGTemp, info: MemAccessInfo), u64, 5, ReadHookId); @@ -651,6 +751,7 @@ create_exec_wrapper!( create_hook_types!( WriteGen, fn( + Qemu, &mut EmulatorModules, Option<&mut S>, pc: GuestAddr, @@ -659,6 +760,7 @@ create_hook_types!( ) -> Option, Box< dyn for<'a> FnMut( + Qemu, &'a mut EmulatorModules, Option<&'a mut S>, GuestAddr, @@ -666,21 +768,33 @@ create_hook_types!( MemAccessInfo, ) -> Option, >, - unsafe extern "C" fn(*const (), pc: GuestAddr, addr: *mut TCGTemp, info: MemAccessInfo) -> u64 + unsafe extern "C" fn( + libafl_qemu_opaque: *const (), + pc: GuestAddr, + addr: *mut TCGTemp, + info: MemAccessInfo, + ) -> u64 ); create_hook_types!( WriteExec, - fn(&mut EmulatorModules, Option<&mut S>, id: u64, addr: GuestAddr), - Box FnMut(&'a mut EmulatorModules, Option<&'a mut S>, u64, GuestAddr)>, - unsafe extern "C" fn(*const (), id: u64, addr: GuestAddr) + fn(Qemu, &mut EmulatorModules, Option<&mut S>, id: u64, addr: GuestAddr), + Box FnMut(Qemu, &'a mut EmulatorModules, Option<&'a mut S>, u64, GuestAddr)>, + unsafe extern "C" fn(libafl_qemu_opaque: *const (), id: u64, addr: GuestAddr) ); create_hook_types!( WriteExecN, - fn(&mut EmulatorModules, Option<&mut S>, id: u64, addr: GuestAddr, size: usize), + fn(Qemu, &mut EmulatorModules, Option<&mut S>, id: u64, addr: GuestAddr, size: usize), Box< - dyn for<'a> FnMut(&'a mut EmulatorModules, Option<&'a mut S>, u64, GuestAddr, usize), + dyn for<'a> FnMut( + Qemu, + &'a mut EmulatorModules, + Option<&'a mut S>, + u64, + GuestAddr, + usize, + ), >, - unsafe extern "C" fn(*const (), id: u64, addr: GuestAddr, size: usize) + unsafe extern "C" fn(libafl_qemu_opaque: *const (), id: u64, addr: GuestAddr, size: usize) ); create_hook_id!(Write, libafl_qemu_remove_write_hook, true); create_gen_wrapper!(write, (pc: GuestAddr, addr: *mut TCGTemp, info: MemAccessInfo), u64, 5, WriteHookId); @@ -699,16 +813,23 @@ create_exec_wrapper!( // Cmp hook wrappers create_hook_types!( CmpGen, - fn(&mut EmulatorModules, Option<&mut S>, pc: GuestAddr, size: usize) -> Option, + fn( + Qemu, + &mut EmulatorModules, + Option<&mut S>, + pc: GuestAddr, + size: usize, + ) -> Option, Box< dyn for<'a> FnMut( + Qemu, &'a mut EmulatorModules, Option<&'a mut S>, GuestAddr, usize, ) -> Option, >, - unsafe extern "C" fn(*const (), pc: GuestAddr, size: usize) -> u64 + unsafe extern "C" fn(libafl_qemu_opaque: *const (), pc: GuestAddr, size: usize) -> u64 ); pub type CmpExecHook = Hook< fn(&mut EmulatorModules, Option<&mut S>, id: u64, v0: SZ, v1: SZ), @@ -724,9 +845,9 @@ create_exec_wrapper!(cmp, (id: u64, v0: u64, v1: u64), 3, 4, CmpHookId); // Crash hook wrappers #[cfg(feature = "usermode")] -pub type CrashHookFn = fn(&mut EmulatorModules, i32); +pub type CrashHookFn = fn(Qemu, &mut EmulatorModules, i32); #[cfg(feature = "usermode")] -pub type CrashHookClosure = Box, i32)>; +pub type CrashHookClosure = Box, i32)>; /// The thin wrapper around QEMU hooks. /// It is considered unsafe to use it directly.