mirror of
https://github.com/fluencelabs/wasmer
synced 2025-04-01 23:41:03 +00:00
expose vfs in emscripten and impl read
syscall, feature flag
This commit is contained in:
parent
b9c3a49f3c
commit
cc3f04efd7
@ -39,7 +39,7 @@ glob = "0.2.11"
|
|||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["fast-tests"]
|
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"]
|
debug = ["wasmer-clif-backend/debug", "wasmer-runtime-core/debug"]
|
||||||
# This feature will allow cargo test to run much faster
|
# This feature will allow cargo test to run much faster
|
||||||
fast-tests = []
|
fast-tests = []
|
||||||
|
@ -10,6 +10,8 @@ build = "build/mod.rs"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
wasmer-runtime-core = { path = "../runtime-core", version = "0.2.1" }
|
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"
|
lazy_static = "1.2.0"
|
||||||
libc = "0.2.49"
|
libc = "0.2.49"
|
||||||
byteorder = "1"
|
byteorder = "1"
|
||||||
@ -19,7 +21,6 @@ time = "0.1.41"
|
|||||||
rand = "0.6"
|
rand = "0.6"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
wasmer-clif-backend = { path = "../clif-backend", version = "0.2.0" }
|
|
||||||
wabt = "0.7.2"
|
wabt = "0.7.2"
|
||||||
|
|
||||||
[target.'cfg(not(windows))'.dev-dependencies]
|
[target.'cfg(not(windows))'.dev-dependencies]
|
||||||
@ -30,4 +31,5 @@ glob = "0.2.11"
|
|||||||
|
|
||||||
[features]
|
[features]
|
||||||
clif = []
|
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
12
lib/emscripten/emtests/test_vfs.c
vendored
Normal 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
6
lib/emscripten/emtests/test_vfs.md
vendored
Normal 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
1
lib/emscripten/emtests/test_vfs.out
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
content: wasmer is awesomer
|
BIN
lib/emscripten/emtests/test_vfs.wasm
vendored
Normal file
BIN
lib/emscripten/emtests/test_vfs.wasm
vendored
Normal file
Binary file not shown.
@ -54,6 +54,11 @@ pub use self::utils::{
|
|||||||
get_emscripten_table_size, is_emscripten_module,
|
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?
|
// TODO: Magic number - how is this calculated?
|
||||||
const TOTAL_STACK: u32 = 5_242_880;
|
const TOTAL_STACK: u32 = 5_242_880;
|
||||||
// TODO: Magic number - how is this calculated?
|
// 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_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_vijiii: Option<Func<'a, (i32, i32, i32, i32, i32, i32, i32)>>,
|
||||||
pub dyn_call_vijj: Option<Func<'a, (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> {
|
impl<'a> EmscriptenData<'a> {
|
||||||
@ -231,17 +239,33 @@ impl<'a> EmscriptenData<'a> {
|
|||||||
dyn_call_viji,
|
dyn_call_viji,
|
||||||
dyn_call_vijiii,
|
dyn_call_vijiii,
|
||||||
dyn_call_vijj,
|
dyn_call_vijj,
|
||||||
|
#[cfg(feature = "vfs")]
|
||||||
|
vfs: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run_emscripten_instance(
|
pub fn run_emscripten_instance(
|
||||||
_module: &Module,
|
module: &Module,
|
||||||
instance: &mut Instance,
|
instance: &mut Instance,
|
||||||
path: &str,
|
path: &str,
|
||||||
args: Vec<&str>,
|
args: Vec<&str>,
|
||||||
) -> CallResult<()> {
|
) -> CallResult<()> {
|
||||||
let mut data = EmscriptenData::new(instance);
|
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;
|
let data_ptr = &mut data as *mut _ as *mut c_void;
|
||||||
instance.context_mut().data = data_ptr;
|
instance.context_mut().data = data_ptr;
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ use libc::{
|
|||||||
// iovec,
|
// iovec,
|
||||||
lseek,
|
lseek,
|
||||||
// open,
|
// open,
|
||||||
read,
|
// read,
|
||||||
// readv,
|
// readv,
|
||||||
rmdir,
|
rmdir,
|
||||||
// writev,
|
// writev,
|
||||||
@ -40,7 +40,6 @@ use libc::{
|
|||||||
use wasmer_runtime_core::vm::Ctx;
|
use wasmer_runtime_core::vm::Ctx;
|
||||||
|
|
||||||
use super::env;
|
use super::env;
|
||||||
use std::cell::Cell;
|
|
||||||
use std::slice;
|
use std::slice;
|
||||||
// use std::sys::fd::FileDesc;
|
// use std::sys::fd::FileDesc;
|
||||||
|
|
||||||
@ -67,6 +66,7 @@ pub fn ___syscall1(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// read
|
/// read
|
||||||
|
#[cfg(not(feature = "vfs"))]
|
||||||
pub fn ___syscall3(ctx: &mut Ctx, which: i32, mut varargs: VarArgs) -> i32 {
|
pub fn ___syscall3(ctx: &mut Ctx, which: i32, mut varargs: VarArgs) -> i32 {
|
||||||
// -> ssize_t
|
// -> ssize_t
|
||||||
debug!("emscripten::___syscall3 (read) {}", which);
|
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);
|
let count: i32 = varargs.get(ctx);
|
||||||
debug!("=> fd: {}, buf_offset: {}, count: {}", fd, buf, count);
|
debug!("=> fd: {}, buf_offset: {}, count: {}", fd, buf, count);
|
||||||
let buf_addr = emscripten_memory_pointer!(ctx.memory(0), buf) as *mut c_void;
|
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);
|
debug!("=> ret: {}", ret);
|
||||||
ret as _
|
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 }
|
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
|
/// close
|
||||||
pub fn ___syscall6(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
pub fn ___syscall6(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
||||||
debug!("emscripten::___syscall6 (close) {}", which);
|
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;
|
as *mut c_void;
|
||||||
let iov_len = (*guest_iov_addr).iov_len as _;
|
let iov_len = (*guest_iov_addr).iov_len as _;
|
||||||
// debug!("=> iov_addr: {:?}, {:?}", iov_base, iov_len);
|
// 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 {
|
if curr < 0 {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -78,6 +78,7 @@ use libc::SO_NOSIGPIPE;
|
|||||||
const SO_NOSIGPIPE: c_int = 0;
|
const SO_NOSIGPIPE: c_int = 0;
|
||||||
|
|
||||||
/// open
|
/// open
|
||||||
|
#[cfg(not(feature = "vfs"))]
|
||||||
pub fn ___syscall5(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
pub fn ___syscall5(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
||||||
debug!("emscripten::___syscall5 (open) {}", which);
|
debug!("emscripten::___syscall5 (open) {}", which);
|
||||||
let pathname: u32 = varargs.get(ctx);
|
let pathname: u32 = varargs.get(ctx);
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
use crate::env::get_emscripten_data;
|
||||||
use crate::utils::copy_cstr_into_wasm;
|
use crate::utils::copy_cstr_into_wasm;
|
||||||
use crate::utils::read_string_from_wasm;
|
use crate::utils::read_string_from_wasm;
|
||||||
use crate::varargs::VarArgs;
|
use crate::varargs::VarArgs;
|
||||||
@ -15,6 +16,7 @@ use wasmer_runtime_core::vm::Ctx;
|
|||||||
type pid_t = c_int;
|
type pid_t = c_int;
|
||||||
|
|
||||||
/// open
|
/// open
|
||||||
|
#[cfg(not(feature = "vfs"))]
|
||||||
pub fn ___syscall5(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
pub fn ___syscall5(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
||||||
debug!("emscripten::___syscall5 (open) {}", which);
|
debug!("emscripten::___syscall5 (open) {}", which);
|
||||||
let pathname: u32 = varargs.get(ctx);
|
let pathname: u32 = varargs.get(ctx);
|
||||||
|
@ -176,6 +176,8 @@ mod test_unary_literal;
|
|||||||
mod test_utf;
|
mod test_utf;
|
||||||
mod test_varargs;
|
mod test_varargs;
|
||||||
mod test_varargs_multi;
|
mod test_varargs_multi;
|
||||||
|
#[cfg(feature = "vfs")]
|
||||||
|
mod test_vfs;
|
||||||
mod test_vprintf;
|
mod test_vprintf;
|
||||||
mod test_vsnprintf;
|
mod test_vsnprintf;
|
||||||
mod test_wprintf;
|
mod test_wprintf;
|
||||||
|
9
lib/emscripten/tests/emtests/test_vfs.rs
Normal file
9
lib/emscripten/tests/emtests/test_vfs.rs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#[test]
|
||||||
|
fn test_vfs() {
|
||||||
|
assert_emscripten_output!(
|
||||||
|
"../../emtests/test_vfs.wasm",
|
||||||
|
"test_vfs",
|
||||||
|
vec![],
|
||||||
|
"../../emtests/test_vfs.out"
|
||||||
|
);
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user