github.com/q45/go@v0.0.0-20151101211701-a4fb8c13db3f/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  	return decode_inuxi(s.P[2*int32(Thearch.Ptrsize)+8+1*int32(Thearch.Ptrsize):], Thearch.Ptrsize)
   114  }
   115  
   116  func decodetype_gcmask(s *LSym) []byte {
   117  	if s.Type == obj.SDYNIMPORT {
   118  		addr := decodetype_gcprog_shlib(s)
   119  		ptrdata := decodetype_ptrdata(s)
   120  		sect := findShlibSection(s.File, addr)
   121  		if sect != nil {
   122  			r := make([]byte, ptrdata/int64(Thearch.Ptrsize))
   123  			sect.ReadAt(r, int64(addr-sect.Addr))
   124  			return r
   125  		}
   126  		Exitf("cannot find gcmask for %s", s.Name)
   127  		return nil
   128  	}
   129  	mask := decode_reloc_sym(s, 2*int32(Thearch.Ptrsize)+8+1*int32(Thearch.Ptrsize))
   130  	return mask.P
   131  }
   132  
   133  // Type.ArrayType.elem and Type.SliceType.Elem
   134  func decodetype_arrayelem(s *LSym) *LSym {
   135  	return decode_reloc_sym(s, int32(commonsize())) // 0x1c / 0x30
   136  }
   137  
   138  func decodetype_arraylen(s *LSym) int64 {
   139  	return int64(decode_inuxi(s.P[commonsize()+2*Thearch.Ptrsize:], Thearch.Ptrsize))
   140  }
   141  
   142  // Type.PtrType.elem
   143  func decodetype_ptrelem(s *LSym) *LSym {
   144  	return decode_reloc_sym(s, int32(commonsize())) // 0x1c / 0x30
   145  }
   146  
   147  // Type.MapType.key, elem
   148  func decodetype_mapkey(s *LSym) *LSym {
   149  	return decode_reloc_sym(s, int32(commonsize())) // 0x1c / 0x30
   150  }
   151  
   152  func decodetype_mapvalue(s *LSym) *LSym {
   153  	return decode_reloc_sym(s, int32(commonsize())+int32(Thearch.Ptrsize)) // 0x20 / 0x38
   154  }
   155  
   156  // Type.ChanType.elem
   157  func decodetype_chanelem(s *LSym) *LSym {
   158  	return decode_reloc_sym(s, int32(commonsize())) // 0x1c / 0x30
   159  }
   160  
   161  // Type.FuncType.dotdotdot
   162  func decodetype_funcdotdotdot(s *LSym) int {
   163  	return int(s.P[commonsize()])
   164  }
   165  
   166  // Type.FuncType.in.length
   167  func decodetype_funcincount(s *LSym) int {
   168  	return int(decode_inuxi(s.P[commonsize()+2*Thearch.Ptrsize:], Thearch.Intsize))
   169  }
   170  
   171  func decodetype_funcoutcount(s *LSym) int {
   172  	return int(decode_inuxi(s.P[commonsize()+3*Thearch.Ptrsize+2*Thearch.Intsize:], Thearch.Intsize))
   173  }
   174  
   175  func decodetype_funcintype(s *LSym, i int) *LSym {
   176  	r := decode_reloc(s, int32(commonsize())+int32(Thearch.Ptrsize))
   177  	if r == nil {
   178  		return nil
   179  	}
   180  	return decode_reloc_sym(r.Sym, int32(r.Add+int64(int32(i)*int32(Thearch.Ptrsize))))
   181  }
   182  
   183  func decodetype_funcouttype(s *LSym, i int) *LSym {
   184  	r := decode_reloc(s, int32(commonsize())+2*int32(Thearch.Ptrsize)+2*int32(Thearch.Intsize))
   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  // Type.StructType.fields.Slice::length
   192  func decodetype_structfieldcount(s *LSym) int {
   193  	return int(decode_inuxi(s.P[commonsize()+Thearch.Ptrsize:], Thearch.Intsize))
   194  }
   195  
   196  func structfieldsize() int {
   197  	return 5 * Thearch.Ptrsize
   198  }
   199  
   200  // Type.StructType.fields[]-> name, typ and offset.
   201  func decodetype_structfieldname(s *LSym, i int) string {
   202  	// go.string."foo"  0x28 / 0x40
   203  	s = decode_reloc_sym(s, int32(commonsize())+int32(Thearch.Ptrsize)+2*int32(Thearch.Intsize)+int32(i)*int32(structfieldsize()))
   204  
   205  	if s == nil { // embedded structs have a nil name.
   206  		return ""
   207  	}
   208  	r := decode_reloc(s, 0) // s has a pointer to the string data at offset 0
   209  	if r == nil {           // shouldn't happen.
   210  		return ""
   211  	}
   212  	return cstring(r.Sym.P[r.Add:])
   213  }
   214  
   215  func decodetype_structfieldtype(s *LSym, i int) *LSym {
   216  	return decode_reloc_sym(s, int32(commonsize())+int32(Thearch.Ptrsize)+2*int32(Thearch.Intsize)+int32(i)*int32(structfieldsize())+2*int32(Thearch.Ptrsize))
   217  }
   218  
   219  func decodetype_structfieldoffs(s *LSym, i int) int64 {
   220  	return int64(decode_inuxi(s.P[commonsize()+Thearch.Ptrsize+2*Thearch.Intsize+i*structfieldsize()+4*Thearch.Ptrsize:], Thearch.Intsize))
   221  }
   222  
   223  // InterfaceType.methods.length
   224  func decodetype_ifacemethodcount(s *LSym) int64 {
   225  	return int64(decode_inuxi(s.P[commonsize()+Thearch.Ptrsize:], Thearch.Intsize))
   226  }