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