use std::cell::RefCell;
use std::path::Path;
use crate::cpu::armv7m::testing::{Bench, CODE, RAM, SIZE, spec, spec_of};
use crate::emulator::{Exit, Fuzzed, Processor, WalkThreads};
use crate::machine::armv7m::Config;
use crate::machine::armv7m::{Fpu, MpuRegions, Variant};
use crate::soc::Region;
const INSTRUCTIONS: u32 = 256;
thread_local! {
static BENCH: RefCell<Bench> = RefCell::new(Bench::new(&[]));
static SERVED: RefCell<[Fuzzed; 2]> = {
let kernels = kernels();
RefCell::new([
served(&spec(), kernels),
served(&spec_of(Variant::M3, Fpu::None, MpuRegions::Eight), kernels),
])
};
}
#[cfg(feature = "cli")]
fn kernels() -> &'static [Box<dyn WalkThreads>] {
Box::leak(crate::cli::kernels().into_boxed_slice())
}
#[cfg(not(feature = "cli"))]
fn kernels() -> &'static [Box<dyn WalkThreads>] {
&[]
}
fn served(config: &Config, kernels: &'static [Box<dyn WalkThreads>]) -> Fuzzed {
let size = SIZE as u64;
let mut spec = config.clone().spec();
spec.aliases.clear();
Fuzzed::new(
&spec,
&[
Region::flash("code", u64::from(CODE), size),
Region::ram("ram", u64::from(RAM), size),
],
kernels,
)
}
pub fn run_code(code: &[u8]) {
let halfwords: Vec<u16> = code
.chunks(2)
.take(SIZE / 2)
.map(|pair| u16::from_le_bytes([pair[0], pair.get(1).copied().unwrap_or(0)]))
.collect();
BENCH.with_borrow_mut(|bench| {
bench.restart(&halfwords);
run_on(bench);
});
}
fn run_on(bench: &mut Bench) {
let mut left = INSTRUCTIONS;
for _ in 0..2 * INSTRUCTIONS {
let (exit, ran) = bench.run(left);
left -= u32::try_from(ran).expect("no more than it was given");
if left == 0 || matches!(exit, Exit::Waiting | Exit::Lockup) {
break;
}
}
}
pub fn load_state(state: &[u8]) {
BENCH.with_borrow_mut(|bench| {
bench.restart(&[]);
if bench.core.load(state).is_ok() {
bench.run(64);
}
});
}
pub fn read_snapshot(file: &[u8]) {
drop(crate::snapshot::parse(file, Path::new("fuzzed")));
}
pub fn gdb_packets(bytes: &[u8]) {
SERVED.with_borrow_mut(|served| {
for server in served {
server.serve(bytes);
}
});
}