Add InterruptShifterMutator

Also add features fuzz_interrupt and muta_interrupt,
which dictate if interrupts are used during fuzzing

Also allow makefile to skip finished iterations
This commit is contained in:
Alwin Berger 2022-06-07 01:50:21 +02:00
parent eb3914e5c1
commit 4dabfc5f00
8 changed files with 196 additions and 47 deletions

View File

@ -9,6 +9,8 @@ default = ["std", "obj_collect"]
std = [] std = []
multicore = [] multicore = []
fuzz_interrupt = [] # use the first bytes of the input for a timed interrupts
# select which feedbacks to use. enable at least one. # select which feedbacks to use. enable at least one.
feed_known_edges = [] feed_known_edges = []
feed_afl = [] feed_afl = []
@ -31,6 +33,7 @@ obj_ticks = []
muta_input = [ "sched_graph" ] muta_input = [ "sched_graph" ]
muta_snip = [ "sched_graph" ] muta_snip = [ "sched_graph" ]
muta_suffix = [ "sched_graph" ] muta_suffix = [ "sched_graph" ]
muta_interrupt = []
benchmark = [] # don't save corpus to disk, easy parallelizable benchmark = [] # don't save corpus to disk, easy parallelizable
dump_infos = [] # dump select corpus items for analysis dump_infos = [] # dump select corpus items for analysis

View File

