From 94674e9d80d4e8e67f5b14ffcc87b4639ffa2434 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Thu, 28 Mar 2019 12:18:05 -0700 Subject: [PATCH 1/4] Add wasi state --- lib/wasi/src/lib.rs | 29 ++++++++++++++++++++++++----- lib/wasi/src/state.rs | 5 +++++ lib/wasi/src/syscalls/mod.rs | 5 +++++ 3 files changed, 34 insertions(+), 5 deletions(-) create mode 100644 lib/wasi/src/state.rs diff --git a/lib/wasi/src/lib.rs b/lib/wasi/src/lib.rs index cade0133297..29f2f3a4ffa 100644 --- a/lib/wasi/src/lib.rs +++ b/lib/wasi/src/lib.rs @@ -1,14 +1,33 @@ +mod state; mod syscalls; -use syscalls::*; +use self::state::WasiState; +use self::syscalls::*; + +use std::ffi::c_void; use wasmer_runtime_core::{func, import::ImportObject, imports}; -pub fn generate_import_object() -> ImportObject { +pub fn generate_import_object(args: Vec, envs: Vec) -> ImportObject { + let state_gen = move || { + fn state_dtor(data: *mut c_void) { + unsafe { + drop(Box::from_raw(data as *mut WasiState)); + } + } + + let state = Box::new(WasiState { + args: &args[..], + envs: &envs[..], + }); + + ( + Box::leak(state) as *mut WasiState as *mut c_void, + state_dtor as fn(*mut c_void), + ) + }; imports! { // This generates the wasi state. - || { - // returns (pointer to state, function that can destruct the state). - }, + state_gen, "wasi_unstable" => { "__wasi_args_get" => func!(__wasi_args_get), "__wasi_args_sizes_get" => func!(__wasi_args_sizes_get), diff --git a/lib/wasi/src/state.rs b/lib/wasi/src/state.rs new file mode 100644 index 00000000000..df5a7ca1ef8 --- /dev/null +++ b/lib/wasi/src/state.rs @@ -0,0 +1,5 @@ +pub struct WasiState<'a> { + // vfs: Vfs, + pub args: &'a [u8], + pub envs: &'a [u8], +} diff --git a/lib/wasi/src/syscalls/mod.rs b/lib/wasi/src/syscalls/mod.rs index f765e9c8763..d4402e8c04f 100644 --- a/lib/wasi/src/syscalls/mod.rs +++ b/lib/wasi/src/syscalls/mod.rs @@ -1,5 +1,10 @@ +use crate::state::WasiState; use wasmer_runtime_core::vm::Ctx; +fn get_wasi_state(ctx: &mut Ctx) -> &mut WasiState { + unsafe { &mut *(ctx.data as *mut WasiState) } +} + pub fn __wasi_args_get(ctx: &mut Ctx) { unimplemented!() } From dbc4176964fb7931b7b2f3665d712058e844eef4 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Thu, 28 Mar 2019 12:56:11 -0700 Subject: [PATCH 2/4] Add env and args syscalls --- lib/wasi/src/lib.rs | 2 +- lib/wasi/src/state.rs | 4 +- lib/wasi/src/syscalls/mod.rs | 95 ++++++++++++++++++++++++++++++++---- 3 files changed, 88 insertions(+), 13 deletions(-) diff --git a/lib/wasi/src/lib.rs b/lib/wasi/src/lib.rs index 29f2f3a4ffa..edbd54aeb72 100644 --- a/lib/wasi/src/lib.rs +++ b/lib/wasi/src/lib.rs @@ -7,7 +7,7 @@ use std::ffi::c_void; use wasmer_runtime_core::{func, import::ImportObject, imports}; -pub fn generate_import_object(args: Vec, envs: Vec) -> ImportObject { +pub fn generate_import_object(args: Vec>, envs: Vec>) -> ImportObject { let state_gen = move || { fn state_dtor(data: *mut c_void) { unsafe { diff --git a/lib/wasi/src/state.rs b/lib/wasi/src/state.rs index df5a7ca1ef8..e7cafc1baf7 100644 --- a/lib/wasi/src/state.rs +++ b/lib/wasi/src/state.rs @@ -1,5 +1,5 @@ pub struct WasiState<'a> { // vfs: Vfs, - pub args: &'a [u8], - pub envs: &'a [u8], + pub args: &'a [Vec], + pub envs: &'a [Vec], } diff --git a/lib/wasi/src/syscalls/mod.rs b/lib/wasi/src/syscalls/mod.rs index d4402e8c04f..20e674b0068 100644 --- a/lib/wasi/src/syscalls/mod.rs +++ b/lib/wasi/src/syscalls/mod.rs @@ -1,28 +1,103 @@ use crate::state::WasiState; -use wasmer_runtime_core::vm::Ctx; +use wasmer_runtime_core::{memory::Memory, vm::Ctx}; -fn get_wasi_state(ctx: &mut Ctx) -> &mut WasiState { +fn get_wasi_state(ctx: &Ctx) -> &mut WasiState { unsafe { &mut *(ctx.data as *mut WasiState) } } -pub fn __wasi_args_get(ctx: &mut Ctx) { - unimplemented!() +fn write_buffer_array( + memory: &Memory, + from: &[Vec], + ptr_buffer_offset: u32, + buffer_offset: u32, +) { + let mut current_buffer_offset = buffer_offset; + for (i, sub_buffer) in from.iter().enumerate() { + memory.view::()[(ptr_buffer_offset as usize)..][i].set(current_buffer_offset); + for (cell, &byte) in memory.view()[(current_buffer_offset as usize)..] + .iter() + .zip(sub_buffer.iter()) + { + cell.set(byte); + } + current_buffer_offset += sub_buffer.len() as u32; + } } -pub fn __wasi_args_sizes_get(ctx: &mut Ctx) { - unimplemented!() + +/// ### `__wasi_args_get()` +/// Read command-line argument data. +/// The sizes of the buffers should match that returned by [`__wasi_args_sizes_get()`](#args_sizes_get). +/// Inputs: +/// - `char **argv` +/// A pointer to a buffer to write the argument pointers. +/// - `char *argv_buf` +/// A pointer to a buffer to write the argument string data. +/// +pub fn __wasi_args_get(ctx: &mut Ctx, ptr_buffer_offset: u32, buffer_offset: u32) { + let state = get_wasi_state(ctx); + let memory = ctx.memory(0); + + write_buffer_array(memory, &*state.args, ptr_buffer_offset, buffer_offset); } + +/// ### `__wasi_args_sizes_get()` +/// Return command-line argument data sizes. +/// Outputs: +/// - `size_t *argc` +/// The number of arguments. +/// - `size_t *argv_buf_size` +/// The size of the argument string data. +pub fn __wasi_args_sizes_get(ctx: &mut Ctx, argc_out: u32, argv_buf_size_out: u32) { + let state = get_wasi_state(ctx); + let memory = ctx.memory(0); + + let arg_count = state.args.len(); + let total_arg_size: usize = state.args.iter().map(|v| v.len()).sum(); + + memory.view::()[(argc_out / 4) as usize].set(arg_count as u32); + memory.view::()[(argv_buf_size_out / 4) as usize].set(total_arg_size as u32); +} + pub fn __wasi_clock_res_get(ctx: &mut Ctx) { unimplemented!() } pub fn __wasi_clock_time_get(ctx: &mut Ctx) { unimplemented!() } -pub fn __wasi_environ_get(ctx: &mut Ctx) { - unimplemented!() + +/// ### `__wasi_environ_get()` +/// Read environment variable data. +/// The sizes of the buffers should match that returned by [`__wasi_environ_sizes_get()`](#environ_sizes_get). +/// Inputs: +/// - `char **environ` +/// A pointer to a buffer to write the environment variable pointers. +/// - `char *environ_buf` +/// A pointer to a buffer to write the environment variable string data. +pub fn __wasi_environ_get(ctx: &mut Ctx, environ: u32, environ_buf: u32) { + let state = get_wasi_state(ctx); + let memory = ctx.memory(0); + + write_buffer_array(memory, &*state.args, environ, environ_buf); } -pub fn __wasi_environ_sizes_get(ctx: &mut Ctx) { - unimplemented!() + +/// ### `__wasi_environ_sizes_get()` +/// Return command-line argument data sizes. +/// Outputs: +/// - `size_t *environ_count` +/// The number of environment variables. +/// - `size_t *environ_buf_size` +/// The size of the environment variable string data. +pub fn __wasi_environ_sizes_get(ctx: &mut Ctx, environ_count_out: u32, environ_buf_size_out: u32) { + let state = get_wasi_state(ctx); + let memory = ctx.memory(0); + + let env_count = state.envs.len(); + let total_env_size: usize = state.envs.iter().map(|v| v.len()).sum(); + + memory.view::()[(environ_count_out / 4) as usize].set(env_count as u32); + memory.view::()[(environ_buf_size_out / 4) as usize].set(total_env_size as u32); } + pub fn __wasi_fd_advise(ctx: &mut Ctx) { unimplemented!() } From 256253a1d5349540670dbed4ec814e4d6692b277 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Thu, 28 Mar 2019 13:10:22 -0700 Subject: [PATCH 3/4] Fix clippy lint --- lib/wasi/src/syscalls/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/wasi/src/syscalls/mod.rs b/lib/wasi/src/syscalls/mod.rs index 20e674b0068..a05c41cea32 100644 --- a/lib/wasi/src/syscalls/mod.rs +++ b/lib/wasi/src/syscalls/mod.rs @@ -1,6 +1,7 @@ use crate::state::WasiState; use wasmer_runtime_core::{memory::Memory, vm::Ctx}; +#[allow(clippy::mut_from_ref)] fn get_wasi_state(ctx: &Ctx) -> &mut WasiState { unsafe { &mut *(ctx.data as *mut WasiState) } } From 5c12fd0b49665ed712beaf0fef1f61bf3d2b9764 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Thu, 28 Mar 2019 13:55:38 -0700 Subject: [PATCH 4/4] fix test --- lib/runtime-core/src/vm.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/runtime-core/src/vm.rs b/lib/runtime-core/src/vm.rs index 90afbc408a0..44511bb8289 100644 --- a/lib/runtime-core/src/vm.rs +++ b/lib/runtime-core/src/vm.rs @@ -481,7 +481,7 @@ mod vm_ctx_tests { str: String, } - extern "C" fn test_data_finalizer(data: *mut c_void) { + fn test_data_finalizer(data: *mut c_void) { let test_data: &mut TestData = unsafe { &mut *(data as *mut TestData) }; assert_eq!(test_data.x, 10); assert_eq!(test_data.y, true);