remove dead code, restructure features

This commit is contained in:
Alwin Berger 2024-05-21 16:06:53 +02:00
parent 3ed8ccd0c7
commit 2886aafb65
8 changed files with 97 additions and 344 deletions

View File

@ -1,32 +1,42 @@
[package] [package]
name = "fret" name = "fret"
version = "0.8.2" version = "0.8.2"
authors = ["Andrea Fioraldi <andreafioraldi@gmail.com>", "Dominik Maier <domenukk@gmail.com>"] authors = ["Alwin Berger <alwin.berger@tu-dortmund.de>"]
edition = "2021" edition = "2021"
[features] [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 = [] std = []
# Exec environemnt basics
snapshot_restore = [] snapshot_restore = []
snapshot_fast = [ "snapshot_restore" ] snapshot_fast = [ "snapshot_restore" ]
singlecore = [] singlecore = []
restarting = ['singlecore'] restarting = ['singlecore']
trace_abbs = [] run_until_saturation = []
systemstate = [] fuzz_int = []
feed_systemgraph = [ "systemstate" ] # information capture
feed_systemtrace = [ "systemstate" ] observe_edges = [] # observe cfg edges
feed_stg = [ "systemstate", "trace_abbs" ] 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_longest = [ ]
feed_afl = [ ] feed_afl = [ ]
feed_genetic = [ ] feed_genetic = []
fuzz_int = [ ]
gensize_1 = [ ] gensize_1 = [ ]
gensize_10 = [ ] gensize_10 = [ ]
gensize_100 = [ ] gensize_100 = [ ]
observer_hitcounts = [] # schedulers
do_hash_notify_state = [] sched_genetic = []
count_iterations = [] sched_afl = []
run_until_saturation = [] 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] [profile.release]
lto = true lto = true

View File

