remove dead code, restructure features
This commit is contained in:
parent
3ed8ccd0c7
commit
2886aafb65
@ -1,32 +1,42 @@
|
||||
[package]
|
||||
name = "fret"
|
||||
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"
|
||||
|
||||
[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
|
||||
|
@ -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::<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
|
||||
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>("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::<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);
|
||||
|
||||
#[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();
|
||||
#[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();
|
||||
|
||||
#[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<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();
|
||||
#[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, "");
|
||||
},
|
||||
|
@ -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<u8> = 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::<IcHist>().unwrap();
|
||||
|
@ -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<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
|
||||
/// A [`Feedback`] meant to dump the system-traces for debugging. Depends on [`QemuSystemStateObserver`]
|
||||
#[derive(Debug)]
|
||||
|
@ -115,7 +115,6 @@ where
|
||||
for wp in self.isr_addrs.keys() {
|
||||
_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>));
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -338,92 +338,6 @@ fn add_abb_info(trace: &mut Vec<ExecInterval>, table: &HashMap<u64, ReducedFreeR
|
||||
for i in 0..trace.len() {
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//============================= 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()}
|
||||
// }
|
||||
// }
|
||||
}
|
@ -193,14 +193,15 @@ impl Named for STGFeedbackState
|
||||
// Wrapper around Vec<RefinedFreeRTOSSystemState> to attach as Metadata
|
||||
#[derive(Debug, Default, Serialize, Deserialize, Clone)]
|
||||
pub struct STGNodeMetadata {
|
||||
pub inner: Vec<NodeIndex>,
|
||||
pub nodes: Vec<NodeIndex>,
|
||||
pub edges: Vec<EdgeIndex>,
|
||||
pub intervals: Vec<ExecInterval>,
|
||||
indices: Vec<usize>,
|
||||
tcref: isize,
|
||||
}
|
||||
impl STGNodeMetadata {
|
||||
pub fn new(inner: Vec<NodeIndex>, intervals: Vec<ExecInterval>) -> Self{
|
||||
Self {indices: inner.iter().map(|x| x.index()).collect(), intervals, inner: inner, tcref: 0}
|
||||
pub fn new(nodes: Vec<NodeIndex>, edges: Vec<EdgeIndex>, intervals: Vec<ExecInterval>) -> 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<Vec<NodeIndex>>,
|
||||
last_node_trace: Option<Vec<NodeIndex>>,
|
||||
last_edge_trace: Option<Vec<EdgeIndex>>,
|
||||
last_intervals: Option<Vec<ExecInterval>>,
|
||||
}
|
||||
#[cfg(feature = "feed_stg")]
|
||||
@ -270,7 +272,7 @@ fn set_observer_map(trace : &Vec<EdgeIndex>) {
|
||||
}
|
||||
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<OT>(&mut self, _state: &mut S, observers: &OT, testcase: &mut Testcase<S::Input>) -> 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(())
|
||||
|
Loading…
x
Reference in New Issue
Block a user