i think the memory model is fixed now? at least until arrays....

This commit is contained in:
Pat Hickey
2020-01-27 20:21:53 -08:00
parent ec456e9e50
commit c780421c28
5 changed files with 105 additions and 53 deletions

View File

@@ -105,12 +105,16 @@ fn define_enum(names: &Names, name: &witx::Id, e: &witx::EnumDatatype) -> TokenS
impl ::memory::GuestTypeCopy for #ident {}
impl ::memory::GuestTypeClone for #ident {
fn from_guest(location: &::memory::GuestPtr<#ident>) -> Result<#ident, ::memory::GuestError> {
fn read_from_guest(location: &::memory::GuestPtr<#ident>) -> Result<#ident, ::memory::GuestError> {
use ::std::convert::TryFrom;
let raw: #repr = unsafe { (location.as_raw() as *const #repr).read() };
let val = #ident::try_from(raw)?;
Ok(val)
}
fn write_to_guest(&self, location: &::memory::GuestPtrMut<#ident>) {
let val: #repr = #repr::from(*self);
unsafe { (location.as_raw() as *mut #repr).write(val) };
}
}
}

View File

@@ -1,4 +1,4 @@
use crate::{GuestError, GuestPtr};
use crate::{GuestError, GuestPtr, GuestPtrMut};
pub trait GuestType: Sized {
// These are morally the same as Rust ::std::mem::size_of / align_of, but they return
@@ -12,11 +12,12 @@ pub trait GuestType: Sized {
pub trait GuestTypeCopy: GuestType + Copy {}
pub trait GuestTypeClone: GuestType + Clone {
fn from_guest<'a>(location: &GuestPtr<'a, Self>) -> Result<Self, GuestError>;
fn read_from_guest<'a>(location: &GuestPtr<'a, Self>) -> Result<Self, GuestError>;
fn write_to_guest<'a>(&self, location: &GuestPtrMut<'a, Self>);
}
pub trait GuestTypeRef<'a>: GuestType {
type Ref;
fn from_guest(location: &GuestPtr<'a, Self>) -> Result<Self::Ref, GuestError>;
pub trait GuestTypePtr<'a>: GuestType {
fn read_from_guest(location: &GuestPtr<'a, Self>) -> Result<Self, GuestError>;
fn write_to_guest(&self, location: &GuestPtrMut<'a, Self>);
}
macro_rules! builtin_type {

View File

@@ -5,6 +5,6 @@ mod memory;
mod region;
pub use error::GuestError;
pub use guest_type::{GuestErrorType, GuestType, GuestTypeClone, GuestTypeCopy, GuestTypeRef};
pub use guest_type::{GuestErrorType, GuestType, GuestTypeClone, GuestTypeCopy, GuestTypePtr};
pub use memory::{GuestMemory, GuestPtr, GuestPtrMut, GuestRef, GuestRefMut};
pub use region::Region;

View File

@@ -3,7 +3,7 @@ use std::marker::PhantomData;
use std::rc::Rc;
use crate::borrow::{BorrowHandle, GuestBorrows};
use crate::{GuestError, GuestType, GuestTypeCopy, GuestTypeRef, Region};
use crate::{GuestError, GuestType, GuestTypeClone, GuestTypeCopy, GuestTypePtr, Region};
pub struct GuestMemory<'a> {
ptr: *mut u8,
@@ -67,6 +67,9 @@ impl<'a, T: GuestType> GuestPtr<'a, T> {
pub fn as_raw(&self) -> *const u8 {
(self.mem.ptr as usize + self.region.start as usize) as *const u8
}
}
impl<'a, T: GuestTypeCopy> GuestPtr<'a, T> {
pub fn as_ref(&self) -> Result<GuestRef<'a, T>, GuestError> {
T::validate(&self)?;
let handle = {
@@ -84,6 +87,18 @@ impl<'a, T: GuestType> GuestPtr<'a, T> {
}
}
impl<'a, T: GuestTypeClone> GuestPtr<'a, T> {
pub fn clone_from_guest(&self) -> Result<T, GuestError> {
T::read_from_guest(self)
}
}
impl<'a, T: GuestTypePtr<'a>> GuestPtr<'a, T> {
pub fn read_ptr_from_guest(&self) -> Result<T, GuestError> {
T::read_from_guest(self)
}
}
impl<'a, T> GuestType for GuestPtr<'a, T>
where
T: GuestType,
@@ -106,17 +121,24 @@ where
}
}
impl<'a, T> GuestTypeRef<'a> for GuestPtr<'a, T>
// Operations for reading and writing Ptrs to memory:
impl<'a, T> GuestTypePtr<'a> for GuestPtr<'a, T>
where
T: GuestType,
{
type Ref = GuestRef<'a, T>;
fn from_guest(location: &GuestPtr<'a, Self>) -> Result<Self::Ref, GuestError> {
fn read_from_guest(location: &GuestPtr<'a, Self>) -> Result<Self, GuestError> {
// location is guaranteed to be in GuestMemory and aligned to 4
let raw_ptr: u32 = unsafe { *(location.as_raw() as *const u32) };
// GuestMemory can validate that the raw pointer contents are legal for T:
let guest_ptr: GuestPtr<'a, T> = location.mem.ptr(raw_ptr)?;
Ok(guest_ptr.as_ref()?)
Ok(guest_ptr)
}
fn write_to_guest(&self, location: &GuestPtrMut<'a, Self>) {
// location is guaranteed to be in GuestMemory and aligned to 4
unsafe {
let raw_ptr: *mut u32 = location.as_raw() as *mut u32;
raw_ptr.write(self.region.start);
}
}
}
@@ -139,7 +161,9 @@ impl<'a, T: GuestType> GuestPtrMut<'a, T> {
pub fn as_raw(&self) -> *const u8 {
self.as_immut().as_raw()
}
}
impl<'a, T: GuestTypeCopy> GuestPtrMut<'a, T> {
pub fn as_ref(&self) -> Result<GuestRef<'a, T>, GuestError> {
self.as_immut().as_ref()
}
@@ -161,6 +185,25 @@ impl<'a, T: GuestType> GuestPtrMut<'a, T> {
}
}
impl<'a, T: GuestTypePtr<'a>> GuestPtrMut<'a, T> {
pub fn read_ptr_from_guest(&self) -> Result<T, GuestError> {
T::read_from_guest(&self.as_immut())
}
pub fn write_ptr_to_guest(&self, ptr: &T) {
T::write_to_guest(ptr, &self);
}
}
impl<'a, T: GuestTypeClone> GuestPtrMut<'a, T> {
pub fn clone_from_guest(&self) -> Result<T, GuestError> {
T::read_from_guest(&self.as_immut())
}
pub fn clone_to_guest(&self, val: &T) {
T::write_to_guest(val, &self)
}
}
impl<'a, T> GuestType for GuestPtrMut<'a, T>
where
T: GuestType,
@@ -183,17 +226,24 @@ where
}
}
impl<'a, T> GuestTypeRef<'a> for GuestPtrMut<'a, T>
// Reading and writing GuestPtrMuts to memory:
impl<'a, T> GuestTypePtr<'a> for GuestPtrMut<'a, T>
where
T: GuestType,
{
type Ref = GuestRefMut<'a, T>;
fn from_guest(location: &GuestPtr<'a, Self>) -> Result<Self::Ref, GuestError> {
fn read_from_guest(location: &GuestPtr<'a, Self>) -> Result<Self, GuestError> {
// location is guaranteed to be in GuestMemory and aligned to 4
let raw_ptr: u32 = unsafe { *(location.as_raw() as *const u32) };
// GuestMemory can validate that the raw pointer contents are legal for T:
let guest_ptr_mut: GuestPtrMut<'a, T> = location.mem.ptr_mut(raw_ptr)?;
Ok(guest_ptr_mut.as_ref_mut()?)
Ok(guest_ptr_mut)
}
fn write_to_guest(&self, location: &GuestPtrMut<'a, Self>) {
// location is guaranteed to be in GuestMemory and aligned to 4
unsafe {
let raw_ptr: *mut u32 = location.as_raw() as *mut u32;
raw_ptr.write(self.region.start);
}
}
}
@@ -204,6 +254,16 @@ pub struct GuestRef<'a, T> {
type_: PhantomData<T>,
}
impl<'a, T> GuestRef<'a, T> {
pub fn as_ptr(&self) -> GuestPtr<'a, T> {
GuestPtr {
mem: self.mem,
region: self.region,
type_: self.type_,
}
}
}
impl<'a, T> ::std::ops::Deref for GuestRef<'a, T>
where
T: GuestTypeCopy,
@@ -218,20 +278,6 @@ where
}
}
impl<'a, T> GuestRef<'a, T>
where
T: GuestTypeRef<'a>,
{
pub fn from_guest(&self) -> Result<T::Ref, GuestError> {
let ptr = GuestPtr {
mem: self.mem,
region: self.region,
type_: self.type_,
};
GuestTypeRef::from_guest(&ptr)
}
}
impl<'a, T> Drop for GuestRef<'a, T> {
fn drop(&mut self) {
let mut borrows = self.mem.borrows.borrow_mut();
@@ -246,6 +292,23 @@ pub struct GuestRefMut<'a, T> {
type_: PhantomData<T>,
}
impl<'a, T> GuestRefMut<'a, T> {
pub fn as_ptr(&self) -> GuestPtr<'a, T> {
GuestPtr {
mem: self.mem,
region: self.region,
type_: self.type_,
}
}
pub fn as_ptr_mut(&self) -> GuestPtrMut<'a, T> {
GuestPtrMut {
mem: self.mem,
region: self.region,
type_: self.type_,
}
}
}
impl<'a, T> ::std::ops::Deref for GuestRefMut<'a, T>
where
T: GuestTypeCopy,
@@ -273,20 +336,6 @@ where
}
}
impl<'a, T> GuestRefMut<'a, T>
where
T: GuestTypeRef<'a>,
{
pub fn from_guest(&self) -> Result<T::Ref, GuestError> {
let ptr = GuestPtr {
mem: self.mem,
region: self.region,
type_: self.type_,
};
GuestTypeRef::from_guest(&ptr)
}
}
impl<'a, T> Drop for GuestRefMut<'a, T> {
fn drop(&mut self) {
let mut borrows = self.mem.borrows.borrow_mut();

View File

@@ -36,22 +36,20 @@ pub mod test {
*a_better_excuse_ref = a_lamer_excuse;
// Read ptr value from mutable ptr:
let mut one_layer_down: ::memory::GuestRefMut<::memory::GuestPtr<types::Excuse>> =
two_layers_of_excuses.as_ref_mut().map_err(|e| {
let one_layer_down: ::memory::GuestPtr<types::Excuse> =
two_layers_of_excuses.read_ptr_from_guest().map_err(|e| {
eprintln!("one_layer_down error: {}", e);
types::Errno::InvalidArg
})?;
// Read enum value from that ptr:
let two_layers_down: ::memory::GuestRef<types::Excuse> =
one_layer_down.from_guest().map_err(|e| {
eprintln!("two_layers_down error: {}", e);
types::Errno::InvalidArg
})?;
let two_layers_down: types::Excuse = *one_layer_down.as_ref().map_err(|e| {
eprintln!("two_layers_down error: {}", e);
types::Errno::InvalidArg
})?;
// Write ptr value to mutable ptr:
// FIXME this is still impossible...
// two_layers_of_excuses.write_guest(&a_better_excuse_by_reference)
two_layers_of_excuses.write_ptr_to_guest(&a_better_excuse_by_reference.as_immut());
println!(
"BAZ: excuse: {:?}, better excuse: {:?}, lamer excuse: {:?}, two layers down: {:?}",