From eabfe020b6f7cf4947e2c19fb52bedb2e6c2e934 Mon Sep 17 00:00:00 2001 From: Alwin Berger Date: Wed, 1 Jun 2022 22:09:39 +0200 Subject: [PATCH] update info duming and makefile --- fuzzers/wcet_qemu_sys/Cargo.toml | 1 + fuzzers/wcet_qemu_sys/Makefile | 56 +++++++----- fuzzers/wcet_qemu_sys/src/bin/fuzzer.rs | 108 +++++++++++++++++++++--- 3 files changed, 132 insertions(+), 33 deletions(-) diff --git a/fuzzers/wcet_qemu_sys/Cargo.toml b/fuzzers/wcet_qemu_sys/Cargo.toml index f9b49b3ba7..6dd9dfd9ff 100644 --- a/fuzzers/wcet_qemu_sys/Cargo.toml +++ b/fuzzers/wcet_qemu_sys/Cargo.toml @@ -33,6 +33,7 @@ muta_snip = [ "sched_graph" ] muta_suffix = [ "sched_graph" ] benchmark = [] # don't save corpus to disk, easy parallelizable +dump_infos = [] # dump select corpus items for analysis [profile.release] debug = true diff --git a/fuzzers/wcet_qemu_sys/Makefile b/fuzzers/wcet_qemu_sys/Makefile index 67cc9b4307..d119027b56 100644 --- a/fuzzers/wcet_qemu_sys/Makefile +++ b/fuzzers/wcet_qemu_sys/Makefile @@ -2,45 +2,57 @@ BENCHDIR = target/bench TARGET = tmr.axf TARGET_TRACE = $(BENCHDIR)/traces/tmr_worst.ron TARGET_EDGES = $(BENCHDIR)/edges/tmr_worst.ron +RUNTIME = 1 $(BENCHDIR)/bin: mkdir -p $@ -$(BENCHDIR)/target_known_edges: $(BENCHDIR)/bin - cargo build --bin fuzzer --target-dir $@ --features benchmark,feed_known_edges,sched_queue,obj_edges +$(BENCHDIR)/target_known_edges: + cargo build --bin fuzzer --target-dir $@ --features benchmark,dump_infos,feed_known_edges,sched_queue -$(BENCHDIR)/target_vanilla: $(BENCHDIR)/bin - cargo build --bin fuzzer --target-dir $@ --features benchmark,feed_afl,sched_mapmax +$(BENCHDIR)/target_afl_queue: + cargo build --bin fuzzer --target-dir $@ --features benchmark,dump_infos,feed_afl,sched_queue -$(BENCHDIR)/target_state: $(BENCHDIR)/bin - cargo build --bin fuzzer --target-dir $@ --features benchmark,feed_state,sched_state +$(BENCHDIR)/target_afl_mapmax: + cargo build --bin fuzzer --target-dir $@ --features benchmark,dump_infos,feed_afl,sched_mapmax -$(BENCHDIR)/target_graph: $(BENCHDIR)/bin - cargo build --bin fuzzer --target-dir $@ --features benchmark,feed_graph,sched_graph +$(BENCHDIR)/target_state: + cargo build --bin fuzzer --target-dir $@ --features benchmark,dump_infos,feed_state,sched_state -$(BENCHDIR)/target_graph_snip: $(BENCHDIR)/bin - cargo build --bin fuzzer --target-dir $@ --features benchmark,feed_graph,sched_graph,muta_snip,muta_input,muta_suffix +$(BENCHDIR)/target_state_afl: + cargo build --bin fuzzer --target-dir $@ --features benchmark,dump_infos,feed_state,sched_state -$(BENCHDIR)/target_graph_afl: $(BENCHDIR)/bin - cargo build --bin fuzzer --target-dir $@ --features benchmark,feed_graph,sched_graph,feed_afl +$(BENCHDIR)/target_graph: + cargo build --bin fuzzer --target-dir $@ --features benchmark,dump_infos,feed_graph,sched_graph -$(BENCHDIR)/target_graph_all: $(BENCHDIR)/bin - cargo build --bin fuzzer --target-dir $@ --features benchmark,feed_graph,sched_graph,feed_afl,muta_snip,muta_input,muta_suffix +$(BENCHDIR)/target_graph_muta: + cargo build --bin fuzzer --target-dir $@ --features benchmark,dump_infos,feed_graph,sched_graph,muta_snip,muta_input,muta_suffix -binaries: $(BENCHDIR)/target_known_edges $(BENCHDIR)/target_vanilla $(BENCHDIR)/target_state $(BENCHDIR)/target_graph $(BENCHDIR)/target_graph_snip $(BENCHDIR)/target_graph_afl $(BENCHDIR)/target_graph_all +$(BENCHDIR)/target_graph_afl: + cargo build --bin fuzzer --target-dir $@ --features benchmark,dump_infos,feed_graph,sched_graph,feed_afl -# variants: vanilla, state, graph, graph_snip, graph_afl, 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 + +binaries: $(BENCHDIR)/target_known_edges $(BENCHDIR)/target_afl_queue $(BENCHDIR)/target_afl_mapmax $(BENCHDIR)/target_state $(BENCHDIR)/target_state_afl \ + $(BENCHDIR)/target_graph $(BENCHDIR)/target_graph_muta $(BENCHDIR)/target_graph_afl $(BENCHDIR)/target_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) - for i in {1..10}; do \ + mkdir -p $(BENCHDIR)/execs + for i in {1..3}; do \ CASE=$$(basename -s.log $@ | cut -d'_' -f 2- ); \ - echo $$CASE Iteration $$i; \ - ./fuzzer_bench.sh $ $@_$$i; \ - sed -i "1 i\\$$CASE " $(BENCHDIR)/bench_$$CASE\_$$i.exec; \ + echo $$CASE iteration $$i; \ + mkdir -p $(BENCHDIR)/infos/$$CASE ; \ + ./fuzzer_bench.sh $ $@_$$i; \ + sed -i "1 i\\$$CASE " $(BENCHDIR)/execs/$$CASE\_$$i.exec; \ done for i in $@_*; do tail -n 1 $$i >> $@; done -benchmarks: target/bench/bench_known_edges.log target/bench/bench_vanilla.log target/bench/bench_state.log target/bench/bench_graph.log target/bench/bench_graph_snip.log target/bench/bench_graph_afl.log target/bench/bench_graph_all.log +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 \ + target/bench/bench_graph.log target/bench/bench_graph_muta.log target/bench/bench_graph_afl.log target/bench/bench_graph_all.log all: binaries benchmarks diff --git a/fuzzers/wcet_qemu_sys/src/bin/fuzzer.rs b/fuzzers/wcet_qemu_sys/src/bin/fuzzer.rs index b05b0922b2..efef1d896a 100644 --- a/fuzzers/wcet_qemu_sys/src/bin/fuzzer.rs +++ b/fuzzers/wcet_qemu_sys/src/bin/fuzzer.rs @@ -1,5 +1,11 @@ //! A singlethreaded QEMU fuzzer that can auto-restart. - +use std::str::FromStr; +use wcet_qemu_sys::worst::DumpEdgesMapMetadata; +use wcet_qemu_sys::worst::DumpMapFeedback; +use libafl::inputs::HasBytesVec; +use wcet_qemu_sys::sysstate::FreeRTOSSystemStateMetadata; +use wcet_qemu_sys::sysstate::feedbacks::DumpSystraceFeedback; +use libafl::state::HasSolutions; use wcet_qemu_sys::worst::TimeMaximizerCorpusScheduler; use libafl::corpus::InMemoryCorpus; use wcet_qemu_sys::sysstate::graph::RandGraphSuffixMutator; @@ -172,6 +178,21 @@ pub fn main() { .long("libafl-targettime") .takes_value(true), ) + .arg( + Arg::new("dump") + .long("libafl-dump") + .takes_value(true), + ) + .arg( + Arg::new("fuzztime") + .long("libafl-fuzztime") + .takes_value(true), + ) + .arg( + Arg::new("graphdump") + .long("libafl-graphdump") + .takes_value(true), + ) .try_get_matches_from(filter_qemu_args()) { Ok(res) => res, @@ -246,7 +267,22 @@ pub fn main() { let snapshot = PathBuf::from(res.value_of("snapshot").unwrap().to_string()); - fuzz(out_dir, crashes, in_dir, tokens, logfile, timeout, kernel, edges, traces, exectimes, targettime, snapshot) + let dump_path = match res.value_of("dump") { + Some(st) => Some(PathBuf::from(st.to_string())), + None => None + }; + + let fuzztime = match res.value_of("fuzztime") { + Some(st) => Some(u64::from_str(st).expect("Failed parsing fuzztime")), + None => None + }; + + let graph_dump = match res.value_of("graphdump") { + Some(st) => Some(PathBuf::from(st.to_string())), + None => None + }; + + fuzz(out_dir, crashes, in_dir, tokens, logfile, timeout, kernel, edges, traces, exectimes, targettime, snapshot, dump_path, fuzztime, graph_dump) .expect("An error occurred while fuzzing"); } @@ -277,6 +313,9 @@ fn fuzz( dump_exectimes: Option, targettime: Option, snapshot: PathBuf, + dump_path: Option, + fuzztime: Option, + graph_dump: Option, ) -> Result<(), Error> { env::remove_var("LD_LIBRARY_PATH"); @@ -377,11 +416,11 @@ fn fuzz( #[cfg(not(feature = "sched_state"))] let sysstate_feedback_state = SysGraphFeedbackState::new(); - let target_map : HashMap<(u64,u64),u8> = match dump_edges { + let target_map : HashMap<(u64,u64),u16> = match dump_edges { None => HashMap::new(), Some(ref s) => { let raw = fs::read(s).expect("Can not read dumped edges"); - let hmap : HashMap<(u64,u64),u8> = ron::from_str(&String::from_utf8_lossy(&raw)).expect("Can not parse HashMap"); + let hmap : HashMap<(u64,u64),u16> = ron::from_str(&String::from_utf8_lossy(&raw)).expect("Can not parse HashMap"); hmap }, }; @@ -395,6 +434,10 @@ fn fuzz( }; // Feedback to rate the interestingness of an input let feedback = ClockFeedback::new_with_observer(&clock_observer); + #[cfg(all(not(feature = "feed_state"), feature = "dump_infos"))] // for diagnostic purposes it's necessary to collect the state in any case + let feedback = feedback_or!(feedback, DumpSystraceFeedback::metadata_only()); + #[cfg(feature = "dump_infos")] // for diagnostic purposes it's necessary to collect the state in any case + let feedback = feedback_or!(feedback, DumpMapFeedback::metadata_only(&edges_observer)); #[cfg(feature = "feed_known_edges")] let feedback = feedback_or!(feedback, HitImprovingFeedback::new(target_map.clone(), &edges_observer)); #[cfg(feature = "feed_afl")] @@ -579,12 +622,14 @@ fn fuzz( dup2(null_fd, io::stderr().as_raw_fd())?; } - fuzzer - .fuzz_for_solution_or_n(&mut stages, &mut executor, &mut state, &mut mgr, 10000) - .expect("Error in the fuzzing loop"); - // fuzzer - // .fuzz_loop_for(&mut stages, &mut executor, &mut state, &mut mgr, 20) - // .expect("Error in the fuzzing loop"); + match fuzztime { + Some(t) => fuzzer + .fuzz_for_solution_or_n(&mut stages, &mut executor, &mut state, &mut mgr, t) + .expect("Error in the fuzzing loop"), + None => fuzzer + .fuzz_for_solution(&mut stages, &mut executor, &mut state, &mut mgr) + .expect("Error in the fuzzing loop"), + }; #[cfg(not(feature = "benchmark"))] @@ -599,7 +644,10 @@ fn fuzz( |_, e| e, ); let tempg = format!("{:?}",Dot::with_config(&newgraph, &[Config::EdgeNoLabel])); - fs::write("./graph.dot",tempg).expect("Graph can not be written"); + match graph_dump { + Some(gd) => fs::write(gd,tempg).expect("Graph can not be written"), + None => (), + } } // Wite out the collected exec times @@ -615,6 +663,44 @@ fn fuzz( None => (), } + #[cfg(feature = "dump_infos")] + { + println!("Start dumping {}", state.corpus().count()); + let c = if state.solutions().count()>0 { state.solutions() } else { state.corpus() }; + let mut worst = Duration::new(0,0); + let mut worst_input : Option> = Some(vec![]); + let mut worst_trace : Option = None; + let mut worst_map : Option = None; + for i in 0..c.count() { + let tc = c.get(i).expect("Could not get element from corpus").borrow(); + if worst < tc.exec_time().expect("Testcase missing duration") { + worst = tc.exec_time().expect("Testcase missing duration"); + let metadata = tc.metadata(); + worst_trace = metadata.get::().cloned(); + worst_map = metadata.get::().cloned(); + worst_input = Some(tc.input().as_ref().unwrap().bytes().to_owned()); + } + } + let mut dump_path = dump_path; + match &mut dump_path { + Some(dp) => { + dp.set_extension("trace"); + println!("Path found: {:?}",dp); + fs::write(&dp,ron::to_string(&worst_trace).expect("Error serializing Trace")).expect("Exec times can not be written"); + dp.set_extension("map"); + println!("Path found: {:?}",dp); + fs::write(&dp,ron::to_string(&worst_map).expect("Error serializing hashmap")).expect("Exec times can not be written"); + dp.set_extension("input"); + println!("Path found: {:?}",dp); + fs::write(&dp,worst_input.unwrap()); + dp.set_extension("time"); + println!("Path found: {:?}",dp); + fs::write(&dp,format!("{}",worst.as_nanos()>>3)); + }, + None => (), + } + } + // Never reached Ok(())