baryl 0.0.2

Public SDK for Baryl, a full-system emulation and introspection engine
//! `baryl`: whole-machine emulation you can write code inside of.
//!
//! A baryl run boots a real disk image under an emulator that has been opened
//! up: you can stop the guest at an address, read and write its memory, ask its
//! kernel what a process is, checkpoint the whole machine and rewind to that
//! point as often as you like. This crate is how you get at that, and there are
//! two ways in.
//!
//! Requires a licence, free, from <https://baryl.crystalpeaksecurity.com>.
//!
//! # Writing a component
//!
//! A component is a `cdylib` a run loads. It subscribes to events by writing an
//! attribute on a method, and each handler is passed a `Control` — every
//! subsystem the run has, in one value.
//!
//! ```ignore
//! use baryl::clap::{self, Parser};
//! use baryl::{Control, component};
//!
//! #[derive(Parser)]
//! #[command(no_binary_name = true)]
//! pub struct Hello {
//!     #[arg(long, default_value = "world")]
//!     who: String,
//! }
//!
//! #[component("hello")]
//! impl Hello {
//!     #[core(first_ring_three)]
//!     fn greet(&mut self, t: &mut Control) {
//!         baryl::logging::info!("hello, {}", self.who);
//!         baryl::logging::info!("{} processes", t.subs.enlighten.processes().len());
//!     }
//! }
//! ```
//!
//! With `crate-type = ["cdylib"]` in `Cargo.toml`, that builds a `libhello.so`
//! a run loads with `--component ./libhello.so --arg hello:who=there`.
//!
//! Events come from `#[core(...)]` for the run's own lifecycle, and from
//! `#[cov]`, `#[arch]`, `#[net]` and `#[fuzz]` for the subsystem that owns
//! them. Subscribing to a subsystem's event is also what asks for that
//! subsystem to be loaded; anything else you cannot run without goes in
//! `#[component("name", requires(engine, breakpoints))]`, and the run refuses
//! to start rather than handing you a handle that is not there.
//!
//! State that must survive a checkpoint goes in the pool — see the `alloc`
//! module, and [`abi::SandboxSafe`] for what may go there. Ordinary Rust state
//! is fine for anything a rewind should forget.
//!
//! # Driving a run from your own program
//!
//! `Baryl` opens an image — a disk to boot or a checkpoint to restore, read
//! from the file rather than named by you — and `Options` carries everything
//! else. Reading through `Baryl::control` runs no guest instructions, so a
//! program can open a checkpoint, inspect it, and close it again.
//!
//! ```ignore
//! use baryl::{Baryl, Options};
//!
//! let baryl = Baryl::open(Path::new("boot.ck"), &Options::default())?;
//! for p in baryl.control().subs.enlighten.processes() {
//!     println!("{} {:?}", p.pid, p.name());
//! }
//! ```
//!
//! # Features
//!
//! `component` and `x86_64` are on by default.
//!
//! - `component` — everything a component needs. Requires nightly.
//! - `cli` — `Baryl`, `Options` and the argument types in the `cli` module, for
//!   a runner of your own. Not on by default: `baryl = { version = "…",
//!   features = ["cli"] }`.
//! - `x86_64` — the x86-64 register file, page-table attributes and fault
//!   decoding. Without it `arch` is the handle and nothing ISA-specific.
//! - `control`, `config`, `logging` — the pieces the two above are built from,
//!   for a build that wants one without the rest.
#![cfg_attr(feature = "component", feature(allocator_api, portable_simd))]

pub mod abi;

#[cfg(feature = "control")]
pub mod alloc;
#[cfg(feature = "control")]
pub mod arch;
#[cfg(feature = "control")]
pub mod breakpoints;

#[cfg(feature = "config")]
pub mod config;
#[cfg(feature = "control")]
pub mod coverage;
#[cfg(feature = "control")]
pub mod engine;
#[cfg(feature = "control")]
pub mod enlighten;
#[cfg(feature = "control")]
pub mod fuzz;
#[cfg(feature = "control")]
pub mod net;

#[cfg(feature = "control")]
pub mod component_core;
#[cfg(feature = "control")]
pub mod control;
#[cfg(feature = "control")]
#[doc(hidden)]
pub mod subsystem_core;

#[cfg(feature = "component")]
pub mod component;

#[cfg(feature = "logging")]
pub mod logging;

#[cfg(feature = "control")]
pub mod mutators;

#[cfg(feature = "cli")]
pub mod cli;
#[cfg(feature = "cli")]
mod loader;
#[cfg(feature = "cli")]
mod run;
#[cfg(feature = "cli")]
mod sys;

/// The vocabulary a component writes in, so `use baryl::VirtAddr` works without
/// naming [`abi`]. The exported macros land here too.
pub use crate::abi::{
    AnonPtr, BpInsertError, FlatCStr, MemAccessError, PhysAddr, SandboxSafe, SbxArray, SbxPtr,
    VMC_BODY_MASK, VMC_DST_BROADCAST, VMC_DST_MASK, VMC_TYPE_MASK, VMCall, VirtAddr, fnv1a_32,
    fnv1a_64, inline_cstr, pack_cstr,
};
/// The two pool-backed collections.
#[cfg(feature = "component")]
pub use crate::abi::{BMap, BVec};
/// The descriptor a component exports and the callback shapes its slots hold.
/// `#[component]` builds one; these are what a hand-written descriptor needs.
#[cfg(feature = "component")]
pub use crate::component::{
    BARYL_COMPONENT_ABI_VERSION, BARYL_COMPONENT_MIN_ABI_VERSION, ComponentDescriptor, ControlFn,
    CoreCallbacks, GenericCb, VmcallCb, VmcallFn,
};
/// `Control`, and the `BARYL_SUB_*` id of every subsystem a `requires(...)`
/// word or a subscribed event can name.
#[cfg(feature = "control")]
pub use crate::control::{
    BARYL_SUB_ARCH, BARYL_SUB_BREAKPOINTS, BARYL_SUB_CORPUS, BARYL_SUB_COVERAGE, BARYL_SUB_ENGINE,
    BARYL_SUB_ENLIGHTEN, BARYL_SUB_FUZZ, BARYL_SUB_NET, BARYL_SUB_STATS, Control, ControlError,
    Subsystems,
};
/// Opening and running a machine from your own program.
#[cfg(feature = "cli")]
pub use crate::run::{Baryl, Options, RunEnd};
/// The window of runtime ABI revisions this build can load. A runtime outside
/// it is refused when the library is opened, rather than misread.
#[cfg(feature = "cli")]
pub use crate::sys::{BARYL_ABI_VERSION, BARYL_MIN_ABI_VERSION};
/// `#[component]`, and one attribute per subsystem whose events a method can
/// subscribe to. The coverage one is spelled `#[cov]`.
pub use baryl_macros::{arch, component, core, cov, fuzz, net};
/// The clap `#[component]` expands into and a runner derives its verbs on.
/// Reach it through here — `use baryl::clap::{self, Parser}` — and your crate
/// needs no clap dependency of its own.
#[cfg(any(feature = "component", feature = "cli"))]
pub use clap;

/// What `#[component]` implements on your type. Never write one by hand.
#[cfg(feature = "component")]
pub trait Component {
    /// The `BARYL_SUB_*` ids this component cannot run without: what
    /// `requires(...)` named, plus one per subsystem a method subscribed to.
    const REQUIRES: &'static [u32];
    /// The descriptor the run reads out of this library.
    const DESCRIPTOR: ComponentDescriptor;
}