Merge remote-tracking branch 'upstream/master' into poll

This commit is contained in:
Marcin Mielniczuk
2020-01-16 13:06:02 +01:00
52 changed files with 1200 additions and 447 deletions

View File

@@ -71,7 +71,7 @@ jobs:
- uses: ./.github/actions/install-rust
with:
toolchain: nightly
- run: cargo install cargo-fuzz --vers "^0.6"
- run: cargo install cargo-fuzz --vers "^0.7"
- run: cargo fetch
working-directory: ./fuzz
- run: cargo fuzz build --release --debug-assertions
@@ -165,6 +165,7 @@ jobs:
- run: rustup target add wasm32-wasi
- run: cargo fetch --locked
- run: cargo fetch --locked --manifest-path crates/test-programs/wasi-tests/Cargo.toml
# Build and test all features except for lightbeam
- run: cargo test --features test_programs --all --exclude lightbeam -- --nocapture
@@ -302,7 +303,7 @@ jobs:
- run: $CENTOS cargo build --release --bin wasmtime --bin wasm2obj
shell: bash
# Build `libwasmtime.so`
- run: $CENTOS cargo build --release --manifest-path crates/api/Cargo.toml
- run: $CENTOS cargo build --release --manifest-path crates/c-api/Cargo.toml
shell: bash
# Test what we just built
- run: $CENTOS cargo test --features test_programs --release --all --exclude lightbeam --exclude wasmtime --exclude wasmtime-fuzzing
@@ -511,4 +512,3 @@ jobs:
files: "dist/*"
name: ${{ steps.tagname.outputs.val }}
token: ${{ secrets.GITHUB_TOKEN }}

4
.gitmodules vendored
View File

@@ -1,8 +1,8 @@
[submodule "spec_testsuite"]
path = tests/spec_testsuite
url = https://github.com/WebAssembly/testsuite
[submodule "crates/api/c-examples/wasm-c-api"]
path = crates/api/c-examples/wasm-c-api
[submodule "crates/c-api/examples/wasm-c-api"]
path = crates/c-api/examples/wasm-c-api
url = https://github.com/WebAssembly/wasm-c-api
[submodule "crates/wasi-common/WASI"]
path = crates/wasi-common/wig/WASI

284
Cargo.lock generated
View File

