You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			144 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			Go
		
	
			
		
		
	
	
			144 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			Go
		
	
| /**
 | |
|  * 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 (
 | |
|     `encoding`
 | |
|     `encoding/binary`
 | |
|     `fmt`
 | |
|     `reflect`
 | |
|     `strings`
 | |
|     `sync`
 | |
|     `unsafe`
 | |
| )
 | |
| 
 | |
| const (
 | |
|     _MinLC uint8 = 1
 | |
|     _PtrSize uint8 = 8
 | |
| )
 | |
| 
 | |
| const (
 | |
|     _N_FUNCDATA = 8
 | |
|     _INVALID_FUNCDATA_OFFSET = ^uint32(0)
 | |
|     _FUNC_SIZE = unsafe.Sizeof(_func{})
 | |
|     
 | |
|     _MINFUNC = 16 // minimum size for a function
 | |
|     _BUCKETSIZE    = 256 * _MINFUNC
 | |
|     _SUBBUCKETS    = 16
 | |
|     _SUB_BUCKETSIZE = _BUCKETSIZE / _SUBBUCKETS
 | |
| )
 | |
| 
 | |
| // PCDATA and FUNCDATA table indexes.
 | |
| //
 | |
| // See funcdata.h and $GROOT/src/cmd/internal/objabi/funcdata.go.
 | |
| const (
 | |
|     _FUNCDATA_ArgsPointerMaps    = 0
 | |
|     _FUNCDATA_LocalsPointerMaps  = 1
 | |
|     _FUNCDATA_StackObjects       = 2
 | |
|     _FUNCDATA_InlTree            = 3
 | |
|     _FUNCDATA_OpenCodedDeferInfo = 4
 | |
|     _FUNCDATA_ArgInfo            = 5
 | |
|     _FUNCDATA_ArgLiveInfo        = 6
 | |
|     _FUNCDATA_WrapInfo           = 7
 | |
| 
 | |
|     // ArgsSizeUnknown is set in Func.argsize to mark all functions
 | |
|     // whose argument size is unknown (C vararg functions, and
 | |
|     // assembly code without an explicit specification).
 | |
|     // This value is generated by the compiler, assembler, or linker.
 | |
|     ArgsSizeUnknown = -0x80000000
 | |
| )
 | |
| 
 | |
| // moduledata used to cache the funcdata and findfuncbucket of one module
 | |
| var moduleCache = struct {
 | |
|     m map[*moduledata][]byte
 | |
|     sync.Mutex
 | |
| }{
 | |
|     m: make(map[*moduledata][]byte),
 | |
| }
 | |
| 
 | |
| // Func contains information about a function.
 | |
| type Func struct {
 | |
|     ID          uint8  // see runtime/symtab.go
 | |
|     Flag        uint8  // see runtime/symtab.go
 | |
|     ArgsSize    int32  // args byte size
 | |
|     EntryOff    uint32 // start pc, offset to moduledata.text
 | |
|     TextSize    uint32 // size of func text
 | |
|     DeferReturn uint32 // offset of start of a deferreturn call instruction from entry, if any.
 | |
|     FileIndex   uint32 // index into filetab 
 | |
|     Name        string // name of function
 | |
| 
 | |
|     // PC data
 | |
|     Pcsp            *Pcdata // PC -> SP delta
 | |
|     Pcfile          *Pcdata // PC -> file index
 | |
|     Pcline          *Pcdata // PC -> line number
 | |
|     PcUnsafePoint   *Pcdata // PC -> unsafe point, must be PCDATA_UnsafePointSafe or PCDATA_UnsafePointUnsafe
 | |
|     PcStackMapIndex *Pcdata // PC -> stack map index, relative to ArgsPointerMaps and LocalsPointerMaps
 | |
|     PcInlTreeIndex  *Pcdata // PC -> inlining tree index, relative to InlTree
 | |
|     PcArgLiveIndex  *Pcdata // PC -> arg live index, relative to ArgLiveInfo
 | |
|     
 | |
|     // Func data, must implement encoding.BinaryMarshaler
 | |
|     ArgsPointerMaps    encoding.BinaryMarshaler // concrete type: *StackMap
 | |
|     LocalsPointerMaps  encoding.BinaryMarshaler // concrete type: *StackMap
 | |
|     StackObjects       encoding.BinaryMarshaler
 | |
|     InlTree            encoding.BinaryMarshaler
 | |
|     OpenCodedDeferInfo encoding.BinaryMarshaler
 | |
|     ArgInfo            encoding.BinaryMarshaler
 | |
|     ArgLiveInfo        encoding.BinaryMarshaler
 | |
|     WrapInfo           encoding.BinaryMarshaler
 | |
| }
 | |
| 
 | |
| func getOffsetOf(data interface{}, field string) uintptr {
 | |
|     t := reflect.TypeOf(data)
 | |
|     fv, ok := t.FieldByName(field)
 | |
|     if !ok {
 | |
|         panic(fmt.Sprintf("field %s not found in struct %s", field, t.Name()))
 | |
|     }
 | |
|     return fv.Offset
 | |
| }
 | |
| 
 | |
| func rnd(v int64, r int64) int64 {
 | |
|     if r <= 0 {
 | |
|         return v
 | |
|     }
 | |
|     v += r - 1
 | |
|     c := v % r
 | |
|     if c < 0 {
 | |
|         c += r
 | |
|     }
 | |
|     v -= c
 | |
|     return v
 | |
| }
 | |
| 
 | |
| var (
 | |
|     byteOrder binary.ByteOrder = binary.LittleEndian
 | |
| )
 | |
| 
 | |
| func funcNameParts(name string) (string, string, string) {
 | |
|     i := strings.IndexByte(name, '[')
 | |
|     if i < 0 {
 | |
|         return name, "", ""
 | |
|     }
 | |
|     // TODO: use LastIndexByte once the bootstrap compiler is >= Go 1.5.
 | |
|     j := len(name) - 1
 | |
|     for j > i && name[j] != ']' {
 | |
|         j--
 | |
|     }
 | |
|     if j <= i {
 | |
|         return name, "", ""
 | |
|     }
 | |
|     return name[:i], "[...]", name[j+1:]
 | |
| } |