add objective selection, dump exec times

This commit is contained in:
Alwin Berger 2022-05-27 01:10:12 +02:00
parent 14e8a81d17
commit ee4056a008
4 changed files with 179 additions and 9 deletions

View File

@ -5,7 +5,7 @@ authors = [ "Alwin Berger <alwin.berger@tu-dortmund.de>" ]
edition = "2021"
[features]
default = ["std"]
default = ["std", "obj_collect"]
std = []
multicore = []
@ -21,6 +21,12 @@ sched_mapmax = []
sched_state = []
sched_graph = []
# objective selection, additive
obj_collect = []
obj_trace = []
obj_edges = []
obj_ticks = []
muta_snip = [ "sched_graph" ]
[profile.release]

View File

@ -1,5 +1,9 @@
//! A singlethreaded QEMU fuzzer that can auto-restart.
use wcet_qemu_sys::worst::DummyFeedback;
use wcet_qemu_sys::worst::ExecTimeCollectorFeedback;
use wcet_qemu_sys::worst::EXEC_TIME_COLLECTION;
use wcet_qemu_sys::worst::ExecTimeReachedFeedback;
use libafl::inputs::Input;
use libafl::feedbacks::Feedback;
use libafl::HasFeedback;
@ -86,7 +90,7 @@ use libafl_qemu::{
clock::ClockFeedback,
clock::QemuClockIncreaseFeedback
};
use wcet_qemu_sys::worst::{SortedFeedback,HitFeedback,HitImprovingFeedback,TimeStateMaximizerCorpusScheduler};
use wcet_qemu_sys::worst::{SortedFeedback,HitFeedback,HitImprovingFeedback,TimeStateMaximizerCorpusScheduler,LenTimeMaximizerCorpusScheduler};
/// The fuzzer main
@ -154,6 +158,16 @@ pub fn main() {
.required(true)
.takes_value(true),
)
.arg(
Arg::new("exectimes")
.long("libafl-exectimes")
.takes_value(true),
)
.arg(
Arg::new("targettime")
.long("libafl-targettime")
.takes_value(true),
)
.try_get_matches_from(filter_qemu_args())
{
Ok(res) => res,
@ -216,9 +230,19 @@ pub fn main() {
None => None
};
let exectimes = match res.value_of("exectimes") {
Some(st) => Some(PathBuf::from(st.to_string())),
None => None
};
let targettime = match res.value_of("targettime") {
Some(st) => Some(st.to_string().parse::<u64>().expect("targettime not a number")),
None => None
};
let snapshot = PathBuf::from(res.value_of("snapshot").unwrap().to_string());
fuzz(out_dir, crashes, in_dir, tokens, logfile, timeout, kernel, edges, traces, snapshot)
fuzz(out_dir, crashes, in_dir, tokens, logfile, timeout, kernel, edges, traces, exectimes, targettime, snapshot)
.expect("An error occurred while fuzzing");
}
@ -246,6 +270,8 @@ fn fuzz(
kernel: PathBuf,
dump_edges: Option<PathBuf>,
dump_traces: Option<PathBuf>,
dump_exectimes: Option<PathBuf>,
targettime: Option<u64>,
snapshot: PathBuf,
) -> Result<(), Error> {
env::remove_var("LD_LIBRARY_PATH");
@ -375,9 +401,15 @@ fn fuzz(
let feedback = feedback_or!(feedback, SysMapFeedback::new());
// A feedback to choose if an input is a solution or not
let objective = feedback_or!(HitFeedback::new(target_map,0.0,&edges_observer),HitSysStateFeedback::new(target_trace));
// let objective = feedback_or!(HitFeedback::new(target_map,0.0,&edges_observer));
// let objective = SortedFeedback::new();
let objective = DummyFeedback::new(false);
#[cfg(feature = "obj_collect")]
let objective = ExecTimeCollectorFeedback::new();
#[cfg(feature = "obj_trace")]
let objective = feedback_or!(HitSysStateFeedback::new(target_trace));
#[cfg(feature = "obj_edges")]
let objective = feedback_or!(HitFeedback::new(target_map,0.0,&edges_observer), objective);
#[cfg(feature = "obj_ticks")]
let objective = feedback_or!(ExecTimeReachedFeedback::new(targettime));
// create a State from scratch
let mut state = state.unwrap_or_else(||{
@ -412,9 +444,10 @@ fn fuzz(
let mutation = StdMutationalStage::new(mutator);
// A minimization+queue policy to get testcasess from the corpus
// let scheduler = IndexesLenTimeMinimizerCorpusScheduler::new(PowerQueueCorpusScheduler::new());
#[cfg(feature = "sched_queue")]
let scheduler = QueueCorpusScheduler::new();
#[cfg(feature = "sched_mapmax")]
let scheduler = LenTimeMaximizerCorpusScheduler::new(QueueCorpusScheduler::new());
#[cfg(feature = "sched_state")]
let scheduler = TimeStateMaximizerCorpusScheduler::new(QueueCorpusScheduler::new());
#[cfg(feature = "sched_graph")]
@ -545,6 +578,18 @@ fn fuzz(
fs::write("./graph.dot",tempg).expect("Graph can not be written");
}
// Wite out the collected exec times
#[cfg(feature = "obj_collect")]
match dump_exectimes {
Some(et) => unsafe {
let mut stringforms : Vec<String> = Vec::new();
for i in EXEC_TIME_COLLECTION.drain(..) {
stringforms.push(format!("{}\n",i));
}
fs::write(et,stringforms.concat()).expect("Exec times can not be written");
}
None => (),
}
// Never reached
Ok(())

View File

@ -1,3 +1,5 @@
use libafl::feedbacks::FeedbackState;
use libafl_qemu::QemuClockObserver;
use crate::sysstate::FreeRTOSSystemStateMetadata;
use num_traits::PrimInt;
use core::fmt::Debug;
@ -593,3 +595,121 @@ impl Default for SortedFeedback {
}
//===================================================================
/// A Feedback which expects a certain minimum execution time
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct ExecTimeReachedFeedback
{
target_time: u64,
}
impl<I, S> Feedback<I, S> for ExecTimeReachedFeedback
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::<QemuClockObserver>("clock")
.expect("QemuClockObserver not found");
Ok(observer.last_runtime() >= self.target_time)
}
}
impl Named for ExecTimeReachedFeedback
{
#[inline]
fn name(&self) -> &str {
"ExecTimeReachedFeedback"
}
}
impl ExecTimeReachedFeedback
where
{
/// Creates a new [`ExecTimeReachedFeedback`]
#[must_use]
pub fn new(target_time : u64) -> Self {
Self {target_time: target_time}
}
}
pub static mut EXEC_TIME_COLLECTION : Vec<u32> = Vec::new();
/// A Noop Feedback which records a list of all execution times
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct ExecTimeCollectorFeedback
{
}
impl<I, S> Feedback<I, S> for ExecTimeCollectorFeedback
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::<QemuClockObserver>("clock")
.expect("QemuClockObserver not found");
unsafe { EXEC_TIME_COLLECTION.push(observer.last_runtime().try_into().unwrap()); }
Ok(false)
}
}
impl Named for ExecTimeCollectorFeedback
{
#[inline]
fn name(&self) -> &str {
"ExecTimeCollectorFeedback"
}
}
impl ExecTimeCollectorFeedback
where
{
/// Creates a new [`ExecTimeCollectorFeedback`]
#[must_use]
pub fn new() -> Self {
Self {}
}
}
/// Shared Metadata for a SysStateFeedback
#[derive(Serialize, Deserialize, Clone, Debug, Default)]
pub struct ExecTimeCollectorFeedbackState
{
collection: Vec<u32>,
}
impl Named for ExecTimeCollectorFeedbackState
{
#[inline]
fn name(&self) -> &str {
"ExecTimeCollectorFeedbackState"
}
}
impl FeedbackState for ExecTimeCollectorFeedbackState
{
fn reset(&mut self) -> Result<(), Error> {
self.collection.clear();
Ok(())
}
}

View File

@ -1,4 +1,3 @@
use crate::libafl_exec_edge_one_off;
use std::ops::Range;
use hashbrown::{hash_map::Entry, HashMap};
use libafl::{executors::ExitKind, inputs::Input, observers::ObserversTuple, state::HasMetadata};