make generic edge-map post-processor

This commit is contained in:
Alwin Berger 2022-02-11 19:44:12 +01:00
parent c252d6cad0
commit bec4743978
4 changed files with 170 additions and 146 deletions

View File

@ -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"

View File

@ -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(||{

View File

@ -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);

View File

@ -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 {