pub struct Image {
pub code: CodeRef,
pub endpoints: BTreeMap<Key, EndpointDef>,
pub memory_mappings: Vec<MemoryMapping>,
pub pinned_slots: BTreeMap<Key, PinnedCap>,
pub initial_slots: BTreeMap<Key, InitialDataCap>,
pub yield_receiver_slot: Option<Key>,
pub gas_slots: Vec<Key>,
pub quota_slots: Vec<Key>,
pub arena: Vec<u8>,
}Expand description
Image: the program spec (code, endpoints, memory layout, slot declarations, pinned ro caps).
pinned_slots and yield_receiver_slot reference cnode slots; the
kernel installs declared pinned content into the Instance’s cnode
at set_image / host_derive_spawn time and treats them as
read-only thereafter.
Validation model. This is the untrusted SSZ wire form; converting
it to a crate::cap::image::ImageCap via
crate::cap::image::image_cap is the “deblob” that validates the
Image’s structure eagerly (sizes, bounds, slot indices, path depth).
The code bytes are never screened — instruction semantics are
validated lazily, at execution. See crate::cap::image::ImageCap for
the full structure-eager / semantics-lazy rationale.
Fields§
§code: CodeRefThe (single) code region: raw RV+C+custom-0 bytes. Mapped RO at
the fixed protocol constant crate::layout::CODE_BASE (PC =
CODE_BASE + byte_offset) — the load address is not chosen by
the Image, so an untrusted Image cannot place code arbitrarily.
Code is mapped RO into the guest address space so the guest can
read its own bytes (AUIPC+load PIC); the JIT executes the native
translation. Empty for codeless images (kernel placeholders).
endpoints: BTreeMap<Key, EndpointDef>Endpoints addressable by a Key selector (the same byte-string key
type as a cnode slot; in the V1 single-byte ABI the selector is one
byte). Sparse — only declared endpoints are present, with no fixed
capacity. An absent key is an undefined endpoint.
memory_mappings: Vec<MemoryMapping>Memory layout. Each entry maps a Cap::Data (resolved through
the source slot path) into the address space at `[start, start
- size)
. RO vs RW is derived from whether the target slot appears inpinned_slots. Code is mapped separately at [crate::layout::CODE_BASE`] and is not described here.
pinned_slots: BTreeMap<Key, PinnedCap>Pinned read-only caps (Cap::Data or Cap::Image) baked into the spec. The kernel rejects mutations to these slots.
initial_slots: BTreeMap<Key, InitialDataCap>Initial cnode state for non-pinned mutable slots. Only honored at standalone (root) Instance bootstrap — a parented Instance receives its cnode from the spawner.
yield_receiver_slot: Option<Key>Slot holding Cap::Instance[YieldReceiver] — the set of yield_keys this
Instance catches. The kernel snapshots it at each downward CALL and
consults the snapshot when routing a yield. None = catches no yields.
gas_slots: Vec<Key>Cnode slots holding the Cap::Instance[Gas{meter_key}] unit handles
the kernel debits while this Instance runs. Slots are consulted in order:
empty declared slots are skipped, the first valid non-empty slot is the
primary meter used in OOG payloads, and later valid slots are fallback
reserves. Empty list = no Image-declared meter (the frame loans its
caller’s gas scope, or the host budget at root).
quota_slots: Vec<Key>Cnode slots holding the Cap::Instance[Quota{quota_key}] unit handles.
Same convention as Self::gas_slots.
arena: Vec<u8>Payload arena: a single byte pool holding the code region and every
data cap’s non-zero pages, packed tightly. CodeRef indexes the
contiguous code slice; each ArenaPageRef indexes a window holding
one page’s non-zero prefix (zero-padded back to PAGE_SIZE at decode).
All-zero pages are never stored — they are elided and materialize
as the canonical zero page at deblob, so blobs carry no .bss/
leading-gap zeros, and trailing zeros within a page are dropped too.
Identical pages may share one window (dedup); sharing is invisible to
cap identity. Trailing field so the structural header decodes without
touching the payload.
Implementations§
Source§impl Image
impl Image
Sourcepub fn empty() -> Self
pub fn empty() -> Self
Empty Image: no code, no endpoints, no mappings, no slots. Useful for tests and as a starting point.
Sourcepub fn with_code(code: Vec<u8>) -> Self
pub fn with_code(code: Vec<u8>) -> Self
An Image carrying only code (no slots/mappings/endpoints): the
arena holds the page-rounded code at offset 0. Convenience for the
test helpers that previously did let mut img = Image::empty(); img.code = bytes; — set the other structural fields after.
Sourcepub fn code_bytes(&self) -> &[u8] ⓘ
pub fn code_bytes(&self) -> &[u8] ⓘ
The raw code bytes: the arena window [code.arena_off, code.arena_off + code.len). Empty slice for a codeless image (or
an out-of-range CodeRef, which the deblob rejects separately).
Sourcepub fn mem_extent(&self) -> u64
pub fn mem_extent(&self) -> u64
The Instance data extent in bytes: mem_top − DATA_BASE, page-rounded
(the size of the RW memory DataCap). Code is RO direct-mapped at
CODE_BASE, so it contributes nothing here.
Sourcepub fn instance_mem_backing(&self) -> DataCap
pub fn instance_mem_backing(&self) -> DataCap
Build the Instance’s memory backing crate::DataCap: every mapping’s source
content (pinned and initial) folded at the mapping’s offset above
DATA_BASE. This is the same byte layout the legacy data_overlays
produced, collapsed into one dense DataCap.
Pinned content is included here (not kept separate) so the cache-free
nub-arch-local engine can seed memory without resolving caps; both
engines still mark the pinned VAs read-only at seed time, and the
recompiler maps them as PinnedCapRo directly from these slabs, so the
pinned-RO gas tier is preserved.
Single source of truth for Instance memory layout: both engines seed from this backing, so they materialize byte-identical memory.
Precondition: the Image must be deblob-validated
(crate::cap::image::image_cap, which runs DataDesc::validate on
every slot) before this is called — it slices self.arena by each
page-ref’s arena_off, so an out-of-range ref on an unvalidated
Image would panic. Producers (ImageBuilder) always emit in-bounds
page-refs, and the deblob rejects malformed ones loudly.
Trait Implementations§
Source§impl Decode for Image
impl Decode for Image
Source§fn is_ssz_fixed_len() -> bool
fn is_ssz_fixed_len() -> bool
true iff this type is fixed-length.Source§fn ssz_fixed_len() -> usize
fn ssz_fixed_len() -> usize
BYTES_PER_LENGTH_OFFSET].Source§fn from_ssz_bytes(bytes: &[u8]) -> Result<Self, DecodeError>
fn from_ssz_bytes(bytes: &[u8]) -> Result<Self, DecodeError>
bytes, rejecting trailing input.Source§impl Encode for Image
impl Encode for Image
Source§fn is_ssz_fixed_len() -> bool
fn is_ssz_fixed_len() -> bool
true iff this type is fixed-length (no variable-length fields).Source§fn ssz_fixed_len() -> usize
fn ssz_fixed_len() -> usize
BYTES_PER_LENGTH_OFFSET] (i.e. the size of the offset slot).Source§fn ssz_bytes_len(&self) -> usize
fn ssz_bytes_len(&self) -> usize
self when serialized.Source§fn ssz_append(&self, buf: &mut Vec<u8>)
fn ssz_append(&self, buf: &mut Vec<u8>)
self to buf.§fn is_basic_type() -> bool
fn is_basic_type() -> bool
true for “basic” SSZ types (uintN, bool), which pack adjacent
elements into shared 32-byte chunks for merkleization. Composite
types (containers, lists, structs) return false (the default).§fn as_ssz_bytes(&self) -> Vec<u8> ⓘ
fn as_ssz_bytes(&self) -> Vec<u8> ⓘ
Vec<u8> allocated through the global allocator.