...
1
16
17 package loader
18
19 import (
20 `encoding`
21 `encoding/binary`
22 `fmt`
23 `reflect`
24 `strings`
25 `sync`
26 `unsafe`
27 )
28
29 const (
30 _MinLC uint8 = 1
31 _PtrSize uint8 = 8
32 )
33
34 const (
35 _N_FUNCDATA = 8
36 _INVALID_FUNCDATA_OFFSET = ^uint32(0)
37 _FUNC_SIZE = unsafe.Sizeof(_func{})
38
39 _MINFUNC = 16
40 _BUCKETSIZE = 256 * _MINFUNC
41 _SUBBUCKETS = 16
42 _SUB_BUCKETSIZE = _BUCKETSIZE / _SUBBUCKETS
43 )
44
45
46 const (
47 FuncFlag_TOPFRAME = 1 << iota
48 FuncFlag_SPWRITE
49 FuncFlag_ASM
50 )
51
52
53
54
55 const (
56 _FUNCDATA_ArgsPointerMaps = 0
57 _FUNCDATA_LocalsPointerMaps = 1
58 _FUNCDATA_StackObjects = 2
59 _FUNCDATA_InlTree = 3
60 _FUNCDATA_OpenCodedDeferInfo = 4
61 _FUNCDATA_ArgInfo = 5
62 _FUNCDATA_ArgLiveInfo = 6
63 _FUNCDATA_WrapInfo = 7
64
65
66
67
68
69 ArgsSizeUnknown = -0x80000000
70 )
71
72
73 var moduleCache = struct {
74 m map[*moduledata][]byte
75 sync.Mutex
76 }{
77 m: make(map[*moduledata][]byte),
78 }
79
80
81 type Func struct {
82 ID uint8
83 Flag uint8
84 ArgsSize int32
85 EntryOff uint32
86 TextSize uint32
87 DeferReturn uint32
88 FileIndex uint32
89 Name string
90
91
92 Pcsp *Pcdata
93 Pcfile *Pcdata
94 Pcline *Pcdata
95 PcUnsafePoint *Pcdata
96 PcStackMapIndex *Pcdata
97 PcInlTreeIndex *Pcdata
98 PcArgLiveIndex *Pcdata
99
100
101 ArgsPointerMaps encoding.BinaryMarshaler
102 LocalsPointerMaps encoding.BinaryMarshaler
103 StackObjects encoding.BinaryMarshaler
104 InlTree encoding.BinaryMarshaler
105 OpenCodedDeferInfo encoding.BinaryMarshaler
106 ArgInfo encoding.BinaryMarshaler
107 ArgLiveInfo encoding.BinaryMarshaler
108 WrapInfo encoding.BinaryMarshaler
109 }
110
111 func getOffsetOf(data interface{}, field string) uintptr {
112 t := reflect.TypeOf(data)
113 fv, ok := t.FieldByName(field)
114 if !ok {
115 panic(fmt.Sprintf("field %s not found in struct %s", field, t.Name()))
116 }
117 return fv.Offset
118 }
119
120 func rnd(v int64, r int64) int64 {
121 if r <= 0 {
122 return v
123 }
124 v += r - 1
125 c := v % r
126 if c < 0 {
127 c += r
128 }
129 v -= c
130 return v
131 }
132
133 var (
134 byteOrder binary.ByteOrder = binary.LittleEndian
135 )
136
137 func funcNameParts(name string) (string, string, string) {
138 i := strings.IndexByte(name, '[')
139 if i < 0 {
140 return name, "", ""
141 }
142
143 j := len(name) - 1
144 for j > i && name[j] != ']' {
145 j--
146 }
147 if j <= i {
148 return name, "", ""
149 }
150 return name[:i], "[...]", name[j+1:]
151 }
152
153
154
155
156
157
158 func makeFuncnameTab(funcs []Func) (tab []byte, offs []int32) {
159 offs = make([]int32, len(funcs))
160 offset := 1
161 tab = []byte{0}
162
163 for i, f := range funcs {
164 offs[i] = int32(offset)
165
166 a, b, c := funcNameParts(f.Name)
167 tab = append(tab, a...)
168 tab = append(tab, b...)
169 tab = append(tab, c...)
170 tab = append(tab, 0)
171 offset += len(a) + len(b) + len(c) + 1
172 }
173
174 return
175 }
176
177
178
179
180
181
182
183
184
185
186
187
188 func makeFilenametab(cus []compilationUnit) (cutab []uint32, filetab []byte, cuOffsets []uint32) {
189 cuOffsets = make([]uint32, len(cus))
190 cuOffset := 0
191 fileOffset := 0
192
193 for i, cu := range cus {
194 cuOffsets[i] = uint32(cuOffset)
195
196 for _, name := range cu.fileNames {
197 cutab = append(cutab, uint32(fileOffset))
198
199 fileOffset += len(name) + 1
200 filetab = append(filetab, name...)
201 filetab = append(filetab, 0)
202 }
203
204 cuOffset += len(cu.fileNames)
205 }
206
207 return
208 }
209
210 func writeFuncdata(out *[]byte, funcs []Func) (fstart int, funcdataOffs [][]uint32) {
211 fstart = len(*out)
212 *out = append(*out, byte(0))
213 offs := uint32(1)
214
215 funcdataOffs = make([][]uint32, len(funcs))
216 for i, f := range funcs {
217
218 var writer = func(fd encoding.BinaryMarshaler) {
219 var ab []byte
220 var err error
221 if fd != nil {
222 ab, err = fd.MarshalBinary()
223 if err != nil {
224 panic(err)
225 }
226 funcdataOffs[i] = append(funcdataOffs[i], offs)
227 } else {
228 ab = []byte{0}
229 funcdataOffs[i] = append(funcdataOffs[i], _INVALID_FUNCDATA_OFFSET)
230 }
231 *out = append(*out, ab...)
232 offs += uint32(len(ab))
233 }
234
235 writer(f.ArgsPointerMaps)
236 writer(f.LocalsPointerMaps)
237 writer(f.StackObjects)
238 writer(f.InlTree)
239 writer(f.OpenCodedDeferInfo)
240 writer(f.ArgInfo)
241 writer(f.ArgLiveInfo)
242 writer(f.WrapInfo)
243 }
244 return
245 }
246
View as plain text