@ -14,7 +14,7 @@ use libafl_qemu::{
}; };
use rand::{SeedableRng, StdRng, Rng}; use rand::{SeedableRng, StdRng, Rng};
use crate::{ 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 std::time::{SystemTime, UNIX_EPOCH};
use clap::{Parser, Subcommand}; 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::<SysGraphFeedbackState>("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 /// Takes a state and a bool, writes out the current graph
macro_rules! do_dump_stg { macro_rules! do_dump_stg {
($state:expr, $cli:expr, $c:expr) => { ($state:expr, $cli:expr, $c:expr) => {
#[cfg(feature = "trace_abbs")] #[cfg(feature = "trace_stg")]
if $cli.dump_graph { if $cli.dump_graph {
let dump_path = $cli.dump_name.clone().unwrap().with_extension(if $c=="" {"stg"} else {$c}); let dump_path = $cli.dump_name.clone().unwrap().with_extension(if $c=="" {"stg"} else {$c});
println!("Dumping graph to {:?}", &dump_path); println!("Dumping graph to {:?}", &dump_path);
if let Some(md) = $state.named_metadata_map_mut().get_mut::<STGFeedbackState>("stgfeedbackstate") { if let Some(md) = $state.named_metadata_map_mut().get_mut::<STGFeedbackState>("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 = Dot::with_config(&out, &[]).to_string();
let outs = outs.replace("\\\"","\""); let outs = outs.replace("\\\"","\"");
let outs = outs.replace(';',"\\n"); 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_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); let input_counter_ptr = try_load_symbol(&elf, &env::var("FUZZ_POINTER").unwrap_or_else(|_| "FUZZ_POINTER".to_owned()), true);
#[cfg(feature = "systemstate")] #[cfg(feature = "observe_systemstate")]
let curr_tcb_pointer = elf // loads to the address specified in elf, without respecting program headers let curr_tcb_pointer = load_symbol(&elf, "pxCurrentTCB", false); // loads to the address specified in elf, without respecting program headers
.resolve_symbol("pxCurrentTCB", 0) #[cfg(feature = "observe_systemstate")]
.expect("Symbol pxCurrentTCBC not found");
// let curr_tcb_pointer = virt2phys(curr_tcb_pointer,&elf);
#[cfg(feature = "systemstate")]
println!("TCB pointer at {:#x}", curr_tcb_pointer); println!("TCB pointer at {:#x}", curr_tcb_pointer);
#[cfg(feature = "systemstate")] #[cfg(feature = "observe_systemstate")]
let task_queue_addr = load_symbol(&elf, "pxReadyTasksLists", false); let task_queue_addr = load_symbol(&elf, "pxReadyTasksLists", false);
#[cfg(feature = "observe_systemstate")]
let task_delay_addr = load_symbol(&elf, "pxDelayedTaskList", false); let task_delay_addr = load_symbol(&elf, "pxDelayedTaskList", false);
#[cfg(feature = "observe_systemstate")]
let task_delay_overflow_addr = load_symbol(&elf, "pxOverflowDelayedTaskList", false); let task_delay_overflow_addr = load_symbol(&elf, "pxOverflowDelayedTaskList", false);
#[cfg(feature = "observe_systemstate")]
let scheduler_lock = load_symbol(&elf, "uxSchedulerSuspended", false); let scheduler_lock = load_symbol(&elf, "uxSchedulerSuspended", false);
#[cfg(feature = "observe_systemstate")]
let scheduler_running = load_symbol(&elf, "xSchedulerRunning", false); let scheduler_running = load_symbol(&elf, "xSchedulerRunning", false);
#[cfg(feature = "observe_systemstate")]
let critical_section = load_symbol(&elf, "uxCriticalNesting", false); let critical_section = load_symbol(&elf, "uxCriticalNesting", false);
// let task_queue_addr = virt2phys(task_queue_addr,&elf.goblin()); #[cfg(feature = "observe_systemstate")]
#[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")]
let app_start = load_symbol(&elf, "__APP_CODE_START__", false); 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); let app_end = load_symbol(&elf, "__APP_CODE_END__", false);
#[cfg(feature = "systemstate")] #[cfg(feature = "observe_systemstate")]
let app_range = app_start..app_end; let app_range = app_start..app_end;
#[cfg(feature = "systemstate")] #[cfg(feature = "observe_systemstate")]
let api_start = load_symbol(&elf, "__API_CODE_START__", false); 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); let api_end = load_symbol(&elf, "__API_CODE_END__", false);
#[cfg(feature = "systemstate")] #[cfg(feature = "observe_systemstate")]
let api_range = api_start..api_end; let api_range = api_start..api_end;
#[cfg(feature = "systemstate")]
dbg!(app_range.clone());
let breakpoint = elf let breakpoint = elf
.resolve_symbol( .resolve_symbol(
@ -399,15 +373,15 @@ pub fn fuzz() {
unsafe {RNG_SEED = str::parse::<u64>(&seed).expect("SEED_RANDOM must be an integer.");} unsafe {RNG_SEED = str::parse::<u64>(&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); let mut api_ranges = get_all_fn_symbol_ranges(&elf, api_range);
#[cfg(feature = "systemstate")] #[cfg(feature = "observe_systemstate")]
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();
#[cfg(feature = "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 = "systemstate")] #[cfg(feature = "observe_systemstate")]
for i in systemstate::helpers::ISR_SYMBOLS { for i in systemstate::helpers::ISR_SYMBOLS {
if isr_ranges.get(&i.to_string()).is_none() { if isr_ranges.get(&i.to_string()).is_none() {
if let Some(fr) = get_function_range(&elf, i) { 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<GuestAddr, String> = api_ranges.iter().map(|(k,v)| (v.start,k.clone())).collect(); let api_addreses : HashMap<GuestAddr, String> = 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(); 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(); let isr_ranges : Vec<_> = isr_ranges.into_iter().collect();
// Client setup ================================================================================ // 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 // Create an observation channel using the coverage map
#[cfg(feature = "observe_edges")]
let edges_observer = unsafe { VariableMapObserver::from_mut_slice( let edges_observer = unsafe { VariableMapObserver::from_mut_slice(
"edges", "edges",
edges_map_mut_slice(), edges_map_mut_slice(),
@ -528,17 +506,14 @@ pub fn fuzz() {
#[cfg(feature = "observer_hitcounts")] #[cfg(feature = "observer_hitcounts")]
let edges_observer = HitcountsMapObserver::new(edges_observer); let edges_observer = HitcountsMapObserver::new(edges_observer);
// #[cfg(feature = "feed_stg")] #[cfg(feature = "feed_stg")]
let stg_observer = unsafe { VariableMapObserver::from_mut_slice( let stg_coverage_observer = unsafe { VariableMapObserver::from_mut_slice(
"stg", "stg",
stg_map_mut_slice(), stg_map_mut_slice(),
addr_of_mut!(MAX_STG_NUM) addr_of_mut!(MAX_STG_NUM)
)}; )};
// Create an observation channel to keep track of the execution time #[cfg(feature = "observe_systemstate")]
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")]
let systemstate_observer = QemuSystemStateObserver::new(); let systemstate_observer = QemuSystemStateObserver::new();
// Feedback to rate the interestingness of an input // 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 // Feedback to reward any input which increses the execution time
ExecTimeIncFeedback::new() ExecTimeIncFeedback::new()
); );
#[cfg(all(feature = "systemstate"))] #[cfg(all(feature = "observe_systemstate"))]
let mut feedback = feedback_or!( let mut feedback = feedback_or!(
feedback, feedback,
DumpSystraceFeedback::with_dump(if cli.dump_traces {cli.dump_name.clone().map(|x| x.with_extension("trace.ron"))} else {None}) 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!( let mut feedback = feedback_or!(
feedback, feedback,
StgFeedback::default() StgFeedback::default()
@ -578,18 +553,7 @@ pub fn fuzz() {
#[cfg(feature = "feed_stg")] #[cfg(feature = "feed_stg")]
let mut feedback = feedback_or!( let mut feedback = feedback_or!(
feedback, feedback,
MaxMapFeedback::tracking(&stg_observer, true, true) MaxMapFeedback::tracking(&stg_coverage_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()
); );
// A feedback to choose if an input is a solution or not // 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 // 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")))] #[cfg(not(any(feature = "sched_afl", feature = "sched_stg", feature = "sched_genetic")))]
let scheduler = QueueScheduler::new(); let scheduler = QueueScheduler::new(); // fallback
#[cfg(all(feature = "feed_afl",not(any(feature = "feed_systemgraph",feature = "feed_systemtrace"))))] #[cfg(feature = "sched_afl",)]
let scheduler = TimeMaximizerCorpusScheduler::new(QueueScheduler::new()); let scheduler = TimeMaximizerCorpusScheduler::new(QueueScheduler::new());
#[cfg(feature = "feed_systemtrace")] #[cfg(feature = "sched_stg")]
let scheduler = LongestTraceScheduler::new(TimeStateMaximizerCorpusScheduler::new(QueueScheduler::new()));
#[cfg(feature = "feed_systemgraph")]
let scheduler = GraphMaximizerCorpusScheduler::new(QueueScheduler::new()); let scheduler = GraphMaximizerCorpusScheduler::new(QueueScheduler::new());
#[cfg(feature = "feed_genetic")] #[cfg(feature = "sched_genetic")]
let scheduler = GenerationScheduler::new(); let scheduler = GenerationScheduler::new();
// A fuzzer with feedbacks and a corpus scheduler // A fuzzer with feedbacks and a corpus scheduler
let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective); let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective);
#[cfg(not(feature = "systemstate"))]
let qhelpers = tuple_list!( let qhelpers = tuple_list!();
QemuEdgeCoverageHelper::default(), #[cfg(feature = "observe_systemstate")]
QemuStateRestoreHelper::new() 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")]
#[cfg(feature = "systemstate")] let qhelpers = (QemuEdgeCoverageHelper::default(), qhelpers);
let qhelpers = tuple_list!( let qhelpers = (QemuStateRestoreHelper::new(), qhelpers);
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 mut hooks = QemuHooks::new(emu.clone(),qhelpers); let mut hooks = QemuHooks::new(emu.clone(),qhelpers);
#[cfg(not(feature = "systemstate"))] let observer_list = tuple_list!();
let observer_list = tuple_list!(edges_observer, clock_time_observer); #[cfg(feature = "observe_systemstate")]
#[cfg(feature = "systemstate")] let observer_list = (systemstate_observer, (stg_coverage_observer, observer_list)); // must come after clock
let observer_list = tuple_list!(edges_observer, clock_time_observer, systemstate_observer, stg_observer); #[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 // Create a QEMU in-process executor
let executor = QemuExecutor::new( let executor = QemuExecutor::new(
@ -663,13 +624,10 @@ pub fn fuzz() {
let mutations = havoc_mutations(); let mutations = havoc_mutations();
// Setup an havoc mutator with a mutational stage // Setup an havoc mutator with a mutational stage
let mutator = StdScheduledMutator::new(mutations); 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)); 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() { if let Commands::Showmap { input } = cli.command.clone() {
let s = input.as_os_str(); 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)) fuzzer.evaluate_input(&mut state, &mut executor, &mut mgr, BytesInput::new(show_input))
.unwrap(); .unwrap();
do_dump_times!(state, &cli, ""); do_dump_times!(state, &cli, "");
do_dump_graph!(state, &cli, "");
do_dump_stg!(state, &cli, ""); do_dump_stg!(state, &cli, "");
} else if let Commands::Fuzz { random, time, seed } = cli.command { } else if let Commands::Fuzz { random, time, seed } = cli.command {
if let Some(se) = seed { if let Some(se) = seed {
@ -748,8 +705,6 @@ pub fn fuzz() {
let mut dumper = |marker : String| { let mut dumper = |marker : String| {
let d = format!("{}.case",marker); let d = format!("{}.case",marker);
do_dump_case!(state, &cli, &d); do_dump_case!(state, &cli, &d);
let _d = format!("{}.graph",marker);
do_dump_graph!(state, &cli, &_d);
let _d = format!("{}.stg",marker); let _d = format!("{}.stg",marker);
do_dump_stg!(state, &cli, &_d); do_dump_stg!(state, &cli, &_d);
let d = format!("{}.toprated",marker); let d = format!("{}.toprated",marker);
@ -771,7 +726,6 @@ pub fn fuzz() {
last=after; last=after;
} }
do_dump_case!(state, &cli, ""); do_dump_case!(state, &cli, "");
do_dump_graph!(state, &cli, "");
do_dump_stg!(state, &cli, ""); do_dump_stg!(state, &cli, "");
do_dump_toprated!(state, &cli, ""); do_dump_toprated!(state, &cli, "");
} }
@ -779,7 +733,6 @@ pub fn fuzz() {
} }
do_dump_times!(state, &cli, ""); do_dump_times!(state, &cli, "");
do_dump_case!(state, &cli, ""); do_dump_case!(state, &cli, "");
do_dump_graph!(state, &cli, "");
do_dump_stg!(state, &cli, ""); do_dump_stg!(state, &cli, "");
do_dump_toprated!(state, &cli, ""); do_dump_toprated!(state, &cli, "");
}, },

View File

@ -99,7 +99,7 @@ where
let mut suffix = target_bytes.split_off(4 * num_interrupts); let mut suffix = target_bytes.split_off(4 * num_interrupts);
let mut prefix : Vec<[u8; 4]> = vec![]; let mut prefix : Vec<[u8; 4]> = vec![];
// let mut suffix : Vec<u8> = vec![]; // let mut suffix : Vec<u8> = vec![];
#[cfg(feature = "feed_stg")] #[cfg(feature = "trace_stg")]
{ {
let feedbackstate = match state let feedbackstate = match state
.named_metadata_map_mut() .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 metadata = state.metadata_map();
let hist = metadata.get::<IcHist>().unwrap(); let hist = metadata.get::<IcHist>().unwrap();

View File

@ -44,14 +44,6 @@ impl Named for SystemStateFeedbackState
"systemstate" "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`] /// A Feedback reporting novel System-State Transitions. Depends on [`QemuSystemStateObserver`]
#[derive(Serialize, Deserialize, Clone, Debug, Default)] #[derive(Serialize, Deserialize, Clone, Debug, Default)]
@ -149,74 +141,6 @@ impl Named for NovelSystemStateFeedback
} }
} }
//=============================
pub fn match_traces(target: &Vec<ReducedFreeRTOSSystemState>, last: &Vec<ReducedFreeRTOSSystemState>) -> 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<String>, last: &Vec<ReducedFreeRTOSSystemState>) -> 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<Vec<String>>,
}
impl<S> Feedback<S> for HitSystemStateFeedback
where
S: State + UsesInput + MaybeHasClientPerfMonitor,
{
fn is_interesting<EM, OT>(
&mut self,
state: &mut S,
manager: &mut EM,
input: &S::Input,
observers: &OT,
exit_kind: &ExitKind,
) -> Result<bool, Error>
where
EM: EventFirer<State = S>,
OT: ObserversTuple<S>
{
let observer = observers.match_name::<QemuSystemStateObserver>("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<Vec<ReducedFreeRTOSSystemState>>) -> Self {
Self {target: target.map(|x| x.into_iter().map(|y| y.current_task.task_name).collect())}
}
}
//=========================== Debugging Feedback //=========================== Debugging Feedback
/// A [`Feedback`] meant to dump the system-traces for debugging. Depends on [`QemuSystemStateObserver`] /// A [`Feedback`] meant to dump the system-traces for debugging. Depends on [`QemuSystemStateObserver`]
#[derive(Debug)] #[derive(Debug)]

View File

@ -115,7 +115,6 @@ where
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); _hooks.instruction(*wp, Hook::Function(exec_isr_hook::<QT, S>), false);
} }
//#[cfg(feature = "trace_abbs")]
_hooks.jmps(Hook::Function(gen_jmp_is_syscall::<QT, S>), Hook::Function(trace_api_call::<QT, S>)); _hooks.jmps(Hook::Function(gen_jmp_is_syscall::<QT, S>), Hook::Function(trace_api_call::<QT, S>));
} }

View File

@ -21,12 +21,6 @@ pub mod graph;
pub mod schedulers; pub mod schedulers;
pub mod stg; 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 // Constants
const NUM_PRIOS: usize = 5; const NUM_PRIOS: usize = 5;

View File

@ -338,92 +338,6 @@ fn add_abb_info(trace: &mut Vec<ExecInterval>, table: &HashMap<u64, ReducedFreeR
for i in 0..trace.len() { for i in 0..trace.len() {
trace[i].abb = Some((*wip_abb_trace[i]).borrow().clone()); trace[i].abb = Some((*wip_abb_trace[i]).borrow().clone());
} }
// let last : Option<&usize> = 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<ExecInterval>) {
lst_valid = i; 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<String,Vec<AtomicBasicBlock>>,
// name: String,
// }
// impl<S> Observer<S> 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()}
// }
// }

View File

@ -193,14 +193,15 @@ impl Named for STGFeedbackState
// Wrapper around Vec<RefinedFreeRTOSSystemState> to attach as Metadata // Wrapper around Vec<RefinedFreeRTOSSystemState> to attach as Metadata
#[derive(Debug, Default, Serialize, Deserialize, Clone)] #[derive(Debug, Default, Serialize, Deserialize, Clone)]
pub struct STGNodeMetadata { pub struct STGNodeMetadata {
pub inner: Vec<NodeIndex>, pub nodes: Vec<NodeIndex>,
pub edges: Vec<EdgeIndex>,
pub intervals: Vec<ExecInterval>, pub intervals: Vec<ExecInterval>,
indices: Vec<usize>, indices: Vec<usize>,
tcref: isize, tcref: isize,
} }
impl STGNodeMetadata { impl STGNodeMetadata {
pub fn new(inner: Vec<NodeIndex>, intervals: Vec<ExecInterval>) -> Self{ pub fn new(nodes: Vec<NodeIndex>, edges: Vec<EdgeIndex>, intervals: Vec<ExecInterval>) -> Self{
Self {indices: inner.iter().map(|x| x.index()).collect(), intervals, inner: inner, tcref: 0} Self {indices: edges.iter().map(|x| x.index()).collect(), intervals, nodes, edges, tcref: 0}
} }
} }
impl AsSlice for STGNodeMetadata { impl AsSlice for STGNodeMetadata {
@ -240,7 +241,8 @@ pub unsafe fn stg_map_mut_slice<'a>() -> OwnedMutSlice<'a, u8> {
pub struct StgFeedback pub struct StgFeedback
{ {
name: String, name: String,
last_trace: Option<Vec<NodeIndex>>, last_node_trace: Option<Vec<NodeIndex>>,
last_edge_trace: Option<Vec<EdgeIndex>>,
last_intervals: Option<Vec<ExecInterval>>, last_intervals: Option<Vec<ExecInterval>>,
} }
#[cfg(feature = "feed_stg")] #[cfg(feature = "feed_stg")]
@ -270,7 +272,7 @@ fn set_observer_map(trace : &Vec<EdgeIndex>) {
} }
impl StgFeedback { impl StgFeedback {
pub fn new() -> Self { 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: /// 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 { if INTEREST_AGGREGATE {
let mut tmp = StgFeedback::abbs_in_exec_order(&observer.last_trace); 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 = Dot::with_config(&out, &[Config::EdgeNoLabel]).to_string();
// let outs = outs.replace(';',"\\n"); // let outs = outs.replace(';',"\\n");
// fs::write("./mystg.dot",outs).expect("Failed to write graph"); // 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()); self.last_intervals = Some(observer.last_trace.clone());
Ok(interesting) Ok(interesting)
@ -408,9 +411,10 @@ 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<OT>(&mut self, _state: &mut S, observers: &OT, testcase: &mut Testcase<S::Input>) -> Result<(), Error> { fn append_metadata<OT>(&mut self, _state: &mut S, observers: &OT, testcase: &mut Testcase<S::Input>) -> Result<(), Error> {
let a = self.last_trace.take(); let nodes = self.last_node_trace.take();
match a { let edges = self.last_edge_trace.take();
Some(s) => testcase.metadata_map_mut().insert(STGNodeMetadata::new(s, self.last_intervals.take().unwrap())), match nodes {
Some(s) => testcase.metadata_map_mut().insert(STGNodeMetadata::new(s, edges.unwrap(), self.last_intervals.take().unwrap())),
None => (), None => (),
} }
Ok(()) Ok(())