@ -2,46 +2,54 @@ BENCHDIR = target/bench
TARGET = tmr.axf TARGET = tmr.axf
TARGET_TRACE = $(BENCHDIR)/traces/tmr_worst.ron TARGET_TRACE = $(BENCHDIR)/traces/tmr_worst.ron
TARGET_EDGES = $(BENCHDIR)/edges/tmr_worst.ron TARGET_EDGES = $(BENCHDIR)/edges/tmr_worst.ron
RUNTIME = 1 RUNTIME = 3600
COMMON_FLAGS = benchmark,dump_infos,fuzz_interrupt
$(BENCHDIR)/bin: $(BENCHDIR)/bin:
mkdir -p $@ mkdir -p $@
$(BENCHDIR)/target_known_edges: $(BENCHDIR)/target_known_edges:
cargo build --bin fuzzer --target-dir $@ --features benchmark,dump_infos,feed_known_edges,sched_queue cargo build --bin fuzzer --target-dir $@ --features $(COMMON_FLAGS),feed_known_edges,sched_queue
$(BENCHDIR)/target_afl_queue: $(BENCHDIR)/target_afl_queue:
cargo build --bin fuzzer --target-dir $@ --features benchmark,dump_infos,feed_afl,sched_queue cargo build --bin fuzzer --target-dir $@ --features $(COMMON_FLAGS),feed_afl,sched_queue
$(BENCHDIR)/target_afl_mapmax: $(BENCHDIR)/target_afl_mapmax:
cargo build --bin fuzzer --target-dir $@ --features benchmark,dump_infos,feed_afl,sched_mapmax cargo build --bin fuzzer --target-dir $@ --features $(COMMON_FLAGS),feed_afl,sched_mapmax
$(BENCHDIR)/target_state: $(BENCHDIR)/target_state:
cargo build --bin fuzzer --target-dir $@ --features benchmark,dump_infos,feed_state,sched_state cargo build --bin fuzzer --target-dir $@ --features $(COMMON_FLAGS),feed_state,sched_state
$(BENCHDIR)/target_state_afl: $(BENCHDIR)/target_state_afl:
cargo build --bin fuzzer --target-dir $@ --features benchmark,dump_infos,feed_state,sched_state cargo build --bin fuzzer --target-dir $@ --features $(COMMON_FLAGS),feed_state,sched_state
$(BENCHDIR)/target_state_afl_int:
cargo build --bin fuzzer --target-dir $@ --features $(COMMON_FLAGS),feed_state,sched_state,muta_interrupt
$(BENCHDIR)/target_graph: $(BENCHDIR)/target_graph:
cargo build --bin fuzzer --target-dir $@ --features benchmark,dump_infos,feed_graph,sched_graph cargo build --bin fuzzer --target-dir $@ --features $(COMMON_FLAGS),feed_graph,sched_graph
$(BENCHDIR)/target_graph_muta: $(BENCHDIR)/target_graph_muta:
cargo build --bin fuzzer --target-dir $@ --features benchmark,dump_infos,feed_graph,sched_graph,muta_snip,muta_input,muta_suffix cargo build --bin fuzzer --target-dir $@ --features $(COMMON_FLAGS),feed_graph,sched_graph,muta_snip,muta_input,muta_suffix
$(BENCHDIR)/target_graph_afl: $(BENCHDIR)/target_graph_afl:
cargo build --bin fuzzer --target-dir $@ --features benchmark,dump_infos,feed_graph,sched_graph,feed_afl cargo build --bin fuzzer --target-dir $@ --features $(COMMON_FLAGS),feed_graph,sched_graph,feed_afl
$(BENCHDIR)/target_graph_muta_afl:
cargo build --bin fuzzer --target-dir $@ --features $(COMMON_FLAGS),feed_graph,sched_graph,feed_afl,muta_snip,muta_input,muta_suffix
$(BENCHDIR)/target_graph_all: $(BENCHDIR)/target_graph_all:
cargo build --bin fuzzer --target-dir $@ --features benchmark,dump_infos,feed_graph,sched_graph,feed_afl,muta_snip,muta_input,muta_suffix cargo build --bin fuzzer --target-dir $@ --features $(COMMON_FLAGS),feed_graph,sched_graph,feed_afl,muta_snip,muta_input,muta_suffix,muta_interrupt
binaries: $(BENCHDIR)/target_known_edges $(BENCHDIR)/target_afl_queue $(BENCHDIR)/target_afl_mapmax $(BENCHDIR)/target_state $(BENCHDIR)/target_state_afl \ binaries: $(BENCHDIR)/target_known_edges $(BENCHDIR)/target_afl_queue $(BENCHDIR)/target_afl_mapmax $(BENCHDIR)/target_state $(BENCHDIR)/target_state_afl $(BENCHDIR)/target_state_afl_int \
$(BENCHDIR)/target_graph $(BENCHDIR)/target_graph_muta $(BENCHDIR)/target_graph_afl $(BENCHDIR)/target_graph_all $(BENCHDIR)/target_graph $(BENCHDIR)/target_graph_muta $(BENCHDIR)/target_graph_afl $(BENCHDIR)/target_graph_muta_afl $(BENCHDIR)/target_graph_all
# variants: known_edges, afl_queue, afl_mapmax, state, state_afl, graph, graph_muta, graph_afl, graph_all # variants: known_edges, afl_queue, afl_mapmax, state, state_afl, graph, graph_muta, graph_afl, graph_all
$(BENCHDIR)/bench_%.log: $(BENCHDIR)/target_% $(TARGET_TRACE) $(BENCHDIR)/bench_%.log: $(BENCHDIR)/target_% $(TARGET_TRACE)
mkdir -p $(BENCHDIR)/execs mkdir -p $(BENCHDIR)/execs
for i in {1..3}; do \ for i in {1..10}; do \
CASE=$$(basename -s.log $@ | cut -d'_' -f 2- ); \ CASE=$$(basename -s.log $@ | cut -d'_' -f 2- ); \
[ -f $(BENCHDIR)/execs/$$CASE\_$$i.exec -a -f $@_$$i ] && continue; \
echo $$CASE iteration $$i; \ echo $$CASE iteration $$i; \
mkdir -p $(BENCHDIR)/infos/$$CASE ; \ mkdir -p $(BENCHDIR)/infos/$$CASE ; \
./fuzzer_bench.sh $</debug/fuzzer $(TARGET) --libafl-traces $(TARGET_TRACE) --libafl-fuzztime $(RUNTIME) \ ./fuzzer_bench.sh $</debug/fuzzer $(TARGET) --libafl-traces $(TARGET_TRACE) --libafl-fuzztime $(RUNTIME) \
@ -51,14 +59,19 @@ $(BENCHDIR)/bench_%.log: $(BENCHDIR)/target_% $(TARGET_TRACE)
done done
for i in $@_*; do tail -n 1 $$i >> $@; done for i in $@_*; do tail -n 1 $$i >> $@; done
benchmarks: target/bench/bench_known_edges.log target/bench/bench_afl_queue.log target/bench/bench_afl_mapmax.log target/bench/bench_state.log target/bench/bench_state_afl.log \ benchmarks_all: target/bench/bench_known_edges.log target/bench/bench_afl_queue.log target/bench/bench_afl_mapmax.log target/bench/bench_state.log target/bench/bench_state_afl.log target/bench/bench_state_afl_int.log \
target/bench/bench_graph.log target/bench/bench_graph_muta.log target/bench/bench_graph_afl.log target/bench/bench_graph_all.log target/bench/bench_graph.log target/bench/bench_graph_muta.log target/bench/bench_graph_afl.log target/bench/bench_graph_muta_afl.log target/bench/bench_graph_all.log
all: binaries benchmarks benchmarks_int_mut: target/bench/bench_graph_muta_afl.log target/bench/bench_graph_all.log target/bench/bench_state_afl.log target/bench/bench_state_afl_int.log
all: binaries benchmarks_all
clean_bench: clean_bench:
rm -rf $(BENCHDIR)/bench_* rm -rf $(BENCHDIR)/bench_*
clean_aggregate:
rm -rf $(BENCHDIR)/bench_*.log
clean: clean:
rm -rf target/bench rm -rf target/bench

