save last post interrupt edge in app
This commit is contained in:
parent
e8b24b0c7a
commit
47a4bc19d4
@ -269,6 +269,16 @@ fn fuzz(
|
|||||||
.expect("Symbol xPortPendSVHandler not found");
|
.expect("Symbol xPortPendSVHandler not found");
|
||||||
let svh = virt2phys(svh,&elf.goblin());
|
let svh = virt2phys(svh,&elf.goblin());
|
||||||
println!("PendHandle at {:#x}", svh);
|
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,
|
&mut harness,
|
||||||
&emu,
|
&emu,
|
||||||
tuple_list!(
|
tuple_list!(
|
||||||
QemuEdgeCoverageHelper::new(),
|
QemuEdgeCoverageHelper::with_app_range(app_range),
|
||||||
// QemuCmpLogHelper::new(),
|
// QemuCmpLogHelper::new(),
|
||||||
// QemuAsanHelper::new(),
|
// QemuAsanHelper::new(),
|
||||||
QemuSysSnapshotHelper::new(),
|
QemuSysSnapshotHelper::new(),
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
use libafl_qemu::edges::QemuEdgesMapMetadata;
|
||||||
use crate::sysstate::RawFreeRTOSSystemState;
|
use crate::sysstate::RawFreeRTOSSystemState;
|
||||||
use crate::sysstate::CURRENT_SYSSTATE_VEC;
|
use crate::sysstate::CURRENT_SYSSTATE_VEC;
|
||||||
use crate::sysstate::NUM_PRIOS;
|
use crate::sysstate::NUM_PRIOS;
|
||||||
@ -11,6 +12,7 @@ use libafl_qemu::{
|
|||||||
emu::Emulator,
|
emu::Emulator,
|
||||||
executor::QemuExecutor,
|
executor::QemuExecutor,
|
||||||
helper::{QemuHelper, QemuHelperTuple, QemuInstrumentationFilter},
|
helper::{QemuHelper, QemuHelperTuple, QemuInstrumentationFilter},
|
||||||
|
edges::SAVED_JUMP,
|
||||||
};
|
};
|
||||||
|
|
||||||
//============================= Struct definitions
|
//============================= Struct definitions
|
||||||
@ -78,7 +80,7 @@ where
|
|||||||
pub fn exec_syscall_hook<I, QT, S>(
|
pub fn exec_syscall_hook<I, QT, S>(
|
||||||
emulator: &Emulator,
|
emulator: &Emulator,
|
||||||
helpers: &mut QT,
|
helpers: &mut QT,
|
||||||
_state: &mut S,
|
state: &mut S,
|
||||||
pc: u64,
|
pc: u64,
|
||||||
)
|
)
|
||||||
where
|
where
|
||||||
@ -99,6 +101,25 @@ where
|
|||||||
|
|
||||||
let curr_tcb_addr : freertos::void_ptr = freertos::emu_lookup::lookup(emulator, h.tcb_addr);
|
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);
|
sysstate.current_tcb = freertos::emu_lookup::lookup(emulator,curr_tcb_addr);
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
match SAVED_JUMP {
|
||||||
|
Some(s) => {
|
||||||
|
let meta = state
|
||||||
|
.metadata_mut()
|
||||||
|
.get::<QemuEdgesMapMetadata>()
|
||||||
|
.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));
|
// println!("{:?}",std::str::from_utf8(¤t_tcb.pcTaskName));
|
||||||
|
|
||||||
for i in 0..NUM_PRIOS {
|
for i in 0..NUM_PRIOS {
|
||||||
|
@ -27,6 +27,7 @@ pub struct RawFreeRTOSSystemState {
|
|||||||
prio_ready_lists: [freertos::List_t; NUM_PRIOS],
|
prio_ready_lists: [freertos::List_t; NUM_PRIOS],
|
||||||
dumping_ground: HashMap<u32,freertos::rtos_struct>,
|
dumping_ground: HashMap<u32,freertos::rtos_struct>,
|
||||||
input_counter: u32,
|
input_counter: u32,
|
||||||
|
last_pc: Option<u64>,
|
||||||
}
|
}
|
||||||
/// List of system state dumps from QemuHelpers
|
/// List of system state dumps from QemuHelpers
|
||||||
static mut CURRENT_SYSSTATE_VEC: Vec<RawFreeRTOSSystemState> = vec![];
|
static mut CURRENT_SYSSTATE_VEC: Vec<RawFreeRTOSSystemState> = vec![];
|
||||||
@ -88,13 +89,15 @@ impl RefinedTCB {
|
|||||||
pub struct RefinedFreeRTOSSystemState {
|
pub struct RefinedFreeRTOSSystemState {
|
||||||
start_tick: u64,
|
start_tick: u64,
|
||||||
end_tick: u64,
|
end_tick: u64,
|
||||||
|
last_pc: Option<u64>,
|
||||||
input_counter: u32,
|
input_counter: u32,
|
||||||
current_task: RefinedTCB,
|
current_task: RefinedTCB,
|
||||||
ready_list_after: Vec<RefinedTCB>,
|
ready_list_after: Vec<RefinedTCB>,
|
||||||
}
|
}
|
||||||
impl PartialEq for RefinedFreeRTOSSystemState {
|
impl PartialEq for RefinedFreeRTOSSystemState {
|
||||||
fn eq(&self, other: &Self) -> bool {
|
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<H: Hasher>(&self, state: &mut H) {
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
self.current_task.hash(state);
|
self.current_task.hash(state);
|
||||||
self.ready_list_after.hash(state);
|
self.ready_list_after.hash(state);
|
||||||
|
self.last_pc.hash(state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl RefinedFreeRTOSSystemState {
|
impl RefinedFreeRTOSSystemState {
|
||||||
|
@ -130,6 +130,7 @@ for mut i in input.drain(..) {
|
|||||||
end_tick: i.qemu_tick,
|
end_tick: i.qemu_tick,
|
||||||
ready_list_after: collector,
|
ready_list_after: collector,
|
||||||
input_counter: i.input_counter,
|
input_counter: i.input_counter,
|
||||||
|
last_pc: i.last_pc,
|
||||||
});
|
});
|
||||||
start_tick=i.qemu_tick;
|
start_tick=i.qemu_tick;
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
use std::ops::Range;
|
||||||
use hashbrown::{hash_map::Entry, HashMap};
|
use hashbrown::{hash_map::Entry, HashMap};
|
||||||
use libafl::{executors::ExitKind, inputs::Input, observers::ObserversTuple, state::HasMetadata};
|
use libafl::{executors::ExitKind, inputs::Input, observers::ObserversTuple, state::HasMetadata};
|
||||||
pub use libafl_targets::{EDGES_MAP, EDGES_MAP_SIZE, MAX_EDGES_NUM};
|
pub use libafl_targets::{EDGES_MAP, EDGES_MAP_SIZE, MAX_EDGES_NUM};
|
||||||
@ -31,6 +32,7 @@ libafl::impl_serdeany!(QemuEdgesMapMetadata);
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct QemuEdgeCoverageHelper {
|
pub struct QemuEdgeCoverageHelper {
|
||||||
filter: QemuInstrumentationFilter,
|
filter: QemuInstrumentationFilter,
|
||||||
|
app_range: Option<Range<u64>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl QemuEdgeCoverageHelper {
|
impl QemuEdgeCoverageHelper {
|
||||||
@ -38,18 +40,37 @@ impl QemuEdgeCoverageHelper {
|
|||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
filter: QemuInstrumentationFilter::None,
|
filter: QemuInstrumentationFilter::None,
|
||||||
|
app_range: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn with_instrumentation_filter(filter: QemuInstrumentationFilter) -> Self {
|
pub fn with_instrumentation_filter(filter: QemuInstrumentationFilter, app_range: Option<Range<u64>>) -> Self {
|
||||||
Self { filter }
|
Self { filter, app_range }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn with_app_range(app_range: Range<u64>) -> Self {
|
||||||
|
Self { filter: QemuInstrumentationFilter::None, app_range: Some(app_range) }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn must_instrument(&self, addr: u64) -> bool {
|
pub fn must_instrument(&self, addr: u64) -> bool {
|
||||||
self.filter.allowed(addr)
|
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 {
|
impl Default for QemuEdgeCoverageHelper {
|
||||||
@ -70,7 +91,14 @@ where
|
|||||||
QT: QemuHelperTuple<I, S>,
|
QT: QemuHelperTuple<I, S>,
|
||||||
{
|
{
|
||||||
executor.hook_edge_generation(gen_unique_edge_ids::<I, QT, S>);
|
executor.hook_edge_generation(gen_unique_edge_ids::<I, QT, S>);
|
||||||
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
|
x
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub static mut MUST_SAVE: [bool; EDGES_MAP_SIZE] = [false; EDGES_MAP_SIZE];
|
||||||
|
pub static mut SAVED_JUMP: Option<u64> = None;
|
||||||
|
|
||||||
pub fn gen_unique_edge_ids<I, QT, S>(
|
pub fn gen_unique_edge_ids<I, QT, S>(
|
||||||
_emulator: &Emulator,
|
_emulator: &Emulator,
|
||||||
helpers: &mut QT,
|
helpers: &mut QT,
|
||||||
@ -95,10 +126,12 @@ where
|
|||||||
I: Input,
|
I: Input,
|
||||||
QT: QemuHelperTuple<I, S>,
|
QT: QemuHelperTuple<I, S>,
|
||||||
{
|
{
|
||||||
|
let mut must_save = false;
|
||||||
if let Some(h) = helpers.match_first_type::<QemuEdgeCoverageHelper>() {
|
if let Some(h) = helpers.match_first_type::<QemuEdgeCoverageHelper>() {
|
||||||
if !h.must_instrument(src) && !h.must_instrument(dest) {
|
if !h.must_instrument(src) && !h.must_instrument(dest) {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
must_save = h.must_save(src, dest);
|
||||||
}
|
}
|
||||||
if state.metadata().get::<QemuEdgesMapMetadata>().is_none() {
|
if state.metadata().get::<QemuEdgesMapMetadata>().is_none() {
|
||||||
state.add_metadata(QemuEdgesMapMetadata::new());
|
state.add_metadata(QemuEdgesMapMetadata::new());
|
||||||
@ -114,6 +147,9 @@ where
|
|||||||
let nxt = (id as usize + 1) & (EDGES_MAP_SIZE - 1);
|
let nxt = (id as usize + 1) & (EDGES_MAP_SIZE - 1);
|
||||||
unsafe {
|
unsafe {
|
||||||
MAX_EDGES_NUM = max(MAX_EDGES_NUM, nxt);
|
MAX_EDGES_NUM = max(MAX_EDGES_NUM, nxt);
|
||||||
|
if must_save {
|
||||||
|
MUST_SAVE[id as usize] = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Some(id)
|
Some(id)
|
||||||
}
|
}
|
||||||
@ -123,6 +159,9 @@ where
|
|||||||
meta.current_id = (id + 1) & (EDGES_MAP_SIZE as u64 - 1);
|
meta.current_id = (id + 1) & (EDGES_MAP_SIZE as u64 - 1);
|
||||||
unsafe {
|
unsafe {
|
||||||
MAX_EDGES_NUM = meta.current_id as usize;
|
MAX_EDGES_NUM = meta.current_id as usize;
|
||||||
|
if must_save {
|
||||||
|
MUST_SAVE[id as usize] = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Some(id as u64)
|
Some(id as u64)
|
||||||
}
|
}
|
||||||
@ -148,6 +187,14 @@ where
|
|||||||
Some(hash_me(src) ^ hash_me(dest))
|
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) {
|
pub extern "C" fn trace_edge_hitcount(id: u64) {
|
||||||
unsafe {
|
unsafe {
|
||||||
EDGES_MAP[id as usize] = EDGES_MAP[id as usize].wrapping_add(1);
|
EDGES_MAP[id as usize] = EDGES_MAP[id as usize].wrapping_add(1);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user