un-hardcode rtos api functions
This commit is contained in:
parent
c013628017
commit
f26582ed75
@ -78,7 +78,7 @@ pub fn try_load_symbol(elf : &EasyElf, symbol : &str, do_translation : bool) ->
|
|||||||
} else {ret}
|
} else {ret}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_function_range(elf: &EasyElf, symbol: &'static str) -> Option<std::ops::Range<GuestAddr>> {
|
pub fn get_function_range(elf: &EasyElf, symbol: &str) -> Option<std::ops::Range<GuestAddr>> {
|
||||||
let gob = elf.goblin();
|
let gob = elf.goblin();
|
||||||
|
|
||||||
let mut funcs : Vec<_> = gob.syms.iter().filter(|x| x.is_function()).collect();
|
let mut funcs : Vec<_> = gob.syms.iter().filter(|x| x.is_function()).collect();
|
||||||
@ -98,7 +98,7 @@ pub fn get_function_range(elf: &EasyElf, symbol: &'static str) -> Option<std::op
|
|||||||
// look for first function after addr
|
// look for first function after addr
|
||||||
let sym_end = funcs.iter().find(|x| x.st_value > sym.st_value);
|
let sym_end = funcs.iter().find(|x| x.st_value > sym.st_value);
|
||||||
if let Some(sym_end) = sym_end {
|
if let Some(sym_end) = sym_end {
|
||||||
println!("{} {:#x}..{} {:#x}", gob.strtab.get_at(sym.st_name).unwrap_or(""),addr, gob.strtab.get_at(sym_end.st_name).unwrap_or(""),sym_end.st_value & !0x1);
|
// println!("{} {:#x}..{} {:#x}", gob.strtab.get_at(sym.st_name).unwrap_or(""),addr, gob.strtab.get_at(sym_end.st_name).unwrap_or(""),sym_end.st_value & !0x1);
|
||||||
return Some(addr..((sym_end.st_value & !0x1) as GuestAddr));
|
return Some(addr..((sym_end.st_value & !0x1) as GuestAddr));
|
||||||
}
|
}
|
||||||
return None;
|
return None;
|
||||||
@ -109,6 +109,29 @@ pub fn get_function_range(elf: &EasyElf, symbol: &'static str) -> Option<std::op
|
|||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_all_fn_symbol_ranges(elf: &EasyElf, api_range: std::ops::Range<GuestAddr>) -> HashMap<String,std::ops::Range<GuestAddr>> {
|
||||||
|
let mut api_addreses : HashMap<String,std::ops::Range<GuestAddr>> = HashMap::new();
|
||||||
|
|
||||||
|
let gob = elf.goblin();
|
||||||
|
|
||||||
|
let mut funcs : Vec<_> = gob.syms.iter().filter(|x| x.is_function() && api_range.contains(&x.st_value.try_into().unwrap())).collect();
|
||||||
|
funcs.sort_unstable_by(|x,y| x.st_value.cmp(&y.st_value));
|
||||||
|
|
||||||
|
for sym in &funcs {
|
||||||
|
let sym_name = gob.strtab.get_at(sym.st_name);
|
||||||
|
if let Some(sym_name) = sym_name {
|
||||||
|
if let Some(r) = get_function_range(elf, sym_name) {
|
||||||
|
api_addreses.insert(sym_name.to_string(), r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for i in api_addreses.iter() {
|
||||||
|
println!("{} {:#x}..{:#x}", i.0, i.1.start, i.1.end);
|
||||||
|
}
|
||||||
|
|
||||||
|
return api_addreses;
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
static mut libafl_interrupt_offsets : [u32; 32];
|
static mut libafl_interrupt_offsets : [u32; 32];
|
||||||
static mut libafl_num_interrupts : usize;
|
static mut libafl_num_interrupts : usize;
|
||||||
@ -199,7 +222,7 @@ macro_rules! do_dump_case {
|
|||||||
macro_rules! do_dump_times {
|
macro_rules! do_dump_times {
|
||||||
($state:expr, $cli:expr, $c:expr) => {
|
($state:expr, $cli:expr, $c:expr) => {
|
||||||
if $cli.dump_times {
|
if $cli.dump_times {
|
||||||
let dump_path = $cli.dump_name.clone().unwrap().with_extension(if $c=="" {"times"} else {$c});
|
let dump_path = $cli.dump_name.clone().unwrap().with_extension(if $c=="" {"time"} else {$c});
|
||||||
let mut file = std::fs::OpenOptions::new()
|
let mut file = std::fs::OpenOptions::new()
|
||||||
.read(true)
|
.read(true)
|
||||||
.write(true)
|
.write(true)
|
||||||
@ -353,6 +376,12 @@ pub fn fuzz() {
|
|||||||
#[cfg(feature = "systemstate")]
|
#[cfg(feature = "systemstate")]
|
||||||
let app_range = app_start..app_end;
|
let app_range = app_start..app_end;
|
||||||
#[cfg(feature = "systemstate")]
|
#[cfg(feature = "systemstate")]
|
||||||
|
let api_start = load_symbol(&elf, "__API_CODE_START__", false);
|
||||||
|
#[cfg(feature = "systemstate")]
|
||||||
|
let api_end = load_symbol(&elf, "__API_CODE_END__", false);
|
||||||
|
#[cfg(feature = "systemstate")]
|
||||||
|
let api_range = api_start..api_end;
|
||||||
|
#[cfg(feature = "systemstate")]
|
||||||
dbg!(app_range.clone());
|
dbg!(app_range.clone());
|
||||||
|
|
||||||
let breakpoint = elf
|
let breakpoint = elf
|
||||||
@ -375,27 +404,48 @@ pub fn fuzz() {
|
|||||||
unsafe {RNG_SEED = str::parse::<u64>(&seed).expect("SEED_RANDOM must be an integer.");}
|
unsafe {RNG_SEED = str::parse::<u64>(&seed).expect("SEED_RANDOM must be an integer.");}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "systemstate")]
|
let mut api_ranges = get_all_fn_symbol_ranges(&elf, api_range);
|
||||||
let mut api_addreses : HashMap<GuestAddr,&'static str> = HashMap::new();
|
|
||||||
#[cfg(feature = "systemstate")]
|
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();
|
||||||
for s in systemstate::helpers::API_SYMBOLS {
|
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();
|
||||||
if let Some(sb) = try_load_symbol(&elf, &s, false) {
|
|
||||||
api_addreses.insert(sb,s);
|
for i in systemstate::helpers::ISR_SYMBOLS {
|
||||||
}
|
if isr_ranges.get(&i.to_string()).is_none() {
|
||||||
}
|
if let Some(fr) = get_function_range(&elf, i) {
|
||||||
#[cfg(feature = "systemstate")]
|
isr_addreses.insert(fr.start, i.to_string());
|
||||||
let mut isr_addreses : HashMap<GuestAddr,&'static str> = HashMap::new();
|
isr_ranges.insert(i.to_string(), fr);
|
||||||
#[cfg(feature = "systemstate")]
|
}
|
||||||
for s in systemstate::helpers::ISR_SYMBOLS {
|
|
||||||
if let Some(sb) = try_load_symbol(&elf, &s, false) {
|
|
||||||
isr_addreses.insert(sb & !1,s);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "systemstate")]
|
let api_addreses : HashMap<GuestAddr, String> = api_ranges.iter().map(|(k,v)| (v.start,k.clone())).collect();
|
||||||
let mut api_ranges : Vec<(&'static str,std::ops::Range<GuestAddr>)> = systemstate::helpers::API_SYMBOLS.iter().filter_map(|x| get_function_range(&elf, x).map(|y| (*x,y))).collect();
|
|
||||||
#[cfg(feature = "systemstate")]
|
let api_ranges : Vec<_> = api_ranges.into_iter().collect();
|
||||||
let mut isr_ranges : Vec<(&'static str,std::ops::Range<GuestAddr>)> = systemstate::helpers::ISR_SYMBOLS.iter().filter_map(|x| get_function_range(&elf, x).map(|y| (*x,y))).collect();
|
let isr_ranges : Vec<_> = isr_ranges.into_iter().collect();
|
||||||
|
|
||||||
|
// println!("all: {}, api: {}, isr: {}", api_ranges.len(), systemstate::helpers::API_SYMBOLS.len(), systemstate::helpers::ISR_SYMBOLS.len());
|
||||||
|
|
||||||
|
// #[cfg(feature = "systemstate")]
|
||||||
|
// let mut api_addreses : HashMap<GuestAddr,&'static str> = HashMap::new();
|
||||||
|
// #[cfg(feature = "systemstate")]
|
||||||
|
// for s in systemstate::helpers::API_SYMBOLS {
|
||||||
|
// if let Some(sb) = try_load_symbol(&elf, &s, false) {
|
||||||
|
// api_addreses.insert(sb,s);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// #[cfg(feature = "systemstate")]
|
||||||
|
// let mut isr_addreses : HashMap<GuestAddr,&'static str> = HashMap::new();
|
||||||
|
// #[cfg(feature = "systemstate")]
|
||||||
|
// for s in systemstate::helpers::ISR_SYMBOLS {
|
||||||
|
// if let Some(sb) = try_load_symbol(&elf, &s, false) {
|
||||||
|
// isr_addreses.insert(sb & !1,s);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// #[cfg(feature = "systemstate")]
|
||||||
|
// let mut api_ranges : Vec<(&'static str,std::ops::Range<GuestAddr>)> = systemstate::helpers::API_SYMBOLS.iter().filter_map(|x| get_function_range(&elf, x).map(|y| (*x,y))).collect();
|
||||||
|
// #[cfg(feature = "systemstate")]
|
||||||
|
// let mut isr_ranges : Vec<(&'static str,std::ops::Range<GuestAddr>)> = systemstate::helpers::ISR_SYMBOLS.iter().filter_map(|x| get_function_range(&elf, x).map(|y| (*x,y))).collect();
|
||||||
|
|
||||||
// Client setup ================================================================================
|
// Client setup ================================================================================
|
||||||
|
|
||||||
|
@ -84,11 +84,11 @@ pub const ISR_SYMBOLS : &'static [&'static str] = &[
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct QemuSystemStateHelper {
|
pub struct QemuSystemStateHelper {
|
||||||
// Address of API functions
|
// Address of API functions
|
||||||
api_fn_addrs: HashMap<GuestAddr, &'static str>,
|
api_fn_addrs: HashMap<GuestAddr, String>,
|
||||||
api_fn_ranges: Vec<(&'static str, std::ops::Range<GuestAddr>)>,
|
api_fn_ranges: Vec<(String, std::ops::Range<GuestAddr>)>,
|
||||||
// Address of interrupt routines
|
// Address of interrupt routines
|
||||||
isr_addrs: HashMap<GuestAddr, &'static str>,
|
isr_addrs: HashMap<GuestAddr, String>,
|
||||||
isr_ranges: Vec<(&'static str, std::ops::Range<GuestAddr>)>,
|
isr_ranges: Vec<(String, std::ops::Range<GuestAddr>)>,
|
||||||
tcb_addr: GuestAddr,
|
tcb_addr: GuestAddr,
|
||||||
ready_queues: GuestAddr,
|
ready_queues: GuestAddr,
|
||||||
delay_queue: GuestAddr,
|
delay_queue: GuestAddr,
|
||||||
@ -102,10 +102,10 @@ pub struct QemuSystemStateHelper {
|
|||||||
impl QemuSystemStateHelper {
|
impl QemuSystemStateHelper {
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn new(
|
pub fn new(
|
||||||
api_fn_addrs: HashMap<GuestAddr, &'static str>,
|
api_fn_addrs: HashMap<GuestAddr, String>,
|
||||||
api_fn_ranges: Vec<(&'static str, std::ops::Range<GuestAddr>)>,
|
api_fn_ranges: Vec<(String, std::ops::Range<GuestAddr>)>,
|
||||||
isr_addrs: HashMap<GuestAddr, &'static str>,
|
isr_addrs: HashMap<GuestAddr, String>,
|
||||||
isr_ranges: Vec<(&'static str, std::ops::Range<GuestAddr>)>,
|
isr_ranges: Vec<(String, std::ops::Range<GuestAddr>)>,
|
||||||
tcb_addr: GuestAddr,
|
tcb_addr: GuestAddr,
|
||||||
ready_queues: GuestAddr,
|
ready_queues: GuestAddr,
|
||||||
delay_queue: GuestAddr,
|
delay_queue: GuestAddr,
|
||||||
@ -165,7 +165,7 @@ where
|
|||||||
let c = emulator.cpu_from_index(0);
|
let c = emulator.cpu_from_index(0);
|
||||||
let pc = c.read_reg::<i32, u32>(15).unwrap();
|
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].edge = (Some(pc),None);
|
||||||
CURRENT_SYSTEMSTATE_VEC[CURRENT_SYSTEMSTATE_VEC.len()-1].capture_point = (CaptureEvent::End,"Breakpoint");
|
CURRENT_SYSTEMSTATE_VEC[CURRENT_SYSTEMSTATE_VEC.len()-1].capture_point = (CaptureEvent::End,"Breakpoint".to_string());
|
||||||
}
|
}
|
||||||
// Find the first ISREnd of vPortSVCHandler and drop anything before
|
// Find the first ISREnd of vPortSVCHandler and drop anything before
|
||||||
unsafe {
|
unsafe {
|
||||||
@ -227,25 +227,28 @@ fn trigger_collection(emulator: &Emulator, edge: (Option<GuestAddr>,Option<Guest
|
|||||||
// ISR End
|
// ISR End
|
||||||
if let Some(src) = edge.0 {
|
if let Some(src) = edge.0 {
|
||||||
if let Some(s) = h.isr_addrs.get(&src) {
|
if let Some(s) = h.isr_addrs.get(&src) {
|
||||||
systemstate.capture_point=(CaptureEvent::ISREnd, s);
|
systemstate.capture_point=(CaptureEvent::ISREnd, s.to_string());
|
||||||
} else {
|
} else {
|
||||||
println!("ISR Ret Not found: {:#x}", src);
|
println!("ISR Ret Not found: {:#x}", src);
|
||||||
systemstate.capture_point=(CaptureEvent::ISREnd, "");
|
systemstate.capture_point=(CaptureEvent::ISREnd, "".to_string());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Some(dest) => {
|
Some(dest) => {
|
||||||
if let Some(src) = edge.0 { // Both set, can be API Call/Ret
|
if let Some(src) = edge.0 { // Both set, can be API Call/Ret
|
||||||
if let Some(s) = h.api_fn_addrs.get(&src) { // API End
|
if let Some(s) = h.api_fn_addrs.get(&src) { // API End
|
||||||
systemstate.capture_point=(CaptureEvent::APIEnd, s);
|
systemstate.capture_point=(CaptureEvent::APIEnd, s.to_string());
|
||||||
|
if !h.app_range.contains(&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
|
||||||
systemstate.capture_point=(CaptureEvent::APIStart, s);
|
systemstate.capture_point=(CaptureEvent::APIStart, s.to_string());
|
||||||
} else {
|
} else {
|
||||||
println!("API Not found: {:#x}", src);
|
println!("API Not found: {:#x}", src);
|
||||||
}
|
}
|
||||||
} else { // No source, must be ISR
|
} else { // No source, must be ISR
|
||||||
if let Some(s) = h.isr_addrs.get(&dest) { // ISR Start
|
if let Some(s) = h.isr_addrs.get(&dest) { // ISR Start
|
||||||
systemstate.capture_point=(CaptureEvent::ISRStart, s);
|
systemstate.capture_point=(CaptureEvent::ISRStart, s.to_string());
|
||||||
} else {
|
} else {
|
||||||
println!("ISR call Not found: {:#x}", dest);
|
println!("ISR call Not found: {:#x}", dest);
|
||||||
}
|
}
|
||||||
@ -405,7 +408,8 @@ where
|
|||||||
}
|
}
|
||||||
} 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");
|
||||||
if in_any_range(&h.api_fn_ranges, dest).is_none() {
|
// Ignore returns to other APIs or ISRs. We only account for the first call depth of API calls from user space.
|
||||||
|
if in_any_range(&h.api_fn_ranges, dest).is_none() && in_any_range(&h.isr_ranges, dest).is_none() {
|
||||||
let emulator = hooks.emulator();
|
let emulator = hooks.emulator();
|
||||||
|
|
||||||
let mut edge = (None, None);
|
let mut edge = (None, None);
|
||||||
@ -427,7 +431,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn in_any_range<'a>(ranges: &'a Vec<(&str, Range<u32>)>, addr : GuestAddr) -> Option<&'a std::ops::Range<GuestAddr>> {
|
pub fn in_any_range<'a>(ranges: &'a Vec<(String, Range<u32>)>, addr : GuestAddr) -> Option<&'a std::ops::Range<GuestAddr>> {
|
||||||
for (_,r) in ranges {
|
for (_,r) in ranges {
|
||||||
if r.contains(&addr) {return Some(r);}
|
if r.contains(&addr) {return Some(r);}
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,7 @@ pub struct RawFreeRTOSSystemState {
|
|||||||
dumping_ground: HashMap<u32,freertos::rtos_struct>,
|
dumping_ground: HashMap<u32,freertos::rtos_struct>,
|
||||||
input_counter: u32,
|
input_counter: u32,
|
||||||
edge: (Option<GuestAddr>,Option<GuestAddr>),
|
edge: (Option<GuestAddr>,Option<GuestAddr>),
|
||||||
capture_point: (CaptureEvent,&'static str)
|
capture_point: (CaptureEvent,String)
|
||||||
}
|
}
|
||||||
/// List of system state dumps from QemuHelpers
|
/// List of system state dumps from QemuHelpers
|
||||||
static mut CURRENT_SYSTEMSTATE_VEC: Vec<RawFreeRTOSSystemState> = vec![];
|
static mut CURRENT_SYSTEMSTATE_VEC: Vec<RawFreeRTOSSystemState> = vec![];
|
||||||
|
Loading…
x
Reference in New Issue
Block a user