refactor interrupt mutation
This commit is contained in:
parent
835d1e1a79
commit
8165fd7cfc
@ -27,15 +27,15 @@ use super::stg::{STGEdge, STGNode};
|
||||
|
||||
pub fn input_bytes_to_interrupt_times(buf: &[u8], config: (usize,u32)) -> Vec<u32> {
|
||||
let len = buf.len();
|
||||
let mut start_tick : u32 = 0;
|
||||
let mut ret = Vec::with_capacity(DO_NUM_INTERRUPT);
|
||||
let mut start_tick;
|
||||
let mut ret = Vec::with_capacity(min(DO_NUM_INTERRUPT, len/4));
|
||||
for i in 0..DO_NUM_INTERRUPT {
|
||||
let mut t : [u8; 4] = [0,0,0,0];
|
||||
if len > (i+1)*4 {
|
||||
let mut buf4b : [u8; 4] = [0,0,0,0];
|
||||
if len >= (i+1)*4 {
|
||||
for j in 0usize..4usize {
|
||||
t[j]=buf[i*4+j];
|
||||
buf4b[j]=buf[i*4+j];
|
||||
}
|
||||
start_tick = u32::from_le_bytes(t);
|
||||
start_tick = u32::from_le_bytes(buf4b);
|
||||
if start_tick < FIRST_INT {start_tick=0;}
|
||||
ret.push(start_tick);
|
||||
} else {break;}
|
||||
@ -53,6 +53,14 @@ pub fn input_bytes_to_interrupt_times(buf: &[u8], config: (usize,u32)) -> Vec<u3
|
||||
ret
|
||||
}
|
||||
|
||||
pub fn interrupt_times_to_input_bytes(interrupt_times: &[u32]) -> Vec<u8> {
|
||||
let mut ret = Vec::with_capacity(interrupt_times.len()*4);
|
||||
for i in interrupt_times {
|
||||
ret.extend(u32::to_le_bytes(*i));
|
||||
}
|
||||
ret
|
||||
}
|
||||
|
||||
|
||||
//======================= Custom mutator
|
||||
|
||||
@ -136,260 +144,234 @@ where
|
||||
myrand.set_seed(state.rand_mut().next());
|
||||
|
||||
|
||||
let mut loopcount = 0;
|
||||
let mut loopbound = 50;
|
||||
loop {
|
||||
let mut rerun_count = 0; // count how many times we rerun the executor
|
||||
// Try many times to find a mutation that is not already in the corpus
|
||||
let loopbound = 50;
|
||||
for _ in 0..loopbound {
|
||||
// Choose which isr to mutate
|
||||
let interrup_config = match myrand.choose(&self.interrup_config) {
|
||||
Some(s) => s,
|
||||
Option::None => return Ok(())
|
||||
};
|
||||
let name = format!("isr_{}_times", interrup_config.0);
|
||||
// manager.log(state, LogSeverity::Info, format!("Mutation {}/{}", loopbound, loopcount))?;
|
||||
loopbound-=1;
|
||||
let current_case = state.current_testcase()?;
|
||||
let old_input = current_case.input().as_ref().unwrap();
|
||||
let old_interrupt_times = old_input.parts_by_name(&name).next();
|
||||
let mut new_input = old_input.clone();
|
||||
|
||||
let mut new_interrupt_times : &mut I = if new_input.parts_by_name(&name).next().is_some() {
|
||||
new_input.parts_by_name_mut(&name).next().unwrap()
|
||||
} else {
|
||||
new_input.add_part(String::from(&name), I::default()); new_input.parts_by_name_mut(&name).next().unwrap()
|
||||
}.1;
|
||||
let mut do_rerun = false;
|
||||
// if state.rand_mut().between(1, 100) <= 50 // only attempt the mutation half of the time
|
||||
{
|
||||
let curr_case = state.current_testcase()?;
|
||||
let curr_input = curr_case.input().as_ref().unwrap();
|
||||
|
||||
// produce a slice of absolute interrupt times
|
||||
let mut interrupt_offsets : [u32; MAX_NUM_INTERRUPT] = [u32::MAX; MAX_NUM_INTERRUPT];
|
||||
let mut num_interrupts : usize = 0;
|
||||
let mut new_input = curr_input.clone();
|
||||
let new_interrupt_part : &mut I = if new_input.parts_by_name(&name).next().is_some() {
|
||||
new_input.parts_by_name_mut(&name).next().unwrap()
|
||||
} else {
|
||||
new_input.add_part(String::from(&name), I::default()); new_input.parts_by_name_mut(&name).next().unwrap()
|
||||
}.1;
|
||||
let old_interrupt_times = input_bytes_to_interrupt_times(new_interrupt_part.bytes(), *interrup_config);
|
||||
let mut new_interrupt_times = Vec::with_capacity(MAX_NUM_INTERRUPT);
|
||||
let mut do_rerun = false;
|
||||
// if state.rand_mut().between(1, 100) <= 50 // only attempt the mutation half of the time
|
||||
{
|
||||
let t = input_bytes_to_interrupt_times(new_interrupt_times.bytes(), *interrup_config);
|
||||
for i in 0..t.len() {interrupt_offsets[i]=t[i];}
|
||||
num_interrupts=t.len();
|
||||
}
|
||||
interrupt_offsets.sort_unstable();
|
||||
|
||||
// println!("Vor Mutator: {:?}", interrupt_offsets[0..num_interrupts].to_vec());
|
||||
let mut prefix : Vec<[u8; 4]> = vec![];
|
||||
// let mut suffix : Vec<u8> = vec![];
|
||||
#[cfg(feature = "mutate_stg")]
|
||||
{
|
||||
let metadata = state.metadata_map();
|
||||
let hist = metadata.get::<IcHist>().unwrap();
|
||||
let maxtick : u64 = hist.1.0;
|
||||
drop(hist);
|
||||
#[cfg(feature = "mutate_stg")]
|
||||
{
|
||||
let choice = myrand.between(1,100);
|
||||
if choice <= 25 || *interrupt_offsets.get(0).unwrap_or(&u32::MAX) as u64 > maxtick { // 0.5*0.25 = 12.5% of the time fully randomize all interrupts
|
||||
do_rerun = true;
|
||||
// let metadata = state.metadata_map();
|
||||
let hist = metadata.get::<IcHist>().unwrap();
|
||||
let maxtick : u64 = hist.1.0;
|
||||
// let maxtick : u64 = (_input.exec_time().expect("No duration found").as_nanos() >> 4).try_into().unwrap();
|
||||
let mut numbers : Vec<u32> = vec![];
|
||||
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")));
|
||||
let metadata = state.metadata_map();
|
||||
let maxtick = {metadata.get::<IcHist>().unwrap().1.0};
|
||||
drop(new_interrupt_part.drain(..).collect::<Vec<u8>>());
|
||||
{
|
||||
let choice = myrand.between(1,100);
|
||||
if choice <= 25 || *old_interrupt_times.get(0).unwrap_or(&u32::MAX) as u64 > maxtick { // 0.5*0.25 = 12.5% of the time fully randomize all interrupts
|
||||
do_rerun = true;
|
||||
let hist = metadata.get::<IcHist>().unwrap();
|
||||
let maxtick : u64 = hist.1.0;
|
||||
// let maxtick : u64 = (_input.exec_time().expect("No duration found").as_nanos() >> 4).try_into().unwrap();
|
||||
for _ in 0..myrand.between(0,min(MAX_NUM_INTERRUPT, (maxtick as usize * 3) / (interrup_config.1 as usize * QEMU_ISNS_PER_USEC as usize * 2))) {
|
||||
new_interrupt_times.push(myrand.between(0, min(maxtick, u32::MAX as u64) as usize).try_into().expect("ticks > u32"));
|
||||
}
|
||||
}
|
||||
}
|
||||
else if choice <= 75 { // 0.5 * 0.25 = 12.5% of cases
|
||||
let feedbackstate = match state
|
||||
.named_metadata_map()
|
||||
.get::<STGFeedbackState>("stgfeedbackstate") {
|
||||
Some(s) => s,
|
||||
Option::None => {
|
||||
panic!("STGfeedbackstate not visible")
|
||||
else if choice <= 75 { // 0.5 * 0.25 = 12.5% of cases
|
||||
let feedbackstate = match state
|
||||
.named_metadata_map()
|
||||
.get::<STGFeedbackState>("stgfeedbackstate") {
|
||||
Some(s) => s,
|
||||
Option::None => {
|
||||
panic!("STGfeedbackstate not visible")
|
||||
}
|
||||
};
|
||||
if let Some(meta) = curr_case.metadata_map().get::<STGNodeMetadata>() {
|
||||
if let Some(t) = try_force_new_branches(&old_interrupt_times, feedbackstate, meta, *interrup_config) {
|
||||
do_rerun = true;
|
||||
new_interrupt_times=t;
|
||||
}
|
||||
};
|
||||
if let Some(meta) = current_case.metadata_map().get::<STGNodeMetadata>() {
|
||||
if let Some(t) = try_force_new_branches(&interrupt_offsets, feedbackstate, meta, *interrup_config) {
|
||||
do_rerun = true;
|
||||
for i in 0..t.len() {
|
||||
if i<num_interrupts {
|
||||
interrupt_offsets[i]=t[i];
|
||||
} else {break;}
|
||||
}
|
||||
// let tmp = current_case.metadata_map().get::<STGNodeMetadata>();
|
||||
// if tmp.is_some() {
|
||||
// let trace = tmp.expect("STGNodeMetadata not found");
|
||||
// let mut node_indices = vec![];
|
||||
// for i in (0..trace.intervals.len()).into_iter() {
|
||||
// if let Some(abb) = &trace.intervals[i].abb {
|
||||
// if let Some(idx) = feedbackstate.state_abb_hash_index.get(&(trace.intervals[i].start_state,abb.get_hash())) {
|
||||
// node_indices.push(Some(idx));
|
||||
// continue;
|
||||
// }
|
||||
// }
|
||||
// node_indices.push(None);
|
||||
// }
|
||||
// // let mut marks : HashMap<u32, usize>= HashMap::new(); // interrupt -> block hit
|
||||
// // for i in 0..trace.intervals.len() {
|
||||
// // let curr = &trace.intervals[i];
|
||||
// // let m = interrupt_offsets[0..num_interrupts].iter().filter(|x| (curr.start_tick..curr.end_tick).contains(&((**x) as u64)));
|
||||
// // for k in m {
|
||||
// // marks.insert(*k,i);
|
||||
// // }
|
||||
// // }
|
||||
// // walk backwards trough the trace and try moving the interrupt to a block that does not have an outgoing interrupt edge or ist already hit by a predecessor
|
||||
// for i in (0..num_interrupts).rev() {
|
||||
// let mut lb = FIRST_INT;
|
||||
// let mut ub : u32 = trace.intervals[trace.intervals.len()-1].end_tick.try_into().expect("ticks > u32");
|
||||
// if i > 0 {
|
||||
// lb = u32::saturating_add(interrupt_offsets[i-1],unsafe{MINIMUM_INTER_ARRIVAL_TIME});
|
||||
// }
|
||||
// if i < num_interrupts-1 {
|
||||
// ub = u32::saturating_sub(interrupt_offsets[i+1],unsafe{MINIMUM_INTER_ARRIVAL_TIME});
|
||||
// }
|
||||
// let alternatives : Vec<_> = (0..trace.intervals.len()).filter(|x|
|
||||
// node_indices[*x].is_some() &&
|
||||
// (trace.intervals[*x].start_tick < (lb as u64) && (lb as u64) < trace.intervals[*x].end_tick
|
||||
// || trace.intervals[*x].start_tick > (lb as u64) && trace.intervals[*x].start_tick < (ub as u64))
|
||||
// ).collect();
|
||||
// let not_yet_hit : Vec<_> = alternatives.iter().filter(
|
||||
// |x| feedbackstate.graph.edges_directed(*node_indices[**x].unwrap(), petgraph::Direction::Outgoing).any(|y| y.weight().event != CaptureEvent::ISRStart)).collect();
|
||||
// if not_yet_hit.len() > 0 {
|
||||
// let replacement = &trace.intervals[*myrand.choose(not_yet_hit).unwrap()];
|
||||
// interrupt_offsets[i] = (myrand.between(replacement.start_tick as usize,
|
||||
// replacement.end_tick as usize)).try_into().expect("ticks > u32");
|
||||
// // println!("chose new alternative, i: {} {} -> {}",i,tmp, interrupt_offsets[i]);
|
||||
// do_rerun = true;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
else { // old version of the alternative search
|
||||
new_interrupt_times = old_interrupt_times.clone();
|
||||
let tmp = curr_case.metadata_map().get::<STGNodeMetadata>();
|
||||
if tmp.is_some() {
|
||||
let trace = tmp.expect("STGNodeMetadata not found");
|
||||
|
||||
// calculate hits and identify snippets
|
||||
let mut last_m = false;
|
||||
let mut marks : Vec<(&ExecInterval, usize, usize)>= vec![]; // 1: got interrupted, 2: interrupt handler
|
||||
for i in 0..trace.intervals.len() {
|
||||
let curr = &trace.intervals[i];
|
||||
let m = old_interrupt_times.iter().any(|x| (curr.start_tick..curr.end_tick).contains(&(*x as u64)));
|
||||
if m {
|
||||
marks.push((curr, i, 1));
|
||||
// println!("1: {}",curr.current_task.0.task_name);
|
||||
} else if last_m {
|
||||
marks.push((curr, i, 2));
|
||||
// println!("2: {}",curr.current_task.0.task_name);
|
||||
} else {
|
||||
marks.push((curr, i, 0));
|
||||
}
|
||||
last_m = m;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
// let tmp = current_case.metadata_map().get::<STGNodeMetadata>();
|
||||
// if tmp.is_some() {
|
||||
// let trace = tmp.expect("STGNodeMetadata not found");
|
||||
// let mut node_indices = vec![];
|
||||
// for i in (0..trace.intervals.len()).into_iter() {
|
||||
// if let Some(abb) = &trace.intervals[i].abb {
|
||||
// if let Some(idx) = feedbackstate.state_abb_hash_index.get(&(trace.intervals[i].start_state,abb.get_hash())) {
|
||||
// node_indices.push(Some(idx));
|
||||
// continue;
|
||||
// }
|
||||
// }
|
||||
// node_indices.push(None);
|
||||
// }
|
||||
// // let mut marks : HashMap<u32, usize>= HashMap::new(); // interrupt -> block hit
|
||||
// // for i in 0..trace.intervals.len() {
|
||||
// // let curr = &trace.intervals[i];
|
||||
// // let m = interrupt_offsets[0..num_interrupts].iter().filter(|x| (curr.start_tick..curr.end_tick).contains(&((**x) as u64)));
|
||||
// // for k in m {
|
||||
// // marks.insert(*k,i);
|
||||
// // }
|
||||
// // }
|
||||
// // walk backwards trough the trace and try moving the interrupt to a block that does not have an outgoing interrupt edge or ist already hit by a predecessor
|
||||
// for i in (0..num_interrupts).rev() {
|
||||
// let mut lb = FIRST_INT;
|
||||
// let mut ub : u32 = trace.intervals[trace.intervals.len()-1].end_tick.try_into().expect("ticks > u32");
|
||||
// if i > 0 {
|
||||
// lb = u32::saturating_add(interrupt_offsets[i-1],unsafe{MINIMUM_INTER_ARRIVAL_TIME});
|
||||
// }
|
||||
// if i < num_interrupts-1 {
|
||||
// ub = u32::saturating_sub(interrupt_offsets[i+1],unsafe{MINIMUM_INTER_ARRIVAL_TIME});
|
||||
// }
|
||||
// let alternatives : Vec<_> = (0..trace.intervals.len()).filter(|x|
|
||||
// node_indices[*x].is_some() &&
|
||||
// (trace.intervals[*x].start_tick < (lb as u64) && (lb as u64) < trace.intervals[*x].end_tick
|
||||
// || trace.intervals[*x].start_tick > (lb as u64) && trace.intervals[*x].start_tick < (ub as u64))
|
||||
// ).collect();
|
||||
// let not_yet_hit : Vec<_> = alternatives.iter().filter(
|
||||
// |x| feedbackstate.graph.edges_directed(*node_indices[**x].unwrap(), petgraph::Direction::Outgoing).any(|y| y.weight().event != CaptureEvent::ISRStart)).collect();
|
||||
// if not_yet_hit.len() > 0 {
|
||||
// let replacement = &trace.intervals[*myrand.choose(not_yet_hit).unwrap()];
|
||||
// interrupt_offsets[i] = (myrand.between(replacement.start_tick as usize,
|
||||
// replacement.end_tick as usize)).try_into().expect("ticks > u32");
|
||||
// // println!("chose new alternative, i: {} {} -> {}",i,tmp, interrupt_offsets[i]);
|
||||
// do_rerun = true;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
else { // old version of the alternative search
|
||||
let tmp = current_case.metadata_map().get::<STGNodeMetadata>();
|
||||
if tmp.is_some() {
|
||||
let trace = tmp.expect("STGNodeMetadata not found");
|
||||
|
||||
// calculate hits and identify snippets
|
||||
let mut last_m = false;
|
||||
let mut marks : Vec<(&ExecInterval, usize, usize)>= vec![]; // 1: got interrupted, 2: interrupt handler
|
||||
for i in 0..trace.intervals.len() {
|
||||
let curr = &trace.intervals[i];
|
||||
let m = interrupt_offsets[0..num_interrupts].iter().any(|x| (curr.start_tick..curr.end_tick).contains(&(*x as u64)));
|
||||
if m {
|
||||
marks.push((curr, i, 1));
|
||||
// println!("1: {}",curr.current_task.0.task_name);
|
||||
} else if last_m {
|
||||
marks.push((curr, i, 2));
|
||||
// println!("2: {}",curr.current_task.0.task_name);
|
||||
} else {
|
||||
marks.push((curr, i, 0));
|
||||
}
|
||||
last_m = m;
|
||||
}
|
||||
for i in 0..num_interrupts {
|
||||
// bounds based on minimum inter-arrival time
|
||||
let mut lb = FIRST_INT;
|
||||
let mut ub : u32 = marks[marks.len()-1].0.end_tick.try_into().expect("ticks > u32");
|
||||
if i > 0 {
|
||||
lb = u32::saturating_add(interrupt_offsets[i-1], interrup_config.1 * QEMU_ISNS_PER_USEC);
|
||||
}
|
||||
if i < num_interrupts-1 {
|
||||
ub = u32::saturating_sub(interrupt_offsets[i+1], interrup_config.1 * QEMU_ISNS_PER_USEC);
|
||||
}
|
||||
// get old hit and handler
|
||||
let old_hit = marks.iter().filter(
|
||||
|x| x.0.start_tick < (interrupt_offsets[i] as u64) && (interrupt_offsets[i] as u64) < x.0.end_tick
|
||||
).next();
|
||||
let old_handler = match old_hit {
|
||||
Some(s) => if s.1 < num_interrupts-1 && s.1 < marks.len()-1 {
|
||||
Some(marks[s.1+1])
|
||||
} else {None},
|
||||
None => None
|
||||
};
|
||||
// find reachable alternatives
|
||||
let alternatives : Vec<_> = marks.iter().filter(|x|
|
||||
x.2 != 2 &&
|
||||
(
|
||||
x.0.start_tick < (lb as u64) && (lb as u64) < x.0.end_tick
|
||||
|| x.0.start_tick > (lb as u64) && x.0.start_tick < (ub as u64))
|
||||
).collect();
|
||||
// in cases there are no alternatives
|
||||
if alternatives.len() == 0 {
|
||||
if old_hit.is_none() {
|
||||
// choose something random
|
||||
let untouched : Vec<_> = marks.iter().filter(
|
||||
|x| x.2 == 0
|
||||
for i in 0..old_interrupt_times.len() {
|
||||
// bounds based on minimum inter-arrival time
|
||||
let mut lb = FIRST_INT;
|
||||
let mut ub : u32 = trace.intervals[trace.intervals.len()-1].end_tick.try_into().expect("ticks > u32");
|
||||
if i > 0 {
|
||||
// use the new times, because changes to preceding timings are not accounted for yet
|
||||
lb = u32::saturating_add(new_interrupt_times[i-1], interrup_config.1 * QEMU_ISNS_PER_USEC);
|
||||
}
|
||||
if i < old_interrupt_times.len()-1 {
|
||||
ub = u32::saturating_sub(new_interrupt_times[i+1], interrup_config.1 * QEMU_ISNS_PER_USEC);
|
||||
}
|
||||
// get old hit and handler
|
||||
let old_hit = marks.iter().filter(
|
||||
|x| x.0.start_tick < (old_interrupt_times[i] as u64) && (old_interrupt_times[i] as u64) < x.0.end_tick
|
||||
).next();
|
||||
let old_handler = match old_hit {
|
||||
Some(s) => if s.1 < old_interrupt_times.len()-1 && s.1 < marks.len()-1 {
|
||||
Some(marks[s.1+1])
|
||||
} else {None},
|
||||
None => None
|
||||
};
|
||||
// find reachable alternatives
|
||||
let alternatives : Vec<_> = marks.iter().filter(|x|
|
||||
x.2 != 2 &&
|
||||
(
|
||||
x.0.start_tick < (lb as u64) && (lb as u64) < x.0.end_tick
|
||||
|| x.0.start_tick > (lb as u64) && x.0.start_tick < (ub as u64))
|
||||
).collect();
|
||||
if untouched.len() > 0 {
|
||||
let tmp = interrupt_offsets[i];
|
||||
let choice = myrand.choose(untouched).unwrap();
|
||||
interrupt_offsets[i] = myrand.between(choice.0.start_tick as usize, choice.0.end_tick as usize)
|
||||
.try_into().expect("tick > u32");
|
||||
// in cases there are no alternatives
|
||||
if alternatives.len() == 0 {
|
||||
if old_hit.is_none() {
|
||||
// choose something random
|
||||
let untouched : Vec<_> = marks.iter().filter(
|
||||
|x| x.2 == 0
|
||||
).collect();
|
||||
if untouched.len() > 0 {
|
||||
let tmp = old_interrupt_times[i];
|
||||
let choice = myrand.choose(untouched).unwrap();
|
||||
new_interrupt_times[i] = myrand.between(choice.0.start_tick as usize, choice.0.end_tick as usize)
|
||||
.try_into().expect("tick > u32");
|
||||
do_rerun = true;
|
||||
}
|
||||
// println!("no alternatives, choose random i: {} {} -> {}",i,tmp,interrupt_offsets[i]);
|
||||
continue;
|
||||
} else {
|
||||
// do nothing
|
||||
// println!("no alternatives, do nothing i: {} {}",i,interrupt_offsets[i]);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
let replacement = myrand.choose(alternatives).unwrap();
|
||||
if (old_hit.map_or(false, |x| x == replacement)) {
|
||||
// use the old value
|
||||
// println!("chose old value, do nothing i: {} {}",i,interrupt_offsets[i]);
|
||||
continue;
|
||||
} else {
|
||||
let extra = if (old_hit.map_or(false, |x| x.1 < replacement.1)) {
|
||||
// move futher back, respect old_handler
|
||||
old_handler.map_or(0, |x| x.0.end_tick - x.0.start_tick)
|
||||
} else { 0 };
|
||||
// let tmp = new_interrupt_times[i];
|
||||
new_interrupt_times[i] = (myrand.between(replacement.0.start_tick as usize,
|
||||
replacement.0.end_tick as usize) + extra as usize).try_into().expect("ticks > u32");
|
||||
// println!("chose new alternative, i: {} {} -> {}",i,tmp, interrupt_offsets[i]);
|
||||
do_rerun = true;
|
||||
}
|
||||
// println!("no alternatives, choose random i: {} {} -> {}",i,tmp,interrupt_offsets[i]);
|
||||
continue;
|
||||
} else {
|
||||
// do nothing
|
||||
// println!("no alternatives, do nothing i: {} {}",i,interrupt_offsets[i]);
|
||||
continue;
|
||||
}
|
||||
// println!("Mutator: {:?}", numbers);
|
||||
// let mut start : u32 = 0;
|
||||
// for i in 0..numbers.len() {
|
||||
// let tmp = numbers[i];
|
||||
// numbers[i] = numbers[i]-start;
|
||||
// start = tmp;
|
||||
// }
|
||||
new_interrupt_part.extend(&interrupt_times_to_input_bytes(&new_interrupt_times));
|
||||
}
|
||||
let replacement = myrand.choose(alternatives).unwrap();
|
||||
if (old_hit.map_or(false, |x| x == replacement)) {
|
||||
// use the old value
|
||||
// println!("chose old value, do nothing i: {} {}",i,interrupt_offsets[i]);
|
||||
continue;
|
||||
} else {
|
||||
let extra = if (old_hit.map_or(false, |x| x.1 < replacement.1)) {
|
||||
// move futher back, respect old_handler
|
||||
old_handler.map_or(0, |x| x.0.end_tick - x.0.start_tick)
|
||||
} else { 0 };
|
||||
let tmp = interrupt_offsets[i];
|
||||
interrupt_offsets[i] = (myrand.between(replacement.0.start_tick as usize,
|
||||
replacement.0.end_tick as usize) + extra as usize).try_into().expect("ticks > u32");
|
||||
// println!("chose new alternative, i: {} {} -> {}",i,tmp, interrupt_offsets[i]);
|
||||
do_rerun = true;
|
||||
}
|
||||
}
|
||||
let mut numbers : Vec<u32> = interrupt_offsets[0..num_interrupts].to_vec();
|
||||
numbers.sort();
|
||||
// println!("Mutator: {:?}", numbers);
|
||||
// let mut start : u32 = 0;
|
||||
// for i in 0..numbers.len() {
|
||||
// let tmp = numbers[i];
|
||||
// numbers[i] = numbers[i]-start;
|
||||
// start = tmp;
|
||||
// }
|
||||
for i in 0..numbers.len() {
|
||||
prefix.push(u32::to_le_bytes(numbers[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#[cfg(not(feature = "trace_stg"))]
|
||||
{
|
||||
if myrand.between(1,100) <= 25 { // we have no hint if interrupt times will change anything
|
||||
do_rerun = true;
|
||||
let metadata = state.metadata_map();
|
||||
let hist = metadata.get::<IcHist>().unwrap();
|
||||
let maxtick : u64 = hist.1.0;
|
||||
// let maxtick : u64 = (_input.exec_time().expect("No duration found").as_nanos() >> 4).try_into().unwrap();
|
||||
let mut numbers : Vec<u32> = vec![];
|
||||
for i in 0..num_interrupts {
|
||||
prefix.push(u32::to_le_bytes(myrand.between(0, min(maxtick as usize, u32::MAX as usize)).try_into().expect("ticks > u32")));
|
||||
#[cfg(not(feature = "trace_stg"))]
|
||||
{
|
||||
if myrand.between(1,100) <= 25 { // we have no hint if interrupt times will change anything
|
||||
do_rerun = true;
|
||||
let metadata = state.metadata_map();
|
||||
let maxtick = {metadata.get::<IcHist>().unwrap().1.0};
|
||||
new_interrupt_times = Vec::with_capacity(MAX_NUM_INTERRUPT);
|
||||
for i in 0..myrand.between(0,min(MAX_NUM_INTERRUPT, (maxtick as usize * 3) / (interrup_config.1 as usize * QEMU_ISNS_PER_USEC as usize * 2))) {
|
||||
new_interrupt_times.push(myrand.between(0, min(maxtick, u32::MAX as u64) as usize).try_into().expect("ticks > u32"));
|
||||
}
|
||||
}
|
||||
}
|
||||
new_interrupt_part.extend(&interrupt_times_to_input_bytes(&new_interrupt_times));
|
||||
}
|
||||
let _t= new_interrupt_times.drain(..).collect::<Vec<_>>();
|
||||
drop(_t);
|
||||
new_interrupt_times.extend(&prefix.concat());
|
||||
}
|
||||
drop(current_case);
|
||||
// InterruptShifterMutator::mutate(&mut mymut, state, &mut input, 0)?;
|
||||
if do_rerun {
|
||||
loopcount+=1;
|
||||
let (_, corpus_idx) = fuzzer.evaluate_input(state, executor, manager, new_input)?;
|
||||
if corpus_idx.is_none() && loopbound<=0 { break;}
|
||||
} else {if loopbound<=0 {break;}}
|
||||
drop(curr_case);
|
||||
if do_rerun {
|
||||
rerun_count+=1;
|
||||
let (_, corpus_idx) = fuzzer.evaluate_input(state, executor, manager, new_input)?;
|
||||
if corpus_idx.is_none() && loopbound<=0 { break;}
|
||||
} else {if loopbound<=0 {break;}}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user