/
injection.go
92 lines (73 loc) · 2.2 KB
/
injection.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
package wasmgo
import (
//"fmt"
"github.com/eosspark/eos-go/wasmgo/wagon/disasm"
"github.com/eosspark/eos-go/wasmgo/wagon/wasm"
ops "github.com/eosspark/eos-go/wasmgo/wagon/wasm/operators"
)
func Inject(m *wasm.Module) {
//inject checktime
importChecktime := wasm.ImportEntry{ModuleName: "env", FieldName: "checktime", Type: wasm.FuncImport{uint32(GetOrCreateCheckTimeSig(m))}}
m.Import.Entries = append([]wasm.ImportEntry{importChecktime}, m.Import.Entries[0:]...)
for i, f := range m.FunctionIndexSpace {
d, err := disasm.Disassemble(f, m)
if err != nil {
panic(err)
}
injectDisassemble := InjectBody(d)
code, _ := disasm.Assemble(injectDisassemble.Code)
m.FunctionIndexSpace[i].Body.Code = code
}
//shift all exported functions by 1
for k, export := range m.Export.Entries {
export.Index = export.Index + 1
m.Export.Entries[k] = export
}
//update the start function
if m.Start != nil {
m.Start.Index++
}
//shift all table entries for call indirect
if m.Elements != nil {
for i, elememts := range m.Elements.Entries {
for j, _ := range elememts.Elems {
m.Elements.Entries[i].Elems[j]++
}
}
}
}
func InjectBody(d *disasm.Disassembly) *disasm.Disassembly {
//inject checktime
disas := &disasm.Disassembly{MaxDepth: d.MaxDepth}
checkTime := disasm.Instr{
Op: ops.Op{Code: 0x10, Name: "call", Polymorphic: true},
//Immediates: make([]interface{}, 1),
}
checkTime.Immediates = append(checkTime.Immediates, uint32(0))
for _, instr := range d.Code {
switch instr.Op.Code {
case ops.Loop:
disas.Code = append(disas.Code, instr)
disas.Code = append(disas.Code, checkTime)
case ops.Call:
i := instr
i.Immediates = nil
for _, imm := range instr.Immediates {
i.Immediates = append(i.Immediates, imm.(uint32)+1)
}
disas.Code = append(disas.Code, i)
default:
disas.Code = append(disas.Code, instr)
}
}
return disas
}
func GetOrCreateCheckTimeSig(m *wasm.Module) int {
for i, typ := range m.Types.Entries {
if len(typ.ParamTypes) == 0 && len(typ.ReturnTypes) == 0 {
return i
}
}
m.Types.Entries = append(m.Types.Entries, wasm.FunctionSig{0, make([]wasm.ValueType, 0), make([]wasm.ValueType, 0)})
return len(m.Types.Entries) - 1
}