Documentation ¶
Overview ¶
Package exec provides functions for executing WebAssembly bytecode.
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
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") // check call stack depth ErrCallStackDepthExceed = errors.New("exec: call stack depth exceeded") )
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") )
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.
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 CompiledModule ¶
func CompileModule ¶
func CompileModule(module *wasm.Module) (*CompiledModule, error)
type InvalidFunctionIndexError ¶
type InvalidFunctionIndexError int64
InvalidFunctionIndexError is returned by (*VM).ExecCode when the function index provided is invalid.
func (InvalidFunctionIndexError) Error ¶
func (e InvalidFunctionIndexError) Error() string
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 ¶
NewProcess creates a VM interface object for host functions
func (*Process) ReadAt ¶
ReadAt implements the ReaderAt interface: it copies into p the content of 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 //add for ontology gas limit ExecMetrics *Gas HostData interface{} //memory limitation MemoryLimitation uint64 //call stack depth CallStackDepth uint32 // contains filtered or unexported fields }
VM is the execution context for executing WebAssembly bytecode.
Example (Add) ¶
package main import ( "bytes" "fmt" "io/ioutil" "log" "math" "reflect" "github.com/ontio/wagon/exec" "github.com/ontio/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, math.MaxUint64) if err != nil { log.Fatalf("could not create wagon vm: %v", err) } GasLimit := uint64(math.MaxUint64) ExecStep := uint64(math.MaxUint64) vm.ExecMetrics = &exec.Gas{GasPrice: 500, GasLimit: &GasLimit, GasFactor: 5, ExecStep: &ExecStep} vm.CallStackDepth = 1000 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/ontio/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 ¶
NewVM creates a new VM from a given module. If the module defines a start function, it will be executed.
func NewVMWithCompiled ¶
func NewVMWithCompiled(module *CompiledModule, memLimit uint64) (*VM, error)
func (*VM) ExecCode ¶
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) GetExportIndex ¶ added in v0.4.2
Source Files ¶
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. |