Support on_crash & on_timeout callbacks for libafl_qemu modules (#2620)
* support (unsafe) on_crash / on_timeout callbacks for modules * use libc types in bindgen
This commit is contained in:
parent
f0da4d15da
commit
d96d833760
@ -181,6 +181,8 @@ pub fn generate(
|
|||||||
.allowlist_function("qemu_main_loop")
|
.allowlist_function("qemu_main_loop")
|
||||||
.allowlist_function("qemu_cleanup")
|
.allowlist_function("qemu_cleanup")
|
||||||
.blocklist_function("main_loop_wait") // bindgen issue #1313
|
.blocklist_function("main_loop_wait") // bindgen issue #1313
|
||||||
|
.blocklist_type("siginfo_t")
|
||||||
|
.raw_line("use libc::siginfo_t;")
|
||||||
.parse_callbacks(Box::new(bindgen::CargoCallbacks::new()));
|
.parse_callbacks(Box::new(bindgen::CargoCallbacks::new()));
|
||||||
|
|
||||||
// arch specific functions
|
// arch specific functions
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
/* 1.83.0-nightly */
|
/* 1.84.0-nightly */
|
||||||
/* qemu git hash: d6637939526f453c69f4c6bfe4635feb5dc5c0be */
|
/* qemu git hash: 805b14ffc44999952562e8f219d81c21a4fa50b9 */
|
||||||
/* automatically generated by rust-bindgen 0.70.1 */
|
/* automatically generated by rust-bindgen 0.70.1 */
|
||||||
|
|
||||||
|
use libc::siginfo_t;
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
|
#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
|
||||||
pub struct __BindgenBitfieldUnit<Storage> {
|
pub struct __BindgenBitfieldUnit<Storage> {
|
||||||
@ -516,15 +518,6 @@ impl ::std::fmt::Debug for sigval {
|
|||||||
pub type __sigval_t = sigval;
|
pub type __sigval_t = sigval;
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub struct siginfo_t {
|
|
||||||
pub si_signo: ::std::os::raw::c_int,
|
|
||||||
pub si_errno: ::std::os::raw::c_int,
|
|
||||||
pub si_code: ::std::os::raw::c_int,
|
|
||||||
pub __pad0: ::std::os::raw::c_int,
|
|
||||||
pub _sifields: siginfo_t__bindgen_ty_1,
|
|
||||||
}
|
|
||||||
#[repr(C)]
|
|
||||||
#[derive(Copy, Clone)]
|
|
||||||
pub union siginfo_t__bindgen_ty_1 {
|
pub union siginfo_t__bindgen_ty_1 {
|
||||||
pub _pad: [::std::os::raw::c_int; 28usize],
|
pub _pad: [::std::os::raw::c_int; 28usize],
|
||||||
pub _kill: siginfo_t__bindgen_ty_1__bindgen_ty_1,
|
pub _kill: siginfo_t__bindgen_ty_1__bindgen_ty_1,
|
||||||
@ -827,31 +820,6 @@ impl ::std::fmt::Debug for siginfo_t__bindgen_ty_1 {
|
|||||||
write!(f, "siginfo_t__bindgen_ty_1 {{ union }}")
|
write!(f, "siginfo_t__bindgen_ty_1 {{ union }}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
|
|
||||||
const _: () = {
|
|
||||||
["Size of siginfo_t"][::std::mem::size_of::<siginfo_t>() - 128usize];
|
|
||||||
["Alignment of siginfo_t"][::std::mem::align_of::<siginfo_t>() - 8usize];
|
|
||||||
["Offset of field: siginfo_t::si_signo"][::std::mem::offset_of!(siginfo_t, si_signo) - 0usize];
|
|
||||||
["Offset of field: siginfo_t::si_errno"][::std::mem::offset_of!(siginfo_t, si_errno) - 4usize];
|
|
||||||
["Offset of field: siginfo_t::si_code"][::std::mem::offset_of!(siginfo_t, si_code) - 8usize];
|
|
||||||
["Offset of field: siginfo_t::__pad0"][::std::mem::offset_of!(siginfo_t, __pad0) - 12usize];
|
|
||||||
["Offset of field: siginfo_t::_sifields"]
|
|
||||||
[::std::mem::offset_of!(siginfo_t, _sifields) - 16usize];
|
|
||||||
};
|
|
||||||
impl Default for siginfo_t {
|
|
||||||
fn default() -> Self {
|
|
||||||
let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
|
|
||||||
unsafe {
|
|
||||||
::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
|
|
||||||
s.assume_init()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl ::std::fmt::Debug for siginfo_t {
|
|
||||||
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
|
|
||||||
write ! (f , "siginfo_t {{ si_signo: {:?}, si_errno: {:?}, si_code: {:?}, __pad0: {:?}, _sifields: {:?} }}" , self . si_signo , self . si_errno , self . si_code , self . __pad0 , self . _sifields)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub type guint8 = ::std::os::raw::c_uchar;
|
pub type guint8 = ::std::os::raw::c_uchar;
|
||||||
pub type gchar = ::std::os::raw::c_char;
|
pub type gchar = ::std::os::raw::c_char;
|
||||||
pub type guint = ::std::os::raw::c_uint;
|
pub type guint = ::std::os::raw::c_uint;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* 1.83.0-nightly */
|
/* 1.84.0-nightly */
|
||||||
/* qemu git hash: d6637939526f453c69f4c6bfe4635feb5dc5c0be */
|
/* qemu git hash: 805b14ffc44999952562e8f219d81c21a4fa50b9 */
|
||||||
/* automatically generated by rust-bindgen 0.70.1 */
|
/* automatically generated by rust-bindgen 0.70.1 */
|
||||||
|
|
||||||
pub const LIBAFL_SYNC_EXIT_OPCODE: u32 = 1727150607;
|
pub const LIBAFL_SYNC_EXIT_OPCODE: u32 = 1727150607;
|
||||||
|
@ -35,9 +35,6 @@ use libafl_bolts::{
|
|||||||
use libafl_qemu_sys::libafl_exit_request_timeout;
|
use libafl_qemu_sys::libafl_exit_request_timeout;
|
||||||
#[cfg(emulation_mode = "usermode")]
|
#[cfg(emulation_mode = "usermode")]
|
||||||
use libafl_qemu_sys::libafl_qemu_handle_crash;
|
use libafl_qemu_sys::libafl_qemu_handle_crash;
|
||||||
#[cfg(emulation_mode = "usermode")]
|
|
||||||
use libafl_qemu_sys::siginfo_t;
|
|
||||||
#[cfg(emulation_mode = "systemmode")]
|
|
||||||
use libc::siginfo_t;
|
use libc::siginfo_t;
|
||||||
|
|
||||||
#[cfg(emulation_mode = "usermode")]
|
#[cfg(emulation_mode = "usermode")]
|
||||||
@ -60,17 +57,26 @@ where
|
|||||||
///
|
///
|
||||||
/// This should be used as a crash handler, and nothing else.
|
/// This should be used as a crash handler, and nothing else.
|
||||||
#[cfg(emulation_mode = "usermode")]
|
#[cfg(emulation_mode = "usermode")]
|
||||||
unsafe fn inproc_qemu_crash_handler(
|
unsafe fn inproc_qemu_crash_handler<ET, S>(
|
||||||
signal: Signal,
|
signal: Signal,
|
||||||
info: &mut siginfo_t,
|
info: &mut siginfo_t,
|
||||||
mut context: Option<&mut ucontext_t>,
|
mut context: Option<&mut ucontext_t>,
|
||||||
_data: &mut InProcessExecutorHandlerData,
|
_data: &mut InProcessExecutorHandlerData,
|
||||||
) {
|
) where
|
||||||
|
ET: EmulatorModuleTuple<S>,
|
||||||
|
S: UsesInput + Unpin,
|
||||||
|
{
|
||||||
let puc = match &mut context {
|
let puc = match &mut context {
|
||||||
Some(v) => ptr::from_mut::<ucontext_t>(*v) as *mut c_void,
|
Some(v) => ptr::from_mut::<ucontext_t>(*v) as *mut c_void,
|
||||||
None => ptr::null_mut(),
|
None => ptr::null_mut(),
|
||||||
};
|
};
|
||||||
libafl_qemu_handle_crash(signal as i32, ptr::from_mut::<siginfo_t>(info), puc);
|
|
||||||
|
// run modules' crash callback
|
||||||
|
if let Some(emulator_modules) = EmulatorModules::<ET, S>::emulator_modules_mut() {
|
||||||
|
emulator_modules.modules_mut().on_crash_all();
|
||||||
|
}
|
||||||
|
|
||||||
|
libafl_qemu_handle_crash(signal as i32, info, puc);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(emulation_mode = "systemmode")]
|
#[cfg(emulation_mode = "systemmode")]
|
||||||
@ -79,8 +85,7 @@ pub(crate) static BREAK_ON_TMOUT: AtomicBool = AtomicBool::new(false);
|
|||||||
/// # Safety
|
/// # Safety
|
||||||
/// Can call through the `unix_signal_handler::inproc_timeout_handler`.
|
/// Can call through the `unix_signal_handler::inproc_timeout_handler`.
|
||||||
/// Calling this method multiple times concurrently can lead to race conditions.
|
/// Calling this method multiple times concurrently can lead to race conditions.
|
||||||
#[cfg(emulation_mode = "systemmode")]
|
pub unsafe fn inproc_qemu_timeout_handler<E, EM, ET, OF, S, Z>(
|
||||||
pub unsafe fn inproc_qemu_timeout_handler<E, EM, OF, Z>(
|
|
||||||
signal: Signal,
|
signal: Signal,
|
||||||
info: &mut siginfo_t,
|
info: &mut siginfo_t,
|
||||||
context: Option<&mut ucontext_t>,
|
context: Option<&mut ucontext_t>,
|
||||||
@ -88,16 +93,36 @@ pub unsafe fn inproc_qemu_timeout_handler<E, EM, OF, Z>(
|
|||||||
) where
|
) where
|
||||||
E: HasObservers + HasInProcessHooks<E::State> + Executor<EM, Z>,
|
E: HasObservers + HasInProcessHooks<E::State> + Executor<EM, Z>,
|
||||||
E::Observers: ObserversTuple<E::Input, E::State>,
|
E::Observers: ObserversTuple<E::Input, E::State>,
|
||||||
EM: EventFirer<State = E::State> + EventRestarter<State = E::State>,
|
|
||||||
OF: Feedback<EM, E::Input, E::Observers, E::State>,
|
|
||||||
E::State: HasExecutions + HasSolutions + HasCorpus,
|
E::State: HasExecutions + HasSolutions + HasCorpus,
|
||||||
|
EM: EventFirer<State = E::State> + EventRestarter<State = E::State>,
|
||||||
|
ET: EmulatorModuleTuple<S>,
|
||||||
|
OF: Feedback<EM, E::Input, E::Observers, E::State>,
|
||||||
|
S: State + Unpin,
|
||||||
Z: HasObjective<Objective = OF, State = E::State>,
|
Z: HasObjective<Objective = OF, State = E::State>,
|
||||||
<<E as UsesState>::State as HasSolutions>::Solutions: Corpus<Input = E::Input>, //delete me
|
<<E as UsesState>::State as HasSolutions>::Solutions: Corpus<Input = E::Input>, //delete me
|
||||||
<<<E as UsesState>::State as HasCorpus>::Corpus as Corpus>::Input: Clone, //delete me
|
<<<E as UsesState>::State as HasCorpus>::Corpus as Corpus>::Input: Clone, //delete me
|
||||||
{
|
{
|
||||||
if BREAK_ON_TMOUT.load(Ordering::Acquire) {
|
#[cfg(emulation_mode = "systemmode")]
|
||||||
libafl_exit_request_timeout();
|
{
|
||||||
} else {
|
if BREAK_ON_TMOUT.load(Ordering::Acquire) {
|
||||||
|
libafl_exit_request_timeout();
|
||||||
|
} else {
|
||||||
|
libafl::executors::hooks::unix::unix_signal_handler::inproc_timeout_handler::<
|
||||||
|
E,
|
||||||
|
EM,
|
||||||
|
OF,
|
||||||
|
Z,
|
||||||
|
>(signal, info, context, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(emulation_mode = "usermode")]
|
||||||
|
{
|
||||||
|
// run modules' crash callback
|
||||||
|
if let Some(emulator_modules) = EmulatorModules::<ET, S>::emulator_modules_mut() {
|
||||||
|
emulator_modules.modules_mut().on_timeout_all();
|
||||||
|
}
|
||||||
|
|
||||||
libafl::executors::hooks::unix::unix_signal_handler::inproc_timeout_handler::<E, EM, OF, Z>(
|
libafl::executors::hooks::unix::unix_signal_handler::inproc_timeout_handler::<E, EM, OF, Z>(
|
||||||
signal, info, context, data,
|
signal, info, context, data,
|
||||||
);
|
);
|
||||||
@ -153,7 +178,8 @@ where
|
|||||||
|
|
||||||
#[cfg(emulation_mode = "usermode")]
|
#[cfg(emulation_mode = "usermode")]
|
||||||
{
|
{
|
||||||
inner.inprocess_hooks_mut().crash_handler = inproc_qemu_crash_handler as *const c_void;
|
inner.inprocess_hooks_mut().crash_handler =
|
||||||
|
inproc_qemu_crash_handler::<ET, S> as *const c_void;
|
||||||
|
|
||||||
let handler = |emulator_modules: &mut EmulatorModules<ET, S>, host_sig| {
|
let handler = |emulator_modules: &mut EmulatorModules<ET, S>, host_sig| {
|
||||||
eprintln!("Crashed with signal {host_sig}");
|
eprintln!("Crashed with signal {host_sig}");
|
||||||
@ -175,15 +201,14 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(emulation_mode = "systemmode")]
|
inner.inprocess_hooks_mut().timeout_handler = inproc_qemu_timeout_handler::<
|
||||||
{
|
StatefulInProcessExecutor<'a, H, OT, S, Emulator<CM, ED, ET, S, SM>>,
|
||||||
inner.inprocess_hooks_mut().timeout_handler = inproc_qemu_timeout_handler::<
|
EM,
|
||||||
StatefulInProcessExecutor<'a, H, OT, S, Emulator<CM, ED, ET, S, SM>>,
|
ET,
|
||||||
EM,
|
OF,
|
||||||
OF,
|
S,
|
||||||
Z,
|
Z,
|
||||||
> as *const c_void;
|
> as *const c_void;
|
||||||
}
|
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
inner,
|
inner,
|
||||||
|
@ -108,6 +108,7 @@ pub struct DrCovModule<F> {
|
|||||||
full_trace: bool,
|
full_trace: bool,
|
||||||
drcov_len: usize,
|
drcov_len: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DrCovModule<NopAddressFilter> {
|
impl DrCovModule<NopAddressFilter> {
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn builder() -> DrCovModuleBuilder<NopAddressFilter> {
|
pub fn builder() -> DrCovModuleBuilder<NopAddressFilter> {
|
||||||
@ -119,11 +120,7 @@ impl DrCovModule<NopAddressFilter> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
impl<F> DrCovModule<F> {
|
||||||
impl<F> DrCovModule<F>
|
|
||||||
where
|
|
||||||
F: AddressFilter,
|
|
||||||
{
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[allow(clippy::let_underscore_untyped)]
|
#[allow(clippy::let_underscore_untyped)]
|
||||||
pub fn new(
|
pub fn new(
|
||||||
@ -146,84 +143,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[must_use]
|
pub fn write(&mut self) {
|
||||||
pub fn must_instrument(&self, addr: GuestAddr) -> bool {
|
|
||||||
self.filter.allowed(&addr)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<F, S> EmulatorModule<S> for DrCovModule<F>
|
|
||||||
where
|
|
||||||
F: AddressFilter,
|
|
||||||
S: Unpin + UsesInput + HasMetadata,
|
|
||||||
{
|
|
||||||
type ModuleAddressFilter = F;
|
|
||||||
#[cfg(emulation_mode = "systemmode")]
|
|
||||||
type ModulePageFilter = NopPageFilter;
|
|
||||||
|
|
||||||
fn init_module<ET>(&self, emulator_modules: &mut EmulatorModules<ET, S>)
|
|
||||||
where
|
|
||||||
ET: EmulatorModuleTuple<S>,
|
|
||||||
{
|
|
||||||
emulator_modules.blocks(
|
|
||||||
Hook::Function(gen_unique_block_ids::<ET, F, S>),
|
|
||||||
Hook::Function(gen_block_lengths::<ET, F, S>),
|
|
||||||
Hook::Function(exec_trace_block::<ET, F, S>),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(emulation_mode = "usermode")]
|
|
||||||
fn first_exec<ET>(&mut self, emulator_modules: &mut EmulatorModules<ET, S>, _state: &mut S)
|
|
||||||
where
|
|
||||||
ET: EmulatorModuleTuple<S>,
|
|
||||||
{
|
|
||||||
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<usize, (u16, String)> = RangeMap::new();
|
|
||||||
|
|
||||||
for (i, (r, p)) in qemu
|
|
||||||
.mappings()
|
|
||||||
.filter_map(|m| {
|
|
||||||
m.path()
|
|
||||||
.map(|p| ((m.start() as usize)..(m.end() as usize), p.to_string()))
|
|
||||||
.filter(|(_, p)| !p.is_empty())
|
|
||||||
})
|
|
||||||
.enumerate()
|
|
||||||
{
|
|
||||||
module_mapping.insert(r, (i as u16, p));
|
|
||||||
}
|
|
||||||
|
|
||||||
self.module_mapping = Some(module_mapping);
|
|
||||||
} else {
|
|
||||||
log::info!("Using user-provided module mapping for DrCov module.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(emulation_mode = "systemmode")]
|
|
||||||
fn first_exec<ET>(&mut self, _emulator_modules: &mut EmulatorModules<ET, S>, _state: &mut S)
|
|
||||||
where
|
|
||||||
ET: EmulatorModuleTuple<S>,
|
|
||||||
{
|
|
||||||
assert!(
|
|
||||||
self.module_mapping.is_some(),
|
|
||||||
"DrCov should have a module mapping already set."
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn post_exec<OT, ET>(
|
|
||||||
&mut self,
|
|
||||||
_emulator_modules: &mut EmulatorModules<ET, S>,
|
|
||||||
_state: &mut S,
|
|
||||||
_input: &S::Input,
|
|
||||||
_observers: &mut OT,
|
|
||||||
_exit_kind: &mut ExitKind,
|
|
||||||
) where
|
|
||||||
OT: ObserversTuple<S::Input, S>,
|
|
||||||
ET: EmulatorModuleTuple<S>,
|
|
||||||
{
|
|
||||||
let lengths_opt = DRCOV_LENGTHS.lock().unwrap();
|
let lengths_opt = DRCOV_LENGTHS.lock().unwrap();
|
||||||
let lengths = lengths_opt.as_ref().unwrap();
|
let lengths = lengths_opt.as_ref().unwrap();
|
||||||
if self.full_trace {
|
if self.full_trace {
|
||||||
@ -322,6 +242,100 @@ where
|
|||||||
self.drcov_len = DRCOV_MAP.lock().unwrap().as_ref().unwrap().len();
|
self.drcov_len = DRCOV_MAP.lock().unwrap().as_ref().unwrap().len();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<F> DrCovModule<F>
|
||||||
|
where
|
||||||
|
F: AddressFilter,
|
||||||
|
{
|
||||||
|
#[must_use]
|
||||||
|
pub fn must_instrument(&self, addr: GuestAddr) -> bool {
|
||||||
|
self.filter.allowed(&addr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<F, S> EmulatorModule<S> for DrCovModule<F>
|
||||||
|
where
|
||||||
|
F: AddressFilter,
|
||||||
|
S: Unpin + UsesInput + HasMetadata,
|
||||||
|
{
|
||||||
|
type ModuleAddressFilter = F;
|
||||||
|
#[cfg(emulation_mode = "systemmode")]
|
||||||
|
type ModulePageFilter = NopPageFilter;
|
||||||
|
|
||||||
|
fn init_module<ET>(&self, emulator_modules: &mut EmulatorModules<ET, S>)
|
||||||
|
where
|
||||||
|
ET: EmulatorModuleTuple<S>,
|
||||||
|
{
|
||||||
|
emulator_modules.blocks(
|
||||||
|
Hook::Function(gen_unique_block_ids::<ET, F, S>),
|
||||||
|
Hook::Function(gen_block_lengths::<ET, F, S>),
|
||||||
|
Hook::Function(exec_trace_block::<ET, F, S>),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(emulation_mode = "usermode")]
|
||||||
|
fn first_exec<ET>(&mut self, emulator_modules: &mut EmulatorModules<ET, S>, _state: &mut S)
|
||||||
|
where
|
||||||
|
ET: EmulatorModuleTuple<S>,
|
||||||
|
{
|
||||||
|
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<usize, (u16, String)> = RangeMap::new();
|
||||||
|
|
||||||
|
for (i, (r, p)) in qemu
|
||||||
|
.mappings()
|
||||||
|
.filter_map(|m| {
|
||||||
|
m.path()
|
||||||
|
.map(|p| ((m.start() as usize)..(m.end() as usize), p.to_string()))
|
||||||
|
.filter(|(_, p)| !p.is_empty())
|
||||||
|
})
|
||||||
|
.enumerate()
|
||||||
|
{
|
||||||
|
module_mapping.insert(r, (i as u16, p));
|
||||||
|
}
|
||||||
|
|
||||||
|
self.module_mapping = Some(module_mapping);
|
||||||
|
} else {
|
||||||
|
log::info!("Using user-provided module mapping for DrCov module.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(emulation_mode = "systemmode")]
|
||||||
|
fn first_exec<ET>(&mut self, _emulator_modules: &mut EmulatorModules<ET, S>, _state: &mut S)
|
||||||
|
where
|
||||||
|
ET: EmulatorModuleTuple<S>,
|
||||||
|
{
|
||||||
|
assert!(
|
||||||
|
self.module_mapping.is_some(),
|
||||||
|
"DrCov should have a module mapping already set."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn post_exec<OT, ET>(
|
||||||
|
&mut self,
|
||||||
|
_emulator_modules: &mut EmulatorModules<ET, S>,
|
||||||
|
_state: &mut S,
|
||||||
|
_input: &S::Input,
|
||||||
|
_observers: &mut OT,
|
||||||
|
_exit_kind: &mut ExitKind,
|
||||||
|
) where
|
||||||
|
OT: ObserversTuple<S::Input, S>,
|
||||||
|
ET: EmulatorModuleTuple<S>,
|
||||||
|
{
|
||||||
|
self.write();
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn on_crash(&mut self) {
|
||||||
|
self.write();
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn on_timeout(&mut self) {
|
||||||
|
self.write();
|
||||||
|
}
|
||||||
|
|
||||||
fn address_filter(&self) -> &Self::ModuleAddressFilter {
|
fn address_filter(&self) -> &Self::ModuleAddressFilter {
|
||||||
&self.filter
|
&self.filter
|
||||||
|
@ -95,6 +95,16 @@ where
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// This is getting executed in a signal handler.
|
||||||
|
unsafe fn on_crash(&mut self) {}
|
||||||
|
|
||||||
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// This is getting executed in a signal handler.
|
||||||
|
unsafe fn on_timeout(&mut self) {}
|
||||||
|
|
||||||
fn address_filter(&self) -> &Self::ModuleAddressFilter;
|
fn address_filter(&self) -> &Self::ModuleAddressFilter;
|
||||||
fn address_filter_mut(&mut self) -> &mut Self::ModuleAddressFilter;
|
fn address_filter_mut(&mut self) -> &mut Self::ModuleAddressFilter;
|
||||||
fn update_address_filter(&mut self, qemu: Qemu, filter: Self::ModuleAddressFilter) {
|
fn update_address_filter(&mut self, qemu: Qemu, filter: Self::ModuleAddressFilter) {
|
||||||
@ -149,6 +159,16 @@ where
|
|||||||
OT: ObserversTuple<S::Input, S>,
|
OT: ObserversTuple<S::Input, S>,
|
||||||
ET: EmulatorModuleTuple<S>;
|
ET: EmulatorModuleTuple<S>;
|
||||||
|
|
||||||
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// This is getting executed in a signal handler.
|
||||||
|
unsafe fn on_crash_all(&mut self);
|
||||||
|
|
||||||
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// This is getting executed in a signal handler.
|
||||||
|
unsafe fn on_timeout_all(&mut self);
|
||||||
|
|
||||||
fn allow_address_range_all(&mut self, address_range: Range<GuestAddr>);
|
fn allow_address_range_all(&mut self, address_range: Range<GuestAddr>);
|
||||||
|
|
||||||
#[cfg(emulation_mode = "systemmode")]
|
#[cfg(emulation_mode = "systemmode")]
|
||||||
@ -196,6 +216,10 @@ where
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsafe fn on_crash_all(&mut self) {}
|
||||||
|
|
||||||
|
unsafe fn on_timeout_all(&mut self) {}
|
||||||
|
|
||||||
fn allow_address_range_all(&mut self, _address_range: Range<GuestAddr>) {}
|
fn allow_address_range_all(&mut self, _address_range: Range<GuestAddr>) {}
|
||||||
|
|
||||||
#[cfg(emulation_mode = "systemmode")]
|
#[cfg(emulation_mode = "systemmode")]
|
||||||
@ -255,6 +279,16 @@ where
|
|||||||
.post_exec_all(emulator_modules, state, input, observers, exit_kind);
|
.post_exec_all(emulator_modules, state, input, observers, exit_kind);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsafe fn on_crash_all(&mut self) {
|
||||||
|
self.0.on_crash();
|
||||||
|
self.1.on_crash_all();
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn on_timeout_all(&mut self) {
|
||||||
|
self.0.on_timeout();
|
||||||
|
self.1.on_timeout_all();
|
||||||
|
}
|
||||||
|
|
||||||
fn allow_address_range_all(&mut self, address_range: Range<GuestAddr>) {
|
fn allow_address_range_all(&mut self, address_range: Range<GuestAddr>) {
|
||||||
self.0.address_filter_mut().register(address_range.clone());
|
self.0.address_filter_mut().register(address_range.clone());
|
||||||
self.1.allow_address_range_all(address_range);
|
self.1.allow_address_range_all(address_range);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user