store tcb hashes

This commit is contained in:
Alwin Berger 2025-08-29 12:37:35 +00:00
parent 37d0e28f53
commit 48e08ce3e7
8 changed files with 156 additions and 98 deletions

View File

@ -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");

View File

@ -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");

View 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(),
}

View File

@ -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));
}

View File

@ -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
}

View File

@ -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);
}
});

View File

@ -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).

View File

@ -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"));
}