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"
|
edition = "2021"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["std"]
|
default = ["std", "obj_collect"]
|
||||||
std = []
|
std = []
|
||||||
multicore = []
|
multicore = []
|
||||||
|
|
||||||
@ -21,6 +21,12 @@ sched_mapmax = []
|
|||||||
sched_state = []
|
sched_state = []
|
||||||
sched_graph = []
|
sched_graph = []
|
||||||
|
|
||||||
|
# objective selection, additive
|
||||||
|
obj_collect = []
|
||||||
|
obj_trace = []
|
||||||
|
obj_edges = []
|
||||||
|
obj_ticks = []
|
||||||
|
|
||||||
muta_snip = [ "sched_graph" ]
|
muta_snip = [ "sched_graph" ]
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
//! A singlethreaded QEMU fuzzer that can auto-restart.
|
//! 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::inputs::Input;
|
||||||
use libafl::feedbacks::Feedback;
|
use libafl::feedbacks::Feedback;
|
||||||
use libafl::HasFeedback;
|
use libafl::HasFeedback;
|
||||||
@ -86,7 +90,7 @@ use libafl_qemu::{
|
|||||||
clock::ClockFeedback,
|
clock::ClockFeedback,
|
||||||
clock::QemuClockIncreaseFeedback
|
clock::QemuClockIncreaseFeedback
|
||||||
};
|
};
|
||||||
use wcet_qemu_sys::worst::{SortedFeedback,HitFeedback,HitImprovingFeedback,TimeStateMaximizerCorpusScheduler};
|
use wcet_qemu_sys::worst::{SortedFeedback,HitFeedback,HitImprovingFeedback,TimeStateMaximizerCorpusScheduler,LenTimeMaximizerCorpusScheduler};
|
||||||
|
|
||||||
|
|
||||||
/// The fuzzer main
|
/// The fuzzer main
|
||||||
@ -154,6 +158,16 @@ pub fn main() {
|
|||||||
.required(true)
|
.required(true)
|
||||||
.takes_value(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())
|
.try_get_matches_from(filter_qemu_args())
|
||||||
{
|
{
|
||||||
Ok(res) => res,
|
Ok(res) => res,
|
||||||
@ -216,9 +230,19 @@ pub fn main() {
|
|||||||
None => None
|
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());
|
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");
|
.expect("An error occurred while fuzzing");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -246,6 +270,8 @@ fn fuzz(
|
|||||||
kernel: PathBuf,
|
kernel: PathBuf,
|
||||||
dump_edges: Option<PathBuf>,
|
dump_edges: Option<PathBuf>,
|
||||||
dump_traces: Option<PathBuf>,
|
dump_traces: Option<PathBuf>,
|
||||||
|
dump_exectimes: Option<PathBuf>,
|
||||||
|
targettime: Option<u64>,
|
||||||
snapshot: PathBuf,
|
snapshot: PathBuf,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
env::remove_var("LD_LIBRARY_PATH");
|
env::remove_var("LD_LIBRARY_PATH");
|
||||||
@ -375,9 +401,15 @@ fn fuzz(
|
|||||||
let feedback = feedback_or!(feedback, SysMapFeedback::new());
|
let feedback = feedback_or!(feedback, SysMapFeedback::new());
|
||||||
|
|
||||||
// A feedback to choose if an input is a solution or not
|
// 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 = DummyFeedback::new(false);
|
||||||
// let objective = feedback_or!(HitFeedback::new(target_map,0.0,&edges_observer));
|
#[cfg(feature = "obj_collect")]
|
||||||
// let objective = SortedFeedback::new();
|
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
|
// create a State from scratch
|
||||||
let mut state = state.unwrap_or_else(||{
|
let mut state = state.unwrap_or_else(||{
|
||||||
@ -412,9 +444,10 @@ fn fuzz(
|
|||||||
let mutation = StdMutationalStage::new(mutator);
|
let mutation = StdMutationalStage::new(mutator);
|
||||||
|
|
||||||
// A minimization+queue policy to get testcasess from the corpus
|
// A minimization+queue policy to get testcasess from the corpus
|
||||||
// let scheduler = IndexesLenTimeMinimizerCorpusScheduler::new(PowerQueueCorpusScheduler::new());
|
|
||||||
#[cfg(feature = "sched_queue")]
|
#[cfg(feature = "sched_queue")]
|
||||||
let scheduler = QueueCorpusScheduler::new();
|
let scheduler = QueueCorpusScheduler::new();
|
||||||
|
#[cfg(feature = "sched_mapmax")]
|
||||||
|
let scheduler = LenTimeMaximizerCorpusScheduler::new(QueueCorpusScheduler::new());
|
||||||
#[cfg(feature = "sched_state")]
|
#[cfg(feature = "sched_state")]
|
||||||
let scheduler = TimeStateMaximizerCorpusScheduler::new(QueueCorpusScheduler::new());
|
let scheduler = TimeStateMaximizerCorpusScheduler::new(QueueCorpusScheduler::new());
|
||||||
#[cfg(feature = "sched_graph")]
|
#[cfg(feature = "sched_graph")]
|
||||||
@ -545,6 +578,18 @@ fn fuzz(
|
|||||||
fs::write("./graph.dot",tempg).expect("Graph can not be written");
|
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
|
// Never reached
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
use libafl::feedbacks::FeedbackState;
|
||||||
|
use libafl_qemu::QemuClockObserver;
|
||||||
use crate::sysstate::FreeRTOSSystemStateMetadata;
|
use crate::sysstate::FreeRTOSSystemStateMetadata;
|
||||||
use num_traits::PrimInt;
|
use num_traits::PrimInt;
|
||||||
use core::fmt::Debug;
|
use core::fmt::Debug;
|
||||||
@ -592,4 +594,122 @@ 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 std::ops::Range;
|
||||||
use hashbrown::{hash_map::Entry, HashMap};
|
use hashbrown::{hash_map::Entry, HashMap};
|
||||||
use libafl::{executors::ExitKind, inputs::Input, observers::ObserversTuple, state::HasMetadata};
|
use libafl::{executors::ExitKind, inputs::Input, observers::ObserversTuple, state::HasMetadata};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user