trace executed abbs, instead of states

This commit is contained in:
Alwin Berger 2024-05-08 12:30:10 +02:00
parent 88c5c8a19f
commit 3f9a2ed6c0
3 changed files with 50 additions and 13 deletions

View File

@ -214,7 +214,7 @@ impl HasRefCnt for FreeRTOSSystemStateMetadata {
libafl_bolts::impl_serdeany!(FreeRTOSSystemStateMetadata); libafl_bolts::impl_serdeany!(FreeRTOSSystemStateMetadata);
#[derive(Default, Serialize, Deserialize, Clone)] #[derive(Default, Serialize, Deserialize, Clone, PartialEq, Eq)]
pub struct AtomicBasicBlock { pub struct AtomicBasicBlock {
start: GuestAddr, start: GuestAddr,
ends: HashSet<GuestAddr>, ends: HashSet<GuestAddr>,
@ -249,6 +249,37 @@ impl fmt::Debug for AtomicBasicBlock {
} }
} }
impl PartialOrd for AtomicBasicBlock {
fn partial_cmp(&self, other: &AtomicBasicBlock) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl Ord for AtomicBasicBlock {
fn cmp(&self, other: &AtomicBasicBlock) -> std::cmp::Ordering {
if self.start.cmp(&other.start) == std::cmp::Ordering::Equal {
// If the start addresses are equal, compare by 'ends'
let end1 = if self.ends.len() == 1 { *self.ends.iter().next().unwrap() as u64 } else {
let mut temp = self.ends.iter().collect::<Vec<_>>().into_iter().collect::<Vec<&GuestAddr>>();
temp.sort_unstable();
let mut h = DefaultHasher::new();
temp.hash(&mut h);
h.finish()
};
let end2 = if other.ends.len() == 1 { *self.ends.iter().next().unwrap() as u64 } else {
let mut temp = other.ends.iter().collect::<Vec<_>>().into_iter().collect::<Vec<&GuestAddr>>();
temp.sort_unstable();
let mut h = DefaultHasher::new();
temp.hash(&mut h);
h.finish()
};
end1.cmp(&end2)
} else {
// If the start addresses are not equal, compare by 'start'
self.start.cmp(&other.start)
}
}
}
fn get_task_names(trace: &Vec<RefinedFreeRTOSSystemState>) -> HashSet<String> { fn get_task_names(trace: &Vec<RefinedFreeRTOSSystemState>) -> HashSet<String> {
@ -363,8 +394,9 @@ fn extract_abbs_from_trace(trace: &Vec<RefinedFreeRTOSSystemState>) -> HashMap<S
abbs_of_task abbs_of_task
} }
/// returns (name, abb, index, ticks) /// returns (name, abb, index, ticks, Option<total abb ticks iff abb termiates here>)
fn trace_to_state_abb(trace: &Vec<RefinedFreeRTOSSystemState>) -> Vec<(String, Rc<AtomicBasicBlock>, usize, u64)> { fn trace_to_state_abb(trace: &Vec<RefinedFreeRTOSSystemState>) -> (Vec<(String, Rc<AtomicBasicBlock>, usize, u64)>, Vec<(AtomicBasicBlock, u64)>) {
let mut abbs_in_exec_order : Vec<(usize,AtomicBasicBlock,u64)> = vec![]; // indices in trace where an abb ends, along with it's time
let mut has_started : HashSet<String> = HashSet::new(); let mut has_started : HashSet<String> = HashSet::new();
let mut abb_begin_end : HashMap<usize,usize> = HashMap::new(); let mut abb_begin_end : HashMap<usize,usize> = HashMap::new();
let mut last_abb_of_task : HashMap<String, usize> = HashMap::new(); let mut last_abb_of_task : HashMap<String, usize> = HashMap::new();
@ -429,19 +461,23 @@ fn trace_to_state_abb(trace: &Vec<RefinedFreeRTOSSystemState>) -> Vec<(String, R
let abb = Rc::new(AtomicBasicBlock {start, ends: HashSet::from([end])}); let abb = Rc::new(AtomicBasicBlock {start, ends: HashSet::from([end])});
// find intervalls where the abb is actually running, not preempted // find intervalls where the abb is actually running, not preempted
// count up exec time // count up exec time
let mut sum_of_pieces = 0;
for i in s..e { for i in s..e {
if trace[i].current_task.0.task_name == curr_name { if trace[i].current_task.0.task_name == curr_name {
match trace[i].capture_point.0 { match trace[i].capture_point.0 {
CaptureEvent::APIEnd => {chunks.push((curr_name.clone(), abb.clone(), i, trace[i+1].end_tick-trace[i].end_tick));}, CaptureEvent::APIEnd => {chunks.push((curr_name.clone(), abb.clone(), i, trace[i+1].end_tick-trace[i].end_tick)); sum_of_pieces+=trace[i+1].end_tick-trace[i].end_tick;},
CaptureEvent::ISRStart => (), CaptureEvent::ISRStart => (),
CaptureEvent::ISREnd => {chunks.push((curr_name.clone(), abb.clone(), i, trace[i+1].end_tick-trace[i].end_tick));}, CaptureEvent::ISREnd => {chunks.push((curr_name.clone(), abb.clone(), i, trace[i+1].end_tick-trace[i].end_tick)); sum_of_pieces+=trace[i+1].end_tick-trace[i].end_tick;},
_ => panic!(), _ => panic!(),
} }
} }
} }
abbs_in_exec_order.push((e,(*abb).clone(), sum_of_pieces));
} }
abbs_in_exec_order.sort_by_key(|x| x.0);
let abbs_in_exec_order : Vec<_> = abbs_in_exec_order.into_iter().map(|(_x,y,z)| (y,z)).collect();
chunks.sort_by_key(|x| x.2); chunks.sort_by_key(|x| x.2);
chunks (chunks, abbs_in_exec_order)
} }
libafl_bolts::impl_serdeany!(AtomicBasicBlock); libafl_bolts::impl_serdeany!(AtomicBasicBlock);

