type fixing

This commit is contained in:
Alwin Berger 2024-12-06 16:10:25 +01:00
parent b12811e1ef
commit 8d7e32559f
18 changed files with 462 additions and 158 deletions

View File

@ -44,7 +44,7 @@ where
) -> Result<bool, Error> ) -> Result<bool, Error>
where where
EM: EventFirer<State = S>, EM: EventFirer<State = S>,
OT: ObserversTuple<S>, OT: ObserversTuple<I, S>,
{ {
if unsafe { counter } > 0 { if unsafe { counter } > 0 {
unsafe { counter -= 1; } unsafe { counter -= 1; }
@ -68,7 +68,7 @@ where
testcase: &mut Testcase<<S>::Input>, testcase: &mut Testcase<<S>::Input>,
) -> Result<(), Error> ) -> Result<(), Error>
where where
OT: ObserversTuple<S>, OT: ObserversTuple<I, S>,
EM: EventFirer<State = S>, EM: EventFirer<State = S>,
{ {
testcase.metadata_map_mut().insert(DebugMetadata { val: true }); testcase.metadata_map_mut().insert(DebugMetadata { val: true });

View File

@ -9,9 +9,8 @@ core_affinity::Cores, ownedref::OwnedMutSlice, rands::StdRand, shmem::{ShMemProv
use libafl::{ use libafl::{
common::{HasMetadata, HasNamedMetadata}, corpus::{Corpus, InMemoryCorpus, OnDiskCorpus}, events::{launcher::Launcher, EventConfig}, executors::ExitKind, feedback_or, feedback_or_fast, feedbacks::{CrashFeedback, MaxMapFeedback, TimeoutFeedback}, fuzzer::{Fuzzer, StdFuzzer}, inputs::{multi::MultipartInput, BytesInput, HasTargetBytes, Input}, monitors::MultiMonitor, observers::{CanTrack, VariableMapObserver}, prelude::{havoc_mutations, minimizer::TopRatedsMetadata, CorpusId, Generator, HitcountsMapObserver, RandBytesGenerator, SimpleEventManager, SimpleMonitor, SimplePrintingMonitor, SimpleRestartingEventManager, StdScheduledMutator}, schedulers::QueueScheduler, stages::StdMutationalStage, state::{HasCorpus, StdState}, Error, Evaluator common::{HasMetadata, HasNamedMetadata}, corpus::{Corpus, InMemoryCorpus, OnDiskCorpus}, events::{launcher::Launcher, EventConfig}, executors::ExitKind, feedback_or, feedback_or_fast, feedbacks::{CrashFeedback, MaxMapFeedback, TimeoutFeedback}, fuzzer::{Fuzzer, StdFuzzer}, inputs::{multi::MultipartInput, BytesInput, HasTargetBytes, Input}, monitors::MultiMonitor, observers::{CanTrack, VariableMapObserver}, prelude::{havoc_mutations, minimizer::TopRatedsMetadata, CorpusId, Generator, HitcountsMapObserver, RandBytesGenerator, SimpleEventManager, SimpleMonitor, SimplePrintingMonitor, SimpleRestartingEventManager, StdScheduledMutator}, schedulers::QueueScheduler, stages::StdMutationalStage, state::{HasCorpus, StdState}, Error, Evaluator
}; };
use libafl_qemu::edges::EDGES_MAP_SIZE_IN_USE;
use libafl_qemu::{ use libafl_qemu::{
edges::{self, edges_map_mut_ptr, QemuEdgeCoverageHelper, MAX_EDGES_FOUND}, elf::EasyElf, emu::Emulator, GuestAddr, GuestPhysAddr, QemuExecutor, QemuExitReason, QemuFilterList, QemuHooks, Regs, StdInstrumentationFilter elf::EasyElf, emu::Emulator, modules::{edges::{self}, FilterList}, GuestAddr, GuestPhysAddr, QemuExecutor, QemuExitReason, QemuHooks, Regs
}; };
use rand::{SeedableRng, StdRng, Rng}; use rand::{SeedableRng, StdRng, Rng};
use crate::{ use crate::{
@ -30,6 +29,7 @@ use crate::cli::set_env_from_config;
use clap::Parser; use clap::Parser;
use log; use log;
use rand::RngCore; use rand::RngCore;
use crate::templates;
// Constants ================================================================================ // Constants ================================================================================
@ -248,7 +248,7 @@ let app_fn_ranges = get_all_fn_symbol_ranges(&elf, app_range.clone());
let mut isr_ranges : HashMap<String,std::ops::Range<GuestAddr>> = systemstate::helpers::ISR_SYMBOLS.iter().filter_map(|x| (api_ranges.get(&x.to_string()).map(|y| (x.to_string(),y.clone())))).collect(); let mut isr_ranges : HashMap<String,std::ops::Range<GuestAddr>> = systemstate::helpers::ISR_SYMBOLS.iter().filter_map(|x| (api_ranges.get(&x.to_string()).map(|y| (x.to_string(),y.clone())))).collect();
systemstate::helpers::ISR_SYMBOLS.iter().for_each(|x| {let _ =(app_fn_ranges.get(&x.to_string()).map(|y| (x.to_string(),y.clone()))).map(|y| isr_ranges.insert(y.0,y.1));}); // add used defined isr systemstate::helpers::ISR_SYMBOLS.iter().for_each(|x| {let _ =(app_fn_ranges.get(&x.to_string()).map(|y| (x.to_string(),y.clone()))).map(|y| isr_ranges.insert(y.0,y.1));}); // add used defined isr
let denylist : Vec<_> =isr_ranges.values().map(|x| x.clone()).collect(); let denylist : Vec<_> =isr_ranges.values().map(|x| x.clone()).collect();
let denylist = QemuFilterList::DenyList(denylist); // do not count isr jumps, which are useless let denylist = FilterList::DenyList(denylist); // do not count isr jumps, which are useless
#[cfg(feature = "observe_systemstate")] #[cfg(feature = "observe_systemstate")]
let mut isr_addreses : HashMap<GuestAddr, String> = systemstate::helpers::ISR_SYMBOLS.iter().filter_map(|x| (api_ranges.remove(&x.to_string()).map(|y| (y.start,x.to_string())))).collect(); let mut isr_addreses : HashMap<GuestAddr, String> = systemstate::helpers::ISR_SYMBOLS.iter().filter_map(|x| (api_ranges.remove(&x.to_string()).map(|y| (y.start,x.to_string())))).collect();
#[cfg(feature = "observe_systemstate")] #[cfg(feature = "observe_systemstate")]
@ -319,7 +319,7 @@ let run_client = |state: Option<_>, mut mgr, _core_id| {
"if=none,format=qcow2,file=dummy.qcow2", "if=none,format=qcow2,file=dummy.qcow2",
].into_iter().map(String::from).collect(); ].into_iter().map(String::from).collect();
let env: Vec<(String, String)> = env::vars().collect(); let env: Vec<(String, String)> = env::vars().collect();
let qemu = Qemu::init(&args, &env).expect("Emulator creation failed"); let qemu = Qemu::init(&args).expect("Emulator creation failed");
if let Some(main_addr) = main_addr { if let Some(main_addr) = main_addr {
qemu.set_breakpoint(main_addr); qemu.set_breakpoint(main_addr);
@ -343,7 +343,7 @@ let run_client = |state: Option<_>, mut mgr, _core_id| {
let initial_snap = None; let initial_snap = None;
// The wrapped harness function, calling out to the LLVM-style harness // The wrapped harness function, calling out to the LLVM-style harness
let mut harness = |input: &MultipartInput<BytesInput>| { let mut harness = |emulator: &mut Emulator<_, _, _, _, _>, state: &mut _, input: &MultipartInput<BytesInput>| {
unsafe { unsafe {
#[cfg(feature = "fuzz_int")] #[cfg(feature = "fuzz_int")]
{ {
@ -369,7 +369,7 @@ let run_client = |state: Option<_>, mut mgr, _core_id| {
// Note: I could not find a difference between write_mem and write_phys_mem for my usecase // Note: I could not find a difference between write_mem and write_phys_mem for my usecase
qemu.write_mem(input_addr, bytes); qemu.write_mem(input_addr, bytes);
if let Some(s) = input_length_ptr { if let Some(s) = input_length_ptr {
qemu.write_mem(s, &len.to_le_bytes()) qemu.write_mem(s, &len.to_le_bytes());
} }
qemu.run(); qemu.run();
@ -496,7 +496,7 @@ let run_client = |state: Option<_>, mut mgr, _core_id| {
let qhelpers = (QemuEdgeCoverageHelper::new(denylist, QemuFilterList::None), qhelpers); let qhelpers = (QemuEdgeCoverageHelper::new(denylist, QemuFilterList::None), qhelpers);
let qhelpers = (QemuStateRestoreHelper::with_fast(initial_snap), qhelpers); let qhelpers = (QemuStateRestoreHelper::with_fast(initial_snap), qhelpers);
let mut hooks = QemuHooks::new(qemu.clone(),qhelpers); let emulator = Emulator::empty().qemu(qemu).modules(qhelpers).build().unwrap();
let observer_list = tuple_list!(); let observer_list = tuple_list!();
#[cfg(feature = "observe_systemstate")] #[cfg(feature = "observe_systemstate")]
@ -507,7 +507,7 @@ let run_client = |state: Option<_>, mut mgr, _core_id| {
// Create a QEMU in-process executor // Create a QEMU in-process executor
let mut executor = QemuExecutor::new( let mut executor = QemuExecutor::new(
&mut hooks, emulator,
&mut harness, &mut harness,
observer_list, observer_list,
&mut fuzzer, &mut fuzzer,
@ -660,7 +660,7 @@ let run_client = |state: Option<_>, mut mgr, _core_id| {
// Initialize QEMU // Initialize QEMU
let args: Vec<String> = env::args().collect(); let args: Vec<String> = env::args().collect();
let env: Vec<(String, String)> = env::vars().collect(); let env: Vec<(String, String)> = env::vars().collect();
let emu = Qemu::init(&args, &env).expect("Emu creation failed"); let emu = Qemu::init(&args).expect("Emu creation failed");
if let Some(main_addr) = main_addr { if let Some(main_addr) = main_addr {
emu.set_breakpoint(main_addr); // BREAKPOINT emu.set_breakpoint(main_addr); // BREAKPOINT

View File

@ -6,3 +6,5 @@ pub mod time;
pub mod systemstate; pub mod systemstate;
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
mod cli; mod cli;
#[cfg(target_os = "linux")]
pub mod templates;

View File

@ -7,6 +7,8 @@ mod time;
mod systemstate; mod systemstate;
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
mod cli; mod cli;
#[cfg(target_os = "linux")]
mod templates;
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
pub fn main() { pub fn main() {

View File

@ -23,6 +23,8 @@ use super::FreeRTOSSystemStateMetadata;
use super::observers::QemuSystemStateObserver; use super::observers::QemuSystemStateObserver;
use std::borrow::Cow; use std::borrow::Cow;
use libafl::prelude::StateInitializer;
//============================= Feedback //============================= Feedback
/// Shared Metadata for a systemstateFeedback /// Shared Metadata for a systemstateFeedback
@ -57,10 +59,14 @@ pub struct NovelSystemStateFeedback
// known_traces: HashMap<u64,(u64,usize)>, // known_traces: HashMap<u64,(u64,usize)>,
} }
impl<S> StateInitializer<S> for NovelSystemStateFeedback {}
impl<EM, I, OT, S> Feedback<EM, I, OT, S> for NovelSystemStateFeedback impl<EM, I, OT, S> Feedback<EM, I, OT, S> for NovelSystemStateFeedback
where where
S: State + UsesInput + MaybeHasClientPerfMonitor + HasNamedMetadata, S: State + UsesInput + MaybeHasClientPerfMonitor + HasNamedMetadata,
S::Input: Default, S::Input: Default,
EM: EventFirer<State = S>,
OT: ObserversTuple<I, S>,
{ {
fn is_interesting( fn is_interesting(
&mut self, &mut self,
@ -71,9 +77,6 @@ where
_exit_kind: &ExitKind, _exit_kind: &ExitKind,
) -> Result<bool, Error> ) -> Result<bool, Error>
where where
EM: EventFirer<State = S>,
OT: ObserversTuple<S>,
S::Input: Default
{ {
let observer : &QemuSystemStateObserver<S::Input> = observers.match_name::<QemuSystemStateObserver<S::Input>>("systemstate") let observer : &QemuSystemStateObserver<S::Input> = observers.match_name::<QemuSystemStateObserver<S::Input>>("systemstate")
.expect("QemuSystemStateObserver not found"); .expect("QemuSystemStateObserver not found");
@ -126,7 +129,7 @@ where
/// Append to the testcase the generated metadata in case of a new corpus item /// Append to the testcase the generated metadata in case of a new corpus item
#[inline] #[inline]
fn append_metadata(&mut self, _state: &mut S, _manager: &mut EM, _observers: &OT, testcase: &mut Testcase<<S as UsesInput>::Input>) -> Result<(), Error> { fn append_metadata(&mut self, _state: &mut S, _manager: &mut EM, _observers: &OT, testcase: &mut Testcase<I>) -> Result<(), Error> {
let a = self.last_trace.take(); let a = self.last_trace.take();
match a { match a {
Some(s) => testcase.metadata_map_mut().insert(FreeRTOSSystemStateMetadata::new(s)), Some(s) => testcase.metadata_map_mut().insert(FreeRTOSSystemStateMetadata::new(s)),
@ -170,9 +173,13 @@ pub struct DumpSystraceFeedback
last_trace: Option<Vec<ExecInterval>>, last_trace: Option<Vec<ExecInterval>>,
} }
impl<S> StateInitializer<S> for DumpSystraceFeedback {}
impl<EM, I, OT, S> Feedback<EM, I, OT, S> for DumpSystraceFeedback impl<EM, I, OT, S> Feedback<EM, I, OT, S> for DumpSystraceFeedback
where where
S: State + UsesInput + MaybeHasClientPerfMonitor, S: State + UsesInput + MaybeHasClientPerfMonitor,
EM: EventFirer<State = S>,
OT: ObserversTuple<I, S>
{ {
fn is_interesting( fn is_interesting(
&mut self, &mut self,
@ -183,8 +190,6 @@ where
_exit_kind: &ExitKind, _exit_kind: &ExitKind,
) -> Result<bool, Error> ) -> Result<bool, Error>
where where
EM: EventFirer<State = S>,
OT: ObserversTuple<S>
{ {
if self.dumpfile.is_none() {return Ok(false)}; if self.dumpfile.is_none() {return Ok(false)};
let observer = observers.match_name::<QemuSystemStateObserver<S::Input>>("systemstate") let observer = observers.match_name::<QemuSystemStateObserver<S::Input>>("systemstate")
@ -225,7 +230,7 @@ where
} }
/// Append to the testcase the generated metadata in case of a new corpus item /// Append to the testcase the generated metadata in case of a new corpus item
#[inline] #[inline]
fn append_metadata(&mut self, _state: &mut S, _manager: &mut EM, _observers: &OT, _testcase: &mut Testcase<<S as UsesInput>::Input>) -> Result<(), Error> { fn append_metadata(&mut self, _state: &mut S, _manager: &mut EM, _observers: &OT, _testcase: &mut Testcase<I>) -> Result<(), Error> {
if !self.dump_metadata {return Ok(());} if !self.dump_metadata {return Ok(());}
// let a = self.last_trace.take(); // let a = self.last_trace.take();
// match a { // match a {
@ -277,10 +282,13 @@ pub struct SystraceErrorFeedback
max_reports: Option<usize>, max_reports: Option<usize>,
} }
impl<S> StateInitializer<S> for SystraceErrorFeedback {}
impl<EM, I, OT, S> Feedback<EM, I, OT, S> for SystraceErrorFeedback impl<EM, I, OT, S> Feedback<EM, I, OT, S> for SystraceErrorFeedback
where where
S: State + UsesInput + MaybeHasClientPerfMonitor, S: State + UsesInput + MaybeHasClientPerfMonitor,
EM: EventFirer<State = S>, EM: EventFirer<State = S>,
OT: ObserversTuple<I, S>
{ {
fn is_interesting( fn is_interesting(
&mut self, &mut self,
@ -291,7 +299,6 @@ where
_exit_kind: &ExitKind, _exit_kind: &ExitKind,
) -> Result<bool, Error> ) -> Result<bool, Error>
where where
OT: ObserversTuple<S>
{ {
#[cfg(feature = "trace_stg")] #[cfg(feature = "trace_stg")]
{ {
@ -313,7 +320,7 @@ where
} }
/// Append to the testcase the generated metadata in case of a new corpus item /// Append to the testcase the generated metadata in case of a new corpus item
#[inline] #[inline]
fn append_metadata(&mut self, _state: &mut S, _manager: &mut EM, _observers: &OT, _testcase: &mut I) -> Result<(), Error> { fn append_metadata(&mut self, _state: &mut S, _manager: &mut EM, _observers: &OT, _testcase: &mut Testcase<I>) -> Result<(), Error> {
Ok(()) Ok(())
} }

View File

@ -4,12 +4,14 @@ use hashbrown::HashSet;
use libafl::prelude::ExitKind; use libafl::prelude::ExitKind;
use libafl::prelude::UsesInput; use libafl::prelude::UsesInput;
use libafl_qemu::elf::EasyElf; use libafl_qemu::elf::EasyElf;
use libafl_qemu::modules::NopAddressFilter;
use libafl_qemu::modules::NopPageFilter;
use libafl_qemu::read_user_reg_unchecked; use libafl_qemu::read_user_reg_unchecked;
use libafl_qemu::GuestAddr; use libafl_qemu::GuestAddr;
use libafl_qemu::GuestPhysAddr; use libafl_qemu::GuestPhysAddr;
use libafl_qemu::QemuHooks; use libafl_qemu::QemuHooks;
use libafl_qemu::Hook; use libafl_qemu::Hook;
use libafl_qemu::helpers::{QemuHelper, QemuHelperTuple}; use libafl_qemu::modules::{EmulatorModule, EmulatorModuleTuple};
use libafl_qemu::sys::TCGTemp; use libafl_qemu::sys::TCGTemp;
use libafl_qemu::qemu::MemAccessInfo; use libafl_qemu::qemu::MemAccessInfo;
@ -22,6 +24,8 @@ use super::freertos::rtos_struct::List_Item_struct;
use super::freertos::rtos_struct::*; use super::freertos::rtos_struct::*;
use super::freertos; use super::freertos;
use super::CaptureEvent; use super::CaptureEvent;
use libafl_qemu::EmulatorModules;
use libafl::prelude::ObserversTuple;
@ -156,41 +160,58 @@ impl QemuSystemStateHelper {
} }
} }
impl<S> QemuHelper<S> for QemuSystemStateHelper impl<S, I> EmulatorModule<S> for QemuSystemStateHelper
where where
S: UsesInput, S: UsesInput<Input = I> + Unpin,
{ {
fn first_exec<QT>(&self, _hooks: &QemuHooks) fn first_exec<ET>(&mut self, _emulator_modules: &mut EmulatorModules<ET, S>, _state: &mut S)
where where
QT: QemuHelperTuple<S>, ET: EmulatorModuleTuple<S>,
{ {
// for wp in self.api_fn_addrs.keys() { // for wp in self.api_fn_addrs.keys() {
// _hooks.instruction(*wp, Hook::Function(exec_syscall_hook::<QT, S>), false); // _hooks.instruction(*wp, Hook::Function(exec_syscall_hook::<ET, S>), false);
// } // }
for wp in self.isr_addrs.keys() { for wp in self.isr_addrs.keys() {
_hooks.instruction(*wp, Hook::Function(exec_isr_hook::<QT, S>), false); _emulator_modules.instructions(*wp, Hook::Function(exec_isr_hook::<ET, S>), false);
} }
_hooks.jmps(Hook::Function(gen_jmp_is_syscall::<QT, S>), Hook::Function(trace_jmp::<QT, S>)); _emulator_modules.jmps(Hook::Function(gen_jmp_is_syscall::<ET, S>), Hook::Function(trace_jmp::<ET, S>));
#[cfg(feature = "trace_job_response_times")] #[cfg(feature = "trace_job_response_times")]
_hooks.instruction(self.job_done_addrs, Hook::Function(job_done_hook::<QT, S>), false); _emulator_modules.instructions(self.job_done_addrs, Hook::Function(job_done_hook::<ET, S>), false);
#[cfg(feature = "trace_reads")] #[cfg(feature = "trace_reads")]
_hooks.reads(Hook::Function(gen_read_is_input::<QT, S>), Hook::Empty,Hook::Empty,Hook::Empty,Hook::Empty,Hook::Function(trace_reads::<QT, S>)); _emulator_modules.reads(Hook::Function(gen_read_is_input::<ET, S>), Hook::Empty,Hook::Empty,Hook::Empty,Hook::Empty,Hook::Function(trace_reads::<ET, S>));
unsafe { INPUT_MEM = self.input_mem.clone() }; unsafe { INPUT_MEM = self.input_mem.clone() };
} }
// TODO: refactor duplicate code // TODO: refactor duplicate code
fn pre_exec(&mut self, _emulator: libafl_qemu::Qemu, _input: &I) { fn pre_exec<ET>(
&mut self,
_emulator_modules: &mut EmulatorModules<ET, S>,
_state: &mut S,
_input: &S::Input,
) where
ET: EmulatorModuleTuple<S>,
{
unsafe { unsafe {
CURRENT_SYSTEMSTATE_VEC.clear(); CURRENT_SYSTEMSTATE_VEC.clear();
JOBS_DONE.clear(); JOBS_DONE.clear();
} }
} }
fn post_exec<OT>(&mut self, emulator: libafl_qemu::Qemu, _input: &I, _observers: &mut OT, _exit_kind: &mut ExitKind) { fn post_exec<OT, ET>(
trigger_collection(&emulator,(0, 0), CaptureEvent::End, self); &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>,
{
trigger_collection(&_emulator_modules.qemu(),(0, 0), CaptureEvent::End, self);
unsafe { unsafe {
let c = emulator.cpu_from_index(0); let c = _emulator_modules.qemu().cpu_from_index(0);
let pc = c.read_reg::<i32, u32>(15).unwrap(); let pc = c.read_reg::<i32>(15).unwrap();
if CURRENT_SYSTEMSTATE_VEC.len() == 0 {return;} if CURRENT_SYSTEMSTATE_VEC.len() == 0 {return;}
CURRENT_SYSTEMSTATE_VEC[CURRENT_SYSTEMSTATE_VEC.len()-1].edge = (pc,0); CURRENT_SYSTEMSTATE_VEC[CURRENT_SYSTEMSTATE_VEC.len()-1].edge = (pc,0);
CURRENT_SYSTEMSTATE_VEC[CURRENT_SYSTEMSTATE_VEC.len()-1].capture_point = (CaptureEvent::End,"Breakpoint".to_string()); CURRENT_SYSTEMSTATE_VEC[CURRENT_SYSTEMSTATE_VEC.len()-1].capture_point = (CaptureEvent::End,"Breakpoint".to_string());
@ -207,6 +228,26 @@ where
CURRENT_SYSTEMSTATE_VEC.drain(..index); CURRENT_SYSTEMSTATE_VEC.drain(..index);
} }
} }
type ModuleAddressFilter = NopAddressFilter;
type ModulePageFilter = NopPageFilter;
fn address_filter(&self) -> &Self::ModuleAddressFilter {
todo!()
}
fn address_filter_mut(&mut self) -> &mut Self::ModuleAddressFilter {
todo!()
}
fn page_filter(&self) -> &Self::ModulePageFilter {
todo!()
}
fn page_filter_mut(&mut self) -> &mut Self::ModulePageFilter {
todo!()
}
} }
fn read_freertos_list(systemstate : &mut RawFreeRTOSSystemState, emulator: &libafl_qemu::Qemu, target: GuestAddr) -> (freertos::List_t, bool) { fn read_freertos_list(systemstate : &mut RawFreeRTOSSystemState, emulator: &libafl_qemu::Qemu, target: GuestAddr) -> (freertos::List_t, bool) {
@ -341,57 +382,57 @@ fn trigger_collection(emulator: &libafl_qemu::Qemu, edge: (GuestAddr, GuestAddr)
pub static mut JOBS_DONE : Vec<(u64, String)> = vec![]; pub static mut JOBS_DONE : Vec<(u64, String)> = vec![];
pub fn job_done_hook<QT, S>( pub fn job_done_hook<QT, S>(
hooks: &mut QemuHooks, hooks: &mut EmulatorModules<QT, S>,
_state: Option<&mut S>, _state: Option<&mut S>,
_pc: GuestAddr, _pc: GuestAddr,
) )
where where
S: UsesInput, S: UsesInput,
QT: QemuHelperTuple<S>, QT: EmulatorModuleTuple<S>,
{ {
let emulator = hooks.qemu(); let emulator = hooks.qemu();
let h = hooks.helpers().match_first_type::<QemuSystemStateHelper>().expect("QemuSystemHelper not found in helper tupel"); let h = hooks.modules().match_first_type::<QemuSystemStateHelper>().expect("QemuSystemHelper not found in helper tupel");
let curr_tcb_addr : freertos::void_ptr = freertos::emu_lookup::lookup(emulator, h.tcb_addr); let curr_tcb_addr : freertos::void_ptr = freertos::emu_lookup::lookup(&emulator, h.tcb_addr);
if curr_tcb_addr == 0 { if curr_tcb_addr == 0 {
return; return;
}; };
let current_tcb : TCB_t = freertos::emu_lookup::lookup(emulator,curr_tcb_addr); let current_tcb : TCB_t = freertos::emu_lookup::lookup(&emulator,curr_tcb_addr);
let tmp = unsafe {std::mem::transmute::<[i8; 10],[u8; 10]>(current_tcb.pcTaskName)}; let tmp = unsafe {std::mem::transmute::<[i8; 10],[u8; 10]>(current_tcb.pcTaskName)};
let name : String = std::str::from_utf8(&tmp).expect("TCB name was not utf8").chars().filter(|x| *x != '\0').collect::<String>(); let name : String = std::str::from_utf8(&tmp).expect("TCB name was not utf8").chars().filter(|x| *x != '\0').collect::<String>();
unsafe { JOBS_DONE.push((get_icount(emulator), name)); } unsafe { JOBS_DONE.push((get_icount(&emulator), name)); }
} }
//============================= Trace interrupt service routines //============================= Trace interrupt service routines
pub fn exec_isr_hook<QT, S>( pub fn exec_isr_hook<QT, S>(
hooks: &mut QemuHooks, hooks: &mut EmulatorModules<QT, S>,
_state: Option<&mut S>, _state: Option<&mut S>,
pc: GuestAddr, pc: GuestAddr,
) )
where where
S: UsesInput, S: UsesInput,
QT: QemuHelperTuple<S>, QT: EmulatorModuleTuple<S>,
{ {
let emulator = hooks.qemu(); let emulator = hooks.qemu();
let h = hooks.helpers().match_first_type::<QemuSystemStateHelper>().expect("QemuSystemHelper not found in helper tupel"); let h = hooks.modules().match_first_type::<QemuSystemStateHelper>().expect("QemuSystemHelper not found in helper tupel");
let src = read_rec_return_stackframe(emulator, 0xfffffffc); let src = read_rec_return_stackframe(&emulator, 0xfffffffc);
trigger_collection(emulator, (src, pc), CaptureEvent::ISRStart, h); trigger_collection(&emulator, (src, pc), CaptureEvent::ISRStart, h);
// println!("Exec ISR Call {:#x} {:#x} {}", src, pc, get_icount(emulator)); // println!("Exec ISR Call {:#x} {:#x} {}", src, pc, get_icount(emulator));
} }
//============================= Trace syscalls and returns //============================= Trace syscalls and returns
pub fn gen_jmp_is_syscall<QT, S>( pub fn gen_jmp_is_syscall<QT, S>(
hooks: &mut QemuHooks, hooks: &mut EmulatorModules<QT, S>,
_state: Option<&mut S>, _state: Option<&mut S>,
src: GuestAddr, src: GuestAddr,
dest: GuestAddr, dest: GuestAddr,
) -> Option<u64> ) -> Option<u64>
where where
S: UsesInput, S: UsesInput,
QT: QemuHelperTuple<S>, QT: EmulatorModuleTuple<S>,
{ {
if let Some(h) = hooks.helpers().match_first_type::<QemuSystemStateHelper>() { if let Some(h) = hooks.modules().match_first_type::<QemuSystemStateHelper>() {
if h.app_range.contains(&src) && !h.app_range.contains(&dest) && in_any_range(&h.isr_ranges,src).is_none() { if h.app_range.contains(&src) && !h.app_range.contains(&dest) && in_any_range(&h.isr_ranges,src).is_none() {
if let Some(_) = in_any_range(&h.api_fn_ranges,dest) { if let Some(_) = in_any_range(&h.api_fn_ranges,dest) {
// println!("New jmp {:x} {:x}", src, dest); // println!("New jmp {:x} {:x}", src, dest);
@ -415,18 +456,18 @@ where
} }
pub fn trace_jmp<QT, S>( pub fn trace_jmp<QT, S>(
hooks: &mut QemuHooks, hooks: &mut EmulatorModules<QT, S>,
_state: Option<&mut S>, _state: Option<&mut S>,
src: GuestAddr, mut dest: GuestAddr, id: u64 src: GuestAddr, mut dest: GuestAddr, id: u64
) )
where where
S: UsesInput, S: UsesInput,
QT: QemuHelperTuple<S>, QT: EmulatorModuleTuple<S>,
{ {
let h = hooks.helpers().match_first_type::<QemuSystemStateHelper>().expect("QemuSystemHelper not found in helper tupel"); let h = hooks.modules().match_first_type::<QemuSystemStateHelper>().expect("QemuSystemHelper not found in helper tupel");
let emulator = hooks.qemu(); let emulator = hooks.qemu();
if id == 1 { // API call if id == 1 { // API call
trigger_collection(emulator, (src, dest), CaptureEvent::APIStart, h); trigger_collection(&emulator, (src, dest), CaptureEvent::APIStart, h);
// println!("Exec API Call {:#x} {:#x} {}", src, dest, get_icount(emulator)); // println!("Exec API Call {:#x} {:#x} {}", src, dest, get_icount(emulator));
} else if id == 2 { // API return } else if id == 2 { // API return
// Ignore returns to other APIs or ISRs. We only account for the first call depth of API calls from user space. // Ignore returns to other APIs or ISRs. We only account for the first call depth of API calls from user space.
@ -436,17 +477,17 @@ where
edge.0=in_any_range(&h.api_fn_ranges, src).unwrap().start; edge.0=in_any_range(&h.api_fn_ranges, src).unwrap().start;
edge.1=dest; edge.1=dest;
trigger_collection(emulator, edge, CaptureEvent::APIEnd, h); trigger_collection(&emulator, edge, CaptureEvent::APIEnd, h);
// println!("Exec API Return Edge {:#x} {:#x} {}", src, dest, get_icount(emulator)); // println!("Exec API Return Edge {:#x} {:#x} {}", src, dest, get_icount(emulator));
} }
} else if id == 3 { // ISR return } else if id == 3 { // ISR return
dest = read_rec_return_stackframe(emulator, dest); dest = read_rec_return_stackframe(&emulator, dest);
let mut edge = (0, 0); let mut edge = (0, 0);
edge.0=in_any_range(&h.isr_ranges, src).unwrap().start; edge.0=in_any_range(&h.isr_ranges, src).unwrap().start;
edge.1=dest; edge.1=dest;
trigger_collection(emulator, edge, CaptureEvent::ISREnd, h); trigger_collection(&emulator, edge, CaptureEvent::ISREnd, h);
// println!("Exec ISR Return Edge {:#x} {:#x} {}", src, dest, get_icount(emulator)); // println!("Exec ISR Return Edge {:#x} {:#x} {}", src, dest, get_icount(emulator));
} }
} }
@ -454,7 +495,7 @@ where
//============================= Read Hooks //============================= Read Hooks
#[allow(unused)] #[allow(unused)]
pub fn gen_read_is_input<QT, S>( pub fn gen_read_is_input<QT, S>(
hooks: &mut QemuHooks, hooks: &mut EmulatorModules<QT, S>,
_state: Option<&mut S>, _state: Option<&mut S>,
pc: GuestAddr, pc: GuestAddr,
_addr: *mut TCGTemp, _addr: *mut TCGTemp,
@ -462,9 +503,9 @@ pub fn gen_read_is_input<QT, S>(
) -> Option<u64> ) -> Option<u64>
where where
S: UsesInput, S: UsesInput,
QT: QemuHelperTuple<S>, QT: EmulatorModuleTuple<S>,
{ {
if let Some(h) = hooks.helpers().match_first_type::<QemuSystemStateHelper>() { if let Some(h) = hooks.modules().match_first_type::<QemuSystemStateHelper>() {
if h.app_range.contains(&pc) { if h.app_range.contains(&pc) {
// println!("gen_read {:x}", pc); // println!("gen_read {:x}", pc);
return Some(1); return Some(1);
@ -478,7 +519,7 @@ static mut MEM_READ : Option<Vec<(GuestAddr, u8)>> = None;
#[allow(unused)] #[allow(unused)]
pub fn trace_reads<QT, S>( pub fn trace_reads<QT, S>(
hooks: &mut QemuHooks, hooks: &mut EmulatorModules<QT, S>,
_state: Option<&mut S>, _state: Option<&mut S>,
_id: u64, _id: u64,
addr: GuestAddr, addr: GuestAddr,
@ -486,7 +527,7 @@ pub fn trace_reads<QT, S>(
) )
where where
S: UsesInput, S: UsesInput,
QT: QemuHelperTuple<S>, QT: EmulatorModuleTuple<S>,
{ {
if unsafe { INPUT_MEM.contains(&addr) } { if unsafe { INPUT_MEM.contains(&addr) } {
let emulator = hooks.qemu(); let emulator = hooks.qemu();

View File

@ -64,7 +64,7 @@ pub struct RawFreeRTOSSystemState {
capture_point: (CaptureEvent,String), capture_point: (CaptureEvent,String),
mem_reads: Vec<(u32, u8)> mem_reads: Vec<(u32, u8)>
} }
/// List of system state dumps from QemuHelpers /// List of system state dumps from EmulatorModules
static mut CURRENT_SYSTEMSTATE_VEC: Vec<RawFreeRTOSSystemState> = vec![]; static mut CURRENT_SYSTEMSTATE_VEC: Vec<RawFreeRTOSSystemState> = vec![];
/// A reduced version of freertos::TCB_t /// A reduced version of freertos::TCB_t

View File

@ -9,7 +9,7 @@ use libafl_bolts::{rands::{
random_seed, Rand, StdRand random_seed, Rand, StdRand
}, Named}; }, Named};
use libafl::{ use libafl::{
common::{HasMetadata, HasNamedMetadata}, corpus::{self, Corpus}, events::{Event, EventFirer, EventProcessor, LogSeverity}, fuzzer::Evaluator, inputs::{HasMutatorBytes, HasTargetBytes, Input, MultipartInput}, mark_feature_time, {new_hash_feedback, AggregatorOps, CorpusId, MutationResult, Mutator, UserStats, UserStatsValue, UsesInput}, stages::Stage, start_timer, state::{HasCorpus, HasRand, MaybeHasClientPerfMonitor, UsesState}, Error common::{HasMetadata, HasNamedMetadata}, corpus::{self, Corpus, HasCurrentCorpusId, Testcase}, events::{Event, EventFirer, EventProcessor, LogSeverity}, fuzzer::Evaluator, inputs::{HasMutatorBytes, HasTargetBytes, Input, MultipartInput}, mark_feature_time, prelude::{new_hash_feedback, AggregatorOps, CorpusId, MutationResult, Mutator, UserStats, UserStatsValue, UsesInput}, stages::Stage, start_timer, state::{HasCorpus, HasRand, MaybeHasClientPerfMonitor, UsesState}, Error
}; };
use libafl::prelude::State; use libafl::prelude::State;
use petgraph::{graph::NodeIndex, graph::{self, DiGraph}}; use petgraph::{graph::NodeIndex, graph::{self, DiGraph}};
@ -163,16 +163,15 @@ where
} }
} }
impl<E, EM, Z, I> Stage<E, EM, Z> for InterruptShiftStage<E, EM, Z> impl<S, E, EM, Z, I> Stage<E, EM, Z> for InterruptShiftStage<E, EM, Z>
where where
E: UsesState<State = Z::State>, E: UsesState<State = S>,
EM: UsesState<State = Z::State>, EM: UsesState<State = S>,
Z: Evaluator<E, EM, State = S>,
S: State<Input = MultipartInput<I>> + HasRand + HasCorpus + HasCurrentTestcase + HasMetadata + HasNamedMetadata,
<<Self as UsesState>::State as HasCorpus>::Corpus: Corpus<Input = Self::Input>, //delete me
EM: EventFirer, EM: EventFirer,
Z: Evaluator<E, EM>, I: Default + Input + HasMutatorBytes,
Z::State: MaybeHasClientPerfMonitor + HasCorpus + HasRand + HasMetadata + HasNamedMetadata,
<Z::State as UsesInput>::Input: Input,
Z::State: UsesInput<Input = MultipartInput<I>>,
I: HasMutatorBytes + Default
{ {
fn perform( fn perform(
&mut self, &mut self,
@ -180,7 +179,8 @@ where
executor: &mut E, executor: &mut E,
state: &mut Self::State, state: &mut Self::State,
manager: &mut EM manager: &mut EM
) -> Result<(), Error> { ) -> Result<(), Error>
where <Z as UsesState>::State: HasCorpus {
if self.interrup_config.len() == 0 {return Ok(());} // configuration implies no interrupts if self.interrup_config.len() == 0 {return Ok(());} // configuration implies no interrupts
let mut myrand = StdRand::new(); let mut myrand = StdRand::new();
myrand.set_seed(state.rand_mut().next()); myrand.set_seed(state.rand_mut().next());
@ -203,10 +203,10 @@ where
let name = format!("isr_{}_times", interrup_config.0); let name = format!("isr_{}_times", interrup_config.0);
// manager.log(state, LogSeverity::Info, format!("Mutation {}/{}", loopbound, loopcount))?; // manager.log(state, LogSeverity::Info, format!("Mutation {}/{}", loopbound, loopcount))?;
let curr_case = state.current_testcase()?; let curr_case : std::cell::Ref<Testcase<MultipartInput<_>>> = state.current_testcase()?;
let curr_input = curr_case.input().as_ref().unwrap(); let curr_input = curr_case.input().as_ref().unwrap();
let mut new_input = curr_input.clone(); let mut new_input : MultipartInput<I> = curr_input.clone();
let new_interrupt_part : &mut I = if new_input.parts_by_name(&name).next().is_some() { let new_interrupt_part : &mut I = if new_input.parts_by_name(&name).next().is_some() {
new_input.parts_by_name_mut(&name).next().unwrap() new_input.parts_by_name_mut(&name).next().unwrap()
} else { } else {
@ -521,7 +521,9 @@ where
Z::State: MaybeHasClientPerfMonitor + HasCorpus + HasRand + HasMetadata + HasNamedMetadata, Z::State: MaybeHasClientPerfMonitor + HasCorpus + HasRand + HasMetadata + HasNamedMetadata,
<Z::State as UsesInput>::Input: Input, <Z::State as UsesInput>::Input: Input,
Z::State: UsesInput<Input = MultipartInput<I>>, Z::State: UsesInput<Input = MultipartInput<I>>,
I: HasMutatorBytes + Default I: HasMutatorBytes + Default,
Z::State: HasCurrentTestcase+HasCorpus+HasCurrentCorpusId,
<Z::State as HasCorpus>::Corpus: Corpus<Input = MultipartInput<I>>
{ {
fn perform( fn perform(
&mut self, &mut self,
@ -537,7 +539,7 @@ where
let current_case = state.current_testcase()?; let current_case = state.current_testcase()?;
let old_input = current_case.input().as_ref().unwrap(); let old_input = current_case.input().as_ref().unwrap();
let mut new_input = old_input.clone(); let mut new_input : MultipartInput<I> = old_input.clone();
let new_bytes = new_input.parts_by_name_mut("bytes").next().expect("bytes not found in multipart input").1.bytes_mut(); let new_bytes = new_input.parts_by_name_mut("bytes").next().expect("bytes not found in multipart input").1.bytes_mut();
// dbg!(current_case.metadata_map()); // dbg!(current_case.metadata_map());
// eprintln!("Run mutator {}", current_case.metadata_map().get::<STGNodeMetadata>().is_some()); // eprintln!("Run mutator {}", current_case.metadata_map().get::<STGNodeMetadata>().is_some());

View File

@ -49,10 +49,11 @@ pub struct QemuSystemStateObserver<I>
name: Cow<'static, str>, name: Cow<'static, str>,
} }
impl<I, S> Observer<<S as UsesInput>::Input, S> for QemuSystemStateObserver<<S as UsesInput>::Input> impl<I, S> Observer<I, S> for QemuSystemStateObserver<I>
where where
S: UsesInput + HasMetadata, S: UsesInput<Input = I> + HasMetadata,
S::Input: Default S::Input: Default,
I: Clone,
{ {
#[inline] #[inline]
fn pre_exec(&mut self, _state: &mut S, _input: &I) -> Result<(), Error> { fn pre_exec(&mut self, _state: &mut S, _input: &I) -> Result<(), Error> {

View File

@ -7,8 +7,9 @@ use libafl_bolts::current_time;
use itertools::Itertools; use itertools::Itertools;
use libafl::{ use libafl::{
corpus::{Corpus, HasCurrentCorpusId}, events::EventFirer, schedulers::minimizer::TopRatedsMetadata, RemovableScheduler, schedulers::minimizer::IsFavoredMetadata, stages::Stage, state::{HasCorpus, HasImported, UsesState}, Error, HasMetadata, HasScheduler corpus::{Corpus, HasCurrentCorpusId}, events::EventFirer, schedulers::minimizer::TopRatedsMetadata, schedulers::RemovableScheduler, schedulers::minimizer::IsFavoredMetadata, stages::Stage, state::{HasCorpus, HasImported, UsesState}, Error, HasMetadata, HasScheduler
}; };
use libafl::prelude::UsesInput;
use libafl::{ use libafl::{
events::Event, events::Event,
monitors::{AggregatorOps, UserStats, UserStatsValue}, monitors::{AggregatorOps, UserStats, UserStatsValue},
@ -20,6 +21,22 @@ use libafl::prelude::mutational::MUTATION_STAGE_ITER;
use libafl::prelude::mutational::MUTATION_STAGE_RETRY; use libafl::prelude::mutational::MUTATION_STAGE_RETRY;
use libafl::prelude::mutational::MUTATION_STAGE_SUCCESS; use libafl::prelude::mutational::MUTATION_STAGE_SUCCESS;
use libafl::HasNamedMetadata;
use libafl::prelude::Feedback;
use libafl::prelude::HasMaxSize;
use libafl::prelude::HasSolutions;
use libafl::prelude::HasExecutions;
use std::hash::Hash;
use libafl_bolts::HasLen;
use libafl::prelude::mutational::MutatedTransform;
use libafl::prelude::FeedbackFactory;
use serde::Serialize;
use libafl::prelude::ObserversTuple;
use libafl::prelude::HasObservers;
use libafl::HasFeedback;
use libafl::ExecutesInput;
use libafl::ExecutionProcessor;
/// The [`AflStatsStage`] is a simple stage that computes and reports some stats. /// The [`AflStatsStage`] is a simple stage that computes and reports some stats.
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct SchedulerStatsStage<E, EM, Z> { pub struct SchedulerStatsStage<E, EM, Z> {
@ -37,13 +54,35 @@ where
type State = E::State; type State = E::State;
} }
impl<E, EM, Z> Stage<E, EM, Z> for SchedulerStatsStage<E, EM, Z> // impl<E, EM, Z> Stage<E, EM, Z> for SchedulerStatsStage<E, EM, Z>
// where
// E: UsesState,
// EM: UsesState<State = Self::State>,
// Z: UsesState<State = Self::State>,
// Self::State: HasNamedMetadata,
// // E: UsesState,
// // EM: EventFirer<State = Self::State>,
// // Z: UsesState<State = Self::State> + HasScheduler,
// // <Z as HasScheduler>::Scheduler: UsesState+RemovableScheduler<<<Z as HasScheduler>::Scheduler as UsesInput>::Input, Self::State>,
// // Self::State: HasImported + HasCorpus + HasMetadata,
// // <E as UsesState>::State: HasMetadata+HasImported+UsesState,
// {
impl<E, EM, IP, Z> Stage<E, EM, Z> for SchedulerStatsStage<E, EM, Z>
where where
E: UsesState, Z: HasScheduler + ExecutionProcessor<EM, E::Observers> + ExecutesInput<E, EM> + HasFeedback,
Z::Scheduler: RemovableScheduler<Self::Input, Self::State>,
E: HasObservers + UsesState<State = Z::State>,
E::Observers: ObserversTuple<Self::Input, Self::State> + Serialize,
EM: EventFirer<State = Self::State>, EM: EventFirer<State = Self::State>,
Z: UsesState<State = Self::State> + HasScheduler, // FF: FeedbackFactory<F, E::Observers>,
<Z as HasScheduler>::Scheduler: RemovableScheduler, // F: Feedback<EM, Self::Input, E::Observers, Self::State>,
Self::State: HasImported + HasCorpus + HasMetadata, Self::Input: MutatedTransform<Self::Input, Self::State, Post = IP> + Clone,
Z::State:
HasMetadata + HasExecutions + HasSolutions + HasCorpus + HasMaxSize + HasNamedMetadata,
Z::Feedback: Feedback<EM, Self::Input, E::Observers, Self::State>,
// M: Mutator<Self::Input, Self::State>,
// IP: MutatedTransformPost<Self::State> + Clone,
<<Self as UsesState>::State as HasCorpus>::Corpus: Corpus<Input = Self::Input>, // delete me
{ {
fn perform( fn perform(
&mut self, &mut self,

View File

@ -45,9 +45,9 @@ where
type State = CS::State; type State = CS::State;
} }
impl<CS> Scheduler<CS::State, CS::Input> for LongestTraceScheduler<CS> impl<CS> Scheduler<CS::Input, CS::State> for LongestTraceScheduler<CS>
where where
CS: UsesState + Scheduler<CS::State, CS::Input>, CS: UsesState + Scheduler<CS::Input, CS::State>,
CS::State: HasCorpus + HasMetadata + HasRand, CS::State: HasCorpus + HasMetadata + HasRand,
{ {
/// Add an entry to the corpus and return its index /// Add an entry to the corpus and return its index
@ -98,7 +98,7 @@ where
.metadata_map() .metadata_map()
.get::<STGNodeMetadata>().map_or(0, |x| x.nodes().len()); .get::<STGNodeMetadata>().map_or(0, |x| x.nodes().len());
let m = self.get_update_trace_length(state,l); let m = self.get_update_trace_length(state,l);
state.rand_mut().below(m as usize) > l state.rand_mut().below(std::num::NonZero::new(m as usize+1).unwrap()) > l
} && state.rand_mut().coinflip(self.skip_non_favored_prob) } && state.rand_mut().coinflip(self.skip_non_favored_prob)
{ {
idx = self.base.next(state)?; idx = self.base.next(state)?;
@ -108,7 +108,7 @@ where
fn set_current_scheduled( fn set_current_scheduled(
&mut self, &mut self,
state: &mut <<CS as UsesState>::State as UsesInput>::Input, state: &mut <CS as UsesState>::State,
next_id: Option<libafl::corpus::CorpusId>, next_id: Option<libafl::corpus::CorpusId>,
) -> Result<(), Error> { ) -> Result<(), Error> {
self.base.set_current_scheduled(state, next_id) self.base.set_current_scheduled(state, next_id)
@ -117,7 +117,7 @@ where
impl<CS> LongestTraceScheduler<CS> impl<CS> LongestTraceScheduler<CS>
where where
CS: UsesState + Scheduler<CS::State, CS::Input>, CS: UsesState + Scheduler<CS::Input, CS::State>,
CS::State: HasCorpus + HasMetadata + HasRand, CS::State: HasCorpus + HasMetadata + HasRand,
{ {
pub fn get_update_trace_length(&self, state: &mut CS::State, par: usize) -> u64 { pub fn get_update_trace_length(&self, state: &mut CS::State, par: usize) -> u64 {
@ -173,6 +173,7 @@ where
impl<I, S> Scheduler<I, S> for GenerationScheduler<S> impl<I, S> Scheduler<I, S> for GenerationScheduler<S>
where where
S: State + HasCorpus + HasMetadata, S: State + HasCorpus + HasMetadata,
<<S as HasCorpus>::Corpus as libafl::corpus::Corpus>::Input: Clone,
{ {
/// get first element in current gen, /// get first element in current gen,
/// if current_gen is empty, swap lists, sort by FavFactor, take top k and return first /// if current_gen is empty, swap lists, sort by FavFactor, take top k and return first
@ -247,7 +248,7 @@ where
state: &mut S, state: &mut S,
next_id: Option<libafl::corpus::CorpusId>, next_id: Option<libafl::corpus::CorpusId>,
) -> Result<(), Error> { ) -> Result<(), Error> {
self.base.set_current_scheduled(state, next_id) Ok(())
} }
// fn on_replace( // fn on_replace(
// &self, // &self,
@ -276,7 +277,7 @@ where
// } // }
} }
impl<S> RemovableScheduler for GenerationScheduler<S> impl<I,S> RemovableScheduler<I,S> for GenerationScheduler<S>
where where
S: State + HasCorpus + HasMetadata, S: State + HasCorpus + HasMetadata,
{ {
@ -285,7 +286,7 @@ where
&mut self, &mut self,
state: &mut <Self as UsesState>::State, state: &mut <Self as UsesState>::State,
idx: CorpusId, idx: CorpusId,
testcase: &Testcase<<<Self as UsesState>::State as UsesInput>::Input>, testcase: &Testcase<I>,
) -> Result<(), Error> { ) -> Result<(), Error> {
Ok(()) Ok(())
} }
@ -295,7 +296,7 @@ where
&mut self, &mut self,
state: &mut <Self as UsesState>::State, state: &mut <Self as UsesState>::State,
idx: CorpusId, idx: CorpusId,
testcase: &Option<Testcase<<<Self as UsesState>::State as UsesInput>::Input>>, testcase: &Option<Testcase<I>>,
) -> Result<(), Error> { ) -> Result<(), Error> {
Ok(()) Ok(())
} }

View File

@ -21,7 +21,6 @@ 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;
use libafl_qemu::edges::EDGES_MAP_SIZE_IN_USE;
use hashbrown::HashMap; use hashbrown::HashMap;
use libafl::{executors::ExitKind, observers::ObserversTuple, common::HasMetadata}; use libafl::{executors::ExitKind, observers::ObserversTuple, common::HasMetadata};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -300,8 +299,8 @@ impl HasRefCnt for STGNodeMetadata {
libafl_bolts::impl_serdeany!(STGNodeMetadata); libafl_bolts::impl_serdeany!(STGNodeMetadata);
pub type GraphMaximizerCorpusScheduler<CS, O> = pub type GraphMaximizerCorpusScheduler<CS, S, O> =
MinimizerScheduler<CS, MaxTimeFavFactor<<CS as UsesState>::State>,STGNodeMetadata,O>; MinimizerScheduler<CS, MaxTimeFavFactor<S>,STGNodeMetadata,O>;
// AI generated, human verified // AI generated, human verified
/// Count the occurrences of each element in a vector, assumes the vector is sorted /// Count the occurrences of each element in a vector, assumes the vector is sorted
@ -336,7 +335,8 @@ where
//============================= Graph Feedback //============================= Graph Feedback
pub static mut STG_MAP: [u16; EDGES_MAP_SIZE_IN_USE] = [0; EDGES_MAP_SIZE_IN_USE]; pub const STG_MAP_SIZE: usize = 1<<20;
pub static mut STG_MAP: [u16; STG_MAP_SIZE] = [0; STG_MAP_SIZE];
pub static mut MAX_STG_NUM: usize = 0; pub static mut MAX_STG_NUM: usize = 0;
pub unsafe fn stg_map_mut_slice<'a>() -> OwnedMutSlice<'a, u16> { pub unsafe fn stg_map_mut_slice<'a>() -> OwnedMutSlice<'a, u16> {
OwnedMutSlice::from_raw_parts_mut(STG_MAP.as_mut_ptr(), STG_MAP.len()) OwnedMutSlice::from_raw_parts_mut(STG_MAP.as_mut_ptr(), STG_MAP.len())
@ -531,7 +531,7 @@ where
S: State + UsesInput + MaybeHasClientPerfMonitor + HasNamedMetadata, S: State + UsesInput + MaybeHasClientPerfMonitor + HasNamedMetadata,
S::Input: Default, S::Input: Default,
EM: EventFirer<State = S>, EM: EventFirer<State = S>,
OT: ObserversTuple<S>, OT: ObserversTuple<I, S>,
{ {
#[allow(clippy::wrong_self_convention)] #[allow(clippy::wrong_self_convention)]
fn is_interesting( fn is_interesting(

View File

@ -0,0 +1,159 @@
use libafl::{events::EventFirer, inputs::UsesInput, prelude::{Feedback, ObserversTuple, StateInitializer}};
use libafl_bolts::Named;
use libafl_qemu::{modules::EmulatorModule, EmulatorModules};
use std::borrow::Cow;
use libafl::prelude::*;
use libafl_qemu::modules::*;
use libafl_qemu::*;
//============================================== Feedback
/// Example Feedback for type correctness
#[derive(Clone, Debug, Default)]
pub struct MinimalFeedback {
/// The name
name: Cow<'static, str>,
}
impl<S> StateInitializer<S> for MinimalFeedback {}
impl<EM, I, OT, S> Feedback<EM, I, OT, S> for MinimalFeedback
where
S: State + UsesInput<Input=I>,
EM: EventFirer<State = S>,
OT: ObserversTuple<I, S>,
{
#[allow(clippy::wrong_self_convention)]
fn is_interesting(
&mut self,
state: &mut S,
manager: &mut EM,
input: &I,
observers: &OT,
exit_kind: &ExitKind,
) -> Result<bool, Error> {
Ok(false)
}
}
impl Named for MinimalFeedback {
#[inline]
fn name(&self) -> &Cow<'static, str> {
&self.name
}
}
//============================================== TestcaseScore
pub struct MinimalTestcaseScore {}
impl<S> TestcaseScore<S> for MinimalTestcaseScore
where
S: HasMetadata + HasCorpus,
{
fn compute(
_state: &S,
entry: &mut Testcase<<S::Corpus as Corpus>::Input>,
) -> Result<f64, Error> {
Ok(0 as f64)
}
}
//============================================== EmulatorModule
#[derive(Debug)]
pub struct MinimalEmulatorModule {
af: NopAddressFilter,
pf: NopPageFilter
}
impl<S> EmulatorModule<S> for MinimalEmulatorModule
where
S: UsesInput,
{
const HOOKS_DO_SIDE_EFFECTS: bool = true;
type ModuleAddressFilter = NopAddressFilter;
type ModulePageFilter = NopPageFilter;
/// 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<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>,
{
}
/// Run once just before fuzzing starts.
/// 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<ET>(&mut self, _emulator_modules: &mut EmulatorModules<ET, S>, _state: &mut S)
where
ET: EmulatorModuleTuple<S>,
{
}
/// Run before a new fuzzing run starts.
/// On the first run, it is executed after [`Self::first_exec`].
fn pre_exec<ET>(
&mut self,
_emulator_modules: &mut EmulatorModules<ET, S>,
_state: &mut S,
_input: &S::Input,
) where
ET: EmulatorModuleTuple<S>,
{
}
/// Run after a fuzzing run ends.
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>,
{
}
/// # 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 {
&self.af
}
fn address_filter_mut(&mut self) -> &mut Self::ModuleAddressFilter {
&mut self.af
}
fn update_address_filter(&mut self, qemu: Qemu, filter: Self::ModuleAddressFilter) {
}
fn page_filter(&self) -> &Self::ModulePageFilter {
&self.pf
}
fn page_filter_mut(&mut self) -> &mut Self::ModulePageFilter {
&mut self.pf
}
}

View File

@ -43,6 +43,8 @@ pub fn tick_to_time(ticks: u64) -> Duration {
pub fn tick_to_ms(ticks: u64) -> f32 { pub fn tick_to_ms(ticks: u64) -> f32 {
(Duration::from_nanos(ticks << QEMU_ICOUNT_SHIFT).as_micros() as f32/10.0).round()/100.0 (Duration::from_nanos(ticks << QEMU_ICOUNT_SHIFT).as_micros() as f32/10.0).round()/100.0
} }
use libafl::prelude::StateInitializer;
//========== Metadata //========== Metadata
#[derive(Debug, SerdeAny, Serialize, Deserialize)] #[derive(Debug, SerdeAny, Serialize, Deserialize)]
@ -216,10 +218,14 @@ pub struct ClockTimeFeedback {
name: Cow<'static, str>, name: Cow<'static, str>,
} }
impl<S> StateInitializer<S> for ClockTimeFeedback {}
impl<EM, I, OT, S> Feedback<EM, I, OT, S> for ClockTimeFeedback impl<EM, I, OT, S> Feedback<EM, I, OT, S> for ClockTimeFeedback
where where
S: State + UsesInput + MaybeHasClientPerfMonitor + HasMetadata, S: State + UsesInput + MaybeHasClientPerfMonitor + HasMetadata,
<S as UsesInput>::Input: Default <S as UsesInput>::Input: Default,
EM: EventFirer<State = S>,
OT: ObserversTuple<I, S>,
{ {
#[allow(clippy::wrong_self_convention)] #[allow(clippy::wrong_self_convention)]
fn is_interesting( fn is_interesting(
@ -231,8 +237,6 @@ where
_exit_kind: &ExitKind, _exit_kind: &ExitKind,
) -> Result<bool, Error> ) -> Result<bool, Error>
where where
EM: EventFirer<State = S>,
OT: ObserversTuple<S>,
{ {
#[cfg(feature="trace_job_response_times")] #[cfg(feature="trace_job_response_times")]
{ {
@ -255,7 +259,7 @@ where
_state: &mut S, _state: &mut S,
_manager: &mut EM, _manager: &mut EM,
_observers: &OT, _observers: &OT,
testcase: &mut Testcase<<S as UsesInput>::Input>, testcase: &mut Testcase<I>,
) -> Result<(), Error> { ) -> Result<(), Error> {
*testcase.exec_time_mut() = self.exec_time; *testcase.exec_time_mut() = self.exec_time;
self.exec_time = None; self.exec_time = None;
@ -305,9 +309,13 @@ pub struct QemuClockIncreaseFeedback {
name: Cow<'static, str>, name: Cow<'static, str>,
} }
impl<S> StateInitializer<S> for QemuClockIncreaseFeedback {}
impl<EM, I, OT, S> Feedback<EM, I, OT, S> for QemuClockIncreaseFeedback impl<EM, I, OT, S> Feedback<EM, I, OT, S> for QemuClockIncreaseFeedback
where where
S: State + UsesInput + HasNamedMetadata + MaybeHasClientPerfMonitor + Debug, S: State + UsesInput + HasNamedMetadata + MaybeHasClientPerfMonitor + Debug,
EM: EventFirer<State = S>,
OT: ObserversTuple<I, S>,
{ {
fn is_interesting( fn is_interesting(
&mut self, &mut self,
@ -318,8 +326,6 @@ where
_exit_kind: &ExitKind, _exit_kind: &ExitKind,
) -> Result<bool, Error> ) -> Result<bool, Error>
where where
EM: EventFirer<State = S>,
OT: ObserversTuple<S>,
{ {
let observer = _observers.match_name::<QemuClockObserver>("clock") let observer = _observers.match_name::<QemuClockObserver>("clock")
.expect("QemuClockObserver not found"); .expect("QemuClockObserver not found");
@ -337,7 +343,7 @@ where
/// Append to the testcase the generated metadata in case of a new corpus item /// Append to the testcase the generated metadata in case of a new corpus item
#[inline] #[inline]
fn append_metadata(&mut self, _state: &mut S, _manager: &mut EM, _observers: &OT, _testcase: &mut Testcase<<S as UsesInput>::Input>) -> Result<(), Error> { fn append_metadata(&mut self, _state: &mut S, _manager: &mut EM, _observers: &OT, _testcase: &mut Testcase<I>) -> Result<(), Error> {
// testcase.metadata_mut().insert(QemuIcountMetadata{runtime: self.last_runtime}); // testcase.metadata_mut().insert(QemuIcountMetadata{runtime: self.last_runtime});
Ok(()) Ok(())
} }

View File

@ -1,10 +1,14 @@
use libafl::prelude::UsesInput; use libafl::prelude::UsesInput;
use libafl_qemu::modules::NopAddressFilter;
use libafl_qemu::modules::NopPageFilter;
use libafl_qemu::sys::CPUArchState; use libafl_qemu::sys::CPUArchState;
use libafl_qemu::FastSnapshotPtr; use libafl_qemu::FastSnapshotPtr;
use libafl_qemu::QemuHelper; use libafl_qemu::modules::EmulatorModule;
use libafl_qemu::QemuHelperTuple; use libafl_qemu::modules::EmulatorModuleTuple;
use libafl::executors::ExitKind; use libafl::executors::ExitKind;
use libafl_qemu::QemuHooks; use libafl_qemu::QemuHooks;
use libafl_qemu::EmulatorModules;
use libafl::prelude::ObserversTuple;
// TODO be thread-safe maybe with https://amanieu.github.io/thread_local-rs/thread_local/index.html // TODO be thread-safe maybe with https://amanieu.github.io/thread_local-rs/thread_local/index.html
#[derive(Debug)] #[derive(Debug)]
@ -39,36 +43,43 @@ impl Default for QemuStateRestoreHelper {
} }
} }
impl<S> QemuHelper<S> for QemuStateRestoreHelper impl<S> EmulatorModule<S> for QemuStateRestoreHelper
where where
S: UsesInput, S: UsesInput,
{ {
const HOOKS_DO_SIDE_EFFECTS: bool = true; const HOOKS_DO_SIDE_EFFECTS: bool = true;
type ModuleAddressFilter = NopAddressFilter;
type ModulePageFilter = NopPageFilter;
fn init_hooks<QT>(&self, _hooks: &QemuHooks) fn post_exec<OT, ET>(
where &mut self,
QT: QemuHelperTuple<S>, _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>,
{ {
}
fn first_exec<QT>(&self, _hooks: &QemuHooks)
where
QT: QemuHelperTuple<S>,
{
}
fn post_exec<OT>(&mut self, _emulator: libafl_qemu::Qemu, _input: &I, _observers: &mut OT, _exit_kind: &mut ExitKind) {
// unsafe { println!("snapshot post {}",emu::icount_get_raw()) }; // unsafe { println!("snapshot post {}",emu::icount_get_raw()) };
} }
fn pre_exec(&mut self, emulator: libafl_qemu::Qemu, _input: &I) { fn pre_exec<ET>(
&mut self,
_emulator_modules: &mut EmulatorModules<ET, S>,
_state: &mut S,
_input: &S::Input,
) where
ET: EmulatorModuleTuple<S>,
{
// only restore in pre-exec, to preserve the post-execution state for inspection // only restore in pre-exec, to preserve the post-execution state for inspection
#[cfg(feature = "snapshot_restore")] #[cfg(feature = "snapshot_restore")]
{ {
#[cfg(feature = "snapshot_fast")] #[cfg(feature = "snapshot_fast")]
match self.fastsnap { match self.fastsnap {
Some(s) => unsafe { emulator.restore_fast_snapshot(s) }, Some(s) => unsafe { _emulator_modules.qemu().restore_fast_snapshot(s) },
None => {self.fastsnap = Some(emulator.create_fast_snapshot(true));}, None => {self.fastsnap = Some(_emulator_modules.qemu().create_fast_snapshot(true));},
} }
#[cfg(not(feature = "snapshot_fast"))] #[cfg(not(feature = "snapshot_fast"))]
if !self.has_snapshot { if !self.has_snapshot {
@ -94,4 +105,20 @@ where
// unsafe { println!("snapshot pre {}",emu::icount_get_raw()) }; // unsafe { println!("snapshot pre {}",emu::icount_get_raw()) };
} }
fn address_filter(&self) -> &Self::ModuleAddressFilter {
todo!()
}
fn address_filter_mut(&mut self) -> &mut Self::ModuleAddressFilter {
todo!()
}
fn page_filter(&self) -> &Self::ModulePageFilter {
todo!()
}
fn page_filter_mut(&mut self) -> &mut Self::ModulePageFilter {
todo!()
}
} }

View File

@ -18,7 +18,7 @@ use libafl::prelude::State;
use libafl::inputs::Input; use libafl::inputs::Input;
use libafl::feedbacks::Feedback; use libafl::feedbacks::Feedback;
use libafl::common::HasMetadata; use libafl::common::HasMetadata;
use libafl_qemu::edges::QemuEdgesMapMetadata; use libafl_qemu::modules::edges::EdgeCoverageModule;
use libafl::observers::MapObserver; use libafl::observers::MapObserver;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::cmp; use std::cmp;
@ -39,6 +39,8 @@ use libafl::{
use crate::time::clock::QemuClockObserver; use crate::time::clock::QemuClockObserver;
use crate::systemstate::FreeRTOSSystemStateMetadata; use crate::systemstate::FreeRTOSSystemStateMetadata;
use libafl::prelude::StateInitializer;
use std::borrow::Cow; use std::borrow::Cow;
//=========================== Scheduler //=========================== Scheduler
@ -59,7 +61,7 @@ impl<S> TestcaseScore<S> for MaxTimeFavFactor<S>
where where
S: HasCorpus + HasMetadata, S: HasCorpus + HasMetadata,
{ {
fn compute(state: &S, entry: &mut Testcase<<S as UsesInput>::Input>) -> Result<f64, Error> { fn compute(state: &S, entry: &mut Testcase<<S::Corpus as Corpus>::Input> ) -> Result<f64, Error> {
// TODO maybe enforce entry.exec_time().is_some() // TODO maybe enforce entry.exec_time().is_some()
let et = entry.exec_time().expect("testcase.exec_time is needed for scheduler"); let et = entry.exec_time().expect("testcase.exec_time is needed for scheduler");
let tns : i64 = et.as_nanos().try_into().expect("failed to convert time"); let tns : i64 = et.as_nanos().try_into().expect("failed to convert time");
@ -104,23 +106,25 @@ pub struct SortedFeedback {
name: Cow<'static, str> name: Cow<'static, str>
} }
impl<S> StateInitializer<S> for SortedFeedback {}
impl<EM, I, OT, S> Feedback<EM, I, OT, S> for SortedFeedback impl<EM, I, OT, S> Feedback<EM, I, OT, S> for SortedFeedback
where where
S: State + UsesInput + MaybeHasClientPerfMonitor, S: State + UsesInput<Input = I> + MaybeHasClientPerfMonitor,
S::Input: HasTargetBytes, S::Input: HasTargetBytes,
EM: EventFirer<State = S>,
OT: ObserversTuple<I, S>,
{ {
#[allow(clippy::wrong_self_convention)] #[allow(clippy::wrong_self_convention)]
fn is_interesting( fn is_interesting(
&mut self, &mut self,
_state: &mut S, _state: &mut S,
_manager: &mut EM, _manager: &mut EM,
_input: &I, _input: &S::Input,
_observers: &OT, _observers: &OT,
_exit_kind: &ExitKind, _exit_kind: &ExitKind,
) -> Result<bool, Error> ) -> Result<bool, Error>
where where
EM: EventFirer<State = S>,
OT: ObserversTuple<S>,
{ {
let t = _input.target_bytes(); let t = _input.target_bytes();
let tmp = t.as_slice(); let tmp = t.as_slice();
@ -178,9 +182,13 @@ pub struct ExecTimeReachedFeedback
target_time: u64, target_time: u64,
} }
impl<S> StateInitializer<S> for ExecTimeReachedFeedback {}
impl<EM, I, OT, S> Feedback<EM, I, OT, S> for ExecTimeReachedFeedback impl<EM, I, OT, S> Feedback<EM, I, OT, S> for ExecTimeReachedFeedback
where where
S: State + UsesInput + MaybeHasClientPerfMonitor, S: State + UsesInput + MaybeHasClientPerfMonitor,
EM: EventFirer<State = S>,
OT: ObserversTuple<I, S>,
{ {
#[allow(clippy::wrong_self_convention)] #[allow(clippy::wrong_self_convention)]
fn is_interesting( fn is_interesting(
@ -192,8 +200,6 @@ where
_exit_kind: &ExitKind, _exit_kind: &ExitKind,
) -> Result<bool, Error> ) -> Result<bool, Error>
where where
EM: EventFirer<State = S>,
OT: ObserversTuple<S>,
{ {
let observer = observers.match_name::<QemuClockObserver>("clock") let observer = observers.match_name::<QemuClockObserver>("clock")
.expect("QemuClockObserver not found"); .expect("QemuClockObserver not found");
@ -228,9 +234,13 @@ pub struct ExecTimeCollectorFeedback
name: Cow<'static, str> name: Cow<'static, str>
} }
impl<S> StateInitializer<S> for ExecTimeCollectorFeedback {}
impl<EM, I, OT, S> Feedback<EM, I, OT, S> for ExecTimeCollectorFeedback impl<EM, I, OT, S> Feedback<EM, I, OT, S> for ExecTimeCollectorFeedback
where where
S: State + UsesInput + MaybeHasClientPerfMonitor, S: State + UsesInput + MaybeHasClientPerfMonitor,
EM: EventFirer<State = S>,
OT: ObserversTuple<I, S>,
{ {
#[allow(clippy::wrong_self_convention)] #[allow(clippy::wrong_self_convention)]
fn is_interesting( fn is_interesting(
@ -242,8 +252,6 @@ where
_exit_kind: &ExitKind, _exit_kind: &ExitKind,
) -> Result<bool, Error> ) -> Result<bool, Error>
where where
EM: EventFirer<State = S>,
OT: ObserversTuple<S>,
{ {
let observer = observers.match_name::<QemuClockObserver>("clock") let observer = observers.match_name::<QemuClockObserver>("clock")
.expect("QemuClockObserver not found"); .expect("QemuClockObserver not found");
@ -300,9 +308,13 @@ pub struct ExecTimeIncFeedback
last_is_longest: bool last_is_longest: bool
} }
impl<S> StateInitializer<S> for ExecTimeIncFeedback {}
impl<EM, I, OT, S> Feedback<EM, I, OT, S> for ExecTimeIncFeedback impl<EM, I, OT, S> Feedback<EM, I, OT, S> for ExecTimeIncFeedback
where where
S: State + UsesInput + MaybeHasClientPerfMonitor, S: State + UsesInput + MaybeHasClientPerfMonitor,
EM: EventFirer<State = S>,
OT: ObserversTuple<I, S>,
{ {
#[allow(clippy::wrong_self_convention)] #[allow(clippy::wrong_self_convention)]
fn is_interesting( fn is_interesting(
@ -314,8 +326,6 @@ where
_exit_kind: &ExitKind, _exit_kind: &ExitKind,
) -> Result<bool, Error> ) -> Result<bool, Error>
where where
EM: EventFirer<State = S>,
OT: ObserversTuple<S>,
{ {
let observer = observers.match_name::<QemuClockObserver>("clocktime") let observer = observers.match_name::<QemuClockObserver>("clocktime")
.expect("QemuClockObserver not found"); .expect("QemuClockObserver not found");
@ -333,7 +343,7 @@ where
_state: &mut S, _state: &mut S,
_manager: &mut EM, _manager: &mut EM,
observers: &OT, observers: &OT,
testcase: &mut Testcase<<S as UsesInput>::Input>, testcase: &mut Testcase<I>,
) -> Result<(), Error> { ) -> Result<(), Error> {
#[cfg(feature = "feed_afl")] #[cfg(feature = "feed_afl")]
if self.last_is_longest { if self.last_is_longest {
@ -370,9 +380,14 @@ pub struct AlwaysTrueFeedback
name: Cow<'static, str> name: Cow<'static, str>
} }
impl<S> StateInitializer<S> for AlwaysTrueFeedback {}
impl<EM, I, OT, S> Feedback<EM, I, OT, S> for AlwaysTrueFeedback impl<EM, I, OT, S> Feedback<EM, I, OT, S> for AlwaysTrueFeedback
where where
S: State + UsesInput + MaybeHasClientPerfMonitor, S: State + UsesInput + MaybeHasClientPerfMonitor,
EM: EventFirer<State = S>,
OT: ObserversTuple<I, S>,
{ {
#[allow(clippy::wrong_self_convention)] #[allow(clippy::wrong_self_convention)]
fn is_interesting( fn is_interesting(
@ -384,8 +399,6 @@ where
_exit_kind: &ExitKind, _exit_kind: &ExitKind,
) -> Result<bool, Error> ) -> Result<bool, Error>
where where
EM: EventFirer<State = S>,
OT: ObserversTuple<S>,
{ {
Ok(true) Ok(true)
} }
@ -425,11 +438,15 @@ where
phantom: PhantomData<S>, phantom: PhantomData<S>,
} }
// impl<S> UsesState for TimeProbMassScheduler<S> {
// type State = S;
// }
impl<S> TestcaseScore<S> for TimeProbFactor<S> impl<S> TestcaseScore<S> for TimeProbFactor<S>
where where
S: HasCorpus + HasMetadata, S: HasCorpus + HasMetadata,
{ {
fn compute(_state: &S, entry: &mut Testcase<<S as UsesInput>::Input>) -> Result<f64, Error> { fn compute(_state: &S, entry: &mut Testcase<<S::Corpus as Corpus>::Input>) -> Result<f64, Error> {
// TODO maybe enforce entry.exec_time().is_some() // TODO maybe enforce entry.exec_time().is_some()
let et = entry.exec_time().expect("testcase.exec_time is needed for scheduler"); let et = entry.exec_time().expect("testcase.exec_time is needed for scheduler");
let tns : i64 = et.as_nanos().try_into().expect("failed to convert time"); let tns : i64 = et.as_nanos().try_into().expect("failed to convert time");

View File

@ -0,0 +1,6 @@
use paste::paste;
use crate::extern_c_checked;
extern_c_checked!(
pub fn icount_get_raw() -> u64;
);

View File

@ -16,6 +16,7 @@ use crate::qemu::{
CrashHookClosure, CrashHookFn, PostSyscallHookClosure, PostSyscallHookFn, CrashHookClosure, CrashHookFn, PostSyscallHookClosure, PostSyscallHookFn,
PreSyscallHookClosure, PreSyscallHookFn, PreSyscallHookClosure, PreSyscallHookFn,
}; };
use crate::{JmpExecHook, JmpGenHook};
use crate::{ use crate::{
cpu_run_post_exec_hook_wrapper, cpu_run_pre_exec_hook_wrapper, cpu_run_post_exec_hook_wrapper, cpu_run_pre_exec_hook_wrapper,
modules::{EmulatorModule, EmulatorModuleTuple}, modules::{EmulatorModule, EmulatorModuleTuple},
@ -765,23 +766,8 @@ where
pub fn jmps( pub fn jmps(
&mut self, &mut self,
generation_hook: Hook< generation_hook: JmpGenHook<ET, S>,
fn(&mut Self, Option<&mut S>, src: GuestAddr, dest: GuestAddr) -> Option<u64>, execution_hook: JmpExecHook<ET, S>,
Box<
dyn for<'a> FnMut(
&'a mut Self,
Option<&'a mut S>,
GuestAddr,
GuestAddr,
) -> Option<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),
>,
) -> JmpHookId { ) -> JmpHookId {
unsafe { unsafe {
let gen = get_raw_hook!( let gen = get_raw_hook!(
@ -1162,6 +1148,14 @@ where
) -> NewThreadHookId { ) -> NewThreadHookId {
self.hooks.thread_creation_closure(hook) self.hooks.thread_creation_closure(hook)
} }
pub fn jmps(
&mut self,
generation_hook: JmpGenHook<ET, S>,
execution_hook: JmpExecHook<ET, S>,
) -> JmpHookId {
self.hooks.jmps(generation_hook, execution_hook)
}
} }
impl<ET, S> EmulatorModules<ET, S> impl<ET, S> EmulatorModules<ET, S>