@@ -30,6 +30,15 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "64cf76cb6e2222ed0ea86b2b0ee2f71c96ec6edd5af42e84d59160e91b836ec4"
[[package]]
name = "arbitrary"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b93b22576af8f14bb2bad6a5dc09c4f80539a801f7ea340c798e222f2ce49859"
dependencies = [
"derive_arbitrary",
]
[[package]]
name = "arrayref"
version = "0.3.5"
@@ -76,9 +85,9 @@ checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d"
[[package]]
name = "backtrace"
version = "0.3.40"
version = "0.3.42"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "924c76597f0d9ca25d762c25a4d369d51267536465dc5064bdf0eb073ed477ea"
checksum = "b4b1549d804b6c73f4817df2ba073709e96e426f12987127c48e6745568c350b"
dependencies = [
"backtrace-sys",
"cfg-if",
@@ -159,8 +168,8 @@ dependencies = [
"lazycell",
"log",
"peeking_take_while",
"proc-macro2",
"quote",
"proc-macro2 1.0.7",
"quote 1.0.2",
"regex",
"rustc-hash",
"shlex",
@@ -341,24 +350,25 @@ dependencies = [
[[package]]
name = "cranelift-bforest"
version = "0.54.0"
version = "0.55.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bd3225fff1be118941c5fb66f1fb1f7f3e86468fac0e7364713c4fb99b72632b"
checksum = "40af6e6f7419110906d0f7b4b8084d3216be64d7da77aa12887885ebe0fc2776"
dependencies = [
"cranelift-entity",
]
[[package]]
name = "cranelift-codegen"
version = "0.54.0"
version = "0.55.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f3e3e6679892029f76a99b9059d2b74e77ac03637d573bb014bc21579ec1b7da"
checksum = "88583eb22e5cd0fe1ef66f0b80d0063d21d30e84e887d08b3d369def3ea7b4be"
dependencies = [
"byteorder",
"cranelift-bforest",
"cranelift-codegen-meta",
"cranelift-codegen-shared",
"cranelift-entity",
"gimli",
"log",
"serde",
"smallvec",
@@ -368,9 +378,9 @@ dependencies = [
[[package]]
name = "cranelift-codegen-meta"
version = "0.54.0"
version = "0.55.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3cabe691548e28ca82ebd218f2fe76eec4c5629b64ef3db8b58443b7d9047275"
checksum = "353872c984943b9134d7c835eb9d12932bd90f4992dbe666593771bee920d673"
dependencies = [
"cranelift-codegen-shared",
"cranelift-entity",
@@ -378,24 +388,24 @@ dependencies = [
[[package]]
name = "cranelift-codegen-shared"
version = "0.54.0"
version = "0.55.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d173252ffade4aa6e929090977b9a4cd5ac28e15a42626f878be3844b3000ad9"
checksum = "cd1e96479a56981cce5c8f14d26773195d662ccdbbeca39fb8eba22b5ca8ea6a"
[[package]]
name = "cranelift-entity"
version = "0.54.0"
version = "0.55.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3498ad9ba021715716a1c52e2b31d7829a149913fb0d88493e4b07d3b772b656"
checksum = "37bc8dc3d4274ededc687d84821f491a8a03447dbb7481983936220892cf55b4"
dependencies = [
"serde",
]
[[package]]
name = "cranelift-frontend"
version = "0.54.0"
version = "0.55.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "521a30773b8de74345c807a38853f055aca8fecaa39a0fc7698bfebc5a3da515"
checksum = "4ea33e55bda8c425f3f533355b03e3a43cf29b4e228b35b868b6a1c43b6a139e"
dependencies = [
"cranelift-codegen",
"log",
@@ -405,9 +415,9 @@ dependencies = [
[[package]]
name = "cranelift-native"
version = "0.54.0"
version = "0.55.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "624e755cbe984e437308968239736e7f9aa3193e99928fb76eec7a1946627b34"
checksum = "2c22cfaaa5e69eddaddd6cfa7a76233de964b9b2245e81a5f47dae739931ad0d"
dependencies = [
"cranelift-codegen",
"raw-cpuid",
@@ -416,9 +426,9 @@ dependencies = [
[[package]]
name = "cranelift-wasm"
version = "0.54.0"
version = "0.55.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0320733e518ab9e0e2d1a22034d40e2851fb403ed14db5220cf9b86576b9cfd4"
checksum = "038f8fd636abc83ccd6f110e0891766521c3599b52173c0f37e61c684f19a15d"
dependencies = [
"cranelift-codegen",
"cranelift-entity",
@@ -426,7 +436,7 @@ dependencies = [
"log",
"serde",
"thiserror",
"wasmparser 0.45.2",
"wasmparser 0.47.0",
]
[[package]]
@@ -513,8 +523,8 @@ version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cd8ce37ad4184ab2ce004c33bf6379185d3b1c95801cab51026bd271bf68eedc"
dependencies = [
"quote",
"syn",
"quote 1.0.2",
"syn 1.0.13",
]
[[package]]
@@ -526,6 +536,17 @@ dependencies = [
"cfg-if",
]
[[package]]
name = "derive_arbitrary"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b979a9f98d526ac07489ae2879e04d948ceeb195d777742997a30c3d1ab1aad6"
dependencies = [
"proc-macro2 0.4.30",
"syn 0.14.9",
"synstructure 0.9.0",
]
[[package]]
name = "digest"
version = "0.8.1"
@@ -567,9 +588,9 @@ dependencies = [
"byteorder",
"lazy_static",
"owning_ref",
"proc-macro2",
"quote",
"syn",
"proc-macro2 1.0.7",
"quote 1.0.2",
"syn 1.0.13",
]
[[package]]
@@ -667,10 +688,10 @@ version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0bc225b78e0391e4b8683440bf2e63c2deeeb2ce5189eab46e2b68c6d3725d08"
dependencies = [
"proc-macro2",
"quote",
"syn",
"synstructure",
"proc-macro2 1.0.7",
"quote 1.0.2",
"syn 1.0.13",
"synstructure 0.12.3",
]
[[package]]
@@ -745,9 +766,9 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2a36606a68532b5640dc86bb1f33c64b45c4682aad4c50f3937b317ea387f3d6"
dependencies = [
"proc-macro2",
"quote",
"syn",
"proc-macro2 1.0.7",
"quote 1.0.2",
"syn 1.0.13",
]
[[package]]
@@ -839,9 +860,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b714fc08d0961716390977cdff1536234415ac37b509e34e5a983def8340fb75"
dependencies = [
"proc-macro-hack",
"proc-macro2",
"quote",
"syn",
"proc-macro2 1.0.7",
"quote 1.0.2",
"syn 1.0.13",
"unindent",
]
@@ -862,9 +883,9 @@ version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a8e30575afe28eea36a9a39136b70b2fb6b0dd0a212a5bd1f30a498395c0274"
dependencies = [
"proc-macro2",
"quote",
"syn",
"proc-macro2 1.0.7",
"quote 1.0.2",
"syn 1.0.13",
]
[[package]]
@@ -917,10 +938,11 @@ checksum = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558"
[[package]]
name = "libfuzzer-sys"
version = "0.1.0"
source = "git+https://github.com/rust-fuzz/libfuzzer-sys.git#0c4507533a79e85e1984f59765bdd35fbdaa7f1b"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94f9e4f036a9cb9f43c637990c03fe045425a33c1c44abf9bc6f555671be5969"
dependencies = [
"arbitrary",
"arbitrary 0.3.2",
"cc",
]
@@ -1144,9 +1166,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4214c9e912ef61bf42b81ba9a47e8aad1b2ffaf739ab162bf96d1e011f54e6c5"
dependencies = [
"proc-macro-hack",
"proc-macro2",
"quote",
"syn",
"proc-macro2 1.0.7",
"quote 1.0.2",
"syn 1.0.13",
]
[[package]]
@@ -1185,10 +1207,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53c98547ceaea14eeb26fcadf51dc70d01a2479a7839170eae133721105e4428"
dependencies = [
"proc-macro-error-attr",
"proc-macro2",
"quote",
"proc-macro2 1.0.7",
"quote 1.0.2",
"rustversion",
"syn",
"syn 1.0.13",
]
[[package]]
@@ -1197,10 +1219,10 @@ version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2bf5d493cf5d3e296beccfd61794e445e830dfc8070a9c248ad3ee071392c6c"
dependencies = [
"proc-macro2",
"quote",
"proc-macro2 1.0.7",
"quote 1.0.2",
"rustversion",
"syn",
"syn 1.0.13",
"syn-mid",
]
@@ -1210,9 +1232,18 @@ version = "0.5.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ecd45702f76d6d3c75a80564378ae228a85f0b59d2f3ed43c91b4a69eb2ebfc5"
dependencies = [
"proc-macro2",
"quote",
"syn",
"proc-macro2 1.0.7",
"quote 1.0.2",
"syn 1.0.13",
]
[[package]]
name = "proc-macro2"
version = "0.4.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759"
dependencies = [
"unicode-xid 0.1.0",
]
[[package]]
@@ -1221,7 +1252,7 @@ version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0319972dcae462681daf4da1adeeaa066e3ebd29c69be96c6abb1259d2ee2bcc"
dependencies = [
"unicode-xid",
"unicode-xid 0.2.0",
]
[[package]]
@@ -1251,9 +1282,9 @@ version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4882d8237fd8c7373cc25cb802fe0dab9ff70830fd56f47ef6c7f3f287fcc057"
dependencies = [
"proc-macro2",
"quote",
"syn",
"proc-macro2 1.0.7",
"quote 1.0.2",
"syn 1.0.13",
]
[[package]]
@@ -1262,10 +1293,10 @@ version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fdf321cfab555f7411298733c86d21e5136f5ded13f5872fabf9de3337beecda"
dependencies = [
"proc-macro2",
"proc-macro2 1.0.7",
"pyo3-derive-backend",
"quote",
"syn",
"quote 1.0.2",
"syn 1.0.13",
]
[[package]]
@@ -1286,13 +1317,22 @@ dependencies = [
"rand_core 0.5.1",
]
[[package]]
name = "quote"
version = "0.6.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1"
dependencies = [
"proc-macro2 0.4.30",
]
[[package]]
name = "quote"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe"
dependencies = [
"proc-macro2",
"proc-macro2 1.0.7",
]
[[package]]
@@ -1517,9 +1557,9 @@ version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3a0538bd897e17257b0128d2fd95c2ed6df939374073a36166051a79e2eb7986"
dependencies = [
"proc-macro2",
"quote",
"syn",
"proc-macro2 1.0.7",
"quote 1.0.2",
"syn 1.0.13",
]
[[package]]
@@ -1549,9 +1589,9 @@ version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8584eea9b9ff42825b46faf46a8c24d2cff13ec152fa2a50df788b87c07ee28"
dependencies = [
"proc-macro2",
"quote",
"syn",
"proc-macro2 1.0.7",
"quote 1.0.2",
"syn 1.0.13",
]
[[package]]
@@ -1584,9 +1624,9 @@ version = "1.0.104"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "128f9e303a5a29922045a830221b8f78ec74a5f544944f3d5984f8ec3895ef64"
dependencies = [
"proc-macro2",
"quote",
"syn",
"proc-macro2 1.0.7",
"quote 1.0.2",
"syn 1.0.13",
]
[[package]]
@@ -1669,9 +1709,20 @@ checksum = "0a97f829a34a0a9d5b353a881025a23b8c9fd09d46be6045df6b22920dbd7a93"
dependencies = [
"heck",
"proc-macro-error",
"proc-macro2",
"quote",
"syn",
"proc-macro2 1.0.7",
"quote 1.0.2",
"syn 1.0.13",
]
[[package]]
name = "syn"
version = "0.14.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "261ae9ecaa397c42b960649561949d69311f08eeaea86a65696e6e46517cf741"
dependencies = [
"proc-macro2 0.4.30",
"quote 0.6.13",
"unicode-xid 0.1.0",
]
[[package]]
@@ -1680,9 +1731,9 @@ version = "1.0.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e4ff033220a41d1a57d8125eab57bf5263783dfdcc18688b1dacc6ce9651ef8"
dependencies = [
"proc-macro2",
"quote",
"unicode-xid",
"proc-macro2 1.0.7",
"quote 1.0.2",
"unicode-xid 0.2.0",
]
[[package]]
@@ -1691,9 +1742,21 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9fd3937748a7eccff61ba5b90af1a20dbf610858923a9192ea0ecb0cb77db1d0"
dependencies = [
"proc-macro2",
"quote",
"syn",
"proc-macro2 1.0.7",
"quote 1.0.2",
"syn 1.0.13",
]
[[package]]
name = "synstructure"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85bb9b7550d063ea184027c9b8c20ac167cd36d3e06b3a40bceb9d746dc1a7b7"
dependencies = [
"proc-macro2 0.4.30",
"quote 0.6.13",
"syn 0.14.9",
"unicode-xid 0.1.0",
]
[[package]]
@@ -1702,10 +1765,10 @@ version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "67656ea1dc1b41b1451851562ea232ec2e5a80242139f7e679ceccfb5d61f545"
dependencies = [
"proc-macro2",
"quote",
"syn",
"unicode-xid",
"proc-macro2 1.0.7",
"quote 1.0.2",
"syn 1.0.13",
"unicode-xid 0.2.0",
]
[[package]]
@@ -1780,9 +1843,9 @@ version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb2e25d25307eb8436894f727aba8f65d07adf02e5b35a13cebed48bd282bfef"
dependencies = [
"proc-macro2",
"quote",
"syn",
"proc-macro2 1.0.7",
"quote 1.0.2",
"syn 1.0.13",
]
[[package]]
@@ -1861,6 +1924,12 @@ version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479"
[[package]]
name = "unicode-xid"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
[[package]]
name = "unicode-xid"
version = "0.2.0"
@@ -1921,9 +1990,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8757b0da38353d55a9687f4dee68a8f441f980dd36e16ab07d6e6c673f505f76"
dependencies = [
"heck",
"proc-macro2",
"quote",
"syn",
"proc-macro2 1.0.7",
"quote 1.0.2",
"syn 1.0.13",
]
[[package]]
@@ -1958,9 +2027,9 @@ dependencies = [
name = "wasi-common-cbindgen"
version = "0.9.0"
dependencies = [
"proc-macro2",
"quote",
"syn",
"proc-macro2 1.0.7",
"quote 1.0.2",
"syn 1.0.13",
"trybuild",
]
@@ -1988,12 +2057,6 @@ version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1527c84a5bd585215f29c06b0e2a5274e478ad4dfc970d26ffad66fdc6cb311d"
[[package]]
name = "wasmparser"
version = "0.45.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b4eab1d9971d0803729cba3617b56eb04fcb4bd25361cb63880ed41a42f20d5"
[[package]]
name = "wasmparser"
version = "0.47.0"
@@ -2015,6 +2078,7 @@ name = "wasmtime"
version = "0.9.0"
dependencies = [
"anyhow",
"backtrace",
"cfg-if",
"file-per-thread-logger",
"libc",
@@ -2031,6 +2095,13 @@ dependencies = [
"winapi",
]
[[package]]
name = "wasmtime-c-api"
version = "0.9.0"
dependencies = [
"wasmtime",
]
[[package]]
name = "wasmtime-cli"
version = "0.9.0"
@@ -2113,7 +2184,7 @@ dependencies = [
name = "wasmtime-fuzz"
version = "0.9.0"
dependencies = [
"arbitrary",
"arbitrary 0.2.0",
"env_logger 0.7.1",
"libfuzzer-sys",
"log",
@@ -2127,7 +2198,7 @@ name = "wasmtime-fuzzing"
version = "0.9.0"
dependencies = [
"anyhow",
"arbitrary",
"arbitrary 0.3.2",
"binaryen",
"env_logger 0.7.1",
"log",
@@ -2205,6 +2276,7 @@ dependencies = [
name = "wasmtime-runtime"
version = "0.9.0"
dependencies = [
"backtrace",
"cc",
"cfg-if",
"indexmap",
@@ -2233,9 +2305,9 @@ dependencies = [
name = "wasmtime-rust-macro"
version = "0.9.0"
dependencies = [
"proc-macro2",
"quote",
"syn",
"proc-macro2 1.0.7",
"quote 1.0.2",
"syn 1.0.13",
]
[[package]]
@@ -2323,8 +2395,8 @@ name = "wig"
version = "0.9.2"
dependencies = [
"heck",
"proc-macro2",
"quote",
"proc-macro2 1.0.7",
"quote 1.0.2",
"witx",
]

View File

@@ -55,6 +55,7 @@ members = [
"crates/fuzzing",
"crates/misc/rust",
"crates/misc/py",
"crates/c-api",
"fuzz",
]

View File

@@ -48,7 +48,7 @@ mkdir tmp/$api_pkgname/lib
mkdir tmp/$api_pkgname/include
cp LICENSE README.md tmp/$api_pkgname
mv bins-$src/* tmp/$api_pkgname/lib
cp crates/api/c-examples/wasm-c-api/include/wasm.h tmp/$api_pkgname/include
cp crates/c-api/examples/wasm-c-api/include/wasm.h tmp/$api_pkgname/include
mktarball $api_pkgname
# Move wheels to dist folder

View File

@@ -8,10 +8,6 @@ repository = "https://github.com/bytecodealliance/wasmtime"
readme = "README.md"
edition = "2018"
[lib]
name = "wasmtime"
crate-type = ["lib", "staticlib", "cdylib"]
[dependencies]
wasmtime-runtime = { path = "../runtime", version = "0.9.0" }
wasmtime-environ = { path = "../environ", version = "0.9.0" }
@@ -22,6 +18,7 @@ anyhow = "1.0.19"
region = "2.0.0"
libc = "0.2"
cfg-if = "0.1.9"
backtrace = "0.3.42"
[target.'cfg(target_os = "windows")'.dependencies]
winapi = "0.3.7"

View File

@@ -1,3 +1,8 @@
# Implementation of wasm-c-api in Rust
## Wasmtime Embedding API
https://github.com/WebAssembly/wasm-c-api
The `wasmtime` crate is an embedding API of the `wasmtime` WebAssembly runtime.
This is intended to be used in Rust projects and provides a high-level API of
working with WebAssembly modules.
If you're interested in embedding `wasmtime` in other languages, you may wish to
take a look a the [C embedding API](../c-api) instead!

View File

@@ -141,13 +141,12 @@ impl WrappedCallable for WasmtimeFn {
// Get the trampoline to call for this function.
let exec_code_buf = self
.store
.context()
.compiler()
.compiler_mut()
.get_published_trampoline(body, &signature, value_size)
.map_err(|e| Trap::new(format!("trampoline error: {:?}", e)))?;
// Call the trampoline.
if let Err(message) = unsafe {
if let Err(error) = unsafe {
self.instance.with_signals_on(|| {
wasmtime_runtime::wasmtime_call_trampoline(
vmctx,
@@ -156,8 +155,7 @@ impl WrappedCallable for WasmtimeFn {
)
})
} {
let trap =
take_api_trap().unwrap_or_else(|| Trap::new(format!("call error: {}", message)));
let trap = take_api_trap().unwrap_or_else(|| Trap::from_jit(error));
return Err(trap);
}

View File

@@ -1,53 +0,0 @@
use crate::Config;
use std::cell::{RefCell, RefMut};
use std::hash::{Hash, Hasher};
use std::rc::Rc;
use wasmtime_environ::settings;
use wasmtime_jit::{native, Compiler, Features};
#[derive(Clone)]
pub struct Context {
compiler: Rc<RefCell<Compiler>>,
features: Features,
debug_info: bool,
}
impl Context {
pub fn new(config: &Config) -> Context {
let isa = native::builder().finish(settings::Flags::new(config.flags.clone()));
Context::new_with_compiler(config, Compiler::new(isa, config.strategy))
}
pub fn new_with_compiler(config: &Config, compiler: Compiler) -> Context {
Context {
compiler: Rc::new(RefCell::new(compiler)),
features: config.features.clone(),
debug_info: config.debug_info,
}
}
pub(crate) fn debug_info(&self) -> bool {
self.debug_info
}
pub(crate) fn compiler(&self) -> RefMut<Compiler> {
self.compiler.borrow_mut()
}
}
impl Hash for Context {
fn hash<H>(&self, state: &mut H)
where
H: Hasher,
{
self.compiler.as_ptr().hash(state)
}
}
impl Eq for Context {}
impl PartialEq for Context {
fn eq(&self, other: &Context) -> bool {
Rc::ptr_eq(&self.compiler, &other.compiler)
}
}

View File

@@ -1,4 +1,3 @@
use crate::context::Context;
use crate::externals::Extern;
use crate::module::Module;
use crate::runtime::Store;
@@ -6,9 +5,6 @@ use crate::trampoline::take_api_trap;
use crate::trap::Trap;
use crate::types::{ExportType, ExternType};
use anyhow::{Error, Result};
use std::cell::RefCell;
use std::collections::{HashMap, HashSet};
use std::rc::Rc;
use wasmtime_jit::{CompiledModule, Resolver};
use wasmtime_runtime::{Export, InstanceHandle, InstantiationError};
@@ -29,19 +25,15 @@ fn instantiate_in_context(
data: &[u8],
imports: &[Extern],
module_name: Option<&str>,
context: Context,
exports: Rc<RefCell<HashMap<String, Option<wasmtime_runtime::Export>>>>,
) -> Result<(InstanceHandle, HashSet<Context>), Error> {
let mut contexts = HashSet::new();
let debug_info = context.debug_info();
) -> Result<InstanceHandle> {
let mut resolver = SimpleResolver { imports };
let mut compiled_module = CompiledModule::new(
&mut context.compiler(),
&mut store.compiler_mut(),
data,
module_name,
&mut resolver,
exports,
debug_info,
store.global_exports().clone(),
store.engine().config().debug_info,
)?;
// Register all module signatures
@@ -52,40 +44,30 @@ fn instantiate_in_context(
let instance = compiled_module.instantiate().map_err(|e| -> Error {
if let Some(trap) = take_api_trap() {
trap.into()
} else if let InstantiationError::StartTrap(msg) = e {
Trap::new(msg).into()
} else if let InstantiationError::StartTrap(trap) = e {
Trap::from_jit(trap).into()
} else {
e.into()
}
})?;
contexts.insert(context);
Ok((instance, contexts))
Ok(instance)
}
#[derive(Clone)]
pub struct Instance {
instance_handle: InstanceHandle,
module: Module,
// We need to keep CodeMemory alive.
contexts: HashSet<Context>,
exports: Box<[Extern]>,
}
impl Instance {
pub fn new(module: &Module, externs: &[Extern]) -> Result<Instance, Error> {
let store = module.store();
let context = store.context().clone();
let exports = store.global_exports().clone();
let (mut instance_handle, contexts) = instantiate_in_context(
module.store(),
let mut instance_handle = instantiate_in_context(
store,
module.binary().expect("binary"),
externs,
module.name(),
context,
exports,
)?;
let exports = {
@@ -104,7 +86,6 @@ impl Instance {
Ok(Instance {
instance_handle,
module: module.clone(),
contexts,
exports,
})
}
@@ -141,8 +122,6 @@ impl Instance {
}
pub fn from_handle(store: &Store, instance_handle: InstanceHandle) -> Instance {
let contexts = HashSet::new();
let mut exports = Vec::new();
let mut exports_types = Vec::new();
let mut mutable = instance_handle.clone();
@@ -175,7 +154,6 @@ impl Instance {
Instance {
instance_handle,
module,
contexts,
exports: exports.into_boxed_slice(),
}
}

View File

@@ -7,7 +7,6 @@
//! itself for consumption from other languages.
mod callable;
mod context;
mod externals;
mod instance;
mod module;
@@ -18,13 +17,11 @@ mod trap;
mod types;
mod values;
pub mod wasm;
pub use crate::callable::Callable;
pub use crate::externals::*;
pub use crate::instance::Instance;
pub use crate::module::Module;
pub use crate::r#ref::AnyRef;
pub use crate::r#ref::{AnyRef, HostInfo, HostRef};
pub use crate::runtime::{Config, Engine, OptLevel, Store, Strategy};
pub use crate::trap::{FrameInfo, Trap};
pub use crate::types::*;

View File

@@ -196,7 +196,7 @@ impl Module {
///
/// [binary]: https://webassembly.github.io/spec/core/binary/index.html
pub fn validate(store: &Store, binary: &[u8]) -> Result<()> {
let features = store.engine().config.features.clone();
let features = store.engine().config().features.clone();
let config = ValidatingParserConfig {
operator_config: OperatorValidatorConfig {
enable_threads: features.threads,

View File

@@ -1,4 +1,3 @@
use crate::context::Context;
use anyhow::Result;
use std::cell::RefCell;
use std::collections::HashMap;
@@ -8,7 +7,7 @@ use wasmtime_environ::{
ir,
settings::{self, Configurable},
};
use wasmtime_jit::{CompilationStrategy, Features};
use wasmtime_jit::{native, CompilationStrategy, Compiler, Features};
// Runtime Environment
@@ -297,7 +296,7 @@ pub enum OptLevel {
/// default settings.
#[derive(Default, Clone)]
pub struct Engine {
pub(crate) config: Arc<Config>,
config: Arc<Config>,
}
impl Engine {
@@ -308,6 +307,11 @@ impl Engine {
config: Arc::new(config.clone()),
}
}
/// Returns the configuration settings that this engine is using.
pub fn config(&self) -> &Config {
&self.config
}
}
// Store
@@ -337,7 +341,7 @@ pub struct Store {
struct StoreInner {
engine: Engine,
context: Context,
compiler: RefCell<Compiler>,
global_exports: Rc<RefCell<HashMap<String, Option<wasmtime_runtime::Export>>>>,
signature_cache: RefCell<HashMap<wasmtime_runtime::VMSharedSignatureIndex, ir::Signature>>,
}
@@ -345,10 +349,12 @@ struct StoreInner {
impl Store {
/// Creates a new store to be associated with the given [`Engine`].
pub fn new(engine: &Engine) -> Store {
let isa = native::builder().finish(settings::Flags::new(engine.config.flags.clone()));
let compiler = Compiler::new(isa, engine.config.strategy);
Store {
inner: Rc::new(StoreInner {
engine: engine.clone(),
context: Context::new(&engine.config),
compiler: RefCell::new(compiler),
global_exports: Rc::new(RefCell::new(HashMap::new())),
signature_cache: RefCell::new(HashMap::new()),
}),
@@ -360,8 +366,8 @@ impl Store {
&self.inner.engine
}
pub(crate) fn context(&self) -> &Context {
&self.inner.context
pub(crate) fn compiler_mut(&self) -> std::cell::RefMut<'_, Compiler> {
self.inner.compiler.borrow_mut()
}
// Specific to wasmtime: hack to pass memory around to wasi
@@ -377,7 +383,7 @@ impl Store {
signature: &ir::Signature,
) -> wasmtime_runtime::VMSharedSignatureIndex {
use std::collections::hash_map::Entry;
let index = self.context().compiler().signatures().register(signature);
let index = self.compiler_mut().signatures().register(signature);
match self.inner.signature_cache.borrow_mut().entry(index) {
Entry::Vacant(v) => {
v.insert(signature.clone());
@@ -398,7 +404,13 @@ impl Store {
.cloned()
}
pub(crate) fn ptr_eq(a: &Store, b: &Store) -> bool {
/// Returns whether the stores `a` and `b` refer to the same underlying
/// `Store`.
///
/// Because the `Store` type is reference counted multiple clones may point
/// to the same underlying storage, and this method can be used to determine
/// whether two stores are indeed the same.
pub fn same(a: &Store, b: &Store) -> bool {
Rc::ptr_eq(&a.inner, &b.inner)
}
}

View File

@@ -11,7 +11,9 @@ use wasmtime_environ::entity::{EntityRef, PrimaryMap};
use wasmtime_environ::ir::types;
use wasmtime_environ::isa::TargetIsa;
use wasmtime_environ::wasm::{DefinedFuncIndex, FuncIndex};
use wasmtime_environ::{ir, settings, CompiledFunction, Export, Module, TrapInformation};
use wasmtime_environ::{
ir, settings, CompiledFunction, CompiledFunctionUnwindInfo, Export, Module, TrapInformation,
};
use wasmtime_jit::trampoline::ir::{
ExternalName, Function, InstBuilder, MemFlags, StackSlotData, StackSlotKind,
};
@@ -136,6 +138,7 @@ fn make_trampoline(
let mut context = Context::new();
context.func = Function::with_name_signature(ExternalName::user(0, 0), signature.clone());
context.func.collect_frame_layout_info();
let ss = context.func.create_stack_slot(StackSlotData::new(
StackSlotKind::ExplicitSlot,
@@ -213,8 +216,7 @@ fn make_trampoline(
.map_err(|error| pretty_error(&context.func, Some(isa), error))
.expect("compile_and_emit");
let mut unwind_info = Vec::new();
context.emit_unwind_info(isa, &mut unwind_info);
let unwind_info = CompiledFunctionUnwindInfo::new(isa, &context);
let traps = trap_sink.traps;

View File

@@ -1,4 +1,5 @@
use crate::instance::Instance;
use backtrace::Backtrace;
use std::fmt;
use std::sync::Arc;
@@ -11,7 +12,8 @@ pub struct Trap {
struct TrapInner {
message: String,
trace: Vec<FrameInfo>,
wasm_trace: Vec<FrameInfo>,
native_trace: Backtrace,
}
fn _assert_trap_is_sync_and_send(t: &Trap) -> (&dyn Sync, &dyn Send) {
@@ -26,10 +28,29 @@ impl Trap {
/// assert_eq!("unexpected error", trap.message());
/// ```
pub fn new<I: Into<String>>(message: I) -> Self {
Trap::new_with_trace(message.into(), Backtrace::new_unresolved())
}
pub(crate) fn from_jit(jit: wasmtime_runtime::Trap) -> Self {
Trap::new_with_trace(jit.to_string(), jit.backtrace)
}
fn new_with_trace(message: String, native_trace: Backtrace) -> Self {
let mut wasm_trace = Vec::new();
for frame in native_trace.frames() {
let pc = frame.ip() as usize;
if let Some(info) = wasmtime_runtime::jit_function_registry::find(pc) {
wasm_trace.push(FrameInfo {
func_index: info.func_index as u32,
module_name: info.module_id.clone(),
})
}
}
Trap {
inner: Arc::new(TrapInner {
message: message.into(),
trace: Vec::new(),
message,
wasm_trace,
native_trace,
}),
}
}
@@ -40,7 +61,7 @@ impl Trap {
}
pub fn trace(&self) -> &[FrameInfo] {
&self.inner.trace
&self.inner.wasm_trace
}
}
@@ -48,7 +69,8 @@ impl fmt::Debug for Trap {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Trap")
.field("message", &self.inner.message)
.field("trace", &self.inner.trace)
.field("wasm_trace", &self.inner.wasm_trace)
.field("native_trace", &self.inner.native_trace)
.finish()
}
}
@@ -62,22 +84,29 @@ impl fmt::Display for Trap {
impl std::error::Error for Trap {}
#[derive(Debug)]
pub struct FrameInfo;
pub struct FrameInfo {
module_name: Option<String>,
func_index: u32,
}
impl FrameInfo {
pub fn instance(&self) -> *const Instance {
unimplemented!("FrameInfo::instance");
}
pub fn func_index() -> usize {
unimplemented!("FrameInfo::func_index");
pub fn func_index(&self) -> u32 {
self.func_index
}
pub fn func_offset() -> usize {
pub fn func_offset(&self) -> usize {
unimplemented!("FrameInfo::func_offset");
}
pub fn module_offset() -> usize {
pub fn module_offset(&self) -> usize {
unimplemented!("FrameInfo::module_offset");
}
pub fn module_name(&self) -> Option<&str> {
self.module_name.as_deref()
}
}

View File

@@ -16,7 +16,7 @@ fn test_invoke_func_via_table() -> Result<()> {
"#,
)?;
let module = Module::new(&store, &binary).context("> Error compiling module!")?;
let instance = Instance::new(&store, &module, &[]).context("> Error instantiating module!")?;
let instance = Instance::new(&module, &[]).context("> Error instantiating module!")?;
let f = instance
.find_export_by_name("table")

View File

@@ -41,3 +41,116 @@ fn test_trap_return() -> Result<(), String> {
Ok(())
}
#[test]
fn test_trap_trace() -> Result<(), String> {
let store = Store::default();
let binary = parse_str(
r#"
(module $hello_mod
(func (export "run") (call $hello))
(func $hello (unreachable))
)
"#,
)
.map_err(|e| format!("failed to parse WebAssembly text source: {}", e))?;
let module =
Module::new(&store, &binary).map_err(|e| format!("failed to compile module: {}", e))?;
let instance = Instance::new(&module, &[])
.map_err(|e| format!("failed to instantiate module: {:?}", e))?;
let run_func = instance.exports()[0]
.func()
.expect("expected function export");
let e = run_func.call(&[]).err().expect("error calling function");
let trace = e.trace();
assert_eq!(trace.len(), 2);
assert_eq!(trace[0].module_name().unwrap(), "hello_mod");
assert_eq!(trace[0].func_index(), 1);
assert_eq!(trace[1].module_name().unwrap(), "hello_mod");
assert_eq!(trace[1].func_index(), 0);
assert!(e.message().contains("unreachable"));
Ok(())
}
#[test]
fn test_trap_trace_cb() -> Result<(), String> {
struct ThrowCallback;
impl Callable for ThrowCallback {
fn call(&self, _params: &[Val], _results: &mut [Val]) -> Result<(), Trap> {
Err(Trap::new("cb throw"))
}
}
let store = Store::default();
let binary = parse_str(
r#"
(module $hello_mod
(import "" "throw" (func $throw))
(func (export "run") (call $hello))
(func $hello (call $throw))
)
"#,
)
.map_err(|e| format!("failed to parse WebAssembly text source: {}", e))?;
let fn_type = FuncType::new(Box::new([]), Box::new([]));
let fn_func = Func::new(&store, fn_type, Rc::new(ThrowCallback));
let module =
Module::new(&store, &binary).map_err(|e| format!("failed to compile module: {}", e))?;
let instance = Instance::new(&module, &[fn_func.into()])
.map_err(|e| format!("failed to instantiate module: {:?}", e))?;
let run_func = instance.exports()[0]
.func()
.expect("expected function export");
let e = run_func.call(&[]).err().expect("error calling function");
let trace = e.trace();
assert_eq!(trace.len(), 2);
assert_eq!(trace[0].module_name().unwrap(), "hello_mod");
assert_eq!(trace[0].func_index(), 1);
assert_eq!(trace[1].module_name().unwrap(), "hello_mod");
assert_eq!(trace[1].func_index(), 0);
assert_eq!(e.message(), "cb throw");
Ok(())
}
#[test]
fn test_trap_stack_overflow() -> Result<(), String> {
let store = Store::default();
let binary = parse_str(
r#"
(module $rec_mod
(func $run (export "run") (call $run))
)
"#,
)
.map_err(|e| format!("failed to parse WebAssembly text source: {}", e))?;
let module =
Module::new(&store, &binary).map_err(|e| format!("failed to compile module: {}", e))?;
let instance = Instance::new(&module, &[])
.map_err(|e| format!("failed to instantiate module: {:?}", e))?;
let run_func = instance.exports()[0]
.func()
.expect("expected function export");
let e = run_func.call(&[]).err().expect("error calling function");
let trace = e.trace();
assert!(trace.len() >= 32);
for i in 0..trace.len() {
assert_eq!(trace[i].module_name().unwrap(), "rec_mod");
assert_eq!(trace[i].func_index(), 0);
}
assert!(e.message().contains("call stack exhausted"));
Ok(())
}

20
crates/c-api/Cargo.toml Normal file
View File

@@ -0,0 +1,20 @@
[package]
name = "wasmtime-c-api"
version = "0.9.0"
authors = ["The Wasmtime Project Developers"]
description = "C API to expose the Wasmtime runtime"
license = "Apache-2.0 WITH LLVM-exception"
repository = "https://github.com/bytecodealliance/wasmtime"
readme = "README.md"
edition = "2018"
publish = false
[lib]
name = "wasmtime"
crate-type = ["staticlib", "cdylib"]
doc = false
test = false
doctest = false
[dependencies]
wasmtime = { path = "../api" }

220
crates/c-api/LICENSE Normal file
View File

@@ -0,0 +1,220 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
--- LLVM Exceptions to the Apache 2.0 License ----
As an exception, if, as a result of your compiling your source code, portions
of this Software are embedded into an Object form of such source code, you
may redistribute such embedded portions in such Object form without complying
with the conditions of Sections 4(a), 4(b) and 4(d) of the License.
In addition, if you combine or link compiled forms of this Software with
software that is licensed under the GPLv2 ("Combined Software") and if a
court of competent jurisdiction determines that the patent provision (Section
3), the indemnity provision (Section 9) or other Section of the License
conflicts with the conditions of the GPLv2, you may retroactively and
prospectively choose to deem waived or otherwise exclude such Section(s) of
the License, but only in their entirety and only with respect to the Combined
Software.

3
crates/c-api/README.md Normal file
View File

@@ -0,0 +1,3 @@
# Implementation of wasm-c-api in Rust
https://github.com/WebAssembly/wasm-c-api

View File

@@ -5,15 +5,14 @@
// TODO complete the C API
use super::{
AnyRef, Callable, Engine, ExportType, Extern, ExternType, Func, FuncType, Global, GlobalType,
ImportType, Instance, Limits, Memory, MemoryType, Module, Store, Table, TableType, Trap, Val,
ValType,
};
use crate::r#ref::{HostInfo, HostRef};
use std::cell::RefCell;
use std::rc::Rc;
use std::{mem, ptr, slice};
use wasmtime::{
AnyRef, Callable, Engine, ExportType, Extern, ExternType, Func, FuncType, Global, GlobalType,
HostInfo, HostRef, ImportType, Instance, Limits, Memory, MemoryType, Module, Store, Table,
TableType, Trap, Val, ValType,
};
macro_rules! declare_vec {
($name:ident, $elem_ty:path) => {
@@ -569,14 +568,18 @@ impl wasm_val_t {
}
}
impl Callable for wasm_func_callback_t {
struct Callback {
callback: wasm_func_callback_t,
}
impl Callable for Callback {
fn call(&self, params: &[Val], results: &mut [Val]) -> Result<(), Trap> {
let params = params
.iter()
.map(|p| wasm_val_t::from_val(p))
.collect::<Vec<_>>();
let mut out_results = vec![wasm_val_t::default(); results.len()];
let func = self.expect("wasm_func_callback_t fn");
let func = self.callback.expect("wasm_func_callback_t fn");
let out = unsafe { func(params.as_ptr(), out_results.as_mut_ptr()) };
if !out.is_null() {
let trap: Box<wasm_trap_t> = unsafe { Box::from_raw(out) };
@@ -633,7 +636,7 @@ pub unsafe extern "C" fn wasm_func_new(
) -> *mut wasm_func_t {
let store = &(*store).store.borrow();
let ty = (*ty).functype.clone();
let callback = Rc::new(callback);
let callback = Rc::new(Callback { callback });
let func = Box::new(wasm_func_t {
ext: wasm_extern_t {
which: ExternHost::Func(HostRef::new(Func::new(store, ty, callback))),
@@ -700,7 +703,7 @@ pub unsafe extern "C" fn wasm_instance_new(
let module = &(*module).module.borrow();
// FIXME(WebAssembly/wasm-c-api#126) what else can we do with the `store`
// argument?
if !Store::ptr_eq(&store, module.store()) {
if !Store::same(&store, module.store()) {
if !result.is_null() {
let trap = Trap::new("wasm_store_t must match store in wasm_module_t");
let trap = Box::new(wasm_trap_t {
@@ -1254,7 +1257,7 @@ pub unsafe extern "C" fn wasm_globaltype_content(
pub unsafe extern "C" fn wasm_globaltype_mutability(
gt: *const wasm_globaltype_t,
) -> wasm_mutability_t {
use super::Mutability::*;
use wasmtime::Mutability::*;
match (*gt).globaltype.mutability() {
Const => 0,
Var => 1,
@@ -1411,7 +1414,7 @@ pub unsafe extern "C" fn wasm_globaltype_new(
ty: *mut wasm_valtype_t,
mutability: wasm_mutability_t,
) -> *mut wasm_globaltype_t {
use super::Mutability::*;
use wasmtime::Mutability::*;
let ty = Box::from_raw(ty);
let mutability = match mutability {
0 => Const,

View File

@@ -13,9 +13,9 @@ edition = "2018"
[dependencies]
anyhow = "1.0"
cranelift-codegen = { version = "0.54", features = ["enable-serde"] }
cranelift-entity = { version = "0.54", features = ["enable-serde"] }
cranelift-wasm = { version = "0.54", features = ["enable-serde"] }
cranelift-codegen = { version = "0.55", features = ["enable-serde"] }
cranelift-entity = { version = "0.55", features = ["enable-serde"] }
cranelift-wasm = { version = "0.55", features = ["enable-serde"] }
wasmparser = "0.47.0"
lightbeam = { path = "../lightbeam", optional = true, version = "0.9.0" }
indexmap = "1.0.2"
@@ -46,7 +46,7 @@ tempfile = "3"
target-lexicon = { version = "0.10.0", default-features = false }
pretty_env_logger = "0.3.0"
rand = { version = "0.7.0", default-features = false, features = ["small_rng"] }
cranelift-codegen = { version = "0.54", features = ["enable-serde", "all-arch"] }
cranelift-codegen = { version = "0.55", features = ["enable-serde", "all-arch"] }
filetime = "0.2.7"
[badges]

View File

@@ -1,7 +1,9 @@
use super::config::tests::test_prolog;
use super::*;
use crate::address_map::{FunctionAddressMap, InstructionAddressMap};
use crate::compilation::{CompiledFunction, Relocation, RelocationTarget, TrapInformation};
use crate::compilation::{
CompiledFunction, CompiledFunctionUnwindInfo, Relocation, RelocationTarget, TrapInformation,
};
use crate::module::{MemoryPlan, MemoryStyle, Module};
use cranelift_codegen::{binemit, ir, isa, settings, ValueLocRange};
use cranelift_entity::EntityRef;
@@ -259,7 +261,7 @@ fn new_module_cache_data(rng: &mut impl Rng) -> ModuleCacheData {
CompiledFunction {
body: (0..(i * 3 / 2)).collect(),
jt_offsets: sm,
unwind_info: (0..(i * 3 / 2)).collect(),
unwind_info: CompiledFunctionUnwindInfo::Windows((0..(i * 3 / 2)).collect()),
}
})
.collect();

View File

@@ -4,13 +4,136 @@
use crate::cache::ModuleCacheDataTupleType;
use crate::module;
use crate::module_environ::FunctionBodyData;
use cranelift_codegen::{binemit, ir, isa};
use cranelift_codegen::{binemit, ir, isa, Context};
use cranelift_entity::PrimaryMap;
use cranelift_wasm::{DefinedFuncIndex, FuncIndex, ModuleTranslationState, WasmError};
use serde::{Deserialize, Serialize};
use std::ops::Range;
use thiserror::Error;
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
pub struct FDERelocEntry(pub i64, pub usize, pub u8);
/// Relocation entry for unwind info.
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
pub struct CompiledFunctionUnwindInfoReloc {
/// Entry offest in the code block.
pub offset: u32,
/// Entry addend relative to the code block.
pub addend: u32,
}
/// Compiled function unwind information.
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
pub enum CompiledFunctionUnwindInfo {
/// No info.
None,
/// Windows UNWIND_INFO.
Windows(Vec<u8>),
/// Frame layout info.
FrameLayout(Vec<u8>, usize, Vec<FDERelocEntry>),
}
impl CompiledFunctionUnwindInfo {
/// Constructs unwind info object.
pub fn new(isa: &dyn isa::TargetIsa, context: &Context) -> Self {
use cranelift_codegen::binemit::{
FrameUnwindKind, FrameUnwindOffset, FrameUnwindSink, Reloc,
};
use cranelift_codegen::isa::CallConv;
struct Sink(Vec<u8>, usize, Vec<FDERelocEntry>);
impl FrameUnwindSink for Sink {
fn len(&self) -> FrameUnwindOffset {
self.0.len()
}
fn bytes(&mut self, b: &[u8]) {
self.0.extend_from_slice(b);
}
fn reserve(&mut self, len: usize) {
self.0.reserve(len)
}
fn reloc(&mut self, r: Reloc, off: FrameUnwindOffset) {
self.2.push(FDERelocEntry(
0,
off,
match r {
Reloc::Abs4 => 4,
Reloc::Abs8 => 8,
_ => {
panic!("unexpected reloc type");
}
},
))
}
fn set_entry_offset(&mut self, off: FrameUnwindOffset) {
self.1 = off;
}
}
let kind = match context.func.signature.call_conv {
CallConv::SystemV | CallConv::Fast | CallConv::Cold => FrameUnwindKind::Libunwind,
CallConv::WindowsFastcall => FrameUnwindKind::Fastcall,
_ => {
return CompiledFunctionUnwindInfo::None;
}
};
let mut sink = Sink(Vec::new(), 0, Vec::new());
context.emit_unwind_info(isa, kind, &mut sink);
let Sink(data, offset, relocs) = sink;
if data.is_empty() {
return CompiledFunctionUnwindInfo::None;
}
match kind {
FrameUnwindKind::Fastcall => CompiledFunctionUnwindInfo::Windows(data),
FrameUnwindKind::Libunwind => {
CompiledFunctionUnwindInfo::FrameLayout(data, offset, relocs)
}
}
}
/// Retuns true is no unwind info data.
pub fn is_empty(&self) -> bool {
match self {
CompiledFunctionUnwindInfo::None => true,
CompiledFunctionUnwindInfo::Windows(d) => d.is_empty(),
CompiledFunctionUnwindInfo::FrameLayout(c, _, _) => c.is_empty(),
}
}
/// Returns size of serilized unwind info.
pub fn len(&self) -> usize {
match self {
CompiledFunctionUnwindInfo::None => 0,
CompiledFunctionUnwindInfo::Windows(d) => d.len(),
CompiledFunctionUnwindInfo::FrameLayout(c, _, _) => c.len(),
}
}
/// Serializes data into byte array.
pub fn serialize(&self, dest: &mut [u8], relocs: &mut Vec<CompiledFunctionUnwindInfoReloc>) {
match self {
CompiledFunctionUnwindInfo::None => (),
CompiledFunctionUnwindInfo::Windows(d) => {
dest.copy_from_slice(d);
}
CompiledFunctionUnwindInfo::FrameLayout(code, _fde_offset, r) => {
dest.copy_from_slice(code);
r.iter().for_each(move |r| {
assert_eq!(r.2, 8);
relocs.push(CompiledFunctionUnwindInfoReloc {
offset: r.1 as u32,
addend: r.0 as u32,
})
});
}
}
}
}
/// Compiled function: machine code body, jump table offsets, and unwind information.
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
pub struct CompiledFunction {
@@ -21,7 +144,7 @@ pub struct CompiledFunction {
pub jt_offsets: ir::JumpTableOffsets,
/// The unwind information.
pub unwind_info: Vec<u8>,
pub unwind_info: CompiledFunctionUnwindInfo,
}
type Functions = PrimaryMap<DefinedFuncIndex, CompiledFunction>;
@@ -50,7 +173,7 @@ impl Compilation {
.map(|(body_range, jt_offsets, unwind_range)| CompiledFunction {
body: buffer[body_range].to_vec(),
jt_offsets,
unwind_info: buffer[unwind_range].to_vec(),
unwind_info: CompiledFunctionUnwindInfo::Windows(buffer[unwind_range].to_vec()),
})
.collect(),
)

View File

@@ -3,7 +3,8 @@
use crate::address_map::{FunctionAddressMap, InstructionAddressMap};
use crate::cache::{ModuleCacheData, ModuleCacheDataTupleType, ModuleCacheEntry};
use crate::compilation::{
Compilation, CompileError, CompiledFunction, Relocation, RelocationTarget, TrapInformation,
Compilation, CompileError, CompiledFunction, CompiledFunctionUnwindInfo, Relocation,
RelocationTarget, TrapInformation,
};
use crate::func_environ::{
get_func_name, get_imported_memory32_grow_name, get_imported_memory32_size_name,
@@ -204,6 +205,7 @@ impl crate::compilation::Compiler for Cranelift {
context.func.name = get_func_name(func_index);
context.func.signature =
module.signatures[module.functions[func_index]].clone();
context.func.collect_frame_layout_info();
if generate_debug_info {
context.func.collect_debug_info();
}
@@ -217,7 +219,6 @@ impl crate::compilation::Compiler for Cranelift {
)?;
let mut code_buf: Vec<u8> = Vec::new();
let mut unwind_info = Vec::new();
let mut reloc_sink = RelocSink::new(func_index);
let mut trap_sink = TrapSink::new();
let mut stackmap_sink = binemit::NullStackmapSink {};
@@ -233,7 +234,7 @@ impl crate::compilation::Compiler for Cranelift {
CompileError::Codegen(pretty_error(&context.func, Some(isa), error))
})?;
context.emit_unwind_info(isa, &mut unwind_info);
let unwind_info = CompiledFunctionUnwindInfo::new(isa, &context);
let address_transform = if generate_debug_info {
let body_len = code_buf.len();

View File

@@ -362,8 +362,8 @@ impl<'module_environment> TargetEnvironment for FuncEnvironment<'module_environm
}
impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'module_environment> {
fn is_wasm_parameter(&self, func: &ir::Function, index: usize) -> bool {
func.signature.params[index].purpose == ir::ArgumentPurpose::Normal
fn is_wasm_parameter(&self, signature: &ir::Signature, index: usize) -> bool {
signature.params[index].purpose == ir::ArgumentPurpose::Normal
}
fn make_table(&mut self, func: &mut ir::Function, index: TableIndex) -> WasmResult<ir::Table> {

View File

@@ -44,8 +44,9 @@ pub use crate::address_map::{
};
pub use crate::cache::{create_new_config as cache_create_new_config, init as cache_init};
pub use crate::compilation::{
Compilation, CompileError, CompiledFunction, Compiler, Relocation, RelocationTarget,
Relocations, TrapInformation, Traps,
Compilation, CompileError, CompiledFunction, CompiledFunctionUnwindInfo,
CompiledFunctionUnwindInfoReloc, Compiler, Relocation, RelocationTarget, Relocations,
TrapInformation, Traps,
};
pub use crate::cranelift::Cranelift;
pub use crate::data_structures::*;

View File

@@ -10,7 +10,7 @@ version = "0.9.0"
[dependencies]
anyhow = "1.0.22"
arbitrary = "0.2.0"
arbitrary = { version = "0.3.2", features = ["derive"] }
binaryen = "0.8.2"
env_logger = { version = "0.7.1", optional = true }
log = "0.4.8"

View File

@@ -31,13 +31,17 @@ impl fmt::Debug for WasmOptTtf {
}
impl Arbitrary for WasmOptTtf {
fn arbitrary<U>(input: &mut U) -> Result<Self, U::Error>
where
U: Unstructured + ?Sized,
{
fn arbitrary(input: &mut Unstructured) -> arbitrary::Result<Self> {
let seed: Vec<u8> = Arbitrary::arbitrary(input)?;
let module = binaryen::tools::translate_to_fuzz_mvp(&seed);
let wasm = module.write();
Ok(WasmOptTtf { wasm })
}
fn arbitrary_take_rest(input: Unstructured) -> arbitrary::Result<Self> {
let seed: Vec<u8> = Arbitrary::arbitrary_take_rest(input)?;
let module = binaryen::tools::translate_to_fuzz_mvp(&seed);
let wasm = module.write();
Ok(WasmOptTtf { wasm })
}
}

View File

@@ -15,8 +15,9 @@
//! [swarm testing]: https://www.cs.utah.edu/~regehr/papers/swarm12.pdf
use arbitrary::{Arbitrary, Unstructured};
use std::collections::HashSet;
use std::collections::BTreeSet;
#[derive(Arbitrary, Debug)]
struct Swarm {
config_debug_info: bool,
module_new: bool,
@@ -26,24 +27,8 @@ struct Swarm {
call_exported_func: bool,
}
impl Arbitrary for Swarm {
fn arbitrary<U>(input: &mut U) -> Result<Self, U::Error>
where
U: Unstructured + ?Sized,
{
Ok(Swarm {
config_debug_info: bool::arbitrary(input)?,
module_new: bool::arbitrary(input)?,
module_drop: bool::arbitrary(input)?,
instance_new: bool::arbitrary(input)?,
instance_drop: bool::arbitrary(input)?,
call_exported_func: bool::arbitrary(input)?,
})
}
}
/// A call to one of Wasmtime's public APIs.
#[derive(Clone, Debug)]
#[derive(Arbitrary, Clone, Debug)]
#[allow(missing_docs)]
pub enum ApiCall {
ConfigNew,
@@ -61,8 +46,8 @@ use ApiCall::*;
#[derive(Default)]
struct Scope {
id_counter: usize,
modules: HashSet<usize>,
instances: HashSet<usize>,
modules: BTreeSet<usize>,
instances: BTreeSet<usize>,
}
impl Scope {
@@ -81,10 +66,7 @@ pub struct ApiCalls {
}
impl Arbitrary for ApiCalls {
fn arbitrary<U>(input: &mut U) -> Result<Self, U::Error>
where
U: Unstructured + ?Sized,
{
fn arbitrary(input: &mut Unstructured) -> arbitrary::Result<Self> {
let swarm = Swarm::arbitrary(input)?;
let mut calls = vec![];
@@ -94,8 +76,8 @@ impl Arbitrary for ApiCalls {
let mut scope = Scope::default();
for _ in 0..input.container_size()? {
let mut choices: Vec<fn(_, &mut Scope) -> Result<ApiCall, U::Error>> = vec![];
for _ in 0..input.arbitrary_len::<ApiCall>()? {
let mut choices: Vec<fn(_, &mut Scope) -> arbitrary::Result<ApiCall>> = vec![];
if swarm.module_new {
choices.push(|input, scope| {
@@ -108,7 +90,7 @@ impl Arbitrary for ApiCalls {
if swarm.module_drop && !scope.modules.is_empty() {
choices.push(|input, scope| {
let modules: Vec<_> = scope.modules.iter().cloned().collect();
let id = arbitrary_choice(input, &modules)?.cloned().unwrap();
let id = *input.choose(&modules)?;
scope.modules.remove(&id);
Ok(ModuleDrop { id })
});
@@ -116,7 +98,7 @@ impl Arbitrary for ApiCalls {
if swarm.instance_new && !scope.modules.is_empty() {
choices.push(|input, scope| {
let modules: Vec<_> = scope.modules.iter().cloned().collect();
let module = arbitrary_choice(input, &modules)?.cloned().unwrap();
let module = *input.choose(&modules)?;
let id = scope.next_id();
scope.instances.insert(id);
Ok(InstanceNew { id, module })
@@ -125,7 +107,7 @@ impl Arbitrary for ApiCalls {
if swarm.instance_drop && !scope.instances.is_empty() {
choices.push(|input, scope| {
let instances: Vec<_> = scope.instances.iter().cloned().collect();
let id = arbitrary_choice(input, &instances)?.cloned().unwrap();
let id = *input.choose(&instances)?;
scope.instances.remove(&id);
Ok(InstanceDrop { id })
});
@@ -133,43 +115,28 @@ impl Arbitrary for ApiCalls {
if swarm.call_exported_func && !scope.instances.is_empty() {
choices.push(|input, scope| {
let instances: Vec<_> = scope.instances.iter().cloned().collect();
let instance = arbitrary_choice(input, &instances)?.cloned().unwrap();
let instance = *input.choose(&instances)?;
let nth = usize::arbitrary(input)?;
Ok(CallExportedFunc { instance, nth })
});
}
if let Some(c) = arbitrary_choice(input, &choices)? {
calls.push(c(input, &mut scope)?);
} else {
if choices.is_empty() {
break;
}
let c = input.choose(&choices)?;
calls.push(c(input, &mut scope)?);
}
Ok(ApiCalls { calls })
}
}
fn arbitrary_choice<'a, T, U>(input: &mut U, choices: &'a [T]) -> Result<Option<&'a T>, U::Error>
where
U: Unstructured + ?Sized,
{
if choices.is_empty() {
Ok(None)
} else {
let i = usize::arbitrary(input)? % choices.len();
Ok(Some(&choices[i]))
}
}
fn arbitrary_config<U>(
input: &mut U,
fn arbitrary_config(
input: &mut Unstructured,
swarm: &Swarm,
calls: &mut Vec<ApiCall>,
) -> Result<(), U::Error>
where
U: Unstructured + ?Sized,
{
) -> arbitrary::Result<()> {
calls.push(ConfigNew);
if swarm.config_debug_info && bool::arbitrary(input)? {

View File

@@ -11,11 +11,11 @@ readme = "README.md"
edition = "2018"
[dependencies]
cranelift-codegen = { version = "0.54", features = ["enable-serde"] }
cranelift-entity = { version = "0.54", features = ["enable-serde"] }
cranelift-wasm = { version = "0.54", features = ["enable-serde"] }
cranelift-native = "0.54"
cranelift-frontend = "0.54"
cranelift-codegen = { version = "0.55", features = ["enable-serde"] }
cranelift-entity = { version = "0.55", features = ["enable-serde"] }
cranelift-wasm = { version = "0.55", features = ["enable-serde"] }
cranelift-native = "0.55"
cranelift-frontend = "0.55"
wasmtime-environ = { path = "../environ", version = "0.9.0" }
wasmtime-runtime = { path = "../runtime", version = "0.9.0" }
wasmtime-debug = { path = "../debug", version = "0.9.0" }

View File

@@ -6,7 +6,7 @@ use std::cmp::max;
use std::{fmt, mem, ptr, slice};
use thiserror::Error;
use wasmtime_environ::ir;
use wasmtime_runtime::{wasmtime_call_trampoline, Export, InstanceHandle, VMInvokeArgument};
use wasmtime_runtime::{wasmtime_call_trampoline, Export, InstanceHandle, Trap, VMInvokeArgument};
/// A runtime value.
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
@@ -100,10 +100,7 @@ pub enum ActionOutcome {
},
/// A trap occurred while the action was executing.
Trapped {
/// The trap message.
message: String,
},
Trapped(Trap),
}
/// An error detected while invoking a wasm function or reading a wasm global.
@@ -191,7 +188,7 @@ pub fn invoke(
compiler.publish_compiled_code();
// Call the trampoline.
if let Err(message) = unsafe {
if let Err(trap) = unsafe {
instance.with_signals_on(|| {
wasmtime_call_trampoline(
callee_vmctx,
@@ -200,7 +197,7 @@ pub fn invoke(
)
})
} {
return Ok(ActionOutcome::Trapped { message });
return Ok(ActionOutcome::Trapped(trap));
}
// Load the return values out of `values_vec`.

View File

@@ -2,14 +2,45 @@
use crate::function_table::FunctionTable;
use region;
use std::mem::ManuallyDrop;
use std::{cmp, mem};
use wasmtime_environ::{Compilation, CompiledFunction};
use wasmtime_runtime::{Mmap, VMFunctionBody};
struct CodeMemoryEntry {
mmap: ManuallyDrop<Mmap>,
table: ManuallyDrop<FunctionTable>,
}
impl CodeMemoryEntry {
fn new() -> Self {
Self {
mmap: ManuallyDrop::new(Mmap::new()),
table: ManuallyDrop::new(FunctionTable::new()),
}
}
fn with_capacity(cap: usize) -> Result<Self, String> {
Ok(Self {
mmap: ManuallyDrop::new(Mmap::with_at_least(cap)?),
table: ManuallyDrop::new(FunctionTable::new()),
})
}
}
impl Drop for CodeMemoryEntry {
fn drop(&mut self) {
unsafe {
// Table needs to be freed before mmap.
ManuallyDrop::drop(&mut self.table);
ManuallyDrop::drop(&mut self.mmap);
}
}
}
/// Memory manager for executable code.
pub struct CodeMemory {
current: (Mmap, FunctionTable),
mmaps: Vec<(Mmap, FunctionTable)>,
current: CodeMemoryEntry,
entries: Vec<CodeMemoryEntry>,
position: usize,
published: usize,
}
@@ -23,8 +54,8 @@ impl CodeMemory {
/// Create a new `CodeMemory` instance.
pub fn new() -> Self {
Self {
current: (Mmap::new(), FunctionTable::new()),
mmaps: Vec::new(),
current: CodeMemoryEntry::new(),
entries: Vec::new(),
position: 0,
published: 0,
}
@@ -81,19 +112,20 @@ impl CodeMemory {
self.push_current(0)
.expect("failed to push current memory map");
for (m, t) in &mut self.mmaps[self.published..] {
for CodeMemoryEntry { mmap: m, table: t } in &mut self.entries[self.published..] {
// Remove write access to the pages due to the relocation fixups.
t.publish(m.as_ptr() as u64)
.expect("failed to publish function table");
if !m.is_empty() {
unsafe {
region::protect(m.as_mut_ptr(), m.len(), region::Protection::ReadExecute)
}
.expect("unable to make memory readonly and executable");
}
t.publish(m.as_ptr() as u64)
.expect("failed to publish function table");
}
self.published = self.mmaps.len();
self.published = self.entries.len();
}
/// Allocate `size` bytes of memory which can be made executable later by
@@ -103,7 +135,7 @@ impl CodeMemory {
///
/// TODO: Add an alignment flag.
fn allocate(&mut self, size: usize) -> Result<(&mut [u8], &mut FunctionTable), String> {
if self.current.0.len() - self.position < size {
if self.current.mmap.len() - self.position < size {
self.push_current(cmp::max(0x10000, size))?;
}
@@ -111,8 +143,8 @@ impl CodeMemory {
self.position += size;
Ok((
&mut self.current.0.as_mut_slice()[old_position..self.position],
&mut self.current.1,
&mut self.current.mmap.as_mut_slice()[old_position..self.position],
&mut self.current.table,
))
}
@@ -153,12 +185,19 @@ impl CodeMemory {
// Keep unwind information 32-bit aligned (round up to the nearest 4 byte boundary)
let padding = ((func.body.len() + 3) & !3) - func.body.len();
let (unwind, remainder) = remainder.split_at_mut(padding + func.unwind_info.len());
unwind[padding..].copy_from_slice(&func.unwind_info);
let mut relocs = Vec::new();
func.unwind_info
.serialize(&mut unwind[padding..], &mut relocs);
let unwind_start = func_end + (padding as u32);
let unwind_end = unwind_start + (func.unwind_info.len() as u32);
table.add_function(func_start, func_end, unwind_start);
relocs.iter_mut().for_each(move |r| {
r.offset += unwind_start;
r.addend += func_start;
});
table.add_function(func_start, func_end, unwind_start, &relocs);
(unwind_end, remainder, table, vmfunc)
}
@@ -174,20 +213,17 @@ impl CodeMemory {
fn push_current(&mut self, new_size: usize) -> Result<(), String> {
let previous = mem::replace(
&mut self.current,
(
if new_size == 0 {
Mmap::new()
CodeMemoryEntry::new()
} else {
Mmap::with_at_least(cmp::max(0x10000, new_size))?
CodeMemoryEntry::with_capacity(cmp::max(0x10000, new_size))?
},
FunctionTable::new(),
),
);
if !previous.0.is_empty() {
self.mmaps.push(previous);
if !previous.mmap.is_empty() {
self.entries.push(previous);
} else {
assert_eq!(previous.1.len(), 0);
assert_eq!(previous.table.len(), 0);
}
self.position = 0;

View File

@@ -16,12 +16,12 @@ use wasmtime_environ::entity::{EntityRef, PrimaryMap};
use wasmtime_environ::isa::{TargetFrontendConfig, TargetIsa};
use wasmtime_environ::wasm::{DefinedFuncIndex, DefinedMemoryIndex};
use wasmtime_environ::{
Compilation, CompileError, CompiledFunction, Compiler as _C, FunctionBodyData, Module,
ModuleVmctxInfo, Relocations, Traps, Tunables, VMOffsets,
Compilation, CompileError, CompiledFunction, CompiledFunctionUnwindInfo, Compiler as _C,
FunctionBodyData, Module, ModuleVmctxInfo, Relocations, Traps, Tunables, VMOffsets,
};
use wasmtime_runtime::{
get_mut_trap_registry, InstantiationError, SignatureRegistry, TrapRegistrationGuard,
VMFunctionBody,
get_mut_trap_registry, jit_function_registry, InstantiationError, SignatureRegistry,
TrapRegistrationGuard, VMFunctionBody,
};
/// Select which kind of compilation to use.
@@ -51,6 +51,7 @@ pub struct Compiler {
code_memory: CodeMemory,
trap_registration_guards: Vec<TrapRegistrationGuard>,
jit_function_ranges: Vec<(usize, usize)>,
trampoline_park: HashMap<*const VMFunctionBody, *const VMFunctionBody>,
signatures: SignatureRegistry,
strategy: CompilationStrategy,
@@ -66,6 +67,7 @@ impl Compiler {
isa,
code_memory: CodeMemory::new(),
trap_registration_guards: Vec::new(),
jit_function_ranges: Vec::new(),
trampoline_park: HashMap::new(),
signatures: SignatureRegistry::new(),
fn_builder_ctx: FunctionBuilderContext::new(),
@@ -85,6 +87,10 @@ impl Drop for Compiler {
// Having a custom drop implementation we are independent from the field order
// in the struct what reduces potential human error.
self.trap_registration_guards.clear();
for (start, end) in self.jit_function_ranges.iter() {
jit_function_registry::unregister(*start, *end);
}
}
}
@@ -155,6 +161,18 @@ impl Compiler {
&mut self.trap_registration_guards,
);
for (i, allocated) in allocated_functions.iter() {
let ptr = (*allocated) as *const VMFunctionBody;
let body_len = compilation.get(i).body.len();
self.jit_function_ranges
.push((ptr as usize, ptr as usize + body_len));
let tag = jit_function_registry::JITFunctionTag {
module_id: module.name.clone(),
func_index: i.index(),
};
jit_function_registry::register(ptr as usize, ptr as usize + body_len, tag);
}
let dbg = if let Some(debug_data) = debug_data {
let target_config = self.isa.frontend_config();
let ofs = VMOffsets::new(target_config.pointer_bytes(), &module);
@@ -215,6 +233,7 @@ impl Compiler {
signature,
value_size,
)?;
entry.insert(body);
body
}
@@ -266,6 +285,7 @@ fn make_trampoline(
let mut context = Context::new();
context.func = ir::Function::with_name_signature(ir::ExternalName::user(0, 0), wrapper_sig);
context.func.collect_frame_layout_info();
{
let mut builder = FunctionBuilder::new(&mut context.func, fn_builder_ctx);
@@ -326,7 +346,6 @@ fn make_trampoline(
}
let mut code_buf = Vec::new();
let mut unwind_info = Vec::new();
let mut reloc_sink = RelocSink {};
let mut trap_sink = binemit::NullTrapSink {};
let mut stackmap_sink = binemit::NullStackmapSink {};
@@ -346,7 +365,7 @@ fn make_trampoline(
)))
})?;
context.emit_unwind_info(isa, &mut unwind_info);
let unwind_info = CompiledFunctionUnwindInfo::new(isa, &context);
Ok(code_memory
.allocate_for_function(&CompiledFunction {

View File

@@ -2,42 +2,7 @@
//!
//! This module is primarily used to track JIT functions on Windows for stack walking and unwind.
/// Represents a runtime function table.
///
/// The runtime function table is not implemented for non-Windows target platforms.
#[cfg(not(target_os = "windows"))]
pub(crate) struct FunctionTable;
#[cfg(not(target_os = "windows"))]
impl FunctionTable {
/// Creates a new function table.
pub fn new() -> Self {
Self
}
/// Returns the number of functions in the table, also referred to as its 'length'.
///
/// For non-Windows platforms, the table will always be empty.
pub fn len(&self) -> usize {
0
}
/// Adds a function to the table based off of the start offset, end offset, and unwind offset.
///
/// The offsets are from the "module base", which is provided when the table is published.
///
/// For non-Windows platforms, this is a no-op.
pub fn add_function(&mut self, _start: u32, _end: u32, _unwind: u32) {}
/// Publishes the function table using the given base address.
///
/// A published function table will automatically be deleted when it is dropped.
///
/// For non-Windows platforms, this is a no-op.
pub fn publish(&mut self, _base_address: u64) -> Result<(), String> {
Ok(())
}
}
type FunctionTableReloc = wasmtime_environ::CompiledFunctionUnwindInfoReloc;
/// Represents a runtime function table.
///
@@ -66,7 +31,14 @@ impl FunctionTable {
/// Adds a function to the table based off of the start offset, end offset, and unwind offset.
///
/// The offsets are from the "module base", which is provided when the table is published.
pub fn add_function(&mut self, start: u32, end: u32, unwind: u32) {
pub fn add_function(
&mut self,
start: u32,
end: u32,
unwind: u32,
_relocs: &[FunctionTableReloc],
) {
assert_eq!(_relocs.len(), 0);
use winapi::um::winnt;
assert!(!self.published, "table has already been published");
@@ -133,3 +105,106 @@ impl Drop for FunctionTable {
}
}
}
/// Represents a runtime function table.
///
/// This is used to register JIT code with the operating system to enable stack walking and unwinding.
#[cfg(any(target_os = "macos", target_os = "linux"))]
pub(crate) struct FunctionTable {
functions: Vec<u32>,
relocs: Vec<FunctionTableReloc>,
published: Option<Vec<usize>>,
}
#[cfg(any(target_os = "macos", target_os = "linux"))]
impl FunctionTable {
/// Creates a new function table.
pub fn new() -> Self {
Self {
functions: Vec::new(),
relocs: Vec::new(),
published: None,
}
}
/// Returns the number of functions in the table, also referred to as its 'length'.
pub fn len(&self) -> usize {
self.functions.len()
}
/// Adds a function to the table based off of the start offset, end offset, and unwind offset.
///
/// The offsets are from the "module base", which is provided when the table is published.
pub fn add_function(
&mut self,
_start: u32,
_end: u32,
unwind: u32,
relocs: &[FunctionTableReloc],
) {
assert!(self.published.is_none(), "table has already been published");
self.functions.push(unwind);
self.relocs.extend_from_slice(relocs);
}
/// Publishes the function table using the given base address.
///
/// A published function table will automatically be deleted when it is dropped.
pub fn publish(&mut self, base_address: u64) -> Result<(), String> {
if self.published.is_some() {
return Err("function table was already published".into());
}
if self.functions.is_empty() {
assert_eq!(self.relocs.len(), 0);
self.published = Some(vec![]);
return Ok(());
}
extern "C" {
// libunwind import
fn __register_frame(fde: *const u8);
}
for reloc in self.relocs.iter() {
let addr = base_address + (reloc.offset as u64);
let target = base_address + (reloc.addend as u64);
unsafe {
std::ptr::write(addr as *mut u64, target);
}
}
let mut fdes = Vec::with_capacity(self.functions.len());
for unwind_offset in self.functions.iter() {
let addr = base_address + (*unwind_offset as u64);
let off = unsafe { std::ptr::read::<u32>(addr as *const u32) } as usize + 4;
let fde = (addr + off as u64) as usize;
unsafe {
__register_frame(fde as *const _);
}
fdes.push(fde);
}
self.published = Some(fdes);
Ok(())
}
}
#[cfg(any(target_os = "macos", target_os = "linux"))]
impl Drop for FunctionTable {
fn drop(&mut self) {
extern "C" {
// libunwind import
fn __deregister_frame(fde: *const u8);
}
if self.published.is_some() {
unsafe {
for fde in self.published.as_ref().unwrap() {
__deregister_frame(*fde as *const _);
}
}
}
}
}

View File

@@ -19,7 +19,7 @@ memoffset = "0.5.3"
itertools = "0.8.2"
capstone = "0.6.0"
thiserror = "1.0.9"
cranelift-codegen = "0.54"
cranelift-codegen = "0.55"
multi_mut = "0.1"
either = "1.5"
typemap = "0.3"

View File

@@ -2,5 +2,6 @@
<PropertyGroup>
<WasmtimeVersion>0.8.0</WasmtimeVersion>
<WasmtimeLibraryName>wasmtime</WasmtimeLibraryName>
<WasmtimePackageName>wasmtime-c-api</WasmtimePackageName>
</PropertyGroup>
</Project>

View File

@@ -6,7 +6,7 @@
<LibraryExtension Condition="'$(LibraryExtension)' == ''">.so</LibraryExtension>
<WasmtimeLibraryFilename>$(LibraryPrefix)$(WasmtimeLibraryName)$(LibraryExtension)</WasmtimeLibraryFilename>
<WasmtimeOutputPath>$(MSBuildThisFileDirectory)../../../target/$(Configuration.ToLower())</WasmtimeOutputPath>
<BuildWasmtimeCommand Condition="'$(Configuration)' == 'Release'">cargo build --release -p $(WasmtimeLibraryName)</BuildWasmtimeCommand>
<BuildWasmtimeCommand Condition="'$(BuildWasmtimeCommand)' == ''">cargo build -p $(WasmtimeLibraryName)</BuildWasmtimeCommand>
<BuildWasmtimeCommand Condition="'$(Configuration)' == 'Release'">cargo build --release -p $(WasmtimePackageName)</BuildWasmtimeCommand>
<BuildWasmtimeCommand Condition="'$(BuildWasmtimeCommand)' == ''">cargo build -p $(WasmtimePackageName)</BuildWasmtimeCommand>
</PropertyGroup>
</Project>

View File

@@ -20,6 +20,7 @@ indexmap = "1.0.2"
thiserror = "1.0.4"
more-asserts = "0.2.1"
cfg-if = "0.1.9"
backtrace = "0.3.42"
[target.'cfg(target_os = "windows")'.dependencies]
winapi = { version = "0.3.7", features = ["winbase", "memoryapi"] }

View File

@@ -9,7 +9,7 @@ use crate::memory::LinearMemory;
use crate::mmap::Mmap;
use crate::signalhandlers::{wasmtime_init_eager, wasmtime_init_finish};
use crate::table::Table;
use crate::traphandlers::wasmtime_call;
use crate::traphandlers::{wasmtime_call, Trap};
use crate::vmcontext::{
VMBuiltinFunctionsArray, VMCallerCheckedAnyfunc, VMContext, VMFunctionBody, VMFunctionImport,
VMGlobalDefinition, VMGlobalImport, VMMemoryDefinition, VMMemoryImport, VMSharedSignatureIndex,
@@ -1398,6 +1398,6 @@ pub enum InstantiationError {
Link(#[from] LinkError),
/// A compilation error occured.
#[error("Trap occurred while invoking start function: {0}")]
StartTrap(String),
#[error("Trap occurred while invoking start function")]
StartTrap(#[source] Trap),
}

View File

@@ -0,0 +1,83 @@
#![allow(missing_docs)]
use lazy_static::lazy_static;
use std::collections::BTreeMap;
use std::sync::{Arc, RwLock};
lazy_static! {
static ref REGISTRY: RwLock<JITFunctionRegistry> = RwLock::new(JITFunctionRegistry::default());
}
#[derive(Clone)]
pub struct JITFunctionTag {
pub module_id: Option<String>,
pub func_index: usize,
}
impl std::fmt::Debug for JITFunctionTag {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if let Some(ref module_id) = self.module_id {
write!(f, "{}", module_id)?;
} else {
write!(f, "(module)")?;
}
write!(f, ":{}", self.func_index)
}
}
struct JITFunctionRegistry {
ranges: BTreeMap<usize, (usize, Arc<JITFunctionTag>)>,
}
impl Default for JITFunctionRegistry {
fn default() -> Self {
Self {
ranges: Default::default(),
}
}
}
impl JITFunctionRegistry {
fn register(&mut self, fn_start: usize, fn_end: usize, tag: JITFunctionTag) {
self.ranges.insert(fn_end, (fn_start, Arc::new(tag)));
}
fn unregister(&mut self, fn_end: usize) {
self.ranges.remove(&fn_end);
}
fn find(&self, pc: usize) -> Option<&Arc<JITFunctionTag>> {
self.ranges
.range(pc..)
.next()
.and_then(|(end, (start, s))| {
if *start <= pc && pc < *end {
Some(s)
} else {
None
}
})
}
}
pub fn register(fn_start: usize, fn_end: usize, tag: JITFunctionTag) {
REGISTRY
.write()
.expect("jit function registry lock got poisoned")
.register(fn_start, fn_end, tag);
}
pub fn unregister(_fn_start: usize, fn_end: usize) {
REGISTRY
.write()
.expect("jit function registry lock got poisoned")
.unregister(fn_end);
}
pub fn find(pc: usize) -> Option<Arc<JITFunctionTag>> {
REGISTRY
.read()
.expect("jit function registry lock got poisoned")
.find(pc)
.cloned()
}

View File

@@ -34,6 +34,7 @@ mod trap_registry;
mod traphandlers;
mod vmcontext;
pub mod jit_function_registry;
pub mod libcalls;
pub use crate::export::Export;
@@ -44,7 +45,7 @@ pub use crate::mmap::Mmap;
pub use crate::sig_registry::SignatureRegistry;
pub use crate::signalhandlers::{wasmtime_init_eager, wasmtime_init_finish};
pub use crate::trap_registry::{get_mut_trap_registry, get_trap_registry, TrapRegistrationGuard};
pub use crate::traphandlers::{wasmtime_call, wasmtime_call_trampoline};
pub use crate::traphandlers::{wasmtime_call, wasmtime_call_trampoline, Trap};
pub use crate::vmcontext::{
VMCallerCheckedAnyfunc, VMContext, VMFunctionBody, VMFunctionImport, VMGlobalDefinition,
VMGlobalImport, VMInvokeArgument, VMMemoryDefinition, VMMemoryImport, VMSharedSignatureIndex,

View File

@@ -4,7 +4,9 @@
use crate::trap_registry::get_trap_registry;
use crate::trap_registry::TrapDescription;
use crate::vmcontext::{VMContext, VMFunctionBody};
use backtrace::Backtrace;
use std::cell::Cell;
use std::fmt;
use std::ptr;
use wasmtime_environ::ir;
@@ -18,7 +20,7 @@ extern "C" {
}
thread_local! {
static RECORDED_TRAP: Cell<Option<TrapDescription>> = Cell::new(None);
static RECORDED_TRAP: Cell<Option<Trap>> = Cell::new(None);
static JMP_BUF: Cell<*const u8> = Cell::new(ptr::null());
static RESET_GUARD_PAGE: Cell<bool> = Cell::new(false);
}
@@ -43,24 +45,26 @@ pub extern "C" fn CheckIfTrapAtAddress(_pc: *const u8) -> i8 {
pub extern "C" fn RecordTrap(pc: *const u8, reset_guard_page: bool) {
// TODO: please see explanation in CheckIfTrapAtAddress.
let registry = get_trap_registry();
let trap_desc = registry
let trap = Trap {
desc: registry
.get_trap(pc as usize)
.unwrap_or_else(|| TrapDescription {
source_loc: ir::SourceLoc::default(),
trap_code: ir::TrapCode::StackOverflow,
});
}),
backtrace: Backtrace::new_unresolved(),
};
if reset_guard_page {
RESET_GUARD_PAGE.with(|v| v.set(true));
}
RECORDED_TRAP.with(|data| {
assert_eq!(
data.get(),
None,
let prev = data.replace(Some(trap));
assert!(
prev.is_none(),
"Only one trap per thread can be recorded at a moment!"
);
data.set(Some(trap_desc))
});
}
@@ -108,16 +112,33 @@ fn reset_guard_page() {
#[cfg(not(target_os = "windows"))]
fn reset_guard_page() {}
fn trap_message() -> String {
let trap_desc = RECORDED_TRAP
.with(|data| data.replace(None))
.expect("trap_message must be called after trap occurred");
/// Stores trace message with backtrace.
#[derive(Debug)]
pub struct Trap {
/// What sort of trap happened, as well as where in the original wasm module
/// it happened.
pub desc: TrapDescription,
/// Native stack backtrace at the time the trap occurred
pub backtrace: Backtrace,
}
format!(
impl fmt::Display for Trap {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"wasm trap: {}, source location: {}",
trap_code_to_expected_string(trap_desc.trap_code),
trap_desc.source_loc,
trap_code_to_expected_string(self.desc.trap_code),
self.desc.source_loc
)
}
}
impl std::error::Error for Trap {}
fn last_trap() -> Trap {
RECORDED_TRAP
.with(|data| data.replace(None))
.expect("trap_message must be called after trap occurred")
}
fn trap_code_to_expected_string(trap_code: ir::TrapCode) -> String {
@@ -146,9 +167,9 @@ pub unsafe extern "C" fn wasmtime_call_trampoline(
vmctx: *mut VMContext,
callee: *const VMFunctionBody,
values_vec: *mut u8,
) -> Result<(), String> {
) -> Result<(), Trap> {
if WasmtimeCallTrampoline(vmctx as *mut u8, callee, values_vec) == 0 {
Err(trap_message())
Err(last_trap())
} else {
Ok(())
}
@@ -160,9 +181,9 @@ pub unsafe extern "C" fn wasmtime_call_trampoline(
pub unsafe extern "C" fn wasmtime_call(
vmctx: *mut VMContext,
callee: *const VMFunctionBody,
) -> Result<(), String> {
) -> Result<(), Trap> {
if WasmtimeCall(vmctx as *mut u8, callee) == 0 {
Err(trap_message())
Err(last_trap())
} else {
Ok(())
}

View File

@@ -14,9 +14,9 @@ edition = "2018"
wasmtime-runtime = { path = "../runtime", version = "0.9.0" }
wasmtime-environ = { path = "../environ", version = "0.9.0" }
wasmtime-jit = { path = "../jit", version = "0.9.0" }
cranelift-codegen = { version = "0.54", features = ["enable-serde"] }
cranelift-entity = { version = "0.54", features = ["enable-serde"] }
cranelift-wasm = { version = "0.54", features = ["enable-serde"] }
cranelift-codegen = { version = "0.55", features = ["enable-serde"] }
cranelift-entity = { version = "0.55", features = ["enable-serde"] }
cranelift-wasm = { version = "0.55", features = ["enable-serde"] }
target-lexicon = "0.10.0"
log = { version = "0.4.8", default-features = false }
libc = "0.2.60"

View File

@@ -1,4 +1,4 @@
use std::io::{Result, Write};
use std::io::{IoSlice, Result, Write};
/// An adapter around a `Write` stream that guarantees that its output
/// is valid UTF-8 and contains no control characters. It does this by
@@ -124,6 +124,27 @@ where
return Ok(result);
}
fn write_vectored(&mut self, bufs: &[IoSlice]) -> Result<usize> {
// Terminal output is [not expected to be atomic], so just write all the
// individual buffers in sequence.
//
// [not expected to be atomic]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/read.html#tag_16_474_08
let mut total_written = 0;
for buf in bufs {
let written = self.write(buf)?;
total_written += written;
// Stop at the first point where the OS writes less than we asked.
if written < buf.len() {
break;
}
}
Ok(total_written)
}
fn flush(&mut self) -> Result<()> {
self.inner.flush()
}

View File

@@ -16,9 +16,9 @@ wasmtime-runtime = { path = "../runtime", version = "0.9.0" }
wasmtime-environ = { path = "../environ", version = "0.9.0" }
wasmtime-jit = { path = "../jit", version = "0.9.0" }
wasi-common = { path = "../wasi-common", version = "0.9.0" }
cranelift-codegen = { version = "0.54", features = ["enable-serde"] }
cranelift-entity = { version = "0.54", features = ["enable-serde"] }
cranelift-wasm = { version = "0.54", features = ["enable-serde"] }
cranelift-codegen = { version = "0.55", features = ["enable-serde"] }
cranelift-entity = { version = "0.55", features = ["enable-serde"] }
cranelift-wasm = { version = "0.55", features = ["enable-serde"] }
target-lexicon = "0.10.0"
log = { version = "0.4.8", default-features = false }
wig = { path = "../wasi-common/wig", version = "0.9.2" }

View File

@@ -15,7 +15,7 @@ log = "0.4.8"
wasmtime-fuzzing = { path = "../crates/fuzzing", features = ["env_logger"] }
wasmtime-jit = { path = "../crates/jit" }
wasmtime = { path = "../crates/api" }
libfuzzer-sys = { git = "https://github.com/rust-fuzz/libfuzzer-sys.git" }
libfuzzer-sys = "0.2.0"
[[bin]]
name = "compile"

View File

@@ -9,7 +9,7 @@ topdir=$(dirname "$0")/..
cd "$topdir"
# All the cranelift-* crates have the same version number
version="0.53"
version="0.55"
# Update all of the Cargo.toml files.
echo "Updating crate versions to $version"

View File

@@ -17,8 +17,7 @@ use wasmtime_interface_types::ModuleData;
use wasmtime_wasi::{
create_wasi_instance, old::snapshot_0::create_wasi_instance as create_wasi_instance_snapshot_0,
};
#[cfg(feature = "wasi-c")]
use wasmtime_wasi_c::instantiate_wasi_c;
#[cfg(feature = "wasi-c")]
use wasmtime_wasi_c::instantiate_wasi_c;
@@ -152,7 +151,8 @@ impl RunCommand {
#[cfg(feature = "wasi-c")]
{
let global_exports = store.global_exports().clone();
let handle = instantiate_wasi_c(global_exports, &preopen_dirs, &argv, &self.vars)?;
let handle =
instantiate_wasi_c("", global_exports, &preopen_dirs, &argv, &self.vars)?;
Instance::from_handle(&store, handle)
}
#[cfg(not(feature = "wasi-c"))]

View File

@@ -128,9 +128,12 @@ mod tests {
{
println!("calling read_out_of_bounds...");
let trap = invoke_export(&instance, "read_out_of_bounds").unwrap_err();
assert!(trap
.message()
.starts_with("call error: wasm trap: out of bounds memory access"));
assert!(
trap.message()
.starts_with("wasm trap: out of bounds memory access"),
"bad trap message: {:?}",
trap.message()
);
}
// these invoke wasmtime_call_trampoline from callable.rs
@@ -151,7 +154,7 @@ mod tests {
let trap = read_out_of_bounds_func.call(&[]).unwrap_err();
assert!(trap
.message()
.starts_with("call error: wasm trap: out of bounds memory access"));
.starts_with("wasm trap: out of bounds memory access"));
}
Ok(())
}