summaryrefslogtreecommitdiff
path: root/vendor/github.com/bytedance/sonic/loader
diff options
context:
space:
mode:
authorLibravatar dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>2023-11-27 13:15:03 +0000
committerLibravatar GitHub <noreply@github.com>2023-11-27 13:15:03 +0000
commit66b77acb1c8b86f0be3836ccaf31683c0bfa317a (patch)
tree9a255a8ea8ef97229b6d75d17de45bdac1755be9 /vendor/github.com/bytedance/sonic/loader
parent[bugfix] Add Actor to outgoing poll vote Create; other fixes (#2384) (diff)
downloadgotosocial-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')
-rw-r--r--vendor/github.com/bytedance/sonic/loader/funcdata.go103
-rw-r--r--vendor/github.com/bytedance/sonic/loader/funcdata_compat.go (renamed from vendor/github.com/bytedance/sonic/loader/funcdata_go115.go)171
-rw-r--r--vendor/github.com/bytedance/sonic/loader/funcdata_go116.go160
-rw-r--r--vendor/github.com/bytedance/sonic/loader/funcdata_go118.go430
-rw-r--r--vendor/github.com/bytedance/sonic/loader/funcdata_go120.go431
-rw-r--r--vendor/github.com/bytedance/sonic/loader/funcdata_go121.go119
-rw-r--r--vendor/github.com/bytedance/sonic/loader/funcdata_latest.go355
-rw-r--r--vendor/github.com/bytedance/sonic/loader/loader.go2
-rw-r--r--vendor/github.com/bytedance/sonic/loader/loader_go115.go28
-rw-r--r--vendor/github.com/bytedance/sonic/loader/loader_latest.go (renamed from vendor/github.com/bytedance/sonic/loader/loader_go116.go)23
-rw-r--r--vendor/github.com/bytedance/sonic/loader/mmap_unix.go2
-rw-r--r--vendor/github.com/bytedance/sonic/loader/pcdata.go61
-rw-r--r--vendor/github.com/bytedance/sonic/loader/wrapper.go185
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]
+ }
+}