Insulate API from intricacies of memory mgmt of calling runtimes

This commit is contained in:
Jakub Konka
2019-05-11 10:44:54 +02:00
parent 751a1a1f7b
commit 75ad92b0f3
5 changed files with 228 additions and 295 deletions

View File

@@ -9,7 +9,6 @@
//!
//! This sort of manual encoding will hopefully be obsolete once the IDL is developed.
use crate::vmctx::VmContextView;
use crate::{host, wasm32};
use cast;
@@ -24,54 +23,52 @@ macro_rules! bail_errno {
}
pub unsafe fn dec_ptr(
vmctx: &VmContextView,
memory: &mut [u8],
ptr: wasm32::uintptr_t,
len: usize,
) -> Result<*mut u8, host::__wasi_errno_t> {
let mut heap = vmctx.memory_mut();
// check that `len` fits in the wasm32 address space
if len > wasm32::UINTPTR_MAX as usize {
bail_errno!(__WASI_EOVERFLOW);
}
// check that `ptr` and `ptr + len` are both within the guest heap
if ptr as usize > heap.len() || ptr as usize + len > heap.len() {
if ptr as usize > memory.len() || ptr as usize + len > memory.len() {
bail_errno!(__WASI_EFAULT);
}
// translate the pointer
Ok(heap.as_mut_ptr().offset(ptr as isize))
Ok(memory.as_mut_ptr().offset(ptr as isize))
}
pub unsafe fn dec_ptr_to<T>(
vmctx: &VmContextView,
memory: &mut [u8],
ptr: wasm32::uintptr_t,
) -> Result<*mut T, host::__wasi_errno_t> {
// check that the ptr is aligned
if ptr as usize % align_of::<T>() != 0 {
bail_errno!(__WASI_EINVAL);
}
dec_ptr(vmctx, ptr, size_of::<T>()).map(|p| p as *mut T)
dec_ptr(memory, ptr, size_of::<T>()).map(|p| p as *mut T)
}
pub unsafe fn dec_pointee<T>(
vmctx: &VmContextView,
memory: &mut [u8],
ptr: wasm32::uintptr_t,
) -> Result<T, host::__wasi_errno_t> {
dec_ptr_to::<T>(vmctx, ptr).map(|p| p.read())
dec_ptr_to::<T>(memory, ptr).map(|p| p.read())
}
pub unsafe fn enc_pointee<T>(
vmctx: &VmContextView,
memory: &mut [u8],
ptr: wasm32::uintptr_t,
t: T,
) -> Result<(), host::__wasi_errno_t> {
dec_ptr_to::<T>(vmctx, ptr).map(|p| p.write(t))
dec_ptr_to::<T>(memory, ptr).map(|p| p.write(t))
}
pub unsafe fn dec_slice_of<T>(
vmctx: &VmContextView,
memory: &mut [u8],
ptr: wasm32::uintptr_t,
len: wasm32::size_t,
) -> Result<(*mut T, usize), host::__wasi_errno_t> {
@@ -86,13 +83,13 @@ pub unsafe fn dec_slice_of<T>(
return Err(host::__WASI_EOVERFLOW);
};
let ptr = dec_ptr(vmctx, ptr, len_bytes)? as *mut T;
let ptr = dec_ptr(memory, ptr, len_bytes)? as *mut T;
Ok((ptr, len))
}
pub unsafe fn enc_slice_of<T>(
vmctx: &VmContextView,
memory: &mut [u8],
slice: &[T],
ptr: wasm32::uintptr_t,
) -> Result<(), host::__wasi_errno_t> {
@@ -108,7 +105,7 @@ pub unsafe fn enc_slice_of<T>(
};
// get the pointer into guest memory, and copy the bytes
let ptr = dec_ptr(vmctx, ptr, len_bytes)? as *mut libc::c_void;
let ptr = dec_ptr(memory, ptr, len_bytes)? as *mut libc::c_void;
libc::memcpy(ptr, slice.as_ptr() as *const libc::c_void, len_bytes);
Ok(())
@@ -121,10 +118,10 @@ macro_rules! dec_enc_scalar {
}
pub unsafe fn $dec_byref(
vmctx: &VmContextView,
memory: &mut [u8],
ptr: wasm32::uintptr_t,
) -> Result<host::$ty, host::__wasi_errno_t> {
dec_pointee::<wasm32::$ty>(vmctx, ptr).map($dec)
dec_pointee::<wasm32::$ty>(memory, ptr).map($dec)
}
pub fn $enc(x: host::$ty) -> wasm32::$ty {
@@ -132,34 +129,34 @@ macro_rules! dec_enc_scalar {
}
pub unsafe fn $enc_byref(
vmctx: &VmContextView,
memory: &mut [u8],
ptr: wasm32::uintptr_t,
x: host::$ty,
) -> Result<(), host::__wasi_errno_t> {
enc_pointee::<wasm32::$ty>(vmctx, ptr, $enc(x))
enc_pointee::<wasm32::$ty>(memory, ptr, $enc(x))
}
};
}
pub unsafe fn dec_ciovec(
vmctx: &VmContextView,
memory: &mut [u8],
ciovec: &wasm32::__wasi_ciovec_t,
) -> Result<host::__wasi_ciovec_t, host::__wasi_errno_t> {
let len = dec_usize(ciovec.buf_len);
Ok(host::__wasi_ciovec_t {
buf: dec_ptr(vmctx, ciovec.buf, len)? as *const host::void,
buf: dec_ptr(memory, ciovec.buf, len)? as *const host::void,
buf_len: len,
})
}
pub unsafe fn dec_ciovec_slice(
vmctx: &VmContextView,
memory: &mut [u8],
ptr: wasm32::uintptr_t,
len: wasm32::size_t,
) -> Result<Vec<host::__wasi_ciovec_t>, host::__wasi_errno_t> {
let slice = dec_slice_of::<wasm32::__wasi_ciovec_t>(vmctx, ptr, len)?;
let slice = dec_slice_of::<wasm32::__wasi_ciovec_t>(memory, ptr, len)?;
let slice = slice::from_raw_parts(slice.0, slice.1);
slice.iter().map(|iov| dec_ciovec(vmctx, iov)).collect()
slice.iter().map(|iov| dec_ciovec(memory, iov)).collect()
}
dec_enc_scalar!(
@@ -227,10 +224,10 @@ pub fn dec_filestat(filestat: wasm32::__wasi_filestat_t) -> host::__wasi_filesta
}
pub unsafe fn dec_filestat_byref(
vmctx: &VmContextView,
memory: &mut [u8],
filestat_ptr: wasm32::uintptr_t,
) -> Result<host::__wasi_filestat_t, host::__wasi_errno_t> {
dec_pointee::<wasm32::__wasi_filestat_t>(vmctx, filestat_ptr).map(dec_filestat)
dec_pointee::<wasm32::__wasi_filestat_t>(memory, filestat_ptr).map(dec_filestat)
}
pub fn enc_filestat(filestat: host::__wasi_filestat_t) -> wasm32::__wasi_filestat_t {
@@ -247,12 +244,12 @@ pub fn enc_filestat(filestat: host::__wasi_filestat_t) -> wasm32::__wasi_filesta
}
pub unsafe fn enc_filestat_byref(
vmctx: &VmContextView,
memory: &mut [u8],
filestat_ptr: wasm32::uintptr_t,
host_filestat: host::__wasi_filestat_t,
) -> Result<(), host::__wasi_errno_t> {
let filestat = enc_filestat(host_filestat);
enc_pointee::<wasm32::__wasi_filestat_t>(vmctx, filestat_ptr, filestat)
enc_pointee::<wasm32::__wasi_filestat_t>(memory, filestat_ptr, filestat)
}
pub fn dec_fdstat(fdstat: wasm32::__wasi_fdstat_t) -> host::__wasi_fdstat_t {
@@ -265,10 +262,10 @@ pub fn dec_fdstat(fdstat: wasm32::__wasi_fdstat_t) -> host::__wasi_fdstat_t {
}
pub unsafe fn dec_fdstat_byref(
vmctx: &VmContextView,
memory: &mut [u8],
fdstat_ptr: wasm32::uintptr_t,
) -> Result<host::__wasi_fdstat_t, host::__wasi_errno_t> {
dec_pointee::<wasm32::__wasi_fdstat_t>(vmctx, fdstat_ptr).map(dec_fdstat)
dec_pointee::<wasm32::__wasi_fdstat_t>(memory, fdstat_ptr).map(dec_fdstat)
}
pub fn enc_fdstat(fdstat: host::__wasi_fdstat_t) -> wasm32::__wasi_fdstat_t {
@@ -282,12 +279,12 @@ pub fn enc_fdstat(fdstat: host::__wasi_fdstat_t) -> wasm32::__wasi_fdstat_t {
}
pub unsafe fn enc_fdstat_byref(
vmctx: &VmContextView,
memory: &mut [u8],
fdstat_ptr: wasm32::uintptr_t,
host_fdstat: host::__wasi_fdstat_t,
) -> Result<(), host::__wasi_errno_t> {
let fdstat = enc_fdstat(host_fdstat);
enc_pointee::<wasm32::__wasi_fdstat_t>(vmctx, fdstat_ptr, fdstat)
enc_pointee::<wasm32::__wasi_fdstat_t>(memory, fdstat_ptr, fdstat)
}
dec_enc_scalar!(
@@ -349,10 +346,10 @@ pub fn dec_prestat(
}
pub unsafe fn dec_prestat_byref(
vmctx: &VmContextView,
memory: &mut [u8],
prestat_ptr: wasm32::uintptr_t,
) -> Result<host::__wasi_prestat_t, host::__wasi_errno_t> {
dec_pointee::<wasm32::__wasi_prestat_t>(vmctx, prestat_ptr).and_then(dec_prestat)
dec_pointee::<wasm32::__wasi_prestat_t>(memory, prestat_ptr).and_then(dec_prestat)
}
pub fn enc_prestat(
@@ -375,12 +372,12 @@ pub fn enc_prestat(
}
pub unsafe fn enc_prestat_byref(
vmctx: &VmContextView,
memory: &mut [u8],
prestat_ptr: wasm32::uintptr_t,
host_prestat: host::__wasi_prestat_t,
) -> Result<(), host::__wasi_errno_t> {
let prestat = enc_prestat(host_prestat)?;
enc_pointee::<wasm32::__wasi_prestat_t>(vmctx, prestat_ptr, prestat)
enc_pointee::<wasm32::__wasi_prestat_t>(memory, prestat_ptr, prestat)
}
dec_enc_scalar!(
@@ -407,11 +404,11 @@ pub fn enc_usize(size: usize) -> wasm32::size_t {
}
pub unsafe fn enc_usize_byref(
vmctx: &VmContextView,
memory: &mut [u8],
usize_ptr: wasm32::uintptr_t,
host_usize: usize,
) -> Result<(), host::__wasi_errno_t> {
enc_pointee::<wasm32::size_t>(vmctx, usize_ptr, enc_usize(host_usize))
enc_pointee::<wasm32::size_t>(memory, usize_ptr, enc_usize(host_usize))
}
dec_enc_scalar!(