diff --git a/fuzzers/FRET/src/fuzzer.rs b/fuzzers/FRET/src/fuzzer.rs index 23e570d932..b0643cc02b 100644 --- a/fuzzers/FRET/src/fuzzer.rs +++ b/fuzzers/FRET/src/fuzzer.rs @@ -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") { - 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"); diff --git a/fuzzers/FRET/src/systemstate/feedbacks.rs b/fuzzers/FRET/src/systemstate/feedbacks.rs index f6f6a2690c..c5690e04ac 100644 --- a/fuzzers/FRET/src/systemstate/feedbacks.rs +++ b/fuzzers/FRET/src/systemstate/feedbacks.rs @@ -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::() - .expect("TraceData not found"); + .expect("TraceData not found").clone(); + let tcb_index = state + .metadata::>() + .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"); diff --git a/fuzzers/FRET/src/systemstate/stg.rs b/fuzzers/FRET/src/systemstate/stg.rs index eec15d9aca..e7a129720f 100644 --- a/fuzzers/FRET/src/systemstate/stg.rs +++ b/fuzzers/FRET/src/systemstate/stg.rs @@ -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 STGNode where SYS: TargetSystem { - pub fn _pretty_print(&self, map: &HashMap) -> 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, tcb_map: &HashMap) -> 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) -> String { + pub fn color_print(&self, state_map: &HashMap, tcb_map: &HashMap) -> 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, STGEdge>, - pub systemstate_index: HashMap, + pub systemstate_index: HashMap, + pub tcb_index: HashMap, pub state_abb_hash_index: HashMap<(u64, u64), NodeIndex>, stgnode_index: HashMap, 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 = 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 = STGNode::default(); let mut exit : STGNode = 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(), } diff --git a/fuzzers/FRET/src/systemstate/target_os/freertos/extraction.rs b/fuzzers/FRET/src/systemstate/target_os/freertos/extraction.rs index 051ff00dfd..156f578aa9 100644 --- a/fuzzers/FRET/src/systemstate/target_os/freertos/extraction.rs +++ b/fuzzers/FRET/src/systemstate/target_os/freertos/extraction.rs @@ -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::>(); jobs }; + _state.metadata_mut::>() + .unwrap() + .tcb_index + .extend(tcb_map.into_iter()); _state.add_metadata(FreeRTOSTraceMetadata::new(refined_states, intervals, mem_reads, jobs, need_to_debug)); } diff --git a/fuzzers/FRET/src/systemstate/target_os/freertos/mod.rs b/fuzzers/FRET/src/systemstate/target_os/freertos/mod.rs index cac6ae4b16..48362b17d6 100644 --- a/fuzzers/FRET/src/systemstate/target_os/freertos/mod.rs +++ b/fuzzers/FRET/src/systemstate/target_os/freertos/mod.rs @@ -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) -> &'a Self::TCB { + tcb_index.get(&self.current_task).expect("TCB not found in index") } - fn get_ready_lists(&self) -> &Vec { - &self.ready_list_after + fn get_ready_lists<'a>(&self, tcb_index: &'a HashMap) -> 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.delay_list_after + fn _get_delay_list<'a>(&self, tcb_index: &'a HashMap) -> 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) -> 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) -> &'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, - delay_list_after: Vec, + current_task: u64, + ready_list_after: Vec, + delay_list_after: Vec, 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::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::>() .join(" "); let delay = self .delay_list_after .iter() - .map(|x| x.task_name.clone()) + .map(|x| format!("{:4x}",x)) .collect::>() .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::State>, + trace_map: HashMap::State>, intervals: Vec, mem_reads: Vec>, jobs: Vec, @@ -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) -> HashSet { +pub(crate) fn get_task_names(trace: &Vec, tcb_index: &HashMap::TCB>) -> HashSet { 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 } diff --git a/fuzzers/FRET/src/systemstate/target_os/freertos/post_processing.rs b/fuzzers/FRET/src/systemstate/target_os/freertos/post_processing.rs index 0e22d54eec..19bbd43764 100644 --- a/fuzzers/FRET/src/systemstate/target_os/freertos/post_processing.rs +++ b/fuzzers/FRET/src/systemstate/target_os/freertos/post_processing.rs @@ -151,43 +151,58 @@ fn tcb_list_to_vec_cached(list: List_t, dump: &mut HashMap) /// - Vec of FreeRTOSSystemStateContext (qemu_tick, (capture_event, capture_name), edge, mem_reads) pub(super) fn refine_system_states( mut input: Vec, -) -> (Vec, Vec) { - let mut ret = (Vec::<_>::new(), Vec::<_>::new()); +) -> (Vec, Vec, HashMap) { + 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::::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 = 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::>(); + 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 = - 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 = - 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 = 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 = 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, meta: Vec, + tcb_map: &HashMap, ) -> ( Vec, Vec>, @@ -240,7 +256,7 @@ pub(super) fn states2intervals( let mut table: HashMap = 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, state_table: &HashMap, edges: &Vec<(u32, u32)>, + tcb_map: &HashMap, ) -> 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, states: &HashMap, + tcb_map: &HashMap, ) -> 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); } }); diff --git a/fuzzers/FRET/src/systemstate/target_os/mod.rs b/fuzzers/FRET/src/systemstate/target_os/mod.rs index d7aa40150f..9b2eaf824a 100644 --- a/fuzzers/FRET/src/systemstate/target_os/mod.rs +++ b/fuzzers/FRET/src/systemstate/target_os/mod.rs @@ -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; /// 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; - fn _get_delay_list(&self) -> &Vec; - fn print_lists(&self) -> String; + fn current_task<'a>(&self, tcb_index: &'a HashMap) -> &'a Self::TCB; + fn current_task_mut<'a>(&mut self, tcb_index: &'a mut HashMap) -> &'a mut Self::TCB; + fn set_current_task<'a>(&mut self, tcb_hash: HashIndex); + fn get_ready_lists<'a>(&self, tcb_index: &'a HashMap) -> Vec<&'a Self::TCB>; + fn _get_delay_list<'a>(&self, tcb_index: &'a HashMap) -> Vec<&'a Self::TCB>; + fn print_lists(&self, tcb_index: &HashMap) -> 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; + fn states_map(&self) -> &HashMap; /// Returns a vector of execution intervals in the trace. fn intervals(&self) -> &Vec; /// Returns a vector of memory reads, where each read is represented as a tuple of (address, value). diff --git a/fuzzers/FRET/tools/state2gantt/src/main.rs b/fuzzers/FRET/tools/state2gantt/src/main.rs index 554764dc82..52ef8a5585 100644 --- a/fuzzers/FRET/tools/state2gantt/src/main.rs +++ b/fuzzers/FRET/tools/state2gantt/src/main.rs @@ -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) = 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, HashMap> = 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")); }