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/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  
    21  func 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  
    35  func commonsize(arch *sys.Arch) int      { return abi.CommonSize(arch.PtrSize) }      // runtime._type
    36  func structfieldSize(arch *sys.Arch) int { return abi.StructFieldSize(arch.PtrSize) } // runtime.structfield
    37  func uncommonSize(arch *sys.Arch) int    { return int(abi.UncommonSize()) }           // runtime.uncommontype
    38  
    39  // Type.commonType.kind
    40  func 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
    45  func 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
    50  func decodetypeSize(arch *sys.Arch, p []byte) int64 {
    51  	return int64(decodeInuxi(arch, p, arch.PtrSize)) // 0x8 / 0x10
    52  }
    53  
    54  // Type.commonType.ptrdata
    55  func 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
    60  func 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
    65  func 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
    70  func decodetypeFuncInCount(arch *sys.Arch, p []byte) int {
    71  	return int(decodeInuxi(arch, p[commonsize(arch):], 2))
    72  }
    73  
    74  func 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
    79  func decodetypeIfaceMethodCount(arch *sys.Arch, p []byte) int64 {
    80  	return int64(decodeInuxi(arch, p[commonsize(arch)+2*arch.PtrSize:], arch.PtrSize))
    81  }
    82  
    83  func 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  
    93  func 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.
    98  func 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  
   113  func 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  
   122  func 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  
   133  func 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  
   137  func 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  
   142  func 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  
   147  func 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  
   152  func 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  
   157  func 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  
   162  func decodetypeMapSwissGroup(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))+2*int32(arch.PtrSize)) // 0x24 / 0x40
   165  }
   166  
   167  func decodetypePtrElem(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym) loader.Sym {
   168  	relocs := ldr.Relocs(symIdx)
   169  	return decodeRelocSym(ldr, symIdx, &relocs, int32(commonsize(arch))) // 0x1c / 0x30
   170  }
   171  
   172  func decodetypeStructFieldCount(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym) int {
   173  	data := ldr.Data(symIdx)
   174  	return int(decodeInuxi(arch, data[commonsize(arch)+2*arch.PtrSize:], arch.PtrSize))
   175  }
   176  
   177  func decodetypeStructFieldArrayOff(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym, i int) int {
   178  	data := ldr.Data(symIdx)
   179  	off := commonsize(arch) + 4*arch.PtrSize
   180  	if decodetypeHasUncommon(arch, data) {
   181  		off += uncommonSize(arch)
   182  	}
   183  	off += i * structfieldSize(arch)
   184  	return off
   185  }
   186  
   187  func decodetypeStructFieldName(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym, i int) string {
   188  	off := decodetypeStructFieldArrayOff(ldr, arch, symIdx, i)
   189  	relocs := ldr.Relocs(symIdx)
   190  	return decodetypeName(ldr, symIdx, &relocs, off)
   191  }
   192  
   193  func decodetypeStructFieldType(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym, i int) loader.Sym {
   194  	off := decodetypeStructFieldArrayOff(ldr, arch, symIdx, i)
   195  	relocs := ldr.Relocs(symIdx)
   196  	return decodeRelocSym(ldr, symIdx, &relocs, int32(off+arch.PtrSize))
   197  }
   198  
   199  func decodetypeStructFieldOffset(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym, i int) int64 {
   200  	off := decodetypeStructFieldArrayOff(ldr, arch, symIdx, i)
   201  	data := ldr.Data(symIdx)
   202  	return int64(decodeInuxi(arch, data[off+2*arch.PtrSize:], arch.PtrSize))
   203  }
   204  
   205  func decodetypeStructFieldEmbedded(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym, i int) bool {
   206  	off := decodetypeStructFieldArrayOff(ldr, arch, symIdx, i)
   207  	relocs := ldr.Relocs(symIdx)
   208  	return decodetypeNameEmbedded(ldr, symIdx, &relocs, off)
   209  }
   210  
   211  // decodetypeStr returns the contents of an rtype's str field (a nameOff).
   212  func decodetypeStr(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym) string {
   213  	relocs := ldr.Relocs(symIdx)
   214  	str := decodetypeName(ldr, symIdx, &relocs, 4*arch.PtrSize+8)
   215  	data := ldr.Data(symIdx)
   216  	if data[abi.TFlagOff(arch.PtrSize)]&byte(abi.TFlagExtraStar) != 0 {
   217  		return str[1:]
   218  	}
   219  	return str
   220  }
   221  
   222  func decodetypeGcmask(ctxt *Link, s loader.Sym) []byte {
   223  	if ctxt.loader.SymType(s) == sym.SDYNIMPORT {
   224  		symData := ctxt.loader.Data(s)
   225  		addr := decodetypeGcprogShlib(ctxt, symData)
   226  		ptrdata := decodetypePtrdata(ctxt.Arch, symData)
   227  		sect := findShlibSection(ctxt, ctxt.loader.SymPkg(s), addr)
   228  		if sect != nil {
   229  			bits := ptrdata / int64(ctxt.Arch.PtrSize)
   230  			r := make([]byte, (bits+7)/8)
   231  			// ldshlibsyms avoids closing the ELF file so sect.ReadAt works.
   232  			// If we remove this read (and the ones in decodetypeGcprog), we
   233  			// can close the file.
   234  			_, err := sect.ReadAt(r, int64(addr-sect.Addr))
   235  			if err != nil {
   236  				log.Fatal(err)
   237  			}
   238  			return r
   239  		}
   240  		Exitf("cannot find gcmask for %s", ctxt.loader.SymName(s))
   241  		return nil
   242  	}
   243  	relocs := ctxt.loader.Relocs(s)
   244  	mask := decodeRelocSym(ctxt.loader, s, &relocs, 2*int32(ctxt.Arch.PtrSize)+8+1*int32(ctxt.Arch.PtrSize))
   245  	return ctxt.loader.Data(mask)
   246  }
   247  
   248  // Type.commonType.gc
   249  func decodetypeGcprog(ctxt *Link, s loader.Sym) []byte {
   250  	if ctxt.loader.SymType(s) == sym.SDYNIMPORT {
   251  		symData := ctxt.loader.Data(s)
   252  		addr := decodetypeGcprogShlib(ctxt, symData)
   253  		sect := findShlibSection(ctxt, ctxt.loader.SymPkg(s), addr)
   254  		if sect != nil {
   255  			// A gcprog is a 4-byte uint32 indicating length, followed by
   256  			// the actual program.
   257  			progsize := make([]byte, 4)
   258  			_, err := sect.ReadAt(progsize, int64(addr-sect.Addr))
   259  			if err != nil {
   260  				log.Fatal(err)
   261  			}
   262  			progbytes := make([]byte, ctxt.Arch.ByteOrder.Uint32(progsize))
   263  			_, err = sect.ReadAt(progbytes, int64(addr-sect.Addr+4))
   264  			if err != nil {
   265  				log.Fatal(err)
   266  			}
   267  			return append(progsize, progbytes...)
   268  		}
   269  		Exitf("cannot find gcprog for %s", ctxt.loader.SymName(s))
   270  		return nil
   271  	}
   272  	relocs := ctxt.loader.Relocs(s)
   273  	rs := decodeRelocSym(ctxt.loader, s, &relocs, 2*int32(ctxt.Arch.PtrSize)+8+1*int32(ctxt.Arch.PtrSize))
   274  	return ctxt.loader.Data(rs)
   275  }
   276  
   277  // Find the elf.Section of a given shared library that contains a given address.
   278  func findShlibSection(ctxt *Link, path string, addr uint64) *elf.Section {
   279  	for _, shlib := range ctxt.Shlibs {
   280  		if shlib.Path == path {
   281  			for _, sect := range shlib.File.Sections[1:] { // skip the NULL section
   282  				if sect.Addr <= addr && addr < sect.Addr+sect.Size {
   283  					return sect
   284  				}
   285  			}
   286  		}
   287  	}
   288  	return nil
   289  }
   290  
   291  func decodetypeGcprogShlib(ctxt *Link, data []byte) uint64 {
   292  	return decodeInuxi(ctxt.Arch, data[2*int32(ctxt.Arch.PtrSize)+8+1*int32(ctxt.Arch.PtrSize):], ctxt.Arch.PtrSize)
   293  }
   294  
   295  // decodeItabType returns the itab.Type field from an itab.
   296  func decodeItabType(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym) loader.Sym {
   297  	relocs := ldr.Relocs(symIdx)
   298  	return decodeRelocSym(ldr, symIdx, &relocs, int32(abi.ITabTypeOff(arch.PtrSize)))
   299  }
   300  

View as plain text