fix build

This commit is contained in:
Alwin Berger 2024-01-16 15:53:57 +01:00
parent fc331fc6d8
commit 2ac7874895
13 changed files with 120 additions and 143 deletions

View File

@ -25,7 +25,8 @@ use libafl_qemu::{
helper::{QemuHelper, QemuHelperTuple, QemuInstrumentationFilter}, helper::{QemuHelper, QemuHelperTuple, QemuInstrumentationFilter},
}; };
use libafl::events::EventFirer; use libafl::events::EventFirer;
use libafl::state::HasClientPerfMonitor; use libafl::state::MaybeHasClientPerfMonitor;
use libafl::prelude::State;
use libafl::inputs::Input; use libafl::inputs::Input;
use libafl::feedbacks::Feedback; use libafl::feedbacks::Feedback;
use libafl::SerdeAny; use libafl::SerdeAny;
@ -203,7 +204,7 @@ pub struct ClockTimeFeedback {
impl<S> Feedback<S> for ClockTimeFeedback impl<S> Feedback<S> for ClockTimeFeedback
where where
S: UsesInput + HasClientPerfMonitor + HasMetadata, S: State + UsesInput + MaybeHasClientPerfMonitor + HasMetadata,
{ {
#[allow(clippy::wrong_self_convention)] #[allow(clippy::wrong_self_convention)]
fn is_interesting<EM, OT>( fn is_interesting<EM, OT>(
@ -280,7 +281,7 @@ pub struct QemuClockIncreaseFeedback {
impl<S> Feedback<S> for QemuClockIncreaseFeedback impl<S> Feedback<S> for QemuClockIncreaseFeedback
where where
S: UsesInput + HasNamedMetadata + HasClientPerfMonitor + Debug, S: State + UsesInput + HasNamedMetadata + MaybeHasClientPerfMonitor + Debug,
{ {
fn is_interesting<EM, OT>( fn is_interesting<EM, OT>(
&mut self, &mut self,

View File

@ -469,7 +469,7 @@ pub fn fuzz() {
QemuStateRestoreHelper::new(), QemuStateRestoreHelper::new(),
QemuSystemStateHelper::new(svh,curr_tcb_pointer,task_queue_addr,task_delay_addr,task_delay_overflow_addr,input_counter_ptr,app_range.clone()) QemuSystemStateHelper::new(svh,curr_tcb_pointer,task_queue_addr,task_delay_addr,task_delay_overflow_addr,input_counter_ptr,app_range.clone())
); );
let mut hooks = QemuHooks::new(&emu,qhelpers); let mut hooks = QemuHooks::new(emu.clone(),qhelpers);
#[cfg(not(feature = "systemstate"))] #[cfg(not(feature = "systemstate"))]
let observer_list = tuple_list!(edges_observer, clock_time_observer); let observer_list = tuple_list!(edges_observer, clock_time_observer);

View File

@ -1,4 +1,3 @@
#![feature(is_sorted)]
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
mod fuzzer; mod fuzzer;
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]

View File

@ -1,4 +1,3 @@
#![feature(is_sorted)]
//! A libfuzzer-like fuzzer using qemu for binary-only coverage //! A libfuzzer-like fuzzer using qemu for binary-only coverage
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
mod fuzzer; mod fuzzer;

View File

@ -14,9 +14,10 @@ use libafl::{
mark_feature_time, mark_feature_time,
stages::{Stage}, stages::{Stage},
start_timer, start_timer,
state::{HasClientPerfMonitor, HasCorpus, HasRand, UsesState, HasMetadata}, state::{MaybeHasClientPerfMonitor, HasCorpus, HasRand, UsesState, HasMetadata},
Error, prelude::{HasBytesVec, UsesInput, new_hash_feedback, MutationResult, Mutator, CorpusId}, Error, prelude::{HasBytesVec, UsesInput, new_hash_feedback, MutationResult, Mutator, CorpusId},
}; };
use libafl::prelude::State;
use crate::{systemstate::{FreeRTOSSystemStateMetadata, RefinedFreeRTOSSystemState}, fuzzer::DO_NUM_INTERRUPT, clock::IcHist}; use crate::{systemstate::{FreeRTOSSystemStateMetadata, RefinedFreeRTOSSystemState}, fuzzer::DO_NUM_INTERRUPT, clock::IcHist};
pub const MINIMUM_INTER_ARRIVAL_TIME : u32 = 700 * 1000 * (1 << 4); pub const MINIMUM_INTER_ARRIVAL_TIME : u32 = 700 * 1000 * (1 << 4);
@ -35,7 +36,7 @@ where
E: UsesState<State = Z::State>, E: UsesState<State = Z::State>,
EM: UsesState<State = Z::State>, EM: UsesState<State = Z::State>,
Z: Evaluator<E, EM>, Z: Evaluator<E, EM>,
Z::State: HasClientPerfMonitor + HasCorpus + HasRand, Z::State: MaybeHasClientPerfMonitor + HasCorpus + HasRand,
{ {
pub fn new() -> Self { pub fn new() -> Self {
Self { phantom: PhantomData } Self { phantom: PhantomData }
@ -47,7 +48,7 @@ where
E: UsesState<State = Z::State>, E: UsesState<State = Z::State>,
EM: UsesState<State = Z::State>, EM: UsesState<State = Z::State>,
Z: Evaluator<E, EM>, Z: Evaluator<E, EM>,
Z::State: HasClientPerfMonitor + HasCorpus + HasRand + HasMetadata, Z::State: MaybeHasClientPerfMonitor + HasCorpus + HasRand + HasMetadata,
<Z::State as UsesInput>::Input: HasBytesVec <Z::State as UsesInput>::Input: HasBytesVec
{ {
fn perform( fn perform(
@ -237,7 +238,7 @@ where
E: UsesState<State = Z::State>, E: UsesState<State = Z::State>,
EM: UsesState<State = Z::State>, EM: UsesState<State = Z::State>,
Z: Evaluator<E, EM>, Z: Evaluator<E, EM>,
Z::State: HasClientPerfMonitor + HasCorpus + HasRand, Z::State: MaybeHasClientPerfMonitor + HasCorpus + HasRand,
{ {
type State = Z::State; type State = Z::State;
} }

View File

@ -44,13 +44,13 @@ where
{ {
const HOOKS_DO_SIDE_EFFECTS: bool = true; const HOOKS_DO_SIDE_EFFECTS: bool = true;
fn init_hooks<QT>(&self, _hooks: &QemuHooks<'_, QT, S>) fn init_hooks<QT>(&self, _hooks: &QemuHooks<QT, S>)
where where
QT: QemuHelperTuple<S>, QT: QemuHelperTuple<S>,
{ {
} }
fn first_exec<QT>(&self, _hooks: &QemuHooks<'_, QT, S>) fn first_exec<QT>(&self, _hooks: &QemuHooks<QT, S>)
where where
QT: QemuHelperTuple<S>, QT: QemuHelperTuple<S>,
{ {

View File

@ -11,7 +11,8 @@ use std::collections::hash_map::DefaultHasher;
use std::hash::Hasher; use std::hash::Hasher;
use std::hash::Hash; use std::hash::Hash;
use libafl::events::EventFirer; use libafl::events::EventFirer;
use libafl::state::HasClientPerfMonitor; use libafl::state::MaybeHasClientPerfMonitor;
use libafl::prelude::State;
use libafl::feedbacks::Feedback; use libafl::feedbacks::Feedback;
use libafl_bolts::Named; use libafl_bolts::Named;
use libafl::Error; use libafl::Error;
@ -62,7 +63,7 @@ pub struct NovelSystemStateFeedback
impl<S> Feedback<S> for NovelSystemStateFeedback impl<S> Feedback<S> for NovelSystemStateFeedback
where where
S: UsesInput + HasClientPerfMonitor + HasNamedMetadata, S: State + UsesInput + MaybeHasClientPerfMonitor + HasNamedMetadata,
{ {
fn is_interesting<EM, OT>( fn is_interesting<EM, OT>(
&mut self, &mut self,
@ -176,7 +177,7 @@ pub struct HitSystemStateFeedback
impl<S> Feedback<S> for HitSystemStateFeedback impl<S> Feedback<S> for HitSystemStateFeedback
where where
S: UsesInput + HasClientPerfMonitor, S: State + UsesInput + MaybeHasClientPerfMonitor,
{ {
fn is_interesting<EM, OT>( fn is_interesting<EM, OT>(
&mut self, &mut self,
@ -228,7 +229,7 @@ pub struct DumpSystraceFeedback
impl<S> Feedback<S> for DumpSystraceFeedback impl<S> Feedback<S> for DumpSystraceFeedback
where where
S: UsesInput + HasClientPerfMonitor, S: State + UsesInput + MaybeHasClientPerfMonitor,
{ {
fn is_interesting<EM, OT>( fn is_interesting<EM, OT>(
&mut self, &mut self,

View File

@ -10,6 +10,7 @@ use libafl::prelude::HasTargetBytes;
use libafl::prelude::UsesInput; use libafl::prelude::UsesInput;
use libafl::state::HasNamedMetadata; use libafl::state::HasNamedMetadata;
use libafl::state::UsesState; use libafl::state::UsesState;
use libafl::prelude::State;
use core::marker::PhantomData; use core::marker::PhantomData;
use libafl::state::HasCorpus; use libafl::state::HasCorpus;
use libafl::state::HasSolutions; use libafl::state::HasSolutions;
@ -29,7 +30,7 @@ use std::collections::hash_map::DefaultHasher;
use std::hash::Hasher; use std::hash::Hasher;
use std::hash::Hash; use std::hash::Hash;
use libafl::events::EventFirer; use libafl::events::EventFirer;
use libafl::state::HasClientPerfMonitor; use libafl::state::MaybeHasClientPerfMonitor;
use libafl::feedbacks::Feedback; use libafl::feedbacks::Feedback;
use libafl_bolts::Named; use libafl_bolts::Named;
use libafl::Error; use libafl::Error;
@ -284,7 +285,7 @@ impl SysMapFeedback {
impl<S> Feedback<S> for SysMapFeedback impl<S> Feedback<S> for SysMapFeedback
where where
S: UsesInput + HasClientPerfMonitor + HasNamedMetadata, S: State + UsesInput + MaybeHasClientPerfMonitor + HasNamedMetadata,
S::Input: HasTargetBytes, S::Input: HasTargetBytes,
{ {
#[allow(clippy::wrong_self_convention)] #[allow(clippy::wrong_self_convention)]

View File

@ -10,6 +10,7 @@ use libafl_qemu::QemuHooks;
use libafl_qemu::edges::QemuEdgesMapMetadata; use libafl_qemu::edges::QemuEdgesMapMetadata;
use libafl_qemu::emu; use libafl_qemu::emu;
use libafl_qemu::hooks; use libafl_qemu::hooks;
use libafl_qemu::Hook;
use crate::systemstate::RawFreeRTOSSystemState; use crate::systemstate::RawFreeRTOSSystemState;
use crate::systemstate::CURRENT_SYSTEMSTATE_VEC; use crate::systemstate::CURRENT_SYSTEMSTATE_VEC;
use crate::systemstate::NUM_PRIOS; use crate::systemstate::NUM_PRIOS;
@ -72,13 +73,13 @@ impl<S> QemuHelper<S> for QemuSystemStateHelper
where where
S: UsesInput, S: UsesInput,
{ {
fn first_exec<QT>(&self, _hooks: &QemuHooks<'_, QT, S>) fn first_exec<QT>(&self, _hooks: &QemuHooks<QT, S>)
where where
QT: QemuHelperTuple<S>, QT: QemuHelperTuple<S>,
{ {
_hooks.instruction(self.kerneladdr, exec_syscall_hook::<QT, S>, false); _hooks.instruction(self.kerneladdr, Hook::Function(exec_syscall_hook::<QT, S>), false);
#[cfg(feature = "trace_abbs")] #[cfg(feature = "trace_abbs")]
_hooks.jmps(Some(gen_jmp_is_syscall::<QT, S>), Some(trace_api_call::<QT, S>)); _hooks.jmps(Hook::Function(gen_jmp_is_syscall::<QT, S>), Hook::Function(trace_api_call::<QT, S>));
} }
// TODO: refactor duplicate code // TODO: refactor duplicate code
@ -133,10 +134,10 @@ fn trigger_collection(emulator: &Emulator, h: &QemuSystemStateHelper) {
unsafe { unsafe {
// TODO: investigate why can_do_io is not set sometimes, as this is just a workaround // TODO: investigate why can_do_io is not set sometimes, as this is just a workaround
let c = emulator.cpu_from_index(0); let c = emulator.cpu_from_index(0);
let can_do_io = (*c.raw_ptr()).can_do_io; let can_do_io = (*c.raw_ptr()).neg.can_do_io;
(*c.raw_ptr()).can_do_io = 1; (*c.raw_ptr()).neg.can_do_io = true;
systemstate.qemu_tick = emu::icount_get_raw(); systemstate.qemu_tick = emu::icount_get_raw();
(*c.raw_ptr()).can_do_io = can_do_io; (*c.raw_ptr()).neg.can_do_io = can_do_io;
} }
let mut buf : [u8; 4] = [0,0,0,0]; let mut buf : [u8; 4] = [0,0,0,0];
match h.input_counter { match h.input_counter {
@ -183,7 +184,7 @@ fn trigger_collection(emulator: &Emulator, h: &QemuSystemStateHelper) {
} }
pub fn exec_syscall_hook<QT, S>( pub fn exec_syscall_hook<QT, S>(
hooks: &mut QemuHooks<'_, QT, S>, hooks: &mut QemuHooks<QT, S>,
_state: Option<&mut S>, _state: Option<&mut S>,
_pc: GuestAddr, _pc: GuestAddr,
) )
@ -199,7 +200,7 @@ where
thread_local!(static LAST_API_CALL : UnsafeCell<Option<(GuestAddr,GuestAddr)>> = UnsafeCell::new(None)); thread_local!(static LAST_API_CALL : UnsafeCell<Option<(GuestAddr,GuestAddr)>> = UnsafeCell::new(None));
pub fn gen_jmp_is_syscall<QT, S>( pub fn gen_jmp_is_syscall<QT, S>(
hooks: &mut QemuHooks<'_, QT, S>, hooks: &mut QemuHooks<QT, S>,
_state: Option<&mut S>, _state: Option<&mut S>,
src: GuestAddr, src: GuestAddr,
dest: GuestAddr, dest: GuestAddr,
@ -218,7 +219,7 @@ where
} }
pub fn trace_api_call<QT, S>( pub fn trace_api_call<QT, S>(
_hooks: &mut QemuHooks<'_, QT, S>, _hooks: &mut QemuHooks<QT, S>,
_state: Option<&mut S>, _state: Option<&mut S>,
src: GuestAddr, dest: GuestAddr, id: u64 src: GuestAddr, dest: GuestAddr, id: u64
) )

View File

@ -160,14 +160,14 @@ pub struct GenerationScheduler<S> {
impl<S> UsesState for GenerationScheduler<S> impl<S> UsesState for GenerationScheduler<S>
where where
S: UsesInput, S: State + UsesInput,
{ {
type State = S; type State = S;
} }
impl<S> Scheduler for GenerationScheduler<S> impl<S> Scheduler for GenerationScheduler<S>
where where
S: HasCorpus + HasMetadata, S: State + HasCorpus + HasMetadata,
S::Input: HasLen, S::Input: HasLen,
{ {
/// get first element in current gen, /// get first element in current gen,

View File

@ -13,7 +13,8 @@ use hashbrown::{HashMap};
use libafl::observers::ObserversTuple; use libafl::observers::ObserversTuple;
use libafl::executors::ExitKind; use libafl::executors::ExitKind;
use libafl::events::EventFirer; use libafl::events::EventFirer;
use libafl::state::{HasClientPerfMonitor, HasCorpus, UsesState}; use libafl::state::{MaybeHasClientPerfMonitor, HasCorpus, UsesState};
use libafl::prelude::State;
use libafl::inputs::Input; use libafl::inputs::Input;
use libafl::feedbacks::Feedback; use libafl::feedbacks::Feedback;
use libafl::state::HasMetadata; use libafl::state::HasMetadata;
@ -101,7 +102,7 @@ pub struct SortedFeedback {
impl<S> Feedback<S> for SortedFeedback impl<S> Feedback<S> for SortedFeedback
where where
S: UsesInput + HasClientPerfMonitor, S: State + UsesInput + MaybeHasClientPerfMonitor,
S::Input: HasTargetBytes, S::Input: HasTargetBytes,
{ {
#[allow(clippy::wrong_self_convention)] #[allow(clippy::wrong_self_convention)]
@ -122,12 +123,24 @@ where
if tmp.len()<32 {return Ok(false);} if tmp.len()<32 {return Ok(false);}
let tmp = Vec::<u8>::from(&tmp[0..32]); let tmp = Vec::<u8>::from(&tmp[0..32]);
// tmp.reverse(); // tmp.reverse();
if tmp.is_sorted_by(|a,b| match a.partial_cmp(b).unwrap_or(Less) { // if tmp.is_sorted_by(|a,b| match a.partial_cmp(b).unwrap_or(Less) {
Less => Some(Greater), // Less => Some(Greater),
Equal => Some(Greater), // Equal => Some(Greater),
Greater => Some(Less), // Greater => Some(Less),
}) {return Ok(true)}; // }) {return Ok(true)};
return Ok(false); let mut is_sorted = true;
if tmp[0]<tmp[1] {
for i in 1..tmp.len() {
is_sorted &= tmp[i-1]<=tmp[i];
if !is_sorted {break;}
}
} else {
for i in 1..tmp.len() {
is_sorted &= tmp[i-1]>=tmp[i];
if !is_sorted {break;}
}
}
return Ok(is_sorted);
} }
} }
@ -162,7 +175,7 @@ pub struct ExecTimeReachedFeedback
impl<S> Feedback<S> for ExecTimeReachedFeedback impl<S> Feedback<S> for ExecTimeReachedFeedback
where where
S: UsesInput + HasClientPerfMonitor, S: State + UsesInput + MaybeHasClientPerfMonitor,
{ {
#[allow(clippy::wrong_self_convention)] #[allow(clippy::wrong_self_convention)]
fn is_interesting<EM, OT>( fn is_interesting<EM, OT>(
@ -211,7 +224,7 @@ pub struct ExecTimeCollectorFeedback
impl<S> Feedback<S> for ExecTimeCollectorFeedback impl<S> Feedback<S> for ExecTimeCollectorFeedback
where where
S: UsesInput + HasClientPerfMonitor, S: State + UsesInput + MaybeHasClientPerfMonitor,
{ {
#[allow(clippy::wrong_self_convention)] #[allow(clippy::wrong_self_convention)]
fn is_interesting<EM, OT>( fn is_interesting<EM, OT>(
@ -276,7 +289,7 @@ pub struct ExecTimeIncFeedback
impl<S> Feedback<S> for ExecTimeIncFeedback impl<S> Feedback<S> for ExecTimeIncFeedback
where where
S: UsesInput + HasClientPerfMonitor, S: State + UsesInput + MaybeHasClientPerfMonitor,
{ {
#[allow(clippy::wrong_self_convention)] #[allow(clippy::wrong_self_convention)]
fn is_interesting<EM, OT>( fn is_interesting<EM, OT>(
@ -344,7 +357,7 @@ pub struct AlwaysTrueFeedback
impl<S> Feedback<S> for AlwaysTrueFeedback impl<S> Feedback<S> for AlwaysTrueFeedback
where where
S: UsesInput + HasClientPerfMonitor, S: State + UsesInput + MaybeHasClientPerfMonitor,
{ {
#[allow(clippy::wrong_self_convention)] #[allow(clippy::wrong_self_convention)]
fn is_interesting<EM, OT>( fn is_interesting<EM, OT>(

View File

@ -404,10 +404,10 @@ extern "C" {
// void (*exec)(target_ulong src, target_ulong dst, uint64_t id, uint64_t data), // void (*exec)(target_ulong src, target_ulong dst, uint64_t id, uint64_t data),
// uint64_t data); // uint64_t data);
fn libafl_add_jmp_hook( fn libafl_add_jmp_hook(
gen: Option<extern "C" fn(GuestAddr, GuestAddr, u64) -> u64>, gen: Option<extern "C" fn(u64, GuestAddr, GuestAddr) -> u64>, // data,src,dest
exec: Option<extern "C" fn(GuestAddr, GuestAddr, u64, u64)>, exec: Option<extern "C" fn(u64, GuestAddr, GuestAddr, u64)>, // data,src,dest,id
data: u64, data: u64,
); ) -> usize;
} }
#[cfg(emulation_mode = "usermode")] #[cfg(emulation_mode = "usermode")]
@ -1520,13 +1520,28 @@ impl Emulator {
} }
} }
pub fn add_jmp_hooks( // pub fn add_jmp_hooks(
// &self,
// gen: Option<extern "C" fn(GuestAddr, GuestAddr, u64) -> u64>,
// exec: Option<extern "C" fn(GuestAddr, GuestAddr, u64, u64)>,
// data: u64,
// ) {
// unsafe { libafl_add_jmp_hook(gen, exec, data) }
// }
pub fn add_jmp_hooks<T: Into<HookData>>(
&self, &self,
gen: Option<extern "C" fn(GuestAddr, GuestAddr, u64) -> u64>, data: T,
exec: Option<extern "C" fn(GuestAddr, GuestAddr, u64, u64)>, gen: Option<extern "C" fn(T, GuestAddr, GuestAddr) -> u64>,
data: u64, exec: Option<extern "C" fn(T, GuestAddr, GuestAddr, u64)>,
) { ) -> HookId {
unsafe { libafl_add_jmp_hook(gen, exec, data) } 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, GuestAddr, GuestAddr, u64)> = core::mem::transmute(exec);
let num = libafl_add_jmp_hook(gen, exec, data);
HookId(num)
}
} }
#[cfg(emulation_mode = "systemmode")] #[cfg(emulation_mode = "systemmode")]

View File

@ -535,77 +535,11 @@ where
} }
} }
static mut JMP_HOOKS: Vec<(Hook, Hook)> = vec![]; static mut JMP_HOOKS: Vec<HookState<1>> = vec![];
create_gen_wrapper!(jmp, (src: GuestAddr, dest: GuestAddr), u64, 1);
create_exec_wrapper!(jmp, (src: GuestAddr, dst: GuestAddr, id: u64), 0, 1);
extern "C" fn gen_jmp_hook_wrapper<QT, S>(src: GuestAddr, dst: GuestAddr, index: u64) -> u64
where
S: UsesInput,
QT: QemuHelperTuple<S>,
{
unsafe {
let hooks = get_qemu_hooks::<QT, S>();
let (gen, _) = &mut JMP_HOOKS[index as usize];
match gen {
Hook::Function(ptr) => {
let func: fn(
&mut QemuHooks<'_, QT, S>,
Option<&mut S>,
GuestAddr,
GuestAddr,
) -> Option<u64> = transmute(*ptr);
(func)(hooks, inprocess_get_state::<S>(), src, dst).map_or(SKIP_EXEC_HOOK, |id| id)
}
Hook::Closure(ptr) => {
let func: &mut Box<
dyn FnMut(
&mut QemuHooks<'_, QT, S>,
Option<&mut S>,
GuestAddr,
GuestAddr,
) -> Option<u64>,
> = transmute(ptr);
(func)(hooks, inprocess_get_state::<S>(), src, dst).map_or(SKIP_EXEC_HOOK, |id| id)
}
_ => 0,
}
}
}
extern "C" fn exec_jmp_hook_wrapper<QT, S>(src: GuestAddr, dst: GuestAddr, id: u64, index: u64)
where
S: UsesInput,
QT: QemuHelperTuple<S>,
{
unsafe {
let hooks = get_qemu_hooks::<QT, S>();
let (_, exec) = &mut JMP_HOOKS[index as usize];
match exec {
Hook::Function(ptr) => {
let func: fn(
&mut QemuHooks<'_, QT, S>,
Option<&mut S>,
GuestAddr,
GuestAddr,
u64,
) = transmute(*ptr);
(func)(hooks, inprocess_get_state::<S>(), src, dst, id);
}
Hook::Closure(ptr) => {
let func: &mut Box<
dyn FnMut(
&mut QemuHooks<'_, QT, S>,
Option<&mut S>,
GuestAddr,
GuestAddr,
u64,
),
> = transmute(ptr);
(func)(hooks, inprocess_get_state::<S>(), src, dst, id);
}
_ => (),
}
}
}
static mut HOOKS_IS_INITIALIZED: bool = false; static mut HOOKS_IS_INITIALIZED: bool = false;
static mut FIRST_EXEC: bool = true; static mut FIRST_EXEC: bool = true;
@ -1483,34 +1417,46 @@ where
pub fn jmps( pub fn jmps(
&self, &self,
generation_hook: Option< generation_hook: Hook<
fn(&mut Self, Option<&mut S>, src: GuestAddr, dest: GuestAddr) -> Option<u64>, fn(&mut Self, Option<&mut S>, src: GuestAddr, dest: GuestAddr) -> Option<u64>,
Box<
dyn for<'a> FnMut(
&'a mut Self,
Option<&'a mut S>,
GuestAddr,
GuestAddr,
) -> Option<u64>,
>, >,
execution_hook: Option<fn(&mut Self, Option<&mut S>, src: GuestAddr, dest: GuestAddr, id: u64)>, extern "C" fn(*const (), src: GuestAddr, dest: GuestAddr) -> u64,
) { >,
execution_hook: Hook<
fn(&mut Self, Option<&mut S>, src: GuestAddr, dest: GuestAddr, id: u64),
Box<dyn for<'a> FnMut(&'a mut Self, Option<&'a mut S>, GuestAddr, GuestAddr, u64)>,
extern "C" fn(*const (), src: GuestAddr, dest: GuestAddr, id: u64),
>,
) -> HookId {
unsafe { unsafe {
let index = JMP_HOOKS.len(); let gen = get_raw_hook!(
self.emulator.add_jmp_hooks( generation_hook,
if generation_hook.is_none() { jmp_gen_hook_wrapper::<QT, S>,
None extern "C" fn(&mut HookState<1>, src: GuestAddr, dest: GuestAddr) -> u64
} else {
Some(gen_jmp_hook_wrapper::<QT, S>)
},
if execution_hook.is_none() {
None
} else {
Some(exec_jmp_hook_wrapper::<QT, S>)
},
index as u64,
); );
JMP_HOOKS.push(( let exec = get_raw_hook!(
generation_hook.map_or(Hook::Empty, |hook| { execution_hook,
Hook::Function(hook as *const libc::c_void) jmp_0_exec_hook_wrapper::<QT, S>,
}), extern "C" fn(&mut HookState<1>, src: GuestAddr, dest: GuestAddr, id: u64)
execution_hook.map_or(Hook::Empty, |hook| { );
Hook::Function(hook as *const libc::c_void) JMP_HOOKS.push(HookState {
}), id: HookId(0),
)); gen: hook_to_repr!(generation_hook),
post_gen: HookRepr::Empty,
execs: [hook_to_repr!(execution_hook)],
});
let id = self
.emulator
.add_jmp_hooks(JMP_HOOKS.last_mut().unwrap(), gen, exec);
JMP_HOOKS.last_mut().unwrap().id = id;
id
} }
} }
} }