1 // Copyright 2017 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 sym 6 7 import ( 8 "cmd/internal/objabi" 9 "cmd/internal/sys" 10 "debug/elf" 11 "fmt" 12 "log" 13 ) 14 15 // Symbol is an entry in the symbol table. 16 type Symbol struct { 17 Name string 18 Extname string 19 Type SymKind 20 Version int16 21 Attr Attribute 22 Localentry uint8 23 Dynid int32 24 Plt int32 25 Got int32 26 Align int32 27 Elfsym int32 28 LocalElfsym int32 29 Value int64 30 Size int64 31 // ElfType is set for symbols read from shared libraries by ldshlibsyms. It 32 // is not set for symbols defined by the packages being linked or by symbols 33 // read by ldelf (and so is left as elf.STT_NOTYPE). 34 ElfType elf.SymType 35 Sub *Symbol 36 Outer *Symbol 37 Gotype *Symbol 38 Reachparent *Symbol 39 File string 40 Dynimplib string 41 Dynimpvers string 42 Sect *Section 43 FuncInfo *FuncInfo 44 Lib *Library // Package defining this symbol 45 // P contains the raw symbol data. 46 P []byte 47 R []Reloc 48 } 49 50 func (s *Symbol) String() string { 51 if s.Version == 0 { 52 return s.Name 53 } 54 return fmt.Sprintf("%s<%d>", s.Name, s.Version) 55 } 56 57 func (s *Symbol) ElfsymForReloc() int32 { 58 // If putelfsym created a local version of this symbol, use that in all 59 // relocations. 60 if s.LocalElfsym != 0 { 61 return s.LocalElfsym 62 } else { 63 return s.Elfsym 64 } 65 } 66 67 func (s *Symbol) Len() int64 { 68 return s.Size 69 } 70 71 func (s *Symbol) Grow(siz int64) { 72 if int64(int(siz)) != siz { 73 log.Fatalf("symgrow size %d too long", siz) 74 } 75 if int64(len(s.P)) >= siz { 76 return 77 } 78 if cap(s.P) < int(siz) { 79 p := make([]byte, 2*(siz+1)) 80 s.P = append(p[:0], s.P...) 81 } 82 s.P = s.P[:siz] 83 } 84 85 func (s *Symbol) AddBytes(bytes []byte) int64 { 86 if s.Type == 0 { 87 s.Type = SDATA 88 } 89 s.Attr |= AttrReachable 90 s.P = append(s.P, bytes...) 91 s.Size = int64(len(s.P)) 92 93 return s.Size 94 } 95 96 func (s *Symbol) AddUint8(v uint8) int64 { 97 off := s.Size 98 if s.Type == 0 { 99 s.Type = SDATA 100 } 101 s.Attr |= AttrReachable 102 s.Size++ 103 s.P = append(s.P, v) 104 105 return off 106 } 107 108 func (s *Symbol) AddUint16(arch *sys.Arch, v uint16) int64 { 109 return s.AddUintXX(arch, uint64(v), 2) 110 } 111 112 func (s *Symbol) AddUint32(arch *sys.Arch, v uint32) int64 { 113 return s.AddUintXX(arch, uint64(v), 4) 114 } 115 116 func (s *Symbol) AddUint64(arch *sys.Arch, v uint64) int64 { 117 return s.AddUintXX(arch, v, 8) 118 } 119 120 func (s *Symbol) AddUint(arch *sys.Arch, v uint64) int64 { 121 return s.AddUintXX(arch, v, arch.PtrSize) 122 } 123 124 func (s *Symbol) SetUint8(arch *sys.Arch, r int64, v uint8) int64 { 125 return s.setUintXX(arch, r, uint64(v), 1) 126 } 127 128 func (s *Symbol) SetUint32(arch *sys.Arch, r int64, v uint32) int64 { 129 return s.setUintXX(arch, r, uint64(v), 4) 130 } 131 132 func (s *Symbol) SetUint(arch *sys.Arch, r int64, v uint64) int64 { 133 return s.setUintXX(arch, r, v, int64(arch.PtrSize)) 134 } 135 136 func (s *Symbol) addAddrPlus(arch *sys.Arch, t *Symbol, add int64, typ objabi.RelocType) int64 { 137 if s.Type == 0 { 138 s.Type = SDATA 139 } 140 s.Attr |= AttrReachable 141 i := s.Size 142 s.Size += int64(arch.PtrSize) 143 s.Grow(s.Size) 144 r := s.AddRel() 145 r.Sym = t 146 r.Off = int32(i) 147 r.Siz = uint8(arch.PtrSize) 148 r.Type = typ 149 r.Add = add 150 return i + int64(r.Siz) 151 } 152 153 func (s *Symbol) AddAddrPlus(arch *sys.Arch, t *Symbol, add int64) int64 { 154 return s.addAddrPlus(arch, t, add, objabi.R_ADDR) 155 } 156 157 func (s *Symbol) AddCURelativeAddrPlus(arch *sys.Arch, t *Symbol, add int64) int64 { 158 return s.addAddrPlus(arch, t, add, objabi.R_ADDRCUOFF) 159 } 160 161 func (s *Symbol) AddPCRelPlus(arch *sys.Arch, t *Symbol, add int64) int64 { 162 if s.Type == 0 { 163 s.Type = SDATA 164 } 165 s.Attr |= AttrReachable 166 i := s.Size 167 s.Size += 4 168 s.Grow(s.Size) 169 r := s.AddRel() 170 r.Sym = t 171 r.Off = int32(i) 172 r.Add = add 173 r.Type = objabi.R_PCREL 174 r.Siz = 4 175 if arch.Family == sys.S390X { 176 r.Variant = RV_390_DBL 177 } 178 return i + int64(r.Siz) 179 } 180 181 func (s *Symbol) AddAddr(arch *sys.Arch, t *Symbol) int64 { 182 return s.AddAddrPlus(arch, t, 0) 183 } 184 185 func (s *Symbol) SetAddrPlus(arch *sys.Arch, off int64, t *Symbol, add int64) int64 { 186 if s.Type == 0 { 187 s.Type = SDATA 188 } 189 s.Attr |= AttrReachable 190 if off+int64(arch.PtrSize) > s.Size { 191 s.Size = off + int64(arch.PtrSize) 192 s.Grow(s.Size) 193 } 194 195 r := s.AddRel() 196 r.Sym = t 197 r.Off = int32(off) 198 r.Siz = uint8(arch.PtrSize) 199 r.Type = objabi.R_ADDR 200 r.Add = add 201 return off + int64(r.Siz) 202 } 203 204 func (s *Symbol) SetAddr(arch *sys.Arch, off int64, t *Symbol) int64 { 205 return s.SetAddrPlus(arch, off, t, 0) 206 } 207 208 func (s *Symbol) AddSize(arch *sys.Arch, t *Symbol) int64 { 209 if s.Type == 0 { 210 s.Type = SDATA 211 } 212 s.Attr |= AttrReachable 213 i := s.Size 214 s.Size += int64(arch.PtrSize) 215 s.Grow(s.Size) 216 r := s.AddRel() 217 r.Sym = t 218 r.Off = int32(i) 219 r.Siz = uint8(arch.PtrSize) 220 r.Type = objabi.R_SIZE 221 return i + int64(r.Siz) 222 } 223 224 func (s *Symbol) AddAddrPlus4(t *Symbol, add int64) int64 { 225 if s.Type == 0 { 226 s.Type = SDATA 227 } 228 s.Attr |= AttrReachable 229 i := s.Size 230 s.Size += 4 231 s.Grow(s.Size) 232 r := s.AddRel() 233 r.Sym = t 234 r.Off = int32(i) 235 r.Siz = 4 236 r.Type = objabi.R_ADDR 237 r.Add = add 238 return i + int64(r.Siz) 239 } 240 241 func (s *Symbol) AddRel() *Reloc { 242 s.R = append(s.R, Reloc{}) 243 return &s.R[len(s.R)-1] 244 } 245 246 func (s *Symbol) AddUintXX(arch *sys.Arch, v uint64, wid int) int64 { 247 off := s.Size 248 s.setUintXX(arch, off, v, int64(wid)) 249 return off 250 } 251 252 func (s *Symbol) setUintXX(arch *sys.Arch, off int64, v uint64, wid int64) int64 { 253 if s.Type == 0 { 254 s.Type = SDATA 255 } 256 s.Attr |= AttrReachable 257 if s.Size < off+wid { 258 s.Size = off + wid 259 s.Grow(s.Size) 260 } 261 262 switch wid { 263 case 1: 264 s.P[off] = uint8(v) 265 case 2: 266 arch.ByteOrder.PutUint16(s.P[off:], uint16(v)) 267 case 4: 268 arch.ByteOrder.PutUint32(s.P[off:], uint32(v)) 269 case 8: 270 arch.ByteOrder.PutUint64(s.P[off:], v) 271 } 272 273 return off + wid 274 } 275 276 // SortSub sorts a linked-list (by Sub) of *Symbol by Value. 277 // Used for sub-symbols when loading host objects (see e.g. ldelf.go). 278 func SortSub(l *Symbol) *Symbol { 279 if l == nil || l.Sub == nil { 280 return l 281 } 282 283 l1 := l 284 l2 := l 285 for { 286 l2 = l2.Sub 287 if l2 == nil { 288 break 289 } 290 l2 = l2.Sub 291 if l2 == nil { 292 break 293 } 294 l1 = l1.Sub 295 } 296 297 l2 = l1.Sub 298 l1.Sub = nil 299 l1 = SortSub(l) 300 l2 = SortSub(l2) 301 302 /* set up lead element */ 303 if l1.Value < l2.Value { 304 l = l1 305 l1 = l1.Sub 306 } else { 307 l = l2 308 l2 = l2.Sub 309 } 310 311 le := l 312 313 for { 314 if l1 == nil { 315 for l2 != nil { 316 le.Sub = l2 317 le = l2 318 l2 = l2.Sub 319 } 320 321 le.Sub = nil 322 break 323 } 324 325 if l2 == nil { 326 for l1 != nil { 327 le.Sub = l1 328 le = l1 329 l1 = l1.Sub 330 } 331 332 break 333 } 334 335 if l1.Value < l2.Value { 336 le.Sub = l1 337 le = l1 338 l1 = l1.Sub 339 } else { 340 le.Sub = l2 341 le = l2 342 l2 = l2.Sub 343 } 344 } 345 346 le.Sub = nil 347 return l 348 } 349 350 type FuncInfo struct { 351 Args int32 352 Locals int32 353 Autom []Auto 354 Pcsp Pcdata 355 Pcfile Pcdata 356 Pcline Pcdata 357 Pcinline Pcdata 358 Pcdata []Pcdata 359 Funcdata []*Symbol 360 Funcdataoff []int64 361 File []*Symbol 362 InlTree []InlinedCall 363 } 364 365 // InlinedCall is a node in a local inlining tree (FuncInfo.InlTree). 366 type InlinedCall struct { 367 Parent int32 // index of parent in InlTree 368 File *Symbol // file of the inlined call 369 Line int32 // line number of the inlined call 370 Func *Symbol // function that was inlined 371 } 372 373 type Pcdata struct { 374 P []byte 375 } 376 377 type Auto struct { 378 Asym *Symbol 379 Gotype *Symbol 380 Aoffset int32 381 Name int16 382 } 383