expose vfs in emscripten and impl read syscall, feature flag

This commit is contained in:
Mackenzie Clark 2019-03-12 10:48:33 -07:00
parent b9c3a49f3c
commit cc3f04efd7
12 changed files with 104 additions and 8 deletions

View File

@ -39,7 +39,7 @@ glob = "0.2.11"
[features]
default = ["fast-tests"]
vfs = ["wasmer-runtime-abi", "wasmer-runtime-core/vfs", "wasmer-emscripten/vfs", "wasmer-clif-backend/vfs"]
debug = ["wasmer-clif-backend/debug", "wasmer-runtime-core/debug"]
# This feature will allow cargo test to run much faster
fast-tests = []

View File

@ -10,6 +10,8 @@ build = "build/mod.rs"
[dependencies]
wasmer-runtime-core = { path = "../runtime-core", version = "0.2.1" }
wasmer-clif-backend = { path = "../clif-backend", version = "0.2.0" }
wasmer-runtime-abi = { path = "../runtime-abi", optional = true }
lazy_static = "1.2.0"
libc = "0.2.49"
byteorder = "1"
@ -19,7 +21,6 @@ time = "0.1.41"
rand = "0.6"
[dev-dependencies]
wasmer-clif-backend = { path = "../clif-backend", version = "0.2.0" }
wabt = "0.7.2"
[target.'cfg(not(windows))'.dev-dependencies]
@ -30,4 +31,5 @@ glob = "0.2.11"
[features]
clif = []
llvm = []
llvm = []
vfs = ["wasmer-runtime-core/vfs", "wasmer-clif-backend/vfs", "wasmer-runtime-abi"]

12
lib/emscripten/emtests/test_vfs.c vendored Normal file
View File

@ -0,0 +1,12 @@
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
int main() {
char data[256] = {0};
ssize_t fd = open("data.txt", 0);
ssize_t result = read((int)fd, &data, 255);
printf("content: %s", data);
printf("fd: %zd\n", fd);
return 0;
}

6
lib/emscripten/emtests/test_vfs.md vendored Normal file
View File

@ -0,0 +1,6 @@
The wasm file `test_vfs.wasm` is generated by compiling the `test_vfs.c` and writing a tar.zst blob with a single file
named `data.txt`.
The program expects to find a file named `data.txt` and reads the contents and the file descriptor.
The runtime should mount the virtual filesystem and expose the file.

1
lib/emscripten/emtests/test_vfs.out vendored Normal file
View File

@ -0,0 +1 @@
content: wasmer is awesomer

BIN
lib/emscripten/emtests/test_vfs.wasm vendored Normal file

Binary file not shown.

View File

