Skip to main content

ironwork_exec/
unit.rs

1//! The interpreter's run unit: `rt::unit`'s, holding each loaded program as its `Compiled` and
2//! calling through the [`Library`].
3
4pub use crate::loader::{AddProgram, Library};
5pub use rt::unit::{ADDRESS_BASE, Clock, Event, LoadError, LoadedProgram, Loader, OS_COMMAND_ROUTINES, Observer, RETURN_CODE, StatementFilter};
6
7use crate::Compiled;
8use std::rc::Rc;
9
10pub type RunUnit<'w> = rt::unit::RunUnit<'w, Rc<Compiled>, Library>;
11
12/// What a run leaves in its run unit: memory, every byte, and each program's name and where its
13/// storage starts, which the differential test compares between the interpreter and the VM.
14#[derive(Clone, Debug, Default, PartialEq, Eq)]
15pub struct Remains {
16    pub mem: Vec<u8>,
17    pub programs: Vec<(String, usize)>,
18    /// Which bytes may hold input, and the first operation taint did not follow, when the run
19    /// traced input.
20    pub taint: Option<(Vec<u64>, Option<&'static str>)>,
21    /// For a run a caller passed arguments to, each argument's bytes as the run left them, which
22    /// the caller sees after its CALL; None for OMITTED.
23    pub arguments: Vec<Option<Vec<u8>>>,
24}
25
26impl Remains {
27    pub fn of<H: Clone, L: Loader<H>>(unit: &rt::unit::RunUnit<'_, H, L>) -> Self {
28        let taint = unit.taint.as_ref().map(|t| (t.bits(), t.not_followed()));
29        Self { mem: unit.mem.clone(), programs: unit.programs.iter().map(|p| (p.name.clone(), p.base)).collect(), taint, arguments: Vec::new() }
30    }
31}