store tcb hashes
This commit is contained in:
parent
37d0e28f53
commit
48e08ce3e7
@ -103,7 +103,7 @@ macro_rules! do_dump_stg {
|
||||
let dump_path = $cli.dump_name.clone().unwrap().with_extension(if $c=="" {"dot"} else {$c});
|
||||
println!("Dumping graph to {:?}", &dump_path);
|
||||
if let Some(md) = $state.named_metadata_map_mut().get_mut::<STGFeedbackState<FreeRTOSSystem>>("stgfeedbackstate") {
|
||||
let out = md.graph.map(|_i,x| x.color_print(&md.systemstate_index), |_i,x| x.color_print());
|
||||
let out = md.graph.map(|_i,x| x.color_print(&md.systemstate_index, &md.tcb_index), |_i,x| x.color_print());
|
||||
let outs = Dot::with_config(&out, &[]).to_string();
|
||||
let outs = outs.replace("\\\"","\"");
|
||||
let outs = outs.replace(';',"\\n");
|
||||
|
@ -17,7 +17,7 @@ use super::target_os::TargetSystem;
|
||||
use std::borrow::Cow;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use crate::systemstate::target_os::*;
|
||||
use crate::systemstate::{stg::STGFeedbackState, target_os::*};
|
||||
use libafl::prelude::StateInitializer;
|
||||
|
||||
//=========================== Debugging Feedback
|
||||
@ -78,10 +78,14 @@ where {
|
||||
let tracename = s.with_extension("trace.ron");
|
||||
let trace = state
|
||||
.metadata::<SYS::TraceData>()
|
||||
.expect("TraceData not found");
|
||||
.expect("TraceData not found").clone();
|
||||
let tcb_index = state
|
||||
.metadata::<STGFeedbackState<SYS>>()
|
||||
.expect("STGFeedbackState not found")
|
||||
.tcb_index.clone();
|
||||
std::fs::write(
|
||||
tracename,
|
||||
ron::to_string(trace)
|
||||
ron::to_string(&(trace, tcb_index))
|
||||
.expect("Error serializing hashmap"),
|
||||
)
|
||||
.expect("Can not dump to file");
|
||||
|
@ -10,6 +10,7 @@ use libafl::schedulers::MinimizerScheduler;
|
||||
use libafl_bolts::HasRefCnt;
|
||||
use serde::de::DeserializeOwned;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
use libafl::corpus::Testcase;
|
||||
use std::collections::hash_map::DefaultHasher;
|
||||
use std::hash::Hasher;
|
||||
@ -65,10 +66,10 @@ where
|
||||
}
|
||||
impl<SYS> STGNode<SYS>
|
||||
where SYS: TargetSystem {
|
||||
pub fn _pretty_print(&self, map: &HashMap<u64, SYS::State>) -> String {
|
||||
format!("{}\nl{} {:x}-{:x}\n{}", map[&self.state].current_task().task_name(), self.abb.level, self.abb.start, self.abb.ends.iter().next().unwrap_or_else(||&0xFFFF), map[&self.state].print_lists())
|
||||
pub fn _pretty_print(&self, state_map: &HashMap<u64, SYS::State>, tcb_map: &HashMap<HashIndex, SYS::TCB>) -> String {
|
||||
format!("{}\nl{} {:x}-{:x}\n{}", state_map[&self.state].current_task(tcb_map).task_name(), self.abb.level, self.abb.start, self.abb.ends.iter().next().unwrap_or_else(||&0xFFFF), state_map[&self.state].print_lists(tcb_map))
|
||||
}
|
||||
pub fn color_print(&self, map: &HashMap<u64, SYS::State>) -> String {
|
||||
pub fn color_print(&self, state_map: &HashMap<u64, SYS::State>, tcb_map: &HashMap<HashIndex, SYS::TCB>) -> String {
|
||||
let color = match self.abb.level {
|
||||
1 => "\", shape=box, style=filled, fillcolor=\"lightblue",
|
||||
2 => "\", shape=box, style=filled, fillcolor=\"yellow",
|
||||
@ -78,10 +79,10 @@ where SYS: TargetSystem {
|
||||
let message = match self.abb.level {
|
||||
1 => format!("API Call"),
|
||||
2 => format!("ISR"),
|
||||
0 => format!("Task: {}",map[&self.state].current_task().task_name()),
|
||||
0 => format!("Task: {}",state_map[&self.state].current_task(tcb_map).task_name()),
|
||||
_ => format!(""),
|
||||
};
|
||||
let mut label = format!("{}\nABB: {:x}-{:x}\nHash:{:X}\n{}", message, self.abb.start, self.abb.ends.iter().next().unwrap_or_else(||&0xFFFF), self.state>>48, map[&self.state].print_lists());
|
||||
let mut label = format!("{}\nABB: {:x}-{:x}\nHash:{:X}\n{}", message, self.abb.start, self.abb.ends.iter().next().unwrap_or_else(||&0xFFFF), self.state>>48, state_map[&self.state].print_lists(tcb_map));
|
||||
label.push_str(color);
|
||||
label
|
||||
}
|
||||
@ -160,7 +161,8 @@ where
|
||||
name: Cow<'static, str>,
|
||||
// aggregated traces as a graph
|
||||
pub graph: DiGraph<STGNode<SYS>, STGEdge>,
|
||||
pub systemstate_index: HashMap<u64, SYS::State>,
|
||||
pub systemstate_index: HashMap<HashIndex, SYS::State>,
|
||||
pub tcb_index: HashMap<HashIndex, SYS::TCB>,
|
||||
pub state_abb_hash_index: HashMap<(u64, u64), NodeIndex>,
|
||||
stgnode_index: HashMap<u64, NodeIndex>,
|
||||
entrypoint: NodeIndex,
|
||||
@ -186,8 +188,20 @@ where
|
||||
let mut graph = DiGraph::new();
|
||||
let mut entry_state = SYS::State::default();
|
||||
let mut exit_state = SYS::State::default();
|
||||
*(entry_state.current_task_mut().task_name_mut())="Start".to_string();
|
||||
*(exit_state.current_task_mut().task_name_mut())="End".to_string();
|
||||
// prepare a temporary tcb_index so we can set the names on the default states
|
||||
let mut tcb_index: HashMap<HashIndex, SYS::TCB> = HashMap::new();
|
||||
let mut start_tcb: SYS::TCB = SYS::TCB::default();
|
||||
*start_tcb.task_name_mut()="Start".to_string();
|
||||
let h_start_tcb = compute_hash(&start_tcb);
|
||||
tcb_index.insert(h_start_tcb, start_tcb);
|
||||
entry_state.set_current_task(h_start_tcb);
|
||||
|
||||
let mut end_tcb: SYS::TCB = SYS::TCB::default();
|
||||
*end_tcb.task_name_mut()="End".to_string();
|
||||
let h_end_tcb = compute_hash(&end_tcb);
|
||||
tcb_index.insert(h_end_tcb, end_tcb);
|
||||
exit_state.set_current_task(h_end_tcb);
|
||||
|
||||
let mut entry : STGNode<SYS> = STGNode::default();
|
||||
let mut exit : STGNode<SYS> = STGNode::default();
|
||||
entry.state=compute_hash(&entry_state);
|
||||
@ -218,6 +232,7 @@ where
|
||||
wort_per_stg_path: HashMap::new(),
|
||||
worst_abb_exec_count: HashMap::new(),
|
||||
systemstate_index,
|
||||
tcb_index,
|
||||
state_abb_hash_index,
|
||||
worst_task_jobs: HashMap::new(),
|
||||
}
|
||||
|
@ -28,8 +28,7 @@ use libafl_qemu::{
|
||||
};
|
||||
|
||||
use crate::{fuzzer::MAX_INPUT_SIZE, systemstate::{
|
||||
helpers::{get_icount, read_rec_return_stackframe, symbol_helpers::in_any_range},
|
||||
target_os::{freertos::{extraction::trigger_collection, post_processing::{refine_system_states, states2intervals,get_releases,get_release_response_pairs}, *}, RTOSJob,
|
||||
helpers::{get_icount, read_rec_return_stackframe, symbol_helpers::in_any_range}, stg::STGFeedbackState, target_os::{freertos::{extraction::trigger_collection, post_processing::{get_release_response_pairs, get_releases, refine_system_states, states2intervals}, *}, RTOSJob,
|
||||
}}};
|
||||
|
||||
use super::{
|
||||
@ -216,16 +215,16 @@ where
|
||||
}
|
||||
}
|
||||
// Start refining the state trace
|
||||
let (refined_states, metadata) =
|
||||
let (refined_states, metadata, tcb_map) =
|
||||
refine_system_states(current_systemstate_vec.split_off(0));
|
||||
let (intervals, mem_reads, dumped_states, success) =
|
||||
states2intervals(refined_states.clone(), metadata);
|
||||
states2intervals(refined_states.clone(), metadata, &tcb_map);
|
||||
need_to_debug |= !success;
|
||||
#[cfg(not(feature = "trace_job_response_times"))]
|
||||
let jobs = Vec::new();
|
||||
#[cfg(feature = "trace_job_response_times")]
|
||||
let jobs = {
|
||||
let releases = get_releases(&intervals, &dumped_states);
|
||||
let releases = get_releases(&intervals, &dumped_states, &tcb_map);
|
||||
let responses = unsafe { std::mem::take((&raw mut JOBS_DONE).as_mut().unwrap()) };
|
||||
let (job_spans, do_report) = get_release_response_pairs(&releases, &responses);
|
||||
need_to_debug |= do_report;
|
||||
@ -280,6 +279,10 @@ where
|
||||
.collect::<Vec<_>>();
|
||||
jobs
|
||||
};
|
||||
_state.metadata_mut::<STGFeedbackState<FreeRTOSSystem>>()
|
||||
.unwrap()
|
||||
.tcb_index
|
||||
.extend(tcb_map.into_iter());
|
||||
_state.add_metadata(FreeRTOSTraceMetadata::new(refined_states, intervals, mem_reads, jobs, need_to_debug));
|
||||
}
|
||||
|
||||
|
@ -39,24 +39,28 @@ impl TaskControlBlock for RefinedTCB {
|
||||
impl SystemState for FreeRTOSSystemState {
|
||||
type TCB = RefinedTCB;
|
||||
|
||||
fn current_task(&self) -> &Self::TCB {
|
||||
&self.current_task
|
||||
fn current_task<'a>(&self, tcb_index: &'a HashMap<u64, Self::TCB>) -> &'a Self::TCB {
|
||||
tcb_index.get(&self.current_task).expect("TCB not found in index")
|
||||
}
|
||||
|
||||
fn get_ready_lists(&self) -> &Vec<Self::TCB> {
|
||||
&self.ready_list_after
|
||||
fn get_ready_lists<'a>(&self, tcb_index: &'a HashMap<u64, Self::TCB>) -> Vec<&'a Self::TCB> {
|
||||
self.ready_list_after.iter().map(|x| tcb_index.get(x).expect("TCB not found in index")).collect()
|
||||
}
|
||||
|
||||
fn _get_delay_list(&self) -> &Vec<Self::TCB> {
|
||||
&self.delay_list_after
|
||||
fn _get_delay_list<'a>(&self, tcb_index: &'a HashMap<u64, Self::TCB>) -> Vec<&'a Self::TCB> {
|
||||
self.delay_list_after.iter().map(|x| tcb_index.get(x).expect("TCB not found in index")).collect()
|
||||
}
|
||||
|
||||
fn print_lists(&self) -> String {
|
||||
self.print_lists()
|
||||
fn print_lists<'a>(&self, tcb_index: &'a HashMap<u64, Self::TCB>) -> String {
|
||||
self.print_lists(tcb_index)
|
||||
}
|
||||
|
||||
fn current_task_mut(&mut self) -> &mut Self::TCB {
|
||||
&mut self.current_task
|
||||
fn current_task_mut<'a>(&mut self, tcb_index: &'a mut HashMap<u64, Self::TCB>) -> &'a mut Self::TCB {
|
||||
tcb_index.get_mut(&self.current_task).expect("TCB not found in index")
|
||||
}
|
||||
|
||||
fn set_current_task<'a>(&mut self, tcb_hash: HashIndex) {
|
||||
self.current_task = tcb_hash;
|
||||
}
|
||||
}
|
||||
|
||||
@ -193,9 +197,9 @@ impl RefinedTCB {
|
||||
/// Reduced information about a systems state, without any execution context
|
||||
#[derive(Debug, Default, Serialize, Deserialize, Clone)]
|
||||
pub struct FreeRTOSSystemState {
|
||||
current_task: RefinedTCB,
|
||||
ready_list_after: Vec<RefinedTCB>,
|
||||
delay_list_after: Vec<RefinedTCB>,
|
||||
current_task: u64,
|
||||
ready_list_after: Vec<u64>,
|
||||
delay_list_after: Vec<u64>,
|
||||
read_invalid: bool,
|
||||
}
|
||||
impl PartialEq for FreeRTOSSystemState {
|
||||
@ -220,14 +224,14 @@ impl FreeRTOSSystemState {
|
||||
///
|
||||
/// # Returns
|
||||
/// A string representation of the ready and delay lists.
|
||||
pub fn print_lists(&self) -> String {
|
||||
pub fn print_lists(&self, tcb_index: &HashMap<HashIndex, <Self as SystemState>::TCB>) -> String {
|
||||
let mut ret = String::from("+");
|
||||
for j in self.ready_list_after.iter() {
|
||||
ret.push_str(format!(" {}", j.task_name).as_str());
|
||||
ret.push_str(format!(" {}", tcb_index[j].task_name).as_str());
|
||||
}
|
||||
ret.push_str("\n-");
|
||||
for j in self.delay_list_after.iter() {
|
||||
ret.push_str(format!(" {}", j.task_name).as_str());
|
||||
ret.push_str(format!(" {}", tcb_index[j].task_name).as_str());
|
||||
}
|
||||
ret
|
||||
}
|
||||
@ -247,20 +251,20 @@ impl fmt::Display for FreeRTOSSystemState {
|
||||
let ready = self
|
||||
.ready_list_after
|
||||
.iter()
|
||||
.map(|x| x.task_name.clone())
|
||||
.map(|x| format!("{:4x}",x))
|
||||
.collect::<Vec<_>>()
|
||||
.join(" ");
|
||||
let delay = self
|
||||
.delay_list_after
|
||||
.iter()
|
||||
.map(|x| x.task_name.clone())
|
||||
.map(|x| format!("{:4x}",x))
|
||||
.collect::<Vec<_>>()
|
||||
.join(" ");
|
||||
write!(
|
||||
f,
|
||||
"Valid: {} | Current: {} | Ready: {} | Delay: {}",
|
||||
u32::from(!self.read_invalid),
|
||||
self.current_task.task_name,
|
||||
format!("{:4x}",self.current_task),
|
||||
ready,
|
||||
delay
|
||||
)
|
||||
@ -279,7 +283,7 @@ pub(super)struct FreeRTOSSystemStateContext {
|
||||
#[derive(Debug, Default, Serialize, Deserialize, Clone)]
|
||||
pub struct FreeRTOSTraceMetadata
|
||||
{
|
||||
trace_map: HashMap<u64, <FreeRTOSTraceMetadata as SystemTraceData>::State>,
|
||||
trace_map: HashMap<HashIndex, <FreeRTOSTraceMetadata as SystemTraceData>::State>,
|
||||
intervals: Vec<ExecInterval>,
|
||||
mem_reads: Vec<Vec<(u32, u8)>>,
|
||||
jobs: Vec<RTOSJob>,
|
||||
@ -376,10 +380,10 @@ libafl_bolts::impl_serdeany!(FreeRTOSSystem);
|
||||
///
|
||||
/// # Returns
|
||||
/// A set of unique task names as strings.
|
||||
pub(crate) fn get_task_names(trace: &Vec<FreeRTOSSystemState>) -> HashSet<String> {
|
||||
pub(crate) fn get_task_names(trace: &Vec<FreeRTOSSystemState>, tcb_index: &HashMap<HashIndex, <FreeRTOSSystemState as SystemState>::TCB>) -> HashSet<String> {
|
||||
let mut ret: HashSet<_, _> = HashSet::new();
|
||||
for state in trace {
|
||||
ret.insert(state.current_task.task_name.to_string());
|
||||
ret.insert(tcb_index[&state.current_task].task_name.to_string());
|
||||
}
|
||||
ret
|
||||
}
|
||||
|
@ -151,43 +151,58 @@ fn tcb_list_to_vec_cached(list: List_t, dump: &mut HashMap<u32, FreeRTOSStruct>)
|
||||
/// - Vec of FreeRTOSSystemStateContext (qemu_tick, (capture_event, capture_name), edge, mem_reads)
|
||||
pub(super) fn refine_system_states(
|
||||
mut input: Vec<RawFreeRTOSSystemState>,
|
||||
) -> (Vec<FreeRTOSSystemState>, Vec<FreeRTOSSystemStateContext>) {
|
||||
let mut ret = (Vec::<_>::new(), Vec::<_>::new());
|
||||
) -> (Vec<FreeRTOSSystemState>, Vec<FreeRTOSSystemStateContext>, HashMap<HashIndex, RefinedTCB>) {
|
||||
let mut ret = (Vec::<_>::new(), Vec::<_>::new(), HashMap::new());
|
||||
for mut i in input.drain(..) {
|
||||
let cur = RefinedTCB::from_tcb_owned(i.current_tcb);
|
||||
// println!("Refine: {} {:?} {:?} {:x}-{:x}", cur.task_name, i.capture_point.0, i.capture_point.1.to_string(), i.edge.0, i.edge.1);
|
||||
// collect ready list
|
||||
let mut collector = Vec::<RefinedTCB>::new();
|
||||
let cur_hash = compute_hash(&cur);
|
||||
// insert or override TCB mapping
|
||||
ret.2.insert(cur_hash, cur.clone());
|
||||
// println!("Refine: {} {:?} {:?} {:x}-{:x}", cur.task_name, i.capture_point.0, i.capture_point.1.to_string(), i.edge.0, i.edge.1);
|
||||
// collect ready list
|
||||
let mut collector: Vec<u64> = Vec::new();
|
||||
for j in i.prio_ready_lists.into_iter().rev() {
|
||||
let mut tmp = tcb_list_to_vec_cached(j, &mut i.dumping_ground)
|
||||
let tmp = tcb_list_to_vec_cached(j, &mut i.dumping_ground)
|
||||
.iter()
|
||||
.map(|x| RefinedTCB::from_tcb(x))
|
||||
.collect();
|
||||
collector.append(&mut tmp);
|
||||
.map(|x| {
|
||||
let r = RefinedTCB::from_tcb(x);
|
||||
let h = compute_hash(&r);
|
||||
ret.2.insert(h, r);
|
||||
h
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
collector.extend(tmp);
|
||||
}
|
||||
#[cfg(feature = "observe_systemstate_unordered")]
|
||||
{
|
||||
// respect the order of the first ``lookahead`` tasks and sort the rest by task name
|
||||
// respect the order of the first ``lookahead`` tasks and sort the rest by hash value
|
||||
const LOOKAHEAD : usize = 2;
|
||||
collector.get_mut(LOOKAHEAD..).map(|x| x.sort_by(|a, b| a.task_name.cmp(&b.task_name)));
|
||||
|
||||
}
|
||||
collector.get_mut(LOOKAHEAD..).map(|slice| slice.sort_by(|a, b| { a.cmp(&*b) }));
|
||||
}
|
||||
// collect delay list
|
||||
let mut delay_list: Vec<RefinedTCB> =
|
||||
tcb_list_to_vec_cached(i.delay_list, &mut i.dumping_ground)
|
||||
.iter()
|
||||
.map(|x| RefinedTCB::from_tcb(x))
|
||||
.collect();
|
||||
let mut delay_list_overflow: Vec<RefinedTCB> =
|
||||
tcb_list_to_vec_cached(i.delay_list_overflow, &mut i.dumping_ground)
|
||||
.iter()
|
||||
.map(|x| RefinedTCB::from_tcb(x))
|
||||
.collect();
|
||||
let mut delay_list: Vec<HashIndex> = tcb_list_to_vec_cached(i.delay_list, &mut i.dumping_ground)
|
||||
.iter()
|
||||
.map(|x| {
|
||||
let r = RefinedTCB::from_tcb(x);
|
||||
let h = compute_hash(&r);
|
||||
ret.2.insert(h, r);
|
||||
h
|
||||
})
|
||||
.collect();
|
||||
let mut delay_list_overflow: Vec<HashIndex> = tcb_list_to_vec_cached(i.delay_list_overflow, &mut i.dumping_ground)
|
||||
.iter()
|
||||
.map(|x| {
|
||||
let r = RefinedTCB::from_tcb(x);
|
||||
let h = compute_hash(&r);
|
||||
ret.2.insert(h, r);
|
||||
h
|
||||
})
|
||||
.collect();
|
||||
delay_list.append(&mut delay_list_overflow);
|
||||
delay_list.sort_by(|a, b| a.task_name.cmp(&b.task_name));
|
||||
delay_list.sort_by(|a, b| a.cmp(&b));
|
||||
|
||||
ret.0.push(FreeRTOSSystemState {
|
||||
current_task: cur,
|
||||
current_task: cur_hash,
|
||||
ready_list_after: collector,
|
||||
delay_list_after: delay_list,
|
||||
read_invalid: i.read_invalid,
|
||||
@ -220,6 +235,7 @@ pub(super) fn refine_system_states(
|
||||
pub(super) fn states2intervals(
|
||||
trace: Vec<FreeRTOSSystemState>,
|
||||
meta: Vec<FreeRTOSSystemStateContext>,
|
||||
tcb_map: &HashMap<u64, RefinedTCB>,
|
||||
) -> (
|
||||
Vec<ExecInterval>,
|
||||
Vec<Vec<(u32, u8)>>,
|
||||
@ -240,7 +256,7 @@ pub(super) fn states2intervals(
|
||||
let mut table: HashMap<u64, FreeRTOSSystemState> = HashMap::new();
|
||||
table.insert(last_hash, trace[0].clone());
|
||||
for i in 0..trace.len() - 1 {
|
||||
let curr_name = trace[i].current_task().task_name().as_str();
|
||||
let curr_name = trace[i].current_task(tcb_map).task_name().as_str();
|
||||
// let mut interval_name = curr_name; // Name of the interval, either the task name or the isr/api funtion name
|
||||
let level = match meta[i].capture_point.0 {
|
||||
CaptureEvent::APIEnd => {
|
||||
@ -318,7 +334,7 @@ pub(super) fn states2intervals(
|
||||
last_hash = next_hash;
|
||||
edges.push((meta[i].edge.1, meta[i + 1].edge.0));
|
||||
}
|
||||
let t = add_abb_to_interval(&mut ret, &table, &edges);
|
||||
let t = add_abb_to_interval(&mut ret, &table, &edges, tcb_map);
|
||||
(ret, reads, table, t)
|
||||
}
|
||||
|
||||
@ -337,6 +353,7 @@ fn add_abb_to_interval(
|
||||
trace: &mut Vec<ExecInterval>,
|
||||
state_table: &HashMap<u64, FreeRTOSSystemState>,
|
||||
edges: &Vec<(u32, u32)>,
|
||||
tcb_map: &HashMap<u64, RefinedTCB>,
|
||||
) -> bool {
|
||||
let mut id_count = 0;
|
||||
let mut ret = true;
|
||||
@ -346,7 +363,7 @@ fn add_abb_to_interval(
|
||||
let mut open_abb_at_this_ret_addr_and_task: HashMap<(u32, &str), usize> = HashMap::new();
|
||||
|
||||
for i in 0..trace.len() {
|
||||
let curr_name = state_table[&trace[i].start_state].current_task().task_name();
|
||||
let curr_name = state_table[&trace[i].start_state].current_task(tcb_map).task_name();
|
||||
// let last : Option<&usize> = last_abb_start_of_task.get(&curr_name);
|
||||
|
||||
// let open_abb = open_abb_at_this_task_or_level.get(&(trace[i].level, if trace[i].level<2 {&curr_name} else {""})).to_owned(); // apps/apis are differentiated by task name, isrs by nested level
|
||||
@ -553,6 +570,7 @@ fn add_abb_to_interval(
|
||||
pub(super) fn get_releases(
|
||||
trace: &Vec<ExecInterval>,
|
||||
states: &HashMap<u64, FreeRTOSSystemState>,
|
||||
tcb_map: &HashMap<u64, RefinedTCB>,
|
||||
) -> Vec<(u64, String)> {
|
||||
let mut ret = Vec::new();
|
||||
let mut initial_released = false;
|
||||
@ -564,8 +582,9 @@ pub(super) fn get_releases(
|
||||
{
|
||||
let start_state = states.get(&i.start_state).expect("State not found");
|
||||
initial_released = true;
|
||||
start_state.get_ready_lists().iter().for_each(|x| {
|
||||
ret.push((i.start_tick, x.task_name().clone()));
|
||||
start_state.get_ready_lists(tcb_map).iter().for_each(|x| {
|
||||
let name = &x.task_name;
|
||||
ret.push((i.start_tick, name.clone()));
|
||||
});
|
||||
continue;
|
||||
}
|
||||
@ -611,14 +630,17 @@ pub(super) fn get_releases(
|
||||
end_index.map(|x| states.get(&trace[x].end_state))
|
||||
{
|
||||
end_state.ready_list_after.iter().for_each(|x| {
|
||||
if x.task_name != end_state.current_task.task_name
|
||||
&& x.task_name != start_state.current_task.task_name
|
||||
let x_name = &tcb_map[x].task_name;
|
||||
let curr_name = &tcb_map[&end_state.current_task].task_name;
|
||||
let start_name = &tcb_map[&start_state.current_task].task_name;
|
||||
if x_name != curr_name
|
||||
&& x_name != start_name
|
||||
&& !start_state
|
||||
.ready_list_after
|
||||
.iter()
|
||||
.any(|y| x.task_name == y.task_name)
|
||||
.any(|y| &tcb_map[y].task_name == x_name)
|
||||
{
|
||||
ret.push((i.end_tick, x.task_name.clone()));
|
||||
ret.push((i.end_tick, x_name.clone()));
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -629,14 +651,17 @@ pub(super) fn get_releases(
|
||||
let start_state = states.get(&i.start_state).expect("State not found");
|
||||
let end_state = states.get(&i.end_state).expect("State not found");
|
||||
end_state.ready_list_after.iter().for_each(|x| {
|
||||
if x.task_name != end_state.current_task.task_name
|
||||
&& x.task_name != start_state.current_task.task_name
|
||||
let x_name = &tcb_map[x].task_name;
|
||||
let curr_name = &tcb_map[&end_state.current_task].task_name;
|
||||
let start_name = &tcb_map[&start_state.current_task].task_name;
|
||||
if x_name != curr_name
|
||||
&& x_name != start_name
|
||||
&& !start_state
|
||||
.ready_list_after
|
||||
.iter()
|
||||
.any(|y| x.task_name == y.task_name)
|
||||
.any(|y| &tcb_map[y].task_name == x_name)
|
||||
{
|
||||
ret.push((i.end_tick, x.task_name.clone()));
|
||||
ret.push((i.end_tick, x_name.clone()));
|
||||
}
|
||||
});
|
||||
} else if i.end_capture.0 == CaptureEvent::ISRStart {
|
||||
@ -651,14 +676,17 @@ pub(super) fn get_releases(
|
||||
isr_has_ended = true;
|
||||
if !end_state.read_invalid {
|
||||
end_state.ready_list_after.iter().for_each(|x| {
|
||||
if x.task_name != end_state.current_task.task_name
|
||||
&& x.task_name != start_state.current_task.task_name
|
||||
let x_name = &tcb_map[x].task_name;
|
||||
let curr_name = &tcb_map[&end_state.current_task].task_name;
|
||||
let start_name = &tcb_map[&start_state.current_task].task_name;
|
||||
if x_name != curr_name
|
||||
&& x_name != start_name
|
||||
&& !start_state
|
||||
.ready_list_after
|
||||
.iter()
|
||||
.any(|y| x.task_name == y.task_name)
|
||||
.any(|y| &tcb_map[y].task_name == x_name)
|
||||
{
|
||||
ret.push((i.end_tick, x.task_name.clone()));
|
||||
ret.push((i.end_tick, x_name.clone()));
|
||||
}
|
||||
});
|
||||
break;
|
||||
@ -692,13 +720,14 @@ pub(super) fn get_releases(
|
||||
.expect("State not found")
|
||||
};
|
||||
api_end_state.ready_list_after.iter().for_each(|x| {
|
||||
if x.task_name != api_start_state.current_task.task_name
|
||||
&& !api_start_state
|
||||
.ready_list_after
|
||||
.iter()
|
||||
.any(|y| x.task_name == y.task_name)
|
||||
let x_name = &tcb_map[x].task_name;
|
||||
let start_name = &tcb_map[&api_start_state.current_task].task_name;
|
||||
if x_name != start_name && !api_start_state
|
||||
.ready_list_after
|
||||
.iter()
|
||||
.any(|y| &tcb_map[y].task_name == x_name)
|
||||
{
|
||||
ret.push((i.end_tick, x.task_name.clone()));
|
||||
ret.push((i.end_tick, x_name.clone()));
|
||||
// eprintln!("Task {} released by API call at {:.1}ms", x.task_name, crate::time::clock::tick_to_time(i.end_tick).as_micros() as f32/1000.0);
|
||||
}
|
||||
});
|
||||
|
@ -20,8 +20,10 @@ pub mod freertos;
|
||||
|
||||
//============================= Trait definitions
|
||||
|
||||
pub type HashIndex = u64;
|
||||
|
||||
/// A trait representing a target system, which includes a system state, task control block, and trace data.
|
||||
pub trait TargetSystem: Serialize + Sized + for<'a> Deserialize<'a> + Default + Debug + Clone + SerdeAny {
|
||||
pub trait TargetSystem: Serialize + Sized + for<'de> Deserialize<'de> + Default + Debug + Clone + SerdeAny {
|
||||
type State: SystemState<TCB = Self::TCB>;
|
||||
/// The type of a task control block used in the system state.
|
||||
type TCB: TaskControlBlock;
|
||||
@ -33,11 +35,12 @@ pub trait TargetSystem: Serialize + Sized + for<'a> Deserialize<'a> + Default +
|
||||
pub trait SystemState: Serialize + Sized + for<'a> Deserialize<'a> + Default + Debug + Hash + PartialEq + Clone + SerdeAny {
|
||||
type TCB: TaskControlBlock;
|
||||
|
||||
fn current_task(&self) -> &Self::TCB;
|
||||
fn current_task_mut(&mut self) -> &mut Self::TCB;
|
||||
fn get_ready_lists(&self) -> &Vec<Self::TCB>;
|
||||
fn _get_delay_list(&self) -> &Vec<Self::TCB>;
|
||||
fn print_lists(&self) -> String;
|
||||
fn current_task<'a>(&self, tcb_index: &'a HashMap<HashIndex, Self::TCB>) -> &'a Self::TCB;
|
||||
fn current_task_mut<'a>(&mut self, tcb_index: &'a mut HashMap<HashIndex, Self::TCB>) -> &'a mut Self::TCB;
|
||||
fn set_current_task<'a>(&mut self, tcb_hash: HashIndex);
|
||||
fn get_ready_lists<'a>(&self, tcb_index: &'a HashMap<HashIndex, Self::TCB>) -> Vec<&'a Self::TCB>;
|
||||
fn _get_delay_list<'a>(&self, tcb_index: &'a HashMap<HashIndex, Self::TCB>) -> Vec<&'a Self::TCB>;
|
||||
fn print_lists(&self, tcb_index: &HashMap<HashIndex, Self::TCB>) -> String;
|
||||
}
|
||||
|
||||
pub trait SystemTraceData: Serialize + Sized + for<'a> Deserialize<'a> + Default + Debug + Clone + SerdeAny + HasRefCnt {
|
||||
@ -46,7 +49,7 @@ pub trait SystemTraceData: Serialize + Sized + for<'a> Deserialize<'a> + Default
|
||||
/// Returns a vector of all system states in the trace.
|
||||
fn states(&self) -> Vec<&Self::State>;
|
||||
/// Returns hash map of system states, where the key is the hash value of the state.
|
||||
fn states_map(&self) -> &HashMap<u64, Self::State>;
|
||||
fn states_map(&self) -> &HashMap<HashIndex, Self::State>;
|
||||
/// Returns a vector of execution intervals in the trace.
|
||||
fn intervals(&self) -> &Vec<ExecInterval>;
|
||||
/// Returns a vector of memory reads, where each read is represented as a tuple of (address, value).
|
||||
|
@ -2,7 +2,7 @@ use hashbrown::HashMap;
|
||||
use std::borrow::Cow;
|
||||
use std::path::PathBuf;
|
||||
use std::fs;
|
||||
use fret::systemstate::{target_os::SystemTraceData, target_os::freertos::FreeRTOSTraceMetadata, target_os::SystemState, target_os::TaskControlBlock};
|
||||
use fret::systemstate::target_os::{freertos::{FreeRTOSTraceMetadata, RefinedTCB}, SystemState, SystemTraceData, TaskControlBlock};
|
||||
use std::io::Write;
|
||||
use clap::Parser;
|
||||
use itertools::Itertools;
|
||||
@ -57,12 +57,12 @@ fn main() {
|
||||
|
||||
|
||||
// Store priority per task
|
||||
let trace : FreeRTOSTraceMetadata = ron::from_str(&String::from_utf8_lossy(&raw_input)).expect("Can not parse HashMap");
|
||||
let (trace, tcb_index) : (FreeRTOSTraceMetadata, HashMap<u64, RefinedTCB>) = ron::from_str(&String::from_utf8_lossy(&raw_input)).expect("Can not parse HashMap");
|
||||
// task_name -> (abb_addr -> (interval_count, exec_count, exec_time, woet))
|
||||
let mut abb_profile : HashMap<Cow<'static, str>, HashMap<u32, (usize, usize, u64, u64)>> = trace.select_abb_profile(conf.task.clone());
|
||||
for s in trace.intervals() {
|
||||
if s.level == 0 {
|
||||
let t = trace.states_map()[&s.start_state].current_task();
|
||||
let t = trace.states_map()[&s.start_state].current_task(&tcb_index);
|
||||
level_per_task.insert(t.task_name().clone(),t.base_priority);
|
||||
}
|
||||
}
|
||||
@ -87,7 +87,7 @@ fn main() {
|
||||
let end_tick = if conf.micros {s.end_tick as f32 / fret::time::clock::QEMU_ISNS_PER_USEC} else {s.end_tick as f32};
|
||||
let state = &trace.states_map()[&s.start_state];
|
||||
if s.level == 0 {
|
||||
activation_file.as_mut().map(|x| writeln!(x,"{},{},{},{},{:X},{},{}",start_tick,end_tick,trace.states_map()[&s.start_state].current_task().priority,trace.states_map()[&s.start_state].current_task().task_name, state.get_hash()>>48, state, s.abb.as_ref().map(|x| x.get_start()).unwrap_or(u32::MAX) ).expect("Could not write to file"));
|
||||
activation_file.as_mut().map(|x| writeln!(x,"{},{},{},{},{:X},{},{}",start_tick,end_tick,trace.states_map()[&s.start_state].current_task(&tcb_index).priority,trace.states_map()[&s.start_state].current_task(&tcb_index).task_name, state.get_hash()>>48, state, s.abb.as_ref().map(|x| x.get_start()).unwrap_or(u32::MAX) ).expect("Could not write to file"));
|
||||
} else {
|
||||
activation_file.as_mut().map(|x| writeln!(x,"{},{},-{},{},{:X},{},{}",start_tick,end_tick,s.level,s.start_capture.1, state.get_hash()>>48, state, s.abb.as_ref().map(|x| x.get_start()).unwrap_or(u32::MAX)).expect("Could not write to file"));
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user