add interesting metrics, reorganize

This commit is contained in:
Alwin Berger 2022-03-20 21:29:25 +01:00
parent 1d0c43081a
commit c92cbe78d8
6 changed files with 269 additions and 207 deletions

View File

@ -1,8 +1,10 @@
//! A singlethreaded QEMU fuzzer that can auto-restart. //! A singlethreaded QEMU fuzzer that can auto-restart.
use wcet_qemu_sys::sysstate::graph::SysMapFeedback;
use wcet_qemu_sys::sysstate::graph::SysGraphFeedbackState;
use libafl::stats::SimpleStats; use libafl::stats::SimpleStats;
use wcet_qemu_sys::sysstate::feedbacks::HitSysStateFeedback; use wcet_qemu_sys::sysstate::feedbacks::HitSysStateFeedback;
use wcet_qemu_sys::sysstate::MiniFreeRTOSSystemState; use wcet_qemu_sys::sysstate::RefinedFreeRTOSSystemState;
use libafl::corpus::QueueCorpusScheduler; use libafl::corpus::QueueCorpusScheduler;
use libafl_qemu::QemuInstrumentationFilter; use libafl_qemu::QemuInstrumentationFilter;
use wcet_qemu_sys::sysstate::helpers::QemuSystemStateHelper; use wcet_qemu_sys::sysstate::helpers::QemuSystemStateHelper;
@ -330,7 +332,8 @@ fn fuzz(
let feedback_state = MapFeedbackState::with_observer(&edges_observer); let feedback_state = MapFeedbackState::with_observer(&edges_observer);
let sysstate_observer = QemuSysStateObserver::new(); let sysstate_observer = QemuSysStateObserver::new();
let sysstate_feedback_state = SysStateFeedbackState::default(); // let sysstate_feedback_state = SysStateFeedbackState::default();
let sysstate_feedback_state = SysGraphFeedbackState::new();
let target_map : HashMap<(u64,u64),u8> = match dump_edges { let target_map : HashMap<(u64,u64),u8> = match dump_edges {
None => HashMap::new(), None => HashMap::new(),
@ -340,11 +343,11 @@ fn fuzz(
hmap hmap
}, },
}; };
let target_trace : Option<Vec<MiniFreeRTOSSystemState>> = match dump_traces { let target_trace : Option<Vec<RefinedFreeRTOSSystemState>> = match dump_traces {
None => None, None => None,
Some(ref s) => { Some(ref s) => {
let raw = fs::read(s).expect("Can not read dumped traces"); let raw = fs::read(s).expect("Can not read dumped traces");
let trace : Vec<MiniFreeRTOSSystemState> = ron::from_str(&String::from_utf8_lossy(&raw)).expect("Can not parse traces"); let trace : Vec<RefinedFreeRTOSSystemState> = ron::from_str(&String::from_utf8_lossy(&raw)).expect("Can not parse traces");
Some(trace) Some(trace)
}, },
}; };
@ -353,14 +356,16 @@ fn fuzz(
let feedback = feedback_or!( let feedback = feedback_or!(
// New maximization map feedback linked to the edges observer and the feedback state // New maximization map feedback linked to the edges observer and the feedback state
MaxMapFeedback::new_tracking(&feedback_state, &edges_observer, true, false), MaxMapFeedback::new_tracking(&feedback_state, &edges_observer, true, false),
HitImprovingFeedback::new(target_map.clone(), &edges_observer), // HitImprovingFeedback::new(target_map.clone(), &edges_observer),
QemuClockIncreaseFeedback::default(), // QemuClockIncreaseFeedback::default(),
ClockFeedback::new_with_observer(&clock_observer), ClockFeedback::new_with_observer(&clock_observer),
NovelSysStateFeedback::default() // NovelSysStateFeedback::default(),
SysMapFeedback::new()
); );
// A feedback to choose if an input is a solution or not // A feedback to choose if an input is a solution or not
let objective = feedback_or!(HitFeedback::new(target_map,0.0,&edges_observer),HitSysStateFeedback::new(target_trace)); // let objective = feedback_or!(HitFeedback::new(target_map,0.0,&edges_observer),HitSysStateFeedback::new(target_trace));
let objective = feedback_or!(HitFeedback::new(target_map,0.0,&edges_observer));
// let objective = SortedFeedback::new(); // let objective = SortedFeedback::new();
// create a State from scratch // create a State from scratch
@ -392,8 +397,8 @@ fn fuzz(
// A minimization+queue policy to get testcasess from the corpus // A minimization+queue policy to get testcasess from the corpus
// let scheduler = IndexesLenTimeMinimizerCorpusScheduler::new(PowerQueueCorpusScheduler::new()); // let scheduler = IndexesLenTimeMinimizerCorpusScheduler::new(PowerQueueCorpusScheduler::new());
let scheduler = TimeStateMaximizerCorpusScheduler::new(QueueCorpusScheduler::new()); // let scheduler = TimeStateMaximizerCorpusScheduler::new(QueueCorpusScheduler::new());
// let scheduler = QueueCorpusScheduler::new(); let scheduler = QueueCorpusScheduler::new();
// A fuzzer with feedbacks and a corpus scheduler // A fuzzer with feedbacks and a corpus scheduler

View File

@ -18,7 +18,7 @@ use hashbrown::HashMap;
use libafl::{executors::ExitKind, inputs::Input, observers::ObserversTuple, state::HasMetadata}; use libafl::{executors::ExitKind, inputs::Input, observers::ObserversTuple, state::HasMetadata};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use super::MiniFreeRTOSSystemState; use super::RefinedFreeRTOSSystemState;
use super::FreeRTOSSystemStateMetadata; use super::FreeRTOSSystemStateMetadata;
use super::observers::QemuSysStateObserver; use super::observers::QemuSysStateObserver;
use petgraph::prelude::DiGraph; use petgraph::prelude::DiGraph;
@ -26,170 +26,6 @@ use petgraph::graph::NodeIndex;
use petgraph::Direction; use petgraph::Direction;
use std::cmp::Ordering; use std::cmp::Ordering;
//============================= Graph Feedback
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Default)]
struct VariantTuple
{
start_tick: u64,
end_tick: u64,
input_counter: u32,
input: Vec<u8>, // in the end any kind of input are bytes, regardless of type and lifetime
}
#[derive(Serialize, Deserialize, Clone, Debug, Default)]
struct SysGraphNode
{
base: MiniFreeRTOSSystemState,
variants: Vec<VariantTuple>,
}
impl SysGraphNode {
fn from(base: MiniFreeRTOSSystemState, input: Vec<u8>) -> Self {
SysGraphNode{variants: vec![VariantTuple{
start_tick: base.start_tick,
end_tick: base.end_tick,
input_counter: base.input_counter,
input:input}], base:base }
}
/// unites the variants of this value with another, draining the other if the bases are equal
fn unite(mut self, other: &mut SysGraphNode) -> bool {
if &self!=other {return false;}
self.variants.append(&mut other.variants);
self.variants.dedup();
return true;
}
}
impl PartialEq for SysGraphNode {
fn eq(&self, other: &SysGraphNode) -> bool {
self.base==other.base
}
}
/// Improved System State Graph
#[derive(Serialize, Deserialize, Clone, Debug, Default)]
pub struct SysMapFeedbackState
{
graph: DiGraph<SysGraphNode, ()>,
entrypoint: NodeIndex,
name: String,
}
impl SysMapFeedbackState
{
pub fn new() -> Self {
let mut graph = DiGraph::<SysGraphNode, ()>::new();
let ind = graph.add_node(SysGraphNode::default());
Self {graph: graph, entrypoint: ind, name: String::from("SysMap")}
}
fn insert(&mut self, list: Vec<MiniFreeRTOSSystemState>, input: &Vec<u8>) {
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].base {
done = true;
current_index = i;
break;
}
}
if !done {
let j = self.graph.add_node(SysGraphNode::from(n,input.clone()));
self.graph.add_edge(current_index, j, ());
current_index = j;
}
}
}
fn update(&mut self, list: &Vec<MiniFreeRTOSSystemState>, input: &Vec<u8>) -> bool {
let mut current_index = self.entrypoint;
let mut novel = false;
for n in list {
let mut matching : Option<NodeIndex> = None;
for i in self.graph.neighbors_directed(current_index, Direction::Outgoing) {
let tmp = &self.graph[i];
if n == &tmp.base {
matching = Some(i);
current_index = i;
break;
}
}
match matching {
None => {
novel = true;
let j = self.graph.add_node(SysGraphNode::from(n.clone(),input.clone()));
self.graph.add_edge(current_index, j, ());
current_index = j;
},
Some(i) => {
if n.get_time() > self.graph[i].base.get_time() {
novel = true;
self.graph[i]=SysGraphNode::from(n.clone(),input.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(SysGraphNode::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<I, S> Feedback<I, S> for SysMapFeedback
where
I: Input,
S: HasClientPerfMonitor + HasFeedbackStates,
{
fn is_interesting<EM, OT>(
&mut self,
state: &mut S,
_manager: &mut EM,
_input: &I,
observers: &OT,
_exit_kind: &ExitKind,
) -> Result<bool, Error>
where
EM: EventFirer<I>,
OT: ObserversTuple<I, S>,
{
let observer = observers.match_name::<QemuSysStateObserver>("sysstate")
.expect("QemuSysStateObserver not found");
let feedbackstate = state
.feedback_states_mut()
.match_name_mut::<SysMapFeedbackState>("SysMap")
.unwrap();
Ok(feedbackstate.update(&observer.last_run, &observer.last_input))
}
}
impl Named for SysMapFeedback
{
#[inline]
fn name(&self) -> &str {
&self.name
}
}
//============================= Feedback //============================= Feedback
/// Shared Metadata for a SysStateFeedback /// Shared Metadata for a SysStateFeedback
@ -197,7 +33,7 @@ impl Named for SysMapFeedback
pub struct SysStateFeedbackState pub struct SysStateFeedbackState
{ {
known_traces: HashMap<u64,(u64,u64,usize)>, // encounters,ticks,length known_traces: HashMap<u64,(u64,u64,usize)>, // encounters,ticks,length
longest: Vec<MiniFreeRTOSSystemState>, longest: Vec<RefinedFreeRTOSSystemState>,
} }
impl Named for SysStateFeedbackState impl Named for SysStateFeedbackState
{ {
@ -219,7 +55,7 @@ impl FeedbackState for SysStateFeedbackState
#[derive(Serialize, Deserialize, Clone, Debug, Default)] #[derive(Serialize, Deserialize, Clone, Debug, Default)]
pub struct NovelSysStateFeedback pub struct NovelSysStateFeedback
{ {
last_trace: Option<Vec<MiniFreeRTOSSystemState>>, last_trace: Option<Vec<RefinedFreeRTOSSystemState>>,
// known_traces: HashMap<u64,(u64,usize)>, // known_traces: HashMap<u64,(u64,usize)>,
} }
@ -304,7 +140,7 @@ impl Named for NovelSysStateFeedback
//============================= //=============================
pub fn match_traces(target: &Vec<MiniFreeRTOSSystemState>, last: &Vec<MiniFreeRTOSSystemState>) -> bool { pub fn match_traces(target: &Vec<RefinedFreeRTOSSystemState>, last: &Vec<RefinedFreeRTOSSystemState>) -> bool {
let mut ret = true; let mut ret = true;
if target.len() > last.len() {return false;} if target.len() > last.len() {return false;}
for i in 0..target.len() { for i in 0..target.len() {
@ -312,7 +148,7 @@ pub fn match_traces(target: &Vec<MiniFreeRTOSSystemState>, last: &Vec<MiniFreeRT
} }
ret ret
} }
pub fn match_traces_name(target: &Vec<String>, last: &Vec<MiniFreeRTOSSystemState>) -> bool { pub fn match_traces_name(target: &Vec<String>, last: &Vec<RefinedFreeRTOSSystemState>) -> bool {
let mut ret = true; let mut ret = true;
if target.len() > last.len() {return false;} if target.len() > last.len() {return false;}
for i in 0..target.len() { for i in 0..target.len() {
@ -367,7 +203,7 @@ impl Named for HitSysStateFeedback
} }
impl HitSysStateFeedback { impl HitSysStateFeedback {
pub fn new(target: Option<Vec<MiniFreeRTOSSystemState>>) -> Self { pub fn new(target: Option<Vec<RefinedFreeRTOSSystemState>>) -> Self {
Self {target: target.map(|x| x.into_iter().map(|y| y.current_task.task_name).collect())} Self {target: target.map(|x| x.into_iter().map(|y| y.current_task.task_name).collect())}
} }
} }

View File

@ -0,0 +1,220 @@
/// Feedbacks organizing SystemStates as a graph
use libafl::bolts::ownedref::OwnedSlice;
use libafl::inputs::BytesInput;
use std::path::PathBuf;
use libafl_qemu::QemuClockObserver;
use libafl::feedbacks::FeedbackState;
use libafl::corpus::Testcase;
use libafl::state::HasFeedbackStates;
use libafl::bolts::tuples::MatchName;
use std::collections::hash_map::DefaultHasher;
use std::hash::Hasher;
use std::hash::Hash;
use libafl::events::EventFirer;
use libafl::state::HasClientPerfMonitor;
use libafl::feedbacks::Feedback;
use libafl::bolts::tuples::Named;
use libafl::Error;
use hashbrown::HashMap;
use libafl::{executors::ExitKind, inputs::Input, observers::ObserversTuple, state::HasMetadata};
use serde::{Deserialize, Serialize};
use super::RefinedFreeRTOSSystemState;
use super::FreeRTOSSystemStateMetadata;
use super::observers::QemuSysStateObserver;
use petgraph::prelude::DiGraph;
use petgraph::graph::NodeIndex;
use petgraph::Direction;
use std::cmp::Ordering;
//============================= Data Structures
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Default)]
struct VariantTuple
{
start_tick: u64,
end_tick: u64,
input_counter: u32,
input: Vec<u8>, // in the end any kind of input are bytes, regardless of type and lifetime
}
impl VariantTuple {
fn from(other: &RefinedFreeRTOSSystemState,input: Vec<u8>) -> Self {
VariantTuple{
start_tick: other.start_tick,
end_tick: other.end_tick,
input_counter: other.input_counter,
input: input,
}
}
}
#[derive(Serialize, Deserialize, Clone, Debug, Default)]
struct SysGraphNode
{
base: RefinedFreeRTOSSystemState,
variants: Vec<VariantTuple>,
}
impl SysGraphNode {
fn from(base: RefinedFreeRTOSSystemState, input: Vec<u8>) -> Self {
SysGraphNode{variants: vec![VariantTuple::from(&base, input)], base:base }
}
/// unites the variants of this value with another, draining the other if the bases are equal
fn unite(&mut self, other: &mut SysGraphNode) -> bool {
if self!=other {return false;}
self.variants.append(&mut other.variants);
self.variants.dedup();
return true;
}
/// add a Varint from a [`RefinedFreeRTOSSystemState`]
fn unite_raw(&mut self, other: &RefinedFreeRTOSSystemState, input: &Vec<u8>) -> bool {
if &self.base!=other {return false;}
self.variants.push(VariantTuple::from(other, input.clone()));
self.variants.dedup();
return true;
}
/// add a Varint from a [`RefinedFreeRTOSSystemState`], if it's interesting
fn unite_interesting(&mut self, other: &RefinedFreeRTOSSystemState, input: &Vec<u8>) -> bool {
if &self.base!=other {return false;}
let interesting =
self.variants.iter().all(|x| x.end_tick-x.start_tick<other.end_tick-other.start_tick) || // longest variant
self.variants.iter().all(|x| x.end_tick-x.start_tick>other.end_tick-other.start_tick) || // shortest variant
self.variants.iter().all(|x| x.input_counter>other.input_counter) || // longest input
self.variants.iter().all(|x| x.input_counter<other.input_counter); // shortest input
if interesting {
let var = VariantTuple::from(other, input.clone());
self.variants.push(var);
}
return interesting;
}
}
impl PartialEq for SysGraphNode {
fn eq(&self, other: &SysGraphNode) -> bool {
self.base==other.base
}
}
//============================= Graph Feedback
/// Improved System State Graph
#[derive(Serialize, Deserialize, Clone, Debug, Default)]
pub struct SysGraphFeedbackState
{
graph: DiGraph<SysGraphNode, ()>,
entrypoint: NodeIndex,
name: String,
}
impl SysGraphFeedbackState
{
pub fn new() -> Self {
let mut graph = DiGraph::<SysGraphNode, ()>::new();
let ind = graph.add_node(SysGraphNode::default());
Self {graph: graph, entrypoint: ind, name: String::from("SysMap")}
}
fn insert(&mut self, list: Vec<RefinedFreeRTOSSystemState>, input: &Vec<u8>) {
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].base {
done = true;
current_index = i;
break;
}
}
if !done {
let j = self.graph.add_node(SysGraphNode::from(n,input.clone()));
self.graph.add_edge(current_index, j, ());
current_index = j;
}
}
}
/// Try adding a system state path from a [Vec<RefinedFreeRTOSSystemState>], return true if the path was interesting
fn update(&mut self, list: &Vec<RefinedFreeRTOSSystemState>, input: &Vec<u8>) -> bool {
let mut current_index = self.entrypoint;
let mut novel = false;
for n in list {
let mut matching : Option<NodeIndex> = None;
for i in self.graph.neighbors_directed(current_index, Direction::Outgoing) {
let tmp = &self.graph[i];
if n == &tmp.base {
matching = Some(i);
current_index = i;
break;
}
}
match matching {
None => {
novel = true;
let j = self.graph.add_node(SysGraphNode::from(n.clone(),input.clone()));
self.graph.add_edge(current_index, j, ());
current_index = j;
},
Some(i) => {
novel |= self.graph[i].unite_interesting(&n, input);
}
}
}
return novel;
}
}
impl Named for SysGraphFeedbackState
{
#[inline]
fn name(&self) -> &str {
&self.name
}
}
impl FeedbackState for SysGraphFeedbackState
{
fn reset(&mut self) -> Result<(), Error> {
self.graph.clear();
self.entrypoint = self.graph.add_node(SysGraphNode::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<I, S> Feedback<I, S> for SysMapFeedback
where
I: Input,
S: HasClientPerfMonitor + HasFeedbackStates,
{
fn is_interesting<EM, OT>(
&mut self,
state: &mut S,
_manager: &mut EM,
_input: &I,
observers: &OT,
_exit_kind: &ExitKind,
) -> Result<bool, Error>
where
EM: EventFirer<I>,
OT: ObserversTuple<I, S>,
{
let observer = observers.match_name::<QemuSysStateObserver>("sysstate")
.expect("QemuSysStateObserver not found");
let feedbackstate = state
.feedback_states_mut()
.match_name_mut::<SysGraphFeedbackState>("SysMap")
.unwrap();
Ok(feedbackstate.update(&observer.last_run, &observer.last_input))
}
}
impl Named for SysMapFeedback
{
#[inline]
fn name(&self) -> &str {
&self.name
}
}

View File

@ -1,4 +1,4 @@
use crate::sysstate::FreeRTOSSystemStateRaw; use crate::sysstate::RawFreeRTOSSystemState;
use crate::sysstate::CURRENT_SYSSTATE_VEC; use crate::sysstate::CURRENT_SYSSTATE_VEC;
use crate::sysstate::NUM_PRIOS; use crate::sysstate::NUM_PRIOS;
use super::freertos::TCB_t; use super::freertos::TCB_t;
@ -91,7 +91,7 @@ where
return; return;
} }
let listbytes : u32 = u32::try_from(std::mem::size_of::<freertos::List_t>()).unwrap(); let listbytes : u32 = u32::try_from(std::mem::size_of::<freertos::List_t>()).unwrap();
let mut sysstate = FreeRTOSSystemStateRaw::default(); let mut sysstate = RawFreeRTOSSystemState::default();
sysstate.qemu_tick = emulator.get_ticks(); sysstate.qemu_tick = emulator.get_ticks();
let mut buf : [u8; 4] = [0,0,0,0]; let mut buf : [u8; 4] = [0,0,0,0];
unsafe { emulator.read_mem(h.input_counter.into(), &mut buf) }; unsafe { emulator.read_mem(h.input_counter.into(), &mut buf) };

View File

@ -13,6 +13,7 @@ pub mod freertos;
pub mod helpers; pub mod helpers;
pub mod observers; pub mod observers;
pub mod feedbacks; pub mod feedbacks;
pub mod graph;
// Constants // Constants
const NUM_PRIOS: usize = 5; const NUM_PRIOS: usize = 5;
@ -20,7 +21,7 @@ const NUM_PRIOS: usize = 5;
//============================= Struct definitions //============================= Struct definitions
/// Raw info Dump from Qemu /// Raw info Dump from Qemu
#[derive(Debug, Default, Serialize, Deserialize)] #[derive(Debug, Default, Serialize, Deserialize)]
pub struct FreeRTOSSystemStateRaw { pub struct RawFreeRTOSSystemState {
qemu_tick: u64, qemu_tick: u64,
current_tcb: TCB_t, current_tcb: TCB_t,
prio_ready_lists: [freertos::List_t; NUM_PRIOS], prio_ready_lists: [freertos::List_t; NUM_PRIOS],
@ -28,11 +29,11 @@ pub struct FreeRTOSSystemStateRaw {
input_counter: u32, input_counter: u32,
} }
/// List of system state dumps from QemuHelpers /// List of system state dumps from QemuHelpers
static mut CURRENT_SYSSTATE_VEC: Vec<FreeRTOSSystemStateRaw> = vec![]; static mut CURRENT_SYSSTATE_VEC: Vec<RawFreeRTOSSystemState> = vec![];
/// A reduced version of freertos::TCB_t /// A reduced version of freertos::TCB_t
#[derive(Debug, Default, Serialize, Deserialize, Clone, PartialEq)] #[derive(Debug, Default, Serialize, Deserialize, Clone, PartialEq)]
pub struct MiniTCB { pub struct RefinedTCB {
task_name: String, task_name: String,
priority: u32, priority: u32,
base_priority: u32, base_priority: u32,
@ -41,7 +42,7 @@ pub struct MiniTCB {
notify_state: u8, notify_state: u8,
} }
impl Hash for MiniTCB { impl Hash for RefinedTCB {
fn hash<H: Hasher>(&self, state: &mut H) { fn hash<H: Hasher>(&self, state: &mut H) {
self.task_name.hash(state); self.task_name.hash(state);
// self.priority.hash(state); // self.priority.hash(state);
@ -51,7 +52,7 @@ impl Hash for MiniTCB {
} }
} }
impl MiniTCB { impl RefinedTCB {
pub fn from_tcb(input: &TCB_t) -> Self { pub fn from_tcb(input: &TCB_t) -> Self {
unsafe { unsafe {
let tmp = std::mem::transmute::<[i8; 10],[u8; 10]>(input.pcTaskName); let tmp = std::mem::transmute::<[i8; 10],[u8; 10]>(input.pcTaskName);
@ -84,40 +85,40 @@ impl MiniTCB {
/// Refined information about the states an execution transitioned between /// Refined information about the states an execution transitioned between
#[derive(Debug, Default, Serialize, Deserialize, Clone)] #[derive(Debug, Default, Serialize, Deserialize, Clone)]
pub struct MiniFreeRTOSSystemState { pub struct RefinedFreeRTOSSystemState {
start_tick: u64, start_tick: u64,
end_tick: u64, end_tick: u64,
input_counter: u32, input_counter: u32,
current_task: MiniTCB, current_task: RefinedTCB,
ready_list_after: Vec<MiniTCB>, ready_list_after: Vec<RefinedTCB>,
} }
impl PartialEq for MiniFreeRTOSSystemState { impl PartialEq for RefinedFreeRTOSSystemState {
fn eq(&self, other: &Self) -> bool { fn eq(&self, other: &Self) -> bool {
self.current_task == other.current_task && self.ready_list_after == other.ready_list_after self.current_task == other.current_task && self.ready_list_after == other.ready_list_after
} }
} }
impl Hash for MiniFreeRTOSSystemState { impl Hash for RefinedFreeRTOSSystemState {
fn hash<H: Hasher>(&self, state: &mut H) { fn hash<H: Hasher>(&self, state: &mut H) {
self.current_task.hash(state); self.current_task.hash(state);
// self.ready_list_after.hash(state); self.ready_list_after.hash(state);
} }
} }
impl MiniFreeRTOSSystemState { impl RefinedFreeRTOSSystemState {
fn get_time(&self) -> u64 { fn get_time(&self) -> u64 {
self.end_tick-self.start_tick self.end_tick-self.start_tick
} }
} }
// Wrapper around Vec<MiniFreeRTOSSystemState> 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 FreeRTOSSystemStateMetadata { pub struct FreeRTOSSystemStateMetadata {
inner: Vec<MiniFreeRTOSSystemState>, inner: Vec<RefinedFreeRTOSSystemState>,
indices: Vec<usize>, // Hashed enumeration of States indices: Vec<usize>, // Hashed enumeration of States
tcref: isize, tcref: isize,
} }
impl FreeRTOSSystemStateMetadata { impl FreeRTOSSystemStateMetadata {
pub fn new(inner: Vec<MiniFreeRTOSSystemState>) -> Self{ pub fn new(inner: Vec<RefinedFreeRTOSSystemState>) -> Self{
let tmp = inner.iter().enumerate().map(|x| compute_hash(x) as usize).collect(); let tmp = inner.iter().enumerate().map(|x| compute_hash(x) as usize).collect();
Self {inner: inner, indices: tmp, tcref: 0} Self {inner: inner, indices: tmp, tcref: 0}
} }

View File

@ -8,9 +8,9 @@ use serde::{Deserialize, Serialize};
use super::{ use super::{
CURRENT_SYSSTATE_VEC, CURRENT_SYSSTATE_VEC,
FreeRTOSSystemStateRaw, RawFreeRTOSSystemState,
MiniTCB, RefinedTCB,
MiniFreeRTOSSystemState, RefinedFreeRTOSSystemState,
freertos::{List_t, TCB_t, rtos_struct, rtos_struct::*}, freertos::{List_t, TCB_t, rtos_struct, rtos_struct::*},
}; };
@ -22,7 +22,7 @@ use super::{
#[allow(clippy::unsafe_derive_deserialize)] #[allow(clippy::unsafe_derive_deserialize)]
pub struct QemuSysStateObserver pub struct QemuSysStateObserver
{ {
pub last_run: Vec<MiniFreeRTOSSystemState>, pub last_run: Vec<RefinedFreeRTOSSystemState>,
pub last_input: Vec<u8>, pub last_input: Vec<u8>,
name: String, name: String,
} }
@ -115,17 +115,17 @@ fn tcb_list_to_vec_cached(list: List_t, dump: &mut HashMap<u32,rtos_struct>) ->
ret ret
} }
/// Drains a List of raw SystemStates to produce a refined trace /// Drains a List of raw SystemStates to produce a refined trace
fn refine_system_states(input: &mut Vec<FreeRTOSSystemStateRaw>) -> Vec<MiniFreeRTOSSystemState> { fn refine_system_states(input: &mut Vec<RawFreeRTOSSystemState>) -> Vec<RefinedFreeRTOSSystemState> {
let mut ret = Vec::<MiniFreeRTOSSystemState>::new(); let mut ret = Vec::<RefinedFreeRTOSSystemState>::new();
let mut start_tick : u64 = 0; let mut start_tick : u64 = 0;
for mut i in input.drain(..) { for mut i in input.drain(..) {
let mut collector = Vec::<MiniTCB>::new(); let mut collector = Vec::<RefinedTCB>::new();
for j in i.prio_ready_lists.into_iter().rev() { for j in i.prio_ready_lists.into_iter().rev() {
let mut tmp = tcb_list_to_vec_cached(j,&mut i.dumping_ground).iter().map(|x| MiniTCB::from_tcb(x)).collect(); let mut tmp = tcb_list_to_vec_cached(j,&mut i.dumping_ground).iter().map(|x| RefinedTCB::from_tcb(x)).collect();
collector.append(&mut tmp); collector.append(&mut tmp);
} }
ret.push(MiniFreeRTOSSystemState { ret.push(RefinedFreeRTOSSystemState {
current_task: MiniTCB::from_tcb_owned(i.current_tcb), current_task: RefinedTCB::from_tcb_owned(i.current_tcb),
start_tick: start_tick, start_tick: start_tick,
end_tick: i.qemu_tick, end_tick: i.qemu_tick,
ready_list_after: collector, ready_list_after: collector,