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 5package sym 6 7import ( 8 "cmd/internal/obj" 9 "cmd/internal/objabi" 10 "cmd/internal/sys" 11 "debug/elf" 12 "fmt" 13 "log" 14) 15 16// Symbol is an entry in the symbol table. 17type Symbol struct { 18 Name string 19 Type SymKind 20 Version int16 21 Attr Attribute 22 Dynid int32 23 Align int32 24 Elfsym int32 25 LocalElfsym int32 26 Value int64 27 Size int64 28 Sub *Symbol 29 Outer *Symbol 30 Gotype *Symbol 31 File string // actually package! 32 auxinfo *AuxSymbol 33 Sect *Section 34 FuncInfo *FuncInfo 35 Unit *CompilationUnit 36 // P contains the raw symbol data. 37 P []byte 38 R []Reloc 39} 40 41// AuxSymbol contains less-frequently used sym.Symbol fields. 42type AuxSymbol struct { 43 extname string 44 dynimplib string 45 dynimpvers string 46 localentry uint8 47 plt int32 48 got int32 49 // ElfType is set for symbols read from shared libraries by ldshlibsyms. It 50 // is not set for symbols defined by the packages being linked or by symbols 51 // read by ldelf (and so is left as elf.STT_NOTYPE). 52 elftype elf.SymType 53} 54 55const ( 56 SymVerABI0 = 0 57 SymVerABIInternal = 1 58 SymVerStatic = 10 // Minimum version used by static (file-local) syms 59) 60 61func ABIToVersion(abi obj.ABI) int { 62 switch abi { 63 case obj.ABI0: 64 return SymVerABI0 65 case obj.ABIInternal: 66 return SymVerABIInternal 67 } 68 return -1 69} 70 71func VersionToABI(v int) (obj.ABI, bool) { 72 switch v { 73 case SymVerABI0: 74 return obj.ABI0, true 75 case SymVerABIInternal: 76 return obj.ABIInternal, true 77 } 78 return ^obj.ABI(0), false 79} 80 81func (s *Symbol) String() string { 82 if s.Version == 0 { 83 return s.Name 84 } 85 return fmt.Sprintf("%s<%d>", s.Name, s.Version) 86} 87 88func (s *Symbol) IsFileLocal() bool { 89 return s.Version >= SymVerStatic 90} 91 92func (s *Symbol) ElfsymForReloc() int32 { 93 // If putelfsym created a local version of this symbol, use that in all 94 // relocations. 95 if s.LocalElfsym != 0 { 96 return s.LocalElfsym 97 } else { 98 return s.Elfsym 99 } 100} 101 102func (s *Symbol) Len() int64 { 103 return s.Size 104} 105 106func (s *Symbol) Grow(siz int64) { 107 if int64(int(siz)) != siz { 108 log.Fatalf("symgrow size %d too long", siz) 109 } 110 if int64(len(s.P)) >= siz { 111 return 112 } 113 if cap(s.P) < int(siz) { 114 p := make([]byte, 2*(siz+1)) 115 s.P = append(p[:0], s.P...) 116 } 117 s.P = s.P[:siz] 118} 119 120func (s *Symbol) AddBytes(bytes []byte) int64 { 121 if s.Type == 0 { 122 s.Type = SDATA 123 } 124 s.Attr |= AttrReachable 125 s.P = append(s.P, bytes...) 126 s.Size = int64(len(s.P)) 127 128 return s.Size 129} 130 131func (s *Symbol) AddUint8(v uint8) int64 { 132 off := s.Size 133 if s.Type == 0 { 134 s.Type = SDATA 135 } 136 s.Attr |= AttrReachable 137 s.Size++ 138 s.P = append(s.P, v) 139 140 return off 141} 142 143func (s *Symbol) AddUint16(arch *sys.Arch, v uint16) int64 { 144 return s.AddUintXX(arch, uint64(v), 2) 145} 146 147func (s *Symbol) AddUint32(arch *sys.Arch, v uint32) int64 { 148 return s.AddUintXX(arch, uint64(v), 4) 149} 150 151func (s *Symbol) AddUint64(arch *sys.Arch, v uint64) int64 { 152 return s.AddUintXX(arch, v, 8) 153} 154 155func (s *Symbol) AddUint(arch *sys.Arch, v uint64) int64 { 156 return s.AddUintXX(arch, v, arch.PtrSize) 157} 158 159func (s *Symbol) SetUint8(arch *sys.Arch, r int64, v uint8) int64 { 160 return s.setUintXX(arch, r, uint64(v), 1) 161} 162 163func (s *Symbol) SetUint16(arch *sys.Arch, r int64, v uint16) int64 { 164 return s.setUintXX(arch, r, uint64(v), 2) 165} 166 167func (s *Symbol) SetUint32(arch *sys.Arch, r int64, v uint32) int64 { 168 return s.setUintXX(arch, r, uint64(v), 4) 169} 170 171func (s *Symbol) SetUint(arch *sys.Arch, r int64, v uint64) int64 { 172 return s.setUintXX(arch, r, v, int64(arch.PtrSize)) 173} 174 175func (s *Symbol) addAddrPlus(arch *sys.Arch, t *Symbol, add int64, typ objabi.RelocType) int64 { 176 if s.Type == 0 { 177 s.Type = SDATA 178 } 179 s.Attr |= AttrReachable 180 i := s.Size 181 s.Size += int64(arch.PtrSize) 182 s.Grow(s.Size) 183 r := s.AddRel() 184 r.Sym = t 185 r.Off = int32(i) 186 r.Siz = uint8(arch.PtrSize) 187 r.Type = typ 188 r.Add = add 189 return i + int64(r.Siz) 190} 191 192func (s *Symbol) AddAddrPlus(arch *sys.Arch, t *Symbol, add int64) int64 { 193 return s.addAddrPlus(arch, t, add, objabi.R_ADDR) 194} 195 196func (s *Symbol) AddCURelativeAddrPlus(arch *sys.Arch, t *Symbol, add int64) int64 { 197 return s.addAddrPlus(arch, t, add, objabi.R_ADDRCUOFF) 198} 199 200func (s *Symbol) AddPCRelPlus(arch *sys.Arch, t *Symbol, add int64) int64 { 201 if s.Type == 0 { 202 s.Type = SDATA 203 } 204 s.Attr |= AttrReachable 205 i := s.Size 206 s.Size += 4 207 s.Grow(s.Size) 208 r := s.AddRel() 209 r.Sym = t 210 r.Off = int32(i) 211 r.Add = add 212 r.Type = objabi.R_PCREL 213 r.Siz = 4 214 if arch.Family == sys.S390X || arch.Family == sys.PPC64 { 215 r.InitExt() 216 } 217 if arch.Family == sys.S390X { 218 r.Variant = RV_390_DBL 219 } 220 return i + int64(r.Siz) 221} 222 223func (s *Symbol) AddAddr(arch *sys.Arch, t *Symbol) int64 { 224 return s.AddAddrPlus(arch, t, 0) 225} 226 227func (s *Symbol) SetAddrPlus(arch *sys.Arch, off int64, t *Symbol, add int64) int64 { 228 if s.Type == 0 { 229 s.Type = SDATA 230 } 231 s.Attr |= AttrReachable 232 if off+int64(arch.PtrSize) > s.Size { 233 s.Size = off + int64(arch.PtrSize) 234 s.Grow(s.Size) 235 } 236 237 r := s.AddRel() 238 r.Sym = t 239 r.Off = int32(off) 240 r.Siz = uint8(arch.PtrSize) 241 r.Type = objabi.R_ADDR 242 r.Add = add 243 return off + int64(r.Siz) 244} 245 246func (s *Symbol) SetAddr(arch *sys.Arch, off int64, t *Symbol) int64 { 247 return s.SetAddrPlus(arch, off, t, 0) 248} 249 250func (s *Symbol) AddSize(arch *sys.Arch, t *Symbol) int64 { 251 if s.Type == 0 { 252 s.Type = SDATA 253 } 254 s.Attr |= AttrReachable 255 i := s.Size 256 s.Size += int64(arch.PtrSize) 257 s.Grow(s.Size) 258 r := s.AddRel() 259 r.Sym = t 260 r.Off = int32(i) 261 r.Siz = uint8(arch.PtrSize) 262 r.Type = objabi.R_SIZE 263 return i + int64(r.Siz) 264} 265 266func (s *Symbol) AddAddrPlus4(t *Symbol, add int64) int64 { 267 if s.Type == 0 { 268 s.Type = SDATA 269 } 270 s.Attr |= AttrReachable 271 i := s.Size 272 s.Size += 4 273 s.Grow(s.Size) 274 r := s.AddRel() 275 r.Sym = t 276 r.Off = int32(i) 277 r.Siz = 4 278 r.Type = objabi.R_ADDR 279 r.Add = add 280 return i + int64(r.Siz) 281} 282 283func (s *Symbol) AddRel() *Reloc { 284 s.R = append(s.R, Reloc{}) 285 return &s.R[len(s.R)-1] 286} 287 288func (s *Symbol) AddUintXX(arch *sys.Arch, v uint64, wid int) int64 { 289 off := s.Size 290 s.setUintXX(arch, off, v, int64(wid)) 291 return off 292} 293 294func (s *Symbol) setUintXX(arch *sys.Arch, off int64, v uint64, wid int64) int64 { 295 if s.Type == 0 { 296 s.Type = SDATA 297 } 298 s.Attr |= AttrReachable 299 if s.Size < off+wid { 300 s.Size = off + wid 301 s.Grow(s.Size) 302 } 303 304 switch wid { 305 case 1: 306 s.P[off] = uint8(v) 307 case 2: 308 arch.ByteOrder.PutUint16(s.P[off:], uint16(v)) 309 case 4: 310 arch.ByteOrder.PutUint32(s.P[off:], uint32(v)) 311 case 8: 312 arch.ByteOrder.PutUint64(s.P[off:], v) 313 } 314 315 return off + wid 316} 317 318func (s *Symbol) makeAuxInfo() { 319 if s.auxinfo == nil { 320 s.auxinfo = &AuxSymbol{extname: s.Name, plt: -1, got: -1} 321 } 322} 323 324func (s *Symbol) Extname() string { 325 if s.auxinfo == nil { 326 return s.Name 327 } 328 return s.auxinfo.extname 329} 330 331func (s *Symbol) SetExtname(n string) { 332 if s.auxinfo == nil { 333 if s.Name == n { 334 return 335 } 336 s.makeAuxInfo() 337 } 338 s.auxinfo.extname = n 339} 340 341func (s *Symbol) Dynimplib() string { 342 if s.auxinfo == nil { 343 return "" 344 } 345 return s.auxinfo.dynimplib 346} 347 348func (s *Symbol) Dynimpvers() string { 349 if s.auxinfo == nil { 350 return "" 351 } 352 return s.auxinfo.dynimpvers 353} 354 355func (s *Symbol) SetDynimplib(lib string) { 356 if s.auxinfo == nil { 357 s.makeAuxInfo() 358 } 359 s.auxinfo.dynimplib = lib 360} 361 362func (s *Symbol) SetDynimpvers(vers string) { 363 if s.auxinfo == nil { 364 s.makeAuxInfo() 365 } 366 s.auxinfo.dynimpvers = vers 367} 368 369func (s *Symbol) ResetDyninfo() { 370 if s.auxinfo != nil { 371 s.auxinfo.dynimplib = "" 372 s.auxinfo.dynimpvers = "" 373 } 374} 375 376func (s *Symbol) Localentry() uint8 { 377 if s.auxinfo == nil { 378 return 0 379 } 380 return s.auxinfo.localentry 381} 382 383func (s *Symbol) SetLocalentry(val uint8) { 384 if s.auxinfo == nil { 385 if val != 0 { 386 return 387 } 388 s.makeAuxInfo() 389 } 390 s.auxinfo.localentry = val 391} 392 393func (s *Symbol) Plt() int32 { 394 if s.auxinfo == nil { 395 return -1 396 } 397 return s.auxinfo.plt 398} 399 400func (s *Symbol) SetPlt(val int32) { 401 if s.auxinfo == nil { 402 if val == -1 { 403 return 404 } 405 s.makeAuxInfo() 406 } 407 s.auxinfo.plt = val 408} 409 410func (s *Symbol) Got() int32 { 411 if s.auxinfo == nil { 412 return -1 413 } 414 return s.auxinfo.got 415} 416 417func (s *Symbol) SetGot(val int32) { 418 if s.auxinfo == nil { 419 if val == -1 { 420 return 421 } 422 s.makeAuxInfo() 423 } 424 s.auxinfo.got = val 425} 426 427func (s *Symbol) ElfType() elf.SymType { 428 if s.auxinfo == nil { 429 return elf.STT_NOTYPE 430 } 431 return s.auxinfo.elftype 432} 433 434func (s *Symbol) SetElfType(val elf.SymType) { 435 if s.auxinfo == nil { 436 if val == elf.STT_NOTYPE { 437 return 438 } 439 s.makeAuxInfo() 440 } 441 s.auxinfo.elftype = val 442} 443 444// SortSub sorts a linked-list (by Sub) of *Symbol by Value. 445// Used for sub-symbols when loading host objects (see e.g. ldelf.go). 446func SortSub(l *Symbol) *Symbol { 447 if l == nil || l.Sub == nil { 448 return l 449 } 450 451 l1 := l 452 l2 := l 453 for { 454 l2 = l2.Sub 455 if l2 == nil { 456 break 457 } 458 l2 = l2.Sub 459 if l2 == nil { 460 break 461 } 462 l1 = l1.Sub 463 } 464 465 l2 = l1.Sub 466 l1.Sub = nil 467 l1 = SortSub(l) 468 l2 = SortSub(l2) 469 470 /* set up lead element */ 471 if l1.Value < l2.Value { 472 l = l1 473 l1 = l1.Sub 474 } else { 475 l = l2 476 l2 = l2.Sub 477 } 478 479 le := l 480 481 for { 482 if l1 == nil { 483 for l2 != nil { 484 le.Sub = l2 485 le = l2 486 l2 = l2.Sub 487 } 488 489 le.Sub = nil 490 break 491 } 492 493 if l2 == nil { 494 for l1 != nil { 495 le.Sub = l1 496 le = l1 497 l1 = l1.Sub 498 } 499 500 break 501 } 502 503 if l1.Value < l2.Value { 504 le.Sub = l1 505 le = l1 506 l1 = l1.Sub 507 } else { 508 le.Sub = l2 509 le = l2 510 l2 = l2.Sub 511 } 512 } 513 514 le.Sub = nil 515 return l 516} 517 518type FuncInfo struct { 519 Args int32 520 Locals int32 521 Pcsp Pcdata 522 Pcfile Pcdata 523 Pcline Pcdata 524 Pcinline Pcdata 525 Pcdata []Pcdata 526 Funcdata []*Symbol 527 Funcdataoff []int64 528 File []*Symbol 529 InlTree []InlinedCall 530} 531 532// InlinedCall is a node in a local inlining tree (FuncInfo.InlTree). 533type InlinedCall struct { 534 Parent int32 // index of parent in InlTree 535 File *Symbol // file of the inlined call 536 Line int32 // line number of the inlined call 537 Func string // name of the function that was inlined 538 ParentPC int32 // PC of the instruction just before the inlined body (offset from function start) 539} 540 541type Pcdata struct { 542 P []byte 543} 544