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::GuestAddr;
|
||||
use libafl_qemu::GuestPhysAddr;
|
||||
use libafl_qemu::GuestReg;
|
||||
use libafl_qemu::QemuHooks;
|
||||
use libafl_qemu::edges::QemuEdgesMapMetadata;
|
||||
use libafl_qemu::emu;
|
||||
use libafl_qemu::hooks;
|
||||
use libafl_qemu::Hook;
|
||||
use crate::systemstate::extract_abbs_from_trace;
|
||||
use crate::systemstate::RawFreeRTOSSystemState;
|
||||
use crate::systemstate::CURRENT_SYSTEMSTATE_VEC;
|
||||
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) {
|
||||
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
|
||||
use std::collections::hash_map::DefaultHasher;
|
||||
use std::fmt;
|
||||
use hashbrown::HashSet;
|
||||
use libafl_bolts::HasRefCnt;
|
||||
use libafl_bolts::AsSlice;
|
||||
use libafl_qemu::GuestAddr;
|
||||
@ -195,3 +197,144 @@ impl HasRefCnt for 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