1
2
3
4
19
20 package loader
21
22 import (
23 `os`
24 `unsafe`
25 `sort`
26
27 `github.com/bytedance/sonic/internal/rt`
28 )
29
30 const (
31 _Magic uint32 = 0xfffffffa
32 )
33
34 type pcHeader struct {
35 magic uint32
36 pad1, pad2 uint8
37 minLC uint8
38 ptrSize uint8
39 nfunc int
40 nfiles uint
41 funcnameOffset uintptr
42 cuOffset uintptr
43 filetabOffset uintptr
44 pctabOffset uintptr
45 pclnOffset uintptr
46 }
47
48 type moduledata struct {
49 pcHeader *pcHeader
50 funcnametab []byte
51 cutab []uint32
52 filetab []byte
53 pctab []byte
54 pclntable []byte
55 ftab []funcTab
56 findfunctab uintptr
57 minpc, maxpc uintptr
58
59 text, etext uintptr
60 noptrdata, enoptrdata uintptr
61 data, edata uintptr
62 bss, ebss uintptr
63 noptrbss, enoptrbss uintptr
64 end, gcdata, gcbss uintptr
65 types, etypes uintptr
66
67 textsectmap []textSection
68 typelinks []int32
69 itablinks []*rt.GoItab
70
71 ptab []ptabEntry
72
73 pluginpath string
74 pkghashes []modulehash
75
76 modulename string
77 modulehashes []modulehash
78
79 hasmain uint8
80
81 gcdatamask, gcbssmask bitVector
82
83 typemap map[int32]*rt.GoType
84
85 bad bool
86
87 next *moduledata
88 }
89
90 type _func struct {
91 entry uintptr
92 nameOff int32
93
94 args int32
95 deferreturn uint32
96
97 pcsp uint32
98 pcfile uint32
99 pcln uint32
100 npcdata uint32
101 cuOffset uint32
102 funcID uint8
103 _ [2]byte
104 nfuncdata uint8
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 type funcTab struct {
130 entry uintptr
131 funcoff uintptr
132 }
133
134 type bitVector struct {
135 n int32
136 bytedata *uint8
137 }
138
139 type ptabEntry struct {
140 name int32
141 typ int32
142 }
143
144 type textSection struct {
145 vaddr uintptr
146 end uintptr
147 baseaddr uintptr
148 }
149
150 type modulehash struct {
151 modulename string
152 linktimehash string
153 runtimehash *string
154 }
155
156
157
158
159
160
161
162
163
164 type findfuncbucket struct {
165 idx uint32
166 _SUBBUCKETS [16]byte
167 }
168
169
170 type compilationUnit struct {
171 fileNames []string
172 }
173
174 func makeFtab(funcs []_func, maxpc uintptr) (ftab []funcTab, pclntabSize int64, startLocations []uint32) {
175
176
177
178 pclntabSize = int64(len(funcs)*2*int(_PtrSize) + int(_PtrSize))
179 startLocations = make([]uint32, len(funcs))
180 for i, f := range funcs {
181 pclntabSize = rnd(pclntabSize, int64(_PtrSize))
182
183 startLocations[i] = uint32(pclntabSize)
184 pclntabSize += int64(uint8(_FUNC_SIZE) + f.nfuncdata*_PtrSize + uint8(f.npcdata)*4)
185 }
186 ftab = make([]funcTab, 0, len(funcs)+1)
187
188
189 for i, f := range funcs {
190 ftab = append(ftab, funcTab{uintptr(f.entry), uintptr(startLocations[i])})
191 }
192
193
194 ftab = append(ftab, funcTab{maxpc, 0})
195
196 return
197 }
198
199
200 func makePclntable(size int64, startLocations []uint32, funcs []_func, maxpc uintptr, pcdataOffs [][]uint32, funcdataAddr uintptr, funcdataOffs [][]uint32) (pclntab []byte) {
201 pclntab = make([]byte, size, size)
202
203
204 offs := 0
205 for i, f := range funcs {
206 byteOrder.PutUint64(pclntab[offs:offs+8], uint64(f.entry))
207 byteOrder.PutUint64(pclntab[offs+8:offs+16], uint64(startLocations[i]))
208 offs += 16
209 }
210
211 byteOrder.PutUint64(pclntab[offs:offs+8], uint64(maxpc))
212 offs += 8
213
214
215 for i, f := range funcs {
216 off := startLocations[i]
217
218
219 byteOrder.PutUint64(pclntab[off:off+8], uint64(f.entry))
220 off += 8
221 byteOrder.PutUint32(pclntab[off:off+4], uint32(f.nameOff))
222 off += 4
223 byteOrder.PutUint32(pclntab[off:off+4], uint32(f.args))
224 off += 4
225 byteOrder.PutUint32(pclntab[off:off+4], uint32(f.deferreturn))
226 off += 4
227 byteOrder.PutUint32(pclntab[off:off+4], uint32(f.pcsp))
228 off += 4
229 byteOrder.PutUint32(pclntab[off:off+4], uint32(f.pcfile))
230 off += 4
231 byteOrder.PutUint32(pclntab[off:off+4], uint32(f.pcln))
232 off += 4
233 byteOrder.PutUint32(pclntab[off:off+4], uint32(f.npcdata))
234 off += 4
235 byteOrder.PutUint32(pclntab[off:off+4], uint32(f.cuOffset))
236 off += 4
237 pclntab[off] = f.funcID
238
239 off += 3
240 pclntab[off] = f.nfuncdata
241 off += 1
242
243
244 for j := 3; j < len(pcdataOffs[i]); j++ {
245 byteOrder.PutUint32(pclntab[off:off+4], uint32(pcdataOffs[i][j]))
246 off += 4
247 }
248
249 off = uint32(rnd(int64(off), int64(_PtrSize)))
250
251
252 for _, funcdata := range funcdataOffs[i] {
253 if funcdata == _INVALID_FUNCDATA_OFFSET {
254 byteOrder.PutUint64(pclntab[off:off+8], 0)
255 } else {
256 byteOrder.PutUint64(pclntab[off:off+8], uint64(funcdataAddr)+uint64(funcdata))
257 }
258 off += 8
259 }
260 }
261
262 return
263 }
264
265
266
267
268
269
270
271
272 func writeFindfunctab(out *[]byte, ftab []funcTab) (start int) {
273 start = len(*out)
274
275 max := ftab[len(ftab)-1].entry
276 min := ftab[0].entry
277 nbuckets := (max - min + _BUCKETSIZE - 1) / _BUCKETSIZE
278 n := (max - min + _SUB_BUCKETSIZE - 1) / _SUB_BUCKETSIZE
279
280 tab := make([]findfuncbucket, 0, nbuckets)
281 var s, e = 0, 0
282 for i := 0; i<int(nbuckets); i++ {
283
284 var fb = findfuncbucket{idx: uint32(s)}
285
286
287 var pc = min + uintptr((i+1)*_BUCKETSIZE)
288 for ; e < len(ftab)-1 && ftab[e+1].entry <= pc; e++ {}
289
290 for j := 0; j<_SUBBUCKETS && (i*_SUBBUCKETS+j)<int(n); j++ {
291
292 fb._SUBBUCKETS[j] = byte(uint32(s) - fb.idx)
293
294
295 pc = min + uintptr(i*_BUCKETSIZE) + uintptr((j+1)*_SUB_BUCKETSIZE)
296 for ; s < len(ftab)-1 && ftab[s+1].entry <= pc; s++ {}
297 }
298
299 s = e
300 tab = append(tab, fb)
301 }
302
303
304 if len(tab) > 0 {
305 size := int(unsafe.Sizeof(findfuncbucket{}))*len(tab)
306 *out = append(*out, rt.BytesFrom(unsafe.Pointer(&tab[0]), size, size)...)
307 }
308 return
309 }
310
311 func makeModuledata(name string, filenames []string, funcsp *[]Func, text []byte) (mod *moduledata) {
312 mod = new(moduledata)
313 mod.modulename = name
314
315
316 funcs := *funcsp
317 sort.Slice(funcs, func(i, j int) bool {
318 return funcs[i].EntryOff < funcs[j].EntryOff
319 })
320 *funcsp = funcs
321
322
323 cu := make([]string, 0, len(filenames))
324 cu = append(cu, filenames...)
325 cutab, filetab, cuOffs := makeFilenametab([]compilationUnit{{cu}})
326 mod.cutab = cutab
327 mod.filetab = filetab
328
329
330 funcnametab, nameOffs := makeFuncnameTab(funcs)
331 mod.funcnametab = funcnametab
332
333
334 p := os.Getpagesize()
335 size := int(rnd(int64(len(text)), int64(p)))
336 addr := mmap(size)
337
338 s := rt.BytesFrom(unsafe.Pointer(addr), len(text), size)
339 copy(s, text)
340
341 mprotect(addr, size)
342
343
344 mod.text = addr
345 mod.etext = addr + uintptr(size)
346 mod.minpc = addr
347 mod.maxpc = addr + uintptr(len(text))
348
349
350
351 cuOff := cuOffs[0]
352 pctab, pcdataOffs, _funcs := makePctab(funcs, addr, cuOff, nameOffs)
353 mod.pctab = pctab
354
355
356
357
358 cache := make([]byte, 0, len(funcs)*int(_PtrSize))
359 fstart, funcdataOffs := writeFuncdata(&cache, funcs)
360
361
362 ftab, pclntSize, startLocations := makeFtab(_funcs, mod.maxpc)
363 mod.ftab = ftab
364
365
366 ffstart := writeFindfunctab(&cache, ftab)
367
368
369 moduleCache.Lock()
370 moduleCache.m[mod] = cache
371 moduleCache.Unlock()
372 mod.findfunctab = uintptr(rt.IndexByte(cache, ffstart))
373 funcdataAddr := uintptr(rt.IndexByte(cache, fstart))
374
375
376 pclntab := makePclntable(pclntSize, startLocations, _funcs, mod.maxpc, pcdataOffs, funcdataAddr, funcdataOffs)
377 mod.pclntable = pclntab
378
379
380 mod.pcHeader = &pcHeader {
381 magic : _Magic,
382 minLC : _MinLC,
383 ptrSize : _PtrSize,
384 nfunc : len(funcs),
385 nfiles: uint(len(cu)),
386 funcnameOffset: getOffsetOf(moduledata{}, "funcnametab"),
387 cuOffset: getOffsetOf(moduledata{}, "cutab"),
388 filetabOffset: getOffsetOf(moduledata{}, "filetab"),
389 pctabOffset: getOffsetOf(moduledata{}, "pctab"),
390 pclnOffset: getOffsetOf(moduledata{}, "pclntable"),
391 }
392
393
394 mod.gcdata = uintptr(unsafe.Pointer(&emptyByte))
395 mod.gcbss = uintptr(unsafe.Pointer(&emptyByte))
396
397 return
398 }
399
400
401
402 func makePctab(funcs []Func, addr uintptr, cuOffset uint32, nameOffset []int32) (pctab []byte, pcdataOffs [][]uint32, _funcs []_func) {
403 _funcs = make([]_func, len(funcs))
404
405
406
407
408 pctab = make([]byte, 1, 12*len(funcs)+1)
409 pcdataOffs = make([][]uint32, len(funcs))
410
411 for i, f := range funcs {
412 _f := &_funcs[i]
413
414 var writer = func(pc *Pcdata) {
415 var ab []byte
416 var err error
417 if pc != nil {
418 ab, err = pc.MarshalBinary()
419 if err != nil {
420 panic(err)
421 }
422 pcdataOffs[i] = append(pcdataOffs[i], uint32(len(pctab)))
423 } else {
424 ab = []byte{0}
425 pcdataOffs[i] = append(pcdataOffs[i], _PCDATA_INVALID_OFFSET)
426 }
427 pctab = append(pctab, ab...)
428 }
429
430 if f.Pcsp != nil {
431 _f.pcsp = uint32(len(pctab))
432 }
433 writer(f.Pcsp)
434 if f.Pcfile != nil {
435 _f.pcfile = uint32(len(pctab))
436 }
437 writer(f.Pcfile)
438 if f.Pcline != nil {
439 _f.pcln = uint32(len(pctab))
440 }
441 writer(f.Pcline)
442 writer(f.PcUnsafePoint)
443 writer(f.PcStackMapIndex)
444 writer(f.PcInlTreeIndex)
445 writer(f.PcArgLiveIndex)
446
447 _f.entry = addr + uintptr(f.EntryOff)
448 _f.nameOff = nameOffset[i]
449 _f.args = f.ArgsSize
450 _f.deferreturn = f.DeferReturn
451
452 _f.npcdata = uint32(_N_PCDATA)
453 _f.cuOffset = cuOffset
454 _f.funcID = f.ID
455 _f.nfuncdata = uint8(_N_FUNCDATA)
456 }
457
458 return
459 }
460
461 func registerFunction(name string, pc uintptr, textSize uintptr, fp int, args int, size uintptr, argptrs uintptr, localptrs uintptr) {}
462
View as plain text