From 8f345dc2843758c430fcbb976f793aeb23a73c2f Mon Sep 17 00:00:00 2001 From: Syrus Date: Sat, 18 May 2019 12:38:22 -0700 Subject: [PATCH 01/22] Updated imports required for jq. Added get_str method in VarArgs --- lib/emscripten/src/env/mod.rs | 17 +++++++++ lib/emscripten/src/lib.rs | 4 +++ lib/emscripten/src/math.rs | 5 +++ lib/emscripten/src/syscalls/mod.rs | 49 +++++++++++++++++--------- lib/emscripten/src/syscalls/unix.rs | 36 +++++++------------ lib/emscripten/src/syscalls/windows.rs | 10 +++--- lib/emscripten/src/time.rs | 14 +++++++- lib/emscripten/src/varargs.rs | 10 ++++++ 8 files changed, 97 insertions(+), 48 deletions(-) diff --git a/lib/emscripten/src/env/mod.rs b/lib/emscripten/src/env/mod.rs index 897fb38f0..74f6caddc 100644 --- a/lib/emscripten/src/env/mod.rs +++ b/lib/emscripten/src/env/mod.rs @@ -112,3 +112,20 @@ pub fn ___assert_fail(_ctx: &mut Ctx, _a: c_int, _b: c_int, _c: c_int, _d: c_int // TODO: Implement like emscripten expects regarding memory/page size // TODO raise an error } + +pub fn _fpathconf(_ctx: &mut Ctx, _fildes: c_int, name: c_int) -> c_int { + debug!("emscripten::_fpathconf {} {}", _fildes, name); + match name { + 0 => 32000, + 1 | 2 | 3 => 255, + 4 | 5 | 16 | 17 | 18 => 4096, + 6 | 7 | 20 => 1, + 8 => 0, + 9 | 10 | 11 | 12 | 14 | 15 | 19 => -1, + 13 => 64, + _ => { + // ___setErrNo(22); + -1 + } + } +} diff --git a/lib/emscripten/src/lib.rs b/lib/emscripten/src/lib.rs index 6b0340513..3970611be 100644 --- a/lib/emscripten/src/lib.rs +++ b/lib/emscripten/src/lib.rs @@ -547,6 +547,8 @@ pub fn generate_emscripten_env(globals: &mut EmscriptenGlobals) -> ImportObject "_sysconf" => func!(crate::env::_sysconf), "_getaddrinfo" => func!(crate::env::_getaddrinfo), "_times" => func!(crate::env::_times), + "_pathconf" => func!(crate::env::_fpathconf), + "_fpathconf" => func!(crate::env::_fpathconf), // Syscalls "___syscall1" => func!(crate::syscalls::___syscall1), @@ -689,6 +691,7 @@ pub fn generate_emscripten_env(globals: &mut EmscriptenGlobals) -> ImportObject "_asctime_r" => func!(crate::time::_asctime_r), "_localtime" => func!(crate::time::_localtime), "_time" => func!(crate::time::_time), + "_timegm" => func!(crate::time::_timegm), "_strftime" => func!(crate::time::_strftime), "_strftime_l" => func!(crate::time::_strftime_l), "_localtime_r" => func!(crate::time::_localtime_r), @@ -707,6 +710,7 @@ pub fn generate_emscripten_env(globals: &mut EmscriptenGlobals) -> ImportObject "_llvm_exp2_f32" => func!(crate::math::_llvm_exp2_f32), "_llvm_exp2_f64" => func!(crate::math::_llvm_exp2_f64), "_llvm_trunc_f64" => func!(crate::math::_llvm_trunc_f64), + "_llvm_fma_f64" => func!(crate::math::_llvm_fma_f64), "_emscripten_random" => func!(crate::math::_emscripten_random), // Jump diff --git a/lib/emscripten/src/math.rs b/lib/emscripten/src/math.rs index 3256b49c5..d266afe70 100644 --- a/lib/emscripten/src/math.rs +++ b/lib/emscripten/src/math.rs @@ -49,6 +49,11 @@ pub fn _llvm_trunc_f64(_ctx: &mut Ctx, value: f64) -> f64 { value.trunc() } +pub fn _llvm_fma_f64(_ctx: &mut Ctx, value: f64, a: f64, b: f64) -> f64 { + debug!("emscripten::_llvm_fma_f64"); + value.mul_add(a, b) +} + pub fn _emscripten_random(_ctx: &mut Ctx) -> f64 { debug!("emscripten::_emscripten_random"); -1.0 diff --git a/lib/emscripten/src/syscalls/mod.rs b/lib/emscripten/src/syscalls/mod.rs index 5654a1299..afffa2e4a 100644 --- a/lib/emscripten/src/syscalls/mod.rs +++ b/lib/emscripten/src/syscalls/mod.rs @@ -38,6 +38,7 @@ use libc::{ // writev, stat, write, + // readlink, }; use wasmer_runtime_core::vm::Ctx; @@ -93,9 +94,8 @@ pub fn ___syscall6(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int // chdir pub fn ___syscall12(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall12 (chdir) {}", _which); - let path_addr: i32 = varargs.get(ctx); + let path_ptr = varargs.get_str(ctx); unsafe { - let path_ptr = emscripten_memory_pointer!(ctx.memory(0), path_addr) as *const i8; let _path = std::ffi::CStr::from_ptr(path_ptr); let ret = chdir(path_ptr); debug!("=> path: {:?}, ret: {}", _path, ret); @@ -122,10 +122,8 @@ pub fn ___syscall20(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 { // rename pub fn ___syscall38(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> i32 { debug!("emscripten::___syscall38 (rename)"); - let old_path_addr: u32 = varargs.get(ctx); - let new_path_addr: u32 = varargs.get(ctx); - let old_path = emscripten_memory_pointer!(ctx.memory(0), old_path_addr) as *const i8; - let new_path = emscripten_memory_pointer!(ctx.memory(0), new_path_addr) as *const i8; + let old_path = varargs.get_str(ctx); + let new_path = varargs.get_str(ctx); let result = unsafe { rename(old_path, new_path) }; debug!( "=> old_path: {}, new_path: {}, result: {}", @@ -139,8 +137,7 @@ pub fn ___syscall38(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> i32 { // rmdir pub fn ___syscall40(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall40 (rmdir)"); - let pathname: u32 = varargs.get(ctx); - let pathname_addr = emscripten_memory_pointer!(ctx.memory(0), pathname) as *const i8; + let pathname_addr = varargs.get_str(ctx); unsafe { rmdir(pathname_addr) } } @@ -201,9 +198,30 @@ pub fn ___syscall75(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 { -1 } -pub fn ___syscall85(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 { - debug!("emscripten::___syscall85"); - -1 +// readlink +pub fn ___syscall85(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> i32 { + debug!("emscripten::___syscall85 (readlink)"); + let _path = varargs.get_str(ctx); + let buf = varargs.get_str(ctx); + // let buf_addr: i32 = varargs.get(ctx); + let buf_size: i32 = varargs.get(ctx); + + let fd = 3; + let ret = unsafe { read(fd, buf as _, buf_size as _) as i32 }; + debug!("=> buf: {}, buf_size: {}, return: {} ", unsafe { std::ffi::CStr::from_ptr(buf as _).to_str().unwrap() }, buf_size, ret); + + // let ret = unsafe { + // readlink(path, buf as _, buf_size as _) as i32 + // }; + // debug!("=> path: {}, buf: {}, buf_size: {}, return: {} ", + // unsafe { std::ffi::CStr::from_ptr(path).to_str().unwrap() }, + // unsafe { std::ffi::CStr::from_ptr(buf as _).to_str().unwrap() }, + // // std::ffi::CStr::from_ptr(buf).to_str().unwrap(), + // // buf, + // buf_size, + // ret); + + ret } pub fn ___syscall91(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 { @@ -397,19 +415,16 @@ pub fn ___syscall199(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 { // stat64 pub fn ___syscall195(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall195 (stat64) {}", _which); - let pathname: u32 = varargs.get(ctx); + let pathname_addr = varargs.get_str(ctx); let buf: u32 = varargs.get(ctx); - let pathname_addr = emscripten_memory_pointer!(ctx.memory(0), pathname) as *const i8; - unsafe { let mut _stat: stat = std::mem::zeroed(); let ret = stat(pathname_addr, &mut _stat); debug!( - "=> pathname: {}, buf: {}, path: {} = {}\nlast os error: {}", - pathname, - buf, + "=> pathname: {}, buf: {} = {}, last os error: {}", std::ffi::CStr::from_ptr(pathname_addr).to_str().unwrap(), + buf, ret, Error::last_os_error() ); diff --git a/lib/emscripten/src/syscalls/unix.rs b/lib/emscripten/src/syscalls/unix.rs index ec8b98f3f..83a972dfa 100644 --- a/lib/emscripten/src/syscalls/unix.rs +++ b/lib/emscripten/src/syscalls/unix.rs @@ -104,19 +104,17 @@ const SO_NOSIGPIPE: c_int = 0; /// open 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); + let pathname_addr = varargs.get_str(ctx); let flags: i32 = varargs.get(ctx); let mode: 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 fd = unsafe { open(pathname_addr, flags, mode) }; debug!( - "=> pathname: {}, flags: {}, mode: {} = fd: {}\npath: {}\nlast os error: {}", - pathname, + "=> path: {}, flags: {}, mode: {} = fd: {}, last os error: {}", + _path_str, flags, mode, fd, - _path_str, Error::last_os_error(), ); fd @@ -126,10 +124,8 @@ pub fn ___syscall5(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int pub fn ___syscall9(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall9 (link) {}", _which); - let oldname: c_int = varargs.get(ctx); - let newname: c_int = varargs.get(ctx); - let oldname_ptr = emscripten_memory_pointer!(ctx.memory(0), oldname) as *const i8; - let newname_ptr = emscripten_memory_pointer!(ctx.memory(0), newname) as *const i8; + let oldname_ptr = varargs.get_str(ctx); + let newname_ptr = varargs.get_str(ctx); let result = unsafe { link(oldname_ptr, newname_ptr) }; debug!( "=> oldname: {}, newname: {}, result: {}", @@ -156,10 +152,8 @@ pub fn ___syscall77(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int pub fn ___syscall83(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall83 (symlink) {}", _which); - let path1_ptr: c_int = varargs.get(ctx); - let path2_ptr: c_int = varargs.get(ctx); - let path1 = emscripten_memory_pointer!(ctx.memory(0), path1_ptr) as *mut i8; - let path2 = emscripten_memory_pointer!(ctx.memory(0), path2_ptr) as *mut i8; + let path1 = varargs.get_str(ctx); + let path2 = varargs.get_str(ctx); let result = unsafe { symlink(path1, path2) }; debug!( "=> path1: {}, path2: {}, result: {}", @@ -186,10 +180,9 @@ pub fn ___syscall194(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in /// lchown pub fn ___syscall198(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall198 (lchown) {}", _which); - let path: c_int = varargs.get(ctx); + let path_ptr = varargs.get_str(ctx); let uid: uid_t = varargs.get(ctx); let gid: gid_t = varargs.get(ctx); - let path_ptr = emscripten_memory_pointer!(ctx.memory(0), path) as *const i8; let result = unsafe { lchown(path_ptr, uid, gid) }; debug!( "=> path: {}, uid: {}, gid: {}, result: {}", @@ -222,12 +215,10 @@ pub fn ___syscall205(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in pub fn ___syscall212(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall212 (chown) {}", _which); - let pathname: u32 = varargs.get(ctx); + let pathname_addr = varargs.get_str(ctx); let owner: u32 = varargs.get(ctx); let group: u32 = varargs.get(ctx); - let pathname_addr = emscripten_memory_pointer!(ctx.memory(0), pathname) as *const i8; - unsafe { chown(pathname_addr, owner, group) } } @@ -247,9 +238,8 @@ pub fn ___syscall219(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in /// access pub fn ___syscall33(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall33 (access) {}", _which); - let path_ptr: c_int = varargs.get(ctx); + let path = varargs.get_str(ctx); let amode: c_int = varargs.get(ctx); - let path = emscripten_memory_pointer!(ctx.memory(0), path_ptr) as *const i8; let result = unsafe { access(path, amode) }; debug!( "=> path: {}, amode: {}, result: {}", @@ -270,9 +260,8 @@ pub fn ___syscall34(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int // mkdir pub fn ___syscall39(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall39 (mkdir) {}", _which); - let pathname: u32 = varargs.get(ctx); + let pathname_addr = varargs.get_str(ctx); let mode: u32 = varargs.get(ctx); - let pathname_addr = emscripten_memory_pointer!(ctx.memory(0), pathname) as *const i8; unsafe { mkdir(pathname_addr, mode as _) } } @@ -771,9 +760,8 @@ pub fn ___syscall122(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in /// lstat64 pub fn ___syscall196(ctx: &mut Ctx, _which: i32, mut varargs: VarArgs) -> i32 { debug!("emscripten::___syscall196 (lstat64) {}", _which); - let path_ptr: c_int = varargs.get(ctx); + let path = varargs.get_str(ctx); let buf_ptr: u32 = varargs.get(ctx); - let path = emscripten_memory_pointer!(ctx.memory(0), path_ptr) as *const i8; unsafe { let mut stat: stat = std::mem::zeroed(); diff --git a/lib/emscripten/src/syscalls/windows.rs b/lib/emscripten/src/syscalls/windows.rs index a7ac8c11c..d74f3c55b 100644 --- a/lib/emscripten/src/syscalls/windows.rs +++ b/lib/emscripten/src/syscalls/windows.rs @@ -18,10 +18,9 @@ pub fn ___syscall5(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall5 (open) {}", which); #[cfg(not(feature = "debug"))] let _ = which; - let pathname: u32 = varargs.get(ctx); + let pathname_addr = varargs.get_str(ctx); let flags: i32 = varargs.get(ctx); let mode: 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() }; match path_str { "/dev/urandom" => { @@ -43,7 +42,7 @@ pub fn ___syscall5(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int { let fd = unsafe { open(raw_pointer_to_urandom_file, flags, mode) }; debug!( "=> pathname: {}, flags: {}, mode: {} = fd: {}", - pathname, flags, mode, fd + path_str, flags, mode, fd ); fd } @@ -51,7 +50,7 @@ pub fn ___syscall5(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int { let fd = unsafe { open(pathname_addr, flags, mode) }; debug!( "=> pathname: {}, flags: {}, mode: {} = fd: {}\npath: {}", - pathname, flags, mode, fd, path_str + path_str, flags, mode, fd, path_str ); fd } @@ -95,8 +94,7 @@ pub fn ___syscall39(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int debug!("emscripten::___syscall39 (mkdir) {}", which); #[cfg(not(feature = "debug"))] let _ = which; - let pathname: u32 = varargs.get(ctx); - let pathname_addr = emscripten_memory_pointer!(ctx.memory(0), pathname) as *const i8; + let pathname_addr = varargs.get_str(ctx); unsafe { mkdir(pathname_addr) } } diff --git a/lib/emscripten/src/time.rs b/lib/emscripten/src/time.rs index 32e7a61c6..eef9046f2 100644 --- a/lib/emscripten/src/time.rs +++ b/lib/emscripten/src/time.rs @@ -4,7 +4,7 @@ use std::mem; use std::time::SystemTime; #[cfg(not(target_os = "windows"))] -use libc::{clockid_t, time as libc_time}; +use libc::{clockid_t, time as libc_time, timegm as libc_timegm}; #[cfg(target_os = "windows")] use libc::time_t; @@ -17,6 +17,8 @@ type clockid_t = c_int; extern "C" { #[link_name = "time"] pub fn libc_time(s: *const time_t) -> time_t; + #[link_name = "timegm"] + pub fn libc_timegm(s: *const time_t) -> time_t; } use time; @@ -298,6 +300,16 @@ pub fn _time(ctx: &mut Ctx, time_p: u32) -> i32 { } } +/// emscripten: _timegm +pub fn _timegm(ctx: &mut Ctx, time_ptr: u32) -> i32 { + debug!("emscripten::_timegm {}", time_ptr); + + unsafe { + let time_p_addr = emscripten_memory_pointer!(ctx.memory(0), time_ptr) as *mut guest_tm; + libc_timegm(time_p_addr as _) as i32 // TODO review i64 + } +} + /// emscripten: _strftime pub fn _strftime( ctx: &mut Ctx, diff --git a/lib/emscripten/src/varargs.rs b/lib/emscripten/src/varargs.rs index a6a1fe46b..8daf78dc8 100644 --- a/lib/emscripten/src/varargs.rs +++ b/lib/emscripten/src/varargs.rs @@ -1,5 +1,7 @@ use std::mem; use wasmer_runtime_core::{types::WasmExternType, vm::Ctx}; +// use std::ffi::CStr; +use std::os::raw::c_char; #[repr(transparent)] #[derive(Copy, Clone)] @@ -13,6 +15,14 @@ impl VarArgs { self.pointer += mem::size_of::() as u32; unsafe { (ptr as *const T).read() } } + + // pub fn getStr<'a>(&mut self, ctx: &mut Ctx) -> &'a CStr { + pub fn get_str(&mut self, ctx: &mut Ctx) -> *const c_char { + let ptr_addr: u32 = self.get(ctx); + let ptr = emscripten_memory_pointer!(ctx.memory(0), ptr_addr) as *const c_char; + ptr + // unsafe { CStr::from_ptr(ptr) } + } } unsafe impl WasmExternType for VarArgs { From c7dceba0d8ce54fabc7496ed3c06509f781b6910 Mon Sep 17 00:00:00 2001 From: Syrus Date: Fri, 24 May 2019 12:09:00 -0700 Subject: [PATCH 02/22] Improved formatting --- lib/emscripten/src/syscalls/mod.rs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/lib/emscripten/src/syscalls/mod.rs b/lib/emscripten/src/syscalls/mod.rs index afffa2e4a..cd7ddd10a 100644 --- a/lib/emscripten/src/syscalls/mod.rs +++ b/lib/emscripten/src/syscalls/mod.rs @@ -205,22 +205,27 @@ pub fn ___syscall85(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> i32 { let buf = varargs.get_str(ctx); // let buf_addr: i32 = varargs.get(ctx); let buf_size: i32 = varargs.get(ctx); - + let fd = 3; let ret = unsafe { read(fd, buf as _, buf_size as _) as i32 }; - debug!("=> buf: {}, buf_size: {}, return: {} ", unsafe { std::ffi::CStr::from_ptr(buf as _).to_str().unwrap() }, buf_size, ret); + debug!( + "=> buf: {}, buf_size: {}, return: {} ", + unsafe { std::ffi::CStr::from_ptr(buf as _).to_str().unwrap() }, + buf_size, + ret + ); // let ret = unsafe { // readlink(path, buf as _, buf_size as _) as i32 // }; - // debug!("=> path: {}, buf: {}, buf_size: {}, return: {} ", + // debug!("=> path: {}, buf: {}, buf_size: {}, return: {} ", // unsafe { std::ffi::CStr::from_ptr(path).to_str().unwrap() }, // unsafe { std::ffi::CStr::from_ptr(buf as _).to_str().unwrap() }, // // std::ffi::CStr::from_ptr(buf).to_str().unwrap(), // // buf, // buf_size, // ret); - + ret } From dd9c5774f3c0999a12a67a62d87e8a5d4cb8ec1d Mon Sep 17 00:00:00 2001 From: Syrus Date: Fri, 24 May 2019 12:15:52 -0700 Subject: [PATCH 03/22] Separate fpathconf from pathconf --- lib/emscripten/src/env/mod.rs | 23 +++++++++++++++++++++++ lib/emscripten/src/lib.rs | 2 +- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/lib/emscripten/src/env/mod.rs b/lib/emscripten/src/env/mod.rs index 74f6caddc..98bc39dc8 100644 --- a/lib/emscripten/src/env/mod.rs +++ b/lib/emscripten/src/env/mod.rs @@ -10,6 +10,8 @@ pub use self::unix::*; #[cfg(windows)] pub use self::windows::*; +use libc::c_char; + use crate::{allocate_on_stack, EmscriptenData}; use std::os::raw::c_int; use wasmer_runtime_core::vm::Ctx; @@ -113,6 +115,27 @@ pub fn ___assert_fail(_ctx: &mut Ctx, _a: c_int, _b: c_int, _c: c_int, _d: c_int // TODO raise an error } +pub fn _pathconf(ctx: &mut Ctx, path_addr: c_int, name: c_int) -> c_int { + debug!( + "emscripten::_pathconf {} {} - UNIMPLEMENTED", + path_addr, name + ); + let _path = emscripten_memory_pointer!(ctx.memory(0), path_addr) as *const c_char; + match name { + 0 => 32000, + 1 | 2 | 3 => 255, + 4 | 5 | 16 | 17 | 18 => 4096, + 6 | 7 | 20 => 1, + 8 => 0, + 9 | 10 | 11 | 12 | 14 | 15 | 19 => -1, + 13 => 64, + _ => { + // ___setErrNo(22); + -1 + } + } +} + pub fn _fpathconf(_ctx: &mut Ctx, _fildes: c_int, name: c_int) -> c_int { debug!("emscripten::_fpathconf {} {}", _fildes, name); match name { diff --git a/lib/emscripten/src/lib.rs b/lib/emscripten/src/lib.rs index cbc881019..400bcd94f 100644 --- a/lib/emscripten/src/lib.rs +++ b/lib/emscripten/src/lib.rs @@ -545,7 +545,7 @@ pub fn generate_emscripten_env(globals: &mut EmscriptenGlobals) -> ImportObject "_sysconf" => func!(crate::env::_sysconf), "_getaddrinfo" => func!(crate::env::_getaddrinfo), "_times" => func!(crate::env::_times), - "_pathconf" => func!(crate::env::_fpathconf), + "_pathconf" => func!(crate::env::_pathconf), "_fpathconf" => func!(crate::env::_fpathconf), // Syscalls From dd3059535805f6dc3179bd35523b05fde3bede2e Mon Sep 17 00:00:00 2001 From: Syrus Date: Fri, 24 May 2019 13:30:41 -0700 Subject: [PATCH 04/22] Trying to fix issues --- lib/emscripten/src/syscalls/mod.rs | 3 --- lib/emscripten/src/time.rs | 14 +++++++++++--- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/lib/emscripten/src/syscalls/mod.rs b/lib/emscripten/src/syscalls/mod.rs index cd7ddd10a..057a8ac19 100644 --- a/lib/emscripten/src/syscalls/mod.rs +++ b/lib/emscripten/src/syscalls/mod.rs @@ -205,7 +205,6 @@ pub fn ___syscall85(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> i32 { let buf = varargs.get_str(ctx); // let buf_addr: i32 = varargs.get(ctx); let buf_size: i32 = varargs.get(ctx); - let fd = 3; let ret = unsafe { read(fd, buf as _, buf_size as _) as i32 }; debug!( @@ -214,7 +213,6 @@ pub fn ___syscall85(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> i32 { buf_size, ret ); - // let ret = unsafe { // readlink(path, buf as _, buf_size as _) as i32 // }; @@ -225,7 +223,6 @@ pub fn ___syscall85(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> i32 { // // buf, // buf_size, // ret); - ret } diff --git a/lib/emscripten/src/time.rs b/lib/emscripten/src/time.rs index eef9046f2..d2bce3376 100644 --- a/lib/emscripten/src/time.rs +++ b/lib/emscripten/src/time.rs @@ -17,8 +17,6 @@ type clockid_t = c_int; extern "C" { #[link_name = "time"] pub fn libc_time(s: *const time_t) -> time_t; - #[link_name = "timegm"] - pub fn libc_timegm(s: *const time_t) -> time_t; } use time; @@ -301,7 +299,8 @@ pub fn _time(ctx: &mut Ctx, time_p: u32) -> i32 { } /// emscripten: _timegm -pub fn _timegm(ctx: &mut Ctx, time_ptr: u32) -> i32 { +#[cfg(not(target_os = "windows"))] +pub fn _timegm(ctx: &mut Ctx, time_ptr: c_int) -> i32 { debug!("emscripten::_timegm {}", time_ptr); unsafe { @@ -310,6 +309,15 @@ pub fn _timegm(ctx: &mut Ctx, time_ptr: u32) -> i32 { } } +#[cfg(target_os = "windows")] +pub fn _timegm(ctx: &mut Ctx, time_ptr: c_int) -> i32 { + debug!( + "emscripten::_timegm - UNIMPLEMENTED IN WINDOWS {}", + time_ptr + ); + -1 +} + /// emscripten: _strftime pub fn _strftime( ctx: &mut Ctx, From fc15bc58f62148d9cf0af586da7dce11f5372845 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Fri, 24 May 2019 18:00:07 -0700 Subject: [PATCH 05/22] add mapdir for emscripten; implement getdents, etc. --- Cargo.lock | 1 + lib/emscripten/Cargo.toml | 7 +- lib/emscripten/src/lib.rs | 12 +++- lib/emscripten/src/syscalls/mod.rs | 53 ++++++++------ lib/emscripten/src/syscalls/unix.rs | 95 ++++++++++++++++++++++++-- lib/emscripten/src/syscalls/windows.rs | 6 ++ lib/emscripten/src/utils.rs | 32 +++++++++ src/bin/wasmer.rs | 1 + 8 files changed, 176 insertions(+), 31 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f5504e8c1..72fda4277 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2336,6 +2336,7 @@ version = "0.4.2" dependencies = [ "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/lib/emscripten/Cargo.toml b/lib/emscripten/Cargo.toml index c9209eb8f..3d9e5df71 100644 --- a/lib/emscripten/Cargo.toml +++ b/lib/emscripten/Cargo.toml @@ -9,14 +9,15 @@ edition = "2018" build = "build/mod.rs" [dependencies] -wasmer-runtime-core = { path = "../runtime-core", version = "0.4.2" } +byteorder = "1" +hashbrown = "0.1" lazy_static = "1.2.0" libc = "0.2.49" -byteorder = "1" time = "0.1.41" wasmer-clif-backend = { path = "../clif-backend", version = "0.4.2" } -wasmer-singlepass-backend = { path = "../singlepass-backend", version = "0.4.2", optional = true } wasmer-llvm-backend = { path = "../llvm-backend", version = "0.4.2", optional = true } +wasmer-runtime-core = { path = "../runtime-core", version = "0.4.2" } +wasmer-singlepass-backend = { path = "../singlepass-backend", version = "0.4.2", optional = true } [target.'cfg(windows)'.dependencies] rand = "0.6" diff --git a/lib/emscripten/src/lib.rs b/lib/emscripten/src/lib.rs index f60156bab..0e6005755 100644 --- a/lib/emscripten/src/lib.rs +++ b/lib/emscripten/src/lib.rs @@ -3,8 +3,10 @@ #[macro_use] extern crate wasmer_runtime_core; +use hashbrown::HashMap; use lazy_static::lazy_static; use std::cell::UnsafeCell; +use std::path::PathBuf; use std::{f64, ffi::c_void}; use wasmer_runtime_core::{ error::CallResult, @@ -141,10 +143,14 @@ pub struct EmscriptenData<'a> { pub stack_save: Option>, pub stack_restore: Option>, pub set_threw: Option>, + pub mapped_dirs: HashMap, } impl<'a> EmscriptenData<'a> { - pub fn new(instance: &'a mut Instance) -> EmscriptenData<'a> { + pub fn new( + instance: &'a mut Instance, + mapped_dirs: HashMap, + ) -> EmscriptenData<'a> { let malloc = instance.func("_malloc").unwrap(); let free = instance.func("_free").unwrap(); let memalign = instance.func("_memalign").ok(); @@ -272,6 +278,7 @@ impl<'a> EmscriptenData<'a> { stack_save, stack_restore, set_threw, + mapped_dirs, } } } @@ -282,8 +289,9 @@ pub fn run_emscripten_instance( path: &str, args: Vec<&str>, entrypoint: Option, + mapped_dirs: Vec<(String, PathBuf)>, ) -> CallResult<()> { - let mut data = EmscriptenData::new(instance); + let mut data = EmscriptenData::new(instance, mapped_dirs.into_iter().collect()); let data_ptr = &mut data as *mut _ as *mut c_void; instance.context_mut().data = data_ptr; diff --git a/lib/emscripten/src/syscalls/mod.rs b/lib/emscripten/src/syscalls/mod.rs index 5654a1299..18808f0ad 100644 --- a/lib/emscripten/src/syscalls/mod.rs +++ b/lib/emscripten/src/syscalls/mod.rs @@ -10,7 +10,8 @@ pub use self::unix::*; #[cfg(windows)] pub use self::windows::*; -use super::utils::copy_stat_into_wasm; +use crate::utils::{copy_stat_into_wasm, get_cstr_path, get_current_directory}; + use super::varargs::VarArgs; use byteorder::{ByteOrder, LittleEndian}; /// NOTE: TODO: These syscalls only support wasm_32 for now because they assume offsets are u32 @@ -94,13 +95,17 @@ pub fn ___syscall6(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int pub fn ___syscall12(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall12 (chdir) {}", _which); let path_addr: i32 = varargs.get(ctx); - unsafe { - let path_ptr = emscripten_memory_pointer!(ctx.memory(0), path_addr) as *const i8; - let _path = std::ffi::CStr::from_ptr(path_ptr); - let ret = chdir(path_ptr); - debug!("=> path: {:?}, ret: {}", _path, ret); + let path_ptr = emscripten_memory_pointer!(ctx.memory(0), path_addr) as *const i8; + let real_path = get_cstr_path(ctx, path_ptr) + .map(|cstr| cstr.as_c_str() as *const _ as *const i8) + .unwrap_or(path_ptr); + let ret = unsafe { chdir(real_path) }; + debug!( + "=> path: {:?}, ret: {}", + unsafe { std::ffi::CStr::from_ptr(real_path) }, ret - } + ); + ret } pub fn ___syscall10(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 { @@ -126,11 +131,17 @@ pub fn ___syscall38(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> i32 { let new_path_addr: u32 = varargs.get(ctx); let old_path = emscripten_memory_pointer!(ctx.memory(0), old_path_addr) as *const i8; let new_path = emscripten_memory_pointer!(ctx.memory(0), new_path_addr) as *const i8; - let result = unsafe { rename(old_path, new_path) }; + let real_old_path = get_cstr_path(ctx, old_path) + .map(|cstr| cstr.as_c_str() as *const _ as *const i8) + .unwrap_or(old_path); + let real_new_path = get_cstr_path(ctx, new_path) + .map(|cstr| cstr.as_c_str() as *const _ as *const i8) + .unwrap_or(new_path); + let result = unsafe { rename(real_old_path, real_new_path) }; debug!( "=> old_path: {}, new_path: {}, result: {}", - unsafe { std::ffi::CStr::from_ptr(old_path).to_str().unwrap() }, - unsafe { std::ffi::CStr::from_ptr(new_path).to_str().unwrap() }, + unsafe { std::ffi::CStr::from_ptr(real_old_path).to_str().unwrap() }, + unsafe { std::ffi::CStr::from_ptr(real_new_path).to_str().unwrap() }, result ); result @@ -141,7 +152,10 @@ pub fn ___syscall40(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int debug!("emscripten::___syscall40 (rmdir)"); let pathname: u32 = varargs.get(ctx); let pathname_addr = emscripten_memory_pointer!(ctx.memory(0), pathname) as *const i8; - unsafe { rmdir(pathname_addr) } + let real_path = get_cstr_path(ctx, pathname_addr) + .map(|cstr| cstr.as_c_str() as *const _ as *const i8) + .unwrap_or(pathname_addr); + unsafe { rmdir(real_path) } } // pipe @@ -224,10 +238,9 @@ pub fn ___syscall110(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 { // getcwd pub fn ___syscall183(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> i32 { debug!("emscripten::___syscall183"); - use std::env; let buf_offset: c_int = varargs.get(ctx); let _size: c_int = varargs.get(ctx); - let path = env::current_dir(); + let path = get_current_directory(ctx); let path_string = path.unwrap().display().to_string(); let len = path_string.len(); unsafe { @@ -401,15 +414,18 @@ pub fn ___syscall195(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in let buf: u32 = varargs.get(ctx); let pathname_addr = emscripten_memory_pointer!(ctx.memory(0), pathname) as *const i8; + let real_path = get_cstr_path(ctx, pathname_addr) + .map(|cstr| cstr.as_c_str() as *const _ as *const i8) + .unwrap_or(pathname_addr); unsafe { let mut _stat: stat = std::mem::zeroed(); - let ret = stat(pathname_addr, &mut _stat); + let ret = stat(real_path, &mut _stat); debug!( "=> pathname: {}, buf: {}, path: {} = {}\nlast os error: {}", pathname, buf, - std::ffi::CStr::from_ptr(pathname_addr).to_str().unwrap(), + std::ffi::CStr::from_ptr(real_path).to_str().unwrap(), ret, Error::last_os_error() ); @@ -440,11 +456,6 @@ pub fn ___syscall197(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in 0 } -pub fn ___syscall220(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 { - debug!("emscripten::___syscall220"); - -1 -} - // fcntl64 pub fn ___syscall221(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall221 (fcntl64) {}", _which); @@ -457,7 +468,7 @@ pub fn ___syscall221(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in // |FNONBLOCK - 0x04 debug!("=> fd: {}, cmd: {}", _fd, cmd); match cmd { - 2 => 0, + 1 | 2 => 0, 13 | 14 => 0, // pretend file locking worked _ => -1, } diff --git a/lib/emscripten/src/syscalls/unix.rs b/lib/emscripten/src/syscalls/unix.rs index ec8b98f3f..0283a756d 100644 --- a/lib/emscripten/src/syscalls/unix.rs +++ b/lib/emscripten/src/syscalls/unix.rs @@ -43,6 +43,7 @@ use libc::{ pid_t, pread, pwrite, + readdir, // readv, recvfrom, recvmsg, @@ -108,8 +109,11 @@ pub fn ___syscall5(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int let flags: i32 = varargs.get(ctx); let mode: 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 fd = unsafe { open(pathname_addr, flags, mode) }; + let real_path = utils::get_cstr_path(ctx, pathname_addr) + .map(|cstr| cstr.as_c_str() as *const _ as *const i8) + .unwrap_or(pathname_addr); + let _path_str = unsafe { std::ffi::CStr::from_ptr(real_path).to_str().unwrap() }; + let fd = unsafe { open(real_path, flags, mode) }; debug!( "=> pathname: {}, flags: {}, mode: {} = fd: {}\npath: {}\nlast os error: {}", pathname, @@ -160,11 +164,17 @@ pub fn ___syscall83(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int let path2_ptr: c_int = varargs.get(ctx); let path1 = emscripten_memory_pointer!(ctx.memory(0), path1_ptr) as *mut i8; let path2 = emscripten_memory_pointer!(ctx.memory(0), path2_ptr) as *mut i8; - let result = unsafe { symlink(path1, path2) }; + let real_path1 = utils::get_cstr_path(ctx, path1) + .map(|cstr| cstr.as_c_str() as *const _ as *const i8) + .unwrap_or(path1); + let real_path2 = utils::get_cstr_path(ctx, path2) + .map(|cstr| cstr.as_c_str() as *const _ as *const i8) + .unwrap_or(path2); + let result = unsafe { symlink(real_path1, real_path2) }; debug!( "=> path1: {}, path2: {}, result: {}", - unsafe { std::ffi::CStr::from_ptr(path1).to_str().unwrap() }, - unsafe { std::ffi::CStr::from_ptr(path2).to_str().unwrap() }, + unsafe { std::ffi::CStr::from_ptr(real_path1).to_str().unwrap() }, + unsafe { std::ffi::CStr::from_ptr(real_path2).to_str().unwrap() }, result, ); result @@ -796,6 +806,81 @@ pub fn ___syscall196(ctx: &mut Ctx, _which: i32, mut varargs: VarArgs) -> i32 { 0 } +// getdents +// dirent structure is +// i64, i64, u16 (280), i8, [i8; 256] +pub fn ___syscall220(ctx: &mut Ctx, _which: i32, mut varargs: VarArgs) -> i32 { + debug!("emscripten::___syscall220"); + let fd: i32 = varargs.get(ctx); + let dirp_addr: i32 = varargs.get(ctx); + let count: u32 = varargs.get(ctx); + + //let dir = dbg!(emscripten_memory_pointer!(ctx.memory(0), dbg!(fd)) as *mut libc::DIR); + let dirp = emscripten_memory_pointer!(ctx.memory(0), dirp_addr) as *mut u8; + + let mut pos = 0; + // need to persist stream across calls? + + let dir: *mut libc::DIR = unsafe { libc::fdopendir(fd) }; + + dbg!("Start loop"); + while pos + 280 <= dbg!(count) as usize { + dbg!("Pre readdir"); + let dirent = unsafe { readdir(dir) }; + dbg!("post readdir"); + if dirent.is_null() { + break; + } + dbg!("dirent is not null"); + unsafe { + *(dirp.add(pos) as *mut u64) = dbg!((*dirent).d_ino); + #[cfg(not(target_os = "macos"))] + { + *(dirp.add(pos + 8) as *mut u64) = 280 //dbg!((*dirent).d_off); + } + #[cfg(target_os = "macos")] + { + *(dirp.add(pos + 8) as *mut u64) = if pos + 280 > count as usize { + count.into() + } else { + dbg!((*dirent).d_seekoff); + pos as u64 + 56 //280 + }; //; + } + dbg!((*dirent).d_namlen); + *(dirp.add(pos + 16) as *mut u16) = 280; //dbg!((*dirent).d_reclen); + *(dirp.add(pos + 18) as *mut u8) = dbg!((*dirent).d_type); + let upper_bound = std::cmp::min((*dirent).d_reclen, 255) as usize; + let mut i = 0; + while i < upper_bound { + *(dirp.add(pos + 19 + i) as *mut i8) = (*dirent).d_name[i]; + //dbg!((*dirent).d_name[i] as u8 as char); + //dbg!((*dirent).d_name[i] as u8 as char); + i += 1; + } + *(dirp.add(pos + 19 + i) as *mut i8) = 0 as i8; + } + dbg!("dirent written to memory"); + pos += 280; + /*unsafe { + eprintln!( + "{}", + std::ffi::CStr::from_bytes_with_nul_unchecked({ + let arr = *(dirent as *const u8 as *const [u8; 256]); + &arr.to_vec() + .into_iter() + .map(|b| b as u8) + .collect::>()[..20] + }) + .to_str() + .unwrap() + ); + }*/ + } + + dbg!(pos as i32) +} + /// fallocate pub fn ___syscall324(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall324 (fallocate) {}", _which); diff --git a/lib/emscripten/src/syscalls/windows.rs b/lib/emscripten/src/syscalls/windows.rs index a7ac8c11c..a65fa733e 100644 --- a/lib/emscripten/src/syscalls/windows.rs +++ b/lib/emscripten/src/syscalls/windows.rs @@ -251,6 +251,12 @@ pub fn ___syscall196(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 { -1 } +// getdents +pub fn ___syscall220(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 { + debug!("emscripten::___syscall220"); + -1 +} + /// fchown pub fn ___syscall207(_ctx: &mut Ctx, _which: c_int, _varargs: VarArgs) -> c_int { debug!("emscripten::___syscall207 (fchown) {}", _which); diff --git a/lib/emscripten/src/utils.rs b/lib/emscripten/src/utils.rs index 2ad5b9a40..090ac25d7 100644 --- a/lib/emscripten/src/utils.rs +++ b/lib/emscripten/src/utils.rs @@ -5,6 +5,7 @@ use libc::stat; use std::ffi::CStr; use std::mem::size_of; use std::os::raw::c_char; +use std::path::PathBuf; use std::slice; use wasmer_runtime_core::memory::Memory; use wasmer_runtime_core::{ @@ -204,6 +205,37 @@ pub fn read_string_from_wasm(memory: &Memory, offset: u32) -> String { String::from_utf8_lossy(&v).to_owned().to_string() } +/// This function trys to find an entry in mapdir +/// translating paths into their correct value +pub fn get_cstr_path(ctx: &mut Ctx, path: *const i8) -> Option { + let path_str = unsafe { std::ffi::CStr::from_ptr(path).to_str().unwrap() }.to_string(); + if let Some(val) = get_emscripten_data(ctx).mapped_dirs.get(&path_str) { + std::ffi::CString::new(val.to_string_lossy().as_bytes()).ok() + } else { + None + } +} + +/// gets the current directory +/// handles mapdir logic +pub fn get_current_directory(ctx: &mut Ctx) -> Option { + if let Some(val) = get_emscripten_data(ctx).mapped_dirs.get(".") { + return Some(val.clone()); + } + std::env::current_dir() + .map(|cwd| { + if let Some(val) = get_emscripten_data(ctx) + .mapped_dirs + .get(&cwd.to_string_lossy().to_string()) + { + val.clone() + } else { + cwd + } + }) + .ok() +} + #[cfg(test)] mod tests { use super::is_emscripten_module; diff --git a/src/bin/wasmer.rs b/src/bin/wasmer.rs index 00249ebf9..cd43a5f07 100644 --- a/src/bin/wasmer.rs +++ b/src/bin/wasmer.rs @@ -458,6 +458,7 @@ fn execute_wasm(options: &Run) -> Result<(), String> { }, options.args.iter().map(|arg| arg.as_str()).collect(), options.em_entrypoint.clone(), + mapped_dirs, ) .map_err(|e| format!("{:?}", e))?; } else { From 6fd6ad92fa098ce3b36319c0b31d4ccd3b95697b Mon Sep 17 00:00:00 2001 From: Syrus Date: Mon, 27 May 2019 12:09:04 -0700 Subject: [PATCH 06/22] Trying to fix timegm --- lib/emscripten/src/time.rs | 40 ++++++++++++++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/lib/emscripten/src/time.rs b/lib/emscripten/src/time.rs index d2bce3376..b3791d32c 100644 --- a/lib/emscripten/src/time.rs +++ b/lib/emscripten/src/time.rs @@ -4,7 +4,9 @@ use std::mem; use std::time::SystemTime; #[cfg(not(target_os = "windows"))] -use libc::{clockid_t, time as libc_time, timegm as libc_timegm}; +use libc::{clockid_t, time as libc_time, timegm as libc_timegm, tm as libc_tm}; +#[cfg(not(target_os = "windows"))] +use std::ffi::CString; #[cfg(target_os = "windows")] use libc::time_t; @@ -305,15 +307,45 @@ pub fn _timegm(ctx: &mut Ctx, time_ptr: c_int) -> i32 { unsafe { let time_p_addr = emscripten_memory_pointer!(ctx.memory(0), time_ptr) as *mut guest_tm; - libc_timegm(time_p_addr as _) as i32 // TODO review i64 + + let x: *mut c_char = CString::new("").expect("CString::new failed").into_raw(); + let mut rust_tm = libc_tm { + tm_sec: 0, + tm_min: 0, + tm_hour: 0, + tm_mday: 0, + tm_mon: 0, + tm_year: 0, + tm_wday: 0, + tm_yday: 0, + tm_isdst: 0, + tm_gmtoff: 0, + tm_zone: x, + }; + + let result = libc_timegm(&mut rust_tm) as i32; + if result != 0 { + (*time_p_addr).tm_sec = rust_tm.tm_sec; + (*time_p_addr).tm_min = rust_tm.tm_min; + (*time_p_addr).tm_hour = rust_tm.tm_hour; + (*time_p_addr).tm_mday = rust_tm.tm_mday; + (*time_p_addr).tm_mon = rust_tm.tm_mon; + (*time_p_addr).tm_year = rust_tm.tm_year; + (*time_p_addr).tm_wday = rust_tm.tm_wday; + (*time_p_addr).tm_yday = rust_tm.tm_yday; + (*time_p_addr).tm_isdst = rust_tm.tm_isdst; + (*time_p_addr).tm_gmtoff = rust_tm.tm_gmtoff as _; + (*time_p_addr).tm_zone = 0; + } + result } } #[cfg(target_os = "windows")] -pub fn _timegm(ctx: &mut Ctx, time_ptr: c_int) -> i32 { +pub fn _timegm(_ctx: &mut Ctx, _time_ptr: c_int) -> i32 { debug!( "emscripten::_timegm - UNIMPLEMENTED IN WINDOWS {}", - time_ptr + _time_ptr ); -1 } From fe3db46173f37b04f438b6702cc6c6031b5c87a1 Mon Sep 17 00:00:00 2001 From: Syrus Date: Mon, 27 May 2019 12:38:41 -0700 Subject: [PATCH 07/22] Fixed time ptr --- lib/emscripten/src/time.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/emscripten/src/time.rs b/lib/emscripten/src/time.rs index b3791d32c..c35d79596 100644 --- a/lib/emscripten/src/time.rs +++ b/lib/emscripten/src/time.rs @@ -302,7 +302,8 @@ pub fn _time(ctx: &mut Ctx, time_p: u32) -> i32 { /// emscripten: _timegm #[cfg(not(target_os = "windows"))] -pub fn _timegm(ctx: &mut Ctx, time_ptr: c_int) -> i32 { +#[allow(clippy::cast_ptr_alignment)] +pub fn _timegm(ctx: &mut Ctx, time_ptr: u32) -> i32 { debug!("emscripten::_timegm {}", time_ptr); unsafe { From df03fc1fd357bae52a0493a5b21a95b528b573b4 Mon Sep 17 00:00:00 2001 From: Syrus Akbary Date: Mon, 27 May 2019 13:57:17 -0700 Subject: [PATCH 08/22] Added Security Policy. Fixed #468 --- SECURITY.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 SECURITY.md diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 000000000..3aab45e54 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,20 @@ +# Security Policy + +## Supported Versions + +While in beta, the latest published version of `wasmer` (`0.x`) will be supported with security updates. + +| Version | Supported | +| ------- | ------------------ | +| 0.x | :white_check_mark: | + +## Reporting a Vulnerability + +The Wasmer team and community take security bugs in Wasmer seriously. +We appreciate your efforts to responsibly disclose your findings, and will make every effort to acknowledge your contributions. + +To report a vulnerability, you can draft a security advisory using Github: +https://github.com/wasmerio/wasmer/security/advisories/new + +The Wasmer team will send a response indicating the next steps in handling your report. +After the initial reply to your report, the security team will keep you informed of the progress towards a fix and full announcement, and may ask for additional information or guidance. From ef4908d3bcbadaae2350e07bb92903a786643df0 Mon Sep 17 00:00:00 2001 From: Syrus Akbary Date: Mon, 27 May 2019 14:41:18 -0700 Subject: [PATCH 09/22] Fix security contact --- SECURITY.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/SECURITY.md b/SECURITY.md index 3aab45e54..11b5c0f13 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -13,8 +13,7 @@ While in beta, the latest published version of `wasmer` (`0.x`) will be supporte The Wasmer team and community take security bugs in Wasmer seriously. We appreciate your efforts to responsibly disclose your findings, and will make every effort to acknowledge your contributions. -To report a vulnerability, you can draft a security advisory using Github: -https://github.com/wasmerio/wasmer/security/advisories/new +To report a security issue, email security@wasmer.io and include the word "SECURITY" in the subject line. The Wasmer team will send a response indicating the next steps in handling your report. After the initial reply to your report, the security team will keep you informed of the progress towards a fix and full announcement, and may ask for additional information or guidance. From 3a4517d5d6e0517450426d8fdf85e3a8ab9563f5 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Tue, 28 May 2019 10:06:22 -0700 Subject: [PATCH 10/22] clean up code, verify it behaves the same as emscripten with js --- lib/emscripten/src/syscalls/unix.rs | 57 +++++------------------------ 1 file changed, 10 insertions(+), 47 deletions(-) diff --git a/lib/emscripten/src/syscalls/unix.rs b/lib/emscripten/src/syscalls/unix.rs index 0283a756d..81d3c667b 100644 --- a/lib/emscripten/src/syscalls/unix.rs +++ b/lib/emscripten/src/syscalls/unix.rs @@ -815,70 +815,33 @@ pub fn ___syscall220(ctx: &mut Ctx, _which: i32, mut varargs: VarArgs) -> i32 { let dirp_addr: i32 = varargs.get(ctx); let count: u32 = varargs.get(ctx); - //let dir = dbg!(emscripten_memory_pointer!(ctx.memory(0), dbg!(fd)) as *mut libc::DIR); let dirp = emscripten_memory_pointer!(ctx.memory(0), dirp_addr) as *mut u8; - - let mut pos = 0; // need to persist stream across calls? - let dir: *mut libc::DIR = unsafe { libc::fdopendir(fd) }; - dbg!("Start loop"); - while pos + 280 <= dbg!(count) as usize { - dbg!("Pre readdir"); + let mut pos = 0; + let offset = 280; + while pos + offset <= count as usize { let dirent = unsafe { readdir(dir) }; - dbg!("post readdir"); if dirent.is_null() { break; } - dbg!("dirent is not null"); unsafe { - *(dirp.add(pos) as *mut u64) = dbg!((*dirent).d_ino); - #[cfg(not(target_os = "macos"))] - { - *(dirp.add(pos + 8) as *mut u64) = 280 //dbg!((*dirent).d_off); - } - #[cfg(target_os = "macos")] - { - *(dirp.add(pos + 8) as *mut u64) = if pos + 280 > count as usize { - count.into() - } else { - dbg!((*dirent).d_seekoff); - pos as u64 + 56 //280 - }; //; - } - dbg!((*dirent).d_namlen); - *(dirp.add(pos + 16) as *mut u16) = 280; //dbg!((*dirent).d_reclen); - *(dirp.add(pos + 18) as *mut u8) = dbg!((*dirent).d_type); - let upper_bound = std::cmp::min((*dirent).d_reclen, 255) as usize; + *(dirp.add(pos) as *mut u64) = (*dirent).d_ino; + *(dirp.add(pos + 8) as *mut u64) = pos as u64 + offset as u64; + *(dirp.add(pos + 16) as *mut u16) = offset as u16; + *(dirp.add(pos + 18) as *mut u8) = (*dirent).d_type; + let upper_bound = std::cmp::min((*dirent).d_reclen, 254) as usize; let mut i = 0; while i < upper_bound { *(dirp.add(pos + 19 + i) as *mut i8) = (*dirent).d_name[i]; - //dbg!((*dirent).d_name[i] as u8 as char); - //dbg!((*dirent).d_name[i] as u8 as char); i += 1; } *(dirp.add(pos + 19 + i) as *mut i8) = 0 as i8; } - dbg!("dirent written to memory"); - pos += 280; - /*unsafe { - eprintln!( - "{}", - std::ffi::CStr::from_bytes_with_nul_unchecked({ - let arr = *(dirent as *const u8 as *const [u8; 256]); - &arr.to_vec() - .into_iter() - .map(|b| b as u8) - .collect::>()[..20] - }) - .to_str() - .unwrap() - ); - }*/ + pos += offset; } - - dbg!(pos as i32) + pos as i32 } /// fallocate From 4b2092d613edf3a4bb22dbb875943e9503e2136f Mon Sep 17 00:00:00 2001 From: Steven Date: Tue, 28 May 2019 14:41:12 -0400 Subject: [PATCH 11/22] =?UTF-8?q?Add=20=F0=9F=A6=80=20to=20the=20Rust=20la?= =?UTF-8?q?nguage?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d67062125..b3a7a070d 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ curl https://get.wasmer.io -sSfL | sh Wasmer runtime can also be embedded in different languages, so you can use WebAssembly anywhere ✨: -* [**Rust**](https://github.com/wasmerio/wasmer-rust-example) +* [🦀 **Rust**](https://github.com/wasmerio/wasmer-rust-example) * [**C/C++**](https://github.com/wasmerio/wasmer-c-api) * [**🐘 PHP**](https://github.com/wasmerio/php-ext-wasm) * [**🐍 Python**](https://github.com/wasmerio/python-ext-wasm) From 6606a7c7b0a73fe21054d487820448177bd81955 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Tue, 28 May 2019 14:06:24 -0700 Subject: [PATCH 12/22] silence clippy on pointer alignment --- lib/emscripten/src/syscalls/unix.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/emscripten/src/syscalls/unix.rs b/lib/emscripten/src/syscalls/unix.rs index 7907e7642..797878fa3 100644 --- a/lib/emscripten/src/syscalls/unix.rs +++ b/lib/emscripten/src/syscalls/unix.rs @@ -814,6 +814,7 @@ pub fn ___syscall220(ctx: &mut Ctx, _which: i32, mut varargs: VarArgs) -> i32 { if dirent.is_null() { break; } + #[allow(clippy::cast_ptr_alignment)] unsafe { *(dirp.add(pos) as *mut u64) = (*dirent).d_ino; *(dirp.add(pos + 8) as *mut u64) = pos as u64 + offset as u64; From 5791583228df8960f34589a5837e37a6b395c5f0 Mon Sep 17 00:00:00 2001 From: Syrus Date: Tue, 28 May 2019 15:04:51 -0700 Subject: [PATCH 13/22] Create dynamic libraries for different platforms per release --- .appveyor.yml | 1 + .circleci/config.yml | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/.appveyor.yml b/.appveyor.yml index 00ccff954..bbba6ac17 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -64,6 +64,7 @@ build_script: - rename target wapm-cli-target - cd .. - move wapm-cli\wapm-cli-target wapm-cli-target + - cargo build --release --manifest-path lib/runtime-c-api/Cargo.toml test_script: - cargo test --manifest-path lib/spectests/Cargo.toml --features clif diff --git a/.circleci/config.yml b/.circleci/config.yml index 520dbc842..30cd67c01 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -191,6 +191,11 @@ jobs: echo "${CIRCLE_TAG}" >> artifacts/git_version make build-install cp ./wasmer.tar.gz ./artifacts/$(./binary-name.sh) + - run: + name: Dynamic library + command: | + cargo build --release --manifest-path lib/runtime-c-api/Cargo.toml + cp target/release/libwasmer_runtime_c_api.so ./artifacts - persist_to_workspace: root: . paths: @@ -278,6 +283,11 @@ jobs: cp ./wasmer.tar.gz ./artifacts/$(./binary-name.sh) # VERSION=$(cargo pkgid | cut -d# -f2 | cut -d: -f2) # echo "${VERSION}" >> artifacts/version + - run: + name: Dynamic library + command: | + cargo build --release --manifest-path lib/runtime-c-api/Cargo.toml + cp target/release/libwasmer_runtime_c_api.dylib ./artifacts - persist_to_workspace: root: . paths: From dd2735d0dc32fda5b46fdda8f8f895260131bd73 Mon Sep 17 00:00:00 2001 From: Syrus Date: Tue, 28 May 2019 15:31:19 -0700 Subject: [PATCH 14/22] Fixed macos build --- .circleci/config.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 30cd67c01..ccdd97780 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -286,6 +286,7 @@ jobs: - run: name: Dynamic library command: | + export PATH="$HOME/.cargo/bin:$PATH" cargo build --release --manifest-path lib/runtime-c-api/Cargo.toml cp target/release/libwasmer_runtime_c_api.dylib ./artifacts - persist_to_workspace: From 74fb26cf24ddcf7f0629e6e2d9194b2516ffa6c3 Mon Sep 17 00:00:00 2001 From: Syrus Akbary Date: Tue, 28 May 2019 18:15:48 -0700 Subject: [PATCH 15/22] Upload artifacts always (when possible) --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index ccdd97780..37b1de24e 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -362,7 +362,7 @@ jobs: # VERSION_TAG=$(git describe --exact-match --tags) #if [ "$VERSION" == "$VERSION_TAG" ]; then # echo "Versions match, publishing to Github" - ghr -t ${GITHUB_TOKEN} -u ${CIRCLE_PROJECT_USERNAME} -r ${CIRCLE_PROJECT_REPONAME} -c ${CIRCLE_SHA1} -soft ${VERSION} ./artifacts/ + ghr -t ${GITHUB_TOKEN} -u ${CIRCLE_PROJECT_USERNAME} -r ${CIRCLE_PROJECT_REPONAME} -c ${CIRCLE_SHA1} ${VERSION} ./artifacts/ #else # echo "Versions don't match. Wasmer output version (wasmer --version) is ${VERSION} while Git tag is ${VERSION_TAG}" # exit 1 From e0d4c9e1b79c3b49a06ceac77b30a1432819ec14 Mon Sep 17 00:00:00 2001 From: Syrus Akbary Date: Wed, 29 May 2019 01:03:51 -0700 Subject: [PATCH 16/22] Trying to make ghr always to pass in CircleCI --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 37b1de24e..11c4035aa 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -362,7 +362,7 @@ jobs: # VERSION_TAG=$(git describe --exact-match --tags) #if [ "$VERSION" == "$VERSION_TAG" ]; then # echo "Versions match, publishing to Github" - ghr -t ${GITHUB_TOKEN} -u ${CIRCLE_PROJECT_USERNAME} -r ${CIRCLE_PROJECT_REPONAME} -c ${CIRCLE_SHA1} ${VERSION} ./artifacts/ + ghr -t ${GITHUB_TOKEN} -u ${CIRCLE_PROJECT_USERNAME} -r ${CIRCLE_PROJECT_REPONAME} -c ${CIRCLE_SHA1} ${VERSION} ./artifacts/ || true #else # echo "Versions don't match. Wasmer output version (wasmer --version) is ${VERSION} while Git tag is ${VERSION_TAG}" # exit 1 From ff5d50b27375000840b13fb974f4d0841c2b2e27 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Wed, 29 May 2019 16:04:07 +0200 Subject: [PATCH 17/22] fix(runtime-c-api) Set the install name of the dylib to `@rpath`. ```sh $ objdump -macho -dylib-id libwasmer_runtime_c_api.dylib libwasmer_runtime_c_api.dylib: /Users/distiller/project/target/release/deps/libwasmer_runtime_c_api.dylib ``` we observe that the dylib ID (aka install name) is set to `/Users/distiller/project/target/release/deps/libwasmer_runtime_c_api.dylib`, which is valid only in the context of CircleCI. This patch changes the dylib ID to `@rpath/libwasmer_runtime_c_api.dylib`, which can be then changed by the linker option `-rpath` (use `-Wl,-rpath,$value` with the compiler to send the `-rpath` value to the linker). This is super useful when dynamically linking libraries against another language. --- .circleci/config.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 11c4035aa..eead29af0 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -284,10 +284,11 @@ jobs: # VERSION=$(cargo pkgid | cut -d# -f2 | cut -d: -f2) # echo "${VERSION}" >> artifacts/version - run: - name: Dynamic library + name: Generate dynamic library for the runtime C API command: | export PATH="$HOME/.cargo/bin:$PATH" cargo build --release --manifest-path lib/runtime-c-api/Cargo.toml + install_name_tool -id "@rpath/libwasmer_runtime_c_api.dylib" target/release/libwasmer_runtime_c_api.dylib cp target/release/libwasmer_runtime_c_api.dylib ./artifacts - persist_to_workspace: root: . From 7a7aa4608aa25964b1a948aef2ea1b998c28c834 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Wed, 29 May 2019 11:41:29 -0700 Subject: [PATCH 18/22] fix emscripten regression tests --- lib/emscripten/tests/emtests/_common.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/emscripten/tests/emtests/_common.rs b/lib/emscripten/tests/emtests/_common.rs index 43c1aecbf..993842a18 100644 --- a/lib/emscripten/tests/emtests/_common.rs +++ b/lib/emscripten/tests/emtests/_common.rs @@ -56,6 +56,7 @@ macro_rules! assert_emscripten_output { $name, $args, None, + vec![], ).expect("run_emscripten_instance finishes"); let output = capturer.end().unwrap().0; From b627fbf8bbbacbb9231c3bff8e95f955f64ee34c Mon Sep 17 00:00:00 2001 From: Syrus Akbary Date: Wed, 29 May 2019 12:36:09 -0700 Subject: [PATCH 19/22] Added support for Go --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index b3a7a070d..27b04baab 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,7 @@ Wasmer runtime can also be embedded in different languages, so you can use WebAs * [**🐘 PHP**](https://github.com/wasmerio/php-ext-wasm) * [**🐍 Python**](https://github.com/wasmerio/python-ext-wasm) * [**💎 Ruby**](https://github.com/wasmerio/ruby-ext-wasm) +* [**🐹 Go**](https://github.com/wasmerio/go-ext-wasm) ### Usage From 281c5ff45d5c066e2e0344347da31e00a4b9de2f Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Wed, 29 May 2019 14:20:52 -0700 Subject: [PATCH 20/22] fix bugs in em mapdir, improve it for relative paths, use it more --- lib/emscripten/src/syscalls/mod.rs | 47 +++++++++++------ lib/emscripten/src/syscalls/unix.rs | 73 ++++++++++++++++++++------ lib/emscripten/src/syscalls/windows.rs | 20 +++++-- lib/emscripten/src/utils.rs | 32 +++++++++-- src/bin/wasmer.rs | 3 -- 5 files changed, 131 insertions(+), 44 deletions(-) diff --git a/lib/emscripten/src/syscalls/mod.rs b/lib/emscripten/src/syscalls/mod.rs index 05766bf79..94f118947 100644 --- a/lib/emscripten/src/syscalls/mod.rs +++ b/lib/emscripten/src/syscalls/mod.rs @@ -96,9 +96,12 @@ pub fn ___syscall6(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int pub fn ___syscall12(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall12 (chdir) {}", _which); let path_ptr = varargs.get_str(ctx); - let real_path = get_cstr_path(ctx, path_ptr) - .map(|cstr| cstr.as_c_str() as *const _ as *const i8) - .unwrap_or(path_ptr); + let real_path_owned = get_cstr_path(ctx, path_ptr); + let real_path = if let Some(ref rp) = real_path_owned { + rp.as_c_str().as_ptr() + } else { + path_ptr + }; let ret = unsafe { chdir(real_path) }; debug!( "=> path: {:?}, ret: {}", @@ -129,12 +132,18 @@ pub fn ___syscall38(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> i32 { debug!("emscripten::___syscall38 (rename)"); let old_path = varargs.get_str(ctx); let new_path = varargs.get_str(ctx); - let real_old_path = get_cstr_path(ctx, old_path) - .map(|cstr| cstr.as_c_str() as *const _ as *const i8) - .unwrap_or(old_path); - let real_new_path = get_cstr_path(ctx, new_path) - .map(|cstr| cstr.as_c_str() as *const _ as *const i8) - .unwrap_or(new_path); + let real_old_path_owned = get_cstr_path(ctx, old_path); + let real_old_path = if let Some(ref rp) = real_old_path_owned { + rp.as_c_str().as_ptr() + } else { + old_path + }; + let real_new_path_owned = get_cstr_path(ctx, new_path); + let real_new_path = if let Some(ref rp) = real_new_path_owned { + rp.as_c_str().as_ptr() + } else { + new_path + }; let result = unsafe { rename(real_old_path, real_new_path) }; debug!( "=> old_path: {}, new_path: {}, result: {}", @@ -149,9 +158,12 @@ pub fn ___syscall38(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> i32 { pub fn ___syscall40(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall40 (rmdir)"); let pathname_addr = varargs.get_str(ctx); - let real_path = get_cstr_path(ctx, pathname_addr) - .map(|cstr| cstr.as_c_str() as *const _ as *const i8) - .unwrap_or(pathname_addr); + let real_path_owned = get_cstr_path(ctx, pathname_addr); + let real_path = if let Some(ref rp) = real_path_owned { + rp.as_c_str().as_ptr() + } else { + pathname_addr + }; unsafe { rmdir(real_path) } } @@ -433,16 +445,19 @@ pub fn ___syscall195(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in let pathname_addr = varargs.get_str(ctx); let buf: u32 = varargs.get(ctx); - let real_path = get_cstr_path(ctx, pathname_addr) - .map(|cstr| cstr.as_c_str() as *const _ as *const i8) - .unwrap_or(pathname_addr); + let real_path_owned = get_cstr_path(ctx, pathname_addr); + let real_path = if let Some(ref rp) = real_path_owned { + rp.as_c_str().as_ptr() + } else { + pathname_addr + }; unsafe { let mut _stat: stat = std::mem::zeroed(); let ret = stat(real_path, &mut _stat); debug!( "=> pathname: {}, buf: {} = {}, last os error: {}", - std::ffi::CStr::from_ptr(pathname_addr).to_str().unwrap(), + std::ffi::CStr::from_ptr(real_path).to_str().unwrap(), buf, ret, Error::last_os_error() diff --git a/lib/emscripten/src/syscalls/unix.rs b/lib/emscripten/src/syscalls/unix.rs index 797878fa3..1c4db071b 100644 --- a/lib/emscripten/src/syscalls/unix.rs +++ b/lib/emscripten/src/syscalls/unix.rs @@ -108,9 +108,12 @@ pub fn ___syscall5(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int let pathname_addr = varargs.get_str(ctx); let flags: i32 = varargs.get(ctx); let mode: u32 = varargs.get(ctx); - let real_path = utils::get_cstr_path(ctx, pathname_addr) - .map(|cstr| cstr.as_c_str() as *const _ as *const i8) - .unwrap_or(pathname_addr); + let real_path_owned = utils::get_cstr_path(ctx, pathname_addr); + let real_path = if let Some(ref rp) = real_path_owned { + rp.as_c_str().as_ptr() + } else { + pathname_addr + }; let _path_str = unsafe { std::ffi::CStr::from_ptr(real_path).to_str().unwrap() }; let fd = unsafe { open(real_path, flags, mode) }; debug!( @@ -158,12 +161,18 @@ pub fn ___syscall83(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int let path1 = varargs.get_str(ctx); let path2 = varargs.get_str(ctx); - let real_path1 = utils::get_cstr_path(ctx, path1) - .map(|cstr| cstr.as_c_str() as *const _ as *const i8) - .unwrap_or(path1); - let real_path2 = utils::get_cstr_path(ctx, path2) - .map(|cstr| cstr.as_c_str() as *const _ as *const i8) - .unwrap_or(path2); + let real_path1_owned = utils::get_cstr_path(ctx, path1); + let real_path1 = if let Some(ref rp) = real_path1_owned { + rp.as_c_str().as_ptr() + } else { + path1 + }; + let real_path2_owned = utils::get_cstr_path(ctx, path2); + let real_path2 = if let Some(ref rp) = real_path2_owned { + rp.as_c_str().as_ptr() + } else { + path2 + }; let result = unsafe { symlink(real_path1, real_path2) }; debug!( "=> path1: {}, path2: {}, result: {}", @@ -191,12 +200,18 @@ pub fn ___syscall194(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in pub fn ___syscall198(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall198 (lchown) {}", _which); let path_ptr = varargs.get_str(ctx); + let real_path_owned = utils::get_cstr_path(ctx, path_ptr); + let real_path = if let Some(ref rp) = real_path_owned { + rp.as_c_str().as_ptr() + } else { + path_ptr + }; let uid: uid_t = varargs.get(ctx); let gid: gid_t = varargs.get(ctx); - let result = unsafe { lchown(path_ptr, uid, gid) }; + let result = unsafe { lchown(real_path, uid, gid) }; debug!( "=> path: {}, uid: {}, gid: {}, result: {}", - unsafe { std::ffi::CStr::from_ptr(path_ptr).to_str().unwrap() }, + unsafe { std::ffi::CStr::from_ptr(real_path).to_str().unwrap() }, uid, gid, result, @@ -226,10 +241,16 @@ pub fn ___syscall212(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in debug!("emscripten::___syscall212 (chown) {}", _which); let pathname_addr = varargs.get_str(ctx); + let real_path_owned = utils::get_cstr_path(ctx, pathname_addr); + let real_path = if let Some(ref rp) = real_path_owned { + rp.as_c_str().as_ptr() + } else { + pathname_addr + }; let owner: u32 = varargs.get(ctx); let group: u32 = varargs.get(ctx); - unsafe { chown(pathname_addr, owner, group) } + unsafe { chown(real_path, owner, group) } } /// madvise @@ -249,11 +270,17 @@ pub fn ___syscall219(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in pub fn ___syscall33(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall33 (access) {}", _which); let path = varargs.get_str(ctx); + let real_path_owned = utils::get_cstr_path(ctx, path); + let real_path = if let Some(ref rp) = real_path_owned { + rp.as_c_str().as_ptr() + } else { + path + }; let amode: c_int = varargs.get(ctx); - let result = unsafe { access(path, amode) }; + let result = unsafe { access(real_path, amode) }; debug!( "=> path: {}, amode: {}, result: {}", - unsafe { std::ffi::CStr::from_ptr(path).to_str().unwrap() }, + unsafe { std::ffi::CStr::from_ptr(real_path).to_str().unwrap() }, amode, result ); @@ -271,8 +298,14 @@ pub fn ___syscall34(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int pub fn ___syscall39(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall39 (mkdir) {}", _which); let pathname_addr = varargs.get_str(ctx); + let real_path_owned = utils::get_cstr_path(ctx, pathname_addr); + let real_path = if let Some(ref rp) = real_path_owned { + rp.as_c_str().as_ptr() + } else { + pathname_addr + }; let mode: u32 = varargs.get(ctx); - unsafe { mkdir(pathname_addr, mode as _) } + unsafe { mkdir(real_path, mode as _) } } /// dup @@ -771,6 +804,12 @@ pub fn ___syscall122(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in pub fn ___syscall196(ctx: &mut Ctx, _which: i32, mut varargs: VarArgs) -> i32 { debug!("emscripten::___syscall196 (lstat64) {}", _which); let path = varargs.get_str(ctx); + let real_path_owned = utils::get_cstr_path(ctx, path); + let real_path = if let Some(ref rp) = real_path_owned { + rp.as_c_str().as_ptr() + } else { + path + }; let buf_ptr: u32 = varargs.get(ctx); unsafe { let mut stat: stat = std::mem::zeroed(); @@ -781,9 +820,9 @@ pub fn ___syscall196(ctx: &mut Ctx, _which: i32, mut varargs: VarArgs) -> i32 { let stat_ptr = &mut stat as *mut stat; #[cfg(target_os = "macos")] - let ret = lstat64(path, stat_ptr); + let ret = lstat64(real_path, stat_ptr); #[cfg(not(target_os = "macos"))] - let ret = lstat(path, stat_ptr); + let ret = lstat(real_path, stat_ptr); debug!("ret: {}", ret); if ret != 0 { diff --git a/lib/emscripten/src/syscalls/windows.rs b/lib/emscripten/src/syscalls/windows.rs index 1355ebb1c..b3f7b748f 100644 --- a/lib/emscripten/src/syscalls/windows.rs +++ b/lib/emscripten/src/syscalls/windows.rs @@ -1,4 +1,4 @@ -use crate::utils::copy_cstr_into_wasm; +use crate::utils::{copy_cstr_into_wasm, get_cstr_path}; use crate::varargs::VarArgs; use libc::mkdir; use libc::open; @@ -19,9 +19,15 @@ pub fn ___syscall5(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int { #[cfg(not(feature = "debug"))] let _ = which; let pathname_addr = varargs.get_str(ctx); + let real_path_owned = get_cstr_path(ctx, pathname_addr); + let real_path = if let Some(ref rp) = real_path_owned { + rp.as_c_str().as_ptr() + } else { + pathname_addr + }; let flags: i32 = varargs.get(ctx); let mode: u32 = varargs.get(ctx); - let path_str = unsafe { std::ffi::CStr::from_ptr(pathname_addr).to_str().unwrap() }; + let path_str = unsafe { std::ffi::CStr::from_ptr(real_path).to_str().unwrap() }; match path_str { "/dev/urandom" => { // create a fake urandom file for windows, super hacky @@ -47,7 +53,7 @@ pub fn ___syscall5(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int { fd } _ => { - let fd = unsafe { open(pathname_addr, flags, mode) }; + let fd = unsafe { open(real_path, flags, mode) }; debug!( "=> pathname: {}, flags: {}, mode: {} = fd: {}\npath: {}", path_str, flags, mode, fd, path_str @@ -95,7 +101,13 @@ pub fn ___syscall39(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int #[cfg(not(feature = "debug"))] let _ = which; let pathname_addr = varargs.get_str(ctx); - unsafe { mkdir(pathname_addr) } + let real_path_owned = get_cstr_path(ctx, pathname_addr); + let real_path = if let Some(ref rp) = real_path_owned { + rp.as_c_str().as_ptr() + } else { + pathname_addr + }; + unsafe { mkdir(real_path) } } /// dup diff --git a/lib/emscripten/src/utils.rs b/lib/emscripten/src/utils.rs index 090ac25d7..112728130 100644 --- a/lib/emscripten/src/utils.rs +++ b/lib/emscripten/src/utils.rs @@ -208,12 +208,36 @@ pub fn read_string_from_wasm(memory: &Memory, offset: u32) -> String { /// This function trys to find an entry in mapdir /// translating paths into their correct value pub fn get_cstr_path(ctx: &mut Ctx, path: *const i8) -> Option { + use std::collections::VecDeque; + let path_str = unsafe { std::ffi::CStr::from_ptr(path).to_str().unwrap() }.to_string(); - if let Some(val) = get_emscripten_data(ctx).mapped_dirs.get(&path_str) { - std::ffi::CString::new(val.to_string_lossy().as_bytes()).ok() - } else { - None + let data = get_emscripten_data(ctx); + let path = PathBuf::from(path_str); + let mut prefix_added = false; + let mut components = path.components().collect::>(); + // TODO(mark): handle absolute/non-canonical/non-relative paths too (this + // functionality should be shared among the abis) + if components.len() == 1 { + components.push_front(std::path::Component::CurDir); + prefix_added = true; } + let mut cumulative_path = PathBuf::new(); + for c in components.into_iter() { + cumulative_path.push(c); + if let Some(val) = data + .mapped_dirs + .get(&cumulative_path.to_string_lossy().to_string()) + { + let rest_of_path = if !prefix_added { + path.strip_prefix(cumulative_path).ok()? + } else { + &path + }; + let rebased_path = val.join(rest_of_path); + return std::ffi::CString::new(rebased_path.to_string_lossy().as_bytes()).ok(); + } + } + None } /// gets the current directory diff --git a/src/bin/wasmer.rs b/src/bin/wasmer.rs index cd43a5f07..6f835b4ec 100644 --- a/src/bin/wasmer.rs +++ b/src/bin/wasmer.rs @@ -445,9 +445,6 @@ fn execute_wasm(options: &Run) -> Result<(), String> { .instantiate(&import_object) .map_err(|e| format!("Can't instantiate module: {:?}", e))?; - if !mapped_dirs.is_empty() { - eprintln!("WARN: mapdir is not implemented for emscripten targets"); - } wasmer_emscripten::run_emscripten_instance( &module, &mut instance, From 4c8915efd842a3fb36345ad3af498e9517c36c1b Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Wed, 29 May 2019 14:35:58 -0700 Subject: [PATCH 21/22] add mapdir pr to changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 93857f7d8..35838a19b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ Blocks of changes will separated by version increments. ## **[Unreleased]** +- [#470](https://github.com/wasmerio/wasmer/pull/470) Add mapdir support to Emscripten, implement getdents for Unix - [#467](https://github.com/wasmerio/wasmer/pull/467) `wasmer_instantiate` returns better error messages in the runtime C API - [#463](https://github.com/wasmerio/wasmer/pull/463) Fix bug in WASI path_open allowing one level above preopened dir to be accessed - [#461](https://github.com/wasmerio/wasmer/pull/461) Prevent passing negative lengths in various places in the runtime C API From 5d63c96d9609defdfcc1bd899563c6897caf0394 Mon Sep 17 00:00:00 2001 From: Syrus Akbary Date: Wed, 29 May 2019 15:12:45 -0700 Subject: [PATCH 22/22] Update ARCHITECTURE.md --- ARCHITECTURE.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index e3d87738d..e1d1c4ae3 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -2,7 +2,7 @@ Wasmer uses the following components: -- [Cranelift](https://github.com/cranestation/cranelift): for compiling Wasm binaries to machine code +- Compiler backends: for compiling Wasm binaries to machine code ([more info here](https://github.com/wasmerio/wasmer/tree/master/lib#backends)) - [wabt](https://github.com/pepyakin/wabt-rs): for transforming `.wast` files to `.wasm` and running WebAssembly spec tests - [wasmparser](https://github.com/yurydelendik/wasmparser.rs): for parsing the `.wasm` files and translating them into WebAssembly modules @@ -67,3 +67,8 @@ Once that's finished, we will have a `Instance` function that will be ready to e Wasmer's Emscripten integration tries to wrap (and emulate) all the different syscalls that Emscripten needs. We provide this integration by filling the `import_object` with the Emscripten functions, while instantiating the WebAssembly Instance. + +## WASI + +Wasmer's WASI integration implements all the different syscalls that WASI needs. +We provide this integration by filling the `import_object` with the WASI functions, while instantiating the WebAssembly Instance.