mirror of
https://github.com/fluencelabs/wasmer
synced 2024-12-13 06:15:33 +00:00
Merge master into feature/llvm-backend
This commit is contained in:
commit
2d87f64f82
164
.appveyor.yml
164
.appveyor.yml
@ -1,151 +1,47 @@
|
||||
# This appveyor build file is heavily inspired by uutils/coreutils
|
||||
# https://raw.githubusercontent.com/uutils/coreutils/d0db7bbaa46dabf65b71e3e33b1ed7595aaacc56/.appveyor.yml
|
||||
|
||||
branches:
|
||||
except:
|
||||
- master
|
||||
|
||||
version: "{build} ~ {branch}"
|
||||
|
||||
os: Visual Studio 2017
|
||||
|
||||
matrix:
|
||||
allow_failures:
|
||||
- CHANNEL: stable
|
||||
# - ABI: gnu
|
||||
# Do not build feature branch with open Pull Requests
|
||||
skip_branch_with_pr: true
|
||||
|
||||
environment:
|
||||
matrix:
|
||||
# minimum version
|
||||
# - CHANNEL: 1.31.0
|
||||
# ARCH: i686
|
||||
# ABI: msvc
|
||||
# # "msvc" ABI
|
||||
# - CHANNEL: stable
|
||||
# ARCH: i686
|
||||
# ABI: msvc
|
||||
# - CHANNEL: stable
|
||||
# ARCH: x86_64
|
||||
# ABI: msvc
|
||||
# - CHANNEL: beta
|
||||
# ARCH: i686
|
||||
# ABI: msvc
|
||||
# - CHANNEL: beta
|
||||
# ARCH: x86_64
|
||||
# ABI: msvc
|
||||
# - CHANNEL: nightly
|
||||
# ARCH: i686
|
||||
# ABI: msvc
|
||||
# - CHANNEL: nightly
|
||||
# ARCH: x86_64
|
||||
# ABI: msvc
|
||||
# # "gnu" ABI
|
||||
# - CHANNEL: stable
|
||||
# ARCH: i686
|
||||
# ABI: gnu
|
||||
# - CHANNEL: stable
|
||||
# ARCH: x86_64
|
||||
# ABI: gnu
|
||||
# - CHANNEL: beta
|
||||
# ARCH: i686
|
||||
# ABI: gnu
|
||||
# - CHANNEL: beta
|
||||
# ARCH: x86_64
|
||||
# ABI: gnu
|
||||
# - CHANNEL: nightly
|
||||
# ARCH: i686
|
||||
# ABI: gnu
|
||||
# - CHANNEL: nightly
|
||||
# ARCH: x86_64
|
||||
# ABI: gnu
|
||||
# * specific gnu compilers
|
||||
# - CHANNEL: stable
|
||||
# ARCH: i686
|
||||
# ABI: gnu
|
||||
# MINGW_URL: https://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win32/Personal%20Builds/mingw-builds/4.9.2/threads-win32/dwarf/i686-4.9.2-release-win32-dwarf-rt_v4-rev4.7z/download
|
||||
# MINGW_ARCHIVE: i686-4.9.2-release-win32-dwarf-rt_v4-rev4.7z
|
||||
- CHANNEL: stable
|
||||
ARCH: x86_64
|
||||
ABI: gnu
|
||||
MINGW_URL: https://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win64/Personal%20Builds/mingw-builds/7.3.0/threads-posix/seh/x86_64-7.3.0-release-posix-seh-rt_v5-rev0.7z/download#mingw-w64-x86_64-7.3.0-posix-seh.7z
|
||||
ABI: msvc
|
||||
TARGET: x86_64-pc-windows-msvc
|
||||
|
||||
install:
|
||||
- echo %PATH%
|
||||
# force branch checkout (if knowable), then reset to the specific commit ## (can be needed for accurate code coverage info)
|
||||
# * this allows later apps to see the branch name using standard `git branch` operations, yet always builds the correct specific commit
|
||||
# * ref: <https://github.com/appveyor/ci/issues/1606>[`@`](https://archive.is/RVpnF)
|
||||
- if DEFINED APPVEYOR_REPO_BRANCH if /I "%APPVEYOR_REPO_SCM%"=="git" ( git checkout "%APPVEYOR_REPO_BRANCH%" & git reset --hard "%APPVEYOR_REPO_COMMIT%" )
|
||||
# ensure CWD is project main directory
|
||||
- cd "%APPVEYOR_BUILD_FOLDER%"
|
||||
# create a working area
|
||||
- ps: if ( ! $env:CI_TEMP_DIR ) { $env:CI_TEMP_DIR = "${env:TEMP}\${env:APPVEYOR_JOB_ID}" ; mkdir -force $env:CI_TEMP_DIR | out-null }
|
||||
|
||||
# rust installation
|
||||
- set "TARGET=%ARCH%-pc-windows-%ABI%"
|
||||
# * install `rust` via `rustup`
|
||||
- appveyor DownloadFile "https://win.rustup.rs/" -FileName "%CI_TEMP_DIR%\rustup-init.exe"
|
||||
- call "%CI_TEMP_DIR%\rustup-init.exe" -y --default-toolchain %CHANNEL% --default-host %TARGET% --no-modify-path >NUL
|
||||
- set "PATH=%PATH%;%USERPROFILE%\.cargo\bin"
|
||||
- ps: $env:TOOLCHAIN = $(rustup show active-toolchain)
|
||||
- rename "C:\Program Files\Git\usr\bin\sh.exe" sh2.exe
|
||||
# * set RUST_BACKTRACE for enhanced error messages
|
||||
- set RUST_BACKTRACE=1
|
||||
# * show versions
|
||||
- appveyor DownloadFile https://win.rustup.rs/ -FileName rustup-init.exe
|
||||
- rustup-init.exe -yv --default-host %target%
|
||||
- set PATH=%PATH%;%USERPROFILE%\.cargo\bin
|
||||
- rustc -vV
|
||||
- cargo -vV
|
||||
|
||||
# finalize FEATURES
|
||||
- if /i "%CHANNEL%"=="nightly" set "FEATURES=nightly"
|
||||
|
||||
# "gnu" ABI setup
|
||||
# * use the system MinGW/MSYS if we can
|
||||
- if /i "%ABI%"=="gnu" set MSYS_BINDIR=C:\msys64\usr\bin
|
||||
- if /i "%ABI%"=="gnu" if /i "%ARCH%"=="i686" set "MSYS_BITS=32"
|
||||
- if /i "%ABI%"=="gnu" if /i "%ARCH%"=="x86_64" set "MSYS_BITS=64"
|
||||
- if defined MSYS_BITS set "MSYS_MINGWDIR=C:\msys64\mingw%MSYS_BITS%"
|
||||
- if defined MSYS_MINGWDIR set "MSYS_BINDIR=C:\msys64\usr\bin"
|
||||
## * workaround for rust-lang/rust#47048 / rust-lang/rust#53454 ## !maint: remove when resolved
|
||||
- if /i "%ABI%"=="gnu" if /i "%ARCH%"=="i686" if not DEFINED MINGW_URL set "MINGW_URL=https://downloads.sourceforge.net/project/mingw-w64/Toolchains targetting Win32/Personal Builds/mingw-builds/8.1.0/threads-posix/dwarf/i686-8.1.0-release-posix-dwarf-rt_v6-rev0.7z"
|
||||
- if /i "%ABI%"=="gnu" if /i "%ARCH%"=="x86_64" if not DEFINED MINGW_URL set "MINGW_URL=https://downloads.sourceforge.net/project/mingw-w64/Toolchains targetting Win64/Personal Builds/mingw-builds/8.1.0/threads-posix/seh/x86_64-8.1.0-release-posix-seh-rt_v6-rev0.7z"
|
||||
##
|
||||
# * specific MinGW, if specified
|
||||
- ps: if ( ! $env:MINGW_ARCHIVE -and $env:MINGW_URL ) { $env:MINGW_ARCHIVE = $($([URI]$env:MINGW_URL).fragment).TrimStart('#') }
|
||||
- ps: if ( ! $env:MINGW_ARCHIVE -and $env:MINGW_URL ) { $env:MINGW_ARCHIVE = $([URI]$env:MINGW_URL).segments[-1] }
|
||||
- if defined MINGW_ARCHIVE curl --insecure -fsSL "%MINGW_URL%" -o "%CI_TEMP_DIR%\%MINGW_ARCHIVE%"
|
||||
- if defined MINGW_ARCHIVE mkdir "%CI_TEMP_DIR%\MinGW" >NUL
|
||||
- if defined MINGW_ARCHIVE 7z x -y "%CI_TEMP_DIR%\%MINGW_ARCHIVE%" -o"%CI_TEMP_DIR%\MinGW" >NUL
|
||||
- if defined MINGW_ARCHIVE set "MSYS_MINGWDIR=%CI_TEMP_DIR%\MinGW\mingw%MSYS_BITS%"
|
||||
- if defined MINGW_ARCHIVE set "MSYS_BINDIR=%MSYS_MINGWDIR%\bin"
|
||||
# * MinGW/MSYS PATH setup
|
||||
- if defined MSYS_MINGWDIR set PATH=%MSYS_MINGWDIR%\%ARCH%-w64-mingw32\bin;%MSYS_BINDIR%;%PATH%
|
||||
## * workaround for rust-lang/rust#47048 / rust-lang/rust#53454 ## !maint: remove when resolved
|
||||
# ** ref: <https://github.com/rust-lang/rust/issues/47048>, <https://github.com/rust-lang/rust/issues/53454>
|
||||
# ** egs: <https://github.com/pkgw/tectonic/commit/29686db533d8732d7d97fc94270ed33b77f29295>, <https://github.com/rukai/PF_Sandbox/blob/e842613cf9ff102dfb3fbd87381319e6e6dfe3ae/appveyor.yml>
|
||||
- if /i "%ABI%"=="gnu" rustup install %CHANNEL%-%ARCH%-pc-windows-msvc
|
||||
- if /i "%ABI%"=="gnu" rustup default %CHANNEL%-%ARCH%-pc-windows-msvc
|
||||
- if /i "%ABI%"=="gnu" rustup target add %TARGET%
|
||||
- if /i "%ABI%"=="gnu" rustup show
|
||||
- if /i "%ABI%"=="gnu" rustc -vV
|
||||
- ps: $env:TOOLCHAIN = $(rustup show active-toolchain)
|
||||
# ** copy libs from gcc toolchain to rust toolchain (more specifically, "crt2.o" and "dllcrt2.o" are needed)
|
||||
- if defined MSYS_MINGWDIR copy /y "%MSYS_MINGWDIR%\%ARCH%-w64-mingw32\lib\*.o" "%USERPROFILE%\.rustup\toolchains\%TOOLCHAIN%\lib\rustlib\%TARGET%\lib" >NUL
|
||||
##
|
||||
- if /i "%ABI%"=="gnu" where gcc
|
||||
- if /i "%ABI%"=="gnu" gcc --version
|
||||
|
||||
# "msvc" ABI setup
|
||||
- if /i "%ABI%" == "msvc" if /i "%ARCH%" == "i686" call "%VS140COMNTOOLS%\..\..\VC\vcvarsall.bat"
|
||||
- if /i "%ABI%" == "msvc" if /i "%ARCH%" == "x86_64" call "C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\SetEnv.cmd" /x64
|
||||
- if /i "%ABI%" == "msvc" if /i "%ARCH%" == "x86_64" call "%VS140COMNTOOLS%\..\..\VC\vcvarsall.bat" x86_amd64
|
||||
|
||||
artifacts:
|
||||
- path: target\%TARGET%\debug\wasmer.exe
|
||||
name: wasmer.exe
|
||||
|
||||
build_script:
|
||||
- set BUILD_CMD=cargo +%TOOLCHAIN% build --target=%TARGET%
|
||||
- echo [ %BUILD_CMD% ] & %BUILD_CMD%
|
||||
- cargo build --verbose
|
||||
|
||||
test_script:
|
||||
- set TEST_CMD=cargo +%TOOLCHAIN% test --target=%TARGET% --no-fail-fast
|
||||
- echo [ %TEST_CMD% ] & %TEST_CMD%
|
||||
- set RUST_BACKTRACE=1
|
||||
- cd ./lib/spectests && cargo test -- --test-threads 1 && cd ../..
|
||||
|
||||
before_deploy:
|
||||
- cd installer
|
||||
- iscc wasmer.iss
|
||||
- copy /y .\WasmerInstaller.exe ..\WasmerInstaller-%APPVEYOR_REPO_TAG_NAME%.exe
|
||||
- appveyor PushArtifact WasmerInstaller-%APPVEYOR_REPO_TAG_NAME%.exe
|
||||
|
||||
artifacts:
|
||||
- path: WasmerInstaller-%APPVEYOR_REPO_TAG_NAME%.exe
|
||||
name: WasmerInstaller.exe
|
||||
|
||||
deploy:
|
||||
description: 'WasmerInstaller'
|
||||
artifact: /.*\.exe/
|
||||
auth_token:
|
||||
secure: CaKtncy7S1PWxzDUQ0p2264pe3HwxzDn5VIyRizDaa72/SVfskNcoMjwwRh0ut22
|
||||
provider: GitHub
|
||||
on:
|
||||
branch: master
|
||||
appveyor_repo_tag: true
|
||||
|
@ -42,6 +42,7 @@ jobs:
|
||||
command: |
|
||||
sudo apt-get install -y cmake
|
||||
- run: make test
|
||||
- run: make integration-tests
|
||||
- save_cache:
|
||||
paths:
|
||||
- /usr/local/cargo/registry
|
||||
|
1173
Cargo.lock
generated
1173
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -27,7 +27,7 @@ wasmer-runtime-core = { path = "lib/runtime-core" }
|
||||
wasmer-emscripten = { path = "lib/emscripten" }
|
||||
|
||||
[workspace]
|
||||
members = ["lib/clif-backend", "lib/runtime", "lib/runtime-core", "lib/emscripten", "lib/spectests", "lib/llvm-backend"]
|
||||
members = ["lib/clif-backend", "lib/runtime", "lib/runtime-core", "lib/emscripten", "lib/spectests", "lib/win-exception-handler", "lib/llvm-backend"]
|
||||
|
||||
[build-dependencies]
|
||||
wabt = "0.7.2"
|
||||
|
2
Makefile
2
Makefile
@ -23,7 +23,7 @@ install:
|
||||
|
||||
integration-tests: release
|
||||
echo "Running Integration Tests"
|
||||
# Commented for now until we fix emscripten
|
||||
./integration_tests/lua/test.sh
|
||||
./integration_tests/nginx/test.sh
|
||||
|
||||
lint:
|
||||
|
10
README.md
10
README.md
@ -47,10 +47,10 @@ Wasmer is structured into different directories:
|
||||
|
||||
Building wasmer requires [rustup](https://rustup.rs/).
|
||||
|
||||
To install on Windows, download and run [`rustup-init.exe`](https://win.rustup.rs/)
|
||||
To build on Windows, download and run [`rustup-init.exe`](https://win.rustup.rs/)
|
||||
then follow the onscreen instructions.
|
||||
|
||||
To install on other systems, run:
|
||||
To build on other systems, run:
|
||||
|
||||
```sh
|
||||
curl https://sh.rustup.rs -sSf | sh
|
||||
@ -86,8 +86,8 @@ sudo apt install cmake
|
||||
|
||||
#### Windows (MSVC)
|
||||
|
||||
Right now Windows support is _highly experimental_.
|
||||
We are working on this so Wasmer can soon be released for Windows.
|
||||
Windows support is _highly experimental_. Only simple wasm programs may be run, and no syscalls are allowed. This means
|
||||
nginx and lua do not work on Windows. See [this issue for ongoing Emscripten syscall polyfills for Windows](https://github.com/wasmerio/wasmer/pull/176).
|
||||
|
||||
1. Install Python for Windows (https://www.python.org/downloads/release/python-2714/). The Windows x86-64 MSI installer is fine.
|
||||
You should change the installation to install the "Add python.exe to Path" feature.
|
||||
@ -95,6 +95,8 @@ We are working on this so Wasmer can soon be released for Windows.
|
||||
2. Install Git for Windows (https://git-scm.com/download/win). DO allow it to add git.exe to the PATH (default
|
||||
settings for the installer are fine).
|
||||
|
||||
3. Install CMake (https://cmake.org/download/). Ensure CMake is in the PATH.
|
||||
|
||||
## Building
|
||||
|
||||
Wasmer is built with [Cargo](https://crates.io/), the Rust package manager.
|
||||
|
71
installer/wasmer.iss
Normal file
71
installer/wasmer.iss
Normal file
@ -0,0 +1,71 @@
|
||||
[Setup]
|
||||
AppName=Wasmer
|
||||
AppVersion=1.5
|
||||
DefaultDirName={pf}\Wasmer
|
||||
DefaultGroupName=Wasmer
|
||||
Compression=lzma2
|
||||
SolidCompression=yes
|
||||
OutputDir=.\
|
||||
DisableProgramGroupPage=yes
|
||||
ChangesEnvironment=yes
|
||||
OutputBaseFilename=WasmerInstaller
|
||||
|
||||
[Files]
|
||||
Source: "..\target\release\wasmer.exe"; DestDir: "{app}\bin"
|
||||
|
||||
[Code]
|
||||
const EnvironmentKey = 'SYSTEM\CurrentControlSet\Control\Session Manager\Environment';
|
||||
|
||||
procedure EnvAddPath(Path: string);
|
||||
var
|
||||
Paths: string;
|
||||
begin
|
||||
{ Retrieve current path (use empty string if entry not exists) }
|
||||
if not RegQueryStringValue(HKEY_LOCAL_MACHINE, EnvironmentKey, 'Path', Paths)
|
||||
then Paths := '';
|
||||
|
||||
{ Skip if string already found in path }
|
||||
if Pos(';' + Uppercase(Path) + ';', ';' + Uppercase(Paths) + ';') > 0 then exit;
|
||||
|
||||
{ App string to the end of the path variable }
|
||||
Paths := Paths + ';'+ Path +';'
|
||||
|
||||
{ Overwrite (or create if missing) path environment variable }
|
||||
if RegWriteStringValue(HKEY_LOCAL_MACHINE, EnvironmentKey, 'Path', Paths)
|
||||
then Log(Format('The [%s] added to PATH: [%s]', [Path, Paths]))
|
||||
else Log(Format('Error while adding the [%s] to PATH: [%s]', [Path, Paths]));
|
||||
end;
|
||||
|
||||
procedure EnvRemovePath(Path: string);
|
||||
var
|
||||
Paths: string;
|
||||
P: Integer;
|
||||
begin
|
||||
{ Skip if registry entry not exists }
|
||||
if not RegQueryStringValue(HKEY_LOCAL_MACHINE, EnvironmentKey, 'Path', Paths) then
|
||||
exit;
|
||||
|
||||
{ Skip if string not found in path }
|
||||
P := Pos(';' + Uppercase(Path) + ';', ';' + Uppercase(Paths) + ';');
|
||||
if P = 0 then exit;
|
||||
|
||||
{ Update path variable }
|
||||
Delete(Paths, P - 1, Length(Path) + 1);
|
||||
|
||||
{ Overwrite path environment variable }
|
||||
if RegWriteStringValue(HKEY_LOCAL_MACHINE, EnvironmentKey, 'Path', Paths)
|
||||
then Log(Format('The [%s] removed from PATH: [%s]', [Path, Paths]))
|
||||
else Log(Format('Error while removing the [%s] from PATH: [%s]', [Path, Paths]));
|
||||
end;
|
||||
|
||||
procedure CurStepChanged(CurStep: TSetupStep);
|
||||
begin
|
||||
if CurStep = ssPostInstall
|
||||
then EnvAddPath(ExpandConstant('{app}') +'\bin');
|
||||
end;
|
||||
|
||||
procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);
|
||||
begin
|
||||
if CurUninstallStep = usPostUninstall
|
||||
then EnvRemovePath(ExpandConstant('{app}') +'\bin');
|
||||
end;
|
9
integration_tests/lua/README.md
Normal file
9
integration_tests/lua/README.md
Normal file
@ -0,0 +1,9 @@
|
||||
# `lua` integration test
|
||||
|
||||
|
||||
This starts wasmer with the lua wasm file. The test asserts on
|
||||
the output of wasmer. Run test with:
|
||||
|
||||
```
|
||||
> ./integration_tests/lua/test.sh
|
||||
```
|
15
integration_tests/lua/test.sh
Executable file
15
integration_tests/lua/test.sh
Executable file
@ -0,0 +1,15 @@
|
||||
#! /bin/bash
|
||||
|
||||
nohup ./target/release/wasmer run examples/lua.wasm &
|
||||
sleep 3s
|
||||
|
||||
if grep "Lua 5.4.0 Copyright (C) 1994-2018 Lua.org, PUC-Rio" ./nohup.out
|
||||
then
|
||||
echo "lua integration test succeeded"
|
||||
rm ./nohup.out
|
||||
exit 0
|
||||
else
|
||||
echo "lua integration test failed"
|
||||
rm ./nohup.out
|
||||
exit -1
|
||||
fi
|
@ -37,6 +37,10 @@ optional = true
|
||||
version = "0.0.7"
|
||||
optional = true
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
winapi = { version = "0.3", features = ["errhandlingapi", "minwindef", "minwinbase", "winnt"] }
|
||||
wasmer-win-exception-handler = { path = "../win-exception-handler", version = "0.0.1" }
|
||||
|
||||
[features]
|
||||
cache = ["serde", "serde_derive", "serde_bytes", "serde-bench", "wasmer-runtime-core/cache"]
|
||||
debug = ["wasmer-runtime-core/debug"]
|
||||
debug = ["wasmer-runtime-core/debug"]
|
||||
|
@ -32,10 +32,10 @@ impl<'env, 'module, 'isa> FuncEnv<'env, 'module, 'isa> {
|
||||
let mut signature = self.env.signatures[Converter(clif_sig_index).into()].clone();
|
||||
|
||||
// Add the vmctx parameter type to it
|
||||
signature.params.push(ir::AbiParam::special(
|
||||
self.pointer_type(),
|
||||
ir::ArgumentPurpose::VMContext,
|
||||
));
|
||||
signature.params.insert(
|
||||
0,
|
||||
ir::AbiParam::special(self.pointer_type(), ir::ArgumentPurpose::VMContext),
|
||||
);
|
||||
|
||||
// Return signature
|
||||
signature
|
||||
@ -461,8 +461,8 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> {
|
||||
// Build a value list for the indirect call instruction containing the call_args
|
||||
// and the vmctx parameter.
|
||||
let mut args = Vec::with_capacity(call_args.len() + 1);
|
||||
args.extend(call_args.iter().cloned());
|
||||
args.push(vmctx_ptr);
|
||||
args.extend(call_args.iter().cloned());
|
||||
|
||||
Ok(pos.ins().call_indirect(sig_ref, func_ptr, &args))
|
||||
}
|
||||
@ -487,8 +487,8 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> {
|
||||
.expect("missing vmctx parameter");
|
||||
|
||||
let mut args = Vec::with_capacity(call_args.len() + 1);
|
||||
args.extend(call_args.iter().cloned());
|
||||
args.push(vmctx);
|
||||
args.extend(call_args.iter().cloned());
|
||||
|
||||
Ok(pos.ins().call(callee, &args))
|
||||
}
|
||||
@ -534,8 +534,8 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> {
|
||||
let sig_ref = pos.func.dfg.ext_funcs[callee].signature;
|
||||
|
||||
let mut args = Vec::with_capacity(call_args.len() + 1);
|
||||
args.extend(call_args.iter().cloned());
|
||||
args.push(imported_vmctx_addr);
|
||||
args.extend(call_args.iter().cloned());
|
||||
|
||||
Ok(pos
|
||||
.ins()
|
||||
@ -561,9 +561,9 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> {
|
||||
let signature = pos.func.import_signature(ir::Signature {
|
||||
call_conv: self.target_config().default_call_conv,
|
||||
params: vec![
|
||||
ir::AbiParam::new(ir::types::I32),
|
||||
ir::AbiParam::new(ir::types::I32),
|
||||
ir::AbiParam::special(self.pointer_type(), ir::ArgumentPurpose::VMContext),
|
||||
ir::AbiParam::new(ir::types::I32),
|
||||
ir::AbiParam::new(ir::types::I32),
|
||||
],
|
||||
returns: vec![ir::AbiParam::new(ir::types::I32)],
|
||||
});
|
||||
@ -607,7 +607,7 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> {
|
||||
|
||||
let call_inst = pos
|
||||
.ins()
|
||||
.call(mem_grow_func, &[const_mem_index, by_value, vmctx]);
|
||||
.call(mem_grow_func, &[vmctx, const_mem_index, by_value]);
|
||||
|
||||
Ok(*pos.func.dfg.inst_results(call_inst).first().unwrap())
|
||||
}
|
||||
@ -626,8 +626,8 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> {
|
||||
let signature = pos.func.import_signature(ir::Signature {
|
||||
call_conv: self.target_config().default_call_conv,
|
||||
params: vec![
|
||||
ir::AbiParam::new(ir::types::I32),
|
||||
ir::AbiParam::special(self.pointer_type(), ir::ArgumentPurpose::VMContext),
|
||||
ir::AbiParam::new(ir::types::I32),
|
||||
],
|
||||
returns: vec![ir::AbiParam::new(ir::types::I32)],
|
||||
});
|
||||
@ -668,7 +668,7 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> {
|
||||
.special_param(ir::ArgumentPurpose::VMContext)
|
||||
.expect("missing vmctx parameter");
|
||||
|
||||
let call_inst = pos.ins().call(mem_grow_func, &[const_mem_index, vmctx]);
|
||||
let call_inst = pos.ins().call(mem_grow_func, &[vmctx, const_mem_index]);
|
||||
|
||||
Ok(*pos.func.dfg.inst_results(call_inst).first().unwrap())
|
||||
}
|
||||
|
@ -416,8 +416,8 @@ impl<'module, 'isa, 'data> ModuleEnvironment<'data> for ModuleEnv<'module, 'isa>
|
||||
let signature = pos.func.import_signature(ir::Signature {
|
||||
call_conv: self.target_config().default_call_conv,
|
||||
params: vec![
|
||||
ir::AbiParam::new(ir::types::I32),
|
||||
ir::AbiParam::special(ir::types::I64, ir::ArgumentPurpose::VMContext),
|
||||
ir::AbiParam::new(ir::types::I32),
|
||||
],
|
||||
returns: vec![],
|
||||
});
|
||||
@ -454,8 +454,8 @@ impl<'module, 'isa, 'data> ModuleEnvironment<'data> for ModuleEnv<'module, 'isa>
|
||||
let signature = pos.func.import_signature(ir::Signature {
|
||||
call_conv: self.target_config().default_call_conv,
|
||||
params: vec![
|
||||
ir::AbiParam::new(ir::types::I32),
|
||||
ir::AbiParam::special(ir::types::I64, ir::ArgumentPurpose::VMContext),
|
||||
ir::AbiParam::new(ir::types::I32),
|
||||
],
|
||||
returns: vec![],
|
||||
});
|
||||
@ -473,8 +473,8 @@ impl<'module, 'isa, 'data> ModuleEnvironment<'data> for ModuleEnv<'module, 'isa>
|
||||
let signature = pos.func.import_signature(ir::Signature {
|
||||
call_conv: self.target_config().default_call_conv,
|
||||
params: vec![
|
||||
ir::AbiParam::new(ir::types::I64),
|
||||
ir::AbiParam::special(ir::types::I64, ir::ArgumentPurpose::VMContext),
|
||||
ir::AbiParam::new(ir::types::I64),
|
||||
],
|
||||
returns: vec![],
|
||||
});
|
||||
@ -492,8 +492,8 @@ impl<'module, 'isa, 'data> ModuleEnvironment<'data> for ModuleEnv<'module, 'isa>
|
||||
let signature = pos.func.import_signature(ir::Signature {
|
||||
call_conv: self.target_config().default_call_conv,
|
||||
params: vec![
|
||||
ir::AbiParam::new(ir::types::F32),
|
||||
ir::AbiParam::special(ir::types::I64, ir::ArgumentPurpose::VMContext),
|
||||
ir::AbiParam::new(ir::types::F32),
|
||||
],
|
||||
returns: vec![],
|
||||
});
|
||||
@ -511,8 +511,8 @@ impl<'module, 'isa, 'data> ModuleEnvironment<'data> for ModuleEnv<'module, 'isa>
|
||||
let signature = pos.func.import_signature(ir::Signature {
|
||||
call_conv: self.target_config().default_call_conv,
|
||||
params: vec![
|
||||
ir::AbiParam::new(ir::types::F64),
|
||||
ir::AbiParam::special(ir::types::I64, ir::ArgumentPurpose::VMContext),
|
||||
ir::AbiParam::new(ir::types::F64),
|
||||
],
|
||||
returns: vec![],
|
||||
});
|
||||
@ -533,14 +533,14 @@ impl<'module, 'isa, 'data> ModuleEnvironment<'data> for ModuleEnv<'module, 'isa>
|
||||
|
||||
let func_index = pos.ins().iconst(ir::types::I32, func_index.index() as i64);
|
||||
|
||||
pos.ins().call(start_debug, &[func_index, vmctx]);
|
||||
pos.ins().call(start_debug, &[vmctx, func_index]);
|
||||
|
||||
for param in new_ebb_params.iter().cloned() {
|
||||
match pos.func.dfg.value_type(param) {
|
||||
ir::types::I32 => pos.ins().call(i32_print, &[param, vmctx]),
|
||||
ir::types::I64 => pos.ins().call(i64_print, &[param, vmctx]),
|
||||
ir::types::F32 => pos.ins().call(f32_print, &[param, vmctx]),
|
||||
ir::types::F64 => pos.ins().call(f64_print, &[param, vmctx]),
|
||||
ir::types::I32 => pos.ins().call(i32_print, &[vmctx, param]),
|
||||
ir::types::I64 => pos.ins().call(i64_print, &[vmctx, param]),
|
||||
ir::types::F32 => pos.ins().call(f32_print, &[vmctx, param]),
|
||||
ir::types::F64 => pos.ins().call(f64_print, &[vmctx, param]),
|
||||
_ => unimplemented!(),
|
||||
};
|
||||
}
|
||||
|
@ -35,6 +35,13 @@ use wasmer_runtime_core::{
|
||||
vm, vmcalls,
|
||||
};
|
||||
|
||||
extern "C" {
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
pub fn __rust_probestack();
|
||||
#[cfg(all(target_os = "windows", target_pointer_width = "64"))]
|
||||
pub fn __chkstk();
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub struct FuncResolverBuilder {
|
||||
resolver: FuncResolver,
|
||||
@ -215,7 +222,10 @@ impl FuncResolverBuilder {
|
||||
LibCall::FloorF64 => libcalls::floorf64 as isize,
|
||||
LibCall::TruncF64 => libcalls::truncf64 as isize,
|
||||
LibCall::NearestF64 => libcalls::nearbyintf64 as isize,
|
||||
LibCall::Probestack => libcalls::__rust_probestack as isize,
|
||||
#[cfg(all(target_pointer_width = "64", target_os = "windows"))]
|
||||
LibCall::Probestack => __chkstk as isize,
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
LibCall::Probestack => __rust_probestack as isize,
|
||||
},
|
||||
RelocationType::Intrinsic(ref name) => match name.as_str() {
|
||||
"i32print" => i32_print as isize,
|
||||
@ -340,21 +350,21 @@ fn round_up(n: usize, multiple: usize) -> usize {
|
||||
(n + multiple - 1) & !(multiple - 1)
|
||||
}
|
||||
|
||||
extern "C" fn i32_print(n: i32) {
|
||||
extern "C" fn i32_print(_ctx: &mut vm::Ctx, n: i32) {
|
||||
print!(" i32: {},", n);
|
||||
}
|
||||
extern "C" fn i64_print(n: i64) {
|
||||
extern "C" fn i64_print(_ctx: &mut vm::Ctx, n: i64) {
|
||||
print!(" i64: {},", n);
|
||||
}
|
||||
extern "C" fn f32_print(n: f32) {
|
||||
extern "C" fn f32_print(_ctx: &mut vm::Ctx, n: f32) {
|
||||
print!(" f32: {},", n);
|
||||
}
|
||||
extern "C" fn f64_print(n: f64) {
|
||||
extern "C" fn f64_print(_ctx: &mut vm::Ctx, n: f64) {
|
||||
print!(" f64: {},", n);
|
||||
}
|
||||
extern "C" fn start_debug(func_index: u32) {
|
||||
extern "C" fn start_debug(_ctx: &mut vm::Ctx, func_index: u32) {
|
||||
print!("func ({}), args: [", func_index);
|
||||
}
|
||||
extern "C" fn end_debug() {
|
||||
extern "C" fn end_debug(_ctx: &mut vm::Ctx) {
|
||||
println!(" ]");
|
||||
}
|
||||
|
@ -110,6 +110,7 @@ impl ProtectedCaller for Caller {
|
||||
.lookup(sig_index)
|
||||
.expect("that trampoline doesn't exist");
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
call_protected(&self.handler_data, || unsafe {
|
||||
// Leap of faith.
|
||||
trampoline(
|
||||
@ -120,6 +121,17 @@ impl ProtectedCaller for Caller {
|
||||
);
|
||||
})?;
|
||||
|
||||
// the trampoline is called from C on windows
|
||||
#[cfg(target_os = "windows")]
|
||||
call_protected(
|
||||
&self.handler_data,
|
||||
trampoline,
|
||||
vmctx_ptr,
|
||||
func_ptr,
|
||||
param_vec.as_ptr(),
|
||||
return_vec.as_mut_ptr(),
|
||||
)?;
|
||||
|
||||
Ok(return_vec
|
||||
.iter()
|
||||
.zip(signature.returns().iter())
|
||||
|
@ -1,6 +1,116 @@
|
||||
use crate::relocation::{TrapCode, TrapData};
|
||||
use crate::signal::HandlerData;
|
||||
use wasmer_runtime_core::error::RuntimeResult;
|
||||
use crate::trampoline::Trampoline;
|
||||
use std::cell::Cell;
|
||||
use std::ffi::c_void;
|
||||
use std::ptr;
|
||||
use wasmer_runtime_core::vm::Ctx;
|
||||
use wasmer_runtime_core::vm::Func;
|
||||
use wasmer_runtime_core::{
|
||||
error::{RuntimeError, RuntimeResult},
|
||||
structures::TypedIndex,
|
||||
types::{MemoryIndex, TableIndex},
|
||||
};
|
||||
use wasmer_win_exception_handler::CallProtectedData;
|
||||
pub use wasmer_win_exception_handler::_call_protected;
|
||||
use winapi::shared::minwindef::DWORD;
|
||||
use winapi::um::minwinbase::{
|
||||
EXCEPTION_ACCESS_VIOLATION, EXCEPTION_FLT_DENORMAL_OPERAND, EXCEPTION_FLT_DIVIDE_BY_ZERO,
|
||||
EXCEPTION_FLT_INEXACT_RESULT, EXCEPTION_FLT_INVALID_OPERATION, EXCEPTION_FLT_OVERFLOW,
|
||||
EXCEPTION_FLT_STACK_CHECK, EXCEPTION_FLT_UNDERFLOW, EXCEPTION_ILLEGAL_INSTRUCTION,
|
||||
EXCEPTION_INT_DIVIDE_BY_ZERO, EXCEPTION_INT_OVERFLOW, EXCEPTION_STACK_OVERFLOW,
|
||||
};
|
||||
|
||||
pub fn call_protected<T>(handler_data: &HandlerData, f: impl FnOnce() -> T) -> RuntimeResult<T> {
|
||||
unimplemented!("TODO");
|
||||
thread_local! {
|
||||
pub static CURRENT_EXECUTABLE_BUFFER: Cell<*const c_void> = Cell::new(ptr::null());
|
||||
}
|
||||
|
||||
pub fn call_protected(
|
||||
handler_data: &HandlerData,
|
||||
trampoline: Trampoline,
|
||||
ctx: *mut Ctx,
|
||||
func: *const Func,
|
||||
param_vec: *const u64,
|
||||
return_vec: *mut u64,
|
||||
) -> RuntimeResult<()> {
|
||||
// TODO: trap early
|
||||
// user code error
|
||||
// if let Some(msg) = super::TRAP_EARLY_DATA.with(|cell| cell.replace(None)) {
|
||||
// return Err(RuntimeError::User { msg });
|
||||
// }
|
||||
|
||||
let result = _call_protected(trampoline, ctx, func, param_vec, return_vec);
|
||||
|
||||
if let Ok(_) = result {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let CallProtectedData {
|
||||
code: signum,
|
||||
exceptionAddress: exception_address,
|
||||
instructionPointer: instruction_pointer,
|
||||
} = result.unwrap_err();
|
||||
|
||||
if let Some(TrapData {
|
||||
trapcode,
|
||||
srcloc: _,
|
||||
}) = handler_data.lookup(instruction_pointer as _)
|
||||
{
|
||||
Err(match signum as DWORD {
|
||||
EXCEPTION_ACCESS_VIOLATION => RuntimeError::OutOfBoundsAccess {
|
||||
memory: MemoryIndex::new(0),
|
||||
addr: None,
|
||||
},
|
||||
EXCEPTION_ILLEGAL_INSTRUCTION => match trapcode {
|
||||
TrapCode::BadSignature => RuntimeError::IndirectCallSignature {
|
||||
table: TableIndex::new(0),
|
||||
},
|
||||
TrapCode::IndirectCallToNull => RuntimeError::IndirectCallToNull {
|
||||
table: TableIndex::new(0),
|
||||
},
|
||||
TrapCode::HeapOutOfBounds => RuntimeError::OutOfBoundsAccess {
|
||||
memory: MemoryIndex::new(0),
|
||||
addr: None,
|
||||
},
|
||||
TrapCode::TableOutOfBounds => RuntimeError::TableOutOfBounds {
|
||||
table: TableIndex::new(0),
|
||||
},
|
||||
_ => RuntimeError::Unknown {
|
||||
msg: "unknown trap".to_string(),
|
||||
},
|
||||
},
|
||||
EXCEPTION_STACK_OVERFLOW => RuntimeError::Unknown {
|
||||
msg: "unknown trap".to_string(),
|
||||
},
|
||||
EXCEPTION_INT_DIVIDE_BY_ZERO => RuntimeError::IllegalArithmeticOperation,
|
||||
EXCEPTION_INT_OVERFLOW => RuntimeError::IllegalArithmeticOperation,
|
||||
_ => RuntimeError::Unknown {
|
||||
msg: "unknown trap".to_string(),
|
||||
},
|
||||
}
|
||||
.into())
|
||||
} else {
|
||||
let signal = match signum as DWORD {
|
||||
EXCEPTION_FLT_DENORMAL_OPERAND
|
||||
| EXCEPTION_FLT_DIVIDE_BY_ZERO
|
||||
| EXCEPTION_FLT_INEXACT_RESULT
|
||||
| EXCEPTION_FLT_INVALID_OPERATION
|
||||
| EXCEPTION_FLT_OVERFLOW
|
||||
| EXCEPTION_FLT_STACK_CHECK
|
||||
| EXCEPTION_FLT_UNDERFLOW => "floating-point exception",
|
||||
EXCEPTION_ILLEGAL_INSTRUCTION => "illegal instruction",
|
||||
EXCEPTION_ACCESS_VIOLATION => "segmentation violation",
|
||||
_ => "unkown trapped signal",
|
||||
};
|
||||
|
||||
Err(RuntimeError::Unknown {
|
||||
msg: format!("trap at {} - {}", exception_address, signal),
|
||||
}
|
||||
.into())
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn trigger_trap() -> ! {
|
||||
// TODO
|
||||
unimplemented!();
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ use cranelift_codegen::{
|
||||
isa, Context,
|
||||
};
|
||||
use hashbrown::HashMap;
|
||||
use std::ffi::c_void;
|
||||
use std::{iter, mem};
|
||||
use wasmer_runtime_core::{
|
||||
backend::sys::{Memory, Protect},
|
||||
@ -23,6 +24,9 @@ impl RelocSink for NullRelocSink {
|
||||
fn reloc_jt(&mut self, _: u32, _: Reloc, _: ir::JumpTable) {}
|
||||
}
|
||||
|
||||
pub type Trampoline =
|
||||
unsafe extern "C" fn(*mut vm::Ctx, *const vm::Func, *const u64, *mut u64) -> c_void;
|
||||
|
||||
pub struct Trampolines {
|
||||
memory: Memory,
|
||||
offsets: HashMap<SigIndex, usize>,
|
||||
@ -138,10 +142,7 @@ impl Trampolines {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn lookup(
|
||||
&self,
|
||||
sig_index: SigIndex,
|
||||
) -> Option<unsafe extern "C" fn(*mut vm::Ctx, *const vm::Func, *const u64, *mut u64)> {
|
||||
pub fn lookup(&self, sig_index: SigIndex) -> Option<Trampoline> {
|
||||
let offset = *self.offsets.get(&sig_index)?;
|
||||
let ptr = unsafe { self.memory.as_ptr().add(offset) };
|
||||
|
||||
@ -169,6 +170,7 @@ fn generate_func(func_sig: &FuncSig) -> ir::Function {
|
||||
let mut pos = FuncCursor::new(&mut func).at_first_insertion_point(entry_ebb);
|
||||
|
||||
let mut args_vec = Vec::with_capacity(func_sig.params().len() + 1);
|
||||
args_vec.push(vmctx_ptr);
|
||||
for (index, wasm_ty) in func_sig.params().iter().enumerate() {
|
||||
let mem_flags = ir::MemFlags::trusted();
|
||||
|
||||
@ -180,7 +182,6 @@ fn generate_func(func_sig: &FuncSig) -> ir::Function {
|
||||
);
|
||||
args_vec.push(val);
|
||||
}
|
||||
args_vec.push(vmctx_ptr);
|
||||
|
||||
let call_inst = pos.ins().call_indirect(export_sig_ref, func_ptr, &args_vec);
|
||||
|
||||
@ -212,7 +213,9 @@ fn wasm_ty_to_clif(ty: Type) -> ir::types::Type {
|
||||
}
|
||||
|
||||
fn generate_trampoline_signature() -> ir::Signature {
|
||||
let mut sig = ir::Signature::new(isa::CallConv::SystemV);
|
||||
let isa = super::get_isa();
|
||||
let call_convention = isa.default_call_conv();
|
||||
let mut sig = ir::Signature::new(call_convention);
|
||||
|
||||
let ptr_param = ir::AbiParam {
|
||||
value_type: ir::types::I64,
|
||||
@ -227,24 +230,25 @@ fn generate_trampoline_signature() -> ir::Signature {
|
||||
}
|
||||
|
||||
fn generate_export_signature(func_sig: &FuncSig) -> ir::Signature {
|
||||
let mut export_clif_sig = ir::Signature::new(isa::CallConv::SystemV);
|
||||
let isa = super::get_isa();
|
||||
let call_convention = isa.default_call_conv();
|
||||
let mut export_clif_sig = ir::Signature::new(call_convention);
|
||||
|
||||
export_clif_sig.params = func_sig
|
||||
.params()
|
||||
.iter()
|
||||
.map(|wasm_ty| ir::AbiParam {
|
||||
value_type: wasm_ty_to_clif(*wasm_ty),
|
||||
purpose: ir::ArgumentPurpose::Normal,
|
||||
extension: ir::ArgumentExtension::None,
|
||||
location: ir::ArgumentLoc::Unassigned,
|
||||
})
|
||||
.chain(iter::once(ir::AbiParam {
|
||||
value_type: ir::types::I64,
|
||||
purpose: ir::ArgumentPurpose::VMContext,
|
||||
extension: ir::ArgumentExtension::None,
|
||||
location: ir::ArgumentLoc::Unassigned,
|
||||
}))
|
||||
.collect();
|
||||
let func_sig_iter = func_sig.params().iter().map(|wasm_ty| ir::AbiParam {
|
||||
value_type: wasm_ty_to_clif(*wasm_ty),
|
||||
purpose: ir::ArgumentPurpose::Normal,
|
||||
extension: ir::ArgumentExtension::None,
|
||||
location: ir::ArgumentLoc::Unassigned,
|
||||
});
|
||||
|
||||
export_clif_sig.params = iter::once(ir::AbiParam {
|
||||
value_type: ir::types::I64,
|
||||
purpose: ir::ArgumentPurpose::VMContext,
|
||||
extension: ir::ArgumentExtension::None,
|
||||
location: ir::ArgumentLoc::Unassigned,
|
||||
})
|
||||
.chain(func_sig_iter)
|
||||
.collect();
|
||||
|
||||
export_clif_sig.returns = func_sig
|
||||
.returns()
|
||||
|
@ -10,7 +10,7 @@
|
||||
```
|
||||
- **abort** ✅ 🔥 [:top:](#host-apis)
|
||||
```rust
|
||||
fn abort(message: u32, ctx: &mut Ctx)
|
||||
fn abort(ctx: &mut Ctx, message: u32, )
|
||||
```
|
||||
- **abort_on_cannot_grow_memory** ✅ [:top:](#host-apis)
|
||||
```rust
|
||||
@ -28,11 +28,11 @@
|
||||
|
||||
- **\_getenv** ✅ [:top:](#host-apis)
|
||||
```rust
|
||||
fn _getenv(name: c_int, ctx: &mut Ctx)
|
||||
fn _getenv(ctx: &mut Ctx, name: c_int, )
|
||||
```
|
||||
- **\_putenv** ✅ [:top:](#host-apis)
|
||||
```rust
|
||||
fn _putenv(name: c_int, ctx: &mut Ctx)
|
||||
fn _putenv(ctx: &mut Ctx, name: c_int, )
|
||||
```
|
||||
- **\_setenv** ✅ [:top:](#host-apis)
|
||||
```rust
|
||||
@ -40,7 +40,7 @@
|
||||
```
|
||||
- **\_unsetenv** ✅ [:top:](#host-apis)
|
||||
```rust
|
||||
fn _unsetenv(name: c_int, ctx: &mut Ctx)
|
||||
fn _unsetenv(ctx: &mut Ctx, name: c_int, )
|
||||
```
|
||||
|
||||
###### THREAD
|
||||
@ -70,7 +70,7 @@
|
||||
|
||||
- **\_emscripten_memcpy_big** ✅ 🔥 [:top:](#host-apis)
|
||||
```rust
|
||||
fn _emscripten_memcpy_big(dest: u32, src: u32, len: u32, ctx: &mut Ctx) -> u32
|
||||
fn _emscripten_memcpy_big(ctx: &mut Ctx, dest: u32, src: u32, len: u32, ) -> u32
|
||||
```
|
||||
- **enlarge_memory** ✅ [:top:](#host-apis)
|
||||
```rust
|
||||
@ -78,7 +78,7 @@
|
||||
```
|
||||
- **get_total_memory** ✅ [:top:](#host-apis)
|
||||
```rust
|
||||
fn get_total_memory(ctx: &mut Ctx) -> u32
|
||||
fn get_total_memory(ctx: &mut Ctx, ) -> u32
|
||||
```
|
||||
|
||||
###### TIMING
|
||||
@ -337,7 +337,7 @@
|
||||
```
|
||||
- **open** (\_\_\_syscall5) ✅ ❗️ 🔥 [:top:](#host-apis)
|
||||
```rust
|
||||
fn open(path: u32, flags: c_int, mode: c_int, ctx: &mut Ctx) -> c_int
|
||||
fn open(ctx: &mut Ctx, path: u32, flags: c_int, mode: c_int, ) -> c_int
|
||||
```
|
||||
- **openat** (\_\_\_syscall295) [:top:](#host-apis)
|
||||
```rust
|
||||
@ -385,7 +385,7 @@
|
||||
```
|
||||
- **read** (\_\_\_syscall3) ✅ ❗️ [:top:](#host-apis)
|
||||
```rust
|
||||
fn read(fd: c_int, buf: u32, count: size_t, ctx: &mut Ctx) -> ssize_t
|
||||
fn read(ctx: &mut Ctx, fd: c_int, buf: u32, count: size_t, ) -> ssize_t
|
||||
```
|
||||
- **readlink** (\_\_\_syscall85) [:top:](#host-apis)
|
||||
```rust
|
||||
|
16
lib/emscripten/src/env/mod.rs
vendored
16
lib/emscripten/src/env/mod.rs
vendored
@ -14,16 +14,16 @@ use crate::{allocate_on_stack, EmscriptenData};
|
||||
use std::os::raw::c_int;
|
||||
use wasmer_runtime_core::vm::Ctx;
|
||||
|
||||
pub fn _getaddrinfo(_one: i32, _two: i32, _three: i32, _four: i32, _ctx: &mut Ctx) -> i32 {
|
||||
pub fn _getaddrinfo(_ctx: &mut Ctx, _one: i32, _two: i32, _three: i32, _four: i32) -> i32 {
|
||||
debug!("emscripten::_getaddrinfo");
|
||||
-1
|
||||
}
|
||||
|
||||
pub fn call_malloc(size: u32, ctx: &mut Ctx) -> u32 {
|
||||
pub fn call_malloc(ctx: &mut Ctx, size: u32) -> u32 {
|
||||
get_emscripten_data(ctx).malloc.call(size).unwrap()
|
||||
}
|
||||
|
||||
pub fn call_memalign(alignment: u32, size: u32, ctx: &mut Ctx) -> u32 {
|
||||
pub fn call_memalign(ctx: &mut Ctx, alignment: u32, size: u32) -> u32 {
|
||||
if let Some(memalign) = &get_emscripten_data(ctx).memalign {
|
||||
memalign.call(alignment, size).unwrap()
|
||||
} else {
|
||||
@ -31,7 +31,7 @@ pub fn call_memalign(alignment: u32, size: u32, ctx: &mut Ctx) -> u32 {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn call_memset(pointer: u32, value: u32, size: u32, ctx: &mut Ctx) -> u32 {
|
||||
pub fn call_memset(ctx: &mut Ctx, pointer: u32, value: u32, size: u32) -> u32 {
|
||||
get_emscripten_data(ctx)
|
||||
.memset
|
||||
.call(pointer, value, size)
|
||||
@ -48,16 +48,16 @@ pub fn _getpagesize(_ctx: &mut Ctx) -> u32 {
|
||||
}
|
||||
|
||||
#[allow(clippy::cast_ptr_alignment)]
|
||||
pub fn ___build_environment(environ: c_int, ctx: &mut Ctx) {
|
||||
pub fn ___build_environment(ctx: &mut Ctx, environ: c_int) {
|
||||
debug!("emscripten::___build_environment {}", environ);
|
||||
const MAX_ENV_VALUES: u32 = 64;
|
||||
const TOTAL_ENV_SIZE: u32 = 1024;
|
||||
let environment = emscripten_memory_pointer!(ctx.memory(0), environ) as *mut c_int;
|
||||
unsafe {
|
||||
let (pool_offset, _pool_slice): (u32, &mut [u8]) =
|
||||
allocate_on_stack(TOTAL_ENV_SIZE as u32, ctx);
|
||||
allocate_on_stack(ctx, TOTAL_ENV_SIZE as u32);
|
||||
let (env_offset, _env_slice): (u32, &mut [u8]) =
|
||||
allocate_on_stack((MAX_ENV_VALUES * 4) as u32, ctx);
|
||||
allocate_on_stack(ctx, (MAX_ENV_VALUES * 4) as u32);
|
||||
let env_ptr = emscripten_memory_pointer!(ctx.memory(0), env_offset) as *mut c_int;
|
||||
let mut _pool_ptr = emscripten_memory_pointer!(ctx.memory(0), pool_offset) as *mut c_int;
|
||||
*env_ptr = pool_offset as i32;
|
||||
@ -70,7 +70,7 @@ pub fn ___build_environment(environ: c_int, ctx: &mut Ctx) {
|
||||
// };
|
||||
}
|
||||
|
||||
pub fn ___assert_fail(a: c_int, b: c_int, c: c_int, d: c_int, _ctx: &mut Ctx) {
|
||||
pub fn ___assert_fail(_ctx: &mut Ctx, a: c_int, b: c_int, c: c_int, d: c_int) {
|
||||
debug!("emscripten::___assert_fail {} {} {} {}", a, b, c, d);
|
||||
// TODO: Implement like emscripten expects regarding memory/page size
|
||||
// TODO raise an error
|
||||
|
25
lib/emscripten/src/env/unix/mod.rs
vendored
25
lib/emscripten/src/env/unix/mod.rs
vendored
@ -1,20 +1,19 @@
|
||||
/// NOTE: These syscalls only support wasm_32 for now because they take u32 offset
|
||||
use libc::{
|
||||
c_int, c_long, getenv, getgrnam as libc_getgrnam, getpwnam as libc_getpwnam, putenv, setenv,
|
||||
sysconf, unsetenv,
|
||||
c_int, getenv, getgrnam as libc_getgrnam, getpwnam as libc_getpwnam, putenv, setenv, sysconf,
|
||||
unsetenv,
|
||||
};
|
||||
use std::ffi::CStr;
|
||||
use std::mem;
|
||||
use std::os::raw::c_char;
|
||||
|
||||
use crate::env::call_malloc;
|
||||
use crate::utils::{allocate_on_stack, copy_cstr_into_wasm, copy_terminated_array_of_cstrs};
|
||||
use crate::EmscriptenData;
|
||||
use crate::utils::{copy_cstr_into_wasm, copy_terminated_array_of_cstrs};
|
||||
use wasmer_runtime_core::vm::Ctx;
|
||||
|
||||
// #[no_mangle]
|
||||
/// emscripten: _getenv // (name: *const char) -> *const c_char;
|
||||
pub fn _getenv(name: i32, ctx: &mut Ctx) -> u32 {
|
||||
pub fn _getenv(ctx: &mut Ctx, name: i32) -> u32 {
|
||||
debug!("emscripten::_getenv");
|
||||
|
||||
let name_addr = emscripten_memory_pointer!(ctx.memory(0), name) as *const c_char;
|
||||
@ -30,7 +29,7 @@ pub fn _getenv(name: i32, ctx: &mut Ctx) -> u32 {
|
||||
}
|
||||
|
||||
/// emscripten: _setenv // (name: *const char, name: *const value, overwrite: int);
|
||||
pub fn _setenv(name: c_int, value: c_int, overwrite: c_int, ctx: &mut Ctx) -> c_int {
|
||||
pub fn _setenv(ctx: &mut Ctx, name: c_int, value: c_int, overwrite: c_int) -> c_int {
|
||||
debug!("emscripten::_setenv");
|
||||
|
||||
let name_addr = emscripten_memory_pointer!(ctx.memory(0), name) as *const c_char;
|
||||
@ -43,7 +42,7 @@ pub fn _setenv(name: c_int, value: c_int, overwrite: c_int, ctx: &mut Ctx) -> c_
|
||||
}
|
||||
|
||||
/// emscripten: _putenv // (name: *const char);
|
||||
pub fn _putenv(name: c_int, ctx: &mut Ctx) -> c_int {
|
||||
pub fn _putenv(ctx: &mut Ctx, name: c_int) -> c_int {
|
||||
debug!("emscripten::_putenv");
|
||||
|
||||
let name_addr = emscripten_memory_pointer!(ctx.memory(0), name) as *const c_char;
|
||||
@ -54,7 +53,7 @@ pub fn _putenv(name: c_int, ctx: &mut Ctx) -> c_int {
|
||||
}
|
||||
|
||||
/// emscripten: _unsetenv // (name: *const char);
|
||||
pub fn _unsetenv(name: c_int, ctx: &mut Ctx) -> c_int {
|
||||
pub fn _unsetenv(ctx: &mut Ctx, name: c_int) -> c_int {
|
||||
debug!("emscripten::_unsetenv");
|
||||
|
||||
let name_addr = emscripten_memory_pointer!(ctx.memory(0), name) as *const c_char;
|
||||
@ -65,7 +64,7 @@ pub fn _unsetenv(name: c_int, ctx: &mut Ctx) -> c_int {
|
||||
}
|
||||
|
||||
#[allow(clippy::cast_ptr_alignment)]
|
||||
pub fn _getpwnam(name_ptr: c_int, ctx: &mut Ctx) -> c_int {
|
||||
pub fn _getpwnam(ctx: &mut Ctx, name_ptr: c_int) -> c_int {
|
||||
debug!("emscripten::_getpwnam {}", name_ptr);
|
||||
|
||||
#[repr(C)]
|
||||
@ -86,7 +85,7 @@ pub fn _getpwnam(name_ptr: c_int, ctx: &mut Ctx) -> c_int {
|
||||
|
||||
unsafe {
|
||||
let passwd = &*libc_getpwnam(name.as_ptr());
|
||||
let passwd_struct_offset = call_malloc(mem::size_of::<GuestPasswd>() as _, ctx);
|
||||
let passwd_struct_offset = call_malloc(ctx, mem::size_of::<GuestPasswd>() as _);
|
||||
|
||||
let passwd_struct_ptr =
|
||||
emscripten_memory_pointer!(ctx.memory(0), passwd_struct_offset) as *mut GuestPasswd;
|
||||
@ -103,7 +102,7 @@ pub fn _getpwnam(name_ptr: c_int, ctx: &mut Ctx) -> c_int {
|
||||
}
|
||||
|
||||
#[allow(clippy::cast_ptr_alignment)]
|
||||
pub fn _getgrnam(name_ptr: c_int, ctx: &mut Ctx) -> c_int {
|
||||
pub fn _getgrnam(ctx: &mut Ctx, name_ptr: c_int) -> c_int {
|
||||
debug!("emscripten::_getgrnam {}", name_ptr);
|
||||
|
||||
#[repr(C)]
|
||||
@ -121,7 +120,7 @@ pub fn _getgrnam(name_ptr: c_int, ctx: &mut Ctx) -> c_int {
|
||||
|
||||
unsafe {
|
||||
let group = &*libc_getgrnam(name.as_ptr());
|
||||
let group_struct_offset = call_malloc(mem::size_of::<GuestGroup>() as _, ctx);
|
||||
let group_struct_offset = call_malloc(ctx, mem::size_of::<GuestGroup>() as _);
|
||||
|
||||
let group_struct_ptr =
|
||||
emscripten_memory_pointer!(ctx.memory(0), group_struct_offset) as *mut GuestGroup;
|
||||
@ -134,7 +133,7 @@ pub fn _getgrnam(name_ptr: c_int, ctx: &mut Ctx) -> c_int {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn _sysconf(name: c_int, _ctx: &mut Ctx) -> i32 {
|
||||
pub fn _sysconf(_ctx: &mut Ctx, name: c_int) -> i32 {
|
||||
debug!("emscripten::_sysconf {}", name);
|
||||
// TODO: Implement like emscripten expects regarding memory/page size
|
||||
unsafe { sysconf(name) as i32 } // TODO review i64
|
||||
|
19
lib/emscripten/src/env/windows/mod.rs
vendored
19
lib/emscripten/src/env/windows/mod.rs
vendored
@ -9,7 +9,6 @@ use crate::env::call_malloc;
|
||||
use crate::utils::{copy_cstr_into_wasm, read_string_from_wasm};
|
||||
use wasmer_runtime_core::vm::Ctx;
|
||||
|
||||
#[link(name = "c")]
|
||||
extern "C" {
|
||||
#[link_name = "_putenv"]
|
||||
pub fn putenv(s: *const c_char) -> c_int;
|
||||
@ -17,7 +16,7 @@ extern "C" {
|
||||
|
||||
// #[no_mangle]
|
||||
/// emscripten: _getenv // (name: *const char) -> *const c_char;
|
||||
pub fn _getenv(name: u32, ctx: &mut Ctx) -> u32 {
|
||||
pub fn _getenv(ctx: &mut Ctx, name: u32) -> u32 {
|
||||
debug!("emscripten::_getenv");
|
||||
let name_string = read_string_from_wasm(ctx.memory(0), name);
|
||||
debug!("=> name({:?})", name_string);
|
||||
@ -29,7 +28,7 @@ pub fn _getenv(name: u32, ctx: &mut Ctx) -> u32 {
|
||||
}
|
||||
|
||||
/// emscripten: _setenv // (name: *const char, name: *const value, overwrite: int);
|
||||
pub fn _setenv(name: u32, value: u32, overwrite: u32, ctx: &mut Ctx) -> c_int {
|
||||
pub fn _setenv(ctx: &mut Ctx, name: u32, value: u32, overwrite: u32) -> c_int {
|
||||
debug!("emscripten::_setenv");
|
||||
let name_addr = emscripten_memory_pointer!(ctx.memory(0), name);
|
||||
let value_addr = emscripten_memory_pointer!(ctx.memory(0), value);
|
||||
@ -45,7 +44,7 @@ pub fn _setenv(name: u32, value: u32, overwrite: u32, ctx: &mut Ctx) -> c_int {
|
||||
}
|
||||
|
||||
/// emscripten: _putenv // (name: *const char);
|
||||
pub fn _putenv(name: c_int, ctx: &mut Ctx) -> c_int {
|
||||
pub fn _putenv(ctx: &mut Ctx, name: c_int) -> c_int {
|
||||
debug!("emscripten::_putenv");
|
||||
|
||||
let name_addr = emscripten_memory_pointer!(ctx.memory(0), name) as *const c_char;
|
||||
@ -55,7 +54,7 @@ pub fn _putenv(name: c_int, ctx: &mut Ctx) -> c_int {
|
||||
}
|
||||
|
||||
/// emscripten: _unsetenv // (name: *const char);
|
||||
pub fn _unsetenv(name: u32, ctx: &mut Ctx) -> c_int {
|
||||
pub fn _unsetenv(ctx: &mut Ctx, name: u32) -> c_int {
|
||||
debug!("emscripten::_unsetenv");
|
||||
let name_addr = emscripten_memory_pointer!(ctx.memory(0), name);
|
||||
let name = read_string_from_wasm(ctx.memory(0), name);
|
||||
@ -68,7 +67,7 @@ pub fn _unsetenv(name: u32, ctx: &mut Ctx) -> c_int {
|
||||
}
|
||||
|
||||
#[allow(clippy::cast_ptr_alignment)]
|
||||
pub fn _getpwnam(name_ptr: c_int, ctx: &mut Ctx) -> c_int {
|
||||
pub fn _getpwnam(ctx: &mut Ctx, name_ptr: c_int) -> c_int {
|
||||
debug!("emscripten::_getpwnam {}", name_ptr);
|
||||
|
||||
#[repr(C)]
|
||||
@ -84,7 +83,7 @@ pub fn _getpwnam(name_ptr: c_int, ctx: &mut Ctx) -> c_int {
|
||||
|
||||
// stub this in windows as it is not valid
|
||||
unsafe {
|
||||
let passwd_struct_offset = call_malloc(mem::size_of::<GuestPasswd>() as _, ctx);
|
||||
let passwd_struct_offset = call_malloc(ctx, mem::size_of::<GuestPasswd>() as _);
|
||||
let passwd_struct_ptr =
|
||||
emscripten_memory_pointer!(ctx.memory(0), passwd_struct_offset) as *mut GuestPasswd;
|
||||
(*passwd_struct_ptr).pw_name = 0;
|
||||
@ -100,7 +99,7 @@ pub fn _getpwnam(name_ptr: c_int, ctx: &mut Ctx) -> c_int {
|
||||
}
|
||||
|
||||
#[allow(clippy::cast_ptr_alignment)]
|
||||
pub fn _getgrnam(name_ptr: c_int, ctx: &mut Ctx) -> c_int {
|
||||
pub fn _getgrnam(ctx: &mut Ctx, name_ptr: c_int) -> c_int {
|
||||
debug!("emscripten::_getgrnam {}", name_ptr);
|
||||
|
||||
#[repr(C)]
|
||||
@ -113,7 +112,7 @@ pub fn _getgrnam(name_ptr: c_int, ctx: &mut Ctx) -> c_int {
|
||||
|
||||
// stub the group struct as it is not supported on windows
|
||||
unsafe {
|
||||
let group_struct_offset = call_malloc(mem::size_of::<GuestGroup>() as _, ctx);
|
||||
let group_struct_offset = call_malloc(ctx, mem::size_of::<GuestGroup>() as _);
|
||||
let group_struct_ptr =
|
||||
emscripten_memory_pointer!(ctx.memory(0), group_struct_offset) as *mut GuestGroup;
|
||||
(*group_struct_ptr).gr_name = 0;
|
||||
@ -124,7 +123,7 @@ pub fn _getgrnam(name_ptr: c_int, ctx: &mut Ctx) -> c_int {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn _sysconf(name: c_int, _ctx: &mut Ctx) -> c_long {
|
||||
pub fn _sysconf(_ctx: &mut Ctx, name: c_int) -> c_long {
|
||||
debug!("emscripten::_sysconf {}", name);
|
||||
// stub because sysconf is not valid on windows
|
||||
0
|
||||
|
@ -1,7 +1,7 @@
|
||||
// use std::collections::HashMap;
|
||||
use wasmer_runtime_core::vm::Ctx;
|
||||
|
||||
pub fn ___seterrno(value: i32, _ctx: &mut Ctx) {
|
||||
pub fn ___seterrno(_ctx: &mut Ctx, value: i32) {
|
||||
debug!("emscripten::___seterrno {}", value);
|
||||
// TODO: Incomplete impl
|
||||
eprintln!("failed to set errno!");
|
||||
|
@ -3,14 +3,14 @@ use super::process::_abort;
|
||||
use wasmer_runtime_core::vm::Ctx;
|
||||
|
||||
/// emscripten: ___cxa_allocate_exception
|
||||
pub fn ___cxa_allocate_exception(size: u32, ctx: &mut Ctx) -> u32 {
|
||||
pub fn ___cxa_allocate_exception(ctx: &mut Ctx, size: u32) -> u32 {
|
||||
debug!("emscripten::___cxa_allocate_exception");
|
||||
env::call_malloc(size as _, ctx)
|
||||
env::call_malloc(ctx, size as _)
|
||||
}
|
||||
|
||||
/// emscripten: ___cxa_throw
|
||||
/// TODO: We don't have support for exceptions yet
|
||||
pub fn ___cxa_throw(_ptr: u32, _ty: u32, _destructor: u32, ctx: &mut Ctx) {
|
||||
pub fn ___cxa_throw(ctx: &mut Ctx, _ptr: u32, _ty: u32, _destructor: u32) {
|
||||
debug!("emscripten::___cxa_throw");
|
||||
_abort(ctx);
|
||||
}
|
||||
|
@ -3,12 +3,12 @@ use libc::printf as _printf;
|
||||
use wasmer_runtime_core::vm::Ctx;
|
||||
|
||||
/// putchar
|
||||
pub fn putchar(chr: i32, ctx: &mut Ctx) {
|
||||
pub fn putchar(ctx: &mut Ctx, chr: i32) {
|
||||
unsafe { libc::putchar(chr) };
|
||||
}
|
||||
|
||||
/// printf
|
||||
pub fn printf(memory_offset: i32, extra: i32, ctx: &mut Ctx) -> i32 {
|
||||
pub fn printf(ctx: &mut Ctx, memory_offset: i32, extra: i32) -> i32 {
|
||||
debug!("emscripten::printf {}, {}", memory_offset, extra);
|
||||
unsafe {
|
||||
let addr = emscripten_memory_pointer!(ctx.memory(0), memory_offset) as _;
|
||||
|
@ -5,25 +5,26 @@ use wasmer_runtime_core::vm::Ctx;
|
||||
// this cfg_attr will try to link with the legacy lib that does not inline printf
|
||||
// this will allow for compiliation, but will produce a linker error if there is a problem
|
||||
// finding printf.
|
||||
#[cfg_attr(
|
||||
all(windows, target_env = "msvc"),
|
||||
link(name = "legacy_stdio_definitions", kind = "static-nobundle")
|
||||
)]
|
||||
extern "C" {
|
||||
#[link_name = "printf"]
|
||||
pub fn _printf(s: *const c_char, ...) -> c_int;
|
||||
}
|
||||
//#[cfg_attr(
|
||||
// all(windows, target_env = "msvc"),
|
||||
// link(name = "legacy_stdio_definitions", kind = "static-nobundle")
|
||||
//)]
|
||||
//extern "C" {
|
||||
// #[link_name = "printf"]
|
||||
// pub fn _printf(s: *const c_char, ...) -> c_int;
|
||||
//}
|
||||
|
||||
/// putchar
|
||||
pub fn putchar(chr: i32, ctx: &mut Ctx) {
|
||||
pub fn putchar(ctx: &mut Ctx, chr: i32) {
|
||||
unsafe { libc::putchar(chr) };
|
||||
}
|
||||
|
||||
/// printf
|
||||
pub fn printf(memory_offset: i32, extra: i32, ctx: &mut Ctx) -> i32 {
|
||||
pub fn printf(ctx: &mut Ctx, memory_offset: i32, extra: i32) -> i32 {
|
||||
debug!("emscripten::printf {}, {}", memory_offset, extra);
|
||||
unsafe {
|
||||
let addr = emscripten_memory_pointer!(ctx.memory(0), memory_offset) as _;
|
||||
_printf(addr, extra)
|
||||
}
|
||||
// unsafe {
|
||||
// let addr = emscripten_memory_pointer!(ctx.memory(0), memory_offset) as _;
|
||||
// _printf(addr, extra)
|
||||
// }
|
||||
-1
|
||||
}
|
||||
|
@ -4,29 +4,28 @@ use std::cell::UnsafeCell;
|
||||
use wasmer_runtime_core::vm::Ctx;
|
||||
|
||||
/// setjmp
|
||||
pub fn __setjmp(env_addr: u32, ctx: &mut Ctx) -> c_int {
|
||||
pub fn __setjmp(ctx: &mut Ctx, env_addr: u32) -> c_int {
|
||||
debug!("emscripten::__setjmp (setjmp)");
|
||||
unsafe {
|
||||
unimplemented!()
|
||||
// // Rather than using the env as the holder of the jump buffer pointer,
|
||||
// // we use the environment address to store the index relative to jumps
|
||||
// // so the address of the jump it's outside the wasm memory itself.
|
||||
// let jump_index = ctx.memory(0).as_ptr().add(env_addr as usize) as *mut i8;
|
||||
// // We create the jump buffer outside of the wasm memory
|
||||
// let jump_buf: UnsafeCell<[c_int; 27]> = UnsafeCell::new([0; 27]);
|
||||
// let jumps = &mut get_emscripten_data(ctx).jumps;
|
||||
// let result = setjmp(jump_buf.get() as _);
|
||||
// // We set the jump index to be the last value of jumps
|
||||
// *jump_index = jumps.len() as _;
|
||||
// // We hold the reference of the jump buffer
|
||||
// jumps.push(jump_buf);
|
||||
// result
|
||||
// Rather than using the env as the holder of the jump buffer pointer,
|
||||
// we use the environment address to store the index relative to jumps
|
||||
// so the address of the jump it's outside the wasm memory itself.
|
||||
let jump_index = emscripten_memory_pointer!(ctx.memory(0), env_addr) as *mut i8;
|
||||
// We create the jump buffer outside of the wasm memory
|
||||
let jump_buf: UnsafeCell<[u32; 27]> = UnsafeCell::new([0; 27]);
|
||||
let jumps = &mut get_emscripten_data(ctx).jumps;
|
||||
let result = setjmp(jump_buf.get() as _);
|
||||
// We set the jump index to be the last 3value of jumps
|
||||
*jump_index = jumps.len() as _;
|
||||
// We hold the reference of the jump buffer
|
||||
jumps.push(jump_buf);
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
/// longjmp
|
||||
#[allow(unreachable_code)]
|
||||
pub fn __longjmp(env_addr: u32, val: c_int, ctx: &mut Ctx) {
|
||||
pub fn __longjmp(ctx: &mut Ctx, env_addr: u32, val: c_int) {
|
||||
debug!("emscripten::__longjmp (longmp)");
|
||||
unsafe {
|
||||
// We retrieve the jump index from the env address
|
||||
|
@ -1,29 +1,20 @@
|
||||
#[macro_use]
|
||||
extern crate wasmer_runtime_core;
|
||||
|
||||
use byteorder::{ByteOrder, LittleEndian};
|
||||
use libc::c_int;
|
||||
use std::cell::UnsafeCell;
|
||||
use std::{f64, ffi::c_void, fmt, mem, ptr};
|
||||
use std::{f64, ffi::c_void};
|
||||
use wasmer_runtime_core::{
|
||||
error::CallResult,
|
||||
export::{Context, Export, FuncPointer},
|
||||
export::Export,
|
||||
func,
|
||||
global::Global,
|
||||
import::{ImportObject, Namespace},
|
||||
import::ImportObject,
|
||||
imports,
|
||||
memory::Memory,
|
||||
table::Table,
|
||||
types::{
|
||||
ElementType, FuncSig, GlobalDescriptor, MemoryDescriptor, TableDescriptor,
|
||||
Type::{self, *},
|
||||
Value,
|
||||
},
|
||||
types::{ElementType, MemoryDescriptor, TableDescriptor, Value},
|
||||
units::Pages,
|
||||
vm::Ctx,
|
||||
vm::LocalGlobal,
|
||||
vm::LocalMemory,
|
||||
vm::LocalTable,
|
||||
Func, Instance, Module,
|
||||
};
|
||||
|
||||
@ -141,7 +132,7 @@ pub fn run_emscripten_instance(
|
||||
let num_params = main_func.signature().params().len();
|
||||
let _result = match num_params {
|
||||
2 => {
|
||||
let (argc, argv) = store_module_arguments(path, args, instance.context_mut());
|
||||
let (argc, argv) = store_module_arguments(instance.context_mut(), path, args);
|
||||
instance.call("_main", &[Value::I32(argc as i32), Value::I32(argv as i32)])?;
|
||||
}
|
||||
0 => {
|
||||
@ -158,17 +149,17 @@ pub fn run_emscripten_instance(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn store_module_arguments(path: &str, args: Vec<&str>, ctx: &mut Ctx) -> (u32, u32) {
|
||||
fn store_module_arguments(ctx: &mut Ctx, path: &str, args: Vec<&str>) -> (u32, u32) {
|
||||
let argc = args.len() + 1;
|
||||
|
||||
let mut args_slice = vec![0; argc];
|
||||
args_slice[0] = unsafe { allocate_cstr_on_stack(path, ctx).0 };
|
||||
args_slice[0] = unsafe { allocate_cstr_on_stack(ctx, path).0 };
|
||||
for (slot, arg) in args_slice[1..argc].iter_mut().zip(args.iter()) {
|
||||
*slot = unsafe { allocate_cstr_on_stack(&arg, ctx).0 };
|
||||
*slot = unsafe { allocate_cstr_on_stack(ctx, &arg).0 };
|
||||
}
|
||||
|
||||
let (argv_offset, argv_slice): (_, &mut [u32]) =
|
||||
unsafe { allocate_on_stack(((argc + 1) * 4) as u32, ctx) };
|
||||
unsafe { allocate_on_stack(ctx, ((argc + 1) * 4) as u32) };
|
||||
assert!(!argv_slice.is_empty());
|
||||
for (slot, arg) in argv_slice[0..argc].iter_mut().zip(args_slice.iter()) {
|
||||
*slot = *arg
|
||||
|
@ -3,19 +3,19 @@ use wasmer_runtime_core::vm::Ctx;
|
||||
// TODO: Need to implement.
|
||||
|
||||
/// emscripten: dlopen(filename: *const c_char, flag: c_int) -> *mut c_void
|
||||
pub fn _dlopen(_filename: u32, _flag: u32, _ctx: &mut Ctx) -> i32 {
|
||||
pub fn _dlopen(_ctx: &mut Ctx, _filename: u32, _flag: u32) -> i32 {
|
||||
debug!("emscripten::_dlopen");
|
||||
-1
|
||||
}
|
||||
|
||||
/// emscripten: dlclose(handle: *mut c_void) -> c_int
|
||||
pub fn _dlclose(_filename: u32, _ctx: &mut Ctx) -> i32 {
|
||||
pub fn _dlclose(_ctx: &mut Ctx, _filename: u32) -> i32 {
|
||||
debug!("emscripten::_dlclose");
|
||||
-1
|
||||
}
|
||||
|
||||
/// emscripten: dlsym(handle: *mut c_void, symbol: *const c_char) -> *mut c_void
|
||||
pub fn _dlsym(_filepath: u32, _symbol: u32, _ctx: &mut Ctx) -> i32 {
|
||||
pub fn _dlsym(_ctx: &mut Ctx, _filepath: u32, _symbol: u32) -> i32 {
|
||||
debug!("emscripten::_dlsym");
|
||||
-1
|
||||
}
|
||||
|
@ -2,16 +2,16 @@ use libc::c_int;
|
||||
use wasmer_runtime_core::vm::Ctx;
|
||||
|
||||
// NOTE: Not implemented by Emscripten
|
||||
pub fn ___lock(what: c_int, _ctx: &mut Ctx) {
|
||||
pub fn ___lock(_ctx: &mut Ctx, what: c_int) {
|
||||
debug!("emscripten::___lock {}", what);
|
||||
}
|
||||
|
||||
// NOTE: Not implemented by Emscripten
|
||||
pub fn ___unlock(what: c_int, _ctx: &mut Ctx) {
|
||||
pub fn ___unlock(_ctx: &mut Ctx, what: c_int) {
|
||||
debug!("emscripten::___unlock {}", what);
|
||||
}
|
||||
|
||||
// NOTE: Not implemented by Emscripten
|
||||
pub fn ___wait(_which: u32, _varargs: u32, _three: u32, _four: u32, _ctx: &mut Ctx) {
|
||||
pub fn ___wait(_ctx: &mut Ctx, _which: u32, _varargs: u32, _three: u32, _four: u32) {
|
||||
debug!("emscripten::___wait");
|
||||
}
|
||||
|
@ -1,23 +1,23 @@
|
||||
use wasmer_runtime_core::vm::Ctx;
|
||||
|
||||
/// emscripten: _llvm_log10_f64
|
||||
pub fn _llvm_log10_f64(value: f64, _ctx: &mut Ctx) -> f64 {
|
||||
pub fn _llvm_log10_f64(_ctx: &mut Ctx, value: f64) -> f64 {
|
||||
debug!("emscripten::_llvm_log10_f64");
|
||||
value.log10()
|
||||
}
|
||||
|
||||
/// emscripten: _llvm_log2_f64
|
||||
pub fn _llvm_log2_f64(value: f64, _ctx: &mut Ctx) -> f64 {
|
||||
pub fn _llvm_log2_f64(_ctx: &mut Ctx, value: f64) -> f64 {
|
||||
debug!("emscripten::_llvm_log2_f64");
|
||||
value.log2()
|
||||
}
|
||||
|
||||
pub fn _llvm_log10_f32(_value: f64, _ctx: &mut Ctx) -> f64 {
|
||||
pub fn _llvm_log10_f32(_ctx: &mut Ctx, _value: f64) -> f64 {
|
||||
debug!("emscripten::_llvm_log10_f32");
|
||||
-1.0
|
||||
}
|
||||
|
||||
pub fn _llvm_log2_f32(_value: f64, _ctx: &mut Ctx) -> f64 {
|
||||
pub fn _llvm_log2_f32(_ctx: &mut Ctx, _value: f64) -> f64 {
|
||||
debug!("emscripten::_llvm_log10_f32");
|
||||
-1.0
|
||||
}
|
||||
@ -28,12 +28,12 @@ pub fn _emscripten_random(_ctx: &mut Ctx) -> f64 {
|
||||
}
|
||||
|
||||
// emscripten: f64-rem
|
||||
pub fn f64_rem(x: f64, y: f64, _ctx: &mut Ctx) -> f64 {
|
||||
pub fn f64_rem(_ctx: &mut Ctx, x: f64, y: f64) -> f64 {
|
||||
debug!("emscripten::f64-rem");
|
||||
x % y
|
||||
}
|
||||
|
||||
// emscripten: global.Math pow
|
||||
pub fn pow(x: f64, y: f64, _ctx: &mut Ctx) -> f64 {
|
||||
pub fn pow(_ctx: &mut Ctx, x: f64, y: f64) -> f64 {
|
||||
x.powf(y)
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ use libc::{c_int, c_void, memcpy, size_t};
|
||||
use wasmer_runtime_core::vm::Ctx;
|
||||
|
||||
/// emscripten: _emscripten_memcpy_big
|
||||
pub fn _emscripten_memcpy_big(dest: u32, src: u32, len: u32, ctx: &mut Ctx) -> u32 {
|
||||
pub fn _emscripten_memcpy_big(ctx: &mut Ctx, dest: u32, src: u32, len: u32) -> u32 {
|
||||
debug!(
|
||||
"emscripten::_emscripten_memcpy_big {}, {}, {}",
|
||||
dest, src, len
|
||||
@ -35,12 +35,12 @@ pub fn enlarge_memory(_ctx: &mut Ctx) -> u32 {
|
||||
/// emscripten: abortOnCannotGrowMemory
|
||||
pub fn abort_on_cannot_grow_memory(ctx: &mut Ctx) -> u32 {
|
||||
debug!("emscripten::abort_on_cannot_grow_memory");
|
||||
abort_with_message("Cannot enlarge memory arrays!", ctx);
|
||||
abort_with_message(ctx, "Cannot enlarge memory arrays!");
|
||||
0
|
||||
}
|
||||
|
||||
/// emscripten: ___map_file
|
||||
pub fn ___map_file(_one: u32, _two: u32, _ctx: &mut Ctx) -> c_int {
|
||||
pub fn ___map_file(_ctx: &mut Ctx, _one: u32, _two: u32) -> c_int {
|
||||
debug!("emscripten::___map_file");
|
||||
// NOTE: TODO: Em returns -1 here as well. May need to implement properly
|
||||
-1
|
||||
|
@ -1,67 +1,67 @@
|
||||
use super::process::abort_with_message;
|
||||
use wasmer_runtime_core::vm::Ctx;
|
||||
|
||||
pub fn nullfunc_i(x: u32, ctx: &mut Ctx) {
|
||||
pub fn nullfunc_i(ctx: &mut Ctx, x: u32) {
|
||||
debug!("emscripten::nullfunc_i {}", x);
|
||||
abort_with_message("Invalid function pointer called with signature 'i'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)", ctx);
|
||||
abort_with_message(ctx, "Invalid function pointer called with signature 'i'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)");
|
||||
}
|
||||
|
||||
pub fn nullfunc_ii(x: u32, ctx: &mut Ctx) {
|
||||
pub fn nullfunc_ii(ctx: &mut Ctx, x: u32) {
|
||||
debug!("emscripten::nullfunc_ii {}", x);
|
||||
abort_with_message("Invalid function pointer called with signature 'ii'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)", ctx);
|
||||
abort_with_message(ctx, "Invalid function pointer called with signature 'ii'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)");
|
||||
}
|
||||
|
||||
pub fn nullfunc_iii(x: u32, ctx: &mut Ctx) {
|
||||
pub fn nullfunc_iii(ctx: &mut Ctx, x: u32) {
|
||||
debug!("emscripten::nullfunc_iii {}", x);
|
||||
abort_with_message("Invalid function pointer called with signature 'iii'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)", ctx);
|
||||
abort_with_message(ctx, "Invalid function pointer called with signature 'iii'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)");
|
||||
}
|
||||
|
||||
pub fn nullfunc_iiii(x: u32, ctx: &mut Ctx) {
|
||||
pub fn nullfunc_iiii(ctx: &mut Ctx, x: u32) {
|
||||
debug!("emscripten::nullfunc_iiii {}", x);
|
||||
abort_with_message("Invalid function pointer called with signature 'iiii'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)", ctx);
|
||||
abort_with_message(ctx, "Invalid function pointer called with signature 'iiii'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)");
|
||||
}
|
||||
|
||||
pub fn nullfunc_iiiii(x: u32, ctx: &mut Ctx) {
|
||||
pub fn nullfunc_iiiii(ctx: &mut Ctx, x: u32) {
|
||||
debug!("emscripten::nullfunc_iiiii {}", x);
|
||||
abort_with_message("Invalid function pointer called with signature 'iiiii'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)", ctx);
|
||||
abort_with_message(ctx, "Invalid function pointer called with signature 'iiiii'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)");
|
||||
}
|
||||
|
||||
pub fn nullfunc_iiiiii(x: u32, ctx: &mut Ctx) {
|
||||
pub fn nullfunc_iiiiii(ctx: &mut Ctx, x: u32) {
|
||||
debug!("emscripten::nullfunc_iiiiii {}", x);
|
||||
abort_with_message("Invalid function pointer called with signature 'iiiiii'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)", ctx);
|
||||
abort_with_message(ctx, "Invalid function pointer called with signature 'iiiiii'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)");
|
||||
}
|
||||
|
||||
pub fn nullfunc_v(x: u32, ctx: &mut Ctx) {
|
||||
pub fn nullfunc_v(ctx: &mut Ctx, x: u32) {
|
||||
debug!("emscripten::nullfunc_v {}", x);
|
||||
abort_with_message("Invalid function pointer called with signature 'v'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)", ctx);
|
||||
abort_with_message(ctx, "Invalid function pointer called with signature 'v'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)");
|
||||
}
|
||||
|
||||
pub fn nullfunc_vi(x: u32, ctx: &mut Ctx) {
|
||||
pub fn nullfunc_vi(ctx: &mut Ctx, x: u32) {
|
||||
debug!("emscripten::nullfunc_vi {}", x);
|
||||
abort_with_message("Invalid function pointer called with signature 'vi'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)", ctx);
|
||||
abort_with_message(ctx, "Invalid function pointer called with signature 'vi'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)");
|
||||
}
|
||||
|
||||
pub fn nullfunc_vii(x: u32, ctx: &mut Ctx) {
|
||||
pub fn nullfunc_vii(ctx: &mut Ctx, x: u32) {
|
||||
debug!("emscripten::nullfunc_vii {}", x);
|
||||
abort_with_message("Invalid function pointer called with signature 'vii'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)", ctx);
|
||||
abort_with_message(ctx, "Invalid function pointer called with signature 'vii'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)");
|
||||
}
|
||||
|
||||
pub fn nullfunc_viii(x: u32, ctx: &mut Ctx) {
|
||||
pub fn nullfunc_viii(ctx: &mut Ctx, x: u32) {
|
||||
debug!("emscripten::nullfunc_viii {}", x);
|
||||
abort_with_message("Invalid function pointer called with signature 'viii'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)", ctx);
|
||||
abort_with_message(ctx, "Invalid function pointer called with signature 'viii'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)");
|
||||
}
|
||||
|
||||
pub fn nullfunc_viiii(x: u32, ctx: &mut Ctx) {
|
||||
pub fn nullfunc_viiii(ctx: &mut Ctx, x: u32) {
|
||||
debug!("emscripten::nullfunc_viiii {}", x);
|
||||
abort_with_message("Invalid function pointer called with signature 'viiii'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)", ctx);
|
||||
abort_with_message(ctx, "Invalid function pointer called with signature 'viiii'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)");
|
||||
}
|
||||
|
||||
pub fn nullfunc_viiiii(_x: u32, ctx: &mut Ctx) {
|
||||
pub fn nullfunc_viiiii(ctx: &mut Ctx, _x: u32) {
|
||||
debug!("emscripten::nullfunc_viiiii");
|
||||
abort_with_message("Invalid function pointer called with signature 'viiiii'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)", ctx);
|
||||
abort_with_message(ctx, "Invalid function pointer called with signature 'viiiii'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)");
|
||||
}
|
||||
|
||||
pub fn nullfunc_viiiiii(_x: u32, ctx: &mut Ctx) {
|
||||
pub fn nullfunc_viiiiii(ctx: &mut Ctx, _x: u32) {
|
||||
debug!("emscripten::nullfunc_viiiiii");
|
||||
abort_with_message("Invalid function pointer called with signature 'viiiiii'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)", ctx);
|
||||
abort_with_message(ctx, "Invalid function pointer called with signature 'viiiiii'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)");
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ type pid_t = c_int;
|
||||
use std::ffi::CStr;
|
||||
use wasmer_runtime_core::vm::Ctx;
|
||||
|
||||
pub fn abort_with_message(message: &str, ctx: &mut Ctx) {
|
||||
pub fn abort_with_message(ctx: &mut Ctx, message: &str) {
|
||||
debug!("emscripten::abort_with_message");
|
||||
println!("{}", message);
|
||||
_abort(ctx);
|
||||
@ -34,19 +34,19 @@ pub fn _endgrent(_ctx: &mut Ctx) {
|
||||
debug!("emscripten::_endgrent");
|
||||
}
|
||||
|
||||
pub fn _execve(_one: i32, _two: i32, _three: i32, _ctx: &mut Ctx) -> i32 {
|
||||
pub fn _execve(_ctx: &mut Ctx, _one: i32, _two: i32, _three: i32) -> i32 {
|
||||
debug!("emscripten::_execve");
|
||||
-1
|
||||
}
|
||||
|
||||
#[allow(unreachable_code)]
|
||||
pub fn _exit(status: c_int, _ctx: &mut Ctx) {
|
||||
pub fn _exit(_ctx: &mut Ctx, status: c_int) {
|
||||
// -> !
|
||||
debug!("emscripten::_exit {}", status);
|
||||
unsafe { exit(status) }
|
||||
}
|
||||
|
||||
pub fn em_abort(message: u32, ctx: &mut Ctx) {
|
||||
pub fn em_abort(ctx: &mut Ctx, message: u32) {
|
||||
debug!("emscripten::em_abort {}", message);
|
||||
let message_addr = emscripten_memory_pointer!(ctx.memory(0), message) as *mut c_char;
|
||||
unsafe {
|
||||
@ -54,11 +54,11 @@ pub fn em_abort(message: u32, ctx: &mut Ctx) {
|
||||
.to_str()
|
||||
.unwrap_or("Unexpected abort");
|
||||
|
||||
abort_with_message(message, ctx);
|
||||
abort_with_message(ctx, message);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn _kill(_one: i32, _two: i32, _ctx: &mut Ctx) -> i32 {
|
||||
pub fn _kill(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
|
||||
debug!("emscripten::_kill");
|
||||
-1
|
||||
}
|
||||
@ -73,26 +73,26 @@ pub fn _llvm_stacksave(_ctx: &mut Ctx) -> i32 {
|
||||
-1
|
||||
}
|
||||
|
||||
pub fn _llvm_stackrestore(_one: i32, _ctx: &mut Ctx) {
|
||||
pub fn _llvm_stackrestore(_ctx: &mut Ctx, _one: i32) {
|
||||
debug!("emscripten::_llvm_stackrestore");
|
||||
}
|
||||
|
||||
pub fn _raise(_one: i32, _ctx: &mut Ctx) -> i32 {
|
||||
pub fn _raise(_ctx: &mut Ctx, _one: i32) -> i32 {
|
||||
debug!("emscripten::_raise");
|
||||
-1
|
||||
}
|
||||
|
||||
pub fn _sem_init(_one: i32, _two: i32, _three: i32, _ctx: &mut Ctx) -> i32 {
|
||||
pub fn _sem_init(_ctx: &mut Ctx, _one: i32, _two: i32, _three: i32) -> i32 {
|
||||
debug!("emscripten::_sem_init");
|
||||
-1
|
||||
}
|
||||
|
||||
pub fn _sem_post(_one: i32, _ctx: &mut Ctx) -> i32 {
|
||||
pub fn _sem_post(_ctx: &mut Ctx, _one: i32) -> i32 {
|
||||
debug!("emscripten::_sem_post");
|
||||
-1
|
||||
}
|
||||
|
||||
pub fn _sem_wait(_one: i32, _ctx: &mut Ctx) -> i32 {
|
||||
pub fn _sem_wait(_ctx: &mut Ctx, _one: i32) -> i32 {
|
||||
debug!("emscripten::_sem_post");
|
||||
-1
|
||||
}
|
||||
@ -107,53 +107,53 @@ pub fn _setgrent(_ctx: &mut Ctx) {
|
||||
debug!("emscripten::_setgrent");
|
||||
}
|
||||
|
||||
pub fn _setgroups(_one: i32, _two: i32, _ctx: &mut Ctx) -> i32 {
|
||||
pub fn _setgroups(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
|
||||
debug!("emscripten::_setgroups");
|
||||
-1
|
||||
}
|
||||
|
||||
pub fn _setitimer(_one: i32, _two: i32, _three: i32, _ctx: &mut Ctx) -> i32 {
|
||||
pub fn _setitimer(_ctx: &mut Ctx, _one: i32, _two: i32, _three: i32) -> i32 {
|
||||
debug!("emscripten::_setitimer");
|
||||
-1
|
||||
}
|
||||
|
||||
pub fn _usleep(_one: i32, _ctx: &mut Ctx) -> i32 {
|
||||
pub fn _usleep(_ctx: &mut Ctx, _one: i32) -> i32 {
|
||||
debug!("emscripten::_usleep");
|
||||
-1
|
||||
}
|
||||
|
||||
pub fn _utimes(_one: i32, _two: i32, _ctx: &mut Ctx) -> i32 {
|
||||
pub fn _utimes(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
|
||||
debug!("emscripten::_utimes");
|
||||
-1
|
||||
}
|
||||
|
||||
pub fn _waitpid(_one: i32, _two: i32, _three: i32, _ctx: &mut Ctx) -> i32 {
|
||||
pub fn _waitpid(_ctx: &mut Ctx, _one: i32, _two: i32, _three: i32) -> i32 {
|
||||
debug!("emscripten::_waitpid");
|
||||
-1
|
||||
}
|
||||
|
||||
pub fn abort_stack_overflow(_what: c_int, ctx: &mut Ctx) {
|
||||
pub fn abort_stack_overflow(ctx: &mut Ctx, _what: c_int) {
|
||||
debug!("emscripten::abort_stack_overflow");
|
||||
// TODO: Message incomplete. Need to finish em runtime data first
|
||||
abort_with_message(
|
||||
"Stack overflow! Attempted to allocate some bytes on the stack",
|
||||
ctx,
|
||||
"Stack overflow! Attempted to allocate some bytes on the stack",
|
||||
);
|
||||
}
|
||||
|
||||
pub fn _llvm_trap(ctx: &mut Ctx) {
|
||||
debug!("emscripten::_llvm_trap");
|
||||
abort_with_message("abort!", ctx);
|
||||
abort_with_message(ctx, "abort!");
|
||||
}
|
||||
|
||||
pub fn _system(_one: i32, _ctx: &mut Ctx) -> c_int {
|
||||
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;
|
||||
}
|
||||
|
||||
pub fn _popen(_one: i32, _two: i32, _ctx: &mut Ctx) -> c_int {
|
||||
pub fn _popen(_ctx: &mut Ctx, _one: i32, _two: i32) -> c_int {
|
||||
debug!("emscripten::_popen");
|
||||
// TODO: May need to change this Em impl to a working version
|
||||
eprintln!("Missing function: popen");
|
||||
|
@ -2,7 +2,7 @@
|
||||
use wasmer_runtime_core::vm::Ctx;
|
||||
|
||||
#[allow(clippy::cast_ptr_alignment)]
|
||||
pub fn _sigemptyset(set: u32, ctx: &mut Ctx) -> i32 {
|
||||
pub fn _sigemptyset(ctx: &mut Ctx, set: u32) -> i32 {
|
||||
debug!("emscripten::_sigemptyset");
|
||||
let set_addr = emscripten_memory_pointer!(ctx.memory(0), set) as *mut u32;
|
||||
unsafe {
|
||||
@ -11,13 +11,13 @@ pub fn _sigemptyset(set: u32, ctx: &mut Ctx) -> i32 {
|
||||
0
|
||||
}
|
||||
|
||||
pub fn _sigaction(signum: u32, act: u32, oldact: u32, _ctx: &mut Ctx) -> i32 {
|
||||
pub fn _sigaction(_ctx: &mut Ctx, signum: u32, act: u32, oldact: u32) -> i32 {
|
||||
debug!("emscripten::_sigaction {}, {}, {}", signum, act, oldact);
|
||||
0
|
||||
}
|
||||
|
||||
#[allow(clippy::cast_ptr_alignment)]
|
||||
pub fn _sigaddset(set: u32, signum: u32, ctx: &mut Ctx) -> i32 {
|
||||
pub fn _sigaddset(ctx: &mut Ctx, set: u32, signum: u32) -> i32 {
|
||||
debug!("emscripten::_sigaddset {}, {}", set, signum);
|
||||
let set_addr = emscripten_memory_pointer!(ctx.memory(0), set) as *mut u32;
|
||||
unsafe {
|
||||
@ -26,17 +26,17 @@ pub fn _sigaddset(set: u32, signum: u32, ctx: &mut Ctx) -> i32 {
|
||||
0
|
||||
}
|
||||
|
||||
pub fn _sigsuspend(_one: i32, _ctx: &mut Ctx) -> i32 {
|
||||
pub fn _sigsuspend(_ctx: &mut Ctx, _one: i32) -> i32 {
|
||||
debug!("emscripten::_sigsuspend");
|
||||
-1
|
||||
}
|
||||
|
||||
pub fn _sigprocmask(_one: i32, _two: i32, _three: i32, _ctx: &mut Ctx) -> i32 {
|
||||
pub fn _sigprocmask(_ctx: &mut Ctx, _one: i32, _two: i32, _three: i32) -> i32 {
|
||||
debug!("emscripten::_sigprocmask");
|
||||
0
|
||||
}
|
||||
|
||||
pub fn _signal(sig: u32, _two: i32, _ctx: &mut Ctx) -> i32 {
|
||||
pub fn _signal(_ctx: &mut Ctx, sig: u32, _two: i32) -> i32 {
|
||||
debug!("emscripten::_signal ({})", sig);
|
||||
0
|
||||
}
|
||||
|
@ -11,6 +11,16 @@ pub struct StdioCapturer {
|
||||
stderr_reader: libc::c_int,
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
use libc::{STDERR_FILENO, STDOUT_FILENO};
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
const STDIN_FILENO: libc::c_int = 0;
|
||||
#[cfg(target_os = "windows")]
|
||||
const STDOUT_FILENO: libc::c_int = 1;
|
||||
#[cfg(target_os = "windows")]
|
||||
const STDERR_FILENO: libc::c_int = 2;
|
||||
|
||||
// Implementation inspired in
|
||||
// https://github.com/rust-lang/rust/blob/7d52cbce6db83e4fc2d8706b4e4b9c7da76cbcf8/src/test/run-pass/issues/issue-30490.rs
|
||||
// Currently only works in Unix systems (Mac, Linux)
|
||||
@ -30,14 +40,14 @@ impl StdioCapturer {
|
||||
}
|
||||
|
||||
pub fn new() -> Self {
|
||||
let stdout_backup = unsafe { libc::dup(libc::STDOUT_FILENO) };
|
||||
let stderr_backup = unsafe { libc::dup(libc::STDERR_FILENO) };
|
||||
let stdout_backup = unsafe { libc::dup(STDOUT_FILENO) };
|
||||
let stderr_backup = unsafe { libc::dup(STDERR_FILENO) };
|
||||
|
||||
let (stdout_reader, stdout_writer) = Self::pipe();
|
||||
let (stderr_reader, stderr_writer) = Self::pipe();
|
||||
|
||||
assert!(unsafe { libc::dup2(stdout_writer, libc::STDOUT_FILENO) } > -1);
|
||||
assert!(unsafe { libc::dup2(stderr_writer, libc::STDERR_FILENO) } > -1);
|
||||
assert!(unsafe { libc::dup2(stdout_writer, STDOUT_FILENO) } > -1);
|
||||
assert!(unsafe { libc::dup2(stderr_writer, STDERR_FILENO) } > -1);
|
||||
|
||||
// Make sure we close any duplicates of the writer end of the pipe,
|
||||
// otherwise we can get stuck reading from the pipe which has open
|
||||
@ -57,8 +67,8 @@ impl StdioCapturer {
|
||||
// The Stdio passed into the Command took over (and closed) std{out, err}
|
||||
// so we should restore them as they were.
|
||||
|
||||
assert!(unsafe { libc::dup2(self.stdout_backup, libc::STDOUT_FILENO) } > -1);
|
||||
assert!(unsafe { libc::dup2(self.stderr_backup, libc::STDERR_FILENO) } > -1);
|
||||
assert!(unsafe { libc::dup2(self.stdout_backup, STDOUT_FILENO) } > -1);
|
||||
assert!(unsafe { libc::dup2(self.stderr_backup, STDERR_FILENO) } > -1);
|
||||
|
||||
let fd = FileDescriptor::new(self.stdout_reader);
|
||||
let mut reader = BufReader::new(fd);
|
||||
|
@ -16,48 +16,30 @@ use byteorder::{ByteOrder, LittleEndian};
|
||||
/// NOTE: TODO: These syscalls only support wasm_32 for now because they assume offsets are u32
|
||||
/// Syscall list: https://www.cs.utexas.edu/~bismith/test/syscalls/syscalls32.html
|
||||
use libc::{
|
||||
accept,
|
||||
bind,
|
||||
// ENOTTY,
|
||||
c_char,
|
||||
c_int,
|
||||
c_void,
|
||||
chdir,
|
||||
// fcntl, setsockopt, getppid
|
||||
close,
|
||||
connect,
|
||||
dup2,
|
||||
exit,
|
||||
fstat,
|
||||
getpeername,
|
||||
getpid,
|
||||
getsockname,
|
||||
getsockopt,
|
||||
// iovec,
|
||||
listen,
|
||||
lseek,
|
||||
mkdir,
|
||||
off_t,
|
||||
open,
|
||||
read,
|
||||
// readv,
|
||||
recvfrom,
|
||||
rmdir,
|
||||
// writev,
|
||||
sendto,
|
||||
setsockopt,
|
||||
sockaddr,
|
||||
socket,
|
||||
ssize_t,
|
||||
stat,
|
||||
write,
|
||||
EINVAL,
|
||||
// sockaddr_in,
|
||||
};
|
||||
use wasmer_runtime_core::vm::Ctx;
|
||||
|
||||
use super::env;
|
||||
use std::mem;
|
||||
use std::slice;
|
||||
// use std::sys::fd::FileDesc;
|
||||
|
||||
@ -70,7 +52,7 @@ use libc::SO_NOSIGPIPE;
|
||||
const SO_NOSIGPIPE: c_int = 0;
|
||||
|
||||
/// exit
|
||||
pub fn ___syscall1(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) {
|
||||
pub fn ___syscall1(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) {
|
||||
debug!("emscripten::___syscall1 (exit) {}", which);
|
||||
let status: i32 = varargs.get(ctx);
|
||||
unsafe {
|
||||
@ -79,7 +61,7 @@ pub fn ___syscall1(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) {
|
||||
}
|
||||
|
||||
/// read
|
||||
pub fn ___syscall3(which: i32, mut varargs: VarArgs, ctx: &mut Ctx) -> i32 {
|
||||
pub fn ___syscall3(ctx: &mut Ctx, which: i32, mut varargs: VarArgs) -> i32 {
|
||||
// -> ssize_t
|
||||
debug!("emscripten::___syscall3 (read) {}", which);
|
||||
let fd: i32 = varargs.get(ctx);
|
||||
@ -93,7 +75,7 @@ pub fn ___syscall3(which: i32, mut varargs: VarArgs, ctx: &mut Ctx) -> i32 {
|
||||
}
|
||||
|
||||
/// write
|
||||
pub fn ___syscall4(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int {
|
||||
pub fn ___syscall4(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall4 (write) {}", which);
|
||||
let fd: i32 = varargs.get(ctx);
|
||||
let buf: u32 = varargs.get(ctx);
|
||||
@ -104,7 +86,7 @@ pub fn ___syscall4(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int {
|
||||
}
|
||||
|
||||
/// open
|
||||
pub fn ___syscall5(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int {
|
||||
pub fn ___syscall5(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall5 (open) {}", which);
|
||||
let pathname: u32 = varargs.get(ctx);
|
||||
let flags: i32 = varargs.get(ctx);
|
||||
@ -120,7 +102,7 @@ pub fn ___syscall5(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int {
|
||||
}
|
||||
|
||||
/// close
|
||||
pub fn ___syscall6(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int {
|
||||
pub fn ___syscall6(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall6 (close) {}", which);
|
||||
let fd: i32 = varargs.get(ctx);
|
||||
debug!("fd: {}", fd);
|
||||
@ -128,7 +110,7 @@ pub fn ___syscall6(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int {
|
||||
}
|
||||
|
||||
// chdir
|
||||
pub fn ___syscall12(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int {
|
||||
pub fn ___syscall12(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall12 (chdir) {}", which);
|
||||
let path_addr: i32 = varargs.get(ctx);
|
||||
unsafe {
|
||||
@ -140,42 +122,42 @@ pub fn ___syscall12(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ___syscall10(_one: i32, _two: i32, _ctx: &mut Ctx) -> i32 {
|
||||
pub fn ___syscall10(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
|
||||
debug!("emscripten::___syscall10");
|
||||
-1
|
||||
}
|
||||
|
||||
pub fn ___syscall15(_one: i32, _two: i32, _ctx: &mut Ctx) -> i32 {
|
||||
pub fn ___syscall15(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
|
||||
debug!("emscripten::___syscall15");
|
||||
-1
|
||||
}
|
||||
|
||||
// getpid
|
||||
pub fn ___syscall20(_one: i32, _two: i32, _ctx: &mut Ctx) -> i32 {
|
||||
pub fn ___syscall20(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
|
||||
debug!("emscripten::___syscall20 (getpid)");
|
||||
unsafe { getpid() }
|
||||
}
|
||||
|
||||
pub fn ___syscall38(_one: i32, _two: i32, _ctx: &mut Ctx) -> i32 {
|
||||
pub fn ___syscall38(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
|
||||
debug!("emscripten::___syscall38");
|
||||
-1
|
||||
}
|
||||
|
||||
// rmdir
|
||||
pub fn ___syscall40(_which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int {
|
||||
pub fn ___syscall40(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall40 (rmdir)");
|
||||
let pathname: u32 = varargs.get(ctx);
|
||||
let pathname_addr = emscripten_memory_pointer!(ctx.memory(0), pathname) as *const i8;
|
||||
unsafe { rmdir(pathname_addr) }
|
||||
}
|
||||
|
||||
pub fn ___syscall60(_one: i32, _two: i32, _ctx: &mut Ctx) -> i32 {
|
||||
pub fn ___syscall60(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
|
||||
debug!("emscripten::___syscall60");
|
||||
-1
|
||||
}
|
||||
|
||||
// dup2
|
||||
pub fn ___syscall63(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int {
|
||||
pub fn ___syscall63(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall63 (dup2) {}", which);
|
||||
|
||||
let src: i32 = varargs.get(ctx);
|
||||
@ -185,43 +167,43 @@ pub fn ___syscall63(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int
|
||||
}
|
||||
|
||||
// getppid
|
||||
pub fn ___syscall64(_one: i32, _two: i32, _ctx: &mut Ctx) -> i32 {
|
||||
pub fn ___syscall64(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
|
||||
debug!("emscripten::___syscall64 (getppid)");
|
||||
unsafe { getpid() }
|
||||
}
|
||||
|
||||
pub fn ___syscall66(_one: i32, _two: i32, _ctx: &mut Ctx) -> i32 {
|
||||
pub fn ___syscall66(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
|
||||
debug!("emscripten::___syscall66");
|
||||
-1
|
||||
}
|
||||
|
||||
pub fn ___syscall75(_one: i32, _two: i32, _ctx: &mut Ctx) -> i32 {
|
||||
pub fn ___syscall75(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
|
||||
debug!("emscripten::___syscall75");
|
||||
-1
|
||||
}
|
||||
|
||||
pub fn ___syscall85(_one: i32, _two: i32, _ctx: &mut Ctx) -> i32 {
|
||||
pub fn ___syscall85(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
|
||||
debug!("emscripten::___syscall85");
|
||||
-1
|
||||
}
|
||||
|
||||
pub fn ___syscall91(_one: i32, _two: i32, _ctx: &mut Ctx) -> i32 {
|
||||
pub fn ___syscall91(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
|
||||
debug!("emscripten::___syscall91");
|
||||
-1
|
||||
}
|
||||
|
||||
pub fn ___syscall97(_one: i32, _two: i32, _ctx: &mut Ctx) -> i32 {
|
||||
pub fn ___syscall97(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
|
||||
debug!("emscripten::___syscall97");
|
||||
-1
|
||||
}
|
||||
|
||||
pub fn ___syscall110(_one: i32, _two: i32, _ctx: &mut Ctx) -> i32 {
|
||||
pub fn ___syscall110(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
|
||||
debug!("emscripten::___syscall110");
|
||||
-1
|
||||
}
|
||||
|
||||
// mmap2
|
||||
pub fn ___syscall192(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int {
|
||||
pub fn ___syscall192(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall192 (mmap2) {}", which);
|
||||
let addr: i32 = varargs.get(ctx);
|
||||
let len: u32 = varargs.get(ctx);
|
||||
@ -235,11 +217,11 @@ pub fn ___syscall192(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int
|
||||
);
|
||||
|
||||
if fd == -1 {
|
||||
let ptr = env::call_memalign(16384, len, ctx);
|
||||
let ptr = env::call_memalign(ctx, 16384, len);
|
||||
if ptr == 0 {
|
||||
return -1;
|
||||
}
|
||||
env::call_memset(ptr, 0, len, ctx);
|
||||
env::call_memset(ctx, ptr, 0, len);
|
||||
ptr as _
|
||||
} else {
|
||||
-1
|
||||
@ -247,7 +229,7 @@ pub fn ___syscall192(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int
|
||||
}
|
||||
|
||||
/// lseek
|
||||
pub fn ___syscall140(which: i32, mut varargs: VarArgs, ctx: &mut Ctx) -> i32 {
|
||||
pub fn ___syscall140(ctx: &mut Ctx, which: i32, mut varargs: VarArgs) -> i32 {
|
||||
// -> c_int
|
||||
debug!("emscripten::___syscall140 (lseek) {}", which);
|
||||
let fd: i32 = varargs.get(ctx);
|
||||
@ -259,7 +241,7 @@ pub fn ___syscall140(which: i32, mut varargs: VarArgs, ctx: &mut Ctx) -> i32 {
|
||||
|
||||
/// readv
|
||||
#[allow(clippy::cast_ptr_alignment)]
|
||||
pub fn ___syscall145(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> i32 {
|
||||
pub fn ___syscall145(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> i32 {
|
||||
// -> ssize_t
|
||||
debug!("emscripten::___syscall145 (readv) {}", which);
|
||||
// let fd: i32 = varargs.get(ctx);
|
||||
@ -302,7 +284,7 @@ pub fn ___syscall145(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> i32 {
|
||||
|
||||
// writev
|
||||
#[allow(clippy::cast_ptr_alignment)]
|
||||
pub fn ___syscall146(which: i32, mut varargs: VarArgs, ctx: &mut Ctx) -> i32 {
|
||||
pub fn ___syscall146(ctx: &mut Ctx, which: i32, mut varargs: VarArgs) -> i32 {
|
||||
// -> ssize_t
|
||||
debug!("emscripten::___syscall146 (writev) {}", which);
|
||||
let fd: i32 = varargs.get(ctx);
|
||||
@ -336,33 +318,33 @@ pub fn ___syscall146(which: i32, mut varargs: VarArgs, ctx: &mut Ctx) -> i32 {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ___syscall168(_one: i32, _two: i32, _ctx: &mut Ctx) -> i32 {
|
||||
pub fn ___syscall168(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
|
||||
debug!("emscripten::___syscall168");
|
||||
-1
|
||||
}
|
||||
|
||||
pub fn ___syscall191(_one: i32, _two: i32, _ctx: &mut Ctx) -> i32 {
|
||||
pub fn ___syscall191(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
|
||||
debug!("emscripten::___syscall191 - stub");
|
||||
-1
|
||||
}
|
||||
|
||||
pub fn ___syscall194(_one: i32, _two: i32, _ctx: &mut Ctx) -> i32 {
|
||||
pub fn ___syscall194(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
|
||||
debug!("emscripten::___syscall194 - stub");
|
||||
-1
|
||||
}
|
||||
|
||||
pub fn ___syscall196(_one: i32, _two: i32, _ctx: &mut Ctx) -> i32 {
|
||||
pub fn ___syscall196(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
|
||||
debug!("emscripten::___syscall194 - stub");
|
||||
-1
|
||||
}
|
||||
|
||||
pub fn ___syscall199(_one: i32, _two: i32, _ctx: &mut Ctx) -> i32 {
|
||||
pub fn ___syscall199(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
|
||||
debug!("emscripten::___syscall199 - stub");
|
||||
-1
|
||||
}
|
||||
|
||||
// stat64
|
||||
pub fn ___syscall195(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int {
|
||||
pub fn ___syscall195(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall195 (stat64) {}", which);
|
||||
let pathname: u32 = varargs.get(ctx);
|
||||
let buf: u32 = varargs.get(ctx);
|
||||
@ -382,7 +364,7 @@ pub fn ___syscall195(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int
|
||||
}
|
||||
|
||||
// fstat64
|
||||
pub fn ___syscall197(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int {
|
||||
pub fn ___syscall197(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall197 (fstat64) {}", which);
|
||||
let fd: c_int = varargs.get(ctx);
|
||||
let buf: u32 = varargs.get(ctx);
|
||||
@ -400,13 +382,13 @@ pub fn ___syscall197(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int
|
||||
0
|
||||
}
|
||||
|
||||
pub fn ___syscall220(_one: i32, _two: i32, _ctx: &mut Ctx) -> i32 {
|
||||
pub fn ___syscall220(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
|
||||
debug!("emscripten::___syscall220");
|
||||
-1
|
||||
}
|
||||
|
||||
// fcntl64
|
||||
pub fn ___syscall221(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int {
|
||||
pub fn ___syscall221(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall221 (fcntl64) {}", which);
|
||||
// fcntl64
|
||||
let _fd: i32 = varargs.get(ctx);
|
||||
@ -417,33 +399,33 @@ pub fn ___syscall221(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ___syscall268(_one: i32, _two: i32, _ctx: &mut Ctx) -> i32 {
|
||||
pub fn ___syscall268(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
|
||||
debug!("emscripten::___syscall268");
|
||||
-1
|
||||
}
|
||||
|
||||
pub fn ___syscall272(_one: i32, _two: i32, _ctx: &mut Ctx) -> i32 {
|
||||
pub fn ___syscall272(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
|
||||
debug!("emscripten::___syscall272");
|
||||
-1
|
||||
}
|
||||
|
||||
pub fn ___syscall295(_one: i32, _two: i32, _ctx: &mut Ctx) -> i32 {
|
||||
pub fn ___syscall295(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
|
||||
debug!("emscripten::___syscall295");
|
||||
-1
|
||||
}
|
||||
|
||||
pub fn ___syscall300(_one: i32, _two: i32, _ctx: &mut Ctx) -> i32 {
|
||||
pub fn ___syscall300(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
|
||||
debug!("emscripten::___syscall300");
|
||||
-1
|
||||
}
|
||||
|
||||
pub fn ___syscall334(_one: i32, _two: i32, _ctx: &mut Ctx) -> i32 {
|
||||
pub fn ___syscall334(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
|
||||
debug!("emscripten::___syscall334");
|
||||
-1
|
||||
}
|
||||
|
||||
// prlimit64
|
||||
pub fn ___syscall340(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int {
|
||||
pub fn ___syscall340(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall340 (prlimit64), {}", which);
|
||||
// NOTE: Doesn't really matter. Wasm modules cannot exceed WASM_PAGE_SIZE anyway.
|
||||
let _pid: i32 = varargs.get(ctx);
|
||||
|
@ -1,5 +1,4 @@
|
||||
use crate::varargs::VarArgs;
|
||||
use byteorder::{ByteOrder, LittleEndian};
|
||||
/// NOTE: TODO: These syscalls only support wasm_32 for now because they assume offsets are u32
|
||||
/// Syscall list: https://www.cs.utexas.edu/~bismith/test/syscalls/syscalls32.html
|
||||
use libc::{
|
||||
@ -9,39 +8,28 @@ use libc::{
|
||||
c_char,
|
||||
c_int,
|
||||
c_void,
|
||||
chdir,
|
||||
chown,
|
||||
// fcntl, setsockopt, getppid
|
||||
close,
|
||||
connect,
|
||||
dup2,
|
||||
exit,
|
||||
fcntl,
|
||||
fstat,
|
||||
getgid,
|
||||
getpeername,
|
||||
getpid,
|
||||
getsockname,
|
||||
getsockopt,
|
||||
gid_t,
|
||||
in_addr_t,
|
||||
in_port_t,
|
||||
ioctl,
|
||||
// iovec,
|
||||
listen,
|
||||
lseek,
|
||||
mkdir,
|
||||
msghdr,
|
||||
off_t,
|
||||
open,
|
||||
pid_t,
|
||||
pread,
|
||||
pwrite,
|
||||
read,
|
||||
// readv,
|
||||
recvfrom,
|
||||
recvmsg,
|
||||
rmdir,
|
||||
// ENOTTY,
|
||||
rusage,
|
||||
sa_family_t,
|
||||
@ -54,11 +42,8 @@ use libc::{
|
||||
sockaddr,
|
||||
socket,
|
||||
socklen_t,
|
||||
ssize_t,
|
||||
stat,
|
||||
uname,
|
||||
utsname,
|
||||
write,
|
||||
EINVAL,
|
||||
// sockaddr_in,
|
||||
FIOCLEX,
|
||||
@ -71,9 +56,7 @@ use libc::{
|
||||
};
|
||||
use wasmer_runtime_core::vm::Ctx;
|
||||
|
||||
use super::env;
|
||||
use std::mem;
|
||||
use std::slice;
|
||||
|
||||
// Linking to functions that are not provided by rust libc
|
||||
#[cfg(target_os = "macos")]
|
||||
@ -94,7 +77,7 @@ use libc::SO_NOSIGPIPE;
|
||||
const SO_NOSIGPIPE: c_int = 0;
|
||||
|
||||
// chown
|
||||
pub fn ___syscall212(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int {
|
||||
pub fn ___syscall212(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall212 (chown) {}", which);
|
||||
|
||||
let pathname: u32 = varargs.get(ctx);
|
||||
@ -107,7 +90,7 @@ pub fn ___syscall212(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int
|
||||
}
|
||||
|
||||
// mkdir
|
||||
pub fn ___syscall39(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int {
|
||||
pub fn ___syscall39(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall39 (mkdir) {}", which);
|
||||
let pathname: u32 = varargs.get(ctx);
|
||||
let mode: u32 = varargs.get(ctx);
|
||||
@ -116,7 +99,7 @@ pub fn ___syscall39(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int
|
||||
}
|
||||
|
||||
// getgid
|
||||
pub fn ___syscall201(_one: i32, _two: i32, _ctx: &mut Ctx) -> i32 {
|
||||
pub fn ___syscall201(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
|
||||
debug!("emscripten::___syscall201 (getgid)");
|
||||
unsafe {
|
||||
// Maybe fix: Emscripten returns 0 always
|
||||
@ -125,7 +108,7 @@ pub fn ___syscall201(_one: i32, _two: i32, _ctx: &mut Ctx) -> i32 {
|
||||
}
|
||||
|
||||
// getgid32
|
||||
pub fn ___syscall202(_one: i32, _two: i32, _ctx: &mut Ctx) -> i32 {
|
||||
pub fn ___syscall202(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
|
||||
// gid_t
|
||||
debug!("emscripten::___syscall202 (getgid32)");
|
||||
unsafe {
|
||||
@ -135,7 +118,7 @@ pub fn ___syscall202(_one: i32, _two: i32, _ctx: &mut Ctx) -> i32 {
|
||||
}
|
||||
|
||||
/// dup3
|
||||
pub fn ___syscall330(_which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> pid_t {
|
||||
pub fn ___syscall330(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> pid_t {
|
||||
// Implementation based on description at https://linux.die.net/man/2/dup3
|
||||
debug!("emscripten::___syscall330 (dup3)");
|
||||
let oldfd: c_int = varargs.get(ctx);
|
||||
@ -169,7 +152,7 @@ pub fn ___syscall330(_which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> pid_
|
||||
}
|
||||
|
||||
/// ioctl
|
||||
pub fn ___syscall54(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int {
|
||||
pub fn ___syscall54(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall54 (ioctl) {}", which);
|
||||
let fd: i32 = varargs.get(ctx);
|
||||
let request: u32 = varargs.get(ctx);
|
||||
@ -212,7 +195,7 @@ pub fn ___syscall54(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int
|
||||
|
||||
// socketcall
|
||||
#[allow(clippy::cast_ptr_alignment)]
|
||||
pub fn ___syscall102(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int {
|
||||
pub fn ___syscall102(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall102 (socketcall) {}", which);
|
||||
let call: u32 = varargs.get(ctx);
|
||||
let mut socket_varargs: VarArgs = varargs.get(ctx);
|
||||
@ -464,7 +447,7 @@ pub fn ___syscall102(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int
|
||||
}
|
||||
|
||||
// pread
|
||||
pub fn ___syscall180(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int {
|
||||
pub fn ___syscall180(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall180 (pread) {}", which);
|
||||
let fd: i32 = varargs.get(ctx);
|
||||
let buf: u32 = varargs.get(ctx);
|
||||
@ -481,7 +464,7 @@ pub fn ___syscall180(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int
|
||||
}
|
||||
|
||||
// pwrite
|
||||
pub fn ___syscall181(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int {
|
||||
pub fn ___syscall181(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall181 (pwrite) {}", which);
|
||||
let fd: i32 = varargs.get(ctx);
|
||||
let buf: u32 = varargs.get(ctx);
|
||||
@ -503,7 +486,7 @@ pub fn ___syscall181(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int
|
||||
|
||||
/// wait4
|
||||
#[allow(clippy::cast_ptr_alignment)]
|
||||
pub fn ___syscall114(_which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> pid_t {
|
||||
pub fn ___syscall114(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> pid_t {
|
||||
debug!("emscripten::___syscall114 (wait4)");
|
||||
let pid: pid_t = varargs.get(ctx);
|
||||
let status: u32 = varargs.get(ctx);
|
||||
@ -521,7 +504,7 @@ pub fn ___syscall114(_which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> pid_
|
||||
|
||||
// select
|
||||
#[allow(clippy::cast_ptr_alignment)]
|
||||
pub fn ___syscall142(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int {
|
||||
pub fn ___syscall142(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall142 (newselect) {}", which);
|
||||
|
||||
let nfds: i32 = varargs.get(ctx);
|
||||
@ -540,7 +523,7 @@ pub fn ___syscall142(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int
|
||||
}
|
||||
|
||||
// setpgid
|
||||
pub fn ___syscall57(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int {
|
||||
pub fn ___syscall57(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall57 (setpgid) {}", which);
|
||||
let pid: i32 = varargs.get(ctx);
|
||||
let pgid: i32 = varargs.get(ctx);
|
||||
@ -549,7 +532,7 @@ pub fn ___syscall57(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int
|
||||
|
||||
/// uname
|
||||
// NOTE: Wondering if we should return custom utsname, like Emscripten.
|
||||
pub fn ___syscall122(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int {
|
||||
pub fn ___syscall122(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall122 (uname) {}", which);
|
||||
let buf: u32 = varargs.get(ctx);
|
||||
debug!("=> buf: {}", buf);
|
||||
|
@ -6,13 +6,13 @@ use wasmer_runtime_core::vm::Ctx;
|
||||
type pid_t = c_int;
|
||||
|
||||
// chown
|
||||
pub fn ___syscall212(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int {
|
||||
pub fn ___syscall212(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall212 (chown) {}", which);
|
||||
-1
|
||||
}
|
||||
|
||||
// mkdir
|
||||
pub fn ___syscall39(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int {
|
||||
pub fn ___syscall39(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall39 (mkdir) {}", which);
|
||||
let pathname: u32 = varargs.get(ctx);
|
||||
let mode: u32 = varargs.get(ctx);
|
||||
@ -21,72 +21,72 @@ pub fn ___syscall39(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int
|
||||
}
|
||||
|
||||
// getgid
|
||||
pub fn ___syscall201(_one: i32, _two: i32, _ctx: &mut Ctx) -> i32 {
|
||||
pub fn ___syscall201(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
|
||||
debug!("emscripten::___syscall201 (getgid)");
|
||||
-1
|
||||
}
|
||||
|
||||
// getgid32
|
||||
pub fn ___syscall202(_one: i32, _two: i32, _ctx: &mut Ctx) -> i32 {
|
||||
pub fn ___syscall202(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
|
||||
// gid_t
|
||||
debug!("emscripten::___syscall202 (getgid32)");
|
||||
-1
|
||||
}
|
||||
|
||||
/// dup3
|
||||
pub fn ___syscall330(_which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> pid_t {
|
||||
pub fn ___syscall330(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> pid_t {
|
||||
debug!("emscripten::___syscall330 (dup3)");
|
||||
-1
|
||||
}
|
||||
|
||||
/// ioctl
|
||||
pub fn ___syscall54(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int {
|
||||
pub fn ___syscall54(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall54 (ioctl) {}", which);
|
||||
-1
|
||||
}
|
||||
|
||||
// socketcall
|
||||
#[allow(clippy::cast_ptr_alignment)]
|
||||
pub fn ___syscall102(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int {
|
||||
pub fn ___syscall102(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall102 (socketcall) {}", which);
|
||||
-1
|
||||
}
|
||||
|
||||
// pread
|
||||
pub fn ___syscall180(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int {
|
||||
pub fn ___syscall180(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall180 (pread) {}", which);
|
||||
-1
|
||||
}
|
||||
|
||||
// pwrite
|
||||
pub fn ___syscall181(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int {
|
||||
pub fn ___syscall181(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall181 (pwrite) {}", which);
|
||||
-1
|
||||
}
|
||||
|
||||
/// wait4
|
||||
#[allow(clippy::cast_ptr_alignment)]
|
||||
pub fn ___syscall114(_which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> pid_t {
|
||||
pub fn ___syscall114(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> pid_t {
|
||||
debug!("emscripten::___syscall114 (wait4)");
|
||||
-1
|
||||
}
|
||||
|
||||
// select
|
||||
#[allow(clippy::cast_ptr_alignment)]
|
||||
pub fn ___syscall142(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int {
|
||||
pub fn ___syscall142(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall142 (newselect) {}", which);
|
||||
-1
|
||||
}
|
||||
|
||||
// setpgid
|
||||
pub fn ___syscall57(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int {
|
||||
pub fn ___syscall57(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall57 (setpgid) {}", which);
|
||||
-1
|
||||
}
|
||||
|
||||
/// uname
|
||||
// NOTE: Wondering if we should return custom utsname, like Emscripten.
|
||||
pub fn ___syscall122(which: c_int, mut varargs: VarArgs, ctx: &mut Ctx) -> c_int {
|
||||
pub fn ___syscall122(ctx: &mut Ctx, which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
debug!("emscripten::___syscall122 (uname) {}", which);
|
||||
-1
|
||||
}
|
||||
|
@ -1,16 +1,18 @@
|
||||
use super::utils::{copy_cstr_into_wasm, write_to_buf};
|
||||
use libc::{c_char, c_int, time_t};
|
||||
use libc::{c_char, c_int};
|
||||
use std::mem;
|
||||
use std::time::SystemTime;
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
use libc::{clockid_t, time as libc_time};
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
use libc::time_t;
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
type clockid_t = c_int;
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
#[link(name = "c")]
|
||||
extern "C" {
|
||||
#[link_name = "time"]
|
||||
pub fn libc_time(s: *const time_t) -> time_t;
|
||||
@ -39,7 +41,7 @@ const CLOCK_MONOTONIC_COARSE: clockid_t = 6;
|
||||
|
||||
/// emscripten: _gettimeofday
|
||||
#[allow(clippy::cast_ptr_alignment)]
|
||||
pub fn _gettimeofday(tp: c_int, tz: c_int, ctx: &mut Ctx) -> c_int {
|
||||
pub fn _gettimeofday(ctx: &mut Ctx, tp: c_int, tz: c_int) -> c_int {
|
||||
debug!("emscripten::_gettimeofday {} {}", tp, tz);
|
||||
#[repr(C)]
|
||||
struct GuestTimeVal {
|
||||
@ -64,7 +66,7 @@ pub fn _gettimeofday(tp: c_int, tz: c_int, ctx: &mut Ctx) -> c_int {
|
||||
|
||||
/// emscripten: _clock_gettime
|
||||
#[allow(clippy::cast_ptr_alignment)]
|
||||
pub fn _clock_gettime(clk_id: clockid_t, tp: c_int, ctx: &mut Ctx) -> c_int {
|
||||
pub fn _clock_gettime(ctx: &mut Ctx, clk_id: clockid_t, tp: c_int) -> c_int {
|
||||
debug!("emscripten::_clock_gettime {} {}", clk_id, tp);
|
||||
// debug!("Memory {:?}", ctx.memory(0)[..]);
|
||||
#[repr(C)]
|
||||
@ -95,9 +97,9 @@ pub fn _clock_gettime(clk_id: clockid_t, tp: c_int, ctx: &mut Ctx) -> c_int {
|
||||
}
|
||||
|
||||
/// emscripten: ___clock_gettime
|
||||
pub fn ___clock_gettime(clk_id: clockid_t, tp: c_int, ctx: &mut Ctx) -> c_int {
|
||||
pub fn ___clock_gettime(ctx: &mut Ctx, clk_id: clockid_t, tp: c_int) -> c_int {
|
||||
debug!("emscripten::___clock_gettime {} {}", clk_id, tp);
|
||||
_clock_gettime(clk_id, tp, ctx)
|
||||
_clock_gettime(ctx, clk_id, tp)
|
||||
}
|
||||
|
||||
/// emscripten: _clock
|
||||
@ -107,22 +109,22 @@ pub fn _clock(_ctx: &mut Ctx) -> c_int {
|
||||
}
|
||||
|
||||
/// emscripten: _difftime
|
||||
pub fn _difftime(t0: u32, t1: u32, _ctx: &mut Ctx) -> f64 {
|
||||
pub fn _difftime(_ctx: &mut Ctx, t0: u32, t1: u32) -> f64 {
|
||||
debug!("emscripten::_difftime");
|
||||
(t0 - t1) as _
|
||||
}
|
||||
|
||||
pub fn _gmtime_r(_one: i32, _two: i32, _ctx: &mut Ctx) -> i32 {
|
||||
pub fn _gmtime_r(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
|
||||
debug!("emscripten::_gmtime_r");
|
||||
-1
|
||||
}
|
||||
|
||||
pub fn _mktime(_one: i32, _ctx: &mut Ctx) -> i32 {
|
||||
pub fn _mktime(_ctx: &mut Ctx, _one: i32) -> i32 {
|
||||
debug!("emscripten::_mktime");
|
||||
-1
|
||||
}
|
||||
|
||||
pub fn _gmtime(_one: i32, _ctx: &mut Ctx) -> i32 {
|
||||
pub fn _gmtime(_ctx: &mut Ctx, _one: i32) -> i32 {
|
||||
debug!("emscripten::_gmtime");
|
||||
-1
|
||||
}
|
||||
@ -149,7 +151,7 @@ pub fn _tvset(_ctx: &mut Ctx) {
|
||||
|
||||
/// formats time as a C string
|
||||
#[allow(clippy::cast_ptr_alignment)]
|
||||
unsafe fn fmt_time(time: u32, ctx: &mut Ctx) -> *const c_char {
|
||||
unsafe fn fmt_time(ctx: &mut Ctx, time: u32) -> *const c_char {
|
||||
let date = &*(emscripten_memory_pointer!(ctx.memory(0), time) as *mut guest_tm);
|
||||
|
||||
let days = vec!["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
|
||||
@ -174,11 +176,11 @@ unsafe fn fmt_time(time: u32, ctx: &mut Ctx) -> *const c_char {
|
||||
}
|
||||
|
||||
/// emscripten: _asctime
|
||||
pub fn _asctime(time: u32, ctx: &mut Ctx) -> u32 {
|
||||
pub fn _asctime(ctx: &mut Ctx, time: u32) -> u32 {
|
||||
debug!("emscripten::_asctime {}", time);
|
||||
|
||||
unsafe {
|
||||
let time_str_ptr = fmt_time(time, ctx);
|
||||
let time_str_ptr = fmt_time(ctx, time);
|
||||
copy_cstr_into_wasm(ctx, time_str_ptr)
|
||||
|
||||
// let c_str = emscripten_memory_pointer!(ctx.memory(0), res) as *mut i8;
|
||||
@ -188,7 +190,7 @@ pub fn _asctime(time: u32, ctx: &mut Ctx) -> u32 {
|
||||
}
|
||||
|
||||
/// emscripten: _asctime_r
|
||||
pub fn _asctime_r(time: u32, buf: u32, ctx: &mut Ctx) -> u32 {
|
||||
pub fn _asctime_r(ctx: &mut Ctx, time: u32, buf: u32) -> u32 {
|
||||
debug!("emscripten::_asctime_r {}, {}", time, buf);
|
||||
|
||||
unsafe {
|
||||
@ -196,8 +198,8 @@ pub fn _asctime_r(time: u32, buf: u32, ctx: &mut Ctx) -> u32 {
|
||||
// to write out more than 26 bytes (including the null terminator).
|
||||
// See http://pubs.opengroup.org/onlinepubs/9699919799/functions/asctime.html
|
||||
// Our undefined behavior is to truncate the write to at most 26 bytes, including null terminator.
|
||||
let time_str_ptr = fmt_time(time, ctx);
|
||||
write_to_buf(time_str_ptr, buf, 26, ctx)
|
||||
let time_str_ptr = fmt_time(ctx, time);
|
||||
write_to_buf(ctx, time_str_ptr, buf, 26)
|
||||
|
||||
// let c_str = emscripten_memory_pointer!(ctx.memory(0), res) as *mut i8;
|
||||
// use std::ffi::CStr;
|
||||
@ -207,7 +209,7 @@ pub fn _asctime_r(time: u32, buf: u32, ctx: &mut Ctx) -> u32 {
|
||||
|
||||
/// emscripten: _localtime
|
||||
#[allow(clippy::cast_ptr_alignment)]
|
||||
pub fn _localtime(time_p: u32, ctx: &mut Ctx) -> c_int {
|
||||
pub fn _localtime(ctx: &mut Ctx, time_p: u32) -> c_int {
|
||||
debug!("emscripten::_localtime {}", time_p);
|
||||
// NOTE: emscripten seems to want tzset() called in this function
|
||||
// https://stackoverflow.com/questions/19170721/real-time-awareness-of-timezone-change-in-localtime-vs-localtime-r
|
||||
@ -220,7 +222,7 @@ pub fn _localtime(time_p: u32, ctx: &mut Ctx) -> c_int {
|
||||
let result_tm = time::at(timespec);
|
||||
|
||||
unsafe {
|
||||
let tm_struct_offset = env::call_malloc(mem::size_of::<guest_tm>() as _, ctx);
|
||||
let tm_struct_offset = env::call_malloc(ctx, mem::size_of::<guest_tm>() as _);
|
||||
let tm_struct_ptr =
|
||||
emscripten_memory_pointer!(ctx.memory(0), tm_struct_offset) as *mut guest_tm;
|
||||
// debug!(
|
||||
@ -245,7 +247,7 @@ pub fn _localtime(time_p: u32, ctx: &mut Ctx) -> c_int {
|
||||
}
|
||||
/// emscripten: _localtime_r
|
||||
#[allow(clippy::cast_ptr_alignment)]
|
||||
pub fn _localtime_r(time_p: u32, result: u32, ctx: &mut Ctx) -> c_int {
|
||||
pub fn _localtime_r(ctx: &mut Ctx, time_p: u32, result: u32) -> c_int {
|
||||
debug!("emscripten::_localtime_r {}", time_p);
|
||||
|
||||
// NOTE: emscripten seems to want tzset() called in this function
|
||||
@ -282,7 +284,7 @@ pub fn _localtime_r(time_p: u32, result: u32, ctx: &mut Ctx) -> c_int {
|
||||
|
||||
/// emscripten: _time
|
||||
#[allow(clippy::cast_ptr_alignment)]
|
||||
pub fn _time(time_p: u32, ctx: &mut Ctx) -> i32 {
|
||||
pub fn _time(ctx: &mut Ctx, time_p: u32) -> i32 {
|
||||
debug!("emscripten::_time {}", time_p);
|
||||
|
||||
unsafe {
|
||||
@ -293,11 +295,11 @@ pub fn _time(time_p: u32, ctx: &mut Ctx) -> i32 {
|
||||
|
||||
/// emscripten: _strftime
|
||||
pub fn _strftime(
|
||||
_ctx: &mut Ctx,
|
||||
s_ptr: c_int,
|
||||
maxsize: u32,
|
||||
format_ptr: c_int,
|
||||
tm_ptr: c_int,
|
||||
_ctx: &mut Ctx,
|
||||
) -> i32 {
|
||||
debug!(
|
||||
"emscripten::_strftime {} {} {} {}",
|
||||
|
@ -2,10 +2,8 @@ use super::env;
|
||||
use super::env::get_emscripten_data;
|
||||
use libc::stat;
|
||||
use std::ffi::CStr;
|
||||
use std::ffi::CString;
|
||||
use std::mem::size_of;
|
||||
use std::os::raw::c_char;
|
||||
use std::os::raw::c_int;
|
||||
use std::slice;
|
||||
use wasmer_runtime_core::memory::Memory;
|
||||
use wasmer_runtime_core::{
|
||||
@ -42,7 +40,7 @@ pub fn get_emscripten_memory_size(module: &Module) -> (Pages, Option<Pages>) {
|
||||
(memory.minimum, memory.maximum)
|
||||
}
|
||||
|
||||
pub unsafe fn write_to_buf(string: *const c_char, buf: u32, max: u32, ctx: &mut Ctx) -> u32 {
|
||||
pub unsafe fn write_to_buf(ctx: &mut Ctx, string: *const c_char, buf: u32, max: u32) -> u32 {
|
||||
let buf_addr = emscripten_memory_pointer!(ctx.memory(0), buf) as *mut c_char;
|
||||
|
||||
for i in 0..max {
|
||||
@ -56,7 +54,7 @@ pub unsafe fn write_to_buf(string: *const c_char, buf: u32, max: u32, ctx: &mut
|
||||
pub unsafe fn copy_cstr_into_wasm(ctx: &mut Ctx, cstr: *const c_char) -> u32 {
|
||||
let s = CStr::from_ptr(cstr).to_str().unwrap();
|
||||
let cstr_len = s.len();
|
||||
let space_offset = env::call_malloc((cstr_len as u32) + 1, ctx);
|
||||
let space_offset = env::call_malloc(ctx, (cstr_len as u32) + 1);
|
||||
let raw_memory = emscripten_memory_pointer!(ctx.memory(0), space_offset) as *mut c_char;
|
||||
let slice = slice::from_raw_parts_mut(raw_memory, cstr_len);
|
||||
|
||||
@ -71,7 +69,7 @@ pub unsafe fn copy_cstr_into_wasm(ctx: &mut Ctx, cstr: *const c_char) -> u32 {
|
||||
space_offset
|
||||
}
|
||||
|
||||
pub unsafe fn allocate_on_stack<'a, T: Copy>(count: u32, ctx: &'a mut Ctx) -> (u32, &'a mut [T]) {
|
||||
pub unsafe fn allocate_on_stack<'a, T: Copy>(ctx: &'a mut Ctx, count: u32) -> (u32, &'a mut [T]) {
|
||||
let offset = get_emscripten_data(ctx)
|
||||
.stack_alloc
|
||||
.call(count * (size_of::<T>() as u32))
|
||||
@ -82,8 +80,8 @@ pub unsafe fn allocate_on_stack<'a, T: Copy>(count: u32, ctx: &'a mut Ctx) -> (u
|
||||
(offset, slice)
|
||||
}
|
||||
|
||||
pub unsafe fn allocate_cstr_on_stack<'a>(s: &str, ctx: &'a mut Ctx) -> (u32, &'a [u8]) {
|
||||
let (offset, slice) = allocate_on_stack((s.len() + 1) as u32, ctx);
|
||||
pub unsafe fn allocate_cstr_on_stack<'a>(ctx: &'a mut Ctx, s: &str) -> (u32, &'a [u8]) {
|
||||
let (offset, slice) = allocate_on_stack(ctx, (s.len() + 1) as u32);
|
||||
|
||||
use std::iter;
|
||||
for (byte, loc) in s.bytes().chain(iter::once(0)).zip(slice.iter_mut()) {
|
||||
|
@ -32,7 +32,7 @@ impl IsExport for Export {
|
||||
/// },
|
||||
/// };
|
||||
///
|
||||
/// fn foo(n: i32, _: &mut Ctx) -> i32 {
|
||||
/// fn foo(_: &mut Ctx, n: i32) -> i32 {
|
||||
/// n
|
||||
/// }
|
||||
/// ```
|
||||
|
@ -38,7 +38,7 @@ macro_rules! func {
|
||||
/// },
|
||||
/// };
|
||||
///
|
||||
/// fn foo(n: i32, _: &mut Ctx) -> i32 {
|
||||
/// fn foo(_: &mut Ctx, n: i32) -> i32 {
|
||||
/// n
|
||||
/// }
|
||||
/// ```
|
||||
|
@ -150,7 +150,8 @@ impl Drop for Memory {
|
||||
fn drop(&mut self) {
|
||||
if !self.ptr.is_null() {
|
||||
let success = unsafe { VirtualFree(self.ptr as _, self.size, MEM_DECOMMIT) };
|
||||
assert_eq!(success, 0, "failed to unmap memory: {}", errno::errno());
|
||||
// If the function succeeds, the return value is nonzero.
|
||||
assert_eq!(success, 1, "failed to unmap memory: {}", errno::errno());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -138,9 +138,9 @@ impl<A: WasmExternType> WasmTypeList for (A,) {
|
||||
}
|
||||
#[allow(non_snake_case)]
|
||||
unsafe fn call<Rets: WasmTypeList>(self, f: *const (), ctx: *mut Ctx) -> Rets {
|
||||
let f: extern "C" fn(A, *mut Ctx) -> Rets = mem::transmute(f);
|
||||
let f: extern "C" fn(*mut Ctx, A) -> Rets = mem::transmute(f);
|
||||
let (a,) = self;
|
||||
f(a, ctx)
|
||||
f(ctx, a)
|
||||
}
|
||||
}
|
||||
|
||||
@ -175,24 +175,24 @@ macro_rules! impl_traits {
|
||||
}
|
||||
#[allow(non_snake_case)]
|
||||
unsafe fn call<Rets: WasmTypeList>(self, f: *const (), ctx: *mut Ctx) -> Rets {
|
||||
let f: extern fn( $( $x, )* *mut Ctx) -> Rets::CStruct = mem::transmute(f);
|
||||
let f: extern fn(*mut Ctx $( ,$x )*) -> Rets::CStruct = mem::transmute(f);
|
||||
#[allow(unused_parens)]
|
||||
let ( $( $x ),* ) = self;
|
||||
let c_struct = f( $( $x, )* ctx);
|
||||
let c_struct = f(ctx $( ,$x )*);
|
||||
Rets::from_c_struct(c_struct)
|
||||
}
|
||||
}
|
||||
|
||||
impl< $( $x: WasmExternType, )* Rets: WasmTypeList, Trap: TrapEarly<Rets>, FN: Fn( $( $x, )* &mut Ctx) -> Trap> ExternalFunction<($( $x ),*), Rets> for FN {
|
||||
impl< $( $x: WasmExternType, )* Rets: WasmTypeList, Trap: TrapEarly<Rets>, FN: Fn( &mut Ctx $( ,$x )* ) -> Trap> ExternalFunction<($( $x ),*), Rets> for FN {
|
||||
#[allow(non_snake_case)]
|
||||
fn to_raw(&self) -> *const () {
|
||||
assert_eq!(mem::size_of::<Self>(), 0, "you cannot use a closure that captures state for `Func`.");
|
||||
|
||||
extern fn wrap<$( $x: WasmExternType, )* Rets: WasmTypeList, Trap: TrapEarly<Rets>, FN: Fn( $( $x, )* &mut Ctx) -> Trap>( $( $x: $x, )* ctx: &mut Ctx) -> Rets::CStruct {
|
||||
extern fn wrap<$( $x: WasmExternType, )* Rets: WasmTypeList, Trap: TrapEarly<Rets>, FN: Fn( &mut Ctx $( ,$x )* ) -> Trap>( ctx: &mut Ctx $( ,$x: $x )* ) -> Rets::CStruct {
|
||||
let f: FN = unsafe { mem::transmute_copy(&()) };
|
||||
|
||||
let msg = match panic::catch_unwind(panic::AssertUnwindSafe(|| {
|
||||
f( $( $x, )* ctx).report()
|
||||
f( ctx $( ,$x )* ).report()
|
||||
})) {
|
||||
Ok(Ok(returns)) => return returns.into_c_struct(),
|
||||
Ok(Err(err)) => err,
|
||||
@ -271,7 +271,7 @@ mod tests {
|
||||
use super::*;
|
||||
#[test]
|
||||
fn test_call() {
|
||||
fn foo(a: i32, b: i32, _ctx: &mut Ctx) -> (i32, i32) {
|
||||
fn foo(_ctx: &mut Ctx, a: i32, b: i32) -> (i32, i32) {
|
||||
(a, b)
|
||||
}
|
||||
|
||||
@ -282,7 +282,7 @@ mod tests {
|
||||
fn test_imports() {
|
||||
use crate::{func, imports};
|
||||
|
||||
fn foo(a: i32, _ctx: &mut Ctx) -> i32 {
|
||||
fn foo(_ctx: &mut Ctx, a: i32) -> i32 {
|
||||
a
|
||||
}
|
||||
|
||||
|
@ -169,6 +169,7 @@ enum InnerFunc {}
|
||||
/// Used to provide type safety (ish) for passing around function pointers.
|
||||
/// The typesystem ensures this cannot be dereferenced since an
|
||||
/// empty enum cannot actually exist.
|
||||
#[repr(C)]
|
||||
pub struct Func(InnerFunc);
|
||||
|
||||
/// An imported function, which contains the vmctx that owns this function.
|
||||
|
@ -13,9 +13,9 @@ use crate::{
|
||||
// +****************************+
|
||||
|
||||
pub unsafe extern "C" fn local_static_memory_grow(
|
||||
ctx: &mut vm::Ctx,
|
||||
memory_index: LocalMemoryIndex,
|
||||
delta: Pages,
|
||||
ctx: &mut vm::Ctx,
|
||||
) -> i32 {
|
||||
let local_memory = *ctx.memories.add(memory_index.index());
|
||||
let memory = (*local_memory).memory as *mut StaticMemory;
|
||||
@ -28,8 +28,8 @@ pub unsafe extern "C" fn local_static_memory_grow(
|
||||
}
|
||||
|
||||
pub unsafe extern "C" fn local_static_memory_size(
|
||||
memory_index: LocalMemoryIndex,
|
||||
ctx: &vm::Ctx,
|
||||
memory_index: LocalMemoryIndex,
|
||||
) -> Pages {
|
||||
let local_memory = *ctx.memories.add(memory_index.index());
|
||||
let memory = (*local_memory).memory as *mut StaticMemory;
|
||||
@ -38,9 +38,9 @@ pub unsafe extern "C" fn local_static_memory_size(
|
||||
}
|
||||
|
||||
pub unsafe extern "C" fn local_dynamic_memory_grow(
|
||||
ctx: &mut vm::Ctx,
|
||||
memory_index: LocalMemoryIndex,
|
||||
delta: Pages,
|
||||
ctx: &mut vm::Ctx,
|
||||
) -> i32 {
|
||||
let local_memory = *ctx.memories.add(memory_index.index());
|
||||
let memory = (*local_memory).memory as *mut DynamicMemory;
|
||||
@ -53,8 +53,8 @@ pub unsafe extern "C" fn local_dynamic_memory_grow(
|
||||
}
|
||||
|
||||
pub unsafe extern "C" fn local_dynamic_memory_size(
|
||||
memory_index: LocalMemoryIndex,
|
||||
ctx: &vm::Ctx,
|
||||
memory_index: LocalMemoryIndex,
|
||||
) -> Pages {
|
||||
let local_memory = *ctx.memories.add(memory_index.index());
|
||||
let memory = (*local_memory).memory as *mut DynamicMemory;
|
||||
@ -67,9 +67,9 @@ pub unsafe extern "C" fn local_dynamic_memory_size(
|
||||
// +****************************+
|
||||
|
||||
pub unsafe extern "C" fn imported_static_memory_grow(
|
||||
ctx: &mut vm::Ctx,
|
||||
import_memory_index: ImportedMemoryIndex,
|
||||
delta: Pages,
|
||||
ctx: &mut vm::Ctx,
|
||||
) -> i32 {
|
||||
let local_memory = *ctx.imported_memories.add(import_memory_index.index());
|
||||
let memory = (*local_memory).memory as *mut StaticMemory;
|
||||
@ -82,8 +82,8 @@ pub unsafe extern "C" fn imported_static_memory_grow(
|
||||
}
|
||||
|
||||
pub unsafe extern "C" fn imported_static_memory_size(
|
||||
import_memory_index: ImportedMemoryIndex,
|
||||
ctx: &vm::Ctx,
|
||||
import_memory_index: ImportedMemoryIndex,
|
||||
) -> Pages {
|
||||
let local_memory = *ctx.imported_memories.add(import_memory_index.index());
|
||||
let memory = (*local_memory).memory as *mut StaticMemory;
|
||||
@ -92,9 +92,9 @@ pub unsafe extern "C" fn imported_static_memory_size(
|
||||
}
|
||||
|
||||
pub unsafe extern "C" fn imported_dynamic_memory_grow(
|
||||
ctx: &mut vm::Ctx,
|
||||
memory_index: ImportedMemoryIndex,
|
||||
delta: Pages,
|
||||
ctx: &mut vm::Ctx,
|
||||
) -> i32 {
|
||||
let local_memory = *ctx.imported_memories.add(memory_index.index());
|
||||
let memory = (*local_memory).memory as *mut DynamicMemory;
|
||||
@ -107,8 +107,8 @@ pub unsafe extern "C" fn imported_dynamic_memory_grow(
|
||||
}
|
||||
|
||||
pub unsafe extern "C" fn imported_dynamic_memory_size(
|
||||
memory_index: ImportedMemoryIndex,
|
||||
ctx: &vm::Ctx,
|
||||
memory_index: ImportedMemoryIndex,
|
||||
) -> Pages {
|
||||
let local_memory = *ctx.imported_memories.add(memory_index.index());
|
||||
let memory = (*local_memory).memory as *mut DynamicMemory;
|
||||
@ -121,9 +121,9 @@ pub unsafe extern "C" fn imported_dynamic_memory_size(
|
||||
// +****************************+
|
||||
|
||||
pub unsafe extern "C" fn local_table_grow(
|
||||
ctx: &mut vm::Ctx,
|
||||
table_index: LocalTableIndex,
|
||||
delta: u32,
|
||||
ctx: &mut vm::Ctx,
|
||||
) -> i32 {
|
||||
let _ = table_index;
|
||||
let _ = delta;
|
||||
@ -131,7 +131,7 @@ pub unsafe extern "C" fn local_table_grow(
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
pub unsafe extern "C" fn local_table_size(table_index: LocalTableIndex, ctx: &vm::Ctx) -> u32 {
|
||||
pub unsafe extern "C" fn local_table_size(ctx: &vm::Ctx, table_index: LocalTableIndex) -> u32 {
|
||||
let _ = table_index;
|
||||
let _ = ctx;
|
||||
unimplemented!()
|
||||
|
@ -1,8 +1,6 @@
|
||||
use std::fs::remove_file;
|
||||
use wabt::wat2wasm;
|
||||
use wasmer_clif_backend::CraneliftCompiler;
|
||||
use wasmer_runtime_core::{
|
||||
cache::Cache,
|
||||
error,
|
||||
global::Global,
|
||||
memory::Memory,
|
||||
@ -15,7 +13,6 @@ use wasmer_runtime_core::{
|
||||
static EXAMPLE_WASM: &'static [u8] = include_bytes!("simple.wasm");
|
||||
|
||||
fn main() -> error::Result<()> {
|
||||
let compiler = CraneliftCompiler::new();
|
||||
let wasm_binary = wat2wasm(IMPORT_MODULE.as_bytes()).expect("WAST not valid or malformed");
|
||||
|
||||
let inner_module = wasmer_runtime_core::compile_with(&wasm_binary, &CraneliftCompiler::new())?;
|
||||
@ -61,7 +58,7 @@ fn main() -> error::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn print_num(n: i32, ctx: &mut vm::Ctx) -> Result<i32, ()> {
|
||||
fn print_num(ctx: &mut vm::Ctx, n: i32) -> Result<i32, ()> {
|
||||
println!("print_num({})", n);
|
||||
|
||||
let memory: &Memory = ctx.memory(0);
|
||||
|
18
lib/win-exception-handler/Cargo.toml
Normal file
18
lib/win-exception-handler/Cargo.toml
Normal file
@ -0,0 +1,18 @@
|
||||
[package]
|
||||
name = "wasmer-win-exception-handler"
|
||||
version = "0.0.1"
|
||||
description = "Wasmer runtime exception handling for Windows"
|
||||
license = "MIT"
|
||||
authors = ["The Wasmer Engineering Team <engineering@wasmer.io>"]
|
||||
repository = "https://github.com/wasmerio/wasmer"
|
||||
edition = "2018"
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
wasmer-runtime-core = { path = "../runtime-core", version = "0.1.2" }
|
||||
winapi = { version = "0.3", features = ["winbase", "errhandlingapi", "minwindef", "minwinbase", "winnt"] }
|
||||
libc = "0.2.48"
|
||||
|
||||
[build-dependencies]
|
||||
cmake = "0.1.35"
|
||||
bindgen = "0.46.0"
|
||||
regex = "1.0.6"
|
11
lib/win-exception-handler/build.rs
Normal file
11
lib/win-exception-handler/build.rs
Normal file
@ -0,0 +1,11 @@
|
||||
use cmake::Config;
|
||||
|
||||
fn main() {
|
||||
#[cfg(target_os = "windows")]
|
||||
{
|
||||
let project_name = "exception_handling";
|
||||
let dst = Config::new(project_name).build();
|
||||
println!("cargo:rustc-link-search=native={}", dst.display());
|
||||
println!("cargo:rustc-link-lib=static={}", project_name);
|
||||
}
|
||||
}
|
1
lib/win-exception-handler/exception_handling/.gitignore
vendored
Normal file
1
lib/win-exception-handler/exception_handling/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
cmake-build-*
|
@ -0,0 +1,6 @@
|
||||
cmake_minimum_required(VERSION 3.0)
|
||||
project(exception_handling C)
|
||||
|
||||
add_library(exception_handling STATIC exception_handling.c)
|
||||
|
||||
install(TARGETS exception_handling DESTINATION .)
|
@ -0,0 +1,74 @@
|
||||
#include <windows.h>
|
||||
#include <setjmp.h>
|
||||
#include "exception_handling.h"
|
||||
|
||||
#define CALL_FIRST 1
|
||||
|
||||
__declspec(thread) jmp_buf jmpBuf;
|
||||
__declspec(thread) PVOID caughtExceptionAddress;
|
||||
__declspec(thread) DWORD64 caughtInstructionPointer;
|
||||
__declspec(thread) PVOID savedStackPointer;
|
||||
__declspec(thread) BOOL exceptionHandlerInstalled = FALSE;
|
||||
__declspec(thread) BOOL alreadyHandlingException = FALSE;
|
||||
|
||||
void longjmpOutOfHere() {
|
||||
longjmp(jmpBuf, 1);
|
||||
}
|
||||
|
||||
/// Get the current address that we use to jmp, the no inline is important
|
||||
static __declspec(noinline) void *get_callee_frame_address(void) {
|
||||
return _AddressOfReturnAddress();
|
||||
}
|
||||
|
||||
static LONG WINAPI
|
||||
exceptionHandler(struct _EXCEPTION_POINTERS *ExceptionInfo) {
|
||||
EXCEPTION_RECORD* pExceptionRecord = ExceptionInfo->ExceptionRecord;
|
||||
PCONTEXT pCONTEXT = ExceptionInfo->ContextRecord;
|
||||
caughtExceptionAddress = pExceptionRecord->ExceptionAddress;
|
||||
caughtInstructionPointer = pCONTEXT->Rip;
|
||||
if (alreadyHandlingException == TRUE) {
|
||||
return EXCEPTION_CONTINUE_SEARCH;
|
||||
}
|
||||
alreadyHandlingException = TRUE;
|
||||
|
||||
// Basically, here, we coerce the os to resume us into a context that calls `longjmp` instead of just continuing.
|
||||
// Presumably, we cannot `longjmp` out of the signal/exception context, like we can on unix.
|
||||
pCONTEXT->Rip = (uintptr_t)(&longjmpOutOfHere);
|
||||
pCONTEXT->Rsp = (uintptr_t)(savedStackPointer);
|
||||
return EXCEPTION_CONTINUE_EXECUTION;
|
||||
}
|
||||
|
||||
uint8_t callProtected(trampoline_t trampoline,
|
||||
const struct wasmer_instance_context_t* ctx,
|
||||
const struct func_t* func,
|
||||
const uint64_t* param_vec,
|
||||
uint64_t* return_vec,
|
||||
struct call_protected_result_t* out_result) {
|
||||
|
||||
// install exception handler
|
||||
if (exceptionHandlerInstalled == FALSE) {
|
||||
exceptionHandlerInstalled = TRUE;
|
||||
AddVectoredExceptionHandler(CALL_FIRST, exceptionHandler);
|
||||
}
|
||||
|
||||
// jmp jmp jmp!
|
||||
int signum = setjmp(jmpBuf);
|
||||
if (signum == 0) {
|
||||
// save the stack pointer
|
||||
savedStackPointer = get_callee_frame_address();
|
||||
trampoline(ctx, func, param_vec, return_vec);
|
||||
out_result->code = 0;
|
||||
out_result->exceptionAddress = 0;
|
||||
out_result->instructionPointer = 0;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
out_result->code = (uint64_t)signum;
|
||||
out_result->exceptionAddress = (uint64_t)caughtExceptionAddress;
|
||||
out_result->instructionPointer = caughtInstructionPointer;
|
||||
|
||||
caughtExceptionAddress = 0;
|
||||
caughtInstructionPointer = 0;
|
||||
|
||||
return FALSE;
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
#ifndef WASMER_EXCEPTION_HANDLING_H
|
||||
#define WASMER_EXCEPTION_HANDLING_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
struct func_t;
|
||||
struct wasmer_instance_context_t;
|
||||
|
||||
typedef void(*trampoline_t)(struct wasmer_instance_context_t*, const struct func_t*, const uint64_t*, uint64_t*);
|
||||
|
||||
struct call_protected_result_t {
|
||||
uint64_t code;
|
||||
uint64_t exceptionAddress;
|
||||
uint64_t instructionPointer;
|
||||
};
|
||||
|
||||
uint8_t callProtected(
|
||||
trampoline_t trampoline,
|
||||
const struct wasmer_instance_context_t* ctx,
|
||||
const struct func_t* func,
|
||||
const uint64_t* param_vec,
|
||||
uint64_t* return_vec,
|
||||
struct call_protected_result_t* out_result);
|
||||
|
||||
#endif //WASMER_EXCEPTION_HANDLING_H
|
53
lib/win-exception-handler/src/exception_handling.rs
Normal file
53
lib/win-exception-handler/src/exception_handling.rs
Normal file
@ -0,0 +1,53 @@
|
||||
use std::ffi::c_void;
|
||||
use wasmer_runtime_core::vm::{Ctx, Func};
|
||||
|
||||
type Trampoline = unsafe extern "C" fn(*mut Ctx, *const Func, *const u64, *mut u64) -> c_void;
|
||||
type CallProtectedResult = Result<(), CallProtectedData>;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct CallProtectedData {
|
||||
pub code: u64,
|
||||
pub exceptionAddress: u64,
|
||||
pub instructionPointer: u64,
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
#[link_name = "callProtected"]
|
||||
pub fn __call_protected(
|
||||
trampoline: Trampoline,
|
||||
ctx: *mut Ctx,
|
||||
func: *const Func,
|
||||
param_vec: *const u64,
|
||||
return_vec: *mut u64,
|
||||
out_result: *mut CallProtectedData,
|
||||
) -> u8;
|
||||
}
|
||||
|
||||
pub fn _call_protected(
|
||||
trampoline: Trampoline,
|
||||
ctx: *mut Ctx,
|
||||
func: *const Func,
|
||||
param_vec: *const u64,
|
||||
return_vec: *mut u64,
|
||||
) -> CallProtectedResult {
|
||||
let mut out_result = CallProtectedData {
|
||||
code: 0,
|
||||
exceptionAddress: 0,
|
||||
instructionPointer: 0,
|
||||
};
|
||||
let result = unsafe {
|
||||
__call_protected(
|
||||
trampoline,
|
||||
ctx,
|
||||
func,
|
||||
param_vec,
|
||||
return_vec,
|
||||
&mut out_result,
|
||||
)
|
||||
};
|
||||
if result == 1 {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(out_result)
|
||||
}
|
||||
}
|
5
lib/win-exception-handler/src/lib.rs
Normal file
5
lib/win-exception-handler/src/lib.rs
Normal file
@ -0,0 +1,5 @@
|
||||
#[cfg(windows)]
|
||||
mod exception_handling;
|
||||
|
||||
#[cfg(windows)]
|
||||
pub use self::exception_handling::*;
|
@ -69,7 +69,7 @@ fn execute_wasm(options: &Run) -> Result<(), String> {
|
||||
let module = webassembly::compile(&wasm_binary[..])
|
||||
.map_err(|e| format!("Can't compile module: {:?}", e))?;
|
||||
|
||||
let (_abi, import_object, em_globals) = if wasmer_emscripten::is_emscripten_module(&module) {
|
||||
let (_abi, import_object, _em_globals) = if wasmer_emscripten::is_emscripten_module(&module) {
|
||||
let mut emscripten_globals = wasmer_emscripten::EmscriptenGlobals::new(&module);
|
||||
(
|
||||
InstanceABI::Emscripten,
|
||||
@ -113,6 +113,11 @@ fn main() {
|
||||
let options = CLIOptions::from_args();
|
||||
match options {
|
||||
CLIOptions::Run(options) => run(options),
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
CLIOptions::SelfUpdate => update::self_update(),
|
||||
#[cfg(target_os = "windows")]
|
||||
CLIOptions::SelfUpdate => {
|
||||
println!("Self update is not supported on Windows. Use install instructions on the Wasmer homepage: https://wasmer.io");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user