diff --git a/fuzzers/FRET/benchmark/Snakefile b/fuzzers/FRET/benchmark/Snakefile index 431b2e40b8..c2497da43b 100644 --- a/fuzzers/FRET/benchmark/Snakefile +++ b/fuzzers/FRET/benchmark/Snakefile @@ -141,8 +141,8 @@ rule run_bench: export RUST_BACKTRACE=1 mkdir -p $(dirname {output[0]}) set +e - echo $(pwd)/{input[1]}/release/fret -n $(pwd)/timedump/{wildcards.fuzzer}/{wildcards.target}#{wildcards.num} -s {select_task} -t -a -g -k {input[0]} -c ./target_symbols.csv fuzz --random -t {RUNTIME} -s {wildcards.num} - $(pwd)/{input[1]}/release/fret -n $(pwd)/timedump/{wildcards.fuzzer}/{wildcards.target}#{wildcards.num} -s {select_task} -t -a -g -k {input[0]} -c ./target_symbols.csv fuzz --random -t {RUNTIME} -s {wildcards.num} > {output[1]} 2>&1 + echo $(pwd)/{input[1]}/release/fret -n $(pwd)/timedump/{wildcards.fuzzer}/{wildcards.target}#{wildcards.num} -s {select_task} -t -a -r -g -k {input[0]} -c ./target_symbols.csv fuzz --random -t {RUNTIME} -s {wildcards.num} + $(pwd)/{input[1]}/release/fret -n $(pwd)/timedump/{wildcards.fuzzer}/{wildcards.target}#{wildcards.num} -s {select_task} -t -a -r -g -k {input[0]} -c ./target_symbols.csv fuzz --random -t {RUNTIME} -s {wildcards.num} > {output[1]} 2>&1 exit 0 """ else: @@ -150,8 +150,8 @@ rule run_bench: export RUST_BACKTRACE=1 mkdir -p $(dirname {output[0]}) set +e - echo $(pwd)/{input[1]}/release/fret -n $(pwd)/timedump/{wildcards.fuzzer}/{wildcards.target}#{wildcards.num} -s {select_task} -t -a -g -k {input[0]} -c ./target_symbols.csv fuzz -t {RUNTIME} -s {wildcards.num} - $(pwd)/{input[1]}/release/fret -n $(pwd)/timedump/{wildcards.fuzzer}/{wildcards.target}#{wildcards.num} -s {select_task} -t -a -g -k {input[0]} -c ./target_symbols.csv fuzz -t {RUNTIME} -s {wildcards.num} > {output[1]} 2>&1 + echo $(pwd)/{input[1]}/release/fret -n $(pwd)/timedump/{wildcards.fuzzer}/{wildcards.target}#{wildcards.num} -s {select_task} -t -a -r -g -k {input[0]} -c ./target_symbols.csv fuzz -t {RUNTIME} -s {wildcards.num} + $(pwd)/{input[1]}/release/fret -n $(pwd)/timedump/{wildcards.fuzzer}/{wildcards.target}#{wildcards.num} -s {select_task} -t -a -r -g -k {input[0]} -c ./target_symbols.csv fuzz -t {RUNTIME} -s {wildcards.num} > {output[1]} 2>&1 exit 0 """ shell(script) diff --git a/fuzzers/FRET/src/systemstate/feedbacks.rs b/fuzzers/FRET/src/systemstate/feedbacks.rs index e63801ea98..cefbee1e63 100644 --- a/fuzzers/FRET/src/systemstate/feedbacks.rs +++ b/fuzzers/FRET/src/systemstate/feedbacks.rs @@ -56,11 +56,11 @@ where where { match &self.dumpfile { Some(s) => { - let time_has_come = self.last_dump.map(|t| Instant::now()-t > Duration::from_secs(60)).unwrap_or(true); + let time_has_come = self.last_dump.map(|t| Instant::now()-t > Duration::from_secs(1200)).unwrap_or(true); if time_has_come { self.last_dump = Some(Instant::now()); // Try dumping the worst case - let casename = s.with_extension(format!("at_{}h.case", (Instant::now()-self.init_time).as_secs()/60)); + let casename = s.with_extension(format!("at_{}h.case", (Instant::now()-self.init_time).as_secs()/3600)); let corpus = state.corpus(); let mut worst = Duration::new(0,0); let mut worst_input = None; diff --git a/fuzzers/FRET/src/systemstate/helpers.rs b/fuzzers/FRET/src/systemstate/helpers.rs index f49bd0a39d..4cd1eddcae 100644 --- a/fuzzers/FRET/src/systemstate/helpers.rs +++ b/fuzzers/FRET/src/systemstate/helpers.rs @@ -1,10 +1,13 @@ use hashbrown::HashMap; use libafl_bolts::prelude::{SerdeAny, SerdeAnyMap}; use libafl_qemu::{elf::EasyElf, read_user_reg_unchecked, GuestAddr, GuestPhysAddr}; -use std::ops::Range; use std::cmp::min; +use std::ops::Range; -use crate::{fuzzer::{DO_NUM_INTERRUPT, FIRST_INT}, time::clock::QEMU_ISNS_PER_USEC}; +use crate::{ + fuzzer::{DO_NUM_INTERRUPT, FIRST_INT}, + time::clock::QEMU_ISNS_PER_USEC, +}; use super::ExecInterval; @@ -99,39 +102,47 @@ pub fn get_icount(emulator: &libafl_qemu::Qemu) -> u64 { } } -pub fn input_bytes_to_interrupt_times(buf: &[u8], config: (usize,u32)) -> Vec { +pub fn input_bytes_to_interrupt_times(buf: &[u8], config: (usize, u32)) -> Vec { let len = buf.len(); let mut start_tick; - let mut ret = Vec::with_capacity(min(DO_NUM_INTERRUPT, len/4)); + let mut ret = Vec::with_capacity(min(DO_NUM_INTERRUPT, len / 4)); for i in 0..DO_NUM_INTERRUPT { - let mut buf4b : [u8; 4] = [0,0,0,0]; - if len >= (i+1)*4 { + let mut buf4b: [u8; 4] = [0, 0, 0, 0]; + if len >= (i + 1) * 4 { for j in 0usize..4usize { - buf4b[j]=buf[i*4+j]; + buf4b[j] = buf[i * 4 + j]; } start_tick = u32::from_le_bytes(buf4b); - if start_tick < FIRST_INT {start_tick=0;} + if start_tick < FIRST_INT { + start_tick = 0; + } ret.push(start_tick); - } else {break;} + } else { + break; + } } ret.sort_unstable(); // obey the minimum inter arrival time while maintaining the sort for i in 0..ret.len() { - if ret[i]==0 {continue;} - for j in i+1..ret.len() { - if ret[j]-ret[i] < config.1 * QEMU_ISNS_PER_USEC { + if ret[i] == 0 { + continue; + } + for j in i + 1..ret.len() { + if ret[j] - ret[i] < config.1 * QEMU_ISNS_PER_USEC { // ret[j] = u32::saturating_add(ret[i],config.1 * QEMU_ISNS_PER_USEC); ret[j] = 0; // remove the interrupt ret.sort_unstable(); break; - } else {break;} + } else { + break; + } } } ret } pub fn interrupt_times_to_input_bytes(interrupt_times: &[u32]) -> Vec { - let mut ret = Vec::with_capacity(interrupt_times.len()*4); + let mut ret = Vec::with_capacity(interrupt_times.len() * 4); for i in interrupt_times { ret.extend(u32::to_le_bytes(*i)); } @@ -178,21 +189,57 @@ where } } - /// Build an ABB-profile from a stretch of intervals -/// returns mapping: task_name -> (abb_addr -> (interval_count, exec_count, exec_time)) +/// returns mapping: task_name -> (abb_addr -> (interval_count, exec_count, exec_time, woet)) #[allow(unused)] pub fn abb_profile( mut intervals: Vec, -) -> HashMap> { - let mut ret: HashMap> = HashMap::new(); +) -> HashMap> { + let mut ret: HashMap> = HashMap::new(); intervals.sort_by_key(|x| x.get_task_name_unchecked()); intervals .chunk_by_mut(|x, y| x.get_task_name_unchecked() == y.get_task_name_unchecked()) - .for_each(|x| { - x.sort_by_key(|y| y.abb.as_ref().unwrap().start); - x.chunk_by(|y, z| y.abb.as_ref().unwrap().start == z.abb.as_ref().unwrap().start) - .for_each(|y| match ret.get_mut(&y[0].get_task_name_unchecked()) { + // Iterate over all tasks + .for_each(|intv_of_task| { + // Iterate over all intervals of this task + intv_of_task.sort_by_key(|y| y.abb.as_ref().unwrap().start); + // Iterate over each abb of this task + let mut inter_per_abb_of_task: Vec<&mut [ExecInterval]> = intv_of_task + .chunk_by_mut(|y, z| y.abb.as_ref().unwrap().start == z.abb.as_ref().unwrap().start) + .collect(); + // arrange the abbs by their start address + inter_per_abb_of_task + .iter_mut() + .for_each(|ivs_of_abb_of_task| { + ivs_of_abb_of_task.sort_by_key(|y| y.abb.as_ref().unwrap().instance_id) + }); + // find the woet for this abb + let abb_woet: HashMap = inter_per_abb_of_task + .iter() + .map(|ivs_of_abb_of_task| { + // group intervals by id, sum up the exec time of the abb instance + ivs_of_abb_of_task + .chunk_by( + |y, z| { + y.abb.as_ref().unwrap().instance_id + == z.abb.as_ref().unwrap().instance_id + }, + ) + .map(|intv_of_abb_with_id| { + ( + intv_of_abb_with_id[0].abb.as_ref().unwrap().start, + intv_of_abb_with_id + .iter() + .map(|z| z.get_exec_time()) + .sum::<_>(), + ) + }) + .max_by_key(|x| x.1) + .unwrap() + }) + .collect(); + inter_per_abb_of_task.into_iter().for_each(|y| { + match ret.get_mut(&y[0].get_task_name_unchecked()) { Option::None => { ret.insert( y[0].get_task_name_unchecked(), @@ -202,6 +249,7 @@ pub fn abb_profile( y.len(), y.iter().filter(|x| x.is_abb_end()).count(), y.iter().map(|z| z.get_exec_time()).sum::<_>(), + abb_woet[&y[0].abb.as_ref().unwrap().start], ), )]), ); @@ -213,15 +261,16 @@ pub fn abb_profile( y.len(), y.iter().filter(|x| x.is_abb_end()).count(), y.iter().map(|z| z.get_exec_time()).sum(), + abb_woet[&y[0].abb.as_ref().unwrap().start], ), ); } - }); + } + }); }); ret } - pub fn unmut(x: &mut T) -> &T { &(*x) } diff --git a/fuzzers/FRET/src/systemstate/target_os/mod.rs b/fuzzers/FRET/src/systemstate/target_os/mod.rs index 82958ac0f9..67b8df6cff 100644 --- a/fuzzers/FRET/src/systemstate/target_os/mod.rs +++ b/fuzzers/FRET/src/systemstate/target_os/mod.rs @@ -77,16 +77,15 @@ pub trait SystemTraceData: Serialize + Sized + for<'a> Deserialize<'a> + Default #[inline] /// extract computation time spent in each task and abb - /// task_name -> (abb_addr -> (interval_count, exec_count, exec_time)) + /// task_name -> (abb_addr -> (interval_count, exec_count, exec_time, woet)) fn select_abb_profile( &self, select_task: Option, - ) -> HashMap> { + ) -> HashMap> { if let Some(select_task) = select_task.as_ref() { // Task selected, only profile this task - if let Some(worst_instance) = self - .worst_jobs_per_task_by_response_time() - .get(select_task) + let wjptybrt = self.worst_jobs_per_task_by_response_time(); + if let Some(worst_instance) = wjptybrt.get(select_task) { let t: Vec<_> = self .intervals()