Pre init module hooks (#2704)
* differenciate pre qemu init and post qemu init hooks * api breakage: Emulator::new_with_qemu is not public anymore.
This commit is contained in:
parent
f74a965ead
commit
b324e88631
@ -12,8 +12,8 @@ use crate::{
|
||||
command::{CommandManager, NopCommandManager, StdCommandManager},
|
||||
config::QemuConfig,
|
||||
modules::{EmulatorModule, EmulatorModuleTuple},
|
||||
Emulator, NopEmulatorDriver, NopSnapshotManager, Qemu, QemuInitError, StdEmulatorDriver,
|
||||
StdSnapshotManager,
|
||||
Emulator, EmulatorHooks, NopEmulatorDriver, NopSnapshotManager, Qemu, QemuHooks, QemuInitError,
|
||||
StdEmulatorDriver, StdSnapshotManager,
|
||||
};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
@ -118,6 +118,10 @@ where
|
||||
{
|
||||
let qemu_builder = self.qemu_builder.ok_or(QemuInitError::EmptyArgs)?;
|
||||
|
||||
let mut emulator_hooks = unsafe { EmulatorHooks::new(QemuHooks::get_unchecked()) };
|
||||
|
||||
self.modules.pre_qemu_init_all(&mut emulator_hooks);
|
||||
|
||||
let qemu: Qemu = match qemu_builder {
|
||||
QemuBuilder::Qemu(qemu) => qemu,
|
||||
QemuBuilder::QemuConfig(qemu_config) => {
|
||||
@ -127,13 +131,16 @@ where
|
||||
QemuBuilder::QemuString(qemu_string) => Qemu::init(&qemu_string)?,
|
||||
};
|
||||
|
||||
Emulator::new_with_qemu(
|
||||
qemu,
|
||||
self.modules,
|
||||
self.driver,
|
||||
self.snapshot_manager,
|
||||
self.command_manager,
|
||||
)
|
||||
unsafe {
|
||||
Ok(Emulator::new_with_qemu(
|
||||
qemu,
|
||||
emulator_hooks,
|
||||
self.modules,
|
||||
self.driver,
|
||||
self.snapshot_manager,
|
||||
self.command_manager,
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -64,7 +64,7 @@ macro_rules! hook_to_repr {
|
||||
};
|
||||
}
|
||||
|
||||
static mut EMULATOR_TOOLS: *mut () = ptr::null_mut();
|
||||
static mut EMULATOR_MODULES: *mut () = ptr::null_mut();
|
||||
|
||||
#[cfg(feature = "usermode")]
|
||||
pub extern "C" fn crash_hook_wrapper<ET, S>(target_sig: i32)
|
||||
@ -919,14 +919,14 @@ where
|
||||
pub unsafe fn emulator_modules_mut_unchecked<'a>() -> &'a mut EmulatorModules<ET, S> {
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
(EMULATOR_TOOLS as *mut EmulatorModules<ET, S>)
|
||||
(EMULATOR_MODULES as *mut EmulatorModules<ET, S>)
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
#[cfg(not(debug_assertions))]
|
||||
{
|
||||
&mut *(EMULATOR_TOOLS as *mut EmulatorModules<ET, S>)
|
||||
&mut *(EMULATOR_MODULES as *mut EmulatorModules<ET, S>)
|
||||
}
|
||||
}
|
||||
|
||||
@ -940,7 +940,7 @@ where
|
||||
/// generic use (it will suppose they are the same as the ones used at initialization time).
|
||||
#[must_use]
|
||||
pub unsafe fn emulator_modules_mut<'a>() -> Option<&'a mut EmulatorModules<ET, S>> {
|
||||
unsafe { (EMULATOR_TOOLS as *mut EmulatorModules<ET, S>).as_mut() }
|
||||
unsafe { (EMULATOR_MODULES as *mut EmulatorModules<ET, S>).as_mut() }
|
||||
}
|
||||
}
|
||||
|
||||
@ -1101,11 +1101,15 @@ where
|
||||
ET: EmulatorModuleTuple<S>,
|
||||
S: UsesInput + Unpin,
|
||||
{
|
||||
pub(super) fn new(qemu: Qemu, modules: ET) -> Pin<Box<Self>> {
|
||||
pub(super) fn new(
|
||||
qemu: Qemu,
|
||||
emulator_hooks: EmulatorHooks<ET, S>,
|
||||
modules: ET,
|
||||
) -> Pin<Box<Self>> {
|
||||
let mut modules = Box::pin(Self {
|
||||
qemu,
|
||||
modules: Box::pin(modules),
|
||||
hooks: EmulatorHooks::default(),
|
||||
hooks: emulator_hooks,
|
||||
phantom: PhantomData,
|
||||
});
|
||||
|
||||
@ -1116,24 +1120,25 @@ where
|
||||
|
||||
// Set global EmulatorModules pointer
|
||||
unsafe {
|
||||
if EMULATOR_TOOLS.is_null() {
|
||||
EMULATOR_TOOLS = ptr::from_mut::<Self>(modules.as_mut().get_mut()) as *mut ();
|
||||
if EMULATOR_MODULES.is_null() {
|
||||
EMULATOR_MODULES = ptr::from_mut::<Self>(modules.as_mut().get_mut()) as *mut ();
|
||||
} else {
|
||||
panic!("Emulator Modules have already been set and is still active. It is not supported to have multiple instances of `EmulatorModules` at the same time yet.")
|
||||
}
|
||||
}
|
||||
|
||||
unsafe {
|
||||
// We give access to EmulatorModuleTuple<S> 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.
|
||||
modules
|
||||
.modules
|
||||
.init_modules_all(Self::emulator_modules_mut_unchecked());
|
||||
}
|
||||
|
||||
modules
|
||||
}
|
||||
|
||||
pub fn post_qemu_init_all(&mut self) {
|
||||
// We give access to EmulatorModuleTuple<S> 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());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn first_exec_all(&mut self, state: &mut S) {
|
||||
// # Safety
|
||||
// We assume that the emulator was initialized correctly
|
||||
@ -1336,7 +1341,7 @@ where
|
||||
fn drop(&mut self) {
|
||||
// Make the global pointer null at drop time
|
||||
unsafe {
|
||||
EMULATOR_TOOLS = ptr::null_mut();
|
||||
EMULATOR_MODULES = ptr::null_mut();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -19,8 +19,8 @@ use crate::{
|
||||
command::{CommandError, CommandManager, NopCommandManager, StdCommandManager},
|
||||
modules::EmulatorModuleTuple,
|
||||
sync_exit::SyncExit,
|
||||
Qemu, QemuExitError, QemuExitReason, QemuInitError, QemuMemoryChunk, QemuShutdownCause, Regs,
|
||||
CPU,
|
||||
Qemu, QemuExitError, QemuExitReason, QemuHooks, QemuInitError, QemuMemoryChunk,
|
||||
QemuShutdownCause, Regs, CPU,
|
||||
};
|
||||
|
||||
mod hooks;
|
||||
@ -325,31 +325,55 @@ where
|
||||
pub fn new(
|
||||
qemu_args: &[String],
|
||||
modules: ET,
|
||||
drivers: ED,
|
||||
snapshot_manager: SM,
|
||||
command_manager: CM,
|
||||
) -> Result<Self, QemuInitError> {
|
||||
let qemu = Qemu::init(qemu_args)?;
|
||||
|
||||
Self::new_with_qemu(qemu, modules, drivers, snapshot_manager, command_manager)
|
||||
}
|
||||
|
||||
pub fn new_with_qemu(
|
||||
qemu: Qemu,
|
||||
modules: ET,
|
||||
driver: ED,
|
||||
snapshot_manager: SM,
|
||||
command_manager: CM,
|
||||
) -> Result<Self, QemuInitError> {
|
||||
Ok(Emulator {
|
||||
modules: EmulatorModules::new(qemu, modules),
|
||||
let mut emulator_hooks = unsafe { EmulatorHooks::new(QemuHooks::get_unchecked()) };
|
||||
|
||||
modules.pre_qemu_init_all(&mut emulator_hooks);
|
||||
|
||||
let qemu = Qemu::init(qemu_args)?;
|
||||
|
||||
unsafe {
|
||||
Ok(Self::new_with_qemu(
|
||||
qemu,
|
||||
emulator_hooks,
|
||||
modules,
|
||||
driver,
|
||||
snapshot_manager,
|
||||
command_manager,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
/// New emulator with already initialized QEMU.
|
||||
/// We suppose modules init hooks have already been run.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// pre-init qemu hooks should be run by then.
|
||||
pub(crate) unsafe fn new_with_qemu(
|
||||
qemu: Qemu,
|
||||
emulator_hooks: EmulatorHooks<ET, S>,
|
||||
modules: ET,
|
||||
driver: ED,
|
||||
snapshot_manager: SM,
|
||||
command_manager: CM,
|
||||
) -> Self {
|
||||
let mut emulator = Emulator {
|
||||
modules: EmulatorModules::new(qemu, emulator_hooks, modules),
|
||||
command_manager,
|
||||
snapshot_manager,
|
||||
driver,
|
||||
breakpoints_by_addr: RefCell::new(HashMap::new()),
|
||||
breakpoints_by_id: RefCell::new(HashMap::new()),
|
||||
qemu,
|
||||
})
|
||||
};
|
||||
|
||||
emulator.modules.post_qemu_init_all();
|
||||
|
||||
emulator
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -399,7 +399,7 @@ where
|
||||
#[cfg(feature = "systemmode")]
|
||||
type ModulePageFilter = NopPageFilter;
|
||||
|
||||
fn init_module<ET>(&self, emulator_modules: &mut EmulatorModules<ET, S>)
|
||||
fn post_qemu_init<ET>(&self, emulator_modules: &mut EmulatorModules<ET, S>)
|
||||
where
|
||||
ET: EmulatorModuleTuple<S>,
|
||||
{
|
||||
|
@ -264,7 +264,7 @@ where
|
||||
#[cfg(feature = "systemmode")]
|
||||
type ModulePageFilter = NopPageFilter;
|
||||
|
||||
fn init_module<ET>(&self, emulator_modules: &mut EmulatorModules<ET, S>)
|
||||
fn post_qemu_init<ET>(&self, emulator_modules: &mut EmulatorModules<ET, S>)
|
||||
where
|
||||
ET: EmulatorModuleTuple<S>,
|
||||
{
|
||||
|
@ -40,7 +40,7 @@ pub mod drcov;
|
||||
#[cfg(not(cpu_target = "hexagon"))]
|
||||
pub use drcov::{DrCovMetadata, DrCovModule, DrCovModuleBuilder};
|
||||
|
||||
use crate::{emu::EmulatorModules, Qemu};
|
||||
use crate::{emu::EmulatorModules, EmulatorHooks, Qemu};
|
||||
|
||||
/// A module for `libafl_qemu`.
|
||||
// TODO remove 'static when specialization will be stable
|
||||
@ -55,10 +55,19 @@ where
|
||||
|
||||
const HOOKS_DO_SIDE_EFFECTS: bool = true;
|
||||
|
||||
/// Initialize the module, mostly used to install some hooks early.
|
||||
/// 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.
|
||||
fn init_module<ET>(&self, _emulator_modules: &mut EmulatorModules<ET, S>)
|
||||
/// Install here hooks that should be alive for the whole execution of the VM, even before QEMU gets initialized.
|
||||
fn pre_qemu_init<ET>(&self, _emulator_hooks: &mut EmulatorHooks<ET, S>)
|
||||
where
|
||||
ET: EmulatorModuleTuple<S>,
|
||||
{
|
||||
}
|
||||
|
||||
/// 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<ET>(&self, _emulator_modules: &mut EmulatorModules<ET, S>)
|
||||
where
|
||||
ET: EmulatorModuleTuple<S>,
|
||||
{
|
||||
@ -137,7 +146,11 @@ where
|
||||
{
|
||||
const HOOKS_DO_SIDE_EFFECTS: bool;
|
||||
|
||||
fn init_modules_all<ET>(&self, _emulator_modules: &mut EmulatorModules<ET, S>)
|
||||
fn pre_qemu_init_all<ET>(&self, _emulator_hooks: &mut EmulatorHooks<ET, S>)
|
||||
where
|
||||
ET: EmulatorModuleTuple<S>;
|
||||
|
||||
fn post_qemu_init_all<ET>(&self, _emulator_modules: &mut EmulatorModules<ET, S>)
|
||||
where
|
||||
ET: EmulatorModuleTuple<S>;
|
||||
|
||||
@ -186,7 +199,13 @@ where
|
||||
{
|
||||
const HOOKS_DO_SIDE_EFFECTS: bool = false;
|
||||
|
||||
fn init_modules_all<ET>(&self, _emulator_modules: &mut EmulatorModules<ET, S>)
|
||||
fn pre_qemu_init_all<ET>(&self, _emulator_hooks: &mut EmulatorHooks<ET, S>)
|
||||
where
|
||||
ET: EmulatorModuleTuple<S>,
|
||||
{
|
||||
}
|
||||
|
||||
fn post_qemu_init_all<ET>(&self, _emulator_modules: &mut EmulatorModules<ET, S>)
|
||||
where
|
||||
ET: EmulatorModuleTuple<S>,
|
||||
{
|
||||
@ -239,12 +258,20 @@ where
|
||||
{
|
||||
const HOOKS_DO_SIDE_EFFECTS: bool = Head::HOOKS_DO_SIDE_EFFECTS || Tail::HOOKS_DO_SIDE_EFFECTS;
|
||||
|
||||
fn init_modules_all<ET>(&self, emulator_modules: &mut EmulatorModules<ET, S>)
|
||||
fn pre_qemu_init_all<ET>(&self, emulator_hooks: &mut EmulatorHooks<ET, S>)
|
||||
where
|
||||
ET: EmulatorModuleTuple<S>,
|
||||
{
|
||||
self.0.init_module(emulator_modules);
|
||||
self.1.init_modules_all(emulator_modules);
|
||||
self.0.pre_qemu_init(emulator_hooks);
|
||||
self.1.pre_qemu_init_all(emulator_hooks);
|
||||
}
|
||||
|
||||
fn post_qemu_init_all<ET>(&self, emulator_modules: &mut EmulatorModules<ET, S>)
|
||||
where
|
||||
ET: EmulatorModuleTuple<S>,
|
||||
{
|
||||
self.0.post_qemu_init(emulator_modules);
|
||||
self.1.post_qemu_init_all(emulator_modules);
|
||||
}
|
||||
|
||||
fn first_exec_all<ET>(&mut self, emulator_modules: &mut EmulatorModules<ET, S>, state: &mut S)
|
||||
|
@ -929,7 +929,7 @@ where
|
||||
type ModuleAddressFilter = StdAddressFilter;
|
||||
const HOOKS_DO_SIDE_EFFECTS: bool = false;
|
||||
|
||||
fn init_module<ET>(&self, emulator_modules: &mut EmulatorModules<ET, S>)
|
||||
fn post_qemu_init<ET>(&self, emulator_modules: &mut EmulatorModules<ET, S>)
|
||||
where
|
||||
ET: EmulatorModuleTuple<S>,
|
||||
{
|
||||
|
@ -262,7 +262,7 @@ where
|
||||
{
|
||||
type ModuleAddressFilter = NopAddressFilter;
|
||||
|
||||
fn init_module<ET>(&self, emulator_modules: &mut EmulatorModules<ET, S>)
|
||||
fn post_qemu_init<ET>(&self, emulator_modules: &mut EmulatorModules<ET, S>)
|
||||
where
|
||||
ET: EmulatorModuleTuple<S>,
|
||||
{
|
||||
|
@ -675,7 +675,7 @@ where
|
||||
{
|
||||
type ModuleAddressFilter = NopAddressFilter;
|
||||
|
||||
fn init_module<ET>(&self, emulator_modules: &mut EmulatorModules<ET, S>)
|
||||
fn post_qemu_init<ET>(&self, emulator_modules: &mut EmulatorModules<ET, S>)
|
||||
where
|
||||
ET: EmulatorModuleTuple<S>,
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user