update to 0.13.0 API
This commit is contained in:
parent
df7333b764
commit
5fad373199
@ -11,8 +11,9 @@ use libafl::{
|
||||
fuzzer::{StdFuzzer},
|
||||
inputs::{BytesInput, HasTargetBytes},
|
||||
observers::{Observer,VariableMapObserver},
|
||||
state::{StdState, HasNamedMetadata},
|
||||
state::{StdState},
|
||||
Error,
|
||||
common::HasNamedMetadata,
|
||||
observers::ObserversTuple, prelude::UsesInput,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
@ -22,7 +23,7 @@ use libafl_qemu::{
|
||||
emu,
|
||||
emu::Emulator,
|
||||
executor::QemuExecutor,
|
||||
helper::{QemuHelper, QemuHelperTuple, QemuInstrumentationFilter},
|
||||
helpers::{QemuHelper, QemuHelperTuple, HasInstrumentationFilter},
|
||||
};
|
||||
use libafl::events::EventFirer;
|
||||
use libafl::state::MaybeHasClientPerfMonitor;
|
||||
@ -30,13 +31,14 @@ use libafl::prelude::State;
|
||||
use libafl::inputs::Input;
|
||||
use libafl::feedbacks::Feedback;
|
||||
use libafl::SerdeAny;
|
||||
use libafl::state::HasMetadata;
|
||||
use libafl::common::HasMetadata;
|
||||
use libafl::corpus::testcase::Testcase;
|
||||
use core::{fmt::Debug, time::Duration};
|
||||
// use libafl::feedbacks::FeedbackState;
|
||||
// use libafl::state::HasFeedbackStates;
|
||||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
use std::path::PathBuf;
|
||||
use std::borrow::Cow;
|
||||
|
||||
pub static mut FUZZ_START_TIMESTAMP : SystemTime = UNIX_EPOCH;
|
||||
|
||||
@ -60,7 +62,7 @@ pub struct QemuIcountMetadata {
|
||||
#[derive(Debug, Serialize, Deserialize, SerdeAny)]
|
||||
pub struct MaxIcountMetadata {
|
||||
pub max_icount_seen: u64,
|
||||
pub name: String,
|
||||
pub name: Cow<'static, str>,
|
||||
}
|
||||
|
||||
// impl FeedbackState for MaxIcountMetadata
|
||||
@ -74,8 +76,8 @@ pub struct MaxIcountMetadata {
|
||||
impl Named for MaxIcountMetadata
|
||||
{
|
||||
#[inline]
|
||||
fn name(&self) -> &str {
|
||||
self.name.as_str()
|
||||
fn name(&self) -> &Cow<'static, str> {
|
||||
&self.name
|
||||
}
|
||||
}
|
||||
|
||||
@ -86,7 +88,7 @@ impl MaxIcountMetadata
|
||||
pub fn new(name: &'static str) -> Self {
|
||||
Self {
|
||||
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.
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub struct QemuClockObserver {
|
||||
name: String,
|
||||
name: Cow<'static, str>,
|
||||
start_tick: u64,
|
||||
end_tick: u64,
|
||||
dump_path: Option<PathBuf>
|
||||
@ -117,7 +119,7 @@ impl QemuClockObserver {
|
||||
#[must_use]
|
||||
pub fn new(name: &'static str, dump_path: Option<PathBuf>) -> Self {
|
||||
Self {
|
||||
name: name.to_string(),
|
||||
name: Cow::from(name),
|
||||
start_tick: 0,
|
||||
end_tick: 0,
|
||||
dump_path
|
||||
@ -149,7 +151,7 @@ where
|
||||
}
|
||||
|
||||
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 {
|
||||
// println!("clock post {}", self.end_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 {
|
||||
#[inline]
|
||||
fn name(&self) -> &str {
|
||||
fn name(&self) -> &Cow<'static, str> {
|
||||
&self.name
|
||||
}
|
||||
}
|
||||
@ -195,7 +197,7 @@ impl Named for QemuClockObserver {
|
||||
impl Default for QemuClockObserver {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
name: String::from("clock"),
|
||||
name: Cow::from(String::from("clock")),
|
||||
start_tick: 0,
|
||||
end_tick: 0,
|
||||
dump_path: None
|
||||
@ -210,7 +212,7 @@ impl Default for QemuClockObserver {
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
pub struct ClockTimeFeedback {
|
||||
exec_time: Option<Duration>,
|
||||
name: String,
|
||||
name: Cow<'static, str>,
|
||||
}
|
||||
|
||||
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
|
||||
#[inline]
|
||||
fn append_metadata<OT>(
|
||||
fn append_metadata<EM, OT>(
|
||||
&mut self,
|
||||
_state: &mut S,
|
||||
_manager: &mut EM,
|
||||
observers: &OT,
|
||||
testcase: &mut Testcase<S::Input>,
|
||||
) -> Result<(), Error> {
|
||||
@ -259,8 +262,8 @@ where
|
||||
|
||||
impl Named for ClockTimeFeedback {
|
||||
#[inline]
|
||||
fn name(&self) -> &str {
|
||||
self.name.as_str()
|
||||
fn name(&self) -> &Cow<'static, str> {
|
||||
&self.name
|
||||
}
|
||||
}
|
||||
|
||||
@ -270,7 +273,7 @@ impl ClockTimeFeedback {
|
||||
pub fn new(name: &'static str) -> Self {
|
||||
Self {
|
||||
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 {
|
||||
Self {
|
||||
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.
|
||||
#[derive(Debug)]
|
||||
pub struct QemuClockIncreaseFeedback {
|
||||
name: String,
|
||||
name: Cow<'static, str>,
|
||||
}
|
||||
|
||||
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
|
||||
#[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});
|
||||
Ok(())
|
||||
}
|
||||
@ -337,7 +340,7 @@ where
|
||||
|
||||
impl Named for QemuClockIncreaseFeedback {
|
||||
#[inline]
|
||||
fn name(&self) -> &str {
|
||||
fn name(&self) -> &Cow<'static, str> {
|
||||
&self.name
|
||||
}
|
||||
}
|
||||
@ -346,7 +349,7 @@ impl QemuClockIncreaseFeedback {
|
||||
/// Creates a new [`HitFeedback`]
|
||||
#[must_use]
|
||||
pub fn new(name: &'static str) -> Self {
|
||||
Self {name: String::from(name)}
|
||||
Self {name: Cow::from(String::from(name))}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 hashbrown::HashMap;
|
||||
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::{
|
||||
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::{
|
||||
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 crate::{
|
||||
@ -25,6 +25,8 @@ use petgraph::graph::NodeIndex;
|
||||
use petgraph::prelude::DiGraph;
|
||||
use crate::systemstate::stg::STGFeedbackState;
|
||||
use crate::clock::QEMU_ICOUNT_SHIFT;
|
||||
use libafl::inputs::HasMutatorBytes;
|
||||
use libafl_qemu::Qemu;
|
||||
|
||||
// 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();
|
||||
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 = QemuInstrumentationFilter::DenyList(denylist); // do not count isr jumps, which are useless
|
||||
let denylist : Vec<_> =isr_ranges.values().map(|x| x.clone()).collect();
|
||||
let denylist = QemuFilterList::DenyList(denylist); // do not count isr jumps, which are useless
|
||||
#[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();
|
||||
#[cfg(feature = "observe_systemstate")]
|
||||
@ -421,22 +423,22 @@ let mut run_client = |state: Option<_>, mut mgr, _core_id| {
|
||||
// "-semihosting",
|
||||
// "--semihosting-config",
|
||||
// "enable=on,target=native",
|
||||
"-snapshot",
|
||||
"-drive",
|
||||
"if=none,format=qcow2,file=dummy.qcow2",
|
||||
// "-snapshot",
|
||||
// "-drive",
|
||||
// "if=none,format=qcow2,file=dummy.qcow2",
|
||||
].into_iter().map(String::from).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 {
|
||||
unsafe {
|
||||
libafl_qemu_set_native_breakpoint(main_addr);
|
||||
emu.run();
|
||||
libafl_qemu_remove_native_breakpoint(main_addr);
|
||||
}
|
||||
}
|
||||
// if let Some(main_addr) = main_addr {
|
||||
// unsafe {
|
||||
// emu.set_breakpoint(main_addr);
|
||||
// emu.run();
|
||||
// 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
|
||||
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
|
||||
let mut pcs = (0..emu.num_cpus())
|
||||
.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
|
||||
.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)
|
||||
)};
|
||||
#[cfg(feature = "observer_hitcounts")]
|
||||
let edges_observer = HitcountsMapObserver::new(edges_observer);
|
||||
let edges_observer = HitcountsMapObserver::new(edges_observer).track_indices();
|
||||
|
||||
#[cfg(feature = "observe_systemstate")]
|
||||
let stg_coverage_observer = unsafe { VariableMapObserver::from_mut_slice(
|
||||
"stg",
|
||||
stg_map_mut_slice(),
|
||||
addr_of_mut!(MAX_STG_NUM)
|
||||
)};
|
||||
)}.track_indices();
|
||||
|
||||
#[cfg(feature = "observe_systemstate")]
|
||||
let systemstate_observer = QemuSystemStateObserver::new();
|
||||
@ -576,7 +578,7 @@ let mut run_client = |state: Option<_>, mut mgr, _core_id| {
|
||||
#[cfg(feature = "sched_afl",)]
|
||||
let scheduler = TimeMaximizerCorpusScheduler::new(QueueScheduler::new());
|
||||
#[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")]
|
||||
let scheduler = GenerationScheduler::new();
|
||||
|
||||
@ -587,7 +589,7 @@ let mut run_client = |state: Option<_>, mut mgr, _core_id| {
|
||||
#[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);
|
||||
#[cfg(feature = "observe_edges")]
|
||||
let qhelpers = (QemuEdgeCoverageHelper::new(denylist), qhelpers);
|
||||
let qhelpers = (QemuEdgeCoverageHelper::new(denylist, QemuFilterList::None), qhelpers);
|
||||
let qhelpers = (QemuStateRestoreHelper::new(), 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);
|
||||
|
||||
// Create a QEMU in-process executor
|
||||
let executor = QemuExecutor::new(
|
||||
let mut executor = QemuExecutor::new(
|
||||
&mut hooks,
|
||||
&mut harness,
|
||||
observer_list,
|
||||
&mut fuzzer,
|
||||
&mut state,
|
||||
&mut mgr,
|
||||
timeout
|
||||
)
|
||||
.expect("Failed to create QemuExecutor");
|
||||
|
||||
// Wrap the executor to keep track of the timeout
|
||||
let mut executor = TimeoutExecutor::new(executor, timeout);
|
||||
executor.break_on_timeout();
|
||||
|
||||
let mutations = havoc_mutations();
|
||||
// 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 {
|
||||
unsafe {
|
||||
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]);
|
||||
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
|
||||
let args: Vec<String> = env::args().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 {
|
||||
unsafe { libafl_qemu_set_native_breakpoint(main_addr); }// BREAKPOINT
|
||||
unsafe { emu.set_breakpoint(main_addr); }// BREAKPOINT
|
||||
}
|
||||
unsafe {
|
||||
emu.run();
|
||||
|
@ -6,14 +6,15 @@ use std::cmp::{max, min};
|
||||
|
||||
use hashbrown::HashMap;
|
||||
use libafl_bolts::rands::{
|
||||
StdRand, RandomSeed,
|
||||
StdRand, random_seed,
|
||||
Rand
|
||||
};
|
||||
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 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;
|
||||
// one isn per 2**4 ns
|
||||
@ -77,32 +78,28 @@ where
|
||||
EM: UsesState<State = Z::State>,
|
||||
Z: Evaluator<E, EM>,
|
||||
Z::State: MaybeHasClientPerfMonitor + HasCorpus + HasRand + HasMetadata + HasNamedMetadata,
|
||||
<Z::State as UsesInput>::Input: HasBytesVec
|
||||
<Z::State as UsesInput>::Input: HasMutatorBytes
|
||||
{
|
||||
fn perform(
|
||||
&mut self,
|
||||
fuzzer: &mut Z,
|
||||
executor: &mut E,
|
||||
state: &mut Self::State,
|
||||
manager: &mut EM,
|
||||
corpus_idx: CorpusId,
|
||||
manager: &mut EM
|
||||
// corpus_idx: CorpusId,
|
||||
) -> Result<(), Error> {
|
||||
let mut _input = state
|
||||
.corpus()
|
||||
.get(corpus_idx)?
|
||||
.borrow_mut().clone();
|
||||
let mut newinput = _input.input_mut().as_mut().unwrap().clone();
|
||||
let mut myrand = StdRand::new();
|
||||
myrand.set_seed(state.rand_mut().next());
|
||||
let mut _input = state.current_testcase()?.clone();
|
||||
let mut newinput = _input.input().as_ref().unwrap().clone();
|
||||
let mut do_rerun = false;
|
||||
// if state.rand_mut().between(1, 100) <= 50 // only attempt the mutation half of the time
|
||||
{
|
||||
// need our own random generator, because borrowing rules
|
||||
let mut myrand = StdRand::new();
|
||||
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();
|
||||
let tmp = &mut state.rand_mut();
|
||||
myrand.set_seed(tmp.next());
|
||||
}
|
||||
|
||||
// produce a slice of absolute interrupt times
|
||||
@ -129,7 +126,7 @@ where
|
||||
if interrupt_offsets[0] as u64 > maxtick { // place interrupt in reachable range
|
||||
do_rerun = true;
|
||||
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 {
|
||||
// let choice = myrand.between(1,100);
|
||||
@ -261,8 +258,8 @@ where
|
||||
).collect();
|
||||
if untouched.len() > 0 {
|
||||
let tmp = interrupt_offsets[i];
|
||||
let choice = myrand.choose(untouched);
|
||||
interrupt_offsets[i] = myrand.between(choice.0.start_tick, choice.0.end_tick)
|
||||
let choice = myrand.choose(untouched).unwrap();
|
||||
interrupt_offsets[i] = myrand.between(choice.0.start_tick as usize, choice.0.end_tick as usize)
|
||||
.try_into().expect("tick > u32");
|
||||
do_rerun = true;
|
||||
}
|
||||
@ -274,7 +271,7 @@ where
|
||||
continue;
|
||||
}
|
||||
}
|
||||
let replacement = myrand.choose(alternatives);
|
||||
let replacement = myrand.choose(alternatives).unwrap();
|
||||
if (old_hit.map_or(false, |x| x == replacement)) {
|
||||
// use the old value
|
||||
// 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)
|
||||
} else { 0 };
|
||||
let tmp = interrupt_offsets[i];
|
||||
interrupt_offsets[i] = (myrand.between(replacement.0.start_tick,
|
||||
replacement.0.end_tick) + extra).try_into().expect("ticks > u32");
|
||||
interrupt_offsets[i] = (myrand.between(replacement.0.start_tick as usize,
|
||||
replacement.0.end_tick as usize) + extra as usize).try_into().expect("ticks > u32");
|
||||
// println!("chose new alternative, i: {} {} -> {}",i,tmp, interrupt_offsets[i]);
|
||||
do_rerun = true;
|
||||
}
|
||||
@ -324,8 +321,8 @@ where
|
||||
|
||||
let mut n : Vec<u8> = vec![];
|
||||
n = [prefix.concat(), suffix].concat();
|
||||
newinput.bytes_mut().clear();
|
||||
newinput.bytes_mut().append(&mut n);
|
||||
newinput.drain(..);
|
||||
newinput.extend(&n);
|
||||
}
|
||||
// InterruptShifterMutator::mutate(&mut mymut, state, &mut input, 0)?;
|
||||
if do_rerun {
|
||||
@ -333,6 +330,14 @@ where
|
||||
}
|
||||
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>
|
||||
|
@ -1,11 +1,12 @@
|
||||
use libafl::prelude::UsesInput;
|
||||
use libafl_qemu::CPUArchState;
|
||||
use libafl_qemu::sys::CPUArchState;
|
||||
use libafl_qemu::Emulator;
|
||||
use libafl_qemu::FastSnapshot;
|
||||
use libafl_qemu::FastSnapshotPtr;
|
||||
use libafl_qemu::Qemu;
|
||||
use libafl_qemu::QemuExecutor;
|
||||
use libafl_qemu::QemuHelper;
|
||||
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::{
|
||||
@ -17,7 +18,7 @@ pub struct QemuStateRestoreHelper {
|
||||
has_snapshot: bool,
|
||||
use_snapshot: bool,
|
||||
saved_cpu_states: Vec<CPUArchState>,
|
||||
fastsnap: Option<FastSnapshot>
|
||||
fastsnap: Option<FastSnapshotPtr>
|
||||
}
|
||||
|
||||
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()) };
|
||||
}
|
||||
|
||||
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
|
||||
#[cfg(feature = "snapshot_restore")]
|
||||
{
|
||||
#[cfg(feature = "snapshot_fast")]
|
||||
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));},
|
||||
}
|
||||
#[cfg(not(feature = "snapshot_fast"))]
|
||||
|
@ -2,7 +2,7 @@ use libafl::SerdeAny;
|
||||
use libafl_bolts::ownedref::OwnedSlice;
|
||||
use libafl::inputs::BytesInput;
|
||||
use libafl::prelude::UsesInput;
|
||||
use libafl::state::HasNamedMetadata;
|
||||
use libafl::common::HasNamedMetadata;
|
||||
use std::path::PathBuf;
|
||||
use crate::clock::QemuClockObserver;
|
||||
use libafl::corpus::Testcase;
|
||||
@ -17,7 +17,7 @@ use libafl::feedbacks::Feedback;
|
||||
use libafl_bolts::Named;
|
||||
use libafl::Error;
|
||||
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 super::ExecInterval;
|
||||
@ -28,28 +28,38 @@ use petgraph::prelude::DiGraph;
|
||||
use petgraph::graph::NodeIndex;
|
||||
use petgraph::Direction;
|
||||
use std::cmp::Ordering;
|
||||
use std::borrow::Cow;
|
||||
|
||||
//============================= Feedback
|
||||
|
||||
/// Shared Metadata for a systemstateFeedback
|
||||
#[derive(Debug, Serialize, Deserialize, SerdeAny, Clone, Default)]
|
||||
#[derive(Debug, Serialize, Deserialize, SerdeAny, Clone)]
|
||||
pub struct SystemStateFeedbackState
|
||||
{
|
||||
name: Cow<'static, str>,
|
||||
known_traces: HashMap<u64,(u64,u64,usize)>, // encounters,ticks,length
|
||||
longest: Vec<ReducedFreeRTOSSystemState>,
|
||||
}
|
||||
impl Named for SystemStateFeedbackState
|
||||
{
|
||||
#[inline]
|
||||
fn name(&self) -> &str {
|
||||
"systemstate"
|
||||
fn name(&self) -> &Cow<'static, str> {
|
||||
&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`]
|
||||
#[derive(Serialize, Deserialize, Clone, Debug, Default)]
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
pub struct NovelSystemStateFeedback
|
||||
{
|
||||
name: Cow<'static, str>,
|
||||
last_trace: Option<Vec<ReducedFreeRTOSSystemState>>,
|
||||
// known_traces: HashMap<u64,(u64,usize)>,
|
||||
}
|
||||
@ -80,7 +90,7 @@ where
|
||||
Some(s) => s,
|
||||
None => {
|
||||
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()
|
||||
}
|
||||
};
|
||||
@ -117,7 +127,7 @@ where
|
||||
|
||||
/// Append to the testcase the generated metadata in case of a new corpus item
|
||||
#[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();
|
||||
match a {
|
||||
Some(s) => testcase.metadata_map_mut().insert(FreeRTOSSystemStateMetadata::new(s)),
|
||||
@ -137,8 +147,15 @@ where
|
||||
impl Named for NovelSystemStateFeedback
|
||||
{
|
||||
#[inline]
|
||||
fn name(&self) -> &str {
|
||||
"systemstate"
|
||||
fn name(&self) -> &Cow<'static, str> {
|
||||
&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)]
|
||||
pub struct DumpSystraceFeedback
|
||||
{
|
||||
name: Cow<'static, str>,
|
||||
dumpfile: Option<PathBuf>,
|
||||
dump_metadata: bool,
|
||||
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
|
||||
#[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(());}
|
||||
// let a = self.last_trace.take();
|
||||
// match a {
|
||||
@ -206,8 +224,8 @@ where
|
||||
impl Named for DumpSystraceFeedback
|
||||
{
|
||||
#[inline]
|
||||
fn name(&self) -> &str {
|
||||
"Dumpsystemstate"
|
||||
fn name(&self) -> &Cow<'static, str> {
|
||||
&self.name
|
||||
}
|
||||
}
|
||||
|
||||
@ -216,13 +234,13 @@ impl DumpSystraceFeedback
|
||||
/// Creates a new [`DumpSystraceFeedback`]
|
||||
#[must_use]
|
||||
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 {
|
||||
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 {
|
||||
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)]
|
||||
pub struct SystraceErrorFeedback
|
||||
{
|
||||
name: Cow<'static, str>,
|
||||
dump_case: bool
|
||||
}
|
||||
|
||||
@ -255,7 +274,7 @@ where
|
||||
}
|
||||
/// Append to the testcase the generated metadata in case of a new corpus item
|
||||
#[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(())
|
||||
}
|
||||
|
||||
@ -269,8 +288,8 @@ where
|
||||
impl Named for SystraceErrorFeedback
|
||||
{
|
||||
#[inline]
|
||||
fn name(&self) -> &str {
|
||||
"SystraceErrorFeedback"
|
||||
fn name(&self) -> &Cow<'static, str> {
|
||||
&self.name
|
||||
}
|
||||
}
|
||||
|
||||
@ -278,6 +297,6 @@ impl SystraceErrorFeedback
|
||||
{
|
||||
#[must_use]
|
||||
pub fn new(dump_case: bool) -> Self {
|
||||
Self {dump_case}
|
||||
Self {name: Cow::from(String::from("SystraceErrorFeedback")), dump_case}
|
||||
}
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
#![allow(non_camel_case_types,non_snake_case,non_upper_case_globals,deref_nullptr)]
|
||||
use serde::{Deserialize, Serialize};
|
||||
// Manual Types
|
||||
use libafl_qemu::Emulator;
|
||||
use libafl_qemu::{Emulator, Qemu};
|
||||
|
||||
/*========== Start of generated Code =============*/
|
||||
pub type char_ptr = ::std::os::raw::c_uint;
|
||||
@ -88,7 +88,7 @@ pub type TCB_t = tskTCB;
|
||||
/*========== End of generated Code =============*/
|
||||
|
||||
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 {
|
||||
($struct_name:ident) => {
|
||||
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>()];
|
||||
unsafe {
|
||||
emu.read_mem(addr.into(), &mut tmp);
|
||||
|
@ -1,14 +1,14 @@
|
||||
|
||||
use libafl::SerdeAny;
|
||||
/// Feedbacks organizing SystemStates as a graph
|
||||
use libafl::inputs::HasBytesVec;
|
||||
use libafl_bolts::rands::RandomSeed;
|
||||
// use libafl::inputs::HasBytesVec;
|
||||
use libafl_bolts::rands::random_seed;
|
||||
use libafl_bolts::rands::StdRand;
|
||||
use libafl::mutators::Mutator;
|
||||
use libafl::mutators::MutationResult;
|
||||
use libafl::prelude::HasTargetBytes;
|
||||
use libafl::prelude::UsesInput;
|
||||
use libafl::state::HasNamedMetadata;
|
||||
use libafl::common::HasNamedMetadata;
|
||||
use libafl::state::UsesState;
|
||||
use libafl::prelude::State;
|
||||
use core::marker::PhantomData;
|
||||
@ -35,7 +35,7 @@ use libafl::feedbacks::Feedback;
|
||||
use libafl_bolts::Named;
|
||||
use libafl::Error;
|
||||
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 super::ExecInterval;
|
||||
@ -46,6 +46,7 @@ use petgraph::prelude::DiGraph;
|
||||
use petgraph::graph::NodeIndex;
|
||||
use petgraph::Direction;
|
||||
use std::cmp::Ordering;
|
||||
use std::borrow::Cow;
|
||||
|
||||
use libafl_bolts::rands::Rand;
|
||||
|
||||
@ -148,14 +149,14 @@ impl SysGraphMetadata {
|
||||
Self {indices: inner.iter().map(|x| x.index()).collect(), inner: inner, tcref: 0}
|
||||
}
|
||||
}
|
||||
impl AsSlice for SysGraphMetadata {
|
||||
/// Convert the slice of system-states to a slice of hashes over enumerated states
|
||||
fn as_slice(&self) -> &[usize] {
|
||||
self.indices.as_slice()
|
||||
}
|
||||
// impl AsSlice for SysGraphMetadata {
|
||||
// /// Convert the slice of system-states to a slice of hashes over enumerated states
|
||||
// fn as_slice(&self) -> &[usize] {
|
||||
// self.indices.as_slice()
|
||||
// }
|
||||
|
||||
type Entry = usize;
|
||||
}
|
||||
// type Entry = usize;
|
||||
// }
|
||||
|
||||
impl HasRefCnt for SysGraphMetadata {
|
||||
fn refcnt(&self) -> isize {
|
||||
@ -169,8 +170,8 @@ impl HasRefCnt for SysGraphMetadata {
|
||||
|
||||
libafl_bolts::impl_serdeany!(SysGraphMetadata);
|
||||
|
||||
pub type GraphMaximizerCorpusScheduler<CS> =
|
||||
MinimizerScheduler<CS, MaxTimeFavFactor<<CS as UsesState>::State>,SysGraphMetadata>;
|
||||
pub type GraphMaximizerCorpusScheduler<CS, O> =
|
||||
MinimizerScheduler<CS, MaxTimeFavFactor<<CS as UsesState>::State>,SysGraphMetadata,O>;
|
||||
|
||||
//============================= Graph Feedback
|
||||
|
||||
@ -181,7 +182,7 @@ pub struct SysGraphFeedbackState
|
||||
pub graph: DiGraph<SysGraphNode, ()>,
|
||||
entrypoint: NodeIndex,
|
||||
exit: NodeIndex,
|
||||
name: String,
|
||||
name: Cow<'static, str>
|
||||
}
|
||||
impl SysGraphFeedbackState
|
||||
{
|
||||
@ -193,7 +194,7 @@ impl SysGraphFeedbackState
|
||||
exit.base.current_task.task_name="End".to_string();
|
||||
let entry = graph.add_node(entry);
|
||||
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>) {
|
||||
let mut current_index = self.entrypoint;
|
||||
@ -251,7 +252,7 @@ impl SysGraphFeedbackState
|
||||
impl Named for SysGraphFeedbackState
|
||||
{
|
||||
#[inline]
|
||||
fn name(&self) -> &str {
|
||||
fn name(&self) -> &Cow<'static, str> {
|
||||
&self.name
|
||||
}
|
||||
}
|
||||
@ -278,12 +279,12 @@ impl SysGraphFeedbackState
|
||||
#[derive(Serialize, Deserialize, Clone, Debug, Default)]
|
||||
pub struct SysMapFeedback
|
||||
{
|
||||
name: String,
|
||||
name: Cow<'static, str>,
|
||||
last_trace: Option<Vec<NodeIndex>>,
|
||||
}
|
||||
impl SysMapFeedback {
|
||||
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,
|
||||
None => {
|
||||
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()
|
||||
}
|
||||
};
|
||||
@ -324,7 +325,7 @@ where
|
||||
|
||||
/// Append to the testcase the generated metadata in case of a new corpus item
|
||||
#[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();
|
||||
match a {
|
||||
Some(s) => testcase.metadata_map_mut().insert(SysGraphMetadata::new(s)),
|
||||
@ -343,7 +344,7 @@ where
|
||||
impl Named for SysMapFeedback
|
||||
{
|
||||
#[inline]
|
||||
fn name(&self) -> &str {
|
||||
fn name(&self) -> &Cow<'static, str> {
|
||||
&self.name
|
||||
}
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ use libafl_qemu::Emulator;
|
||||
use libafl_qemu::GuestAddr;
|
||||
use libafl_qemu::GuestPhysAddr;
|
||||
use libafl_qemu::GuestReg;
|
||||
use libafl_qemu::Qemu;
|
||||
use libafl_qemu::QemuHooks;
|
||||
use libafl_qemu::edges::QemuEdgesMapMetadata;
|
||||
use libafl_qemu::emu;
|
||||
@ -26,7 +27,7 @@ use super::freertos;
|
||||
use super::CaptureEvent;
|
||||
|
||||
use libafl_qemu::{
|
||||
helper::{QemuHelper, QemuHelperTuple},
|
||||
helpers::{QemuHelper, QemuHelperTuple},
|
||||
// edges::SAVED_JUMP,
|
||||
};
|
||||
|
||||
@ -120,14 +121,14 @@ where
|
||||
}
|
||||
|
||||
// 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 {
|
||||
CURRENT_SYSTEMSTATE_VEC.clear();
|
||||
}
|
||||
}
|
||||
|
||||
fn post_exec<OT>(&mut self, emulator: &Emulator, _input: &S::Input, _observers: &mut OT, _exit_kind: &mut ExitKind) {
|
||||
trigger_collection(emulator,(0, 0), CaptureEvent::End, self);
|
||||
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);
|
||||
unsafe {
|
||||
let c = emulator.cpu_from_index(0);
|
||||
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 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]
|
||||
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 mut systemstate = RawFreeRTOSSystemState::default();
|
||||
|
||||
@ -272,7 +273,7 @@ where
|
||||
S: UsesInput,
|
||||
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 src = read_rec_return_stackframe(emulator, 0xfffffffc);
|
||||
trigger_collection(emulator, (src, pc), CaptureEvent::ISRStart, h);
|
||||
@ -324,7 +325,7 @@ where
|
||||
QT: QemuHelperTuple<S>,
|
||||
{
|
||||
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
|
||||
trigger_collection(emulator, (src, dest), CaptureEvent::APIStart, h);
|
||||
// println!("Exec API Call {:#x} {:#x} {}", src, dest, get_icount(emulator));
|
||||
@ -353,19 +354,19 @@ where
|
||||
|
||||
//============================= Utility functions
|
||||
|
||||
fn get_icount(emulator : &Emulator) -> u64 {
|
||||
fn get_icount(emulator : &libafl_qemu::Qemu) -> u64 {
|
||||
unsafe {
|
||||
// TODO: investigate why can_do_io is not set sometimes, as this is just a workaround
|
||||
let c = emulator.cpu_from_index(0);
|
||||
let can_do_io = (*c.raw_ptr()).neg.can_do_io;
|
||||
(*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;
|
||||
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;
|
||||
if lr_ == 0xfffffffc || lr_ == 0xFFFFFFF8 || lr_ == 0xFFFFFFF0 {
|
||||
unsafe {
|
||||
|
@ -242,14 +242,14 @@ where
|
||||
s.finish()
|
||||
}
|
||||
|
||||
impl AsSlice for FreeRTOSSystemStateMetadata {
|
||||
/// Convert the slice of system-states to a slice of hashes over enumerated states
|
||||
fn as_slice(&self) -> &[usize] {
|
||||
self.indices.as_slice()
|
||||
}
|
||||
// impl AsSlice for FreeRTOSSystemStateMetadata {
|
||||
// /// Convert the slice of system-states to a slice of hashes over enumerated states
|
||||
// fn as_slice(&self) -> &[usize] {
|
||||
// self.indices.as_slice()
|
||||
// }
|
||||
|
||||
type Entry = usize;
|
||||
}
|
||||
// type Entry = usize;
|
||||
// }
|
||||
|
||||
impl HasRefCnt for FreeRTOSSystemStateMetadata {
|
||||
fn refcnt(&self) -> isize {
|
||||
|
@ -12,6 +12,7 @@ use crate::systemstate::CaptureEvent;
|
||||
use std::rc::Rc;
|
||||
use std::cell::RefCell;
|
||||
use std::collections::VecDeque;
|
||||
use std::borrow::Cow;
|
||||
|
||||
use super::{ AtomicBasicBlock, ExecInterval};
|
||||
use super::{
|
||||
@ -26,7 +27,7 @@ use super::{
|
||||
|
||||
/// The Qemusystemstate Observer retrieves the systemstate
|
||||
/// that will get updated by the target.
|
||||
#[derive(Serialize, Deserialize, Debug, Default)]
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
#[allow(clippy::unsafe_derive_deserialize)]
|
||||
pub struct QemuSystemStateObserver
|
||||
{
|
||||
@ -35,7 +36,7 @@ pub struct QemuSystemStateObserver
|
||||
pub last_trace: Vec<ExecInterval>,
|
||||
pub last_input: Vec<u8>,
|
||||
pub success: bool,
|
||||
name: String,
|
||||
name: Cow<'static, str>,
|
||||
}
|
||||
|
||||
impl<S> Observer<S> for QemuSystemStateObserver
|
||||
@ -74,9 +75,8 @@ where
|
||||
|
||||
impl Named for QemuSystemStateObserver
|
||||
{
|
||||
#[inline]
|
||||
fn name(&self) -> &str {
|
||||
self.name.as_str()
|
||||
fn name(&self) -> &Cow<'static, str> {
|
||||
&self.name
|
||||
}
|
||||
}
|
||||
|
||||
@ -90,9 +90,13 @@ impl HasLen for QemuSystemStateObserver
|
||||
|
||||
impl QemuSystemStateObserver {
|
||||
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
|
||||
|
@ -11,7 +11,8 @@ use libafl::{
|
||||
corpus::{Corpus, Testcase},
|
||||
inputs::UsesInput,
|
||||
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,
|
||||
|
||||
};
|
||||
@ -39,7 +40,7 @@ impl LongestTracesMetadata {
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct LongestTraceScheduler<CS> {
|
||||
base: CS,
|
||||
skip_non_favored_prob: u64,
|
||||
skip_non_favored_prob: usize,
|
||||
}
|
||||
|
||||
impl<CS> UsesState for LongestTraceScheduler<CS>
|
||||
@ -102,7 +103,7 @@ where
|
||||
.metadata_map()
|
||||
.get::<STGNodeMetadata>().map_or(0, |x| x.nodes.len());
|
||||
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
|
||||
{
|
||||
idx = self.base.next(state)?;
|
||||
@ -130,7 +131,7 @@ where
|
||||
pub fn new(base: CS) -> Self {
|
||||
Self {
|
||||
base,
|
||||
skip_non_favored_prob: DEFAULT_SKIP_NON_FAVORED_PROB,
|
||||
skip_non_favored_prob: (DEFAULT_SKIP_NON_FAVORED_PROB * 100.0) as usize,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,17 +2,18 @@
|
||||
use hashbrown::HashSet;
|
||||
use libafl::SerdeAny;
|
||||
/// Feedbacks organizing SystemStates as a graph
|
||||
use libafl::inputs::HasBytesVec;
|
||||
// use libafl::inputs::HasBytesVec;
|
||||
use libafl_bolts::ownedref::OwnedMutSlice;
|
||||
use libafl_bolts::AsIter;
|
||||
use petgraph::graph::EdgeIndex;
|
||||
use std::fs;
|
||||
use libafl_bolts::rands::RandomSeed;
|
||||
use libafl_bolts::rands::random_seed;
|
||||
use libafl_bolts::rands::StdRand;
|
||||
use libafl::mutators::Mutator;
|
||||
use libafl::mutators::MutationResult;
|
||||
use libafl::prelude::HasTargetBytes;
|
||||
use libafl::prelude::UsesInput;
|
||||
use libafl::state::HasNamedMetadata;
|
||||
use libafl::common::HasNamedMetadata;
|
||||
use libafl::state::UsesState;
|
||||
use libafl::prelude::State;
|
||||
use petgraph::dot::Config;
|
||||
@ -40,9 +41,9 @@ use libafl::state::MaybeHasClientPerfMonitor;
|
||||
use libafl::feedbacks::Feedback;
|
||||
use libafl_bolts::Named;
|
||||
use libafl::Error;
|
||||
use libafl_qemu::edges::EDGES_MAP_SIZE;
|
||||
use libafl_qemu::edges::EDGES_MAP_SIZE_IN_USE;
|
||||
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 super::feedbacks::SystemStateFeedbackState;
|
||||
@ -63,6 +64,9 @@ use libafl_bolts::rands::Rand;
|
||||
use crate::clock::FUZZ_START_TIMESTAMP;
|
||||
use std::time::SystemTime;
|
||||
use std::{fs::OpenOptions, io::Write};
|
||||
use std::borrow::Cow;
|
||||
use std::ops::Deref;
|
||||
use std::ops::DerefMut;
|
||||
|
||||
//============================= Data Structures
|
||||
#[derive(Serialize, Deserialize, Clone, Debug, Default, Hash)]
|
||||
@ -144,6 +148,7 @@ impl STGEdge {
|
||||
#[derive(Debug, Serialize, Deserialize, SerdeAny, Clone)]
|
||||
pub struct STGFeedbackState
|
||||
{
|
||||
name: Cow<'static, str>,
|
||||
// aggregated traces as a graph
|
||||
pub graph: DiGraph<STGNode, STGEdge>,
|
||||
systemstate_index: HashMap<u64, ReducedFreeRTOSSystemState>,
|
||||
@ -179,6 +184,7 @@ impl Default for STGFeedbackState {
|
||||
let index = HashMap::from([(h_entry, entrypoint), (h_exit, exitpoint)]);
|
||||
|
||||
STGFeedbackState {
|
||||
name: Cow::from("stgfeedbackstate".to_string()),
|
||||
graph,
|
||||
stgnode_index: index,
|
||||
entrypoint,
|
||||
@ -196,8 +202,8 @@ impl Default for STGFeedbackState {
|
||||
impl Named for STGFeedbackState
|
||||
{
|
||||
#[inline]
|
||||
fn name(&self) -> &str {
|
||||
"stgfeedbackstate"
|
||||
fn name(&self) -> &Cow<'static, str> {
|
||||
&self.name
|
||||
}
|
||||
}
|
||||
|
||||
@ -238,13 +244,31 @@ impl STGNodeMetadata {
|
||||
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
|
||||
fn as_slice(&self) -> &[usize] {
|
||||
self.indices.as_slice()
|
||||
|
||||
// impl AsSlice for STGNodeMetadata {
|
||||
// /// Convert the slice of system-states to a slice of hashes over enumerated states
|
||||
// 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 {
|
||||
@ -259,8 +283,8 @@ impl HasRefCnt for STGNodeMetadata {
|
||||
|
||||
libafl_bolts::impl_serdeany!(STGNodeMetadata);
|
||||
|
||||
pub type GraphMaximizerCorpusScheduler<CS> =
|
||||
MinimizerScheduler<CS, MaxTimeFavFactor<<CS as UsesState>::State>,STGNodeMetadata>;
|
||||
pub type GraphMaximizerCorpusScheduler<CS, O> =
|
||||
MinimizerScheduler<CS, MaxTimeFavFactor<<CS as UsesState>::State>,STGNodeMetadata,O>;
|
||||
|
||||
// AI generated, human verified
|
||||
fn count_occurrences<T>(vec: &Vec<T>) -> HashMap<&T, usize>
|
||||
@ -294,7 +318,7 @@ where
|
||||
|
||||
//============================= 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 unsafe fn stg_map_mut_slice<'a>() -> OwnedMutSlice<'a, u16> {
|
||||
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)]
|
||||
pub struct StgFeedback
|
||||
{
|
||||
name: String,
|
||||
name: Cow<'static, str>,
|
||||
last_node_trace: Option<Vec<NodeIndex>>,
|
||||
last_edge_trace: Option<Vec<EdgeIndex>>,
|
||||
last_intervals: Option<Vec<ExecInterval>>,
|
||||
@ -468,7 +492,7 @@ where
|
||||
Some(s) => s,
|
||||
None => {
|
||||
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()
|
||||
}
|
||||
};
|
||||
@ -565,7 +589,7 @@ where
|
||||
|
||||
/// Append to the testcase the generated metadata in case of a new corpus item
|
||||
#[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 edges = self.last_edge_trace.take();
|
||||
match nodes {
|
||||
@ -584,7 +608,7 @@ where
|
||||
impl Named for StgFeedback
|
||||
{
|
||||
#[inline]
|
||||
fn name(&self) -> &str {
|
||||
fn name(&self) -> &Cow<'static, str> {
|
||||
&self.name
|
||||
}
|
||||
}
|
@ -17,7 +17,7 @@ use libafl::state::{MaybeHasClientPerfMonitor, HasCorpus, UsesState};
|
||||
use libafl::prelude::State;
|
||||
use libafl::inputs::Input;
|
||||
use libafl::feedbacks::Feedback;
|
||||
use libafl::state::HasMetadata;
|
||||
use libafl::common::HasMetadata;
|
||||
use libafl_qemu::edges::QemuEdgesMapMetadata;
|
||||
use libafl::observers::MapObserver;
|
||||
use serde::{Deserialize, Serialize};
|
||||
@ -35,10 +35,12 @@ use libafl::{
|
||||
|
||||
use crate::clock::QemuClockObserver;
|
||||
use crate::systemstate::FreeRTOSSystemStateMetadata;
|
||||
|
||||
use std::borrow::Cow;
|
||||
//=========================== Scheduler
|
||||
|
||||
pub type TimeMaximizerCorpusScheduler<CS> =
|
||||
MinimizerScheduler<CS, MaxTimeFavFactor<<CS as UsesState>::State>, MapIndexesMetadata>;
|
||||
pub type TimeMaximizerCorpusScheduler<CS, O> =
|
||||
MinimizerScheduler<CS, MaxTimeFavFactor<<CS as UsesState>::State>, MapIndexesMetadata, O>;
|
||||
|
||||
/// Multiply the testcase size with the execution time.
|
||||
/// This favors small and quick testcases.
|
||||
@ -64,11 +66,11 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pub type LenTimeMaximizerCorpusScheduler<CS> =
|
||||
MinimizerScheduler<CS, MaxExecsLenFavFactor<<CS as UsesState>::State>, MapIndexesMetadata>;
|
||||
pub type LenTimeMaximizerCorpusScheduler<CS, O> =
|
||||
MinimizerScheduler<CS, MaxExecsLenFavFactor<<CS as UsesState>::State>, MapIndexesMetadata, O>;
|
||||
|
||||
pub type TimeStateMaximizerCorpusScheduler<CS> =
|
||||
MinimizerScheduler<CS, MaxTimeFavFactor<<CS as UsesState>::State>, FreeRTOSSystemStateMetadata>;
|
||||
pub type TimeStateMaximizerCorpusScheduler<CS, O> =
|
||||
MinimizerScheduler<CS, MaxTimeFavFactor<<CS as UsesState>::State>, FreeRTOSSystemStateMetadata, O>;
|
||||
|
||||
/// Multiply the testcase size with the execution time.
|
||||
/// This favors small and quick testcases.
|
||||
@ -98,6 +100,7 @@ where
|
||||
/// A Feedback reporting if the Input consists of strictly decreasing bytes.
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
pub struct SortedFeedback {
|
||||
name: Cow<'static, str>
|
||||
}
|
||||
|
||||
impl<S> Feedback<S> for SortedFeedback
|
||||
@ -146,8 +149,8 @@ where
|
||||
|
||||
impl Named for SortedFeedback {
|
||||
#[inline]
|
||||
fn name(&self) -> &str {
|
||||
"Sorted"
|
||||
fn name(&self) -> &Cow<'static, str> {
|
||||
&self.name
|
||||
}
|
||||
}
|
||||
|
||||
@ -155,7 +158,7 @@ impl SortedFeedback {
|
||||
/// Creates a new [`HitFeedback`]
|
||||
#[must_use]
|
||||
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)]
|
||||
pub struct ExecTimeReachedFeedback
|
||||
{
|
||||
name: Cow<'static, str>,
|
||||
target_time: u64,
|
||||
}
|
||||
|
||||
@ -199,8 +203,8 @@ where
|
||||
impl Named for ExecTimeReachedFeedback
|
||||
{
|
||||
#[inline]
|
||||
fn name(&self) -> &str {
|
||||
"ExecTimeReachedFeedback"
|
||||
fn name(&self) -> &Cow<'static, str> {
|
||||
&self.name
|
||||
}
|
||||
}
|
||||
|
||||
@ -210,7 +214,7 @@ where
|
||||
/// Creates a new [`ExecTimeReachedFeedback`]
|
||||
#[must_use]
|
||||
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)]
|
||||
pub struct ExecTimeCollectorFeedback
|
||||
{
|
||||
name: Cow<'static, str>
|
||||
}
|
||||
|
||||
impl<S> Feedback<S> for ExecTimeCollectorFeedback
|
||||
@ -249,8 +254,8 @@ where
|
||||
impl Named for ExecTimeCollectorFeedback
|
||||
{
|
||||
#[inline]
|
||||
fn name(&self) -> &str {
|
||||
"ExecTimeCollectorFeedback"
|
||||
fn name(&self) -> &Cow<'static, str> {
|
||||
&self.name
|
||||
}
|
||||
}
|
||||
|
||||
@ -260,21 +265,27 @@ where
|
||||
/// Creates a new [`ExecTimeCollectorFeedback`]
|
||||
#[must_use]
|
||||
pub fn new() -> Self {
|
||||
Self {}
|
||||
Self {name: Cow::from("ExecTimeCollectorFeedback".to_string())}
|
||||
}
|
||||
}
|
||||
|
||||
/// Shared Metadata for a SysStateFeedback
|
||||
#[derive(Serialize, Deserialize, Clone, Debug, Default)]
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
pub struct ExecTimeCollectorFeedbackState
|
||||
{
|
||||
name: Cow<'static, str>,
|
||||
collection: Vec<u32>,
|
||||
}
|
||||
impl Named for ExecTimeCollectorFeedbackState
|
||||
{
|
||||
#[inline]
|
||||
fn name(&self) -> &str {
|
||||
"ExecTimeCollectorFeedbackState"
|
||||
fn name(&self) -> &Cow<'static, str> {
|
||||
&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)]
|
||||
pub struct ExecTimeIncFeedback
|
||||
{
|
||||
name: Cow<'static, str>,
|
||||
longest_time: u64,
|
||||
last_is_longest: bool
|
||||
}
|
||||
@ -315,9 +327,10 @@ where
|
||||
Ok(false)
|
||||
}
|
||||
}
|
||||
fn append_metadata<OT>(
|
||||
fn append_metadata<EM, OT>(
|
||||
&mut self,
|
||||
_state: &mut S,
|
||||
_manager: &mut EM,
|
||||
observers: &OT,
|
||||
testcase: &mut Testcase<<S as UsesInput>::Input>,
|
||||
) -> Result<(), Error> {
|
||||
@ -334,8 +347,8 @@ where
|
||||
impl Named for ExecTimeIncFeedback
|
||||
{
|
||||
#[inline]
|
||||
fn name(&self) -> &str {
|
||||
"ExecTimeReachedFeedback"
|
||||
fn name(&self) -> &Cow<'static, str> {
|
||||
&self.name
|
||||
}
|
||||
}
|
||||
|
||||
@ -345,7 +358,7 @@ where
|
||||
/// Creates a new [`ExecTimeReachedFeedback`]
|
||||
#[must_use]
|
||||
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)]
|
||||
pub struct AlwaysTrueFeedback
|
||||
{
|
||||
name: Cow<'static, str>
|
||||
}
|
||||
|
||||
impl<S> Feedback<S> for AlwaysTrueFeedback
|
||||
@ -379,8 +393,8 @@ where
|
||||
impl Named for AlwaysTrueFeedback
|
||||
{
|
||||
#[inline]
|
||||
fn name(&self) -> &str {
|
||||
"AlwaysTrueFeedback"
|
||||
fn name(&self) -> &Cow<'static, str> {
|
||||
&self.name
|
||||
}
|
||||
}
|
||||
|
||||
@ -391,6 +405,7 @@ where
|
||||
#[must_use]
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
name: Cow::from("AlwaysTrueFeedback".to_string())
|
||||
}
|
||||
}
|
||||
}
|
@ -16,9 +16,4 @@ extern_c_checked! {
|
||||
|
||||
pub fn icount_get_raw() -> u64;
|
||||
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;
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ use crate::{
|
||||
helpers::QemuHelperTuple,
|
||||
qemu::{MemAccessInfo, Qemu, SKIP_EXEC_HOOK},
|
||||
sys::TCGTemp,
|
||||
BackdoorHookId, BlockHookId, CmpHookId, EdgeHookId, HookId, InstructionHookId, ReadHookId,
|
||||
BackdoorHookId, BlockHookId, CmpHookId, EdgeHookId, HookId, InstructionHookId, ReadHookId, JmpHookId,
|
||||
WriteHookId,
|
||||
};
|
||||
#[cfg(emulation_mode = "usermode")]
|
||||
@ -370,9 +370,9 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
static mut JMP_HOOKS: Vec<HookState<1>> = vec![];
|
||||
create_gen_wrapper!(jmp, (src: GuestAddr, dest: GuestAddr), u64, 1);
|
||||
create_exec_wrapper!(jmp, (src: GuestAddr, dst: GuestAddr, id: u64), 0, 1);
|
||||
static mut JMP_HOOKS: Vec<Pin<Box<HookState<1, JmpHookId>>>> = vec![];
|
||||
create_gen_wrapper!(jmp, (src: GuestAddr, dest: GuestAddr), u64, 1, JmpHookId);
|
||||
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)>,
|
||||
extern "C" fn(*const (), src: GuestAddr, dest: GuestAddr, id: u64),
|
||||
>,
|
||||
) -> HookId {
|
||||
) -> JmpHookId {
|
||||
unsafe {
|
||||
let gen = get_raw_hook!(
|
||||
generation_hook,
|
||||
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!(
|
||||
execution_hook,
|
||||
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 {
|
||||
id: HookId(0),
|
||||
JMP_HOOKS.push(Box::pin(HookState {
|
||||
id: JmpHookId(0),
|
||||
gen: hook_to_repr!(generation_hook),
|
||||
post_gen: HookRepr::Empty,
|
||||
execs: [hook_to_repr!(execution_hook)],
|
||||
});
|
||||
}));
|
||||
let id = self
|
||||
.emulator
|
||||
.add_jmp_hooks(JMP_HOOKS.last_mut().unwrap(), gen, exec);
|
||||
JMP_HOOKS.last_mut().unwrap().id = id;
|
||||
.qemu
|
||||
.add_jmp_hooks(JMP_HOOKS.last_mut().unwrap().as_mut().get_unchecked_mut(),
|
||||
gen,
|
||||
exec
|
||||
);
|
||||
JMP_HOOKS
|
||||
.last_mut()
|
||||
.unwrap()
|
||||
.as_mut()
|
||||
.get_unchecked_mut()
|
||||
.id = id;
|
||||
id
|
||||
}
|
||||
}
|
||||
|
@ -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!(PostSyscall, libafl_qemu_remove_post_syscall_hook, false);
|
||||
create_hook_id!(NewThread, libafl_qemu_remove_new_thread_hook, false);
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
create_hook_id!(Jmp, libafl_qemu_remove_jmp_hook, true);
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum QemuInitError {
|
||||
@ -251,7 +236,7 @@ pub struct MemAccessInfo {
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
#[repr(transparent)]
|
||||
pub struct CPU {
|
||||
ptr: CPUStatePtr,
|
||||
pub ptr: CPUStatePtr,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
@ -1028,6 +1013,22 @@ impl Qemu {
|
||||
pub fn host_page_size(&self) -> usize {
|
||||
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 {
|
||||
|
@ -8,9 +8,7 @@ use std::{
|
||||
|
||||
use bytes_utils::SegmentedBuf;
|
||||
use libafl_qemu_sys::{
|
||||
libafl_load_qemu_snapshot, libafl_page_from_addr, libafl_qemu_current_paging_id,
|
||||
libafl_save_qemu_snapshot, qemu_cleanup, qemu_main_loop, vm_start, GuestAddr, GuestPhysAddr,
|
||||
GuestUsize, GuestVirtAddr,
|
||||
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
|
||||
};
|
||||
use num_traits::Zero;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user