exec

package
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 7, 2018 License: BSD-3-Clause Imports: 11 Imported by: 0

Documentation

Overview

Package exec provides functions for executing WebAssembly bytecode.

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	// ErrSignatureMismatch is the error value used while trapping the VM when
	// a signature mismatch between the table entry and the type entry is found
	// in a call_indirect operation.
	ErrSignatureMismatch = errors.New("exec: signature mismatch in call_indirect")
	// ErrUndefinedElementIndex is the error value used while trapping the VM when
	// an invalid index to the module's table space is used as an operand to
	// call_indirect
	ErrUndefinedElementIndex = errors.New("exec: undefined element index")
)
View Source
var (
	// ErrMultipleLinearMemories is returned by (*VM).NewVM when the module
	// has more then one entries in the linear memory space.
	ErrMultipleLinearMemories = errors.New("exec: more than one linear memories in module")
	// ErrInvalidArgumentCount is returned by (*VM).ExecCode when an invalid
	// number of arguments to the WebAssembly function are passed to it.
	ErrInvalidArgumentCount = errors.New("exec: invalid number of arguments to function")
)
View Source
var ErrOutOfBoundsMemoryAccess = errors.New("exec: out of bounds memory access")

ErrOutOfBoundsMemoryAccess is the error value used while trapping the VM when it detects an out of bounds access to the linear memory.

View Source
var ErrUnreachable = errors.New("exec: reached unreachable")

ErrUnreachable is the error value used while trapping the VM when an unreachable operator is reached during execution.

Functions

This section is empty.

Types

type InvalidFunctionIndexError

type InvalidFunctionIndexError int64

InvalidFunctionIndexError is returned by (*VM).ExecCode when the function index provided is invalid.

func (InvalidFunctionIndexError) Error

type InvalidReturnTypeError

type InvalidReturnTypeError int8

InvalidReturnTypeError is returned by (*VM).ExecCode when the module specifies an invalid return type value for the executed function.

func (InvalidReturnTypeError) Error

func (e InvalidReturnTypeError) Error() string

type Process

type Process struct {
	// contains filtered or unexported fields
}

Process is a proxy passed to host functions in order to access things such as memory and control.

func NewProcess

func NewProcess(vm *VM) *Process

NewProcess creates a VM interface object for host functions

func (*Process) ReadAt

func (proc *Process) ReadAt(p []byte, off int64) (int, error)

ReadAt implements the ReaderAt interface: it copies into p the content of memory at offset off.

func (*Process) Terminate

func (proc *Process) Terminate()

Terminate stops the execution of the current module.

func (*Process) WriteAt

func (proc *Process) WriteAt(p []byte, off int64) (int, error)

WriteAt implements the WriterAt interface: it writes the content of p into the VM memory at offset off.

type VM

type VM struct {

	// RecoverPanic controls whether the `ExecCode` method
	// recovers from a panic and returns it as an error
	// instead.
	// A panic can occur either when executing an invalid VM
	// or encountering an invalid instruction, e.g. `unreachable`.
	RecoverPanic bool
	// contains filtered or unexported fields
}

VM is the execution context for executing WebAssembly bytecode.

Example (Add)
package main

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"log"
	"reflect"

	"github.com/go-interpreter/wagon/exec"
	"github.com/go-interpreter/wagon/wasm"
)

