[][src]Trait wiggle_runtime::GuestMemory

pub unsafe trait GuestMemory {
    fn base(&self) -> (*mut u8, u32);

    fn validate_size_align(
        &self,
        offset: u32,
        align: usize,
        len: u32
    ) -> Result<*mut u8, GuestError> { ... }
fn ptr<'a, T: ?Sized>(&'a self, offset: T::Pointer) -> GuestPtr<'a, T>
    where
        Self: Sized,
        T: Pointee
, { ... } }

A trait which abstracts how to get at the region of host memory taht 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.

Using Raw Pointers

Methods like GuestMemory::base or GuestPtr::as_raw will return raw pointers to use. Returning raw pointers is significant because it shows there are hazards with using the returned pointers, and they can't blanket be used in a safe fashion. It is possible to use these pointers safely, but any usage needs to uphold a few guarantees.

  • Whenever a *mut T is accessed or modified, it must be guaranteed that since the pointer was originally obtained the guest memory wasn't relocated in any way. This means you can't call back into the guest, call other arbitrary functions which might call into the guest, etc. The problem here is that the guest could execute instructions like memory.grow which would invalidate the raw pointer. If, however, after you acquire *mut T you only execute your own code and it doesn't touch the guest, then *mut T is still guaranteed to point to valid code.

  • Furthermore, Rust's aliasing rules must still be upheld. For example you can't have two &mut T types that point to the area or overlap in any way. This in particular becomes an issue when you're dealing with multiple GuestPtr types. If you want to simultaneously work with them then you need to dynamically validate that you're either working with them all in a shared fashion (e.g. as if they were &T) or you must verify that they do not overlap to work with them as &mut T.

Note that safely using the raw pointers is relatively difficult. This crate strives to provide utilities to safely work with guest pointers so long as the previous guarantees are all upheld. If advanced operations are done with guest pointers it's recommended to be extremely cautious and thoroughly consider possible ramifications with respect to this API before codifying implementation details.

Required methods

fn base(&self) -> (*mut u8, u32)

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.

Loading content...

Provided methods

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, after offset, 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.

fn ptr<'a, T: ?Sized>(&'a self, offset: T::Pointer) -> GuestPtr<'a, T> where
    Self: Sized,
    T: 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).

Loading content...

Implementations on Foreign Types

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

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

impl<T: ?Sized + GuestMemory> GuestMemory for Box<T>[src]

impl<T: ?Sized + GuestMemory> GuestMemory for Rc<T>[src]

impl<T: ?Sized + GuestMemory> GuestMemory for Arc<T>[src]

Loading content...

Implementors

Loading content...