/
names.go
135 lines (109 loc) · 3.21 KB
/
names.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
131
132
133
134
135
// Copyright (c) 2016 Timo Savola. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package section
import (
"errors"
"math"
"gate.computer/wag/internal"
"gate.computer/wag/internal/loader"
"gate.computer/wag/internal/module"
"import.name/pan"
)
const (
maxFuncNames = 1000000 // Industry standard.
maxLocalNames = 50000 // Industry standard.
)
const CustomName = "name"
const (
nameSubsectionModuleName byte = iota
nameSubsectionFunctionNames
nameSubsectionLocalNames
)
type FuncName struct {
FuncName string
LocalNames []string
}
type NameSection struct {
ModuleName string
FuncNames []FuncName
}
// Load "name" section.
func (ns *NameSection) Load(_ string, r Reader, length uint32) (err error) {
if internal.DontPanic() {
defer func() { err = internal.Error(recover()) }()
}
load, ok := r.(*loader.L)
if !ok {
// Use bogus offsets to avoid possible confusion.
load = loader.New(r, math.MaxUint32)
}
for begin := load.Tell(); ; {
switch pos := load.Tell() - begin; {
case pos == int64(length):
return
case pos > int64(length):
pan.Panic(errors.New("name section content exceeded payload length"))
default:
ns.readSubsection(load)
}
}
}
func (ns *NameSection) readSubsection(load *loader.L) {
id := load.Byte()
contentSize := load.Varuint32()
switch id {
case nameSubsectionModuleName:
ns.ModuleName = load.String(contentSize, "name section: module name")
case nameSubsectionFunctionNames, nameSubsectionLocalNames:
for range load.Span(maxFuncNames, "function name count") {
funcIndex := load.Varuint32()
if funcIndex >= uint32(len(ns.FuncNames)) {
if funcIndex >= maxFuncNames {
pan.Panic(module.Errorf("function name index is too large: %d", funcIndex))
}
buf := make([]FuncName, funcIndex+1)
copy(buf, ns.FuncNames)
ns.FuncNames = buf
}
fn := &ns.FuncNames[funcIndex]
switch id {
case nameSubsectionFunctionNames:
funcNameLen := load.Varuint32()
fn.FuncName = load.String(funcNameLen, "name section: function name")
case nameSubsectionLocalNames:
count := load.Varuint32()
if count > maxLocalNames {
pan.Panic(module.Errorf("local name count is too large: %d", count))
}
fn.LocalNames = make([]string, count)
for range make([]struct{}, count) {
localIndex := load.Varuint32()
if localIndex >= uint32(len(fn.LocalNames)) {
if localIndex >= maxLocalNames {
pan.Panic(module.Errorf("local name index is too large: %d", localIndex))
}
buf := make([]string, localIndex+1)
copy(buf, fn.LocalNames)
fn.LocalNames = buf
}
localNameLen := load.Varuint32()
fn.LocalNames[localIndex] = load.String(localNameLen, "name section: local name")
}
}
}
default:
load.Discard(contentSize)
}
}
type MappedNameSection struct {
NameSection
Mapping ByteRange
}
// Loader of "name" section. Remembers position.
func (ns *MappedNameSection) Loader(sectionMap *Map) func(string, Reader, uint32) error {
return func(sectionName string, r Reader, length uint32) error {
ns.Mapping = sectionMap.Sections[Custom] // The latest one.
return ns.NameSection.Load(sectionName, r, length)
}
}