extract ABBs
This commit is contained in:
parent
a045b7bcd6
commit
6793d48dbd
@ -7,11 +7,13 @@ use libafl::prelude::UsesInput;
|
|||||||
use libafl_qemu::Emulator;
|
use libafl_qemu::Emulator;
|
||||||
use libafl_qemu::GuestAddr;
|
use libafl_qemu::GuestAddr;
|
||||||
use libafl_qemu::GuestPhysAddr;
|
use libafl_qemu::GuestPhysAddr;
|
||||||
|
use libafl_qemu::GuestReg;
|
||||||
use libafl_qemu::QemuHooks;
|
use libafl_qemu::QemuHooks;
|
||||||
use libafl_qemu::edges::QemuEdgesMapMetadata;
|
use libafl_qemu::edges::QemuEdgesMapMetadata;
|
||||||
use libafl_qemu::emu;
|
use libafl_qemu::emu;
|
||||||
use libafl_qemu::hooks;
|
use libafl_qemu::hooks;
|
||||||
use libafl_qemu::Hook;
|
use libafl_qemu::Hook;
|
||||||
|
use crate::systemstate::extract_abbs_from_trace;
|
||||||
use crate::systemstate::RawFreeRTOSSystemState;
|
use crate::systemstate::RawFreeRTOSSystemState;
|
||||||
use crate::systemstate::CURRENT_SYSTEMSTATE_VEC;
|
use crate::systemstate::CURRENT_SYSTEMSTATE_VEC;
|
||||||
use crate::systemstate::NUM_PRIOS;
|
use crate::systemstate::NUM_PRIOS;
|
||||||
@ -152,6 +154,27 @@ where
|
|||||||
|
|
||||||
fn post_exec<OT>(&mut self, emulator: &Emulator, _input: &S::Input, _observers: &mut OT, _exit_kind: &mut ExitKind) {
|
fn post_exec<OT>(&mut self, emulator: &Emulator, _input: &S::Input, _observers: &mut OT, _exit_kind: &mut ExitKind) {
|
||||||
trigger_collection(emulator,(None, None), self);
|
trigger_collection(emulator,(None, None), self);
|
||||||
|
unsafe {
|
||||||
|
let c = emulator.cpu_from_index(0);
|
||||||
|
let pc = c.read_reg::<i32, u32>(15).unwrap();;
|
||||||
|
CURRENT_SYSTEMSTATE_VEC[CURRENT_SYSTEMSTATE_VEC.len()-1].edge = (Some(pc),None);
|
||||||
|
CURRENT_SYSTEMSTATE_VEC[CURRENT_SYSTEMSTATE_VEC.len()-1].capture_point = (CaptureEvent::End,"Breakpoint");
|
||||||
|
}
|
||||||
|
// Find the first ISREnd of vPortSVCHandler and drop anything before
|
||||||
|
unsafe {
|
||||||
|
let mut index = 0;
|
||||||
|
while index < CURRENT_SYSTEMSTATE_VEC.len() {
|
||||||
|
if CaptureEvent::ISREnd == CURRENT_SYSTEMSTATE_VEC[index].capture_point.0 && CURRENT_SYSTEMSTATE_VEC[index].capture_point.1 == "xPortPendSVHandler" {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
index += 1;
|
||||||
|
}
|
||||||
|
CURRENT_SYSTEMSTATE_VEC.drain(..index);
|
||||||
|
}
|
||||||
|
unsafe {
|
||||||
|
let abbs = extract_abbs_from_trace(&CURRENT_SYSTEMSTATE_VEC);
|
||||||
|
println!("{:?}", abbs);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
//! systemstate referes to the State of a FreeRTOS fuzzing target
|
//! systemstate referes to the State of a FreeRTOS fuzzing target
|
||||||
use std::collections::hash_map::DefaultHasher;
|
use std::collections::hash_map::DefaultHasher;
|
||||||
|
use std::fmt;
|
||||||
|
use hashbrown::HashSet;
|
||||||
use libafl_bolts::HasRefCnt;
|
use libafl_bolts::HasRefCnt;
|
||||||
use libafl_bolts::AsSlice;
|
use libafl_bolts::AsSlice;
|
||||||
use libafl_qemu::GuestAddr;
|
use libafl_qemu::GuestAddr;
|
||||||
@ -195,3 +197,144 @@ impl HasRefCnt for FreeRTOSSystemStateMetadata {
|
|||||||
}
|
}
|
||||||
|
|
||||||
libafl_bolts::impl_serdeany!(FreeRTOSSystemStateMetadata);
|
libafl_bolts::impl_serdeany!(FreeRTOSSystemStateMetadata);
|
||||||
|
|
||||||
|
#[derive(Default, Serialize, Deserialize, Clone)]
|
||||||
|
pub struct AtomicBasicBlock {
|
||||||
|
start: GuestAddr,
|
||||||
|
ends: HashSet<GuestAddr>,
|
||||||
|
}
|
||||||
|
impl fmt::Display for AtomicBasicBlock {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
let mut ends_str = String::new();
|
||||||
|
for end in &self.ends {
|
||||||
|
ends_str.push_str(&format!("0x{:#x}, ", end));
|
||||||
|
}
|
||||||
|
write!(f, "AtomicBasicBlock {{ start: 0x{:#x}, ends: [{}]}}", self.start, ends_str.trim().trim_matches(','))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl fmt::Debug for AtomicBasicBlock {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
let mut ends_str = String::new();
|
||||||
|
for end in &self.ends {
|
||||||
|
ends_str.push_str(&format!("{:#x}, ", end));
|
||||||
|
}
|
||||||
|
write!(f, "AtomicBasicBlock {{ start: {:#x}, ends: [{}]}}", self.start, ends_str.trim().trim_matches(','))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
fn get_task_names(trace: &Vec<RefinedFreeRTOSSystemState>) -> HashSet<String> {
|
||||||
|
let mut ret: HashSet<_, _> = HashSet::new();
|
||||||
|
for state in trace {
|
||||||
|
ret.insert(state.current_task.0.task_name.to_string());
|
||||||
|
}
|
||||||
|
ret
|
||||||
|
}
|
||||||
|
|
||||||
|
fn extract_abbs_from_trace(trace: &Vec<RawFreeRTOSSystemState>) -> HashMap<String,Vec<AtomicBasicBlock>> {
|
||||||
|
let mut abbs_of_task : HashMap<String, Vec<AtomicBasicBlock>> = HashMap::new();
|
||||||
|
let mut last_abb_of_task : HashMap<String, usize> = HashMap::new();
|
||||||
|
// iterate over all states and extract atomic basic blocks
|
||||||
|
// an atomic base block has a single entry and multiple exits
|
||||||
|
// the cuts between blocks are api calls
|
||||||
|
// when capture_point is APIEnd, the destination of the edge is the start of an atomic block
|
||||||
|
// so the next APIStart with the same current_tcb.pcTaskName is the end of the atomic block
|
||||||
|
for i in 0..trace.len() {
|
||||||
|
let tmp = unsafe { std::mem::transmute::<[i8; 10],[u8; 10]>(trace[i].current_tcb.pcTaskName) };
|
||||||
|
let curr_name : String = std::str::from_utf8(&tmp).expect("TCB name was not utf8").chars().filter(|x| *x != '\0').collect::<String>();
|
||||||
|
let last : Option<&usize> = last_abb_of_task.get(&curr_name);
|
||||||
|
match trace[i].capture_point.0 {
|
||||||
|
CaptureEvent::APIStart => {
|
||||||
|
// end the last atomic block
|
||||||
|
if let Some(&l) = last {
|
||||||
|
let start = trace[l].edge.1.unwrap();
|
||||||
|
let end = trace[i].edge.0.unwrap();
|
||||||
|
match abbs_of_task.get_mut(&curr_name) {
|
||||||
|
Some(v) => {
|
||||||
|
match v.iter_mut().find(|x| x.start==start) {
|
||||||
|
Some(abb) => {
|
||||||
|
abb.ends.insert(end);
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
let mut t = HashSet::new();
|
||||||
|
t.insert(end);
|
||||||
|
v.push(AtomicBasicBlock {start, ends: t});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
let mut v = Vec::new();
|
||||||
|
let mut t = HashSet::new();
|
||||||
|
t.insert(end);
|
||||||
|
v.push(AtomicBasicBlock {start, ends: t});
|
||||||
|
abbs_of_task.insert(curr_name, v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// first API call of this task
|
||||||
|
let mut v = Vec::new();
|
||||||
|
let mut t = HashSet::new();
|
||||||
|
let end = trace[i].edge.0.unwrap();
|
||||||
|
t.insert(end);
|
||||||
|
v.push(AtomicBasicBlock {start: 0, ends: t});
|
||||||
|
abbs_of_task.insert(curr_name, v);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
CaptureEvent::APIEnd => {
|
||||||
|
match last {
|
||||||
|
Some(&l) => {
|
||||||
|
//assert!(trace[l].capture_point.0 == CaptureEvent::APIStart);
|
||||||
|
},
|
||||||
|
None => (),
|
||||||
|
}
|
||||||
|
last_abb_of_task.insert(curr_name, i);
|
||||||
|
},
|
||||||
|
CaptureEvent::ISRStart => {
|
||||||
|
},
|
||||||
|
CaptureEvent::ISREnd => {
|
||||||
|
},
|
||||||
|
CaptureEvent::End => {
|
||||||
|
// end the last atomic block
|
||||||
|
if let Some(&l) = last {
|
||||||
|
let start = trace[l].edge.1.unwrap();
|
||||||
|
let end = trace[i].edge.0.unwrap();
|
||||||
|
match abbs_of_task.get_mut(&curr_name) {
|
||||||
|
Some(v) => {
|
||||||
|
match v.iter_mut().find(|x| x.start==start) {
|
||||||
|
Some(abb) => {
|
||||||
|
abb.ends.insert(end);
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
let mut t = HashSet::new();
|
||||||
|
t.insert(end);
|
||||||
|
v.push(AtomicBasicBlock {start, ends: t});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
let mut v = Vec::new();
|
||||||
|
let mut t = HashSet::new();
|
||||||
|
t.insert(end);
|
||||||
|
v.push(AtomicBasicBlock {start, ends: t});
|
||||||
|
abbs_of_task.insert(curr_name, v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// first API call of this task
|
||||||
|
let mut v = Vec::new();
|
||||||
|
let mut t = HashSet::new();
|
||||||
|
let end = trace[i].edge.0.unwrap();
|
||||||
|
t.insert(end);
|
||||||
|
v.push(AtomicBasicBlock {start: 0, ends: t});
|
||||||
|
abbs_of_task.insert(curr_name, v);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
CaptureEvent::Undefined => {
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
abbs_of_task
|
||||||
|
}
|
||||||
|
|
||||||
|
libafl_bolts::impl_serdeany!(AtomicBasicBlock);
|
Loading…
x
Reference in New Issue
Block a user