@ -54,6 +54,11 @@ pub use self::utils::{
get_emscripten_table_size, is_emscripten_module,
};
use std::fs::File;
use std::io::Write;
#[cfg(feature = "vfs")]
use wasmer_runtime_abi::vfs::vfs::VfsBacking;
// TODO: Magic number - how is this calculated?
const TOTAL_STACK: u32 = 5_242_880;
// TODO: Magic number - how is this calculated?
@ -135,6 +140,9 @@ pub struct EmscriptenData<'a> {
pub dyn_call_viji: Option<Func<'a, (i32, i32, i32, i32, i32)>>,
pub dyn_call_vijiii: Option<Func<'a, (i32, i32, i32, i32, i32, i32, i32)>>,
pub dyn_call_vijj: Option<Func<'a, (i32, i32, i32, i32, i32, i32)>>,
#[cfg(feature = "vfs")]
pub vfs: Option<VfsBacking>,
}
impl<'a> EmscriptenData<'a> {
@ -231,17 +239,33 @@ impl<'a> EmscriptenData<'a> {
dyn_call_viji,
dyn_call_vijiii,
dyn_call_vijj,
#[cfg(feature = "vfs")]
vfs: None,
}
}
}
pub fn run_emscripten_instance(
_module: &Module,
module: &Module,
instance: &mut Instance,
path: &str,
args: Vec<&str>,
) -> CallResult<()> {
let mut data = EmscriptenData::new(instance);
// Construct a new virtual filesystem and inject it into the emscripten data
// This is behind a feature flag for now, but will be default in the future
#[cfg(feature = "vfs")]
{
data.vfs = match module.info().custom_sections.get("wasmer_fs") {
Some(bytes) => match VfsBacking::from_tar_zstd_bytes(&bytes[..]) {
Ok(vfs_backing) => Some(vfs_backing),
Err(_) => None,
},
None => None,
};
}
let data_ptr = &mut data as *mut _ as *mut c_void;
instance.context_mut().data = data_ptr;

View File

@ -29,7 +29,7 @@ use libc::{
// iovec,
lseek,
// open,
read,
// read,
// readv,
rmdir,
// writev,
@ -40,7 +40,6 @@ use libc::{
use wasmer_runtime_core::vm::Ctx;
use super::env;
use std::cell::Cell;
use std::slice;
// use std::sys::fd::FileDesc;
@ -67,6 +66,7 @@ pub fn ___syscall1(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) {
}
/// read
#[cfg(not(feature = "vfs"))]
pub fn ___syscall3(ctx: &mut Ctx, which: i32, mut varargs: VarArgs) -> i32 {
// -> ssize_t
debug!("emscripten::___syscall3 (read) {}", which);
@ -75,7 +75,27 @@ pub fn ___syscall3(ctx: &mut Ctx, which: i32, mut varargs: VarArgs) -> i32 {
let count: i32 = varargs.get(ctx);
debug!("=> fd: {}, buf_offset: {}, count: {}", fd, buf, count);
let buf_addr = emscripten_memory_pointer!(ctx.memory(0), buf) as *mut c_void;
let ret = unsafe { read(fd, buf_addr, count as _) };
let ret = unsafe { libc::read(fd, buf_addr, count as _) };
debug!("=> ret: {}", ret);
ret as _
}
/// read
#[cfg(feature = "vfs")]
pub fn ___syscall3(ctx: &mut Ctx, which: i32, mut varargs: VarArgs) -> i32 {
// -> ssize_t
debug!("emscripten::___syscall3 (read - vfs) {}", which);
let fd: i32 = varargs.get(ctx);
let buf: u32 = varargs.get(ctx);
let count: i32 = varargs.get(ctx);
debug!("=> fd: {}, buf_offset: {}, count: {}", fd, buf, count);
let buf_addr = emscripten_memory_pointer!(ctx.memory(0), buf) as *mut u8;
let mut buf_slice = unsafe { slice::from_raw_parts_mut(buf_addr, count as _) };
let emscripten_data = get_emscripten_data(ctx);
let ret = match &mut emscripten_data.vfs {
Some(vfs) => vfs.read_file(fd as _, &mut buf_slice).unwrap(),
None => 0,
};
debug!("=> ret: {}", ret);
ret as _
}
@ -91,6 +111,23 @@ pub fn ___syscall4(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
unsafe { write(fd, buf_addr, count as _) as i32 }
}
/// open
#[cfg(feature = "vfs")]
pub fn ___syscall5(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
debug!("emscripten::___syscall5 (open vfs) {}", which);
let pathname: u32 = varargs.get(ctx);
let pathname_addr = emscripten_memory_pointer!(ctx.memory(0), pathname) as *const i8;
let path_str = unsafe { std::ffi::CStr::from_ptr(pathname_addr).to_str().unwrap() };
let emscripten_data = get_emscripten_data(ctx);
let fd = if let Some(vfs) = &mut emscripten_data.vfs {
vfs.open_file(path_str).unwrap_or(-1)
} else {
-1
};
debug!("=> fd: {}", fd);
return fd as _;
}
/// close
pub fn ___syscall6(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
debug!("emscripten::___syscall6 (close) {}", which);
@ -307,7 +344,7 @@ pub fn ___syscall145(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> i32 {
as *mut c_void;
let iov_len = (*guest_iov_addr).iov_len as _;
// debug!("=> iov_addr: {:?}, {:?}", iov_base, iov_len);
let curr = read(fd, iov_base, iov_len);
let curr = libc::read(fd, iov_base, iov_len);
if curr < 0 {
return -1;
}

View File

@ -78,6 +78,7 @@ use libc::SO_NOSIGPIPE;
const SO_NOSIGPIPE: c_int = 0;
/// open
#[cfg(not(feature = "vfs"))]
pub fn ___syscall5(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
debug!("emscripten::___syscall5 (open) {}", which);
let pathname: u32 = varargs.get(ctx);

View File

@ -1,3 +1,4 @@
use crate::env::get_emscripten_data;
use crate::utils::copy_cstr_into_wasm;
use crate::utils::read_string_from_wasm;
use crate::varargs::VarArgs;
@ -15,6 +16,7 @@ use wasmer_runtime_core::vm::Ctx;
type pid_t = c_int;
/// open
#[cfg(not(feature = "vfs"))]
pub fn ___syscall5(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
debug!("emscripten::___syscall5 (open) {}", which);
let pathname: u32 = varargs.get(ctx);

View File

@ -176,6 +176,8 @@ mod test_unary_literal;
mod test_utf;
mod test_varargs;
mod test_varargs_multi;
#[cfg(feature = "vfs")]
mod test_vfs;
mod test_vprintf;
mod test_vsnprintf;
mod test_wprintf;

View File

@ -0,0 +1,9 @@
#[test]
fn test_vfs() {
assert_emscripten_output!(
"../../emtests/test_vfs.wasm",
"test_vfs",
vec![],
"../../emtests/test_vfs.out"
);
}