diff --git a/fuzzers/FRET/benchmark/.gitignore b/fuzzers/FRET/benchmark/.gitignore index 8ae16ec83e..0a356bac3c 100644 --- a/fuzzers/FRET/benchmark/.gitignore +++ b/fuzzers/FRET/benchmark/.gitignore @@ -1,7 +1,8 @@ -timedump +*dump +timedump* corpora build mnt .R* *.png -*.pdf \ No newline at end of file +*.pdf diff --git a/fuzzers/FRET/src/clock.rs b/fuzzers/FRET/src/clock.rs index c9987c67e1..131b66b85b 100644 --- a/fuzzers/FRET/src/clock.rs +++ b/fuzzers/FRET/src/clock.rs @@ -11,10 +11,10 @@ use libafl::{ observers::{Observer,VariableMapObserver}, state::{StdState, HasNamedMetadata}, Error, - observers::ObserversTuple, prelude::UsesInput, + observers::ObserversTuple, prelude::UsesInput, impl_serdeany, }; use serde::{Deserialize, Serialize}; -use std::{cell::UnsafeCell, cmp::max}; +use std::{cell::UnsafeCell, cmp::max, env, fs::OpenOptions, io::Write}; use libafl::bolts::tuples::Named; use libafl_qemu::{ @@ -82,9 +82,11 @@ impl Default for MaxIcountMetadata { } } -//========== Observer +/// A piece of metadata tracking all icounts +#[derive(Debug, SerdeAny, Serialize, Deserialize)] +pub struct IcHist(pub Vec); -pub static mut ICOUNT_HISTORY : Vec = vec![]; +//========== Observer /// A simple observer, just overlooking the runtime of the target. #[derive(Serialize, Deserialize, Debug, Clone)] @@ -114,7 +116,7 @@ impl QemuClockObserver { impl Observer for QemuClockObserver where - S: UsesInput, + S: UsesInput + HasMetadata, { fn pre_exec(&mut self, _state: &mut S, _input: &S::Input) -> Result<(), Error> { // Only remember the pre-run ticks if presistent mode ist used @@ -133,7 +135,32 @@ where unsafe { self.end_tick = emu::icount_get_raw() }; // println!("clock post {}", self.end_tick); // println!("Number of Ticks: {} <- {} {}",self.end_tick - self.start_tick, self.end_tick, self.start_tick); - unsafe { ICOUNT_HISTORY.push(self.end_tick - self.start_tick) }; + let metadata =_state.metadata_mut(); + let hist = metadata.get_mut::(); + match hist { + None => { + metadata.insert(IcHist(vec![self.end_tick - self.start_tick])); + } + Some(v) => { + v.0.push(self.end_tick - self.start_tick); + if v.0.len() >= 1000 { + if let Ok(td) = env::var("TIME_DUMP") { + let mut file = OpenOptions::new() + .read(true) + .write(true) + .create(true) + .append(true) + .open(td).expect("Could not open timedump"); + for i in std::mem::take(&mut v.0).into_iter() { + writeln!(file, "{}", i).expect("Write to dump failed"); + } + } else { + // If we don't write out values we don't need to remember them at all + v.0.clear(); + } + } + } + } Ok(()) } } @@ -167,7 +194,7 @@ pub struct ClockTimeFeedback { impl Feedback for ClockTimeFeedback where - S: UsesInput + HasClientPerfMonitor, + S: UsesInput + HasClientPerfMonitor + HasMetadata, { #[allow(clippy::wrong_self_convention)] fn is_interesting( diff --git a/fuzzers/FRET/src/fuzzer.rs b/fuzzers/FRET/src/fuzzer.rs index 45be58c1f2..1e05eca309 100644 --- a/fuzzers/FRET/src/fuzzer.rs +++ b/fuzzers/FRET/src/fuzzer.rs @@ -26,7 +26,7 @@ use libafl::{ observers::{VariableMapObserver}, schedulers::{IndexesLenTimeMinimizerScheduler, QueueScheduler}, stages::StdMutationalStage, - state::{HasCorpus, StdState}, + state::{HasCorpus, StdState, HasMetadata}, Error, prelude::{SimpleMonitor, SimpleEventManager, AsMutSlice, RandBytesGenerator, Generator, SimpleRestartingEventManager}, Evaluator, }; @@ -35,7 +35,7 @@ use libafl_qemu::{ QemuHooks, Regs, QemuInstrumentationFilter, GuestAddr, }; use crate::{ - clock::{QemuClockObserver, ClockTimeFeedback, QemuClockIncreaseFeedback, ICOUNT_HISTORY}, + clock::{QemuClockObserver, ClockTimeFeedback, QemuClockIncreaseFeedback, IcHist}, qemustate::QemuStateRestoreHelper, systemstate::{helpers::QemuSystemStateHelper, observers::QemuSystemStateObserver, feedbacks::{DumpSystraceFeedback, NovelSystemStateFeedback}}, worst::{TimeMaximizerCorpusScheduler, ExecTimeIncFeedback, TimeStateMaximizerCorpusScheduler}, }; @@ -360,10 +360,10 @@ pub fn fuzz() { .read(true) .write(true) .create(true) - .append(false) + .append(true) .open(td).expect("Could not open timedump"); - unsafe { - for i in ICOUNT_HISTORY.iter() { + if let Some(ichist) = state.metadata().get::() { + for i in ichist.0.iter() { writeln!(file, "{}", i).expect("Write to dump failed"); } } @@ -400,24 +400,24 @@ pub fn fuzz() { #[cfg(feature = "singlecore")] { let monitor = SimpleMonitor::new(|s| println!("{}", s)); - let mgr = SimpleEventManager::new(monitor); - run_client(None, mgr, 0); + // let mgr = SimpleEventManager::new(monitor); + // run_client(None, mgr, 0); - // let mut shmem_provider = StdShMemProvider::new().unwrap(); - // let (state, mut mgr) = match SimpleRestartingEventManager::launch(monitor, &mut shmem_provider) - // { - // // The restarting state will spawn the same process again as child, then restarted it each time it crashes. - // Ok(res) => res, - // Err(err) => match err { - // Error::ShuttingDown => { - // return; - // } - // _ => { - // panic!("Failed to setup the restarter: {}", err); - // } - // }, - // }; - // run_client(state, mgr, 0); + let mut shmem_provider = StdShMemProvider::new().unwrap(); + let (state, mut mgr) = match SimpleRestartingEventManager::launch(monitor, &mut shmem_provider) + { + // The restarting state will spawn the same process again as child, then restarted it each time it crashes. + Ok(res) => res, + Err(err) => match err { + Error::ShuttingDown => { + return; + } + _ => { + panic!("Failed to setup the restarter: {}", err); + } + }, + }; + run_client(state, mgr, 0); } // else -> multicore #[cfg(not(feature = "singlecore"))]