Source file src/cmd/link/internal/ld/decodesym.go

     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  	"cmd/internal/objabi"
     9  	"cmd/internal/sys"
    10  	"cmd/link/internal/loader"
    11  	"cmd/link/internal/sym"
    12  	"debug/elf"
    13  	"encoding/binary"
    14  	"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  }
   309  

View as plain text