Trait wiggle::GuestMemory

source ·
pub unsafe trait GuestMemory: Send + Sync {
    // Required methods
    fn base(&self) -> &[UnsafeCell<u8>];
    fn has_outstanding_borrows(&self) -> bool;
    fn is_mut_borrowed(&self, r: Region) -> bool;
    fn is_shared_borrowed(&self, r: Region) -> bool;
    fn mut_borrow(&self, r: Region) -> Result<BorrowHandle, GuestError>;
    fn shared_borrow(&self, r: Region) -> Result<BorrowHandle, GuestError>;
    fn mut_unborrow(&self, h: BorrowHandle);
    fn shared_unborrow(&self, h: BorrowHandle);

    // Provided methods
    fn ptr<'a, T>(&'a self, offset: T::Pointer) -> GuestPtr<'a, T>
       where Self: Sized,
             T: ?Sized + Pointee { ... }
    fn is_shared_memory(&self) -> bool { ... }
}
Expand description

A trait which abstracts how to get at the region of host memory that contains guest memory.

All GuestPtr types will contain a handle to this trait, signifying where the pointer is actually pointing into. This type will need to be implemented for the host’s memory storage object.

§Safety

Safety around this type is tricky, and the trait is unsafe since there are a few contracts you need to uphold to implement this type correctly and have everything else in this crate work out safely.

The most important method of this trait is the base method. This returns, in host memory, a pointer and a length. The pointer should point to valid memory for the guest to read/write for the length contiguous bytes afterwards.

The region returned by base must not only be valid, however, but it must be valid for “a period of time before the guest is reentered”. This isn’t exactly well defined but the general idea is that GuestMemory is allowed to change under our feet to accommodate instructions like memory.grow or other guest modifications. Memory, however, cannot be changed if the guest is not reentered or if no explicitly action is taken to modify the guest memory.

This provides the guarantee that host pointers based on the return value of base have a dynamic period for which they are valid. This time duration must be “somehow nonzero in length” to allow users of GuestMemory and GuestPtr to safely read and write interior data.

This type also provides methods for run-time borrow checking of references into the memory. The safety of this mechanism depends on there being exactly one associated tracking of borrows for a given WebAssembly memory. There must be no other reads or writes of WebAssembly the memory by either Rust or WebAssembly code while there are any outstanding borrows, as given by GuestMemory::has_outstanding_borrows().

§Using References

The GuestPtr::as_slice or GuestPtr::as_str will return smart pointers GuestSlice and GuestStr. These types, which implement std::ops::Deref and std::ops::DerefMut, provide mutable references into the memory region given by a GuestMemory.

These smart pointers are dynamically borrow-checked by the borrow checker methods on this trait. While a GuestSlice or a GuestStr are live, the GuestMemory::has_outstanding_borrows() method will always return true. If you need to re-enter the guest or otherwise read or write to the contents of a WebAssembly memory, all GuestSlices and GuestStrs for the memory must be dropped, at which point GuestMemory::has_outstanding_borrows() will return false.

Required Methods§

source

fn base(&self) -> &[UnsafeCell<u8>]

Returns the base allocation of this guest memory, located in host memory.

A pointer/length pair are returned to signify where the guest memory lives in the host, and how many contiguous bytes the memory is valid for after the returned pointer.

Note that there are safety guarantees about this method that implementations must uphold, and for more details see the GuestMemory documentation.

source

fn has_outstanding_borrows(&self) -> bool

Indicates whether any outstanding borrows are known to the GuestMemory. This function must be false in order for it to be safe to recursively call into a WebAssembly module, or to manipulate the WebAssembly memory by any other means.

source

fn is_mut_borrowed(&self, r: Region) -> bool

Check if a region of linear memory is exclusively borrowed. This is called during any GuestPtr::read or GuestPtr::write operation to ensure that wiggle is not reading or writing a region of memory which Rust believes it has exclusive access to.

source

fn is_shared_borrowed(&self, r: Region) -> bool

Check if a region of linear memory has any shared borrows.

source

fn mut_borrow(&self, r: Region) -> Result<BorrowHandle, GuestError>

Exclusively borrow a region of linear memory. This is used when constructing a GuestSliceMut or GuestStrMut. Those types will give Rust &mut access to the region of linear memory, therefore, the GuestMemory impl must guarantee that at most one BorrowHandle is issued to a given region, GuestMemory::has_outstanding_borrows is true for the duration of the borrow, and that GuestMemory::is_mut_borrowed of any overlapping region is false for the duration of the borrow.

source

fn shared_borrow(&self, r: Region) -> Result<BorrowHandle, GuestError>

Shared borrow a region of linear memory. This is used when constructing a GuestSlice or GuestStr. Those types will give Rust & (shared reference) access to the region of linear memory.

source

fn mut_unborrow(&self, h: BorrowHandle)

Unborrow a previously borrowed mutable region. As long as GuestSliceMut and GuestStrMut are implemented correctly, a mut BorrowHandle should only be unborrowed once.

source

fn shared_unborrow(&self, h: BorrowHandle)

Unborrow a previously borrowed shared region. As long as GuestSlice and GuestStr are implemented correctly, a shared BorrowHandle should only be unborrowed once.

Provided Methods§

source

fn ptr<'a, T>(&'a self, offset: T::Pointer) -> GuestPtr<'a, T>
where Self: Sized, T: ?Sized + Pointee,

Convenience method for creating a GuestPtr at a particular offset.

Note that T can be almost any type, and typically offset is a u32. The exception is slices and strings, in which case offset is a (u32, u32) of (offset, length).

source

fn is_shared_memory(&self) -> bool

Check if the underlying memory is shared across multiple threads; e.g., with a WebAssembly shared memory.

Implementations on Foreign Types§

source§

impl<'a, T: ?Sized + GuestMemory> GuestMemory for &'a T

source§

impl<'a, T: ?Sized + GuestMemory> GuestMemory for &'a mut T

source§

impl<T: ?Sized + GuestMemory> GuestMemory for Box<T>

source§

impl<T: ?Sized + GuestMemory> GuestMemory for Arc<T>

Implementors§