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