github.com/bir3/gocompiler@v0.9.2202/src/cmd/link/internal/ld/decodesym.go (about) 1 // Copyright 2012 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package ld 6 7 import ( 8 "github.com/bir3/gocompiler/src/cmd/internal/objabi" 9 "github.com/bir3/gocompiler/src/cmd/internal/sys" 10 "github.com/bir3/gocompiler/src/cmd/link/internal/loader" 11 "github.com/bir3/gocompiler/src/cmd/link/internal/sym" 12 "debug/elf" 13 "encoding/binary" 14 "github.com/bir3/gocompiler/src/internal/abi" 15 "log" 16 ) 17 18 // Decoding the type.* symbols. This has to be in sync with 19 // ../../runtime/type.go, or more specifically, with what 20 // cmd/compile/internal/reflectdata/reflect.go stuffs in these. 21 22 func decodeInuxi(arch *sys.Arch, p []byte, sz int) uint64 { 23 switch sz { 24 case 2: 25 return uint64(arch.ByteOrder.Uint16(p)) 26 case 4: 27 return uint64(arch.ByteOrder.Uint32(p)) 28 case 8: 29 return arch.ByteOrder.Uint64(p) 30 default: 31 Exitf("dwarf: decode inuxi %d", sz) 32 panic("unreachable") 33 } 34 } 35 36 func commonsize(arch *sys.Arch) int { return abi.CommonSize(arch.PtrSize) } // runtime._type 37 func structfieldSize(arch *sys.Arch) int { return abi.StructFieldSize(arch.PtrSize) } // runtime.structfield 38 func uncommonSize(arch *sys.Arch) int { return int(abi.UncommonSize()) } // runtime.uncommontype 39 40 // Type.commonType.kind 41 func decodetypeKind(arch *sys.Arch, p []byte) uint8 { 42 return p[2*arch.PtrSize+7] & objabi.KindMask // 0x13 / 0x1f 43 } 44 45 // Type.commonType.kind 46 func decodetypeUsegcprog(arch *sys.Arch, p []byte) uint8 { 47 return p[2*arch.PtrSize+7] & objabi.KindGCProg // 0x13 / 0x1f 48 } 49 50 // Type.commonType.size 51 func decodetypeSize(arch *sys.Arch, p []byte) int64 { 52 return int64(decodeInuxi(arch, p, arch.PtrSize)) // 0x8 / 0x10 53 } 54 55 // Type.commonType.ptrdata 56 func decodetypePtrdata(arch *sys.Arch, p []byte) int64 { 57 return int64(decodeInuxi(arch, p[arch.PtrSize:], arch.PtrSize)) // 0x8 / 0x10 58 } 59 60 // Type.commonType.tflag 61 func decodetypeHasUncommon(arch *sys.Arch, p []byte) bool { 62 return abi.TFlag(p[abi.TFlagOff(arch.PtrSize)])&abi.TFlagUncommon != 0 63 } 64 65 // Type.FuncType.dotdotdot 66 func decodetypeFuncDotdotdot(arch *sys.Arch, p []byte) bool { 67 return uint16(decodeInuxi(arch, p[commonsize(arch)+2:], 2))&(1<<15) != 0 68 } 69 70 // Type.FuncType.inCount 71 func decodetypeFuncInCount(arch *sys.Arch, p []byte) int { 72 return int(decodeInuxi(arch, p[commonsize(arch):], 2)) 73 } 74 75 func decodetypeFuncOutCount(arch *sys.Arch, p []byte) int { 76 return int(uint16(decodeInuxi(arch, p[commonsize(arch)+2:], 2)) & (1<<15 - 1)) 77 } 78 79 // InterfaceType.methods.length 80 func decodetypeIfaceMethodCount(arch *sys.Arch, p []byte) int64 { 81 return int64(decodeInuxi(arch, p[commonsize(arch)+2*arch.PtrSize:], arch.PtrSize)) 82 } 83 84 // Matches runtime/typekind.go and reflect.Kind. 85 const ( 86 kindArray = 17 87 kindChan = 18 88 kindFunc = 19 89 kindInterface = 20 90 kindMap = 21 91 kindPtr = 22 92 kindSlice = 23 93 kindStruct = 25 94 kindMask = (1 << 5) - 1 95 ) 96 97 func decodeReloc(ldr *loader.Loader, symIdx loader.Sym, relocs *loader.Relocs, off int32) loader.Reloc { 98 for j := 0; j < relocs.Count(); j++ { 99 rel := relocs.At(j) 100 if rel.Off() == off { 101 return rel 102 } 103 } 104 return loader.Reloc{} 105 } 106 107 func decodeRelocSym(ldr *loader.Loader, symIdx loader.Sym, relocs *loader.Relocs, off int32) loader.Sym { 108 return decodeReloc(ldr, symIdx, relocs, off).Sym() 109 } 110 111 // decodetypeName decodes the name from a reflect.name. 112 func decodetypeName(ldr *loader.Loader, symIdx loader.Sym, relocs *loader.Relocs, off int) string { 113 r := decodeRelocSym(ldr, symIdx, relocs, int32(off)) 114 if r == 0 { 115 return "" 116 } 117 118 data := ldr.DataString(r) 119 n := 1 + binary.MaxVarintLen64 120 if len(data) < n { 121 n = len(data) 122 } 123 nameLen, nameLenLen := binary.Uvarint([]byte(data[1:n])) 124 return data[1+nameLenLen : 1+nameLenLen+int(nameLen)] 125 } 126 127 func decodetypeNameEmbedded(ldr *loader.Loader, symIdx loader.Sym, relocs *loader.Relocs, off int) bool { 128 r := decodeRelocSym(ldr, symIdx, relocs, int32(off)) 129 if r == 0 { 130 return false 131 } 132 data := ldr.Data(r) 133 return data[0]&(1<<3) != 0 134 } 135 136 func decodetypeFuncInType(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym, relocs *loader.Relocs, i int) loader.Sym { 137 uadd := commonsize(arch) + 4 138 if arch.PtrSize == 8 { 139 uadd += 4 140 } 141 if decodetypeHasUncommon(arch, ldr.Data(symIdx)) { 142 uadd += uncommonSize(arch) 143 } 144 return decodeRelocSym(ldr, symIdx, relocs, int32(uadd+i*arch.PtrSize)) 145 } 146 147 func decodetypeFuncOutType(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym, relocs *loader.Relocs, i int) loader.Sym { 148 return decodetypeFuncInType(ldr, arch, symIdx, relocs, i+decodetypeFuncInCount(arch, ldr.Data(symIdx))) 149 } 150 151 func decodetypeArrayElem(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym) loader.Sym { 152 relocs := ldr.Relocs(symIdx) 153 return decodeRelocSym(ldr, symIdx, &relocs, int32(commonsize(arch))) // 0x1c / 0x30 154 } 155 156 func decodetypeArrayLen(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym) int64 { 157 data := ldr.Data(symIdx) 158 return int64(decodeInuxi(arch, data[commonsize(arch)+2*arch.PtrSize:], arch.PtrSize)) 159 } 160 161 func decodetypeChanElem(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym) loader.Sym { 162 relocs := ldr.Relocs(symIdx) 163 return decodeRelocSym(ldr, symIdx, &relocs, int32(commonsize(arch))) // 0x1c / 0x30 164 } 165 166 func decodetypeMapKey(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym) loader.Sym { 167 relocs := ldr.Relocs(symIdx) 168 return decodeRelocSym(ldr, symIdx, &relocs, int32(commonsize(arch))) // 0x1c / 0x30 169 } 170 171 func decodetypeMapValue(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym) loader.Sym { 172 relocs := ldr.Relocs(symIdx) 173 return decodeRelocSym(ldr, symIdx, &relocs, int32(commonsize(arch))+int32(arch.PtrSize)) // 0x20 / 0x38 174 } 175 176 func decodetypePtrElem(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym) loader.Sym { 177 relocs := ldr.Relocs(symIdx) 178 return decodeRelocSym(ldr, symIdx, &relocs, int32(commonsize(arch))) // 0x1c / 0x30 179 } 180 181 func decodetypeStructFieldCount(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym) int { 182 data := ldr.Data(symIdx) 183 return int(decodeInuxi(arch, data[commonsize(arch)+2*arch.PtrSize:], arch.PtrSize)) 184 } 185 186 func decodetypeStructFieldArrayOff(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym, i int) int { 187 data := ldr.Data(symIdx) 188 off := commonsize(arch) + 4*arch.PtrSize 189 if decodetypeHasUncommon(arch, data) { 190 off += uncommonSize(arch) 191 } 192 off += i * structfieldSize(arch) 193 return off 194 } 195 196 func decodetypeStructFieldName(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym, i int) string { 197 off := decodetypeStructFieldArrayOff(ldr, arch, symIdx, i) 198 relocs := ldr.Relocs(symIdx) 199 return decodetypeName(ldr, symIdx, &relocs, off) 200 } 201 202 func decodetypeStructFieldType(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym, i int) loader.Sym { 203 off := decodetypeStructFieldArrayOff(ldr, arch, symIdx, i) 204 relocs := ldr.Relocs(symIdx) 205 return decodeRelocSym(ldr, symIdx, &relocs, int32(off+arch.PtrSize)) 206 } 207 208 func decodetypeStructFieldOffset(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym, i int) int64 { 209 off := decodetypeStructFieldArrayOff(ldr, arch, symIdx, i) 210 data := ldr.Data(symIdx) 211 return int64(decodeInuxi(arch, data[off+2*arch.PtrSize:], arch.PtrSize)) 212 } 213 214 func decodetypeStructFieldEmbedded(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym, i int) bool { 215 off := decodetypeStructFieldArrayOff(ldr, arch, symIdx, i) 216 relocs := ldr.Relocs(symIdx) 217 return decodetypeNameEmbedded(ldr, symIdx, &relocs, off) 218 } 219 220 // decodetypeStr returns the contents of an rtype's str field (a nameOff). 221 func decodetypeStr(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym) string { 222 relocs := ldr.Relocs(symIdx) 223 str := decodetypeName(ldr, symIdx, &relocs, 4*arch.PtrSize+8) 224 data := ldr.Data(symIdx) 225 if data[abi.TFlagOff(arch.PtrSize)]&byte(abi.TFlagExtraStar) != 0 { 226 return str[1:] 227 } 228 return str 229 } 230 231 func decodetypeGcmask(ctxt *Link, s loader.Sym) []byte { 232 if ctxt.loader.SymType(s) == sym.SDYNIMPORT { 233 symData := ctxt.loader.Data(s) 234 addr := decodetypeGcprogShlib(ctxt, symData) 235 ptrdata := decodetypePtrdata(ctxt.Arch, symData) 236 sect := findShlibSection(ctxt, ctxt.loader.SymPkg(s), addr) 237 if sect != nil { 238 bits := ptrdata / int64(ctxt.Arch.PtrSize) 239 r := make([]byte, (bits+7)/8) 240 // ldshlibsyms avoids closing the ELF file so sect.ReadAt works. 241 // If we remove this read (and the ones in decodetypeGcprog), we 242 // can close the file. 243 _, err := sect.ReadAt(r, int64(addr-sect.Addr)) 244 if err != nil { 245 log.Fatal(err) 246 } 247 return r 248 } 249 Exitf("cannot find gcmask for %s", ctxt.loader.SymName(s)) 250 return nil 251 } 252 relocs := ctxt.loader.Relocs(s) 253 mask := decodeRelocSym(ctxt.loader, s, &relocs, 2*int32(ctxt.Arch.PtrSize)+8+1*int32(ctxt.Arch.PtrSize)) 254 return ctxt.loader.Data(mask) 255 } 256 257 // Type.commonType.gc 258 func decodetypeGcprog(ctxt *Link, s loader.Sym) []byte { 259 if ctxt.loader.SymType(s) == sym.SDYNIMPORT { 260 symData := ctxt.loader.Data(s) 261 addr := decodetypeGcprogShlib(ctxt, symData) 262 sect := findShlibSection(ctxt, ctxt.loader.SymPkg(s), addr) 263 if sect != nil { 264 // A gcprog is a 4-byte uint32 indicating length, followed by 265 // the actual program. 266 progsize := make([]byte, 4) 267 _, err := sect.ReadAt(progsize, int64(addr-sect.Addr)) 268 if err != nil { 269 log.Fatal(err) 270 } 271 progbytes := make([]byte, ctxt.Arch.ByteOrder.Uint32(progsize)) 272 _, err = sect.ReadAt(progbytes, int64(addr-sect.Addr+4)) 273 if err != nil { 274 log.Fatal(err) 275 } 276 return append(progsize, progbytes...) 277 } 278 Exitf("cannot find gcmask for %s", ctxt.loader.SymName(s)) 279 return nil 280 } 281 relocs := ctxt.loader.Relocs(s) 282 rs := decodeRelocSym(ctxt.loader, s, &relocs, 2*int32(ctxt.Arch.PtrSize)+8+1*int32(ctxt.Arch.PtrSize)) 283 return ctxt.loader.Data(rs) 284 } 285 286 // Find the elf.Section of a given shared library that contains a given address. 287 func findShlibSection(ctxt *Link, path string, addr uint64) *elf.Section { 288 for _, shlib := range ctxt.Shlibs { 289 if shlib.Path == path { 290 for _, sect := range shlib.File.Sections[1:] { // skip the NULL section 291 if sect.Addr <= addr && addr < sect.Addr+sect.Size { 292 return sect 293 } 294 } 295 } 296 } 297 return nil 298 } 299 300 func decodetypeGcprogShlib(ctxt *Link, data []byte) uint64 { 301 return decodeInuxi(ctxt.Arch, data[2*int32(ctxt.Arch.PtrSize)+8+1*int32(ctxt.Arch.PtrSize):], ctxt.Arch.PtrSize) 302 } 303 304 // decodeItabType returns the itab._type field from an itab. 305 func decodeItabType(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym) loader.Sym { 306 relocs := ldr.Relocs(symIdx) 307 return decodeRelocSym(ldr, symIdx, &relocs, int32(arch.PtrSize)) 308 }