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