diff options
author | 2023-11-27 13:15:03 +0000 | |
---|---|---|
committer | 2023-11-27 13:15:03 +0000 | |
commit | 66b77acb1c8b86f0be3836ccaf31683c0bfa317a (patch) | |
tree | 9a255a8ea8ef97229b6d75d17de45bdac1755be9 /vendor/github.com/bytedance/sonic/loader | |
parent | [bugfix] Add Actor to outgoing poll vote Create; other fixes (#2384) (diff) | |
download | gotosocial-66b77acb1c8b86f0be3836ccaf31683c0bfa317a.tar.xz |
[chore]: Bump github.com/gin-contrib/cors from 1.4.0 to 1.5.0 (#2388)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Diffstat (limited to 'vendor/github.com/bytedance/sonic/loader')
13 files changed, 884 insertions, 1186 deletions
diff --git a/vendor/github.com/bytedance/sonic/loader/funcdata.go b/vendor/github.com/bytedance/sonic/loader/funcdata.go index 9b760f615..0e8594c2e 100644 --- a/vendor/github.com/bytedance/sonic/loader/funcdata.go +++ b/vendor/github.com/bytedance/sonic/loader/funcdata.go @@ -42,6 +42,13 @@ const ( _SUB_BUCKETSIZE = _BUCKETSIZE / _SUBBUCKETS ) +// Note: This list must match the list in runtime/symtab.go. +const ( + FuncFlag_TOPFRAME = 1 << iota + FuncFlag_SPWRITE + FuncFlag_ASM +) + // PCDATA and FUNCDATA table indexes. // // See funcdata.h and $GROOT/src/cmd/internal/objabi/funcdata.go. @@ -141,4 +148,98 @@ func funcNameParts(name string) (string, string, string) { return name, "", "" } return name[:i], "[...]", name[j+1:] -}
\ No newline at end of file +} + + +// func name table format: +// nameOff[0] -> namePartA namePartB namePartC \x00 +// nameOff[1] -> namePartA namePartB namePartC \x00 +// ... +func makeFuncnameTab(funcs []Func) (tab []byte, offs []int32) { + offs = make([]int32, len(funcs)) + offset := 1 + tab = []byte{0} + + for i, f := range funcs { + offs[i] = int32(offset) + + a, b, c := funcNameParts(f.Name) + tab = append(tab, a...) + tab = append(tab, b...) + tab = append(tab, c...) + tab = append(tab, 0) + offset += len(a) + len(b) + len(c) + 1 + } + + return +} + +// CU table format: +// cuOffsets[0] -> filetabOffset[0] filetabOffset[1] ... filetabOffset[len(CUs[0].fileNames)-1] +// cuOffsets[1] -> filetabOffset[len(CUs[0].fileNames)] ... filetabOffset[len(CUs[0].fileNames) + len(CUs[1].fileNames)-1] +// ... +// +// file name table format: +// filetabOffset[0] -> CUs[0].fileNames[0] \x00 +// ... +// filetabOffset[len(CUs[0]-1)] -> CUs[0].fileNames[len(CUs[0].fileNames)-1] \x00 +// ... +// filetabOffset[SUM(CUs,fileNames)-1] -> CUs[len(CU)-1].fileNames[len(CUs[len(CU)-1].fileNames)-1] \x00 +func makeFilenametab(cus []compilationUnit) (cutab []uint32, filetab []byte, cuOffsets []uint32) { + cuOffsets = make([]uint32, len(cus)) + cuOffset := 0 + fileOffset := 0 + + for i, cu := range cus { + cuOffsets[i] = uint32(cuOffset) + + for _, name := range cu.fileNames { + cutab = append(cutab, uint32(fileOffset)) + + fileOffset += len(name) + 1 + filetab = append(filetab, name...) + filetab = append(filetab, 0) + } + + cuOffset += len(cu.fileNames) + } + + return +} + +func writeFuncdata(out *[]byte, funcs []Func) (fstart int, funcdataOffs [][]uint32) { + fstart = len(*out) + *out = append(*out, byte(0)) + offs := uint32(1) + + funcdataOffs = make([][]uint32, len(funcs)) + for i, f := range funcs { + + var writer = func(fd encoding.BinaryMarshaler) { + var ab []byte + var err error + if fd != nil { + ab, err = fd.MarshalBinary() + if err != nil { + panic(err) + } + funcdataOffs[i] = append(funcdataOffs[i], offs) + } else { + ab = []byte{0} + funcdataOffs[i] = append(funcdataOffs[i], _INVALID_FUNCDATA_OFFSET) + } + *out = append(*out, ab...) + offs += uint32(len(ab)) + } + + writer(f.ArgsPointerMaps) + writer(f.LocalsPointerMaps) + writer(f.StackObjects) + writer(f.InlTree) + writer(f.OpenCodedDeferInfo) + writer(f.ArgInfo) + writer(f.ArgLiveInfo) + writer(f.WrapInfo) + } + return +} diff --git a/vendor/github.com/bytedance/sonic/loader/funcdata_go115.go b/vendor/github.com/bytedance/sonic/loader/funcdata_compat.go index a2e3e65f9..1af575aaa 100644 --- a/vendor/github.com/bytedance/sonic/loader/funcdata_go115.go +++ b/vendor/github.com/bytedance/sonic/loader/funcdata_compat.go @@ -1,5 +1,5 @@ -//go:build go1.15 && !go1.16 -// +build go1.15,!go1.16 +//go:build !go1.16 +// +build !go1.16 /* * Copyright 2021 ByteDance Inc. @@ -20,11 +20,11 @@ package loader import ( - `encoding` - `os` - `unsafe` + `os` + `unsafe` + `sort` - `github.com/bytedance/sonic/internal/rt` + `github.com/bytedance/sonic/internal/rt` ) const ( @@ -171,99 +171,7 @@ type compilationUnit struct { fileNames []string } -// func name table format: -// nameOff[0] -> namePartA namePartB namePartC \x00 -// nameOff[1] -> namePartA namePartB namePartC \x00 -// ... -func makeFuncnameTab(funcs []Func) (tab []byte, offs []int32) { - offs = make([]int32, len(funcs)) - offset := 0 - - for i, f := range funcs { - offs[i] = int32(offset) - - a, b, c := funcNameParts(f.Name) - tab = append(tab, a...) - tab = append(tab, b...) - tab = append(tab, c...) - tab = append(tab, 0) - offset += len(a) + len(b) + len(c) + 1 - } - - return -} - -// CU table format: -// cuOffsets[0] -> filetabOffset[0] filetabOffset[1] ... filetabOffset[len(CUs[0].fileNames)-1] -// cuOffsets[1] -> filetabOffset[len(CUs[0].fileNames)] ... filetabOffset[len(CUs[0].fileNames) + len(CUs[1].fileNames)-1] -// ... -// -// file name table format: -// filetabOffset[0] -> CUs[0].fileNames[0] \x00 -// ... -// filetabOffset[len(CUs[0]-1)] -> CUs[0].fileNames[len(CUs[0].fileNames)-1] \x00 -// ... -// filetabOffset[SUM(CUs,fileNames)-1] -> CUs[len(CU)-1].fileNames[len(CUs[len(CU)-1].fileNames)-1] \x00 -func makeFilenametab(cus []compilationUnit) (cutab []uint32, filetab []byte, cuOffsets []uint32) { - cuOffsets = make([]uint32, len(cus)) - cuOffset := 0 - fileOffset := 0 - - for i, cu := range cus { - cuOffsets[i] = uint32(cuOffset) - - for _, name := range cu.fileNames { - cutab = append(cutab, uint32(fileOffset)) - - fileOffset += len(name) + 1 - filetab = append(filetab, name...) - filetab = append(filetab, 0) - } - - cuOffset += len(cu.fileNames) - } - - return -} - -func writeFuncdata(out *[]byte, funcs []Func) (fstart int, funcdataOffs [][]uint32) { - fstart = len(*out) - *out = append(*out, byte(0)) - offs := uint32(1) - - funcdataOffs = make([][]uint32, len(funcs)) - for i, f := range funcs { - - var writer = func(fd encoding.BinaryMarshaler) { - var ab []byte - var err error - if fd != nil { - ab, err = fd.MarshalBinary() - if err != nil { - panic(err) - } - funcdataOffs[i] = append(funcdataOffs[i], offs) - } else { - ab = []byte{0} - funcdataOffs[i] = append(funcdataOffs[i], _INVALID_FUNCDATA_OFFSET) - } - *out = append(*out, ab...) - offs += uint32(len(ab)) - } - - writer(f.ArgsPointerMaps) - writer(f.LocalsPointerMaps) - writer(f.StackObjects) - writer(f.InlTree) - writer(f.OpenCodedDeferInfo) - writer(f.ArgInfo) - writer(f.ArgLiveInfo) - writer(f.WrapInfo) - } - return -} - -func makeFtab(funcs []_func, lastFuncSize uint32) (ftab []funcTab, pclntabSize int64, startLocations []uint32) { +func makeFtab(funcs []_func, maxpc uintptr) (ftab []funcTab, pclntabSize int64, startLocations []uint32) { // Allocate space for the pc->func table. This structure consists of a pc offset // and an offset to the func structure. After that, we have a single pc // value that marks the end of the last function in the binary. @@ -283,14 +191,12 @@ func makeFtab(funcs []_func, lastFuncSize uint32) (ftab []funcTab, pclntabSize i } // Final entry of table is just end pc offset. - lastFunc := funcs[len(funcs)-1] - ftab = append(ftab, funcTab{lastFunc.entry + uintptr(lastFuncSize), 0}) - + ftab = append(ftab, funcTab{maxpc, 0}) return } // Pcln table format: [...]funcTab + [...]_Func -func makePclntable(size int64, startLocations []uint32, funcs []_func, lastFuncSize uint32, pcdataOffs [][]uint32, funcdataAddr uintptr, funcdataOffs [][]uint32) (pclntab []byte) { +func makePclntable(size int64, startLocations []uint32, funcs []_func, maxpc uintptr, pcdataOffs [][]uint32, funcdataAddr uintptr, funcdataOffs [][]uint32) (pclntab []byte) { pclntab = make([]byte, size, size) // write a map of pc->func info offsets @@ -301,8 +207,7 @@ func makePclntable(size int64, startLocations []uint32, funcs []_func, lastFuncS offs += 16 } // Final entry of table is just end pc offset. - lastFunc := funcs[len(funcs)-1] - byteOrder.PutUint64(pclntab[offs:offs+8], uint64(lastFunc.entry)+uint64(lastFuncSize)) + byteOrder.PutUint64(pclntab[offs:offs+8], uint64(maxpc)) offs += 8 // write func info table @@ -374,21 +279,22 @@ func writeFindfunctab(out *[]byte, ftab []funcTab) (start int) { tab := make([]findfuncbucket, 0, nbuckets) var s, e = 0, 0 for i := 0; i<int(nbuckets); i++ { - var pc = min + uintptr((i+1)*_BUCKETSIZE) - // find the end func of the bucket - for ; e < len(ftab)-1 && ftab[e+1].entry <= pc; e++ {} // store the start func of the bucket var fb = findfuncbucket{idx: uint32(s)} + // find the last e-th func of the bucket + var pc = min + uintptr((i+1)*_BUCKETSIZE) + for ; e < len(ftab)-1 && ftab[e+1].entry <= pc; e++ {} + for j := 0; j<_SUBBUCKETS && (i*_SUBBUCKETS+j)<int(n); j++ { - pc = min + uintptr(i*_BUCKETSIZE) + uintptr((j+1)*_SUB_BUCKETSIZE) - var ss = s - // find the end func of the subbucket - for ; ss < len(ftab)-1 && ftab[ss+1].entry <= pc; ss++ {} // store the start func of the subbucket fb._SUBBUCKETS[j] = byte(uint32(s) - fb.idx) - s = ss + + // find the s-th end func of the subbucket + pc = min + uintptr(i*_BUCKETSIZE) + uintptr((j+1)*_SUB_BUCKETSIZE) + for ; s < len(ftab)-1 && ftab[s+1].entry <= pc; s++ {} } + s = e tab = append(tab, fb) } @@ -401,15 +307,20 @@ func writeFindfunctab(out *[]byte, ftab []funcTab) (start int) { return } -func makeModuledata(name string, filenames []string, funcs []Func, text []byte) (mod *moduledata) { +func makeModuledata(name string, filenames []string, funcsp *[]Func, text []byte) (mod *moduledata) { mod = new(moduledata) mod.modulename = name + // sort funcs by entry + funcs := *funcsp + sort.Slice(funcs, func(i, j int) bool { + return funcs[i].EntryOff < funcs[j].EntryOff + }) + *funcsp = funcs + // make filename table cu := make([]string, 0, len(filenames)) - for _, f := range filenames { - cu = append(cu, f) - } + cu = append(cu, filenames...) cutab, filetab, cuOffs := makeFilenametab([]compilationUnit{{cu}}) mod.cutab = cutab mod.filetab = filetab @@ -428,9 +339,16 @@ func makeModuledata(name string, filenames []string, funcs []Func, text []byte) // make it executable mprotect(addr, size) + // assign addresses + mod.text = addr + mod.etext = addr + uintptr(size) + mod.minpc = addr + mod.maxpc = addr + uintptr(len(text)) + // make pcdata table // NOTICE: _func only use offset to index pcdata, thus no need mmap() pcdata - pctab, pcdataOffs, _funcs := makePctab(funcs, addr, cuOffs, nameOffs) + cuOff := cuOffs[0] + pctab, pcdataOffs, _funcs := makePctab(funcs, addr, cuOff, nameOffs) mod.pctab = pctab // write func data @@ -440,8 +358,7 @@ func makeModuledata(name string, filenames []string, funcs []Func, text []byte) fstart, funcdataOffs := writeFuncdata(&cache, funcs) // make pc->func (binary search) func table - lastFuncsize := funcs[len(funcs)-1].TextSize - ftab, pclntSize, startLocations := makeFtab(_funcs, lastFuncsize) + ftab, pclntSize, startLocations := makeFtab(_funcs, mod.maxpc) mod.ftab = ftab // write pc->func (modmap) findfunc table @@ -455,15 +372,9 @@ func makeModuledata(name string, filenames []string, funcs []Func, text []byte) funcdataAddr := uintptr(rt.IndexByte(cache, fstart)) // make pclnt table - pclntab := makePclntable(pclntSize, startLocations, _funcs, lastFuncsize, pcdataOffs, funcdataAddr, funcdataOffs) + pclntab := makePclntable(pclntSize, startLocations, _funcs, mod.maxpc, pcdataOffs, funcdataAddr, funcdataOffs) mod.pclntable = pclntab - // assign addresses - mod.text = addr - mod.etext = addr + uintptr(size) - mod.minpc = addr - mod.maxpc = addr + uintptr(len(text)) - // make pc header mod.pcHeader = &pcHeader { magic : _Magic, @@ -487,7 +398,7 @@ func makeModuledata(name string, filenames []string, funcs []Func, text []byte) // makePctab generates pcdelta->valuedelta tables for functions, // and returns the table and the entry offset of every kind pcdata in the table. -func makePctab(funcs []Func, addr uintptr, cuOffset []uint32, nameOffset []int32) (pctab []byte, pcdataOffs [][]uint32, _funcs []_func) { +func makePctab(funcs []Func, addr uintptr, cuOffset uint32, nameOffset []int32) (pctab []byte, pcdataOffs [][]uint32, _funcs []_func) { _funcs = make([]_func, len(funcs)) // Pctab offsets of 0 are considered invalid in the runtime. We respect @@ -538,7 +449,7 @@ func makePctab(funcs []Func, addr uintptr, cuOffset []uint32, nameOffset []int32 _f.deferreturn = f.DeferReturn // NOTICE: _func.pcdata is always as [PCDATA_UnsafePoint(0) : PCDATA_ArgLiveIndex(3)] _f.npcdata = uint32(_N_PCDATA) - _f.cuOffset = cuOffset[i] + _f.cuOffset = cuOffset _f.funcID = f.ID _f.nfuncdata = uint8(_N_FUNCDATA) } @@ -546,4 +457,4 @@ func makePctab(funcs []Func, addr uintptr, cuOffset []uint32, nameOffset []int32 return } -func registerFunction(name string, pc uintptr, textSize uintptr, fp int, args int, size uintptr, argptrs uintptr, localptrs uintptr) {}
\ No newline at end of file +func registerFunction(name string, pc uintptr, textSize uintptr, fp int, args int, size uintptr, argptrs uintptr, localptrs uintptr) {} diff --git a/vendor/github.com/bytedance/sonic/loader/funcdata_go116.go b/vendor/github.com/bytedance/sonic/loader/funcdata_go116.go index 508268e7d..1dfe2297d 100644 --- a/vendor/github.com/bytedance/sonic/loader/funcdata_go116.go +++ b/vendor/github.com/bytedance/sonic/loader/funcdata_go116.go @@ -20,9 +20,9 @@ package loader import ( - `encoding` `os` `unsafe` + `sort` `github.com/bytedance/sonic/internal/rt` ) @@ -171,99 +171,7 @@ type compilationUnit struct { fileNames []string } -// func name table format: -// nameOff[0] -> namePartA namePartB namePartC \x00 -// nameOff[1] -> namePartA namePartB namePartC \x00 -// ... -func makeFuncnameTab(funcs []Func) (tab []byte, offs []int32) { - offs = make([]int32, len(funcs)) - offset := 0 - - for i, f := range funcs { - offs[i] = int32(offset) - - a, b, c := funcNameParts(f.Name) - tab = append(tab, a...) - tab = append(tab, b...) - tab = append(tab, c...) - tab = append(tab, 0) - offset += len(a) + len(b) + len(c) + 1 - } - - return -} - -// CU table format: -// cuOffsets[0] -> filetabOffset[0] filetabOffset[1] ... filetabOffset[len(CUs[0].fileNames)-1] -// cuOffsets[1] -> filetabOffset[len(CUs[0].fileNames)] ... filetabOffset[len(CUs[0].fileNames) + len(CUs[1].fileNames)-1] -// ... -// -// file name table format: -// filetabOffset[0] -> CUs[0].fileNames[0] \x00 -// ... -// filetabOffset[len(CUs[0]-1)] -> CUs[0].fileNames[len(CUs[0].fileNames)-1] \x00 -// ... -// filetabOffset[SUM(CUs,fileNames)-1] -> CUs[len(CU)-1].fileNames[len(CUs[len(CU)-1].fileNames)-1] \x00 -func makeFilenametab(cus []compilationUnit) (cutab []uint32, filetab []byte, cuOffsets []uint32) { - cuOffsets = make([]uint32, len(cus)) - cuOffset := 0 - fileOffset := 0 - - for i, cu := range cus { - cuOffsets[i] = uint32(cuOffset) - - for _, name := range cu.fileNames { - cutab = append(cutab, uint32(fileOffset)) - - fileOffset += len(name) + 1 - filetab = append(filetab, name...) - filetab = append(filetab, 0) - } - - cuOffset += len(cu.fileNames) - } - - return -} - -func writeFuncdata(out *[]byte, funcs []Func) (fstart int, funcdataOffs [][]uint32) { - fstart = len(*out) - *out = append(*out, byte(0)) - offs := uint32(1) - - funcdataOffs = make([][]uint32, len(funcs)) - for i, f := range funcs { - - var writer = func(fd encoding.BinaryMarshaler) { - var ab []byte - var err error - if fd != nil { - ab, err = fd.MarshalBinary() - if err != nil { - panic(err) - } - funcdataOffs[i] = append(funcdataOffs[i], offs) - } else { - ab = []byte{0} - funcdataOffs[i] = append(funcdataOffs[i], _INVALID_FUNCDATA_OFFSET) - } - *out = append(*out, ab...) - offs += uint32(len(ab)) - } - - writer(f.ArgsPointerMaps) - writer(f.LocalsPointerMaps) - writer(f.StackObjects) - writer(f.InlTree) - writer(f.OpenCodedDeferInfo) - writer(f.ArgInfo) - writer(f.ArgLiveInfo) - writer(f.WrapInfo) - } - return -} - -func makeFtab(funcs []_func, lastFuncSize uint32) (ftab []funcTab, pclntabSize int64, startLocations []uint32) { +func makeFtab(funcs []_func, maxpc uintptr) (ftab []funcTab, pclntabSize int64, startLocations []uint32) { // Allocate space for the pc->func table. This structure consists of a pc offset // and an offset to the func structure. After that, we have a single pc // value that marks the end of the last function in the binary. @@ -283,14 +191,13 @@ func makeFtab(funcs []_func, lastFuncSize uint32) (ftab []funcTab, pclntabSize i } // Final entry of table is just end pc offset. - lastFunc := funcs[len(funcs)-1] - ftab = append(ftab, funcTab{lastFunc.entry + uintptr(lastFuncSize), 0}) + ftab = append(ftab, funcTab{maxpc, 0}) return } // Pcln table format: [...]funcTab + [...]_Func -func makePclntable(size int64, startLocations []uint32, funcs []_func, lastFuncSize uint32, pcdataOffs [][]uint32, funcdataAddr uintptr, funcdataOffs [][]uint32) (pclntab []byte) { +func makePclntable(size int64, startLocations []uint32, funcs []_func, maxpc uintptr, pcdataOffs [][]uint32, funcdataAddr uintptr, funcdataOffs [][]uint32) (pclntab []byte) { pclntab = make([]byte, size, size) // write a map of pc->func info offsets @@ -301,8 +208,7 @@ func makePclntable(size int64, startLocations []uint32, funcs []_func, lastFuncS offs += 16 } // Final entry of table is just end pc offset. - lastFunc := funcs[len(funcs)-1] - byteOrder.PutUint64(pclntab[offs:offs+8], uint64(lastFunc.entry)+uint64(lastFuncSize)) + byteOrder.PutUint64(pclntab[offs:offs+8], uint64(maxpc)) offs += 8 // write func info table @@ -374,21 +280,22 @@ func writeFindfunctab(out *[]byte, ftab []funcTab) (start int) { tab := make([]findfuncbucket, 0, nbuckets) var s, e = 0, 0 for i := 0; i<int(nbuckets); i++ { - var pc = min + uintptr((i+1)*_BUCKETSIZE) - // find the end func of the bucket - for ; e < len(ftab)-1 && ftab[e+1].entry <= pc; e++ {} // store the start func of the bucket var fb = findfuncbucket{idx: uint32(s)} + // find the last e-th func of the bucket + var pc = min + uintptr((i+1)*_BUCKETSIZE) + for ; e < len(ftab)-1 && ftab[e+1].entry <= pc; e++ {} + for j := 0; j<_SUBBUCKETS && (i*_SUBBUCKETS+j)<int(n); j++ { - pc = min + uintptr(i*_BUCKETSIZE) + uintptr((j+1)*_SUB_BUCKETSIZE) - var ss = s - // find the end func of the subbucket - for ; ss < len(ftab)-1 && ftab[ss+1].entry <= pc; ss++ {} // store the start func of the subbucket fb._SUBBUCKETS[j] = byte(uint32(s) - fb.idx) - s = ss + + // find the s-th end func of the subbucket + pc = min + uintptr(i*_BUCKETSIZE) + uintptr((j+1)*_SUB_BUCKETSIZE) + for ; s < len(ftab)-1 && ftab[s+1].entry <= pc; s++ {} } + s = e tab = append(tab, fb) } @@ -401,15 +308,20 @@ func writeFindfunctab(out *[]byte, ftab []funcTab) (start int) { return } -func makeModuledata(name string, filenames []string, funcs []Func, text []byte) (mod *moduledata) { +func makeModuledata(name string, filenames []string, funcsp *[]Func, text []byte) (mod *moduledata) { mod = new(moduledata) mod.modulename = name + // sort funcs by entry + funcs := *funcsp + sort.Slice(funcs, func(i, j int) bool { + return funcs[i].EntryOff < funcs[j].EntryOff + }) + *funcsp = funcs + // make filename table cu := make([]string, 0, len(filenames)) - for _, f := range filenames { - cu = append(cu, f) - } + cu = append(cu, filenames...) cutab, filetab, cuOffs := makeFilenametab([]compilationUnit{{cu}}) mod.cutab = cutab mod.filetab = filetab @@ -428,9 +340,16 @@ func makeModuledata(name string, filenames []string, funcs []Func, text []byte) // make it executable mprotect(addr, size) + // assign addresses + mod.text = addr + mod.etext = addr + uintptr(size) + mod.minpc = addr + mod.maxpc = addr + uintptr(len(text)) + // make pcdata table // NOTICE: _func only use offset to index pcdata, thus no need mmap() pcdata - pctab, pcdataOffs, _funcs := makePctab(funcs, addr, cuOffs, nameOffs) + cuOff := cuOffs[0] + pctab, pcdataOffs, _funcs := makePctab(funcs, addr, cuOff, nameOffs) mod.pctab = pctab // write func data @@ -440,8 +359,7 @@ func makeModuledata(name string, filenames []string, funcs []Func, text []byte) fstart, funcdataOffs := writeFuncdata(&cache, funcs) // make pc->func (binary search) func table - lastFuncsize := funcs[len(funcs)-1].TextSize - ftab, pclntSize, startLocations := makeFtab(_funcs, lastFuncsize) + ftab, pclntSize, startLocations := makeFtab(_funcs, mod.maxpc) mod.ftab = ftab // write pc->func (modmap) findfunc table @@ -455,15 +373,9 @@ func makeModuledata(name string, filenames []string, funcs []Func, text []byte) funcdataAddr := uintptr(rt.IndexByte(cache, fstart)) // make pclnt table - pclntab := makePclntable(pclntSize, startLocations, _funcs, lastFuncsize, pcdataOffs, funcdataAddr, funcdataOffs) + pclntab := makePclntable(pclntSize, startLocations, _funcs, mod.maxpc, pcdataOffs, funcdataAddr, funcdataOffs) mod.pclntable = pclntab - // assign addresses - mod.text = addr - mod.etext = addr + uintptr(size) - mod.minpc = addr - mod.maxpc = addr + uintptr(len(text)) - // make pc header mod.pcHeader = &pcHeader { magic : _Magic, @@ -487,7 +399,7 @@ func makeModuledata(name string, filenames []string, funcs []Func, text []byte) // makePctab generates pcdelta->valuedelta tables for functions, // and returns the table and the entry offset of every kind pcdata in the table. -func makePctab(funcs []Func, addr uintptr, cuOffset []uint32, nameOffset []int32) (pctab []byte, pcdataOffs [][]uint32, _funcs []_func) { +func makePctab(funcs []Func, addr uintptr, cuOffset uint32, nameOffset []int32) (pctab []byte, pcdataOffs [][]uint32, _funcs []_func) { _funcs = make([]_func, len(funcs)) // Pctab offsets of 0 are considered invalid in the runtime. We respect @@ -538,7 +450,7 @@ func makePctab(funcs []Func, addr uintptr, cuOffset []uint32, nameOffset []int32 _f.deferreturn = f.DeferReturn // NOTICE: _func.pcdata is always as [PCDATA_UnsafePoint(0) : PCDATA_ArgLiveIndex(3)] _f.npcdata = uint32(_N_PCDATA) - _f.cuOffset = cuOffset[i] + _f.cuOffset = cuOffset _f.funcID = f.ID _f.nfuncdata = uint8(_N_FUNCDATA) } @@ -546,4 +458,4 @@ func makePctab(funcs []Func, addr uintptr, cuOffset []uint32, nameOffset []int32 return } -func registerFunction(name string, pc uintptr, textSize uintptr, fp int, args int, size uintptr, argptrs uintptr, localptrs uintptr) {}
\ No newline at end of file +func registerFunction(name string, pc uintptr, textSize uintptr, fp int, args int, size uintptr, argptrs uintptr, localptrs uintptr) {} diff --git a/vendor/github.com/bytedance/sonic/loader/funcdata_go118.go b/vendor/github.com/bytedance/sonic/loader/funcdata_go118.go index a2bac857a..84178ab85 100644 --- a/vendor/github.com/bytedance/sonic/loader/funcdata_go118.go +++ b/vendor/github.com/bytedance/sonic/loader/funcdata_go118.go @@ -1,4 +1,5 @@ // go:build go1.18 && !go1.20 +//go:build go1.18 && !go1.20 // +build go1.18,!go1.20 /* @@ -20,10 +21,6 @@ package loader import ( - `encoding` - `os` - `unsafe` - `github.com/bytedance/sonic/internal/rt` ) @@ -31,21 +28,6 @@ const ( _Magic uint32 = 0xfffffff0 ) -type pcHeader struct { - magic uint32 // 0xFFFFFFF0 - pad1, pad2 uint8 // 0,0 - minLC uint8 // min instruction size - ptrSize uint8 // size of a ptr in bytes - nfunc int // number of functions in the module - nfiles uint // number of entries in the file tab - textStart uintptr // base for function entry PC offsets in this module, equal to moduledata.text - funcnameOffset uintptr // offset to the funcnametab variable from pcHeader - cuOffset uintptr // offset to the cutab variable from pcHeader - filetabOffset uintptr // offset to the filetab variable from pcHeader - pctabOffset uintptr // offset to the pctab variable from pcHeader - pclnOffset uintptr // offset to the pclntab variable from pcHeader -} - type moduledata struct { pcHeader *pcHeader funcnametab []byte @@ -129,413 +111,3 @@ type _func struct { // // funcdata [nfuncdata]uint32 } - -type funcTab struct { - entry uint32 - funcoff uint32 -} - -type bitVector struct { - n int32 // # of bits - bytedata *uint8 -} - -type ptabEntry struct { - name int32 - typ int32 -} - -type textSection struct { - vaddr uintptr // prelinked section vaddr - end uintptr // vaddr + section length - baseaddr uintptr // relocated section address -} - -type modulehash struct { - modulename string - linktimehash string - runtimehash *string -} - -// findfuncbucket is an array of these structures. -// Each bucket represents 4096 bytes of the text segment. -// Each subbucket represents 256 bytes of the text segment. -// To find a function given a pc, locate the bucket and subbucket for -// that pc. Add together the idx and subbucket value to obtain a -// function index. Then scan the functab array starting at that -// index to find the target function. -// This table uses 20 bytes for every 4096 bytes of code, or ~0.5% overhead. -type findfuncbucket struct { - idx uint32 - _SUBBUCKETS [16]byte -} - -// func name table format: -// nameOff[0] -> namePartA namePartB namePartC \x00 -// nameOff[1] -> namePartA namePartB namePartC \x00 -// ... -func makeFuncnameTab(funcs []Func) (tab []byte, offs []int32) { - offs = make([]int32, len(funcs)) - offset := 0 - - for i, f := range funcs { - offs[i] = int32(offset) - - a, b, c := funcNameParts(f.Name) - tab = append(tab, a...) - tab = append(tab, b...) - tab = append(tab, c...) - tab = append(tab, 0) - offset += len(a) + len(b) + len(c) + 1 - } - - return -} - -type compilationUnit struct { - fileNames []string -} - -// CU table format: -// cuOffsets[0] -> filetabOffset[0] filetabOffset[1] ... filetabOffset[len(CUs[0].fileNames)-1] -// cuOffsets[1] -> filetabOffset[len(CUs[0].fileNames)] ... filetabOffset[len(CUs[0].fileNames) + len(CUs[1].fileNames)-1] -// ... -// -// file name table format: -// filetabOffset[0] -> CUs[0].fileNames[0] \x00 -// ... -// filetabOffset[len(CUs[0]-1)] -> CUs[0].fileNames[len(CUs[0].fileNames)-1] \x00 -// ... -// filetabOffset[SUM(CUs,fileNames)-1] -> CUs[len(CU)-1].fileNames[len(CUs[len(CU)-1].fileNames)-1] \x00 -func makeFilenametab(cus []compilationUnit) (cutab []uint32, filetab []byte, cuOffsets []uint32) { - cuOffsets = make([]uint32, len(cus)) - cuOffset := 0 - fileOffset := 0 - - for i, cu := range cus { - cuOffsets[i] = uint32(cuOffset) - - for _, name := range cu.fileNames { - cutab = append(cutab, uint32(fileOffset)) - - fileOffset += len(name) + 1 - filetab = append(filetab, name...) - filetab = append(filetab, 0) - } - - cuOffset += len(cu.fileNames) - } - - return -} - -func writeFuncdata(out *[]byte, funcs []Func) (fstart int, funcdataOffs [][]uint32) { - fstart = len(*out) - *out = append(*out, byte(0)) - offs := uint32(1) - - funcdataOffs = make([][]uint32, len(funcs)) - for i, f := range funcs { - - var writer = func(fd encoding.BinaryMarshaler) { - var ab []byte - var err error - if fd != nil { - ab, err = fd.MarshalBinary() - if err != nil { - panic(err) - } - funcdataOffs[i] = append(funcdataOffs[i], offs) - } else { - ab = []byte{0} - funcdataOffs[i] = append(funcdataOffs[i], _INVALID_FUNCDATA_OFFSET) - } - *out = append(*out, ab...) - offs += uint32(len(ab)) - } - - writer(f.ArgsPointerMaps) - writer(f.LocalsPointerMaps) - writer(f.StackObjects) - writer(f.InlTree) - writer(f.OpenCodedDeferInfo) - writer(f.ArgInfo) - writer(f.ArgLiveInfo) - writer(f.WrapInfo) - } - return -} - -func makeFtab(funcs []_func, lastFuncSize uint32) (ftab []funcTab) { - // Allocate space for the pc->func table. This structure consists of a pc offset - // and an offset to the func structure. After that, we have a single pc - // value that marks the end of the last function in the binary. - var size int64 = int64(len(funcs)*2*4 + 4) - var startLocations = make([]uint32, len(funcs)) - for i, f := range funcs { - size = rnd(size, int64(_PtrSize)) - //writePCToFunc - startLocations[i] = uint32(size) - size += int64(uint8(_FUNC_SIZE)+f.nfuncdata*4+uint8(f.npcdata)*4) - } - - ftab = make([]funcTab, 0, len(funcs)+1) - - // write a map of pc->func info offsets - for i, f := range funcs { - ftab = append(ftab, funcTab{uint32(f.entryOff), uint32(startLocations[i])}) - } - - // Final entry of table is just end pc offset. - lastFunc := funcs[len(funcs)-1] - ftab = append(ftab, funcTab{uint32(lastFunc.entryOff + lastFuncSize), 0}) - - return -} - -// Pcln table format: [...]funcTab + [...]_Func -func makePclntable(funcs []_func, lastFuncSize uint32, pcdataOffs [][]uint32, funcdataOffs [][]uint32) (pclntab []byte) { - // Allocate space for the pc->func table. This structure consists of a pc offset - // and an offset to the func structure. After that, we have a single pc - // value that marks the end of the last function in the binary. - var size int64 = int64(len(funcs)*2*4 + 4) - var startLocations = make([]uint32, len(funcs)) - for i := range funcs { - size = rnd(size, int64(_PtrSize)) - //writePCToFunc - startLocations[i] = uint32(size) - size += int64(int(_FUNC_SIZE)+len(funcdataOffs[i])*4+len(pcdataOffs[i])*4) - } - - pclntab = make([]byte, size, size) - - // write a map of pc->func info offsets - offs := 0 - for i, f := range funcs { - byteOrder.PutUint32(pclntab[offs:offs+4], uint32(f.entryOff)) - byteOrder.PutUint32(pclntab[offs+4:offs+8], uint32(startLocations[i])) - offs += 8 - } - // Final entry of table is just end pc offset. - lastFunc := funcs[len(funcs)-1] - byteOrder.PutUint32(pclntab[offs:offs+4], uint32(lastFunc.entryOff+lastFuncSize)) - - // write func info table - for i, f := range funcs { - off := startLocations[i] - - // write _func structure to pclntab - fb := rt.BytesFrom(unsafe.Pointer(&f), int(_FUNC_SIZE), int(_FUNC_SIZE)) - copy(pclntab[off:off+uint32(_FUNC_SIZE)], fb) - off += uint32(_FUNC_SIZE) - - // NOTICE: _func.pcdata always starts from PcUnsafePoint, which is index 3 - for j := 3; j < len(pcdataOffs[i]); j++ { - byteOrder.PutUint32(pclntab[off:off+4], uint32(pcdataOffs[i][j])) - off += 4 - } - - // funcdata refs as offsets from gofunc - for _, funcdata := range funcdataOffs[i] { - byteOrder.PutUint32(pclntab[off:off+4], uint32(funcdata)) - off += 4 - } - - } - - return -} - -// findfunc table used to map pc to belonging func, -// returns the index in the func table. -// -// All text section are divided into buckets sized _BUCKETSIZE(4K): -// every bucket is divided into _SUBBUCKETS sized _SUB_BUCKETSIZE(64), -// and it has a base idx to plus the offset stored in jth subbucket. -// see findfunc() in runtime/symtab.go -func writeFindfunctab(out *[]byte, ftab []funcTab) (start int) { - start = len(*out) - - max := ftab[len(ftab)-1].entry - min := ftab[0].entry - nbuckets := (max - min + _BUCKETSIZE - 1) / _BUCKETSIZE - n := (max - min + _SUB_BUCKETSIZE - 1) / _SUB_BUCKETSIZE - - tab := make([]findfuncbucket, 0, nbuckets) - var s, e = 0, 0 - for i := 0; i<int(nbuckets); i++ { - var pc = min + uint32((i+1)*_BUCKETSIZE) - // find the end func of the bucket - for ; e < len(ftab)-1 && ftab[e+1].entry <= pc; e++ {} - // store the start func of the bucket - var fb = findfuncbucket{idx: uint32(s)} - - for j := 0; j<_SUBBUCKETS && (i*_SUBBUCKETS+j)<int(n); j++ { - pc = min + uint32(i*_BUCKETSIZE) + uint32((j+1)*_SUB_BUCKETSIZE) - var ss = s - // find the end func of the subbucket - for ; ss < len(ftab)-1 && ftab[ss+1].entry <= pc; ss++ {} - // store the start func of the subbucket - fb._SUBBUCKETS[j] = byte(uint32(s) - fb.idx) - s = ss - } - s = e - tab = append(tab, fb) - } - - // write findfuncbucket - if len(tab) > 0 { - size := int(unsafe.Sizeof(findfuncbucket{}))*len(tab) - *out = append(*out, rt.BytesFrom(unsafe.Pointer(&tab[0]), size, size)...) - } - return -} - -func makeModuledata(name string, filenames []string, funcs []Func, text []byte) (mod *moduledata) { - mod = new(moduledata) - mod.modulename = name - - // make filename table - cu := make([]string, 0, len(filenames)) - for _, f := range filenames { - cu = append(cu, f) - } - cutab, filetab, cuOffs := makeFilenametab([]compilationUnit{{cu}}) - mod.cutab = cutab - mod.filetab = filetab - - // make funcname table - funcnametab, nameOffs := makeFuncnameTab(funcs) - mod.funcnametab = funcnametab - - // make pcdata table - // NOTICE: _func only use offset to index pcdata, thus no need mmap() pcdata - pctab, pcdataOffs, _funcs := makePctab(funcs, cuOffs, nameOffs) - mod.pctab = pctab - - // write func data - // NOTICE: _func use mod.gofunc+offset to directly point funcdata, thus need cache funcdata - // TODO: estimate accurate capacity - cache := make([]byte, 0, len(funcs)*int(_PtrSize)) - fstart, funcdataOffs := writeFuncdata(&cache, funcs) - - // make pc->func (binary search) func table - lastFuncsize := funcs[len(funcs)-1].TextSize - ftab := makeFtab(_funcs, lastFuncsize) - mod.ftab = ftab - - // write pc->func (modmap) findfunc table - ffstart := writeFindfunctab(&cache, ftab) - - // make pclnt table - pclntab := makePclntable(_funcs, lastFuncsize, pcdataOffs, funcdataOffs) - mod.pclntable = pclntab - - // mmap() text and funcdata segements - p := os.Getpagesize() - size := int(rnd(int64(len(text)), int64(p))) - addr := mmap(size) - // copy the machine code - s := rt.BytesFrom(unsafe.Pointer(addr), len(text), size) - copy(s, text) - // make it executable - mprotect(addr, size) - - // assign addresses - mod.text = addr - mod.etext = addr + uintptr(size) - mod.minpc = addr - mod.maxpc = addr + uintptr(len(text)) - - // cache funcdata and findfuncbucket - moduleCache.Lock() - moduleCache.m[mod] = cache - moduleCache.Unlock() - mod.gofunc = uintptr(unsafe.Pointer(&cache[fstart])) - mod.findfunctab = uintptr(unsafe.Pointer(&cache[ffstart])) - - // make pc header - mod.pcHeader = &pcHeader { - magic : _Magic, - minLC : _MinLC, - ptrSize : _PtrSize, - nfunc : len(funcs), - nfiles: uint(len(cu)), - textStart: mod.text, - funcnameOffset: getOffsetOf(moduledata{}, "funcnametab"), - cuOffset: getOffsetOf(moduledata{}, "cutab"), - filetabOffset: getOffsetOf(moduledata{}, "filetab"), - pctabOffset: getOffsetOf(moduledata{}, "pctab"), - pclnOffset: getOffsetOf(moduledata{}, "pclntable"), - } - - // sepecial case: gcdata and gcbss must by non-empty - mod.gcdata = uintptr(unsafe.Pointer(&emptyByte)) - mod.gcbss = uintptr(unsafe.Pointer(&emptyByte)) - - return -} - -// makePctab generates pcdelta->valuedelta tables for functions, -// and returns the table and the entry offset of every kind pcdata in the table. -func makePctab(funcs []Func, cuOffset []uint32, nameOffset []int32) (pctab []byte, pcdataOffs [][]uint32, _funcs []_func) { - _funcs = make([]_func, len(funcs)) - - // Pctab offsets of 0 are considered invalid in the runtime. We respect - // that by just padding a single byte at the beginning of runtime.pctab, - // that way no real offsets can be zero. - pctab = make([]byte, 1, 12*len(funcs)+1) - pcdataOffs = make([][]uint32, len(funcs)) - - for i, f := range funcs { - _f := &_funcs[i] - - var writer = func(pc *Pcdata) { - var ab []byte - var err error - if pc != nil { - ab, err = pc.MarshalBinary() - if err != nil { - panic(err) - } - pcdataOffs[i] = append(pcdataOffs[i], uint32(len(pctab))) - } else { - ab = []byte{0} - pcdataOffs[i] = append(pcdataOffs[i], _PCDATA_INVALID_OFFSET) - } - pctab = append(pctab, ab...) - } - - if f.Pcsp != nil { - _f.pcsp = uint32(len(pctab)) - } - writer(f.Pcsp) - if f.Pcfile != nil { - _f.pcfile = uint32(len(pctab)) - } - writer(f.Pcfile) - if f.Pcline != nil { - _f.pcln = uint32(len(pctab)) - } - writer(f.Pcline) - writer(f.PcUnsafePoint) - writer(f.PcStackMapIndex) - writer(f.PcInlTreeIndex) - writer(f.PcArgLiveIndex) - - _f.entryOff = f.EntryOff - _f.nameOff = nameOffset[i] - _f.args = f.ArgsSize - _f.deferreturn = f.DeferReturn - // NOTICE: _func.pcdata is always as [PCDATA_UnsafePoint(0) : PCDATA_ArgLiveIndex(3)] - _f.npcdata = uint32(_N_PCDATA) - _f.cuOffset = cuOffset[i] - _f.funcID = f.ID - _f.flag = f.Flag - _f.nfuncdata = uint8(_N_FUNCDATA) - } - - return -} - -func registerFunction(name string, pc uintptr, textSize uintptr, fp int, args int, size uintptr, argptrs uintptr, localptrs uintptr) {}
\ No newline at end of file diff --git a/vendor/github.com/bytedance/sonic/loader/funcdata_go120.go b/vendor/github.com/bytedance/sonic/loader/funcdata_go120.go index 906fe375d..ed3e7d1a4 100644 --- a/vendor/github.com/bytedance/sonic/loader/funcdata_go120.go +++ b/vendor/github.com/bytedance/sonic/loader/funcdata_go120.go @@ -20,10 +20,6 @@ package loader import ( - `encoding` - `os` - `unsafe` - `github.com/bytedance/sonic/internal/rt` ) @@ -51,8 +47,6 @@ type moduledata struct { end, gcdata, gcbss uintptr types, etypes uintptr rodata uintptr - - // TODO: generate funcinfo object to memory gofunc uintptr // go.func.* is actual funcinfo object in image textsectmap []textSection // see runtime/symtab.go: textAddr() @@ -118,428 +112,3 @@ type _func struct { // // funcdata [nfuncdata]uint32 } - -type funcTab struct { - entry uint32 - funcoff uint32 -} - -type pcHeader struct { - magic uint32 // 0xFFFFFFF0 - pad1, pad2 uint8 // 0,0 - minLC uint8 // min instruction size - ptrSize uint8 // size of a ptr in bytes - nfunc int // number of functions in the module - nfiles uint // number of entries in the file tab - textStart uintptr // base for function entry PC offsets in this module, equal to moduledata.text - funcnameOffset uintptr // offset to the funcnametab variable from pcHeader - cuOffset uintptr // offset to the cutab variable from pcHeader - filetabOffset uintptr // offset to the filetab variable from pcHeader - pctabOffset uintptr // offset to the pctab variable from pcHeader - pclnOffset uintptr // offset to the pclntab variable from pcHeader -} - -type bitVector struct { - n int32 // # of bits - bytedata *uint8 -} - -type ptabEntry struct { - name int32 - typ int32 -} - -type textSection struct { - vaddr uintptr // prelinked section vaddr - end uintptr // vaddr + section length - baseaddr uintptr // relocated section address -} - -type modulehash struct { - modulename string - linktimehash string - runtimehash *string -} - -// findfuncbucket is an array of these structures. -// Each bucket represents 4096 bytes of the text segment. -// Each subbucket represents 256 bytes of the text segment. -// To find a function given a pc, locate the bucket and subbucket for -// that pc. Add together the idx and subbucket value to obtain a -// function index. Then scan the functab array starting at that -// index to find the target function. -// This table uses 20 bytes for every 4096 bytes of code, or ~0.5% overhead. -type findfuncbucket struct { - idx uint32 - _SUBBUCKETS [16]byte -} - -// func name table format: -// nameOff[0] -> namePartA namePartB namePartC \x00 -// nameOff[1] -> namePartA namePartB namePartC \x00 -// ... -func makeFuncnameTab(funcs []Func) (tab []byte, offs []int32) { - offs = make([]int32, len(funcs)) - offset := 0 - - for i, f := range funcs { - offs[i] = int32(offset) - - a, b, c := funcNameParts(f.Name) - tab = append(tab, a...) - tab = append(tab, b...) - tab = append(tab, c...) - tab = append(tab, 0) - offset += len(a) + len(b) + len(c) + 1 - } - - return -} - -type compilationUnit struct { - fileNames []string -} - -// CU table format: -// cuOffsets[0] -> filetabOffset[0] filetabOffset[1] ... filetabOffset[len(CUs[0].fileNames)-1] -// cuOffsets[1] -> filetabOffset[len(CUs[0].fileNames)] ... filetabOffset[len(CUs[0].fileNames) + len(CUs[1].fileNames)-1] -// ... -// -// file name table format: -// filetabOffset[0] -> CUs[0].fileNames[0] \x00 -// ... -// filetabOffset[len(CUs[0]-1)] -> CUs[0].fileNames[len(CUs[0].fileNames)-1] \x00 -// ... -// filetabOffset[SUM(CUs,fileNames)-1] -> CUs[len(CU)-1].fileNames[len(CUs[len(CU)-1].fileNames)-1] \x00 -func makeFilenametab(cus []compilationUnit) (cutab []uint32, filetab []byte, cuOffsets []uint32) { - cuOffsets = make([]uint32, len(cus)) - cuOffset := 0 - fileOffset := 0 - - for i, cu := range cus { - cuOffsets[i] = uint32(cuOffset) - - for _, name := range cu.fileNames { - cutab = append(cutab, uint32(fileOffset)) - - fileOffset += len(name) + 1 - filetab = append(filetab, name...) - filetab = append(filetab, 0) - } - - cuOffset += len(cu.fileNames) - } - - return -} - -func writeFuncdata(out *[]byte, funcs []Func) (fstart int, funcdataOffs [][]uint32) { - fstart = len(*out) - *out = append(*out, byte(0)) - offs := uint32(1) - - funcdataOffs = make([][]uint32, len(funcs)) - for i, f := range funcs { - - var writer = func(fd encoding.BinaryMarshaler) { - var ab []byte - var err error - if fd != nil { - ab, err = fd.MarshalBinary() - if err != nil { - panic(err) - } - funcdataOffs[i] = append(funcdataOffs[i], offs) - } else { - ab = []byte{0} - funcdataOffs[i] = append(funcdataOffs[i], _INVALID_FUNCDATA_OFFSET) - } - *out = append(*out, ab...) - offs += uint32(len(ab)) - } - - writer(f.ArgsPointerMaps) - writer(f.LocalsPointerMaps) - writer(f.StackObjects) - writer(f.InlTree) - writer(f.OpenCodedDeferInfo) - writer(f.ArgInfo) - writer(f.ArgLiveInfo) - writer(f.WrapInfo) - } - return -} - -func makeFtab(funcs []_func, lastFuncSize uint32) (ftab []funcTab) { - // Allocate space for the pc->func table. This structure consists of a pc offset - // and an offset to the func structure. After that, we have a single pc - // value that marks the end of the last function in the binary. - var size int64 = int64(len(funcs)*2*4 + 4) - var startLocations = make([]uint32, len(funcs)) - for i, f := range funcs { - size = rnd(size, int64(_PtrSize)) - //writePCToFunc - startLocations[i] = uint32(size) - size += int64(uint8(_FUNC_SIZE)+f.nfuncdata*4+uint8(f.npcdata)*4) - } - - ftab = make([]funcTab, 0, len(funcs)+1) - - // write a map of pc->func info offsets - for i, f := range funcs { - ftab = append(ftab, funcTab{uint32(f.entryOff), uint32(startLocations[i])}) - } - - // Final entry of table is just end pc offset. - lastFunc := funcs[len(funcs)-1] - ftab = append(ftab, funcTab{uint32(lastFunc.entryOff + lastFuncSize), 0}) - - return -} - -// Pcln table format: [...]funcTab + [...]_Func -func makePclntable(funcs []_func, lastFuncSize uint32, pcdataOffs [][]uint32, funcdataOffs [][]uint32) (pclntab []byte) { - // Allocate space for the pc->func table. This structure consists of a pc offset - // and an offset to the func structure. After that, we have a single pc - // value that marks the end of the last function in the binary. - var size int64 = int64(len(funcs)*2*4 + 4) - var startLocations = make([]uint32, len(funcs)) - for i := range funcs { - size = rnd(size, int64(_PtrSize)) - //writePCToFunc - startLocations[i] = uint32(size) - size += int64(int(_FUNC_SIZE)+len(funcdataOffs[i])*4+len(pcdataOffs[i])*4) - } - - pclntab = make([]byte, size, size) - - // write a map of pc->func info offsets - offs := 0 - for i, f := range funcs { - byteOrder.PutUint32(pclntab[offs:offs+4], uint32(f.entryOff)) - byteOrder.PutUint32(pclntab[offs+4:offs+8], uint32(startLocations[i])) - offs += 8 - } - // Final entry of table is just end pc offset. - lastFunc := funcs[len(funcs)-1] - byteOrder.PutUint32(pclntab[offs:offs+4], uint32(lastFunc.entryOff+lastFuncSize)) - - // write func info table - for i, f := range funcs { - off := startLocations[i] - - // write _func structure to pclntab - fb := rt.BytesFrom(unsafe.Pointer(&f), int(_FUNC_SIZE), int(_FUNC_SIZE)) - copy(pclntab[off:off+uint32(_FUNC_SIZE)], fb) - off += uint32(_FUNC_SIZE) - - // NOTICE: _func.pcdata always starts from PcUnsafePoint, which is index 3 - for j := 3; j < len(pcdataOffs[i]); j++ { - byteOrder.PutUint32(pclntab[off:off+4], uint32(pcdataOffs[i][j])) - off += 4 - } - - // funcdata refs as offsets from gofunc - for _, funcdata := range funcdataOffs[i] { - byteOrder.PutUint32(pclntab[off:off+4], uint32(funcdata)) - off += 4 - } - - } - - return -} - -// findfunc table used to map pc to belonging func, -// returns the index in the func table. -// -// All text section are divided into buckets sized _BUCKETSIZE(4K): -// every bucket is divided into _SUBBUCKETS sized _SUB_BUCKETSIZE(64), -// and it has a base idx to plus the offset stored in jth subbucket. -// see findfunc() in runtime/symtab.go -func writeFindfunctab(out *[]byte, ftab []funcTab) (start int) { - start = len(*out) - - max := ftab[len(ftab)-1].entry - min := ftab[0].entry - nbuckets := (max - min + _BUCKETSIZE - 1) / _BUCKETSIZE - n := (max - min + _SUB_BUCKETSIZE - 1) / _SUB_BUCKETSIZE - - tab := make([]findfuncbucket, 0, nbuckets) - var s, e = 0, 0 - for i := 0; i<int(nbuckets); i++ { - var pc = min + uint32((i+1)*_BUCKETSIZE) - // find the end func of the bucket - for ; e < len(ftab)-1 && ftab[e+1].entry <= pc; e++ {} - // store the start func of the bucket - var fb = findfuncbucket{idx: uint32(s)} - - for j := 0; j<_SUBBUCKETS && (i*_SUBBUCKETS+j)<int(n); j++ { - pc = min + uint32(i*_BUCKETSIZE) + uint32((j+1)*_SUB_BUCKETSIZE) - var ss = s - // find the end func of the subbucket - for ; ss < len(ftab)-1 && ftab[ss+1].entry <= pc; ss++ {} - // store the start func of the subbucket - fb._SUBBUCKETS[j] = byte(uint32(s) - fb.idx) - s = ss - } - s = e - tab = append(tab, fb) - } - - // write findfuncbucket - if len(tab) > 0 { - size := int(unsafe.Sizeof(findfuncbucket{}))*len(tab) - *out = append(*out, rt.BytesFrom(unsafe.Pointer(&tab[0]), size, size)...) - } - return -} - -func makeModuledata(name string, filenames []string, funcs []Func, text []byte) (mod *moduledata) { - mod = new(moduledata) - mod.modulename = name - - // make filename table - cu := make([]string, 0, len(filenames)) - for _, f := range filenames { - cu = append(cu, f) - } - cutab, filetab, cuOffs := makeFilenametab([]compilationUnit{{cu}}) - mod.cutab = cutab - mod.filetab = filetab - - // make funcname table - funcnametab, nameOffs := makeFuncnameTab(funcs) - mod.funcnametab = funcnametab - - // make pcdata table - // NOTICE: _func only use offset to index pcdata, thus no need mmap() pcdata - pctab, pcdataOffs, _funcs := makePctab(funcs, cuOffs, nameOffs) - mod.pctab = pctab - - // write func data - // NOTICE: _func use mod.gofunc+offset to directly point funcdata, thus need cache funcdata - // TODO: estimate accurate capacity - cache := make([]byte, 0, len(funcs)*int(_PtrSize)) - fstart, funcdataOffs := writeFuncdata(&cache, funcs) - - // make pc->func (binary search) func table - lastFuncsize := funcs[len(funcs)-1].TextSize - ftab := makeFtab(_funcs, lastFuncsize) - mod.ftab = ftab - - // write pc->func (modmap) findfunc table - ffstart := writeFindfunctab(&cache, ftab) - - // make pclnt table - pclntab := makePclntable(_funcs, lastFuncsize, pcdataOffs, funcdataOffs) - mod.pclntable = pclntab - - // mmap() text and funcdata segements - p := os.Getpagesize() - size := int(rnd(int64(len(text)), int64(p))) - addr := mmap(size) - // copy the machine code - s := rt.BytesFrom(unsafe.Pointer(addr), len(text), size) - copy(s, text) - // make it executable - mprotect(addr, size) - - // assign addresses - mod.text = addr - mod.etext = addr + uintptr(size) - mod.minpc = addr - mod.maxpc = addr + uintptr(len(text)) - - // cache funcdata and findfuncbucket - moduleCache.Lock() - moduleCache.m[mod] = cache - moduleCache.Unlock() - mod.gofunc = uintptr(unsafe.Pointer(&cache[fstart])) - mod.findfunctab = uintptr(unsafe.Pointer(&cache[ffstart])) - - // make pc header - mod.pcHeader = &pcHeader { - magic : _Magic, - minLC : _MinLC, - ptrSize : _PtrSize, - nfunc : len(funcs), - nfiles: uint(len(cu)), - textStart: mod.text, - funcnameOffset: getOffsetOf(moduledata{}, "funcnametab"), - cuOffset: getOffsetOf(moduledata{}, "cutab"), - filetabOffset: getOffsetOf(moduledata{}, "filetab"), - pctabOffset: getOffsetOf(moduledata{}, "pctab"), - pclnOffset: getOffsetOf(moduledata{}, "pclntable"), - } - - // sepecial case: gcdata and gcbss must by non-empty - mod.gcdata = uintptr(unsafe.Pointer(&emptyByte)) - mod.gcbss = uintptr(unsafe.Pointer(&emptyByte)) - - return -} - -// makePctab generates pcdelta->valuedelta tables for functions, -// and returns the table and the entry offset of every kind pcdata in the table. -func makePctab(funcs []Func, cuOffset []uint32, nameOffset []int32) (pctab []byte, pcdataOffs [][]uint32, _funcs []_func) { - _funcs = make([]_func, len(funcs)) - - // Pctab offsets of 0 are considered invalid in the runtime. We respect - // that by just padding a single byte at the beginning of runtime.pctab, - // that way no real offsets can be zero. - pctab = make([]byte, 1, 12*len(funcs)+1) - pcdataOffs = make([][]uint32, len(funcs)) - - for i, f := range funcs { - _f := &_funcs[i] - - var writer = func(pc *Pcdata) { - var ab []byte - var err error - if pc != nil { - ab, err = pc.MarshalBinary() - if err != nil { - panic(err) - } - pcdataOffs[i] = append(pcdataOffs[i], uint32(len(pctab))) - } else { - ab = []byte{0} - pcdataOffs[i] = append(pcdataOffs[i], _PCDATA_INVALID_OFFSET) - } - pctab = append(pctab, ab...) - } - - if f.Pcsp != nil { - _f.pcsp = uint32(len(pctab)) - } - writer(f.Pcsp) - if f.Pcfile != nil { - _f.pcfile = uint32(len(pctab)) - } - writer(f.Pcfile) - if f.Pcline != nil { - _f.pcln = uint32(len(pctab)) - } - writer(f.Pcline) - writer(f.PcUnsafePoint) - writer(f.PcStackMapIndex) - writer(f.PcInlTreeIndex) - writer(f.PcArgLiveIndex) - - _f.entryOff = f.EntryOff - _f.nameOff = nameOffset[i] - _f.args = f.ArgsSize - _f.deferreturn = f.DeferReturn - // NOTICE: _func.pcdata is always as [PCDATA_UnsafePoint(0) : PCDATA_ArgLiveIndex(3)] - _f.npcdata = uint32(_N_PCDATA) - _f.cuOffset = cuOffset[i] - _f.funcID = f.ID - _f.flag = f.Flag - _f.nfuncdata = uint8(_N_FUNCDATA) - } - - return -} - -func registerFunction(name string, pc uintptr, textSize uintptr, fp int, args int, size uintptr, argptrs uintptr, localptrs uintptr) {}
\ No newline at end of file diff --git a/vendor/github.com/bytedance/sonic/loader/funcdata_go121.go b/vendor/github.com/bytedance/sonic/loader/funcdata_go121.go new file mode 100644 index 000000000..f50663e2a --- /dev/null +++ b/vendor/github.com/bytedance/sonic/loader/funcdata_go121.go @@ -0,0 +1,119 @@ +//go:build go1.21 && !go1.22 +// +build go1.21,!go1.22 + +/* + * Copyright 2021 ByteDance Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package loader + +import ( + `unsafe` + `github.com/bytedance/sonic/internal/rt` +) + +const ( + _Magic uint32 = 0xFFFFFFF1 +) + +type moduledata struct { + pcHeader *pcHeader + funcnametab []byte + cutab []uint32 + filetab []byte + pctab []byte + pclntable []byte + ftab []funcTab + findfunctab uintptr + minpc, maxpc uintptr // first func address, last func address + last func size + + text, etext uintptr // start/end of text, (etext-text) must be greater than MIN_FUNC + noptrdata, enoptrdata uintptr + data, edata uintptr + bss, ebss uintptr + noptrbss, enoptrbss uintptr + covctrs, ecovctrs uintptr + end, gcdata, gcbss uintptr + types, etypes uintptr + rodata uintptr + gofunc uintptr // go.func.* is actual funcinfo object in image + + textsectmap []textSection // see runtime/symtab.go: textAddr() + typelinks []int32 // offsets from types + itablinks []*rt.GoItab + + ptab []ptabEntry + + pluginpath string + pkghashes []modulehash + + // This slice records the initializing tasks that need to be + // done to start up the program. It is built by the linker. + inittasks []unsafe.Pointer + + modulename string + modulehashes []modulehash + + hasmain uint8 // 1 if module contains the main function, 0 otherwise + + gcdatamask, gcbssmask bitVector + + typemap map[int32]*rt.GoType // offset to *_rtype in previous module + + bad bool // module failed to load and should be ignored + + next *moduledata +} + +type _func struct { + entryOff uint32 // start pc, as offset from moduledata.text/pcHeader.textStart + nameOff int32 // function name, as index into moduledata.funcnametab. + + args int32 // in/out args size + deferreturn uint32 // offset of start of a deferreturn call instruction from entry, if any. + + pcsp uint32 + pcfile uint32 + pcln uint32 + npcdata uint32 + cuOffset uint32 // runtime.cutab offset of this function's CU + startLine int32 // line number of start of function (func keyword/TEXT directive) + funcID uint8 // set for certain special runtime functions + flag uint8 + _ [1]byte // pad + nfuncdata uint8 // + + // The end of the struct is followed immediately by two variable-length + // arrays that reference the pcdata and funcdata locations for this + // function. + + // pcdata contains the offset into moduledata.pctab for the start of + // that index's table. e.g., + // &moduledata.pctab[_func.pcdata[_PCDATA_UnsafePoint]] is the start of + // the unsafe point table. + // + // An offset of 0 indicates that there is no table. + // + // pcdata [npcdata]uint32 + + // funcdata contains the offset past moduledata.gofunc which contains a + // pointer to that index's funcdata. e.g., + // *(moduledata.gofunc + _func.funcdata[_FUNCDATA_ArgsPointerMaps]) is + // the argument pointer map. + // + // An offset of ^uint32(0) indicates that there is no entry. + // + // funcdata [nfuncdata]uint32 +} diff --git a/vendor/github.com/bytedance/sonic/loader/funcdata_latest.go b/vendor/github.com/bytedance/sonic/loader/funcdata_latest.go new file mode 100644 index 000000000..52c6097fb --- /dev/null +++ b/vendor/github.com/bytedance/sonic/loader/funcdata_latest.go @@ -0,0 +1,355 @@ +// go:build go1.18 && !go1.22 +// +build go1.18,!go1.22 + +/* + * Copyright 2021 ByteDance Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package loader + +import ( + `os` + `sort` + `unsafe` + + `github.com/bytedance/sonic/internal/rt` +) + +type funcTab struct { + entry uint32 + funcoff uint32 +} + +type pcHeader struct { + magic uint32 // 0xFFFFFFF0 + pad1, pad2 uint8 // 0,0 + minLC uint8 // min instruction size + ptrSize uint8 // size of a ptr in bytes + nfunc int // number of functions in the module + nfiles uint // number of entries in the file tab + textStart uintptr // base for function entry PC offsets in this module, equal to moduledata.text + funcnameOffset uintptr // offset to the funcnametab variable from pcHeader + cuOffset uintptr // offset to the cutab variable from pcHeader + filetabOffset uintptr // offset to the filetab variable from pcHeader + pctabOffset uintptr // offset to the pctab variable from pcHeader + pclnOffset uintptr // offset to the pclntab variable from pcHeader +} + +type bitVector struct { + n int32 // # of bits + bytedata *uint8 +} + +type ptabEntry struct { + name int32 + typ int32 +} + +type textSection struct { + vaddr uintptr // prelinked section vaddr + end uintptr // vaddr + section length + baseaddr uintptr // relocated section address +} + +type modulehash struct { + modulename string + linktimehash string + runtimehash *string +} + +// findfuncbucket is an array of these structures. +// Each bucket represents 4096 bytes of the text segment. +// Each subbucket represents 256 bytes of the text segment. +// To find a function given a pc, locate the bucket and subbucket for +// that pc. Add together the idx and subbucket value to obtain a +// function index. Then scan the functab array starting at that +// index to find the target function. +// This table uses 20 bytes for every 4096 bytes of code, or ~0.5% overhead. +type findfuncbucket struct { + idx uint32 + _SUBBUCKETS [16]byte +} + +type compilationUnit struct { + fileNames []string +} + +func makeFtab(funcs []_func, maxpc uint32) (ftab []funcTab, pclntabSize int64, startLocations []uint32) { + // Allocate space for the pc->func table. This structure consists of a pc offset + // and an offset to the func structure. After that, we have a single pc + // value that marks the end of the last function in the binary. + pclntabSize = int64(len(funcs)*2*int(_PtrSize) + int(_PtrSize)) + startLocations = make([]uint32, len(funcs)) + for i, f := range funcs { + pclntabSize = rnd(pclntabSize, int64(_PtrSize)) + //writePCToFunc + startLocations[i] = uint32(pclntabSize) + pclntabSize += int64(uint8(_FUNC_SIZE)+f.nfuncdata*4+uint8(f.npcdata)*4) + } + + ftab = make([]funcTab, 0, len(funcs)+1) + + // write a map of pc->func info offsets + for i, f := range funcs { + ftab = append(ftab, funcTab{uint32(f.entryOff), uint32(startLocations[i])}) + } + + // Final entry of table is just end pc offset. + ftab = append(ftab, funcTab{maxpc, 0}) + return +} + +// Pcln table format: [...]funcTab + [...]_Func +func makePclntable(size int64, startLocations []uint32, funcs []_func, maxpc uint32, pcdataOffs [][]uint32, funcdataOffs [][]uint32) (pclntab []byte) { + // Allocate space for the pc->func table. This structure consists of a pc offset + // and an offset to the func structure. After that, we have a single pc + // value that marks the end of the last function in the binary. + pclntab = make([]byte, size, size) + + // write a map of pc->func info offsets + offs := 0 + for i, f := range funcs { + byteOrder.PutUint32(pclntab[offs:offs+4], uint32(f.entryOff)) + byteOrder.PutUint32(pclntab[offs+4:offs+8], uint32(startLocations[i])) + offs += 8 + } + // Final entry of table is just end pc offset. + byteOrder.PutUint32(pclntab[offs:offs+4], maxpc) + + // write func info table + for i := range funcs { + off := startLocations[i] + + // write _func structure to pclntab + fb := rt.BytesFrom(unsafe.Pointer(&funcs[i]), int(_FUNC_SIZE), int(_FUNC_SIZE)) + copy(pclntab[off:off+uint32(_FUNC_SIZE)], fb) + off += uint32(_FUNC_SIZE) + + // NOTICE: _func.pcdata always starts from PcUnsafePoint, which is index 3 + for j := 3; j < len(pcdataOffs[i]); j++ { + byteOrder.PutUint32(pclntab[off:off+4], uint32(pcdataOffs[i][j])) + off += 4 + } + + // funcdata refs as offsets from gofunc + for _, funcdata := range funcdataOffs[i] { + byteOrder.PutUint32(pclntab[off:off+4], uint32(funcdata)) + off += 4 + } + + } + + return +} + +// findfunc table used to map pc to belonging func, +// returns the index in the func table. +// +// All text section are divided into buckets sized _BUCKETSIZE(4K): +// every bucket is divided into _SUBBUCKETS sized _SUB_BUCKETSIZE(64), +// and it has a base idx to plus the offset stored in jth subbucket. +// see findfunc() in runtime/symtab.go +func writeFindfunctab(out *[]byte, ftab []funcTab) (start int) { + start = len(*out) + + max := ftab[len(ftab)-1].entry + min := ftab[0].entry + nbuckets := (max - min + _BUCKETSIZE - 1) / _BUCKETSIZE + n := (max - min + _SUB_BUCKETSIZE - 1) / _SUB_BUCKETSIZE + + tab := make([]findfuncbucket, 0, nbuckets) + var s, e = 0, 0 + for i := 0; i<int(nbuckets); i++ { + // store the start s-th func of the bucket + var fb = findfuncbucket{idx: uint32(s)} + + // find the last e-th func of the bucket + var pc = min + uint32((i+1)*_BUCKETSIZE) + for ; e < len(ftab)-1 && ftab[e+1].entry <= pc; e++ {} + + for j := 0; j<_SUBBUCKETS && (i*_SUBBUCKETS+j)<int(n); j++ { + // store the start func of the subbucket + fb._SUBBUCKETS[j] = byte(uint32(s) - fb.idx) + + // find the s-th end func of the subbucket + pc = min + uint32(i*_BUCKETSIZE) + uint32((j+1)*_SUB_BUCKETSIZE) + for ; s < len(ftab)-1 && ftab[s+1].entry <= pc; s++ {} + } + + s = e + tab = append(tab, fb) + } + + // write findfuncbucket + if len(tab) > 0 { + size := int(unsafe.Sizeof(findfuncbucket{}))*len(tab) + *out = append(*out, rt.BytesFrom(unsafe.Pointer(&tab[0]), size, size)...) + } + return +} + +func makeModuledata(name string, filenames []string, funcsp *[]Func, text []byte) (mod *moduledata) { + mod = new(moduledata) + mod.modulename = name + + // sort funcs by entry + funcs := *funcsp + sort.Slice(funcs, func(i, j int) bool { + return funcs[i].EntryOff < funcs[j].EntryOff + }) + *funcsp = funcs + + // make filename table + cu := make([]string, 0, len(filenames)) + cu = append(cu, filenames...) + cutab, filetab, cuOffs := makeFilenametab([]compilationUnit{{cu}}) + mod.cutab = cutab + mod.filetab = filetab + + // make funcname table + funcnametab, nameOffs := makeFuncnameTab(funcs) + mod.funcnametab = funcnametab + + // mmap() text and funcdata segements + p := os.Getpagesize() + size := int(rnd(int64(len(text)), int64(p))) + addr := mmap(size) + // copy the machine code + s := rt.BytesFrom(unsafe.Pointer(addr), len(text), size) + copy(s, text) + // make it executable + mprotect(addr, size) + + // assign addresses + mod.text = addr + mod.etext = addr + uintptr(size) + mod.minpc = addr + mod.maxpc = addr + uintptr(len(text)) + + // make pcdata table + // NOTICE: _func only use offset to index pcdata, thus no need mmap() pcdata + cuOff := cuOffs[0] + pctab, pcdataOffs, _funcs := makePctab(funcs, cuOff, nameOffs) + mod.pctab = pctab + + // write func data + // NOTICE: _func use mod.gofunc+offset to directly point funcdata, thus need cache funcdata + // TODO: estimate accurate capacity + cache := make([]byte, 0, len(funcs)*int(_PtrSize)) + fstart, funcdataOffs := writeFuncdata(&cache, funcs) + + // make pc->func (binary search) func table + ftab, pclntSize, startLocations := makeFtab(_funcs, uint32(len(text))) + mod.ftab = ftab + + // write pc->func (modmap) findfunc table + ffstart := writeFindfunctab(&cache, ftab) + + // cache funcdata and findfuncbucket + moduleCache.Lock() + moduleCache.m[mod] = cache + moduleCache.Unlock() + mod.gofunc = uintptr(unsafe.Pointer(&cache[fstart])) + mod.findfunctab = uintptr(unsafe.Pointer(&cache[ffstart])) + + // make pclnt table + pclntab := makePclntable(pclntSize, startLocations, _funcs, uint32(len(text)), pcdataOffs, funcdataOffs) + mod.pclntable = pclntab + + // make pc header + mod.pcHeader = &pcHeader { + magic : _Magic, + minLC : _MinLC, + ptrSize : _PtrSize, + nfunc : len(funcs), + nfiles: uint(len(cu)), + textStart: mod.text, + funcnameOffset: getOffsetOf(moduledata{}, "funcnametab"), + cuOffset: getOffsetOf(moduledata{}, "cutab"), + filetabOffset: getOffsetOf(moduledata{}, "filetab"), + pctabOffset: getOffsetOf(moduledata{}, "pctab"), + pclnOffset: getOffsetOf(moduledata{}, "pclntable"), + } + + // sepecial case: gcdata and gcbss must by non-empty + mod.gcdata = uintptr(unsafe.Pointer(&emptyByte)) + mod.gcbss = uintptr(unsafe.Pointer(&emptyByte)) + + return +} + +// makePctab generates pcdelta->valuedelta tables for functions, +// and returns the table and the entry offset of every kind pcdata in the table. +func makePctab(funcs []Func, cuOffset uint32, nameOffset []int32) (pctab []byte, pcdataOffs [][]uint32, _funcs []_func) { + _funcs = make([]_func, len(funcs)) + + // Pctab offsets of 0 are considered invalid in the runtime. We respect + // that by just padding a single byte at the beginning of runtime.pctab, + // that way no real offsets can be zero. + pctab = make([]byte, 1, 12*len(funcs)+1) + pcdataOffs = make([][]uint32, len(funcs)) + + for i, f := range funcs { + _f := &_funcs[i] + + var writer = func(pc *Pcdata) { + var ab []byte + var err error + if pc != nil { + ab, err = pc.MarshalBinary() + if err != nil { + panic(err) + } + pcdataOffs[i] = append(pcdataOffs[i], uint32(len(pctab))) + } else { + ab = []byte{0} + pcdataOffs[i] = append(pcdataOffs[i], _PCDATA_INVALID_OFFSET) + } + pctab = append(pctab, ab...) + } + + if f.Pcsp != nil { + _f.pcsp = uint32(len(pctab)) + } + writer(f.Pcsp) + if f.Pcfile != nil { + _f.pcfile = uint32(len(pctab)) + } + writer(f.Pcfile) + if f.Pcline != nil { + _f.pcln = uint32(len(pctab)) + } + writer(f.Pcline) + writer(f.PcUnsafePoint) + writer(f.PcStackMapIndex) + writer(f.PcInlTreeIndex) + writer(f.PcArgLiveIndex) + + _f.entryOff = f.EntryOff + _f.nameOff = nameOffset[i] + _f.args = f.ArgsSize + _f.deferreturn = f.DeferReturn + // NOTICE: _func.pcdata is always as [PCDATA_UnsafePoint(0) : PCDATA_ArgLiveIndex(3)] + _f.npcdata = uint32(_N_PCDATA) + _f.cuOffset = cuOffset + _f.funcID = f.ID + _f.flag = f.Flag + _f.nfuncdata = uint8(_N_FUNCDATA) + } + + return +} + +func registerFunction(name string, pc uintptr, textSize uintptr, fp int, args int, size uintptr, argptrs uintptr, localptrs uintptr) {} diff --git a/vendor/github.com/bytedance/sonic/loader/loader.go b/vendor/github.com/bytedance/sonic/loader/loader.go index 929d8c23d..43eaeb459 100644 --- a/vendor/github.com/bytedance/sonic/loader/loader.go +++ b/vendor/github.com/bytedance/sonic/loader/loader.go @@ -34,4 +34,4 @@ type Loader struct { Name string // module name File string // file name Options -}
\ No newline at end of file +} diff --git a/vendor/github.com/bytedance/sonic/loader/loader_go115.go b/vendor/github.com/bytedance/sonic/loader/loader_go115.go deleted file mode 100644 index a1d4d7892..000000000 --- a/vendor/github.com/bytedance/sonic/loader/loader_go115.go +++ /dev/null @@ -1,28 +0,0 @@ -//go:build go1.15 && !go1.16 -// +build go1.15,!go1.16 - -/* - * Copyright 2021 ByteDance Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package loader - -import ( - `github.com/bytedance/sonic/internal/loader` -) - -func (self Loader) LoadOne(text []byte, funcName string, frameSize int, argSize int, argStackmap []bool, localStackmap []bool) Function { - return Function(loader.Loader(text).Load(funcName, frameSize, argSize, argStackmap, localStackmap)) -}
\ No newline at end of file diff --git a/vendor/github.com/bytedance/sonic/loader/loader_go116.go b/vendor/github.com/bytedance/sonic/loader/loader_latest.go index ea30ec9a5..b6e3e75f8 100644 --- a/vendor/github.com/bytedance/sonic/loader/loader_go116.go +++ b/vendor/github.com/bytedance/sonic/loader/loader_latest.go @@ -1,5 +1,5 @@ -//go:build go1.16 && !go1.21 -// +build go1.16,!go1.21 +//go:build go1.16 && !go1.22 +// +build go1.16,!go1.22 /* * Copyright 2021 ByteDance Inc. @@ -87,18 +87,27 @@ func (self Loader) LoadOne(text []byte, funcName string, frameSize int, argSize // and returns runnable function pointer // WARN: this API is experimental, use it carefully func Load(text []byte, funcs []Func, modulename string, filenames []string) (out []Function) { + ids := make([]string, len(funcs)) + for i, f := range funcs { + ids[i] = f.Name + } // generate module data and allocate memory address - mod := makeModuledata(modulename, filenames, funcs, text) + mod := makeModuledata(modulename, filenames, &funcs, text) // verify and register the new module moduledataverify1(mod) registerModule(mod) + // // encapsulate function address out = make([]Function, len(funcs)) - for i, f := range funcs { - m := uintptr(mod.text + uintptr(f.EntryOff)) - out[i] = Function(&m) + for i, s := range ids { + for _, f := range funcs { + if f.Name == s { + m := uintptr(mod.text + uintptr(f.EntryOff)) + out[i] = Function(&m) + } + } } return -}
\ No newline at end of file +} diff --git a/vendor/github.com/bytedance/sonic/loader/mmap_unix.go b/vendor/github.com/bytedance/sonic/loader/mmap_unix.go index 50b80bf20..3ea944ed6 100644 --- a/vendor/github.com/bytedance/sonic/loader/mmap_unix.go +++ b/vendor/github.com/bytedance/sonic/loader/mmap_unix.go @@ -42,4 +42,4 @@ func mprotect(p uintptr, nb int) { if _, _, err := syscall.RawSyscall(syscall.SYS_MPROTECT, p, uintptr(nb), _RX); err != 0 { panic(err) } -}
\ No newline at end of file +} diff --git a/vendor/github.com/bytedance/sonic/loader/pcdata.go b/vendor/github.com/bytedance/sonic/loader/pcdata.go index b5c62d17b..efab4dac3 100644 --- a/vendor/github.com/bytedance/sonic/loader/pcdata.go +++ b/vendor/github.com/bytedance/sonic/loader/pcdata.go @@ -16,6 +16,10 @@ package loader +import ( + `encoding/binary` +) + const ( _N_PCDATA = 4 @@ -49,40 +53,16 @@ const ( var emptyByte byte -func encodeValue(v int) []byte { - return encodeVariant(toZigzag(v)) -} - -func toZigzag(v int) int { - return (v << 1) ^ (v >> 31) -} - -func encodeVariant(v int) []byte { - var u int - var r []byte - - /* split every 7 bits */ - for v > 127 { - u = v & 0x7f - v = v >> 7 - r = append(r, byte(u) | 0x80) - } - - /* check for last one */ - if v == 0 { - return r - } - - /* add the last one */ - r = append(r, byte(v)) - return r -} - +// Pcvalue is the program count corresponding to the value Val +// WARN: we use relative value here (to function entry) type Pcvalue struct { - PC uint32 // PC offset from func entry - Val int32 + PC uint32 // program count relative to function entry + Val int32 // value relative to the value in function entry } +// Pcdata represents pc->value mapping table. +// WARN: we use ** [Pcdata[i].PC, Pcdata[i+1].PC) ** +// as the range where the Pcdata[i].Val is effective. type Pcdata []Pcvalue // see https://docs.google.com/document/d/1lyPIbmsYbXnpNj57a261hgOYVpNRcgydurVQIyZOz_o/pub @@ -90,11 +70,24 @@ func (self Pcdata) MarshalBinary() (data []byte, err error) { // delta value always starts from -1 sv := int32(_PCDATA_START_VAL) sp := uint32(0) + buf := make([]byte, binary.MaxVarintLen32) for _, v := range self { - data = append(data, encodeVariant(toZigzag(int(v.Val - sv)))...) - data = append(data, encodeVariant(int(v.PC - sp))...) + if v.PC < sp { + panic("PC must be in ascending order!") + } + dp := uint64(v.PC - sp) + dv := int64(v.Val - sv) + if dv == 0 || dp == 0 { + continue + } + n := binary.PutVarint(buf, dv) + data = append(data, buf[:n]...) + n2 := binary.PutUvarint(buf, dp) + data = append(data, buf[:n2]...) sp = v.PC sv = v.Val } + // put 0 to indicate ends + data = append(data, 0) return -}
\ No newline at end of file +} diff --git a/vendor/github.com/bytedance/sonic/loader/wrapper.go b/vendor/github.com/bytedance/sonic/loader/wrapper.go new file mode 100644 index 000000000..73ebc3518 --- /dev/null +++ b/vendor/github.com/bytedance/sonic/loader/wrapper.go @@ -0,0 +1,185 @@ +/** +* Copyright 2023 ByteDance Inc. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +package loader + +import ( + `reflect` + `unsafe` + + `github.com/bytedance/sonic/internal/abi` + `github.com/bytedance/sonic/internal/rt` +) + +var _C_Redzone = []bool{false, false, false, false} + +// CFunc is a function information for C func +type CFunc struct { + // C function name + Name string + + // entry pc relative to entire text segment + EntryOff uint32 + + // function text size in bytes + TextSize uint32 + + // maximum stack depth of the function + MaxStack uintptr + + // PC->SP delta lists of the function + Pcsp [][2]uint32 +} + +// GoC is the wrapper for Go calls to C +type GoC struct { + // CName is the name of corresponding C function + CName string + + // CEntry points out where to store the entry address of corresponding C function. + // It won't be set if nil + CEntry *uintptr + + // GoFunc is the POINTER of corresponding go stub function. + // It is used to generate Go-C ABI conversion wrapper and receive the wrapper's address + // eg. &func(a int, b int) int + // FOR + // int add(int a, int b) + // It won't be set if nil + GoFunc interface{} +} + +// WrapGoC wraps C functions and loader it into Go stubs +func WrapGoC(text []byte, natives []CFunc, stubs []GoC, modulename string, filename string) { + funcs := make([]Func, len(natives)) + + // register C funcs + for i, f := range natives { + fn := Func{ + Flag: FuncFlag_ASM, + EntryOff: f.EntryOff, + TextSize: f.TextSize, + Name: f.Name, + } + if len(f.Pcsp) != 0 { + fn.Pcsp = (*Pcdata)(unsafe.Pointer(&natives[i].Pcsp)) + } + // NOTICE: always forbid async preempt + fn.PcUnsafePoint = &Pcdata{ + {PC: f.TextSize, Val: PCDATA_UnsafePointUnsafe}, + } + // NOTICE: always refer to first file + fn.Pcfile = &Pcdata{ + {PC: f.TextSize, Val: 0}, + } + // NOTICE: always refer to first line + fn.Pcline = &Pcdata{ + {PC: f.TextSize, Val: 1}, + } + // NOTICE: copystack need locals stackmap + fn.PcStackMapIndex = &Pcdata{ + {PC: f.TextSize, Val: 0}, + } + sm := rt.StackMapBuilder{} + sm.AddField(false) + fn.ArgsPointerMaps = sm.Build() + fn.LocalsPointerMaps = sm.Build() + funcs[i] = fn + } + rets := Load(text, funcs, modulename, []string{filename}) + + // got absolute entry address + native_entry := **(**uintptr)(unsafe.Pointer(&rets[0])) + // println("native_entry: ", native_entry) + + wraps := make([]Func, 0, len(stubs)) + wrapIds := make([]int, 0, len(stubs)) + code := make([]byte, 0, len(wraps)) + entryOff := uint32(0) + + // register go wrappers + for i := range stubs { + for j := range natives { + if stubs[i].CName != natives[j].Name { + continue + } + + // calculate corresponding C entry + pc := uintptr(native_entry + uintptr(natives[j].EntryOff)) + if stubs[i].CEntry != nil { + *stubs[i].CEntry = pc + } + + // no need to generate wrapper, continue next + if stubs[i].GoFunc == nil { + continue + } + + // assemble wrapper codes + layout := abi.NewFunctionLayout(reflect.TypeOf(stubs[i].GoFunc).Elem()) + frame := abi.NewFrame(&layout, _C_Redzone, true) + tcode := abi.CallC(pc, frame, natives[j].MaxStack) + code = append(code, tcode...) + size := uint32(len(tcode)) + + fn := Func{ + Flag: FuncFlag_ASM, + ArgsSize: int32(layout.ArgSize()), + EntryOff: entryOff, + TextSize: size, + Name: stubs[i].CName + "_go", + } + + // add check-stack and grow-stack texts' pcsp + fn.Pcsp = &Pcdata{ + {PC: uint32(frame.StackCheckTextSize()), Val: 0}, + {PC: size - uint32(frame.GrowStackTextSize()), Val: int32(frame.Size())}, + {PC: size, Val: 0}, + } + // NOTICE: always refer to first file + fn.Pcfile = &Pcdata{ + {PC: size, Val: 0}, + } + // NOTICE: always refer to first line + fn.Pcline = &Pcdata{ + {PC: size, Val: 1}, + } + // NOTICE: always forbid async preempt + fn.PcUnsafePoint = &Pcdata{ + {PC: size, Val: PCDATA_UnsafePointUnsafe}, + } + + // register pointer stackmaps + fn.PcStackMapIndex = &Pcdata{ + {PC: size, Val: 0}, + } + fn.ArgsPointerMaps = frame.ArgPtrs() + fn.LocalsPointerMaps = frame.LocalPtrs() + + entryOff += size + wraps = append(wraps, fn) + wrapIds = append(wrapIds, i) + } + } + gofuncs := Load(code, wraps, modulename+"/go", []string{filename+".go"}) + + // set go func value + for i := range gofuncs { + idx := wrapIds[i] + w := rt.UnpackEface(stubs[idx].GoFunc) + *(*Function)(w.Value) = gofuncs[i] + } +} |