github.com/sean-/go@v0.0.0-20151219100004-97f854cd7bb6/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  	"cmd/internal/obj"
     9  	"debug/elf"
    10  )
    11  
    12  // Decoding the type.* symbols.	 This has to be in sync with
    13  // ../../runtime/type.go, or more specifically, with what
    14  // ../gc/reflect.c stuffs in these.
    15  
    16  func decode_reloc(s *LSym, off int32) *Reloc {
    17  	for i := 0; i < len(s.R); i++ {
    18  		if s.R[i].Off == off {
    19  			return &s.R[i:][0]
    20  		}
    21  	}
    22  	return nil
    23  }
    24  
    25  func decode_reloc_sym(s *LSym, off int32) *LSym {
    26  	r := decode_reloc(s, off)
    27  	if r == nil {
    28  		return nil
    29  	}
    30  	return r.Sym
    31  }
    32  
    33  func decode_inuxi(p []byte, sz int) uint64 {
    34  	switch sz {
    35  	case 2:
    36  		return uint64(Ctxt.Arch.ByteOrder.Uint16(p))
    37  	case 4:
    38  		return uint64(Ctxt.Arch.ByteOrder.Uint32(p))
    39  	case 8:
    40  		return Ctxt.Arch.ByteOrder.Uint64(p)
    41  	default:
    42  		Exitf("dwarf: decode inuxi %d", sz)
    43  		panic("unreachable")
    44  	}
    45  }
    46  
    47  // commonsize returns the size of the common prefix for all type
    48  // structures (runtime._type).
    49  func commonsize() int {
    50  	return 7*Thearch.Ptrsize + 8
    51  }
    52  
    53  // Type.commonType.kind
    54  func decodetype_kind(s *LSym) uint8 {
    55  	return uint8(s.P[2*Thearch.Ptrsize+7] & obj.KindMask) //  0x13 / 0x1f
    56  }
    57  
    58  // Type.commonType.kind
    59  func decodetype_noptr(s *LSym) uint8 {
    60  	return uint8(s.P[2*Thearch.Ptrsize+7] & obj.KindNoPointers) //  0x13 / 0x1f
    61  }
    62  
    63  // Type.commonType.kind
    64  func decodetype_usegcprog(s *LSym) uint8 {
    65  	return uint8(s.P[2*Thearch.Ptrsize+7] & obj.KindGCProg) //  0x13 / 0x1f
    66  }
    67  
    68  // Type.commonType.size
    69  func decodetype_size(s *LSym) int64 {
    70  	return int64(decode_inuxi(s.P, Thearch.Ptrsize)) // 0x8 / 0x10
    71  }
    72  
    73  // Type.commonType.ptrdata
    74  func decodetype_ptrdata(s *LSym) int64 {
    75  	return int64(decode_inuxi(s.P[Thearch.Ptrsize:], Thearch.Ptrsize)) // 0x8 / 0x10
    76  }
    77  
    78  // Find the elf.Section of a given shared library that contains a given address.
    79  func findShlibSection(path string, addr uint64) *elf.Section {
    80  	for _, shlib := range Ctxt.Shlibs {
    81  		if shlib.Path == path {
    82  			for _, sect := range shlib.File.Sections {
    83  				if sect.Addr <= addr && addr <= sect.Addr+sect.Size {
    84  					return sect
    85  				}
    86  			}
    87  		}
    88  	}
    89  	return nil
    90  }
    91  
    92  // Type.commonType.gc
    93  func decodetype_gcprog(s *LSym) []byte {
    94  	if s.Type == obj.SDYNIMPORT {
    95  		addr := decodetype_gcprog_shlib(s)
    96  		sect := findShlibSection(s.File, addr)
    97  		if sect != nil {
    98  			// A gcprog is a 4-byte uint32 indicating length, followed by
    99  			// the actual program.
   100  			progsize := make([]byte, 4)
   101  			sect.ReadAt(progsize, int64(addr-sect.Addr))
   102  			progbytes := make([]byte, Ctxt.Arch.ByteOrder.Uint32(progsize))
   103  			sect.ReadAt(progbytes, int64(addr-sect.Addr+4))
   104  			return append(progsize, progbytes...)
   105  		}
   106  		Exitf("cannot find gcprog for %s", s.Name)
   107  		return nil
   108  	}
   109  	return decode_reloc_sym(s, 2*int32(Thearch.Ptrsize)+8+1*int32(Thearch.Ptrsize)).P
   110  }
   111  
   112  func decodetype_gcprog_shlib(s *LSym) uint64 {
   113  	if Thearch.Thechar == '7' {
   114  		for _, shlib := range Ctxt.Shlibs {
   115  			if shlib.Path == s.File {
   116  				return shlib.gcdata_addresses[s]
   117  			}
   118  		}
   119  		return 0
   120  	}
   121  	return decode_inuxi(s.P[2*int32(Thearch.Ptrsize)+8+1*int32(Thearch.Ptrsize):], Thearch.Ptrsize)
   122  }
   123  
   124  func decodetype_gcmask(s *LSym) []byte {
   125  	if s.Type == obj.SDYNIMPORT {
   126  		addr := decodetype_gcprog_shlib(s)
   127  		ptrdata := decodetype_ptrdata(s)
   128  		sect := findShlibSection(s.File, addr)
   129  		if sect != nil {
   130  			r := make([]byte, ptrdata/int64(Thearch.Ptrsize))
   131  			sect.ReadAt(r, int64(addr-sect.Addr))
   132  			return r
   133  		}
   134  		Exitf("cannot find gcmask for %s", s.Name)
   135  		return nil
   136  	}
   137  	mask := decode_reloc_sym(s, 2*int32(Thearch.Ptrsize)+8+1*int32(Thearch.Ptrsize))
   138  	return mask.P
   139  }
   140  
   141  // Type.ArrayType.elem and Type.SliceType.Elem
   142  func decodetype_arrayelem(s *LSym) *LSym {
   143  	return decode_reloc_sym(s, int32(commonsize())) // 0x1c / 0x30
   144  }
   145  
   146  func decodetype_arraylen(s *LSym) int64 {
   147  	return int64(decode_inuxi(s.P[commonsize()+2*Thearch.Ptrsize:], Thearch.Ptrsize))
   148  }
   149  
   150  // Type.PtrType.elem
   151  func decodetype_ptrelem(s *LSym) *LSym {
   152  	return decode_reloc_sym(s, int32(commonsize())) // 0x1c / 0x30
   153  }
   154  
   155  // Type.MapType.key, elem
   156  func decodetype_mapkey(s *LSym) *LSym {
   157  	return decode_reloc_sym(s, int32(commonsize())) // 0x1c / 0x30
   158  }
   159  
   160  func decodetype_mapvalue(s *LSym) *LSym {
   161  	return decode_reloc_sym(s, int32(commonsize())+int32(Thearch.Ptrsize)) // 0x20 / 0x38
   162  }
   163  
   164  // Type.ChanType.elem
   165  func decodetype_chanelem(s *LSym) *LSym {
   166  	return decode_reloc_sym(s, int32(commonsize())) // 0x1c / 0x30
   167  }
   168  
   169  // Type.FuncType.dotdotdot
   170  func decodetype_funcdotdotdot(s *LSym) int {
   171  	return int(s.P[commonsize()])
   172  }
   173  
   174  // Type.FuncType.in.length
   175  func decodetype_funcincount(s *LSym) int {
   176  	return int(decode_inuxi(s.P[commonsize()+2*Thearch.Ptrsize:], Thearch.Intsize))
   177  }
   178  
   179  func decodetype_funcoutcount(s *LSym) int {
   180  	return int(decode_inuxi(s.P[commonsize()+3*Thearch.Ptrsize+2*Thearch.Intsize:], Thearch.Intsize))
   181  }
   182  
   183  func decodetype_funcintype(s *LSym, i int) *LSym {
   184  	r := decode_reloc(s, int32(commonsize())+int32(Thearch.Ptrsize))
   185  	if r == nil {
   186  		return nil
   187  	}
   188  	return decode_reloc_sym(r.Sym, int32(r.Add+int64(int32(i)*int32(Thearch.Ptrsize))))
   189  }
   190  
   191  func decodetype_funcouttype(s *LSym, i int) *LSym {
   192  	r := decode_reloc(s, int32(commonsize())+2*int32(Thearch.Ptrsize)+2*int32(Thearch.Intsize))
   193  	if r == nil {
   194  		return nil
   195  	}
   196  	return decode_reloc_sym(r.Sym, int32(r.Add+int64(int32(i)*int32(Thearch.Ptrsize))))
   197  }
   198  
   199  // Type.StructType.fields.Slice::length
   200  func decodetype_structfieldcount(s *LSym) int {
   201  	return int(decode_inuxi(s.P[commonsize()+Thearch.Ptrsize:], Thearch.Intsize))
   202  }
   203  
   204  func structfieldsize() int {
   205  	return 5 * Thearch.Ptrsize
   206  }
   207  
   208  // Type.StructType.fields[]-> name, typ and offset.
   209  func decodetype_structfieldname(s *LSym, i int) string {
   210  	// go.string."foo"  0x28 / 0x40
   211  	s = decode_reloc_sym(s, int32(commonsize())+int32(Thearch.Ptrsize)+2*int32(Thearch.Intsize)+int32(i)*int32(structfieldsize()))
   212  
   213  	if s == nil { // embedded structs have a nil name.
   214  		return ""
   215  	}
   216  	r := decode_reloc(s, 0) // s has a pointer to the string data at offset 0
   217  	if r == nil {           // shouldn't happen.
   218  		return ""
   219  	}
   220  	return cstring(r.Sym.P[r.Add:])
   221  }
   222  
   223  func decodetype_structfieldtype(s *LSym, i int) *LSym {
   224  	return decode_reloc_sym(s, int32(commonsize())+int32(Thearch.Ptrsize)+2*int32(Thearch.Intsize)+int32(i)*int32(structfieldsize())+2*int32(Thearch.Ptrsize))
   225  }
   226  
   227  func decodetype_structfieldoffs(s *LSym, i int) int64 {
   228  	return int64(decode_inuxi(s.P[commonsize()+Thearch.Ptrsize+2*Thearch.Intsize+i*structfieldsize()+4*Thearch.Ptrsize:], Thearch.Intsize))
   229  }
   230  
   231  // InterfaceType.methods.length
   232  func decodetype_ifacemethodcount(s *LSym) int64 {
   233  	return int64(decode_inuxi(s.P[commonsize()+Thearch.Ptrsize:], Thearch.Intsize))
   234  }