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