-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmain.go
130 lines (105 loc) · 3.88 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
package main
import (
"flag"
"fmt"
"io/ioutil"
"path/filepath"
"strconv"
"github.com/SummerCash/ursa/compiler"
"github.com/SummerCash/ursa/vm"
)
// Resolver - define imports for WebAssembly modules
type Resolver struct {
tempRet0 int64
}
var (
sourceFlag = flag.String("source", "", "specify .wasm source file to run") // Init source flag
gasLimitFlag = flag.Int("gas-limit", 1000, "run .wasm with given gas limit") // Init gas limit flag
gasPerInstruction = flag.Int64("gas-per", 1, "run .wasm with given gas policy") // Init gas policy flag
entryFunctionFlag = flag.String("entry", "", "run .wasm from given entry function") // Init entry flag
)
func main() {
flag.Parse() // Parse flags
if sourceFlag == nil || *sourceFlag == "" { // Check for nil .wasm source
panic("no .wasm file provided, exiting") // Panic
}
gasPolicy := &compiler.SimpleGasPolicy{GasPerInstruction: *gasPerInstruction} // Init simple gas policy
sourcePath, err := filepath.Abs(filepath.FromSlash(*sourceFlag)) // Get source path
if err != nil { // Check for errors
panic(err) // Panic
}
wasmSource, err := ioutil.ReadFile(sourcePath) // Read WASM source
if err != nil { // Check for errors
panic(err) // Panic
}
vm, err := vm.NewVirtualMachine(wasmSource, vm.Environment{
EnableJIT: false,
DefaultMemoryPages: 128,
DefaultTableSize: 65536,
}, new(Resolver), gasPolicy) // Init virtual machine
if err != nil { // Check for errors
panic(err) // Panic
}
entryID, ok := vm.GetFunctionExport(*entryFunctionFlag) // Get function ID from entry flag
if !ok { // Check for errors
fmt.Printf("Entry function %s not found; starting from 0.\n", *entryFunctionFlag) // Log fail
entryID = 0 // Set entry ID
}
var args []int64 // Init arg buffer
if len(flag.Args()) != 0 { // Check has non-flag args
for _, arg := range flag.Args() { // Iterate through args
//fmt.Println(arg) // Log arg
if ia, err := strconv.Atoi(arg); err != nil { // Check for possible errors
panic(err) // Panic
} else {
args = append(args, int64(ia)) // Append arg to args buffer
}
}
}
ret, err := vm.RunWithGasLimit(entryID, *gasLimitFlag, args...) // Run with given entry function, params, gas
if err != nil { // Check for errors
vm.PrintStackTrace() // Log stack trace
panic(err) // Panic
}
fmt.Printf("Return Value: %d, Gas Used: %d\n", ret, vm.Gas) // Log successful run
}
// ResolveFunc - define a set of import functions that may be called within a WebAssembly module
func (r *Resolver) ResolveFunc(module, field string) vm.FunctionImport {
//fmt.Printf("Resolve func: %s %s\n", module, field) // Log resolve
switch module { // Handle module types
case "env": // Env module
switch field { // Handle fields
case "__ursa_ping":
return func(vm *vm.VirtualMachine) int64 {
return vm.GetCurrentFrame().Locals[0] + 1
}
case "__ursa_log":
return func(vm *vm.VirtualMachine) int64 {
ptr := int(uint32(vm.GetCurrentFrame().Locals[0]))
msgLen := int(uint32(vm.GetCurrentFrame().Locals[1]))
msg := vm.Memory[ptr : ptr+msgLen]
fmt.Printf("[app] %s\n", string(msg))
return 0
}
default:
panic(fmt.Errorf("unknown field: %s", field)) // Panic
}
default:
panic(fmt.Errorf("unknown module: %s", module)) // Panic
}
}
// ResolveGlobal - define a set of global variables for use within a WebAssembly module
func (r *Resolver) ResolveGlobal(module, field string) int64 {
fmt.Printf("Resolve global: %s %s\n", module, field) // Log resolve global
switch module { // Handle module types
case "env": // Env module
switch field { // Handle fields
case "__ursa_magic":
return 424 // Return magic
default:
panic(fmt.Errorf("unknown field: %s", field)) // Panic
}
default:
panic(fmt.Errorf("unknown module: %s", module)) // Panic
}
}