github.com/Rookout/GoSDK@v0.1.48/pkg/services/instrumentation/module/module1.18.go (about) 1 //go:build go1.18 && !go1.20 2 // +build go1.18,!go1.20 3 4 package module 5 6 import ( 7 "runtime" 8 "unsafe" 9 ) 10 11 12 13 type funcFlag uint8 14 15 type functab struct { 16 entryoff uint32 17 funcoff uint32 18 } 19 20 type textsect struct { 21 vaddr uintptr 22 end uintptr 23 baseaddr uintptr 24 } 25 26 type _func struct { 27 entryoff uint32 28 nameoff int32 29 30 args int32 31 deferreturn uint32 32 33 pcsp uint32 34 pcfile uint32 35 pcln uint32 36 npcdata uint32 37 cuOffset uint32 38 funcID FuncID 39 flag funcFlag 40 _ [1]byte 41 nfuncdata uint8 42 } 43 44 type pcHeader struct { 45 magic uint32 46 pad1, pad2 uint8 47 minLC uint8 48 ptrSize uint8 49 nfunc int 50 nfiles uint 51 textStart uintptr 52 funcnameOffset uintptr 53 cuOffset uintptr 54 filetabOffset uintptr 55 pctabOffset uintptr 56 pclnOffset uintptr 57 } 58 59 type moduledata struct { 60 pcHeader *pcHeader 61 funcnametab []byte 62 cutab []uint32 63 filetab []byte 64 pctab []byte 65 pclntable []byte 66 ftab []functab 67 findfunctab uintptr 68 minpc, maxpc uintptr 69 70 text, etext uintptr 71 noptrdata, enoptrdata uintptr 72 data, edata uintptr 73 bss, ebss uintptr 74 noptrbss, enoptrbss uintptr 75 end, gcdata, gcbss uintptr 76 types, etypes uintptr 77 rodata uintptr 78 gofunc uintptr // go.func.* 79 80 textsectmap []textsect 81 typelinks []int32 82 itablinks []*itab 83 84 ptab []ptabEntry 85 86 pluginpath string 87 pkghashes []modulehash 88 89 modulename string 90 modulehashes []modulehash 91 92 hasmain uint8 93 94 gcdatamask, gcbssmask bitvector 95 96 typemap map[TypeOff]*_type 97 98 bad bool 99 100 next *moduledata 101 } 102 103 func getPCTab(m *moduledata) []byte { 104 return m.pctab 105 } 106 107 func (f *FuncInfo) getEntry() uintptr { 108 entry, _ := f.datap.textAddr(f.entryoff) 109 return entry 110 } 111 112 113 func findFuncOffsetInModule(pc uintptr, datap *moduledata) (uintptr, bool) { 114 if datap == nil { 115 return 0, false 116 } 117 const nsub = uintptr(len(findfuncbucket{}.subbuckets)) 118 119 pcOff, ok := datap.textOff(pc) 120 if !ok { 121 return 0, false 122 } 123 124 x := uintptr(pcOff) + datap.text - datap.minpc 125 b := x / pcbucketsize 126 i := x % pcbucketsize / (pcbucketsize / nsub) 127 128 ffb := (*findfuncbucket)(add(unsafe.Pointer(datap.findfunctab), b*unsafe.Sizeof(findfuncbucket{}))) 129 idx := ffb.idx + uint32(ffb.subbuckets[i]) 130 131 132 for datap.ftab[idx+1].entryoff <= pcOff { 133 idx++ 134 } 135 136 funcoff := uintptr(datap.ftab[idx].funcoff) 137 if funcoff == ^uintptr(0) { 138 139 140 141 142 return 0, false 143 } 144 145 return funcoff, true 146 } 147 148 149 func (md *moduledata) textOff(pc uintptr) (uint32, bool) { 150 res := uint32(pc - md.text) 151 if len(md.textsectmap) > 1 { 152 for i, sect := range md.textsectmap { 153 if sect.baseaddr > pc { 154 155 return 0, false 156 } 157 end := sect.baseaddr + (sect.end - sect.vaddr) 158 159 if i == len(md.textsectmap) { 160 end++ 161 } 162 if pc < end { 163 res = uint32(pc - sect.baseaddr + sect.vaddr) 164 break 165 } 166 } 167 } 168 return res, true 169 } 170 171 172 func (md *moduledata) textAddr(off32 uint32) (uintptr, bool) { 173 off := uintptr(off32) 174 res := md.text + off 175 if len(md.textsectmap) > 1 { 176 for i, sect := range md.textsectmap { 177 178 if off >= sect.vaddr && off < sect.end || (i == len(md.textsectmap)-1 && off == sect.end) { 179 res = sect.baseaddr + off - sect.vaddr 180 break 181 } 182 } 183 if res > md.etext && runtime.GOARCH != "wasm" { 184 println("runtime: textAddr", hex(res), "out of range", hex(md.text), "-", hex(md.etext)) 185 return 0, false 186 } 187 } 188 return res, true 189 } 190 191 type hex uint64 192 193 func (md *moduledata) GetTypeMap() map[TypeOff]uintptr { 194 typemap := make(map[TypeOff]uintptr) 195 for k, v := range md.typemap { 196 typemap[k] = uintptr(unsafe.Pointer(v)) 197 } 198 return typemap 199 }