update to 0.13.0 API

This commit is contained in:
Alwin Berger 2024-06-19 13:30:36 +02:00
parent df7333b764
commit 5fad373199
17 changed files with 313 additions and 235 deletions

View File

@ -11,8 +11,9 @@ use libafl::{
fuzzer::{StdFuzzer}, fuzzer::{StdFuzzer},
inputs::{BytesInput, HasTargetBytes}, inputs::{BytesInput, HasTargetBytes},
observers::{Observer,VariableMapObserver}, observers::{Observer,VariableMapObserver},
state::{StdState, HasNamedMetadata}, state::{StdState},
Error, Error,
common::HasNamedMetadata,
observers::ObserversTuple, prelude::UsesInput, observers::ObserversTuple, prelude::UsesInput,
}; };
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -22,7 +23,7 @@ use libafl_qemu::{
emu, emu,
emu::Emulator, emu::Emulator,
executor::QemuExecutor, executor::QemuExecutor,
helper::{QemuHelper, QemuHelperTuple, QemuInstrumentationFilter}, helpers::{QemuHelper, QemuHelperTuple, HasInstrumentationFilter},
}; };
use libafl::events::EventFirer; use libafl::events::EventFirer;
use libafl::state::MaybeHasClientPerfMonitor; use libafl::state::MaybeHasClientPerfMonitor;
@ -30,13 +31,14 @@ use libafl::prelude::State;
use libafl::inputs::Input; use libafl::inputs::Input;
use libafl::feedbacks::Feedback; use libafl::feedbacks::Feedback;
use libafl::SerdeAny; use libafl::SerdeAny;
use libafl::state::HasMetadata; use libafl::common::HasMetadata;
use libafl::corpus::testcase::Testcase; use libafl::corpus::testcase::Testcase;
use core::{fmt::Debug, time::Duration}; use core::{fmt::Debug, time::Duration};
// use libafl::feedbacks::FeedbackState; // use libafl::feedbacks::FeedbackState;
// use libafl::state::HasFeedbackStates; // use libafl::state::HasFeedbackStates;
use std::time::{SystemTime, UNIX_EPOCH}; use std::time::{SystemTime, UNIX_EPOCH};
use std::path::PathBuf; use std::path::PathBuf;
use std::borrow::Cow;
pub static mut FUZZ_START_TIMESTAMP : SystemTime = UNIX_EPOCH; pub static mut FUZZ_START_TIMESTAMP : SystemTime = UNIX_EPOCH;
@ -60,7 +62,7 @@ pub struct QemuIcountMetadata {
#[derive(Debug, Serialize, Deserialize, SerdeAny)] #[derive(Debug, Serialize, Deserialize, SerdeAny)]
pub struct MaxIcountMetadata { pub struct MaxIcountMetadata {
pub max_icount_seen: u64, pub max_icount_seen: u64,
pub name: String, pub name: Cow<'static, str>,
} }
// impl FeedbackState for MaxIcountMetadata // impl FeedbackState for MaxIcountMetadata
@ -74,8 +76,8 @@ pub struct MaxIcountMetadata {
impl Named for MaxIcountMetadata impl Named for MaxIcountMetadata
{ {
#[inline] #[inline]
fn name(&self) -> &str { fn name(&self) -> &Cow<'static, str> {
self.name.as_str() &self.name
} }
} }
@ -86,7 +88,7 @@ impl MaxIcountMetadata
pub fn new(name: &'static str) -> Self { pub fn new(name: &'static str) -> Self {
Self { Self {
max_icount_seen: 0, max_icount_seen: 0,
name: name.to_string(), name: Cow::from(name),
} }
} }
} }
@ -106,7 +108,7 @@ pub struct IcHist (pub Vec<(u64, u128)>, pub (u64,u128));
/// A simple observer, just overlooking the runtime of the target. /// A simple observer, just overlooking the runtime of the target.
#[derive(Serialize, Deserialize, Debug, Clone)] #[derive(Serialize, Deserialize, Debug, Clone)]
pub struct QemuClockObserver { pub struct QemuClockObserver {
name: String, name: Cow<'static, str>,
start_tick: u64, start_tick: u64,
end_tick: u64, end_tick: u64,
dump_path: Option<PathBuf> dump_path: Option<PathBuf>
@ -117,7 +119,7 @@ impl QemuClockObserver {
#[must_use] #[must_use]
pub fn new(name: &'static str, dump_path: Option<PathBuf>) -> Self { pub fn new(name: &'static str, dump_path: Option<PathBuf>) -> Self {
Self { Self {
name: name.to_string(), name: Cow::from(name),
start_tick: 0, start_tick: 0,
end_tick: 0, end_tick: 0,
dump_path dump_path
@ -149,7 +151,7 @@ where
} }
fn post_exec(&mut self, _state: &mut S, _input: &S::Input, _exit_kind: &ExitKind) -> Result<(), Error> { fn post_exec(&mut self, _state: &mut S, _input: &S::Input, _exit_kind: &ExitKind) -> Result<(), Error> {
unsafe { self.end_tick = emu::icount_get_raw() }; unsafe { self.end_tick = libafl_qemu::sys::icount_get_raw() };
if let Some(td) = &self.dump_path { if let Some(td) = &self.dump_path {
// println!("clock post {}", self.end_tick); // println!("clock post {}", self.end_tick);
// println!("Number of Ticks: {} <- {} {}",self.end_tick - self.start_tick, self.end_tick, self.start_tick); // println!("Number of Ticks: {} <- {} {}",self.end_tick - self.start_tick, self.end_tick, self.start_tick);
@ -187,7 +189,7 @@ where
impl Named for QemuClockObserver { impl Named for QemuClockObserver {
#[inline] #[inline]
fn name(&self) -> &str { fn name(&self) -> &Cow<'static, str> {
&self.name &self.name
} }
} }
@ -195,7 +197,7 @@ impl Named for QemuClockObserver {
impl Default for QemuClockObserver { impl Default for QemuClockObserver {
fn default() -> Self { fn default() -> Self {
Self { Self {
name: String::from("clock"), name: Cow::from(String::from("clock")),
start_tick: 0, start_tick: 0,
end_tick: 0, end_tick: 0,
dump_path: None dump_path: None
@ -210,7 +212,7 @@ impl Default for QemuClockObserver {
#[derive(Serialize, Deserialize, Clone, Debug)] #[derive(Serialize, Deserialize, Clone, Debug)]
pub struct ClockTimeFeedback { pub struct ClockTimeFeedback {
exec_time: Option<Duration>, exec_time: Option<Duration>,
name: String, name: Cow<'static, str>,
} }
impl<S> Feedback<S> for ClockTimeFeedback impl<S> Feedback<S> for ClockTimeFeedback
@ -238,9 +240,10 @@ where
/// Append to the testcase the generated metadata in case of a new corpus item /// Append to the testcase the generated metadata in case of a new corpus item
#[inline] #[inline]
fn append_metadata<OT>( fn append_metadata<EM, OT>(
&mut self, &mut self,
_state: &mut S, _state: &mut S,
_manager: &mut EM,
observers: &OT, observers: &OT,
testcase: &mut Testcase<S::Input>, testcase: &mut Testcase<S::Input>,
) -> Result<(), Error> { ) -> Result<(), Error> {
@ -259,8 +262,8 @@ where
impl Named for ClockTimeFeedback { impl Named for ClockTimeFeedback {
#[inline] #[inline]
fn name(&self) -> &str { fn name(&self) -> &Cow<'static, str> {
self.name.as_str() &self.name
} }
} }
@ -270,7 +273,7 @@ impl ClockTimeFeedback {
pub fn new(name: &'static str) -> Self { pub fn new(name: &'static str) -> Self {
Self { Self {
exec_time: None, exec_time: None,
name: name.to_string(), name: Cow::from(name.to_string()),
} }
} }
@ -279,7 +282,7 @@ impl ClockTimeFeedback {
pub fn new_with_observer(observer: &QemuClockObserver) -> Self { pub fn new_with_observer(observer: &QemuClockObserver) -> Self {
Self { Self {
exec_time: None, exec_time: None,
name: observer.name().to_string(), name: observer.name().clone(),
} }
} }
} }
@ -287,7 +290,7 @@ impl ClockTimeFeedback {
/// A [`Feedback`] rewarding increasing the execution cycles on Qemu. /// A [`Feedback`] rewarding increasing the execution cycles on Qemu.
#[derive(Debug)] #[derive(Debug)]
pub struct QemuClockIncreaseFeedback { pub struct QemuClockIncreaseFeedback {
name: String, name: Cow<'static, str>,
} }
impl<S> Feedback<S> for QemuClockIncreaseFeedback impl<S> Feedback<S> for QemuClockIncreaseFeedback
@ -322,7 +325,7 @@ where
/// Append to the testcase the generated metadata in case of a new corpus item /// Append to the testcase the generated metadata in case of a new corpus item
#[inline] #[inline]
fn append_metadata<OT>(&mut self, _state: &mut S, observers: &OT, testcase: &mut Testcase<S::Input>) -> Result<(), Error> { fn append_metadata<EM, OT>(&mut self, _state: &mut S, _manager: &mut EM, observers: &OT, testcase: &mut Testcase<S::Input>) -> Result<(), Error> {
// testcase.metadata_mut().insert(QemuIcountMetadata{runtime: self.last_runtime}); // testcase.metadata_mut().insert(QemuIcountMetadata{runtime: self.last_runtime});
Ok(()) Ok(())
} }
@ -337,7 +340,7 @@ where
impl Named for QemuClockIncreaseFeedback { impl Named for QemuClockIncreaseFeedback {
#[inline] #[inline]
fn name(&self) -> &str { fn name(&self) -> &Cow<'static, str> {
&self.name &self.name
} }
} }
@ -346,7 +349,7 @@ impl QemuClockIncreaseFeedback {
/// Creates a new [`HitFeedback`] /// Creates a new [`HitFeedback`]
#[must_use] #[must_use]
pub fn new(name: &'static str) -> Self { pub fn new(name: &'static str) -> Self {
Self {name: String::from(name)} Self {name: Cow::from(String::from(name))}
} }
} }

View File

@ -4,13 +4,13 @@ use core::time::Duration;
use std::{env, path::PathBuf, process::{self, abort}, io::{Read, Write}, fs::{self, OpenOptions}, cmp::{min, max}, mem::transmute_copy, collections::btree_map::Range, ptr::addr_of_mut, ffi::OsStr}; use std::{env, path::PathBuf, process::{self, abort}, io::{Read, Write}, fs::{self, OpenOptions}, cmp::{min, max}, mem::transmute_copy, collections::btree_map::Range, ptr::addr_of_mut, ffi::OsStr};
use hashbrown::HashMap; use hashbrown::HashMap;
use libafl_bolts::{ use libafl_bolts::{
core_affinity::Cores, current_nanos, rands::StdRand, shmem::{ShMemProvider, StdShMemProvider}, tuples::tuple_list, AsMutSlice, AsSlice core_affinity::Cores, current_nanos, rands::StdRand, shmem::{ShMemProvider, StdShMemProvider}, tuples::tuple_list, AsSlice
}; };
use libafl::{ use libafl::{
corpus::{Corpus, InMemoryCorpus, OnDiskCorpus}, events::{launcher::Launcher, EventConfig}, executors::{ExitKind, TimeoutExecutor}, feedback_or, feedback_or_fast, feedbacks::{CrashFeedback, MaxMapFeedback, TimeoutFeedback}, fuzzer::{Fuzzer, StdFuzzer}, inputs::{BytesInput, HasTargetBytes}, monitors::MultiMonitor, observers::VariableMapObserver, prelude::{havoc_mutations, minimizer::TopRatedsMetadata, CorpusId, Generator, HasBytesVec, HitcountsMapObserver, RandBytesGenerator, SimpleEventManager, SimpleMonitor, SimpleRestartingEventManager, StdScheduledMutator}, schedulers::{IndexesLenTimeMinimizerScheduler, QueueScheduler}, stages::StdMutationalStage, state::{HasCorpus, HasMetadata, HasNamedMetadata, StdState}, Error, Evaluator common::{HasMetadata, HasNamedMetadata}, corpus::{Corpus, InMemoryCorpus, OnDiskCorpus}, events::{launcher::Launcher, EventConfig}, executors::ExitKind, feedback_or, feedback_or_fast, feedbacks::{CrashFeedback, MaxMapFeedback, TimeoutFeedback}, fuzzer::{Fuzzer, StdFuzzer}, inputs::{BytesInput, HasTargetBytes}, monitors::MultiMonitor, observers::{CanTrack, VariableMapObserver}, prelude::{havoc_mutations, minimizer::TopRatedsMetadata, CorpusId, Generator, HitcountsMapObserver, RandBytesGenerator, SimpleEventManager, SimpleMonitor, SimpleRestartingEventManager, StdScheduledMutator}, schedulers::{IndexesLenTimeMinimizerScheduler, QueueScheduler}, stages::StdMutationalStage, state::{HasCorpus, StdState}, Error, Evaluator
}; };
use libafl_qemu::{ use libafl_qemu::{
edges::{self, edges_map_mut_slice, QemuEdgeCoverageHelper, MAX_EDGES_NUM}, elf::EasyElf, emu::{libafl_qemu_remove_native_breakpoint, libafl_qemu_set_native_breakpoint, Emulator}, GuestAddr, GuestPhysAddr, QemuExecutor, QemuHooks, QemuInstrumentationFilter, Regs edges::{self, edges_map_mut_ptr, QemuEdgeCoverageHelper, MAX_EDGES_FOUND}, elf::EasyElf, emu::Emulator, GuestAddr, GuestPhysAddr, QemuExecutor, QemuFilterList, QemuHooks, Regs, StdInstrumentationFilter
}; };
use rand::{SeedableRng, StdRng, Rng}; use rand::{SeedableRng, StdRng, Rng};
use crate::{ use crate::{
@ -25,6 +25,8 @@ use petgraph::graph::NodeIndex;
use petgraph::prelude::DiGraph; use petgraph::prelude::DiGraph;
use crate::systemstate::stg::STGFeedbackState; use crate::systemstate::stg::STGFeedbackState;
use crate::clock::QEMU_ICOUNT_SHIFT; use crate::clock::QEMU_ICOUNT_SHIFT;
use libafl::inputs::HasMutatorBytes;
use libafl_qemu::Qemu;
// Constants ================================================================================ // Constants ================================================================================
@ -373,8 +375,8 @@ let app_fn_ranges = get_all_fn_symbol_ranges(&elf, app_range.clone());
let mut isr_ranges : HashMap<String,std::ops::Range<GuestAddr>> = systemstate::helpers::ISR_SYMBOLS.iter().filter_map(|x| (api_ranges.get(&x.to_string()).map(|y| (x.to_string(),y.clone())))).collect(); let mut isr_ranges : HashMap<String,std::ops::Range<GuestAddr>> = systemstate::helpers::ISR_SYMBOLS.iter().filter_map(|x| (api_ranges.get(&x.to_string()).map(|y| (x.to_string(),y.clone())))).collect();
systemstate::helpers::ISR_SYMBOLS.iter().for_each(|x| {let _ =(app_fn_ranges.get(&x.to_string()).map(|y| (x.to_string(),y.clone()))).map(|y| isr_ranges.insert(y.0,y.1));}); // add used defined isr systemstate::helpers::ISR_SYMBOLS.iter().for_each(|x| {let _ =(app_fn_ranges.get(&x.to_string()).map(|y| (x.to_string(),y.clone()))).map(|y| isr_ranges.insert(y.0,y.1));}); // add used defined isr
let denylist=isr_ranges.values().map(|x| x.clone()).collect(); let denylist : Vec<_> =isr_ranges.values().map(|x| x.clone()).collect();
let denylist = QemuInstrumentationFilter::DenyList(denylist); // do not count isr jumps, which are useless let denylist = QemuFilterList::DenyList(denylist); // do not count isr jumps, which are useless
#[cfg(feature = "observe_systemstate")] #[cfg(feature = "observe_systemstate")]
let mut isr_addreses : HashMap<GuestAddr, String> = systemstate::helpers::ISR_SYMBOLS.iter().filter_map(|x| (api_ranges.remove(&x.to_string()).map(|y| (y.start,x.to_string())))).collect(); let mut isr_addreses : HashMap<GuestAddr, String> = systemstate::helpers::ISR_SYMBOLS.iter().filter_map(|x| (api_ranges.remove(&x.to_string()).map(|y| (y.start,x.to_string())))).collect();
#[cfg(feature = "observe_systemstate")] #[cfg(feature = "observe_systemstate")]
@ -421,22 +423,22 @@ let mut run_client = |state: Option<_>, mut mgr, _core_id| {
// "-semihosting", // "-semihosting",
// "--semihosting-config", // "--semihosting-config",
// "enable=on,target=native", // "enable=on,target=native",
"-snapshot", // "-snapshot",
"-drive", // "-drive",
"if=none,format=qcow2,file=dummy.qcow2", // "if=none,format=qcow2,file=dummy.qcow2",
].into_iter().map(String::from).collect(); ].into_iter().map(String::from).collect();
let env: Vec<(String, String)> = env::vars().collect(); let env: Vec<(String, String)> = env::vars().collect();
let emu = Emulator::new(&args, &env).expect("Emulator creation failed"); let emu = Qemu::init(&args, &env).expect("Emulator creation failed");
if let Some(main_addr) = main_addr { // if let Some(main_addr) = main_addr {
unsafe { // unsafe {
libafl_qemu_set_native_breakpoint(main_addr); // emu.set_breakpoint(main_addr);
emu.run(); // emu.run();
libafl_qemu_remove_native_breakpoint(main_addr); // emu.remove_breakpoint(main_addr);
} // }
} // }
unsafe { libafl_qemu_set_native_breakpoint(breakpoint); }// BREAKPOINT unsafe { emu.set_breakpoint(breakpoint); }// BREAKPOINT
// The wrapped harness function, calling out to the LLVM-style harness // The wrapped harness function, calling out to the LLVM-style harness
let mut harness = |input: &BytesInput| { let mut harness = |input: &BytesInput| {
@ -475,7 +477,7 @@ let mut run_client = |state: Option<_>, mut mgr, _core_id| {
// If the execution stops at any point other then the designated breakpoint (e.g. a breakpoint on a panic method) we consider it a crash // If the execution stops at any point other then the designated breakpoint (e.g. a breakpoint on a panic method) we consider it a crash
let mut pcs = (0..emu.num_cpus()) let mut pcs = (0..emu.num_cpus())
.map(|i| emu.cpu_from_index(i)) .map(|i| emu.cpu_from_index(i))
.map(|cpu| -> Result<u32, String> { cpu.read_reg(Regs::Pc) }); .map(|cpu| -> Result<u32, _> { cpu.read_reg(Regs::Pc) });
match pcs match pcs
.find(|pc| (breakpoint..breakpoint + 5).contains(pc.as_ref().unwrap_or(&0))) .find(|pc| (breakpoint..breakpoint + 5).contains(pc.as_ref().unwrap_or(&0)))
{ {
@ -496,14 +498,14 @@ let mut run_client = |state: Option<_>, mut mgr, _core_id| {
addr_of_mut!(MAX_EDGES_NUM) addr_of_mut!(MAX_EDGES_NUM)
)}; )};
#[cfg(feature = "observer_hitcounts")] #[cfg(feature = "observer_hitcounts")]
let edges_observer = HitcountsMapObserver::new(edges_observer); let edges_observer = HitcountsMapObserver::new(edges_observer).track_indices();
#[cfg(feature = "observe_systemstate")] #[cfg(feature = "observe_systemstate")]
let stg_coverage_observer = unsafe { VariableMapObserver::from_mut_slice( let stg_coverage_observer = unsafe { VariableMapObserver::from_mut_slice(
"stg", "stg",
stg_map_mut_slice(), stg_map_mut_slice(),
addr_of_mut!(MAX_STG_NUM) addr_of_mut!(MAX_STG_NUM)
)}; )}.track_indices();
#[cfg(feature = "observe_systemstate")] #[cfg(feature = "observe_systemstate")]
let systemstate_observer = QemuSystemStateObserver::new(); let systemstate_observer = QemuSystemStateObserver::new();
@ -576,7 +578,7 @@ let mut run_client = |state: Option<_>, mut mgr, _core_id| {
#[cfg(feature = "sched_afl",)] #[cfg(feature = "sched_afl",)]
let scheduler = TimeMaximizerCorpusScheduler::new(QueueScheduler::new()); let scheduler = TimeMaximizerCorpusScheduler::new(QueueScheduler::new());
#[cfg(feature = "sched_stg")] #[cfg(feature = "sched_stg")]
let scheduler = LongestTraceScheduler::new(GraphMaximizerCorpusScheduler::new(QueueScheduler::new())); let scheduler = LongestTraceScheduler::new(GraphMaximizerCorpusScheduler::new(&stg_coverage_observer,QueueScheduler::new()));
#[cfg(feature = "sched_genetic")] #[cfg(feature = "sched_genetic")]
let scheduler = GenerationScheduler::new(); let scheduler = GenerationScheduler::new();
@ -587,7 +589,7 @@ let mut run_client = |state: Option<_>, mut mgr, _core_id| {
#[cfg(feature = "observe_systemstate")] #[cfg(feature = "observe_systemstate")]
let qhelpers = (QemuSystemStateHelper::new(api_addreses,api_ranges,isr_addreses,isr_ranges,curr_tcb_pointer,task_queue_addr,task_delay_addr,task_delay_overflow_addr,scheduler_lock,scheduler_running, critical_section,input_counter_ptr,app_range.clone()), qhelpers); let qhelpers = (QemuSystemStateHelper::new(api_addreses,api_ranges,isr_addreses,isr_ranges,curr_tcb_pointer,task_queue_addr,task_delay_addr,task_delay_overflow_addr,scheduler_lock,scheduler_running, critical_section,input_counter_ptr,app_range.clone()), qhelpers);
#[cfg(feature = "observe_edges")] #[cfg(feature = "observe_edges")]
let qhelpers = (QemuEdgeCoverageHelper::new(denylist), qhelpers); let qhelpers = (QemuEdgeCoverageHelper::new(denylist, QemuFilterList::None), qhelpers);
let qhelpers = (QemuStateRestoreHelper::new(), qhelpers); let qhelpers = (QemuStateRestoreHelper::new(), qhelpers);
let mut hooks = QemuHooks::new(emu.clone(),qhelpers); let mut hooks = QemuHooks::new(emu.clone(),qhelpers);
@ -600,18 +602,18 @@ let mut run_client = |state: Option<_>, mut mgr, _core_id| {
let observer_list = (clock_time_observer, observer_list); let observer_list = (clock_time_observer, observer_list);
// Create a QEMU in-process executor // Create a QEMU in-process executor
let executor = QemuExecutor::new( let mut executor = QemuExecutor::new(
&mut hooks, &mut hooks,
&mut harness, &mut harness,
observer_list, observer_list,
&mut fuzzer, &mut fuzzer,
&mut state, &mut state,
&mut mgr, &mut mgr,
timeout
) )
.expect("Failed to create QemuExecutor"); .expect("Failed to create QemuExecutor");
// Wrap the executor to keep track of the timeout executor.break_on_timeout();
let mut executor = TimeoutExecutor::new(executor, timeout);
let mutations = havoc_mutations(); let mutations = havoc_mutations();
// Setup an havoc mutator with a mutational stage // Setup an havoc mutator with a mutational stage
@ -641,7 +643,7 @@ let mut run_client = |state: Option<_>, mut mgr, _core_id| {
if let Some(se) = seed { if let Some(se) = seed {
unsafe { unsafe {
let mut rng = StdRng::seed_from_u64(se); let mut rng = StdRng::seed_from_u64(se);
for i in 0..1000 { for i in 0..10 {
let inp = BytesInput::new(vec![rng.gen::<u8>(); MAX_INPUT_SIZE]); let inp = BytesInput::new(vec![rng.gen::<u8>(); MAX_INPUT_SIZE]);
fuzzer.evaluate_input(&mut state, &mut executor, &mut mgr, inp).unwrap(); fuzzer.evaluate_input(&mut state, &mut executor, &mut mgr, inp).unwrap();
} }
@ -740,10 +742,10 @@ let mut run_client = |state: Option<_>, mut mgr, _core_id| {
// Initialize QEMU // Initialize QEMU
let args: Vec<String> = env::args().collect(); let args: Vec<String> = env::args().collect();
let env: Vec<(String, String)> = env::vars().collect(); let env: Vec<(String, String)> = env::vars().collect();
let emu = Emulator::new(&args, &env).expect("Emu creation failed"); let emu = Qemu::init(&args, &env).expect("Emu creation failed");
if let Some(main_addr) = main_addr { if let Some(main_addr) = main_addr {
unsafe { libafl_qemu_set_native_breakpoint(main_addr); }// BREAKPOINT unsafe { emu.set_breakpoint(main_addr); }// BREAKPOINT
} }
unsafe { unsafe {
emu.run(); emu.run();

View File

@ -6,14 +6,15 @@ use std::cmp::{max, min};
use hashbrown::HashMap; use hashbrown::HashMap;
use libafl_bolts::rands::{ use libafl_bolts::rands::{
StdRand, RandomSeed, StdRand, random_seed,
Rand Rand
}; };
use libafl::{ use libafl::{
corpus::{self, Corpus}, fuzzer::Evaluator, mark_feature_time, prelude::{new_hash_feedback, CorpusId, HasBytesVec, MutationResult, Mutator, UsesInput}, stages::Stage, start_timer, state::{HasCorpus, HasMetadata, HasNamedMetadata, HasRand, MaybeHasClientPerfMonitor, UsesState}, Error common::{HasMetadata, HasNamedMetadata}, corpus::{self, Corpus}, fuzzer::Evaluator, inputs::HasMutatorBytes, mark_feature_time, prelude::{new_hash_feedback, CorpusId, MutationResult, Mutator, UsesInput}, stages::Stage, start_timer, state::{HasCorpus, HasRand, MaybeHasClientPerfMonitor, UsesState}, Error
}; };
use libafl::prelude::State; use libafl::prelude::State;
use crate::{clock::{IcHist, QEMU_ISNS_PER_USEC}, fuzzer::{DO_NUM_INTERRUPT, FIRST_INT, MAX_NUM_INTERRUPT}, systemstate::{stg::{STGFeedbackState, STGNodeMetadata}, CaptureEvent, ExecInterval, FreeRTOSSystemStateMetadata, ReducedFreeRTOSSystemState}}; use crate::{clock::{IcHist, QEMU_ISNS_PER_USEC}, fuzzer::{DO_NUM_INTERRUPT, FIRST_INT, MAX_NUM_INTERRUPT}, systemstate::{stg::{STGFeedbackState, STGNodeMetadata}, CaptureEvent, ExecInterval, FreeRTOSSystemStateMetadata, ReducedFreeRTOSSystemState}};
use libafl::state::HasCurrentTestcase;
pub static mut MINIMUM_INTER_ARRIVAL_TIME : u32 = 1000 /*us*/ * QEMU_ISNS_PER_USEC; pub static mut MINIMUM_INTER_ARRIVAL_TIME : u32 = 1000 /*us*/ * QEMU_ISNS_PER_USEC;
// one isn per 2**4 ns // one isn per 2**4 ns
@ -77,32 +78,28 @@ where
EM: UsesState<State = Z::State>, EM: UsesState<State = Z::State>,
Z: Evaluator<E, EM>, Z: Evaluator<E, EM>,
Z::State: MaybeHasClientPerfMonitor + HasCorpus + HasRand + HasMetadata + HasNamedMetadata, Z::State: MaybeHasClientPerfMonitor + HasCorpus + HasRand + HasMetadata + HasNamedMetadata,
<Z::State as UsesInput>::Input: HasBytesVec <Z::State as UsesInput>::Input: HasMutatorBytes
{ {
fn perform( fn perform(
&mut self, &mut self,
fuzzer: &mut Z, fuzzer: &mut Z,
executor: &mut E, executor: &mut E,
state: &mut Self::State, state: &mut Self::State,
manager: &mut EM, manager: &mut EM
corpus_idx: CorpusId, // corpus_idx: CorpusId,
) -> Result<(), Error> { ) -> Result<(), Error> {
let mut _input = state let mut myrand = StdRand::new();
.corpus() myrand.set_seed(state.rand_mut().next());
.get(corpus_idx)? let mut _input = state.current_testcase()?.clone();
.borrow_mut().clone(); let mut newinput = _input.input().as_ref().unwrap().clone();
let mut newinput = _input.input_mut().as_mut().unwrap().clone();
let mut do_rerun = false; let mut do_rerun = false;
// if state.rand_mut().between(1, 100) <= 50 // only attempt the mutation half of the time // if state.rand_mut().between(1, 100) <= 50 // only attempt the mutation half of the time
{ {
// need our own random generator, because borrowing rules // need our own random generator, because borrowing rules
let mut myrand = StdRand::new();
let mut target_bytes : Vec<u8> = vec![]; let mut target_bytes : Vec<u8> = vec![];
{ {
let input = _input.input_mut().as_ref().unwrap(); let input = _input.input().as_ref().unwrap();
target_bytes = input.bytes().to_vec(); target_bytes = input.bytes().to_vec();
let tmp = &mut state.rand_mut();
myrand.set_seed(tmp.next());
} }
// produce a slice of absolute interrupt times // produce a slice of absolute interrupt times
@ -129,7 +126,7 @@ where
if interrupt_offsets[0] as u64 > maxtick { // place interrupt in reachable range if interrupt_offsets[0] as u64 > maxtick { // place interrupt in reachable range
do_rerun = true; do_rerun = true;
for _ in 0..num_interrupts { for _ in 0..num_interrupts {
prefix.push(u32::to_le_bytes(myrand.between(0, min(maxtick, u32::MAX as u64)).try_into().expect("ticks > u32"))); prefix.push(u32::to_le_bytes(myrand.between(0, min(maxtick as usize, u32::MAX as usize)).try_into().expect("ticks > u32")));
} }
} else { } else {
// let choice = myrand.between(1,100); // let choice = myrand.between(1,100);
@ -261,8 +258,8 @@ where
).collect(); ).collect();
if untouched.len() > 0 { if untouched.len() > 0 {
let tmp = interrupt_offsets[i]; let tmp = interrupt_offsets[i];
let choice = myrand.choose(untouched); let choice = myrand.choose(untouched).unwrap();
interrupt_offsets[i] = myrand.between(choice.0.start_tick, choice.0.end_tick) interrupt_offsets[i] = myrand.between(choice.0.start_tick as usize, choice.0.end_tick as usize)
.try_into().expect("tick > u32"); .try_into().expect("tick > u32");
do_rerun = true; do_rerun = true;
} }
@ -274,7 +271,7 @@ where
continue; continue;
} }
} }
let replacement = myrand.choose(alternatives); let replacement = myrand.choose(alternatives).unwrap();
if (old_hit.map_or(false, |x| x == replacement)) { if (old_hit.map_or(false, |x| x == replacement)) {
// use the old value // use the old value
// println!("chose old value, do nothing i: {} {}",i,interrupt_offsets[i]); // println!("chose old value, do nothing i: {} {}",i,interrupt_offsets[i]);
@ -285,8 +282,8 @@ where
old_handler.map_or(0, |x| x.0.end_tick - x.0.start_tick) old_handler.map_or(0, |x| x.0.end_tick - x.0.start_tick)
} else { 0 }; } else { 0 };
let tmp = interrupt_offsets[i]; let tmp = interrupt_offsets[i];
interrupt_offsets[i] = (myrand.between(replacement.0.start_tick, interrupt_offsets[i] = (myrand.between(replacement.0.start_tick as usize,
replacement.0.end_tick) + extra).try_into().expect("ticks > u32"); replacement.0.end_tick as usize) + extra as usize).try_into().expect("ticks > u32");
// println!("chose new alternative, i: {} {} -> {}",i,tmp, interrupt_offsets[i]); // println!("chose new alternative, i: {} {} -> {}",i,tmp, interrupt_offsets[i]);
do_rerun = true; do_rerun = true;
} }
@ -324,8 +321,8 @@ where
let mut n : Vec<u8> = vec![]; let mut n : Vec<u8> = vec![];
n = [prefix.concat(), suffix].concat(); n = [prefix.concat(), suffix].concat();
newinput.bytes_mut().clear(); newinput.drain(..);
newinput.bytes_mut().append(&mut n); newinput.extend(&n);
} }
// InterruptShifterMutator::mutate(&mut mymut, state, &mut input, 0)?; // InterruptShifterMutator::mutate(&mut mymut, state, &mut input, 0)?;
if do_rerun { if do_rerun {
@ -333,6 +330,14 @@ where
} }
Ok(()) Ok(())
} }
fn restart_progress_should_run(&mut self, state: &mut Self::State) -> Result<bool, Error> {
Ok(true)
}
fn clear_restart_progress(&mut self, state: &mut Self::State) -> Result<(), Error> {
Ok(())
}
} }
impl<E, EM, Z> UsesState for InterruptShiftStage<E, EM, Z> impl<E, EM, Z> UsesState for InterruptShiftStage<E, EM, Z>

View File

@ -1,11 +1,12 @@
use libafl::prelude::UsesInput; use libafl::prelude::UsesInput;
use libafl_qemu::CPUArchState; use libafl_qemu::sys::CPUArchState;
use libafl_qemu::Emulator; use libafl_qemu::Emulator;
use libafl_qemu::FastSnapshot; use libafl_qemu::FastSnapshotPtr;
use libafl_qemu::Qemu;
use libafl_qemu::QemuExecutor; use libafl_qemu::QemuExecutor;
use libafl_qemu::QemuHelper; use libafl_qemu::QemuHelper;
use libafl_qemu::QemuHelperTuple; use libafl_qemu::QemuHelperTuple;
use libafl::{executors::ExitKind, inputs::Input, observers::ObserversTuple, state::HasMetadata}; use libafl::{executors::ExitKind, inputs::Input, observers::ObserversTuple, common::HasMetadata};
use libafl_qemu::QemuHooks; use libafl_qemu::QemuHooks;
use libafl_qemu::{ use libafl_qemu::{
@ -17,7 +18,7 @@ pub struct QemuStateRestoreHelper {
has_snapshot: bool, has_snapshot: bool,
use_snapshot: bool, use_snapshot: bool,
saved_cpu_states: Vec<CPUArchState>, saved_cpu_states: Vec<CPUArchState>,
fastsnap: Option<FastSnapshot> fastsnap: Option<FastSnapshotPtr>
} }
impl QemuStateRestoreHelper { impl QemuStateRestoreHelper {
@ -56,17 +57,17 @@ where
{ {
} }
fn post_exec<OT>(&mut self, emulator: &Emulator, _input: &S::Input, _observers: &mut OT, _exit_kind: &mut ExitKind) { fn post_exec<OT>(&mut self, emulator: libafl_qemu::Qemu, _input: &S::Input, _observers: &mut OT, _exit_kind: &mut ExitKind) {
// unsafe { println!("snapshot post {}",emu::icount_get_raw()) }; // unsafe { println!("snapshot post {}",emu::icount_get_raw()) };
} }
fn pre_exec(&mut self, emulator: &Emulator, _input: &S::Input) { fn pre_exec(&mut self, emulator: libafl_qemu::Qemu, _input: &S::Input) {
// only restore in pre-exec, to preserve the post-execution state for inspection // only restore in pre-exec, to preserve the post-execution state for inspection
#[cfg(feature = "snapshot_restore")] #[cfg(feature = "snapshot_restore")]
{ {
#[cfg(feature = "snapshot_fast")] #[cfg(feature = "snapshot_fast")]
match self.fastsnap { match self.fastsnap {
Some(s) => emulator.restore_fast_snapshot(s), Some(s) => unsafe { emulator.restore_fast_snapshot(s) },
None => {self.fastsnap = Some(emulator.create_fast_snapshot(true));}, None => {self.fastsnap = Some(emulator.create_fast_snapshot(true));},
} }
#[cfg(not(feature = "snapshot_fast"))] #[cfg(not(feature = "snapshot_fast"))]

View File

@ -2,7 +2,7 @@ use libafl::SerdeAny;
use libafl_bolts::ownedref::OwnedSlice; use libafl_bolts::ownedref::OwnedSlice;
use libafl::inputs::BytesInput; use libafl::inputs::BytesInput;
use libafl::prelude::UsesInput; use libafl::prelude::UsesInput;
use libafl::state::HasNamedMetadata; use libafl::common::HasNamedMetadata;
use std::path::PathBuf; use std::path::PathBuf;
use crate::clock::QemuClockObserver; use crate::clock::QemuClockObserver;
use libafl::corpus::Testcase; use libafl::corpus::Testcase;
@ -17,7 +17,7 @@ use libafl::feedbacks::Feedback;
use libafl_bolts::Named; use libafl_bolts::Named;
use libafl::Error; use libafl::Error;
use hashbrown::HashMap; use hashbrown::HashMap;
use libafl::{executors::ExitKind, inputs::Input, observers::ObserversTuple, state::HasMetadata}; use libafl::{executors::ExitKind, inputs::Input, observers::ObserversTuple, common::HasMetadata};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use super::ExecInterval; use super::ExecInterval;
@ -28,28 +28,38 @@ use petgraph::prelude::DiGraph;
use petgraph::graph::NodeIndex; use petgraph::graph::NodeIndex;
use petgraph::Direction; use petgraph::Direction;
use std::cmp::Ordering; use std::cmp::Ordering;
use std::borrow::Cow;
//============================= Feedback //============================= Feedback
/// Shared Metadata for a systemstateFeedback /// Shared Metadata for a systemstateFeedback
#[derive(Debug, Serialize, Deserialize, SerdeAny, Clone, Default)] #[derive(Debug, Serialize, Deserialize, SerdeAny, Clone)]
pub struct SystemStateFeedbackState pub struct SystemStateFeedbackState
{ {
name: Cow<'static, str>,
known_traces: HashMap<u64,(u64,u64,usize)>, // encounters,ticks,length known_traces: HashMap<u64,(u64,u64,usize)>, // encounters,ticks,length
longest: Vec<ReducedFreeRTOSSystemState>, longest: Vec<ReducedFreeRTOSSystemState>,
} }
impl Named for SystemStateFeedbackState impl Named for SystemStateFeedbackState
{ {
#[inline] #[inline]
fn name(&self) -> &str { fn name(&self) -> &Cow<'static, str> {
"systemstate" &self.name
}
}
impl Default for SystemStateFeedbackState
{
fn default() -> Self {
Self {name: Cow::from("systemstate".to_string()), known_traces: HashMap::new(), longest: Vec::new() }
} }
} }
/// A Feedback reporting novel System-State Transitions. Depends on [`QemuSystemStateObserver`] /// A Feedback reporting novel System-State Transitions. Depends on [`QemuSystemStateObserver`]
#[derive(Serialize, Deserialize, Clone, Debug, Default)] #[derive(Serialize, Deserialize, Clone, Debug)]
pub struct NovelSystemStateFeedback pub struct NovelSystemStateFeedback
{ {
name: Cow<'static, str>,
last_trace: Option<Vec<ReducedFreeRTOSSystemState>>, last_trace: Option<Vec<ReducedFreeRTOSSystemState>>,
// known_traces: HashMap<u64,(u64,usize)>, // known_traces: HashMap<u64,(u64,usize)>,
} }
@ -80,7 +90,7 @@ where
Some(s) => s, Some(s) => s,
None => { None => {
let n=SystemStateFeedbackState::default(); let n=SystemStateFeedbackState::default();
state.named_metadata_map_mut().insert(n, "systemstate"); state.named_metadata_map_mut().insert("systemstate",n);
state.named_metadata_map_mut().get_mut::<SystemStateFeedbackState>("systemstate").unwrap() state.named_metadata_map_mut().get_mut::<SystemStateFeedbackState>("systemstate").unwrap()
} }
}; };
@ -117,7 +127,7 @@ where
/// Append to the testcase the generated metadata in case of a new corpus item /// Append to the testcase the generated metadata in case of a new corpus item
#[inline] #[inline]
fn append_metadata<OT>(&mut self, _state: &mut S, observers: &OT, testcase: &mut Testcase<S::Input>) -> Result<(), Error> { fn append_metadata<EM, OT>(&mut self, _state: &mut S, _manager: &mut EM, observers: &OT, testcase: &mut Testcase<S::Input>) -> Result<(), Error> {
let a = self.last_trace.take(); let a = self.last_trace.take();
match a { match a {
Some(s) => testcase.metadata_map_mut().insert(FreeRTOSSystemStateMetadata::new(s)), Some(s) => testcase.metadata_map_mut().insert(FreeRTOSSystemStateMetadata::new(s)),
@ -137,8 +147,15 @@ where
impl Named for NovelSystemStateFeedback impl Named for NovelSystemStateFeedback
{ {
#[inline] #[inline]
fn name(&self) -> &str { fn name(&self) -> &Cow<'static, str> {
"systemstate" &self.name
}
}
impl Default for NovelSystemStateFeedback
{
fn default() -> Self {
Self {name: Cow::from("NovelSystemStateFeedback".to_string()), last_trace: None }
} }
} }
@ -147,6 +164,7 @@ impl Named for NovelSystemStateFeedback
#[derive(Debug)] #[derive(Debug)]
pub struct DumpSystraceFeedback pub struct DumpSystraceFeedback
{ {
name: Cow<'static, str>,
dumpfile: Option<PathBuf>, dumpfile: Option<PathBuf>,
dump_metadata: bool, dump_metadata: bool,
last_states: Option<HashMap<u64, ReducedFreeRTOSSystemState>>, last_states: Option<HashMap<u64, ReducedFreeRTOSSystemState>>,
@ -185,7 +203,7 @@ where
} }
/// Append to the testcase the generated metadata in case of a new corpus item /// Append to the testcase the generated metadata in case of a new corpus item
#[inline] #[inline]
fn append_metadata<OT>(&mut self, _state: &mut S, observers: &OT, testcase: &mut Testcase<S::Input>) -> Result<(), Error> { fn append_metadata<EM, OT>(&mut self, _state: &mut S, _manager: &mut EM, observers: &OT, testcase: &mut Testcase<S::Input>) -> Result<(), Error> {
if !self.dump_metadata {return Ok(());} if !self.dump_metadata {return Ok(());}
// let a = self.last_trace.take(); // let a = self.last_trace.take();
// match a { // match a {
@ -206,8 +224,8 @@ where
impl Named for DumpSystraceFeedback impl Named for DumpSystraceFeedback
{ {
#[inline] #[inline]
fn name(&self) -> &str { fn name(&self) -> &Cow<'static, str> {
"Dumpsystemstate" &self.name
} }
} }
@ -216,13 +234,13 @@ impl DumpSystraceFeedback
/// Creates a new [`DumpSystraceFeedback`] /// Creates a new [`DumpSystraceFeedback`]
#[must_use] #[must_use]
pub fn new() -> Self { pub fn new() -> Self {
Self {dumpfile: None, dump_metadata: false, last_trace: None, last_states: None } Self {name: Cow::from("Dumpsystemstate".to_string()), dumpfile: None, dump_metadata: false, last_trace: None, last_states: None }
} }
pub fn with_dump(dumpfile: Option<PathBuf>) -> Self { pub fn with_dump(dumpfile: Option<PathBuf>) -> Self {
Self {dumpfile: dumpfile, dump_metadata: false, last_trace: None, last_states: None} Self {name: Cow::from("Dumpsystemstate".to_string()), dumpfile: dumpfile, dump_metadata: false, last_trace: None, last_states: None}
} }
pub fn metadata_only() -> Self { pub fn metadata_only() -> Self {
Self {dumpfile: None, dump_metadata: true, last_trace: None, last_states: None} Self {name: Cow::from("Dumpsystemstate".to_string()), dumpfile: None, dump_metadata: true, last_trace: None, last_states: None}
} }
} }
@ -230,6 +248,7 @@ impl DumpSystraceFeedback
#[derive(Debug, Default)] #[derive(Debug, Default)]
pub struct SystraceErrorFeedback pub struct SystraceErrorFeedback
{ {
name: Cow<'static, str>,
dump_case: bool dump_case: bool
} }
@ -255,7 +274,7 @@ where
} }
/// Append to the testcase the generated metadata in case of a new corpus item /// Append to the testcase the generated metadata in case of a new corpus item
#[inline] #[inline]
fn append_metadata<OT>(&mut self, _state: &mut S, _observers: &OT, _testcase: &mut Testcase<S::Input>) -> Result<(), Error> { fn append_metadata<EM, OT>(&mut self, _state: &mut S, _manager: &mut EM, _observers: &OT, _testcase: &mut Testcase<S::Input>) -> Result<(), Error> {
Ok(()) Ok(())
} }
@ -269,8 +288,8 @@ where
impl Named for SystraceErrorFeedback impl Named for SystraceErrorFeedback
{ {
#[inline] #[inline]
fn name(&self) -> &str { fn name(&self) -> &Cow<'static, str> {
"SystraceErrorFeedback" &self.name
} }
} }
@ -278,6 +297,6 @@ impl SystraceErrorFeedback
{ {
#[must_use] #[must_use]
pub fn new(dump_case: bool) -> Self { pub fn new(dump_case: bool) -> Self {
Self {dump_case} Self {name: Cow::from(String::from("SystraceErrorFeedback")), dump_case}
} }
} }

View File

@ -1,7 +1,7 @@
#![allow(non_camel_case_types,non_snake_case,non_upper_case_globals,deref_nullptr)] #![allow(non_camel_case_types,non_snake_case,non_upper_case_globals,deref_nullptr)]
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
// Manual Types // Manual Types
use libafl_qemu::Emulator; use libafl_qemu::{Emulator, Qemu};
/*========== Start of generated Code =============*/ /*========== Start of generated Code =============*/
pub type char_ptr = ::std::os::raw::c_uint; pub type char_ptr = ::std::os::raw::c_uint;
@ -88,7 +88,7 @@ pub type TCB_t = tskTCB;
/*========== End of generated Code =============*/ /*========== End of generated Code =============*/
pub trait emu_lookup { pub trait emu_lookup {
fn lookup(emu: &Emulator, addr: ::std::os::raw::c_uint) -> Self; fn lookup(emu: &Qemu, addr: ::std::os::raw::c_uint) -> Self;
} }
@ -104,7 +104,7 @@ pub enum rtos_struct {
macro_rules! impl_emu_lookup { macro_rules! impl_emu_lookup {
($struct_name:ident) => { ($struct_name:ident) => {
impl $crate::systemstate::freertos::emu_lookup for $struct_name { impl $crate::systemstate::freertos::emu_lookup for $struct_name {
fn lookup(emu: &Emulator, addr: ::std::os::raw::c_uint) -> $struct_name { fn lookup(emu: &Qemu, addr: ::std::os::raw::c_uint) -> $struct_name {
let mut tmp : [u8; std::mem::size_of::<$struct_name>()] = [0u8; std::mem::size_of::<$struct_name>()]; let mut tmp : [u8; std::mem::size_of::<$struct_name>()] = [0u8; std::mem::size_of::<$struct_name>()];
unsafe { unsafe {
emu.read_mem(addr.into(), &mut tmp); emu.read_mem(addr.into(), &mut tmp);

View File

@ -1,14 +1,14 @@
use libafl::SerdeAny; use libafl::SerdeAny;
/// Feedbacks organizing SystemStates as a graph /// Feedbacks organizing SystemStates as a graph
use libafl::inputs::HasBytesVec; // use libafl::inputs::HasBytesVec;
use libafl_bolts::rands::RandomSeed; use libafl_bolts::rands::random_seed;
use libafl_bolts::rands::StdRand; use libafl_bolts::rands::StdRand;
use libafl::mutators::Mutator; use libafl::mutators::Mutator;
use libafl::mutators::MutationResult; use libafl::mutators::MutationResult;
use libafl::prelude::HasTargetBytes; use libafl::prelude::HasTargetBytes;
use libafl::prelude::UsesInput; use libafl::prelude::UsesInput;
use libafl::state::HasNamedMetadata; use libafl::common::HasNamedMetadata;
use libafl::state::UsesState; use libafl::state::UsesState;
use libafl::prelude::State; use libafl::prelude::State;
use core::marker::PhantomData; use core::marker::PhantomData;
@ -35,7 +35,7 @@ use libafl::feedbacks::Feedback;
use libafl_bolts::Named; use libafl_bolts::Named;
use libafl::Error; use libafl::Error;
use hashbrown::HashMap; use hashbrown::HashMap;
use libafl::{executors::ExitKind, inputs::Input, observers::ObserversTuple, state::HasMetadata}; use libafl::{executors::ExitKind, inputs::Input, observers::ObserversTuple, common::HasMetadata};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use super::ExecInterval; use super::ExecInterval;
@ -46,6 +46,7 @@ use petgraph::prelude::DiGraph;
use petgraph::graph::NodeIndex; use petgraph::graph::NodeIndex;
use petgraph::Direction; use petgraph::Direction;
use std::cmp::Ordering; use std::cmp::Ordering;
use std::borrow::Cow;
use libafl_bolts::rands::Rand; use libafl_bolts::rands::Rand;
@ -148,14 +149,14 @@ impl SysGraphMetadata {
Self {indices: inner.iter().map(|x| x.index()).collect(), inner: inner, tcref: 0} Self {indices: inner.iter().map(|x| x.index()).collect(), inner: inner, tcref: 0}
} }
} }
impl AsSlice for SysGraphMetadata { // impl AsSlice for SysGraphMetadata {
/// Convert the slice of system-states to a slice of hashes over enumerated states // /// Convert the slice of system-states to a slice of hashes over enumerated states
fn as_slice(&self) -> &[usize] { // fn as_slice(&self) -> &[usize] {
self.indices.as_slice() // self.indices.as_slice()
} // }
type Entry = usize; // type Entry = usize;
} // }
impl HasRefCnt for SysGraphMetadata { impl HasRefCnt for SysGraphMetadata {
fn refcnt(&self) -> isize { fn refcnt(&self) -> isize {
@ -169,8 +170,8 @@ impl HasRefCnt for SysGraphMetadata {
libafl_bolts::impl_serdeany!(SysGraphMetadata); libafl_bolts::impl_serdeany!(SysGraphMetadata);
pub type GraphMaximizerCorpusScheduler<CS> = pub type GraphMaximizerCorpusScheduler<CS, O> =
MinimizerScheduler<CS, MaxTimeFavFactor<<CS as UsesState>::State>,SysGraphMetadata>; MinimizerScheduler<CS, MaxTimeFavFactor<<CS as UsesState>::State>,SysGraphMetadata,O>;
//============================= Graph Feedback //============================= Graph Feedback
@ -181,7 +182,7 @@ pub struct SysGraphFeedbackState
pub graph: DiGraph<SysGraphNode, ()>, pub graph: DiGraph<SysGraphNode, ()>,
entrypoint: NodeIndex, entrypoint: NodeIndex,
exit: NodeIndex, exit: NodeIndex,
name: String, name: Cow<'static, str>
} }
impl SysGraphFeedbackState impl SysGraphFeedbackState
{ {
@ -193,7 +194,7 @@ impl SysGraphFeedbackState
exit.base.current_task.task_name="End".to_string(); exit.base.current_task.task_name="End".to_string();
let entry = graph.add_node(entry); let entry = graph.add_node(entry);
let exit = graph.add_node(exit); let exit = graph.add_node(exit);
Self {graph: graph, entrypoint: entry, exit: exit, name: String::from("SysMap")} Self {graph: graph, entrypoint: entry, exit: exit, name: Cow::from(String::from("SysMap"))}
} }
fn insert(&mut self, list: Vec<ReducedFreeRTOSSystemState>, input: &Vec<u8>) { fn insert(&mut self, list: Vec<ReducedFreeRTOSSystemState>, input: &Vec<u8>) {
let mut current_index = self.entrypoint; let mut current_index = self.entrypoint;
@ -251,7 +252,7 @@ impl SysGraphFeedbackState
impl Named for SysGraphFeedbackState impl Named for SysGraphFeedbackState
{ {
#[inline] #[inline]
fn name(&self) -> &str { fn name(&self) -> &Cow<'static, str> {
&self.name &self.name
} }
} }
@ -278,12 +279,12 @@ impl SysGraphFeedbackState
#[derive(Serialize, Deserialize, Clone, Debug, Default)] #[derive(Serialize, Deserialize, Clone, Debug, Default)]
pub struct SysMapFeedback pub struct SysMapFeedback
{ {
name: String, name: Cow<'static, str>,
last_trace: Option<Vec<NodeIndex>>, last_trace: Option<Vec<NodeIndex>>,
} }
impl SysMapFeedback { impl SysMapFeedback {
pub fn new() -> Self { pub fn new() -> Self {
Self {name: String::from("SysMapFeedback"), last_trace: None } Self {name: Cow::from(String::from("SysMapFeedback")), last_trace: None }
} }
} }
@ -313,7 +314,7 @@ where
Some(s) => s, Some(s) => s,
None => { None => {
let n=SysGraphFeedbackState::default(); let n=SysGraphFeedbackState::default();
state.named_metadata_map_mut().insert(n, "SysMap"); state.named_metadata_map_mut().insert("SysMap",n);
state.named_metadata_map_mut().get_mut::<SysGraphFeedbackState>("SysMap").unwrap() state.named_metadata_map_mut().get_mut::<SysGraphFeedbackState>("SysMap").unwrap()
} }
}; };
@ -324,7 +325,7 @@ where
/// Append to the testcase the generated metadata in case of a new corpus item /// Append to the testcase the generated metadata in case of a new corpus item
#[inline] #[inline]
fn append_metadata<OT>(&mut self, _state: &mut S, _observers: &OT, testcase: &mut Testcase<S::Input>) -> Result<(), Error> { fn append_metadata<EM, OT>(&mut self, _state: &mut S, _manager: &mut EM, _observers: &OT, testcase: &mut Testcase<S::Input>) -> Result<(), Error> {
let a = self.last_trace.take(); let a = self.last_trace.take();
match a { match a {
Some(s) => testcase.metadata_map_mut().insert(SysGraphMetadata::new(s)), Some(s) => testcase.metadata_map_mut().insert(SysGraphMetadata::new(s)),
@ -343,7 +344,7 @@ where
impl Named for SysMapFeedback impl Named for SysMapFeedback
{ {
#[inline] #[inline]
fn name(&self) -> &str { fn name(&self) -> &Cow<'static, str> {
&self.name &self.name
} }
} }

View File

@ -9,6 +9,7 @@ use libafl_qemu::Emulator;
use libafl_qemu::GuestAddr; use libafl_qemu::GuestAddr;
use libafl_qemu::GuestPhysAddr; use libafl_qemu::GuestPhysAddr;
use libafl_qemu::GuestReg; use libafl_qemu::GuestReg;
use libafl_qemu::Qemu;
use libafl_qemu::QemuHooks; use libafl_qemu::QemuHooks;
use libafl_qemu::edges::QemuEdgesMapMetadata; use libafl_qemu::edges::QemuEdgesMapMetadata;
use libafl_qemu::emu; use libafl_qemu::emu;
@ -26,7 +27,7 @@ use super::freertos;
use super::CaptureEvent; use super::CaptureEvent;
use libafl_qemu::{ use libafl_qemu::{
helper::{QemuHelper, QemuHelperTuple}, helpers::{QemuHelper, QemuHelperTuple},
// edges::SAVED_JUMP, // edges::SAVED_JUMP,
}; };
@ -120,14 +121,14 @@ where
} }
// TODO: refactor duplicate code // TODO: refactor duplicate code
fn pre_exec(&mut self, _emulator: &Emulator, _input: &S::Input) { fn pre_exec(&mut self, _emulator: libafl_qemu::Qemu, _input: &S::Input) {
unsafe { unsafe {
CURRENT_SYSTEMSTATE_VEC.clear(); CURRENT_SYSTEMSTATE_VEC.clear();
} }
} }
fn post_exec<OT>(&mut self, emulator: &Emulator, _input: &S::Input, _observers: &mut OT, _exit_kind: &mut ExitKind) { fn post_exec<OT>(&mut self, emulator: libafl_qemu::Qemu, _input: &S::Input, _observers: &mut OT, _exit_kind: &mut ExitKind) {
trigger_collection(emulator,(0, 0), CaptureEvent::End, self); trigger_collection(&emulator,(0, 0), CaptureEvent::End, self);
unsafe { unsafe {
let c = emulator.cpu_from_index(0); let c = emulator.cpu_from_index(0);
let pc = c.read_reg::<i32, u32>(15).unwrap(); let pc = c.read_reg::<i32, u32>(15).unwrap();
@ -148,7 +149,7 @@ where
} }
} }
fn read_freertos_list(systemstate : &mut RawFreeRTOSSystemState, emulator: &Emulator, target: GuestAddr) -> freertos::List_t { fn read_freertos_list(systemstate : &mut RawFreeRTOSSystemState, emulator: &libafl_qemu::Qemu, target: GuestAddr) -> freertos::List_t {
let read : freertos::List_t = freertos::emu_lookup::lookup(emulator, target); let read : freertos::List_t = freertos::emu_lookup::lookup(emulator, target);
let listbytes : GuestAddr = GuestAddr::try_from(std::mem::size_of::<freertos::List_t>()).unwrap(); let listbytes : GuestAddr = GuestAddr::try_from(std::mem::size_of::<freertos::List_t>()).unwrap();
@ -187,7 +188,7 @@ fn read_freertos_list(systemstate : &mut RawFreeRTOSSystemState, emulator: &Emul
} }
#[inline] #[inline]
fn trigger_collection(emulator: &Emulator, edge: (GuestAddr, GuestAddr), event: CaptureEvent, h: &QemuSystemStateHelper) { fn trigger_collection(emulator: &libafl_qemu::Qemu, edge: (GuestAddr, GuestAddr), event: CaptureEvent, h: &QemuSystemStateHelper) {
let listbytes : GuestAddr = GuestAddr::try_from(std::mem::size_of::<freertos::List_t>()).unwrap(); let listbytes : GuestAddr = GuestAddr::try_from(std::mem::size_of::<freertos::List_t>()).unwrap();
let mut systemstate = RawFreeRTOSSystemState::default(); let mut systemstate = RawFreeRTOSSystemState::default();
@ -272,7 +273,7 @@ where
S: UsesInput, S: UsesInput,
QT: QemuHelperTuple<S>, QT: QemuHelperTuple<S>,
{ {
let emulator = hooks.emulator(); let emulator = hooks.qemu();
let h = hooks.helpers().match_first_type::<QemuSystemStateHelper>().expect("QemuSystemHelper not found in helper tupel"); let h = hooks.helpers().match_first_type::<QemuSystemStateHelper>().expect("QemuSystemHelper not found in helper tupel");
let src = read_rec_return_stackframe(emulator, 0xfffffffc); let src = read_rec_return_stackframe(emulator, 0xfffffffc);
trigger_collection(emulator, (src, pc), CaptureEvent::ISRStart, h); trigger_collection(emulator, (src, pc), CaptureEvent::ISRStart, h);
@ -324,7 +325,7 @@ where
QT: QemuHelperTuple<S>, QT: QemuHelperTuple<S>,
{ {
let h = hooks.helpers().match_first_type::<QemuSystemStateHelper>().expect("QemuSystemHelper not found in helper tupel"); let h = hooks.helpers().match_first_type::<QemuSystemStateHelper>().expect("QemuSystemHelper not found in helper tupel");
let emulator = hooks.emulator(); let emulator = hooks.qemu();
if id == 1 { // API call if id == 1 { // API call
trigger_collection(emulator, (src, dest), CaptureEvent::APIStart, h); trigger_collection(emulator, (src, dest), CaptureEvent::APIStart, h);
// println!("Exec API Call {:#x} {:#x} {}", src, dest, get_icount(emulator)); // println!("Exec API Call {:#x} {:#x} {}", src, dest, get_icount(emulator));
@ -353,19 +354,19 @@ where
//============================= Utility functions //============================= Utility functions
fn get_icount(emulator : &Emulator) -> u64 { fn get_icount(emulator : &libafl_qemu::Qemu) -> u64 {
unsafe { unsafe {
// TODO: investigate why can_do_io is not set sometimes, as this is just a workaround // TODO: investigate why can_do_io is not set sometimes, as this is just a workaround
let c = emulator.cpu_from_index(0); let c = emulator.cpu_from_index(0);
let can_do_io = (*c.raw_ptr()).neg.can_do_io; let can_do_io = (*c.raw_ptr()).neg.can_do_io;
(*c.raw_ptr()).neg.can_do_io = true; (*c.raw_ptr()).neg.can_do_io = true;
let r = emu::icount_get_raw(); let r = libafl_qemu::sys::icount_get_raw();
(*c.raw_ptr()).neg.can_do_io = can_do_io; (*c.raw_ptr()).neg.can_do_io = can_do_io;
r r
} }
} }
fn read_rec_return_stackframe(emu : &Emulator, lr : GuestAddr) -> GuestAddr { fn read_rec_return_stackframe(emu : &libafl_qemu::Qemu, lr : GuestAddr) -> GuestAddr {
let lr_ = lr & u32::MAX-1; let lr_ = lr & u32::MAX-1;
if lr_ == 0xfffffffc || lr_ == 0xFFFFFFF8 || lr_ == 0xFFFFFFF0 { if lr_ == 0xfffffffc || lr_ == 0xFFFFFFF8 || lr_ == 0xFFFFFFF0 {
unsafe { unsafe {

View File

@ -242,14 +242,14 @@ where
s.finish() s.finish()
} }
impl AsSlice for FreeRTOSSystemStateMetadata { // impl AsSlice for FreeRTOSSystemStateMetadata {
/// Convert the slice of system-states to a slice of hashes over enumerated states // /// Convert the slice of system-states to a slice of hashes over enumerated states
fn as_slice(&self) -> &[usize] { // fn as_slice(&self) -> &[usize] {
self.indices.as_slice() // self.indices.as_slice()
} // }
type Entry = usize; // type Entry = usize;
} // }
impl HasRefCnt for FreeRTOSSystemStateMetadata { impl HasRefCnt for FreeRTOSSystemStateMetadata {
fn refcnt(&self) -> isize { fn refcnt(&self) -> isize {

View File

@ -12,6 +12,7 @@ use crate::systemstate::CaptureEvent;
use std::rc::Rc; use std::rc::Rc;
use std::cell::RefCell; use std::cell::RefCell;
use std::collections::VecDeque; use std::collections::VecDeque;
use std::borrow::Cow;
use super::{ AtomicBasicBlock, ExecInterval}; use super::{ AtomicBasicBlock, ExecInterval};
use super::{ use super::{
@ -26,7 +27,7 @@ use super::{
/// The Qemusystemstate Observer retrieves the systemstate /// The Qemusystemstate Observer retrieves the systemstate
/// that will get updated by the target. /// that will get updated by the target.
#[derive(Serialize, Deserialize, Debug, Default)] #[derive(Serialize, Deserialize, Debug)]
#[allow(clippy::unsafe_derive_deserialize)] #[allow(clippy::unsafe_derive_deserialize)]
pub struct QemuSystemStateObserver pub struct QemuSystemStateObserver
{ {
@ -35,7 +36,7 @@ pub struct QemuSystemStateObserver
pub last_trace: Vec<ExecInterval>, pub last_trace: Vec<ExecInterval>,
pub last_input: Vec<u8>, pub last_input: Vec<u8>,
pub success: bool, pub success: bool,
name: String, name: Cow<'static, str>,
} }
impl<S> Observer<S> for QemuSystemStateObserver impl<S> Observer<S> for QemuSystemStateObserver
@ -74,9 +75,8 @@ where
impl Named for QemuSystemStateObserver impl Named for QemuSystemStateObserver
{ {
#[inline] fn name(&self) -> &Cow<'static, str> {
fn name(&self) -> &str { &self.name
self.name.as_str()
} }
} }
@ -90,9 +90,13 @@ impl HasLen for QemuSystemStateObserver
impl QemuSystemStateObserver { impl QemuSystemStateObserver {
pub fn new() -> Self { pub fn new() -> Self {
Self{last_run: vec![], last_trace: vec![], last_input: vec![], name: "systemstate".to_string(), last_states: HashMap::new(), success: false } Self{last_run: vec![], last_trace: vec![], last_input: vec![], name: Cow::from("systemstate".to_string()), last_states: HashMap::new(), success: false }
}
}
impl Default for QemuSystemStateObserver {
fn default() -> Self {
Self::new()
} }
} }
//============================= Parsing helpers //============================= Parsing helpers

View File

@ -11,7 +11,8 @@ use libafl::{
corpus::{Corpus, Testcase}, corpus::{Corpus, Testcase},
inputs::UsesInput, inputs::UsesInput,
schedulers::{Scheduler, TestcaseScore, minimizer::DEFAULT_SKIP_NON_FAVORED_PROB }, schedulers::{Scheduler, TestcaseScore, minimizer::DEFAULT_SKIP_NON_FAVORED_PROB },
state::{HasCorpus, HasMetadata, HasRand, UsesState, State}, state::{HasCorpus, HasRand, UsesState, State},
common::HasMetadata,
Error, SerdeAny, prelude::CorpusId, Error, SerdeAny, prelude::CorpusId,
}; };
@ -39,7 +40,7 @@ impl LongestTracesMetadata {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct LongestTraceScheduler<CS> { pub struct LongestTraceScheduler<CS> {
base: CS, base: CS,
skip_non_favored_prob: u64, skip_non_favored_prob: usize,
} }
impl<CS> UsesState for LongestTraceScheduler<CS> impl<CS> UsesState for LongestTraceScheduler<CS>
@ -102,7 +103,7 @@ where
.metadata_map() .metadata_map()
.get::<STGNodeMetadata>().map_or(0, |x| x.nodes.len()); .get::<STGNodeMetadata>().map_or(0, |x| x.nodes.len());
let m = self.get_update_trace_length(state,l); let m = self.get_update_trace_length(state,l);
state.rand_mut().below(m) > l as u64 state.rand_mut().below(m as usize) > l
} && state.rand_mut().below(100) < self.skip_non_favored_prob } && state.rand_mut().below(100) < self.skip_non_favored_prob
{ {
idx = self.base.next(state)?; idx = self.base.next(state)?;
@ -130,7 +131,7 @@ where
pub fn new(base: CS) -> Self { pub fn new(base: CS) -> Self {
Self { Self {
base, base,
skip_non_favored_prob: DEFAULT_SKIP_NON_FAVORED_PROB, skip_non_favored_prob: (DEFAULT_SKIP_NON_FAVORED_PROB * 100.0) as usize,
} }
} }
} }

View File

@ -2,17 +2,18 @@
use hashbrown::HashSet; use hashbrown::HashSet;
use libafl::SerdeAny; use libafl::SerdeAny;
/// Feedbacks organizing SystemStates as a graph /// Feedbacks organizing SystemStates as a graph
use libafl::inputs::HasBytesVec; // use libafl::inputs::HasBytesVec;
use libafl_bolts::ownedref::OwnedMutSlice; use libafl_bolts::ownedref::OwnedMutSlice;
use libafl_bolts::AsIter;
use petgraph::graph::EdgeIndex; use petgraph::graph::EdgeIndex;
use std::fs; use std::fs;
use libafl_bolts::rands::RandomSeed; use libafl_bolts::rands::random_seed;
use libafl_bolts::rands::StdRand; use libafl_bolts::rands::StdRand;
use libafl::mutators::Mutator; use libafl::mutators::Mutator;
use libafl::mutators::MutationResult; use libafl::mutators::MutationResult;
use libafl::prelude::HasTargetBytes; use libafl::prelude::HasTargetBytes;
use libafl::prelude::UsesInput; use libafl::prelude::UsesInput;
use libafl::state::HasNamedMetadata; use libafl::common::HasNamedMetadata;
use libafl::state::UsesState; use libafl::state::UsesState;
use libafl::prelude::State; use libafl::prelude::State;
use petgraph::dot::Config; use petgraph::dot::Config;
@ -40,9 +41,9 @@ use libafl::state::MaybeHasClientPerfMonitor;
use libafl::feedbacks::Feedback; use libafl::feedbacks::Feedback;
use libafl_bolts::Named; use libafl_bolts::Named;
use libafl::Error; use libafl::Error;
use libafl_qemu::edges::EDGES_MAP_SIZE; use libafl_qemu::edges::EDGES_MAP_SIZE_IN_USE;
use hashbrown::HashMap; use hashbrown::HashMap;
use libafl::{executors::ExitKind, inputs::Input, observers::ObserversTuple, state::HasMetadata}; use libafl::{executors::ExitKind, inputs::Input, observers::ObserversTuple, common::HasMetadata};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use super::feedbacks::SystemStateFeedbackState; use super::feedbacks::SystemStateFeedbackState;
@ -63,6 +64,9 @@ use libafl_bolts::rands::Rand;
use crate::clock::FUZZ_START_TIMESTAMP; use crate::clock::FUZZ_START_TIMESTAMP;
use std::time::SystemTime; use std::time::SystemTime;
use std::{fs::OpenOptions, io::Write}; use std::{fs::OpenOptions, io::Write};
use std::borrow::Cow;
use std::ops::Deref;
use std::ops::DerefMut;
//============================= Data Structures //============================= Data Structures
#[derive(Serialize, Deserialize, Clone, Debug, Default, Hash)] #[derive(Serialize, Deserialize, Clone, Debug, Default, Hash)]
@ -144,6 +148,7 @@ impl STGEdge {
#[derive(Debug, Serialize, Deserialize, SerdeAny, Clone)] #[derive(Debug, Serialize, Deserialize, SerdeAny, Clone)]
pub struct STGFeedbackState pub struct STGFeedbackState
{ {
name: Cow<'static, str>,
// aggregated traces as a graph // aggregated traces as a graph
pub graph: DiGraph<STGNode, STGEdge>, pub graph: DiGraph<STGNode, STGEdge>,
systemstate_index: HashMap<u64, ReducedFreeRTOSSystemState>, systemstate_index: HashMap<u64, ReducedFreeRTOSSystemState>,
@ -179,6 +184,7 @@ impl Default for STGFeedbackState {
let index = HashMap::from([(h_entry, entrypoint), (h_exit, exitpoint)]); let index = HashMap::from([(h_entry, entrypoint), (h_exit, exitpoint)]);
STGFeedbackState { STGFeedbackState {
name: Cow::from("stgfeedbackstate".to_string()),
graph, graph,
stgnode_index: index, stgnode_index: index,
entrypoint, entrypoint,
@ -196,8 +202,8 @@ impl Default for STGFeedbackState {
impl Named for STGFeedbackState impl Named for STGFeedbackState
{ {
#[inline] #[inline]
fn name(&self) -> &str { fn name(&self) -> &Cow<'static, str> {
"stgfeedbackstate" &self.name
} }
} }
@ -238,13 +244,31 @@ impl STGNodeMetadata {
Self {indices, intervals, nodes, abbs, aggregate, top_abb_counts, edges, tcref: 0} Self {indices, intervals, nodes, abbs, aggregate, top_abb_counts, edges, tcref: 0}
} }
} }
impl AsSlice for STGNodeMetadata {
/// Convert the slice of system-states to a slice of hashes over enumerated states // impl AsSlice for STGNodeMetadata {
fn as_slice(&self) -> &[usize] { // /// Convert the slice of system-states to a slice of hashes over enumerated states
self.indices.as_slice() // fn as_slice(&self) -> &[usize] {
// self.indices.as_slice()
// }
// type Entry = usize;
// type SliceRef = &[usize];
// }
impl Deref for STGNodeMetadata {
type Target = [usize];
/// Convert to a slice
fn deref(&self) -> &[usize] {
&self.indices
}
} }
type Entry = usize; impl DerefMut for STGNodeMetadata {
/// Convert to a slice
fn deref_mut(&mut self) -> &mut [usize] {
&mut self.indices
}
} }
impl HasRefCnt for STGNodeMetadata { impl HasRefCnt for STGNodeMetadata {
@ -259,8 +283,8 @@ impl HasRefCnt for STGNodeMetadata {
libafl_bolts::impl_serdeany!(STGNodeMetadata); libafl_bolts::impl_serdeany!(STGNodeMetadata);
pub type GraphMaximizerCorpusScheduler<CS> = pub type GraphMaximizerCorpusScheduler<CS, O> =
MinimizerScheduler<CS, MaxTimeFavFactor<<CS as UsesState>::State>,STGNodeMetadata>; MinimizerScheduler<CS, MaxTimeFavFactor<<CS as UsesState>::State>,STGNodeMetadata,O>;
// AI generated, human verified // AI generated, human verified
fn count_occurrences<T>(vec: &Vec<T>) -> HashMap<&T, usize> fn count_occurrences<T>(vec: &Vec<T>) -> HashMap<&T, usize>
@ -294,7 +318,7 @@ where
//============================= Graph Feedback //============================= Graph Feedback
pub static mut STG_MAP: [u16; EDGES_MAP_SIZE] = [0; EDGES_MAP_SIZE]; pub static mut STG_MAP: [u16; EDGES_MAP_SIZE_IN_USE] = [0; EDGES_MAP_SIZE_IN_USE];
pub static mut MAX_STG_NUM: usize = 0; pub static mut MAX_STG_NUM: usize = 0;
pub unsafe fn stg_map_mut_slice<'a>() -> OwnedMutSlice<'a, u16> { pub unsafe fn stg_map_mut_slice<'a>() -> OwnedMutSlice<'a, u16> {
OwnedMutSlice::from_raw_parts_mut(STG_MAP.as_mut_ptr(), STG_MAP.len()) OwnedMutSlice::from_raw_parts_mut(STG_MAP.as_mut_ptr(), STG_MAP.len())
@ -304,7 +328,7 @@ pub unsafe fn stg_map_mut_slice<'a>() -> OwnedMutSlice<'a, u16> {
#[derive(Serialize, Deserialize, Clone, Debug, Default)] #[derive(Serialize, Deserialize, Clone, Debug, Default)]
pub struct StgFeedback pub struct StgFeedback
{ {
name: String, name: Cow<'static, str>,
last_node_trace: Option<Vec<NodeIndex>>, last_node_trace: Option<Vec<NodeIndex>>,
last_edge_trace: Option<Vec<EdgeIndex>>, last_edge_trace: Option<Vec<EdgeIndex>>,
last_intervals: Option<Vec<ExecInterval>>, last_intervals: Option<Vec<ExecInterval>>,
@ -468,7 +492,7 @@ where
Some(s) => s, Some(s) => s,
None => { None => {
let n=STGFeedbackState::default(); let n=STGFeedbackState::default();
state.named_metadata_map_mut().insert(n, "stgfeedbackstate"); state.named_metadata_map_mut().insert("stgfeedbackstate",n);
state.named_metadata_map_mut().get_mut::<STGFeedbackState>("stgfeedbackstate").unwrap() state.named_metadata_map_mut().get_mut::<STGFeedbackState>("stgfeedbackstate").unwrap()
} }
}; };
@ -565,7 +589,7 @@ where
/// Append to the testcase the generated metadata in case of a new corpus item /// Append to the testcase the generated metadata in case of a new corpus item
#[inline] #[inline]
fn append_metadata<OT>(&mut self, _state: &mut S, _observers: &OT, testcase: &mut Testcase<S::Input>) -> Result<(), Error> { fn append_metadata<EM, OT>(&mut self, _state: &mut S, _manager: &mut EM, _observers: &OT, testcase: &mut Testcase<S::Input>) -> Result<(), Error> {
let nodes = self.last_node_trace.take(); let nodes = self.last_node_trace.take();
let edges = self.last_edge_trace.take(); let edges = self.last_edge_trace.take();
match nodes { match nodes {
@ -584,7 +608,7 @@ where
impl Named for StgFeedback impl Named for StgFeedback
{ {
#[inline] #[inline]
fn name(&self) -> &str { fn name(&self) -> &Cow<'static, str> {
&self.name &self.name
} }
} }

View File

@ -17,7 +17,7 @@ use libafl::state::{MaybeHasClientPerfMonitor, HasCorpus, UsesState};
use libafl::prelude::State; use libafl::prelude::State;
use libafl::inputs::Input; use libafl::inputs::Input;
use libafl::feedbacks::Feedback; use libafl::feedbacks::Feedback;
use libafl::state::HasMetadata; use libafl::common::HasMetadata;
use libafl_qemu::edges::QemuEdgesMapMetadata; use libafl_qemu::edges::QemuEdgesMapMetadata;
use libafl::observers::MapObserver; use libafl::observers::MapObserver;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -35,10 +35,12 @@ use libafl::{
use crate::clock::QemuClockObserver; use crate::clock::QemuClockObserver;
use crate::systemstate::FreeRTOSSystemStateMetadata; use crate::systemstate::FreeRTOSSystemStateMetadata;
use std::borrow::Cow;
//=========================== Scheduler //=========================== Scheduler
pub type TimeMaximizerCorpusScheduler<CS> = pub type TimeMaximizerCorpusScheduler<CS, O> =
MinimizerScheduler<CS, MaxTimeFavFactor<<CS as UsesState>::State>, MapIndexesMetadata>; MinimizerScheduler<CS, MaxTimeFavFactor<<CS as UsesState>::State>, MapIndexesMetadata, O>;
/// Multiply the testcase size with the execution time. /// Multiply the testcase size with the execution time.
/// This favors small and quick testcases. /// This favors small and quick testcases.
@ -64,11 +66,11 @@ where
} }
} }
pub type LenTimeMaximizerCorpusScheduler<CS> = pub type LenTimeMaximizerCorpusScheduler<CS, O> =
MinimizerScheduler<CS, MaxExecsLenFavFactor<<CS as UsesState>::State>, MapIndexesMetadata>; MinimizerScheduler<CS, MaxExecsLenFavFactor<<CS as UsesState>::State>, MapIndexesMetadata, O>;
pub type TimeStateMaximizerCorpusScheduler<CS> = pub type TimeStateMaximizerCorpusScheduler<CS, O> =
MinimizerScheduler<CS, MaxTimeFavFactor<<CS as UsesState>::State>, FreeRTOSSystemStateMetadata>; MinimizerScheduler<CS, MaxTimeFavFactor<<CS as UsesState>::State>, FreeRTOSSystemStateMetadata, O>;
/// Multiply the testcase size with the execution time. /// Multiply the testcase size with the execution time.
/// This favors small and quick testcases. /// This favors small and quick testcases.
@ -98,6 +100,7 @@ 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 {
name: Cow<'static, str>
} }
impl<S> Feedback<S> for SortedFeedback impl<S> Feedback<S> for SortedFeedback
@ -146,8 +149,8 @@ where
impl Named for SortedFeedback { impl Named for SortedFeedback {
#[inline] #[inline]
fn name(&self) -> &str { fn name(&self) -> &Cow<'static, str> {
"Sorted" &self.name
} }
} }
@ -155,7 +158,7 @@ impl SortedFeedback {
/// Creates a new [`HitFeedback`] /// Creates a new [`HitFeedback`]
#[must_use] #[must_use]
pub fn new() -> Self { pub fn new() -> Self {
Self {} Self {name: Cow::from("Sorted".to_string()),}
} }
} }
@ -170,6 +173,7 @@ impl Default for SortedFeedback {
#[derive(Serialize, Deserialize, Clone, Debug)] #[derive(Serialize, Deserialize, Clone, Debug)]
pub struct ExecTimeReachedFeedback pub struct ExecTimeReachedFeedback
{ {
name: Cow<'static, str>,
target_time: u64, target_time: u64,
} }
@ -199,8 +203,8 @@ where
impl Named for ExecTimeReachedFeedback impl Named for ExecTimeReachedFeedback
{ {
#[inline] #[inline]
fn name(&self) -> &str { fn name(&self) -> &Cow<'static, str> {
"ExecTimeReachedFeedback" &self.name
} }
} }
@ -210,7 +214,7 @@ where
/// Creates a new [`ExecTimeReachedFeedback`] /// Creates a new [`ExecTimeReachedFeedback`]
#[must_use] #[must_use]
pub fn new(target_time : u64) -> Self { pub fn new(target_time : u64) -> Self {
Self {target_time: target_time} Self {name: Cow::from("ExecTimeReachedFeedback".to_string()), target_time: target_time}
} }
} }
@ -220,6 +224,7 @@ pub static mut EXEC_TIME_COLLECTION : Vec<u32> = Vec::new();
#[derive(Serialize, Deserialize, Clone, Debug)] #[derive(Serialize, Deserialize, Clone, Debug)]
pub struct ExecTimeCollectorFeedback pub struct ExecTimeCollectorFeedback
{ {
name: Cow<'static, str>
} }
impl<S> Feedback<S> for ExecTimeCollectorFeedback impl<S> Feedback<S> for ExecTimeCollectorFeedback
@ -249,8 +254,8 @@ where
impl Named for ExecTimeCollectorFeedback impl Named for ExecTimeCollectorFeedback
{ {
#[inline] #[inline]
fn name(&self) -> &str { fn name(&self) -> &Cow<'static, str> {
"ExecTimeCollectorFeedback" &self.name
} }
} }
@ -260,21 +265,27 @@ where
/// Creates a new [`ExecTimeCollectorFeedback`] /// Creates a new [`ExecTimeCollectorFeedback`]
#[must_use] #[must_use]
pub fn new() -> Self { pub fn new() -> Self {
Self {} Self {name: Cow::from("ExecTimeCollectorFeedback".to_string())}
} }
} }
/// Shared Metadata for a SysStateFeedback /// Shared Metadata for a SysStateFeedback
#[derive(Serialize, Deserialize, Clone, Debug, Default)] #[derive(Serialize, Deserialize, Clone, Debug)]
pub struct ExecTimeCollectorFeedbackState pub struct ExecTimeCollectorFeedbackState
{ {
name: Cow<'static, str>,
collection: Vec<u32>, collection: Vec<u32>,
} }
impl Named for ExecTimeCollectorFeedbackState impl Named for ExecTimeCollectorFeedbackState
{ {
#[inline] #[inline]
fn name(&self) -> &str { fn name(&self) -> &Cow<'static, str> {
"ExecTimeCollectorFeedbackState" &self.name
}
}
impl Default for ExecTimeCollectorFeedbackState {
fn default() -> Self {
Self {name: Cow::from("ExecTimeCollectorFeedbackState".to_string()), collection: Vec::new()}
} }
} }
@ -283,6 +294,7 @@ impl Named for ExecTimeCollectorFeedbackState
#[derive(Serialize, Deserialize, Clone, Debug)] #[derive(Serialize, Deserialize, Clone, Debug)]
pub struct ExecTimeIncFeedback pub struct ExecTimeIncFeedback
{ {
name: Cow<'static, str>,
longest_time: u64, longest_time: u64,
last_is_longest: bool last_is_longest: bool
} }
@ -315,9 +327,10 @@ where
Ok(false) Ok(false)
} }
} }
fn append_metadata<OT>( fn append_metadata<EM, OT>(
&mut self, &mut self,
_state: &mut S, _state: &mut S,
_manager: &mut EM,
observers: &OT, observers: &OT,
testcase: &mut Testcase<<S as UsesInput>::Input>, testcase: &mut Testcase<<S as UsesInput>::Input>,
) -> Result<(), Error> { ) -> Result<(), Error> {
@ -334,8 +347,8 @@ where
impl Named for ExecTimeIncFeedback impl Named for ExecTimeIncFeedback
{ {
#[inline] #[inline]
fn name(&self) -> &str { fn name(&self) -> &Cow<'static, str> {
"ExecTimeReachedFeedback" &self.name
} }
} }
@ -345,7 +358,7 @@ where
/// Creates a new [`ExecTimeReachedFeedback`] /// Creates a new [`ExecTimeReachedFeedback`]
#[must_use] #[must_use]
pub fn new() -> Self { pub fn new() -> Self {
Self {longest_time: 0, last_is_longest: false} Self {name: Cow::from("ExecTimeReachedFeedback".to_string()), longest_time: 0, last_is_longest: false}
} }
} }
@ -353,6 +366,7 @@ where
#[derive(Serialize, Deserialize, Clone, Debug)] #[derive(Serialize, Deserialize, Clone, Debug)]
pub struct AlwaysTrueFeedback pub struct AlwaysTrueFeedback
{ {
name: Cow<'static, str>
} }
impl<S> Feedback<S> for AlwaysTrueFeedback impl<S> Feedback<S> for AlwaysTrueFeedback
@ -379,8 +393,8 @@ where
impl Named for AlwaysTrueFeedback impl Named for AlwaysTrueFeedback
{ {
#[inline] #[inline]
fn name(&self) -> &str { fn name(&self) -> &Cow<'static, str> {
"AlwaysTrueFeedback" &self.name
} }
} }
@ -391,6 +405,7 @@ where
#[must_use] #[must_use]
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
name: Cow::from("AlwaysTrueFeedback".to_string())
} }
} }
} }

View File

@ -16,9 +16,4 @@ extern_c_checked! {
pub fn icount_get_raw() -> u64; pub fn icount_get_raw() -> u64;
pub fn libafl_start_int_timer(); pub fn libafl_start_int_timer();
pub fn libafl_add_jmp_hook(
gen: Option<extern "C" fn(u64, GuestAddr, GuestAddr) -> u64>, // data,src,dest
exec: Option<extern "C" fn(u64, GuestAddr, GuestAddr, u64)>, // data,src,dest,id
data: u64
) -> usize;
} }

View File

@ -24,7 +24,7 @@ use crate::{
helpers::QemuHelperTuple, helpers::QemuHelperTuple,
qemu::{MemAccessInfo, Qemu, SKIP_EXEC_HOOK}, qemu::{MemAccessInfo, Qemu, SKIP_EXEC_HOOK},
sys::TCGTemp, sys::TCGTemp,
BackdoorHookId, BlockHookId, CmpHookId, EdgeHookId, HookId, InstructionHookId, ReadHookId, BackdoorHookId, BlockHookId, CmpHookId, EdgeHookId, HookId, InstructionHookId, ReadHookId, JmpHookId,
WriteHookId, WriteHookId,
}; };
#[cfg(emulation_mode = "usermode")] #[cfg(emulation_mode = "usermode")]
@ -370,9 +370,9 @@ where
} }
} }
static mut JMP_HOOKS: Vec<HookState<1>> = vec![]; static mut JMP_HOOKS: Vec<Pin<Box<HookState<1, JmpHookId>>>> = vec![];
create_gen_wrapper!(jmp, (src: GuestAddr, dest: GuestAddr), u64, 1); create_gen_wrapper!(jmp, (src: GuestAddr, dest: GuestAddr), u64, 1, JmpHookId);
create_exec_wrapper!(jmp, (src: GuestAddr, dst: GuestAddr, id: u64), 0, 1); create_exec_wrapper!(jmp, (src: GuestAddr, dst: GuestAddr, id: u64), 0, 1, JmpHookId);
@ -1410,28 +1410,36 @@ where
Box<dyn for<'a> FnMut(&'a mut Self, Option<&'a mut S>, GuestAddr, GuestAddr, u64)>, Box<dyn for<'a> FnMut(&'a mut Self, Option<&'a mut S>, GuestAddr, GuestAddr, u64)>,
extern "C" fn(*const (), src: GuestAddr, dest: GuestAddr, id: u64), extern "C" fn(*const (), src: GuestAddr, dest: GuestAddr, id: u64),
>, >,
) -> HookId { ) -> JmpHookId {
unsafe { unsafe {
let gen = get_raw_hook!( let gen = get_raw_hook!(
generation_hook, generation_hook,
jmp_gen_hook_wrapper::<QT, S>, jmp_gen_hook_wrapper::<QT, S>,
extern "C" fn(&mut HookState<1>, src: GuestAddr, dest: GuestAddr) -> u64 unsafe extern "C" fn(&mut HookState<1, JmpHookId>, src: GuestAddr, dest: GuestAddr) -> u64
); );
let exec = get_raw_hook!( let exec = get_raw_hook!(
execution_hook, execution_hook,
jmp_0_exec_hook_wrapper::<QT, S>, jmp_0_exec_hook_wrapper::<QT, S>,
extern "C" fn(&mut HookState<1>, src: GuestAddr, dest: GuestAddr, id: u64) unsafe extern "C" fn(&mut HookState<1, JmpHookId>, src: GuestAddr, dest: GuestAddr, id: u64)
); );
JMP_HOOKS.push(HookState { JMP_HOOKS.push(Box::pin(HookState {
id: HookId(0), id: JmpHookId(0),
gen: hook_to_repr!(generation_hook), gen: hook_to_repr!(generation_hook),
post_gen: HookRepr::Empty, post_gen: HookRepr::Empty,
execs: [hook_to_repr!(execution_hook)], execs: [hook_to_repr!(execution_hook)],
}); }));
let id = self let id = self
.emulator .qemu
.add_jmp_hooks(JMP_HOOKS.last_mut().unwrap(), gen, exec); .add_jmp_hooks(JMP_HOOKS.last_mut().unwrap().as_mut().get_unchecked_mut(),
JMP_HOOKS.last_mut().unwrap().id = id; gen,
exec
);
JMP_HOOKS
.last_mut()
.unwrap()
.as_mut()
.get_unchecked_mut()
.id = id;
id id
} }
} }

View File

@ -85,22 +85,7 @@ create_hook_id!(Cmp, libafl_qemu_remove_cmp_hook, true);
create_hook_id!(PreSyscall, libafl_qemu_remove_pre_syscall_hook, false); create_hook_id!(PreSyscall, libafl_qemu_remove_pre_syscall_hook, false);
create_hook_id!(PostSyscall, libafl_qemu_remove_post_syscall_hook, false); create_hook_id!(PostSyscall, libafl_qemu_remove_post_syscall_hook, false);
create_hook_id!(NewThread, libafl_qemu_remove_new_thread_hook, false); create_hook_id!(NewThread, libafl_qemu_remove_new_thread_hook, false);
create_hook_id!(Jmp, libafl_qemu_remove_jmp_hook, true);
pub fn add_jmp_hooks<T: Into<HookData>>(
&self,
data: T,
gen: Option<extern "C" fn(T, GuestAddr, GuestAddr) -> u64>,
exec: Option<extern "C" fn(T, GuestAddr, GuestAddr, u64)>,
) -> HookId {
unsafe {
let data: u64 = data.into().0;
let gen: Option<extern "C" fn(u64, GuestAddr, GuestAddr) -> u64> =
core::mem::transmute(gen);
let exec: Option<extern "C" fn(u64, GuestAddr, GuestAddr, u64)> = core::mem::transmute(exec);
let num = libafl_add_jmp_hook(gen, exec, data);
HookId(num)
}
}
#[derive(Debug)] #[derive(Debug)]
pub enum QemuInitError { pub enum QemuInitError {
@ -251,7 +236,7 @@ pub struct MemAccessInfo {
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
#[repr(transparent)] #[repr(transparent)]
pub struct CPU { pub struct CPU {
ptr: CPUStatePtr, pub ptr: CPUStatePtr,
} }
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
@ -1028,6 +1013,22 @@ impl Qemu {
pub fn host_page_size(&self) -> usize { pub fn host_page_size(&self) -> usize {
unsafe { libafl_qemu_sys::libafl_qemu_host_page_size() } unsafe { libafl_qemu_sys::libafl_qemu_host_page_size() }
} }
pub fn add_jmp_hooks<T: Into<HookData>>(
&self,
data: T,
gen: Option<unsafe extern "C" fn(T, GuestAddr, GuestAddr) -> u64>,
exec: Option<unsafe extern "C" fn(T, GuestAddr, GuestAddr, u64)>,
) -> JmpHookId {
unsafe {
let data: u64 = data.into().0;
let gen: Option<unsafe extern "C" fn(u64, GuestAddr, GuestAddr) -> u64> =
core::mem::transmute(gen);
let exec: Option<unsafe extern "C" fn(u64, GuestAddr, GuestAddr, u64)> = core::mem::transmute(exec);
let num = libafl_qemu_sys::libafl_add_jmp_hook(gen, exec, data);
JmpHookId(num)
}
}
} }
impl ArchExtras for Qemu { impl ArchExtras for Qemu {

View File

@ -8,9 +8,7 @@ use std::{
use bytes_utils::SegmentedBuf; use bytes_utils::SegmentedBuf;
use libafl_qemu_sys::{ use libafl_qemu_sys::{
libafl_load_qemu_snapshot, libafl_page_from_addr, libafl_qemu_current_paging_id, libafl_load_qemu_snapshot, libafl_page_from_addr, libafl_qemu_current_paging_id, libafl_save_qemu_snapshot, libafl_start_int_timer, qemu_cleanup, qemu_main_loop, vm_start, GuestAddr, GuestPhysAddr, GuestUsize, GuestVirtAddr
libafl_save_qemu_snapshot, qemu_cleanup, qemu_main_loop, vm_start, GuestAddr, GuestPhysAddr,
GuestUsize, GuestVirtAddr,
}; };
use num_traits::Zero; use num_traits::Zero;