func main() {
	raw, err := compileWast2Wasm("testdata/add-ex-main.wast")
	if err != nil {
		log.Fatalf("could not compile wast file: %v", err)
	}

	m, err := wasm.ReadModule(bytes.NewReader(raw), func(name string) (*wasm.Module, error) {
		// ReadModule takes as a second argument an optional "importer" function
		// that is supposed to locate and import other modules when some module is
		// requested (by name.)
		// Theoretically, a general "importer" function not unlike the Python's 'import'
		// mechanism (that tries to locate and import modules from a $PYTHONPATH)
		// could be devised.
		switch name {
		case "add":
			raw, err := compileWast2Wasm("testdata/add-ex.wast")
			if err != nil {
				return nil, fmt.Errorf("could not compile wast file hosting %q: %v", name, err)
			}

			add, err := wasm.ReadModule(bytes.NewReader(raw), nil)
			if err != nil {
				return nil, fmt.Errorf("could not read wasm %q module: %v", name, err)
			}
			return add, nil
		case "go":
			// create a whole new module, called "go", from scratch.
			// this module will contain one exported function "print",
			// implemented itself in pure Go.
			print := func(proc *exec.Process, v int32) {
				fmt.Printf("result = %v\n", v)
			}

			m := wasm.NewModule()
			m.Types = &wasm.SectionTypes{
				Entries: []wasm.FunctionSig{
					{
						Form:       0, // value for the 'func' type constructor
						ParamTypes: []wasm.ValueType{wasm.ValueTypeI32},
					},
				},
			}
			m.FunctionIndexSpace = []wasm.Function{
				{
					Sig:  &m.Types.Entries[0],
					Host: reflect.ValueOf(print),
					Body: &wasm.FunctionBody{}, // create a dummy wasm body (the actual value will be taken from Host.)
				},
			}
			m.Export = &wasm.SectionExports{
				Entries: map[string]wasm.ExportEntry{
					"print": {
						FieldStr: "print",
						Kind:     wasm.ExternalFunction,
						Index:    0,
					},
				},
			}

			return m, nil
		}
		return nil, fmt.Errorf("module %q unknown", name)
	})
	if err != nil {
		log.Fatalf("could not read module: %v", err)
	}

	vm, err := exec.NewVM(m)
	if err != nil {
		log.Fatalf("could not create wagon vm: %v", err)
	}

	const fct1 = 2 // index of function fct1
	out, err := vm.ExecCode(fct1)
	if err != nil {
		log.Fatalf("could not execute fct1(): %v", err)
	}
	fmt.Printf("fct1() -> %v\n", out)

	const fct2 = 3 // index of function fct2
	out, err = vm.ExecCode(fct2, 40, 6)
	if err != nil {
		log.Fatalf("could not execute fct2(40, 6): %v", err)
	}
	fmt.Printf("fct2() -> %v\n", out)

	const fct3 = 4 // index of function fct3
	out, err = vm.ExecCode(fct3, 42, 42)
	if err != nil {
		log.Fatalf("could not execute fct3(42, 42): %v", err)
	}
	fmt.Printf("fct3() -> %v\n", out)

}

// compileWast2Wasm fakes a compilation pass from WAST to WASM.
//
// When wagon gets a WAST parser, this function will be running an actual compilation.
// See: https://github.com/go-interpreter/wagon/issues/34
func compileWast2Wasm(fname string) ([]byte, error) {
	switch fname {
	case "testdata/add-ex.wast":
		// obtained by running:
		//  $> wat2wasm -v -o add-ex.wasm add-ex.wast
		return ioutil.ReadFile("testdata/add-ex.wasm")
	case "testdata/add-ex-main.wast":
		// obtained by running:
		//  $> wat2wasm -v -o add-ex-main.wasm add-ex-main.wast
		return ioutil.ReadFile("testdata/add-ex-main.wasm")
	}
	return nil, fmt.Errorf("unknown wast test file %q", fname)
}
Output:

fct1() -> 42
fct2() -> 46
result = 84
fct3() -> <nil>

func NewVM

func NewVM(module *wasm.Module) (*VM, error)

NewVM creates a new VM from a given module. If the module defines a start function, it will be executed.

func (*VM) ExecCode

func (vm *VM) ExecCode(fnIndex int64, args ...uint64) (rtrn interface{}, err error)

ExecCode calls the function with the given index and arguments. fnIndex should be a valid index into the function index space of the VM's module.

func (*VM) Memory

func (vm *VM) Memory() []byte

Memory returns the linear memory space for the VM.

Directories

Path Synopsis
internal
compile
Package compile is used internally by wagon to convert standard structured WebAssembly bytecode into an unstructured form suitable for execution by it's VM.
Package compile is used internally by wagon to convert standard structured WebAssembly bytecode into an unstructured form suitable for execution by it's VM.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL