Merge branch 'master' into atomic-transparent-repr

This commit is contained in:
Brandon Fish
2019-04-30 17:09:18 -07:00
committed by GitHub
62 changed files with 929 additions and 529 deletions

View File

@ -103,7 +103,7 @@ jobs:
- run:
name: Install Rust
command: |
curl https://sh.rustup.rs -sSf | sh -s -- -y
curl -sSf https://sh.rustup.rs | sh -s -- -y
export PATH="$HOME/.cargo/bin:$PATH"
cargo --version
- run:
@ -150,6 +150,11 @@ jobs:
- image: circleci/rust:latest
steps:
- checkout
- run:
name: "Pull dependencies"
command: |
git submodule init
git submodule update --remote
- restore_cache:
keys:
- v8-cargo-cache-linux-nightly-{{ arch }}-{{ checksum "Cargo.lock" }}
@ -178,6 +183,7 @@ jobs:
command: |
export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04/"
make production-release
cargo build --release --manifest-path wapm-cli/Cargo.toml --features telemetry
mkdir -p artifacts
VERSION=$(cargo pkgid | cut -d# -f2 | cut -d: -f2)
# GIT_VERSION=$(git describe --exact-match --tags)
@ -202,6 +208,9 @@ jobs:
- target/release/.fingerprint
- target/release/build
- target/release/deps
- wapm-cli/target/release/.fingerprint
- wapm-cli/target/release/build
- wapm-cli/target/release/deps
key: v8-cargo-cache-linux-nightly-{{ arch }}-{{ checksum "Cargo.lock" }}
test-and-build-macos:
@ -209,6 +218,11 @@ jobs:
xcode: "9.0"
steps:
- checkout
- run:
name: "Pull dependencies"
command: |
git submodule init
git submodule update --remote
- restore_cache:
keys:
- v8-cargo-cache-darwin-nightly-{{ arch }}-{{ checksum "Cargo.lock" }}
@ -226,7 +240,7 @@ jobs:
- run:
name: Install Rust
command: |
curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain nightly-2019-04-11
curl -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain nightly
export PATH="$HOME/.cargo/bin:$PATH"
cargo --version
# Use rust nightly (for singlepass, for now)
@ -263,6 +277,7 @@ jobs:
export PATH="$HOME/.cargo/bin:$PATH"
export LLVM_SYS_70_PREFIX="`pwd`/clang+llvm-7.0.0-x86_64-apple-darwin/"
make production-release
cargo build --release --manifest-path wapm-cli/Cargo.toml --features telemetry
mkdir -p artifacts
make build-install
cp ./wasmer.tar.gz ./artifacts/$(./binary-name.sh)
@ -281,6 +296,9 @@ jobs:
- target/release/.fingerprint
- target/release/build
- target/release/deps
- wapm-cli/target/release/.fingerprint
- wapm-cli/target/release/build
- wapm-cli/target/release/deps
key: v8-cargo-cache-darwin-nightly-{ arch }}-{{ checksum "Cargo.lock" }}
test-rust-nightly:

3
.gitmodules vendored Normal file
View File

@ -0,0 +1,3 @@
[submodule "wapm-cli"]
path = wapm-cli
url = https://github.com/wasmerio/wapm-cli.git

View File

