github.com/sanprasirt/go@v0.0.0-20170607001320-a027466e4b6d/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  	"bytes"
     9  	"cmd/internal/objabi"
    10  	"cmd/internal/sys"
    11  	"debug/elf"
    12  	"fmt"
    13  )
    14  
    15  // Decoding the type.* symbols.	 This has to be in sync with
    16  // ../../runtime/type.go, or more specifically, with what
    17  // cmd/compile/internal/gc/reflect.go stuffs in these.
    18  
    19  // tflag is documented in reflect/type.go.
    20  //
    21  // tflag values must be kept in sync with copies in:
    22  //	cmd/compile/internal/gc/reflect.go
    23  //	cmd/link/internal/ld/decodesym.go
    24  //	reflect/type.go
    25  //	runtime/type.go
    26  const (
    27  	tflagUncommon  = 1 << 0
    28  	tflagExtraStar = 1 << 1
    29  )
    30  
    31  func decodeReloc(s *Symbol, off int32) *Reloc {
    32  	for i := range s.R {
    33  		if s.R[i].Off == off {
    34  			return &s.R[i]
    35  		}
    36  	}
    37  	return nil
    38  }
    39  
    40  func decodeRelocSym(s *Symbol, off int32) *Symbol {
    41  	r := decodeReloc(s, off)
    42  	if r == nil {
    43  		return nil
    44  	}
    45  	return r.Sym
    46  }
    47  
    48  func decodeInuxi(arch *sys.Arch, p []byte, sz int) uint64 {
    49  	switch sz {
    50  	case 2:
    51  		return uint64(arch.ByteOrder.Uint16(p))
    52  	case 4:
    53  		return uint64(arch.ByteOrder.Uint32(p))
    54  	case 8:
    55  		return arch.ByteOrder.Uint64(p)
    56  	default:
    57  		Exitf("dwarf: decode inuxi %d", sz)
    58  		panic("unreachable")
    59  	}
    60  }
    61  
    62  func commonsize() int      { return 4*SysArch.PtrSize + 8 + 8 } // runtime._type
    63  func structfieldSize() int { return 3 * SysArch.PtrSize }       // runtime.structfield
    64  func uncommonSize() int    { return 4 + 2 + 2 + 4 + 4 }         // runtime.uncommontype
    65  
    66  // Type.commonType.kind
    67  func decodetypeKind(s *Symbol) uint8 {
    68  	return s.P[2*SysArch.PtrSize+7] & objabi.KindMask //  0x13 / 0x1f
    69  }
    70  
    71  // Type.commonType.kind
    72  func decodetypeUsegcprog(s *Symbol) uint8 {
    73  	return s.P[2*SysArch.PtrSize+7] & objabi.KindGCProg //  0x13 / 0x1f
    74  }
    75  
    76  // Type.commonType.size
    77  func decodetypeSize(arch *sys.Arch, s *Symbol) int64 {
    78  	return int64(decodeInuxi(arch, s.P, SysArch.PtrSize)) // 0x8 / 0x10
    79  }
    80  
    81  // Type.commonType.ptrdata
    82  func decodetypePtrdata(arch *sys.Arch, s *Symbol) int64 {
    83  	return int64(decodeInuxi(arch, s.P[SysArch.PtrSize:], SysArch.PtrSize)) // 0x8 / 0x10
    84  }
    85  
    86  // Type.commonType.tflag
    87  func decodetypeHasUncommon(s *Symbol) bool {
    88  	return s.P[2*SysArch.PtrSize+4]&tflagUncommon != 0
    89  }
    90  
    91  // Find the elf.Section of a given shared library that contains a given address.
    92  func findShlibSection(ctxt *Link, path string, addr uint64) *elf.Section {
    93  	for _, shlib := range ctxt.Shlibs {
    94  		if shlib.Path == path {
    95  			for _, sect := range shlib.File.Sections {
    96  				if sect.Addr <= addr && addr <= sect.Addr+sect.Size {
    97  					return sect
    98  				}
    99  			}
   100  		}
   101  	}
   102  	return nil
   103  }
   104  
   105  // Type.commonType.gc
   106  func decodetypeGcprog(ctxt *Link, s *Symbol) []byte {
   107  	if s.Type == SDYNIMPORT {
   108  		addr := decodetypeGcprogShlib(ctxt, s)
   109  		sect := findShlibSection(ctxt, s.File, addr)
   110  		if sect != nil {
   111  			// A gcprog is a 4-byte uint32 indicating length, followed by
   112  			// the actual program.
   113  			progsize := make([]byte, 4)
   114  			sect.ReadAt(progsize, int64(addr-sect.Addr))
   115  			progbytes := make([]byte, ctxt.Arch.ByteOrder.Uint32(progsize))
   116  			sect.ReadAt(progbytes, int64(addr-sect.Addr+4))
   117  			return append(progsize, progbytes...)
   118  		}
   119  		Exitf("cannot find gcprog for %s", s.Name)
   120  		return nil
   121  	}
   122  	return decodeRelocSym(s, 2*int32(SysArch.PtrSize)+8+1*int32(SysArch.PtrSize)).P
   123  }
   124  
   125  func decodetypeGcprogShlib(ctxt *Link, s *Symbol) uint64 {
   126  	if SysArch.Family == sys.ARM64 {
   127  		for _, shlib := range ctxt.Shlibs {
   128  			if shlib.Path == s.File {
   129  				return shlib.gcdataAddresses[s]
   130  			}
   131  		}
   132  		return 0
   133  	}
   134  	return decodeInuxi(ctxt.Arch, s.P[2*int32(SysArch.PtrSize)+8+1*int32(SysArch.PtrSize):], SysArch.PtrSize)
   135  }
   136  
   137  func decodetypeGcmask(ctxt *Link, s *Symbol) []byte {
   138  	if s.Type == SDYNIMPORT {
   139  		addr := decodetypeGcprogShlib(ctxt, s)
   140  		ptrdata := decodetypePtrdata(ctxt.Arch, s)
   141  		sect := findShlibSection(ctxt, s.File, addr)
   142  		if sect != nil {
   143  			r := make([]byte, ptrdata/int64(SysArch.PtrSize))
   144  			sect.ReadAt(r, int64(addr-sect.Addr))
   145  			return r
   146  		}
   147  		Exitf("cannot find gcmask for %s", s.Name)
   148  		return nil
   149  	}
   150  	mask := decodeRelocSym(s, 2*int32(SysArch.PtrSize)+8+1*int32(SysArch.PtrSize))
   151  	return mask.P
   152  }
   153  
   154  // Type.ArrayType.elem and Type.SliceType.Elem
   155  func decodetypeArrayElem(s *Symbol) *Symbol {
   156  	return decodeRelocSym(s, int32(commonsize())) // 0x1c / 0x30
   157  }
   158  
   159  func decodetypeArrayLen(arch *sys.Arch, s *Symbol) int64 {
   160  	return int64(decodeInuxi(arch, s.P[commonsize()+2*SysArch.PtrSize:], SysArch.PtrSize))
   161  }
   162  
   163  // Type.PtrType.elem
   164  func decodetypePtrElem(s *Symbol) *Symbol {
   165  	return decodeRelocSym(s, int32(commonsize())) // 0x1c / 0x30
   166  }
   167  
   168  // Type.MapType.key, elem
   169  func decodetypeMapKey(s *Symbol) *Symbol {
   170  	return decodeRelocSym(s, int32(commonsize())) // 0x1c / 0x30
   171  }
   172  
   173  func decodetypeMapValue(s *Symbol) *Symbol {
   174  	return decodeRelocSym(s, int32(commonsize())+int32(SysArch.PtrSize)) // 0x20 / 0x38
   175  }
   176  
   177  // Type.ChanType.elem
   178  func decodetypeChanElem(s *Symbol) *Symbol {
   179  	return decodeRelocSym(s, int32(commonsize())) // 0x1c / 0x30
   180  }
   181  
   182  // Type.FuncType.dotdotdot
   183  func decodetypeFuncDotdotdot(arch *sys.Arch, s *Symbol) bool {
   184  	return uint16(decodeInuxi(arch, s.P[commonsize()+2:], 2))&(1<<15) != 0
   185  }
   186  
   187  // Type.FuncType.inCount
   188  func decodetypeFuncInCount(arch *sys.Arch, s *Symbol) int {
   189  	return int(decodeInuxi(arch, s.P[commonsize():], 2))
   190  }
   191  
   192  func decodetypeFuncOutCount(arch *sys.Arch, s *Symbol) int {
   193  	return int(uint16(decodeInuxi(arch, s.P[commonsize()+2:], 2)) & (1<<15 - 1))
   194  }
   195  
   196  func decodetypeFuncInType(s *Symbol, i int) *Symbol {
   197  	uadd := commonsize() + 4
   198  	if SysArch.PtrSize == 8 {
   199  		uadd += 4
   200  	}
   201  	if decodetypeHasUncommon(s) {
   202  		uadd += uncommonSize()
   203  	}
   204  	return decodeRelocSym(s, int32(uadd+i*SysArch.PtrSize))
   205  }
   206  
   207  func decodetypeFuncOutType(arch *sys.Arch, s *Symbol, i int) *Symbol {
   208  	return decodetypeFuncInType(s, i+decodetypeFuncInCount(arch, s))
   209  }
   210  
   211  // Type.StructType.fields.Slice::length
   212  func decodetypeStructFieldCount(arch *sys.Arch, s *Symbol) int {
   213  	return int(decodeInuxi(arch, s.P[commonsize()+2*SysArch.PtrSize:], SysArch.PtrSize))
   214  }
   215  
   216  func decodetypeStructFieldArrayOff(s *Symbol, i int) int {
   217  	off := commonsize() + 4*SysArch.PtrSize
   218  	if decodetypeHasUncommon(s) {
   219  		off += uncommonSize()
   220  	}
   221  	off += i * structfieldSize()
   222  	return off
   223  }
   224  
   225  // decodetypeStr returns the contents of an rtype's str field (a nameOff).
   226  func decodetypeStr(s *Symbol) string {
   227  	str := decodetypeName(s, 4*SysArch.PtrSize+8)
   228  	if s.P[2*SysArch.PtrSize+4]&tflagExtraStar != 0 {
   229  		return str[1:]
   230  	}
   231  	return str
   232  }
   233  
   234  // decodetypeName decodes the name from a reflect.name.
   235  func decodetypeName(s *Symbol, off int) string {
   236  	r := decodeReloc(s, int32(off))
   237  	if r == nil {
   238  		return ""
   239  	}
   240  
   241  	data := r.Sym.P
   242  	namelen := int(uint16(data[1])<<8 | uint16(data[2]))
   243  	return string(data[3 : 3+namelen])
   244  }
   245  
   246  func decodetypeStructFieldName(s *Symbol, i int) string {
   247  	off := decodetypeStructFieldArrayOff(s, i)
   248  	return decodetypeName(s, off)
   249  }
   250  
   251  func decodetypeStructFieldType(s *Symbol, i int) *Symbol {
   252  	off := decodetypeStructFieldArrayOff(s, i)
   253  	return decodeRelocSym(s, int32(off+SysArch.PtrSize))
   254  }
   255  
   256  func decodetypeStructFieldOffs(arch *sys.Arch, s *Symbol, i int) int64 {
   257  	return decodetypeStructFieldOffsAnon(arch, s, i) >> 1
   258  }
   259  
   260  func decodetypeStructFieldOffsAnon(arch *sys.Arch, s *Symbol, i int) int64 {
   261  	off := decodetypeStructFieldArrayOff(s, i)
   262  	return int64(decodeInuxi(arch, s.P[off+2*SysArch.PtrSize:], SysArch.PtrSize))
   263  }
   264  
   265  // InterfaceType.methods.length
   266  func decodetypeIfaceMethodCount(arch *sys.Arch, s *Symbol) int64 {
   267  	return int64(decodeInuxi(arch, s.P[commonsize()+2*SysArch.PtrSize:], SysArch.PtrSize))
   268  }
   269  
   270  // methodsig is a fully qualified typed method signature, like
   271  // "Visit(type.go/ast.Node) (type.go/ast.Visitor)".
   272  type methodsig string
   273  
   274  // Matches runtime/typekind.go and reflect.Kind.
   275  const (
   276  	kindArray     = 17
   277  	kindChan      = 18
   278  	kindFunc      = 19
   279  	kindInterface = 20
   280  	kindMap       = 21
   281  	kindPtr       = 22
   282  	kindSlice     = 23
   283  	kindStruct    = 25
   284  	kindMask      = (1 << 5) - 1
   285  )
   286  
   287  // decodeMethodSig decodes an array of method signature information.
   288  // Each element of the array is size bytes. The first 4 bytes is a
   289  // nameOff for the method name, and the next 4 bytes is a typeOff for
   290  // the function type.
   291  //
   292  // Conveniently this is the layout of both runtime.method and runtime.imethod.
   293  func decodeMethodSig(arch *sys.Arch, s *Symbol, off, size, count int) []methodsig {
   294  	var buf bytes.Buffer
   295  	var methods []methodsig
   296  	for i := 0; i < count; i++ {
   297  		buf.WriteString(decodetypeName(s, off))
   298  		mtypSym := decodeRelocSym(s, int32(off+4))
   299  
   300  		buf.WriteRune('(')
   301  		inCount := decodetypeFuncInCount(arch, mtypSym)
   302  		for i := 0; i < inCount; i++ {
   303  			if i > 0 {
   304  				buf.WriteString(", ")
   305  			}
   306  			buf.WriteString(decodetypeFuncInType(mtypSym, i).Name)
   307  		}
   308  		buf.WriteString(") (")
   309  		outCount := decodetypeFuncOutCount(arch, mtypSym)
   310  		for i := 0; i < outCount; i++ {
   311  			if i > 0 {
   312  				buf.WriteString(", ")
   313  			}
   314  			buf.WriteString(decodetypeFuncOutType(arch, mtypSym, i).Name)
   315  		}
   316  		buf.WriteRune(')')
   317  
   318  		off += size
   319  		methods = append(methods, methodsig(buf.String()))
   320  		buf.Reset()
   321  	}
   322  	return methods
   323  }
   324  
   325  func decodeIfaceMethods(arch *sys.Arch, s *Symbol) []methodsig {
   326  	if decodetypeKind(s)&kindMask != kindInterface {
   327  		panic(fmt.Sprintf("symbol %q is not an interface", s.Name))
   328  	}
   329  	r := decodeReloc(s, int32(commonsize()+SysArch.PtrSize))
   330  	if r == nil {
   331  		return nil
   332  	}
   333  	if r.Sym != s {
   334  		panic(fmt.Sprintf("imethod slice pointer in %q leads to a different symbol", s.Name))
   335  	}
   336  	off := int(r.Add) // array of reflect.imethod values
   337  	numMethods := int(decodetypeIfaceMethodCount(arch, s))
   338  	sizeofIMethod := 4 + 4
   339  	return decodeMethodSig(arch, s, off, sizeofIMethod, numMethods)
   340  }
   341  
   342  func decodetypeMethods(arch *sys.Arch, s *Symbol) []methodsig {
   343  	if !decodetypeHasUncommon(s) {
   344  		panic(fmt.Sprintf("no methods on %q", s.Name))
   345  	}
   346  	off := commonsize() // reflect.rtype
   347  	switch decodetypeKind(s) & kindMask {
   348  	case kindStruct: // reflect.structType
   349  		off += 4 * SysArch.PtrSize
   350  	case kindPtr: // reflect.ptrType
   351  		off += SysArch.PtrSize
   352  	case kindFunc: // reflect.funcType
   353  		off += SysArch.PtrSize // 4 bytes, pointer aligned
   354  	case kindSlice: // reflect.sliceType
   355  		off += SysArch.PtrSize
   356  	case kindArray: // reflect.arrayType
   357  		off += 3 * SysArch.PtrSize
   358  	case kindChan: // reflect.chanType
   359  		off += 2 * SysArch.PtrSize
   360  	case kindMap: // reflect.mapType
   361  		off += 4*SysArch.PtrSize + 8
   362  	case kindInterface: // reflect.interfaceType
   363  		off += 3 * SysArch.PtrSize
   364  	default:
   365  		// just Sizeof(rtype)
   366  	}
   367  
   368  	mcount := int(decodeInuxi(arch, s.P[off+4:], 2))
   369  	moff := int(decodeInuxi(arch, s.P[off+4+2+2:], 4))
   370  	off += moff                // offset to array of reflect.method values
   371  	const sizeofMethod = 4 * 4 // sizeof reflect.method in program
   372  	return decodeMethodSig(arch, s, off, sizeofMethod, mcount)
   373  }