diff --git a/fuzzers/FRET/Cargo.toml b/fuzzers/FRET/Cargo.toml index 93d9b2d32b..bd58cb2e76 100644 --- a/fuzzers/FRET/Cargo.toml +++ b/fuzzers/FRET/Cargo.toml @@ -1,32 +1,42 @@ [package] name = "fret" version = "0.8.2" -authors = ["Andrea Fioraldi ", "Dominik Maier "] +authors = ["Alwin Berger "] edition = "2021" [features] -default = ["std", "snapshot_restore", "singlecore", "restarting", "feed_systemtrace", "fuzz_int", "do_hash_notify_state" ] +default = ["std", "snapshot_restore", "singlecore", "restarting", "do_hash_notify_state", "config_stg" ] std = [] +# Exec environemnt basics snapshot_restore = [] snapshot_fast = [ "snapshot_restore" ] singlecore = [] restarting = ['singlecore'] -trace_abbs = [] -systemstate = [] -feed_systemgraph = [ "systemstate" ] -feed_systemtrace = [ "systemstate" ] -feed_stg = [ "systemstate", "trace_abbs" ] +run_until_saturation = [] +fuzz_int = [] +# information capture +observe_edges = [] # observe cfg edges +observe_hitcounts = [ "observe_edges" ] # reduces edge granularity +observe_systemstate = [] +do_hash_notify_state = [] +trace_stg = [ "observe_systemstate" ] +# feedbacks +feed_stg = [ "trace_stg", "observe_systemstate" ] feed_longest = [ ] feed_afl = [ ] -feed_genetic = [ ] -fuzz_int = [ ] +feed_genetic = [] gensize_1 = [ ] gensize_10 = [ ] gensize_100 = [ ] -observer_hitcounts = [] -do_hash_notify_state = [] -count_iterations = [] -run_until_saturation = [] +# schedulers +sched_genetic = [] +sched_afl = [] +sched_stg = [] +# overall_configs +config_genetic = ["gensize_100","feed_genetic","sched_genetic"] +config_afl = ["feed_afl","sched_afl"] +config_frafl = ["feed_afl","sched_afl","feed_longest"] +config_stg = ["feed_stg","sched_stg"] [profile.release] lto = true diff --git a/fuzzers/FRET/src/fuzzer.rs b/fuzzers/FRET/src/fuzzer.rs index c1b3b04148..1e25134e63 100644 --- a/fuzzers/FRET/src/fuzzer.rs +++ b/fuzzers/FRET/src/fuzzer.rs @@ -14,7 +14,7 @@ use libafl_qemu::{ }; use rand::{SeedableRng, StdRng, Rng}; use crate::{ - clock::{ClockTimeFeedback, IcHist, QemuClockIncreaseFeedback, QemuClockObserver, FUZZ_START_TIMESTAMP}, mutational::{InterruptShiftStage, MINIMUM_INTER_ARRIVAL_TIME}, qemustate::QemuStateRestoreHelper, systemstate::{self, feedbacks::{DumpSystraceFeedback, NovelSystemStateFeedback}, graph::{GraphMaximizerCorpusScheduler, SysGraphFeedbackState, SysMapFeedback}, helpers::{QemuSystemStateHelper, ISR_SYMBOLS}, observers::QemuSystemStateObserver, schedulers::{GenerationScheduler, LongestTraceScheduler}, stg::{stg_map_mut_slice, STGEdge, STGNode, StgFeedback, MAX_STG_NUM}}, worst::{AlwaysTrueFeedback, ExecTimeIncFeedback, TimeMaximizerCorpusScheduler, TimeStateMaximizerCorpusScheduler} + clock::{ClockTimeFeedback, IcHist, QemuClockIncreaseFeedback, QemuClockObserver, FUZZ_START_TIMESTAMP}, mutational::{InterruptShiftStage, MINIMUM_INTER_ARRIVAL_TIME}, qemustate::QemuStateRestoreHelper, systemstate::{self, feedbacks::{DumpSystraceFeedback, NovelSystemStateFeedback}, stg::{GraphMaximizerCorpusScheduler}, helpers::{QemuSystemStateHelper, ISR_SYMBOLS}, observers::QemuSystemStateObserver, schedulers::{GenerationScheduler, LongestTraceScheduler}, stg::{stg_map_mut_slice, STGEdge, STGNode, StgFeedback, MAX_STG_NUM}}, worst::{AlwaysTrueFeedback, ExecTimeIncFeedback, TimeMaximizerCorpusScheduler, TimeStateMaximizerCorpusScheduler} }; use std::time::{SystemTime, UNIX_EPOCH}; use clap::{Parser, Subcommand}; @@ -221,32 +221,15 @@ macro_rules! do_dump_times { }; } -/// Takes a state and a bool, writes out the current graph -macro_rules! do_dump_graph { - ($state:expr, $cli:expr, $c:expr) => { - #[cfg(feature = "feed_systemgraph")] - if $cli.dump_graph { - let dump_path = $cli.dump_name.clone().unwrap().with_extension(if $c=="" {"graph"} else {$c}); - println!("Dumping graph to {:?}", &dump_path); - if let Some(md) = $state.named_metadata_map_mut().get_mut::("SysMap") { - let out = md.graph.map(|i,x| x.pretty_print(), |_,_| ""); - let outs = Dot::with_config(&out, &[Config::EdgeNoLabel]).to_string(); - let outs = outs.replace(';',"\\n"); - fs::write(dump_path,outs).expect("Failed to write graph"); - } - } - }; -} - /// Takes a state and a bool, writes out the current graph macro_rules! do_dump_stg { ($state:expr, $cli:expr, $c:expr) => { - #[cfg(feature = "trace_abbs")] + #[cfg(feature = "trace_stg")] if $cli.dump_graph { let dump_path = $cli.dump_name.clone().unwrap().with_extension(if $c=="" {"stg"} else {$c}); println!("Dumping graph to {:?}", &dump_path); if let Some(md) = $state.named_metadata_map_mut().get_mut::("stgfeedbackstate") { - let out = md.graph.map(|i,x| x.color_print(), |i,x| x.color_print()); + let out = md.graph.map(|_i,x| x.color_print(), |_i,x| x.color_print()); let outs = Dot::with_config(&out, &[]).to_string(); let outs = outs.replace("\\\"","\""); let outs = outs.replace(';',"\\n"); @@ -341,43 +324,34 @@ pub fn fuzz() { let input_length_ptr = try_load_symbol(&elf, &env::var("FUZZ_LENGTH").unwrap_or_else(|_| "FUZZ_LENGTH".to_owned()), true); let input_counter_ptr = try_load_symbol(&elf, &env::var("FUZZ_POINTER").unwrap_or_else(|_| "FUZZ_POINTER".to_owned()), true); - #[cfg(feature = "systemstate")] - let curr_tcb_pointer = elf // loads to the address specified in elf, without respecting program headers - .resolve_symbol("pxCurrentTCB", 0) - .expect("Symbol pxCurrentTCBC not found"); - // let curr_tcb_pointer = virt2phys(curr_tcb_pointer,&elf); - #[cfg(feature = "systemstate")] + #[cfg(feature = "observe_systemstate")] + let curr_tcb_pointer = load_symbol(&elf, "pxCurrentTCB", false); // loads to the address specified in elf, without respecting program headers + #[cfg(feature = "observe_systemstate")] println!("TCB pointer at {:#x}", curr_tcb_pointer); - #[cfg(feature = "systemstate")] + #[cfg(feature = "observe_systemstate")] let task_queue_addr = load_symbol(&elf, "pxReadyTasksLists", false); + #[cfg(feature = "observe_systemstate")] let task_delay_addr = load_symbol(&elf, "pxDelayedTaskList", false); + #[cfg(feature = "observe_systemstate")] let task_delay_overflow_addr = load_symbol(&elf, "pxOverflowDelayedTaskList", false); + #[cfg(feature = "observe_systemstate")] let scheduler_lock = load_symbol(&elf, "uxSchedulerSuspended", false); + #[cfg(feature = "observe_systemstate")] let scheduler_running = load_symbol(&elf, "xSchedulerRunning", false); + #[cfg(feature = "observe_systemstate")] let critical_section = load_symbol(&elf, "uxCriticalNesting", false); - // let task_queue_addr = virt2phys(task_queue_addr,&elf.goblin()); - #[cfg(feature = "systemstate")] - println!("Task Queue at {:#x}", task_queue_addr); - // #[cfg(feature = "systemstate")] - // let svh = load_symbol(&elf, "xPortPendSVHandler", false); - // let svh=virt2phys(svh, &elf); - // let svh = elf - // .resolve_symbol("vPortEnterCritical", 0) - // .expect("Symbol vPortEnterCritical not found"); - #[cfg(feature = "systemstate")] + #[cfg(feature = "observe_systemstate")] let app_start = load_symbol(&elf, "__APP_CODE_START__", false); - #[cfg(feature = "systemstate")] + #[cfg(feature = "observe_systemstate")] let app_end = load_symbol(&elf, "__APP_CODE_END__", false); - #[cfg(feature = "systemstate")] + #[cfg(feature = "observe_systemstate")] let app_range = app_start..app_end; - #[cfg(feature = "systemstate")] + #[cfg(feature = "observe_systemstate")] let api_start = load_symbol(&elf, "__API_CODE_START__", false); - #[cfg(feature = "systemstate")] + #[cfg(feature = "observe_systemstate")] let api_end = load_symbol(&elf, "__API_CODE_END__", false); - #[cfg(feature = "systemstate")] + #[cfg(feature = "observe_systemstate")] let api_range = api_start..api_end; - #[cfg(feature = "systemstate")] - dbg!(app_range.clone()); let breakpoint = elf .resolve_symbol( @@ -399,15 +373,15 @@ pub fn fuzz() { unsafe {RNG_SEED = str::parse::(&seed).expect("SEED_RANDOM must be an integer.");} } - #[cfg(feature = "systemstate")] + #[cfg(feature = "observe_systemstate")] let mut api_ranges = get_all_fn_symbol_ranges(&elf, api_range); - #[cfg(feature = "systemstate")] + #[cfg(feature = "observe_systemstate")] let mut isr_ranges : HashMap> = systemstate::helpers::ISR_SYMBOLS.iter().filter_map(|x| (api_ranges.get(&x.to_string()).map(|y| (x.to_string(),y.clone())))).collect(); - #[cfg(feature = "systemstate")] + #[cfg(feature = "observe_systemstate")] let mut isr_addreses : HashMap = systemstate::helpers::ISR_SYMBOLS.iter().filter_map(|x| (api_ranges.remove(&x.to_string()).map(|y| (y.start,x.to_string())))).collect(); - #[cfg(feature = "systemstate")] + #[cfg(feature = "observe_systemstate")] for i in systemstate::helpers::ISR_SYMBOLS { if isr_ranges.get(&i.to_string()).is_none() { if let Some(fr) = get_function_range(&elf, i) { @@ -417,12 +391,12 @@ pub fn fuzz() { } } - #[cfg(feature = "systemstate")] + #[cfg(feature = "observe_systemstate")] let api_addreses : HashMap = api_ranges.iter().map(|(k,v)| (v.start,k.clone())).collect(); - #[cfg(feature = "systemstate")] + #[cfg(feature = "observe_systemstate")] let api_ranges : Vec<_> = api_ranges.into_iter().collect(); - #[cfg(feature = "systemstate")] + #[cfg(feature = "observe_systemstate")] let isr_ranges : Vec<_> = isr_ranges.into_iter().collect(); // Client setup ================================================================================ @@ -519,7 +493,11 @@ pub fn fuzz() { } }; + // Create an observation channel to keep track of the execution time + let clock_time_observer = QemuClockObserver::new("clocktime", if cli.dump_times {cli.dump_name.clone().map(|x| x.with_extension("time"))} else {None} ); + // Create an observation channel using the coverage map + #[cfg(feature = "observe_edges")] let edges_observer = unsafe { VariableMapObserver::from_mut_slice( "edges", edges_map_mut_slice(), @@ -528,17 +506,14 @@ pub fn fuzz() { #[cfg(feature = "observer_hitcounts")] let edges_observer = HitcountsMapObserver::new(edges_observer); - // #[cfg(feature = "feed_stg")] - let stg_observer = unsafe { VariableMapObserver::from_mut_slice( + #[cfg(feature = "feed_stg")] + let stg_coverage_observer = unsafe { VariableMapObserver::from_mut_slice( "stg", stg_map_mut_slice(), addr_of_mut!(MAX_STG_NUM) )}; - // Create an observation channel to keep track of the execution time - let clock_time_observer = QemuClockObserver::new("clocktime", if cli.dump_times {cli.dump_name.clone().map(|x| x.with_extension("time"))} else {None} ); - - #[cfg(feature = "systemstate")] + #[cfg(feature = "observe_systemstate")] let systemstate_observer = QemuSystemStateObserver::new(); // Feedback to rate the interestingness of an input @@ -565,12 +540,12 @@ pub fn fuzz() { // Feedback to reward any input which increses the execution time ExecTimeIncFeedback::new() ); - #[cfg(all(feature = "systemstate"))] + #[cfg(all(feature = "observe_systemstate"))] let mut feedback = feedback_or!( feedback, DumpSystraceFeedback::with_dump(if cli.dump_traces {cli.dump_name.clone().map(|x| x.with_extension("trace.ron"))} else {None}) ); - #[cfg(feature = "systemstate")] + #[cfg(feature = "trace_stg")] let mut feedback = feedback_or!( feedback, StgFeedback::default() @@ -578,18 +553,7 @@ pub fn fuzz() { #[cfg(feature = "feed_stg")] let mut feedback = feedback_or!( feedback, - MaxMapFeedback::tracking(&stg_observer, true, true) - ); - #[cfg(feature = "feed_systemtrace")] - let mut feedback = feedback_or!( - feedback, - // AlwaysTrueFeedback::new(), - NovelSystemStateFeedback::default() - ); - #[cfg(feature = "feed_systemgraph")] - let mut feedback = feedback_or!( - feedback, - SysMapFeedback::default() + MaxMapFeedback::tracking(&stg_coverage_observer, true, true) ); // A feedback to choose if an input is a solution or not @@ -615,36 +579,33 @@ pub fn fuzz() { }); // A minimization+queue policy to get testcasess from the corpus - #[cfg(not(any(feature = "feed_afl",feature = "feed_systemgraph",feature = "feed_systemtrace", feature = "feed_genetic")))] - let scheduler = QueueScheduler::new(); - #[cfg(all(feature = "feed_afl",not(any(feature = "feed_systemgraph",feature = "feed_systemtrace"))))] + #[cfg(not(any(feature = "sched_afl", feature = "sched_stg", feature = "sched_genetic")))] + let scheduler = QueueScheduler::new(); // fallback + #[cfg(feature = "sched_afl",)] let scheduler = TimeMaximizerCorpusScheduler::new(QueueScheduler::new()); - #[cfg(feature = "feed_systemtrace")] - let scheduler = LongestTraceScheduler::new(TimeStateMaximizerCorpusScheduler::new(QueueScheduler::new())); - #[cfg(feature = "feed_systemgraph")] + #[cfg(feature = "sched_stg")] let scheduler = GraphMaximizerCorpusScheduler::new(QueueScheduler::new()); - #[cfg(feature = "feed_genetic")] + #[cfg(feature = "sched_genetic")] let scheduler = GenerationScheduler::new(); // A fuzzer with feedbacks and a corpus scheduler let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective); - #[cfg(not(feature = "systemstate"))] - let qhelpers = tuple_list!( - QemuEdgeCoverageHelper::default(), - QemuStateRestoreHelper::new() - ); - #[cfg(feature = "systemstate")] - let qhelpers = tuple_list!( - QemuEdgeCoverageHelper::default(), - QemuStateRestoreHelper::new(), - QemuSystemStateHelper::new(api_addreses,api_ranges,isr_addreses,isr_ranges,curr_tcb_pointer,task_queue_addr,task_delay_addr,task_delay_overflow_addr,scheduler_lock,scheduler_running, critical_section,input_counter_ptr,app_range.clone()) - ); + + let qhelpers = tuple_list!(); + #[cfg(feature = "observe_systemstate")] + let qhelpers = (QemuSystemStateHelper::new(api_addreses,api_ranges,isr_addreses,isr_ranges,curr_tcb_pointer,task_queue_addr,task_delay_addr,task_delay_overflow_addr,scheduler_lock,scheduler_running, critical_section,input_counter_ptr,app_range.clone()), qhelpers); + #[cfg(feature = "observe_edges")] + let qhelpers = (QemuEdgeCoverageHelper::default(), qhelpers); + let qhelpers = (QemuStateRestoreHelper::new(), qhelpers); + let mut hooks = QemuHooks::new(emu.clone(),qhelpers); - #[cfg(not(feature = "systemstate"))] - let observer_list = tuple_list!(edges_observer, clock_time_observer); - #[cfg(feature = "systemstate")] - let observer_list = tuple_list!(edges_observer, clock_time_observer, systemstate_observer, stg_observer); + let observer_list = tuple_list!(); + #[cfg(feature = "observe_systemstate")] + let observer_list = (systemstate_observer, (stg_coverage_observer, observer_list)); // must come after clock + #[cfg(feature = "observe_edges")] + let observer_list = (edges_observer, observer_list); + let observer_list = (clock_time_observer, observer_list); // Create a QEMU in-process executor let executor = QemuExecutor::new( @@ -663,13 +624,10 @@ pub fn fuzz() { let mutations = havoc_mutations(); // Setup an havoc mutator with a mutational stage let mutator = StdScheduledMutator::new(mutations); - // #[cfg(not(all(feature = "feed_systemtrace", feature = "fuzz_int")))] - // let mut stages = tuple_list!(StdMutationalStage::new(mutator)); - // #[cfg(all(feature = "feed_systemtrace", feature = "fuzz_int"))] - #[cfg(feature = "fuzz_int")] - let mut stages = tuple_list!(StdMutationalStage::new(mutator),InterruptShiftStage::new()); - #[cfg(not(feature = "fuzz_int"))] + let mut stages = tuple_list!(StdMutationalStage::new(mutator)); + #[cfg(feature = "fuzz_int")] + let mut stages = (InterruptShiftStage::new(), stages); if let Commands::Showmap { input } = cli.command.clone() { let s = input.as_os_str(); @@ -685,7 +643,6 @@ pub fn fuzz() { fuzzer.evaluate_input(&mut state, &mut executor, &mut mgr, BytesInput::new(show_input)) .unwrap(); do_dump_times!(state, &cli, ""); - do_dump_graph!(state, &cli, ""); do_dump_stg!(state, &cli, ""); } else if let Commands::Fuzz { random, time, seed } = cli.command { if let Some(se) = seed { @@ -748,8 +705,6 @@ pub fn fuzz() { let mut dumper = |marker : String| { let d = format!("{}.case",marker); do_dump_case!(state, &cli, &d); - let _d = format!("{}.graph",marker); - do_dump_graph!(state, &cli, &_d); let _d = format!("{}.stg",marker); do_dump_stg!(state, &cli, &_d); let d = format!("{}.toprated",marker); @@ -771,7 +726,6 @@ pub fn fuzz() { last=after; } do_dump_case!(state, &cli, ""); - do_dump_graph!(state, &cli, ""); do_dump_stg!(state, &cli, ""); do_dump_toprated!(state, &cli, ""); } @@ -779,7 +733,6 @@ pub fn fuzz() { } do_dump_times!(state, &cli, ""); do_dump_case!(state, &cli, ""); - do_dump_graph!(state, &cli, ""); do_dump_stg!(state, &cli, ""); do_dump_toprated!(state, &cli, ""); }, diff --git a/fuzzers/FRET/src/mutational.rs b/fuzzers/FRET/src/mutational.rs index b273c45bf8..69bbc8504c 100644 --- a/fuzzers/FRET/src/mutational.rs +++ b/fuzzers/FRET/src/mutational.rs @@ -99,7 +99,7 @@ where let mut suffix = target_bytes.split_off(4 * num_interrupts); let mut prefix : Vec<[u8; 4]> = vec![]; // let mut suffix : Vec = vec![]; - #[cfg(feature = "feed_stg")] + #[cfg(feature = "trace_stg")] { let feedbackstate = match state .named_metadata_map_mut() @@ -211,7 +211,7 @@ where } } } - #[cfg(not(feature = "feed_systemtrace"))] + #[cfg(not(feature = "trace_stg"))] { let metadata = state.metadata_map(); let hist = metadata.get::().unwrap(); diff --git a/fuzzers/FRET/src/systemstate/feedbacks.rs b/fuzzers/FRET/src/systemstate/feedbacks.rs index bc396d5d62..7b4997bbb1 100644 --- a/fuzzers/FRET/src/systemstate/feedbacks.rs +++ b/fuzzers/FRET/src/systemstate/feedbacks.rs @@ -44,14 +44,6 @@ impl Named for SystemStateFeedbackState "systemstate" } } -// impl FeedbackState for systemstateFeedbackState -// { -// fn reset(&mut self) -> Result<(), Error> { -// self.longest.clear(); -// self.known_traces.clear(); -// Ok(()) -// } -// } /// A Feedback reporting novel System-State Transitions. Depends on [`QemuSystemStateObserver`] #[derive(Serialize, Deserialize, Clone, Debug, Default)] @@ -149,74 +141,6 @@ impl Named for NovelSystemStateFeedback } } -//============================= - -pub fn match_traces(target: &Vec, last: &Vec) -> bool { - let mut ret = true; - if target.len() > last.len() {return false;} - for i in 0..target.len() { - ret &= target[i].current_task.task_name==last[i].current_task.task_name; - } - ret -} -pub fn match_traces_name(target: &Vec, last: &Vec) -> bool { - let mut ret = true; - if target.len() > last.len() {return false;} - for i in 0..target.len() { - ret &= target[i]==last[i].current_task.task_name; - } - ret -} - -/// A Feedback reporting novel System-State Transitions. Depends on [`QemuSystemStateObserver`] -#[derive(Serialize, Deserialize, Clone, Debug, Default)] -pub struct HitSystemStateFeedback -{ - target: Option>, -} - -impl Feedback for HitSystemStateFeedback -where - S: State + UsesInput + MaybeHasClientPerfMonitor, -{ - fn is_interesting( - &mut self, - state: &mut S, - manager: &mut EM, - input: &S::Input, - observers: &OT, - exit_kind: &ExitKind, - ) -> Result - where - EM: EventFirer, - OT: ObserversTuple - { - let observer = observers.match_name::("systemstate") - .expect("QemuSystemStateObserver not found"); - // Do Stuff - match &self.target { - Some(s) => { - // #[cfg(debug_assertions)] eprintln!("Hit systemstate Feedback trigger"); - Ok(match_traces_name(s, &observer.last_run)) - }, - None => Ok(false), - } - } -} - -impl Named for HitSystemStateFeedback -{ - #[inline] - fn name(&self) -> &str { - "hit_systemstate" - } -} - -impl HitSystemStateFeedback { - pub fn new(target: Option>) -> Self { - Self {target: target.map(|x| x.into_iter().map(|y| y.current_task.task_name).collect())} - } -} //=========================== Debugging Feedback /// A [`Feedback`] meant to dump the system-traces for debugging. Depends on [`QemuSystemStateObserver`] #[derive(Debug)] diff --git a/fuzzers/FRET/src/systemstate/helpers.rs b/fuzzers/FRET/src/systemstate/helpers.rs index 06b88e743c..7c7be729a9 100644 --- a/fuzzers/FRET/src/systemstate/helpers.rs +++ b/fuzzers/FRET/src/systemstate/helpers.rs @@ -115,7 +115,6 @@ where for wp in self.isr_addrs.keys() { _hooks.instruction(*wp, Hook::Function(exec_isr_hook::), false); } - //#[cfg(feature = "trace_abbs")] _hooks.jmps(Hook::Function(gen_jmp_is_syscall::), Hook::Function(trace_api_call::)); } diff --git a/fuzzers/FRET/src/systemstate/mod.rs b/fuzzers/FRET/src/systemstate/mod.rs index 89263210c8..642f5e22a6 100644 --- a/fuzzers/FRET/src/systemstate/mod.rs +++ b/fuzzers/FRET/src/systemstate/mod.rs @@ -21,12 +21,6 @@ pub mod graph; pub mod schedulers; pub mod stg; -// #[cfg(feature = "fuzz_interrupt")] -// pub const IRQ_INPUT_BYTES_NUMBER : u32 = 2; // Offset for interrupt bytes -// #[cfg(not(feature = "fuzz_interrupt"))] -// pub const IRQ_INPUT_BYTES_NUMBER : u32 = 0; // Offset for interrupt bytes -// pub const IRQ_INPUT_OFFSET : u32 = 347780; // Tick offset for app code start - // Constants const NUM_PRIOS: usize = 5; diff --git a/fuzzers/FRET/src/systemstate/observers.rs b/fuzzers/FRET/src/systemstate/observers.rs index d83d947f50..a97690369a 100644 --- a/fuzzers/FRET/src/systemstate/observers.rs +++ b/fuzzers/FRET/src/systemstate/observers.rs @@ -338,92 +338,6 @@ fn add_abb_info(trace: &mut Vec, table: &HashMap = last_abb_start_of_task.get(&curr_name); - // // genric start of an ABB that gets preeempted - // match trace[i].start_capture.0 { - // CaptureEvent::APIEnd => { - // if last.is_some() { - // panic!("End an API call with open ABB"); - // } - // last_abb_start_of_task.insert(curr_name, i); - // } - // CaptureEvent::ISREnd => { - // if last.is_none() && trace[i].end_capture.1=="xPortPendSVHandler" && !task_has_started.contains(&curr_name) { - // // The initial ABB of a tasks starts not when an api call ends, but when it is fist scheduled - // last_abb_start_of_task.insert(curr_name.clone(), i); - // task_has_started.insert(curr_name); - // } - // }, - // _ => (), - // } - // // genric end of an ABB that got preeempted - // match trace[i].end_capture.0 { - // CaptureEvent::APIStart => { - // if let Some(&l) = last { - // // let start = trace[l].edge.1.unwrap(); - // // let end = trace[i].edge.0.unwrap(); - // abb_begin_end.insert(l, i); - // } else { - // panic!("Start an API call with no ABB to terminate"); - // } - // last_abb_start_of_task.remove(&curr_name); - // } - // CaptureEvent::End => { - // if let Some(&l) = last { - // // let start = trace[l].edge.1.unwrap(); - // // let end = trace[i].edge.0.unwrap(); - // abb_begin_end.insert(l, i); - // last_abb_start_of_task.remove(&curr_name); - // } else { - // eprintln!("End with no ABB to terminate"); // could happen if the run ends in a kernel panic - // } - // } - // _ => (), - // } - // } - // } - - // for (b,e) in abb_begin_end.into_iter() { - // let curr_name = table[&trace[i].start_state].current_task.task_name.clone(); - // let abb = Some(AtomicBasicBlock{start: edges[b].0.unwrap(), ends: HashSet::from([edges[e].1.unwrap()])}); - // for j in b..(e+1) { - // if trace[j].current_task.0.task_name == curr_name { - // trace[j].abb=abb.clone(); - // } - // } - // } - - // let mut abb_intervals : Vec<_> = abb_begin_end.into_iter().collect(); - // abb_intervals.sort_by_key(|(x,_)| *x); - // let mut chunks = Vec::new(); // (name, abb, index, ticks) - // for &(s,e) in abb_intervals.iter() { - // let curr_name = trace[s].current_task.0.task_name.clone(); - // let start = match trace[s].capture_point.0 { - // CaptureEvent::ISREnd => 0, - // CaptureEvent::APIEnd => trace[s].edge.1.unwrap(), - // _ => panic!(), - // }; - // let end = trace[e].edge.0.unwrap(); - // let abb = Rc::new(AtomicBasicBlock {start, ends: HashSet::from([end])}); - // // find intervalls where the abb is actually running, not preempted - // // count up exec time - // let mut sum_of_pieces = 0; - // for i in s..e { - // if trace[i].current_task.0.task_name == curr_name { - // match trace[i].capture_point.0 { - // CaptureEvent::APIEnd => {chunks.push((curr_name.clone(), abb.clone(), i, trace[i+1].end_tick-trace[i].end_tick)); sum_of_pieces+=trace[i+1].end_tick-trace[i].end_tick;}, - // CaptureEvent::ISRStart => (), - // CaptureEvent::ISREnd => {chunks.push((curr_name.clone(), abb.clone(), i, trace[i+1].end_tick-trace[i].end_tick)); sum_of_pieces+=trace[i+1].end_tick-trace[i].end_tick;}, - // _ => panic!(), - // } - // } - // } - // abbs_in_exec_order.push((e,(*abb).clone(), sum_of_pieces)); - // } - // abbs_in_exec_order.sort_by_key(|x| x.0); - // let abbs_in_exec_order : Vec<_> = abbs_in_exec_order.into_iter().map(|(_x,y,z)| (y,z)).collect(); - // chunks.sort_by_key(|x| x.2); - // (chunks, abbs_in_exec_order) } @@ -462,49 +376,4 @@ fn merge_subsequent_abbs(trace: &mut Vec) { lst_valid = i; } } -} - -//============================= ABB Observer - -// The Qemusystemstate Observer retrieves the systemstate -// that will get updated by the target. -// #[derive(Serialize, Deserialize, Debug, Default)] -// #[allow(clippy::unsafe_derive_deserialize)] -// pub struct ABBObserver -// { -// pub last_run: HashMap>, -// name: String, -// } - -// impl Observer for ABBObserver -// where -// S: UsesInput, -// S::Input : HasTargetBytes, -// { -// #[inline] -// fn pre_exec(&mut self, _state: &mut S, _input: &S::Input) -> Result<(), Error> { -// self.last_run.clear(); -// Ok(()) -// } - -// #[inline] -// fn post_exec(&mut self, _state: &mut S, _input: &S::Input, _exit_kind: &ExitKind) -> Result<(), Error> { -// unsafe {self.last_run=extract_abbs_from_trace(&mut CURRENT_SYSTEMSTATE_VEC);} -// println!("{:?}", self.last_run); -// Ok(()) -// } -// } - -// impl Named for ABBObserver -// { -// #[inline] -// fn name(&self) -> &str { -// self.name.as_str() -// } -// } - -// impl ABBObserver { -// pub fn new() -> Self { -// Self{last_run: HashMap::new(), name: "abbs".to_string()} -// } -// } \ No newline at end of file +} \ No newline at end of file diff --git a/fuzzers/FRET/src/systemstate/stg.rs b/fuzzers/FRET/src/systemstate/stg.rs index 6037a72d58..0e560d4382 100644 --- a/fuzzers/FRET/src/systemstate/stg.rs +++ b/fuzzers/FRET/src/systemstate/stg.rs @@ -193,14 +193,15 @@ impl Named for STGFeedbackState // Wrapper around Vec to attach as Metadata #[derive(Debug, Default, Serialize, Deserialize, Clone)] pub struct STGNodeMetadata { - pub inner: Vec, + pub nodes: Vec, + pub edges: Vec, pub intervals: Vec, indices: Vec, tcref: isize, } impl STGNodeMetadata { - pub fn new(inner: Vec, intervals: Vec) -> Self{ - Self {indices: inner.iter().map(|x| x.index()).collect(), intervals, inner: inner, tcref: 0} + pub fn new(nodes: Vec, edges: Vec, intervals: Vec) -> Self{ + Self {indices: edges.iter().map(|x| x.index()).collect(), intervals, nodes, edges, tcref: 0} } } impl AsSlice for STGNodeMetadata { @@ -240,7 +241,8 @@ pub unsafe fn stg_map_mut_slice<'a>() -> OwnedMutSlice<'a, u8> { pub struct StgFeedback { name: String, - last_trace: Option>, + last_node_trace: Option>, + last_edge_trace: Option>, last_intervals: Option>, } #[cfg(feature = "feed_stg")] @@ -270,7 +272,7 @@ fn set_observer_map(trace : &Vec) { } impl StgFeedback { pub fn new() -> Self { - Self {name: String::from("STGFeedback"), last_trace: None, last_intervals: None } + Self {name: String::from("STGFeedback"), last_node_trace: None, last_edge_trace: None, last_intervals: None } } /// params: @@ -377,7 +379,7 @@ where } }; - let (nodetrace, _edgetrace, mut interesting) = StgFeedback::update_stg_interval(&observer.last_trace, &observer.last_states, feedbackstate); + let (nodetrace, edgetrace, mut interesting) = StgFeedback::update_stg_interval(&observer.last_trace, &observer.last_states, feedbackstate); if INTEREST_AGGREGATE { let mut tmp = StgFeedback::abbs_in_exec_order(&observer.last_trace); @@ -399,7 +401,8 @@ where // let outs = Dot::with_config(&out, &[Config::EdgeNoLabel]).to_string(); // let outs = outs.replace(';',"\\n"); // fs::write("./mystg.dot",outs).expect("Failed to write graph"); - self.last_trace = Some(nodetrace); + self.last_node_trace = Some(nodetrace); + self.last_edge_trace = Some(edgetrace); self.last_intervals = Some(observer.last_trace.clone()); Ok(interesting) @@ -408,9 +411,10 @@ where /// Append to the testcase the generated metadata in case of a new corpus item #[inline] fn append_metadata(&mut self, _state: &mut S, observers: &OT, testcase: &mut Testcase) -> Result<(), Error> { - let a = self.last_trace.take(); - match a { - Some(s) => testcase.metadata_map_mut().insert(STGNodeMetadata::new(s, self.last_intervals.take().unwrap())), + let nodes = self.last_node_trace.take(); + let edges = self.last_edge_trace.take(); + match nodes { + Some(s) => testcase.metadata_map_mut().insert(STGNodeMetadata::new(s, edges.unwrap(), self.last_intervals.take().unwrap())), None => (), } Ok(())