update to 0.13.0 API
This commit is contained in:
parent
df7333b764
commit
5fad373199
@ -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))}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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();
|
||||||
|
@ -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>
|
||||||
|
@ -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"))]
|
||||||
|
@ -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}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -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);
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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 {
|
||||||
|
@ -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 {
|
||||||
|
@ -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
|
||||||
|
@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -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())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -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;
|
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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 {
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user