Trait wiggle::GuestMemory
source · [−]pub unsafe trait GuestMemory: Send + Sync {
fn base(&self) -> (*mut u8, u32);
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);
fn validate_size_align(
&self,
offset: u32,
align: usize,
len: u32
) -> Result<*mut u8, GuestError> { ... }
fn ptr<'a, T>(&'a self, offset: T::Pointer) -> GuestPtr<'a, T>
where
Self: Sized,
T: ?Sized + Pointee,
{ ... }
}
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 accomodate 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 GuestSlice
s and GuestStr
s for the memory
must be dropped, at which point GuestMemory::has_outstanding_borrows()
will return false
.
Required methods
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.
fn has_outstanding_borrows(&self) -> bool
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.
fn is_mut_borrowed(&self, r: Region) -> bool
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.
Check if a region of linear memory has any shared borrows.
fn mut_borrow(&self, r: Region) -> Result<BorrowHandle, GuestError>
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.
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.
fn mut_unborrow(&self, h: BorrowHandle)
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.
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
fn validate_size_align(
&self,
offset: u32,
align: usize,
len: u32
) -> Result<*mut u8, GuestError>
fn validate_size_align(
&self,
offset: u32,
align: usize,
len: u32
) -> Result<*mut u8, GuestError>
Validates a guest-relative pointer given various attributes, and returns the corresponding host pointer.
offset
- this is the guest-relative pointer, an offset from the base.align
- this is the desired alignment of the guest pointer, and if successful the host pointer will be guaranteed to have this alignment.len
- this is the number of bytes, afteroffset
, that the returned pointer must be valid for.
This function will guarantee that the returned pointer is in-bounds of
base
, at this time, for len
bytes and has alignment align
. If
any guarantees are not upheld then an error will be returned.
Note that the returned pointer is an unsafe pointer. This is not safe to
use in general because guest memory can be relocated. Additionally the
guest may be modifying/reading memory as well. Consult the
GuestMemory
documentation for safety information about using this
returned pointer.
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)
.