make generic edge-map post-processor
This commit is contained in:
parent
c252d6cad0
commit
bec4743978
@ -21,3 +21,4 @@ hashbrown = { version = "0.11", features = ["serde", "ahash-compile-time-rng"],
|
|||||||
nix = "0.23.0"
|
nix = "0.23.0"
|
||||||
goblin = "0.4.2"
|
goblin = "0.4.2"
|
||||||
either = "1.6.1"
|
either = "1.6.1"
|
||||||
|
num-traits = "0.2"
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
//! A singlethreaded QEMU fuzzer that can auto-restart.
|
//! A singlethreaded QEMU fuzzer that can auto-restart.
|
||||||
|
|
||||||
|
use wcet_qemu_sys::worst::QemuHashMapObserver;
|
||||||
use hashbrown::HashMap;
|
use hashbrown::HashMap;
|
||||||
use clap::{App, Arg};
|
use clap::{App, Arg};
|
||||||
use core::{cell::RefCell, time::Duration};
|
use core::{cell::RefCell, time::Duration};
|
||||||
@ -64,7 +65,7 @@ use libafl_qemu::{
|
|||||||
clock::ClockFeedback,
|
clock::ClockFeedback,
|
||||||
clock::QemuClockIncreaseFeedback
|
clock::QemuClockIncreaseFeedback
|
||||||
};
|
};
|
||||||
use wcet_qemu_sys::worst::{SortedFeedback,HitFeedback,HitcountsMapObserver,HitImprovingFeedback,LenTimeMaximizerCorpusScheduler};
|
use wcet_qemu_sys::worst::{SortedFeedback,HitFeedback,HitImprovingFeedback,LenTimeMaximizerCorpusScheduler};
|
||||||
|
|
||||||
|
|
||||||
/// The fuzzer main
|
/// The fuzzer main
|
||||||
@ -276,7 +277,7 @@ fn fuzz(
|
|||||||
let edges = unsafe { &mut edges::EDGES_MAP };
|
let edges = unsafe { &mut edges::EDGES_MAP };
|
||||||
let edges_counter = unsafe { &mut edges::MAX_EDGES_NUM };
|
let edges_counter = unsafe { &mut edges::MAX_EDGES_NUM };
|
||||||
let edges_observer =
|
let edges_observer =
|
||||||
HitcountsMapObserver::new(VariableMapObserver::new("edges", edges, edges_counter));
|
QemuHashMapObserver::new(VariableMapObserver::new("edges", edges, edges_counter));
|
||||||
|
|
||||||
// Create an observation channel to keep track of the execution time
|
// Create an observation channel to keep track of the execution time
|
||||||
// let time_observer = TimeObserver::new("time");
|
// let time_observer = TimeObserver::new("time");
|
||||||
@ -301,14 +302,14 @@ fn fuzz(
|
|||||||
let feedback = feedback_or!(
|
let feedback = feedback_or!(
|
||||||
// New maximization map feedback linked to the edges observer and the feedback state
|
// New maximization map feedback linked to the edges observer and the feedback state
|
||||||
MaxMapFeedback::new_tracking(&feedback_state, &edges_observer, true, false),
|
MaxMapFeedback::new_tracking(&feedback_state, &edges_observer, true, false),
|
||||||
// HitImprovingFeedback::new(target_map.clone()),
|
HitImprovingFeedback::new(target_map.clone(), &edges_observer),
|
||||||
QemuClockIncreaseFeedback::default(),
|
QemuClockIncreaseFeedback::default(),
|
||||||
ClockFeedback::new_with_observer(&clock_observer)
|
ClockFeedback::new_with_observer(&clock_observer)
|
||||||
);
|
);
|
||||||
|
|
||||||
// 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 = HitFeedback::new(target_map,0.0);
|
let objective = HitFeedback::new(target_map,0.0,&edges_observer);
|
||||||
let objective = SortedFeedback::new();
|
// let objective = SortedFeedback::new();
|
||||||
|
|
||||||
// create a State from scratch
|
// create a State from scratch
|
||||||
let mut state = state.unwrap_or_else(||{
|
let mut state = state.unwrap_or_else(||{
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
//! A singlethreaded QEMU fuzzer that can auto-restart.
|
//! A singlethreaded QEMU fuzzer that can auto-restart.
|
||||||
|
|
||||||
|
use wcet_qemu_sys::worst::QemuHashMapObserver;
|
||||||
use wcet_qemu_sys::{
|
use wcet_qemu_sys::{
|
||||||
worst::{DumpMapFeedback,DummyFeedback,HitcountsMapObserver},
|
worst::{DumpMapFeedback,DummyFeedback},
|
||||||
system_trace::QemuSystemStateHelper,
|
system_trace::QemuSystemStateHelper,
|
||||||
};
|
};
|
||||||
use clap::{App, Arg};
|
use clap::{App, Arg};
|
||||||
@ -262,13 +263,13 @@ fn fuzz(
|
|||||||
let edges = unsafe { &mut edges::EDGES_MAP };
|
let edges = unsafe { &mut edges::EDGES_MAP };
|
||||||
let edges_counter = unsafe { &mut edges::MAX_EDGES_NUM };
|
let edges_counter = unsafe { &mut edges::MAX_EDGES_NUM };
|
||||||
let edges_observer =
|
let edges_observer =
|
||||||
HitcountsMapObserver::new(VariableMapObserver::new("edges", edges, edges_counter));
|
QemuHashMapObserver::new(VariableMapObserver::new("edges", edges, edges_counter));
|
||||||
|
|
||||||
//========== Observe Execution Cycles
|
//========== Observe Execution Cycles
|
||||||
let clock_observer = QemuClockObserver::default();
|
let clock_observer = QemuClockObserver::default();
|
||||||
|
|
||||||
//========= Feedback-Function evaluate the Maps. Need to dump it for debugging and check if it reaches targets.
|
//========= Feedback-Function evaluate the Maps. Need to dump it for debugging and check if it reaches targets.
|
||||||
let feedback = DumpMapFeedback::with_dump(dump_edges);
|
let feedback = DumpMapFeedback::with_dump(dump_edges, &edges_observer);
|
||||||
|
|
||||||
// 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 = DummyFeedback::new(false);
|
let objective = DummyFeedback::new(false);
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
use num_traits::PrimInt;
|
||||||
|
use core::fmt::Debug;
|
||||||
use core::cmp::Ordering::{Greater,Less,Equal};
|
use core::cmp::Ordering::{Greater,Less,Equal};
|
||||||
use libafl::inputs::BytesInput;
|
use libafl::inputs::BytesInput;
|
||||||
use libafl::inputs::HasTargetBytes;
|
use libafl::inputs::HasTargetBytes;
|
||||||
@ -8,7 +10,6 @@ use core::marker::PhantomData;
|
|||||||
use libafl::corpus::MinimizerCorpusScheduler;
|
use libafl::corpus::MinimizerCorpusScheduler;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use libafl::observers::VariableMapObserver;
|
|
||||||
use hashbrown::{HashMap};
|
use hashbrown::{HashMap};
|
||||||
use libafl::observers::ObserversTuple;
|
use libafl::observers::ObserversTuple;
|
||||||
use libafl::executors::ExitKind;
|
use libafl::executors::ExitKind;
|
||||||
@ -30,36 +31,23 @@ use libafl::{
|
|||||||
observers::Observer,
|
observers::Observer,
|
||||||
Error,
|
Error,
|
||||||
};
|
};
|
||||||
|
//===================================================================
|
||||||
/// Map observer with hitcounts postprocessing
|
/// A wrapper around some other [`MapObserver`], using [`QemuEdgesMapMetadata`] to offer a convinient Hashmap.
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||||
#[serde(bound = "M: serde::de::DeserializeOwned")]
|
#[serde(bound = "M: serde::de::DeserializeOwned")]
|
||||||
pub struct HitcountsMapObserver<M>
|
pub struct QemuHashMapObserver<M,T>
|
||||||
where
|
where
|
||||||
M: serde::Serialize + serde::de::DeserializeOwned,
|
M: serde::Serialize + serde::de::DeserializeOwned,
|
||||||
|
T: PrimInt + Default + Copy + 'static + Serialize + serde::de::DeserializeOwned + Debug,
|
||||||
{
|
{
|
||||||
base: M,
|
base: M,
|
||||||
pub edgemap: HashMap<(u64,u64),u8>,
|
pub edgemap: HashMap<(u64,u64),T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
static COUNT_CLASS_LOOKUP: [u8; 256] = [
|
impl<I, S, M, T> Observer<I, S> for QemuHashMapObserver<M, T>
|
||||||
0, 1, 2, 4, 8, 8, 8, 8, 16, 16, 16, 16, 16, 16, 16, 16, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
|
|
||||||
32, 32, 32, 32, 32, 32, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
|
||||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
|
||||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
|
||||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
|
||||||
64, 64, 64, 64, 64, 64, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
|
|
||||||
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
|
|
||||||
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
|
|
||||||
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
|
|
||||||
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
|
|
||||||
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
|
|
||||||
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
|
|
||||||
];
|
|
||||||
|
|
||||||
impl<I, S, M> Observer<I, S> for HitcountsMapObserver<M>
|
|
||||||
where
|
where
|
||||||
M: MapObserver<u8> + Observer<I, S>,
|
M: MapObserver<T> + Observer<I, S>,
|
||||||
|
T: PrimInt + Default + Copy + 'static + Serialize + serde::de::DeserializeOwned + Debug,
|
||||||
S: HasMetadata, // Need to grab the HashMap from a Helper
|
S: HasMetadata, // Need to grab the HashMap from a Helper
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -70,25 +58,18 @@ where
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn post_exec(&mut self, state: &mut S, input: &I) -> Result<(), Error> {
|
fn post_exec(&mut self, state: &mut S, input: &I) -> Result<(), Error> {
|
||||||
//new stuff
|
let original_hashmap=&state.metadata().get::<QemuEdgesMapMetadata>().expect("QemuEdgesMapMetadata not found").map;
|
||||||
let original_hashmap=&state.metadata().get::<QemuEdgesMapMetadata>().unwrap().map;
|
|
||||||
for (key, val) in original_hashmap.iter() {
|
for (key, val) in original_hashmap.iter() {
|
||||||
self.edgemap.insert(*key,*self.base.get(*val as usize));
|
self.edgemap.insert(*key,*self.base.get(*val as usize));
|
||||||
}
|
}
|
||||||
// println!("Post-Exec Len: {} Cap: {}",self.edgemap.len(),self.edgemap.capacity());
|
|
||||||
// println!("{:#?}",self.edgemap);
|
|
||||||
//end new stuff
|
|
||||||
let cnt = self.usable_count();
|
|
||||||
for i in 0..cnt {
|
|
||||||
*self.get_mut(i) = COUNT_CLASS_LOOKUP[*self.get(i) as usize];
|
|
||||||
}
|
|
||||||
self.base.post_exec(state, input)
|
self.base.post_exec(state, input)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<M> Named for HitcountsMapObserver<M>
|
impl<M, T> Named for QemuHashMapObserver<M, T>
|
||||||
where
|
where
|
||||||
M: Named + serde::Serialize + serde::de::DeserializeOwned,
|
M: Named + serde::Serialize + serde::de::DeserializeOwned,
|
||||||
|
T: PrimInt + Default + Copy + 'static + Serialize + serde::de::DeserializeOwned + Debug,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
@ -96,9 +77,10 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<M> HasLen for HitcountsMapObserver<M>
|
impl<M, T> HasLen for QemuHashMapObserver<M, T>
|
||||||
where
|
where
|
||||||
M: MapObserver<u8>,
|
M: MapObserver<u8>,
|
||||||
|
T: PrimInt + Default + Copy + 'static + Serialize + serde::de::DeserializeOwned + Debug,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn len(&self) -> usize {
|
fn len(&self) -> usize {
|
||||||
@ -106,9 +88,10 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<M> MapObserver<u8> for HitcountsMapObserver<M>
|
impl<M, T> MapObserver<u8> for QemuHashMapObserver<M, T>
|
||||||
where
|
where
|
||||||
M: MapObserver<u8>,
|
M: MapObserver<u8>,
|
||||||
|
T: PrimInt + Default + Copy + 'static + Serialize + serde::de::DeserializeOwned + Debug,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn map(&self) -> Option<&[u8]> {
|
fn map(&self) -> Option<&[u8]> {
|
||||||
@ -141,9 +124,10 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<M> HitcountsMapObserver<M>
|
impl<M, T> QemuHashMapObserver<M, T>
|
||||||
where
|
where
|
||||||
M: serde::Serialize + serde::de::DeserializeOwned,
|
M: serde::Serialize + serde::de::DeserializeOwned,
|
||||||
|
T: PrimInt + Default + Copy + 'static + Serialize + serde::de::DeserializeOwned + Debug,
|
||||||
{
|
{
|
||||||
/// Creates a new [`MapObserver`]
|
/// Creates a new [`MapObserver`]
|
||||||
pub fn new(base: M) -> Self {
|
pub fn new(base: M) -> Self {
|
||||||
@ -156,15 +140,23 @@ where
|
|||||||
|
|
||||||
/// A [`HitFeedback`] reports as interesting when all predicted worst case edges have been matched.
|
/// A [`HitFeedback`] reports as interesting when all predicted worst case edges have been matched.
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||||
pub struct HitFeedback {
|
#[serde(bound = "T: serde::de::DeserializeOwned")]
|
||||||
target_map: HashMap<(u64,u64),u8>,
|
pub struct HitFeedback<O, T>
|
||||||
|
where
|
||||||
|
T: PrimInt + Default + Copy + 'static + Serialize + serde::de::DeserializeOwned + Debug,
|
||||||
|
O: MapObserver<T>,
|
||||||
|
{
|
||||||
|
target_map: HashMap<(u64,u64),T>,
|
||||||
target_msd: f64,
|
target_msd: f64,
|
||||||
|
phantom: PhantomData<(O, T)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<I, S> Feedback<I, S> for HitFeedback
|
impl<I, S, T, O> Feedback<I, S> for HitFeedback<O, T>
|
||||||
where
|
where
|
||||||
I: Input,
|
I: Input,
|
||||||
S: HasClientPerfMonitor,
|
S: HasClientPerfMonitor,
|
||||||
|
T: PrimInt + Default + Copy + 'static + Serialize + serde::de::DeserializeOwned + Debug,
|
||||||
|
O: MapObserver<T>,
|
||||||
{
|
{
|
||||||
fn is_interesting<EM, OT>(
|
fn is_interesting<EM, OT>(
|
||||||
&mut self,
|
&mut self,
|
||||||
@ -178,15 +170,17 @@ where
|
|||||||
EM: EventFirer<I>,
|
EM: EventFirer<I>,
|
||||||
OT: ObserversTuple<I, S>,
|
OT: ObserversTuple<I, S>,
|
||||||
{
|
{
|
||||||
let observer = _observers.match_name::<HitcountsMapObserver<VariableMapObserver<u8>>>("edges")
|
let observer = _observers.match_name::<QemuHashMapObserver<O, T>>("edges")
|
||||||
.expect("HitcountsMapObserver not found");
|
.expect("QemuHashMapObserver not found");
|
||||||
if self.target_map.len() == 0 { return Ok(false) };
|
if self.target_map.len() == 0 { return Ok(false) };
|
||||||
|
|
||||||
let mut sum_of_square_difference : u64 = 0; // does not include found edges not in target
|
let mut sum_of_square_difference : u64 = 0; // does not include found edges not in target
|
||||||
for (edg, val) in &self.target_map {
|
for (edg, val) in &self.target_map {
|
||||||
match observer.edgemap.get(&edg) {
|
match observer.edgemap.get(&edg) {
|
||||||
Some(x) => sum_of_square_difference+=((cmp::max(*x,*val)-cmp::min(*x,*val)) as u64).pow(2),
|
Some(x) => {
|
||||||
None => sum_of_square_difference+=(*val as u64).pow(2),
|
sum_of_square_difference+=((cmp::max(*x,*val)-cmp::min(*x,*val)).to_u64().unwrap()).pow(2);
|
||||||
|
},
|
||||||
|
None => sum_of_square_difference+=((*val).to_u64().unwrap()).pow(2),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let mean_sum_of_squares = (sum_of_square_difference as f64) / (self.target_map.len() as f64);
|
let mean_sum_of_squares = (sum_of_square_difference as f64) / (self.target_map.len() as f64);
|
||||||
@ -200,99 +194,111 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Named for HitFeedback {
|
impl<O, T> Named for HitFeedback<O, T>
|
||||||
|
where
|
||||||
|
T: PrimInt + Default + Copy + 'static + Serialize + serde::de::DeserializeOwned + Debug,
|
||||||
|
O: MapObserver<T>,
|
||||||
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"HitFeedback"
|
"HitFeedback"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HitFeedback {
|
impl<O, T> HitFeedback<O, T>
|
||||||
|
where
|
||||||
|
T: PrimInt + Default + Copy + 'static + Serialize + serde::de::DeserializeOwned + Debug,
|
||||||
|
O: MapObserver<T>,
|
||||||
|
{
|
||||||
/// Creates a new [`HitFeedback`]
|
/// Creates a new [`HitFeedback`]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn new(target_map: HashMap<(u64,u64),u8>, target_msd: f64) -> Self {
|
pub fn new(target_map: HashMap<(u64,u64),T>, target_msd: f64, _map_observer: &O) -> Self {
|
||||||
Self {target_map: target_map, target_msd: target_msd}
|
Self {target_map: target_map, target_msd: target_msd, phantom: PhantomData}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for HitFeedback {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self::new(HashMap::new(),0.0)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//===================================================================
|
//===================================================================
|
||||||
|
|
||||||
|
|
||||||
/// A [`MapHitIncreaseFeedback`] reports as interesting when the total number of used edges increases.
|
// /// A [`MapHitIncreaseFeedback`] reports as interesting when the total number of used edges increases.
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
// #[derive(Serialize, Deserialize, Clone, Debug)]
|
||||||
pub struct MapHitIncreaseFeedback {
|
// pub struct MapHitIncreaseFeedback {
|
||||||
record_high : u64,
|
// record_high : u64,
|
||||||
}
|
// }
|
||||||
|
|
||||||
impl<I, S> Feedback<I, S> for MapHitIncreaseFeedback
|
// impl<I, S, O, T> Feedback<I, S> for MapHitIncreaseFeedback
|
||||||
where
|
// where
|
||||||
I: Input,
|
// I: Input,
|
||||||
S: HasClientPerfMonitor,
|
// S: HasClientPerfMonitor,
|
||||||
{
|
// T: PrimInt + Default + Copy + 'static + Serialize + serde::de::DeserializeOwned + Debug,
|
||||||
fn is_interesting<EM, OT>(
|
// O: MapObserver<T>,
|
||||||
&mut self,
|
// {
|
||||||
_state: &mut S,
|
// fn is_interesting<EM, OT>(
|
||||||
_manager: &mut EM,
|
// &mut self,
|
||||||
_input: &I,
|
// _state: &mut S,
|
||||||
_observers: &OT,
|
// _manager: &mut EM,
|
||||||
_exit_kind: &ExitKind,
|
// _input: &I,
|
||||||
) -> Result<bool, Error>
|
// _observers: &OT,
|
||||||
where
|
// _exit_kind: &ExitKind,
|
||||||
EM: EventFirer<I>,
|
// ) -> Result<bool, Error>
|
||||||
OT: ObserversTuple<I, S>,
|
// where
|
||||||
{
|
// EM: EventFirer<I>,
|
||||||
let observer = _observers.match_name::<HitcountsMapObserver<VariableMapObserver<u8>>>("edges")
|
// OT: ObserversTuple<I, S>,
|
||||||
.expect("HitcountsMapObserver not found");
|
// {
|
||||||
let cur = observer.edgemap.values().fold(0,|a,b| a+(*b as u64));
|
// let observer = _observers.match_name::<QemuHashMapObserver<O, T>>("edges")
|
||||||
if cur > self.record_high {
|
// .expect("QemuHashMapObserver not found");
|
||||||
self.record_high = cur;
|
// let cur = observer.edgemap.values().fold(0,|a,b| a+(*b as u64));
|
||||||
return Ok(true);
|
// if cur > self.record_high {
|
||||||
}
|
// self.record_high = cur;
|
||||||
return Ok(false);
|
// return Ok(true);
|
||||||
}
|
// }
|
||||||
}
|
// return Ok(false);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
impl Named for MapHitIncreaseFeedback {
|
// impl Named for MapHitIncreaseFeedback {
|
||||||
#[inline]
|
// #[inline]
|
||||||
fn name(&self) -> &str {
|
// fn name(&self) -> &str {
|
||||||
"HitFeedback"
|
// "HitFeedback"
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
impl MapHitIncreaseFeedback {
|
// impl MapHitIncreaseFeedback {
|
||||||
/// Creates a new [`HitFeedback`]
|
// /// Creates a new [`HitFeedback`]
|
||||||
#[must_use]
|
// #[must_use]
|
||||||
pub fn new() -> Self {
|
// pub fn new() -> Self {
|
||||||
Self {record_high: 0}
|
// Self {record_high: 0}
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
impl Default for MapHitIncreaseFeedback {
|
// impl Default for MapHitIncreaseFeedback {
|
||||||
fn default() -> Self {
|
// fn default() -> Self {
|
||||||
Self::new()
|
// Self::new()
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
//===================================================================
|
//===================================================================
|
||||||
|
|
||||||
|
|
||||||
/// A [`HitFeedback`] reports as interesting when all predicted worst case edges have been matched.
|
/// A [`HitFeedback`] reports as interesting when all predicted worst case edges have been matched.
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||||
pub struct HitImprovingFeedback {
|
#[serde(bound = "T: serde::de::DeserializeOwned")]
|
||||||
target_map: HashMap<(u64,u64),u8>,
|
pub struct HitImprovingFeedback<O, T>
|
||||||
|
where
|
||||||
|
T: PrimInt + Default + Copy + 'static + Serialize + serde::de::DeserializeOwned + Debug,
|
||||||
|
O: MapObserver<T>,
|
||||||
|
{
|
||||||
|
target_map: HashMap<(u64,u64),T>,
|
||||||
best_msd: f64,
|
best_msd: f64,
|
||||||
|
phantom: PhantomData<(O, T)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<I, S> Feedback<I, S> for HitImprovingFeedback
|
impl<O, T, I, S> Feedback<I, S> for HitImprovingFeedback<O, T>
|
||||||
where
|
where
|
||||||
I: Input,
|
I: Input,
|
||||||
S: HasClientPerfMonitor,
|
S: HasClientPerfMonitor,
|
||||||
|
T: PrimInt + Default + Copy + 'static + Serialize + serde::de::DeserializeOwned + Debug,
|
||||||
|
O: MapObserver<T>,
|
||||||
{
|
{
|
||||||
fn is_interesting<EM, OT>(
|
fn is_interesting<EM, OT>(
|
||||||
&mut self,
|
&mut self,
|
||||||
@ -306,15 +312,17 @@ where
|
|||||||
EM: EventFirer<I>,
|
EM: EventFirer<I>,
|
||||||
OT: ObserversTuple<I, S>,
|
OT: ObserversTuple<I, S>,
|
||||||
{
|
{
|
||||||
let observer = _observers.match_name::<HitcountsMapObserver<VariableMapObserver<u8>>>("edges")
|
let observer = _observers.match_name::<QemuHashMapObserver<O, T>>("edges")
|
||||||
.expect("HitcountsMapObserver not found");
|
.expect("QemuHashMapObserver not found");
|
||||||
if self.target_map.len() == 0 { return Ok(false) };
|
if self.target_map.len() == 0 { return Ok(false) };
|
||||||
|
|
||||||
let mut sum_of_square_difference : u64 = 0; // does not include found edges not in target
|
let mut sum_of_square_difference : u64 = 0; // does not include found edges not in target
|
||||||
for (edg, val) in &self.target_map {
|
for (edg, val) in &self.target_map {
|
||||||
match observer.edgemap.get(&edg) {
|
match observer.edgemap.get(&edg) {
|
||||||
Some(x) => sum_of_square_difference+=((cmp::max(*x,*val)-cmp::min(*x,*val)) as u64).pow(2),
|
Some(x) => {
|
||||||
None => sum_of_square_difference+=(*val as u64).pow(2),
|
sum_of_square_difference+=((cmp::max(*x,*val)-cmp::min(*x,*val)).to_u64().unwrap()).pow(2);
|
||||||
|
},
|
||||||
|
None => sum_of_square_difference+=((*val).to_u64().unwrap()).pow(2),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let mean_sum_of_squares = (sum_of_square_difference as f64) / (self.target_map.len() as f64);
|
let mean_sum_of_squares = (sum_of_square_difference as f64) / (self.target_map.len() as f64);
|
||||||
@ -329,38 +337,47 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Named for HitImprovingFeedback {
|
impl<O, T> Named for HitImprovingFeedback<O, T>
|
||||||
|
where
|
||||||
|
T: PrimInt + Default + Copy + 'static + Serialize + serde::de::DeserializeOwned + Debug,
|
||||||
|
O: MapObserver<T>,
|
||||||
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"HitFeedback"
|
"HitImprovingFeedback"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HitImprovingFeedback {
|
impl<O, T> HitImprovingFeedback<O, T>
|
||||||
/// Creates a new [`HitFeedback`]
|
where
|
||||||
|
T: PrimInt + Default + Copy + 'static + Serialize + serde::de::DeserializeOwned + Debug,
|
||||||
|
O: MapObserver<T>,
|
||||||
|
{
|
||||||
|
/// Creates a new [`HitImprovingFeedback`]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn new(target_map: HashMap<(u64,u64),u8>) -> Self {
|
pub fn new(target_map: HashMap<(u64,u64),T>, _map_observer: &O) -> Self {
|
||||||
Self {target_map: target_map, best_msd: f64::MAX}
|
Self {target_map: target_map, best_msd: f64::MAX, phantom: PhantomData}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for HitImprovingFeedback {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self::new(HashMap::new())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//=========================== Debugging Feedback
|
//=========================== Debugging Feedback
|
||||||
/// A [`Feedback`] meant to dump the edgemap for debugging.
|
/// A [`Feedback`] meant to dump the edgemap for debugging.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct DumpMapFeedback {
|
pub struct DumpMapFeedback<O, T>
|
||||||
dumpfile: Option<PathBuf>
|
where
|
||||||
|
T: PrimInt + Default + Copy + 'static + Serialize + serde::de::DeserializeOwned + Debug,
|
||||||
|
O: MapObserver<T>,
|
||||||
|
{
|
||||||
|
dumpfile: Option<PathBuf>,
|
||||||
|
phantom: PhantomData<(O, T)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<I, S> Feedback<I, S> for DumpMapFeedback
|
impl<I, S, O, T> Feedback<I, S> for DumpMapFeedback<O, T>
|
||||||
where
|
where
|
||||||
I: Input,
|
I: Input,
|
||||||
S: HasClientPerfMonitor,
|
S: HasClientPerfMonitor,
|
||||||
|
T: PrimInt + Default + Copy + 'static + Serialize + serde::de::DeserializeOwned + Debug,
|
||||||
|
O: MapObserver<T>,
|
||||||
{
|
{
|
||||||
fn is_interesting<EM, OT>(
|
fn is_interesting<EM, OT>(
|
||||||
&mut self,
|
&mut self,
|
||||||
@ -374,8 +391,8 @@ where
|
|||||||
EM: EventFirer<I>,
|
EM: EventFirer<I>,
|
||||||
OT: ObserversTuple<I, S>,
|
OT: ObserversTuple<I, S>,
|
||||||
{
|
{
|
||||||
let observer = _observers.match_name::<HitcountsMapObserver<VariableMapObserver<u8>>>("edges")
|
let observer = _observers.match_name::<QemuHashMapObserver<O, T>>("edges")
|
||||||
.expect("HitcountsMapObserver not found");
|
.expect("QemuHashMapObserver not found");
|
||||||
match &self.dumpfile {
|
match &self.dumpfile {
|
||||||
Some(s) => {
|
Some(s) => {
|
||||||
fs::write(s,ron::to_string(&observer.edgemap).expect("Error serializing hashmap")).expect("Can not dump to file");
|
fs::write(s,ron::to_string(&observer.edgemap).expect("Error serializing hashmap")).expect("Can not dump to file");
|
||||||
@ -387,27 +404,29 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Named for DumpMapFeedback {
|
impl<O, T> Named for DumpMapFeedback<O, T>
|
||||||
|
where
|
||||||
|
T: PrimInt + Default + Copy + 'static + Serialize + serde::de::DeserializeOwned + Debug,
|
||||||
|
O: MapObserver<T>,
|
||||||
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"HitFeedback"
|
"HitFeedback"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DumpMapFeedback {
|
impl<O, T> DumpMapFeedback<O, T>
|
||||||
|
where
|
||||||
|
T: PrimInt + Default + Copy + 'static + Serialize + serde::de::DeserializeOwned + Debug,
|
||||||
|
O: MapObserver<T>,
|
||||||
|
{
|
||||||
/// Creates a new [`HitFeedback`]
|
/// Creates a new [`HitFeedback`]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn new() -> Self {
|
pub fn new(_map_observer: &O) -> Self {
|
||||||
Self {dumpfile: None}
|
Self {dumpfile: None, phantom: PhantomData}
|
||||||
}
|
}
|
||||||
pub fn with_dump(dumpfile: Option<PathBuf>) -> Self {
|
pub fn with_dump(dumpfile: Option<PathBuf>,_map_observer: &O) -> Self {
|
||||||
Self {dumpfile: dumpfile}
|
Self {dumpfile: dumpfile, phantom: PhantomData}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for DumpMapFeedback {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self::new()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -511,6 +530,8 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//===================================================================
|
||||||
|
|
||||||
/// A Feedback reporting if the Input consists of strictly decreasing bytes.
|
/// A Feedback reporting if the Input consists of strictly decreasing bytes.
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||||
pub struct SortedFeedback {
|
pub struct SortedFeedback {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user