Skip to content

Commit

Permalink
Merge #301
Browse files Browse the repository at this point in the history
301: Add arg and env support to wasi r=lachlansneff a=lachlansneff



Co-authored-by: Lachlan Sneff <[email protected]>
  • Loading branch information
bors[bot] and lachlansneff committed Mar 28, 2019
2 parents c045da3 + 256253a commit edac9b4
Show file tree
Hide file tree
Showing 3 changed files with 119 additions and 14 deletions.
29 changes: 24 additions & 5 deletions lib/wasi/src/lib.rs
Original file line number Diff line number Diff line change
@@ -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<Vec<u8>>, envs: Vec<Vec<u8>>) -> 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),
Expand Down
5 changes: 5 additions & 0 deletions lib/wasi/src/state.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
pub struct WasiState<'a> {
// vfs: Vfs,
pub args: &'a [Vec<u8>],
pub envs: &'a [Vec<u8>],
}
99 changes: 90 additions & 9 deletions lib/wasi/src/syscalls/mod.rs
Original file line number Diff line number Diff line change
@@ -1,23 +1,104 @@
use wasmer_runtime_core::vm::Ctx;
use crate::state::WasiState;
use wasmer_runtime_core::{memory::Memory, vm::Ctx};

pub fn __wasi_args_get(ctx: &mut Ctx) {
unimplemented!()
#[allow(clippy::mut_from_ref)]
fn get_wasi_state(ctx: &Ctx) -> &mut WasiState {
unsafe { &mut *(ctx.data as *mut WasiState) }
}
pub fn __wasi_args_sizes_get(ctx: &mut Ctx) {
unimplemented!()

fn write_buffer_array(
memory: &Memory,
from: &[Vec<u8>],
ptr_buffer_offset: u32,
buffer_offset: u32,
) {
let mut current_buffer_offset = buffer_offset;
for (i, sub_buffer) in from.iter().enumerate() {
memory.view::<u32>()[(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;
}
}

/// ### `__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::<u32>()[(argc_out / 4) as usize].set(arg_count as u32);
memory.view::<u32>()[(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::<u32>()[(environ_count_out / 4) as usize].set(env_count as u32);
memory.view::<u32>()[(environ_buf_size_out / 4) as usize].set(total_env_size as u32);
}

pub fn __wasi_fd_advise(ctx: &mut Ctx) {
unimplemented!()
}
Expand Down

0 comments on commit edac9b4

Please sign in to comment.