configurable interrupt sources
This commit is contained in:
parent
288abeb6bf
commit
740ce09d31
@ -1,33 +1,34 @@
|
|||||||
kernel,main_function,input_symbol,input_size,return_function,select_task
|
kernel,main_function,input_symbol,input_size,return_function,select_task,interrupts
|
||||||
mpeg2,mpeg2_main,mpeg2_oldorgframe,90112,mpeg2_return,NONE
|
mpeg2,mpeg2_main,mpeg2_oldorgframe,90112,mpeg2_return,NONE,0#1000
|
||||||
audiobeam,audiobeam_main,audiobeam_input,11520,audiobeam_return,NONE
|
audiobeam,audiobeam_main,audiobeam_input,11520,audiobeam_return,NONE,0#1000
|
||||||
epic,epic_main,epic_image,4096,epic_return,NONE
|
epic,epic_main,epic_image,4096,epic_return,NONE,0#1000
|
||||||
dijkstra,dijkstra_main,dijkstra_AdjMatrix,10000,dijkstra_return,NONE
|
dijkstra,dijkstra_main,dijkstra_AdjMatrix,10000,dijkstra_return,NONE,0#1000
|
||||||
fft,fft_main,fft_twidtable,2046,fft_return,NONE
|
fft,fft_main,fft_twidtable,2046,fft_return,NONE,0#1000
|
||||||
bsort,bsort_main,bsort_Array,400,bsort_return,NONE
|
bsort,bsort_main,bsort_Array,400,bsort_return,NONE,0#1000
|
||||||
insertsort,insertsort_main,insertsort_a,400,insertsort_return,NONE
|
insertsort,insertsort_main,insertsort_a,400,insertsort_return,NONE,0#1000
|
||||||
g723_enc,g723_enc_main,g723_enc_INPUT,1024,g723_enc_return,NONE
|
g723_enc,g723_enc_main,g723_enc_INPUT,1024,g723_enc_return,NONE,0#1000
|
||||||
rijndael_dec,rijndael_dec_main,rijndael_dec_data,32768,rijndael_dec_return,NONE
|
rijndael_dec,rijndael_dec_main,rijndael_dec_data,32768,rijndael_dec_return,NONE,0#1000
|
||||||
rijndael_enc,rijndael_enc_main,rijndael_enc_data,31369,rijndael_enc_return,NONE
|
rijndael_enc,rijndael_enc_main,rijndael_enc_data,31369,rijndael_enc_return,NONE,0#1000
|
||||||
huff_dec,huff_dec_main,huff_dec_encoded,419,huff_dec_return,NONE
|
huff_dec,huff_dec_main,huff_dec_encoded,419,huff_dec_return,NONE,0#1000
|
||||||
huff_enc,huff_enc_main,huff_enc_plaintext,600,huff_enc_return,NONE
|
huff_enc,huff_enc_main,huff_enc_plaintext,600,huff_enc_return,NONE,0#1000
|
||||||
gsm_enc,gsm_enc_main,gsm_enc_pcmdata,6400,gsm_enc_return,NONE
|
gsm_enc,gsm_enc_main,gsm_enc_pcmdata,6400,gsm_enc_return,NONE,0#1000
|
||||||
tmr,main,FUZZ_INPUT,32,trigger_Qemu_break,NONE
|
tmr,main,FUZZ_INPUT,32,trigger_Qemu_break,NONE,0#1000
|
||||||
tacle_rtos,prvStage0,FUZZ_INPUT,604,trigger_Qemu_break,NONE
|
tacle_rtos,prvStage0,FUZZ_INPUT,604,trigger_Qemu_break,NONE,0#1000
|
||||||
lift,main_lift,FUZZ_INPUT,100,trigger_Qemu_break,NONE
|
lift,main_lift,FUZZ_INPUT,100,trigger_Qemu_break,NONE,0#1000
|
||||||
waters,main_waters,FUZZ_INPUT,4096,trigger_Qemu_break,1129
|
waters,main_waters,FUZZ_INPUT,4096,trigger_Qemu_break,1129,0#1000
|
||||||
watersv2,main_waters,FUZZ_INPUT,4096,trigger_Qemu_break,1129
|
watersv2,main_waters,FUZZ_INPUT,4096,trigger_Qemu_break,1129,0#1000
|
||||||
waterspart,main_waters,FUZZ_INPUT,4096,trigger_Qemu_break,1129
|
waterspart,main_waters,FUZZ_INPUT,4096,trigger_Qemu_break,1129,0#1000
|
||||||
waterspartv2,main_waters,FUZZ_INPUT,4096,trigger_Qemu_break,1129
|
waterspartv2,main_waters,FUZZ_INPUT,4096,trigger_Qemu_break,1129,0#1000
|
||||||
waters_int,main_waters,FUZZ_INPUT,4096,trigger_Qemu_break,1129
|
waters_int,main_waters,FUZZ_INPUT,4096,trigger_Qemu_break,1129,0#1000
|
||||||
watersv2_int,main_waters,FUZZ_INPUT,4096,trigger_Qemu_break,1129
|
watersv2_int,main_waters,FUZZ_INPUT,4096,trigger_Qemu_break,1129,0#1000
|
||||||
waterspart_int,main_waters,FUZZ_INPUT,4096,trigger_Qemu_break,1129
|
waterspart_int,main_waters,FUZZ_INPUT,4096,trigger_Qemu_break,1129,0#1000
|
||||||
waterspartv2_int,main_waters,FUZZ_INPUT,4096,trigger_Qemu_break,1129
|
waterspartv2_int,main_waters,FUZZ_INPUT,4096,trigger_Qemu_break,1129,0#1000
|
||||||
micro_branchless,main_branchless,FUZZ_INPUT,4,trigger_Qemu_break,NONE
|
micro_branchless,main_branchless,FUZZ_INPUT,4,trigger_Qemu_break,NONE,0#1000
|
||||||
micro_int,main_int,FUZZ_INPUT,16,trigger_Qemu_break,NONE
|
micro_int,main_int,FUZZ_INPUT,16,trigger_Qemu_break,NONE,0#1000
|
||||||
micro_longint,main_micro_longint,FUZZ_INPUT,16,trigger_Qemu_break,NONE
|
micro_longint,main_micro_longint,FUZZ_INPUT,16,trigger_Qemu_break,NONE,0#1000
|
||||||
minimal,main_minimal,FUZZ_INPUT,4096,trigger_Qemu_break,NONE
|
minimal,main_minimal,FUZZ_INPUT,4096,trigger_Qemu_break,NONE,0#1000
|
||||||
gen3,main_minimal,FUZZ_INPUT,4096,trigger_Qemu_break,NONE
|
gen3,main_minimal,FUZZ_INPUT,4096,trigger_Qemu_break,NONE,0#1000
|
||||||
interact,main_interact,FUZZ_INPUT,4096,trigger_Qemu_break,NONE
|
interact,main_interact,FUZZ_INPUT,4096,trigger_Qemu_break,NONE,0#1000
|
||||||
interact_int,main_interact,FUZZ_INPUT,4096,trigger_Qemu_break,NONE
|
interact_int,main_interact,FUZZ_INPUT,4096,trigger_Qemu_break,NONE,0#1000
|
||||||
release,main_release,FUZZ_INPUT,4096,trigger_Qemu_break,T3
|
release,main_release,FUZZ_INPUT,4096,trigger_Qemu_break,T3,0#10000;1#1000;2#2000;3#3000
|
||||||
|
|
||||||
|
|
@ -90,3 +90,26 @@ pub fn set_env_from_config(kernel : &PathBuf, path : &PathBuf) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_interrupt_config(kernel : &PathBuf, path : &PathBuf) -> Vec<(usize,u32)>{
|
||||||
|
let is_csv = path.as_path().extension().map_or(false, |x| x=="csv");
|
||||||
|
if !is_csv {
|
||||||
|
panic!("Interrupt config must be inside a CSV file");
|
||||||
|
} else {
|
||||||
|
let mut reader = csv::Reader::from_path(path).expect("CSV read from config failed");
|
||||||
|
let p = kernel.as_path();
|
||||||
|
let stem = p.file_stem().expect("Kernel filename error").to_str().unwrap();
|
||||||
|
for r in reader.records() {
|
||||||
|
let rec = r.expect("CSV entry error");
|
||||||
|
if stem == &rec[0] {
|
||||||
|
let ret = rec[6].split(';').map(|x| {
|
||||||
|
let pair = x.split_once('#').expect("Interrupt config error");
|
||||||
|
(pair.0.parse().expect("Interrupt config error"), pair.1.parse().expect("Interrupt config error"))
|
||||||
|
}).collect();
|
||||||
|
println!("Interrupt config {:?}", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Vec::new();
|
||||||
|
}
|
@ -21,7 +21,7 @@ use crate::{
|
|||||||
qemustate::QemuStateRestoreHelper
|
qemustate::QemuStateRestoreHelper
|
||||||
},
|
},
|
||||||
systemstate::{self, feedbacks::{DumpSystraceFeedback, SystraceErrorFeedback}, helpers::{get_function_range, load_symbol, try_load_symbol, QemuSystemStateHelper}, observers::QemuSystemStateObserver, schedulers::{GenerationScheduler, LongestTraceScheduler}, stg::{stg_map_mut_slice, GraphMaximizerCorpusScheduler, STGEdge, STGNode, StgFeedback, MAX_STG_NUM}},
|
systemstate::{self, feedbacks::{DumpSystraceFeedback, SystraceErrorFeedback}, helpers::{get_function_range, load_symbol, try_load_symbol, QemuSystemStateHelper}, observers::QemuSystemStateObserver, schedulers::{GenerationScheduler, LongestTraceScheduler}, stg::{stg_map_mut_slice, GraphMaximizerCorpusScheduler, STGEdge, STGNode, StgFeedback, MAX_STG_NUM}},
|
||||||
systemstate::mutational::{input_bytes_to_interrupt_times, InterruptShiftStage, MINIMUM_INTER_ARRIVAL_TIME},
|
systemstate::mutational::{input_bytes_to_interrupt_times, InterruptShiftStage},
|
||||||
};
|
};
|
||||||
use std::time::SystemTime;
|
use std::time::SystemTime;
|
||||||
use petgraph::dot::Dot;
|
use petgraph::dot::Dot;
|
||||||
@ -164,6 +164,7 @@ log::set_max_level(log::LevelFilter::Info);
|
|||||||
SimpleStderrLogger::set_logger().unwrap();
|
SimpleStderrLogger::set_logger().unwrap();
|
||||||
let cli = Cli::parse();
|
let cli = Cli::parse();
|
||||||
set_env_from_config(&cli.kernel, &cli.config);
|
set_env_from_config(&cli.kernel, &cli.config);
|
||||||
|
let interrupt_config = crate::cli::get_interrupt_config(&cli.kernel, &cli.config);
|
||||||
unsafe {FUZZ_START_TIMESTAMP = SystemTime::now();}
|
unsafe {FUZZ_START_TIMESTAMP = SystemTime::now();}
|
||||||
if cli.dump_name.is_none() && (cli.dump_times || cli.dump_cases || cli.dump_traces || cli.dump_graph) {
|
if cli.dump_name.is_none() && (cli.dump_times || cli.dump_cases || cli.dump_traces || cli.dump_graph) {
|
||||||
panic!("Dump name not give but dump is requested");
|
panic!("Dump name not give but dump is requested");
|
||||||
@ -272,6 +273,18 @@ let api_ranges : Vec<_> = api_ranges.into_iter().collect();
|
|||||||
#[cfg(feature = "observe_systemstate")]
|
#[cfg(feature = "observe_systemstate")]
|
||||||
let isr_ranges : Vec<_> = isr_ranges.into_iter().collect();
|
let isr_ranges : Vec<_> = isr_ranges.into_iter().collect();
|
||||||
|
|
||||||
|
/// Setup the interrupt inputs. Noop if interrupts are not fuzzed
|
||||||
|
fn setup_interrupt_inputs(mut input : MultipartInput<BytesInput>, interrupt_config : &Vec<(usize,u32)>) -> MultipartInput<BytesInput> {
|
||||||
|
#[cfg(feature = "fuzz_int")]
|
||||||
|
for (i,_) in interrupt_config {
|
||||||
|
let name = format!("interrupts_{}",i);
|
||||||
|
if input.parts_by_name(&name).next().is_none() {
|
||||||
|
input.add_part(name, BytesInput::new([0; MAX_NUM_INTERRUPT*4].to_vec()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
input
|
||||||
|
}
|
||||||
|
|
||||||
// Client setup ================================================================================
|
// Client setup ================================================================================
|
||||||
|
|
||||||
let run_client = |state: Option<_>, mut mgr, _core_id| {
|
let run_client = |state: Option<_>, mut mgr, _core_id| {
|
||||||
@ -331,10 +344,14 @@ let run_client = |state: Option<_>, mut mgr, _core_id| {
|
|||||||
unsafe {
|
unsafe {
|
||||||
#[cfg(feature = "fuzz_int")]
|
#[cfg(feature = "fuzz_int")]
|
||||||
{
|
{
|
||||||
let time_bytes = input.parts_by_name("interrupts").next().map(|x| x.1.bytes()).unwrap_or(&[0u8; MAX_NUM_INTERRUPT*4]);
|
for &c in &interrupt_config {
|
||||||
let t = input_bytes_to_interrupt_times(time_bytes);
|
let (i,_) = c;
|
||||||
for i in 0..t.len() {libafl_interrupt_offsets[0][i]=t[i];}
|
let name = format!("interrupts_{}",i);
|
||||||
libafl_num_interrupts[0]=t.len();
|
let input_bytes = input.parts_by_name(&name).next().map(|x| x.1.bytes()).unwrap_or(&[0u8; MAX_NUM_INTERRUPT*4]);
|
||||||
|
let t = input_bytes_to_interrupt_times(input_bytes, c);
|
||||||
|
for j in 0..t.len() {libafl_interrupt_offsets[i][j]=t[j];}
|
||||||
|
libafl_num_interrupts[i]=t.len();
|
||||||
|
}
|
||||||
|
|
||||||
// println!("Load: {:?}", libafl_interrupt_offsets[0..libafl_num_interrupts].to_vec());
|
// println!("Load: {:?}", libafl_interrupt_offsets[0..libafl_num_interrupts].to_vec());
|
||||||
}
|
}
|
||||||
@ -502,7 +519,7 @@ let run_client = |state: Option<_>, mut mgr, _core_id| {
|
|||||||
let stages = (systemstate::report::SchedulerStatsStage::default(),());
|
let stages = (systemstate::report::SchedulerStatsStage::default(),());
|
||||||
let mut stages = (StdMutationalStage::new(mutator), stages);
|
let mut stages = (StdMutationalStage::new(mutator), stages);
|
||||||
#[cfg(feature = "fuzz_int")]
|
#[cfg(feature = "fuzz_int")]
|
||||||
let mut stages = (InterruptShiftStage::new(), stages);
|
let mut stages = (InterruptShiftStage::new(&interrupt_config), stages);
|
||||||
|
|
||||||
if let Commands::Showmap { input } = cli.command.clone() {
|
if let Commands::Showmap { input } = cli.command.clone() {
|
||||||
let s = input.as_os_str();
|
let s = input.as_os_str();
|
||||||
@ -519,7 +536,7 @@ let run_client = |state: Option<_>, mut mgr, _core_id| {
|
|||||||
Ok(x) => x,
|
Ok(x) => x,
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
println!("Interpreting input file as raw input");
|
println!("Interpreting input file as raw input");
|
||||||
MultipartInput::from([("interrupts",BytesInput::new([0; MAX_NUM_INTERRUPT].to_vec())),("bytes",BytesInput::new(input.as_os_str().as_encoded_bytes().to_vec()))])
|
setup_interrupt_inputs(MultipartInput::from([("bytes",BytesInput::new(input.as_os_str().as_encoded_bytes().to_vec()))]), &interrupt_config)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
fuzzer.evaluate_input(&mut state, &mut executor, &mut mgr, show_input)
|
fuzzer.evaluate_input(&mut state, &mut executor, &mut mgr, show_input)
|
||||||
@ -533,7 +550,7 @@ let run_client = |state: Option<_>, mut mgr, _core_id| {
|
|||||||
for _ in 0..100 {
|
for _ in 0..100 {
|
||||||
let inp1 = BytesInput::new(vec![rng.gen::<u8>(); MAX_NUM_INTERRUPT*4]);
|
let inp1 = BytesInput::new(vec![rng.gen::<u8>(); MAX_NUM_INTERRUPT*4]);
|
||||||
let inp2 = BytesInput::new(vec![rng.gen::<u8>(); MAX_INPUT_SIZE]);
|
let inp2 = BytesInput::new(vec![rng.gen::<u8>(); MAX_INPUT_SIZE]);
|
||||||
let inp = MultipartInput::from([("interrupts",inp1),("bytes",inp2)]);
|
let inp = setup_interrupt_inputs(MultipartInput::from([("bytes",inp2)]), &interrupt_config);
|
||||||
fuzzer.evaluate_input(&mut state, &mut executor, &mut mgr, inp).unwrap();
|
fuzzer.evaluate_input(&mut state, &mut executor, &mut mgr, inp).unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -576,7 +593,7 @@ let run_client = |state: Option<_>, mut mgr, _core_id| {
|
|||||||
// libafl's generator is too slow
|
// libafl's generator is too slow
|
||||||
let inp1 = BytesInput::new(vec![rng.gen::<u8>(); MAX_NUM_INTERRUPT*4]);
|
let inp1 = BytesInput::new(vec![rng.gen::<u8>(); MAX_NUM_INTERRUPT*4]);
|
||||||
let inp2 = BytesInput::new(vec![rng.gen::<u8>(); MAX_INPUT_SIZE]);
|
let inp2 = BytesInput::new(vec![rng.gen::<u8>(); MAX_INPUT_SIZE]);
|
||||||
let inp = MultipartInput::from([("interrupts",inp1),("bytes",inp2)]);
|
let inp = setup_interrupt_inputs(MultipartInput::from([("bytes",inp2)]), &interrupt_config);
|
||||||
fuzzer.evaluate_input(&mut state, &mut executor, &mut mgr, inp).unwrap();
|
fuzzer.evaluate_input(&mut state, &mut executor, &mut mgr, inp).unwrap();
|
||||||
}
|
}
|
||||||
}} else {
|
}} else {
|
||||||
|
@ -19,13 +19,13 @@ use std::borrow::Cow;
|
|||||||
|
|
||||||
use super::stg::{STGEdge, STGNode};
|
use super::stg::{STGEdge, STGNode};
|
||||||
|
|
||||||
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
|
||||||
// virtual insn/sec 62500000 = 1/16 GHz
|
// virtual insn/sec 62500000 = 1/16 GHz
|
||||||
// 1ms = 62500 insn
|
// 1ms = 62500 insn
|
||||||
// 1us = 62.5 insn
|
// 1us = 62.5 insn
|
||||||
|
|
||||||
pub fn input_bytes_to_interrupt_times(buf: &[u8]) -> Vec<u32> {
|
pub fn input_bytes_to_interrupt_times(buf: &[u8], config: (usize,u32)) -> Vec<u32> {
|
||||||
let len = buf.len();
|
let len = buf.len();
|
||||||
let mut start_tick : u32 = 0;
|
let mut start_tick : u32 = 0;
|
||||||
let mut ret = Vec::with_capacity(DO_NUM_INTERRUPT);
|
let mut ret = Vec::with_capacity(DO_NUM_INTERRUPT);
|
||||||
@ -45,8 +45,8 @@ pub fn input_bytes_to_interrupt_times(buf: &[u8]) -> Vec<u32> {
|
|||||||
for i in 0..ret.len() {
|
for i in 0..ret.len() {
|
||||||
if ret[i]==0 {continue;}
|
if ret[i]==0 {continue;}
|
||||||
for j in i+1..ret.len()-1 {
|
for j in i+1..ret.len()-1 {
|
||||||
if ret[j]-ret[i] < unsafe{MINIMUM_INTER_ARRIVAL_TIME} {
|
if ret[j]-ret[i] < config.1 as u32 * QEMU_ISNS_PER_USEC {
|
||||||
ret[j] = u32::saturating_add(ret[i],unsafe{MINIMUM_INTER_ARRIVAL_TIME});
|
ret[j] = u32::saturating_add(ret[i],config.1 * QEMU_ISNS_PER_USEC);
|
||||||
} else {break;}
|
} else {break;}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -70,11 +70,11 @@ fn is_candidate_for_new_branches(graph: &DiGraph<STGNode, STGEdge>, node: NodeIn
|
|||||||
|
|
||||||
// TODO: this can be much more efficient, if the graph stored snapshots of the state and input progress was tracked
|
// TODO: this can be much more efficient, if the graph stored snapshots of the state and input progress was tracked
|
||||||
/// Determines if a given node in the state transition graph (STG) is a candidate for introducing new branches.
|
/// Determines if a given node in the state transition graph (STG) is a candidate for introducing new branches.
|
||||||
pub fn try_force_new_branches(interrupt_ticks : &[u32], fbs: &STGFeedbackState, meta: &STGNodeMetadata) -> Option<Vec<u32>> {
|
pub fn try_force_new_branches(interrupt_ticks : &[u32], fbs: &STGFeedbackState, meta: &STGNodeMetadata, config: (usize, u32)) -> Option<Vec<u32>> {
|
||||||
let mut new = false;
|
let mut new = false;
|
||||||
let mut new_interrupt_times = Vec::new();
|
let mut new_interrupt_times = Vec::new();
|
||||||
for (num,&interrupt_time) in interrupt_ticks.iter().enumerate() {
|
for (num,&interrupt_time) in interrupt_ticks.iter().enumerate() {
|
||||||
let lower_bound = if num==0 {FIRST_INT} else {interrupt_ticks[num-1].saturating_add(unsafe{MINIMUM_INTER_ARRIVAL_TIME})};
|
let lower_bound = if num==0 {FIRST_INT} else {interrupt_ticks[num-1].saturating_add(config.1 * QEMU_ISNS_PER_USEC)};
|
||||||
let next = if interrupt_ticks.len()>num {interrupt_ticks[num+1]} else {u32::MAX};
|
let next = if interrupt_ticks.len()>num {interrupt_ticks[num+1]} else {u32::MAX};
|
||||||
for exec_interval in meta.intervals.iter().filter(|x| x.start_tick >= lower_bound as u64 && x.start_tick < next as u64) {
|
for exec_interval in meta.intervals.iter().filter(|x| x.start_tick >= lower_bound as u64 && x.start_tick < next as u64) {
|
||||||
if !(exec_interval.start_capture.0==CaptureEvent::ISRStart) { // shortcut to skip interrupt handers without node lookup
|
if !(exec_interval.start_capture.0==CaptureEvent::ISRStart) { // shortcut to skip interrupt handers without node lookup
|
||||||
@ -98,6 +98,7 @@ pub fn try_force_new_branches(interrupt_ticks : &[u32], fbs: &STGFeedbackState,
|
|||||||
pub struct InterruptShiftStage<E, EM, Z> {
|
pub struct InterruptShiftStage<E, EM, Z> {
|
||||||
#[allow(clippy::type_complexity)]
|
#[allow(clippy::type_complexity)]
|
||||||
phantom: PhantomData<(E, EM, Z)>,
|
phantom: PhantomData<(E, EM, Z)>,
|
||||||
|
interrup_config: Vec<(usize,u32)>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E, EM, Z> InterruptShiftStage<E, EM, Z>
|
impl<E, EM, Z> InterruptShiftStage<E, EM, Z>
|
||||||
@ -107,8 +108,8 @@ where
|
|||||||
Z: Evaluator<E, EM>,
|
Z: Evaluator<E, EM>,
|
||||||
Z::State: MaybeHasClientPerfMonitor + HasCorpus + HasRand,
|
Z::State: MaybeHasClientPerfMonitor + HasCorpus + HasRand,
|
||||||
{
|
{
|
||||||
pub fn new() -> Self {
|
pub fn new(config : &Vec<(usize,u32)>) -> Self {
|
||||||
Self { phantom: PhantomData }
|
Self { phantom: PhantomData, interrup_config: config.clone() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,20 +134,26 @@ where
|
|||||||
let mut myrand = StdRand::new();
|
let mut myrand = StdRand::new();
|
||||||
myrand.set_seed(state.rand_mut().next());
|
myrand.set_seed(state.rand_mut().next());
|
||||||
|
|
||||||
|
|
||||||
let mut loopcount = 0;
|
let mut loopcount = 0;
|
||||||
let mut loopbound = 50;
|
let mut loopbound = 50;
|
||||||
loop {
|
loop {
|
||||||
|
let interrup_config = match myrand.choose(&self.interrup_config) {
|
||||||
|
Some(s) => s,
|
||||||
|
Option::None => return Ok(())
|
||||||
|
};
|
||||||
|
let name = format!("interrupts_{}", interrup_config.0);
|
||||||
// manager.log(state, LogSeverity::Info, format!("Mutation {}/{}", loopbound, loopcount))?;
|
// manager.log(state, LogSeverity::Info, format!("Mutation {}/{}", loopbound, loopcount))?;
|
||||||
loopbound-=1;
|
loopbound-=1;
|
||||||
let current_case = state.current_testcase()?;
|
let current_case = state.current_testcase()?;
|
||||||
let old_input = current_case.input().as_ref().unwrap();
|
let old_input = current_case.input().as_ref().unwrap();
|
||||||
let old_interrupt_times = old_input.parts_by_name("interrupts").next();
|
let old_interrupt_times = old_input.parts_by_name(&name).next();
|
||||||
let mut new_input = old_input.clone();
|
let mut new_input = old_input.clone();
|
||||||
|
|
||||||
let mut new_interrupt_times : &mut I = if new_input.parts_by_name("interrupts").next().is_some() {
|
let mut new_interrupt_times : &mut I = if new_input.parts_by_name(&name).next().is_some() {
|
||||||
new_input.parts_by_name_mut("interrupts").next().unwrap()
|
new_input.parts_by_name_mut(&name).next().unwrap()
|
||||||
} else {
|
} else {
|
||||||
new_input.add_part(String::from("interrupts"), I::default()); new_input.parts_by_name_mut("interrupts").next().unwrap()
|
new_input.add_part(String::from(&name), I::default()); new_input.parts_by_name_mut(&name).next().unwrap()
|
||||||
}.1;
|
}.1;
|
||||||
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
|
||||||
@ -156,7 +163,7 @@ where
|
|||||||
let mut interrupt_offsets : [u32; MAX_NUM_INTERRUPT] = [u32::MAX; MAX_NUM_INTERRUPT];
|
let mut interrupt_offsets : [u32; MAX_NUM_INTERRUPT] = [u32::MAX; MAX_NUM_INTERRUPT];
|
||||||
let mut num_interrupts : usize = 0;
|
let mut num_interrupts : usize = 0;
|
||||||
{
|
{
|
||||||
let t = input_bytes_to_interrupt_times(new_interrupt_times.bytes());
|
let t = input_bytes_to_interrupt_times(new_interrupt_times.bytes(), *interrup_config);
|
||||||
for i in 0..t.len() {interrupt_offsets[i]=t[i];}
|
for i in 0..t.len() {interrupt_offsets[i]=t[i];}
|
||||||
num_interrupts=t.len();
|
num_interrupts=t.len();
|
||||||
}
|
}
|
||||||
@ -180,7 +187,7 @@ where
|
|||||||
let maxtick : u64 = hist.1.0;
|
let maxtick : u64 = hist.1.0;
|
||||||
// let maxtick : u64 = (_input.exec_time().expect("No duration found").as_nanos() >> 4).try_into().unwrap();
|
// let maxtick : u64 = (_input.exec_time().expect("No duration found").as_nanos() >> 4).try_into().unwrap();
|
||||||
let mut numbers : Vec<u32> = vec![];
|
let mut numbers : Vec<u32> = vec![];
|
||||||
for i in 0..myrand.between(0,2*min(MAX_NUM_INTERRUPT, maxtick as usize / unsafe{MINIMUM_INTER_ARRIVAL_TIME as usize})) {
|
for i in 0..myrand.between(0,2*min(MAX_NUM_INTERRUPT, maxtick as usize / (interrup_config.1 as usize * QEMU_ISNS_PER_USEC as usize))) {
|
||||||
prefix.push(u32::to_le_bytes(myrand.between(0, min(maxtick, u32::MAX as u64) as usize).try_into().expect("ticks > u32")));
|
prefix.push(u32::to_le_bytes(myrand.between(0, min(maxtick, u32::MAX as u64) as usize).try_into().expect("ticks > u32")));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -194,7 +201,7 @@ where
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
if let Some(meta) = current_case.metadata_map().get::<STGNodeMetadata>() {
|
if let Some(meta) = current_case.metadata_map().get::<STGNodeMetadata>() {
|
||||||
if let Some(t) = try_force_new_branches(&interrupt_offsets, feedbackstate, meta) {
|
if let Some(t) = try_force_new_branches(&interrupt_offsets, feedbackstate, meta, *interrup_config) {
|
||||||
do_rerun = true;
|
do_rerun = true;
|
||||||
for i in 0..t.len() {
|
for i in 0..t.len() {
|
||||||
if i<num_interrupts {
|
if i<num_interrupts {
|
||||||
@ -280,10 +287,10 @@ where
|
|||||||
let mut lb = FIRST_INT;
|
let mut lb = FIRST_INT;
|
||||||
let mut ub : u32 = marks[marks.len()-1].0.end_tick.try_into().expect("ticks > u32");
|
let mut ub : u32 = marks[marks.len()-1].0.end_tick.try_into().expect("ticks > u32");
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
lb = u32::saturating_add(interrupt_offsets[i-1],unsafe{MINIMUM_INTER_ARRIVAL_TIME});
|
lb = u32::saturating_add(interrupt_offsets[i-1], interrup_config.1 * QEMU_ISNS_PER_USEC);
|
||||||
}
|
}
|
||||||
if i < num_interrupts-1 {
|
if i < num_interrupts-1 {
|
||||||
ub = u32::saturating_sub(interrupt_offsets[i+1],unsafe{MINIMUM_INTER_ARRIVAL_TIME});
|
ub = u32::saturating_sub(interrupt_offsets[i+1], interrup_config.1 * QEMU_ISNS_PER_USEC);
|
||||||
}
|
}
|
||||||
// get old hit and handler
|
// get old hit and handler
|
||||||
let old_hit = marks.iter().filter(
|
let old_hit = marks.iter().filter(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user