From b34505cf3647dc0900a23c661bb30f12d767d5a4 Mon Sep 17 00:00:00 2001 From: fgh1999 Date: Thu, 13 Jun 2024 17:57:02 +0800 Subject: [PATCH 1/2] Add an example wrapper based on rust std --- .gitignore | 1 + .../wasi-wrapper/wasi-wrapper-rust/.gitignore | 3 + .../wasi-wrapper/wasi-wrapper-rust/Cargo.lock | 16 +++++ .../wasi-wrapper/wasi-wrapper-rust/Cargo.toml | 8 +++ .../wasi-wrapper/wasi-wrapper-rust/README.md | 16 +++++ .../wasi-wrapper/wasi-wrapper-rust/build.rs | 41 ++++++++++++ .../wasi-wrapper-rust/src/main.rs | 13 ++++ .../wasi-wrapper-rust/src/memory.rs | 56 +++++++++++++++++ .../wasi-wrapper-rust/src/wasi.rs | 62 +++++++++++++++++++ 9 files changed, 216 insertions(+) create mode 100644 examples/wasi-wrapper/wasi-wrapper-rust/.gitignore create mode 100644 examples/wasi-wrapper/wasi-wrapper-rust/Cargo.lock create mode 100644 examples/wasi-wrapper/wasi-wrapper-rust/Cargo.toml create mode 100644 examples/wasi-wrapper/wasi-wrapper-rust/README.md create mode 100644 examples/wasi-wrapper/wasi-wrapper-rust/build.rs create mode 100644 examples/wasi-wrapper/wasi-wrapper-rust/src/main.rs create mode 100644 examples/wasi-wrapper/wasi-wrapper-rust/src/memory.rs create mode 100644 examples/wasi-wrapper/wasi-wrapper-rust/src/wasi.rs diff --git a/.gitignore b/.gitignore index 66149fc..cd6ff33 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ *.o *.wasm *.ll +*.a misc misc/* misc/* diff --git a/examples/wasi-wrapper/wasi-wrapper-rust/.gitignore b/examples/wasi-wrapper/wasi-wrapper-rust/.gitignore new file mode 100644 index 0000000..6b004ae --- /dev/null +++ b/examples/wasi-wrapper/wasi-wrapper-rust/.gitignore @@ -0,0 +1,3 @@ +/target +*.a +.vscode diff --git a/examples/wasi-wrapper/wasi-wrapper-rust/Cargo.lock b/examples/wasi-wrapper/wasi-wrapper-rust/Cargo.lock new file mode 100644 index 0000000..b49f6b6 --- /dev/null +++ b/examples/wasi-wrapper/wasi-wrapper-rust/Cargo.lock @@ -0,0 +1,16 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasi-wrapper" +version = "0.1.0" +dependencies = [ + "wasi", +] diff --git a/examples/wasi-wrapper/wasi-wrapper-rust/Cargo.toml b/examples/wasi-wrapper/wasi-wrapper-rust/Cargo.toml new file mode 100644 index 0000000..c8ffe31 --- /dev/null +++ b/examples/wasi-wrapper/wasi-wrapper-rust/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "wasi-wrapper" +version = "0.1.0" +edition = "2021" +build = "build.rs" + +[dependencies] +wasi = "0.11.0+wasi-snapshot-preview1" diff --git a/examples/wasi-wrapper/wasi-wrapper-rust/README.md b/examples/wasi-wrapper/wasi-wrapper-rust/README.md new file mode 100644 index 0000000..4f285a7 --- /dev/null +++ b/examples/wasi-wrapper/wasi-wrapper-rust/README.md @@ -0,0 +1,16 @@ +# An Example of Running Wasker Output Based on Rust Std + +Similar to the [Linux WASI wrapper](../wasi-wrapper-linux.c), +4 mock WASI interfaces are implemented in order to support [the rust example](../../rust/README.md). + +## Prerequisite + +Have Wasker installed. + +## Run the example + +Just run. Check build options in [`build.rs`](./build.rs). + +```shell +cargo run +``` diff --git a/examples/wasi-wrapper/wasi-wrapper-rust/build.rs b/examples/wasi-wrapper/wasi-wrapper-rust/build.rs new file mode 100644 index 0000000..d3aa871 --- /dev/null +++ b/examples/wasi-wrapper/wasi-wrapper-rust/build.rs @@ -0,0 +1,41 @@ +use std::{path::Path, process::Command}; + +fn path_to_str(path: &Path) -> &str { + path.as_os_str().to_str().unwrap() +} + +fn main() { + let target_name = "wasm"; + let target_obj_name = format!("{}.o", target_name); + let wasm_path = Path::new("../../rust"); + let target_path = wasm_path.join(&target_obj_name); + println!("cargo:rerun-if-changed={}", path_to_str(&target_path)); + + std::env::set_current_dir(wasm_path).unwrap(); + Command::new("cargo") + .args(["build", "--target=wasm32-wasi"]) + .status() + .expect("failed to compile target into WASM"); + Command::new("wasker") + .args([ + "-o", + &target_obj_name, + "target/wasm32-wasi/debug/rust.wasm", + ]) + .status() + .expect("failed to compile target into obj"); + + let target_lib_name = format!("lib{}.a", target_name); + Command::new("ar") + .args([ + "rcs", + &target_lib_name, + &target_obj_name, + ]) + .status() + .expect("failed to execute process"); + + println!("cargo:rustc-link-arg=-no-pie"); + println!("cargo:rustc-link-search=native={}", path_to_str(wasm_path)); + println!("cargo:rustc-link-lib=static={}", target_name); +} diff --git a/examples/wasi-wrapper/wasi-wrapper-rust/src/main.rs b/examples/wasi-wrapper/wasi-wrapper-rust/src/main.rs new file mode 100644 index 0000000..a132f9c --- /dev/null +++ b/examples/wasi-wrapper/wasi-wrapper-rust/src/main.rs @@ -0,0 +1,13 @@ +mod memory; +mod wasi; + +extern "C" { + fn wasker_main(); +} + +fn main() { + unsafe { + wasker_main(); + } + println!("wasker_main from the compiled target WASM done!"); +} diff --git a/examples/wasi-wrapper/wasi-wrapper-rust/src/memory.rs b/examples/wasi-wrapper/wasi-wrapper-rust/src/memory.rs new file mode 100644 index 0000000..3ef4709 --- /dev/null +++ b/examples/wasi-wrapper/wasi-wrapper-rust/src/memory.rs @@ -0,0 +1,56 @@ +/// Linear Memory +use std::sync::Mutex; + +const LINEAR_MEMORY_BLOCK_SIZE: i32 = 64 * 1024; +const LINEAR_MEMORY_BLOCK_NUM_MAX: i32 = 32; + +static mut LINEAR_MEMORY_BASE: *mut u8 = 0 as _; +static LINEAR_MEMORY_BLOCK_NUM: Mutex = Mutex::new(0); + +#[inline] +pub unsafe fn get_memory_base() -> *mut u8 { + unsafe { LINEAR_MEMORY_BASE } +} + +unsafe fn alloc_memory() -> *mut u8 { + use std::alloc::{alloc, Layout}; // delloc + unsafe { + LINEAR_MEMORY_BASE = alloc( + Layout::from_size_align( + (LINEAR_MEMORY_BLOCK_SIZE * LINEAR_MEMORY_BLOCK_NUM_MAX) as usize, + 8, + ) + .unwrap(), + ); + LINEAR_MEMORY_BASE + } +} + +// fn get_memory_block_num() -> i32 { +// LINEAR_MEMORY_BLOCK_NUM.lock().unwrap().clone() +// } + +fn inc_memory_block_num(block_num: i32) -> i32 { + assert!( + block_num >= 0, + "block_num must be greater than or equal to 0" + ); + let mut num = LINEAR_MEMORY_BLOCK_NUM.lock().unwrap(); + let old_val = *num; + if num.checked_add(block_num).unwrap() > LINEAR_MEMORY_BLOCK_NUM_MAX { + println!("memory_grow: failed to grow memory"); + return -1; + } + *num += block_num; + old_val +} + +#[no_mangle] +pub extern "C" fn memory_base() -> i32 { + unsafe { alloc_memory() as i32 } +} + +#[no_mangle] +pub extern "C" fn memory_grow(block_num: i32) -> i32 { + inc_memory_block_num(block_num) +} diff --git a/examples/wasi-wrapper/wasi-wrapper-rust/src/wasi.rs b/examples/wasi-wrapper/wasi-wrapper-rust/src/wasi.rs new file mode 100644 index 0000000..ab86f47 --- /dev/null +++ b/examples/wasi-wrapper/wasi-wrapper-rust/src/wasi.rs @@ -0,0 +1,62 @@ +/// WASI Implementation based on Rust Std Lib +use crate::memory::get_memory_base; +use wasi::{Errno, ERRNO_SUCCESS}; + +#[repr(C)] +#[derive(Clone, Copy)] +struct IoVec { + iov_base: i32, + iov_len: i32, +} + +type WasiError = i32; + +const fn errno2i32(errno: &Errno) -> WasiError { + errno.raw() as WasiError +} + +#[no_mangle] +pub extern "C" fn fd_write( + _fd: i32, + buf_iovec_addr: i32, + vec_len: i32, + size_addr: i32, +) -> WasiError { + let vec_len = vec_len as usize; + let memory_base = unsafe { get_memory_base() }; + let iovec: *const IoVec = unsafe { memory_base.offset(buf_iovec_addr as isize) } as *const _; + + let mut len = 0; + for i in 0..vec_len { + let IoVec { iov_base, iov_len } = unsafe { *iovec.add(i) }; + let buf = unsafe { memory_base.add(iov_base as usize) }; + let slice = unsafe { std::slice::from_raw_parts(buf, iov_len as usize) }; + + if slice.is_empty() { + continue; + } + print!("{}", String::from_utf8_lossy(slice)); + len += slice.len(); + } + + unsafe { + let size_ptr = memory_base.offset(size_addr as isize); + *(size_ptr as *mut i32) = len as i32; + } + errno2i32(&ERRNO_SUCCESS) +} + +#[no_mangle] +pub extern "C" fn environ_get(_env_addrs: i32, _env_buf_addr: i32) -> WasiError { + errno2i32(&ERRNO_SUCCESS) +} + +#[no_mangle] +pub extern "C" fn environ_sizes_get(_env_count_addr: i32, _env_buf_size_addr: i32) -> WasiError { + errno2i32(&ERRNO_SUCCESS) +} + +#[no_mangle] +pub extern "C" fn proc_exit(code: i32) -> ! { + std::process::exit(code); +} From 36a5e71216b96be25d34876203c4f05dfa0bb49c Mon Sep 17 00:00:00 2001 From: fgh1999 Date: Wed, 19 Jun 2024 00:27:02 +0800 Subject: [PATCH 2/2] Separate directories in `wasi-wrapper` by language --- README.md | 4 ++-- examples/wasi-wrapper/{ => c}/wasi-wrapper-linux.c | 0 examples/wasi-wrapper/{wasi-wrapper-rust => rust}/.gitignore | 0 examples/wasi-wrapper/{wasi-wrapper-rust => rust}/Cargo.lock | 0 examples/wasi-wrapper/{wasi-wrapper-rust => rust}/Cargo.toml | 0 examples/wasi-wrapper/{wasi-wrapper-rust => rust}/README.md | 2 +- examples/wasi-wrapper/{wasi-wrapper-rust => rust}/build.rs | 2 +- examples/wasi-wrapper/{wasi-wrapper-rust => rust}/src/main.rs | 3 ++- .../wasi-wrapper/{wasi-wrapper-rust => rust}/src/memory.rs | 4 ++-- examples/wasi-wrapper/{wasi-wrapper-rust => rust}/src/wasi.rs | 2 +- 10 files changed, 9 insertions(+), 8 deletions(-) rename examples/wasi-wrapper/{ => c}/wasi-wrapper-linux.c (100%) rename examples/wasi-wrapper/{wasi-wrapper-rust => rust}/.gitignore (100%) rename examples/wasi-wrapper/{wasi-wrapper-rust => rust}/Cargo.lock (100%) rename examples/wasi-wrapper/{wasi-wrapper-rust => rust}/Cargo.toml (100%) rename examples/wasi-wrapper/{wasi-wrapper-rust => rust}/README.md (82%) rename examples/wasi-wrapper/{wasi-wrapper-rust => rust}/build.rs (95%) rename examples/wasi-wrapper/{wasi-wrapper-rust => rust}/src/main.rs (51%) rename examples/wasi-wrapper/{wasi-wrapper-rust => rust}/src/memory.rs (95%) rename examples/wasi-wrapper/{wasi-wrapper-rust => rust}/src/wasi.rs (97%) diff --git a/README.md b/README.md index ed68ba9..fdf2de6 100644 --- a/README.md +++ b/README.md @@ -69,11 +69,11 @@ ELF file generated by Wasker is OS-independent: WASI calls from Wasm application Please write your own WASI wrapper for your favorite OS to be linked with Wasker output. -Here, we'll show a [tiny example](./examples/wasi-wrapper/wasi-wrapper-linux.c) of running Wasker output on Linux. +Here, we'll show a [tiny example](./examples/wasi-wrapper/c/wasi-wrapper-linux.c) of running Wasker output on Linux. Link Wasker output and WASI wapper for Linux ``` -gcc -no-pie ./examples/wasi-wrapper/wasi-wrapper-linux.c ./wasm.o -o hello +gcc -no-pie ./examples/wasi-wrapper/c/wasi-wrapper-linux.c ./wasm.o -o hello ``` Run!! diff --git a/examples/wasi-wrapper/wasi-wrapper-linux.c b/examples/wasi-wrapper/c/wasi-wrapper-linux.c similarity index 100% rename from examples/wasi-wrapper/wasi-wrapper-linux.c rename to examples/wasi-wrapper/c/wasi-wrapper-linux.c diff --git a/examples/wasi-wrapper/wasi-wrapper-rust/.gitignore b/examples/wasi-wrapper/rust/.gitignore similarity index 100% rename from examples/wasi-wrapper/wasi-wrapper-rust/.gitignore rename to examples/wasi-wrapper/rust/.gitignore diff --git a/examples/wasi-wrapper/wasi-wrapper-rust/Cargo.lock b/examples/wasi-wrapper/rust/Cargo.lock similarity index 100% rename from examples/wasi-wrapper/wasi-wrapper-rust/Cargo.lock rename to examples/wasi-wrapper/rust/Cargo.lock diff --git a/examples/wasi-wrapper/wasi-wrapper-rust/Cargo.toml b/examples/wasi-wrapper/rust/Cargo.toml similarity index 100% rename from examples/wasi-wrapper/wasi-wrapper-rust/Cargo.toml rename to examples/wasi-wrapper/rust/Cargo.toml diff --git a/examples/wasi-wrapper/wasi-wrapper-rust/README.md b/examples/wasi-wrapper/rust/README.md similarity index 82% rename from examples/wasi-wrapper/wasi-wrapper-rust/README.md rename to examples/wasi-wrapper/rust/README.md index 4f285a7..a00bd1a 100644 --- a/examples/wasi-wrapper/wasi-wrapper-rust/README.md +++ b/examples/wasi-wrapper/rust/README.md @@ -1,6 +1,6 @@ # An Example of Running Wasker Output Based on Rust Std -Similar to the [Linux WASI wrapper](../wasi-wrapper-linux.c), +Similar to the [Linux WASI wrapper](../c/wasi-wrapper-linux.c), 4 mock WASI interfaces are implemented in order to support [the rust example](../../rust/README.md). ## Prerequisite diff --git a/examples/wasi-wrapper/wasi-wrapper-rust/build.rs b/examples/wasi-wrapper/rust/build.rs similarity index 95% rename from examples/wasi-wrapper/wasi-wrapper-rust/build.rs rename to examples/wasi-wrapper/rust/build.rs index d3aa871..e0956ae 100644 --- a/examples/wasi-wrapper/wasi-wrapper-rust/build.rs +++ b/examples/wasi-wrapper/rust/build.rs @@ -33,7 +33,7 @@ fn main() { &target_obj_name, ]) .status() - .expect("failed to execute process"); + .expect("failed to convert obj into lib"); println!("cargo:rustc-link-arg=-no-pie"); println!("cargo:rustc-link-search=native={}", path_to_str(wasm_path)); diff --git a/examples/wasi-wrapper/wasi-wrapper-rust/src/main.rs b/examples/wasi-wrapper/rust/src/main.rs similarity index 51% rename from examples/wasi-wrapper/wasi-wrapper-rust/src/main.rs rename to examples/wasi-wrapper/rust/src/main.rs index a132f9c..8b4ecfb 100644 --- a/examples/wasi-wrapper/wasi-wrapper-rust/src/main.rs +++ b/examples/wasi-wrapper/rust/src/main.rs @@ -7,7 +7,8 @@ extern "C" { fn main() { unsafe { + // Entrypoint of ELF generated by Wasker wasker_main(); } - println!("wasker_main from the compiled target WASM done!"); + println!("wasker_main from the compiled target WASM done."); } diff --git a/examples/wasi-wrapper/wasi-wrapper-rust/src/memory.rs b/examples/wasi-wrapper/rust/src/memory.rs similarity index 95% rename from examples/wasi-wrapper/wasi-wrapper-rust/src/memory.rs rename to examples/wasi-wrapper/rust/src/memory.rs index 3ef4709..919cf68 100644 --- a/examples/wasi-wrapper/wasi-wrapper-rust/src/memory.rs +++ b/examples/wasi-wrapper/rust/src/memory.rs @@ -1,4 +1,4 @@ -/// Linear Memory +//! Linear Memory use std::sync::Mutex; const LINEAR_MEMORY_BLOCK_SIZE: i32 = 64 * 1024; @@ -13,7 +13,7 @@ pub unsafe fn get_memory_base() -> *mut u8 { } unsafe fn alloc_memory() -> *mut u8 { - use std::alloc::{alloc, Layout}; // delloc + use std::alloc::{alloc, Layout}; unsafe { LINEAR_MEMORY_BASE = alloc( Layout::from_size_align( diff --git a/examples/wasi-wrapper/wasi-wrapper-rust/src/wasi.rs b/examples/wasi-wrapper/rust/src/wasi.rs similarity index 97% rename from examples/wasi-wrapper/wasi-wrapper-rust/src/wasi.rs rename to examples/wasi-wrapper/rust/src/wasi.rs index ab86f47..f0c13de 100644 --- a/examples/wasi-wrapper/wasi-wrapper-rust/src/wasi.rs +++ b/examples/wasi-wrapper/rust/src/wasi.rs @@ -1,4 +1,4 @@ -/// WASI Implementation based on Rust Std Lib +//! WASI Implementation based on Rust Std Lib use crate::memory::get_memory_base; use wasi::{Errno, ERRNO_SUCCESS};