Merge branch 'feature/vm_refactor' into feature/vm_refactor_errors

This commit is contained in:
Lachlan Sneff 2019-01-18 09:20:55 -08:00 committed by GitHub
commit e8dcbc5897
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
39 changed files with 1809 additions and 1387 deletions

151
.appveyor.yml Normal file
View File

@ -0,0 +1,151 @@
# This appveyor build file is heavily inspired by uutils/coreutils
# https://raw.githubusercontent.com/uutils/coreutils/d0db7bbaa46dabf65b71e3e33b1ed7595aaacc56/.appveyor.yml
branches:
except:
- master
version: "{build} ~ {branch}"
os: Visual Studio 2017
matrix:
allow_failures:
- CHANNEL: nightly
# - ABI: gnu
environment:
matrix:
# minimum version
# - CHANNEL: 1.31.0
# ARCH: i686
# ABI: msvc
# # "msvc" ABI
# - CHANNEL: stable
# ARCH: i686
# ABI: msvc
# - CHANNEL: stable
# ARCH: x86_64
# ABI: msvc
# - CHANNEL: beta
# ARCH: i686
# ABI: msvc
# - CHANNEL: beta
# ARCH: x86_64
# ABI: msvc
# - CHANNEL: nightly
# ARCH: i686
# ABI: msvc
# - CHANNEL: nightly
# ARCH: x86_64
# ABI: msvc
# # "gnu" ABI
# - CHANNEL: stable
# ARCH: i686
# ABI: gnu
# - CHANNEL: stable
# ARCH: x86_64
# ABI: gnu
# - CHANNEL: beta
# ARCH: i686
# ABI: gnu
# - CHANNEL: beta
# ARCH: x86_64
# ABI: gnu
# - CHANNEL: nightly
# ARCH: i686
# ABI: gnu
# - CHANNEL: nightly
# ARCH: x86_64
# ABI: gnu
# * specific gnu compilers
# - CHANNEL: stable
# ARCH: i686
# ABI: gnu
# MINGW_URL: https://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win32/Personal%20Builds/mingw-builds/4.9.2/threads-win32/dwarf/i686-4.9.2-release-win32-dwarf-rt_v4-rev4.7z/download
# MINGW_ARCHIVE: i686-4.9.2-release-win32-dwarf-rt_v4-rev4.7z
- CHANNEL: stable
ARCH: x86_64
ABI: gnu
MINGW_URL: https://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win64/Personal%20Builds/mingw-builds/7.3.0/threads-posix/seh/x86_64-7.3.0-release-posix-seh-rt_v5-rev0.7z/download#mingw-w64-x86_64-7.3.0-posix-seh.7z
install:
- echo %PATH%
# force branch checkout (if knowable), then reset to the specific commit ## (can be needed for accurate code coverage info)
# * this allows later apps to see the branch name using standard `git branch` operations, yet always builds the correct specific commit
# * ref: <https://github.com/appveyor/ci/issues/1606>[`@`](https://archive.is/RVpnF)
- if DEFINED APPVEYOR_REPO_BRANCH if /I "%APPVEYOR_REPO_SCM%"=="git" ( git checkout "%APPVEYOR_REPO_BRANCH%" & git reset --hard "%APPVEYOR_REPO_COMMIT%" )
# ensure CWD is project main directory
- cd "%APPVEYOR_BUILD_FOLDER%"
# create a working area
- ps: if ( ! $env:CI_TEMP_DIR ) { $env:CI_TEMP_DIR = "${env:TEMP}\${env:APPVEYOR_JOB_ID}" ; mkdir -force $env:CI_TEMP_DIR | out-null }
# rust installation
- set "TARGET=%ARCH%-pc-windows-%ABI%"
# * install `rust` via `rustup`
- appveyor DownloadFile "https://win.rustup.rs/" -FileName "%CI_TEMP_DIR%\rustup-init.exe"
- call "%CI_TEMP_DIR%\rustup-init.exe" -y --default-toolchain %CHANNEL% --default-host %TARGET% --no-modify-path >NUL
- set "PATH=%PATH%;%USERPROFILE%\.cargo\bin"
- ps: $env:TOOLCHAIN = $(rustup show active-toolchain)
- rename "C:\Program Files\Git\usr\bin\sh.exe" sh2.exe
# * set RUST_BACKTRACE for enhanced error messages
- set RUST_BACKTRACE=1
# * show versions
- rustc -vV
- cargo -vV
# finalize FEATURES
- if /i "%CHANNEL%"=="nightly" set "FEATURES=nightly"
# "gnu" ABI setup
# * use the system MinGW/MSYS if we can
- if /i "%ABI%"=="gnu" set MSYS_BINDIR=C:\msys64\usr\bin
- if /i "%ABI%"=="gnu" if /i "%ARCH%"=="i686" set "MSYS_BITS=32"
- if /i "%ABI%"=="gnu" if /i "%ARCH%"=="x86_64" set "MSYS_BITS=64"
- if defined MSYS_BITS set "MSYS_MINGWDIR=C:\msys64\mingw%MSYS_BITS%"
- if defined MSYS_MINGWDIR set "MSYS_BINDIR=C:\msys64\usr\bin"
## * workaround for rust-lang/rust#47048 / rust-lang/rust#53454 ## !maint: remove when resolved
- if /i "%ABI%"=="gnu" if /i "%ARCH%"=="i686" if not DEFINED MINGW_URL set "MINGW_URL=https://downloads.sourceforge.net/project/mingw-w64/Toolchains targetting Win32/Personal Builds/mingw-builds/8.1.0/threads-posix/dwarf/i686-8.1.0-release-posix-dwarf-rt_v6-rev0.7z"
- if /i "%ABI%"=="gnu" if /i "%ARCH%"=="x86_64" if not DEFINED MINGW_URL set "MINGW_URL=https://downloads.sourceforge.net/project/mingw-w64/Toolchains targetting Win64/Personal Builds/mingw-builds/8.1.0/threads-posix/seh/x86_64-8.1.0-release-posix-seh-rt_v6-rev0.7z"
##
# * specific MinGW, if specified
- ps: if ( ! $env:MINGW_ARCHIVE -and $env:MINGW_URL ) { $env:MINGW_ARCHIVE = $($([URI]$env:MINGW_URL).fragment).TrimStart('#') }
- ps: if ( ! $env:MINGW_ARCHIVE -and $env:MINGW_URL ) { $env:MINGW_ARCHIVE = $([URI]$env:MINGW_URL).segments[-1] }
- if defined MINGW_ARCHIVE curl --insecure -fsSL "%MINGW_URL%" -o "%CI_TEMP_DIR%\%MINGW_ARCHIVE%"
- if defined MINGW_ARCHIVE mkdir "%CI_TEMP_DIR%\MinGW" >NUL
- if defined MINGW_ARCHIVE 7z x -y "%CI_TEMP_DIR%\%MINGW_ARCHIVE%" -o"%CI_TEMP_DIR%\MinGW" >NUL
- if defined MINGW_ARCHIVE set "MSYS_MINGWDIR=%CI_TEMP_DIR%\MinGW\mingw%MSYS_BITS%"
- if defined MINGW_ARCHIVE set "MSYS_BINDIR=%MSYS_MINGWDIR%\bin"
# * MinGW/MSYS PATH setup
- if defined MSYS_MINGWDIR set PATH=%MSYS_MINGWDIR%\%ARCH%-w64-mingw32\bin;%MSYS_BINDIR%;%PATH%
## * workaround for rust-lang/rust#47048 / rust-lang/rust#53454 ## !maint: remove when resolved
# ** ref: <https://github.com/rust-lang/rust/issues/47048>, <https://github.com/rust-lang/rust/issues/53454>
# ** egs: <https://github.com/pkgw/tectonic/commit/29686db533d8732d7d97fc94270ed33b77f29295>, <https://github.com/rukai/PF_Sandbox/blob/e842613cf9ff102dfb3fbd87381319e6e6dfe3ae/appveyor.yml>
- if /i "%ABI%"=="gnu" rustup install %CHANNEL%-%ARCH%-pc-windows-msvc
- if /i "%ABI%"=="gnu" rustup default %CHANNEL%-%ARCH%-pc-windows-msvc
- if /i "%ABI%"=="gnu" rustup target add %TARGET%
- if /i "%ABI%"=="gnu" rustup show
- if /i "%ABI%"=="gnu" rustc -vV
- ps: $env:TOOLCHAIN = $(rustup show active-toolchain)
# ** copy libs from gcc toolchain to rust toolchain (more specifically, "crt2.o" and "dllcrt2.o" are needed)
- if defined MSYS_MINGWDIR copy /y "%MSYS_MINGWDIR%\%ARCH%-w64-mingw32\lib\*.o" "%USERPROFILE%\.rustup\toolchains\%TOOLCHAIN%\lib\rustlib\%TARGET%\lib" >NUL
##
- if /i "%ABI%"=="gnu" where gcc
- if /i "%ABI%"=="gnu" gcc --version
# "msvc" ABI setup
- if /i "%ABI%" == "msvc" if /i "%ARCH%" == "i686" call "%VS140COMNTOOLS%\..\..\VC\vcvarsall.bat"
- if /i "%ABI%" == "msvc" if /i "%ARCH%" == "x86_64" call "C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\SetEnv.cmd" /x64
- if /i "%ABI%" == "msvc" if /i "%ARCH%" == "x86_64" call "%VS140COMNTOOLS%\..\..\VC\vcvarsall.bat" x86_amd64
artifacts:
- path: target\%TARGET%\debug\wasmer.exe
name: wasmer.exe
build_script:
- set BUILD_CMD=cargo +%TOOLCHAIN% build --target=%TARGET%
- echo [ %BUILD_CMD% ] & %BUILD_CMD%
test_script:
- set TEST_CMD=cargo +%TOOLCHAIN% test --target=%TARGET% --no-fail-fast
- echo [ %TEST_CMD% ] & %TEST_CMD%

