1
2
3
4
19
20 package loader
21
22 import (
23 `os`
24 `sort`
25 `unsafe`
26
27 `github.com/bytedance/sonic/internal/rt`
28 )
29
30 type funcTab struct {
31 entry uint32
32 funcoff uint32
33 }
34
35 type pcHeader struct {
36 magic uint32
37 pad1, pad2 uint8
38 minLC uint8
39 ptrSize uint8
40 nfunc int
41 nfiles uint
42 textStart uintptr
43 funcnameOffset uintptr
44 cuOffset uintptr
45 filetabOffset uintptr
46 pctabOffset uintptr
47 pclnOffset uintptr
48 }
49
50 type bitVector struct {
51 n int32
52 bytedata *uint8
53 }
54
55 type ptabEntry struct {
56 name int32
57 typ int32
58 }
59
60 type textSection struct {
61 vaddr uintptr
62 end uintptr
63 baseaddr uintptr
64 }
65
66 type modulehash struct {
67 modulename string
68 linktimehash string
69 runtimehash *string
70 }
71
72
73
74
75
76
77
78
79
80 type findfuncbucket struct {
81 idx uint32
82 _SUBBUCKETS [16]byte
83 }
84
85 type compilationUnit struct {
86 fileNames []string
87 }
88
89 func makeFtab(funcs []_func, maxpc uint32) (ftab []funcTab, pclntabSize int64, startLocations []uint32) {
90
91
92
93 pclntabSize = int64(len(funcs)*2*int(_PtrSize) + int(_PtrSize))
94 startLocations = make([]uint32, len(funcs))
95 for i, f := range funcs {
96 pclntabSize = rnd(pclntabSize, int64(_PtrSize))
97
98 startLocations[i] = uint32(pclntabSize)
99 pclntabSize += int64(uint8(_FUNC_SIZE)+f.nfuncdata*4+uint8(f.npcdata)*4)
100 }
101
102 ftab = make([]funcTab, 0, len(funcs)+1)
103
104
105 for i, f := range funcs {
106 ftab = append(ftab, funcTab{uint32(f.entryOff), uint32(startLocations[i])})
107 }
108
109
110 ftab = append(ftab, funcTab{maxpc, 0})
111 return
112 }
113
114
115 func makePclntable(size int64, startLocations []uint32, funcs []_func, maxpc uint32, pcdataOffs [][]uint32, funcdataOffs [][]uint32) (pclntab []byte) {
116
117
118
119 pclntab = make([]byte, size, size)
120
121
122 offs := 0
123 for i, f := range funcs {
124 byteOrder.PutUint32(pclntab[offs:offs+4], uint32(f.entryOff))
125 byteOrder.PutUint32(pclntab[offs+4:offs+8], uint32(startLocations[i]))
126 offs += 8
127 }
128
129 byteOrder.PutUint32(pclntab[offs:offs+4], maxpc)
130
131
132 for i := range funcs {
133 off := startLocations[i]
134
135
136 fb := rt.BytesFrom(unsafe.Pointer(&funcs[i]), int(_FUNC_SIZE), int(_FUNC_SIZE))
137 copy(pclntab[off:off+uint32(_FUNC_SIZE)], fb)
138 off += uint32(_FUNC_SIZE)
139
140
141 for j := 3; j < len(pcdataOffs[i]); j++ {
142 byteOrder.PutUint32(pclntab[off:off+4], uint32(pcdataOffs[i][j]))
143 off += 4
144 }
145
146
147 for _, funcdata := range funcdataOffs[i] {
148 byteOrder.PutUint32(pclntab[off:off+4], uint32(funcdata))
149 off += 4
150 }
151
152 }
153
154 return
155 }
156
157
158
159
160
161
162
163
164 func writeFindfunctab(out *[]byte, ftab []funcTab) (start int) {
165 start = len(*out)
166
167 max := ftab[len(ftab)-1].entry
168 min := ftab[0].entry
169 nbuckets := (max - min + _BUCKETSIZE - 1) / _BUCKETSIZE
170 n := (max - min + _SUB_BUCKETSIZE - 1) / _SUB_BUCKETSIZE
171
172 tab := make([]findfuncbucket, 0, nbuckets)
173 var s, e = 0, 0
174 for i := 0; i<int(nbuckets); i++ {
175
176 var fb = findfuncbucket{idx: uint32(s)}
177
178
179 var pc = min + uint32((i+1)*_BUCKETSIZE)
180 for ; e < len(ftab)-1 && ftab[e+1].entry <= pc; e++ {}
181
182 for j := 0; j<_SUBBUCKETS && (i*_SUBBUCKETS+j)<int(n); j++ {
183
184 fb._SUBBUCKETS[j] = byte(uint32(s) - fb.idx)
185
186
187 pc = min + uint32(i*_BUCKETSIZE) + uint32((j+1)*_SUB_BUCKETSIZE)
188 for ; s < len(ftab)-1 && ftab[s+1].entry <= pc; s++ {}
189 }
190
191 s = e
192 tab = append(tab, fb)
193 }
194
195
196 if len(tab) > 0 {
197 size := int(unsafe.Sizeof(findfuncbucket{}))*len(tab)
198 *out = append(*out, rt.BytesFrom(unsafe.Pointer(&tab[0]), size, size)...)
199 }
200 return
201 }
202
203 func makeModuledata(name string, filenames []string, funcsp *[]Func, text []byte) (mod *moduledata) {
204 mod = new(moduledata)
205 mod.modulename = name
206
207
208 funcs := *funcsp
209 sort.Slice(funcs, func(i, j int) bool {
210 return funcs[i].EntryOff < funcs[j].EntryOff
211 })
212 *funcsp = funcs
213
214
215 cu := make([]string, 0, len(filenames))
216 cu = append(cu, filenames...)
217 cutab, filetab, cuOffs := makeFilenametab([]compilationUnit{{cu}})
218 mod.cutab = cutab
219 mod.filetab = filetab
220
221
222 funcnametab, nameOffs := makeFuncnameTab(funcs)
223 mod.funcnametab = funcnametab
224
225
226 p := os.Getpagesize()
227 size := int(rnd(int64(len(text)), int64(p)))
228 addr := mmap(size)
229
230 s := rt.BytesFrom(unsafe.Pointer(addr), len(text), size)
231 copy(s, text)
232
233 mprotect(addr, size)
234
235
236 mod.text = addr
237 mod.etext = addr + uintptr(size)
238 mod.minpc = addr
239 mod.maxpc = addr + uintptr(len(text))
240
241
242
243 cuOff := cuOffs[0]
244 pctab, pcdataOffs, _funcs := makePctab(funcs, cuOff, nameOffs)
245 mod.pctab = pctab
246
247
248
249
250 cache := make([]byte, 0, len(funcs)*int(_PtrSize))
251 fstart, funcdataOffs := writeFuncdata(&cache, funcs)
252
253
254 ftab, pclntSize, startLocations := makeFtab(_funcs, uint32(len(text)))
255 mod.ftab = ftab
256
257
258 ffstart := writeFindfunctab(&cache, ftab)
259
260
261 moduleCache.Lock()
262 moduleCache.m[mod] = cache
263 moduleCache.Unlock()
264 mod.gofunc = uintptr(unsafe.Pointer(&cache[fstart]))
265 mod.findfunctab = uintptr(unsafe.Pointer(&cache[ffstart]))
266
267
268 pclntab := makePclntable(pclntSize, startLocations, _funcs, uint32(len(text)), pcdataOffs, funcdataOffs)
269 mod.pclntable = pclntab
270
271
272 mod.pcHeader = &pcHeader {
273 magic : _Magic,
274 minLC : _MinLC,
275 ptrSize : _PtrSize,
276 nfunc : len(funcs),
277 nfiles: uint(len(cu)),
278 textStart: mod.text,
279 funcnameOffset: getOffsetOf(moduledata{}, "funcnametab"),
280 cuOffset: getOffsetOf(moduledata{}, "cutab"),
281 filetabOffset: getOffsetOf(moduledata{}, "filetab"),
282 pctabOffset: getOffsetOf(moduledata{}, "pctab"),
283 pclnOffset: getOffsetOf(moduledata{}, "pclntable"),
284 }
285
286
287 mod.gcdata = uintptr(unsafe.Pointer(&emptyByte))
288 mod.gcbss = uintptr(unsafe.Pointer(&emptyByte))
289
290 return
291 }
292
293
294
295 func makePctab(funcs []Func, cuOffset uint32, nameOffset []int32) (pctab []byte, pcdataOffs [][]uint32, _funcs []_func) {
296 _funcs = make([]_func, len(funcs))
297
298
299
300
301 pctab = make([]byte, 1, 12*len(funcs)+1)
302 pcdataOffs = make([][]uint32, len(funcs))
303
304 for i, f := range funcs {
305 _f := &_funcs[i]
306
307 var writer = func(pc *Pcdata) {
308 var ab []byte
309 var err error
310 if pc != nil {
311 ab, err = pc.MarshalBinary()
312 if err != nil {
313 panic(err)
314 }
315 pcdataOffs[i] = append(pcdataOffs[i], uint32(len(pctab)))
316 } else {
317 ab = []byte{0}
318 pcdataOffs[i] = append(pcdataOffs[i], _PCDATA_INVALID_OFFSET)
319 }
320 pctab = append(pctab, ab...)
321 }
322
323 if f.Pcsp != nil {
324 _f.pcsp = uint32(len(pctab))
325 }
326 writer(f.Pcsp)
327 if f.Pcfile != nil {
328 _f.pcfile = uint32(len(pctab))
329 }
330 writer(f.Pcfile)
331 if f.Pcline != nil {
332 _f.pcln = uint32(len(pctab))
333 }
334 writer(f.Pcline)
335 writer(f.PcUnsafePoint)
336 writer(f.PcStackMapIndex)
337 writer(f.PcInlTreeIndex)
338 writer(f.PcArgLiveIndex)
339
340 _f.entryOff = f.EntryOff
341 _f.nameOff = nameOffset[i]
342 _f.args = f.ArgsSize
343 _f.deferreturn = f.DeferReturn
344
345 _f.npcdata = uint32(_N_PCDATA)
346 _f.cuOffset = cuOffset
347 _f.funcID = f.ID
348 _f.flag = f.Flag
349 _f.nfuncdata = uint8(_N_FUNCDATA)
350 }
351
352 return
353 }
354
355 func registerFunction(name string, pc uintptr, textSize uintptr, fp int, args int, size uintptr, argptrs uintptr, localptrs uintptr) {}
356
View as plain text