Git Product home page Git Product logo

awsm's Introduction

aWsm - An Awesome Wasm Compiler and Runtime

Note: Previously known as Silverfish

What is aWsm?

aWsm is a compiler and runtime for compiling WebAssembly (Wasm) code into llvm bytecode, then into sandboxed binaries you can run on various platforms. It focuses on generating very fast code (best of breed for WebAssembly), having a simple and extensible code-base, and on portability.

What is WebAssembly? Wasm is a standard binary format that is platform agnostic, debuggable, fast, and safe. Please see the official webpage, and its specification. Many languages (including C/C++, Rust, C#, Go, Kotlin, Swift, and more, see a more complete list) compile to Wasm. Wasm can be run in all the major browsers, thus is broadly deployed and available.

We're interested in taking Wasm out of the browser, and into all different types of computers (from servers to microcontrollers). Wasm provides a number of benefits outside of the web including:

  • Sandboxing. Regardless which language is compiled to Wasm, the Wasm runtime can execute them safely (including those languages with footguns like C). This uses Software Fault Isolation (SFI) -- to ensure that loads and stores are only within the sandbox-- and Control-Flow Integrity (CFI) -- only allowing the execution of code intentionally generated by the compiler -- to provide safe execution. Restricting SFI protects the surrounding code from faulty or malicious code, and CFI prevents a compromise from hijacking the flow of execution (see buffer overflows and ROP chains).

    Sandboxing can act as a process replacement, especially on systems that don't have hardware support for processes, or where high-density is required.

  • Ubiquity. Wasm is a high-level assembly, independent from any specific hardware. This has the potential to provide a universal specification of computation that can execute in the cloud, on the edge, or in an embedded device.

Why aWsm?

We've investigated how aWsm changes serverless on the edge (see our Sledge runtime for that), and reliability in embedded systems. See the publications and videos:

Why does aWsm enable these cool domains? The Web Assembly eco-system is still developing, and we see the need for a system focusing on:

  • Performance. aWsm is an ahead-of-time compiler that leverages the LLVM compiler to optimize code, and target different architectural backends. We have evaluated aWsm on x86-64, aarch64 (Raspberry Pi), and thumb (ARM Cortex-M4 and M7), and performance on the microprocessors is within 10% of native, and within 40% on the microcontrollers on Polybench benchmarks.
  • Simplicity. The entire code base for the compiler and runtime is relatively small. The compiler is <3.5K lines of Rust, and the runtime (for all platforms) is <5K lines of C. It is nearly trivial to implement different means of sandboxing memory accesses. We've implemented seven different mechanisms for this!
  • Portability. Both the compiler and runtime are mostly platform-independent code, and porting to a new platform only really requires additional work if you need to tweak stack sizes (microcontrollers), or use architectural features (e.g., MPX, segmentation, etc...). aWsm only links what is needed, so it's possible to avoid microcontroller-expensive operations such as f64, f32, and even dynamic memory.
  • Composability. The final output of aWsm is simple *.o elf objects that can be linked into larger systems. This enables the trivial composition of sandboxes together, and sandboxes into larger programs.

We believe that aWsm is one of the best options for ahead-of-time compilation for Wasm execution outside of the browser. If you want to learn more about aWsm, see the design, or the publications listed above.

Where does aWsm Help Out?

  • Edge and Serverless: aWsm enables small-footprint, efficient edge, serverless runtime that we call sledge (or ServerLess on the EDGE). aWsm sandboxes don't take up many more resources than a native binary, and sledge can create sandboxes, thus edge functions, in around 50 microseconds. This enables massive benefits on the latency-sensitive edge!
  • Embedded devices: aWsm is used in eWasm to provide sandboxed isolation in small microcontrollers (~64-128KiB of SRAM!). aWsm enables memory savings compared to other embedded techniques, and near-native C performance. aWsm is used in bento boxes that provide an abstraction for embedded processes. They also have shown the huge performance benefit of aWsm.
  • Cloud: Similar to the serverless argument above, aWsm can provide additional security by sandboxing tenant computation. aWsm makes it trivial to filter system calls and system requires in accordance with your security policies.
  • Desktop: Similarly, aWsm can provide increased security where necessary.
  • Embedding policy into frameworks: Lua is often used to embed policy into C++ game engines, and eBPF is used to embed logic into the Linux kernel. Wasm can be targeted by many languages, making it an appealing target, and aWsm enables it to be efficiently embedded into the surrounding framework.

Where aWsm isn't yet a great fit:

  • Browsers: Browsers have their own Wasm engines that can't easily be replaced. Until the browser makers are breaking down our door to get aWsm in their browser, you'll have to use their built-in engines.
  • Wherever interpreters or Jit are required: Some domains focus almost entirely on the delay from download to execution. An AoT compiler is not a great fit for that domain due to the latency of compilation. However, aWsm has been demonstrated to generate code that has exceptional performance, so we focus on domains that benefit from efficiency.

Performance

PolyBench/C benchmarks for x86-64 (slowdown over native C):

Wasmer WAVM Node.js + Emscripten Lucet aWsm
Avg. Slowdown 149.8% 28.1% 84.0% 92.8% 13.4%
Stdev. in Slowdown 194.09 53.09 107.84 117.25 34.65

PolyBench/C benchmarks for Arm aarch64 (slowdown over native C):

aWsm
Avg. Slowdown 6.7%
Stdev. of Slowdown 19.38

Polybench/C benchmarks for Arm Cortex-M microcontrollers (slowdown over native C):

Architectures aWsm
Cortex-M7 Avg. slowdown 40.2%
Cortex-M4 Avg. slowdown 24.9%

In comparison, the wasm3 interpreter's slowdown on microcontrollers is more than 10x. For more details (including other bounds checking mechanisms), see the paper.

Note: these numbers are from May 2020.

There are many compelling runtimes, but we believe that aWsm is useful in generating very fast code, while being simple and extensible.

Comparison to Existing Wasm Ecosystems

There are many existing compilers and runtimes. aWsm fills the niche of a compiler

  • based on ahead-of-time compilation using the popular LLVM infrastructure,
  • that generates fast, safe code (even on microcontrollers), and
  • that is designed for to be lightweight and easily extended.

Adding runtime functions and changing safety checking mechanisms are trivial operations.

Runtime Method x86_64 x86 aarch64 thumb URL
aWsm AoT You are here
Wasmtime AoT https://github.com/bytecodealliance/wasmtime
Wasmer AoT https://github.com/wasmerio/wasmer
WAMR Pseudo-AoT/Int https://github.com/bytecodealliance/wasm-micro-runtime
Wasm3 Int https://github.com/wasm3/wasm3
Wasmi Int https://github.com/paritytech/wasmi

This is not an exhaustive list! There are many others as this is a pretty active area.

Note: this table is from the best of our understanding of each system in July 2020.

Getting started!

aWsm 0.1.0
Gregor Peach <[email protected]>

USAGE:
    awsm [FLAGS] [OPTIONS] <input>

FLAGS:
    -h, --help                           Prints help information
    -i, --inline-constant-globals        Force inlining of constant globals
    -u, --fast-unsafe-implementations    Allow unsafe instruction implementations that may be faster
        --runtime-globals                Don't generate native globals, let the runtime handle it
    -V, --version                        Prints version information

OPTIONS:
    -o, --output <output>    Output bc file
        --target <target>    Set compilation target

ARGS:
    <input>    Input wasm file

Installation from Source

Debian-based Systems

git clone https://github.com/gwsystems/aWsm.git
cd aWsm
./install_deb.sh

The compiler can now be run via awsm

Other Systems

  1. Install Rust
  2. Install LLVM
  3. Link Your Clang Installation so clang-9 and llvm-config-9 are in your path aliased to clang and llvm-config. For example, the following commands accomplish this using update-alternatives after replacing LLVM_VERSION with the version returned you installed above (In *NIX systems, this can be confirmed with ls /usr/bin/clang*)
LLVM_VERSION=9
sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-$LLVM_VERSION 100
sudo update-alternatives --install /usr/bin/llvm-config llvm-config /usr/bin/llvm-config-$LLVM_VERSION 100
  1. Install the C++ Standard Library for LLVM
  2. Clone and build aWsm
git clone https://github.com/gwsystems/aWsm.git
cd aWsm
cargo build --release
  1. The aWsm binary is built at target/release/awsm. Copy this to the appropriate place for your platform and add to your PATH if necessary.

Executing and Testing aWsm

The tests can run with

cd code_benches; ./run.py

Please see the design to understand the pipeline, and see run.py for an example of how to connect existing compilers (to generate Wasm, and generate machine code from LLVM IR) with aWsm.

Note that aWsm is still a research prototype, so might have some rough edges. It is not currently turn-key. You likely need to understand how to generate Wasm, and use an LLVM compile chain. We're happy to accept PRs with fixes, and "quality of life" improvements.

We're in the processes of standing up a CI infrastructure.

Tour of the Source

The source is organized as such:

  • src/ - the Rust source of the compiler, and the awsm binary. Look here for the logic for taking in Wasm, and generating LLVM bytecode. cargo guides the compilation of this code.
  • code_benches/ - This is a relatively large set of benchmarks, many of which are derived from Polybench (pb_*), MiBench (mb_*), or various applications (custom_* including NN inference, sqlite, a PID controller, and an extended Kalman filter). The run.py file guides the compilation and execution of these as effectively a set of unit tests, and is an example of the compilation structure of an application with the runtime in aWsm.
  • example_code/ - More atomic tests for specific Wasm features (bounds checks, indirect function invocations, etc...). This ensures that changes to the compiler don't break Wasm sandboxing, and provides regression tests.
  • runtime/ - The aWsm runtime. This includes most of the code that provides the sandboxing guarantees (for example, including bounds checks, indirect function call type checks and indirection). Microcontroller-specific runtime code (for Arm Cortex-M processors) referred to in eWasm, is in cortex_m_glue/ and libc/cortex_m_backing.c. Various pluggable bounds checks can be found in runtime/memory/. The runtime is compiled separately, and combined with the LLVM IR output by aWsm (using LTO) to generate the final sandboxed object.
  • doc/ - Documentation directory. See the *.md files there.

Limitations and Assumptions

Additional Wasm instruction support needed. aWsm has not focused on a complete implementation of every Wasm instruction, instead focusing on supporting the code generated by the LLVM front-end. The code is extensible, and we've added instructions as needs-be. Please make a PR with support for additional instructions if you need them!

Limited support for future Wasm features. The features on the Wasm roadmap are not supported. We're quite interested in supporting as many of these feature sets as possible, and would happily accept PRs.

Advice for Wasm Standardization

We've done quite a bit of work targeting microcontrollers (Arm Cortex-Ms), and have discovered a number of limitations of the current Wasm Specification for that domain. We provide details in Section 7 of our EMSOFT publication. We believe that some changes to the specification, or the creation of an embedded profile might be warranted. The main limitations:

  1. Variant page sizes selected by the runtime. Wasm uses 64KiB pages. That is far too large for embedded systems. aWsm uses smaller pages, while simulating the larger default pages. Enabling smaller pages would make Wasm's use on microcontrollers -- often with only 64KiB of memory total -- easier. In aWsm, the page size is configurable.
  2. Separation of read-only and read-write memory. In Wasm, all data is accessed in linear memory, which provides strong sandboxing, but does not discriminate between RW and RO data. Microcontrollers often use Execute in Place (XIP) read-only memory, which allows RO data to be accessed and executed directly from flash. This is beneficial in microcontrollers with on the order of 64KiB of memory (SRAM), but around 1MIB of flash. Wasm does not separate RO and RW memory, preventing this optimization that is essential for density on such systems.
  3. Allow undefined behavior on Out of Bounds (OoB) accesses. The specification requires any access outside of the allocated bounds of linear memory to be caught, and the sandbox terminated. We show in the publication that relaxing this requirement, and allowing undefined behavior on OoB accesses can significantly speed up execution, and shrink code sizes, while maintaining strong sandboxed isolation.

Acknowledgements

aWsm was designed and implemented by Gregor Peach (@Others) while an undergraduate researcher in the GW Systems Lab. Demonstrating the value of the WebAssembly specification in a systems context, aWsm inspired the GW Systems Lab to fund and pursue follow-up WebAssembly-based research systems outside of its traditional focus on component-based operating systems.

Collaboration with members of the Arm Research team have been particularly instrumental in growing aWsm from its initial prototype. Additionally, financial support from SRC, Arm, and NSF have supported researchers working on aWsm and follow-up projects.

About Us

The GWU Systems group focuses on low-level system design and implementation. One of our main research vehicles is the Composite component-based operating system, which we aim to integrate with Wasm through aWsm. If you're interested in low-level hacking and system building, in secure and reliable systems, in embedded systems, or in models for parallelism, don't hesitate to contact Gabe about doing a PhD or becoming involved with the group.

awsm's People

Contributors

bushidocodes avatar emil916 avatar geky avatar gparmer avatar others avatar phanikishoreg avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

awsm's Issues

Translation when table is exported

Hello!

Does aWsm translate binaries whose tables are exported? I keep getting the following error when I try to compile binaries that export their libraries.

thread 'main' panicked at 'Have not implemented export kind Table', src/wasm.rs:1238:26
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

Thanks!

mismatch in type_id for function pointer-based calls

I've been trying to get GOCR compiling and running with silverfish but there seem to be some weirdness around the function pointers. Was able to succesfully compile it.

The call here leads to an assert in the runtime: https://github.com/phanikishoreg/gocr/blob/master/src/list.c#L325

assert triggered in the runtime: https://github.com/gparmer/silverfish/blob/master/runtime/memory/64bit_nix.c#L129

I debugged to see what the assert is and why that is triggered, and this is the log:

$ ./gocr.out -f ASCII < test.pbm 
// log here: "add_function_to_table" <func_index> <func type_id> <func addr>
add_function_to_table 1 3 0x40a760
add_function_to_table 2 1 0x40a7c0
add_function_to_table 3 1 0x40a9a0
add_function_to_table 4 2 0x40ac40
add_function_to_table 5 0 0x40bf10
add_function_to_table 6 2 0x40bf70
add_function_to_table 7 1 0x40bf20
add_function_to_table 8 1 0x40cd70
add_function_to_table 9 1 0x40cda0
add_function_to_table 10 4 0x40ec10
add_function_to_table 11 2 0x53a080        // this seem to be the function..
add_function_to_table 12 4 0x53a180
add_function_to_table 13 4 0x53a150
01 // program output
// log here: "get_function_from_table" <func_idx> <func typeid in indirect table> <type_id param>
get_function_from_table 11 2 5         // called with a different type id 5
get_function_from_table 11 2 5         // second call.. 
$ 

The problem is, on function table initialization, the type_id of that function is set to 2. But on call to get_function_from_table, the type_id requested is 5. Unsure how this is happening but this is how far I got with the debugging so far. In the above logs, I've disabled that assert I pointed to and the program works otherwise, outputs "01" that's in the input image.

@Others : I would really appreciate if you can help me fix this. For now, I'm going to just comment out the "type check" assert in the runtime (still keeping the function pointer NULL check).

Adding data layout meta

Hi @geky

In my use of case the data-layout metadata is needed. Taking a look at the llvm-alt crate, it seems that there is no way using the wrapper. However, calling directly to the llvm-sys underlying crate seems to work.

if let Some(ref layout) = opt.layout {
        unsafe {
            let c_target = std::ffi::CString::new(layout.to_string()).unwrap();
            llvm::ffi::core::LLVMSetDataLayout(llvm_module.into(), c_target.as_ptr());
        }
    }

WDYT? Thanks in advance

Document odd conditional in runtime_heap_base initialization logic

The runtime heap base is currently set to memory_size under certain conditions, but the reasoning is undocumented and no contributor recalls why this is written this way. Given that this code was recently refactored, this should be investigated by checking out the following commit (cd9b619) and using GitLens or a similar tool to track down the origin of this code to better understand and document this logic. It likely is useful to also review how wasmg___heap_base is generated to understands paths when that might be zero or non-zero.

runtime_heap_base = wasmg___heap_base;
if (runtime_heap_base == 0) {
    runtime_heap_base = memory_size;
}

Follow up context from @Others

"I do think it maybe should always be at the end of memory (not at the heap base), since otherwise malloc might overwrite this. Honestly this is basically just a wasmception hack since wasi does APIs in a more sane way."

LLVM ERROR: inconsistency in registered CommandLine options

At the moment the dual dependencies on llvm-sys causes a strange error with LLVM:

$ ./target/debug/silverfish               
: CommandLine Error: Option 'help-list' registered more than once!
LLVM ERROR: inconsistency in registered CommandLine options       

Some googling around shows this is an issue that can happen if libLLVM gets linked twice:
https://stackoverflow.com/questions/54273632/llvm-linking-commandline-error-option-help-list-registered-more-than-once-l

The dual dependencies against llvm-sys might be the issue? I'm not sure if there is a way to tell cargo to deduplicate the linking:

$ cargo tree
llvm-alt v0.5.0 (git+https://github.com/Others/llvm-rs.git#754fdf857f83e64d371a046dcb8fa3587a176cf8)     
├── cbox v0.3.0                                                                                          
│   └── libc v0.2.51 (*)                                                                                 
├── libc v0.2.51 (*)                                                                                     
└── llvm-sys v0.3.0 (git+https://github.com/Others/llvm-sys.rs#f4d6b7523e9c3e71a45aa8155f0ef0911689033a) 

llvm-sys v90.0.0    
└── libc v0.2.51 (*)

Compilation errors and functional correctness vary based on WASI-SDK Optimization levels.

This bug is related to WASI-SDK work and thus is in the branch wasi-abstract-interface.

Currently, at least two tests trigger a fatal LLVM error during the final clang step linking the *.bc emitted from aWsm with the uvwasi runtime:

error: Invalid instruction with no BB (Producer: 'LLVM11.1.0' Reader: 'LLVM 11.1.0')

This suggests that perhaps the LLVM bitcode emitted by the compiler is invalid

Additionally, one test is functionally correct at optimization level, but returns a different result at a different optimization level.
This suggests that different WebAssembly opcodes emitted at different optimization levels may cause a control flow bug.

Here follows steps to recreate the bugs and a zip containing the *.wasm files of the two apps at optimization levels 0-3 with associated textfiles containing opcode counts of each variant.

Steps to Replicate

  1. Checkout wasi-abstract-interface. The setup scripts likely differ from what you already have, so you may need to run the setup script.
  2. Navigate to awsm/test/wasi

The first test I want you to look at is in awsm/test/wasi/c/atof.c This program deserializes arg 1 into a float and then serialized it back out to stdout.

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char** argv) {
    double pi = atof(argv[1]);
    printf("%.2lf\n", pi);
}

You can build and run this natively with the following to get a feel for it:

sean@MANPUTER:~/projects/awsm/tests/wasi$ clang c/atof.c
sean@MANPUTER:~/projects/awsm/tests/wasi$ ./a.out 3.14
3.14
sean@MANPUTER:~/projects/awsm/tests/wasi$ rm a.out

It turns out that the behavior of this program varies on the optimization level passed to the WASI-SDK clang compiler.

At optimization level 3,

wasm/%.wasm: c/%.c
	@mkdir -p wasm
	${WASMCC} ${WASMLINKFLAGS} ${OPTFLAGS} -O3 $< -o $@

everything builds and runs correctly:

sean@MANPUTER:~/projects/awsm/tests/wasi$ ./vm/atof_vm 3.14
3.14

At optimization levels 1 and 2:

wasm/%.wasm: c/%.c
	@mkdir -p wasm
	${WASMCC} ${WASMLINKFLAGS} ${OPTFLAGS} -O2 $< -o $@

aWsm compiles correctly, but the final clang linking with the runtime fails with an error error: Invalid instruction with no BB (Producer: 'LLVM11.1.0' Reader: 'LLVM 11.1.0') that suggests that maybe LLVM bitcode emitted by the compiler is invalid:

sean@MANPUTER:~/projects/awsm/tests/wasi$ make clean vm/atof_vm
rm -f ./wasm/* ./bc/* ./vm/*_vm
/opt/wasi-sdk//bin/clang --sysroot=/opt/wasi-sdk//share/wasi-sysroot -Wl,--allow-undefined,-z,stack-size=32768,--threads=1 -O3 -flto -O2 c/atof.c -o wasm/atof.wasm
../../target/release/awsm  wasm/atof.wasm -o bc/atof.bc
INFO [awsm] running awsm("wasm/atof.wasm", Some("bc/atof.bc"))
INFO [awsm::wasm] Globals taking up 4 bytes
INFO [awsm::wasm] Data initializers taking up 2239 bytes
INFO [awsm::wasm] Function table entries 4 (ignoring fragmentation)
INFO [awsm::codegen::memory] memory limits ResizableLimits { initial: 1, maximum: None }
INFO [awsm] awsm finished successfully
clang -pthread -ldl -lm -O3 -flto  -I../../runtime/libc/wasi/include -I../../runtime/thirdparty/dist/include bc/atof.bc ../../runtime/runtime.c ../../runtime/libc/wasi/wasi_main.c ../../runtime/libc/wasi/wasi_backing.c ../../runtime/libc/wasi/wasi_impl_uvwasi.c ../../runtime/libc/env.c ../../runtime/memory/64bit_nix.c ../../runtime/thirdparty/dist/lib/libuvwasi_a.a ../../runtime/thirdparty/dist/lib/libuv_a.a -o vm/atof_vm
error: Invalid instruction with no BB (Producer: 'LLVM11.1.0' Reader: 'LLVM 11.1.0')
1 error generated.
make: *** [Makefile:24: vm/atof_vm] Error 1
rm bc/atof.bc wasm/atof.wasm

At optimization level 0:

wasm/%.wasm: c/%.c
	@mkdir -p wasm
	${WASMCC} ${WASMLINKFLAGS} ${OPTFLAGS} -O0 $< -o $@

Everything compiles correctly, but the program does not work as expected:

sean@MANPUTER:~/projects/awsm/tests/wasi$ ./vm/atof_vm 3.14
0.00

The Fibonacci app works a bit differently. It is only able to compile at optimization level 0

wasm/%.wasm: c/%.c
	@mkdir -p wasm
	${WASMCC} ${WASMLINKFLAGS} ${OPTFLAGS} -O0 $< -o $@
sean@MANPUTER:~/projects/awsm/tests/wasi$ echo "10" | ./vm/fibonacci_vm 
55

At optimization levels 1, 2, and 3, it errors out in the final linking step with the same error message as above error: Invalid instruction with no BB (Producer: 'LLVM11.1.0' Reader: 'LLVM 11.1.0')

Here is the zip containing the wasm files and associated opcode counts. Despite the issues identified above, all of these *.wasm files correctly execute on wamtime:
sample.wasm.zip

Harden or Replace use of VLAs in abstract WASI serialization layer

Currently, the abstract WASI layer uses dynamic memory allocation via VLAs. This has negative security implications for stack overflows and likely will inhibit refactoring of the cortex-m backing to use WASI. This should be addressed and improved to resolve these issues.

Improve efficiency of bounds checking code

From @Others in #47 : "this is probably not the most efficient assert here. This may be more now that you're using this code more. Can be deferred to the future"

 assert(bounds_check < WASM_PAGE_SIZE || (memory_size > bounds_check && offset <= memory_size - bounds_check));

Update Wasmparser

As of this comment, wasmparser is on 0.83.0. Given that a release that may contain breaking changes occurs every month, this may be a higher version when you read this.

In #77, I updated from 0.39.2 to 0.58.0. I stopped at this level because 0.59.0 contains a complete rewrite of the parsing logic. This may require substantial changed on our end. See bytecodealliance/wasm-tools@db2ef19 for specifics.

Given that breaking changes occur every 3 releases or so, I estimate that going from 0.58.0 to 0.83.0 may take up to 40 hours of engineering effort. This is a hard technical blocker for an WebAssembly instructions that 0.58.0 cannot parse.

Feature: Reference Instructions

This is a higher-level post MVP feature that may not make sense for us. The idea of a reference is that a WebAssembly sandbox can be passed an opaque host reference that it can manage.

  • ref.null
  • ref.is_null
  • ref.func

References:

Diagnose printf/scanf perf issues

Xiaosu noticed that printf and scanf functions seem to cause a substantial slowdown of modules running under Sledge. This might be due to LTO, it might be Sledge-backing specific, or it might be here.

image

The scope of this task is to compare the overhead of scanf and printf under wasmception, wasi-sdk, and native to determine if this is an issue here or downstream.

Run WASI entrypoint _start instead of main

Currently, the awsm runtime implicitly treats a function called main as the entrypoint.

However, this differs from the WASI standard, which expects this to be _start.

I propose that we change this to align to WASI and make it simpler for us to run WASI module.

Remove wasmception

Given the shift to WASI and the uvwasi backing, we can potentially remove wasmception from the runtimes in this repo.

Add Continuous Integration

Add a CI infrastructure to aWsm. Run a subset of the tests on each PR to validate the soundness of the request.

Investigate and validate build_result code paths

A recent bug turned out to be due to calls to build_result being executed with the builder being in the right place. A fix for this was to explicitly call b.position_at_end(self.bb); at the top of the function. This task is to investigate the different code paths where build_result is called to determine if there are either:

  1. related logical bugs that the wasm test suite is not picking up
  2. a cleaner refactor that doesn't require repositioning the builder

Feature: Multi Value

This feature enables a WebAssembly function to return a tuple of values. When writing WebAssembly by hand, I've found this to be a helpful way to return an (i32, i32) fat pointer to a string or static array of values stored in linear memory.

I am unclear how one can do this with C via WASI-SDK. I've seen code examples that have suggested to me that rightmost arguments can be tagged to be returned as part of a multi-value return. See the C header for WASI itself as an example.

Reference: https://github.com/WebAssembly/multi-value

Cleanse identifier names to ensure callable from C runtime

It's possible that we might ingest WASI functions exported with names that are not valid C identifiers.

For example, here is a test in the wasm spec test suite:

 (func (export "type-f64-value") (result f64)
    (block (result f64) (f64.neg (br_if 0 (f64.const 4) (i32.const 1))))
  )

This seems to generate valid LLVM bitcode with the same symbol:

; Function Attrs: nounwind
define double @wasmf_type-f64-value() #1 {
entry:
  br label %b_0

exit:                                             ; preds = %b_1
  ret double %0

b_0:                                              ; preds = %entry
  br i1 true, label %b_1, label %b_2

b_1:                                              ; preds = %b_2, %b_0
  %0 = phi double [ 4.000000e+00, %b_0 ], [ -4.000000e+00, %b_2 ]
  br label %exit

b_2:                                              ; preds = %b_0
  br label %b_1
}

However, this fails when we try to link with C runtime code:

dist/br_if_0.c:12:25: error: expected ';' after top level declarator
extern double wasmf_type-f64-value();
                        ^
                        ;

This is because C only supports ASCII characters, numbers, and underscores in symbol names.

Given the way that we resolve exported symbols, I suspect that we need to encode export names. I suggest replacing invalid symbols with ASCII char codes with leading and trailing underscores.

For example, wasmf_type-f64-value would be encoded as wasmf_type_45_f64_45_value

Tighten invariants around block edge cases

We still don't support blocks that consume an argument, or yield more than one piece of data. We probably should assert that those aren't being generated somewhere. It likely would just lead to a crash, but weird code gen bugs are best proactively avoided

Enhance "fast unsafe" compilation option

There are some corners of the WebAssembly spec that are strict and explicit where the C and LLVM specifications remain undefined. An example of this is UINT32_MIN % -1, which overflows with undefined semantics in C and LLVM, but which correctly returns 0 in WebAssembly. Achieving strict compliance thus requires special shims beyond LLVM intrinsics. There may be a performance cost to this.

We can enhance our fast unsafe math compiler option to use a "close enough" LLVM intrinsic in place of a totally compliant implementation in certain cases.

Validate Stack Size Configuration in preparation for cortex-m

The clang WebAssembly linker takes a flag to statically set the stack size of the resulting binary.

Currently our Makefiles define linker flags as follows:

WASMLINKFLAGS=-Wl,--allow-undefined,-z,stack-size=32768,--threads=1

In order to prepare for the cortex-m refactor for WASI, we need to better understand how this flag impacts the memory consumption of the resulting binary.

What LLVM versions are supported?

Does aWsm support using an LLVM version other than 9? I tried building with LLVM 15, and managed to build the binary but it encounters an immediate segmentation fault when trying to build something. It looks like the crash happens inside LLVMGetElementType in libLLVM-15.so at src/codegen/function.rs:172.

Generating a Call Graph from LLVM IR?

Hi everyone!

First, thanks a lot for the cool project and making the source code of your research public! :-)

I have a question regarding using aWsm not for executing Wasm binaries, but for program analysis. In particular, I was wondering if you have tested lifting WebAssembly binaries to LLVM IR with aWsm, and then analyzing that LLVM IR with standard analysis passes.

E.g., we tried obtaining a callgraph of a Wasm binary by first compiling with awsm binary.wasm -o bitcode.bc and then running llvm-opt bitcode.bc --dot-callgraph on aWsm's LLVM IR output. However, the produced call graph is missing edges for indirect calls. I know it is not the original use case of aWsm, but since you know Wasm and LLVM well, I wanted to ask anyway:

  1. Can aWsm generate a call graph for WebAssembly binaries somehow?
  2. Do you know why the LLVM --dot-callgraph analysis produces a call graph with missing edges for indirect calls? Is there a better LLVM call graph analysis that could work on your produced bitcode?
  3. Do you know of another way for getting a static call graph for WebAssembly binaries?

Thanks again and all the best!

Improve "Trap Handling" for out of bounds memory access and other traps

According to the WebAssembly specification, abnormal behavior, such as an out-of-bounds memory access, should trigger a "trap."

image
Source:

In the web context, this causes a JavaScript exception. However, the WebAssembly specification is being extended to support "in module" trap handlers (https://github.com/WebAssembly/exception-handling/blob/master/proposals/exception-handling/Exceptions.md)

Currently, we are mostly enforcing invariants via assert. We should likely replace this with a centralized entrypoint for trap handling logic called via setjmp and longjmp. I believe this would just log a descriptive and error out for now.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.