funcdata.go (4341B)
1 /** 2 * Copyright 2023 ByteDance Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package loader 18 19 import ( 20 `encoding` 21 `encoding/binary` 22 `fmt` 23 `reflect` 24 `strings` 25 `sync` 26 `unsafe` 27 ) 28 29 const ( 30 _MinLC uint8 = 1 31 _PtrSize uint8 = 8 32 ) 33 34 const ( 35 _N_FUNCDATA = 8 36 _INVALID_FUNCDATA_OFFSET = ^uint32(0) 37 _FUNC_SIZE = unsafe.Sizeof(_func{}) 38 39 _MINFUNC = 16 // minimum size for a function 40 _BUCKETSIZE = 256 * _MINFUNC 41 _SUBBUCKETS = 16 42 _SUB_BUCKETSIZE = _BUCKETSIZE / _SUBBUCKETS 43 ) 44 45 // PCDATA and FUNCDATA table indexes. 46 // 47 // See funcdata.h and $GROOT/src/cmd/internal/objabi/funcdata.go. 48 const ( 49 _FUNCDATA_ArgsPointerMaps = 0 50 _FUNCDATA_LocalsPointerMaps = 1 51 _FUNCDATA_StackObjects = 2 52 _FUNCDATA_InlTree = 3 53 _FUNCDATA_OpenCodedDeferInfo = 4 54 _FUNCDATA_ArgInfo = 5 55 _FUNCDATA_ArgLiveInfo = 6 56 _FUNCDATA_WrapInfo = 7 57 58 // ArgsSizeUnknown is set in Func.argsize to mark all functions 59 // whose argument size is unknown (C vararg functions, and 60 // assembly code without an explicit specification). 61 // This value is generated by the compiler, assembler, or linker. 62 ArgsSizeUnknown = -0x80000000 63 ) 64 65 // moduledata used to cache the funcdata and findfuncbucket of one module 66 var moduleCache = struct { 67 m map[*moduledata][]byte 68 sync.Mutex 69 }{ 70 m: make(map[*moduledata][]byte), 71 } 72 73 // Func contains information about a function. 74 type Func struct { 75 ID uint8 // see runtime/symtab.go 76 Flag uint8 // see runtime/symtab.go 77 ArgsSize int32 // args byte size 78 EntryOff uint32 // start pc, offset to moduledata.text 79 TextSize uint32 // size of func text 80 DeferReturn uint32 // offset of start of a deferreturn call instruction from entry, if any. 81 FileIndex uint32 // index into filetab 82 Name string // name of function 83 84 // PC data 85 Pcsp *Pcdata // PC -> SP delta 86 Pcfile *Pcdata // PC -> file index 87 Pcline *Pcdata // PC -> line number 88 PcUnsafePoint *Pcdata // PC -> unsafe point, must be PCDATA_UnsafePointSafe or PCDATA_UnsafePointUnsafe 89 PcStackMapIndex *Pcdata // PC -> stack map index, relative to ArgsPointerMaps and LocalsPointerMaps 90 PcInlTreeIndex *Pcdata // PC -> inlining tree index, relative to InlTree 91 PcArgLiveIndex *Pcdata // PC -> arg live index, relative to ArgLiveInfo 92 93 // Func data, must implement encoding.BinaryMarshaler 94 ArgsPointerMaps encoding.BinaryMarshaler // concrete type: *StackMap 95 LocalsPointerMaps encoding.BinaryMarshaler // concrete type: *StackMap 96 StackObjects encoding.BinaryMarshaler 97 InlTree encoding.BinaryMarshaler 98 OpenCodedDeferInfo encoding.BinaryMarshaler 99 ArgInfo encoding.BinaryMarshaler 100 ArgLiveInfo encoding.BinaryMarshaler 101 WrapInfo encoding.BinaryMarshaler 102 } 103 104 func getOffsetOf(data interface{}, field string) uintptr { 105 t := reflect.TypeOf(data) 106 fv, ok := t.FieldByName(field) 107 if !ok { 108 panic(fmt.Sprintf("field %s not found in struct %s", field, t.Name())) 109 } 110 return fv.Offset 111 } 112 113 func rnd(v int64, r int64) int64 { 114 if r <= 0 { 115 return v 116 } 117 v += r - 1 118 c := v % r 119 if c < 0 { 120 c += r 121 } 122 v -= c 123 return v 124 } 125 126 var ( 127 byteOrder binary.ByteOrder = binary.LittleEndian 128 ) 129 130 func funcNameParts(name string) (string, string, string) { 131 i := strings.IndexByte(name, '[') 132 if i < 0 { 133 return name, "", "" 134 } 135 // TODO: use LastIndexByte once the bootstrap compiler is >= Go 1.5. 136 j := len(name) - 1 137 for j > i && name[j] != ']' { 138 j-- 139 } 140 if j <= i { 141 return name, "", "" 142 } 143 return name[:i], "[...]", name[j+1:] 144 }