mirror of
https://github.com/fluencelabs/wasmer
synced 2024-12-12 22:05:33 +00:00
Merge remote-tracking branch 'origin/master' into feature/wasi-readlink
This commit is contained in:
commit
78702fc1a0
@ -111,6 +111,10 @@ jobs:
|
||||
name: Debug flag checked
|
||||
command: |
|
||||
cargo check --features "debug" --release
|
||||
- run:
|
||||
name: Check
|
||||
command: |
|
||||
make check
|
||||
- run:
|
||||
name: Release
|
||||
command: make release-fast
|
||||
@ -163,6 +167,11 @@ jobs:
|
||||
ulimit -n 8000
|
||||
sudo sysctl -w kern.maxfiles=655360 kern.maxfilesperproc=327680
|
||||
make test
|
||||
- run:
|
||||
name: Check
|
||||
command: |
|
||||
export PATH="$HOME/.cargo/bin:$PATH"
|
||||
make check
|
||||
- run:
|
||||
name: Release
|
||||
command: |
|
||||
|
@ -5,6 +5,11 @@ All PRs to the Wasmer repository must add to this file.
|
||||
Blocks of changes will separated by version increments.
|
||||
|
||||
## **[Unreleased]**
|
||||
- [#563](https://github.com/wasmerio/wasmer/pull/563) Improve wasi testing infrastructure
|
||||
- fixes arg parsing from comments & fixes the mapdir test to have the native code doing the same thing as the WASI code
|
||||
- makes wasitests-generate output stdout/stderr by default & adds function to print stdout and stderr for a command if it fails
|
||||
- compiles wasm with size optimizations & strips generated wasm with wasm-strip
|
||||
- [#554](https://github.com/wasmerio/wasmer/pull/554) Finish implementation of `wasi::fd_seek`, fix bug in filestat
|
||||
|
||||
## 0.5.5
|
||||
- [#541](https://github.com/wasmerio/wasmer/pull/541) Fix dependency graph by making separate test crates; ABI implementations should not depend on compilers. Add Cranelift fork as git submodule of clif-backend
|
||||
|
@ -67,7 +67,7 @@ rustc_version = "0.2.3"
|
||||
|
||||
[features]
|
||||
default = ["fast-tests", "wasi"]
|
||||
"loader:kernel" = ["wasmer-kernel-loader"]
|
||||
"loader-kernel" = ["wasmer-kernel-loader"]
|
||||
debug = ["wasmer-runtime-core/debug"]
|
||||
trace = ["wasmer-runtime-core/trace"]
|
||||
extra-debug = ["wasmer-clif-backend/debug", "wasmer-runtime-core/debug"]
|
||||
|
7
Makefile
7
Makefile
@ -8,7 +8,7 @@ generate-emtests:
|
||||
WASM_EMSCRIPTEN_GENERATE_EMTESTS=1 cargo build -p wasmer-emscripten-tests --release
|
||||
|
||||
generate-wasitests:
|
||||
WASM_WASI_GENERATE_WASITESTS=1 cargo build -p wasmer-wasi-tests --release
|
||||
WASM_WASI_GENERATE_WASITESTS=1 cargo build -p wasmer-wasi-tests --release -vv
|
||||
|
||||
generate: generate-spectests generate-emtests generate-wasitests
|
||||
|
||||
@ -117,8 +117,11 @@ debug:
|
||||
install:
|
||||
cargo install --path .
|
||||
|
||||
check:
|
||||
cargo check --release --features backend-singlepass,backend-llvm,loader-kernel
|
||||
|
||||
release:
|
||||
cargo build --release --features backend-singlepass,backend-llvm,loader:kernel
|
||||
cargo build --release --features backend-singlepass,backend-llvm,loader-kernel
|
||||
|
||||
# Only one backend (cranelift)
|
||||
release-fast:
|
||||
|
4
fuzz/.gitignore
vendored
Normal file
4
fuzz/.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
|
||||
target
|
||||
corpus
|
||||
artifacts
|
21
fuzz/Cargo.toml
Normal file
21
fuzz/Cargo.toml
Normal file
@ -0,0 +1,21 @@
|
||||
|
||||
[package]
|
||||
name = "wasmer-fuzz"
|
||||
version = "0.0.1"
|
||||
authors = ["Automatically generated"]
|
||||
publish = false
|
||||
|
||||
[package.metadata]
|
||||
cargo-fuzz = true
|
||||
|
||||
[dependencies]
|
||||
wasmer-runtime = { path = "../lib/runtime" }
|
||||
libfuzzer-sys = { git = "https://github.com/rust-fuzz/libfuzzer-sys.git" }
|
||||
|
||||
# Prevent this from interfering with workspaces
|
||||
[workspace]
|
||||
members = ["."]
|
||||
|
||||
[[bin]]
|
||||
name = "simple_instantiate"
|
||||
path = "fuzz_targets/simple_instantiate.rs"
|
38
fuzz/README.md
Normal file
38
fuzz/README.md
Normal file
@ -0,0 +1,38 @@
|
||||
This directory contains the fuzz tests for wasmer. To fuzz, we use the `cargo-fuzz` package.
|
||||
|
||||
## Installation
|
||||
|
||||
You may need to install the `cargo-fuzz` package to get the `cargo fuzz` subcommand. Use
|
||||
|
||||
```sh
|
||||
$ cargo install cargo-fuzz
|
||||
```
|
||||
|
||||
`cargo-fuzz` is documented in the [Rust Fuzz Book](https://rust-fuzz.github.io/book/cargo-fuzz.html).
|
||||
|
||||
## Running a fuzzer
|
||||
|
||||
Once `cargo-fuzz` is installed, you can run the `simple_instantiate` fuzzer with
|
||||
```sh
|
||||
cargo fuzz run simple_instantiate
|
||||
```
|
||||
|
||||
You should see output that looks something like this:
|
||||
|
||||
```
|
||||
INFO: Seed: 3276026494
|
||||
INFO: 8 files found in wasmer/fuzz/corpus/simple_instantiate
|
||||
INFO: -max_len is not provided; libFuzzer will not generate inputs larger than 4096 bytes
|
||||
INFO: seed corpus: files: 8 min: 1b max: 1b total: 8b rss: 133Mb
|
||||
#9 INITED ft: 3 corp: 3/3b lim: 4 exec/s: 0 rss: 142Mb
|
||||
#23 NEW ft: 4 corp: 4/5b lim: 4 exec/s: 0 rss: 142Mb L: 2/2 MS: 4 ChangeByte-InsertByte-ShuffleBytes-ChangeBit-
|
||||
#25 NEW ft: 5 corp: 5/6b lim: 4 exec/s: 0 rss: 142Mb L: 1/2 MS: 2 ChangeBinInt-ChangeBit-
|
||||
#27 NEW ft: 6 corp: 6/9b lim: 4 exec/s: 0 rss: 142Mb L: 3/3 MS: 2 InsertByte-ChangeByte-
|
||||
#190 REDUCE ft: 6 corp: 6/7b lim: 4 exec/s: 0 rss: 142Mb L: 1/2 MS: 3 ChangeBit-EraseBytes-CrossOver-
|
||||
#205 REDUCE ft: 7 corp: 7/11b lim: 4 exec/s: 0 rss: 142Mb L: 4/4 MS: 5 ShuffleBytes-CrossOver-InsertByte-ChangeBinInt-CrossOver-
|
||||
```
|
||||
It will continue to generate random inputs forever, until it finds a bug or is terminated. The testcases for bugs it finds go into `fuzz/artifacts/simple_instantiate` and you can rerun the fuzzer on a single input by passing it on the command line `cargo fuzz run simple_instantiate my_testcase.wasm`.
|
||||
|
||||
## Trophy case
|
||||
|
||||
- [x] https://github.com/wasmerio/wasmer/issues/558
|
13
fuzz/fuzz_targets/simple_instantiate.rs
Normal file
13
fuzz/fuzz_targets/simple_instantiate.rs
Normal file
@ -0,0 +1,13 @@
|
||||
#![no_main]
|
||||
#[macro_use] extern crate libfuzzer_sys;
|
||||
extern crate wasmer_runtime;
|
||||
|
||||
use wasmer_runtime::{
|
||||
instantiate,
|
||||
imports,
|
||||
};
|
||||
|
||||
fuzz_target!(|data: &[u8]| {
|
||||
let import_object = imports! {};
|
||||
instantiate(data, &import_object);
|
||||
});
|
@ -117,6 +117,7 @@ pub struct CompilerConfig {
|
||||
pub symbol_map: Option<HashMap<u32, String>>,
|
||||
pub memory_bound_check_mode: MemoryBoundCheckMode,
|
||||
pub enforce_stack_check: bool,
|
||||
pub track_state: bool,
|
||||
}
|
||||
|
||||
pub trait Compiler {
|
||||
|
@ -111,7 +111,13 @@ impl ModuleStateMap {
|
||||
.unwrap();
|
||||
|
||||
match fsm.call_offsets.get(&(ip - base)) {
|
||||
Some(x) => Some((fsm, fsm.diffs[x.diff_id].build_state(fsm))),
|
||||
Some(x) => {
|
||||
if x.diff_id < fsm.diffs.len() {
|
||||
Some((fsm, fsm.diffs[x.diff_id].build_state(fsm)))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
@ -132,7 +138,13 @@ impl ModuleStateMap {
|
||||
.unwrap();
|
||||
|
||||
match fsm.trappable_offsets.get(&(ip - base)) {
|
||||
Some(x) => Some((fsm, fsm.diffs[x.diff_id].build_state(fsm))),
|
||||
Some(x) => {
|
||||
if x.diff_id < fsm.diffs.len() {
|
||||
Some((fsm, fsm.diffs[x.diff_id].build_state(fsm)))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
@ -149,7 +161,13 @@ impl ModuleStateMap {
|
||||
.unwrap();
|
||||
|
||||
match fsm.loop_offsets.get(&(ip - base)) {
|
||||
Some(x) => Some((fsm, fsm.diffs[x.diff_id].build_state(fsm))),
|
||||
Some(x) => {
|
||||
if x.diff_id < fsm.diffs.len() {
|
||||
Some((fsm, fsm.diffs[x.diff_id].build_state(fsm)))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
|
@ -74,7 +74,7 @@ pub struct InternalCtx {
|
||||
/// A pointer to an array of locally-defined globals, indexed by `GlobalIndex`.
|
||||
pub globals: *mut *mut LocalGlobal,
|
||||
|
||||
/// A pointer to an array of imported memories, indexed by `MemoryIndex,
|
||||
/// A pointer to an array of imported memories, indexed by `MemoryIndex`,
|
||||
pub imported_memories: *mut *mut LocalMemory,
|
||||
|
||||
/// A pointer to an array of imported tables, indexed by `TableIndex`.
|
||||
|
@ -317,6 +317,7 @@ pub struct CodegenError {
|
||||
struct CodegenConfig {
|
||||
memory_bound_check_mode: MemoryBoundCheckMode,
|
||||
enforce_stack_check: bool,
|
||||
track_state: bool,
|
||||
}
|
||||
|
||||
impl ModuleCodeGenerator<X64FunctionCode, X64ExecutionContext, CodegenError>
|
||||
@ -366,7 +367,8 @@ impl ModuleCodeGenerator<X64FunctionCode, X64ExecutionContext, CodegenError>
|
||||
|
||||
begin_label_info.1 = Some(begin_offset);
|
||||
let begin_label = begin_label_info.0;
|
||||
let machine = Machine::new();
|
||||
let mut machine = Machine::new();
|
||||
machine.track_state = self.config.as_ref().unwrap().track_state;
|
||||
|
||||
dynasm!(
|
||||
assembler
|
||||
@ -532,6 +534,7 @@ impl ModuleCodeGenerator<X64FunctionCode, X64ExecutionContext, CodegenError>
|
||||
self.config = Some(Arc::new(CodegenConfig {
|
||||
memory_bound_check_mode: config.memory_bound_check_mode,
|
||||
enforce_stack_check: config.enforce_stack_check,
|
||||
track_state: config.track_state,
|
||||
}));
|
||||
Ok(())
|
||||
}
|
||||
@ -1594,6 +1597,9 @@ impl X64FunctionCode {
|
||||
fsm: &mut FunctionStateMap,
|
||||
control_stack: &mut [ControlFrame],
|
||||
) -> usize {
|
||||
if !m.track_state {
|
||||
return ::std::usize::MAX;
|
||||
}
|
||||
let last_frame = control_stack.last_mut().unwrap();
|
||||
let mut diff = m.state.diff(&last_frame.state);
|
||||
diff.last = Some(last_frame.state_diff_id);
|
||||
@ -1769,7 +1775,7 @@ impl FunctionCodeGenerator<CodegenError> for X64FunctionCode {
|
||||
.unwrap()
|
||||
.insert(a.get_offset(), callback);
|
||||
}
|
||||
InternalEvent::FunctionBegin(_) | InternalEvent::FunctionEnd => {},
|
||||
InternalEvent::FunctionBegin(_) | InternalEvent::FunctionEnd => {}
|
||||
InternalEvent::GetInternal(idx) => {
|
||||
let idx = idx as usize;
|
||||
assert!(idx < INTERNALS_SIZE);
|
||||
@ -1820,7 +1826,11 @@ impl FunctionCodeGenerator<CodegenError> for X64FunctionCode {
|
||||
),
|
||||
Location::GPR(tmp),
|
||||
);
|
||||
let loc = get_location_released(a, &mut self.machine, self.value_stack.pop().unwrap());
|
||||
let loc = get_location_released(
|
||||
a,
|
||||
&mut self.machine,
|
||||
self.value_stack.pop().unwrap(),
|
||||
);
|
||||
|
||||
// Move internal into storage.
|
||||
Self::emit_relaxed_binop(
|
||||
@ -1832,8 +1842,7 @@ impl FunctionCodeGenerator<CodegenError> for X64FunctionCode {
|
||||
Location::Memory(tmp, (idx * 8) as i32),
|
||||
);
|
||||
self.machine.release_temp_gpr(tmp);
|
||||
}
|
||||
//_ => unimplemented!(),
|
||||
} //_ => unimplemented!(),
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
@ -2411,7 +2420,14 @@ impl FunctionCodeGenerator<CodegenError> for X64FunctionCode {
|
||||
loc_b,
|
||||
);
|
||||
a.emit_jmp(Condition::NotEqual, normal_path);
|
||||
a.emit_mov(Size::S64, Location::Imm64(0), ret);
|
||||
Self::emit_relaxed_binop(
|
||||
a,
|
||||
&mut self.machine,
|
||||
Assembler::emit_mov,
|
||||
Size::S64,
|
||||
Location::Imm64(0),
|
||||
ret,
|
||||
);
|
||||
a.emit_jmp(Condition::None, end);
|
||||
|
||||
a.emit_label(normal_path);
|
||||
@ -4525,9 +4541,14 @@ impl FunctionCodeGenerator<CodegenError> for X64FunctionCode {
|
||||
|a, m, addr| {
|
||||
match ret {
|
||||
Location::GPR(_) => {}
|
||||
_ => {
|
||||
a.emit_mov(Size::S64, Location::Imm64(0), ret);
|
||||
Location::Memory(base, offset) => {
|
||||
a.emit_mov(
|
||||
Size::S32,
|
||||
Location::Imm32(0),
|
||||
Location::Memory(base, offset + 4),
|
||||
); // clear upper bits
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
Self::emit_relaxed_binop(
|
||||
a,
|
||||
|
@ -13,6 +13,7 @@ pub struct Machine {
|
||||
stack_offset: MachineStackOffset,
|
||||
save_area_offset: Option<MachineStackOffset>,
|
||||
pub state: MachineState,
|
||||
pub(crate) track_state: bool,
|
||||
}
|
||||
|
||||
impl Machine {
|
||||
@ -23,6 +24,7 @@ impl Machine {
|
||||
stack_offset: MachineStackOffset(0),
|
||||
save_area_offset: None,
|
||||
state: x64::new_machine_state(),
|
||||
track_state: true,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -20,7 +20,6 @@ static BANNER: &str = "// !!! THIS IS A GENERATED FILE !!!
|
||||
// Files autogenerated with cargo build (build/wasitests.rs).\n";
|
||||
|
||||
pub fn compile(file: &str, ignores: &HashSet<String>) -> Option<String> {
|
||||
dbg!(file);
|
||||
let mut output_path = PathBuf::from(file);
|
||||
output_path.set_extension("out");
|
||||
|
||||
@ -31,13 +30,14 @@ pub fn compile(file: &str, ignores: &HashSet<String>) -> Option<String> {
|
||||
nn
|
||||
};
|
||||
|
||||
Command::new("rustc")
|
||||
.arg("+nightly")
|
||||
println!("Compiling program {} to native", file);
|
||||
let native_out = Command::new("rustc")
|
||||
.arg(file)
|
||||
.arg("-o")
|
||||
.arg(&normalized_name)
|
||||
.output()
|
||||
.expect("Failed to compile program to native code");
|
||||
print_info_on_error(&native_out, "COMPILATION FAILED");
|
||||
|
||||
#[cfg(unix)]
|
||||
{
|
||||
@ -58,18 +58,29 @@ pub fn compile(file: &str, ignores: &HashSet<String>) -> Option<String> {
|
||||
let result = Command::new(&normalized_name)
|
||||
.output()
|
||||
.expect("Failed to execute native program");
|
||||
print_info_on_error(&result, "NATIVE PROGRAM FAILED");
|
||||
|
||||
std::fs::remove_file(&normalized_name).expect("could not delete executable");
|
||||
let wasm_out_name = format!("{}.wasm", &normalized_name);
|
||||
|
||||
Command::new("rustc")
|
||||
let wasm_compilation_out = Command::new("rustc")
|
||||
.arg("+nightly")
|
||||
.arg("--target=wasm32-wasi")
|
||||
.arg("-C")
|
||||
.arg("opt-level=s")
|
||||
.arg(file)
|
||||
.arg("-o")
|
||||
.arg(&wasm_out_name)
|
||||
.output()
|
||||
.expect("Failed to compile program to native code");
|
||||
print_info_on_error(&wasm_compilation_out, "WASM COMPILATION");
|
||||
|
||||
// to prevent commiting huge binary blobs forever
|
||||
let wasm_strip_out = Command::new("wasm-strip")
|
||||
.arg(&wasm_out_name)
|
||||
.output()
|
||||
.expect("Failed to strip compiled wasm module");
|
||||
print_info_on_error(&wasm_strip_out, "STRIPPING WASM");
|
||||
|
||||
let ignored = if ignores.contains(&rs_module_name) {
|
||||
"\n#[ignore]"
|
||||
@ -85,7 +96,7 @@ pub fn compile(file: &str, ignores: &HashSet<String>) -> Option<String> {
|
||||
out_str.push_str("vec![");
|
||||
for (alias, real_dir) in args.mapdir {
|
||||
out_str.push_str(&format!(
|
||||
"(\"{}\".to_string(), \"{}\".to_string()),",
|
||||
"(\"{}\".to_string(), ::std::path::PathBuf::from(\"{}\")),",
|
||||
alias, real_dir
|
||||
));
|
||||
}
|
||||
@ -194,25 +205,36 @@ fn extract_args_from_source_file(source_code: &str) -> Option<Args> {
|
||||
{
|
||||
let tokenized = arg_line
|
||||
.split_whitespace()
|
||||
// skip trailing space
|
||||
.skip(1)
|
||||
.map(String::from)
|
||||
.collect::<Vec<String>>();
|
||||
match tokenized[1].as_ref() {
|
||||
let command_name = {
|
||||
let mut cn = tokenized[0].clone();
|
||||
assert_eq!(
|
||||
cn.pop(),
|
||||
Some(':'),
|
||||
"Final character of argname must be a colon"
|
||||
);
|
||||
cn
|
||||
};
|
||||
|
||||
match command_name.as_ref() {
|
||||
"mapdir" => {
|
||||
if let [alias, real_dir] = &tokenized[2].split(':').collect::<Vec<&str>>()[..] {
|
||||
if let [alias, real_dir] = &tokenized[1].split(':').collect::<Vec<&str>>()[..] {
|
||||
args.mapdir.push((alias.to_string(), real_dir.to_string()));
|
||||
} else {
|
||||
eprintln!(
|
||||
"Parse error in mapdir {} not parsed correctly",
|
||||
&tokenized[2]
|
||||
&tokenized[1]
|
||||
);
|
||||
}
|
||||
}
|
||||
"env" => {
|
||||
if let [name, val] = &tokenized[2].split('=').collect::<Vec<&str>>()[..] {
|
||||
if let [name, val] = &tokenized[1].split('=').collect::<Vec<&str>>()[..] {
|
||||
args.envvars.push((name.to_string(), val.to_string()));
|
||||
} else {
|
||||
eprintln!("Parse error in env {} not parsed correctly", &tokenized[2]);
|
||||
eprintln!("Parse error in env {} not parsed correctly", &tokenized[1]);
|
||||
}
|
||||
}
|
||||
e => {
|
||||
@ -224,3 +246,17 @@ fn extract_args_from_source_file(source_code: &str) -> Option<Args> {
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn print_info_on_error(output: &std::process::Output, context: &str) {
|
||||
if !output.status.success() {
|
||||
println!("{}", context);
|
||||
println!(
|
||||
"stdout:\n{}",
|
||||
std::str::from_utf8(&output.stdout[..]).unwrap()
|
||||
);
|
||||
eprintln!(
|
||||
"stderr:\n{}",
|
||||
std::str::from_utf8(&output.stderr[..]).unwrap()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
5
lib/wasi-tests/tests/README.md
Normal file
5
lib/wasi-tests/tests/README.md
Normal file
@ -0,0 +1,5 @@
|
||||
Most of the files here are generated.
|
||||
|
||||
`_common.rs` is a file containing a macro that the generated tests use to avoid code duplication.
|
||||
|
||||
If you want to add new features, edit `_common.rs` and `wasi-tests/build/wasitests.rs` to use the changed macro.
|
13
lib/wasi-tests/tests/wasitests/fseek.rs
Normal file
13
lib/wasi-tests/tests/wasitests/fseek.rs
Normal file
@ -0,0 +1,13 @@
|
||||
#[test]
|
||||
fn test_fseek() {
|
||||
assert_wasi_output!(
|
||||
"../../wasitests/fseek.wasm",
|
||||
"fseek",
|
||||
vec![(
|
||||
".".to_string(),
|
||||
::std::path::PathBuf::from("wasitests/test_fs/hamlet")
|
||||
),],
|
||||
vec![],
|
||||
"../../wasitests/fseek.out"
|
||||
);
|
||||
}
|
@ -9,6 +9,7 @@ mod create_dir;
|
||||
mod envvar;
|
||||
mod file_metadata;
|
||||
mod fs_sandbox_test;
|
||||
mod fseek;
|
||||
mod hello;
|
||||
mod mapdir;
|
||||
mod quine;
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
11
lib/wasi-tests/wasitests/fseek.out
Normal file
11
lib/wasi-tests/wasitests/fseek.out
Normal file
@ -0,0 +1,11 @@
|
||||
SCENE III. A room in Polonius' h
|
||||
ouse.
|
||||
|
||||
Enter LAERTES and OPH
|
||||
And, sister, as the winds gi
|
||||
r talk with the Lord Hamlet.
|
||||
|
||||
uits,
|
||||
Breathing like sanctif
|
||||
is is for all:
|
||||
I would not,
|
47
lib/wasi-tests/wasitests/fseek.rs
Normal file
47
lib/wasi-tests/wasitests/fseek.rs
Normal file
@ -0,0 +1,47 @@
|
||||
// Args:
|
||||
// mapdir: .:wasitests/test_fs/hamlet
|
||||
|
||||
use std::fs;
|
||||
use std::io::{Read, Seek, SeekFrom};
|
||||
use std::path::PathBuf;
|
||||
|
||||
fn main() {
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
let mut base = PathBuf::from("wasitests/test_fs/hamlet");
|
||||
#[cfg(target_os = "wasi")]
|
||||
let mut base = PathBuf::from(".");
|
||||
|
||||
base.push("act1/scene3.txt");
|
||||
|
||||
let mut file = fs::File::open(&base).expect("Could not open file");
|
||||
|
||||
let mut buffer = [0u8; 32];
|
||||
|
||||
assert_eq!(file.read(&mut buffer).unwrap(), 32);
|
||||
let str_val = std::str::from_utf8(&buffer[..]).unwrap();
|
||||
println!("{}", str_val);
|
||||
|
||||
assert_eq!(file.read(&mut buffer).unwrap(), 32);
|
||||
let str_val = std::str::from_utf8(&buffer[..]).unwrap();
|
||||
println!("{}", str_val);
|
||||
|
||||
assert_eq!(file.seek(SeekFrom::Start(123)).unwrap(), 123);
|
||||
assert_eq!(file.read(&mut buffer).unwrap(), 32);
|
||||
let str_val = std::str::from_utf8(&buffer[..]).unwrap();
|
||||
println!("{}", str_val);
|
||||
|
||||
assert_eq!(file.seek(SeekFrom::End(-123)).unwrap(), 6617);
|
||||
assert_eq!(file.read(&mut buffer).unwrap(), 32);
|
||||
let str_val = std::str::from_utf8(&buffer[..]).unwrap();
|
||||
println!("{}", str_val);
|
||||
|
||||
assert_eq!(file.seek(SeekFrom::Current(-250)).unwrap(), 6399);
|
||||
assert_eq!(file.read(&mut buffer).unwrap(), 32);
|
||||
let str_val = std::str::from_utf8(&buffer[..]).unwrap();
|
||||
println!("{}", str_val);
|
||||
|
||||
assert_eq!(file.seek(SeekFrom::Current(50)).unwrap(), 6481);
|
||||
assert_eq!(file.read(&mut buffer).unwrap(), 32);
|
||||
let str_val = std::str::from_utf8(&buffer[..]).unwrap();
|
||||
println!("{}", str_val);
|
||||
}
|
BIN
lib/wasi-tests/wasitests/fseek.wasm
Executable file
BIN
lib/wasi-tests/wasitests/fseek.wasm
Executable file
Binary file not shown.
Binary file not shown.
@ -4,9 +4,11 @@
|
||||
use std::fs;
|
||||
|
||||
fn main() {
|
||||
#[cfg(not(target = "wasi"))]
|
||||
let read_dir = fs::read_dir("wasitests/test_fs/hamlet").unwrap();
|
||||
#[cfg(target = "wasi")]
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
let cur_dir = std::env::current_dir().unwrap();
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
std::env::set_current_dir("wasitests/test_fs/hamlet").unwrap();
|
||||
|
||||
let read_dir = fs::read_dir(".").unwrap();
|
||||
let mut out = vec![];
|
||||
for entry in read_dir {
|
||||
@ -17,4 +19,7 @@ fn main() {
|
||||
for p in out {
|
||||
println!("{}", p);
|
||||
}
|
||||
// return to the current directory
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
std::env::set_current_dir(cur_dir).unwrap();
|
||||
}
|
||||
|
Binary file not shown.
Binary file not shown.
@ -911,7 +911,28 @@ pub fn fd_seek(
|
||||
// TODO: handle case if fd is a dir?
|
||||
match whence {
|
||||
__WASI_WHENCE_CUR => fd_entry.offset = (fd_entry.offset as i64 + offset) as u64,
|
||||
__WASI_WHENCE_END => unimplemented!("__WASI__WHENCE_END in wasi::fd_seek"),
|
||||
__WASI_WHENCE_END => {
|
||||
use std::io::SeekFrom;
|
||||
match state.fs.inodes[fd_entry.inode].kind {
|
||||
Kind::File { ref mut handle } => {
|
||||
let end = wasi_try!(handle.seek(SeekFrom::End(0)).ok().ok_or(__WASI_EIO));
|
||||
// TODO: handle case if fd_entry.offset uses 64 bits of a u64
|
||||
fd_entry.offset = (end as i64 + offset) as u64;
|
||||
}
|
||||
Kind::Symlink { .. } => {
|
||||
unimplemented!("wasi::fd_seek not implemented for symlinks")
|
||||
}
|
||||
Kind::Dir { .. } => {
|
||||
// TODO: check this
|
||||
return __WASI_EINVAL;
|
||||
}
|
||||
Kind::Buffer { .. } => {
|
||||
// seeking buffers probably makes sense
|
||||
// TODO: implement this
|
||||
return __WASI_EINVAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
__WASI_WHENCE_SET => fd_entry.offset = offset as u64,
|
||||
_ => return __WASI_EINVAL,
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
ignore = [
|
||||
"src/spectests",
|
||||
"src/emtests",
|
||||
"src/emscripten-tests",
|
||||
"src/wasi-tests",
|
||||
]
|
||||
|
@ -5,10 +5,10 @@ extern crate structopt;
|
||||
|
||||
use structopt::StructOpt;
|
||||
|
||||
#[cfg(feature = "loader:kernel")]
|
||||
#[cfg(feature = "loader-kernel")]
|
||||
use wasmer_singlepass_backend::SinglePassCompiler;
|
||||
|
||||
#[cfg(feature = "loader:kernel")]
|
||||
#[cfg(feature = "loader-kernel")]
|
||||
use std::os::unix::net::{UnixListener, UnixStream};
|
||||
|
||||
#[derive(Debug, StructOpt)]
|
||||
@ -24,14 +24,14 @@ struct Listen {
|
||||
socket: String,
|
||||
}
|
||||
|
||||
#[cfg(feature = "loader:kernel")]
|
||||
#[cfg(feature = "loader-kernel")]
|
||||
const CMD_RUN_CODE: u32 = 0x901;
|
||||
#[cfg(feature = "loader:kernel")]
|
||||
#[cfg(feature = "loader-kernel")]
|
||||
const CMD_READ_MEMORY: u32 = 0x902;
|
||||
#[cfg(feature = "loader:kernel")]
|
||||
#[cfg(feature = "loader-kernel")]
|
||||
const CMD_WRITE_MEMORY: u32 = 0x903;
|
||||
|
||||
#[cfg(feature = "loader:kernel")]
|
||||
#[cfg(feature = "loader-kernel")]
|
||||
fn handle_client(mut stream: UnixStream) {
|
||||
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
|
||||
use std::io::{Read, Write};
|
||||
@ -54,6 +54,7 @@ fn handle_client(mut stream: UnixStream) {
|
||||
symbol_map: None,
|
||||
memory_bound_check_mode: MemoryBoundCheckMode::Disable,
|
||||
enforce_stack_check: true,
|
||||
track_state: false,
|
||||
},
|
||||
&SinglePassCompiler::new(),
|
||||
)
|
||||
@ -131,7 +132,7 @@ fn handle_client(mut stream: UnixStream) {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "loader:kernel")]
|
||||
#[cfg(feature = "loader-kernel")]
|
||||
fn run_listen(opts: Listen) {
|
||||
let listener = UnixListener::bind(&opts.socket).unwrap();
|
||||
use std::thread;
|
||||
@ -154,7 +155,7 @@ fn run_listen(opts: Listen) {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "loader:kernel")]
|
||||
#[cfg(feature = "loader-kernel")]
|
||||
fn main() {
|
||||
let options = CLIOptions::from_args();
|
||||
match options {
|
||||
@ -164,7 +165,7 @@ fn main() {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "loader:kernel"))]
|
||||
#[cfg(not(feature = "loader-kernel"))]
|
||||
fn main() {
|
||||
panic!("Kwasm loader is not enabled during compilation.");
|
||||
}
|
||||
|
@ -112,10 +112,16 @@ struct Run {
|
||||
)]
|
||||
loader: Option<LoaderName>,
|
||||
|
||||
/// Path to previously saved instance image to resume.
|
||||
#[cfg(feature = "backend-singlepass")]
|
||||
#[structopt(long = "resume")]
|
||||
resume: Option<String>,
|
||||
|
||||
/// Whether or not state tracking should be disabled during compilation.
|
||||
/// State tracking is necessary for tier switching and backtracing.
|
||||
#[structopt(long = "no-track-state")]
|
||||
no_track_state: bool,
|
||||
|
||||
/// The command name is a string that will override the first argument passed
|
||||
/// to the wasm program. This is used in wapm to provide nicer output in
|
||||
/// help commands and error messages of the running wasm program
|
||||
@ -137,7 +143,7 @@ struct Run {
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
enum LoaderName {
|
||||
Local,
|
||||
#[cfg(feature = "loader:kernel")]
|
||||
#[cfg(feature = "loader-kernel")]
|
||||
Kernel,
|
||||
}
|
||||
|
||||
@ -145,7 +151,7 @@ impl LoaderName {
|
||||
pub fn variants() -> &'static [&'static str] {
|
||||
&[
|
||||
"local",
|
||||
#[cfg(feature = "loader:kernel")]
|
||||
#[cfg(feature = "loader-kernel")]
|
||||
"kernel",
|
||||
]
|
||||
}
|
||||
@ -156,7 +162,7 @@ impl FromStr for LoaderName {
|
||||
fn from_str(s: &str) -> Result<LoaderName, String> {
|
||||
match s.to_lowercase().as_str() {
|
||||
"local" => Ok(LoaderName::Local),
|
||||
#[cfg(feature = "loader:kernel")]
|
||||
#[cfg(feature = "loader-kernel")]
|
||||
"kernel" => Ok(LoaderName::Kernel),
|
||||
_ => Err(format!("The loader {} doesn't exist", s)),
|
||||
}
|
||||
@ -326,14 +332,16 @@ fn execute_wasm(options: &Run) -> Result<(), String> {
|
||||
Backend::LLVM => return Err("the llvm backend is not enabled".to_string()),
|
||||
};
|
||||
|
||||
#[cfg(feature = "loader:kernel")]
|
||||
let track_state = !options.no_track_state;
|
||||
|
||||
#[cfg(feature = "loader-kernel")]
|
||||
let is_kernel_loader = if let Some(LoaderName::Kernel) = options.loader {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
};
|
||||
|
||||
#[cfg(not(feature = "loader:kernel"))]
|
||||
#[cfg(not(feature = "loader-kernel"))]
|
||||
let is_kernel_loader = false;
|
||||
|
||||
let module = if is_kernel_loader {
|
||||
@ -343,6 +351,7 @@ fn execute_wasm(options: &Run) -> Result<(), String> {
|
||||
symbol_map: em_symbol_map,
|
||||
memory_bound_check_mode: MemoryBoundCheckMode::Disable,
|
||||
enforce_stack_check: true,
|
||||
track_state,
|
||||
},
|
||||
&*compiler,
|
||||
)
|
||||
@ -352,6 +361,7 @@ fn execute_wasm(options: &Run) -> Result<(), String> {
|
||||
&wasm_binary[..],
|
||||
CompilerConfig {
|
||||
symbol_map: em_symbol_map,
|
||||
track_state,
|
||||
..Default::default()
|
||||
},
|
||||
&*compiler,
|
||||
@ -397,6 +407,7 @@ fn execute_wasm(options: &Run) -> Result<(), String> {
|
||||
&wasm_binary[..],
|
||||
CompilerConfig {
|
||||
symbol_map: em_symbol_map,
|
||||
track_state,
|
||||
..Default::default()
|
||||
},
|
||||
&*compiler,
|
||||
@ -440,7 +451,7 @@ fn execute_wasm(options: &Run) -> Result<(), String> {
|
||||
.load(LocalLoader)
|
||||
.expect("Can't use the local loader"),
|
||||
),
|
||||
#[cfg(feature = "loader:kernel")]
|
||||
#[cfg(feature = "loader-kernel")]
|
||||
LoaderName::Kernel => Box::new(
|
||||
instance
|
||||
.load(::wasmer_kernel_loader::KernelLoader)
|
||||
|
Loading…
Reference in New Issue
Block a user