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