View File

@ -44,7 +44,7 @@ where
#[inline] #[inline]
fn post_exec(&mut self, _state: &mut S, _input: &S::Input, _exit_kind: &ExitKind) -> Result<(), Error> { fn post_exec(&mut self, _state: &mut S, _input: &S::Input, _exit_kind: &ExitKind) -> Result<(), Error> {
unsafe {self.last_run = post_process_trace(refine_system_states(&mut CURRENT_SYSTEMSTATE_VEC));} unsafe {self.last_run = remove_ineffective_isr(refine_system_states(&mut CURRENT_SYSTEMSTATE_VEC));}
self.last_input=_input.target_bytes().as_slice().to_owned(); self.last_input=_input.target_bytes().as_slice().to_owned();
Ok(()) Ok(())
} }
@ -171,8 +171,8 @@ fn refine_system_states(input: &mut Vec<RawFreeRTOSSystemState>) -> Vec<RefinedF
return ret; return ret;
} }
fn post_process_trace(mut trace: Vec<RefinedFreeRTOSSystemState>) -> Vec<RefinedFreeRTOSSystemState> { fn remove_ineffective_isr(mut trace: Vec<RefinedFreeRTOSSystemState>) -> Vec<RefinedFreeRTOSSystemState> {
// remove subsequent pairs of equal states where an ISRStart follows an ISREnd // remove subsequent pairs of equal states where an ISREnd follows an ISRStart. If the interrupt had no effect on the system we, are not interested.
let mut ret : Vec<RefinedFreeRTOSSystemState> = Vec::new(); let mut ret : Vec<RefinedFreeRTOSSystemState> = Vec::new();
ret.push(trace[0].clone()); ret.push(trace[0].clone());
let mut i = 1; let mut i = 1;

View File

@ -92,7 +92,7 @@ pub struct STGFeedbackState
entrypoint: NodeIndex, entrypoint: NodeIndex,
exit: NodeIndex, exit: NodeIndex,
// Metadata about aggregated traces. aggegated meaning, order has been removed // Metadata about aggregated traces. aggegated meaning, order has been removed
worst_observed_per_aggegated_path: HashMap<Vec<NodeIndex>,u64> worst_observed_per_aggegated_path: HashMap<Vec<AtomicBasicBlock>,u64>
} }
impl Default for STGFeedbackState { impl Default for STGFeedbackState {
@ -256,12 +256,13 @@ where
} }
}; };
let abbs = trace_to_state_abb(&observer.last_run); let (abbs, ordered) = trace_to_state_abb(&observer.last_run);
// println!("{:?}",abbs); // println!("{:?}",abbs);
let (trace, _, mut interesting) = StgFeedback::update_stg(&observer.last_run, abbs, feedbackstate); let (_trace, _, mut interesting) = StgFeedback::update_stg(&observer.last_run, abbs, feedbackstate);
if INTEREST_AGGREGATE { if INTEREST_AGGREGATE {
let (it1, _it2) : (Vec<_>, Vec<_>) = ordered.into_iter().unzip();
// aggegation by sorting, order of states is not relevant // aggegation by sorting, order of states is not relevant
let mut tmp = trace.clone(); let mut tmp : Vec<_> = it1;
tmp.sort(); tmp.sort();
if let Some(x) = feedbackstate.worst_observed_per_aggegated_path.get_mut(&tmp) { if let Some(x) = feedbackstate.worst_observed_per_aggegated_path.get_mut(&tmp) {
let t = clock_observer.last_runtime(); let t = clock_observer.last_runtime();