prepare system state observer+feedback
This commit is contained in:
parent
819f759be9
commit
c3f398a315
@ -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,
|
||||
|
@ -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<u32,freertos::rtos_struct>);
|
||||
|
||||
/// 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<u32,freertos::rtos_struct>)>,
|
||||
}
|
||||
|
||||
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<SysState> = 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<I, S>,
|
||||
QT: QemuHelperTuple<I, S>,
|
||||
{
|
||||
// emu::Emulator{_private: ()}.set_gen_block_hook(test_gen_hook);
|
||||
executor.hook_block_generation(gen_not_exec_block_hook::<I, QT, S>);
|
||||
executor.hook_block_execution(exec_syscall_hook::<I, QT, S>);
|
||||
}
|
||||
}
|
||||
@ -84,26 +102,135 @@ where
|
||||
if !h.must_instrument(pc) {
|
||||
return;
|
||||
}
|
||||
if state.metadata().get::<QemuSystemStateMetadata>().is_none() {
|
||||
state.add_metadata(QemuSystemStateMetadata::new());
|
||||
}
|
||||
let meta = state
|
||||
.metadata_mut()
|
||||
.get_mut::<QemuSystemStateMetadata>()
|
||||
.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<u32,freertos::rtos_struct>) = (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::<freertos::List_t>()*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<I, QT, S>(
|
||||
_emulator: &Emulator,
|
||||
helpers: &mut QT,
|
||||
_state: &mut S,
|
||||
pc: u64,
|
||||
)
|
||||
-> Option<u64> where
|
||||
S: HasMetadata,
|
||||
I: Input,
|
||||
QT: QemuHelperTuple<I, S>,
|
||||
{
|
||||
let h = helpers.match_first_type::<QemuSystemStateHelper>().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<SysState>,
|
||||
name: String,
|
||||
}
|
||||
|
||||
impl<I, S> Observer<I, S> 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<I, S> Feedback<I, S> for SysStateFeedback
|
||||
where
|
||||
I: Input,
|
||||
S: HasClientPerfMonitor,
|
||||
{
|
||||
fn is_interesting<EM, OT>(
|
||||
&mut self,
|
||||
_state: &mut S,
|
||||
_manager: &mut EM,
|
||||
_input: &I,
|
||||
_observers: &OT,
|
||||
_exit_kind: &ExitKind,
|
||||
) -> Result<bool, Error>
|
||||
where
|
||||
EM: EventFirer<I>,
|
||||
OT: ObserversTuple<I, S>,
|
||||
{
|
||||
let observer = _observers.match_name::<QemuSysStateObserver>("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 {}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user