View File

@ -67,6 +67,12 @@ jobs:
sudo sysctl -w kern.maxfiles=655360 kern.maxfilesperproc=327680
make test
make lint
- run:
name: Execute integration tests
command: |
export PATH="`pwd`/cmake-3.4.1-Darwin-x86_64/CMake.app/Contents/bin:$PATH"
export PATH="$HOME/.cargo/bin:$PATH"
./integration_tests/nginx/test.sh
test-and-build:
docker:

1
.gitignore vendored
View File

@ -2,3 +2,4 @@
**/*.rs.bk
/artifacts
.DS_Store
.idea

1
Cargo.lock generated
View File

@ -1125,6 +1125,7 @@ version = "0.1.1"
dependencies = [
"byteorder 1.2.7 (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.7 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.44 (git+https://github.com/rust-lang/libc)",
"time 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)",
"wabt 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",

View File

@ -29,7 +29,7 @@ precommit: lint test
test:
# We use one thread so the emscripten stdouts doesn't collide
cargo test --all -- --test-threads=1 $(runargs)
cargo test --all --exclude wasmer-emscripten -- --test-threads=1 $(runargs)
release:
# If you are in OS-X, you will need mingw-w64 for cross compiling to windows

View File

@ -0,0 +1,12 @@
# `nginx` integration test
This starts wasmer with the nginx wasm file and serves an html
file with some simple text to assert on. The test script does
the assertion.
Run test with:
```
> ./integration_tests/nginx/test.sh
```

View File

@ -0,0 +1 @@
wasmer

View File

@ -0,0 +1 @@
26310

View File

@ -0,0 +1,24 @@
events {
}
# We need this for now, as we want to run nginx as a worker
daemon off;
master_process off;
# We show the errors and info in stderr
error_log /dev/stderr info;
http {
# We show access in the stdout
access_log /dev/stdout;
server {
listen 8080;
server_name _;
location / {
# IMPORTANT: Replace the dir with the one you want to serve (that have an index.html file)
root ./html/;
index index.html;
}
}
}

24
integration_tests/nginx/test.sh Executable file
View File

@ -0,0 +1,24 @@
#! /bin/bash
# Build the release and run nginx
make release
nohup ./target/release/wasmer run examples/nginx/nginx.wasm -- -p integration_tests/nginx/ -c nginx.conf &
sleep 3s
curl localhost:8080 > ./nginx.out
if grep "wasmer" ./nginx.out
then
echo "nginx integration test succeeded"
rm ./nohup.out
rm ./nginx.out
rm -rf ./integration_tests/nginx/*_temp
exit 0
else
echo "nginx integration test failed"
rm ./nohup.out
rm ./nginx.out
rm -rf ./integration_tests/nginx/*_temp
exit -1
fi

View File

@ -33,7 +33,7 @@ impl FuncResolver for PlaceholderFuncResolver {
/// This contains all of the items in a `ModuleInner` except the `func_resolver`.
pub struct Module {
module: ModuleInner,
pub module: ModuleInner,
}
impl Module {

View File

@ -6,6 +6,7 @@ edition = "2018"
build = "build/mod.rs"
[dependencies]
hashbrown = "0.1"
wasmer-runtime = { path = "../runtime" }
libc = { git = "https://github.com/rust-lang/libc" }
byteorder = "1"

View File

@ -8,4 +8,4 @@ fn main() {
if env::var(EMTESTS_ENV_VAR).unwrap_or("0".to_string()) == "1" {
emtests::build();
}
}
}

View File

@ -18,7 +18,6 @@ This process will do something similar to:
```
# Generate the .wasm file
emcc localtime.c -o localtime.js
# Delte the js file, as we don't need it
# Delete the js file, as we don't need it
rm localtime.js
```

View File

@ -8,8 +8,8 @@ use std::mem;
use std::os::raw::c_char;
use super::utils::{allocate_on_stack, copy_cstr_into_wasm, copy_terminated_array_of_cstrs};
use super::EmscriptenData;
use wasmer_runtime::{types::Value, Instance};
//use super::EmscriptenData;
//impl Instance {
// pub fn memory_offset_addr(&self, index: usize, offset: usize) -> *const usize {
@ -73,6 +73,7 @@ pub extern "C" fn _unsetenv(name: c_int, instance: &mut Instance) {
unsafe { unsetenv(name_addr) };
}
#[allow(clippy::cast_ptr_alignment)]
pub extern "C" fn _getpwnam(name_ptr: c_int, instance: &mut Instance) -> c_int {
debug!("emscripten::_getpwnam {}", name_ptr);
@ -110,6 +111,7 @@ pub extern "C" fn _getpwnam(name_ptr: c_int, instance: &mut Instance) -> c_int {
}
}
#[allow(clippy::cast_ptr_alignment)]
pub extern "C" fn _getgrnam(name_ptr: c_int, instance: &mut Instance) -> c_int {
debug!("emscripten::_getgrnam {}", name_ptr);
@ -189,6 +191,7 @@ pub extern "C" fn _getpagesize() -> u32 {
16384
}
#[allow(clippy::cast_ptr_alignment)]
pub extern "C" fn ___build_environment(environ: c_int, instance: &mut Instance) {
debug!("emscripten::___build_environment {}", environ);
const MAX_ENV_VALUES: u32 = 64;

View File

@ -1,5 +1,5 @@
use super::process::_abort;
use super::env;
use super::process::_abort;
use wasmer_runtime::Instance;
/// emscripten: ___cxa_allocate_exception

View File

@ -1,40 +1,40 @@
use wasmer_runtime::Instance;
use libc::{c_int, c_void};
use std::cell::UnsafeCell;
use wasmer_runtime::Instance;
/// setjmp
pub extern "C" fn __setjmp(env_addr: u32, instance: &mut Instance) -> c_int {
debug!("emscripten::__setjmp (setjmp)");
unimplemented!()
// unsafe {
// // Rather than using the env as the holder of the jump buffer pointer,
// // we use the environment address to store the index relative to jumps
// // so the address of the jump it's outside the wasm memory itself.
// let jump_index = instance.memory_offset_addr(0, env_addr as usize) as *mut i8;
// // We create the jump buffer outside of the wasm memory
// let jump_buf: UnsafeCell<[c_int; 27]> = UnsafeCell::new([0; 27]);
// let mut jumps = &mut instance.emscripten_data().as_mut().unwrap().jumps;
// let result = setjmp(jump_buf.get() as _);
// // We set the jump index to be the last value of jumps
// *jump_index = jumps.len() as _;
// // We hold the reference of the jump buffer
// jumps.push(jump_buf);
// result
// }
// unsafe {
// // Rather than using the env as the holder of the jump buffer pointer,
// // we use the environment address to store the index relative to jumps
// // so the address of the jump it's outside the wasm memory itself.
// let jump_index = instance.memory_offset_addr(0, env_addr as usize) as *mut i8;
// // We create the jump buffer outside of the wasm memory
// let jump_buf: UnsafeCell<[c_int; 27]> = UnsafeCell::new([0; 27]);
// let mut jumps = &mut instance.emscripten_data().as_mut().unwrap().jumps;
// let result = setjmp(jump_buf.get() as _);
// // We set the jump index to be the last value of jumps
// *jump_index = jumps.len() as _;
// // We hold the reference of the jump buffer
// jumps.push(jump_buf);
// result
// }
}
/// longjmp
pub extern "C" fn __longjmp(env_addr: u32, val: c_int, instance: &mut Instance) -> ! {
debug!("emscripten::__longjmp (longjmp) {}", val);
unimplemented!()
// unsafe {
// // We retrieve the jump index from the env address
// let jump_index = instance.memory_offset_addr(0, env_addr as usize) as *mut i8;
// let mut jumps = &mut instance.emscripten_data().as_mut().unwrap().jumps;
// // We get the real jump buffer from the jumps vector, using the retrieved index
// let mut jump_buf = &jumps[*jump_index as usize];
// longjmp(jump_buf.get() as _, val)
// };
// unsafe {
// // We retrieve the jump index from the env address
// let jump_index = instance.memory_offset_addr(0, env_addr as usize) as *mut i8;
// let mut jumps = &mut instance.emscripten_data().as_mut().unwrap().jumps;
// // We get the real jump buffer from the jumps vector, using the retrieved index
// let mut jump_buf = &jumps[*jump_index as usize];
// longjmp(jump_buf.get() as _, val)
// };
}
extern "C" {

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
use wasmer_runtime::Instance;
use libc::c_int;
use wasmer_runtime::Instance;
// NOTE: Not implemented by Emscripten
pub extern "C" fn ___lock(which: c_int, varargs: c_int, _instance: &mut Instance) {

View File

@ -1,6 +1,6 @@
use super::process::abort_with_message;
use wasmer_runtime::Instance;
use libc::{c_int, c_void, memcpy, size_t};
use wasmer_runtime::Instance;
/// emscripten: _emscripten_memcpy_big
pub extern "C" fn _emscripten_memcpy_big(

View File

@ -1,7 +1,7 @@
use libc::{abort, c_char, c_int, exit, pid_t, EAGAIN};
use wasmer_runtime::Instance;
use std::ffi::CStr;
use wasmer_runtime::Instance;
pub extern "C" fn abort_with_message(message: &str) {
debug!("emscripten::abort_with_message");

View File

@ -1,6 +1,7 @@
// use super::varargs::VarArgs;
use wasmer_runtime::Instance;
#[allow(clippy::cast_ptr_alignment)]
pub extern "C" fn _sigemptyset(set: u32, instance: &mut Instance) -> i32 {
debug!("emscripten::_sigemptyset");
let set_addr = instance.memory_offset_addr(0, set as _) as *mut u32;
@ -15,6 +16,7 @@ pub extern "C" fn _sigaction(signum: u32, act: u32, oldact: u32, _instance: &mut
0
}
#[allow(clippy::cast_ptr_alignment)]
pub extern "C" fn _sigaddset(set: u32, signum: u32, instance: &mut Instance) -> i32 {
debug!("emscripten::_sigaddset {}, {}", set, signum);
let set_addr = instance.memory_offset_addr(0, set as _) as *mut u32;

View File

@ -1,6 +1,5 @@
use super::utils::copy_stat_into_wasm;
use super::varargs::VarArgs;
use wasmer_runtime::Instance;
use byteorder::{ByteOrder, LittleEndian};
/// NOTE: TODO: These syscalls only support wasm_32 for now because they assume offsets are u32
/// Syscall list: https://www.cs.utexas.edu/~bismith/test/syscalls/syscalls32.html
@ -68,8 +67,10 @@ use libc::{
F_GETFD,
F_SETFD,
SOL_SOCKET,
SO_REUSEADDR,
TIOCGWINSZ,
};
use wasmer_runtime::Instance;
use super::env;
use std::mem;
@ -294,6 +295,7 @@ pub extern "C" fn ___syscall64() -> pid_t {
}
// socketcall
#[allow(clippy::cast_ptr_alignment)]
pub extern "C" fn ___syscall102(
which: c_int,
mut varargs: VarArgs,
@ -336,18 +338,17 @@ pub extern "C" fn ___syscall102(
unsafe {
ioctl(fd, FIOCLEX);
};
if cfg!(target_os = "darwin") {
type T = u32;
let payload = 1 as *const T as *const c_void;
unsafe {
setsockopt(
fd,
SOL_SOCKET,
SO_NOSIGPIPE,
payload,
mem::size_of::<T>() as socklen_t,
);
};
type T = u32;
let payload = 1 as *const T as *const c_void;
unsafe {
setsockopt(
fd,
SOL_SOCKET,
SO_NOSIGPIPE,
payload,
mem::size_of::<T>() as socklen_t,
);
};
debug!(
@ -364,12 +365,7 @@ pub extern "C" fn ___syscall102(
let address: u32 = socket_varargs.get(instance);
let address_len: u32 = socket_varargs.get(instance);
let address = instance.memory_offset_addr(0, address as usize) as *mut sockaddr;
// unsafe {
// debug!(
// "=> address.sin_family: {:?}, address.sin_port: {:?}, address.sin_addr.s_addr: {:?}",
// (*address).sin_family, (*address).sin_port, (*address).sin_addr.s_addr
// );
// }
// we convert address as a sockaddr (even if this is incorrect), to bypass the type
// issue with libc bind
@ -437,25 +433,13 @@ pub extern "C" fn ___syscall102(
(*address_linux).sa_family = (*address).sa_family as u16;
(*address_linux).sa_data = (*address).sa_data;
};
// // Debug received address
// unsafe {
// let proper_address = address as *const GuestSockaddrIn;
// debug!(
// "=> address.sin_family: {:?}, address.sin_port: {:?}, address.sin_addr.s_addr: {:?}",
// (*proper_address).sin_family, (*proper_address).sin_port, (*proper_address).sin_addr.s_addr
// );
// debug!(
// "=> address.sa_family: {:?}",
// (*address).sa_family
// );
// }
// set_cloexec
unsafe {
ioctl(fd, FIOCLEX);
};
debug!("fd: {}", fd);
// nix::unistd::write(fd, "Hello, World!".as_bytes()).unwrap();
// nix::unistd::fsync(fd).unwrap();
fd
}
6 => {
@ -515,20 +499,19 @@ pub extern "C" fn ___syscall102(
// name: Em passes SO_ACCEPTCONN, but Nginx complains about REUSEADDR
// https://github.com/openbsd/src/blob/master/sys/sys/socket.h#L156
// setsockopt (socket: c_int, level: c_int, name: c_int, value: *const c_void, option_len: socklen_t) -> c_int
let socket: i32 = socket_varargs.get(instance);
// SOL_SOCKET = 0xffff in BSD
let level: i32 = 0xffff;
// SOL_SOCKET = 0xffff (BSD, Linux)
let level: i32 = SOL_SOCKET;
let _: u32 = socket_varargs.get(instance);
// SO_ACCEPTCONN = 0x4
let name: i32 = 0x4;
// SO_REUSEADDR = 0x4 (BSD, Linux)
let name: i32 = SO_REUSEADDR;
let _: u32 = socket_varargs.get(instance);
let value: u32 = socket_varargs.get(instance);
let option_len: u32 = socket_varargs.get(instance);
let value_addr = instance.memory_offset_addr(0, value as usize) as *mut c_void; // Endian problem
let ret = unsafe { setsockopt(socket, level, name, value_addr, option_len) };
// debug!("option_value = {:?}", unsafe { *(value_addr as *const u32) });
debug!("=> socketfd: {}, level: {} (SOL_SOCKET/0xffff), name: {} (SO_REUSEADDR/4), value_addr: {:?}, option_len: {} = status: {}", socket, level, name, value_addr, option_len, ret);
ret
}
@ -571,6 +554,7 @@ pub extern "C" fn ___syscall102(
}
/// wait4
#[allow(clippy::cast_ptr_alignment)]
pub extern "C" fn ___syscall114(
_which: c_int,
mut varargs: VarArgs,
@ -606,6 +590,7 @@ pub extern "C" fn ___syscall122(
}
// select
#[allow(clippy::cast_ptr_alignment)]
pub extern "C" fn ___syscall142(
which: c_int,
mut varargs: VarArgs,
@ -673,6 +658,7 @@ pub extern "C" fn ___syscall140(
}
/// readv
#[allow(clippy::cast_ptr_alignment)]
pub extern "C" fn ___syscall145(
which: c_int,
mut varargs: VarArgs,
@ -718,6 +704,7 @@ pub extern "C" fn ___syscall145(
}
// writev
#[allow(clippy::cast_ptr_alignment)]
pub extern "C" fn ___syscall146(
which: c_int,
mut varargs: VarArgs,

View File

@ -25,6 +25,7 @@ const CLOCK_MONOTONIC: libc::clockid_t = 1;
const CLOCK_MONOTONIC_COARSE: libc::clockid_t = 6;
/// emscripten: _gettimeofday
#[allow(clippy::cast_ptr_alignment)]
pub extern "C" fn _gettimeofday(tp: c_int, tz: c_int, instance: &mut Instance) -> c_int {
debug!("emscripten::_gettimeofday {} {}", tp, tz);
#[repr(C)]
@ -49,6 +50,7 @@ pub extern "C" fn _gettimeofday(tp: c_int, tz: c_int, instance: &mut Instance) -
}
/// emscripten: _clock_gettime
#[allow(clippy::cast_ptr_alignment)]
pub extern "C" fn _clock_gettime(
clk_id: libc::clockid_t,
tp: c_int,
@ -124,6 +126,7 @@ pub extern "C" fn _tvset() {
}
/// formats time as a C string
#[allow(clippy::cast_ptr_alignment)]
unsafe extern "C" fn fmt_time(time: u32, instance: &Instance) -> *const c_char {
let date = &*(instance.memory_offset_addr(0, time as _) as *mut guest_tm);
@ -181,6 +184,7 @@ pub extern "C" fn _asctime_r(time: u32, buf: u32, instance: &mut Instance) -> u3
}
/// emscripten: _localtime
#[allow(clippy::cast_ptr_alignment)]
pub extern "C" fn _localtime(time_p: u32, instance: &mut Instance) -> c_int {
debug!("emscripten::_localtime {}", time_p);
// NOTE: emscripten seems to want tzset() called in this function
@ -217,6 +221,7 @@ pub extern "C" fn _localtime(time_p: u32, instance: &mut Instance) -> c_int {
}
}
/// emscripten: _localtime_r
#[allow(clippy::cast_ptr_alignment)]
pub extern "C" fn _localtime_r(time_p: u32, result: u32, instance: &mut Instance) -> c_int {
debug!("emscripten::_localtime_r {}", time_p);
@ -253,6 +258,7 @@ pub extern "C" fn _localtime_r(time_p: u32, result: u32, instance: &mut Instance
}
/// emscripten: _time
#[allow(clippy::cast_ptr_alignment)]
pub extern "C" fn _time(time_p: u32, instance: &mut Instance) -> time_t {
debug!("emscripten::_time {}", time_p);

View File

@ -1,4 +1,4 @@
use wasmer_runtime::{Instance, module::Module};
use wasmer_runtime::{module::Module, Instance};
//use wasmer_runtime::Instance;
use super::env;
use libc::stat;
@ -6,10 +6,11 @@ use std::ffi::CStr;
use std::mem::size_of;
use std::os::raw::c_char;
use std::slice;
use std::sync::Arc;
/// We check if a provided module is an Emscripten generated one
pub fn is_emscripten_module(module: &Module) -> bool {
for (_, import_name) in &module.imported_functions {
if import_name.name == "_emscripten_memcpy_big" && import_name.module == "env" {
pub fn is_emscripten_module(module: &Arc<Module>) -> bool {
for (_, import_name) in &module.0.imported_functions {
if import_name.name == "_emscripten_memcpy_big" && import_name.namespace == "env" {
return true;
}
}
@ -50,14 +51,14 @@ pub unsafe fn allocate_on_stack<'a, T: Copy>(
instance: &'a Instance,
) -> (u32, &'a mut [T]) {
unimplemented!("allocate_on_stack not implemented")
// let offset = (instance.emscripten_data().as_ref().unwrap().stack_alloc)(
// count * (size_of::<T>() as u32),
// instance,
// );
// let addr = instance.memory_offset_addr(0, offset as _) as *mut T;
// let slice = slice::from_raw_parts_mut(addr, count as usize);
//
// (offset, slice)
// let offset = (instance.emscripten_data().as_ref().unwrap().stack_alloc)(
// count * (size_of::<T>() as u32),
// instance,
// );
// let addr = instance.memory_offset_addr(0, offset as _) as *mut T;
// let slice = slice::from_raw_parts_mut(addr, count as usize);
//
// (offset, slice)
}
pub unsafe fn allocate_cstr_on_stack<'a>(s: &str, instance: &'a Instance) -> (u32, &'a [u8]) {
@ -111,6 +112,7 @@ pub struct GuestStat {
st_ino: u64,
}
#[allow(clippy::cast_ptr_alignment)]
pub unsafe fn copy_stat_into_wasm(instance: &mut Instance, buf: u32, stat: &stat) {
let stat_ptr = instance.memory_offset_addr(0, buf as _) as *mut GuestStat;
(*stat_ptr).st_dev = stat.st_dev as _;
@ -141,14 +143,18 @@ pub unsafe fn copy_stat_into_wasm(instance: &mut Instance, buf: u32, stat: &stat
#[cfg(test)]
mod tests {
use super::is_emscripten_module;
use wasmer_clif_backend::CraneliftCompiler;
use std::sync::Arc;
use wabt::wat2wasm;
use wasmer_clif_backend::CraneliftCompiler;
use wasmer_runtime::{compile, module::Module};
#[test]
fn should_detect_emscripten_files() {
const wast_bytes: &[u8] = include_bytes!("tests/is_emscripten_true.wast");
let wasm_binary = wat2wasm(wast_bytes.to_vec()).expect("Can't convert to wasm");
let module = wasmer_runtime::compile(&wasm_binary[..], &CraneliftCompiler::new()).expect("WASM can't be compiled");
let module =
compile(&wasm_binary[..], &CraneliftCompiler::new()).expect("WASM can't be compiled");
let module = Arc::new(module);
assert!(is_emscripten_module(&module));
}
@ -156,7 +162,9 @@ mod tests {
fn should_detect_non_emscripten_files() {
const wast_bytes: &[u8] = include_bytes!("tests/is_emscripten_false.wast");
let wasm_binary = wat2wasm(wast_bytes.to_vec()).expect("Can't convert to wasm");
let module = wasmer_runtime::compile(&wasm_binary[..], &CraneliftCompiler::new()).expect("WASM can't be compiled");
let module =
compile(&wasm_binary[..], &CraneliftCompiler::new()).expect("WASM can't be compiled");
let module = Arc::new(module);
assert!(!is_emscripten_module(&module));
}
}

View File

@ -1,5 +1,5 @@
use wasmer_runtime::Instance;
use std::mem;
use wasmer_runtime::Instance;
#[repr(transparent)]
pub struct VarArgs {

View File

@ -1,46 +1,55 @@
macro_rules! assert_emscripten_output {
($file:expr, $name:expr, $args:expr, $expected:expr) => {{
use wasmer_emscripten::generate_emscripten_env;
// use wasmer::common::stdio::StdioCapturer;
use wasmer_runtime::{Import, Imports, FuncRef};
use wasmer_runtime::table::TableBacking;
use wasmer_runtime::{Instance, module::Module};
use wasmer_clif_backend::CraneliftCompiler;
use std::sync::Arc;
use wasmer_clif_backend::CraneliftCompiler;
use wasmer_emscripten::{
EmscriptenGlobals,
generate_emscripten_env,
stdio::StdioCapturer
};
let wasm_bytes = include_bytes!($file);
let import_object = generate_emscripten_env();
// let options = Some(InstanceOptions {
// mock_missing_imports: true,
// mock_missing_globals: true,
// mock_missing_tables: true,
// abi: InstanceABI::Emscripten,
// show_progressbar: false,
// // isa: get_isa(),
// });
// let mut result_object = instantiate(&wasm_bytes.to_vec(), &import_object, options)
// .expect("Not compiled properly");
let module = wasmer_runtime::compile(&wasm_bytes[..], &CraneliftCompiler::new()).expect("WASM can't be compiled");
let instance = module.instantiate(&import_object).expect("WASM can't be instantiated");
let module = wasmer_runtime::compile(&wasm_bytes[..], &CraneliftCompiler::new())
.expect("WASM can't be compiled");
// let module = compile(&wasm_bytes[..])
// .map_err(|err| format!("Can't create the WebAssembly module: {}", err)).unwrap(); // NOTE: Need to figure what the unwrap is for ??
let emscripten_globals = EmscriptenGlobals::new();
let import_object = generate_emscripten_env(&emscripten_globals);
let mut instance = module.instantiate(import_object)
.map_err(|err| format!("Can't instantiate the WebAssembly module: {}", err)).unwrap(); // NOTE: Need to figure what the unwrap is for ??
// start_instance(
// Arc::clone(&module),
// &mut instance,
// $name,
// $args,
// );
// let capturer = StdioCapturer::new();
// start_instance(
// Arc::clone(&result_object.module),
// &mut result_object.instance,
// $name,
// $args,
// )
// .unwrap();
// let output = capturer.end().unwrap().0;
// let expected_output = include_str!($expected);
assert!(false, "Emscripten tests are mocked");
// assert!(
// output.contains(expected_output),
// "Output: `{}` does not contain expected output: `{}`",
// output,
// expected_output
// );
let capturer = StdioCapturer::new();
instance.call("_main", &[]).map(|_o| ()).unwrap();
// TODO handle start instance logic
// start_instance(
// Arc::clone(&result_object.module),
// &mut result_object.instance,
// $name,
// $args,
// )
// .unwrap();
let output = capturer.end().unwrap().0;
let expected_output = include_str!($expected);
assert!(false, "Emscripten tests are mocked");
assert!(
output.contains(expected_output),
"Output: `{}` does not contain expected output: `{}`",
output,
expected_output
);
}};
}

View File

@ -142,6 +142,7 @@ impl LocalBacking {
tables.into_boxed_map()
}
#[allow(clippy::cast_ptr_alignment)]
fn finalize_tables(
module: &ModuleInner,
imports: &ImportBacking,

View File

@ -25,7 +25,7 @@ pub(crate) struct InstanceInner {
}
pub struct Instance {
pub(crate) module: Rc<ModuleInner>,
pub module: Rc<ModuleInner>,
inner: Box<InstanceInner>,
#[allow(dead_code)]
imports: Box<Imports>,
@ -351,7 +351,7 @@ impl Namespace for Instance {
// TODO Remove this later, only needed for compilation till emscripten is updated
impl Instance {
pub fn memory_offset_addr(&self, _index: usize, _offset: usize) -> *const usize {
unimplemented!("TODO replace this emscripten stub")
pub fn memory_offset_addr(&self, index: usize, offset: usize) -> *const u8 {
unimplemented!()
}
}

View File

@ -3,14 +3,14 @@
extern crate field_offset;
#[macro_use]
mod macros;
pub mod macros;
#[doc(hidden)]
pub mod backend;
mod backing;
pub mod error;
pub mod export;
pub mod import;
mod instance;
pub mod instance;
pub mod memory;
mod mmap;
pub mod module;

View File

@ -1,3 +1,4 @@
#[macro_export]
macro_rules! debug {
($fmt:expr) => (if cfg!(any(debug_assertions, feature="debug")) { println!(concat!("wasmer-runtime(:{})::", $fmt), line!()) });
($fmt:expr, $($arg:tt)*) => (if cfg!(any(debug_assertions, feature="debug")) { println!(concat!("wasmer-runtime(:{})::", $fmt, "\n"), line!(), $($arg)*) });

View File

@ -40,7 +40,7 @@ pub struct ModuleInner {
pub sig_registry: SigRegistry,
}
pub struct Module(Rc<ModuleInner>);
pub struct Module(pub Rc<ModuleInner>);
impl Module {
pub(crate) fn new(inner: Rc<ModuleInner>) -> Self {

View File

@ -84,6 +84,7 @@ impl Ctx {
}
}
#[allow(clippy::erasing_op)] // TODO
pub fn offset_memories() -> u8 {
0 * (mem::size_of::<usize>() as u8)
}
@ -131,6 +132,7 @@ pub struct ImportedFunc {
}
impl ImportedFunc {
#[allow(clippy::erasing_op)] // TODO
pub fn offset_func() -> u8 {
0 * (mem::size_of::<usize>() as u8)
}
@ -157,6 +159,7 @@ pub struct LocalTable {
}
impl LocalTable {
#[allow(clippy::erasing_op)] // TODO
pub fn offset_base() -> u8 {
0 * (mem::size_of::<usize>() as u8)
}
@ -180,6 +183,7 @@ pub struct ImportedTable {
}
impl ImportedTable {
#[allow(clippy::erasing_op)] // TODO
pub fn offset_table() -> u8 {
0 * (mem::size_of::<usize>() as u8)
}
@ -206,6 +210,7 @@ pub struct LocalMemory {
}
impl LocalMemory {
#[allow(clippy::erasing_op)] // TODO
pub fn offset_base() -> u8 {
0 * (mem::size_of::<usize>() as u8)
}
@ -228,6 +233,7 @@ pub struct ImportedMemory {
}
impl ImportedMemory {
#[allow(clippy::erasing_op)] // TODO
pub fn offset_memory() -> u8 {
0 * (mem::size_of::<usize>() as u8)
}
@ -249,6 +255,7 @@ pub struct LocalGlobal {
}
impl LocalGlobal {
#[allow(clippy::erasing_op)] // TODO
pub fn offset_data() -> u8 {
0 * (mem::size_of::<usize>() as u8)
}
@ -269,6 +276,7 @@ pub struct ImportedGlobal {
}
impl ImportedGlobal {
#[allow(clippy::erasing_op)] // TODO
pub fn offset_global() -> u8 {
0 * (mem::size_of::<usize>() as u8)
}
@ -301,6 +309,7 @@ impl Anyfunc {
}
}
#[allow(clippy::erasing_op)] // TODO
pub fn offset_func() -> u8 {
0 * (mem::size_of::<usize>() as u8)
}

View File

@ -11,8 +11,8 @@ use std::sync::Arc;
use structopt::StructOpt;
use wasmer::*;
use wasmer_runtime;
use wasmer_emscripten;
use wasmer_runtime;
#[derive(Debug, StructOpt)]
#[structopt(name = "wasmer", about = "WASM execution runtime.")]
@ -80,10 +80,12 @@ fn execute_wasm(options: &Run) -> Result<(), String> {
webassembly::InstanceABI::None
};
let import_object = if abi == webassembly::InstanceABI::Emscripten {
wasmer_emscripten::generate_emscripten_env()
let emscripten_globals = wasmer_emscripten::EmscriptenGlobals::new();
let mut import_object = if abi == webassembly::InstanceABI::Emscripten {
wasmer_emscripten::generate_emscripten_env(&emscripten_globals)
} else {
wasmer_runtime::Imports::new()
wasmer_runtime::import::Imports::new()
};
let instance_options = webassembly::InstanceOptions {
@ -92,12 +94,12 @@ fn execute_wasm(options: &Run) -> Result<(), String> {
mock_missing_tables: true,
abi: abi,
show_progressbar: true,
// isa: isa,
};
debug!("webassembly - creating instance");
let mut instance = module.instantiate(&import_object)
let mut instance = module
.instantiate(import_object)
.map_err(|err| format!("Can't instantiate the WebAssembly module: {}", err))?;
webassembly::start_instance(

View File

@ -1,6 +1,2 @@
pub mod mmap;
pub mod slice;
mod file_descriptor;
#[cfg(test)]
pub mod stdio;

View File

@ -8,10 +8,10 @@ extern crate libc;
extern crate region;
extern crate structopt;
extern crate wabt;
extern crate wasmparser;
extern crate wasmer_clif_backend;
extern crate wasmer_runtime;
extern crate wasmer_emscripten;
extern crate wasmparser;
// extern crate wasmer_emscripten;
#[macro_use]
extern crate target_lexicon;
extern crate byteorder;

View File

@ -4,14 +4,19 @@ pub mod relocation;
pub mod utils;
use wasmer_clif_backend::CraneliftCompiler;
use wasmer_runtime::{backend::Compiler, module::Module};
use wasmer_runtime;
use wasmer_runtime::{Import, Imports, Instance};
use wasmer_runtime::{
backend::Compiler,
import::Imports,
instance::Instance,
module::{Module, ModuleInner},
};
use cranelift_codegen::{
isa,
settings::{self, Configurable},
};
use std::panic;
use std::rc::Rc;
use std::str::FromStr;
use std::sync::Arc;
use target_lexicon;
@ -31,7 +36,6 @@ pub struct ResultObject {
pub instance: Box<Instance>,
}
pub struct InstanceOptions {
// Shall we mock automatically the imported functions if they don't exist?
pub mock_missing_imports: bool,
@ -39,7 +43,7 @@ pub struct InstanceOptions {
pub mock_missing_tables: bool,
pub abi: InstanceABI,
pub show_progressbar: bool,
// pub isa: Box<isa::TargetIsa>, TODO isa
// pub isa: Box<isa::TargetIsa>, TODO isa
}
#[derive(PartialEq)]
@ -71,10 +75,10 @@ pub fn instantiate(
//let instance = Instance::new(&module, import_object, options)?;
unimplemented!()
// let instance = wasmer_runtime::instantiate(buffer_source, &CraneliftCompiler::new(), import_object)
// .map_err(|e| ErrorKind::CompileError(e))?;
//
// let isa = get_isa();
// let instance = wasmer_runtime::instantiate(buffer_source, &CraneliftCompiler::new(), import_object)
// .map_err(|e| ErrorKind::CompileError(e))?;
//
// let isa = get_isa();
// let abi = if is_emscripten_module(&instance.module) {
// InstanceABI::Emscripten
// } else {
@ -90,11 +94,11 @@ pub fn instantiate(
// isa,
// });
// debug!("webassembly - instance created");
// Ok(ResultObject {
// module: Arc::clone(&instance.module),
// instance,
// })
// debug!("webassembly - instance created");
// Ok(ResultObject {
// module: Arc::clone(&instance.module),
// instance,
// })
}
/// The webassembly::instantiate_streaming() function compiles and instantiates
@ -119,11 +123,11 @@ pub fn instantiate_streaming(
/// webassembly::CompileError.
pub fn compile(buffer_source: &[u8]) -> Result<Arc<Module>, ErrorKind> {
let compiler = &CraneliftCompiler {};
let module = compiler
let module_inner = compiler
.compile(buffer_source)
.map_err(|e| ErrorKind::CompileError(e))?;
Ok(Arc::new(module))
Ok(Arc::new(Module(Rc::new(module_inner))))
}
/// The webassembly::validate() function validates a given typed
@ -169,23 +173,23 @@ pub fn get_isa() -> Box<isa::TargetIsa> {
isa::lookup(triple!("x86_64")).unwrap().finish(flags)
}
fn store_module_arguments(path: &str, args: Vec<&str>, instance: &mut Instance) -> (u32, u32) {
let argc = args.len() + 1;
// fn store_module_arguments(path: &str, args: Vec<&str>, instance: &mut Instance) -> (u32, u32) {
// let argc = args.len() + 1;
let (argv_offset, argv_slice): (_, &mut [u32]) =
unsafe { allocate_on_stack(((argc + 1) * 4) as u32, instance) };
assert!(!argv_slice.is_empty());
// let (argv_offset, argv_slice): (_, &mut [u32]) =
// unsafe { allocate_on_stack(((argc + 1) * 4) as u32, instance) };
// assert!(!argv_slice.is_empty());
argv_slice[0] = unsafe { allocate_cstr_on_stack(path, instance).0 };
// argv_slice[0] = unsafe { allocate_cstr_on_stack(path, instance).0 };
for (slot, arg) in argv_slice[1..argc].iter_mut().zip(args.iter()) {
*slot = unsafe { allocate_cstr_on_stack(&arg, instance).0 };
}
// for (slot, arg) in argv_slice[1..argc].iter_mut().zip(args.iter()) {
// *slot = unsafe { allocate_cstr_on_stack(&arg, instance).0 };
// }
argv_slice[argc] = 0;
// argv_slice[argc] = 0;
(argc as u32, argv_offset)
}
// (argc as u32, argv_offset)
// }
// fn get_module_arguments(options: &Run, instance: &mut webassembly::Instance) -> (u32, u32) {
// // Application Arguments
@ -227,7 +231,7 @@ pub fn start_instance(
path: &str,
args: Vec<&str>,
) -> Result<(), String> {
let main_name = if is_emscripten_module(&instance.module) {
let main_name = if is_emscripten_module(&module) {
"_main"
} else {
"main"