add interesting metrics, reorganize
This commit is contained in:
parent
1d0c43081a
commit
c92cbe78d8
@ -1,8 +1,10 @@
|
||||
//! 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 wcet_qemu_sys::sysstate::feedbacks::HitSysStateFeedback;
|
||||
use wcet_qemu_sys::sysstate::MiniFreeRTOSSystemState;
|
||||
use wcet_qemu_sys::sysstate::RefinedFreeRTOSSystemState;
|
||||
use libafl::corpus::QueueCorpusScheduler;
|
||||
use libafl_qemu::QemuInstrumentationFilter;
|
||||
use wcet_qemu_sys::sysstate::helpers::QemuSystemStateHelper;
|
||||
@ -330,7 +332,8 @@ fn fuzz(
|
||||
let feedback_state = MapFeedbackState::with_observer(&edges_observer);
|
||||
|
||||
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 {
|
||||
None => HashMap::new(),
|
||||
@ -340,11 +343,11 @@ fn fuzz(
|
||||
hmap
|
||||
},
|
||||
};
|
||||
let target_trace : Option<Vec<MiniFreeRTOSSystemState>> = match dump_traces {
|
||||
let target_trace : Option<Vec<RefinedFreeRTOSSystemState>> = match dump_traces {
|
||||
None => None,
|
||||
Some(ref s) => {
|
||||
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)
|
||||
},
|
||||
};
|
||||
@ -353,14 +356,16 @@ fn fuzz(
|
||||
let feedback = feedback_or!(
|
||||
// New maximization map feedback linked to the edges observer and the feedback state
|
||||
MaxMapFeedback::new_tracking(&feedback_state, &edges_observer, true, false),
|
||||
HitImprovingFeedback::new(target_map.clone(), &edges_observer),
|
||||
QemuClockIncreaseFeedback::default(),
|
||||
// HitImprovingFeedback::new(target_map.clone(), &edges_observer),
|
||||
// QemuClockIncreaseFeedback::default(),
|
||||
ClockFeedback::new_with_observer(&clock_observer),
|
||||
NovelSysStateFeedback::default()
|
||||
// NovelSysStateFeedback::default(),
|
||||
SysMapFeedback::new()
|
||||
);
|
||||
|
||||
// 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();
|
||||
|
||||
// create a State from scratch
|
||||
@ -392,8 +397,8 @@ fn fuzz(
|
||||
|
||||
// A minimization+queue policy to get testcasess from the corpus
|
||||
// let scheduler = IndexesLenTimeMinimizerCorpusScheduler::new(PowerQueueCorpusScheduler::new());
|
||||
let scheduler = TimeStateMaximizerCorpusScheduler::new(QueueCorpusScheduler::new());
|
||||
// let scheduler = QueueCorpusScheduler::new();
|
||||
// let scheduler = TimeStateMaximizerCorpusScheduler::new(QueueCorpusScheduler::new());
|
||||
let scheduler = QueueCorpusScheduler::new();
|
||||
|
||||
|
||||
// A fuzzer with feedbacks and a corpus scheduler
|
||||
|
@ -18,7 +18,7 @@ use hashbrown::HashMap;
|
||||
use libafl::{executors::ExitKind, inputs::Input, observers::ObserversTuple, state::HasMetadata};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use super::MiniFreeRTOSSystemState;
|
||||
use super::RefinedFreeRTOSSystemState;
|
||||
use super::FreeRTOSSystemStateMetadata;
|
||||
use super::observers::QemuSysStateObserver;
|
||||
use petgraph::prelude::DiGraph;
|
||||
@ -26,170 +26,6 @@ use petgraph::graph::NodeIndex;
|
||||
use petgraph::Direction;
|
||||
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
|
||||
|
||||
/// Shared Metadata for a SysStateFeedback
|
||||
@ -197,7 +33,7 @@ impl Named for SysMapFeedback
|
||||
pub struct SysStateFeedbackState
|
||||
{
|
||||
known_traces: HashMap<u64,(u64,u64,usize)>, // encounters,ticks,length
|
||||
longest: Vec<MiniFreeRTOSSystemState>,
|
||||
longest: Vec<RefinedFreeRTOSSystemState>,
|
||||
}
|
||||
impl Named for SysStateFeedbackState
|
||||
{
|
||||
@ -219,7 +55,7 @@ impl FeedbackState for SysStateFeedbackState
|
||||
#[derive(Serialize, Deserialize, Clone, Debug, Default)]
|
||||
pub struct NovelSysStateFeedback
|
||||
{
|
||||
last_trace: Option<Vec<MiniFreeRTOSSystemState>>,
|
||||
last_trace: Option<Vec<RefinedFreeRTOSSystemState>>,
|
||||
// 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;
|
||||
if target.len() > last.len() {return false;}
|
||||
for i in 0..target.len() {
|
||||
@ -312,7 +148,7 @@ pub fn match_traces(target: &Vec<MiniFreeRTOSSystemState>, last: &Vec<MiniFreeRT
|
||||
}
|
||||
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;
|
||||
if target.len() > last.len() {return false;}
|
||||
for i in 0..target.len() {
|
||||
@ -367,7 +203,7 @@ impl Named for 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())}
|
||||
}
|
||||
}
|
||||
|
220
fuzzers/wcet_qemu_sys/src/sysstate/graph.rs
Normal file
220
fuzzers/wcet_qemu_sys/src/sysstate/graph.rs
Normal 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
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
use crate::sysstate::FreeRTOSSystemStateRaw;
|
||||
use crate::sysstate::RawFreeRTOSSystemState;
|
||||
use crate::sysstate::CURRENT_SYSSTATE_VEC;
|
||||
use crate::sysstate::NUM_PRIOS;
|
||||
use super::freertos::TCB_t;
|
||||
@ -91,7 +91,7 @@ where
|
||||
return;
|
||||
}
|
||||
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();
|
||||
let mut buf : [u8; 4] = [0,0,0,0];
|
||||
unsafe { emulator.read_mem(h.input_counter.into(), &mut buf) };
|
||||
|
@ -13,6 +13,7 @@ pub mod freertos;
|
||||
pub mod helpers;
|
||||
pub mod observers;
|
||||
pub mod feedbacks;
|
||||
pub mod graph;
|
||||
|
||||
// Constants
|
||||
const NUM_PRIOS: usize = 5;
|
||||
@ -20,7 +21,7 @@ const NUM_PRIOS: usize = 5;
|
||||
//============================= Struct definitions
|
||||
/// Raw info Dump from Qemu
|
||||
#[derive(Debug, Default, Serialize, Deserialize)]
|
||||
pub struct FreeRTOSSystemStateRaw {
|
||||
pub struct RawFreeRTOSSystemState {
|
||||
qemu_tick: u64,
|
||||
current_tcb: TCB_t,
|
||||
prio_ready_lists: [freertos::List_t; NUM_PRIOS],
|
||||
@ -28,11 +29,11 @@ pub struct FreeRTOSSystemStateRaw {
|
||||
input_counter: u32,
|
||||
}
|
||||
/// 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
|
||||
#[derive(Debug, Default, Serialize, Deserialize, Clone, PartialEq)]
|
||||
pub struct MiniTCB {
|
||||
pub struct RefinedTCB {
|
||||
task_name: String,
|
||||
priority: u32,
|
||||
base_priority: u32,
|
||||
@ -41,7 +42,7 @@ pub struct MiniTCB {
|
||||
notify_state: u8,
|
||||
}
|
||||
|
||||
impl Hash for MiniTCB {
|
||||
impl Hash for RefinedTCB {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.task_name.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 {
|
||||
unsafe {
|
||||
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
|
||||
#[derive(Debug, Default, Serialize, Deserialize, Clone)]
|
||||
pub struct MiniFreeRTOSSystemState {
|
||||
pub struct RefinedFreeRTOSSystemState {
|
||||
start_tick: u64,
|
||||
end_tick: u64,
|
||||
input_counter: u32,
|
||||
current_task: MiniTCB,
|
||||
ready_list_after: Vec<MiniTCB>,
|
||||
current_task: RefinedTCB,
|
||||
ready_list_after: Vec<RefinedTCB>,
|
||||
}
|
||||
impl PartialEq for MiniFreeRTOSSystemState {
|
||||
impl PartialEq for RefinedFreeRTOSSystemState {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
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) {
|
||||
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 {
|
||||
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)]
|
||||
pub struct FreeRTOSSystemStateMetadata {
|
||||
inner: Vec<MiniFreeRTOSSystemState>,
|
||||
inner: Vec<RefinedFreeRTOSSystemState>,
|
||||
indices: Vec<usize>, // Hashed enumeration of States
|
||||
tcref: isize,
|
||||
}
|
||||
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();
|
||||
Self {inner: inner, indices: tmp, tcref: 0}
|
||||
}
|
||||
|
@ -8,9 +8,9 @@ use serde::{Deserialize, Serialize};
|
||||
|
||||
use super::{
|
||||
CURRENT_SYSSTATE_VEC,
|
||||
FreeRTOSSystemStateRaw,
|
||||
MiniTCB,
|
||||
MiniFreeRTOSSystemState,
|
||||
RawFreeRTOSSystemState,
|
||||
RefinedTCB,
|
||||
RefinedFreeRTOSSystemState,
|
||||
freertos::{List_t, TCB_t, rtos_struct, rtos_struct::*},
|
||||
};
|
||||
|
||||
@ -22,7 +22,7 @@ use super::{
|
||||
#[allow(clippy::unsafe_derive_deserialize)]
|
||||
pub struct QemuSysStateObserver
|
||||
{
|
||||
pub last_run: Vec<MiniFreeRTOSSystemState>,
|
||||
pub last_run: Vec<RefinedFreeRTOSSystemState>,
|
||||
pub last_input: Vec<u8>,
|
||||
name: String,
|
||||
}
|
||||
@ -115,17 +115,17 @@ fn tcb_list_to_vec_cached(list: List_t, dump: &mut HashMap<u32,rtos_struct>) ->
|
||||
ret
|
||||
}
|
||||
/// Drains a List of raw SystemStates to produce a refined trace
|
||||
fn refine_system_states(input: &mut Vec<FreeRTOSSystemStateRaw>) -> Vec<MiniFreeRTOSSystemState> {
|
||||
let mut ret = Vec::<MiniFreeRTOSSystemState>::new();
|
||||
fn refine_system_states(input: &mut Vec<RawFreeRTOSSystemState>) -> Vec<RefinedFreeRTOSSystemState> {
|
||||
let mut ret = Vec::<RefinedFreeRTOSSystemState>::new();
|
||||
let mut start_tick : u64 = 0;
|
||||
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() {
|
||||
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);
|
||||
}
|
||||
ret.push(MiniFreeRTOSSystemState {
|
||||
current_task: MiniTCB::from_tcb_owned(i.current_tcb),
|
||||
ret.push(RefinedFreeRTOSSystemState {
|
||||
current_task: RefinedTCB::from_tcb_owned(i.current_tcb),
|
||||
start_tick: start_tick,
|
||||
end_tick: i.qemu_tick,
|
||||
ready_list_after: collector,
|
||||
|
Loading…
x
Reference in New Issue
Block a user