...
1 package experimental_test
2
3 import (
4 "context"
5 _ "embed"
6 "fmt"
7 "log"
8 "sort"
9
10 "github.com/tetratelabs/wazero"
11 "github.com/tetratelabs/wazero/api"
12 "github.com/tetratelabs/wazero/experimental"
13 "github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1"
14 "github.com/tetratelabs/wazero/internal/wasm"
15 )
16
17
18
19
20
21
22 var listenerWasm []byte
23
24
25 type uniqGoFuncs map[string]struct{}
26
27
28 func (u uniqGoFuncs) callees() []string {
29 ret := make([]string, 0, len(u))
30 for k := range u {
31 ret = append(ret, k)
32 }
33
34 sort.Strings(ret)
35 return ret
36 }
37
38
39 func (u uniqGoFuncs) NewFunctionListener(def api.FunctionDefinition) experimental.FunctionListener {
40 if def.GoFunction() == nil {
41 return nil
42 }
43 return u
44 }
45
46
47 func (u uniqGoFuncs) Before(ctx context.Context, _ api.Module, def api.FunctionDefinition, _ []uint64, _ experimental.StackIterator) {
48 u[def.DebugName()] = struct{}{}
49 }
50
51
52 func (u uniqGoFuncs) After(context.Context, api.Module, api.FunctionDefinition, []uint64) {}
53
54
55 func (u uniqGoFuncs) Abort(context.Context, api.Module, api.FunctionDefinition, error) {}
56
57
58 func Example_customListenerFactory() {
59 u := uniqGoFuncs{}
60
61
62 ctx := context.WithValue(context.Background(), experimental.FunctionListenerFactoryKey{}, u)
63
64 r := wazero.NewRuntime(ctx)
65 defer r.Close(ctx)
66
67 wasi_snapshot_preview1.MustInstantiate(ctx, r)
68
69 mod, err := r.Instantiate(ctx, listenerWasm)
70 if err != nil {
71 log.Panicln(err)
72 }
73
74 for i := 0; i < 5; i++ {
75 if _, err = mod.ExportedFunction("rand").Call(ctx, 4); err != nil {
76 log.Panicln(err)
77 }
78 }
79
80
81 for _, f := range u.callees() {
82 fmt.Println(f)
83 }
84
85
86
87
88 }
89
90 func Example_stackIterator() {
91 it := &fakeStackIterator{}
92
93 for it.Next() {
94 fn := it.Function()
95 pc := it.ProgramCounter()
96 fmt.Println("function:", fn.Definition().DebugName())
97 fmt.Println("\tprogram counter:", pc)
98 fmt.Println("\tsource offset:", fn.SourceOffsetForPC(pc))
99 }
100
101
102
103
104
105
106
107
108
109
110
111 }
112
113 type fakeStackIterator struct {
114 iteration int
115 def api.FunctionDefinition
116 args []uint64
117 pc uint64
118 sourceOffset uint64
119 }
120
121 func (s *fakeStackIterator) Next() bool {
122 switch s.iteration {
123 case 0:
124 s.def = &mockFunctionDefinition{debugName: "fn0"}
125 s.args = []uint64{1, 2, 3}
126 s.pc = 5890831
127 s.sourceOffset = 1234
128 case 1:
129 s.def = &mockFunctionDefinition{debugName: "fn1"}
130 s.args = []uint64{}
131 s.pc = 5899822
132 s.sourceOffset = 7286
133 case 2:
134 s.def = &mockFunctionDefinition{debugName: "fn2"}
135 s.args = []uint64{4}
136 s.pc = 6820312
137 s.sourceOffset = 935891
138 case 3:
139 return false
140 }
141 s.iteration++
142 return true
143 }
144
145 func (s *fakeStackIterator) Function() experimental.InternalFunction {
146 return internalFunction{
147 definition: s.def,
148 sourceOffset: s.sourceOffset,
149 }
150 }
151
152 func (s *fakeStackIterator) ProgramCounter() experimental.ProgramCounter {
153 return experimental.ProgramCounter(s.pc)
154 }
155
156 var _ experimental.StackIterator = &fakeStackIterator{}
157
158 type internalFunction struct {
159 definition api.FunctionDefinition
160 sourceOffset uint64
161 }
162
163 func (f internalFunction) Definition() api.FunctionDefinition {
164 return f.definition
165 }
166
167 func (f internalFunction) SourceOffsetForPC(pc experimental.ProgramCounter) uint64 {
168 return f.sourceOffset
169 }
170
171 type mockFunctionDefinition struct {
172 debugName string
173 *wasm.FunctionDefinition
174 }
175
176 func (f *mockFunctionDefinition) DebugName() string {
177 return f.debugName
178 }
179
180 func (f *mockFunctionDefinition) ParamTypes() []wasm.ValueType {
181 return []wasm.ValueType{}
182 }
183
184 func (f *mockFunctionDefinition) ResultTypes() []wasm.ValueType {
185 return []wasm.ValueType{}
186 }
187
View as plain text