forked from tetratelabs/wazero
-
Notifications
You must be signed in to change notification settings - Fork 0
/
proxy.go
99 lines (86 loc) · 3.74 KB
/
proxy.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
package proxy
import (
"github.com/tetratelabs/wazero"
"github.com/tetratelabs/wazero/api"
"github.com/tetratelabs/wazero/experimental"
"github.com/tetratelabs/wazero/experimental/logging"
"github.com/tetratelabs/wazero/internal/leb128"
"github.com/tetratelabs/wazero/internal/testing/binaryencoding"
"github.com/tetratelabs/wazero/internal/wasm"
)
const proxyModuleName = "internal/testing/proxy/proxy.go"
// NewLoggingListenerFactory is like logging.NewHostLoggingListenerFactory,
// except it skips logging proxying functions from NewModuleBinary.
func NewLoggingListenerFactory(writer logging.Writer, scopes logging.LogScopes) experimental.FunctionListenerFactory {
return &loggingListenerFactory{logging.NewHostLoggingListenerFactory(writer, scopes)}
}
type loggingListenerFactory struct {
delegate experimental.FunctionListenerFactory
}
// NewFunctionListener implements the same method as documented on
// experimental.FunctionListener.
func (f *loggingListenerFactory) NewFunctionListener(fnd api.FunctionDefinition) experimental.FunctionListener {
if fnd.ModuleName() == proxyModuleName {
return nil // don't log proxy stuff
}
return f.delegate.NewFunctionListener(fnd)
}
// NewModuleBinary creates the proxy module to proxy a function call against
// all the exported functions in `proxyTarget`, and returns its encoded binary.
// The resulting module exports the proxy functions whose names are exactly the same
// as the proxy destination.
//
// This is used to test host call implementations. If logging, use
// NewLoggingListenerFactory to avoid messages from the proxying module.
func NewModuleBinary(moduleName string, proxyTarget wazero.CompiledModule) []byte {
funcDefs := proxyTarget.ExportedFunctions()
funcNum := uint32(len(funcDefs))
proxyModule := &wasm.Module{
MemorySection: &wasm.Memory{Min: 1},
ExportSection: []wasm.Export{{Name: "memory", Type: api.ExternTypeMemory}},
NameSection: &wasm.NameSection{ModuleName: proxyModuleName},
}
var cnt wasm.Index
for _, def := range funcDefs {
proxyModule.TypeSection = append(proxyModule.TypeSection, wasm.FunctionType{
Params: def.ParamTypes(), Results: def.ResultTypes(),
})
// Imports the function.
name := def.ExportNames()[0]
proxyModule.ImportSection = append(proxyModule.ImportSection, wasm.Import{
Module: moduleName,
Name: name,
DescFunc: cnt,
})
// Ensures that type of the proxy function matches the imported function.
proxyModule.FunctionSection = append(proxyModule.FunctionSection, cnt)
// Build the function body of the proxy function.
var body []byte
for i := range def.ParamTypes() {
body = append(body, wasm.OpcodeLocalGet)
body = append(body, leb128.EncodeUint32(uint32(i))...)
}
body = append(body, wasm.OpcodeCall)
body = append(body, leb128.EncodeUint32(cnt)...)
body = append(body, wasm.OpcodeEnd)
proxyModule.CodeSection = append(proxyModule.CodeSection, wasm.Code{Body: body})
proxyFuncIndex := cnt + funcNum
// Assigns the same params name as the imported one.
paramNames := wasm.NameMapAssoc{Index: proxyFuncIndex}
for i, n := range def.ParamNames() {
paramNames.NameMap = append(paramNames.NameMap, wasm.NameAssoc{Index: wasm.Index(i), Name: n})
}
proxyModule.NameSection.LocalNames = append(proxyModule.NameSection.LocalNames, paramNames)
// Plus, assigns the same function name.
proxyModule.NameSection.FunctionNames = append(proxyModule.NameSection.FunctionNames,
wasm.NameAssoc{Index: proxyFuncIndex, Name: name})
// Finally, exports the proxy function with the same name as the imported one.
proxyModule.ExportSection = append(proxyModule.ExportSection, wasm.Export{
Type: wasm.ExternTypeFunc,
Name: name,
Index: proxyFuncIndex,
})
cnt++
}
return binaryencoding.EncodeModule(proxyModule)
}