Home | History | Annotate | Download | only in ld
      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 8*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 }
    227