implement STGSnippetStage, fix missing metadata
This commit is contained in:
parent
3d0c0247b7
commit
013f3db487
@ -70,3 +70,4 @@ clap = { version = "4.4.11", features = ["derive"] }
|
||||
csv = "1.3.0"
|
||||
log = "0.4"
|
||||
simple_moving_average = "1.0.2"
|
||||
itertools = "0.13.0"
|
||||
|
@ -15,7 +15,7 @@ edges::{self, edges_map_mut_ptr, QemuEdgeCoverageHelper, MAX_EDGES_FOUND}, elf::
|
||||
};
|
||||
use rand::{SeedableRng, StdRng, Rng};
|
||||
use crate::{
|
||||
systemstate::{self, feedbacks::{DumpSystraceFeedback, SystraceErrorFeedback}, helpers::{get_function_range, load_symbol, try_load_symbol, QemuSystemStateHelper}, mutational::{input_bytes_to_interrupt_times, InterruptShiftStage}, observers::QemuSystemStateObserver, schedulers::{GenerationScheduler, LongestTraceScheduler}, stg::{stg_map_mut_slice, GraphMaximizerCorpusScheduler, STGEdge, STGNode, StgFeedback, MAX_STG_NUM}}, time::{
|
||||
systemstate::{self, feedbacks::{DumpSystraceFeedback, SystraceErrorFeedback}, helpers::{get_function_range, load_symbol, try_load_symbol, QemuSystemStateHelper}, mutational::{input_bytes_to_interrupt_times, InterruptShiftStage, STGSnippetStage}, observers::QemuSystemStateObserver, schedulers::{GenerationScheduler, LongestTraceScheduler}, stg::{stg_map_mut_slice, GraphMaximizerCorpusScheduler, STGEdge, STGNode, StgFeedback, MAX_STG_NUM}}, time::{
|
||||
clock::{ClockTimeFeedback, IcHist, QemuClockIncreaseFeedback, QemuClockObserver, FUZZ_START_TIMESTAMP, QEMU_ICOUNT_SHIFT, QEMU_ISNS_PER_USEC}, qemustate::QemuStateRestoreHelper, worst::{AlwaysTrueFeedback, ExecTimeIncFeedback, TimeMaximizerCorpusScheduler, TimeProbMassScheduler, TimeStateMaximizerCorpusScheduler}
|
||||
}
|
||||
};
|
||||
@ -478,7 +478,7 @@ let run_client = |state: Option<_>, mut mgr, _core_id| {
|
||||
#[cfg(feature = "sched_afl",)]
|
||||
let scheduler = TimeMaximizerCorpusScheduler::new(&edges_observer,TimeProbMassScheduler::new());
|
||||
#[cfg(feature = "sched_stg")]
|
||||
let scheduler = GraphMaximizerCorpusScheduler::new(&stg_coverage_observer,TimeProbMassScheduler::new());
|
||||
let scheduler = GraphMaximizerCorpusScheduler::non_metadata_removing(&stg_coverage_observer,TimeProbMassScheduler::new());
|
||||
#[cfg(feature = "sched_genetic")]
|
||||
let scheduler = GenerationScheduler::new();
|
||||
|
||||
@ -520,7 +520,8 @@ let run_client = |state: Option<_>, mut mgr, _core_id| {
|
||||
let mutator = StdScheduledMutator::new(mutations);
|
||||
|
||||
let stages = (systemstate::report::SchedulerStatsStage::default(),());
|
||||
let mut stages = (StdMutationalStage::new(mutator), stages);
|
||||
let stages = (StdMutationalStage::new(mutator), stages);
|
||||
let mut stages = (STGSnippetStage::new(input_addr), stages);
|
||||
#[cfg(feature = "fuzz_int")]
|
||||
let mut stages = (InterruptShiftStage::new(&interrupt_config), stages);
|
||||
|
||||
|
@ -192,9 +192,9 @@ where
|
||||
let names : Vec<String> = observer.last_run.iter().map(|x| x.current_task.task_name.clone()).collect();
|
||||
match &self.dumpfile {
|
||||
Some(s) => {
|
||||
let per_task_metadata = if let Some(worst_instance) = observer.job_instances.iter().filter(|x| Some(x.2.clone()) == observer.select_task).max_by(|a,b| (a.1-a.0).cmp(&(b.1-b.0))) {
|
||||
let per_task_metadata = if let Some(worst_instance) = observer.job_instances.iter().filter(|x| Some(&x.name) == observer.select_task.as_ref()).max_by(|a,b| (a.response-a.release).cmp(&(b.response-b.release))) {
|
||||
// extract computation time spent in each task and abb
|
||||
let t : Vec<_> = observer.last_trace.iter().filter(|x| x.start_tick < worst_instance.1 && x.end_tick > worst_instance.0 ).cloned().collect();
|
||||
let t : Vec<_> = observer.last_trace.iter().filter(|x| x.start_tick < worst_instance.response && x.end_tick > worst_instance.release ).cloned().collect();
|
||||
// task_name -> addr -> (count, time)
|
||||
let mut ret : HashMap<String, HashMap<u32, (usize, usize, u64)>> = HashMap::new();
|
||||
let mut t2 = t.clone();
|
||||
@ -212,7 +212,7 @@ where
|
||||
}
|
||||
});
|
||||
});
|
||||
dbg!(&ret);
|
||||
// dbg!(&ret);
|
||||
ret
|
||||
} else {HashMap::new()};
|
||||
std::fs::write(s,ron::to_string(&(&observer.last_trace,&observer.last_states,&observer.job_instances,per_task_metadata)).expect("Error serializing hashmap")).expect("Can not dump to file");
|
||||
|
@ -8,6 +8,7 @@ use std::hash::Hasher;
|
||||
use std::hash::Hash;
|
||||
use hashbrown::HashMap;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use itertools::Itertools;
|
||||
|
||||
use freertos::TCB_t;
|
||||
|
||||
@ -452,18 +453,34 @@ impl TaskJob {
|
||||
self.hash_cache
|
||||
}
|
||||
}
|
||||
pub fn try_update(&mut self, other: &mut JobInstance) -> bool {
|
||||
assert_eq!(self.get_hash(), other.get_hash());
|
||||
pub fn try_update(&mut self, other: &JobInstance) -> bool {
|
||||
assert_eq!(self.get_hash(), other.get_hash_cached());
|
||||
let mut ret = false;
|
||||
if other.exec_ticks > self.woet_ticks {
|
||||
self.woet_ticks = other.exec_ticks;
|
||||
self.woet_per_abb = other.ticks_per_abb.clone();
|
||||
other.mem_reads.sort_by(|a,b| a.0.cmp(&b.0));
|
||||
self.worst_bytes = other.mem_reads.iter().map(|x| x.1).collect();
|
||||
self.worst_bytes = other.mem_reads.iter().sorted_by(|a,b| a.0.cmp(&b.0)).map(|x| x.1).collect();
|
||||
ret = true;
|
||||
}
|
||||
ret
|
||||
}
|
||||
pub fn from_instance(input: &JobInstance) -> Self {
|
||||
let c = input.get_hash_cached();
|
||||
Self {
|
||||
name: input.name.clone(),
|
||||
worst_bytes: input.mem_reads.iter().map(|x| x.1.clone()).collect(),
|
||||
woet_ticks: input.exec_ticks,
|
||||
woet_per_abb: input.ticks_per_abb.clone(),
|
||||
abbs: input.abbs.clone(),
|
||||
hash_cache: c
|
||||
}
|
||||
}
|
||||
pub fn map_bytes_onto(&self, input: &JobInstance, offset: Option<u32>) -> Vec<(u32,u8)> {
|
||||
if input.mem_reads.len() == 0 {return vec![];}
|
||||
let ret = input.mem_reads.iter().take(self.worst_bytes.len()).enumerate().filter_map(|(idx,(addr,oldbyte))| if self.worst_bytes[idx]!=*oldbyte {Some((*addr-offset.unwrap_or_default(), self.worst_bytes[idx]))} else {None}).collect();
|
||||
// eprintln!("Mapped: {:?}", ret);
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -9,7 +9,7 @@ use libafl_bolts::{rands::{
|
||||
random_seed, Rand, StdRand
|
||||
}, Named};
|
||||
use libafl::{
|
||||
common::{HasMetadata, HasNamedMetadata}, corpus::{self, Corpus}, events::{Event, EventFirer, LogSeverity}, fuzzer::Evaluator, inputs::{HasMutatorBytes, HasTargetBytes, Input, MultipartInput}, mark_feature_time, prelude::{new_hash_feedback, AggregatorOps, CorpusId, MutationResult, Mutator, UserStats, UserStatsValue, UsesInput}, stages::Stage, start_timer, state::{HasCorpus, HasRand, MaybeHasClientPerfMonitor, UsesState}, Error
|
||||
common::{HasMetadata, HasNamedMetadata}, corpus::{self, Corpus}, events::{Event, EventFirer, EventProcessor, LogSeverity}, fuzzer::Evaluator, inputs::{HasMutatorBytes, HasTargetBytes, Input, MultipartInput}, mark_feature_time, prelude::{new_hash_feedback, AggregatorOps, CorpusId, MutationResult, Mutator, UserStats, UserStatsValue, UsesInput}, stages::Stage, start_timer, state::{HasCorpus, HasRand, MaybeHasClientPerfMonitor, UsesState}, Error
|
||||
};
|
||||
use libafl::prelude::State;
|
||||
use petgraph::{graph::NodeIndex, graph::{self, DiGraph}};
|
||||
@ -19,7 +19,7 @@ use std::borrow::Cow;
|
||||
|
||||
use simple_moving_average::SMA;
|
||||
|
||||
use super::stg::{STGEdge, STGNode};
|
||||
use super::{stg::{STGEdge, STGNode}, JobInstance};
|
||||
|
||||
// pub static mut MINIMUM_INTER_ARRIVAL_TIME : u32 = 1000 /*us*/ * QEMU_ISNS_PER_USEC;
|
||||
// one isn per 2**4 ns
|
||||
@ -88,7 +88,7 @@ pub fn try_force_new_branches(interrupt_ticks : &[u32], fbs: &STGFeedbackState,
|
||||
for (num,&interrupt_time) in interrupt_ticks.iter().enumerate() {
|
||||
let lower_bound = if num==0 {FIRST_INT} else {interrupt_ticks[num-1].saturating_add(config.1 * QEMU_ISNS_PER_USEC)};
|
||||
let next = if interrupt_ticks.len()>num+1 {interrupt_ticks[num+1]} else {u32::MAX};
|
||||
for exec_interval in meta.intervals.iter().filter(|x| x.start_tick >= lower_bound as u64 && x.start_tick < next as u64) {
|
||||
for exec_interval in meta.intervals().iter().filter(|x| x.start_tick >= lower_bound as u64 && x.start_tick < next as u64) {
|
||||
if !(exec_interval.start_capture.0==CaptureEvent::ISRStart) { // shortcut to skip interrupt handers without node lookup
|
||||
let node_index = fbs.state_abb_hash_index.get(&exec_interval.get_hash_index()).unwrap();
|
||||
if !has_interrupt_handler_non_systick(&fbs.graph, node_index.clone()) {
|
||||
@ -306,8 +306,8 @@ where
|
||||
// calculate hits and identify snippets
|
||||
let mut last_m = false;
|
||||
let mut marks : Vec<(&ExecInterval, usize, usize)>= vec![]; // 1: got interrupted, 2: interrupt handler
|
||||
for i in 0..trace.intervals.len() {
|
||||
let curr = &trace.intervals[i];
|
||||
for i in 0..trace.intervals().len() {
|
||||
let curr = &trace.intervals()[i];
|
||||
let m = old_interrupt_times.iter().any(|x| (curr.start_tick..curr.end_tick).contains(&(*x as u64)));
|
||||
if m {
|
||||
marks.push((curr, i, 1));
|
||||
@ -323,7 +323,7 @@ where
|
||||
for i in 0..old_interrupt_times.len() {
|
||||
// bounds based on minimum inter-arrival time
|
||||
let mut lb = FIRST_INT;
|
||||
let mut ub : u32 = trace.intervals[trace.intervals.len()-1].end_tick.try_into().expect("ticks > u32");
|
||||
let mut ub : u32 = trace.intervals()[trace.intervals().len()-1].end_tick.try_into().expect("ticks > u32");
|
||||
if i > 0 {
|
||||
// use the new times, because changes to preceding timings are not accounted for yet
|
||||
lb = u32::saturating_add(new_interrupt_times[i-1], interrup_config.1 * QEMU_ISNS_PER_USEC);
|
||||
@ -453,18 +453,23 @@ where
|
||||
pub fn try_worst_snippets(bytes : &[u8], fbs: &STGFeedbackState, meta: &STGNodeMetadata) -> Option<Vec<u8>> {
|
||||
let mut new = false;
|
||||
let mut ret = Vec::new();
|
||||
for (num,interval) in meta.intervals.iter().enumerate() {
|
||||
for (num,interval) in meta.intervals().iter().enumerate() {
|
||||
todo!();
|
||||
}
|
||||
if new {Some(ret)} else {None}
|
||||
}
|
||||
|
||||
|
||||
static mut num_snippet_stage_execs : u64 = 0;
|
||||
static mut num_snippet_rerun : u64 = 0;
|
||||
static mut num_snippet_success : u64 = 0;
|
||||
|
||||
/// The default mutational stage
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct STGSnippetStage<E, EM, Z> {
|
||||
#[allow(clippy::type_complexity)]
|
||||
phantom: PhantomData<(E, EM, Z)>,
|
||||
input_addr: u32
|
||||
}
|
||||
|
||||
impl<E, EM, Z> STGSnippetStage<E, EM, Z>
|
||||
@ -474,8 +479,36 @@ where
|
||||
Z: Evaluator<E, EM>,
|
||||
Z::State: MaybeHasClientPerfMonitor + HasCorpus + HasRand,
|
||||
{
|
||||
pub fn new() -> Self {
|
||||
Self { phantom: PhantomData }
|
||||
pub fn new(input_addr: u32) -> Self {
|
||||
Self { phantom: PhantomData, input_addr }
|
||||
}
|
||||
}
|
||||
|
||||
impl<E, EM, Z, I> STGSnippetStage<E, EM, Z>
|
||||
where
|
||||
E: UsesState<State = Z::State>,
|
||||
EM: UsesState<State = Z::State>,
|
||||
EM: EventFirer,
|
||||
Z: Evaluator<E, EM>,
|
||||
Z::State: MaybeHasClientPerfMonitor + HasCorpus + HasRand + HasMetadata + HasNamedMetadata,
|
||||
<Z::State as UsesInput>::Input: Input,
|
||||
Z::State: UsesInput<Input = MultipartInput<I>>,
|
||||
I: HasMutatorBytes + Default
|
||||
{
|
||||
fn report_stats(&self, state: &mut <STGSnippetStage<E, EM, Z> as UsesState>::State, manager: &mut EM) {
|
||||
unsafe {
|
||||
let _ = manager.fire(
|
||||
state,
|
||||
Event::UpdateUserStats {
|
||||
name: Cow::from("STGSnippetStage"),
|
||||
value: UserStats::new(
|
||||
UserStatsValue::String(Cow::from(format!("{} -> {}/{} {:.1}% ", num_snippet_stage_execs, num_snippet_success, num_snippet_rerun, num_snippet_success as f32 * 100.0 / num_snippet_rerun as f32))),
|
||||
AggregatorOps::None,
|
||||
),
|
||||
phantom: PhantomData,
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -500,24 +533,46 @@ where
|
||||
let mut myrand = StdRand::new();
|
||||
myrand.set_seed(state.rand_mut().next());
|
||||
|
||||
let mut do_rerun = false;
|
||||
|
||||
let current_case = state.current_testcase()?;
|
||||
let old_input = current_case.input().as_ref().unwrap();
|
||||
let mut new_input = old_input.clone();
|
||||
if let Some(bytes) = old_input.parts_by_name("bytes").next() {
|
||||
let new_bytes = new_input.parts_by_name("bytes").next();
|
||||
if let Some(meta) = current_case.metadata_map().get::<STGNodeMetadata>() {
|
||||
let feedbackstate = match state
|
||||
.named_metadata_map()
|
||||
.get::<STGFeedbackState>("stgfeedbackstate") {
|
||||
Some(s) => s,
|
||||
Option::None => {
|
||||
panic!("STGfeedbackstate not visible")
|
||||
let new_bytes = new_input.parts_by_name_mut("bytes").next().expect("bytes not found in multipart input").1.bytes_mut();
|
||||
// dbg!(current_case.metadata_map());
|
||||
// eprintln!("Run mutator {}", current_case.metadata_map().get::<STGNodeMetadata>().is_some());
|
||||
if let Some(meta) = current_case.metadata_map().get::<STGNodeMetadata>() {
|
||||
let feedbackstate = match state
|
||||
.named_metadata_map()
|
||||
.get::<STGFeedbackState>("stgfeedbackstate") {
|
||||
Some(s) => s,
|
||||
Option::None => {
|
||||
panic!("STGfeedbackstate not visible")
|
||||
}
|
||||
};
|
||||
// Maximize all snippets
|
||||
// dbg!(meta.jobs().len());
|
||||
for jobinst in meta.jobs().iter() {
|
||||
match feedbackstate.worst_task_jobs.get(&jobinst.get_hash_cached()) {
|
||||
Some(worst) => {
|
||||
let new = worst.map_bytes_onto(jobinst, Some(self.input_addr));
|
||||
do_rerun |= new.len() > 0;
|
||||
for (addr, byte) in new {
|
||||
new_bytes[addr as usize] = byte;
|
||||
}
|
||||
};
|
||||
todo!();
|
||||
},
|
||||
Option::None => {}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
drop(current_case);
|
||||
unsafe {num_snippet_stage_execs+=1;}
|
||||
if do_rerun {
|
||||
unsafe {num_snippet_rerun+=1;}
|
||||
let (_, corpus_idx) = fuzzer.evaluate_input(state, executor, manager, new_input)?;
|
||||
if corpus_idx.is_some() { unsafe{num_snippet_success+=1; self.report_stats(state, manager);}}
|
||||
|
||||
} else if {unsafe{num_snippet_stage_execs}} % 5 == 0 {self.report_stats(state, manager);}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -41,9 +41,9 @@ pub struct QemuSystemStateObserver<I>
|
||||
pub last_trace: Vec<ExecInterval>,
|
||||
pub last_reads: Vec<Vec<(u32, u8)>>,
|
||||
pub last_input: I,
|
||||
pub job_instances: Vec<(u64, u64, String)>,
|
||||
pub job_instances: Vec<JobInstance>,
|
||||
pub do_report: bool,
|
||||
pub worst_job_instances: HashMap<String, u64>,
|
||||
pub worst_job_instances: HashMap<String, JobInstance>,
|
||||
pub select_task: Option<String>,
|
||||
pub success: bool,
|
||||
name: Cow<'static, str>,
|
||||
@ -96,18 +96,18 @@ where
|
||||
hash_cache: 0
|
||||
}
|
||||
}).collect::<Vec<_>>();
|
||||
println!("Instances: {:?}",&job_instances);
|
||||
// println!("Instances: {:?}",&job_instances);
|
||||
self.job_instances = job_instances;
|
||||
let observer = &self;
|
||||
let mut worst_case_per_task = HashMap::new();
|
||||
let mut worst_case_per_task : HashMap<String, JobInstance> = HashMap::new();
|
||||
observer.job_instances.iter().for_each(|x| {
|
||||
let time = x.1-x.0;
|
||||
if worst_case_per_task.get(&x.2).is_some() {
|
||||
let old = worst_case_per_task.get_mut(&x.2).unwrap();
|
||||
if time > *old {
|
||||
*old=time;
|
||||
if worst_case_per_task.get(&x.name).is_some() {
|
||||
let old = worst_case_per_task.get_mut(&x.name).unwrap();
|
||||
if x.exec_ticks > old.exec_ticks {
|
||||
old.exec_ticks=x.exec_ticks;
|
||||
}
|
||||
} else {
|
||||
worst_case_per_task.insert(x.2.clone(), time);
|
||||
worst_case_per_task.insert(x.name.clone(), x.clone());
|
||||
}
|
||||
});
|
||||
self.worst_job_instances = worst_case_per_task;
|
||||
@ -160,7 +160,7 @@ where I: Default {
|
||||
Self{last_run: vec![], last_trace: vec![], last_reads: vec![], last_input: I::default(), worst_job_instances: HashMap::new(), do_report: false, select_task: select_task.clone(), name: Cow::from("systemstate".to_string()), last_states: HashMap::new(), success: false, job_instances: vec![]}
|
||||
}
|
||||
pub fn last_runtime(&self) -> u64 {
|
||||
self.select_task.as_ref().map(|x| self.worst_job_instances.get(x).unwrap_or(&0).clone()).unwrap_or(unsafe{libafl_qemu::sys::icount_get_raw()})
|
||||
self.select_task.as_ref().map(|x| self.worst_job_instances.get(x).map(|y| y.response-y.release).unwrap_or(0).clone()).unwrap_or(unsafe{libafl_qemu::sys::icount_get_raw()})
|
||||
}
|
||||
}
|
||||
impl<I> Default for QemuSystemStateObserver<I>
|
||||
|
@ -101,7 +101,7 @@ where
|
||||
.get(idx)?
|
||||
.borrow()
|
||||
.metadata_map()
|
||||
.get::<STGNodeMetadata>().map_or(0, |x| x.nodes.len());
|
||||
.get::<STGNodeMetadata>().map_or(0, |x| x.nodes().len());
|
||||
let m = self.get_update_trace_length(state,l);
|
||||
state.rand_mut().below(m as usize) > l
|
||||
} && state.rand_mut().coinflip(self.skip_non_favored_prob)
|
||||
|
@ -29,8 +29,10 @@ use serde::{Deserialize, Serialize};
|
||||
use super::AtomicBasicBlock;
|
||||
use super::CaptureEvent;
|
||||
use super::ExecInterval;
|
||||
use super::JobInstance;
|
||||
use super::ReducedFreeRTOSSystemState;
|
||||
use super::observers::QemuSystemStateObserver;
|
||||
use super::TaskJob;
|
||||
use petgraph::prelude::DiGraph;
|
||||
use petgraph::graph::NodeIndex;
|
||||
use petgraph::Direction;
|
||||
@ -151,7 +153,9 @@ pub struct STGFeedbackState
|
||||
worst_observed_per_aggegated_path: HashMap<Vec<AtomicBasicBlock>,u64>,
|
||||
worst_observed_per_abb_path: HashMap<u64,u64>,
|
||||
worst_observed_per_stg_path: HashMap<u64,u64>,
|
||||
worst_abb_exec_count: HashMap<AtomicBasicBlock, usize>
|
||||
worst_abb_exec_count: HashMap<AtomicBasicBlock, usize>,
|
||||
// Metadata about job instances
|
||||
pub worst_task_jobs: HashMap<u64, TaskJob>,
|
||||
}
|
||||
|
||||
impl Default for STGFeedbackState {
|
||||
@ -185,7 +189,8 @@ impl Default for STGFeedbackState {
|
||||
worst_observed_per_stg_path: HashMap::new(),
|
||||
worst_abb_exec_count: HashMap::new(),
|
||||
systemstate_index,
|
||||
state_abb_hash_index
|
||||
state_abb_hash_index,
|
||||
worst_task_jobs: HashMap::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -201,17 +206,18 @@ impl Named for STGFeedbackState
|
||||
// Wrapper around Vec<RefinedFreeRTOSSystemState> to attach as Metadata
|
||||
#[derive(Debug, Default, Serialize, Deserialize, Clone)]
|
||||
pub struct STGNodeMetadata {
|
||||
pub nodes: Vec<NodeIndex>,
|
||||
pub edges: Vec<EdgeIndex>,
|
||||
pub abbs: u64,
|
||||
pub aggregate: u64,
|
||||
pub top_abb_counts: Vec<u64>,
|
||||
pub intervals: Vec<ExecInterval>,
|
||||
nodes: Vec<NodeIndex>,
|
||||
edges: Vec<EdgeIndex>,
|
||||
abbs: u64,
|
||||
aggregate: u64,
|
||||
top_abb_counts: Vec<u64>,
|
||||
intervals: Vec<ExecInterval>,
|
||||
jobs: Vec<JobInstance>,
|
||||
indices: Vec<usize>,
|
||||
tcref: isize,
|
||||
}
|
||||
impl STGNodeMetadata {
|
||||
pub fn new(nodes: Vec<NodeIndex>, edges: Vec<EdgeIndex>, abbs: u64, aggregate: u64, top_abb_counts: Vec<u64>, intervals: Vec<ExecInterval>) -> Self{
|
||||
pub fn new(nodes: Vec<NodeIndex>, edges: Vec<EdgeIndex>, abbs: u64, aggregate: u64, top_abb_counts: Vec<u64>, intervals: Vec<ExecInterval>, jobs: Vec<JobInstance>) -> Self {
|
||||
#[allow(unused)]
|
||||
let mut indices : Vec<_> = vec![];
|
||||
#[cfg(all(feature = "sched_stg",not(any(feature = "sched_stg_pathhash",feature = "sched_stg_abbhash",feature = "sched_stg_aggregatehash"))))]
|
||||
@ -233,7 +239,35 @@ impl STGNodeMetadata {
|
||||
// indices.push(aggregate as usize);
|
||||
indices = top_abb_counts.iter().map(|x| (*x) as usize).collect();
|
||||
}
|
||||
Self {indices, intervals, nodes, abbs, aggregate, top_abb_counts, edges, tcref: 0}
|
||||
Self {indices, intervals, jobs, nodes, abbs, aggregate, top_abb_counts, edges, tcref: 0}
|
||||
}
|
||||
|
||||
pub fn nodes(&self) -> &Vec<NodeIndex> {
|
||||
&self.nodes
|
||||
}
|
||||
|
||||
pub fn edges(&self) -> &Vec<EdgeIndex> {
|
||||
&self.edges
|
||||
}
|
||||
|
||||
pub fn abbs(&self) -> u64 {
|
||||
self.abbs
|
||||
}
|
||||
|
||||
pub fn aggregate(&self) -> u64 {
|
||||
self.aggregate
|
||||
}
|
||||
|
||||
pub fn top_abb_counts(&self) -> &Vec<u64> {
|
||||
&self.top_abb_counts
|
||||
}
|
||||
|
||||
pub fn intervals(&self) -> &Vec<ExecInterval> {
|
||||
&self.intervals
|
||||
}
|
||||
|
||||
pub fn jobs(&self) -> &Vec<JobInstance> {
|
||||
&self.jobs
|
||||
}
|
||||
}
|
||||
|
||||
@ -317,6 +351,7 @@ pub struct StgFeedback
|
||||
last_abbs_hash: Option<u64>, // only set, if it was interesting
|
||||
last_aggregate_hash: Option<u64>, // only set, if it was interesting
|
||||
last_top_abb_hashes: Option<Vec<u64>>, // only set, if it was interesting
|
||||
last_job_trace: Option<Vec<JobInstance>>, // only set, if it was interesting
|
||||
dump_path: Option<PathBuf>
|
||||
}
|
||||
#[cfg(feature = "feed_stg")]
|
||||
@ -340,6 +375,9 @@ const INTEREST_PATH : bool = false;
|
||||
const INTEREST_ABBPATH : bool = false;
|
||||
#[cfg(not(feature = "feed_stg_aggregatehash"))]
|
||||
const INTEREST_AGGREGATE : bool = false;
|
||||
|
||||
const INTEREST_JOB_INSTANCE : bool = true;
|
||||
|
||||
fn set_observer_map(trace : &Vec<EdgeIndex>) {
|
||||
unsafe {
|
||||
for i in 0..MAX_STG_NUM {
|
||||
@ -526,8 +564,23 @@ where
|
||||
}
|
||||
};
|
||||
|
||||
// --------------------------------- Update STG
|
||||
let (nodetrace, edgetrace, mut interesting, mut updated) = StgFeedback::update_stg_interval(&observer.last_trace, &observer.last_reads, &observer.last_states, feedbackstate);
|
||||
|
||||
// --------------------------------- Update job instances
|
||||
for i in observer.worst_job_instances.iter() {
|
||||
interesting |= INTEREST_JOB_INSTANCE && if let Some(x) = feedbackstate.worst_task_jobs.get_mut(&i.1.get_hash_cached()) {
|
||||
// eprintln!("Job instance already present");
|
||||
x.try_update(i.1)
|
||||
} else {
|
||||
// eprintln!("New Job instance");
|
||||
feedbackstate.worst_task_jobs.insert(i.1.get_hash_cached(), TaskJob::from_instance(&i.1));
|
||||
true
|
||||
}
|
||||
};
|
||||
self.last_job_trace = Some(observer.job_instances.clone());
|
||||
// dbg!(&observer.job_instances);
|
||||
|
||||
{
|
||||
let h = get_generic_hash(&edgetrace);
|
||||
if let Some(x) = feedbackstate.worst_observed_per_stg_path.get_mut(&h) {
|
||||
@ -547,8 +600,8 @@ where
|
||||
let tmp = StgFeedback::abbs_in_exec_order(&observer.last_trace);
|
||||
#[cfg(feature = "trace_job_response_times")]
|
||||
let tmp = {
|
||||
if let Some(worst_instance) = observer.job_instances.iter().filter(|x| Some(x.2.clone()) == observer.select_task).max_by(|a,b| (a.1-a.0).cmp(&(b.1-b.0))) {
|
||||
let t = observer.last_trace.iter().filter(|x| x.start_tick < worst_instance.1 && x.end_tick > worst_instance.0 ).cloned().collect();
|
||||
if let Some(worst_instance) = observer.job_instances.iter().filter(|x| Some(x.name.clone()) == observer.select_task).max_by(|a,b| (a.response-a.release).cmp(&(b.response-b.release))) {
|
||||
let t = observer.last_trace.iter().filter(|x| x.start_tick < worst_instance.response && x.end_tick > worst_instance.release ).cloned().collect();
|
||||
StgFeedback::abbs_in_exec_order(&t)
|
||||
} else {
|
||||
if observer.select_task.is_none() { // if nothing was selected, just take the whole trace, otherwise there is nothing interesting here
|
||||
@ -633,12 +686,8 @@ where
|
||||
/// Append to the testcase the generated metadata in case of a new corpus item
|
||||
#[inline]
|
||||
fn append_metadata<EM, OT>(&mut self, _state: &mut S, _manager: &mut EM, _observers: &OT, testcase: &mut Testcase<S::Input>) -> Result<(), Error> {
|
||||
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_abbs_hash.take().unwrap_or_default(), self.last_aggregate_hash.take().unwrap_or_default(), self.last_top_abb_hashes.take().unwrap_or_default(), self.last_intervals.take().unwrap())),
|
||||
Option::None => (),
|
||||
}
|
||||
let meta = STGNodeMetadata::new(self.last_node_trace.take().unwrap_or_default(), self.last_edge_trace.take().unwrap_or_default(), self.last_abbs_hash.take().unwrap_or_default(), self.last_aggregate_hash.take().unwrap_or_default(), self.last_top_abb_hashes.take().unwrap_or_default(), self.last_intervals.take().unwrap_or_default(), self.last_job_trace.take().unwrap_or_default());
|
||||
testcase.metadata_map_mut().insert(meta);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -342,7 +342,7 @@ where
|
||||
.map
|
||||
.insert(elem, idx);
|
||||
}
|
||||
println!("Number of interesting corpus elements: {}", state.metadata_map_mut().get::<TopRatedsMetadata>().unwrap().get_number());
|
||||
// println!("Number of interesting corpus elements: {}", state.metadata_map_mut().get::<TopRatedsMetadata>().unwrap().get_number());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user