timeshift variable, handle nested isr+api, bump max_interrupts

This commit is contained in:
Alwin Berger 2024-06-06 14:39:45 +02:00
parent c7bf1be8b1
commit b9e388d9d5
5 changed files with 420 additions and 379 deletions

View File

@ -40,6 +40,16 @@ use std::path::PathBuf;
pub static mut FUZZ_START_TIMESTAMP : SystemTime = UNIX_EPOCH; pub static mut FUZZ_START_TIMESTAMP : SystemTime = UNIX_EPOCH;
pub const QEMU_ICOUNT_SHIFT : u32 = 5;
pub const QEMU_ISNS_PER_SEC : u32 = u32::pow(10, 9) / u32::pow(2, QEMU_ICOUNT_SHIFT);
pub const QEMU_ISNS_PER_USEC : u32 = QEMU_ISNS_PER_SEC / 1000000;
pub const QEMU_NS_PER_ISN : u32 = 1 << QEMU_ICOUNT_SHIFT;
pub const TARGET_SYSCLK_FREQ : u32 = 25 * 1000 * 1000;
pub const TARGET_MHZ_PER_MIPS : f32 = TARGET_SYSCLK_FREQ as f32 / QEMU_ISNS_PER_SEC as f32;
pub const TARGET_MIPS_PER_MHZ : f32 = QEMU_ISNS_PER_SEC as f32 / TARGET_SYSCLK_FREQ as f32;
pub const TARGET_SYSCLK_PER_QEMU_SEC : u32 = (TARGET_SYSCLK_FREQ as f32 * TARGET_MIPS_PER_MHZ) as u32;
pub const QEMU_SYSCLK_PER_TARGET_SEC : u32 = (TARGET_SYSCLK_FREQ as f32 * TARGET_MHZ_PER_MIPS) as u32;
//========== Metadata //========== Metadata
#[derive(Debug, SerdeAny, Serialize, Deserialize)] #[derive(Debug, SerdeAny, Serialize, Deserialize)]
pub struct QemuIcountMetadata { pub struct QemuIcountMetadata {
@ -222,7 +232,7 @@ where
{ {
// TODO Replace with match_name_type when stable // TODO Replace with match_name_type when stable
let observer = observers.match_name::<QemuClockObserver>(self.name()).unwrap(); let observer = observers.match_name::<QemuClockObserver>(self.name()).unwrap();
self.exec_time = Some(Duration::from_nanos(observer.last_runtime() << 4)); // Assume a somewhat realistic multiplier of clock, it does not matter self.exec_time = Some(Duration::from_nanos(observer.last_runtime() << QEMU_ICOUNT_SHIFT)); // Assume a somewhat realistic multiplier of clock, it does not matter
Ok(false) Ok(false)
} }

View File

@ -24,6 +24,7 @@ use petgraph::graph::EdgeIndex;
use petgraph::graph::NodeIndex; use petgraph::graph::NodeIndex;
use petgraph::prelude::DiGraph; use petgraph::prelude::DiGraph;
use crate::systemstate::stg::STGFeedbackState; use crate::systemstate::stg::STGFeedbackState;
use crate::clock::QEMU_ICOUNT_SHIFT;
// Constants ================================================================================ // Constants ================================================================================
@ -32,8 +33,8 @@ pub static mut RNG_SEED: u64 = 1;
pub static mut LIMIT : u32 = u32::MAX; pub static mut LIMIT : u32 = u32::MAX;
pub const FIRST_INT : u32 = 500000; pub const FIRST_INT : u32 = 500000;
pub const MAX_NUM_INTERRUPT: usize = 32; pub const MAX_NUM_INTERRUPT: usize = 128;
pub const DO_NUM_INTERRUPT: usize = 32; pub const DO_NUM_INTERRUPT: usize = 128;
pub static mut MAX_INPUT_SIZE: usize = 32; pub static mut MAX_INPUT_SIZE: usize = 32;
/// Read ELF program headers to resolve physical load addresses. /// Read ELF program headers to resolve physical load addresses.
fn virt2phys(vaddr: GuestPhysAddr, tab: &EasyElf) -> GuestPhysAddr { fn virt2phys(vaddr: GuestPhysAddr, tab: &EasyElf) -> GuestPhysAddr {
@ -116,7 +117,7 @@ pub fn get_all_fn_symbol_ranges(elf: &EasyElf, api_range: std::ops::Range<GuestA
} }
extern "C" { extern "C" {
static mut libafl_interrupt_offsets : [u32; 32]; static mut libafl_interrupt_offsets : [u32; MAX_NUM_INTERRUPT];
static mut libafl_num_interrupts : usize; static mut libafl_num_interrupts : usize;
} }
@ -368,12 +369,15 @@ pub fn fuzz() {
} }
let mut api_ranges = get_all_fn_symbol_ranges(&elf, api_range); let mut api_ranges = get_all_fn_symbol_ranges(&elf, api_range);
let app_fn_ranges = get_all_fn_symbol_ranges(&elf, app_range.clone());
let mut isr_ranges : HashMap<String,std::ops::Range<GuestAddr>> = systemstate::helpers::ISR_SYMBOLS.iter().filter_map(|x| (api_ranges.get(&x.to_string()).map(|y| (x.to_string(),y.clone())))).collect(); let mut isr_ranges : HashMap<String,std::ops::Range<GuestAddr>> = systemstate::helpers::ISR_SYMBOLS.iter().filter_map(|x| (api_ranges.get(&x.to_string()).map(|y| (x.to_string(),y.clone())))).collect();
systemstate::helpers::ISR_SYMBOLS.iter().for_each(|x| {let _ =(app_fn_ranges.get(&x.to_string()).map(|y| (x.to_string(),y.clone()))).map(|y| isr_ranges.insert(y.0,y.1));}); // add used defined isr
let denylist=isr_ranges.values().map(|x| x.clone()).collect(); let denylist=isr_ranges.values().map(|x| x.clone()).collect();
let denylist = QemuInstrumentationFilter::DenyList(denylist); // do not count isr jumps, which are useless let denylist = QemuInstrumentationFilter::DenyList(denylist); // do not count isr jumps, which are useless
#[cfg(feature = "observe_systemstate")] #[cfg(feature = "observe_systemstate")]
let mut isr_addreses : HashMap<GuestAddr, String> = systemstate::helpers::ISR_SYMBOLS.iter().filter_map(|x| (api_ranges.remove(&x.to_string()).map(|y| (y.start,x.to_string())))).collect(); let mut isr_addreses : HashMap<GuestAddr, String> = systemstate::helpers::ISR_SYMBOLS.iter().filter_map(|x| (api_ranges.remove(&x.to_string()).map(|y| (y.start,x.to_string())))).collect();
systemstate::helpers::ISR_SYMBOLS.iter().for_each(|x| {let _ =(app_fn_ranges.get(&x.to_string()).map(|y| (x.to_string(),y.clone()))).map(|y| isr_addreses.insert(y.1.start, y.0));}); // add used defined isr
#[cfg(feature = "observe_systemstate")] #[cfg(feature = "observe_systemstate")]
for i in systemstate::helpers::ISR_SYMBOLS { for i in systemstate::helpers::ISR_SYMBOLS {
@ -400,9 +404,11 @@ pub fn fuzz() {
let args: Vec<String> = vec![ let args: Vec<String> = vec![
"target/debug/fret", "target/debug/fret",
"-icount", "-icount",
"shift=4,align=off,sleep=off", &format!("shift={},align=off,sleep=off", QEMU_ICOUNT_SHIFT),
"-machine", "-machine",
"mps2-an385", "mps2-an385",
"-cpu",
"cortex-m3",
"-monitor", "-monitor",
"null", "null",
"-kernel", "-kernel",
@ -411,9 +417,9 @@ pub fn fuzz() {
"null", "null",
"-nographic", "-nographic",
"-S", "-S",
"-semihosting", // "-semihosting",
"--semihosting-config", // "--semihosting-config",
"enable=on,target=native", // "enable=on,target=native",
"-snapshot", "-snapshot",
"-drive", "-drive",
"if=none,format=qcow2,file=dummy.qcow2", "if=none,format=qcow2,file=dummy.qcow2",
@ -447,6 +453,9 @@ pub fn fuzz() {
buf = &buf[libafl_num_interrupts*4..]; buf = &buf[libafl_num_interrupts*4..];
len = buf.len(); len = buf.len();
} }
// for i in 0 .. libafl_num_interrupts {
// libafl_interrupt_offsets[i] = FIRST_INT+TryInto::<u32>::try_into(i).unwrap()*MINIMUM_INTER_ARRIVAL_TIME;
// }
// println!("Load: {:?}", libafl_interrupt_offsets[0..libafl_num_interrupts].to_vec()); // println!("Load: {:?}", libafl_interrupt_offsets[0..libafl_num_interrupts].to_vec());
} }
if len > MAX_INPUT_SIZE { if len > MAX_INPUT_SIZE {

View File

@ -13,9 +13,9 @@ use libafl::{
corpus::{self, Corpus}, fuzzer::Evaluator, mark_feature_time, prelude::{new_hash_feedback, CorpusId, HasBytesVec, MutationResult, Mutator, UsesInput}, stages::Stage, start_timer, state::{HasCorpus, HasMetadata, HasNamedMetadata, HasRand, MaybeHasClientPerfMonitor, UsesState}, Error corpus::{self, Corpus}, fuzzer::Evaluator, mark_feature_time, prelude::{new_hash_feedback, CorpusId, HasBytesVec, MutationResult, Mutator, UsesInput}, stages::Stage, start_timer, state::{HasCorpus, HasMetadata, HasNamedMetadata, HasRand, MaybeHasClientPerfMonitor, UsesState}, Error
}; };
use libafl::prelude::State; use libafl::prelude::State;
use crate::{clock::IcHist, fuzzer::{DO_NUM_INTERRUPT, FIRST_INT}, systemstate::{stg::{STGFeedbackState, STGNodeMetadata}, CaptureEvent, ExecInterval, FreeRTOSSystemStateMetadata, ReducedFreeRTOSSystemState}}; use crate::{clock::{IcHist, QEMU_ISNS_PER_USEC}, fuzzer::{DO_NUM_INTERRUPT, FIRST_INT}, systemstate::{stg::{STGFeedbackState, STGNodeMetadata}, CaptureEvent, ExecInterval, FreeRTOSSystemStateMetadata, ReducedFreeRTOSSystemState}};
pub static mut MINIMUM_INTER_ARRIVAL_TIME : u32 = 1000 /*ms*/ * 62500; pub static mut MINIMUM_INTER_ARRIVAL_TIME : u32 = 1000 /*us*/ * QEMU_ISNS_PER_USEC;
// one isn per 2**4 ns // one isn per 2**4 ns
// virtual insn/sec 62500000 = 1/16 GHz // virtual insn/sec 62500000 = 1/16 GHz
// 1ms = 62500 insn // 1ms = 62500 insn

View File

@ -109,9 +109,9 @@ where
where where
QT: QemuHelperTuple<S>, QT: QemuHelperTuple<S>,
{ {
for wp in self.api_fn_addrs.keys() { // for wp in self.api_fn_addrs.keys() {
_hooks.instruction(*wp, Hook::Function(exec_syscall_hook::<QT, S>), false); // _hooks.instruction(*wp, Hook::Function(exec_syscall_hook::<QT, S>), false);
} // }
for wp in self.isr_addrs.keys() { for wp in self.isr_addrs.keys() {
_hooks.instruction(*wp, Hook::Function(exec_isr_hook::<QT, S>), false); _hooks.instruction(*wp, Hook::Function(exec_isr_hook::<QT, S>), false);
} }
@ -213,7 +213,11 @@ fn trigger_collection(emulator: &Emulator, edge: (Option<GuestAddr>,Option<Guest
println!("API Not found: {:#x} {:#x}", src, dest); println!("API Not found: {:#x} {:#x}", src, dest);
} }
} else if let Some(s) = h.api_fn_addrs.get(&dest) { // API Call } else if let Some(s) = h.api_fn_addrs.get(&dest) { // API Call
// if let None = in_any_range(&h.isr_ranges, src) {
systemstate.capture_point=(CaptureEvent::APIStart, s.to_string()); systemstate.capture_point=(CaptureEvent::APIStart, s.to_string());
// } else {
// return;
// }
} else { } else {
println!("API Not found: {:#x}", src); println!("API Not found: {:#x}", src);
} }
@ -315,14 +319,13 @@ where
let mut edge = (None, Some(pc)); let mut edge = (None, Some(pc));
unsafe { unsafe {
LAST_API_CALL.with(|x| { LAST_API_CALL.with(|x| {
match *x.get() { match (*x.get()).take() {
Some(s) => { Some(s) => {
edge.0=Some(s.0); edge.0=Some(s.0);
trigger_collection(emulator, edge, h); trigger_collection(emulator, edge, h);
}, },
None => (), None => (),
} }
*x.get()=None;
}); });
} }
@ -343,11 +346,13 @@ where
QT: QemuHelperTuple<S>, QT: QemuHelperTuple<S>,
{ {
if let Some(h) = hooks.helpers().match_first_type::<QemuSystemStateHelper>() { if let Some(h) = hooks.helpers().match_first_type::<QemuSystemStateHelper>() {
if h.app_range.contains(&src) && !h.app_range.contains(&dest) { if h.app_range.contains(&src) && !h.app_range.contains(&dest) && in_any_range(&h.isr_ranges,src).is_none() {
if let Some(_) = in_any_range(&h.api_fn_ranges,dest) { if let Some(_) = in_any_range(&h.api_fn_ranges,dest) {
// println!("New jmp {:x} {:x}", src, dest); // println!("New jmp {:x} {:x}", src, dest);
// println!("API Call Edge {:x} {:x}", src, dest); // println!("API Call Edge {:x} {:x}", src, dest);
return Some(1); return Some(1);
// TODO: trigger collection right here
// otherwise there can be a race-condition, where LAST_API_CALL is set before the api starts, if the interrupt handler calls an api function, it will misidentify the callsite of that api call
} }
} else if dest == 0 { // !h.app_range.contains(&src) && } else if dest == 0 { // !h.app_range.contains(&src) &&
if let Some(_) = in_any_range(&h.api_fn_ranges, src) { if let Some(_) = in_any_range(&h.api_fn_ranges, src) {
@ -363,6 +368,18 @@ where
return None; return None;
} }
fn get_icount(emulator : &Emulator) -> u64 {
unsafe {
// TODO: investigate why can_do_io is not set sometimes, as this is just a workaround
let c = emulator.cpu_from_index(0);
let can_do_io = (*c.raw_ptr()).neg.can_do_io;
(*c.raw_ptr()).neg.can_do_io = true;
let r = emu::icount_get_raw();
(*c.raw_ptr()).neg.can_do_io = can_do_io;
r
}
}
pub fn trace_api_call<QT, S>( pub fn trace_api_call<QT, S>(
hooks: &mut QemuHooks<QT, S>, hooks: &mut QemuHooks<QT, S>,
_state: Option<&mut S>, _state: Option<&mut S>,
@ -373,11 +390,10 @@ where
QT: QemuHelperTuple<S>, QT: QemuHelperTuple<S>,
{ {
if id == 1 { // API call if id == 1 { // API call
unsafe { let h = hooks.helpers().match_first_type::<QemuSystemStateHelper>().expect("QemuSystemHelper not found in helper tupel");
let p = LAST_API_CALL.with(|x| x.get()); let emulator = hooks.emulator();
*p = Some((src,dest)); trigger_collection(emulator, (Some(src), Some(dest)), h);
// println!("Jump {:#x} {:#x}", src, dest); // println!("Exec API Call {:#x} {:#x} {}", src, dest, get_icount(emulator));
}
} else if id == 2 { // API return } else if id == 2 { // API return
let h = hooks.helpers().match_first_type::<QemuSystemStateHelper>().expect("QemuSystemHelper not found in helper tupel"); let h = hooks.helpers().match_first_type::<QemuSystemStateHelper>().expect("QemuSystemHelper not found in helper tupel");
// Ignore returns to other APIs or ISRs. We only account for the first call depth of API calls from user space. // Ignore returns to other APIs or ISRs. We only account for the first call depth of API calls from user space.
@ -389,7 +405,7 @@ where
edge.1=Some(dest); edge.1=Some(dest);
trigger_collection(emulator, edge, h); trigger_collection(emulator, edge, h);
// println!("Exec API Return Edge {:#x} {:#x}", src, dest); // println!("Exec API Return Edge {:#x} {:#x} {}", src, dest, get_icount(emulator));
} }
} else if id == 3 { // ISR return } else if id == 3 { // ISR return
let h = hooks.helpers().match_first_type::<QemuSystemStateHelper>().expect("QemuSystemHelper not found in helper tupel"); let h = hooks.helpers().match_first_type::<QemuSystemStateHelper>().expect("QemuSystemHelper not found in helper tupel");
@ -399,7 +415,7 @@ where
edge.0=Some(in_any_range(&h.isr_ranges, src).unwrap().start); edge.0=Some(in_any_range(&h.isr_ranges, src).unwrap().start);
trigger_collection(emulator, edge, h); trigger_collection(emulator, edge, h);
// println!("Exec ISR Return Edge {:#x} {:#x}", src, dest); // println!("Exec ISR Return Edge {:#x} {:#x} {}", src, dest, get_icount(emulator));
} }
} }

View File

@ -53,7 +53,7 @@ where
// unsafe {self.last_run = invalidate_ineffective_isr(refine_system_states(&mut CURRENT_SYSTEMSTATE_VEC));} // unsafe {self.last_run = invalidate_ineffective_isr(refine_system_states(&mut CURRENT_SYSTEMSTATE_VEC));}
unsafe { unsafe {
let mut temp = refine_system_states(&mut CURRENT_SYSTEMSTATE_VEC); let mut temp = refine_system_states(&mut CURRENT_SYSTEMSTATE_VEC);
fix_broken_trace(&mut temp.1); // fix_broken_trace(&mut temp.1);
self.last_run = temp.0.clone(); self.last_run = temp.0.clone();
// println!("{:?}",temp); // println!("{:?}",temp);
let mut temp = states2intervals(temp.0, temp.1); let mut temp = states2intervals(temp.0, temp.1);
@ -154,6 +154,7 @@ fn refine_system_states(input: &mut Vec<RawFreeRTOSSystemState>) -> (Vec<Reduced
delay_list_after: delay_list, delay_list_after: delay_list,
// input_counter: i.input_counter,//+IRQ_INPUT_BYTES_NUMBER, // input_counter: i.input_counter,//+IRQ_INPUT_BYTES_NUMBER,
}); });
// println!("Refine: {:?} {:?} {:x}-{:x}",i.capture_point.0, i.capture_point.1.to_string(), i.edge.0.unwrap_or(0), i.edge.1.unwrap_or(0));
ret.1.push((i.qemu_tick, i.capture_point.0, i.capture_point.1.to_string(), i.edge)); ret.1.push((i.qemu_tick, i.capture_point.0, i.capture_point.1.to_string(), i.edge));
} }
return ret; return ret;
@ -161,6 +162,7 @@ fn refine_system_states(input: &mut Vec<RawFreeRTOSSystemState>) -> (Vec<Reduced
/// Transform the states and metadata into a list of ExecIntervals /// Transform the states and metadata into a list of ExecIntervals
fn states2intervals(trace: Vec<ReducedFreeRTOSSystemState>, meta: Vec<(u64, CaptureEvent, String, (Option<u32>, Option<u32>))>) -> (Vec<ExecInterval>, HashMap<u64, ReducedFreeRTOSSystemState>) { fn states2intervals(trace: Vec<ReducedFreeRTOSSystemState>, meta: Vec<(u64, CaptureEvent, String, (Option<u32>, Option<u32>))>) -> (Vec<ExecInterval>, HashMap<u64, ReducedFreeRTOSSystemState>) {
if trace.len() == 0 {return (Vec::new(), HashMap::new());}
let mut isr_stack : VecDeque<u8> = VecDeque::from([]); // 2+ = ISR, 1 = systemcall, 0 = APP. Trace starts with an ISREnd and executes the app let mut isr_stack : VecDeque<u8> = VecDeque::from([]); // 2+ = ISR, 1 = systemcall, 0 = APP. Trace starts with an ISREnd and executes the app
@ -179,11 +181,11 @@ fn states2intervals(trace: Vec<ReducedFreeRTOSSystemState>, meta: Vec<(u64, Capt
level_of_task.insert(curr_name, 0); level_of_task.insert(curr_name, 0);
} }
*level_of_task.get_mut(curr_name).unwrap()=0; *level_of_task.get_mut(curr_name).unwrap()=0;
&0 0
}, },
CaptureEvent::APIStart => { // API start can only be called in the app CaptureEvent::APIStart => { // API start can only be called in the app
*level_of_task.get_mut(curr_name).unwrap()=1; *level_of_task.get_mut(curr_name).unwrap()=1;
&1 1
}, },
CaptureEvent::ISREnd => { CaptureEvent::ISREnd => {
// special case where the next block is an app start // special case where the next block is an app start
@ -192,12 +194,12 @@ fn states2intervals(trace: Vec<ReducedFreeRTOSSystemState>, meta: Vec<(u64, Capt
} }
// nested isr, TODO: Test level > 2 // nested isr, TODO: Test level > 2
if isr_stack.len() > 1 { if isr_stack.len() > 1 {
isr_stack.pop_back(); isr_stack.pop_back().unwrap();
isr_stack.back().unwrap() *isr_stack.back().unwrap()
} else { } else {
isr_stack.pop_back(); isr_stack.pop_back();
// possibly go back to an api call that is still running for this task // possibly go back to an api call that is still running for this task
level_of_task.get(curr_name).unwrap() *level_of_task.get(curr_name).unwrap()
} }
}, },
CaptureEvent::ISRStart => { CaptureEvent::ISRStart => {
@ -207,16 +209,16 @@ fn states2intervals(trace: Vec<ReducedFreeRTOSSystemState>, meta: Vec<(u64, Capt
// } else { // } else {
// regular case // regular case
if isr_stack.len() > 0 { if isr_stack.len() > 0 {
let l = isr_stack.back().unwrap(); let l = *isr_stack.back().unwrap();
isr_stack.push_back(*l); isr_stack.push_back(l+1);
isr_stack.back().unwrap() l+1
} else { } else {
isr_stack.push_back(2); isr_stack.push_back(2);
&2 2
} }
// } // }
} }
_ => &100 _ => 100
}; };
// if trace[i].2 == CaptureEvent::End {break;} // if trace[i].2 == CaptureEvent::End {break;}
let next_hash=trace[i+1].get_hash(); let next_hash=trace[i+1].get_hash();
@ -230,7 +232,7 @@ fn states2intervals(trace: Vec<ReducedFreeRTOSSystemState>, meta: Vec<(u64, Capt
end_state: next_hash, end_state: next_hash,
start_capture: (meta[i].1, meta[i].2.clone()), start_capture: (meta[i].1, meta[i].2.clone()),
end_capture: (meta[i+1].1, meta[i+1].2.clone()), end_capture: (meta[i+1].1, meta[i+1].2.clone()),
level: *level, level: level,
tick_spend_preempted: 0, tick_spend_preempted: 0,
abb: None abb: None
}); });
@ -250,8 +252,9 @@ fn add_abb_info(trace: &mut Vec<ExecInterval>, table: &HashMap<u64, ReducedFreeR
let curr_name = &table[&trace[i].start_state].current_task.task_name; let curr_name = &table[&trace[i].start_state].current_task.task_name;
// let last : Option<&usize> = last_abb_start_of_task.get(&curr_name); // let last : Option<&usize> = last_abb_start_of_task.get(&curr_name);
let open_abb = open_abb_at_this_task_or_level.get(&(trace[i].level, if trace[i].level<2 {&curr_name} else {trace[i].start_capture.1.as_str()})).to_owned(); // apps/apis are differentiated by task name, isrs by nested level let open_abb = open_abb_at_this_task_or_level.get(&(trace[i].level, if trace[i].level<2 {&curr_name} else {""})).to_owned(); // apps/apis are differentiated by task name, isrs by nested level
// println!("Edge {:x}-{:x}", edges[i].0.unwrap_or(0xffff), edges[i].1.unwrap_or(0xffff));
match (&trace[i].start_capture.0, &trace[i].end_capture.0) { match (&trace[i].start_capture.0, &trace[i].end_capture.0) {
// case with abb to block correspondence // case with abb to block correspondence
@ -269,35 +272,38 @@ fn add_abb_info(trace: &mut Vec<ExecInterval>, table: &HashMap<u64, ReducedFreeR
match trace[i].start_capture.0 { match trace[i].start_capture.0 {
// generic api abb start // generic api abb start
CaptureEvent::APIStart => { CaptureEvent::APIStart => {
// assert_eq!(open_abb, None); assert_eq!(open_abb, None);
open_abb_at_this_task_or_level.insert((trace[i].level, if trace[i].level<2 {&curr_name} else {""}), i); open_abb_at_this_task_or_level.insert((trace[i].level, if trace[i].level<2 {&curr_name} else {""}), i);
wip_abb_trace.push(Rc::new(RefCell::new(AtomicBasicBlock{start: edges[i].0.unwrap(), ends: HashSet::new(), level: if trace[i].level<2 {trace[i].level} else {2}}))); wip_abb_trace.push(Rc::new(RefCell::new(AtomicBasicBlock{start: edges[i].0.unwrap(), ends: HashSet::new(), level: if trace[i].level<2 {trace[i].level} else {2}})));
}, },
// generic isr abb start // generic isr abb start
CaptureEvent::ISRStart => { CaptureEvent::ISRStart => {
// assert_eq!(open_abb, None); assert_eq!(open_abb, None);
open_abb_at_this_task_or_level.insert( (trace[i].level, if trace[i].level<2 {&curr_name} else {trace[i].start_capture.1.as_str()}) , i); open_abb_at_this_task_or_level.insert( (trace[i].level, if trace[i].level<2 {&curr_name} else {""}) , i);
wip_abb_trace.push(Rc::new(RefCell::new(AtomicBasicBlock{start: edges[i].0.unwrap(), ends: HashSet::new(), level: if trace[i].level<2 {trace[i].level} else {2}}))); wip_abb_trace.push(Rc::new(RefCell::new(AtomicBasicBlock{start: edges[i].0.unwrap(), ends: HashSet::new(), level: if trace[i].level<2 {trace[i].level} else {2}})));
}, },
// generic app abb start // generic app abb start
CaptureEvent::APIEnd => { CaptureEvent::APIEnd => {
// assert_eq!(open_abb, None); assert_eq!(open_abb, None);
open_abb_at_this_task_or_level.insert( (trace[i].level, if trace[i].level<2 {&curr_name} else {trace[i].start_capture.1.as_str()}) , i); open_abb_at_this_task_or_level.insert( (trace[i].level, if trace[i].level<2 {&curr_name} else {""}) , i);
wip_abb_trace.push(Rc::new(RefCell::new(AtomicBasicBlock{start: edges[i].0.unwrap(), ends: HashSet::new(), level: if trace[i].level<2 {trace[i].level} else {2}}))); wip_abb_trace.push(Rc::new(RefCell::new(AtomicBasicBlock{start: edges[i].0.unwrap(), ends: HashSet::new(), level: if trace[i].level<2 {trace[i].level} else {2}})));
}, },
// generic continued blocks // generic continued blocks
CaptureEvent::ISREnd => { CaptureEvent::ISREnd => {
// special case app abb start // special case app abb start
if trace[i].start_capture.1=="xPortPendSVHandler" && !task_has_started.contains(curr_name) { if trace[i].start_capture.1=="xPortPendSVHandler" && !task_has_started.contains(curr_name) {
// assert_eq!(open_abb, None); assert_eq!(open_abb, None);
wip_abb_trace.push(Rc::new(RefCell::new(AtomicBasicBlock{start: 0, ends: HashSet::new(), level: if trace[i].level<2 {trace[i].level} else {2}}))); wip_abb_trace.push(Rc::new(RefCell::new(AtomicBasicBlock{start: 0, ends: HashSet::new(), level: if trace[i].level<2 {trace[i].level} else {2}})));
open_abb_at_this_task_or_level.insert( (trace[i].level, if trace[i].level<2 {&curr_name} else {trace[i].start_capture.1.as_str()}) , i); open_abb_at_this_task_or_level.insert( (trace[i].level, if trace[i].level<2 {&curr_name} else {""}) , i);
task_has_started.insert(curr_name.clone()); task_has_started.insert(curr_name.clone());
} else { } else {
if let Some(last) = open_abb_at_this_task_or_level.get(&(trace[i].level, if trace[i].level<2 {&curr_name} else {trace[i].start_capture.1.as_str()})) { // assert_ne!(open_abb,None);
if let Some(last) = open_abb_at_this_task_or_level.get(&(trace[i].level, if trace[i].level<2 {&curr_name} else {""})) {
wip_abb_trace.push(wip_abb_trace[*last].clone()); wip_abb_trace.push(wip_abb_trace[*last].clone());
} else { } else {
eprintln!("Continued block with no start {} {:?} {:?} {} {}", trace[i].start_tick, trace[i].start_capture, trace[i].end_capture, task_has_started.contains(curr_name),trace[i].level); // panic!();
eprintln!("Continued block with no start {} {:?} {:?} {:x}-{:x} {} {}", trace[i].start_tick, trace[i].start_capture, trace[i].end_capture, edges[i].0.unwrap_or(0xffff), edges[i].1.unwrap_or(0xffff),task_has_started.contains(curr_name),trace[i].level);
panic!();
wip_abb_trace.push(Rc::new(RefCell::new(AtomicBasicBlock{start: edges[i].1.unwrap_or(0), ends: HashSet::new(), level: if trace[i].level<2 {trace[i].level} else {2}}))) wip_abb_trace.push(Rc::new(RefCell::new(AtomicBasicBlock{start: edges[i].1.unwrap_or(0), ends: HashSet::new(), level: if trace[i].level<2 {trace[i].level} else {2}})))
} }
} }
@ -309,29 +315,29 @@ fn add_abb_info(trace: &mut Vec<ExecInterval>, table: &HashMap<u64, ReducedFreeR
CaptureEvent::APIStart => { CaptureEvent::APIStart => {
let _t = &wip_abb_trace[i]; let _t = &wip_abb_trace[i];
RefCell::borrow_mut(&*wip_abb_trace[i]).ends.insert(edges[i].1.unwrap()); RefCell::borrow_mut(&*wip_abb_trace[i]).ends.insert(edges[i].1.unwrap());
open_abb_at_this_task_or_level.remove(&(trace[i].level, if trace[i].level<2 {&curr_name} else {trace[i].start_capture.1.as_str()})); open_abb_at_this_task_or_level.remove(&(trace[i].level, if trace[i].level<2 {&curr_name} else {""}));
}, },
// generic api abb end // generic api abb end
CaptureEvent::APIEnd => { CaptureEvent::APIEnd => {
RefCell::borrow_mut(&*wip_abb_trace[i]).ends.insert(edges[i].1.unwrap()); RefCell::borrow_mut(&*wip_abb_trace[i]).ends.insert(edges[i].1.unwrap());
open_abb_at_this_task_or_level.remove(&(trace[i].level, if trace[i].level<2 {&curr_name} else {trace[i].start_capture.1.as_str()})); open_abb_at_this_task_or_level.remove(&(trace[i].level, if trace[i].level<2 {&curr_name} else {""}));
}, },
// generic isr abb end // generic isr abb end
CaptureEvent::ISREnd => { CaptureEvent::ISREnd => {
RefCell::borrow_mut(&*wip_abb_trace[i]).ends.insert(edges[i].1.unwrap()); RefCell::borrow_mut(&*wip_abb_trace[i]).ends.insert(edges[i].1.unwrap());
open_abb_at_this_task_or_level.remove(&(trace[i].level, if trace[i].level<2 {&curr_name} else {trace[i].start_capture.1.as_str()})); open_abb_at_this_task_or_level.remove(&(trace[i].level, if trace[i].level<2 {&curr_name} else {""}));
}, },
// end anything // end anything
CaptureEvent::End => { CaptureEvent::End => {
RefCell::borrow_mut(&*wip_abb_trace[i]).ends.insert(edges[i].1.unwrap()); RefCell::borrow_mut(&*wip_abb_trace[i]).ends.insert(edges[i].1.unwrap());
open_abb_at_this_task_or_level.remove(&(trace[i].level, if trace[i].level<2 {&curr_name} else {trace[i].start_capture.1.as_str()})); open_abb_at_this_task_or_level.remove(&(trace[i].level, if trace[i].level<2 {&curr_name} else {""}));
}, },
CaptureEvent::ISRStart => (), CaptureEvent::ISRStart => (),
_ => panic!("Undefined block end") _ => panic!("Undefined block end")
} }
} }
} }
// println!("{} {} {:x}-{:x} {:x}-{:X} {:?} {:?} {}",curr_name, trace[i].level, edges[i].0.unwrap_or(0xffff), edges[i].1.unwrap_or(0xffff), ((*wip_abb_trace[i])).borrow().start, ((*wip_abb_trace[i])).borrow().ends.iter().next().unwrap_or(&0xffff), trace[i].start_capture, trace[i].end_capture, trace[i].start_tick); // println!("{} {} {:x}-{:x} {:x}-{:x} {:?} {:?} {}",curr_name, trace[i].level, edges[i].0.unwrap_or(0xffff), edges[i].1.unwrap_or(0xffff), ((*wip_abb_trace[i])).borrow().start, ((*wip_abb_trace[i])).borrow().ends.iter().next().unwrap_or(&0xffff), trace[i].start_capture, trace[i].end_capture, trace[i].start_tick);
} }
drop(open_abb_at_this_task_or_level); drop(open_abb_at_this_task_or_level);