README

wag is a WebAssembly compiler implemented as a Go package.

Features

  • The input is a wasm binary module.

  • The output is machine code.

  • It is only a compiler. A runtime environment for the compiled program, including all import functions, needs to be implemented separately. (But see wasys for an example runtime.)

  • Single-pass, fast ahead-of-time compilation. Early functions can be executed while the latter functions are still being compiled, even while the source is still being downloaded.

  • The generated code requires minimal runtime support; it's designed to be executed in an isolated environment. Calling standard library ABIs is not directly supported, but see wasys for an example which exposes syscalls as WebAssembly import functions.

  • Supports snapshot-and-restore across compiler versions and CPU architectures.

  • Supports breakpoint debugging via recompilation.

  • Cross-compilation is supported via Go build tags. If wagamd64 is specified, the x86-64 code generator is used regardless of host architecture, and CPU feature detection is disabled with pessimistic assumptions. Likewise for wagarm64 (but feature detection is not used for ARM64).

Status

  • Supports WebAssembly version 1 (wasm32). No wasm extensions are supported.

  • Supports x86-64 and ARM64 code generation.

  • Generated x86-64 code requires SSE4.1 ROUNDSS/ROUNDSD instructions.

Security

Spectre variant 1: Out-of-bounds linear memory access detection requires that addressable but unallocated memory is inaccessible. It naturally prevents conditional branch exploitation.

Spectre variant 2: On x86, Retpoline is used to protect the runtime environment (although user programs shouldn't be able to inject arbitrary addresses into the branch target buffer).

Testing

Requires Linux, Go, make, cmake, clang++ and libcapstone. About 75% of the WebAssembly spec testsuite is run, by first converting the tests to binary format:

  • git clone --recurse-submodules https://github.com/tsavola/wag.git
  • cd wag
  • make check

Screenshot #1

$ go get github.com/tsavola/wag/cmd/wasys
$ wasys -v $GOPATH/src/github.com/tsavola/wag/testdata/hello.wasm
import write(i32, i32, i32) i32
import openat(i32, i32, i32, i32) i32
import read(i32, i32, i32) i32
import close(i32) i32
import pipe2(i32, i32) i32
import _exit(i32)
hello, world

Screenshot #2

=== RUN   TestSnapshot
--- PASS: TestSnapshot (0.00s)
    snapshot_test.go:80: print output:
        10
        --- snapshotting ---
        current memory limit: 0x6a96051ca000
        current stack ptr:    0x6a960533ffc0
        globals+memory addr:  0x6a96051ba000
        stack addr:           0x6a960533f000
        globals+memory size:  65536
        memory size:          65536
        stack offset:         4032
        stacktrace:
        #1  func-3
        #2  func-2
        --- shot snapped ---
        20
    snapshot_test.go:88: resuming
    snapshot_test.go:100: print output:
        20
        30
        330
        40
        440
Expand ▾ Collapse ▴

Documentation

Overview

Package wag provides a high-level WebAssembly compiler API.

See the Compile function's source code for an example of how to use the low-level compiler APIs (implemented in subpackages).

Errors

ModuleError and ResourceLimit error types are accessible via errors subpackage. Such errors may be returned by compilation and other parsing functions. Other types of errors indicate either a read error or an internal compiler error. (Unexpected EOF is a ModuleError which wraps io.ErrUnexpectedEOF.)

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func CompileLibrary

func CompileLibrary(r compile.Reader, imports binding.LibraryImportResolver) (lib compile.Library, err error)

Types

type Config

type Config struct {
	ImportResolver  binding.ImportResolver // Imports are mapped to the library by default.
	Text            compile.CodeBuffer     // Defaults to dynamically sized buffer.
	GlobalsMemory   compile.DataBuffer     // Defaults to dynamically sized buffer.
	MemoryAlignment int                    // Defaults to minimal valid alignment.
	Entry           string                 // No entry function by default.
}

Config for a single compiler invocation. Zero values are replaced with effective defaults during compilation.

type Object

type Object struct {
	FuncTypes         []wa.FuncType       // Signatures for debug output.
	InitialMemorySize int                 // Current memory allocation.
	MemorySizeLimit   int                 // -1 if not limited.
	Text              []byte              // Machine code and read-only data.
	debug.InsnMap                         // Stack unwinding and debug metadata.
	MemoryOffset      int                 // Threshold between globals and memory.
	GlobalsMemory     []byte              // Global values and memory contents.
	StackFrame        []byte              // Start and entry function addresses.
	Names             section.NameSection // Symbols for debug output.
	Debug             *dwarf.Data         // More detailed debug information.
}

Object code with debug information. The fields are roughly in order of appearance during compilation.

Executing the code requires a platform-specific mechanism. It is not supported by this package, but see the compile subpackage for information.

func Compile

func Compile(objectConfig *Config, r compile.Reader, lib compile.Library) (object *Object, err error)

Compile a WebAssembly binary module into machine code. The Object is constructed incrementally so that populated fields may be inspected on error.

See the source code for examples of how to use the lower-level APIs.

Directories

Path Synopsis
binding Package binding contains import and export utilities.
buffer Package buffer implements compile.CodeBuffer and compile.DataBuffer.
cmd/wasys Program wasys implements a standalone toy compiler and runtime.
compile Package compile implements a WebAssembly compiler.
compile/event
errors Package errors exports common error types without unnecessary dependencies.
internal/cmd/opcodes
internal/cmd/syscalls
internal/code
internal/data
internal/datalayout
internal/errorpanic
internal/errors
internal/gen
internal/gen/atomic
internal/gen/codegen
internal/gen/condition
internal/gen/debug
internal/gen/link
internal/gen/operand
internal/gen/reg
internal/gen/regalloc
internal/gen/rodata
internal/gen/storage
internal/initexpr
internal/isa Documented interfaces.
internal/isa/arm
internal/isa/arm/in
internal/isa/program
internal/isa/prop
internal/isa/reglayout
internal/isa/x86
internal/isa/x86/in
internal/isa/x86/nonabi
internal/loader
internal/module
internal/obj
internal/reader
internal/section
internal/test/fuzzutil
internal/test/library
internal/test/runner
internal/test/runner/imports
internal/test/sexp
internal/test/wat
internal/typedecode
object Package object contains ObjectMapper implementations.
object/abi
object/debug Package debug contains DebugObjectMapper implementations.
object/debug/dump
object/stack Package stack provides runtime call stack manipulation functions.
object/stack/stacktrace
section Package section contains binary stream manipulation utilities.
trap Package trap enumerates trap identifiers.
wa Package wa contains miscellaneous WebAssembly-related things.
wa/opcode Package opcode enumerates WebAssembly instructions.