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 return
196 }
197
198
199 func makePclntable(size int64, startLocations []uint32, funcs []_func, maxpc uintptr, pcdataOffs [][]uint32, funcdataAddr uintptr, funcdataOffs [][]uint32) (pclntab []byte) {
200 pclntab = make([]byte, size, size)
201
202
203 offs := 0
204 for i, f := range funcs {
205 byteOrder.PutUint64(pclntab[offs:offs+8], uint64(f.entry))
206 byteOrder.PutUint64(pclntab[offs+8:offs+16], uint64(startLocations[i]))
207 offs += 16
208 }
209
210 byteOrder.PutUint64(pclntab[offs:offs+8], uint64(maxpc))
211 offs += 8
212
213
214 for i, f := range funcs {
215 off := startLocations[i]
216
217
218 byteOrder.PutUint64(pclntab[off:off+8], uint64(f.entry))
219 off += 8
220 byteOrder.PutUint32(pclntab[off:off+4], uint32(f.nameOff))
221 off += 4
222 byteOrder.PutUint32(pclntab[off:off+4], uint32(f.args))
223 off += 4
224 byteOrder.PutUint32(pclntab[off:off+4], uint32(f.deferreturn))
225 off += 4
226 byteOrder.PutUint32(pclntab[off:off+4], uint32(f.pcsp))
227 off += 4
228 byteOrder.PutUint32(pclntab[off:off+4], uint32(f.pcfile))
229 off += 4
230 byteOrder.PutUint32(pclntab[off:off+4], uint32(f.pcln))
231 off += 4
232 byteOrder.PutUint32(pclntab[off:off+4], uint32(f.npcdata))
233 off += 4
234 byteOrder.PutUint32(pclntab[off:off+4], uint32(f.cuOffset))
235 off += 4
236 pclntab[off] = f.funcID
237
238 off += 3
239 pclntab[off] = f.nfuncdata
240 off += 1
241
242
243 for j := 3; j < len(pcdataOffs[i]); j++ {
244 byteOrder.PutUint32(pclntab[off:off+4], uint32(pcdataOffs[i][j]))
245 off += 4
246 }
247
248 off = uint32(rnd(int64(off), int64(_PtrSize)))
249
250
251 for _, funcdata := range funcdataOffs[i] {
252 if funcdata == _INVALID_FUNCDATA_OFFSET {
253 byteOrder.PutUint64(pclntab[off:off+8], 0)
254 } else {
255 byteOrder.PutUint64(pclntab[off:off+8], uint64(funcdataAddr)+uint64(funcdata))
256 }
257 off += 8
258 }
259 }
260
261 return
262 }
263
264
265
266
267
268
269
270
271 func writeFindfunctab(out *[]byte, ftab []funcTab) (start int) {
272 start = len(*out)
273
274 max := ftab[len(ftab)-1].entry
275 min := ftab[0].entry
276 nbuckets := (max - min + _BUCKETSIZE - 1) / _BUCKETSIZE
277 n := (max - min + _SUB_BUCKETSIZE - 1) / _SUB_BUCKETSIZE
278
279 tab := make([]findfuncbucket, 0, nbuckets)
280 var s, e = 0, 0
281 for i := 0; i<int(nbuckets); i++ {
282
283 var fb = findfuncbucket{idx: uint32(s)}
284
285
286 var pc = min + uintptr((i+1)*_BUCKETSIZE)
287 for ; e < len(ftab)-1 && ftab[e+1].entry <= pc; e++ {}
288
289 for j := 0; j<_SUBBUCKETS && (i*_SUBBUCKETS+j)<int(n); j++ {
290
291 fb._SUBBUCKETS[j] = byte(uint32(s) - fb.idx)
292
293
294 pc = min + uintptr(i*_BUCKETSIZE) + uintptr((j+1)*_SUB_BUCKETSIZE)
295 for ; s < len(ftab)-1 && ftab[s+1].entry <= pc; s++ {}
296 }
297
298 s = e
299 tab = append(tab, fb)
300 }
301
302
303 if len(tab) > 0 {
304 size := int(unsafe.Sizeof(findfuncbucket{}))*len(tab)
305 *out = append(*out, rt.BytesFrom(unsafe.Pointer(&tab[0]), size, size)...)
306 }
307 return
308 }
309
310 func makeModuledata(name string, filenames []string, funcsp *[]Func, text []byte) (mod *moduledata) {
311 mod = new(moduledata)
312 mod.modulename = name
313
314
315 funcs := *funcsp
316 sort.Slice(funcs, func(i, j int) bool {
317 return funcs[i].EntryOff < funcs[j].EntryOff
318 })
319 *funcsp = funcs
320
321
322 cu := make([]string, 0, len(filenames))
323 cu = append(cu, filenames...)
324 cutab, filetab, cuOffs := makeFilenametab([]compilationUnit{{cu}})
325 mod.cutab = cutab
326 mod.filetab = filetab
327
328
329 funcnametab, nameOffs := makeFuncnameTab(funcs)
330 mod.funcnametab = funcnametab
331
332
333 p := os.Getpagesize()
334 size := int(rnd(int64(len(text)), int64(p)))
335 addr := mmap(size)
336
337 s := rt.BytesFrom(unsafe.Pointer(addr), len(text), size)
338 copy(s, text)
339
340 mprotect(addr, size)
341
342
343 mod.text = addr
344 mod.etext = addr + uintptr(size)
345 mod.minpc = addr
346 mod.maxpc = addr + uintptr(len(text))
347
348
349
350 cuOff := cuOffs[0]
351 pctab, pcdataOffs, _funcs := makePctab(funcs, addr, cuOff, nameOffs)
352 mod.pctab = pctab
353
354
355
356
357 cache := make([]byte, 0, len(funcs)*int(_PtrSize))
358 fstart, funcdataOffs := writeFuncdata(&cache, funcs)
359
360
361 ftab, pclntSize, startLocations := makeFtab(_funcs, mod.maxpc)
362 mod.ftab = ftab
363
364
365 ffstart := writeFindfunctab(&cache, ftab)
366
367
368 moduleCache.Lock()
369 moduleCache.m[mod] = cache
370 moduleCache.Unlock()
371 mod.findfunctab = uintptr(rt.IndexByte(cache, ffstart))
372 funcdataAddr := uintptr(rt.IndexByte(cache, fstart))
373
374
375 pclntab := makePclntable(pclntSize, startLocations, _funcs, mod.maxpc, pcdataOffs, funcdataAddr, funcdataOffs)
376 mod.pclntable = pclntab
377
378
379 mod.pcHeader = &pcHeader {
380 magic : _Magic,
381 minLC : _MinLC,
382 ptrSize : _PtrSize,
383 nfunc : len(funcs),
384 nfiles: uint(len(cu)),
385 funcnameOffset: getOffsetOf(moduledata{}, "funcnametab"),
386 cuOffset: getOffsetOf(moduledata{}, "cutab"),
387 filetabOffset: getOffsetOf(moduledata{}, "filetab"),
388 pctabOffset: getOffsetOf(moduledata{}, "pctab"),
389 pclnOffset: getOffsetOf(moduledata{}, "pclntable"),
390 }
391
392
393 mod.gcdata = uintptr(unsafe.Pointer(&emptyByte))
394 mod.gcbss = uintptr(unsafe.Pointer(&emptyByte))
395
396 return
397 }
398
399
400
401 func makePctab(funcs []Func, addr uintptr, cuOffset uint32, nameOffset []int32) (pctab []byte, pcdataOffs [][]uint32, _funcs []_func) {
402 _funcs = make([]_func, len(funcs))
403
404
405
406
407 pctab = make([]byte, 1, 12*len(funcs)+1)
408 pcdataOffs = make([][]uint32, len(funcs))
409
410 for i, f := range funcs {
411 _f := &_funcs[i]
412
413 var writer = func(pc *Pcdata) {
414 var ab []byte
415 var err error
416 if pc != nil {
417 ab, err = pc.MarshalBinary()
418 if err != nil {
419 panic(err)
420 }
421 pcdataOffs[i] = append(pcdataOffs[i], uint32(len(pctab)))
422 } else {
423 ab = []byte{0}
424 pcdataOffs[i] = append(pcdataOffs[i], _PCDATA_INVALID_OFFSET)
425 }
426 pctab = append(pctab, ab...)
427 }
428
429 if f.Pcsp != nil {
430 _f.pcsp = uint32(len(pctab))
431 }
432 writer(f.Pcsp)
433 if f.Pcfile != nil {
434 _f.pcfile = uint32(len(pctab))
435 }
436 writer(f.Pcfile)
437 if f.Pcline != nil {
438 _f.pcln = uint32(len(pctab))
439 }
440 writer(f.Pcline)
441 writer(f.PcUnsafePoint)
442 writer(f.PcStackMapIndex)
443 writer(f.PcInlTreeIndex)
444 writer(f.PcArgLiveIndex)
445
446 _f.entry = addr + uintptr(f.EntryOff)
447 _f.nameOff = nameOffset[i]
448 _f.args = f.ArgsSize
449 _f.deferreturn = f.DeferReturn
450
451 _f.npcdata = uint32(_N_PCDATA)
452 _f.cuOffset = cuOffset
453 _f.funcID = f.ID
454 _f.nfuncdata = uint8(_N_FUNCDATA)
455 }
456
457 return
458 }
459
460 func registerFunction(name string, pc uintptr, textSize uintptr, fp int, args int, size uintptr, argptrs uintptr, localptrs uintptr) {}
461
View as plain text