add objective selection, dump exec times
This commit is contained in:
parent
14e8a81d17
commit
ee4056a008
@ -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]
|
||||
|
@ -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(())
|
||||
|
@ -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(())
|
||||
}
|
||||
}
|
@ -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};
|
||||
|
Loading…
x
Reference in New Issue
Block a user