View File

@ -1,4 +1,7 @@
//! A singlethreaded QEMU fuzzer that can auto-restart. //! A singlethreaded QEMU fuzzer that can auto-restart.
use core::cmp::min;
use wcet_qemu_sys::sysstate::mutators::InterruptShifterMutator;
use wcet_qemu_sys::sysstate::IRQ_INPUT_OFFSET;
use std::str::FromStr; use std::str::FromStr;
use wcet_qemu_sys::worst::DumpEdgesMapMetadata; use wcet_qemu_sys::worst::DumpEdgesMapMetadata;
use wcet_qemu_sys::worst::DumpMapFeedback; use wcet_qemu_sys::worst::DumpMapFeedback;
@ -34,7 +37,7 @@ use wcet_qemu_sys::sysstate::helpers::QemuSystemStateHelper;
use wcet_qemu_sys::sysstate::observers::QemuSysStateObserver; use wcet_qemu_sys::sysstate::observers::QemuSysStateObserver;
use wcet_qemu_sys::sysstate::feedbacks::SysStateFeedbackState; use wcet_qemu_sys::sysstate::feedbacks::SysStateFeedbackState;
use wcet_qemu_sys::sysstate::feedbacks::NovelSysStateFeedback; use wcet_qemu_sys::sysstate::feedbacks::NovelSysStateFeedback;
use wcet_qemu_sys::sysstate::INPUT_BYTES_OFFSET; use wcet_qemu_sys::sysstate::IRQ_INPUT_BYTES_NUMBER;
use wcet_qemu_sys::worst::QemuHashMapObserver; use wcet_qemu_sys::worst::QemuHashMapObserver;
use wcet_qemu_sys::minimizer::QemuCaseMinimizerStage; use wcet_qemu_sys::minimizer::QemuCaseMinimizerStage;
use hashbrown::HashMap; use hashbrown::HashMap;
@ -505,6 +508,8 @@ fn fuzz(
let mutator_list = mutator_list.merge(tuple_list!(RandGraphSuffixMutator::new())); let mutator_list = mutator_list.merge(tuple_list!(RandGraphSuffixMutator::new()));
#[cfg(feature = "muta_snip")] #[cfg(feature = "muta_snip")]
let mutator_list = mutator_list.merge(tuple_list!(RandGraphSnippetMutator::new())); let mutator_list = mutator_list.merge(tuple_list!(RandGraphSnippetMutator::new()));
#[cfg(all(feature = "muta_interrupt",feature = "fuzz_interrupt"))]
let mutator_list = mutator_list.merge(tuple_list!(InterruptShifterMutator::new()));
// Setup a MOPT mutator // Setup a MOPT mutator
let mutator = StdMOptMutator::new(&mut state, mutator_list,5)?; let mutator = StdMOptMutator::new(&mut state, mutator_list,5)?;
@ -531,15 +536,14 @@ fn fuzz(
let mut buf = target.as_slice(); let mut buf = target.as_slice();
let mut len = buf.len(); let mut len = buf.len();
let mut int_tick : Option<u32> = None; let mut int_tick : Option<u32> = None;
if INPUT_BYTES_OFFSET!= 0 { if len > IRQ_INPUT_BYTES_NUMBER as usize {
if len > 2 {
let mut t : [u8; 4] = [0,0,0,0]; // 4 extra bytes determine the tick to execute an interrupt let mut t : [u8; 4] = [0,0,0,0]; // 4 extra bytes determine the tick to execute an interrupt
t[0]=buf[0]; for i in 0..min(4,IRQ_INPUT_BYTES_NUMBER) {
t[1]=buf[1]; t[i as usize]=buf[i as usize];
int_tick = Some(u32::from_le_bytes(t));
buf = &buf[2..];
len = buf.len();
} }
int_tick = Some(u32::from_le_bytes(t));
buf = &buf[IRQ_INPUT_BYTES_NUMBER as usize..];
len = buf.len();
} }
if len >= 32 { if len >= 32 {
buf = &buf[0..32]; buf = &buf[0..32];
@ -547,8 +551,8 @@ fn fuzz(
} }
unsafe { unsafe {
if INPUT_BYTES_OFFSET!= 0 { if IRQ_INPUT_BYTES_NUMBER!= 0 {
libafl_int_offset = 347780+int_tick.unwrap_or(0); libafl_int_offset = IRQ_INPUT_OFFSET+int_tick.unwrap_or(0);
} }
// INTR_OFFSET = int_tick; // INTR_OFFSET = int_tick;
emu.write_mem(test_length_ptr,&(len as u32).to_le_bytes()); emu.write_mem(test_length_ptr,&(len as u32).to_le_bytes());

View File

@ -1,10 +1,12 @@
//! A singlethreaded QEMU fuzzer that can auto-restart. //! A singlethreaded QEMU fuzzer that can auto-restart.
use core::cmp::min;
use wcet_qemu_sys::sysstate::IRQ_INPUT_OFFSET;
use wcet_qemu_sys::sysstate::IRQ_INPUT_BYTES_NUMBER;
use wcet_qemu_sys::sysstate::helpers::INTR_OFFSET; use wcet_qemu_sys::sysstate::helpers::INTR_OFFSET;
use std::io::Read; use std::io::Read;
use wcet_qemu_sys::sysstate::observers::QemuSysStateObserver; use wcet_qemu_sys::sysstate::observers::QemuSysStateObserver;
use wcet_qemu_sys::sysstate::feedbacks::DumpSystraceFeedback; use wcet_qemu_sys::sysstate::feedbacks::DumpSystraceFeedback;
use wcet_qemu_sys::sysstate::INPUT_BYTES_OFFSET;
use wcet_qemu_sys::worst::QemuHashMapObserver; use wcet_qemu_sys::worst::QemuHashMapObserver;
use wcet_qemu_sys::{ use wcet_qemu_sys::{
worst::{DumpMapFeedback,DummyFeedback}, worst::{DumpMapFeedback,DummyFeedback},
@ -340,15 +342,14 @@ fn fuzz(
let mut buf = target.as_slice(); let mut buf = target.as_slice();
let mut len = buf.len(); let mut len = buf.len();
let mut int_tick : Option<u32> = None; let mut int_tick : Option<u32> = None;
if INPUT_BYTES_OFFSET!= 0 { if len > IRQ_INPUT_BYTES_NUMBER as usize {
if len > 2 {
let mut t : [u8; 4] = [0,0,0,0]; // 4 extra bytes determine the tick to execute an interrupt let mut t : [u8; 4] = [0,0,0,0]; // 4 extra bytes determine the tick to execute an interrupt
t[0]=buf[0]; for i in 0..min(4,IRQ_INPUT_BYTES_NUMBER) {
t[1]=buf[1]; t[i as usize]=buf[i as usize];
int_tick = Some(u32::from_le_bytes(t));
buf = &buf[2..];
len = buf.len();
} }
int_tick = Some(u32::from_le_bytes(t));
buf = &buf[IRQ_INPUT_BYTES_NUMBER as usize..];
len = buf.len();
} }
if len >= 32 { if len >= 32 {
buf = &buf[0..32]; buf = &buf[0..32];
@ -356,8 +357,8 @@ fn fuzz(
} }
unsafe { unsafe {
if INPUT_BYTES_OFFSET!= 0 { if IRQ_INPUT_BYTES_NUMBER!= 0 {
libafl_int_offset = 347780+int_tick.unwrap_or(0); libafl_int_offset = IRQ_INPUT_OFFSET+int_tick.unwrap_or(0);
} }
// INTR_OFFSET = int_tick; // INTR_OFFSET = int_tick;
emu.write_mem(test_length_ptr,&(len as u32).to_le_bytes()); emu.write_mem(test_length_ptr,&(len as u32).to_le_bytes());

View File

@ -45,12 +45,12 @@ use libafl::bolts::rands::Rand;
//============================= Data Structures //============================= Data Structures
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Default)] #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Default)]
struct VariantTuple pub struct VariantTuple
{ {
start_tick: u64, pub start_tick: u64,
end_tick: u64, pub end_tick: u64,
input_counter: u32, input_counter: u32,
input: Vec<u8>, // in the end any kind of input are bytes, regardless of type and lifetime pub input: Vec<u8>, // in the end any kind of input are bytes, regardless of type and lifetime
} }
impl VariantTuple { impl VariantTuple {
fn from(other: &RefinedFreeRTOSSystemState,input: Vec<u8>) -> Self { fn from(other: &RefinedFreeRTOSSystemState,input: Vec<u8>) -> Self {
@ -67,7 +67,7 @@ impl VariantTuple {
pub struct SysGraphNode pub struct SysGraphNode
{ {
base: RefinedFreeRTOSSystemState, base: RefinedFreeRTOSSystemState,
variants: Vec<VariantTuple>, pub variants: Vec<VariantTuple>,
} }
impl SysGraphNode { impl SysGraphNode {
fn from(base: RefinedFreeRTOSSystemState, input: Vec<u8>) -> Self { fn from(base: RefinedFreeRTOSSystemState, input: Vec<u8>) -> Self {
@ -117,7 +117,7 @@ impl PartialEq for SysGraphNode {
// Wrapper around Vec<RefinedFreeRTOSSystemState> to attach as Metadata // Wrapper around Vec<RefinedFreeRTOSSystemState> to attach as Metadata
#[derive(Debug, Default, Serialize, Deserialize, Clone)] #[derive(Debug, Default, Serialize, Deserialize, Clone)]
pub struct SysGraphMetadata { pub struct SysGraphMetadata {
inner: Vec<NodeIndex>, pub inner: Vec<NodeIndex>,
indices: Vec<usize>, indices: Vec<usize>,
tcref: isize, tcref: isize,
} }

View File

@ -14,8 +14,13 @@ pub mod helpers;
pub mod observers; pub mod observers;
pub mod feedbacks; pub mod feedbacks;
pub mod graph; pub mod graph;
pub mod mutators;
pub const INPUT_BYTES_OFFSET : u32 = 2; // Offset for interrupt bytes #[cfg(feature = "fuzz_interrupt")]
pub const IRQ_INPUT_BYTES_NUMBER : u32 = 2; // Offset for interrupt bytes
#[cfg(not(feature = "fuzz_interrupt"))]
pub const IRQ_INPUT_BYTES_NUMBER : u32 = 0; // Offset for interrupt bytes
pub const IRQ_INPUT_OFFSET : u32 = 347780; // Tick offset for app code start
// Constants // Constants
const NUM_PRIOS: usize = 5; const NUM_PRIOS: usize = 5;

View File

@ -0,0 +1,123 @@
use crate::sysstate::graph::SysGraphMetadata;
use crate::sysstate::graph::SysGraphNode;
use libafl::state::HasFeedbackStates;
use crate::sysstate::IRQ_INPUT_OFFSET;
use crate::sysstate::IRQ_INPUT_BYTES_NUMBER;
use crate::sysstate::graph::SysGraphFeedbackState;
use libafl::inputs::HasBytesVec;
use libafl::bolts::rands::RandomSeed;
use libafl::bolts::rands::StdRand;
use libafl::mutators::Mutator;
use libafl::mutators::MutationResult;
use core::marker::PhantomData;
use libafl::state::HasCorpus;
use libafl::state::HasSolutions;
use libafl::state::HasRand;
use libafl::bolts::tuples::MatchName;
use libafl::bolts::tuples::Named;
use libafl::Error;
use libafl::{inputs::Input, state::HasMetadata};
use super::FreeRTOSSystemStateMetadata;
use libafl::bolts::rands::Rand;
//=============================== Interrupt
/// Sets up the interrupt to a random block in the trace. Works for both state and graph metadata
pub struct InterruptShifterMutator<I, S>
where
I: Input + HasBytesVec,
S: HasRand + HasMetadata + HasCorpus<I> + HasSolutions<I>,
{
phantom: PhantomData<(I, S)>,
}
impl<I, S> InterruptShifterMutator<I, S>
where
I: Input + HasBytesVec,
S: HasRand + HasMetadata + HasCorpus<I> + HasSolutions<I>,
{
pub fn new() -> Self {
InterruptShifterMutator{phantom: PhantomData}
}
}
impl<I, S> Mutator<I, S> for InterruptShifterMutator<I, S>
where
I: Input + HasBytesVec,
S: HasRand + HasMetadata + HasCorpus<I> + HasSolutions<I> + HasFeedbackStates,
{
fn mutate(
&mut self,
state: &mut S,
input: &mut I,
_stage_idx: i32
) -> Result<MutationResult, Error>
{
// need our own random generator, because borrowing rules
let mut myrand = StdRand::new();
let tmp = &mut state.rand_mut();
myrand.set_seed(tmp.next());
drop(tmp);
let target_bytes = input.bytes_mut();
let mut target_tick = 0;
#[cfg(feature = "sched_state")]
{
let tmp = state.metadata().get::<FreeRTOSSystemStateMetadata>();
if tmp.is_none() { // if there are no metadata it was probably not interesting anyways
return Ok(MutationResult::Skipped);
}
let trace =tmp.expect("FreeRTOSSystemStateMetadata not found");
let target_block = myrand.choose(trace.inner.iter());
target_tick = myrand.between(target_block.start_tick,target_block.end_tick)-IRQ_INPUT_OFFSET as u64;
}
#[cfg(feature = "sched_state")]
{
let feedbackstate = state
.feedback_states()
.match_name::<SysGraphFeedbackState>("SysMap")
.unwrap();
let g = &feedbackstate.graph;
let tmp = state.metadata().get::<SysGraphMetadata>();
if tmp.is_none() { // if there are no metadata it was probably not interesting anyways
return Ok(MutationResult::Skipped);
}
let trace = tmp.expect("SysGraphMetadata not found");
let target_block : &SysGraphNode = &g[*myrand.choose(trace.inner.iter())];
target_tick = match target_block.variants.iter().find(|x| &x.input == target_bytes) {
Some(s) => myrand.between(s.start_tick,s.end_tick)-IRQ_INPUT_OFFSET as u64,
None => myrand.between(target_block.variants[0].start_tick,target_block.variants[0].end_tick)-IRQ_INPUT_OFFSET as u64,
};
}
if target_bytes.len() > IRQ_INPUT_BYTES_NUMBER as usize && IRQ_INPUT_BYTES_NUMBER > 0 {
for i in 0..IRQ_INPUT_BYTES_NUMBER as usize {
target_bytes[i] = u64::to_le_bytes(target_tick)[i];
}
return Ok(MutationResult::Mutated);
} else {
return Ok(MutationResult::Skipped);
}
}
fn post_exec(
&mut self,
_state: &mut S,
_stage_idx: i32,
_corpus_idx: Option<usize>
) -> Result<(), Error> {
Ok(())
}
}
impl<I, S> Named for InterruptShifterMutator<I, S>
where
I: Input + HasBytesVec,
S: HasRand + HasMetadata + HasCorpus<I> + HasSolutions<I> + HasFeedbackStates,
{
fn name(&self) -> &str {
"InterruptShifterMutator"
}
}

View File

@ -1,4 +1,4 @@
use crate::sysstate::INPUT_BYTES_OFFSET; use crate::sysstate::IRQ_INPUT_BYTES_NUMBER;
use libafl::inputs::HasTargetBytes; use libafl::inputs::HasTargetBytes;
use libafl::bolts::HasLen; use libafl::bolts::HasLen;
use libafl::bolts::tuples::Named; use libafl::bolts::tuples::Named;
@ -130,7 +130,7 @@ for mut i in input.drain(..) {
start_tick: start_tick, start_tick: start_tick,
end_tick: i.qemu_tick, end_tick: i.qemu_tick,
ready_list_after: collector, ready_list_after: collector,
input_counter: i.input_counter+INPUT_BYTES_OFFSET, input_counter: i.input_counter+IRQ_INPUT_BYTES_NUMBER,
last_pc: i.last_pc, last_pc: i.last_pc,
}); });
start_tick=i.qemu_tick; start_tick=i.qemu_tick;