@ -5,6 +5,18 @@ All PRs to the Wasmer repository must add to this file.
Blocks of changes will separated by version increments.
## **[Unreleased]**
- [#409](https://github.com/wasmerio/wasmer/pull/409) Improved Emscripten functions to run JavascriptCore compiled to wasm
- [#399](https://github.com/wasmerio/wasmer/pull/399) Add example of using a plugin extended from WASI
- [#397](https://github.com/wasmerio/wasmer/pull/397) Fix WASI fs abstraction to work on Windows
- [#390](https://github.com/wasmerio/wasmer/pull/390) Pin released wapm version and add it as a git submodule
- [#408](https://github.com/wasmerio/wasmer/pull/408) Add images to windows installer and update installer to add wapm bin directory to path
## 0.4.0 - 2018-04-23
- [#383](https://github.com/wasmerio/wasmer/pull/383) Hook up wasi exit code to wasmer cli.
- [#382](https://github.com/wasmerio/wasmer/pull/382) Improve error message on `--backend` flag to only suggest currently enabled backends
- [#381](https://github.com/wasmerio/wasmer/pull/381) Allow retrieving propagated user errors.
- [#379](https://github.com/wasmerio/wasmer/pull/379) Fix small return types from imported functions.
- [#371](https://github.com/wasmerio/wasmer/pull/371) Add more Debug impl for WASI types
- [#368](https://github.com/wasmerio/wasmer/pull/368) Fix issue with write buffering
- [#343](https://github.com/wasmerio/wasmer/pull/343) Implement preopened files for WASI and fix aligment issue when accessing WASI memory
@ -16,3 +28,17 @@ Blocks of changes will separated by version increments.
- [#351](https://github.com/wasmerio/wasmer/pull/351) Add hidden option to specify wasm program name (can be used to improve error messages)
- [#350](https://github.com/wasmerio/wasmer/pull/350) Enforce that CHANGELOG.md is updated through CI.
- [#349](https://github.com/wasmerio/wasmer/pull/349) Add [CHANGELOG.md](https://github.com/wasmerio/wasmer/blob/master/CHANGELOG.md).
## 0.3.0 - 2018-04-12
- [#276](https://github.com/wasmerio/wasmer/pull/276) [#288](https://github.com/wasmerio/wasmer/pull/288) [#344](https://github.com/wasmerio/wasmer/pull/344) Use new singlepass backend (with the `--backend=singlepass` when running Wasmer)
- [#338](https://github.com/wasmerio/wasmer/pull/338) Actually catch traps/panics/etc when using a typed func.
- [#325](https://github.com/wasmerio/wasmer/pull/325) Fixed func_index in debug mode
- [#323](https://github.com/wasmerio/wasmer/pull/323) Add validate subcommand to validate Wasm files
- [#321](https://github.com/wasmerio/wasmer/pull/321) Upgrade to Cranelift 0.3.0
- [#319](https://github.com/wasmerio/wasmer/pull/319) Add Export and GlobalDescriptor to Runtime API
- [#310](https://github.com/wasmerio/wasmer/pull/310) Cleanup warnings
- [#299](https://github.com/wasmerio/wasmer/pull/299) [#300](https://github.com/wasmerio/wasmer/pull/300) [#301](https://github.com/wasmerio/wasmer/pull/301) [#303](https://github.com/wasmerio/wasmer/pull/303) [#304](https://github.com/wasmerio/wasmer/pull/304) [#305](https://github.com/wasmerio/wasmer/pull/305) [#306](https://github.com/wasmerio/wasmer/pull/306) [#307](https://github.com/wasmerio/wasmer/pull/307) Add support for WASI 🎉
- [#286](https://github.com/wasmerio/wasmer/pull/286) Add extend to imports
- [#278](https://github.com/wasmerio/wasmer/pull/278) Add versioning to cache
- [#250](https://github.com/wasmerio/wasmer/pull/250) Setup bors

27
Cargo.lock generated
View File

@ -1317,6 +1317,10 @@ name = "plain"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "plugin-for-example"
version = "0.1.0"
[[package]]
name = "podio"
version = "0.1.6"
@ -2222,7 +2226,7 @@ dependencies = [
[[package]]
name = "wasmer"
version = "0.3.0"
version = "0.4.0"
dependencies = [
"errno 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
"glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2260,7 +2264,7 @@ dependencies = [
"target-lexicon 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"wasmer-runtime-core 0.3.0",
"wasmer-win-exception-handler 0.3.0",
"wasmparser 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)",
"wasmparser 0.29.2 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -2299,7 +2303,7 @@ dependencies = [
"smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)",
"wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)",
"wasmer-runtime-core 0.3.0",
"wasmparser 0.28.0 (registry+https://github.com/rust-lang/crates.io-index)",
"wasmparser 0.29.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -2327,7 +2331,7 @@ dependencies = [
"tar 0.4.22 (registry+https://github.com/rust-lang/crates.io-index)",
"tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"wasmer-runtime-core 0.3.0",
"wasmparser 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)",
"wasmparser 0.29.2 (registry+https://github.com/rust-lang/crates.io-index)",
"zbox 0.6.1 (git+https://github.com/wasmerio/zbox?branch=bundle-libsodium)",
"zstd 0.4.22+zstd.1.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -2381,7 +2385,7 @@ dependencies = [
"nix 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)",
"wasmer-runtime-core 0.3.0",
"wasmparser 0.28.0 (registry+https://github.com/rust-lang/crates.io-index)",
"wasmparser 0.29.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -2406,7 +2410,6 @@ dependencies = [
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
"wasmer-runtime-core 0.3.0",
"zbox 0.6.1 (git+https://github.com/wasmerio/zbox?branch=bundle-libsodium)",
]
[[package]]
@ -2421,16 +2424,6 @@ dependencies = [
"winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "wasmparser"
version = "0.23.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "wasmparser"
version = "0.28.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "wasmparser"
version = "0.29.2"
@ -2824,8 +2817,6 @@ dependencies = [
"checksum wabt-sys 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a6265b25719e82598d104b3717375e37661d41753e2c84cde3f51050c7ed7e3c"
"checksum walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9d9d7ed3431229a144296213105a390676cc49c9b6a72bd19f3176c98e129fa1"
"checksum want 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "797464475f30ddb8830cc529aaaae648d581f99e2036a928877dfde027ddf6b3"
"checksum wasmparser 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b5e01c420bc7d36e778bd242e1167b079562ba8b34087122cc9057187026d060"
"checksum wasmparser 0.28.0 (registry+https://github.com/rust-lang/crates.io-index)" = "40f426b1929bd26517fb10702e2a8e520d1845c49567aa4d244f426f10b206c1"
"checksum wasmparser 0.29.2 (registry+https://github.com/rust-lang/crates.io-index)" = "981a8797cf89762e0233ec45fae731cb79a4dfaee12d9f0fe6cee01e4ac58d00"
"checksum which 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b57acb10231b9493c8472b20cb57317d0679a49e0bdbee44b3b803a6473af164"
"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"

View File

@ -1,6 +1,6 @@
[package]
name = "wasmer"
version = "0.3.0"
version = "0.4.0"
authors = ["The Wasmer Engineering Team <engineering@wasmer.io>"]
edition = "2018"
repository = "https://github.com/wasmerio/wasmer"
@ -33,7 +33,7 @@ wasmer-llvm-backend = { path = "lib/llvm-backend", optional = true }
wasmer-wasi = { path = "lib/wasi", optional = true }
[workspace]
members = ["lib/clif-backend", "lib/singlepass-backend", "lib/runtime", "lib/runtime-abi", "lib/runtime-core", "lib/emscripten", "lib/spectests", "lib/win-exception-handler", "lib/runtime-c-api", "lib/llvm-backend", "lib/wasi"]
members = ["lib/clif-backend", "lib/singlepass-backend", "lib/runtime", "lib/runtime-abi", "lib/runtime-core", "lib/emscripten", "lib/spectests", "lib/win-exception-handler", "lib/runtime-c-api", "lib/llvm-backend", "lib/wasi", "examples/plugin-for-example"]
[build-dependencies]
wabt = "0.7.2"
@ -49,3 +49,7 @@ fast-tests = []
"backend:singlepass" = ["wasmer-singlepass-backend"]
wasi = ["wasmer-wasi"]
vfs = ["wasmer-runtime-abi"]
[[example]]
name = "plugin"
crate-type = ["bin"]

View File

@ -25,6 +25,7 @@ integration-tests: release
echo "Running Integration Tests"
./integration_tests/lua/test.sh
./integration_tests/nginx/test.sh
./integration_tests/cowsay/test.sh
lint:
cargo fmt --all -- --check
@ -34,8 +35,9 @@ precommit: lint test
build-install:
mkdir -p ./install/bin
cp ./wapm-cli/target/release/wapm ./install/bin/
cp ./target/release/wasmer ./install/bin/
tar -C ./install -zcvf wasmer.tar.gz bin/wasmer
tar -C ./install -zcvf wasmer.tar.gz bin/wapm bin/wasmer
# For installing the contents locally
do-install:

View File

@ -100,7 +100,7 @@ sudo port install cmake
#### Debian-based Linuxes
```sh
sudo apt install cmake
sudo apt install cmake pkg-config libssl-dev
```
#### FreeBSD
@ -181,7 +181,7 @@ Below are some of the goals of this project (in order of priority):
- [x] It should be 100% compatible with the [WebAssembly spec tests](https://github.com/wasmerio/wasmer/tree/master/lib/spectests/spectests)
- [x] It should be fast _(partially achieved)_
- [ ] Support WASI _(in the works)_
- [x] Support WASI - released in [0.3.0](https://github.com/wasmerio/wasmer/releases/tag/0.3.0)
- [ ] Support Emscripten calls _(in the works)_
- [ ] Support Rust ABI calls
- [ ] Support Go ABI calls

BIN
examples/cowsay.wasm Executable file

Binary file not shown.

11
examples/exit.wat Normal file
View File

@ -0,0 +1,11 @@
(module
(import "wasi_unstable" "proc_exit" (func $proc_exit (param i32)))
(export "_start" (func $_start))
(memory 10)
(export "memory" (memory 0))
(func $_start
(call $proc_exit (i32.const 7))
)
)

BIN
examples/plugin-for-example.wasm Executable file

Binary file not shown.

View File

@ -0,0 +1,7 @@
[package]
name = "plugin-for-example"
version = "0.1.0"
authors = ["The Wasmer Engineering Team <enigneering@wasmer.io>"]
edition = "2018"
[dependencies]

View File

@ -0,0 +1,43 @@
# WASI plugin example
In this example we extend the imports of Wasmer's WASI ABI to demonstrate how custom plugins work.
See the `wasmer/examples/plugin.rs` file for the source code of the host system.
## Compiling
_Attention Windows users: WASI target only works with the `nightly-x86_64-pc-windows-gnu` toolchain._
```
# Install an up to date version of Rust nightly
# Add the target
rustup target add wasm32-unknown-wasi
# build it
cargo +nightly build --release --target=wasm32-unknown-wasi
# copy it to examples folder
cp ../../target/wasm32-unknown-wasi/release/plugin-for-example.wasm ../
```
## Running
```
# Go back to top level Wasmer dir
cd ..
# Run the example
cargo run --example plugin
```
## Inspecting the plugin
```
# Install wabt via wapm; installed globally with the `g` flag
wapm install -g wabt
# Turn the binary WASM file in to a readable WAT text file
wapm run wasm2wat examples/plugin-for-example.wasm
```
At the top of the file we can see which functions this plugin expects. Most are covered by WASI, but we handle the rest.
## Explanation
In this example, we instantiate a system with an extended (WASI)[wasi] ABI, allowing our program to rely on Wasmer's implementation of the syscalls defined by WASI as well as our own that we made. This allows us to use the full power of an existing ABI, like WASI, and give it super-powers for our specific use case.
Because the Rust WASI doesn't support the crate type of `cdylib`, we have to include a main function which we don't use. This is being discussed [here](https://github.com/WebAssembly/WASI/issues/24).
[wasi]: https://hacks.mozilla.org/2019/03/standardizing-wasi-a-webassembly-system-interface/

View File

@ -0,0 +1,12 @@
extern "C" {
fn it_works() -> i32;
}
#[no_mangle]
pub fn plugin_entrypoint(n: i32) -> i32 {
println!("Hello from inside WASI");
let result = unsafe { it_works() };
result + n
}
pub fn main() {}

View File

@ -0,0 +1,12 @@
[package]
name = "plugin-for-example"
version = "0.1.0"
description = "A plugin for our example system"
readme = "README.md"
repository = "https://github.com/wasmerio/wasmer/examples/plugin-for-example"
license = "MIT"
[[module]]
name = "plugin-for-example"
source = "../../target/wasm32-unknown-wasi/release/plugin-for-example.wasm"
abi = "none"

38
examples/plugin.rs Normal file
View File

@ -0,0 +1,38 @@
use wasmer_runtime::{func, imports, instantiate};
use wasmer_runtime_core::vm::Ctx;
use wasmer_wasi::generate_import_object;
static PLUGIN_LOCATION: &'static str = "examples/plugin-for-example.wasm";
fn it_works(_ctx: &mut Ctx) -> i32 {
println!("Hello from outside WASI");
5
}
fn main() {
// Load the plugin data
let wasm_bytes = std::fs::read(PLUGIN_LOCATION).expect(&format!(
"Could not read in WASM plugin at {}",
PLUGIN_LOCATION
));
// WASI imports
let mut base_imports = generate_import_object(vec![], vec![], vec![]);
// env is the default namespace for extern functions
let custom_imports = imports! {
"env" => {
"it_works" => func!(it_works),
},
};
// The WASI imports object contains all required import functions for a WASI module to run.
// Extend this imports with our custom imports containing "it_works" function so that our custom wasm code may run.
base_imports.extend(custom_imports);
let instance =
instantiate(&wasm_bytes[..], &base_imports).expect("failed to instantiate wasm module");
// get a reference to the function "plugin_entrypoint" which takes an i32 and returns an i32
let entry_point = instance.func::<(i32), i32>("plugin_entrypoint").unwrap();
// call the "entry_point" function in WebAssembly with the number "2" as the i32 argument
let result = entry_point.call(2).expect("failed to execute plugin");
println!("result: {}", result);
}

View File

@ -131,7 +131,7 @@ wasmer_link() {
printf "$cyan> Adding to bash profile...$reset\n"
WASMER_PROFILE="$(wasmer_detect_profile)"
LOAD_STR="\n# Wasmer\nexport WASMER_DIR=\"\$HOME/.wasmer\"\n[ -s \"\$WASMER_DIR/wasmer.sh\" ] && source \"\$WASMER_DIR/wasmer.sh\" # This loads wasmer\n"
SOURCE_STR="# Wasmer config\nexport WASMER_DIR=\"\$HOME/.wasmer\"\nexport WASMER_CACHE_DIR=\"\$WASMER_DIR/cache\"\nexport PATH=\"\$HOME/.wasmer/bin:\$PATH\"\n"
SOURCE_STR="# Wasmer config\nexport WASMER_DIR=\"\$HOME/.wasmer\"\nexport WASMER_CACHE_DIR=\"\$WASMER_DIR/cache\"\nexport PATH=\"\$HOME/.wasmer/bin:\$HOME/.wasmer/globals/wapm_packages/.bin:\$PATH\"\n"
# We create the wasmer.sh file
printf "$SOURCE_STR" > "$HOME/.wasmer/wasmer.sh"
@ -162,7 +162,9 @@ wasmer_link() {
)
printf "$green> Successfully installed $version!\n\n${reset}If you want to have the command available now please execute:\nsource $HOME/.wasmer/wasmer.sh$reset\n"
printf "\nOtherwise, wasmer will be available the next time you open the terminal.\n"
printf "\nOtherwise, wasmer and wapm will be available the next time you open the terminal.\n"
echo "Note: during the alpha release of wapm, telemetry is enabled by default; if you would like to opt out, run \`wapm config set telemetry.enabled false\`."
echo "If you notice anything wrong or have any issues, please file a bug at https://github.com/wasmerio/wapm-cli :)"
fi
}
@ -292,7 +294,6 @@ wasmer_install() {
# exit 0
# fi
# fi
wasmer_download # $1 $2
wasmer_link
wasmer_reset

View File

@ -0,0 +1,9 @@
# `cowsay` integration test
This starts Wasmer with the Cowsay WASI Wasm file. The test makes assertions on
the output of Wasmer. Run test with:
```bash
./integration_tests/cowsay/test.sh
```

View File

@ -0,0 +1,14 @@
#! /bin/bash
nohup ./target/release/wasmer run examples/cowsay.wasm --disable-cache -- "hello integration"
if grep "hello integration" ./nohup.out
then
echo "cowsay wasi integration test succeeded"
rm ./nohup.out
exit 0
else
echo "cowsay wasi integration test failed"
rm ./nohup.out
exit -1
fi

View File

@ -15,7 +15,7 @@ cranelift-entity = "0.30.0"
cranelift-wasm = "0.30.0"
hashbrown = "0.1"
target-lexicon = "0.3.0"
wasmparser = "0.23.0"
wasmparser = "0.29.2"
byteorder = "1"
nix = "0.13.0"
libc = "0.2.49"

View File

@ -5,7 +5,7 @@ use std::sync::Arc;
use wasmer_runtime_core::{
backend::{sys::Memory, CacheGen},
cache::{Artifact, Error},
module::{ModuleInfo, ModuleInner},
module::ModuleInfo,
structures::Map,
types::{LocalFuncIndex, SigIndex},
};

View File

@ -27,6 +27,11 @@ thread_local! {
pub static TRAP_EARLY_DATA: Cell<Option<Box<dyn Any>>> = Cell::new(None);
}
pub enum CallProtError {
Trap(WasmTrapInfo),
Error(Box<dyn Any>),
}
pub struct Caller {
handler_data: HandlerData,
trampolines: Arc<Trampolines>,
@ -59,7 +64,8 @@ impl RunnableModule for Caller {
func: NonNull<vm::Func>,
args: *const u64,
rets: *mut u64,
_trap_info: *mut WasmTrapInfo,
trap_info: *mut WasmTrapInfo,
user_error: *mut Option<Box<dyn Any>>,
invoke_env: Option<NonNull<c_void>>,
) -> bool {
let handler_data = &*invoke_env.unwrap().cast().as_ptr();
@ -68,14 +74,22 @@ impl RunnableModule for Caller {
let res = call_protected(handler_data, || {
// Leap of faith.
trampoline(ctx, func, args, rets);
})
.is_ok();
});
// the trampoline is called from C on windows
#[cfg(target_os = "windows")]
let res = call_protected(handler_data, trampoline, ctx, func, args, rets).is_ok();
let res = call_protected(handler_data, trampoline, ctx, func, args, rets);
res
match res {
Err(err) => {
match err {
CallProtError::Trap(info) => *trap_info = info,
CallProtError::Error(data) => *user_error = Some(data),
}
false
}
Ok(()) => true,
}
}
let trampoline = self

View File

@ -10,7 +10,7 @@
//! unless you have memory unsafety elsewhere in your code.
//!
use crate::relocation::{TrapCode, TrapData};
use crate::signal::HandlerData;
use crate::signal::{CallProtError, HandlerData};
use libc::{c_int, c_void, siginfo_t};
use nix::sys::signal::{
sigaction, SaFlags, SigAction, SigHandler, SigSet, Signal, SIGBUS, SIGFPE, SIGILL, SIGSEGV,
@ -18,7 +18,7 @@ use nix::sys::signal::{
use std::cell::{Cell, UnsafeCell};
use std::ptr;
use std::sync::Once;
use wasmer_runtime_core::error::{RuntimeError, RuntimeResult};
use wasmer_runtime_core::typed_func::WasmTrapInfo;
extern "C" fn signal_trap_handler(
signum: ::nix::libc::c_int,
@ -62,7 +62,10 @@ pub unsafe fn trigger_trap() -> ! {
longjmp(jmp_buf as *mut c_void, 0)
}
pub fn call_protected<T>(handler_data: &HandlerData, f: impl FnOnce() -> T) -> RuntimeResult<T> {
pub fn call_protected<T>(
handler_data: &HandlerData,
f: impl FnOnce() -> T,
) -> Result<T, CallProtError> {
unsafe {
let jmp_buf = SETJMP_BUFFER.with(|buf| buf.get());
let prev_jmp_buf = *jmp_buf;
@ -76,7 +79,7 @@ pub fn call_protected<T>(handler_data: &HandlerData, f: impl FnOnce() -> T) -> R
*jmp_buf = prev_jmp_buf;
if let Some(data) = super::TRAP_EARLY_DATA.with(|cell| cell.replace(None)) {
Err(RuntimeError::Panic { data })
Err(CallProtError::Error(data))
} else {
let (faulting_addr, inst_ptr) = CAUGHT_ADDRESSES.with(|cell| cell.get());
@ -85,33 +88,18 @@ pub fn call_protected<T>(handler_data: &HandlerData, f: impl FnOnce() -> T) -> R
srcloc: _,
}) = handler_data.lookup(inst_ptr)
{
Err(match Signal::from_c_int(signum) {
Err(CallProtError::Trap(match Signal::from_c_int(signum) {
Ok(SIGILL) => match trapcode {
TrapCode::BadSignature => RuntimeError::Trap {
msg: "incorrect call_indirect signature".into(),
},
TrapCode::IndirectCallToNull => RuntimeError::Trap {
msg: "indirect call to null".into(),
},
TrapCode::HeapOutOfBounds => RuntimeError::Trap {
msg: "memory out-of-bounds access".into(),
},
TrapCode::TableOutOfBounds => RuntimeError::Trap {
msg: "table out-of-bounds access".into(),
},
_ => RuntimeError::Trap {
msg: "unknown trap".into(),
},
},
Ok(SIGSEGV) | Ok(SIGBUS) => RuntimeError::Trap {
msg: "memory out-of-bounds access".into(),
},
Ok(SIGFPE) => RuntimeError::Trap {
msg: "illegal arithmetic operation".into(),
TrapCode::BadSignature => WasmTrapInfo::IncorrectCallIndirectSignature,
TrapCode::IndirectCallToNull => WasmTrapInfo::CallIndirectOOB,
TrapCode::HeapOutOfBounds => WasmTrapInfo::MemoryOutOfBounds,
TrapCode::TableOutOfBounds => WasmTrapInfo::CallIndirectOOB,
_ => WasmTrapInfo::Unknown,
},
Ok(SIGSEGV) | Ok(SIGBUS) => WasmTrapInfo::MemoryOutOfBounds,
Ok(SIGFPE) => WasmTrapInfo::IllegalArithmetic,
_ => unimplemented!(),
}
.into())
}))
} else {
let signal = match Signal::from_c_int(signum) {
Ok(SIGFPE) => "floating-point exception",
@ -122,10 +110,8 @@ pub fn call_protected<T>(handler_data: &HandlerData, f: impl FnOnce() -> T) -> R
_ => "unkown trapped signal",
};
// When the trap-handler is fully implemented, this will return more information.
Err(RuntimeError::Trap {
msg: format!("unknown trap at {:p} - {}", faulting_addr, signal).into(),
}
.into())
let s = format!("unknown trap at {:p} - {}", faulting_addr, signal);
Err(CallProtError::Error(Box::new(s)))
}
}
} else {

View File

@ -1,10 +1,11 @@
use crate::relocation::{TrapCode, TrapData};
use crate::signal::HandlerData;
use crate::signal::{CallProtError, HandlerData};
use crate::trampoline::Trampoline;
use std::cell::Cell;
use std::ffi::c_void;
use std::ptr::{self, NonNull};
use wasmer_runtime_core::error::{RuntimeError, RuntimeResult};
use wasmer_runtime_core::typed_func::WasmTrapInfo;
use wasmer_runtime_core::vm::Ctx;
use wasmer_runtime_core::vm::Func;
use wasmer_win_exception_handler::CallProtectedData;
@ -28,7 +29,7 @@ pub fn call_protected(
func: NonNull<Func>,
param_vec: *const u64,
return_vec: *mut u64,
) -> RuntimeResult<()> {
) -> Result<(), CallProtError> {
// TODO: trap early
// user code error
// if let Some(msg) = super::TRAP_EARLY_DATA.with(|cell| cell.replace(None)) {
@ -52,38 +53,22 @@ pub fn call_protected(
srcloc: _,
}) = handler_data.lookup(instruction_pointer as _)
{
Err(match signum as DWORD {
EXCEPTION_ACCESS_VIOLATION => RuntimeError::Trap {
msg: "memory out-of-bounds access".into(),
},
Err(CallProtError::Trap(match signum as DWORD {
EXCEPTION_ACCESS_VIOLATION => WasmTrapInfo::MemoryOutOfBounds,
EXCEPTION_ILLEGAL_INSTRUCTION => match trapcode {
TrapCode::BadSignature => RuntimeError::Trap {
msg: "incorrect call_indirect signature".into(),
},
TrapCode::IndirectCallToNull => RuntimeError::Trap {
msg: "indirect call to null".into(),
},
TrapCode::HeapOutOfBounds => RuntimeError::Trap {
msg: "memory out-of-bounds access".into(),
},
TrapCode::TableOutOfBounds => RuntimeError::Trap {
msg: "table out-of-bounds access".into(),
},
_ => RuntimeError::Trap {
msg: "unknown trap".into(),
},
},
EXCEPTION_STACK_OVERFLOW => RuntimeError::Trap {
msg: "stack overflow trap".into(),
},
EXCEPTION_INT_DIVIDE_BY_ZERO | EXCEPTION_INT_OVERFLOW => RuntimeError::Trap {
msg: "illegal arithmetic operation".into(),
},
_ => RuntimeError::Trap {
msg: "unknown trap".into(),
TrapCode::BadSignature => WasmTrapInfo::IncorrectCallIndirectSignature,
TrapCode::IndirectCallToNull => WasmTrapInfo::CallIndirectOOB,
TrapCode::HeapOutOfBounds => WasmTrapInfo::MemoryOutOfBounds,
TrapCode::TableOutOfBounds => WasmTrapInfo::CallIndirectOOB,
TrapCode::UnreachableCodeReached => WasmTrapInfo::Unreachable,
_ => WasmTrapInfo::Unknown,
},
EXCEPTION_STACK_OVERFLOW => WasmTrapInfo::Unknown,
EXCEPTION_INT_DIVIDE_BY_ZERO | EXCEPTION_INT_OVERFLOW => {
WasmTrapInfo::IllegalArithmetic
}
.into())
_ => WasmTrapInfo::Unknown,
}))
} else {
let signal = match signum as DWORD {
EXCEPTION_FLT_DENORMAL_OPERAND
@ -98,10 +83,9 @@ pub fn call_protected(
_ => "unkown trapped signal",
};
Err(RuntimeError::Trap {
msg: format!("unknown trap at {} - {}", exception_address, signal).into(),
}
.into())
let s = format!("unknown trap at {} - {}", exception_address, signal);
Err(CallProtError::Error(Box::new(s)))
}
}

View File

@ -15,6 +15,15 @@ pub fn getTempRet0(ctx: &mut Ctx) -> i32 {
get_emscripten_data(ctx).temp_ret_0
}
pub fn _atexit(_ctx: &mut Ctx, _func: i32) -> i32 {
debug!("emscripten::_atexit");
// TODO: implement atexit properly
// __ATEXIT__.unshift({
// func: func,
// arg: arg
// });
0
}
pub fn __Unwind_Backtrace(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 {
debug!("emscripten::__Unwind_Backtrace");
0
@ -45,14 +54,42 @@ pub fn _dladdr(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 {
debug!("emscripten::_dladdr");
0
}
pub fn _pthread_attr_init(_ctx: &mut Ctx, _a: i32) -> i32 {
debug!("emscripten::_pthread_attr_init");
0
}
pub fn _pthread_attr_destroy(_ctx: &mut Ctx, _a: i32) -> i32 {
debug!("emscripten::_pthread_attr_destroy");
0
}
pub fn _pthread_attr_getstack(
_ctx: &mut Ctx,
_stackaddr: i32,
_stacksize: i32,
_other: i32,
) -> i32 {
debug!("emscripten::_pthread_attr_getstack");
// TODO: Translate from Emscripten
// HEAP32[stackaddr >> 2] = STACK_BASE;
// HEAP32[stacksize >> 2] = TOTAL_STACK;
0
}
pub fn _pthread_cond_destroy(_ctx: &mut Ctx, _a: i32) -> i32 {
debug!("emscripten::_pthread_cond_destroy");
0
}
pub fn _pthread_cond_timedwait(_ctx: &mut Ctx, _a: i32, _b: i32, _c: i32) -> i32 {
debug!("emscripten::_pthread_cond_timedwait");
0
}
pub fn _pthread_getspecific(_ctx: &mut Ctx, _a: i32) -> i32 {
debug!("emscripten::_pthread_getspecific");
0
}
pub fn _pthread_getattr_np(_ctx: &mut Ctx, _thread: i32, _attr: i32) -> i32 {
debug!("emscripten::_pthread_getattr_np");
0
}
pub fn _pthread_setspecific(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 {
debug!("emscripten::_pthread_setspecific");
0
@ -69,6 +106,10 @@ pub fn _pthread_create(_ctx: &mut Ctx, _a: i32, _b: i32, _c: i32, _d: i32) -> i3
debug!("emscripten::_pthread_create");
0
}
pub fn _pthread_detach(_ctx: &mut Ctx, _a: i32) -> i32 {
debug!("emscripten::_pthread_detach");
0
}
pub fn _pthread_join(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 {
debug!("emscripten::_pthread_join");
0

View File

@ -28,3 +28,9 @@ pub fn ___cxa_uncaught_exception(_ctx: &mut Ctx) -> i32 {
debug!("emscripten::___cxa_uncaught_exception");
-1
}
pub fn ___cxa_pure_virtual(_ctx: &mut Ctx) {
debug!("emscripten::___cxa_pure_virtual");
// ABORT = true
panic!("Pure virtual function called!");
}

View File

@ -619,6 +619,7 @@ pub fn generate_emscripten_env(globals: &mut EmscriptenGlobals) -> ImportObject
"_llvm_eh_typeid_for" => func!(crate::process::_llvm_eh_typeid_for),
"_raise" => func!(crate::process::_raise),
"_sem_init" => func!(crate::process::_sem_init),
"_sem_destroy" => func!(crate::process::_sem_destroy),
"_sem_post" => func!(crate::process::_sem_post),
"_sem_wait" => func!(crate::process::_sem_wait),
"_getgrent" => func!(crate::process::_getgrent),
@ -646,6 +647,9 @@ pub fn generate_emscripten_env(globals: &mut EmscriptenGlobals) -> ImportObject
"_emscripten_get_heap_size" => func!(crate::memory::_emscripten_get_heap_size),
"_emscripten_resize_heap" => func!(crate::memory::_emscripten_resize_heap),
"enlargeMemory" => func!(crate::memory::enlarge_memory),
"segfault" => func!(crate::memory::segfault),
"alignfault" => func!(crate::memory::alignfault),
"ftfault" => func!(crate::memory::ftfault),
"getTotalMemory" => func!(crate::memory::get_total_memory),
"___map_file" => func!(crate::memory::___map_file),
@ -655,6 +659,7 @@ pub fn generate_emscripten_env(globals: &mut EmscriptenGlobals) -> ImportObject
"___cxa_begin_catch" => func!(crate::exception::___cxa_begin_catch),
"___cxa_end_catch" => func!(crate::exception::___cxa_end_catch),
"___cxa_uncaught_exception" => func!(crate::exception::___cxa_uncaught_exception),
"___cxa_pure_virtual" => func!(crate::exception::___cxa_pure_virtual),
// Time
"_gettimeofday" => func!(crate::time::_gettimeofday),
@ -683,6 +688,7 @@ pub fn generate_emscripten_env(globals: &mut EmscriptenGlobals) -> ImportObject
"_llvm_cos_f64" => func!(crate::math::_llvm_cos_f64),
"_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),
"_emscripten_random" => func!(crate::math::_emscripten_random),
// Jump
@ -701,6 +707,7 @@ pub fn generate_emscripten_env(globals: &mut EmscriptenGlobals) -> ImportObject
"_dlsym" => func!(crate::linking::_dlsym),
// wasm32-unknown-emscripten
"_atexit" => func!(crate::emscripten_target::_atexit),
"setTempRet0" => func!(crate::emscripten_target::setTempRet0),
"getTempRet0" => func!(crate::emscripten_target::getTempRet0),
"invoke_i" => func!(crate::emscripten_target::invoke_i),
@ -723,10 +730,15 @@ pub fn generate_emscripten_env(globals: &mut EmscriptenGlobals) -> ImportObject
"___resumeException" => func!(crate::emscripten_target::___resumeException),
"_dladdr" => func!(crate::emscripten_target::_dladdr),
"_pthread_create" => func!(crate::emscripten_target::_pthread_create),
"_pthread_detach" => func!(crate::emscripten_target::_pthread_detach),
"_pthread_join" => func!(crate::emscripten_target::_pthread_join),
"_pthread_cond_destroy" => func!(crate::emscripten_target::_pthread_cond_destroy),
"_pthread_attr_init" => func!(crate::emscripten_target::_pthread_attr_init),
"_pthread_attr_destroy" => func!(crate::emscripten_target::_pthread_attr_destroy),
"_pthread_attr_getstack" => func!(crate::emscripten_target::_pthread_attr_getstack),
"_pthread_cond_init" => func!(crate::emscripten_target::_pthread_cond_init),
"_pthread_cond_destroy" => func!(crate::emscripten_target::_pthread_cond_destroy),
"_pthread_cond_signal" => func!(crate::emscripten_target::_pthread_cond_signal),
"_pthread_cond_timedwait" => func!(crate::emscripten_target::_pthread_cond_timedwait),
"_pthread_cond_wait" => func!(crate::emscripten_target::_pthread_cond_wait),
"_pthread_condattr_destroy" => func!(crate::emscripten_target::_pthread_condattr_destroy),
"_pthread_condattr_init" => func!(crate::emscripten_target::_pthread_condattr_init),
@ -740,6 +752,7 @@ pub fn generate_emscripten_env(globals: &mut EmscriptenGlobals) -> ImportObject
"_pthread_rwlock_unlock" => func!(crate::emscripten_target::_pthread_rwlock_unlock),
"_pthread_setcancelstate" => func!(crate::emscripten_target::_pthread_setcancelstate),
"_pthread_getspecific" => func!(crate::emscripten_target::_pthread_getspecific),
"_pthread_getattr_np" => func!(crate::emscripten_target::_pthread_getattr_np),
"_pthread_setspecific" => func!(crate::emscripten_target::_pthread_setspecific),
"_pthread_once" => func!(crate::emscripten_target::_pthread_once),
"_pthread_key_create" => func!(crate::emscripten_target::_pthread_key_create),

View File

@ -44,6 +44,11 @@ pub fn _llvm_exp2_f64(_ctx: &mut Ctx, value: f64) -> f64 {
2f64.powf(value)
}
pub fn _llvm_trunc_f64(_ctx: &mut Ctx, value: f64) -> f64 {
debug!("emscripten::_llvm_trunc_f64");
value.trunc()
}
pub fn _emscripten_random(_ctx: &mut Ctx) -> f64 {
debug!("emscripten::_emscripten_random");
-1.0

View File

@ -95,6 +95,24 @@ pub fn abort_on_cannot_grow_memory_old(ctx: &mut Ctx) -> u32 {
0
}
/// emscripten: segfault
pub fn segfault(ctx: &mut Ctx) {
debug!("emscripten::segfault");
abort_with_message(ctx, "segmentation fault");
}
/// emscripten: alignfault
pub fn alignfault(ctx: &mut Ctx) {
debug!("emscripten::alignfault");
abort_with_message(ctx, "alignment fault");
}
/// emscripten: ftfault
pub fn ftfault(ctx: &mut Ctx) {
debug!("emscripten::ftfault");
abort_with_message(ctx, "Function table mask error");
}
/// emscripten: ___map_file
pub fn ___map_file(_ctx: &mut Ctx, _one: u32, _two: u32) -> c_int {
debug!("emscripten::___map_file");

View File

@ -83,7 +83,12 @@ pub fn _raise(_ctx: &mut Ctx, _one: i32) -> i32 {
pub fn _sem_init(_ctx: &mut Ctx, _one: i32, _two: i32, _three: i32) -> i32 {
debug!("emscripten::_sem_init");
-1
0
}
pub fn _sem_destroy(_ctx: &mut Ctx, _one: i32) -> i32 {
debug!("emscripten::_sem_destroy");
0
}
pub fn _sem_post(_ctx: &mut Ctx, _one: i32) -> i32 {
@ -159,7 +164,7 @@ pub fn _system(_ctx: &mut Ctx, _one: i32) -> c_int {
debug!("emscripten::_system");
// TODO: May need to change this Em impl to a working version
eprintln!("Can't call external programs");
return EAGAIN;
EAGAIN
}
pub fn _popen(_ctx: &mut Ctx, _one: i32, _two: i32) -> c_int {

View File

@ -345,7 +345,7 @@ pub fn _strftime(
// pad for null?
let bytes = result_str.chars().count();
if bytes as u32 > maxsize {
return 0;
0
} else {
// write output string
for (i, c) in result_str.chars().enumerate() {

View File

@ -1,8 +1,5 @@
use std::mem;
use wasmer_runtime_core::{
types::{Type, WasmExternType},
vm::Ctx,
};
use wasmer_runtime_core::{types::WasmExternType, vm::Ctx};
#[repr(transparent)]
#[derive(Copy, Clone)]
@ -19,12 +16,12 @@ impl VarArgs {
}
unsafe impl WasmExternType for VarArgs {
const TYPE: Type = Type::I32;
type Native = i32;
fn to_bits(self) -> u64 {
self.pointer as u64
fn to_native(self) -> Self::Native {
self.pointer as _
}
fn from_bits(n: u64) -> Self {
fn from_native(n: Self::Native) -> Self {
Self { pointer: n as u32 }
}
}

View File

@ -7,7 +7,7 @@ edition = "2018"
[dependencies]
wasmer-runtime-core = { path = "../runtime-core", version = "0.3.0" }
inkwell = { git = "https://github.com/wasmerio/inkwell", branch = "llvm7-0" }
wasmparser = "0.28.0"
wasmparser = "0.29.2"
hashbrown = "0.1.8"
smallvec = "0.6.8"
goblin = "0.0.20"

View File

@ -213,6 +213,8 @@ fn main() {
println!("cargo:rustc-link-lib=static=llvm-backend");
println!("cargo:rerun-if-changed=build.rs");
println!("cargo:rerun-if-changed=cpp/object_loader.cpp");
println!("cargo:rerun-if-changed=cpp/object_loader.hh");
// Enable "nightly" cfg if the current compiler is nightly.
if rustc_version::version_meta().unwrap().channel == rustc_version::Channel::Nightly {

View File

@ -43,6 +43,11 @@ typedef struct
visit_fde_t visit_fde;
} callbacks_t;
typedef struct
{
size_t data, vtable;
} box_any_t;
struct WasmException
{
public:
@ -61,7 +66,7 @@ struct UncatchableException : WasmException
struct UserException : UncatchableException
{
public:
UserException(size_t data, size_t vtable) : data(data), vtable(vtable) {}
UserException(size_t data, size_t vtable) : error_data({ data, vtable }) {}
virtual std::string description() const noexcept override
{
@ -69,7 +74,7 @@ struct UserException : UncatchableException
}
// The parts of a `Box<dyn Any>`.
size_t data, vtable;
box_any_t error_data;
};
struct WasmTrap : UncatchableException
@ -194,6 +199,7 @@ extern "C"
void *params,
void *results,
WasmTrap::Type *trap_out,
box_any_t *user_error,
void *invoke_env) throw()
{
try
@ -206,6 +212,11 @@ extern "C"
*trap_out = e.type;
return false;
}
catch (const UserException &e)
{
*user_error = e.error_data;
return false;
}
catch (const WasmException &e)
{
*trap_out = WasmTrap::Type::Unknown;

View File

@ -93,6 +93,7 @@ extern "C" {
params: *const u64,
results: *mut u64,
trap_out: *mut WasmTrapInfo,
user_error: *mut Option<Box<dyn Any>>,
invoke_env: Option<NonNull<c_void>>,
) -> bool;
}
@ -297,7 +298,7 @@ impl LLVMBackend {
let callbacks = get_callbacks();
let mut module: *mut LLVMModule = ptr::null_mut();
let slice = unsafe { memory.as_slice() };
let slice = memory.as_slice();
let res = module_load(slice.as_ptr(), slice.len(), callbacks, &mut module);
@ -307,7 +308,7 @@ impl LLVMBackend {
static SIGNAL_HANDLER_INSTALLED: Once = Once::new();
SIGNAL_HANDLER_INSTALLED.call_once(|| unsafe {
SIGNAL_HANDLER_INSTALLED.call_once(|| {
crate::platform::install_signal_handler();
});

View File

@ -1468,7 +1468,7 @@ fn parse_function(
context,
&function,
-2147483904.0,
2147483648.0,
2_147_483_648.0,
v1,
);
let res =
@ -1482,8 +1482,8 @@ fn parse_function(
intrinsics,
context,
&function,
-2147483649.0,
2147483648.0,
-2_147_483_649.0,
2_147_483_648.0,
v1,
);
let res =
@ -1503,8 +1503,8 @@ fn parse_function(
intrinsics,
context,
&function,
-9223373136366403584.0,
9223372036854775808.0,
-9_223_373_136_366_403_584.0,
9_223_372_036_854_775_808.0,
v1,
);
let res =

View File

@ -13,7 +13,7 @@ wasmer-runtime-core = { path = "../runtime-core" }
hashbrown = "0.1"
failure = "0.1"
tar = "0.4"
wasmparser = "0.23.0"
wasmparser = "0.29.2"
zstd = "0.4"
[target.'cfg(unix)'.dependencies.zbox]

View File

@ -1,4 +1,4 @@
use crate::types::{FuncSig, GlobalDescriptor, MemoryDescriptor, TableDescriptor, Type, Value};
use crate::types::{FuncSig, GlobalDescriptor, MemoryDescriptor, TableDescriptor, Type};
use core::borrow::Borrow;
use std::any::Any;
@ -121,8 +121,7 @@ impl std::error::Error for LinkError {}
/// Comparing two `RuntimeError`s always evaluates to false.
pub enum RuntimeError {
Trap { msg: Box<str> },
Exception { data: Box<[Value]> },
Panic { data: Box<dyn Any> },
Error { data: Box<dyn Any> },
}
impl PartialEq for RuntimeError {
@ -137,19 +136,14 @@ impl std::fmt::Display for RuntimeError {
RuntimeError::Trap { ref msg } => {
write!(f, "WebAssembly trap occured during runtime: {}", msg)
}
RuntimeError::Exception { ref data } => {
write!(f, "Uncaught WebAssembly exception: {:?}", data)
}
RuntimeError::Panic { data } => {
let msg = if let Some(s) = data.downcast_ref::<String>() {
s
RuntimeError::Error { data } => {
if let Some(s) = data.downcast_ref::<String>() {
write!(f, "\"{}\"", s)
} else if let Some(s) = data.downcast_ref::<&str>() {
s
write!(f, "\"{}\"", s)
} else {
"user-defined, opaque"
};
write!(f, "{}", msg)
write!(f, "unknown error")
}
}
}
}

View File

@ -528,6 +528,7 @@ fn call_func_with_index(
let run_wasm = |result_space: *mut u64| unsafe {
let mut trap_info = WasmTrapInfo::Unknown;
let mut user_error = None;
let success = invoke(
trampoline,
@ -536,16 +537,21 @@ fn call_func_with_index(
raw_args.as_ptr(),
result_space,
&mut trap_info,
&mut user_error,
invoke_env,
);
if success {
Ok(())
} else {
if let Some(data) = user_error {
Err(RuntimeError::Error { data })
} else {
Err(RuntimeError::Trap {
msg: trap_info.to_string().into(),
})
}
}
};
let raw_to_value = |raw, ty| match ty {
@ -651,10 +657,3 @@ impl<'a> DynFunc<'a> {
}
}
}
#[doc(hidden)]
impl Instance {
pub fn memory_offset_addr(&self, _: u32, _: usize) -> *const u8 {
unimplemented!()
}
}

View File

@ -2,11 +2,12 @@ use crate::{
error::RuntimeError,
export::{Context, Export, FuncPointer},
import::IsExport,
types::{FuncSig, Type, WasmExternType},
types::{FuncSig, NativeWasmType, Type, WasmExternType},
vm::{self, Ctx},
};
use std::{
any::Any,
convert::Infallible,
ffi::c_void,
fmt,
marker::PhantomData,
@ -57,6 +58,7 @@ pub type Invoke = unsafe extern "C" fn(
*const u64,
*mut u64,
*mut WasmTrapInfo,
*mut Option<Box<dyn Any>>,
Option<NonNull<c_void>>,
) -> bool;
@ -103,7 +105,7 @@ pub trait WasmTypeList {
f: NonNull<vm::Func>,
wasm: Wasm,
ctx: *mut Ctx,
) -> Result<Rets, WasmTrapInfo>
) -> Result<Rets, RuntimeError>
where
Rets: WasmTypeList;
}
@ -120,14 +122,16 @@ pub trait TrapEarly<Rets>
where
Rets: WasmTypeList,
{
fn report(self) -> Result<Rets, Box<dyn Any>>;
type Error: 'static;
fn report(self) -> Result<Rets, Self::Error>;
}
impl<Rets> TrapEarly<Rets> for Rets
where
Rets: WasmTypeList,
{
fn report(self) -> Result<Rets, Box<dyn Any>> {
type Error = Infallible;
fn report(self) -> Result<Rets, Infallible> {
Ok(self)
}
}
@ -135,10 +139,11 @@ where
impl<Rets, E> TrapEarly<Rets> for Result<Rets, E>
where
Rets: WasmTypeList,
E: Any,
E: 'static,
{
fn report(self) -> Result<Rets, Box<dyn Any>> {
self.map_err(|err| Box::new(err) as Box<dyn Any>)
type Error = E;
fn report(self) -> Result<Rets, E> {
self
}
}
@ -209,26 +214,57 @@ where
}
}
impl WasmTypeList for Infallible {
type CStruct = Infallible;
type RetArray = [u64; 0];
fn from_ret_array(_: Self::RetArray) -> Self {
unreachable!()
}
fn empty_ret_array() -> Self::RetArray {
unreachable!()
}
fn from_c_struct(_: Self::CStruct) -> Self {
unreachable!()
}
fn into_c_struct(self) -> Self::CStruct {
unreachable!()
}
fn types() -> &'static [Type] {
&[]
}
#[allow(non_snake_case)]
unsafe fn call<Rets: WasmTypeList>(
self,
_: NonNull<vm::Func>,
_: Wasm,
_: *mut Ctx,
) -> Result<Rets, RuntimeError> {
unreachable!()
}
}
impl<A: WasmExternType> WasmTypeList for (A,) {
type CStruct = S1<A>;
type RetArray = [u64; 1];
fn from_ret_array(array: Self::RetArray) -> Self {
(WasmExternType::from_bits(array[0]),)
(WasmExternType::from_native(NativeWasmType::from_bits(
array[0],
)),)
}
fn empty_ret_array() -> Self::RetArray {
[0u64]
}
fn from_c_struct(c_struct: Self::CStruct) -> Self {
let S1(a) = c_struct;
(a,)
(WasmExternType::from_native(a),)
}
fn into_c_struct(self) -> Self::CStruct {
#[allow(unused_parens, non_snake_case)]
let (a,) = self;
S1(a)
S1(WasmExternType::to_native(a))
}
fn types() -> &'static [Type] {
&[A::TYPE]
&[A::Native::TYPE]
}
#[allow(non_snake_case)]
unsafe fn call<Rets: WasmTypeList>(
@ -236,14 +272,12 @@ impl<A: WasmExternType> WasmTypeList for (A,) {
f: NonNull<vm::Func>,
wasm: Wasm,
ctx: *mut Ctx,
) -> Result<Rets, WasmTrapInfo> {
// type Trampoline = extern "C" fn(*mut Ctx, *const c_void, *const u64, *mut u64);
// type Invoke = extern "C" fn(Trampoline, *mut Ctx, *const c_void, *const u64, *mut u64, &mut WasmTrapInfo) -> bool;
) -> Result<Rets, RuntimeError> {
let (a,) = self;
let args = [a.to_bits()];
let args = [a.to_native().to_bits()];
let mut rets = Rets::empty_ret_array();
let mut trap = WasmTrapInfo::Unknown;
let mut user_error = None;
if (wasm.invoke)(
wasm.trampoline,
@ -252,11 +286,18 @@ impl<A: WasmExternType> WasmTypeList for (A,) {
args.as_ptr(),
rets.as_mut().as_mut_ptr(),
&mut trap,
&mut user_error,
wasm.invoke_env,
) {
Ok(Rets::from_ret_array(rets))
} else {
Err(trap)
if let Some(data) = user_error {
Err(RuntimeError::Error { data })
} else {
Err(RuntimeError::Trap {
msg: trap.to_string().into(),
})
}
}
}
}
@ -266,18 +307,14 @@ where
Rets: WasmTypeList,
{
pub fn call(&self, a: A) -> Result<Rets, RuntimeError> {
unsafe { <A as WasmTypeList>::call(a, self.f, self.inner, self.ctx) }.map_err(|e| {
RuntimeError::Trap {
msg: e.to_string().into(),
}
})
unsafe { <A as WasmTypeList>::call(a, self.f, self.inner, self.ctx) }
}
}
macro_rules! impl_traits {
( [$repr:ident] $struct_name:ident, $( $x:ident ),* ) => {
#[repr($repr)]
pub struct $struct_name <$( $x ),*> ( $( $x ),* );
pub struct $struct_name <$( $x: WasmExternType ),*> ( $( <$x as WasmExternType>::Native ),* );
impl< $( $x: WasmExternType, )* > WasmTypeList for ( $( $x ),* ) {
type CStruct = $struct_name<$( $x ),*>;
@ -285,7 +322,7 @@ macro_rules! impl_traits {
fn from_ret_array(array: Self::RetArray) -> Self {
#[allow(non_snake_case)]
let [ $( $x ),* ] = array;
( $( WasmExternType::from_bits($x) ),* )
( $( WasmExternType::from_native(NativeWasmType::from_bits($x)) ),* )
}
fn empty_ret_array() -> Self::RetArray {
[0; count_idents!( $( $x ),* )]
@ -293,38 +330,34 @@ macro_rules! impl_traits {
fn from_c_struct(c_struct: Self::CStruct) -> Self {
#[allow(non_snake_case)]
let $struct_name ( $( $x ),* ) = c_struct;
( $( $x ),* )
( $( WasmExternType::from_native($x) ),* )
}
fn into_c_struct(self) -> Self::CStruct {
#[allow(unused_parens, non_snake_case)]
let ( $( $x ),* ) = self;
$struct_name ( $( $x ),* )
$struct_name ( $( WasmExternType::to_native($x) ),* )
}
fn types() -> &'static [Type] {
&[$( $x::TYPE, )*]
&[$( $x::Native::TYPE, )*]
}
#[allow(non_snake_case)]
unsafe fn call<Rets: WasmTypeList>(self, f: NonNull<vm::Func>, wasm: Wasm, ctx: *mut Ctx) -> Result<Rets, WasmTrapInfo> {
// type Trampoline = extern "C" fn(*mut Ctx, *const c_void, *const u64, *mut u64);
// type Invoke = extern "C" fn(Trampoline, *mut Ctx, *const c_void, *const u64, *mut u64, &mut WasmTrapInfo) -> bool;
unsafe fn call<Rets: WasmTypeList>(self, f: NonNull<vm::Func>, wasm: Wasm, ctx: *mut Ctx) -> Result<Rets, RuntimeError> {
#[allow(unused_parens)]
let ( $( $x ),* ) = self;
let args = [ $( $x.to_bits() ),* ];
let args = [ $( $x.to_native().to_bits() ),* ];
let mut rets = Rets::empty_ret_array();
let mut trap = WasmTrapInfo::Unknown;
let mut user_error = None;
if (wasm.invoke)(wasm.trampoline, ctx, f, args.as_ptr(), rets.as_mut().as_mut_ptr(), &mut trap, wasm.invoke_env) {
if (wasm.invoke)(wasm.trampoline, ctx, f, args.as_ptr(), rets.as_mut().as_mut_ptr(), &mut trap, &mut user_error, wasm.invoke_env) {
Ok(Rets::from_ret_array(rets))
} else {
Err(trap)
if let Some(data) = user_error {
Err(RuntimeError::Error { data })
} else {
Err(RuntimeError::Trap { msg: trap.to_string().into() })
}
}
// let f: extern fn(*mut Ctx $( ,$x )*) -> Rets::CStruct = mem::transmute(f);
// #[allow(unused_parens)]
// let ( $( $x ),* ) = self;
// let c_struct = f(ctx $( ,$x )*);
// Rets::from_c_struct(c_struct)
}
}
@ -335,15 +368,17 @@ macro_rules! impl_traits {
/// This is required for the llvm backend to be able to unwind through this function.
#[cfg_attr(nightly, unwind(allowed))]
extern fn wrap<$( $x: WasmExternType, )* Rets: WasmTypeList, Trap: TrapEarly<Rets>, FN: Fn( &mut Ctx $( ,$x )* ) -> Trap>( ctx: &mut Ctx $( ,$x: $x )* ) -> Rets::CStruct {
extern fn wrap<$( $x: WasmExternType, )* Rets: WasmTypeList, Trap: TrapEarly<Rets>, FN: Fn( &mut Ctx $( ,$x )* ) -> Trap>( ctx: &mut Ctx $( ,$x: <$x as WasmExternType>::Native )* ) -> Rets::CStruct {
let f: FN = unsafe { mem::transmute_copy(&()) };
let err = match panic::catch_unwind(panic::AssertUnwindSafe(|| {
let res = f( ctx $( ,$x )* ).report();
res
f( ctx $( ,WasmExternType::from_native($x) )* ).report()
})) {
Ok(Ok(returns)) => return returns.into_c_struct(),
Ok(Err(err)) => err,
Ok(Err(err)) => {
let b: Box<_> = err.into();
b as Box<dyn Any>
},
Err(err) => err,
};
@ -363,11 +398,7 @@ macro_rules! impl_traits {
#[allow(non_snake_case)]
pub fn call(&self, $( $x: $x, )* ) -> Result<Rets, RuntimeError> {
#[allow(unused_parens)]
unsafe { <( $( $x ),* ) as WasmTypeList>::call(( $($x),* ), self.f, self.inner, self.ctx) }.map_err(|e| {
RuntimeError::Trap {
msg: e.to_string().into(),
}
})
unsafe { <( $( $x ),* ) as WasmTypeList>::call(( $($x),* ), self.f, self.inner, self.ctx) }
}
}
};

View File

@ -71,103 +71,149 @@ impl From<f64> for Value {
}
}
pub unsafe trait WasmExternType: Copy + Clone
pub unsafe trait NativeWasmType: Copy + Into<Value>
where
Self: Sized,
{
const TYPE: Type;
fn from_bits(bits: u64) -> Self;
fn to_bits(self) -> u64;
fn from_bits(n: u64) -> Self;
}
unsafe impl NativeWasmType for i32 {
const TYPE: Type = Type::I32;
fn from_bits(bits: u64) -> Self {
bits as _
}
fn to_bits(self) -> u64 {
self as _
}
}
unsafe impl NativeWasmType for i64 {
const TYPE: Type = Type::I64;
fn from_bits(bits: u64) -> Self {
bits as _
}
fn to_bits(self) -> u64 {
self as _
}
}
unsafe impl NativeWasmType for f32 {
const TYPE: Type = Type::F32;
fn from_bits(bits: u64) -> Self {
bits as _
}
fn to_bits(self) -> u64 {
self as _
}
}
unsafe impl NativeWasmType for f64 {
const TYPE: Type = Type::F64;
fn from_bits(bits: u64) -> Self {
bits as _
}
fn to_bits(self) -> u64 {
self as _
}
}
pub unsafe trait WasmExternType: Copy
where
Self: Sized,
{
type Native: NativeWasmType;
fn from_native(native: Self::Native) -> Self;
fn to_native(self) -> Self::Native;
}
unsafe impl WasmExternType for i8 {
const TYPE: Type = Type::I32;
fn to_bits(self) -> u64 {
self as u64
type Native = i32;
fn from_native(native: Self::Native) -> Self {
native as _
}
fn from_bits(n: u64) -> Self {
n as _
fn to_native(self) -> Self::Native {
self as _
}
}
unsafe impl WasmExternType for u8 {
const TYPE: Type = Type::I32;
fn to_bits(self) -> u64 {
self as u64
type Native = i32;
fn from_native(native: Self::Native) -> Self {
native as _
}
fn from_bits(n: u64) -> Self {
n as _
fn to_native(self) -> Self::Native {
self as _
}
}
unsafe impl WasmExternType for i16 {
const TYPE: Type = Type::I32;
fn to_bits(self) -> u64 {
self as u64
type Native = i32;
fn from_native(native: Self::Native) -> Self {
native as _
}
fn from_bits(n: u64) -> Self {
n as _
fn to_native(self) -> Self::Native {
self as _
}
}
unsafe impl WasmExternType for u16 {
const TYPE: Type = Type::I32;
fn to_bits(self) -> u64 {
self as u64
type Native = i32;
fn from_native(native: Self::Native) -> Self {
native as _
}
fn from_bits(n: u64) -> Self {
n as _
fn to_native(self) -> Self::Native {
self as _
}
}
unsafe impl WasmExternType for i32 {
const TYPE: Type = Type::I32;
fn to_bits(self) -> u64 {
self as u64
type Native = i32;
fn from_native(native: Self::Native) -> Self {
native
}
fn from_bits(n: u64) -> Self {
n as _
fn to_native(self) -> Self::Native {
self
}
}
unsafe impl WasmExternType for u32 {
const TYPE: Type = Type::I32;
fn to_bits(self) -> u64 {
self as u64
type Native = i32;
fn from_native(native: Self::Native) -> Self {
native as _
}
fn from_bits(n: u64) -> Self {
n as _
fn to_native(self) -> Self::Native {
self as _
}
}
unsafe impl WasmExternType for i64 {
const TYPE: Type = Type::I64;
fn to_bits(self) -> u64 {
self as u64
type Native = i64;
fn from_native(native: Self::Native) -> Self {
native
}
fn from_bits(n: u64) -> Self {
n as _
fn to_native(self) -> Self::Native {
self
}
}
unsafe impl WasmExternType for u64 {
const TYPE: Type = Type::I64;
fn to_bits(self) -> u64 {
self
type Native = i64;
fn from_native(native: Self::Native) -> Self {
native as _
}
fn from_bits(n: u64) -> Self {
n
fn to_native(self) -> Self::Native {
self as _
}
}
unsafe impl WasmExternType for f32 {
const TYPE: Type = Type::F32;
fn to_bits(self) -> u64 {
self.to_bits() as u64
type Native = f32;
fn from_native(native: Self::Native) -> Self {
native
}
fn from_bits(n: u64) -> Self {
f32::from_bits(n as u32)
fn to_native(self) -> Self::Native {
self
}
}
unsafe impl WasmExternType for f64 {
const TYPE: Type = Type::F64;
fn to_bits(self) -> u64 {
self.to_bits()
type Native = f64;
fn from_native(native: Self::Native) -> Self {
native
}
fn from_bits(n: u64) -> Self {
f64::from_bits(n)
fn to_native(self) -> Self::Native {
self
}
}

View File

@ -1,4 +1,4 @@
use wasmer_runtime::{compile, error, imports, Ctx, Func, Value};
use wasmer_runtime::{compile, error, error::RuntimeError, imports, Ctx, Func, Value};
use wabt::wat2wasm;
@ -7,6 +7,8 @@ static WAT: &'static str = r#"
(type (;0;) (func (result i32)))
(import "env" "do_panic" (func $do_panic (type 0)))
(func $dbz (result i32)
call $do_panic
drop
i32.const 42
i32.const 0
i32.div_u
@ -34,8 +36,13 @@ fn foobar(_ctx: &mut Ctx) -> i32 {
42
}
fn do_panic(_ctx: &mut Ctx) -> Result<i32, String> {
Err("error".to_string())
#[derive(Debug)]
struct ExitCode {
code: i32,
}
fn do_panic(_ctx: &mut Ctx) -> Result<i32, ExitCode> {
Err(ExitCode { code: 42 })
}
fn main() -> Result<(), error::Error> {
@ -63,5 +70,11 @@ fn main() -> Result<(), error::Error> {
println!("result: {:?}", result);
if let Err(RuntimeError::Error { data }) = result {
if let Ok(exit_code) = data.downcast::<ExitCode>() {
println!("exit code: {:?}", exit_code);
}
}
Ok(())
}

View File

@ -0,0 +1,49 @@
#[test]
fn error_propagation() {
use std::convert::Infallible;
use wabt::wat2wasm;
use wasmer_runtime::{compile, error::RuntimeError, imports, Ctx, Func};
static WAT: &'static str = r#"
(module
(type (;0;) (func))
(import "env" "ret_err" (func $ret_err (type 0)))
(func $call_panic
call $ret_err
)
(export "call_err" (func $call_panic))
)
"#;
#[derive(Debug)]
struct ExitCode {
code: i32,
}
fn ret_err(_ctx: &mut Ctx) -> Result<Infallible, ExitCode> {
Err(ExitCode { code: 42 })
}
let wasm = wat2wasm(WAT).unwrap();
let module = compile(&wasm).unwrap();
let instance = module
.instantiate(&imports! {
"env" => {
"ret_err" => Func::new(ret_err),
},
})
.unwrap();
let foo: Func<(), ()> = instance.func("call_err").unwrap();
let result = foo.call();
if let Err(RuntimeError::Error { data }) = result {
let exit_code = data.downcast::<ExitCode>().unwrap();
assert_eq!(exit_code.code, 42);
} else {
panic!("didn't return RuntimeError::Error")
}
}

View File

@ -9,7 +9,7 @@ edition = "2018"
[dependencies]
wasmer-runtime-core = { path = "../runtime-core", version = "0.3.0" }
wasmparser = "0.28.0"
wasmparser = "0.29.2"
dynasm = "0.3.1"
dynasmrt = "0.3.1"
lazy_static = "1.2.0"

View File

@ -205,7 +205,8 @@ impl RunnableModule for X64ExecutionContext {
func: NonNull<vm::Func>,
args: *const u64,
rets: *mut u64,
_trap_info: *mut WasmTrapInfo,
trap_info: *mut WasmTrapInfo,
user_error: *mut Option<Box<dyn Any>>,
num_params_plus_one: Option<NonNull<c_void>>,
) -> bool {
let args = ::std::slice::from_raw_parts(
@ -227,7 +228,13 @@ impl RunnableModule for X64ExecutionContext {
}
true
}
Err(_) => false,
Err(err) => {
match err {
protect_unix::CallProtError::Trap(info) => *trap_info = info,
protect_unix::CallProtError::Error(data) => *user_error = Some(data),
}
false
}
}
}

View File

@ -31,7 +31,7 @@ use wasmer_runtime_core::{
backend::{sys::Memory, Backend, CacheGen, Compiler, CompilerConfig, Token},
cache::{Artifact, Error as CacheError},
error::{CompileError, CompileResult},
module::{ModuleInfo, ModuleInner},
module::ModuleInner,
};
struct Placeholder;

View File

@ -15,8 +15,7 @@ use wasmer_runtime_core::{
units::Pages,
};
use wasmparser::{
BinaryReaderError, Data, DataKind, Element, ElementKind, Export, ExternalKind, FuncType,
Import, ImportSectionEntryType, InitExpr, ModuleReader, Operator, SectionCode, Type as WpType,
BinaryReaderError, ExternalKind, FuncType, ImportSectionEntryType, Operator, Type as WpType,
WasmDecoder,
};

View File

@ -11,13 +11,13 @@
//!
use libc::{c_int, c_void, siginfo_t};
use nix::sys::signal::{
sigaction, SaFlags, SigAction, SigHandler, SigSet, Signal, SIGBUS, SIGFPE, SIGILL, SIGSEGV,
sigaction, SaFlags, SigAction, SigHandler, SigSet, SIGBUS, SIGFPE, SIGILL, SIGSEGV,
};
use std::any::Any;
use std::cell::{Cell, UnsafeCell};
use std::ptr;
use std::sync::Once;
use wasmer_runtime_core::error::{RuntimeError, RuntimeResult};
use wasmer_runtime_core::typed_func::WasmTrapInfo;
extern "C" fn signal_trap_handler(
signum: ::nix::libc::c_int,
@ -62,7 +62,12 @@ pub unsafe fn trigger_trap() -> ! {
longjmp(jmp_buf as *mut c_void, 0)
}
pub fn call_protected<T>(f: impl FnOnce() -> T) -> RuntimeResult<T> {
pub enum CallProtError {
Trap(WasmTrapInfo),
Error(Box<dyn Any>),
}
pub fn call_protected<T>(f: impl FnOnce() -> T) -> Result<T, CallProtError> {
unsafe {
let jmp_buf = SETJMP_BUFFER.with(|buf| buf.get());
let prev_jmp_buf = *jmp_buf;
@ -76,23 +81,24 @@ pub fn call_protected<T>(f: impl FnOnce() -> T) -> RuntimeResult<T> {
*jmp_buf = prev_jmp_buf;
if let Some(data) = TRAP_EARLY_DATA.with(|cell| cell.replace(None)) {
Err(RuntimeError::Panic { data })
Err(CallProtError::Error(data))
} else {
let (faulting_addr, _inst_ptr) = CAUGHT_ADDRESSES.with(|cell| cell.get());
// let (faulting_addr, _inst_ptr) = CAUGHT_ADDRESSES.with(|cell| cell.get());
let signal = match Signal::from_c_int(signum) {
Ok(SIGFPE) => "floating-point exception",
Ok(SIGILL) => "illegal instruction",
Ok(SIGSEGV) => "segmentation violation",
Ok(SIGBUS) => "bus error",
Err(_) => "error while getting the Signal",
_ => "unkown trapped signal",
};
// When the trap-handler is fully implemented, this will return more information.
Err(RuntimeError::Trap {
msg: format!("unknown trap at {:p} - {}", faulting_addr, signal).into(),
}
.into())
// let signal = match Signal::from_c_int(signum) {
// Ok(SIGFPE) => "floating-point exception",
// Ok(SIGILL) => "illegal instruction",
// Ok(SIGSEGV) => "segmentation violation",
// Ok(SIGBUS) => "bus error",
// Err(_) => "error while getting the Signal",
// _ => "unkown trapped signal",
// };
// // When the trap-handler is fully implemented, this will return more information.
// Err(RuntimeError::Trap {
// msg: format!("unknown trap at {:p} - {}", faulting_addr, signal).into(),
// }
// .into())
Err(CallProtError::Trap(WasmTrapInfo::Unknown))
}
} else {
let ret = f(); // TODO: Switch stack?

View File

@ -16,8 +16,3 @@ hashbrown = "0.1.8"
generational-arena = "0.2.2"
log = "0.4.6"
byteorder = "1.3.1"
[dependencies.zbox]
git = "https://github.com/wasmerio/zbox"
branch = "bundle-libsodium"
features = ["libsodium-bundled"]

View File

@ -17,6 +17,12 @@ pub use self::utils::is_wasi_module;
use wasmer_runtime_core::{func, import::ImportObject, imports};
/// This is returned in the Box<dyn Any> RuntimeError::Error variant.
/// Use `downcast` or `downcast_ref` to retrieve the `ExitCode`.
pub struct ExitCode {
pub code: syscalls::types::__wasi_exitcode_t,
}
pub fn generate_import_object(
args: Vec<Vec<u8>>,
envs: Vec<Vec<u8>>,

View File

@ -2,7 +2,7 @@ use crate::syscalls::types::{__wasi_errno_t, __WASI_EFAULT};
use std::{cell::Cell, fmt, marker::PhantomData, mem};
use wasmer_runtime_core::{
memory::Memory,
types::{Type, ValueType, WasmExternType},
types::{ValueType, WasmExternType},
};
pub struct Array;
@ -73,12 +73,12 @@ impl<T: Copy + ValueType> WasmPtr<T, Array> {
}
unsafe impl<T: Copy, Ty> WasmExternType for WasmPtr<T, Ty> {
const TYPE: Type = Type::I32;
type Native = i32;
fn to_bits(self) -> u64 {
self.offset as u64
fn to_native(self) -> Self::Native {
self.offset as i32
}
fn from_bits(n: u64) -> Self {
fn from_native(n: Self::Native) -> Self {
Self {
offset: n as u32,
_phantom: PhantomData,

View File

@ -9,45 +9,39 @@ use std::{
cell::Cell,
fs,
io::{self, Read, Seek, Write},
path::PathBuf,
time::SystemTime,
};
use wasmer_runtime_core::debug;
use zbox::init_env as zbox_init_env;
pub const MAX_SYMLINKS: usize = 100;
#[derive(Debug)]
pub enum WasiFile {
#[allow(dead_code)]
ZboxFile(zbox::File),
HostFile(fs::File),
}
impl Write for WasiFile {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
match self {
WasiFile::ZboxFile(zbf) => zbf.write(buf),
WasiFile::HostFile(hf) => hf.write(buf),
}
}
fn flush(&mut self) -> io::Result<()> {
match self {
WasiFile::ZboxFile(zbf) => zbf.flush(),
WasiFile::HostFile(hf) => hf.flush(),
}
}
fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
match self {
WasiFile::ZboxFile(zbf) => zbf.write_all(buf),
WasiFile::HostFile(hf) => hf.write_all(buf),
}
}
fn write_fmt(&mut self, fmt: ::std::fmt::Arguments) -> io::Result<()> {
match self {
WasiFile::ZboxFile(zbf) => zbf.write_fmt(fmt),
WasiFile::HostFile(hf) => hf.write_fmt(fmt),
}
}
@ -56,28 +50,24 @@ impl Write for WasiFile {
impl Read for WasiFile {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
match self {
WasiFile::ZboxFile(zbf) => zbf.read(buf),
WasiFile::HostFile(hf) => hf.read(buf),
}
}
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
match self {
WasiFile::ZboxFile(zbf) => zbf.read_to_end(buf),
WasiFile::HostFile(hf) => hf.read_to_end(buf),
}
}
fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
match self {
WasiFile::ZboxFile(zbf) => zbf.read_to_string(buf),
WasiFile::HostFile(hf) => hf.read_to_string(buf),
}
}
fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
match self {
WasiFile::ZboxFile(zbf) => zbf.read_exact(buf),
WasiFile::HostFile(hf) => hf.read_exact(buf),
}
}
@ -86,7 +76,6 @@ impl Read for WasiFile {
impl Seek for WasiFile {
fn seek(&mut self, pos: io::SeekFrom) -> io::Result<u64> {
match self {
WasiFile::ZboxFile(zbf) => zbf.seek(pos),
WasiFile::HostFile(hf) => hf.seek(pos),
}
}
@ -150,7 +139,9 @@ pub enum Kind {
handle: WasiFile,
},
Dir {
handle: WasiFile,
// TODO: wrap it like WasiFile
/// The path on the host system where the directory is located
path: PathBuf,
/// The entries of a directory are lazily filled.
entries: HashMap<String, Inode>,
},
@ -182,10 +173,7 @@ pub struct WasiFs {
}
impl WasiFs {
pub fn new(preopened_files: &[String]) -> Result<Self, String> {
debug!("wasi::fs::init");
zbox_init_env();
debug!("wasi::fs::repo");
pub fn new(preopened_dirs: &[String]) -> Result<Self, String> {
/*let repo = RepoOpener::new()
.create(true)
.open("mem://wasmer-test-fs", "")
@ -200,29 +188,26 @@ impl WasiFs {
next_fd: Cell::new(3),
inode_counter: Cell::new(1000),
};
for file in preopened_files {
debug!("Attempting to preopen {}", &file);
for dir in preopened_dirs {
debug!("Attempting to preopen {}", &dir);
// TODO: think about this
let default_rights = 0x1FFFFFFF; // all rights
let cur_file: fs::File = fs::OpenOptions::new()
.read(true)
.open(file)
.expect("Could not find file");
let cur_file_metadata = cur_file.metadata().unwrap();
let kind = if cur_file_metadata.is_dir() {
let cur_dir = PathBuf::from(dir);
let cur_dir_metadata = cur_dir.metadata().expect("Could not find directory");
let kind = if cur_dir_metadata.is_dir() {
Kind::Dir {
handle: WasiFile::HostFile(cur_file),
path: cur_dir.clone(),
entries: Default::default(),
}
} else {
return Err(format!(
"WASI only supports pre-opened directories right now; found \"{}\"",
file
&dir
));
};
// TODO: handle nested pats in `file`
let inode_val =
InodeVal::from_file_metadata(&cur_file_metadata, file.clone(), true, kind);
InodeVal::from_file_metadata(&cur_dir_metadata, dir.clone(), true, kind);
let inode = wasi_fs.inodes.insert(inode_val);
wasi_fs.inodes[inode].stat.st_ino = wasi_fs.inode_counter.get();

View File

@ -9,9 +9,11 @@ use self::types::*;
use crate::{
ptr::{Array, WasmPtr},
state::{Fd, InodeVal, Kind, WasiFile, WasiState, MAX_SYMLINKS},
ExitCode,
};
use rand::{thread_rng, Rng};
use std::cell::Cell;
use std::convert::Infallible;
use std::io::{self, Read, Seek, Write};
use wasmer_runtime_core::{debug, memory::Memory, vm::Ctx};
@ -1240,15 +1242,12 @@ pub fn path_open(
};
// TODO: handle __WASI_O_TRUNC on directories
let cur_dir = wasi_try!(open_options
.open(&cumulative_path)
.map_err(|_| __WASI_EINVAL));
// TODO: refactor and reuse
let cur_file_metadata = cur_dir.metadata().unwrap();
let cur_file_metadata =
wasi_try!(cumulative_path.metadata().map_err(|_| __WASI_EINVAL));
let kind = if cur_file_metadata.is_dir() {
Kind::Dir {
handle: WasiFile::HostFile(cur_dir),
path: cumulative_path.clone(),
entries: Default::default(),
}
} else {
@ -1430,9 +1429,9 @@ pub fn poll_oneoff(
debug!("wasi::poll_oneoff");
unimplemented!()
}
pub fn proc_exit(ctx: &mut Ctx, rval: __wasi_exitcode_t) -> Result<(), &'static str> {
debug!("wasi::proc_exit, {}", rval);
Err("Instance exited")
pub fn proc_exit(ctx: &mut Ctx, code: __wasi_exitcode_t) -> Result<Infallible, ExitCode> {
debug!("wasi::proc_exit, {}", code);
Err(ExitCode { code })
}
pub fn proc_raise(ctx: &mut Ctx, sig: __wasi_signal_t) -> __wasi_errno_t {
debug!("wasi::proc_raise");

View File

@ -43,84 +43,84 @@ pub struct __wasi_dirent_t {
pub d_type: __wasi_filetype_t,
}
pub type __wasi_errno_t = u32;
pub const __WASI_ESUCCESS: u32 = 0;
pub const __WASI_E2BIG: u32 = 1;
pub const __WASI_EACCES: u32 = 2;
pub const __WASI_EADDRINUSE: u32 = 3;
pub const __WASI_EADDRNOTAVAIL: u32 = 4;
pub const __WASI_EAFNOSUPPORT: u32 = 5;
pub const __WASI_EAGAIN: u32 = 6;
pub const __WASI_EALREADY: u32 = 7;
pub const __WASI_EBADF: u32 = 8;
pub const __WASI_EBADMSG: u32 = 9;
pub const __WASI_EBUSY: u32 = 10;
pub const __WASI_ECANCELED: u32 = 11;
pub const __WASI_ECHILD: u32 = 12;
pub const __WASI_ECONNABORTED: u32 = 13;
pub const __WASI_ECONNREFUSED: u32 = 14;
pub const __WASI_ECONNRESET: u32 = 15;
pub const __WASI_EDEADLK: u32 = 16;
pub const __WASI_EDESTADDRREQ: u32 = 17;
pub const __WASI_EDOM: u32 = 18;
pub const __WASI_EDQUOT: u32 = 19;
pub const __WASI_EEXIST: u32 = 20;
pub const __WASI_EFAULT: u32 = 21;
pub const __WASI_EFBIG: u32 = 22;
pub const __WASI_EHOSTUNREACH: u32 = 23;
pub const __WASI_EIDRM: u32 = 24;
pub const __WASI_EILSEQ: u32 = 25;
pub const __WASI_EINPROGRESS: u32 = 26;
pub const __WASI_EINTR: u32 = 27;
pub const __WASI_EINVAL: u32 = 28;
pub const __WASI_EIO: u32 = 29;
pub const __WASI_EISCONN: u32 = 30;
pub const __WASI_EISDIR: u32 = 31;
pub const __WASI_ELOOP: u32 = 32;
pub const __WASI_EMFILE: u32 = 33;
pub const __WASI_EMLINK: u32 = 34;
pub const __WASI_EMSGSIZE: u32 = 35;
pub const __WASI_EMULTIHOP: u32 = 36;
pub const __WASI_ENAMETOOLONG: u32 = 37;
pub const __WASI_ENETDOWN: u32 = 38;
pub const __WASI_ENETRESET: u32 = 39;
pub const __WASI_ENETUNREACH: u32 = 40;
pub const __WASI_ENFILE: u32 = 41;
pub const __WASI_ENOBUFS: u32 = 42;
pub const __WASI_ENODEV: u32 = 43;
pub const __WASI_ENOENT: u32 = 44;
pub const __WASI_ENOEXEC: u32 = 45;
pub const __WASI_ENOLCK: u32 = 46;
pub const __WASI_ENOLINK: u32 = 47;
pub const __WASI_ENOMEM: u32 = 48;
pub const __WASI_ENOMSG: u32 = 49;
pub const __WASI_ENOPROTOOPT: u32 = 50;
pub const __WASI_ENOSPC: u32 = 51;
pub const __WASI_ENOSYS: u32 = 52;
pub const __WASI_ENOTCONN: u32 = 53;
pub const __WASI_ENOTDIR: u32 = 54;
pub const __WASI_ENOTEMPTY: u32 = 55;
pub const __WASI_ENOTRECOVERABLE: u32 = 56;
pub const __WASI_ENOTSOCK: u32 = 57;
pub const __WASI_ENOTSUP: u32 = 58;
pub const __WASI_ENOTTY: u32 = 59;
pub const __WASI_ENXIO: u32 = 60;
pub const __WASI_EOVERFLOW: u32 = 61;
pub const __WASI_EOWNERDEAD: u32 = 62;
pub const __WASI_EPERM: u32 = 63;
pub const __WASI_EPIPE: u32 = 64;
pub const __WASI_EPROTO: u32 = 65;
pub const __WASI_EPROTONOSUPPORT: u32 = 66;
pub const __WASI_EPROTOTYPE: u32 = 67;
pub const __WASI_ERANGE: u32 = 68;
pub const __WASI_EROFS: u32 = 69;
pub const __WASI_ESPIPE: u32 = 70;
pub const __WASI_ESRCH: u32 = 71;
pub const __WASI_ESTALE: u32 = 72;
pub const __WASI_ETIMEDOUT: u32 = 73;
pub const __WASI_ETXTBSY: u32 = 74;
pub const __WASI_EXDEV: u32 = 75;
pub const __WASI_ENOTCAPABLE: u32 = 76;
pub type __wasi_errno_t = u16;
pub const __WASI_ESUCCESS: u16 = 0;
pub const __WASI_E2BIG: u16 = 1;
pub const __WASI_EACCES: u16 = 2;
pub const __WASI_EADDRINUSE: u16 = 3;
pub const __WASI_EADDRNOTAVAIL: u16 = 4;
pub const __WASI_EAFNOSUPPORT: u16 = 5;
pub const __WASI_EAGAIN: u16 = 6;
pub const __WASI_EALREADY: u16 = 7;
pub const __WASI_EBADF: u16 = 8;
pub const __WASI_EBADMSG: u16 = 9;
pub const __WASI_EBUSY: u16 = 10;
pub const __WASI_ECANCELED: u16 = 11;
pub const __WASI_ECHILD: u16 = 12;
pub const __WASI_ECONNABORTED: u16 = 13;
pub const __WASI_ECONNREFUSED: u16 = 14;
pub const __WASI_ECONNRESET: u16 = 15;
pub const __WASI_EDEADLK: u16 = 16;
pub const __WASI_EDESTADDRREQ: u16 = 17;
pub const __WASI_EDOM: u16 = 18;
pub const __WASI_EDQUOT: u16 = 19;
pub const __WASI_EEXIST: u16 = 20;
pub const __WASI_EFAULT: u16 = 21;
pub const __WASI_EFBIG: u16 = 22;
pub const __WASI_EHOSTUNREACH: u16 = 23;
pub const __WASI_EIDRM: u16 = 24;
pub const __WASI_EILSEQ: u16 = 25;
pub const __WASI_EINPROGRESS: u16 = 26;
pub const __WASI_EINTR: u16 = 27;
pub const __WASI_EINVAL: u16 = 28;
pub const __WASI_EIO: u16 = 29;
pub const __WASI_EISCONN: u16 = 30;
pub const __WASI_EISDIR: u16 = 31;
pub const __WASI_ELOOP: u16 = 32;
pub const __WASI_EMFILE: u16 = 33;
pub const __WASI_EMLINK: u16 = 34;
pub const __WASI_EMSGSIZE: u16 = 35;
pub const __WASI_EMULTIHOP: u16 = 36;
pub const __WASI_ENAMETOOLONG: u16 = 37;
pub const __WASI_ENETDOWN: u16 = 38;
pub const __WASI_ENETRESET: u16 = 39;
pub const __WASI_ENETUNREACH: u16 = 40;
pub const __WASI_ENFILE: u16 = 41;
pub const __WASI_ENOBUFS: u16 = 42;
pub const __WASI_ENODEV: u16 = 43;
pub const __WASI_ENOENT: u16 = 44;
pub const __WASI_ENOEXEC: u16 = 45;
pub const __WASI_ENOLCK: u16 = 46;
pub const __WASI_ENOLINK: u16 = 47;
pub const __WASI_ENOMEM: u16 = 48;
pub const __WASI_ENOMSG: u16 = 49;
pub const __WASI_ENOPROTOOPT: u16 = 50;
pub const __WASI_ENOSPC: u16 = 51;
pub const __WASI_ENOSYS: u16 = 52;
pub const __WASI_ENOTCONN: u16 = 53;
pub const __WASI_ENOTDIR: u16 = 54;
pub const __WASI_ENOTEMPTY: u16 = 55;
pub const __WASI_ENOTRECOVERABLE: u16 = 56;
pub const __WASI_ENOTSOCK: u16 = 57;
pub const __WASI_ENOTSUP: u16 = 58;
pub const __WASI_ENOTTY: u16 = 59;
pub const __WASI_ENXIO: u16 = 60;
pub const __WASI_EOVERFLOW: u16 = 61;
pub const __WASI_EOWNERDEAD: u16 = 62;
pub const __WASI_EPERM: u16 = 63;
pub const __WASI_EPIPE: u16 = 64;
pub const __WASI_EPROTO: u16 = 65;
pub const __WASI_EPROTONOSUPPORT: u16 = 66;
pub const __WASI_EPROTOTYPE: u16 = 67;
pub const __WASI_ERANGE: u16 = 68;
pub const __WASI_EROFS: u16 = 69;
pub const __WASI_ESPIPE: u16 = 70;
pub const __WASI_ESRCH: u16 = 71;
pub const __WASI_ESTALE: u16 = 72;
pub const __WASI_ETIMEDOUT: u16 = 73;
pub const __WASI_ETXTBSY: u16 = 74;
pub const __WASI_EXDEV: u16 = 75;
pub const __WASI_ENOTCAPABLE: u16 = 76;
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[repr(C)]
@ -174,8 +174,8 @@ impl __wasi_event_t {
}
}
pub type __wasi_eventrwflags_t = u32;
pub const __WASI_EVENT_FD_READWRITE_HANGUP: u32 = 1 << 0;
pub type __wasi_eventrwflags_t = u16;
pub const __WASI_EVENT_FD_READWRITE_HANGUP: u16 = 1 << 0;
pub type __wasi_eventtype_t = u8;
pub const __WASI_EVENTTYPE_CLOCK: u8 = 0;
@ -189,12 +189,12 @@ pub const __WASI_STDIN_FILENO: u32 = 0;
pub const __WASI_STDOUT_FILENO: u32 = 1;
pub const __WASI_STDERR_FILENO: u32 = 2;
pub type __wasi_fdflags_t = u32;
pub const __WASI_FDFLAG_APPEND: u32 = 1 << 0;
pub const __WASI_FDFLAG_DSYNC: u32 = 1 << 1;
pub const __WASI_FDFLAG_NONBLOCK: u32 = 1 << 2;
pub const __WASI_FDFLAG_RSYNC: u32 = 1 << 3;
pub const __WASI_FDFLAG_SYNC: u32 = 1 << 4;
pub type __wasi_fdflags_t = u16;
pub const __WASI_FDFLAG_APPEND: u16 = 1 << 0;
pub const __WASI_FDFLAG_DSYNC: u16 = 1 << 1;
pub const __WASI_FDFLAG_NONBLOCK: u16 = 1 << 2;
pub const __WASI_FDFLAG_RSYNC: u16 = 1 << 3;
pub const __WASI_FDFLAG_SYNC: u16 = 1 << 4;
pub type __wasi_preopentype_t = u8;
pub const __WASI_PREOPENTYPE_DIR: u8 = 0;
@ -296,11 +296,11 @@ pub const __WASI_FILETYPE_SOCKET_DGRAM: u8 = 5;
pub const __WASI_FILETYPE_SOCKET_STREAM: u8 = 6;
pub const __WASI_FILETYPE_SYMBOLIC_LINK: u8 = 7;
pub type __wasi_fstflags_t = u32;
pub const __WASI_FILESTAT_SET_ATIM: u32 = 1 << 0;
pub const __WASI_FILESTAT_SET_ATIM_NOW: u32 = 1 << 1;
pub const __WASI_FILESTAT_SET_MTIM: u32 = 1 << 2;
pub const __WASI_FILESTAT_SET_MTIM_NOW: u32 = 1 << 3;
pub type __wasi_fstflags_t = u16;
pub const __WASI_FILESTAT_SET_ATIM: u16 = 1 << 0;
pub const __WASI_FILESTAT_SET_ATIM_NOW: u16 = 1 << 1;
pub const __WASI_FILESTAT_SET_MTIM: u16 = 1 << 2;
pub const __WASI_FILESTAT_SET_MTIM_NOW: u16 = 1 << 3;
pub type __wasi_inode_t = u64;
@ -318,15 +318,15 @@ pub type __wasi_linkcount_t = u32;
pub type __wasi_lookupflags_t = u32;
pub const __WASI_LOOKUP_SYMLINK_FOLLOW: u32 = 1 << 0;
pub type __wasi_oflags_t = u32;
pub const __WASI_O_CREAT: u32 = 1 << 0;
pub const __WASI_O_DIRECTORY: u32 = 1 << 1;
pub const __WASI_O_EXCL: u32 = 1 << 2;
pub const __WASI_O_TRUNC: u32 = 1 << 3;
pub type __wasi_oflags_t = u16;
pub const __WASI_O_CREAT: u16 = 1 << 0;
pub const __WASI_O_DIRECTORY: u16 = 1 << 1;
pub const __WASI_O_EXCL: u16 = 1 << 2;
pub const __WASI_O_TRUNC: u16 = 1 << 3;
pub type __wasi_riflags_t = u32;
pub const __WASI_SOCK_RECV_PEEK: u32 = 1 << 0;
pub const __WASI_SOCK_RECV_WAITALL: u32 = 1 << 1;
pub type __wasi_riflags_t = u16;
pub const __WASI_SOCK_RECV_PEEK: u16 = 1 << 0;
pub const __WASI_SOCK_RECV_WAITALL: u16 = 1 << 1;
pub type __wasi_rights_t = u64;
pub const __WASI_RIGHT_FD_DATASYNC: u64 = 1 << 0;
@ -359,14 +359,14 @@ pub const __WASI_RIGHT_PATH_REMOVE_DIRECTORY: u64 = 1 << 26;
pub const __WASI_RIGHT_POLL_FD_READWRITE: u64 = 1 << 27;
pub const __WASI_RIGHT_SOCK_SHUTDOWN: u64 = 1 << 28;
pub type __wasi_roflags_t = u32;
pub const __WASI_SOCK_RECV_DATA_TRUNCATED: u32 = 1 << 0;
pub type __wasi_roflags_t = u16;
pub const __WASI_SOCK_RECV_DATA_TRUNCATED: u16 = 1 << 0;
pub type __wasi_sdflags_t = u8;
pub const __WASI_SHUT_RD: u8 = 1 << 0;
pub const __WASI_SHUT_WR: u8 = 1 << 1;
pub type __wasi_siflags_t = u32;
pub type __wasi_siflags_t = u16;
pub type __wasi_signal_t = u8;
pub const __WASI_SIGABRT: u8 = 0;
@ -396,8 +396,8 @@ pub const __WASI_SIGVTALRM: u8 = 23;
pub const __WASI_SIGXCPU: u8 = 24;
pub const __WASI_SIGXFSZ: u8 = 25;
pub type __wasi_subclockflags_t = u32;
pub const __WASI_SUBSCRIPTION_CLOCK_ABSTIME: u32 = 1 << 0;
pub type __wasi_subclockflags_t = u16;
pub const __WASI_SUBSCRIPTION_CLOCK_ABSTIME: u16 = 1 << 0;
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[repr(C)]

View File

@ -1,8 +1,7 @@
use cmake::Config;
fn main() {
#[cfg(target_os = "windows")]
{
use cmake::Config;
let project_name = "exception_handling";
let dst = Config::new(project_name).build();
println!("cargo:rustc-link-search=native={}", dst.display());

BIN
media/wizard_logo.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

BIN
media/wizard_logo_2.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 958 KiB

BIN
media/wizard_logo_small.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

View File

@ -11,12 +11,15 @@ use std::str::FromStr;
use hashbrown::HashMap;
use structopt::StructOpt;
use wasmer::webassembly::InstanceABI;
use wasmer::*;
use wasmer_clif_backend::CraneliftCompiler;
#[cfg(feature = "backend:llvm")]
use wasmer_llvm_backend::LLVMCompiler;
use wasmer_runtime::cache::{Cache as BaseCache, FileSystemCache, WasmHash, WASMER_VERSION_HASH};
use wasmer_runtime::{
cache::{Cache as BaseCache, FileSystemCache, WasmHash, WASMER_VERSION_HASH},
error::RuntimeError,
Func, Value,
};
use wasmer_runtime_core::{
self,
backend::{Compiler, CompilerConfig},
@ -105,7 +108,13 @@ enum Backend {
impl Backend {
pub fn variants() -> &'static [&'static str] {
&["singlepass", "cranelift", "llvm"]
&[
"cranelift",
#[cfg(feature = "backend:singlepass")]
"singlepass",
#[cfg(feature = "backend:llvm")]
"llvm",
]
}
}
@ -295,18 +304,27 @@ fn execute_wasm(options: &Run) -> Result<(), String> {
};
// TODO: refactor this
let (abi, import_object, _em_globals) = if wasmer_emscripten::is_emscripten_module(&module) {
if wasmer_emscripten::is_emscripten_module(&module) {
let mut emscripten_globals = wasmer_emscripten::EmscriptenGlobals::new(&module);
(
InstanceABI::Emscripten,
wasmer_emscripten::generate_emscripten_env(&mut emscripten_globals),
Some(emscripten_globals), // TODO Em Globals is here to extend, lifetime, find better solution
let import_object = wasmer_emscripten::generate_emscripten_env(&mut emscripten_globals);
let mut instance = module
.instantiate(&import_object)
.map_err(|e| format!("Can't instantiate module: {:?}", e))?;
wasmer_emscripten::run_emscripten_instance(
&module,
&mut instance,
if let Some(cn) = &options.command_name {
cn
} else {
options.path.to_str().unwrap()
},
options.args.iter().map(|arg| arg.as_str()).collect(),
)
.map_err(|e| format!("{:?}", e))?;
} else {
if cfg!(feature = "wasi") && wasmer_wasi::is_wasi_module(&module) {
(
InstanceABI::WASI,
wasmer_wasi::generate_import_object(
let import_object = wasmer_wasi::generate_import_object(
if let Some(cn) = &options.command_name {
[cn.clone()]
} else {
@ -321,34 +339,46 @@ fn execute_wasm(options: &Run) -> Result<(), String> {
.map(|(k, v)| format!("{}={}", k, v).into_bytes())
.collect(),
options.pre_opened_directories.clone(),
),
None,
)
} else {
(
InstanceABI::None,
wasmer_runtime_core::import::ImportObject::new(),
None,
)
}
};
);
let mut instance = module
let instance = module
.instantiate(&import_object)
.map_err(|e| format!("Can't instantiate module: {:?}", e))?;
webassembly::run_instance(
&module,
&mut instance,
abi,
if let Some(cn) = &options.command_name {
cn
let start: Func<(), ()> = instance.func("_start").map_err(|e| format!("{:?}", e))?;
let result = start.call();
if let Err(ref err) = result {
match err {
RuntimeError::Trap { msg } => panic!("wasm trap occured: {}", msg),
RuntimeError::Error { data } => {
if let Some(error_code) = data.downcast_ref::<wasmer_wasi::ExitCode>() {
std::process::exit(error_code.code as i32)
}
}
}
panic!("error: {:?}", err)
}
} else {
options.path.to_str().unwrap()
},
options.args.iter().map(|arg| arg.as_str()).collect(),
)
let import_object = wasmer_runtime_core::import::ImportObject::new();
let instance = module
.instantiate(&import_object)
.map_err(|e| format!("Can't instantiate module: {:?}", e))?;
let args: Vec<Value> = options
.args
.iter()
.map(|arg| arg.as_str())
.map(|x| Value::I32(x.parse().unwrap()))
.collect();
instance
.dyn_func("main")
.map_err(|e| format!("{:?}", e))?
.call(&args)
.map_err(|e| format!("{:?}", e))?;
}
}
Ok(())
}

View File

@ -1,6 +1,6 @@
[Setup]
AppName=Wasmer
AppVersion=1.5
AppVersion=0.4.0
DefaultDirName={pf}\Wasmer
DefaultGroupName=Wasmer
Compression=lzma2
@ -9,9 +9,14 @@ OutputDir=.\
DisableProgramGroupPage=yes
ChangesEnvironment=yes
OutputBaseFilename=WasmerInstaller
WizardImageFile=..\..\media\wizard_logo_2.bmp
WizardSmallImageFile=..\..\media\wizard_logo_small.bmp
SetupIconFile=..\..\media\wizard_logo.ico
DisableWelcomePage=no
[Files]
Source: "..\..\target\release\wasmer.exe"; DestDir: "{app}\bin"
Source: "..\..\wapm-cli\target\release\wapm.exe"; DestDir: "{app}\bin"
[Code]
const EnvironmentKey = 'SYSTEM\CurrentControlSet\Control\Session Manager\Environment';
@ -61,11 +66,17 @@ end;
procedure CurStepChanged(CurStep: TSetupStep);
begin
if CurStep = ssPostInstall
then EnvAddPath(ExpandConstant('{app}') +'\bin');
then begin
EnvAddPath(ExpandConstant('{app}') +'\bin');
EnvAddPath(ExpandConstant('{app}') +'\globals\wapm_packages\.bin');
end
end;
procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);
begin
if CurUninstallStep = usPostUninstall
then EnvRemovePath(ExpandConstant('{app}') +'\bin');
then begin
EnvRemovePath(ExpandConstant('{app}') +'\bin');
EnvAddPath(ExpandConstant('{app}') +'\globals\wapm_packages\.bin');
end
end;

View File

@ -1,13 +1,6 @@
use std::panic;
pub use wasmer_runtime::compile_with_config_with;
use wasmer_runtime::{
self as runtime,
error::{CallResult, Result},
ImportObject, Instance, Module,
};
use wasmer_runtime_core::types::Value;
use wasmer_emscripten::run_emscripten_instance;
use wasmer_runtime::{self as runtime, error::Result, ImportObject, Instance, Module};
pub struct ResultObject {
/// A webassembly::Module object representing the compiled WebAssembly module.
@ -77,40 +70,3 @@ pub fn compile(buffer_source: &[u8]) -> Result<Module> {
let module = runtime::compile(buffer_source)?;
Ok(module)
}
// /// The same as `compile` but takes a `CompilerConfig` for the purpose of
// /// changing the compiler's behavior
// pub fn compile_with_config_with(
// buffer_source: &[u8],
// compiler_config: CompilerConfig,
// ) -> Result<Module> {
// let module = runtime::compile_with_config(buffer_source, compiler_config)?;
// Ok(module)
// }
/// Performs common instance operations needed when an instance is first run
/// including data setup, handling arguments and calling a main function
pub fn run_instance(
module: &Module,
instance: &mut Instance,
abi: InstanceABI,
path: &str,
args: Vec<&str>,
) -> CallResult<()> {
match abi {
InstanceABI::Emscripten => {
run_emscripten_instance(module, instance, path, args)?;
}
InstanceABI::WASI => {
instance.call("_start", &[])?;
}
InstanceABI::None => {
let args: Vec<Value> = args
.into_iter()
.map(|x| Value::I32(x.parse().unwrap()))
.collect();
instance.call("main", &args)?;
}
}
Ok(())
}

1
wapm-cli Submodule

Submodule wapm-cli added at c9399f3fb1