diff --git a/fuzzers/wcet_qemu_sys/src/bin/showmap.rs b/fuzzers/wcet_qemu_sys/src/bin/showmap.rs index 8030fa7731..39b23c933f 100644 --- a/fuzzers/wcet_qemu_sys/src/bin/showmap.rs +++ b/fuzzers/wcet_qemu_sys/src/bin/showmap.rs @@ -1,5 +1,6 @@ //! A singlethreaded QEMU fuzzer that can auto-restart. +use wcet_qemu_sys::system_trace::QemuSysStateObserver; use wcet_qemu_sys::worst::QemuHashMapObserver; use wcet_qemu_sys::{ worst::{DumpMapFeedback,DummyFeedback}, @@ -328,7 +329,7 @@ fn fuzz( QemuSysSnapshotHelper::new(), QemuSystemStateHelper::with_instrumentation_filter(system_state_filter,curr_tcb_pointer.try_into().unwrap(),task_queue_addr.try_into().unwrap()) ), - tuple_list!(edges_observer,clock_observer), + tuple_list!(edges_observer,clock_observer,QemuSysStateObserver::new()), &mut fuzzer, &mut state, &mut mgr, diff --git a/fuzzers/wcet_qemu_sys/src/system_trace.rs b/fuzzers/wcet_qemu_sys/src/system_trace.rs index 8b0c4860c8..8cc16d3360 100644 --- a/fuzzers/wcet_qemu_sys/src/system_trace.rs +++ b/fuzzers/wcet_qemu_sys/src/system_trace.rs @@ -1,3 +1,10 @@ +use libafl::events::EventFirer; +use libafl::state::HasClientPerfMonitor; +use libafl::feedbacks::Feedback; +use libafl::bolts::HasLen; +use libafl::bolts::tuples::Named; +use libafl::Error; +use libafl::observers::Observer; use crate::freertos::rtos_struct::*; use crate::freertos; use hashbrown::HashMap; @@ -5,27 +12,36 @@ use libafl::{executors::ExitKind, inputs::Input, observers::ObserversTuple, stat use serde::{Deserialize, Serialize}; use libafl_qemu::{ + emu, emu::Emulator, executor::QemuExecutor, helper::{QemuHelper, QemuHelperTuple, QemuInstrumentationFilter}, }; +//============================= Datatypes + +/// Info Dump from Qemu +pub type SysState = (u64,freertos::TCB_t,HashMap); + +/// Refined information about the states an execution transitioned between #[derive(Debug, Default, Serialize, Deserialize)] pub struct QemuSystemStateMetadata { - pub rtos_states: Vec<(freertos::TCB_t,HashMap)>, } impl QemuSystemStateMetadata { #[must_use] pub fn new() -> Self { - Self { - rtos_states: Vec::new(), - } + Self {} } } libafl::impl_serdeany!(QemuSystemStateMetadata); + +//============================= Qemu Helper +static mut CURRENT_SYSSTATE_VEC: Vec = vec![]; + +/// A Qemu Helper with reads FreeRTOS specific structs from Qemu whenever certain syscalls occur #[derive(Debug)] pub struct QemuSystemStateHelper { filter: QemuInstrumentationFilter, @@ -65,6 +81,8 @@ where OT: ObserversTuple, QT: QemuHelperTuple, { + // emu::Emulator{_private: ()}.set_gen_block_hook(test_gen_hook); + executor.hook_block_generation(gen_not_exec_block_hook::); executor.hook_block_execution(exec_syscall_hook::); } } @@ -84,26 +102,135 @@ where if !h.must_instrument(pc) { return; } - if state.metadata().get::().is_none() { - state.add_metadata(QemuSystemStateMetadata::new()); - } - let meta = state - .metadata_mut() - .get_mut::() - .unwrap(); + let current_clock = emulator.get_ticks(); let curr_tcb_addr : freertos::void_ptr = freertos::emu_lookup::lookup(emulator, h.tcb_addr); - // println!("Current TCB addr: {:x}",curr_tcb_addr); let current_tcb : freertos::TCB_t = freertos::emu_lookup::lookup(emulator,curr_tcb_addr); - println!("{:?}",current_tcb); - println!("{}", std::str::from_utf8(¤t_tcb.pcTaskName).unwrap()); - let mut result_tup : (freertos::TCB_t,HashMap) = (current_tcb, HashMap::with_capacity(5)); + let mut result_tup : SysState = (current_clock,current_tcb, HashMap::with_capacity(5)); for i in 0..4 { let target : u32= (std::mem::size_of::()*i).try_into().unwrap(); let ready_list : freertos::List_t = freertos::emu_lookup::lookup(emulator, h.ready_queues+target); let a : freertos::rtos_struct = List_struct(ready_list); - result_tup.1.insert(target,a); - // println!("{:?}",ready_list); - // println!("Prio: {} Number: {} first {:x}",i,ready_list.uxNumberOfItems, ready_list.pxIndex); + result_tup.2.insert(target,a); } - meta.rtos_states.push(result_tup); + + unsafe { CURRENT_SYSSTATE_VEC.push(result_tup); } } + +extern "C" fn test_gen_hook(pc: u64) -> u64 { + u32::MAX as u64 +} + +pub fn gen_not_exec_block_hook( + _emulator: &Emulator, + helpers: &mut QT, + _state: &mut S, + pc: u64, +) +-> Option where + S: HasMetadata, + I: Input, + QT: QemuHelperTuple, +{ + let h = helpers.match_first_type::().expect("QemuSystemHelper not found in helper tupel"); + if !h.must_instrument(pc) { + None + } else {Some(1)} +} + +//============================= Observer + +/// The QemuSysState Observer retrieves the SysState +/// that will get updated by the target. +#[derive(Serialize, Deserialize, Debug, Default)] +#[allow(clippy::unsafe_derive_deserialize)] +pub struct QemuSysStateObserver +{ + last_run: Vec, + name: String, +} + +impl Observer for QemuSysStateObserver +{ + #[inline] + fn pre_exec(&mut self, _state: &mut S, _input: &I) -> Result<(), Error> { + unsafe {CURRENT_SYSSTATE_VEC.clear(); } + Ok(()) + } + + #[inline] + fn post_exec(&mut self, _state: &mut S, _input: &I) -> Result<(), Error> { + unsafe {self.last_run.append(&mut CURRENT_SYSSTATE_VEC);} + Ok(()) + } +} + +impl Named for QemuSysStateObserver +{ + #[inline] + fn name(&self) -> &str { + self.name.as_str() + } +} + +impl HasLen for QemuSysStateObserver +{ + #[inline] + fn len(&self) -> usize { + self.last_run.len() + } +} + +impl QemuSysStateObserver { + pub fn new() -> Self { + Self{last_run: vec![], name: "sysstate".to_string()} + } +} + +//============================= Feedback + +/// A Feedback reporting interesting System-State Transitions +#[derive(Serialize, Deserialize, Clone, Debug)] +pub struct SysStateFeedback +{ +} + +impl Feedback for SysStateFeedback +where + I: Input, + S: HasClientPerfMonitor, +{ + fn is_interesting( + &mut self, + _state: &mut S, + _manager: &mut EM, + _input: &I, + _observers: &OT, + _exit_kind: &ExitKind, + ) -> Result + where + EM: EventFirer, + OT: ObserversTuple, + { + let observer = _observers.match_name::("sysstate") + .expect("QemuSysStateObserver not found"); + // Do Stuff + Ok(false) + } +} + +impl Named for SysStateFeedback +{ + #[inline] + fn name(&self) -> &str { + "sysstate" + } +} + +impl SysStateFeedback +{ + /// Creates a new [`SysStateFeedback`] + #[must_use] + pub fn new() -> Self { + Self {} + } +} \ No newline at end of file