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 }