diff --git a/fuzzers/wcet_qemu_sys/src/bin/showmap.rs b/fuzzers/wcet_qemu_sys/src/bin/showmap.rs index ab30216796..0888b33cee 100644 --- a/fuzzers/wcet_qemu_sys/src/bin/showmap.rs +++ b/fuzzers/wcet_qemu_sys/src/bin/showmap.rs @@ -269,6 +269,16 @@ fn fuzz( .expect("Symbol xPortPendSVHandler not found"); let svh = virt2phys(svh,&elf.goblin()); println!("PendHandle at {:#x}", svh); + let app_code_start = elf + .resolve_symbol("__APP_CODE_START__", 0) + .expect("Symbol __APP_CODE_START__ not found"); + let app_code_start = virt2phys(app_code_start,&elf.goblin()); + let app_code_end = elf + .resolve_symbol("__APP_CODE_END__", 0) + .expect("Symbol __APP_CODE_END__ not found"); + let app_code_end = virt2phys(app_code_end,&elf.goblin()); + let app_range = app_code_start..app_code_end; + println!("App Code {:x}-{:x}",app_code_start,app_code_end); @@ -349,7 +359,7 @@ fn fuzz( &mut harness, &emu, tuple_list!( - QemuEdgeCoverageHelper::new(), + QemuEdgeCoverageHelper::with_app_range(app_range), // QemuCmpLogHelper::new(), // QemuAsanHelper::new(), QemuSysSnapshotHelper::new(), diff --git a/fuzzers/wcet_qemu_sys/src/sysstate/helpers.rs b/fuzzers/wcet_qemu_sys/src/sysstate/helpers.rs index 793081dc6c..30c4b4fa52 100644 --- a/fuzzers/wcet_qemu_sys/src/sysstate/helpers.rs +++ b/fuzzers/wcet_qemu_sys/src/sysstate/helpers.rs @@ -1,3 +1,4 @@ +use libafl_qemu::edges::QemuEdgesMapMetadata; use crate::sysstate::RawFreeRTOSSystemState; use crate::sysstate::CURRENT_SYSSTATE_VEC; use crate::sysstate::NUM_PRIOS; @@ -11,6 +12,7 @@ use libafl_qemu::{ emu::Emulator, executor::QemuExecutor, helper::{QemuHelper, QemuHelperTuple, QemuInstrumentationFilter}, + edges::SAVED_JUMP, }; //============================= Struct definitions @@ -78,7 +80,7 @@ where pub fn exec_syscall_hook( emulator: &Emulator, helpers: &mut QT, - _state: &mut S, + state: &mut S, pc: u64, ) where @@ -99,6 +101,25 @@ where let curr_tcb_addr : freertos::void_ptr = freertos::emu_lookup::lookup(emulator, h.tcb_addr); sysstate.current_tcb = freertos::emu_lookup::lookup(emulator,curr_tcb_addr); + + unsafe { + match SAVED_JUMP { + Some(s) => { + let meta = state + .metadata_mut() + .get::() + .unwrap(); + for (k,v) in meta.map.iter() { + if *v==s { + // println!("Jump Saved {:x}",k.1); + sysstate.last_pc = Some(k.1); /* Currently save APP entry points */ + break; + } + } + }, + None => (), + } + } // println!("{:?}",std::str::from_utf8(¤t_tcb.pcTaskName)); for i in 0..NUM_PRIOS { diff --git a/fuzzers/wcet_qemu_sys/src/sysstate/mod.rs b/fuzzers/wcet_qemu_sys/src/sysstate/mod.rs index cd97a928a7..16649c61be 100644 --- a/fuzzers/wcet_qemu_sys/src/sysstate/mod.rs +++ b/fuzzers/wcet_qemu_sys/src/sysstate/mod.rs @@ -27,6 +27,7 @@ pub struct RawFreeRTOSSystemState { prio_ready_lists: [freertos::List_t; NUM_PRIOS], dumping_ground: HashMap, input_counter: u32, + last_pc: Option, } /// List of system state dumps from QemuHelpers static mut CURRENT_SYSSTATE_VEC: Vec = vec![]; @@ -88,13 +89,15 @@ impl RefinedTCB { pub struct RefinedFreeRTOSSystemState { start_tick: u64, end_tick: u64, + last_pc: Option, input_counter: u32, current_task: RefinedTCB, ready_list_after: Vec, } impl PartialEq for RefinedFreeRTOSSystemState { fn eq(&self, other: &Self) -> bool { - self.current_task == other.current_task && self.ready_list_after == other.ready_list_after + self.current_task == other.current_task && self.ready_list_after == other.ready_list_after && + self.last_pc == other.last_pc } } @@ -102,6 +105,7 @@ impl Hash for RefinedFreeRTOSSystemState { fn hash(&self, state: &mut H) { self.current_task.hash(state); self.ready_list_after.hash(state); + self.last_pc.hash(state); } } impl RefinedFreeRTOSSystemState { diff --git a/fuzzers/wcet_qemu_sys/src/sysstate/observers.rs b/fuzzers/wcet_qemu_sys/src/sysstate/observers.rs index fc7ff1c6a2..3328cc1db0 100644 --- a/fuzzers/wcet_qemu_sys/src/sysstate/observers.rs +++ b/fuzzers/wcet_qemu_sys/src/sysstate/observers.rs @@ -130,6 +130,7 @@ for mut i in input.drain(..) { end_tick: i.qemu_tick, ready_list_after: collector, input_counter: i.input_counter, + last_pc: i.last_pc, }); start_tick=i.qemu_tick; } diff --git a/libafl_qemu/src/edges.rs b/libafl_qemu/src/edges.rs index 7da9b452f8..545d337470 100644 --- a/libafl_qemu/src/edges.rs +++ b/libafl_qemu/src/edges.rs @@ -1,3 +1,4 @@ +use std::ops::Range; use hashbrown::{hash_map::Entry, HashMap}; use libafl::{executors::ExitKind, inputs::Input, observers::ObserversTuple, state::HasMetadata}; pub use libafl_targets::{EDGES_MAP, EDGES_MAP_SIZE, MAX_EDGES_NUM}; @@ -31,6 +32,7 @@ libafl::impl_serdeany!(QemuEdgesMapMetadata); #[derive(Debug)] pub struct QemuEdgeCoverageHelper { filter: QemuInstrumentationFilter, + app_range: Option>, } impl QemuEdgeCoverageHelper { @@ -38,18 +40,37 @@ impl QemuEdgeCoverageHelper { pub fn new() -> Self { Self { filter: QemuInstrumentationFilter::None, + app_range: None, } } #[must_use] - pub fn with_instrumentation_filter(filter: QemuInstrumentationFilter) -> Self { - Self { filter } + pub fn with_instrumentation_filter(filter: QemuInstrumentationFilter, app_range: Option>) -> Self { + Self { filter, app_range } + } + + #[must_use] + pub fn with_app_range(app_range: Range) -> Self { + Self { filter: QemuInstrumentationFilter::None, app_range: Some(app_range) } } #[must_use] pub fn must_instrument(&self, addr: u64) -> bool { self.filter.allowed(addr) } + + #[must_use] + pub fn must_save(&self, src: u64, dst: u64) -> bool { + match &self.app_range { + None => false, + Some(s) => { + // println!("must_save {} {:x} {:x}",s.contains(&src) != s.contains(&dst),src,dst); + // s.contains(&src) && !s.contains(&dst) + // println!("must_save {} {:x} {:x}",src==0&&dst!=0x9cc,src,dst); + src==0&&dst!=0x9cc + }, + } + } } impl Default for QemuEdgeCoverageHelper { @@ -70,7 +91,14 @@ where QT: QemuHelperTuple, { executor.hook_edge_generation(gen_unique_edge_ids::); - executor.emulator().set_exec_edge_hook(trace_edge_hitcount); + match self.app_range { + None => executor.emulator().set_exec_edge_hook(trace_edge_hitcount), + Some(_) => executor.emulator().set_exec_edge_hook(trace_edge_hitcount_and_app_range), + } + } + + fn pre_exec(&mut self, _emulator: &Emulator, _input: &I) { + unsafe { SAVED_JUMP=None; } } } @@ -83,6 +111,9 @@ fn hash_me(mut x: u64) -> u64 { x } +pub static mut MUST_SAVE: [bool; EDGES_MAP_SIZE] = [false; EDGES_MAP_SIZE]; +pub static mut SAVED_JUMP: Option = None; + pub fn gen_unique_edge_ids( _emulator: &Emulator, helpers: &mut QT, @@ -95,10 +126,12 @@ where I: Input, QT: QemuHelperTuple, { + let mut must_save = false; if let Some(h) = helpers.match_first_type::() { if !h.must_instrument(src) && !h.must_instrument(dest) { return None; } + must_save = h.must_save(src, dest); } if state.metadata().get::().is_none() { state.add_metadata(QemuEdgesMapMetadata::new()); @@ -114,6 +147,9 @@ where let nxt = (id as usize + 1) & (EDGES_MAP_SIZE - 1); unsafe { MAX_EDGES_NUM = max(MAX_EDGES_NUM, nxt); + if must_save { + MUST_SAVE[id as usize] = true; + } } Some(id) } @@ -123,6 +159,9 @@ where meta.current_id = (id + 1) & (EDGES_MAP_SIZE as u64 - 1); unsafe { MAX_EDGES_NUM = meta.current_id as usize; + if must_save { + MUST_SAVE[id as usize] = true; + } } Some(id as u64) } @@ -148,6 +187,14 @@ where Some(hash_me(src) ^ hash_me(dest)) } + +pub extern "C" fn trace_edge_hitcount_and_app_range(id: u64) { + unsafe { + if MUST_SAVE[id as usize] { SAVED_JUMP=Some(id); } + EDGES_MAP[id as usize] = EDGES_MAP[id as usize].wrapping_add(1); + } +} + pub extern "C" fn trace_edge_hitcount(id: u64) { unsafe { EDGES_MAP[id as usize] = EDGES_MAP[id as usize].wrapping_add(1);