1// Copyright 2019 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 loader 6 7import ( 8 "bytes" 9 "cmd/internal/bio" 10 "cmd/internal/goobj" 11 "cmd/internal/obj" 12 "cmd/internal/objabi" 13 "cmd/internal/sys" 14 "cmd/link/internal/sym" 15 "debug/elf" 16 "fmt" 17 "internal/abi" 18 "io" 19 "log" 20 "math/bits" 21 "os" 22 "sort" 23 "strings" 24) 25 26var _ = fmt.Print 27 28// Sym encapsulates a global symbol index, used to identify a specific 29// Go symbol. The 0-valued Sym is corresponds to an invalid symbol. 30type Sym = sym.LoaderSym 31 32// Relocs encapsulates the set of relocations on a given symbol; an 33// instance of this type is returned by the Loader Relocs() method. 34type Relocs struct { 35 rs []goobj.Reloc 36 37 li uint32 // local index of symbol whose relocs we're examining 38 r *oReader // object reader for containing package 39 l *Loader // loader 40} 41 42// ExtReloc contains the payload for an external relocation. 43type ExtReloc struct { 44 Xsym Sym 45 Xadd int64 46 Type objabi.RelocType 47 Size uint8 48} 49 50// Reloc holds a "handle" to access a relocation record from an 51// object file. 52type Reloc struct { 53 *goobj.Reloc 54 r *oReader 55 l *Loader 56} 57 58func (rel Reloc) Type() objabi.RelocType { return objabi.RelocType(rel.Reloc.Type()) &^ objabi.R_WEAK } 59func (rel Reloc) Weak() bool { return objabi.RelocType(rel.Reloc.Type())&objabi.R_WEAK != 0 } 60func (rel Reloc) SetType(t objabi.RelocType) { rel.Reloc.SetType(uint16(t)) } 61func (rel Reloc) Sym() Sym { return rel.l.resolve(rel.r, rel.Reloc.Sym()) } 62func (rel Reloc) SetSym(s Sym) { rel.Reloc.SetSym(goobj.SymRef{PkgIdx: 0, SymIdx: uint32(s)}) } 63func (rel Reloc) IsMarker() bool { return rel.Siz() == 0 } 64 65// Aux holds a "handle" to access an aux symbol record from an 66// object file. 67type Aux struct { 68 *goobj.Aux 69 r *oReader 70 l *Loader 71} 72 73func (a Aux) Sym() Sym { return a.l.resolve(a.r, a.Aux.Sym()) } 74 75// oReader is a wrapper type of obj.Reader, along with some 76// extra information. 77type oReader struct { 78 *goobj.Reader 79 unit *sym.CompilationUnit 80 version int // version of static symbol 81 pkgprefix string 82 syms []Sym // Sym's global index, indexed by local index 83 pkg []uint32 // indices of referenced package by PkgIdx (index into loader.objs array) 84 ndef int // cache goobj.Reader.NSym() 85 nhashed64def int // cache goobj.Reader.NHashed64Def() 86 nhasheddef int // cache goobj.Reader.NHashedDef() 87 objidx uint32 // index of this reader in the objs slice 88} 89 90// Total number of defined symbols (package symbols, hashed symbols, and 91// non-package symbols). 92func (r *oReader) NAlldef() int { return r.ndef + r.nhashed64def + r.nhasheddef + r.NNonpkgdef() } 93 94// objSym represents a symbol in an object file. It is a tuple of 95// the object and the symbol's local index. 96// For external symbols, objidx is the index of l.extReader (extObj), 97// s is its index into the payload array. 98// {0, 0} represents the nil symbol. 99type objSym struct { 100 objidx uint32 // index of the object (in l.objs array) 101 s uint32 // local index 102} 103 104type nameVer struct { 105 name string 106 v int 107} 108 109type Bitmap []uint32 110 111// set the i-th bit. 112func (bm Bitmap) Set(i Sym) { 113 n, r := uint(i)/32, uint(i)%32 114 bm[n] |= 1 << r 115} 116 117// unset the i-th bit. 118func (bm Bitmap) Unset(i Sym) { 119 n, r := uint(i)/32, uint(i)%32 120 bm[n] &^= (1 << r) 121} 122 123// whether the i-th bit is set. 124func (bm Bitmap) Has(i Sym) bool { 125 n, r := uint(i)/32, uint(i)%32 126 return bm[n]&(1<<r) != 0 127} 128 129// return current length of bitmap in bits. 130func (bm Bitmap) Len() int { 131 return len(bm) * 32 132} 133 134// return the number of bits set. 135func (bm Bitmap) Count() int { 136 s := 0 137 for _, x := range bm { 138 s += bits.OnesCount32(x) 139 } 140 return s 141} 142 143func MakeBitmap(n int) Bitmap { 144 return make(Bitmap, (n+31)/32) 145} 146 147// growBitmap insures that the specified bitmap has enough capacity, 148// reallocating (doubling the size) if needed. 149func growBitmap(reqLen int, b Bitmap) Bitmap { 150 curLen := b.Len() 151 if reqLen > curLen { 152 b = append(b, MakeBitmap(reqLen+1-curLen)...) 153 } 154 return b 155} 156 157type symAndSize struct { 158 sym Sym 159 size uint32 160} 161 162// A Loader loads new object files and resolves indexed symbol references. 163// 164// Notes on the layout of global symbol index space: 165// 166// - Go object files are read before host object files; each Go object 167// read adds its defined package symbols to the global index space. 168// Nonpackage symbols are not yet added. 169// 170// - In loader.LoadNonpkgSyms, add non-package defined symbols and 171// references in all object files to the global index space. 172// 173// - Host object file loading happens; the host object loader does a 174// name/version lookup for each symbol it finds; this can wind up 175// extending the external symbol index space range. The host object 176// loader stores symbol payloads in loader.payloads using SymbolBuilder. 177// 178// - Each symbol gets a unique global index. For duplicated and 179// overwriting/overwritten symbols, the second (or later) appearance 180// of the symbol gets the same global index as the first appearance. 181type Loader struct { 182 objs []*oReader 183 extStart Sym // from this index on, the symbols are externally defined 184 builtinSyms []Sym // global index of builtin symbols 185 186 objSyms []objSym // global index mapping to local index 187 188 symsByName [2]map[string]Sym // map symbol name to index, two maps are for ABI0 and ABIInternal 189 extStaticSyms map[nameVer]Sym // externally defined static symbols, keyed by name 190 191 extReader *oReader // a dummy oReader, for external symbols 192 payloadBatch []extSymPayload 193 payloads []*extSymPayload // contents of linker-materialized external syms 194 values []int64 // symbol values, indexed by global sym index 195 196 sects []*sym.Section // sections 197 symSects []uint16 // symbol's section, index to sects array 198 199 align []uint8 // symbol 2^N alignment, indexed by global index 200 201 deferReturnTramp map[Sym]bool // whether the symbol is a trampoline of a deferreturn call 202 203 objByPkg map[string]uint32 // map package path to the index of its Go object reader 204 205 anonVersion int // most recently assigned ext static sym pseudo-version 206 207 // Bitmaps and other side structures used to store data used to store 208 // symbol flags/attributes; these are to be accessed via the 209 // corresponding loader "AttrXXX" and "SetAttrXXX" methods. Please 210 // visit the comments on these methods for more details on the 211 // semantics / interpretation of the specific flags or attribute. 212 attrReachable Bitmap // reachable symbols, indexed by global index 213 attrOnList Bitmap // "on list" symbols, indexed by global index 214 attrLocal Bitmap // "local" symbols, indexed by global index 215 attrNotInSymbolTable Bitmap // "not in symtab" symbols, indexed by global idx 216 attrUsedInIface Bitmap // "used in interface" symbols, indexed by global idx 217 attrSpecial Bitmap // "special" frame symbols, indexed by global idx 218 attrVisibilityHidden Bitmap // hidden symbols, indexed by ext sym index 219 attrDuplicateOK Bitmap // dupOK symbols, indexed by ext sym index 220 attrShared Bitmap // shared symbols, indexed by ext sym index 221 attrExternal Bitmap // external symbols, indexed by ext sym index 222 generatedSyms Bitmap // symbols that generate their content, indexed by ext sym idx 223 224 attrReadOnly map[Sym]bool // readonly data for this sym 225 attrCgoExportDynamic map[Sym]struct{} // "cgo_export_dynamic" symbols 226 attrCgoExportStatic map[Sym]struct{} // "cgo_export_static" symbols 227 228 // Outer and Sub relations for symbols. 229 outer []Sym // indexed by global index 230 sub map[Sym]Sym 231 232 dynimplib map[Sym]string // stores Dynimplib symbol attribute 233 dynimpvers map[Sym]string // stores Dynimpvers symbol attribute 234 localentry map[Sym]uint8 // stores Localentry symbol attribute 235 extname map[Sym]string // stores Extname symbol attribute 236 elfType map[Sym]elf.SymType // stores elf type symbol property 237 elfSym map[Sym]int32 // stores elf sym symbol property 238 localElfSym map[Sym]int32 // stores "local" elf sym symbol property 239 symPkg map[Sym]string // stores package for symbol, or library for shlib-derived syms 240 plt map[Sym]int32 // stores dynimport for pe objects 241 got map[Sym]int32 // stores got for pe objects 242 dynid map[Sym]int32 // stores Dynid for symbol 243 244 relocVariant map[relocId]sym.RelocVariant // stores variant relocs 245 246 // Used to implement field tracking; created during deadcode if 247 // field tracking is enabled. Reachparent[K] contains the index of 248 // the symbol that triggered the marking of symbol K as live. 249 Reachparent []Sym 250 251 // CgoExports records cgo-exported symbols by SymName. 252 CgoExports map[string]Sym 253 254 flags uint32 255 256 strictDupMsgs int // number of strict-dup warning/errors, when FlagStrictDups is enabled 257 258 errorReporter *ErrorReporter 259 260 npkgsyms int // number of package symbols, for accounting 261 nhashedsyms int // number of hashed symbols, for accounting 262} 263 264const ( 265 pkgDef = iota 266 hashed64Def 267 hashedDef 268 nonPkgDef 269 nonPkgRef 270) 271 272// objidx 273const ( 274 nilObj = iota 275 extObj 276 goObjStart 277) 278 279// extSymPayload holds the payload (data + relocations) for linker-synthesized 280// external symbols (note that symbol value is stored in a separate slice). 281type extSymPayload struct { 282 name string // TODO: would this be better as offset into str table? 283 size int64 284 ver int 285 kind sym.SymKind 286 objidx uint32 // index of original object if sym made by cloneToExternal 287 relocs []goobj.Reloc 288 data []byte 289 auxs []goobj.Aux 290} 291 292const ( 293 // Loader.flags 294 FlagStrictDups = 1 << iota 295 FlagCheckLinkname 296) 297 298func NewLoader(flags uint32, reporter *ErrorReporter) *Loader { 299 nbuiltin := goobj.NBuiltin() 300 extReader := &oReader{objidx: extObj} 301 ldr := &Loader{ 302 objs: []*oReader{nil, extReader}, // reserve index 0 for nil symbol, 1 for external symbols 303 objSyms: make([]objSym, 1, 1), // This will get overwritten later. 304 extReader: extReader, 305 symsByName: [2]map[string]Sym{make(map[string]Sym, 80000), make(map[string]Sym, 50000)}, // preallocate ~2MB for ABI0 and ~1MB for ABI1 symbols 306 objByPkg: make(map[string]uint32), 307 sub: make(map[Sym]Sym), 308 dynimplib: make(map[Sym]string), 309 dynimpvers: make(map[Sym]string), 310 localentry: make(map[Sym]uint8), 311 extname: make(map[Sym]string), 312 attrReadOnly: make(map[Sym]bool), 313 elfType: make(map[Sym]elf.SymType), 314 elfSym: make(map[Sym]int32), 315 localElfSym: make(map[Sym]int32), 316 symPkg: make(map[Sym]string), 317 plt: make(map[Sym]int32), 318 got: make(map[Sym]int32), 319 dynid: make(map[Sym]int32), 320 attrCgoExportDynamic: make(map[Sym]struct{}), 321 attrCgoExportStatic: make(map[Sym]struct{}), 322 deferReturnTramp: make(map[Sym]bool), 323 extStaticSyms: make(map[nameVer]Sym), 324 builtinSyms: make([]Sym, nbuiltin), 325 flags: flags, 326 errorReporter: reporter, 327 sects: []*sym.Section{nil}, // reserve index 0 for nil section 328 } 329 reporter.ldr = ldr 330 return ldr 331} 332 333// Add object file r 334func (l *Loader) addObj(pkg string, r *oReader) { 335 pkg = objabi.PathToPrefix(pkg) // the object file contains escaped package path 336 if _, ok := l.objByPkg[pkg]; !ok { 337 l.objByPkg[pkg] = r.objidx 338 } 339 l.objs = append(l.objs, r) 340} 341 342// Add a symbol from an object file, return the global index. 343// If the symbol already exist, it returns the index of that symbol. 344func (st *loadState) addSym(name string, ver int, r *oReader, li uint32, kind int, osym *goobj.Sym) Sym { 345 l := st.l 346 if l.extStart != 0 { 347 panic("addSym called after external symbol is created") 348 } 349 i := Sym(len(l.objSyms)) 350 if int(i) != len(l.objSyms) { // overflow 351 panic("too many symbols") 352 } 353 addToGlobal := func() { 354 l.objSyms = append(l.objSyms, objSym{r.objidx, li}) 355 } 356 if name == "" && kind != hashed64Def && kind != hashedDef { 357 addToGlobal() 358 return i // unnamed aux symbol 359 } 360 if ver == r.version { 361 // Static symbol. Add its global index but don't 362 // add to name lookup table, as it cannot be 363 // referenced by name. 364 addToGlobal() 365 return i 366 } 367 switch kind { 368 case pkgDef: 369 // Defined package symbols cannot be dup to each other. 370 // We load all the package symbols first, so we don't need 371 // to check dup here. 372 // We still add it to the lookup table, as it may still be 373 // referenced by name (e.g. through linkname). 374 l.symsByName[ver][name] = i 375 addToGlobal() 376 return i 377 case hashed64Def, hashedDef: 378 // Hashed (content-addressable) symbol. Check the hash 379 // but don't add to name lookup table, as they are not 380 // referenced by name. Also no need to do overwriting 381 // check, as same hash indicates same content. 382 var checkHash func() (symAndSize, bool) 383 var addToHashMap func(symAndSize) 384 var h64 uint64 // only used for hashed64Def 385 var h *goobj.HashType // only used for hashedDef 386 if kind == hashed64Def { 387 checkHash = func() (symAndSize, bool) { 388 h64 = r.Hash64(li - uint32(r.ndef)) 389 s, existed := st.hashed64Syms[h64] 390 return s, existed 391 } 392 addToHashMap = func(ss symAndSize) { st.hashed64Syms[h64] = ss } 393 } else { 394 checkHash = func() (symAndSize, bool) { 395 h = r.Hash(li - uint32(r.ndef+r.nhashed64def)) 396 s, existed := st.hashedSyms[*h] 397 return s, existed 398 } 399 addToHashMap = func(ss symAndSize) { st.hashedSyms[*h] = ss } 400 } 401 siz := osym.Siz() 402 if s, existed := checkHash(); existed { 403 // The content hash is built from symbol data and relocations. In the 404 // object file, the symbol data may not always contain trailing zeros, 405 // e.g. for [5]int{1,2,3} and [100]int{1,2,3}, the data is same 406 // (although the size is different). 407 // Also, for short symbols, the content hash is the identity function of 408 // the 8 bytes, and trailing zeros doesn't change the hash value, e.g. 409 // hash("A") == hash("A\0\0\0"). 410 // So when two symbols have the same hash, we need to use the one with 411 // larger size. 412 if siz > s.size { 413 // New symbol has larger size, use the new one. Rewrite the index mapping. 414 l.objSyms[s.sym] = objSym{r.objidx, li} 415 addToHashMap(symAndSize{s.sym, siz}) 416 } 417 return s.sym 418 } 419 addToHashMap(symAndSize{i, siz}) 420 addToGlobal() 421 return i 422 } 423 424 // Non-package (named) symbol. 425 // Check if it already exists. 426 oldi, existed := l.symsByName[ver][name] 427 if !existed { 428 l.symsByName[ver][name] = i 429 addToGlobal() 430 return i 431 } 432 // symbol already exists 433 if osym.Dupok() { 434 if l.flags&FlagStrictDups != 0 { 435 l.checkdup(name, r, li, oldi) 436 } 437 // Fix for issue #47185 -- given two dupok symbols with 438 // different sizes, favor symbol with larger size. See 439 // also issue #46653. 440 szdup := l.SymSize(oldi) 441 sz := int64(r.Sym(li).Siz()) 442 if szdup < sz { 443 // new symbol overwrites old symbol. 444 l.objSyms[oldi] = objSym{r.objidx, li} 445 } 446 return oldi 447 } 448 oldr, oldli := l.toLocal(oldi) 449 oldsym := oldr.Sym(oldli) 450 if oldsym.Dupok() { 451 return oldi 452 } 453 overwrite := r.DataSize(li) != 0 454 if overwrite { 455 // new symbol overwrites old symbol. 456 oldtyp := sym.AbiSymKindToSymKind[objabi.SymKind(oldsym.Type())] 457 if !(oldtyp.IsData() && oldr.DataSize(oldli) == 0) { 458 log.Fatalf("duplicated definition of symbol %s, from %s and %s", name, r.unit.Lib.Pkg, oldr.unit.Lib.Pkg) 459 } 460 l.objSyms[oldi] = objSym{r.objidx, li} 461 } else { 462 // old symbol overwrites new symbol. 463 typ := sym.AbiSymKindToSymKind[objabi.SymKind(oldsym.Type())] 464 if !typ.IsData() { // only allow overwriting data symbol 465 log.Fatalf("duplicated definition of symbol %s, from %s and %s", name, r.unit.Lib.Pkg, oldr.unit.Lib.Pkg) 466 } 467 } 468 return oldi 469} 470 471// newExtSym creates a new external sym with the specified 472// name/version. 473func (l *Loader) newExtSym(name string, ver int) Sym { 474 i := Sym(len(l.objSyms)) 475 if int(i) != len(l.objSyms) { // overflow 476 panic("too many symbols") 477 } 478 if l.extStart == 0 { 479 l.extStart = i 480 } 481 l.growValues(int(i) + 1) 482 l.growOuter(int(i) + 1) 483 l.growAttrBitmaps(int(i) + 1) 484 pi := l.newPayload(name, ver) 485 l.objSyms = append(l.objSyms, objSym{l.extReader.objidx, uint32(pi)}) 486 l.extReader.syms = append(l.extReader.syms, i) 487 return i 488} 489 490// LookupOrCreateSym looks up the symbol with the specified name/version, 491// returning its Sym index if found. If the lookup fails, a new external 492// Sym will be created, entered into the lookup tables, and returned. 493func (l *Loader) LookupOrCreateSym(name string, ver int) Sym { 494 i := l.Lookup(name, ver) 495 if i != 0 { 496 return i 497 } 498 i = l.newExtSym(name, ver) 499 static := ver >= sym.SymVerStatic || ver < 0 500 if static { 501 l.extStaticSyms[nameVer{name, ver}] = i 502 } else { 503 l.symsByName[ver][name] = i 504 } 505 return i 506} 507 508// AddCgoExport records a cgo-exported symbol in l.CgoExports. 509// This table is used to identify the correct Go symbol ABI to use 510// to resolve references from host objects (which don't have ABIs). 511func (l *Loader) AddCgoExport(s Sym) { 512 if l.CgoExports == nil { 513 l.CgoExports = make(map[string]Sym) 514 } 515 l.CgoExports[l.SymName(s)] = s 516} 517 518// LookupOrCreateCgoExport is like LookupOrCreateSym, but if ver 519// indicates a global symbol, it uses the CgoExport table to determine 520// the appropriate symbol version (ABI) to use. ver must be either 0 521// or a static symbol version. 522func (l *Loader) LookupOrCreateCgoExport(name string, ver int) Sym { 523 if ver >= sym.SymVerStatic { 524 return l.LookupOrCreateSym(name, ver) 525 } 526 if ver != 0 { 527 panic("ver must be 0 or a static version") 528 } 529 // Look for a cgo-exported symbol from Go. 530 if s, ok := l.CgoExports[name]; ok { 531 return s 532 } 533 // Otherwise, this must just be a symbol in the host object. 534 // Create a version 0 symbol for it. 535 return l.LookupOrCreateSym(name, 0) 536} 537 538func (l *Loader) IsExternal(i Sym) bool { 539 r, _ := l.toLocal(i) 540 return l.isExtReader(r) 541} 542 543func (l *Loader) isExtReader(r *oReader) bool { 544 return r == l.extReader 545} 546 547// For external symbol, return its index in the payloads array. 548// XXX result is actually not a global index. We (ab)use the Sym type 549// so we don't need conversion for accessing bitmaps. 550func (l *Loader) extIndex(i Sym) Sym { 551 _, li := l.toLocal(i) 552 return Sym(li) 553} 554 555// Get a new payload for external symbol, return its index in 556// the payloads array. 557func (l *Loader) newPayload(name string, ver int) int { 558 pi := len(l.payloads) 559 pp := l.allocPayload() 560 pp.name = name 561 pp.ver = ver 562 l.payloads = append(l.payloads, pp) 563 l.growExtAttrBitmaps() 564 return pi 565} 566 567// getPayload returns a pointer to the extSymPayload struct for an 568// external symbol if the symbol has a payload. Will panic if the 569// symbol in question is bogus (zero or not an external sym). 570func (l *Loader) getPayload(i Sym) *extSymPayload { 571 if !l.IsExternal(i) { 572 panic(fmt.Sprintf("bogus symbol index %d in getPayload", i)) 573 } 574 pi := l.extIndex(i) 575 return l.payloads[pi] 576} 577 578// allocPayload allocates a new payload. 579func (l *Loader) allocPayload() *extSymPayload { 580 batch := l.payloadBatch 581 if len(batch) == 0 { 582 batch = make([]extSymPayload, 1000) 583 } 584 p := &batch[0] 585 l.payloadBatch = batch[1:] 586 return p 587} 588 589func (ms *extSymPayload) Grow(siz int64) { 590 if int64(int(siz)) != siz { 591 log.Fatalf("symgrow size %d too long", siz) 592 } 593 if int64(len(ms.data)) >= siz { 594 return 595 } 596 if cap(ms.data) < int(siz) { 597 cl := len(ms.data) 598 ms.data = append(ms.data, make([]byte, int(siz)+1-cl)...) 599 ms.data = ms.data[0:cl] 600 } 601 ms.data = ms.data[:siz] 602} 603 604// Convert a local index to a global index. 605func (l *Loader) toGlobal(r *oReader, i uint32) Sym { 606 return r.syms[i] 607} 608 609// Convert a global index to a local index. 610func (l *Loader) toLocal(i Sym) (*oReader, uint32) { 611 return l.objs[l.objSyms[i].objidx], l.objSyms[i].s 612} 613 614// Resolve a local symbol reference. Return global index. 615func (l *Loader) resolve(r *oReader, s goobj.SymRef) Sym { 616 var rr *oReader 617 switch p := s.PkgIdx; p { 618 case goobj.PkgIdxInvalid: 619 // {0, X} with non-zero X is never a valid sym reference from a Go object. 620 // We steal this space for symbol references from external objects. 621 // In this case, X is just the global index. 622 if l.isExtReader(r) { 623 return Sym(s.SymIdx) 624 } 625 if s.SymIdx != 0 { 626 panic("bad sym ref") 627 } 628 return 0 629 case goobj.PkgIdxHashed64: 630 i := int(s.SymIdx) + r.ndef 631 return r.syms[i] 632 case goobj.PkgIdxHashed: 633 i := int(s.SymIdx) + r.ndef + r.nhashed64def 634 return r.syms[i] 635 case goobj.PkgIdxNone: 636 i := int(s.SymIdx) + r.ndef + r.nhashed64def + r.nhasheddef 637 return r.syms[i] 638 case goobj.PkgIdxBuiltin: 639 if bi := l.builtinSyms[s.SymIdx]; bi != 0 { 640 return bi 641 } 642 l.reportMissingBuiltin(int(s.SymIdx), r.unit.Lib.Pkg) 643 return 0 644 case goobj.PkgIdxSelf: 645 rr = r 646 default: 647 rr = l.objs[r.pkg[p]] 648 } 649 return l.toGlobal(rr, s.SymIdx) 650} 651 652// reportMissingBuiltin issues an error in the case where we have a 653// relocation against a runtime builtin whose definition is not found 654// when the runtime package is built. The canonical example is 655// "runtime.racefuncenter" -- currently if you do something like 656// 657// go build -gcflags=-race myprogram.go 658// 659// the compiler will insert calls to the builtin runtime.racefuncenter, 660// but the version of the runtime used for linkage won't actually contain 661// definitions of that symbol. See issue #42396 for details. 662// 663// As currently implemented, this is a fatal error. This has drawbacks 664// in that if there are multiple missing builtins, the error will only 665// cite the first one. On the plus side, terminating the link here has 666// advantages in that we won't run the risk of panics or crashes later 667// on in the linker due to R_CALL relocations with 0-valued target 668// symbols. 669func (l *Loader) reportMissingBuiltin(bsym int, reflib string) { 670 bname, _ := goobj.BuiltinName(bsym) 671 log.Fatalf("reference to undefined builtin %q from package %q", 672 bname, reflib) 673} 674 675// Look up a symbol by name, return global index, or 0 if not found. 676// This is more like Syms.ROLookup than Lookup -- it doesn't create 677// new symbol. 678func (l *Loader) Lookup(name string, ver int) Sym { 679 if ver >= sym.SymVerStatic || ver < 0 { 680 return l.extStaticSyms[nameVer{name, ver}] 681 } 682 return l.symsByName[ver][name] 683} 684 685// Check that duplicate symbols have same contents. 686func (l *Loader) checkdup(name string, r *oReader, li uint32, dup Sym) { 687 p := r.Data(li) 688 rdup, ldup := l.toLocal(dup) 689 pdup := rdup.Data(ldup) 690 reason := "same length but different contents" 691 if len(p) != len(pdup) { 692 reason = fmt.Sprintf("new length %d != old length %d", len(p), len(pdup)) 693 } else if bytes.Equal(p, pdup) { 694 // For BSS symbols, we need to check size as well, see issue 46653. 695 szdup := l.SymSize(dup) 696 sz := int64(r.Sym(li).Siz()) 697 if szdup == sz { 698 return 699 } 700 reason = fmt.Sprintf("different sizes: new size %d != old size %d", 701 sz, szdup) 702 } 703 fmt.Fprintf(os.Stderr, "cmd/link: while reading object for '%v': duplicate symbol '%s', previous def at '%v', with mismatched payload: %s\n", r.unit.Lib, name, rdup.unit.Lib, reason) 704 705 // For the moment, allow DWARF subprogram DIEs for 706 // auto-generated wrapper functions. What seems to happen 707 // here is that we get different line numbers on formal 708 // params; I am guessing that the pos is being inherited 709 // from the spot where the wrapper is needed. 710 allowed := strings.HasPrefix(name, "go:info.go.interface") || 711 strings.HasPrefix(name, "go:info.go.builtin") || 712 strings.HasPrefix(name, "go:debuglines") 713 if !allowed { 714 l.strictDupMsgs++ 715 } 716} 717 718func (l *Loader) NStrictDupMsgs() int { return l.strictDupMsgs } 719 720// Number of total symbols. 721func (l *Loader) NSym() int { 722 return len(l.objSyms) 723} 724 725// Number of defined Go symbols. 726func (l *Loader) NDef() int { 727 return int(l.extStart) 728} 729 730// Number of reachable symbols. 731func (l *Loader) NReachableSym() int { 732 return l.attrReachable.Count() 733} 734 735// Returns the name of the i-th symbol. 736func (l *Loader) SymName(i Sym) string { 737 if l.IsExternal(i) { 738 pp := l.getPayload(i) 739 return pp.name 740 } 741 r, li := l.toLocal(i) 742 if r == nil { 743 return "?" 744 } 745 return r.Sym(li).Name(r.Reader) 746} 747 748// Returns the version of the i-th symbol. 749func (l *Loader) SymVersion(i Sym) int { 750 if l.IsExternal(i) { 751 pp := l.getPayload(i) 752 return pp.ver 753 } 754 r, li := l.toLocal(i) 755 return int(abiToVer(r.Sym(li).ABI(), r.version)) 756} 757 758func (l *Loader) IsFileLocal(i Sym) bool { 759 return l.SymVersion(i) >= sym.SymVerStatic 760} 761 762// IsFromAssembly returns true if this symbol is derived from an 763// object file generated by the Go assembler. 764func (l *Loader) IsFromAssembly(i Sym) bool { 765 if l.IsExternal(i) { 766 pp := l.getPayload(i) 767 if pp.objidx != 0 { 768 r := l.objs[pp.objidx] 769 return r.FromAssembly() 770 } 771 return false 772 } 773 r, _ := l.toLocal(i) 774 return r.FromAssembly() 775} 776 777// Returns the type of the i-th symbol. 778func (l *Loader) SymType(i Sym) sym.SymKind { 779 if l.IsExternal(i) { 780 pp := l.getPayload(i) 781 if pp != nil { 782 return pp.kind 783 } 784 return 0 785 } 786 r, li := l.toLocal(i) 787 return sym.AbiSymKindToSymKind[objabi.SymKind(r.Sym(li).Type())] 788} 789 790// Returns the attributes of the i-th symbol. 791func (l *Loader) SymAttr(i Sym) uint8 { 792 if l.IsExternal(i) { 793 // TODO: do something? External symbols have different representation of attributes. 794 // For now, ReflectMethod, NoSplit, GoType, and Typelink are used and they cannot be 795 // set by external symbol. 796 return 0 797 } 798 r, li := l.toLocal(i) 799 return r.Sym(li).Flag() 800} 801 802// Returns the size of the i-th symbol. 803func (l *Loader) SymSize(i Sym) int64 { 804 if l.IsExternal(i) { 805 pp := l.getPayload(i) 806 return pp.size 807 } 808 r, li := l.toLocal(i) 809 return int64(r.Sym(li).Siz()) 810} 811 812// AttrReachable returns true for symbols that are transitively 813// referenced from the entry points. Unreachable symbols are not 814// written to the output. 815func (l *Loader) AttrReachable(i Sym) bool { 816 return l.attrReachable.Has(i) 817} 818 819// SetAttrReachable sets the reachability property for a symbol (see 820// AttrReachable). 821func (l *Loader) SetAttrReachable(i Sym, v bool) { 822 if v { 823 l.attrReachable.Set(i) 824 } else { 825 l.attrReachable.Unset(i) 826 } 827} 828 829// AttrOnList returns true for symbols that are on some list (such as 830// the list of all text symbols, or one of the lists of data symbols) 831// and is consulted to avoid bugs where a symbol is put on a list 832// twice. 833func (l *Loader) AttrOnList(i Sym) bool { 834 return l.attrOnList.Has(i) 835} 836 837// SetAttrOnList sets the "on list" property for a symbol (see 838// AttrOnList). 839func (l *Loader) SetAttrOnList(i Sym, v bool) { 840 if v { 841 l.attrOnList.Set(i) 842 } else { 843 l.attrOnList.Unset(i) 844 } 845} 846 847// AttrLocal returns true for symbols that are only visible within the 848// module (executable or shared library) being linked. This attribute 849// is applied to thunks and certain other linker-generated symbols. 850func (l *Loader) AttrLocal(i Sym) bool { 851 return l.attrLocal.Has(i) 852} 853 854// SetAttrLocal the "local" property for a symbol (see AttrLocal above). 855func (l *Loader) SetAttrLocal(i Sym, v bool) { 856 if v { 857 l.attrLocal.Set(i) 858 } else { 859 l.attrLocal.Unset(i) 860 } 861} 862 863// AttrUsedInIface returns true for a type symbol that is used in 864// an interface. 865func (l *Loader) AttrUsedInIface(i Sym) bool { 866 return l.attrUsedInIface.Has(i) 867} 868 869func (l *Loader) SetAttrUsedInIface(i Sym, v bool) { 870 if v { 871 l.attrUsedInIface.Set(i) 872 } else { 873 l.attrUsedInIface.Unset(i) 874 } 875} 876 877// SymAddr checks that a symbol is reachable, and returns its value. 878func (l *Loader) SymAddr(i Sym) int64 { 879 if !l.AttrReachable(i) { 880 panic("unreachable symbol in symaddr") 881 } 882 return l.values[i] 883} 884 885// AttrNotInSymbolTable returns true for symbols that should not be 886// added to the symbol table of the final generated load module. 887func (l *Loader) AttrNotInSymbolTable(i Sym) bool { 888 return l.attrNotInSymbolTable.Has(i) 889} 890 891// SetAttrNotInSymbolTable the "not in symtab" property for a symbol 892// (see AttrNotInSymbolTable above). 893func (l *Loader) SetAttrNotInSymbolTable(i Sym, v bool) { 894 if v { 895 l.attrNotInSymbolTable.Set(i) 896 } else { 897 l.attrNotInSymbolTable.Unset(i) 898 } 899} 900 901// AttrVisibilityHidden symbols returns true for ELF symbols with 902// visibility set to STV_HIDDEN. They become local symbols in 903// the final executable. Only relevant when internally linking 904// on an ELF platform. 905func (l *Loader) AttrVisibilityHidden(i Sym) bool { 906 if !l.IsExternal(i) { 907 return false 908 } 909 return l.attrVisibilityHidden.Has(l.extIndex(i)) 910} 911 912// SetAttrVisibilityHidden sets the "hidden visibility" property for a 913// symbol (see AttrVisibilityHidden). 914func (l *Loader) SetAttrVisibilityHidden(i Sym, v bool) { 915 if !l.IsExternal(i) { 916 panic("tried to set visibility attr on non-external symbol") 917 } 918 if v { 919 l.attrVisibilityHidden.Set(l.extIndex(i)) 920 } else { 921 l.attrVisibilityHidden.Unset(l.extIndex(i)) 922 } 923} 924 925// AttrDuplicateOK returns true for a symbol that can be present in 926// multiple object files. 927func (l *Loader) AttrDuplicateOK(i Sym) bool { 928 if !l.IsExternal(i) { 929 // TODO: if this path winds up being taken frequently, it 930 // might make more sense to copy the flag value out of the object 931 // into a larger bitmap during preload. 932 r, li := l.toLocal(i) 933 return r.Sym(li).Dupok() 934 } 935 return l.attrDuplicateOK.Has(l.extIndex(i)) 936} 937 938// SetAttrDuplicateOK sets the "duplicate OK" property for an external 939// symbol (see AttrDuplicateOK). 940func (l *Loader) SetAttrDuplicateOK(i Sym, v bool) { 941 if !l.IsExternal(i) { 942 panic("tried to set dupok attr on non-external symbol") 943 } 944 if v { 945 l.attrDuplicateOK.Set(l.extIndex(i)) 946 } else { 947 l.attrDuplicateOK.Unset(l.extIndex(i)) 948 } 949} 950 951// AttrShared returns true for symbols compiled with the -shared option. 952func (l *Loader) AttrShared(i Sym) bool { 953 if !l.IsExternal(i) { 954 // TODO: if this path winds up being taken frequently, it 955 // might make more sense to copy the flag value out of the 956 // object into a larger bitmap during preload. 957 r, _ := l.toLocal(i) 958 return r.Shared() 959 } 960 return l.attrShared.Has(l.extIndex(i)) 961} 962 963// SetAttrShared sets the "shared" property for an external 964// symbol (see AttrShared). 965func (l *Loader) SetAttrShared(i Sym, v bool) { 966 if !l.IsExternal(i) { 967 panic(fmt.Sprintf("tried to set shared attr on non-external symbol %d %s", i, l.SymName(i))) 968 } 969 if v { 970 l.attrShared.Set(l.extIndex(i)) 971 } else { 972 l.attrShared.Unset(l.extIndex(i)) 973 } 974} 975 976// AttrExternal returns true for function symbols loaded from host 977// object files. 978func (l *Loader) AttrExternal(i Sym) bool { 979 if !l.IsExternal(i) { 980 return false 981 } 982 return l.attrExternal.Has(l.extIndex(i)) 983} 984 985// SetAttrExternal sets the "external" property for a host object 986// symbol (see AttrExternal). 987func (l *Loader) SetAttrExternal(i Sym, v bool) { 988 if !l.IsExternal(i) { 989 panic(fmt.Sprintf("tried to set external attr on non-external symbol %q", l.SymName(i))) 990 } 991 if v { 992 l.attrExternal.Set(l.extIndex(i)) 993 } else { 994 l.attrExternal.Unset(l.extIndex(i)) 995 } 996} 997 998// AttrSpecial returns true for a symbols that do not have their 999// address (i.e. Value) computed by the usual mechanism of 1000// data.go:dodata() & data.go:address(). 1001func (l *Loader) AttrSpecial(i Sym) bool { 1002 return l.attrSpecial.Has(i) 1003} 1004 1005// SetAttrSpecial sets the "special" property for a symbol (see 1006// AttrSpecial). 1007func (l *Loader) SetAttrSpecial(i Sym, v bool) { 1008 if v { 1009 l.attrSpecial.Set(i) 1010 } else { 1011 l.attrSpecial.Unset(i) 1012 } 1013} 1014 1015// AttrCgoExportDynamic returns true for a symbol that has been 1016// specially marked via the "cgo_export_dynamic" compiler directive 1017// written by cgo (in response to //export directives in the source). 1018func (l *Loader) AttrCgoExportDynamic(i Sym) bool { 1019 _, ok := l.attrCgoExportDynamic[i] 1020 return ok 1021} 1022 1023// SetAttrCgoExportDynamic sets the "cgo_export_dynamic" for a symbol 1024// (see AttrCgoExportDynamic). 1025func (l *Loader) SetAttrCgoExportDynamic(i Sym, v bool) { 1026 if v { 1027 l.attrCgoExportDynamic[i] = struct{}{} 1028 } else { 1029 delete(l.attrCgoExportDynamic, i) 1030 } 1031} 1032 1033// ForAllCgoExportDynamic calls f for every symbol that has been 1034// marked with the "cgo_export_dynamic" compiler directive. 1035func (l *Loader) ForAllCgoExportDynamic(f func(Sym)) { 1036 for s := range l.attrCgoExportDynamic { 1037 f(s) 1038 } 1039} 1040 1041// AttrCgoExportStatic returns true for a symbol that has been 1042// specially marked via the "cgo_export_static" directive 1043// written by cgo. 1044func (l *Loader) AttrCgoExportStatic(i Sym) bool { 1045 _, ok := l.attrCgoExportStatic[i] 1046 return ok 1047} 1048 1049// SetAttrCgoExportStatic sets the "cgo_export_static" for a symbol 1050// (see AttrCgoExportStatic). 1051func (l *Loader) SetAttrCgoExportStatic(i Sym, v bool) { 1052 if v { 1053 l.attrCgoExportStatic[i] = struct{}{} 1054 } else { 1055 delete(l.attrCgoExportStatic, i) 1056 } 1057} 1058 1059// IsGeneratedSym returns true if a symbol's been previously marked as a 1060// generator symbol through the SetIsGeneratedSym. The functions for generator 1061// symbols are kept in the Link context. 1062func (l *Loader) IsGeneratedSym(i Sym) bool { 1063 if !l.IsExternal(i) { 1064 return false 1065 } 1066 return l.generatedSyms.Has(l.extIndex(i)) 1067} 1068 1069// SetIsGeneratedSym marks symbols as generated symbols. Data shouldn't be 1070// stored in generated symbols, and a function is registered and called for 1071// each of these symbols. 1072func (l *Loader) SetIsGeneratedSym(i Sym, v bool) { 1073 if !l.IsExternal(i) { 1074 panic("only external symbols can be generated") 1075 } 1076 if v { 1077 l.generatedSyms.Set(l.extIndex(i)) 1078 } else { 1079 l.generatedSyms.Unset(l.extIndex(i)) 1080 } 1081} 1082 1083func (l *Loader) AttrCgoExport(i Sym) bool { 1084 return l.AttrCgoExportDynamic(i) || l.AttrCgoExportStatic(i) 1085} 1086 1087// AttrReadOnly returns true for a symbol whose underlying data 1088// is stored via a read-only mmap. 1089func (l *Loader) AttrReadOnly(i Sym) bool { 1090 if v, ok := l.attrReadOnly[i]; ok { 1091 return v 1092 } 1093 if l.IsExternal(i) { 1094 pp := l.getPayload(i) 1095 if pp.objidx != 0 { 1096 return l.objs[pp.objidx].ReadOnly() 1097 } 1098 return false 1099 } 1100 r, _ := l.toLocal(i) 1101 return r.ReadOnly() 1102} 1103 1104// SetAttrReadOnly sets the "data is read only" property for a symbol 1105// (see AttrReadOnly). 1106func (l *Loader) SetAttrReadOnly(i Sym, v bool) { 1107 l.attrReadOnly[i] = v 1108} 1109 1110// AttrSubSymbol returns true for symbols that are listed as a 1111// sub-symbol of some other outer symbol. The sub/outer mechanism is 1112// used when loading host objects (sections from the host object 1113// become regular linker symbols and symbols go on the Sub list of 1114// their section) and for constructing the global offset table when 1115// internally linking a dynamic executable. 1116// 1117// Note that in later stages of the linker, we set Outer(S) to some 1118// container symbol C, but don't set Sub(C). Thus we have two 1119// distinct scenarios: 1120// 1121// - Outer symbol covers the address ranges of its sub-symbols. 1122// Outer.Sub is set in this case. 1123// - Outer symbol doesn't cover the address ranges. It is zero-sized 1124// and doesn't have sub-symbols. In the case, the inner symbol is 1125// not actually a "SubSymbol". (Tricky!) 1126// 1127// This method returns TRUE only for sub-symbols in the first scenario. 1128// 1129// FIXME: would be better to do away with this and have a better way 1130// to represent container symbols. 1131 1132func (l *Loader) AttrSubSymbol(i Sym) bool { 1133 // we don't explicitly store this attribute any more -- return 1134 // a value based on the sub-symbol setting. 1135 o := l.OuterSym(i) 1136 if o == 0 { 1137 return false 1138 } 1139 return l.SubSym(o) != 0 1140} 1141 1142// Note that we don't have a 'SetAttrSubSymbol' method in the loader; 1143// clients should instead use the AddInteriorSym method to establish 1144// containment relationships for host object symbols. 1145 1146// Returns whether the i-th symbol has ReflectMethod attribute set. 1147func (l *Loader) IsReflectMethod(i Sym) bool { 1148 return l.SymAttr(i)&goobj.SymFlagReflectMethod != 0 1149} 1150 1151// Returns whether the i-th symbol is nosplit. 1152func (l *Loader) IsNoSplit(i Sym) bool { 1153 return l.SymAttr(i)&goobj.SymFlagNoSplit != 0 1154} 1155 1156// Returns whether this is a Go type symbol. 1157func (l *Loader) IsGoType(i Sym) bool { 1158 return l.SymAttr(i)&goobj.SymFlagGoType != 0 1159} 1160 1161// Returns whether this symbol should be included in typelink. 1162func (l *Loader) IsTypelink(i Sym) bool { 1163 return l.SymAttr(i)&goobj.SymFlagTypelink != 0 1164} 1165 1166// Returns whether this symbol is an itab symbol. 1167func (l *Loader) IsItab(i Sym) bool { 1168 if l.IsExternal(i) { 1169 return false 1170 } 1171 r, li := l.toLocal(i) 1172 return r.Sym(li).IsItab() 1173} 1174 1175// Returns whether this symbol is a dictionary symbol. 1176func (l *Loader) IsDict(i Sym) bool { 1177 if l.IsExternal(i) { 1178 return false 1179 } 1180 r, li := l.toLocal(i) 1181 return r.Sym(li).IsDict() 1182} 1183 1184// Returns whether this symbol is a compiler-generated package init func. 1185func (l *Loader) IsPkgInit(i Sym) bool { 1186 if l.IsExternal(i) { 1187 return false 1188 } 1189 r, li := l.toLocal(i) 1190 return r.Sym(li).IsPkgInit() 1191} 1192 1193// Return whether this is a trampoline of a deferreturn call. 1194func (l *Loader) IsDeferReturnTramp(i Sym) bool { 1195 return l.deferReturnTramp[i] 1196} 1197 1198// Set that i is a trampoline of a deferreturn call. 1199func (l *Loader) SetIsDeferReturnTramp(i Sym, v bool) { 1200 l.deferReturnTramp[i] = v 1201} 1202 1203// growValues grows the slice used to store symbol values. 1204func (l *Loader) growValues(reqLen int) { 1205 curLen := len(l.values) 1206 if reqLen > curLen { 1207 l.values = append(l.values, make([]int64, reqLen+1-curLen)...) 1208 } 1209} 1210 1211// SymValue returns the value of the i-th symbol. i is global index. 1212func (l *Loader) SymValue(i Sym) int64 { 1213 return l.values[i] 1214} 1215 1216// SetSymValue sets the value of the i-th symbol. i is global index. 1217func (l *Loader) SetSymValue(i Sym, val int64) { 1218 l.values[i] = val 1219} 1220 1221// AddToSymValue adds to the value of the i-th symbol. i is the global index. 1222func (l *Loader) AddToSymValue(i Sym, val int64) { 1223 l.values[i] += val 1224} 1225 1226// Returns the symbol content of the i-th symbol. i is global index. 1227func (l *Loader) Data(i Sym) []byte { 1228 if l.IsExternal(i) { 1229 pp := l.getPayload(i) 1230 if pp != nil { 1231 return pp.data 1232 } 1233 return nil 1234 } 1235 r, li := l.toLocal(i) 1236 return r.Data(li) 1237} 1238 1239// Returns the symbol content of the i-th symbol as a string. i is global index. 1240func (l *Loader) DataString(i Sym) string { 1241 if l.IsExternal(i) { 1242 pp := l.getPayload(i) 1243 return string(pp.data) 1244 } 1245 r, li := l.toLocal(i) 1246 return r.DataString(li) 1247} 1248 1249// FreeData clears the symbol data of an external symbol, allowing the memory 1250// to be freed earlier. No-op for non-external symbols. 1251// i is global index. 1252func (l *Loader) FreeData(i Sym) { 1253 if l.IsExternal(i) { 1254 pp := l.getPayload(i) 1255 if pp != nil { 1256 pp.data = nil 1257 } 1258 } 1259} 1260 1261// SymAlign returns the alignment for a symbol. 1262func (l *Loader) SymAlign(i Sym) int32 { 1263 if int(i) >= len(l.align) { 1264 // align is extended lazily -- it the sym in question is 1265 // outside the range of the existing slice, then we assume its 1266 // alignment has not yet been set. 1267 return 0 1268 } 1269 // TODO: would it make sense to return an arch-specific 1270 // alignment depending on section type? E.g. STEXT => 32, 1271 // SDATA => 1, etc? 1272 abits := l.align[i] 1273 if abits == 0 { 1274 return 0 1275 } 1276 return int32(1 << (abits - 1)) 1277} 1278 1279// SetSymAlign sets the alignment for a symbol. 1280func (l *Loader) SetSymAlign(i Sym, align int32) { 1281 // Reject nonsense alignments. 1282 if align < 0 || align&(align-1) != 0 { 1283 panic("bad alignment value") 1284 } 1285 if int(i) >= len(l.align) { 1286 l.align = append(l.align, make([]uint8, l.NSym()-len(l.align))...) 1287 } 1288 if align == 0 { 1289 l.align[i] = 0 1290 } 1291 l.align[i] = uint8(bits.Len32(uint32(align))) 1292} 1293 1294// SymSect returns the section of the i-th symbol. i is global index. 1295func (l *Loader) SymSect(i Sym) *sym.Section { 1296 if int(i) >= len(l.symSects) { 1297 // symSects is extended lazily -- it the sym in question is 1298 // outside the range of the existing slice, then we assume its 1299 // section has not yet been set. 1300 return nil 1301 } 1302 return l.sects[l.symSects[i]] 1303} 1304 1305// SetSymSect sets the section of the i-th symbol. i is global index. 1306func (l *Loader) SetSymSect(i Sym, sect *sym.Section) { 1307 if int(i) >= len(l.symSects) { 1308 l.symSects = append(l.symSects, make([]uint16, l.NSym()-len(l.symSects))...) 1309 } 1310 l.symSects[i] = sect.Index 1311} 1312 1313// NewSection creates a new (output) section. 1314func (l *Loader) NewSection() *sym.Section { 1315 sect := new(sym.Section) 1316 idx := len(l.sects) 1317 if idx != int(uint16(idx)) { 1318 panic("too many sections created") 1319 } 1320 sect.Index = uint16(idx) 1321 l.sects = append(l.sects, sect) 1322 return sect 1323} 1324 1325// SymDynimplib returns the "dynimplib" attribute for the specified 1326// symbol, making up a portion of the info for a symbol specified 1327// on a "cgo_import_dynamic" compiler directive. 1328func (l *Loader) SymDynimplib(i Sym) string { 1329 return l.dynimplib[i] 1330} 1331 1332// SetSymDynimplib sets the "dynimplib" attribute for a symbol. 1333func (l *Loader) SetSymDynimplib(i Sym, value string) { 1334 // reject bad symbols 1335 if i >= Sym(len(l.objSyms)) || i == 0 { 1336 panic("bad symbol index in SetDynimplib") 1337 } 1338 if value == "" { 1339 delete(l.dynimplib, i) 1340 } else { 1341 l.dynimplib[i] = value 1342 } 1343} 1344 1345// SymDynimpvers returns the "dynimpvers" attribute for the specified 1346// symbol, making up a portion of the info for a symbol specified 1347// on a "cgo_import_dynamic" compiler directive. 1348func (l *Loader) SymDynimpvers(i Sym) string { 1349 return l.dynimpvers[i] 1350} 1351 1352// SetSymDynimpvers sets the "dynimpvers" attribute for a symbol. 1353func (l *Loader) SetSymDynimpvers(i Sym, value string) { 1354 // reject bad symbols 1355 if i >= Sym(len(l.objSyms)) || i == 0 { 1356 panic("bad symbol index in SetDynimpvers") 1357 } 1358 if value == "" { 1359 delete(l.dynimpvers, i) 1360 } else { 1361 l.dynimpvers[i] = value 1362 } 1363} 1364 1365// SymExtname returns the "extname" value for the specified 1366// symbol. 1367func (l *Loader) SymExtname(i Sym) string { 1368 if s, ok := l.extname[i]; ok { 1369 return s 1370 } 1371 return l.SymName(i) 1372} 1373 1374// SetSymExtname sets the "extname" attribute for a symbol. 1375func (l *Loader) SetSymExtname(i Sym, value string) { 1376 // reject bad symbols 1377 if i >= Sym(len(l.objSyms)) || i == 0 { 1378 panic("bad symbol index in SetExtname") 1379 } 1380 if value == "" { 1381 delete(l.extname, i) 1382 } else { 1383 l.extname[i] = value 1384 } 1385} 1386 1387// SymElfType returns the previously recorded ELF type for a symbol 1388// (used only for symbols read from shared libraries by ldshlibsyms). 1389// It is not set for symbols defined by the packages being linked or 1390// by symbols read by ldelf (and so is left as elf.STT_NOTYPE). 1391func (l *Loader) SymElfType(i Sym) elf.SymType { 1392 if et, ok := l.elfType[i]; ok { 1393 return et 1394 } 1395 return elf.STT_NOTYPE 1396} 1397 1398// SetSymElfType sets the elf type attribute for a symbol. 1399func (l *Loader) SetSymElfType(i Sym, et elf.SymType) { 1400 // reject bad symbols 1401 if i >= Sym(len(l.objSyms)) || i == 0 { 1402 panic("bad symbol index in SetSymElfType") 1403 } 1404 if et == elf.STT_NOTYPE { 1405 delete(l.elfType, i) 1406 } else { 1407 l.elfType[i] = et 1408 } 1409} 1410 1411// SymElfSym returns the ELF symbol index for a given loader 1412// symbol, assigned during ELF symtab generation. 1413func (l *Loader) SymElfSym(i Sym) int32 { 1414 return l.elfSym[i] 1415} 1416 1417// SetSymElfSym sets the elf symbol index for a symbol. 1418func (l *Loader) SetSymElfSym(i Sym, es int32) { 1419 if i == 0 { 1420 panic("bad sym index") 1421 } 1422 if es == 0 { 1423 delete(l.elfSym, i) 1424 } else { 1425 l.elfSym[i] = es 1426 } 1427} 1428 1429// SymLocalElfSym returns the "local" ELF symbol index for a given loader 1430// symbol, assigned during ELF symtab generation. 1431func (l *Loader) SymLocalElfSym(i Sym) int32 { 1432 return l.localElfSym[i] 1433} 1434 1435// SetSymLocalElfSym sets the "local" elf symbol index for a symbol. 1436func (l *Loader) SetSymLocalElfSym(i Sym, es int32) { 1437 if i == 0 { 1438 panic("bad sym index") 1439 } 1440 if es == 0 { 1441 delete(l.localElfSym, i) 1442 } else { 1443 l.localElfSym[i] = es 1444 } 1445} 1446 1447// SymPlt returns the PLT offset of symbol s. 1448func (l *Loader) SymPlt(s Sym) int32 { 1449 if v, ok := l.plt[s]; ok { 1450 return v 1451 } 1452 return -1 1453} 1454 1455// SetPlt sets the PLT offset of symbol i. 1456func (l *Loader) SetPlt(i Sym, v int32) { 1457 if i >= Sym(len(l.objSyms)) || i == 0 { 1458 panic("bad symbol for SetPlt") 1459 } 1460 if v == -1 { 1461 delete(l.plt, i) 1462 } else { 1463 l.plt[i] = v 1464 } 1465} 1466 1467// SymGot returns the GOT offset of symbol s. 1468func (l *Loader) SymGot(s Sym) int32 { 1469 if v, ok := l.got[s]; ok { 1470 return v 1471 } 1472 return -1 1473} 1474 1475// SetGot sets the GOT offset of symbol i. 1476func (l *Loader) SetGot(i Sym, v int32) { 1477 if i >= Sym(len(l.objSyms)) || i == 0 { 1478 panic("bad symbol for SetGot") 1479 } 1480 if v == -1 { 1481 delete(l.got, i) 1482 } else { 1483 l.got[i] = v 1484 } 1485} 1486 1487// SymDynid returns the "dynid" property for the specified symbol. 1488func (l *Loader) SymDynid(i Sym) int32 { 1489 if s, ok := l.dynid[i]; ok { 1490 return s 1491 } 1492 return -1 1493} 1494 1495// SetSymDynid sets the "dynid" property for a symbol. 1496func (l *Loader) SetSymDynid(i Sym, val int32) { 1497 // reject bad symbols 1498 if i >= Sym(len(l.objSyms)) || i == 0 { 1499 panic("bad symbol index in SetSymDynid") 1500 } 1501 if val == -1 { 1502 delete(l.dynid, i) 1503 } else { 1504 l.dynid[i] = val 1505 } 1506} 1507 1508// DynidSyms returns the set of symbols for which dynID is set to an 1509// interesting (non-default) value. This is expected to be a fairly 1510// small set. 1511func (l *Loader) DynidSyms() []Sym { 1512 sl := make([]Sym, 0, len(l.dynid)) 1513 for s := range l.dynid { 1514 sl = append(sl, s) 1515 } 1516 sort.Slice(sl, func(i, j int) bool { return sl[i] < sl[j] }) 1517 return sl 1518} 1519 1520// SymGoType returns the 'Gotype' property for a given symbol (set by 1521// the Go compiler for variable symbols). This version relies on 1522// reading aux symbols for the target sym -- it could be that a faster 1523// approach would be to check for gotype during preload and copy the 1524// results in to a map (might want to try this at some point and see 1525// if it helps speed things up). 1526func (l *Loader) SymGoType(i Sym) Sym { return l.aux1(i, goobj.AuxGotype) } 1527 1528// SymUnit returns the compilation unit for a given symbol (which will 1529// typically be nil for external or linker-manufactured symbols). 1530func (l *Loader) SymUnit(i Sym) *sym.CompilationUnit { 1531 if l.IsExternal(i) { 1532 pp := l.getPayload(i) 1533 if pp.objidx != 0 { 1534 r := l.objs[pp.objidx] 1535 return r.unit 1536 } 1537 return nil 1538 } 1539 r, _ := l.toLocal(i) 1540 return r.unit 1541} 1542 1543// SymPkg returns the package where the symbol came from (for 1544// regular compiler-generated Go symbols), but in the case of 1545// building with "-linkshared" (when a symbol is read from a 1546// shared library), will hold the library name. 1547// NOTE: this corresponds to sym.Symbol.File field. 1548func (l *Loader) SymPkg(i Sym) string { 1549 if f, ok := l.symPkg[i]; ok { 1550 return f 1551 } 1552 if l.IsExternal(i) { 1553 pp := l.getPayload(i) 1554 if pp.objidx != 0 { 1555 r := l.objs[pp.objidx] 1556 return r.unit.Lib.Pkg 1557 } 1558 return "" 1559 } 1560 r, _ := l.toLocal(i) 1561 return r.unit.Lib.Pkg 1562} 1563 1564// SetSymPkg sets the package/library for a symbol. This is 1565// needed mainly for external symbols, specifically those imported 1566// from shared libraries. 1567func (l *Loader) SetSymPkg(i Sym, pkg string) { 1568 // reject bad symbols 1569 if i >= Sym(len(l.objSyms)) || i == 0 { 1570 panic("bad symbol index in SetSymPkg") 1571 } 1572 l.symPkg[i] = pkg 1573} 1574 1575// SymLocalentry returns an offset in bytes of the "local entry" of a symbol. 1576// 1577// On PPC64, a value of 1 indicates the symbol does not use or preserve a TOC 1578// pointer in R2, nor does it have a distinct local entry. 1579func (l *Loader) SymLocalentry(i Sym) uint8 { 1580 return l.localentry[i] 1581} 1582 1583// SetSymLocalentry sets the "local entry" offset attribute for a symbol. 1584func (l *Loader) SetSymLocalentry(i Sym, value uint8) { 1585 // reject bad symbols 1586 if i >= Sym(len(l.objSyms)) || i == 0 { 1587 panic("bad symbol index in SetSymLocalentry") 1588 } 1589 if value == 0 { 1590 delete(l.localentry, i) 1591 } else { 1592 l.localentry[i] = value 1593 } 1594} 1595 1596// Returns the number of aux symbols given a global index. 1597func (l *Loader) NAux(i Sym) int { 1598 if l.IsExternal(i) { 1599 return 0 1600 } 1601 r, li := l.toLocal(i) 1602 return r.NAux(li) 1603} 1604 1605// Returns the "handle" to the j-th aux symbol of the i-th symbol. 1606func (l *Loader) Aux(i Sym, j int) Aux { 1607 if l.IsExternal(i) { 1608 return Aux{} 1609 } 1610 r, li := l.toLocal(i) 1611 if j >= r.NAux(li) { 1612 return Aux{} 1613 } 1614 return Aux{r.Aux(li, j), r, l} 1615} 1616 1617// WasmImportSym returns the auxiliary WebAssembly import symbol associated with 1618// a given function symbol. The aux sym only exists for Go function stubs that 1619// have been annotated with the //go:wasmimport directive. The aux sym 1620// contains the information necessary for the linker to add a WebAssembly 1621// import statement. 1622// (https://webassembly.github.io/spec/core/syntax/modules.html#imports) 1623func (l *Loader) WasmImportSym(fnSymIdx Sym) (Sym, bool) { 1624 if l.SymType(fnSymIdx) != sym.STEXT { 1625 log.Fatalf("error: non-function sym %d/%s t=%s passed to WasmImportSym", fnSymIdx, l.SymName(fnSymIdx), l.SymType(fnSymIdx).String()) 1626 } 1627 r, li := l.toLocal(fnSymIdx) 1628 auxs := r.Auxs(li) 1629 for i := range auxs { 1630 a := &auxs[i] 1631 switch a.Type() { 1632 case goobj.AuxWasmImport: 1633 return l.resolve(r, a.Sym()), true 1634 } 1635 } 1636 1637 return 0, false 1638} 1639 1640// SEHUnwindSym returns the auxiliary SEH unwind symbol associated with 1641// a given function symbol. 1642func (l *Loader) SEHUnwindSym(fnSymIdx Sym) Sym { 1643 if l.SymType(fnSymIdx) != sym.STEXT { 1644 log.Fatalf("error: non-function sym %d/%s t=%s passed to SEHUnwindSym", fnSymIdx, l.SymName(fnSymIdx), l.SymType(fnSymIdx).String()) 1645 } 1646 1647 return l.aux1(fnSymIdx, goobj.AuxSehUnwindInfo) 1648} 1649 1650// GetFuncDwarfAuxSyms collects and returns the auxiliary DWARF 1651// symbols associated with a given function symbol. Prior to the 1652// introduction of the loader, this was done purely using name 1653// lookups, e.f. for function with name XYZ we would then look up 1654// go.info.XYZ, etc. 1655func (l *Loader) GetFuncDwarfAuxSyms(fnSymIdx Sym) (auxDwarfInfo, auxDwarfLoc, auxDwarfRanges, auxDwarfLines Sym) { 1656 if l.SymType(fnSymIdx) != sym.STEXT { 1657 log.Fatalf("error: non-function sym %d/%s t=%s passed to GetFuncDwarfAuxSyms", fnSymIdx, l.SymName(fnSymIdx), l.SymType(fnSymIdx).String()) 1658 } 1659 r, auxs := l.auxs(fnSymIdx) 1660 1661 for i := range auxs { 1662 a := &auxs[i] 1663 switch a.Type() { 1664 case goobj.AuxDwarfInfo: 1665 auxDwarfInfo = l.resolve(r, a.Sym()) 1666 if l.SymType(auxDwarfInfo) != sym.SDWARFFCN { 1667 panic("aux dwarf info sym with wrong type") 1668 } 1669 case goobj.AuxDwarfLoc: 1670 auxDwarfLoc = l.resolve(r, a.Sym()) 1671 if l.SymType(auxDwarfLoc) != sym.SDWARFLOC { 1672 panic("aux dwarf loc sym with wrong type") 1673 } 1674 case goobj.AuxDwarfRanges: 1675 auxDwarfRanges = l.resolve(r, a.Sym()) 1676 if l.SymType(auxDwarfRanges) != sym.SDWARFRANGE { 1677 panic("aux dwarf ranges sym with wrong type") 1678 } 1679 case goobj.AuxDwarfLines: 1680 auxDwarfLines = l.resolve(r, a.Sym()) 1681 if l.SymType(auxDwarfLines) != sym.SDWARFLINES { 1682 panic("aux dwarf lines sym with wrong type") 1683 } 1684 } 1685 } 1686 return 1687} 1688 1689func (l *Loader) GetVarDwarfAuxSym(i Sym) Sym { 1690 aux := l.aux1(i, goobj.AuxDwarfInfo) 1691 if aux != 0 && l.SymType(aux) != sym.SDWARFVAR { 1692 fmt.Println(l.SymName(i), l.SymType(i), l.SymType(aux), sym.SDWARFVAR) 1693 panic("aux dwarf info sym with wrong type") 1694 } 1695 return aux 1696} 1697 1698// AddInteriorSym sets up 'interior' as an interior symbol of 1699// container/payload symbol 'container'. An interior symbol does not 1700// itself have data, but gives a name to a subrange of the data in its 1701// container symbol. The container itself may or may not have a name. 1702// This method is intended primarily for use in the host object 1703// loaders, to capture the semantics of symbols and sections in an 1704// object file. When reading a host object file, we'll typically 1705// encounter a static section symbol (ex: ".text") containing content 1706// for a collection of functions, then a series of ELF (or macho, etc) 1707// symbol table entries each of which points into a sub-section 1708// (offset and length) of its corresponding container symbol. Within 1709// the go linker we create a loader.Sym for the container (which is 1710// expected to have the actual content/payload) and then a set of 1711// interior loader.Sym's that point into a portion of the container. 1712func (l *Loader) AddInteriorSym(container Sym, interior Sym) { 1713 // Container symbols are expected to have content/data. 1714 // NB: this restriction may turn out to be too strict (it's possible 1715 // to imagine a zero-sized container with an interior symbol pointing 1716 // into it); it's ok to relax or remove it if we counter an 1717 // oddball host object that triggers this. 1718 if l.SymSize(container) == 0 && len(l.Data(container)) == 0 { 1719 panic("unexpected empty container symbol") 1720 } 1721 // The interior symbols for a container are not expected to have 1722 // content/data or relocations. 1723 if len(l.Data(interior)) != 0 { 1724 panic("unexpected non-empty interior symbol") 1725 } 1726 // Interior symbol is expected to be in the symbol table. 1727 if l.AttrNotInSymbolTable(interior) { 1728 panic("interior symbol must be in symtab") 1729 } 1730 // Only a single level of containment is allowed. 1731 if l.OuterSym(container) != 0 { 1732 panic("outer has outer itself") 1733 } 1734 // Interior sym should not already have a sibling. 1735 if l.SubSym(interior) != 0 { 1736 panic("sub set for subsym") 1737 } 1738 // Interior sym should not already point at a container. 1739 if l.OuterSym(interior) != 0 { 1740 panic("outer already set for subsym") 1741 } 1742 l.sub[interior] = l.sub[container] 1743 l.sub[container] = interior 1744 l.outer[interior] = container 1745} 1746 1747// OuterSym gets the outer/container symbol. 1748func (l *Loader) OuterSym(i Sym) Sym { 1749 return l.outer[i] 1750} 1751 1752// SubSym gets the subsymbol for host object loaded symbols. 1753func (l *Loader) SubSym(i Sym) Sym { 1754 return l.sub[i] 1755} 1756 1757// growOuter grows the slice used to store outer symbol. 1758func (l *Loader) growOuter(reqLen int) { 1759 curLen := len(l.outer) 1760 if reqLen > curLen { 1761 l.outer = append(l.outer, make([]Sym, reqLen-curLen)...) 1762 } 1763} 1764 1765// SetCarrierSym declares that 'c' is the carrier or container symbol 1766// for 's'. Carrier symbols are used in the linker to as a container 1767// for a collection of sub-symbols where the content of the 1768// sub-symbols is effectively concatenated to form the content of the 1769// carrier. The carrier is given a name in the output symbol table 1770// while the sub-symbol names are not. For example, the Go compiler 1771// emits named string symbols (type SGOSTRING) when compiling a 1772// package; after being deduplicated, these symbols are collected into 1773// a single unit by assigning them a new carrier symbol named 1774// "go:string.*" (which appears in the final symbol table for the 1775// output load module). 1776func (l *Loader) SetCarrierSym(s Sym, c Sym) { 1777 if c == 0 { 1778 panic("invalid carrier in SetCarrierSym") 1779 } 1780 if s == 0 { 1781 panic("invalid sub-symbol in SetCarrierSym") 1782 } 1783 // Carrier symbols are not expected to have content/data. It is 1784 // ok for them to have non-zero size (to allow for use of generator 1785 // symbols). 1786 if len(l.Data(c)) != 0 { 1787 panic("unexpected non-empty carrier symbol") 1788 } 1789 l.outer[s] = c 1790 // relocsym's foldSubSymbolOffset requires that we only 1791 // have a single level of containment-- enforce here. 1792 if l.outer[c] != 0 { 1793 panic("invalid nested carrier sym") 1794 } 1795} 1796 1797// Initialize Reachable bitmap and its siblings for running deadcode pass. 1798func (l *Loader) InitReachable() { 1799 l.growAttrBitmaps(l.NSym() + 1) 1800} 1801 1802type symWithVal struct { 1803 s Sym 1804 v int64 1805} 1806type bySymValue []symWithVal 1807 1808func (s bySymValue) Len() int { return len(s) } 1809func (s bySymValue) Swap(i, j int) { s[i], s[j] = s[j], s[i] } 1810func (s bySymValue) Less(i, j int) bool { return s[i].v < s[j].v } 1811 1812// SortSub walks through the sub-symbols for 's' and sorts them 1813// in place by increasing value. Return value is the new 1814// sub symbol for the specified outer symbol. 1815func (l *Loader) SortSub(s Sym) Sym { 1816 1817 if s == 0 || l.sub[s] == 0 { 1818 return s 1819 } 1820 1821 // Sort symbols using a slice first. Use a stable sort on the off 1822 // chance that there's more than once symbol with the same value, 1823 // so as to preserve reproducible builds. 1824 sl := []symWithVal{} 1825 for ss := l.sub[s]; ss != 0; ss = l.sub[ss] { 1826 sl = append(sl, symWithVal{s: ss, v: l.SymValue(ss)}) 1827 } 1828 sort.Stable(bySymValue(sl)) 1829 1830 // Then apply any changes needed to the sub map. 1831 ns := Sym(0) 1832 for i := len(sl) - 1; i >= 0; i-- { 1833 s := sl[i].s 1834 l.sub[s] = ns 1835 ns = s 1836 } 1837 1838 // Update sub for outer symbol, then return 1839 l.sub[s] = sl[0].s 1840 return sl[0].s 1841} 1842 1843// SortSyms sorts a list of symbols by their value. 1844func (l *Loader) SortSyms(ss []Sym) { 1845 sort.SliceStable(ss, func(i, j int) bool { return l.SymValue(ss[i]) < l.SymValue(ss[j]) }) 1846} 1847 1848// Insure that reachable bitmap and its siblings have enough size. 1849func (l *Loader) growAttrBitmaps(reqLen int) { 1850 if reqLen > l.attrReachable.Len() { 1851 // These are indexed by global symbol 1852 l.attrReachable = growBitmap(reqLen, l.attrReachable) 1853 l.attrOnList = growBitmap(reqLen, l.attrOnList) 1854 l.attrLocal = growBitmap(reqLen, l.attrLocal) 1855 l.attrNotInSymbolTable = growBitmap(reqLen, l.attrNotInSymbolTable) 1856 l.attrUsedInIface = growBitmap(reqLen, l.attrUsedInIface) 1857 l.attrSpecial = growBitmap(reqLen, l.attrSpecial) 1858 } 1859 l.growExtAttrBitmaps() 1860} 1861 1862func (l *Loader) growExtAttrBitmaps() { 1863 // These are indexed by external symbol index (e.g. l.extIndex(i)) 1864 extReqLen := len(l.payloads) 1865 if extReqLen > l.attrVisibilityHidden.Len() { 1866 l.attrVisibilityHidden = growBitmap(extReqLen, l.attrVisibilityHidden) 1867 l.attrDuplicateOK = growBitmap(extReqLen, l.attrDuplicateOK) 1868 l.attrShared = growBitmap(extReqLen, l.attrShared) 1869 l.attrExternal = growBitmap(extReqLen, l.attrExternal) 1870 l.generatedSyms = growBitmap(extReqLen, l.generatedSyms) 1871 } 1872} 1873 1874func (relocs *Relocs) Count() int { return len(relocs.rs) } 1875 1876// At returns the j-th reloc for a global symbol. 1877func (relocs *Relocs) At(j int) Reloc { 1878 if relocs.l.isExtReader(relocs.r) { 1879 return Reloc{&relocs.rs[j], relocs.r, relocs.l} 1880 } 1881 return Reloc{&relocs.rs[j], relocs.r, relocs.l} 1882} 1883 1884// Relocs returns a Relocs object for the given global sym. 1885func (l *Loader) Relocs(i Sym) Relocs { 1886 r, li := l.toLocal(i) 1887 if r == nil { 1888 panic(fmt.Sprintf("trying to get oreader for invalid sym %d\n\n", i)) 1889 } 1890 return l.relocs(r, li) 1891} 1892 1893// relocs returns a Relocs object given a local sym index and reader. 1894func (l *Loader) relocs(r *oReader, li uint32) Relocs { 1895 var rs []goobj.Reloc 1896 if l.isExtReader(r) { 1897 pp := l.payloads[li] 1898 rs = pp.relocs 1899 } else { 1900 rs = r.Relocs(li) 1901 } 1902 return Relocs{ 1903 rs: rs, 1904 li: li, 1905 r: r, 1906 l: l, 1907 } 1908} 1909 1910func (l *Loader) auxs(i Sym) (*oReader, []goobj.Aux) { 1911 if l.IsExternal(i) { 1912 pp := l.getPayload(i) 1913 return l.objs[pp.objidx], pp.auxs 1914 } else { 1915 r, li := l.toLocal(i) 1916 return r, r.Auxs(li) 1917 } 1918} 1919 1920// Returns a specific aux symbol of type t for symbol i. 1921func (l *Loader) aux1(i Sym, t uint8) Sym { 1922 r, auxs := l.auxs(i) 1923 for j := range auxs { 1924 a := &auxs[j] 1925 if a.Type() == t { 1926 return l.resolve(r, a.Sym()) 1927 } 1928 } 1929 return 0 1930} 1931 1932func (l *Loader) Pcsp(i Sym) Sym { return l.aux1(i, goobj.AuxPcsp) } 1933 1934// Returns all aux symbols of per-PC data for symbol i. 1935// tmp is a scratch space for the pcdata slice. 1936func (l *Loader) PcdataAuxs(i Sym, tmp []Sym) (pcsp, pcfile, pcline, pcinline Sym, pcdata []Sym) { 1937 pcdata = tmp[:0] 1938 r, auxs := l.auxs(i) 1939 for j := range auxs { 1940 a := &auxs[j] 1941 switch a.Type() { 1942 case goobj.AuxPcsp: 1943 pcsp = l.resolve(r, a.Sym()) 1944 case goobj.AuxPcline: 1945 pcline = l.resolve(r, a.Sym()) 1946 case goobj.AuxPcfile: 1947 pcfile = l.resolve(r, a.Sym()) 1948 case goobj.AuxPcinline: 1949 pcinline = l.resolve(r, a.Sym()) 1950 case goobj.AuxPcdata: 1951 pcdata = append(pcdata, l.resolve(r, a.Sym())) 1952 } 1953 } 1954 return 1955} 1956 1957// Returns the number of pcdata for symbol i. 1958func (l *Loader) NumPcdata(i Sym) int { 1959 n := 0 1960 _, auxs := l.auxs(i) 1961 for j := range auxs { 1962 a := &auxs[j] 1963 if a.Type() == goobj.AuxPcdata { 1964 n++ 1965 } 1966 } 1967 return n 1968} 1969 1970// Returns all funcdata symbols of symbol i. 1971// tmp is a scratch space. 1972func (l *Loader) Funcdata(i Sym, tmp []Sym) []Sym { 1973 fd := tmp[:0] 1974 r, auxs := l.auxs(i) 1975 for j := range auxs { 1976 a := &auxs[j] 1977 if a.Type() == goobj.AuxFuncdata { 1978 fd = append(fd, l.resolve(r, a.Sym())) 1979 } 1980 } 1981 return fd 1982} 1983 1984// Returns the number of funcdata for symbol i. 1985func (l *Loader) NumFuncdata(i Sym) int { 1986 n := 0 1987 _, auxs := l.auxs(i) 1988 for j := range auxs { 1989 a := &auxs[j] 1990 if a.Type() == goobj.AuxFuncdata { 1991 n++ 1992 } 1993 } 1994 return n 1995} 1996 1997// FuncInfo provides hooks to access goobj.FuncInfo in the objects. 1998type FuncInfo struct { 1999 l *Loader 2000 r *oReader 2001 data []byte 2002 lengths goobj.FuncInfoLengths 2003} 2004 2005func (fi *FuncInfo) Valid() bool { return fi.r != nil } 2006 2007func (fi *FuncInfo) Args() int { 2008 return int((*goobj.FuncInfo)(nil).ReadArgs(fi.data)) 2009} 2010 2011func (fi *FuncInfo) Locals() int { 2012 return int((*goobj.FuncInfo)(nil).ReadLocals(fi.data)) 2013} 2014 2015func (fi *FuncInfo) FuncID() abi.FuncID { 2016 return (*goobj.FuncInfo)(nil).ReadFuncID(fi.data) 2017} 2018 2019func (fi *FuncInfo) FuncFlag() abi.FuncFlag { 2020 return (*goobj.FuncInfo)(nil).ReadFuncFlag(fi.data) 2021} 2022 2023func (fi *FuncInfo) StartLine() int32 { 2024 return (*goobj.FuncInfo)(nil).ReadStartLine(fi.data) 2025} 2026 2027// Preload has to be called prior to invoking the various methods 2028// below related to pcdata, funcdataoff, files, and inltree nodes. 2029func (fi *FuncInfo) Preload() { 2030 fi.lengths = (*goobj.FuncInfo)(nil).ReadFuncInfoLengths(fi.data) 2031} 2032 2033func (fi *FuncInfo) NumFile() uint32 { 2034 if !fi.lengths.Initialized { 2035 panic("need to call Preload first") 2036 } 2037 return fi.lengths.NumFile 2038} 2039 2040func (fi *FuncInfo) File(k int) goobj.CUFileIndex { 2041 if !fi.lengths.Initialized { 2042 panic("need to call Preload first") 2043 } 2044 return (*goobj.FuncInfo)(nil).ReadFile(fi.data, fi.lengths.FileOff, uint32(k)) 2045} 2046 2047// TopFrame returns true if the function associated with this FuncInfo 2048// is an entry point, meaning that unwinders should stop when they hit 2049// this function. 2050func (fi *FuncInfo) TopFrame() bool { 2051 return (fi.FuncFlag() & abi.FuncFlagTopFrame) != 0 2052} 2053 2054type InlTreeNode struct { 2055 Parent int32 2056 File goobj.CUFileIndex 2057 Line int32 2058 Func Sym 2059 ParentPC int32 2060} 2061 2062func (fi *FuncInfo) NumInlTree() uint32 { 2063 if !fi.lengths.Initialized { 2064 panic("need to call Preload first") 2065 } 2066 return fi.lengths.NumInlTree 2067} 2068 2069func (fi *FuncInfo) InlTree(k int) InlTreeNode { 2070 if !fi.lengths.Initialized { 2071 panic("need to call Preload first") 2072 } 2073 node := (*goobj.FuncInfo)(nil).ReadInlTree(fi.data, fi.lengths.InlTreeOff, uint32(k)) 2074 return InlTreeNode{ 2075 Parent: node.Parent, 2076 File: node.File, 2077 Line: node.Line, 2078 Func: fi.l.resolve(fi.r, node.Func), 2079 ParentPC: node.ParentPC, 2080 } 2081} 2082 2083func (l *Loader) FuncInfo(i Sym) FuncInfo { 2084 r, auxs := l.auxs(i) 2085 for j := range auxs { 2086 a := &auxs[j] 2087 if a.Type() == goobj.AuxFuncInfo { 2088 b := r.Data(a.Sym().SymIdx) 2089 return FuncInfo{l, r, b, goobj.FuncInfoLengths{}} 2090 } 2091 } 2092 return FuncInfo{} 2093} 2094 2095// Preload a package: adds autolib. 2096// Does not add defined package or non-packaged symbols to the symbol table. 2097// These are done in LoadSyms. 2098// Does not read symbol data. 2099// Returns the fingerprint of the object. 2100func (l *Loader) Preload(localSymVersion int, f *bio.Reader, lib *sym.Library, unit *sym.CompilationUnit, length int64) goobj.FingerprintType { 2101 roObject, readonly, err := f.Slice(uint64(length)) // TODO: no need to map blocks that are for tools only (e.g. RefName) 2102 if err != nil { 2103 log.Fatal("cannot read object file:", err) 2104 } 2105 r := goobj.NewReaderFromBytes(roObject, readonly) 2106 if r == nil { 2107 if len(roObject) >= 8 && bytes.Equal(roObject[:8], []byte("\x00go114ld")) { 2108 log.Fatalf("found object file %s in old format", f.File().Name()) 2109 } 2110 panic("cannot read object file") 2111 } 2112 pkgprefix := objabi.PathToPrefix(lib.Pkg) + "." 2113 ndef := r.NSym() 2114 nhashed64def := r.NHashed64def() 2115 nhasheddef := r.NHasheddef() 2116 or := &oReader{ 2117 Reader: r, 2118 unit: unit, 2119 version: localSymVersion, 2120 pkgprefix: pkgprefix, 2121 syms: make([]Sym, ndef+nhashed64def+nhasheddef+r.NNonpkgdef()+r.NNonpkgref()), 2122 ndef: ndef, 2123 nhasheddef: nhasheddef, 2124 nhashed64def: nhashed64def, 2125 objidx: uint32(len(l.objs)), 2126 } 2127 2128 if r.Unlinkable() { 2129 log.Fatalf("link: unlinkable object (from package %s) - compiler requires -p flag", lib.Pkg) 2130 } 2131 2132 // Autolib 2133 lib.Autolib = append(lib.Autolib, r.Autolib()...) 2134 2135 // DWARF file table 2136 nfile := r.NFile() 2137 unit.FileTable = make([]string, nfile) 2138 for i := range unit.FileTable { 2139 unit.FileTable[i] = r.File(i) 2140 } 2141 2142 l.addObj(lib.Pkg, or) 2143 2144 // The caller expects us consuming all the data 2145 f.MustSeek(length, io.SeekCurrent) 2146 2147 return r.Fingerprint() 2148} 2149 2150// Holds the loader along with temporary states for loading symbols. 2151type loadState struct { 2152 l *Loader 2153 hashed64Syms map[uint64]symAndSize // short hashed (content-addressable) symbols, keyed by content hash 2154 hashedSyms map[goobj.HashType]symAndSize // hashed (content-addressable) symbols, keyed by content hash 2155 2156 linknameVarRefs []linknameVarRef // linknamed var refererces 2157} 2158 2159type linknameVarRef struct { 2160 pkg string // package of reference (not definition) 2161 name string 2162 sym Sym 2163} 2164 2165// Preload symbols of given kind from an object. 2166func (st *loadState) preloadSyms(r *oReader, kind int) { 2167 l := st.l 2168 var start, end uint32 2169 switch kind { 2170 case pkgDef: 2171 start = 0 2172 end = uint32(r.ndef) 2173 case hashed64Def: 2174 start = uint32(r.ndef) 2175 end = uint32(r.ndef + r.nhashed64def) 2176 case hashedDef: 2177 start = uint32(r.ndef + r.nhashed64def) 2178 end = uint32(r.ndef + r.nhashed64def + r.nhasheddef) 2179 case nonPkgDef: 2180 start = uint32(r.ndef + r.nhashed64def + r.nhasheddef) 2181 end = uint32(r.ndef + r.nhashed64def + r.nhasheddef + r.NNonpkgdef()) 2182 default: 2183 panic("preloadSyms: bad kind") 2184 } 2185 l.growAttrBitmaps(len(l.objSyms) + int(end-start)) 2186 loadingRuntimePkg := r.unit.Lib.Pkg == "runtime" 2187 for i := start; i < end; i++ { 2188 osym := r.Sym(i) 2189 var name string 2190 var v int 2191 if kind != hashed64Def && kind != hashedDef { // we don't need the name, etc. for hashed symbols 2192 name = osym.Name(r.Reader) 2193 v = abiToVer(osym.ABI(), r.version) 2194 } 2195 gi := st.addSym(name, v, r, i, kind, osym) 2196 r.syms[i] = gi 2197 if kind == nonPkgDef && osym.IsLinkname() && r.DataSize(i) == 0 && strings.Contains(name, ".") { 2198 // This is a linknamed "var" "reference" (var x T with no data and //go:linkname x). 2199 // We want to check if a linkname reference is allowed. Here we haven't loaded all 2200 // symbol definitions, so we don't yet know all the push linknames. So we add to a 2201 // list and check later after all symbol defs are loaded. Linknamed vars are rare, 2202 // so this list won't be long. 2203 // Only check references (pull), not definitions (push, with non-zero size), 2204 // so push is always allowed. 2205 // This use of linkname is usually for referencing C symbols, so allow symbols 2206 // with no "." in its name (not a regular Go symbol). 2207 // Linkname is always a non-package reference. 2208 st.linknameVarRefs = append(st.linknameVarRefs, linknameVarRef{r.unit.Lib.Pkg, name, gi}) 2209 } 2210 if osym.Local() { 2211 l.SetAttrLocal(gi, true) 2212 } 2213 if osym.UsedInIface() { 2214 l.SetAttrUsedInIface(gi, true) 2215 } 2216 if strings.HasPrefix(name, "runtime.") || 2217 (loadingRuntimePkg && strings.HasPrefix(name, "type:")) { 2218 if bi := goobj.BuiltinIdx(name, int(osym.ABI())); bi != -1 { 2219 // This is a definition of a builtin symbol. Record where it is. 2220 l.builtinSyms[bi] = gi 2221 } 2222 } 2223 if a := int32(osym.Align()); a != 0 && a > l.SymAlign(gi) { 2224 l.SetSymAlign(gi, a) 2225 } 2226 } 2227} 2228 2229// Add syms, hashed (content-addressable) symbols, non-package symbols, and 2230// references to external symbols (which are always named). 2231func (l *Loader) LoadSyms(arch *sys.Arch) { 2232 // Allocate space for symbols, making a guess as to how much space we need. 2233 // This function was determined empirically by looking at the cmd/compile on 2234 // Darwin, and picking factors for hashed and hashed64 syms. 2235 var symSize, hashedSize, hashed64Size int 2236 for _, r := range l.objs[goObjStart:] { 2237 symSize += r.ndef + r.nhasheddef/2 + r.nhashed64def/2 + r.NNonpkgdef() 2238 hashedSize += r.nhasheddef / 2 2239 hashed64Size += r.nhashed64def / 2 2240 } 2241 // Index 0 is invalid for symbols. 2242 l.objSyms = make([]objSym, 1, symSize) 2243 2244 st := loadState{ 2245 l: l, 2246 hashed64Syms: make(map[uint64]symAndSize, hashed64Size), 2247 hashedSyms: make(map[goobj.HashType]symAndSize, hashedSize), 2248 } 2249 2250 for _, r := range l.objs[goObjStart:] { 2251 st.preloadSyms(r, pkgDef) 2252 } 2253 l.npkgsyms = l.NSym() 2254 for _, r := range l.objs[goObjStart:] { 2255 st.preloadSyms(r, hashed64Def) 2256 st.preloadSyms(r, hashedDef) 2257 st.preloadSyms(r, nonPkgDef) 2258 } 2259 for _, vr := range st.linknameVarRefs { 2260 l.checkLinkname(vr.pkg, vr.name, vr.sym) 2261 } 2262 l.nhashedsyms = len(st.hashed64Syms) + len(st.hashedSyms) 2263 for _, r := range l.objs[goObjStart:] { 2264 loadObjRefs(l, r, arch) 2265 } 2266 l.values = make([]int64, l.NSym(), l.NSym()+1000) // +1000 make some room for external symbols 2267 l.outer = make([]Sym, l.NSym(), l.NSym()+1000) 2268} 2269 2270func loadObjRefs(l *Loader, r *oReader, arch *sys.Arch) { 2271 // load non-package refs 2272 ndef := uint32(r.NAlldef()) 2273 for i, n := uint32(0), uint32(r.NNonpkgref()); i < n; i++ { 2274 osym := r.Sym(ndef + i) 2275 name := osym.Name(r.Reader) 2276 v := abiToVer(osym.ABI(), r.version) 2277 gi := l.LookupOrCreateSym(name, v) 2278 r.syms[ndef+i] = gi 2279 if osym.IsLinkname() { 2280 // Check if a linkname reference is allowed. 2281 // Only check references (pull), not definitions (push), 2282 // so push is always allowed. 2283 // Linkname is always a non-package reference. 2284 l.checkLinkname(r.unit.Lib.Pkg, name, gi) 2285 } 2286 if osym.Local() { 2287 l.SetAttrLocal(gi, true) 2288 } 2289 if osym.UsedInIface() { 2290 l.SetAttrUsedInIface(gi, true) 2291 } 2292 } 2293 2294 // referenced packages 2295 npkg := r.NPkg() 2296 r.pkg = make([]uint32, npkg) 2297 for i := 1; i < npkg; i++ { // PkgIdx 0 is a dummy invalid package 2298 pkg := r.Pkg(i) 2299 objidx, ok := l.objByPkg[pkg] 2300 if !ok { 2301 log.Fatalf("%v: reference to nonexistent package %s", r.unit.Lib, pkg) 2302 } 2303 r.pkg[i] = objidx 2304 } 2305 2306 // load flags of package refs 2307 for i, n := 0, r.NRefFlags(); i < n; i++ { 2308 rf := r.RefFlags(i) 2309 gi := l.resolve(r, rf.Sym()) 2310 if rf.Flag2()&goobj.SymFlagUsedInIface != 0 { 2311 l.SetAttrUsedInIface(gi, true) 2312 } 2313 } 2314} 2315 2316func abiToVer(abi uint16, localSymVersion int) int { 2317 var v int 2318 if abi == goobj.SymABIstatic { 2319 // Static 2320 v = localSymVersion 2321 } else if abiver := sym.ABIToVersion(obj.ABI(abi)); abiver != -1 { 2322 // Note that data symbols are "ABI0", which maps to version 0. 2323 v = abiver 2324 } else { 2325 log.Fatalf("invalid symbol ABI: %d", abi) 2326 } 2327 return v 2328} 2329 2330// A list of blocked linknames. Some linknames are allowed only 2331// in specific packages. This maps symbol names to allowed packages. 2332// If a name is not in this map, it is allowed iff the definition 2333// has a linkname (push). 2334// If a name is in this map, it is allowed only in listed packages, 2335// even if it has a linknamed definition. 2336var blockedLinknames = map[string][]string{ 2337 // coroutines 2338 "runtime.coroswitch": {"iter"}, 2339 "runtime.newcoro": {"iter"}, 2340 // weak references 2341 "internal/weak.runtime_registerWeakPointer": {"internal/weak"}, 2342 "internal/weak.runtime_makeStrongFromWeak": {"internal/weak"}, 2343} 2344 2345// check if a linkname reference to symbol s from pkg is allowed 2346func (l *Loader) checkLinkname(pkg, name string, s Sym) { 2347 if l.flags&FlagCheckLinkname == 0 { 2348 return 2349 } 2350 2351 error := func() { 2352 log.Fatalf("%s: invalid reference to %s", pkg, name) 2353 } 2354 pkgs, ok := blockedLinknames[name] 2355 if ok { 2356 for _, p := range pkgs { 2357 if pkg == p { 2358 return // pkg is allowed 2359 } 2360 } 2361 error() 2362 } 2363 r, li := l.toLocal(s) 2364 if r == l.extReader { // referencing external symbol is okay 2365 return 2366 } 2367 if !r.Std() { // For now, only check for symbols defined in std 2368 return 2369 } 2370 if r.unit.Lib.Pkg == pkg { // assembly reference from same package 2371 return 2372 } 2373 osym := r.Sym(li) 2374 if osym.IsLinkname() || osym.ABIWrapper() { 2375 // Allow if the def has a linkname (push). 2376 // ABI wrapper usually wraps an assembly symbol, a linknamed symbol, 2377 // or an external symbol, or provide access of a Go symbol to assembly. 2378 // For now, allow ABI wrappers. 2379 // TODO: check the wrapped symbol? 2380 return 2381 } 2382 error() 2383} 2384 2385// TopLevelSym tests a symbol (by name and kind) to determine whether 2386// the symbol first class sym (participating in the link) or is an 2387// anonymous aux or sub-symbol containing some sub-part or payload of 2388// another symbol. 2389func (l *Loader) TopLevelSym(s Sym) bool { 2390 return topLevelSym(l.SymName(s), l.SymType(s)) 2391} 2392 2393// topLevelSym tests a symbol name and kind to determine whether 2394// the symbol first class sym (participating in the link) or is an 2395// anonymous aux or sub-symbol containing some sub-part or payload of 2396// another symbol. 2397func topLevelSym(sname string, skind sym.SymKind) bool { 2398 if sname != "" { 2399 return true 2400 } 2401 switch skind { 2402 case sym.SDWARFFCN, sym.SDWARFABSFCN, sym.SDWARFTYPE, sym.SDWARFCONST, sym.SDWARFCUINFO, sym.SDWARFRANGE, sym.SDWARFLOC, sym.SDWARFLINES, sym.SGOFUNC: 2403 return true 2404 default: 2405 return false 2406 } 2407} 2408 2409// cloneToExternal takes the existing object file symbol (symIdx) 2410// and creates a new external symbol payload that is a clone with 2411// respect to name, version, type, relocations, etc. The idea here 2412// is that if the linker decides it wants to update the contents of 2413// a symbol originally discovered as part of an object file, it's 2414// easier to do this if we make the updates to an external symbol 2415// payload. 2416func (l *Loader) cloneToExternal(symIdx Sym) { 2417 if l.IsExternal(symIdx) { 2418 panic("sym is already external, no need for clone") 2419 } 2420 2421 // Read the particulars from object. 2422 r, li := l.toLocal(symIdx) 2423 osym := r.Sym(li) 2424 sname := osym.Name(r.Reader) 2425 sver := abiToVer(osym.ABI(), r.version) 2426 skind := sym.AbiSymKindToSymKind[objabi.SymKind(osym.Type())] 2427 2428 // Create new symbol, update version and kind. 2429 pi := l.newPayload(sname, sver) 2430 pp := l.payloads[pi] 2431 pp.kind = skind 2432 pp.ver = sver 2433 pp.size = int64(osym.Siz()) 2434 pp.objidx = r.objidx 2435 2436 // If this is a def, then copy the guts. We expect this case 2437 // to be very rare (one case it may come up is with -X). 2438 if li < uint32(r.NAlldef()) { 2439 2440 // Copy relocations 2441 relocs := l.Relocs(symIdx) 2442 pp.relocs = make([]goobj.Reloc, relocs.Count()) 2443 for i := range pp.relocs { 2444 // Copy the relocs slice. 2445 // Convert local reference to global reference. 2446 rel := relocs.At(i) 2447 pp.relocs[i].Set(rel.Off(), rel.Siz(), uint16(rel.Type()), rel.Add(), goobj.SymRef{PkgIdx: 0, SymIdx: uint32(rel.Sym())}) 2448 } 2449 2450 // Copy data 2451 pp.data = r.Data(li) 2452 } 2453 2454 // If we're overriding a data symbol, collect the associated 2455 // Gotype, so as to propagate it to the new symbol. 2456 auxs := r.Auxs(li) 2457 pp.auxs = auxs 2458 2459 // Install new payload to global index space. 2460 // (This needs to happen at the end, as the accessors above 2461 // need to access the old symbol content.) 2462 l.objSyms[symIdx] = objSym{l.extReader.objidx, uint32(pi)} 2463 l.extReader.syms = append(l.extReader.syms, symIdx) 2464 2465 // Some attributes were encoded in the object file. Copy them over. 2466 l.SetAttrDuplicateOK(symIdx, r.Sym(li).Dupok()) 2467 l.SetAttrShared(symIdx, r.Shared()) 2468} 2469 2470// Copy the payload of symbol src to dst. Both src and dst must be external 2471// symbols. 2472// The intended use case is that when building/linking against a shared library, 2473// where we do symbol name mangling, the Go object file may have reference to 2474// the original symbol name whereas the shared library provides a symbol with 2475// the mangled name. When we do mangling, we copy payload of mangled to original. 2476func (l *Loader) CopySym(src, dst Sym) { 2477 if !l.IsExternal(dst) { 2478 panic("dst is not external") //l.newExtSym(l.SymName(dst), l.SymVersion(dst)) 2479 } 2480 if !l.IsExternal(src) { 2481 panic("src is not external") //l.cloneToExternal(src) 2482 } 2483 l.payloads[l.extIndex(dst)] = l.payloads[l.extIndex(src)] 2484 l.SetSymPkg(dst, l.SymPkg(src)) 2485 // TODO: other attributes? 2486} 2487 2488// CreateExtSym creates a new external symbol with the specified name 2489// without adding it to any lookup tables, returning a Sym index for it. 2490func (l *Loader) CreateExtSym(name string, ver int) Sym { 2491 return l.newExtSym(name, ver) 2492} 2493 2494// CreateStaticSym creates a new static symbol with the specified name 2495// without adding it to any lookup tables, returning a Sym index for it. 2496func (l *Loader) CreateStaticSym(name string) Sym { 2497 // Assign a new unique negative version -- this is to mark the 2498 // symbol so that it is not included in the name lookup table. 2499 l.anonVersion-- 2500 return l.newExtSym(name, l.anonVersion) 2501} 2502 2503func (l *Loader) FreeSym(i Sym) { 2504 if l.IsExternal(i) { 2505 pp := l.getPayload(i) 2506 *pp = extSymPayload{} 2507 } 2508} 2509 2510// relocId is essentially a <S,R> tuple identifying the Rth 2511// relocation of symbol S. 2512type relocId struct { 2513 sym Sym 2514 ridx int 2515} 2516 2517// SetRelocVariant sets the 'variant' property of a relocation on 2518// some specific symbol. 2519func (l *Loader) SetRelocVariant(s Sym, ri int, v sym.RelocVariant) { 2520 // sanity check 2521 if relocs := l.Relocs(s); ri >= relocs.Count() { 2522 panic("invalid relocation ID") 2523 } 2524 if l.relocVariant == nil { 2525 l.relocVariant = make(map[relocId]sym.RelocVariant) 2526 } 2527 if v != 0 { 2528 l.relocVariant[relocId{s, ri}] = v 2529 } else { 2530 delete(l.relocVariant, relocId{s, ri}) 2531 } 2532} 2533 2534// RelocVariant returns the 'variant' property of a relocation on 2535// some specific symbol. 2536func (l *Loader) RelocVariant(s Sym, ri int) sym.RelocVariant { 2537 return l.relocVariant[relocId{s, ri}] 2538} 2539 2540// UndefinedRelocTargets iterates through the global symbol index 2541// space, looking for symbols with relocations targeting undefined 2542// references. The linker's loadlib method uses this to determine if 2543// there are unresolved references to functions in system libraries 2544// (for example, libgcc.a), presumably due to CGO code. Return value 2545// is a pair of lists of loader.Sym's. First list corresponds to the 2546// corresponding to the undefined symbols themselves, the second list 2547// is the symbol that is making a reference to the undef. The "limit" 2548// param controls the maximum number of results returned; if "limit" 2549// is -1, then all undefs are returned. 2550func (l *Loader) UndefinedRelocTargets(limit int) ([]Sym, []Sym) { 2551 result, fromr := []Sym{}, []Sym{} 2552outerloop: 2553 for si := Sym(1); si < Sym(len(l.objSyms)); si++ { 2554 relocs := l.Relocs(si) 2555 for ri := 0; ri < relocs.Count(); ri++ { 2556 r := relocs.At(ri) 2557 rs := r.Sym() 2558 if rs != 0 && l.SymType(rs) == sym.SXREF && l.SymName(rs) != ".got" { 2559 result = append(result, rs) 2560 fromr = append(fromr, si) 2561 if limit != -1 && len(result) >= limit { 2562 break outerloop 2563 } 2564 } 2565 } 2566 } 2567 return result, fromr 2568} 2569 2570// AssignTextSymbolOrder populates the Textp slices within each 2571// library and compilation unit, insuring that packages are laid down 2572// in dependency order (internal first, then everything else). Return value 2573// is a slice of all text syms. 2574func (l *Loader) AssignTextSymbolOrder(libs []*sym.Library, intlibs []bool, extsyms []Sym) []Sym { 2575 2576 // Library Textp lists should be empty at this point. 2577 for _, lib := range libs { 2578 if len(lib.Textp) != 0 { 2579 panic("expected empty Textp slice for library") 2580 } 2581 if len(lib.DupTextSyms) != 0 { 2582 panic("expected empty DupTextSyms slice for library") 2583 } 2584 } 2585 2586 // Used to record which dupok symbol we've assigned to a unit. 2587 // Can't use the onlist attribute here because it will need to 2588 // clear for the later assignment of the sym.Symbol to a unit. 2589 // NB: we can convert to using onList once we no longer have to 2590 // call the regular addToTextp. 2591 assignedToUnit := MakeBitmap(l.NSym() + 1) 2592 2593 // Start off textp with reachable external syms. 2594 textp := []Sym{} 2595 for _, sym := range extsyms { 2596 if !l.attrReachable.Has(sym) { 2597 continue 2598 } 2599 textp = append(textp, sym) 2600 } 2601 2602 // Walk through all text symbols from Go object files and append 2603 // them to their corresponding library's textp list. 2604 for _, r := range l.objs[goObjStart:] { 2605 lib := r.unit.Lib 2606 for i, n := uint32(0), uint32(r.NAlldef()); i < n; i++ { 2607 gi := l.toGlobal(r, i) 2608 if !l.attrReachable.Has(gi) { 2609 continue 2610 } 2611 osym := r.Sym(i) 2612 st := sym.AbiSymKindToSymKind[objabi.SymKind(osym.Type())] 2613 if st != sym.STEXT { 2614 continue 2615 } 2616 dupok := osym.Dupok() 2617 if r2, i2 := l.toLocal(gi); r2 != r || i2 != i { 2618 // A dupok text symbol is resolved to another package. 2619 // We still need to record its presence in the current 2620 // package, as the trampoline pass expects packages 2621 // are laid out in dependency order. 2622 lib.DupTextSyms = append(lib.DupTextSyms, sym.LoaderSym(gi)) 2623 continue // symbol in different object 2624 } 2625 if dupok { 2626 lib.DupTextSyms = append(lib.DupTextSyms, sym.LoaderSym(gi)) 2627 continue 2628 } 2629 2630 lib.Textp = append(lib.Textp, sym.LoaderSym(gi)) 2631 } 2632 } 2633 2634 // Now assemble global textp, and assign text symbols to units. 2635 for _, doInternal := range [2]bool{true, false} { 2636 for idx, lib := range libs { 2637 if intlibs[idx] != doInternal { 2638 continue 2639 } 2640 lists := [2][]sym.LoaderSym{lib.Textp, lib.DupTextSyms} 2641 for i, list := range lists { 2642 for _, s := range list { 2643 sym := Sym(s) 2644 if !assignedToUnit.Has(sym) { 2645 textp = append(textp, sym) 2646 unit := l.SymUnit(sym) 2647 if unit != nil { 2648 unit.Textp = append(unit.Textp, s) 2649 assignedToUnit.Set(sym) 2650 } 2651 // Dupok symbols may be defined in multiple packages; the 2652 // associated package for a dupok sym is chosen sort of 2653 // arbitrarily (the first containing package that the linker 2654 // loads). Canonicalizes its Pkg to the package with which 2655 // it will be laid down in text. 2656 if i == 1 /* DupTextSyms2 */ && l.SymPkg(sym) != lib.Pkg { 2657 l.SetSymPkg(sym, lib.Pkg) 2658 } 2659 } 2660 } 2661 } 2662 lib.Textp = nil 2663 lib.DupTextSyms = nil 2664 } 2665 } 2666 2667 return textp 2668} 2669 2670// ErrorReporter is a helper class for reporting errors. 2671type ErrorReporter struct { 2672 ldr *Loader 2673 AfterErrorAction func() 2674} 2675 2676// Errorf method logs an error message. 2677// 2678// After each error, the error actions function will be invoked; this 2679// will either terminate the link immediately (if -h option given) 2680// or it will keep a count and exit if more than 20 errors have been printed. 2681// 2682// Logging an error means that on exit cmd/link will delete any 2683// output file and return a non-zero error code. 2684func (reporter *ErrorReporter) Errorf(s Sym, format string, args ...interface{}) { 2685 if s != 0 && reporter.ldr.SymName(s) != "" { 2686 // Note: Replace is needed here because symbol names might have % in them, 2687 // due to the use of LinkString for names of instantiating types. 2688 format = strings.Replace(reporter.ldr.SymName(s), "%", "%%", -1) + ": " + format 2689 } else { 2690 format = fmt.Sprintf("sym %d: %s", s, format) 2691 } 2692 format += "\n" 2693 fmt.Fprintf(os.Stderr, format, args...) 2694 reporter.AfterErrorAction() 2695} 2696 2697// GetErrorReporter returns the loader's associated error reporter. 2698func (l *Loader) GetErrorReporter() *ErrorReporter { 2699 return l.errorReporter 2700} 2701 2702// Errorf method logs an error message. See ErrorReporter.Errorf for details. 2703func (l *Loader) Errorf(s Sym, format string, args ...interface{}) { 2704 l.errorReporter.Errorf(s, format, args...) 2705} 2706 2707// Symbol statistics. 2708func (l *Loader) Stat() string { 2709 s := fmt.Sprintf("%d symbols, %d reachable\n", l.NSym(), l.NReachableSym()) 2710 s += fmt.Sprintf("\t%d package symbols, %d hashed symbols, %d non-package symbols, %d external symbols\n", 2711 l.npkgsyms, l.nhashedsyms, int(l.extStart)-l.npkgsyms-l.nhashedsyms, l.NSym()-int(l.extStart)) 2712 return s 2713} 2714 2715// For debugging. 2716func (l *Loader) Dump() { 2717 fmt.Println("objs") 2718 for _, r := range l.objs[goObjStart:] { 2719 if r != nil { 2720 fmt.Println(r.unit.Lib) 2721 } 2722 } 2723 fmt.Println("extStart:", l.extStart) 2724 fmt.Println("Nsyms:", len(l.objSyms)) 2725 fmt.Println("syms") 2726 for i := Sym(1); i < Sym(len(l.objSyms)); i++ { 2727 pi := "" 2728 if l.IsExternal(i) { 2729 pi = fmt.Sprintf("<ext %d>", l.extIndex(i)) 2730 } 2731 sect := "" 2732 if l.SymSect(i) != nil { 2733 sect = l.SymSect(i).Name 2734 } 2735 fmt.Printf("%v %v %v %v %x %v\n", i, l.SymName(i), l.SymType(i), pi, l.SymValue(i), sect) 2736 } 2737 fmt.Println("symsByName") 2738 for name, i := range l.symsByName[0] { 2739 fmt.Println(i, name, 0) 2740 } 2741 for name, i := range l.symsByName[1] { 2742 fmt.Println(i, name, 1) 2743 } 2744 fmt.Println("payloads:") 2745 for i := range l.payloads { 2746 pp := l.payloads[i] 2747 fmt.Println(i, pp.name, pp.ver, pp.kind) 2748 } 2749} 2750