mirror of
https://github.com/superseriousbusiness/gotosocial.git
synced 2024-12-05 10:02:47 +00:00
201 lines
5.9 KiB
Go
201 lines
5.9 KiB
Go
|
// +build go1.18,!go1.20
|
||
|
|
||
|
/*
|
||
|
* 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`
|
||
|
)
|
||
|
|
||
|
// A FuncFlag holds bits about a function.
|
||
|
// This list must match the list in cmd/internal/objabi/funcid.go.
|
||
|
type funcFlag uint8
|
||
|
|
||
|
type _Func struct {
|
||
|
entryOff uint32 // start pc
|
||
|
nameoff int32 // function name
|
||
|
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
|
||
|
funcID uint8 // set for certain special runtime functions
|
||
|
flag funcFlag
|
||
|
_ [1]byte // pad
|
||
|
nfuncdata uint8 // must be last
|
||
|
argptrs uint32
|
||
|
localptrs 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
|
||
|
length uintptr // section length
|
||
|
baseaddr uintptr // relocated section address
|
||
|
}
|
||
|
|
||
|
type _ModuleData struct {
|
||
|
pcHeader *_PCHeader
|
||
|
funcnametab []byte
|
||
|
cutab []uint32
|
||
|
filetab []byte
|
||
|
pctab []byte
|
||
|
pclntable []byte
|
||
|
ftab []_FuncTab
|
||
|
findfunctab *_FindFuncBucket
|
||
|
minpc, maxpc uintptr
|
||
|
text, etext uintptr
|
||
|
noptrdata, enoptrdata uintptr
|
||
|
data, edata uintptr
|
||
|
bss, ebss uintptr
|
||
|
noptrbss, enoptrbss uintptr
|
||
|
end, gcdata, gcbss uintptr
|
||
|
types, etypes uintptr
|
||
|
rodata uintptr
|
||
|
gofunc uintptr
|
||
|
textsectmap []_TextSection
|
||
|
typelinks []int32
|
||
|
itablinks []unsafe.Pointer
|
||
|
ptab []_PtabEntry
|
||
|
pluginpath string
|
||
|
pkghashes []struct{}
|
||
|
modulename string
|
||
|
modulehashes []struct{}
|
||
|
hasmain uint8
|
||
|
gcdatamask, gcbssmask _BitVector
|
||
|
typemap map[int32]unsafe.Pointer
|
||
|
bad bool
|
||
|
next *_ModuleData
|
||
|
}
|
||
|
|
||
|
|
||
|
type _FindFuncBucket struct {
|
||
|
idx uint32
|
||
|
subbuckets [16]byte
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
func makePCtab(fp int) []byte {
|
||
|
return append([]byte{0}, encodeVariant((fp + 1) << 1)...)
|
||
|
}
|
||
|
|
||
|
func registerFunction(name string, pc uintptr, textSize uintptr, fp int, args int, size uintptr, argPtrs []bool, localPtrs []bool) {
|
||
|
mod := new(_ModuleData)
|
||
|
|
||
|
minpc := pc
|
||
|
maxpc := pc + size
|
||
|
|
||
|
findFuncTab := make([]_FindFuncBucket, textSize/4096 + 1)
|
||
|
|
||
|
modHeader := &_PCHeader {
|
||
|
magic : 0xfffffff0,
|
||
|
minLC : 1,
|
||
|
nfunc : 1,
|
||
|
ptrSize : 4 << (^uintptr(0) >> 63),
|
||
|
textStart: minpc,
|
||
|
}
|
||
|
|
||
|
// cache arg and local stackmap
|
||
|
argptrs, localptrs := cacheStackmap(argPtrs, localPtrs, mod)
|
||
|
|
||
|
base := argptrs
|
||
|
if argptrs > localptrs {
|
||
|
base = localptrs
|
||
|
}
|
||
|
|
||
|
/* function entry */
|
||
|
lnt := []_Func {{
|
||
|
entryOff : 0,
|
||
|
nameoff : 1,
|
||
|
args : int32(args),
|
||
|
pcsp : 1,
|
||
|
nfuncdata : 2,
|
||
|
argptrs: uint32(argptrs - base),
|
||
|
localptrs: uint32(localptrs - base),
|
||
|
}}
|
||
|
nlnt := len(lnt)*int(unsafe.Sizeof(_Func{}))
|
||
|
plnt := unsafe.Pointer(&lnt[0])
|
||
|
|
||
|
/* function table */
|
||
|
ftab := []_FuncTab {
|
||
|
{entry : 0, funcoff : 16},
|
||
|
{entry : uint32(size)},
|
||
|
}
|
||
|
nftab := len(ftab)*int(unsafe.Sizeof(_FuncTab{}))
|
||
|
pftab := unsafe.Pointer(&ftab[0])
|
||
|
|
||
|
pclntab := make([]byte, 0, nftab + nlnt)
|
||
|
pclntab = append(pclntab, rt.BytesFrom(pftab, nftab, nftab)...)
|
||
|
pclntab = append(pclntab, rt.BytesFrom(plnt, nlnt, nlnt)...)
|
||
|
|
||
|
/* module data */
|
||
|
*mod = _ModuleData {
|
||
|
pcHeader : modHeader,
|
||
|
funcnametab : append(append([]byte{0}, name...), 0),
|
||
|
pctab : append(makePCtab(fp), encodeVariant(int(size))...),
|
||
|
pclntable : pclntab,
|
||
|
ftab : ftab,
|
||
|
text : minpc,
|
||
|
etext : pc + textSize,
|
||
|
findfunctab : &findFuncTab[0],
|
||
|
minpc : minpc,
|
||
|
maxpc : maxpc,
|
||
|
modulename : name,
|
||
|
gcdata: uintptr(unsafe.Pointer(&emptyByte)),
|
||
|
gcbss: uintptr(unsafe.Pointer(&emptyByte)),
|
||
|
gofunc: base,
|
||
|
}
|
||
|
|
||
|
/* verify and register the new module */
|
||
|
moduledataverify1(mod)
|
||
|
registerModule(mod)
|
||
|
}
|