WIP: per-task response times
This commit is contained in:
parent
bf7ad374a0
commit
e9fb73e65b
@ -5,7 +5,7 @@ authors = ["Alwin Berger <alwin.berger@tu-dortmund.de>"]
|
|||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["std", "snapshot_restore", "snapshot_fast", "singlecore", "restarting", "do_hash_notify_state", "config_stg", "fuzz_int" ]
|
default = ["std", "snapshot_restore", "snapshot_fast", "singlecore", "restarting", "do_hash_notify_state", "config_stg", "fuzz_int", "trace_job_response_times" ]
|
||||||
std = []
|
std = []
|
||||||
# Exec environemnt basics
|
# Exec environemnt basics
|
||||||
snapshot_restore = []
|
snapshot_restore = []
|
||||||
@ -19,6 +19,7 @@ observe_edges = [] # observe cfg edges
|
|||||||
observe_hitcounts = [ "observe_edges" ] # reduces edge granularity
|
observe_hitcounts = [ "observe_edges" ] # reduces edge granularity
|
||||||
observe_systemstate = []
|
observe_systemstate = []
|
||||||
do_hash_notify_state = []
|
do_hash_notify_state = []
|
||||||
|
trace_job_response_times = [ "trace_stg" ]
|
||||||
trace_stg = [ "observe_systemstate" ]
|
trace_stg = [ "observe_systemstate" ]
|
||||||
trace_reads = [ "trace_stg" ]
|
trace_reads = [ "trace_stg" ]
|
||||||
# feedbacks
|
# feedbacks
|
||||||
@ -60,7 +61,7 @@ libafl_qemu = { path = "../../libafl_qemu/", features = ["arm", "systemmode"] }
|
|||||||
serde = { version = "1.0", default-features = false, features = ["alloc"] } # serialization lib
|
serde = { version = "1.0", default-features = false, features = ["alloc"] } # serialization lib
|
||||||
serde_json = { version = "1.0", default-features = false, features = ["alloc"] }
|
serde_json = { version = "1.0", default-features = false, features = ["alloc"] }
|
||||||
hashbrown = { version = "0.14.0", features = ["serde"] } # A faster hashmap, nostd compatible
|
hashbrown = { version = "0.14.0", features = ["serde"] } # A faster hashmap, nostd compatible
|
||||||
petgraph = { version="0.6.4", features = ["serde-1"] }
|
petgraph = { version="0.6.5", features = ["serde-1"] }
|
||||||
ron = "0.7" # write serialized data - including hashmaps
|
ron = "0.7" # write serialized data - including hashmaps
|
||||||
rand = "0.5"
|
rand = "0.5"
|
||||||
clap = { version = "4.4.11", features = ["derive"] }
|
clap = { version = "4.4.11", features = ["derive"] }
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import csv
|
import csv
|
||||||
import os
|
import os
|
||||||
def_flags="--no-default-features --features std,snapshot_restore,singlecore,restarting,do_hash_notify_state"
|
def_flags="--no-default-features --features std,snapshot_restore,singlecore,restarting,do_hash_notify_state,trace_job_response_times"
|
||||||
remote="remote/"
|
remote="remote/"
|
||||||
RUNTIME=1800
|
RUNTIME=1800
|
||||||
TARGET_REPS_A=2
|
TARGET_REPS_A=2
|
||||||
@ -200,7 +200,7 @@ rule tarnsform_trace:
|
|||||||
output:
|
output:
|
||||||
"{remote}timedump/{fuzzer}/{target}.{num}.trace.csv"
|
"{remote}timedump/{fuzzer}/{target}.{num}.trace.csv"
|
||||||
shell:
|
shell:
|
||||||
"$(pwd)/../../../../state2gantt/target/debug/state2gantt {input} > {output[0]}"
|
"$(pwd)/../../../../state2gantt/target/debug/state2gantt {input} {output[0]} {output[0]}2"
|
||||||
|
|
||||||
rule trace2gantt:
|
rule trace2gantt:
|
||||||
input:
|
input:
|
||||||
@ -236,11 +236,11 @@ rule all_compare_afl_int:
|
|||||||
|
|
||||||
rule all_images:
|
rule all_images:
|
||||||
input:
|
input:
|
||||||
expand("{remote}timedump/{fuzzer}/{target}.{num}.trace.csv.png",remote=remote, fuzzer=['afl','feedgeneration10','state'], target=['waters','watersv2'],num=range(0,3))
|
expand("{remote}timedump/{fuzzer}/{target}.{num}.trace.csv.png",remote=remote, fuzzer=['frafl','feedgeneration10','state'], target=['waters'],num=range(0,3))
|
||||||
|
|
||||||
rule all_images_int:
|
rule all_images_int:
|
||||||
input:
|
input:
|
||||||
expand("{remote}timedump/{fuzzer}/{target}.{num}.trace.csv.png",remote=remote, fuzzer=['afl_int','feedgeneration10_int','state_int'], target=['waters_int','watersv2_int'],num=range(0,3))
|
expand("{remote}timedump/{fuzzer}/{target}.{num}.trace.csv.png",remote=remote, fuzzer=['frafl_int','feedgeneration10_int','state_int'], target=['waters_int'],num=range(0,3))
|
||||||
|
|
||||||
rule clusterfuzz:
|
rule clusterfuzz:
|
||||||
input:
|
input:
|
||||||
|
@ -1,32 +1,33 @@
|
|||||||
kernel,main_function,input_symbol,input_size,return_function
|
kernel,main_function,input_symbol,input_size,return_function,target_task_name
|
||||||
mpeg2,mpeg2_main,mpeg2_oldorgframe,90112,mpeg2_return
|
mpeg2,mpeg2_main,mpeg2_oldorgframe,90112,mpeg2_return,
|
||||||
audiobeam,audiobeam_main,audiobeam_input,11520,audiobeam_return
|
audiobeam,audiobeam_main,audiobeam_input,11520,audiobeam_return,
|
||||||
epic,epic_main,epic_image,4096,epic_return
|
epic,epic_main,epic_image,4096,epic_return,
|
||||||
dijkstra,dijkstra_main,dijkstra_AdjMatrix,10000,dijkstra_return
|
dijkstra,dijkstra_main,dijkstra_AdjMatrix,10000,dijkstra_return,
|
||||||
fft,fft_main,fft_twidtable,2046,fft_return
|
fft,fft_main,fft_twidtable,2046,fft_return,
|
||||||
bsort,bsort_main,bsort_Array,400,bsort_return
|
bsort,bsort_main,bsort_Array,400,bsort_return,
|
||||||
insertsort,insertsort_main,insertsort_a,400,insertsort_return
|
insertsort,insertsort_main,insertsort_a,400,insertsort_return,
|
||||||
g723_enc,g723_enc_main,g723_enc_INPUT,1024,g723_enc_return
|
g723_enc,g723_enc_main,g723_enc_INPUT,1024,g723_enc_return,
|
||||||
rijndael_dec,rijndael_dec_main,rijndael_dec_data,32768,rijndael_dec_return
|
rijndael_dec,rijndael_dec_main,rijndael_dec_data,32768,rijndael_dec_return,
|
||||||
rijndael_enc,rijndael_enc_main,rijndael_enc_data,31369,rijndael_enc_return
|
rijndael_enc,rijndael_enc_main,rijndael_enc_data,31369,rijndael_enc_return,
|
||||||
huff_dec,huff_dec_main,huff_dec_encoded,419,huff_dec_return
|
huff_dec,huff_dec_main,huff_dec_encoded,419,huff_dec_return,
|
||||||
huff_enc,huff_enc_main,huff_enc_plaintext,600,huff_enc_return
|
huff_enc,huff_enc_main,huff_enc_plaintext,600,huff_enc_return,
|
||||||
gsm_enc,gsm_enc_main,gsm_enc_pcmdata,6400,gsm_enc_return
|
gsm_enc,gsm_enc_main,gsm_enc_pcmdata,6400,gsm_enc_return,
|
||||||
tmr,main,FUZZ_INPUT,32,trigger_Qemu_break
|
tmr,main,FUZZ_INPUT,32,trigger_Qemu_break,
|
||||||
tacle_rtos,prvStage0,FUZZ_INPUT,604,trigger_Qemu_break
|
tacle_rtos,prvStage0,FUZZ_INPUT,604,trigger_Qemu_break,
|
||||||
lift,main_lift,FUZZ_INPUT,100,trigger_Qemu_break
|
lift,main_lift,FUZZ_INPUT,100,trigger_Qemu_break,
|
||||||
waters,main_waters,FUZZ_INPUT,4096,trigger_Qemu_break
|
waters,main_waters,FUZZ_INPUT,4096,trigger_Qemu_break,1129
|
||||||
watersv2,main_waters,FUZZ_INPUT,4096,trigger_Qemu_break
|
watersv2,main_waters,FUZZ_INPUT,4096,trigger_Qemu_break,1129
|
||||||
waterspart,main_waters,FUZZ_INPUT,4096,trigger_Qemu_break
|
waterspart,main_waters,FUZZ_INPUT,4096,trigger_Qemu_break,1129
|
||||||
waterspartv2,main_waters,FUZZ_INPUT,4096,trigger_Qemu_break
|
waterspartv2,main_waters,FUZZ_INPUT,4096,trigger_Qemu_break,1129
|
||||||
waters_int,main_waters,FUZZ_INPUT,4096,trigger_Qemu_break
|
waters_int,main_waters,FUZZ_INPUT,4096,trigger_Qemu_break,1129
|
||||||
watersv2_int,main_waters,FUZZ_INPUT,4096,trigger_Qemu_break
|
watersv2_int,main_waters,FUZZ_INPUT,4096,trigger_Qemu_break,1129
|
||||||
waterspart_int,main_waters,FUZZ_INPUT,4096,trigger_Qemu_break
|
waterspart_int,main_waters,FUZZ_INPUT,4096,trigger_Qemu_break,1129
|
||||||
waterspartv2_int,main_waters,FUZZ_INPUT,4096,trigger_Qemu_break
|
waterspartv2_int,main_waters,FUZZ_INPUT,4096,trigger_Qemu_break,1129
|
||||||
micro_branchless,main_branchless,FUZZ_INPUT,4,trigger_Qemu_break
|
micro_branchless,main_branchless,FUZZ_INPUT,4,trigger_Qemu_break,
|
||||||
micro_int,main_int,FUZZ_INPUT,16,trigger_Qemu_break
|
micro_int,main_int,FUZZ_INPUT,16,trigger_Qemu_break,
|
||||||
micro_longint,main_micro_longint,FUZZ_INPUT,16,trigger_Qemu_break
|
micro_longint,main_micro_longint,FUZZ_INPUT,16,trigger_Qemu_break,
|
||||||
minimal,main_minimal,FUZZ_INPUT,4096,trigger_Qemu_break
|
minimal,main_minimal,FUZZ_INPUT,4096,trigger_Qemu_break,
|
||||||
gen3,main_minimal,FUZZ_INPUT,4096,trigger_Qemu_break
|
gen3,main_minimal,FUZZ_INPUT,4096,trigger_Qemu_break,
|
||||||
interact,main_interact,FUZZ_INPUT,4096,trigger_Qemu_break
|
interact,main_interact,FUZZ_INPUT,4096,trigger_Qemu_break,
|
||||||
interact_int,main_interact,FUZZ_INPUT,4096,trigger_Qemu_break
|
interact_int,main_interact,FUZZ_INPUT,4096,trigger_Qemu_break,
|
||||||
|
|
||||||
|
|
@ -34,6 +34,10 @@ pub struct Cli {
|
|||||||
#[arg(short='g', long)]
|
#[arg(short='g', long)]
|
||||||
pub dump_graph: bool,
|
pub dump_graph: bool,
|
||||||
|
|
||||||
|
/// select a task for measurments
|
||||||
|
#[arg(short='s', long)]
|
||||||
|
pub select_task: Option<String>,
|
||||||
|
|
||||||
#[command(subcommand)]
|
#[command(subcommand)]
|
||||||
pub command: Commands,
|
pub command: Commands,
|
||||||
}
|
}
|
||||||
|
@ -219,6 +219,7 @@ let app_range = app_start..app_end;
|
|||||||
let api_start = load_symbol(&elf, "__API_CODE_START__", false);
|
let api_start = load_symbol(&elf, "__API_CODE_START__", false);
|
||||||
let api_end = load_symbol(&elf, "__API_CODE_END__", false);
|
let api_end = load_symbol(&elf, "__API_CODE_END__", false);
|
||||||
let api_range = api_start..api_end;
|
let api_range = api_start..api_end;
|
||||||
|
let job_done_addr = load_symbol(&elf, "trigger_job_done", false);
|
||||||
|
|
||||||
let breakpoint = elf
|
let breakpoint = elf
|
||||||
.resolve_symbol(
|
.resolve_symbol(
|
||||||
@ -386,13 +387,13 @@ let run_client = |state: Option<_>, mut mgr, _core_id| {
|
|||||||
)}.track_indices();
|
)}.track_indices();
|
||||||
|
|
||||||
#[cfg(feature = "observe_systemstate")]
|
#[cfg(feature = "observe_systemstate")]
|
||||||
let systemstate_observer = QemuSystemStateObserver::new();
|
let systemstate_observer = QemuSystemStateObserver::new(&cli.select_task);
|
||||||
|
|
||||||
// Feedback to rate the interestingness of an input
|
// Feedback to rate the interestingness of an input
|
||||||
// This one is composed by two Feedbacks in OR
|
// This one is composed by two Feedbacks in OR
|
||||||
let mut feedback = feedback_or!(
|
let mut feedback = feedback_or!(
|
||||||
// Time feedback, this one does not need a feedback state
|
// Time feedback, this one does not need a feedback state
|
||||||
ClockTimeFeedback::new_with_observer(&clock_time_observer)
|
ClockTimeFeedback::new_with_observer(&clock_time_observer, &cli.select_task)
|
||||||
);
|
);
|
||||||
#[cfg(feature = "feed_genetic")]
|
#[cfg(feature = "feed_genetic")]
|
||||||
let mut feedback = feedback_or!(
|
let mut feedback = feedback_or!(
|
||||||
@ -465,7 +466,7 @@ let run_client = |state: Option<_>, mut mgr, _core_id| {
|
|||||||
|
|
||||||
let qhelpers = tuple_list!();
|
let qhelpers = tuple_list!();
|
||||||
#[cfg(feature = "observe_systemstate")]
|
#[cfg(feature = "observe_systemstate")]
|
||||||
let qhelpers = (QemuSystemStateHelper::new(api_addreses,api_ranges,isr_addreses,isr_ranges,input_addr..(input_addr+unsafe { MAX_INPUT_SIZE } as u32),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,input_addr..(input_addr+unsafe { MAX_INPUT_SIZE } as u32),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(), job_done_addr), qhelpers);
|
||||||
#[cfg(feature = "observe_edges")]
|
#[cfg(feature = "observe_edges")]
|
||||||
let qhelpers = (QemuEdgeCoverageHelper::new(denylist, QemuFilterList::None), qhelpers);
|
let qhelpers = (QemuEdgeCoverageHelper::new(denylist, QemuFilterList::None), qhelpers);
|
||||||
let qhelpers = (QemuStateRestoreHelper::with_fast(initial_snap), qhelpers);
|
let qhelpers = (QemuStateRestoreHelper::with_fast(initial_snap), qhelpers);
|
||||||
|
@ -3,6 +3,6 @@ mod fuzzer;
|
|||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
mod time;
|
mod time;
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
mod systemstate;
|
pub mod systemstate;
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
mod cli;
|
mod cli;
|
@ -60,6 +60,7 @@ pub struct NovelSystemStateFeedback
|
|||||||
impl<S> Feedback<S> for NovelSystemStateFeedback
|
impl<S> Feedback<S> for NovelSystemStateFeedback
|
||||||
where
|
where
|
||||||
S: State + UsesInput + MaybeHasClientPerfMonitor + HasNamedMetadata,
|
S: State + UsesInput + MaybeHasClientPerfMonitor + HasNamedMetadata,
|
||||||
|
S::Input: Default,
|
||||||
{
|
{
|
||||||
fn is_interesting<EM, OT>(
|
fn is_interesting<EM, OT>(
|
||||||
&mut self,
|
&mut self,
|
||||||
@ -71,9 +72,10 @@ where
|
|||||||
) -> Result<bool, Error>
|
) -> Result<bool, Error>
|
||||||
where
|
where
|
||||||
EM: EventFirer<State = S>,
|
EM: EventFirer<State = S>,
|
||||||
OT: ObserversTuple<S>
|
OT: ObserversTuple<S>,
|
||||||
|
S::Input: Default
|
||||||
{
|
{
|
||||||
let observer = observers.match_name::<QemuSystemStateObserver<S::Input>>("systemstate")
|
let observer : &QemuSystemStateObserver<S::Input> = observers.match_name::<QemuSystemStateObserver<S::Input>>("systemstate")
|
||||||
.expect("QemuSystemStateObserver not found");
|
.expect("QemuSystemStateObserver not found");
|
||||||
let clock_observer = observers.match_name::<QemuClockObserver>("clocktime") //TODO not fixed
|
let clock_observer = observers.match_name::<QemuClockObserver>("clocktime") //TODO not fixed
|
||||||
.expect("QemuClockObserver not found");
|
.expect("QemuClockObserver not found");
|
||||||
@ -81,12 +83,16 @@ where
|
|||||||
.named_metadata_map_mut()
|
.named_metadata_map_mut()
|
||||||
.get_mut::<SystemStateFeedbackState>("systemstate") {
|
.get_mut::<SystemStateFeedbackState>("systemstate") {
|
||||||
Some(s) => s,
|
Some(s) => s,
|
||||||
None => {
|
Option::None => {
|
||||||
let n=SystemStateFeedbackState::default();
|
let n=SystemStateFeedbackState::default();
|
||||||
state.named_metadata_map_mut().insert("systemstate",n);
|
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()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
#[cfg(feature = "trace_job_response_times")]
|
||||||
|
let last_runtime = observer.last_runtime();
|
||||||
|
#[cfg(not(feature = "trace_job_response_times"))]
|
||||||
|
let last_runtime = clock_observer.last_runtime();
|
||||||
// let feedbackstate = state
|
// let feedbackstate = state
|
||||||
// .feedback_states_mut()
|
// .feedback_states_mut()
|
||||||
// .match_name_mut::<systemstateFeedbackState>("systemstate")
|
// .match_name_mut::<systemstateFeedbackState>("systemstate")
|
||||||
@ -98,14 +104,14 @@ where
|
|||||||
let mut is_novel = false;
|
let mut is_novel = false;
|
||||||
let mut takes_longer = false;
|
let mut takes_longer = false;
|
||||||
match feedbackstate.known_traces.get_mut(&somehash) {
|
match feedbackstate.known_traces.get_mut(&somehash) {
|
||||||
None => {
|
Option::None => {
|
||||||
is_novel = true;
|
is_novel = true;
|
||||||
feedbackstate.known_traces.insert(somehash,(1,clock_observer.last_runtime(),observer.last_run.len()));
|
feedbackstate.known_traces.insert(somehash,(1,last_runtime,observer.last_run.len()));
|
||||||
}
|
}
|
||||||
Some(s) => {
|
Some(s) => {
|
||||||
s.0+=1;
|
s.0+=1;
|
||||||
if s.1 < clock_observer.last_runtime() {
|
if s.1 < last_runtime {
|
||||||
s.1 = clock_observer.last_runtime();
|
s.1 = last_runtime;
|
||||||
takes_longer = true;
|
takes_longer = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -124,7 +130,7 @@ where
|
|||||||
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)),
|
||||||
None => (),
|
Option::None => (),
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -186,10 +192,10 @@ where
|
|||||||
let names : Vec<String> = observer.last_run.iter().map(|x| x.current_task.task_name.clone()).collect();
|
let names : Vec<String> = observer.last_run.iter().map(|x| x.current_task.task_name.clone()).collect();
|
||||||
match &self.dumpfile {
|
match &self.dumpfile {
|
||||||
Some(s) => {
|
Some(s) => {
|
||||||
std::fs::write(s,ron::to_string(&(&observer.last_trace,&observer.last_states)).expect("Error serializing hashmap")).expect("Can not dump to file");
|
std::fs::write(s,ron::to_string(&(&observer.last_trace,&observer.last_states,&observer.job_instances)).expect("Error serializing hashmap")).expect("Can not dump to file");
|
||||||
self.dumpfile = None
|
self.dumpfile = None
|
||||||
},
|
},
|
||||||
None => if self.dump_metadata {println!("{:?}\n{:?}",observer.last_run,names);}
|
Option::None => if self.dump_metadata {println!("{:?}\n{:?}",observer.last_run,names);}
|
||||||
};
|
};
|
||||||
// if self.dump_metadata {self.last_trace=Some(observer.last_trace.clone());}
|
// if self.dump_metadata {self.last_trace=Some(observer.last_trace.clone());}
|
||||||
Ok(false)
|
Ok(false)
|
||||||
|
@ -111,6 +111,7 @@ pub struct QemuSystemStateHelper {
|
|||||||
critical_addr: GuestAddr,
|
critical_addr: GuestAddr,
|
||||||
input_counter: Option<GuestAddr>,
|
input_counter: Option<GuestAddr>,
|
||||||
app_range: Range<GuestAddr>,
|
app_range: Range<GuestAddr>,
|
||||||
|
job_done_addrs: GuestAddr,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl QemuSystemStateHelper {
|
impl QemuSystemStateHelper {
|
||||||
@ -130,6 +131,7 @@ impl QemuSystemStateHelper {
|
|||||||
critical_addr: GuestAddr,
|
critical_addr: GuestAddr,
|
||||||
input_counter: Option<GuestAddr>,
|
input_counter: Option<GuestAddr>,
|
||||||
app_range: Range<GuestAddr>,
|
app_range: Range<GuestAddr>,
|
||||||
|
job_done_addrs: GuestAddr,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
QemuSystemStateHelper {
|
QemuSystemStateHelper {
|
||||||
api_fn_addrs,
|
api_fn_addrs,
|
||||||
@ -146,6 +148,7 @@ impl QemuSystemStateHelper {
|
|||||||
critical_addr,
|
critical_addr,
|
||||||
input_counter: input_counter,
|
input_counter: input_counter,
|
||||||
app_range,
|
app_range,
|
||||||
|
job_done_addrs,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -165,6 +168,8 @@ where
|
|||||||
_hooks.instruction(*wp, Hook::Function(exec_isr_hook::<QT, S>), false);
|
_hooks.instruction(*wp, Hook::Function(exec_isr_hook::<QT, S>), false);
|
||||||
}
|
}
|
||||||
_hooks.jmps(Hook::Function(gen_jmp_is_syscall::<QT, S>), Hook::Function(trace_jmp::<QT, S>));
|
_hooks.jmps(Hook::Function(gen_jmp_is_syscall::<QT, S>), Hook::Function(trace_jmp::<QT, S>));
|
||||||
|
#[cfg(feature = "trace_job_response_times")]
|
||||||
|
_hooks.instruction(self.job_done_addrs, Hook::Function(job_done_hook::<QT, S>), false);
|
||||||
#[cfg(feature = "trace_reads")]
|
#[cfg(feature = "trace_reads")]
|
||||||
_hooks.reads(Hook::Function(gen_read_is_input::<QT, S>), Hook::Empty,Hook::Empty,Hook::Empty,Hook::Empty,Hook::Function(trace_reads::<QT, S>));
|
_hooks.reads(Hook::Function(gen_read_is_input::<QT, S>), Hook::Empty,Hook::Empty,Hook::Empty,Hook::Empty,Hook::Function(trace_reads::<QT, S>));
|
||||||
unsafe { INPUT_MEM = self.input_mem.clone() };
|
unsafe { INPUT_MEM = self.input_mem.clone() };
|
||||||
@ -314,6 +319,31 @@ fn trigger_collection(emulator: &libafl_qemu::Qemu, edge: (GuestAddr, GuestAddr)
|
|||||||
unsafe { CURRENT_SYSTEMSTATE_VEC.push(systemstate); }
|
unsafe { CURRENT_SYSTEMSTATE_VEC.push(systemstate); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//============================= Trace job response times
|
||||||
|
|
||||||
|
pub static mut JOBS_DONE : Vec<(u64, String)> = vec![];
|
||||||
|
|
||||||
|
pub fn job_done_hook<QT, S>(
|
||||||
|
hooks: &mut QemuHooks<QT, S>,
|
||||||
|
_state: Option<&mut S>,
|
||||||
|
_pc: GuestAddr,
|
||||||
|
)
|
||||||
|
where
|
||||||
|
S: UsesInput,
|
||||||
|
QT: QemuHelperTuple<S>,
|
||||||
|
{
|
||||||
|
let emulator = hooks.qemu();
|
||||||
|
let h = hooks.helpers().match_first_type::<QemuSystemStateHelper>().expect("QemuSystemHelper not found in helper tupel");
|
||||||
|
let curr_tcb_addr : freertos::void_ptr = freertos::emu_lookup::lookup(emulator, h.tcb_addr);
|
||||||
|
if curr_tcb_addr == 0 {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let current_tcb : TCB_t = freertos::emu_lookup::lookup(emulator,curr_tcb_addr);
|
||||||
|
let tmp = unsafe {std::mem::transmute::<[i8; 10],[u8; 10]>(current_tcb.pcTaskName)};
|
||||||
|
let name : String = std::str::from_utf8(&tmp).expect("TCB name was not utf8").chars().filter(|x| *x != '\0').collect::<String>();
|
||||||
|
unsafe { JOBS_DONE.push((get_icount(emulator), name)); }
|
||||||
|
}
|
||||||
|
|
||||||
//============================= Trace interrupt service routines
|
//============================= Trace interrupt service routines
|
||||||
|
|
||||||
pub fn exec_isr_hook<QT, S>(
|
pub fn exec_isr_hook<QT, S>(
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use libafl::prelude::ExitKind;
|
use libafl::prelude::ExitKind;
|
||||||
use libafl::prelude::UsesInput;
|
use libafl::prelude::UsesInput;
|
||||||
|
use libafl::HasMetadata;
|
||||||
use libafl_bolts::HasLen;
|
use libafl_bolts::HasLen;
|
||||||
use libafl_bolts::Named;
|
use libafl_bolts::Named;
|
||||||
use libafl::Error;
|
use libafl::Error;
|
||||||
@ -7,6 +8,9 @@ use libafl::observers::Observer;
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use hashbrown::{HashMap, HashSet};
|
use hashbrown::{HashMap, HashSet};
|
||||||
use crate::systemstate::CaptureEvent;
|
use crate::systemstate::CaptureEvent;
|
||||||
|
use crate::time::clock::IcHist;
|
||||||
|
use crate::time::clock::FUZZ_START_TIMESTAMP;
|
||||||
|
use std::time::SystemTime;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
@ -19,6 +23,7 @@ use super::{
|
|||||||
RefinedTCB,
|
RefinedTCB,
|
||||||
ReducedFreeRTOSSystemState,
|
ReducedFreeRTOSSystemState,
|
||||||
freertos::{List_t, TCB_t, rtos_struct, rtos_struct::*},
|
freertos::{List_t, TCB_t, rtos_struct, rtos_struct::*},
|
||||||
|
helpers::JOBS_DONE,
|
||||||
};
|
};
|
||||||
|
|
||||||
//============================= Observer
|
//============================= Observer
|
||||||
@ -34,13 +39,17 @@ pub struct QemuSystemStateObserver<I>
|
|||||||
pub last_trace: Vec<ExecInterval>,
|
pub last_trace: Vec<ExecInterval>,
|
||||||
pub last_reads: Vec<HashSet<u32>>,
|
pub last_reads: Vec<HashSet<u32>>,
|
||||||
pub last_input: I,
|
pub last_input: I,
|
||||||
|
pub job_instances: Vec<(u64, u64, String)>,
|
||||||
|
pub worst_job_instances: HashMap<String, u64>,
|
||||||
|
pub select_task: Option<String>,
|
||||||
pub success: bool,
|
pub success: bool,
|
||||||
name: Cow<'static, str>,
|
name: Cow<'static, str>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S> Observer<S> for QemuSystemStateObserver<S::Input>
|
impl<S> Observer<S> for QemuSystemStateObserver<S::Input>
|
||||||
where
|
where
|
||||||
S: UsesInput,
|
S: UsesInput + HasMetadata,
|
||||||
|
S::Input: Default
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn pre_exec(&mut self, _state: &mut S, _input: &S::Input) -> Result<(), Error> {
|
fn pre_exec(&mut self, _state: &mut S, _input: &S::Input) -> Result<(), Error> {
|
||||||
@ -61,7 +70,46 @@ where
|
|||||||
self.last_reads = temp.1;
|
self.last_reads = temp.1;
|
||||||
self.last_states = temp.2;
|
self.last_states = temp.2;
|
||||||
self.success = temp.3;
|
self.success = temp.3;
|
||||||
// println!("{:?}",temp);
|
#[cfg(feature="trace_job_response_times")]
|
||||||
|
{
|
||||||
|
let metadata =_state.metadata_map_mut();
|
||||||
|
let releases = get_releases(&self.last_trace, &self.last_states);
|
||||||
|
// println!("Releases: {:?}",&releases);
|
||||||
|
let jobs_done = JOBS_DONE.split_off(0);
|
||||||
|
self.job_instances = get_release_response_pairs(&releases, &jobs_done);
|
||||||
|
// println!("Instances: {:?}",&self.job_instances);
|
||||||
|
let observer = &self;
|
||||||
|
let mut worst_case_per_task = HashMap::new();
|
||||||
|
observer.job_instances.iter().for_each(|x| {
|
||||||
|
let time = (x.1-x.0);
|
||||||
|
if worst_case_per_task.get(&x.2).is_some() {
|
||||||
|
let old = worst_case_per_task.get_mut(&x.2).unwrap();
|
||||||
|
if time > *old {
|
||||||
|
*old=time;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
worst_case_per_task.insert(x.2.clone(), time);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
self.worst_job_instances = worst_case_per_task;
|
||||||
|
// copy-paste form clock observer
|
||||||
|
{
|
||||||
|
let hist = metadata.get_mut::<IcHist>();
|
||||||
|
let timestamp = SystemTime::now().duration_since(unsafe {FUZZ_START_TIMESTAMP}).unwrap().as_millis();
|
||||||
|
match hist {
|
||||||
|
Option::None => {
|
||||||
|
metadata.insert(IcHist(vec![(self.last_runtime(), timestamp)],
|
||||||
|
(self.last_runtime(), timestamp)));
|
||||||
|
}
|
||||||
|
Some(v) => {
|
||||||
|
v.0.push((self.last_runtime(), timestamp));
|
||||||
|
if v.1.0 < self.last_runtime() {
|
||||||
|
v.1 = (self.last_runtime(), timestamp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// let abbs = extract_abbs_from_trace(&self.last_run);
|
// let abbs = extract_abbs_from_trace(&self.last_run);
|
||||||
// println!("{:?}",abbs);
|
// println!("{:?}",abbs);
|
||||||
@ -89,14 +137,17 @@ impl<I> HasLen for QemuSystemStateObserver<I>
|
|||||||
|
|
||||||
impl<I> QemuSystemStateObserver<I>
|
impl<I> QemuSystemStateObserver<I>
|
||||||
where I: Default {
|
where I: Default {
|
||||||
pub fn new() -> Self {
|
pub fn new(select_task: &Option<String>) -> Self {
|
||||||
Self{last_run: vec![], last_trace: vec![], last_reads: vec![], last_input: I::default(), name: Cow::from("systemstate".to_string()), last_states: HashMap::new(), success: false }
|
Self{last_run: vec![], last_trace: vec![], last_reads: vec![], last_input: I::default(), worst_job_instances: HashMap::new(), select_task: select_task.clone(), name: Cow::from("systemstate".to_string()), last_states: HashMap::new(), success: false, job_instances: vec![]}
|
||||||
|
}
|
||||||
|
pub fn last_runtime(&self) -> u64 {
|
||||||
|
self.select_task.as_ref().map(|x| self.worst_job_instances.get(x).unwrap_or(&unsafe{libafl_qemu::sys::icount_get_raw()}).clone()).unwrap_or(unsafe{libafl_qemu::sys::icount_get_raw()})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<I> Default for QemuSystemStateObserver<I>
|
impl<I> Default for QemuSystemStateObserver<I>
|
||||||
where I: Default {
|
where I: Default {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self::new()
|
Self::new(&None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -167,6 +218,75 @@ fn refine_system_states(mut input: Vec<RawFreeRTOSSystemState>) -> (Vec<ReducedF
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Find all task release times. A release is SysTickHandler isr block that moves a task from the delay list to the ready list
|
||||||
|
fn get_releases(tarce: &Vec<ExecInterval>, states: &HashMap<u64, ReducedFreeRTOSSystemState>) -> Vec<(u64, String)> {
|
||||||
|
let mut ret = Vec::new();
|
||||||
|
let mut initial_released = false;
|
||||||
|
for (_n, i) in tarce.iter().enumerate() {
|
||||||
|
if !initial_released && i.start_capture.0 == CaptureEvent::ISREnd && i.start_capture.1 == "xPortPendSVHandler" {
|
||||||
|
let start_state = states.get(&i.start_state).expect("State not found");
|
||||||
|
initial_released = true;
|
||||||
|
start_state.ready_list_after.iter().for_each(|x| {
|
||||||
|
ret.push((i.start_tick, x.task_name.clone()));
|
||||||
|
});
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if i.start_capture.0 == CaptureEvent::ISRStart && ( i.start_capture.1 == "xPortSysTickHandler" || i.start_capture.1 == "isr_starter" ) && i.end_capture.0 == CaptureEvent::ISREnd {
|
||||||
|
let start_state = states.get(&i.start_state).expect("State not found");
|
||||||
|
let end_state = states.get(&i.end_state).expect("State not found");
|
||||||
|
end_state.ready_list_after.iter().for_each(|x| {
|
||||||
|
if x.task_name != end_state.current_task.task_name && x.task_name != start_state.current_task.task_name && !start_state.ready_list_after.iter().any(|y| x.task_name == y.task_name) {
|
||||||
|
ret.push((i.end_tick, x.task_name.clone()));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// start_state.delay_list_after.iter().for_each(|x| {
|
||||||
|
// if !end_state.delay_list_after.iter().any(|y| x.task_name == y.task_name) {
|
||||||
|
// ret.push((i.end_tick, x.task_name.clone()));
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ret
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_release_response_pairs(rel: &Vec<(u64, String)>, resp: &Vec<(u64, String)>) -> Vec<(u64, u64, String)> {
|
||||||
|
let mut ret = Vec::new();
|
||||||
|
let mut ready : HashMap<&String, u64> = HashMap::new();
|
||||||
|
let mut r = rel.iter().peekable();
|
||||||
|
let mut d = resp.iter().peekable();
|
||||||
|
loop {
|
||||||
|
while let Some(peek_rel) = r.peek() {
|
||||||
|
if !ready.contains_key(&peek_rel.1) {
|
||||||
|
ready.insert(&peek_rel.1, peek_rel.0);
|
||||||
|
r.next();
|
||||||
|
} else {
|
||||||
|
if let Some(peek_resp) = d.peek() {
|
||||||
|
if peek_resp.0 >= peek_rel.0 { // multiple releases before respopnse, only use the latest release
|
||||||
|
eprintln!("Task {} released multiple times before response", peek_rel.1);
|
||||||
|
ready.insert(&peek_rel.1, peek_rel.0);
|
||||||
|
r.next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Some(peek_resp) = d.next() {
|
||||||
|
if ready.contains_key(&peek_resp.1) {
|
||||||
|
assert!(peek_resp.0 >= ready[&peek_resp.1]);
|
||||||
|
ret.push((ready[&peek_resp.1], peek_resp.0, peek_resp.1.clone()));
|
||||||
|
ready.remove(&peek_resp.1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
eprintln!("Task {} not found in ready list", peek_resp.1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// TODO: should remaining released tasks be counted as finished?
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Transform the states and metadata into a list of ExecIntervals, along with a HashMap of states, a list of HashSets marking memory reads and a bool indicating success
|
/// Transform the states and metadata into a list of ExecIntervals, along with a HashMap of states, a list of HashSets marking memory reads and a bool indicating success
|
||||||
fn states2intervals(trace: Vec<ReducedFreeRTOSSystemState>, meta: Vec<(u64, CaptureEvent, String, (u32, u32), HashSet<u32>)>) -> (Vec<ExecInterval>, Vec<HashSet<u32>>, HashMap<u64, ReducedFreeRTOSSystemState>, bool) {
|
fn states2intervals(trace: Vec<ReducedFreeRTOSSystemState>, meta: Vec<(u64, CaptureEvent, String, (u32, u32), HashSet<u32>)>) -> (Vec<ExecInterval>, Vec<HashSet<u32>>, HashMap<u64, ReducedFreeRTOSSystemState>, bool) {
|
||||||
if trace.len() == 0 {return (Vec::new(), Vec::new(), HashMap::new(), true);}
|
if trace.len() == 0 {return (Vec::new(), Vec::new(), HashMap::new(), true);}
|
||||||
|
@ -490,6 +490,7 @@ impl StgFeedback {
|
|||||||
impl<S> Feedback<S> for StgFeedback
|
impl<S> Feedback<S> for StgFeedback
|
||||||
where
|
where
|
||||||
S: State + UsesInput + MaybeHasClientPerfMonitor + HasNamedMetadata,
|
S: State + UsesInput + MaybeHasClientPerfMonitor + HasNamedMetadata,
|
||||||
|
S::Input: Default,
|
||||||
{
|
{
|
||||||
#[allow(clippy::wrong_self_convention)]
|
#[allow(clippy::wrong_self_convention)]
|
||||||
fn is_interesting<EM, OT>(
|
fn is_interesting<EM, OT>(
|
||||||
@ -503,11 +504,16 @@ where
|
|||||||
where
|
where
|
||||||
EM: EventFirer<State = S>,
|
EM: EventFirer<State = S>,
|
||||||
OT: ObserversTuple<S>,
|
OT: ObserversTuple<S>,
|
||||||
|
S::Input: Default,
|
||||||
{
|
{
|
||||||
let observer = observers.match_name::<QemuSystemStateObserver<S::Input>>("systemstate")
|
let observer = observers.match_name::<QemuSystemStateObserver<S::Input>>("systemstate")
|
||||||
.expect("QemuSystemStateObserver not found");
|
.expect("QemuSystemStateObserver not found");
|
||||||
let clock_observer = observers.match_name::<QemuClockObserver>("clocktime")
|
let clock_observer = observers.match_name::<QemuClockObserver>("clocktime")
|
||||||
.expect("QemuClockObserver not found");
|
.expect("QemuClockObserver not found");
|
||||||
|
#[cfg(feature = "trace_job_response_times")]
|
||||||
|
let last_runtime = observer.last_runtime();
|
||||||
|
#[cfg(not(feature = "trace_job_response_times"))]
|
||||||
|
let last_runtime = clock_observer.last_runtime();
|
||||||
let feedbackstate = match state
|
let feedbackstate = match state
|
||||||
.named_metadata_map_mut()
|
.named_metadata_map_mut()
|
||||||
.get_mut::<STGFeedbackState>("stgfeedbackstate") {
|
.get_mut::<STGFeedbackState>("stgfeedbackstate") {
|
||||||
@ -524,13 +530,13 @@ where
|
|||||||
{
|
{
|
||||||
let h = get_generic_hash(&edgetrace);
|
let h = get_generic_hash(&edgetrace);
|
||||||
if let Some(x) = feedbackstate.worst_observed_per_stg_path.get_mut(&h) {
|
if let Some(x) = feedbackstate.worst_observed_per_stg_path.get_mut(&h) {
|
||||||
let t = clock_observer.last_runtime();
|
let t = last_runtime;
|
||||||
if t > *x {
|
if t > *x {
|
||||||
*x = t;
|
*x = t;
|
||||||
interesting |= INTEREST_PATH;
|
interesting |= INTEREST_PATH;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
feedbackstate.worst_observed_per_stg_path.insert(h, clock_observer.last_runtime());
|
feedbackstate.worst_observed_per_stg_path.insert(h, last_runtime);
|
||||||
updated = true;
|
updated = true;
|
||||||
interesting |= INTEREST_PATH;
|
interesting |= INTEREST_PATH;
|
||||||
}
|
}
|
||||||
@ -543,13 +549,13 @@ where
|
|||||||
self.last_abbs_hash = Some(h);
|
self.last_abbs_hash = Some(h);
|
||||||
// order of execution is relevant
|
// order of execution is relevant
|
||||||
if let Some(x) = feedbackstate.worst_observed_per_abb_path.get_mut(&h) {
|
if let Some(x) = feedbackstate.worst_observed_per_abb_path.get_mut(&h) {
|
||||||
let t = clock_observer.last_runtime();
|
let t = last_runtime;
|
||||||
if t > *x {
|
if t > *x {
|
||||||
*x = t;
|
*x = t;
|
||||||
interesting |= INTEREST_ABBPATH;
|
interesting |= INTEREST_ABBPATH;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
feedbackstate.worst_observed_per_abb_path.insert(h, clock_observer.last_runtime());
|
feedbackstate.worst_observed_per_abb_path.insert(h, last_runtime);
|
||||||
interesting |= INTEREST_ABBPATH;
|
interesting |= INTEREST_ABBPATH;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -574,13 +580,13 @@ where
|
|||||||
|
|
||||||
self.last_aggregate_hash = Some(get_generic_hash(&_tmp));
|
self.last_aggregate_hash = Some(get_generic_hash(&_tmp));
|
||||||
if let Some(x) = feedbackstate.worst_observed_per_aggegated_path.get_mut(&_tmp) {
|
if let Some(x) = feedbackstate.worst_observed_per_aggegated_path.get_mut(&_tmp) {
|
||||||
let t = clock_observer.last_runtime();
|
let t = last_runtime;
|
||||||
if t > *x {
|
if t > *x {
|
||||||
*x = t;
|
*x = t;
|
||||||
interesting |= INTEREST_AGGREGATE;
|
interesting |= INTEREST_AGGREGATE;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
feedbackstate.worst_observed_per_aggegated_path.insert(_tmp, clock_observer.last_runtime());
|
feedbackstate.worst_observed_per_aggegated_path.insert(_tmp, last_runtime);
|
||||||
interesting |= INTEREST_AGGREGATE;
|
interesting |= INTEREST_AGGREGATE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
use hashbrown::HashMap;
|
||||||
use libafl_bolts::Named;
|
use libafl_bolts::Named;
|
||||||
use libafl::{
|
use libafl::{
|
||||||
executors::ExitKind,
|
executors::ExitKind,
|
||||||
@ -21,6 +22,8 @@ use std::time::{SystemTime, UNIX_EPOCH};
|
|||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
||||||
|
use crate::systemstate::observers::QemuSystemStateObserver;
|
||||||
|
|
||||||
pub static mut FUZZ_START_TIMESTAMP : SystemTime = UNIX_EPOCH;
|
pub static mut FUZZ_START_TIMESTAMP : SystemTime = UNIX_EPOCH;
|
||||||
|
|
||||||
pub const QEMU_ICOUNT_SHIFT : u32 = 5;
|
pub const QEMU_ICOUNT_SHIFT : u32 = 5;
|
||||||
@ -140,15 +143,23 @@ where
|
|||||||
let hist = metadata.get_mut::<IcHist>();
|
let hist = metadata.get_mut::<IcHist>();
|
||||||
let timestamp = SystemTime::now().duration_since(unsafe {FUZZ_START_TIMESTAMP}).unwrap().as_millis();
|
let timestamp = SystemTime::now().duration_since(unsafe {FUZZ_START_TIMESTAMP}).unwrap().as_millis();
|
||||||
match hist {
|
match hist {
|
||||||
None => {
|
Option::None => {
|
||||||
|
#[cfg(not(feature="trace_job_response_times"))]
|
||||||
|
{
|
||||||
metadata.insert(IcHist(vec![(self.end_tick - self.start_tick, timestamp)],
|
metadata.insert(IcHist(vec![(self.end_tick - self.start_tick, timestamp)],
|
||||||
(self.end_tick - self.start_tick, timestamp)));
|
(self.end_tick - self.start_tick, timestamp)));
|
||||||
}
|
}
|
||||||
|
#[cfg(feature="trace_job_response_times")]
|
||||||
|
metadata.insert(IcHist(vec![],(0,timestamp)));
|
||||||
|
}
|
||||||
Some(v) => {
|
Some(v) => {
|
||||||
|
#[cfg(not(feature="trace_job_response_times"))]
|
||||||
|
{
|
||||||
v.0.push((self.end_tick - self.start_tick, timestamp));
|
v.0.push((self.end_tick - self.start_tick, timestamp));
|
||||||
if v.1.0 < self.end_tick-self.start_tick {
|
if v.1.0 < self.end_tick-self.start_tick {
|
||||||
v.1 = (self.end_tick - self.start_tick, timestamp);
|
v.1 = (self.end_tick - self.start_tick, timestamp);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if v.0.len() >= 100 {
|
if v.0.len() >= 100 {
|
||||||
let mut file = OpenOptions::new()
|
let mut file = OpenOptions::new()
|
||||||
.read(true)
|
.read(true)
|
||||||
@ -193,6 +204,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>,
|
||||||
|
select_task: Option<String>,
|
||||||
name: Cow<'static, str>,
|
name: Cow<'static, str>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -213,6 +225,19 @@ where
|
|||||||
EM: EventFirer<State = S>,
|
EM: EventFirer<State = S>,
|
||||||
OT: ObserversTuple<S>,
|
OT: ObserversTuple<S>,
|
||||||
{
|
{
|
||||||
|
#[cfg(feature="trace_job_response_times")]
|
||||||
|
{
|
||||||
|
if let Some(t) = &self.select_task {
|
||||||
|
let observer = observers.match_name::<QemuSystemStateObserver<S::Input>>("systemstate").unwrap();
|
||||||
|
if let Some(time) = observer.worst_job_instances.get(t) {
|
||||||
|
self.exec_time = Some(Duration::from_nanos(*time));
|
||||||
|
return Ok(true);
|
||||||
|
} else {
|
||||||
|
self.exec_time = Some(Duration::from_nanos(0));
|
||||||
|
return Ok(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
// TODO Replace with match_name_type when stable
|
// TODO Replace with match_name_type when stable
|
||||||
let observer = observers.match_name::<QemuClockObserver>(self.name()).unwrap();
|
let observer = observers.match_name::<QemuClockObserver>(self.name()).unwrap();
|
||||||
self.exec_time = Some(Duration::from_nanos(observer.last_runtime() << QEMU_ICOUNT_SHIFT)); // Assume a somewhat realistic multiplier of clock, it does not matter
|
self.exec_time = Some(Duration::from_nanos(observer.last_runtime() << QEMU_ICOUNT_SHIFT)); // Assume a somewhat realistic multiplier of clock, it does not matter
|
||||||
@ -251,18 +276,20 @@ impl Named for ClockTimeFeedback {
|
|||||||
impl ClockTimeFeedback {
|
impl ClockTimeFeedback {
|
||||||
/// Creates a new [`ClockFeedback`], deciding if the value of a [`QemuClockObserver`] with the given `name` of a run is interesting.
|
/// Creates a new [`ClockFeedback`], deciding if the value of a [`QemuClockObserver`] with the given `name` of a run is interesting.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn new(name: &'static str) -> Self {
|
pub fn new(name: &'static str, select_task: Option<String>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
exec_time: None,
|
exec_time: None,
|
||||||
|
select_task: select_task,
|
||||||
name: Cow::from(name.to_string()),
|
name: Cow::from(name.to_string()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new [`ClockFeedback`], deciding if the given [`QemuClockObserver`] value of a run is interesting.
|
/// Creates a new [`ClockFeedback`], deciding if the given [`QemuClockObserver`] value of a run is interesting.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn new_with_observer(observer: &QemuClockObserver) -> Self {
|
pub fn new_with_observer(observer: &QemuClockObserver, select_task: &Option<String>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
exec_time: None,
|
exec_time: None,
|
||||||
|
select_task: select_task.clone(),
|
||||||
name: observer.name().clone(),
|
name: observer.name().clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user