diff --git a/fuzzers/wcet_qemu_sys/Cargo.toml b/fuzzers/wcet_qemu_sys/Cargo.toml index da6876e87e..15e4ab7942 100644 --- a/fuzzers/wcet_qemu_sys/Cargo.toml +++ b/fuzzers/wcet_qemu_sys/Cargo.toml @@ -23,3 +23,4 @@ nix = "0.23.0" goblin = "0.4.2" either = "1.6.1" num-traits = "0.2" +petgraph = { version="0.6.0", features = ["serde-1"] } \ No newline at end of file diff --git a/fuzzers/wcet_qemu_sys/src/sysstate/feedbacks.rs b/fuzzers/wcet_qemu_sys/src/sysstate/feedbacks.rs index fee5317482..2bf7c143e8 100644 --- a/fuzzers/wcet_qemu_sys/src/sysstate/feedbacks.rs +++ b/fuzzers/wcet_qemu_sys/src/sysstate/feedbacks.rs @@ -19,6 +19,138 @@ use serde::{Deserialize, Serialize}; use super::MiniFreeRTOSSystemState; use super::FreeRTOSSystemStateMetadata; use super::observers::QemuSysStateObserver; +use petgraph::prelude::DiGraph; +use petgraph::graph::NodeIndex; +use petgraph::Direction; +use std::cmp::Ordering; + +//============================= Graph Feedback + +/// Improved System State Graph +#[derive(Serialize, Deserialize, Clone, Debug, Default)] +pub struct SysMapFeedbackState +{ + graph: DiGraph, + entrypoint: NodeIndex, + name: String, +} +impl SysMapFeedbackState +{ + pub fn new() -> Self { + let mut graph = DiGraph::::new(); + let ind = graph.add_node(MiniFreeRTOSSystemState::default()); + Self {graph: graph, entrypoint: ind, name: String::from("SysMap")} + } + fn insert(&mut self, list: Vec) { + let mut current_index = self.entrypoint; + for n in list { + let mut done = false; + for i in self.graph.neighbors_directed(current_index, Direction::Outgoing) { + if n == self.graph[i] { + done = true; + current_index = i; + break; + } + } + if !done { + let j = self.graph.add_node(n); + self.graph.add_edge(current_index, j, ()); + current_index = j; + } + } + } + fn update(&mut self, list: &Vec) -> bool { + let mut current_index = self.entrypoint; + let mut novel = false; + for n in list { + let mut matching : Option = None; + for i in self.graph.neighbors_directed(current_index, Direction::Outgoing) { + let tmp = &self.graph[i]; + if n == tmp { + matching = Some(i); + current_index = i; + break; + } + } + match matching { + None => { + novel = true; + let j = self.graph.add_node(n.clone()); + self.graph.add_edge(current_index, j, ()); + current_index = j; + }, + Some(i) => { + if n.get_time() > self.graph[i].get_time() { + novel = true; + self.graph[i]=n.clone(); + } + } + } + } + return novel; + } +} +impl Named for SysMapFeedbackState +{ + #[inline] + fn name(&self) -> &str { + &self.name + } +} +impl FeedbackState for SysMapFeedbackState +{ + fn reset(&mut self) -> Result<(), Error> { + self.graph.clear(); + self.entrypoint = self.graph.add_node(MiniFreeRTOSSystemState::default()); + Ok(()) + } +} + +/// A Feedback reporting novel System-State Transitions. Depends on [`QemuSysStateObserver`] +#[derive(Serialize, Deserialize, Clone, Debug, Default)] +pub struct SysMapFeedback +{ + name: String +} +impl SysMapFeedback { + pub fn new() -> Self { + Self {name: String::from("SysMapFeedback") } + } +} + +impl Feedback for SysMapFeedback +where + I: Input, + S: HasClientPerfMonitor + HasFeedbackStates, +{ + fn is_interesting( + &mut self, + state: &mut S, + _manager: &mut EM, + _input: &I, + observers: &OT, + _exit_kind: &ExitKind, + ) -> Result + where + EM: EventFirer, + OT: ObserversTuple, + { + let observer = observers.match_name::("sysstate") + .expect("QemuSysStateObserver not found"); + let feedbackstate = state + .feedback_states_mut() + .match_name_mut::("SysMap") + .unwrap(); + Ok(feedbackstate.update(&observer.last_run)) + } +} +impl Named for SysMapFeedback +{ + #[inline] + fn name(&self) -> &str { + &self.name + } +} //============================= Feedback diff --git a/fuzzers/wcet_qemu_sys/src/sysstate/mod.rs b/fuzzers/wcet_qemu_sys/src/sysstate/mod.rs index 1fb8d69692..af2ca9b0ae 100644 --- a/fuzzers/wcet_qemu_sys/src/sysstate/mod.rs +++ b/fuzzers/wcet_qemu_sys/src/sysstate/mod.rs @@ -30,7 +30,7 @@ pub struct FreeRTOSSystemStateRaw { static mut CURRENT_SYSSTATE_VEC: Vec = vec![]; /// A reduced version of freertos::TCB_t -#[derive(Debug, Default, Serialize, Deserialize, Clone)] +#[derive(Debug, Default, Serialize, Deserialize, Clone, PartialEq)] pub struct MiniTCB { task_name: String, priority: u32, @@ -89,6 +89,11 @@ pub struct MiniFreeRTOSSystemState { current_task: MiniTCB, ready_list_after: Vec, } +impl PartialEq for MiniFreeRTOSSystemState { + fn eq(&self, other: &Self) -> bool { + self.current_task == other.current_task && self.ready_list_after == other.ready_list_after + } +} impl Hash for MiniFreeRTOSSystemState { fn hash(&self, state: &mut H) { @@ -96,6 +101,11 @@ impl Hash for MiniFreeRTOSSystemState { // self.ready_list_after.hash(state); } } +impl MiniFreeRTOSSystemState { + fn get_time(&self) -> u64 { + self.end_tick-self.start_tick + } +} // Wrapper around Vec to attach as Metadata #[derive(Debug, Default, Serialize, Deserialize, Clone)]