134 lines
4.5 KiB
Rust
134 lines
4.5 KiB
Rust
// use crate::systemstate::IRQ_INPUT_BYTES_NUMBER;
|
|
use libafl::prelude::ExitKind;
|
|
use libafl::{inputs::HasTargetBytes, prelude::UsesInput};
|
|
use libafl_bolts::HasLen;
|
|
use libafl_bolts::Named;
|
|
use libafl_bolts::AsSlice;
|
|
use libafl::Error;
|
|
use libafl::observers::Observer;
|
|
use hashbrown::HashMap;
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
use super::{
|
|
CURRENT_SYSTEMSTATE_VEC,
|
|
RawFreeRTOSSystemState,
|
|
RefinedTCB,
|
|
RefinedFreeRTOSSystemState,
|
|
freertos::{List_t, TCB_t, rtos_struct, rtos_struct::*},
|
|
};
|
|
|
|
//============================= Observer
|
|
|
|
/// The Qemusystemstate Observer retrieves the systemstate
|
|
/// that will get updated by the target.
|
|
#[derive(Serialize, Deserialize, Debug, Default)]
|
|
#[allow(clippy::unsafe_derive_deserialize)]
|
|
pub struct QemuSystemStateObserver
|
|
{
|
|
pub last_run: Vec<RefinedFreeRTOSSystemState>,
|
|
pub last_input: Vec<u8>,
|
|
name: String,
|
|
}
|
|
|
|
impl<S> Observer<S> for QemuSystemStateObserver
|
|
where
|
|
S: UsesInput,
|
|
S::Input : HasTargetBytes,
|
|
{
|
|
#[inline]
|
|
fn pre_exec(&mut self, _state: &mut S, _input: &S::Input) -> Result<(), Error> {
|
|
unsafe {CURRENT_SYSTEMSTATE_VEC.clear(); }
|
|
Ok(())
|
|
}
|
|
|
|
#[inline]
|
|
fn post_exec(&mut self, _state: &mut S, _input: &S::Input, _exit_kind: &ExitKind) -> Result<(), Error> {
|
|
unsafe {self.last_run = refine_system_states(&mut CURRENT_SYSTEMSTATE_VEC);}
|
|
self.last_input=_input.target_bytes().as_slice().to_owned();
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
impl Named for QemuSystemStateObserver
|
|
{
|
|
#[inline]
|
|
fn name(&self) -> &str {
|
|
self.name.as_str()
|
|
}
|
|
}
|
|
|
|
impl HasLen for QemuSystemStateObserver
|
|
{
|
|
#[inline]
|
|
fn len(&self) -> usize {
|
|
self.last_run.len()
|
|
}
|
|
}
|
|
|
|
impl QemuSystemStateObserver {
|
|
pub fn new() -> Self {
|
|
Self{last_run: vec![], last_input: vec![], name: "systemstate".to_string()}
|
|
}
|
|
|
|
}
|
|
|
|
//============================= Parsing helpers
|
|
|
|
/// Parse a List_t containing TCB_t into Vec<TCB_t> from cache. Consumes the elements from cache
|
|
fn tcb_list_to_vec_cached(list: List_t, dump: &mut HashMap<u32,rtos_struct>) -> Vec<TCB_t>
|
|
{
|
|
let mut ret : Vec<TCB_t> = Vec::new();
|
|
if list.uxNumberOfItems == 0 {return ret;}
|
|
let last_list_item = match dump.remove(&list.pxIndex).expect("List_t entry was not in Hashmap") {
|
|
List_Item_struct(li) => li,
|
|
List_MiniItem_struct(mli) => match dump.remove(&mli.pxNext).expect("MiniListItem pointer invaild") {
|
|
List_Item_struct(li) => li,
|
|
_ => panic!("MiniListItem of a non empty List does not point to ListItem"),
|
|
},
|
|
_ => panic!("List_t entry was not a ListItem"),
|
|
};
|
|
let mut next_index = last_list_item.pxNext;
|
|
let last_tcb = match dump.remove(&last_list_item.pvOwner).expect("ListItem Owner not in Hashmap") {
|
|
TCB_struct(t) => t,
|
|
_ => panic!("List content does not equal type"),
|
|
};
|
|
for _ in 0..list.uxNumberOfItems-1 {
|
|
let next_list_item = match dump.remove(&next_index).expect("List_t entry was not in Hashmap") {
|
|
List_Item_struct(li) => li,
|
|
List_MiniItem_struct(mli) => match dump.remove(&mli.pxNext).expect("MiniListItem pointer invaild") {
|
|
List_Item_struct(li) => li,
|
|
_ => panic!("MiniListItem of a non empty List does not point to ListItem"),
|
|
},
|
|
_ => panic!("List_t entry was not a ListItem"),
|
|
};
|
|
match dump.remove(&next_list_item.pvOwner).expect("ListItem Owner not in Hashmap") {
|
|
TCB_struct(t) => {ret.push(t)},
|
|
_ => panic!("List content does not equal type"),
|
|
}
|
|
next_index=next_list_item.pxNext;
|
|
}
|
|
ret.push(last_tcb);
|
|
ret
|
|
}
|
|
/// Drains a List of raw SystemStates to produce a refined trace
|
|
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::<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| RefinedTCB::from_tcb(x)).collect();
|
|
collector.append(&mut tmp);
|
|
}
|
|
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,
|
|
input_counter: i.input_counter,//+IRQ_INPUT_BYTES_NUMBER,
|
|
last_pc: i.last_pc,
|
|
});
|
|
start_tick=i.qemu_tick;
|
|
}
|
|
return ret;
|
|
} |