github.com/gagliardetto/golang-go@v0.0.0-20201020153340-53909ea70814/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/gagliardetto/golang-go/cmd/internal/bio" 10 "github.com/gagliardetto/golang-go/cmd/internal/dwarf" 11 "github.com/gagliardetto/golang-go/cmd/internal/goobj2" 12 "github.com/gagliardetto/golang-go/cmd/internal/obj" 13 "github.com/gagliardetto/golang-go/cmd/internal/objabi" 14 "github.com/gagliardetto/golang-go/cmd/internal/sys" 15 "github.com/gagliardetto/golang-go/cmd/link/internal/sym" 16 "fmt" 17 "log" 18 "os" 19 "sort" 20 "strconv" 21 "strings" 22 ) 23 24 var _ = 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. 28 type 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. 32 type Relocs struct { 33 Count int // number of relocs 34 35 li int // local index of symbol whose relocs we're examining 36 r *oReader // object reader for containing package 37 l *Loader // loader 38 39 ext *sym.Symbol // external symbol if not nil 40 } 41 42 // Reloc contains the payload for a specific relocation. 43 // TODO: replace this with sym.Reloc, once we change the 44 // relocation target from "*sym.Symbol" to "loader.Sym" in sym.Reloc. 45 type Reloc struct { 46 Off int32 // offset to rewrite 47 Size uint8 // number of bytes to rewrite: 0, 1, 2, or 4 48 Type objabi.RelocType // the relocation type 49 Add int64 // addend 50 Sym Sym // global index of symbol the reloc addresses 51 } 52 53 // oReader is a wrapper type of obj.Reader, along with some 54 // extra information. 55 // TODO: rename to objReader once the old one is gone? 56 type oReader struct { 57 *goobj2.Reader 58 unit *sym.CompilationUnit 59 version int // version of static symbol 60 flags uint32 // read from object file 61 pkgprefix string 62 rcache []Sym // cache mapping local PkgNone symbol to resolved Sym 63 } 64 65 type objIdx struct { 66 r *oReader 67 i Sym // start index 68 e Sym // end index 69 } 70 71 type nameVer struct { 72 name string 73 v int 74 } 75 76 type bitmap []uint32 77 78 // set the i-th bit. 79 func (bm bitmap) Set(i Sym) { 80 n, r := uint(i)/32, uint(i)%32 81 bm[n] |= 1 << r 82 } 83 84 // whether the i-th bit is set. 85 func (bm bitmap) Has(i Sym) bool { 86 n, r := uint(i)/32, uint(i)%32 87 return bm[n]&(1<<r) != 0 88 } 89 90 func makeBitmap(n int) bitmap { 91 return make(bitmap, (n+31)/32) 92 } 93 94 // A Loader loads new object files and resolves indexed symbol references. 95 type Loader struct { 96 start map[*oReader]Sym // map from object file to its start index 97 objs []objIdx // sorted by start index (i.e. objIdx.i) 98 max Sym // current max index 99 extStart Sym // from this index on, the symbols are externally defined 100 extSyms []nameVer // externally defined symbols 101 builtinSyms []Sym // global index of builtin symbols 102 ocache int // index (into 'objs') of most recent lookup 103 104 symsByName [2]map[string]Sym // map symbol name to index, two maps are for ABI0 and ABIInternal 105 extStaticSyms map[nameVer]Sym // externally defined static symbols, keyed by name 106 overwrite map[Sym]Sym // overwrite[i]=j if symbol j overwrites symbol i 107 108 itablink map[Sym]struct{} // itablink[j] defined if j is go.itablink.* 109 110 objByPkg map[string]*oReader // map package path to its Go object reader 111 112 Syms []*sym.Symbol // indexed symbols. XXX we still make sym.Symbol for now. 113 114 anonVersion int // most recently assigned ext static sym pseudo-version 115 116 Reachable bitmap // bitmap of reachable symbols, indexed by global index 117 118 // Used to implement field tracking; created during deadcode if 119 // field tracking is enabled. Reachparent[K] contains the index of 120 // the symbol that triggered the marking of symbol K as live. 121 Reachparent []Sym 122 123 relocBatch []sym.Reloc // for bulk allocation of relocations 124 125 flags uint32 126 127 strictDupMsgs int // number of strict-dup warning/errors, when FlagStrictDups is enabled 128 } 129 130 const ( 131 // Loader.flags 132 FlagStrictDups = 1 << iota 133 ) 134 135 func NewLoader(flags uint32) *Loader { 136 nbuiltin := goobj2.NBuiltin() 137 return &Loader{ 138 start: make(map[*oReader]Sym), 139 objs: []objIdx{{nil, 0, 0}}, 140 symsByName: [2]map[string]Sym{make(map[string]Sym), make(map[string]Sym)}, 141 objByPkg: make(map[string]*oReader), 142 overwrite: make(map[Sym]Sym), 143 itablink: make(map[Sym]struct{}), 144 extStaticSyms: make(map[nameVer]Sym), 145 builtinSyms: make([]Sym, nbuiltin), 146 flags: flags, 147 } 148 } 149 150 // Return the start index in the global index space for a given object file. 151 func (l *Loader) startIndex(r *oReader) Sym { 152 return l.start[r] 153 } 154 155 // Add object file r, return the start index. 156 func (l *Loader) addObj(pkg string, r *oReader) Sym { 157 if _, ok := l.start[r]; ok { 158 panic("already added") 159 } 160 pkg = objabi.PathToPrefix(pkg) // the object file contains escaped package path 161 if _, ok := l.objByPkg[pkg]; !ok { 162 l.objByPkg[pkg] = r 163 } 164 n := r.NSym() + r.NNonpkgdef() 165 i := l.max + 1 166 l.start[r] = i 167 l.objs = append(l.objs, objIdx{r, i, i + Sym(n) - 1}) 168 l.max += Sym(n) 169 return i 170 } 171 172 // Add a symbol with a given index, return if it is added. 173 func (l *Loader) AddSym(name string, ver int, i Sym, r *oReader, dupok bool, typ sym.SymKind) bool { 174 if l.extStart != 0 { 175 panic("AddSym called after AddExtSym is called") 176 } 177 if ver == r.version { 178 // Static symbol. Add its global index but don't 179 // add to name lookup table, as it cannot be 180 // referenced by name. 181 return true 182 } 183 if oldi, ok := l.symsByName[ver][name]; ok { 184 if dupok { 185 if l.flags&FlagStrictDups != 0 { 186 l.checkdup(name, i, r, oldi) 187 } 188 return false 189 } 190 oldr, li := l.toLocal(oldi) 191 oldsym := goobj2.Sym{} 192 oldsym.Read(oldr.Reader, oldr.SymOff(li)) 193 if oldsym.Dupok() { 194 return false 195 } 196 overwrite := r.DataSize(int(i-l.startIndex(r))) != 0 197 if overwrite { 198 // new symbol overwrites old symbol. 199 oldtyp := sym.AbiSymKindToSymKind[objabi.SymKind(oldsym.Type)] 200 if !oldtyp.IsData() && r.DataSize(li) == 0 { 201 log.Fatalf("duplicated definition of symbol " + name) 202 } 203 l.overwrite[oldi] = i 204 } else { 205 // old symbol overwrites new symbol. 206 if typ != sym.SDATA && typ != sym.SNOPTRDATA && typ != sym.SBSS && typ != sym.SNOPTRBSS { // only allow overwriting data symbol 207 log.Fatalf("duplicated definition of symbol " + name) 208 } 209 l.overwrite[i] = oldi 210 return false 211 } 212 } 213 l.symsByName[ver][name] = i 214 return true 215 } 216 217 // Add an external symbol (without index). Return the index of newly added 218 // symbol, or 0 if not added. 219 func (l *Loader) AddExtSym(name string, ver int) Sym { 220 static := ver >= sym.SymVerStatic 221 if static { 222 if _, ok := l.extStaticSyms[nameVer{name, ver}]; ok { 223 return 0 224 } 225 } else { 226 if _, ok := l.symsByName[ver][name]; ok { 227 return 0 228 } 229 } 230 i := l.max + 1 231 if static { 232 l.extStaticSyms[nameVer{name, ver}] = i 233 } else { 234 l.symsByName[ver][name] = i 235 } 236 l.max++ 237 if l.extStart == 0 { 238 l.extStart = i 239 } 240 l.extSyms = append(l.extSyms, nameVer{name, ver}) 241 l.growSyms(int(i)) 242 return i 243 } 244 245 func (l *Loader) IsExternal(i Sym) bool { 246 return l.extStart != 0 && i >= l.extStart 247 } 248 249 // Ensure Syms slice has enough space. 250 func (l *Loader) growSyms(i int) { 251 n := len(l.Syms) 252 if n > i { 253 return 254 } 255 l.Syms = append(l.Syms, make([]*sym.Symbol, i+1-n)...) 256 } 257 258 // Convert a local index to a global index. 259 func (l *Loader) toGlobal(r *oReader, i int) Sym { 260 g := l.startIndex(r) + Sym(i) 261 if ov, ok := l.overwrite[g]; ok { 262 return ov 263 } 264 return g 265 } 266 267 // Convert a global index to a local index. 268 func (l *Loader) toLocal(i Sym) (*oReader, int) { 269 if ov, ok := l.overwrite[i]; ok { 270 i = ov 271 } 272 if l.IsExternal(i) { 273 return nil, int(i - l.extStart) 274 } 275 oc := l.ocache 276 if oc != 0 && i >= l.objs[oc].i && i <= l.objs[oc].e { 277 return l.objs[oc].r, int(i - l.objs[oc].i) 278 } 279 // Search for the local object holding index i. 280 // Below k is the first one that has its start index > i, 281 // so k-1 is the one we want. 282 k := sort.Search(len(l.objs), func(k int) bool { 283 return l.objs[k].i > i 284 }) 285 l.ocache = k - 1 286 return l.objs[k-1].r, int(i - l.objs[k-1].i) 287 } 288 289 // rcacheGet checks for a valid entry for 's' in the readers cache, 290 // where 's' is a local PkgIdxNone ref or def, or zero if 291 // the cache is empty or doesn't contain a value for 's'. 292 func (or *oReader) rcacheGet(symIdx uint32) Sym { 293 if len(or.rcache) > 0 { 294 return or.rcache[symIdx] 295 } 296 return 0 297 } 298 299 // rcacheSet installs a new entry in the oReader's PkgNone 300 // resolver cache for the specified PkgIdxNone ref or def, 301 // allocating a new cache if needed. 302 func (or *oReader) rcacheSet(symIdx uint32, gsym Sym) { 303 if len(or.rcache) == 0 { 304 or.rcache = make([]Sym, or.NNonpkgdef()+or.NNonpkgref()) 305 } 306 or.rcache[symIdx] = gsym 307 } 308 309 // Resolve a local symbol reference. Return global index. 310 func (l *Loader) resolve(r *oReader, s goobj2.SymRef) Sym { 311 var rr *oReader 312 switch p := s.PkgIdx; p { 313 case goobj2.PkgIdxInvalid: 314 if s.SymIdx != 0 { 315 panic("bad sym ref") 316 } 317 return 0 318 case goobj2.PkgIdxNone: 319 // Check for cached version first 320 if cached := r.rcacheGet(s.SymIdx); cached != 0 { 321 return cached 322 } 323 // Resolve by name 324 i := int(s.SymIdx) + r.NSym() 325 osym := goobj2.Sym{} 326 osym.Read(r.Reader, r.SymOff(i)) 327 name := strings.Replace(osym.Name, "\"\".", r.pkgprefix, -1) 328 v := abiToVer(osym.ABI, r.version) 329 gsym := l.Lookup(name, v) 330 // Add to cache, then return. 331 r.rcacheSet(s.SymIdx, gsym) 332 return gsym 333 case goobj2.PkgIdxBuiltin: 334 return l.builtinSyms[s.SymIdx] 335 case goobj2.PkgIdxSelf: 336 rr = r 337 default: 338 pkg := r.Pkg(int(p)) 339 var ok bool 340 rr, ok = l.objByPkg[pkg] 341 if !ok { 342 log.Fatalf("reference of nonexisted package %s, from %v", pkg, r.unit.Lib) 343 } 344 } 345 return l.toGlobal(rr, int(s.SymIdx)) 346 } 347 348 // Look up a symbol by name, return global index, or 0 if not found. 349 // This is more like Syms.ROLookup than Lookup -- it doesn't create 350 // new symbol. 351 func (l *Loader) Lookup(name string, ver int) Sym { 352 if ver >= sym.SymVerStatic || ver < 0 { 353 return l.extStaticSyms[nameVer{name, ver}] 354 } 355 return l.symsByName[ver][name] 356 } 357 358 // Returns whether i is a dup of another symbol, and i is not 359 // "primary", i.e. Lookup i by name will not return i. 360 func (l *Loader) IsDup(i Sym) bool { 361 if _, ok := l.overwrite[i]; ok { 362 return true 363 } 364 if l.IsExternal(i) { 365 return false 366 } 367 r, li := l.toLocal(i) 368 osym := goobj2.Sym{} 369 osym.Read(r.Reader, r.SymOff(li)) 370 if !osym.Dupok() { 371 return false 372 } 373 if osym.Name == "" { 374 return false // Unnamed aux symbol cannot be dup. 375 } 376 if osym.ABI == goobj2.SymABIstatic { 377 return false // Static symbol cannot be dup. 378 } 379 name := strings.Replace(osym.Name, "\"\".", r.pkgprefix, -1) 380 ver := abiToVer(osym.ABI, r.version) 381 return l.symsByName[ver][name] != i 382 } 383 384 // Check that duplicate symbols have same contents. 385 func (l *Loader) checkdup(name string, i Sym, r *oReader, dup Sym) { 386 li := int(i - l.startIndex(r)) 387 p := r.Data(li) 388 if strings.HasPrefix(name, "go.info.") { 389 p, _ = patchDWARFName1(p, r) 390 } 391 rdup, ldup := l.toLocal(dup) 392 pdup := rdup.Data(ldup) 393 if strings.HasPrefix(name, "go.info.") { 394 pdup, _ = patchDWARFName1(pdup, rdup) 395 } 396 if bytes.Equal(p, pdup) { 397 return 398 } 399 reason := "same length but different contents" 400 if len(p) != len(pdup) { 401 reason = fmt.Sprintf("new length %d != old length %d", len(p), len(pdup)) 402 } 403 fmt.Fprintf(os.Stderr, "github.com/gagliardetto/golang-go/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) 404 405 // For the moment, whitelist DWARF subprogram DIEs for 406 // auto-generated wrapper functions. What seems to happen 407 // here is that we get different line numbers on formal 408 // params; I am guessing that the pos is being inherited 409 // from the spot where the wrapper is needed. 410 whitelist := strings.HasPrefix(name, "go.info.go.interface") || 411 strings.HasPrefix(name, "go.info.go.builtin") || 412 strings.HasPrefix(name, "go.debuglines") 413 if !whitelist { 414 l.strictDupMsgs++ 415 } 416 } 417 418 func (l *Loader) NStrictDupMsgs() int { return l.strictDupMsgs } 419 420 // Number of total symbols. 421 func (l *Loader) NSym() int { 422 return int(l.max + 1) 423 } 424 425 // Number of defined Go symbols. 426 func (l *Loader) NDef() int { 427 return int(l.extStart) 428 } 429 430 // Returns the raw (unpatched) name of the i-th symbol. 431 func (l *Loader) RawSymName(i Sym) string { 432 if l.IsExternal(i) { 433 if s := l.Syms[i]; s != nil { 434 return s.Name 435 } 436 return "" 437 } 438 r, li := l.toLocal(i) 439 osym := goobj2.Sym{} 440 osym.Read(r.Reader, r.SymOff(li)) 441 return osym.Name 442 } 443 444 // Returns the (patched) name of the i-th symbol. 445 func (l *Loader) SymName(i Sym) string { 446 if l.IsExternal(i) { 447 if s := l.Syms[i]; s != nil { 448 return s.Name // external name should already be patched? 449 } 450 return "" 451 } 452 r, li := l.toLocal(i) 453 osym := goobj2.Sym{} 454 osym.Read(r.Reader, r.SymOff(li)) 455 return strings.Replace(osym.Name, "\"\".", r.pkgprefix, -1) 456 } 457 458 // Returns the type of the i-th symbol. 459 func (l *Loader) SymType(i Sym) sym.SymKind { 460 if l.IsExternal(i) { 461 if s := l.Syms[i]; s != nil { 462 return s.Type 463 } 464 return 0 465 } 466 r, li := l.toLocal(i) 467 osym := goobj2.Sym{} 468 osym.Read(r.Reader, r.SymOff(li)) 469 return sym.AbiSymKindToSymKind[objabi.SymKind(osym.Type)] 470 } 471 472 // Returns the attributes of the i-th symbol. 473 func (l *Loader) SymAttr(i Sym) uint8 { 474 if l.IsExternal(i) { 475 // TODO: do something? External symbols have different representation of attributes. For now, ReflectMethod is the only thing matters and it cannot be set by external symbol. 476 return 0 477 } 478 r, li := l.toLocal(i) 479 osym := goobj2.Sym{} 480 osym.Read(r.Reader, r.SymOff(li)) 481 return osym.Flag 482 } 483 484 // Returns whether the i-th symbol has ReflectMethod attribute set. 485 func (l *Loader) IsReflectMethod(i Sym) bool { 486 return l.SymAttr(i)&goobj2.SymFlagReflectMethod != 0 487 } 488 489 // Returns whether this is a Go type symbol. 490 func (l *Loader) IsGoType(i Sym) bool { 491 return l.SymAttr(i)&goobj2.SymFlagGoType != 0 492 } 493 494 // Returns whether this is a "go.itablink.*" symbol. 495 func (l *Loader) IsItabLink(i Sym) bool { 496 if _, ok := l.itablink[i]; ok { 497 return true 498 } 499 return false 500 } 501 502 // Returns the symbol content of the i-th symbol. i is global index. 503 func (l *Loader) Data(i Sym) []byte { 504 if l.IsExternal(i) { 505 if s := l.Syms[i]; s != nil { 506 return s.P 507 } 508 return nil 509 } 510 r, li := l.toLocal(i) 511 return r.Data(li) 512 } 513 514 // Returns the number of aux symbols given a global index. 515 func (l *Loader) NAux(i Sym) int { 516 if l.IsExternal(i) { 517 return 0 518 } 519 r, li := l.toLocal(i) 520 return r.NAux(li) 521 } 522 523 // Returns the referred symbol of the j-th aux symbol of the i-th 524 // symbol. 525 func (l *Loader) AuxSym(i Sym, j int) Sym { 526 if l.IsExternal(i) { 527 return 0 528 } 529 r, li := l.toLocal(i) 530 a := goobj2.Aux{} 531 a.Read(r.Reader, r.AuxOff(li, j)) 532 return l.resolve(r, a.Sym) 533 } 534 535 // ReadAuxSyms reads the aux symbol ids for the specified symbol into the 536 // slice passed as a parameter. If the slice capacity is not large enough, a new 537 // larger slice will be allocated. Final slice is returned. 538 func (l *Loader) ReadAuxSyms(symIdx Sym, dst []Sym) []Sym { 539 if l.IsExternal(symIdx) { 540 return dst[:0] 541 } 542 naux := l.NAux(symIdx) 543 if naux == 0 { 544 return dst[:0] 545 } 546 547 if cap(dst) < naux { 548 dst = make([]Sym, naux) 549 } 550 dst = dst[:0] 551 552 r, li := l.toLocal(symIdx) 553 for i := 0; i < naux; i++ { 554 a := goobj2.Aux{} 555 a.Read(r.Reader, r.AuxOff(li, i)) 556 dst = append(dst, l.resolve(r, a.Sym)) 557 } 558 559 return dst 560 } 561 562 // OuterSym gets the outer symbol for host object loaded symbols. 563 func (l *Loader) OuterSym(i Sym) Sym { 564 sym := l.Syms[i] 565 if sym != nil && sym.Outer != nil { 566 outer := sym.Outer 567 return l.Lookup(outer.Name, int(outer.Version)) 568 } 569 return 0 570 } 571 572 // SubSym gets the subsymbol for host object loaded symbols. 573 func (l *Loader) SubSym(i Sym) Sym { 574 sym := l.Syms[i] 575 if sym != nil && sym.Sub != nil { 576 sub := sym.Sub 577 return l.Lookup(sub.Name, int(sub.Version)) 578 } 579 return 0 580 } 581 582 // Initialize Reachable bitmap for running deadcode pass. 583 func (l *Loader) InitReachable() { 584 l.Reachable = makeBitmap(l.NSym()) 585 } 586 587 // At method returns the j-th reloc for a global symbol. 588 func (relocs *Relocs) At(j int) Reloc { 589 if relocs.ext != nil { 590 rel := &relocs.ext.R[j] 591 return Reloc{ 592 Off: rel.Off, 593 Size: rel.Siz, 594 Type: rel.Type, 595 Add: rel.Add, 596 Sym: relocs.l.Lookup(rel.Sym.Name, int(rel.Sym.Version)), 597 } 598 } 599 rel := goobj2.Reloc{} 600 rel.Read(relocs.r.Reader, relocs.r.RelocOff(relocs.li, j)) 601 target := relocs.l.resolve(relocs.r, rel.Sym) 602 return Reloc{ 603 Off: rel.Off, 604 Size: rel.Siz, 605 Type: objabi.RelocType(rel.Type), 606 Add: rel.Add, 607 Sym: target, 608 } 609 } 610 611 // ReadAll method reads all relocations for a symbol into the 612 // specified slice. If the slice capacity is not large enough, a new 613 // larger slice will be allocated. Final slice is returned. 614 func (relocs *Relocs) ReadAll(dst []Reloc) []Reloc { 615 if relocs.Count == 0 { 616 return dst[:0] 617 } 618 619 if cap(dst) < relocs.Count { 620 dst = make([]Reloc, relocs.Count) 621 } 622 dst = dst[:0] 623 624 if relocs.ext != nil { 625 for i := 0; i < relocs.Count; i++ { 626 erel := &relocs.ext.R[i] 627 rel := Reloc{ 628 Off: erel.Off, 629 Size: erel.Siz, 630 Type: erel.Type, 631 Add: erel.Add, 632 Sym: relocs.l.Lookup(erel.Sym.Name, int(erel.Sym.Version)), 633 } 634 dst = append(dst, rel) 635 } 636 return dst 637 } 638 639 off := relocs.r.RelocOff(relocs.li, 0) 640 for i := 0; i < relocs.Count; i++ { 641 rel := goobj2.Reloc{} 642 rel.Read(relocs.r.Reader, off) 643 off += uint32(rel.Size()) 644 target := relocs.l.resolve(relocs.r, rel.Sym) 645 dst = append(dst, Reloc{ 646 Off: rel.Off, 647 Size: rel.Siz, 648 Type: objabi.RelocType(rel.Type), 649 Add: rel.Add, 650 Sym: target, 651 }) 652 } 653 return dst 654 } 655 656 // Relocs returns a Relocs object for the given global sym. 657 func (l *Loader) Relocs(i Sym) Relocs { 658 if l.IsExternal(i) { 659 if s := l.Syms[i]; s != nil { 660 return Relocs{Count: len(s.R), l: l, ext: s} 661 } 662 return Relocs{} 663 } 664 r, li := l.toLocal(i) 665 return l.relocs(r, li) 666 } 667 668 // Relocs returns a Relocs object given a local sym index and reader. 669 func (l *Loader) relocs(r *oReader, li int) Relocs { 670 return Relocs{ 671 Count: r.NReloc(li), 672 li: li, 673 r: r, 674 l: l, 675 } 676 } 677 678 // Preload a package: add autolibs, add symbols to the symbol table. 679 // Does not read symbol data yet. 680 func (l *Loader) Preload(arch *sys.Arch, syms *sym.Symbols, f *bio.Reader, lib *sym.Library, unit *sym.CompilationUnit, length int64, pn string, flags int) { 681 roObject, readonly, err := f.Slice(uint64(length)) 682 if err != nil { 683 log.Fatal("cannot read object file:", err) 684 } 685 r := goobj2.NewReaderFromBytes(roObject, readonly) 686 if r == nil { 687 panic("cannot read object file") 688 } 689 localSymVersion := syms.IncVersion() 690 pkgprefix := objabi.PathToPrefix(lib.Pkg) + "." 691 or := &oReader{r, unit, localSymVersion, r.Flags(), pkgprefix, nil} 692 693 // Autolib 694 lib.ImportStrings = append(lib.ImportStrings, r.Autolib()...) 695 696 // DWARF file table 697 nfile := r.NDwarfFile() 698 unit.DWARFFileTable = make([]string, nfile) 699 for i := range unit.DWARFFileTable { 700 unit.DWARFFileTable[i] = r.DwarfFile(i) 701 } 702 703 istart := l.addObj(lib.Pkg, or) 704 705 ndef := r.NSym() 706 nnonpkgdef := r.NNonpkgdef() 707 for i, n := 0, ndef+nnonpkgdef; i < n; i++ { 708 osym := goobj2.Sym{} 709 osym.Read(r, r.SymOff(i)) 710 name := strings.Replace(osym.Name, "\"\".", pkgprefix, -1) 711 if name == "" { 712 continue // don't add unnamed aux symbol 713 } 714 v := abiToVer(osym.ABI, localSymVersion) 715 dupok := osym.Dupok() 716 added := l.AddSym(name, v, istart+Sym(i), or, dupok, sym.AbiSymKindToSymKind[objabi.SymKind(osym.Type)]) 717 if added && strings.HasPrefix(name, "go.itablink.") { 718 l.itablink[istart+Sym(i)] = struct{}{} 719 } 720 if added && strings.HasPrefix(name, "runtime.") { 721 if bi := goobj2.BuiltinIdx(name, v); bi != -1 { 722 // This is a definition of a builtin symbol. Record where it is. 723 l.builtinSyms[bi] = istart + Sym(i) 724 } 725 } 726 } 727 728 // The caller expects us consuming all the data 729 f.MustSeek(length, os.SEEK_CUR) 730 } 731 732 // Make sure referenced symbols are added. Most of them should already be added. 733 // This should only be needed for referenced external symbols. 734 func (l *Loader) LoadRefs(arch *sys.Arch, syms *sym.Symbols) { 735 for _, o := range l.objs[1:] { 736 loadObjRefs(l, o.r, arch, syms) 737 } 738 } 739 740 func loadObjRefs(l *Loader, r *oReader, arch *sys.Arch, syms *sym.Symbols) { 741 ndef := r.NSym() + r.NNonpkgdef() 742 for i, n := 0, r.NNonpkgref(); i < n; i++ { 743 osym := goobj2.Sym{} 744 osym.Read(r.Reader, r.SymOff(ndef+i)) 745 name := strings.Replace(osym.Name, "\"\".", r.pkgprefix, -1) 746 v := abiToVer(osym.ABI, r.version) 747 l.AddExtSym(name, v) 748 } 749 } 750 751 func abiToVer(abi uint16, localSymVersion int) int { 752 var v int 753 if abi == goobj2.SymABIstatic { 754 // Static 755 v = localSymVersion 756 } else if abiver := sym.ABIToVersion(obj.ABI(abi)); abiver != -1 { 757 // Note that data symbols are "ABI0", which maps to version 0. 758 v = abiver 759 } else { 760 log.Fatalf("invalid symbol ABI: %d", abi) 761 } 762 return v 763 } 764 765 func preprocess(arch *sys.Arch, s *sym.Symbol) { 766 if s.Name != "" && s.Name[0] == '$' && len(s.Name) > 5 && s.Type == 0 && len(s.P) == 0 { 767 x, err := strconv.ParseUint(s.Name[5:], 16, 64) 768 if err != nil { 769 log.Panicf("failed to parse $-symbol %s: %v", s.Name, err) 770 } 771 s.Type = sym.SRODATA 772 s.Attr |= sym.AttrLocal 773 switch s.Name[:5] { 774 case "$f32.": 775 if uint64(uint32(x)) != x { 776 log.Panicf("$-symbol %s too large: %d", s.Name, x) 777 } 778 s.AddUint32(arch, uint32(x)) 779 case "$f64.", "$i64.": 780 s.AddUint64(arch, x) 781 default: 782 log.Panicf("unrecognized $-symbol: %s", s.Name) 783 } 784 } 785 } 786 787 // Load full contents. 788 func (l *Loader) LoadFull(arch *sys.Arch, syms *sym.Symbols) { 789 // create all Symbols first. 790 l.growSyms(l.NSym()) 791 792 nr := 0 // total number of sym.Reloc's we'll need 793 for _, o := range l.objs[1:] { 794 nr += loadObjSyms(l, syms, o.r) 795 } 796 797 // allocate a single large slab of relocations for all live symbols 798 l.relocBatch = make([]sym.Reloc, nr) 799 800 // external symbols 801 for i := l.extStart; i <= l.max; i++ { 802 if s := l.Syms[i]; s != nil { 803 s.Attr.Set(sym.AttrReachable, l.Reachable.Has(i)) 804 continue // already loaded from external object 805 } 806 nv := l.extSyms[i-l.extStart] 807 if l.Reachable.Has(i) || strings.HasPrefix(nv.name, "gofile..") { // XXX file symbols are used but not marked 808 s := syms.Newsym(nv.name, nv.v) 809 preprocess(arch, s) 810 s.Attr.Set(sym.AttrReachable, l.Reachable.Has(i)) 811 l.Syms[i] = s 812 } 813 } 814 815 // load contents of defined symbols 816 for _, o := range l.objs[1:] { 817 loadObjFull(l, o.r) 818 } 819 820 // Resolve ABI aliases for external symbols. This is only 821 // needed for internal cgo linking. 822 // (The old code does this in deadcode, but deadcode2 doesn't 823 // do this.) 824 for i := l.extStart; i <= l.max; i++ { 825 if s := l.Syms[i]; s != nil && s.Attr.Reachable() { 826 for ri := range s.R { 827 r := &s.R[ri] 828 if r.Sym != nil && r.Sym.Type == sym.SABIALIAS { 829 r.Sym = r.Sym.R[0].Sym 830 } 831 } 832 } 833 } 834 } 835 836 // ExtractSymbols grabs the symbols out of the loader for work that hasn't been 837 // ported to the new symbol type. 838 func (l *Loader) ExtractSymbols(syms *sym.Symbols) { 839 // Nil out overwritten symbols. 840 // Overwritten Go symbols aren't a problem (as they're lazy loaded), but 841 // symbols loaded from host object loaders are fully loaded, and we might 842 // have multiple symbols with the same name. This loop nils them out. 843 for oldI := range l.overwrite { 844 l.Syms[oldI] = nil 845 } 846 847 // Add symbols to the ctxt.Syms lookup table. This explicitly 848 // skips things created via loader.Create (marked with versions 849 // less than zero), since if we tried to add these we'd wind up 850 // with collisions. Along the way, update the version from the 851 // negative anon version to something larger than sym.SymVerStatic 852 // (needed so that sym.symbol.IsFileLocal() works properly). 853 anonVerReplacement := syms.IncVersion() 854 for _, s := range l.Syms { 855 if s == nil { 856 continue 857 } 858 if s.Name != "" && s.Version >= 0 { 859 syms.Add(s) 860 } 861 if s.Version < 0 { 862 s.Version = int16(anonVerReplacement) 863 } 864 } 865 } 866 867 // addNewSym adds a new sym.Symbol to the i-th index in the list of symbols. 868 func (l *Loader) addNewSym(i Sym, syms *sym.Symbols, name string, ver int, unit *sym.CompilationUnit, t sym.SymKind) *sym.Symbol { 869 s := syms.Newsym(name, ver) 870 if s.Type != 0 && s.Type != sym.SXREF { 871 fmt.Println("symbol already processed:", unit.Lib, i, s) 872 panic("symbol already processed") 873 } 874 if t == sym.SBSS && (s.Type == sym.SRODATA || s.Type == sym.SNOPTRBSS) { 875 t = s.Type 876 } 877 s.Type = t 878 s.Unit = unit 879 l.growSyms(int(i)) 880 l.Syms[i] = s 881 return s 882 } 883 884 // loadObjSyms creates sym.Symbol objects for the live Syms in the 885 // object corresponding to object reader "r". Return value is the 886 // number of sym.Reloc entries required for all the new symbols. 887 func loadObjSyms(l *Loader, syms *sym.Symbols, r *oReader) int { 888 istart := l.startIndex(r) 889 nr := 0 890 891 for i, n := 0, r.NSym()+r.NNonpkgdef(); i < n; i++ { 892 // If it's been previously loaded in host object loading, we don't need to do it again. 893 if s := l.Syms[istart+Sym(i)]; s != nil { 894 // Mark symbol as reachable as it wasn't marked as such before. 895 s.Attr.Set(sym.AttrReachable, l.Reachable.Has(istart+Sym(i))) 896 nr += r.NReloc(i) 897 continue 898 } 899 osym := goobj2.Sym{} 900 osym.Read(r.Reader, r.SymOff(i)) 901 name := strings.Replace(osym.Name, "\"\".", r.pkgprefix, -1) 902 if name == "" { 903 continue 904 } 905 ver := abiToVer(osym.ABI, r.version) 906 if osym.ABI != goobj2.SymABIstatic && l.symsByName[ver][name] != istart+Sym(i) { 907 continue 908 } 909 910 t := sym.AbiSymKindToSymKind[objabi.SymKind(osym.Type)] 911 if t == sym.SXREF { 912 log.Fatalf("bad sxref") 913 } 914 if t == 0 { 915 log.Fatalf("missing type for %s in %s", name, r.unit.Lib) 916 } 917 if !l.Reachable.Has(istart+Sym(i)) && !(t == sym.SRODATA && strings.HasPrefix(name, "type.")) && name != "runtime.addmoduledata" && name != "runtime.lastmoduledatap" { 918 // No need to load unreachable symbols. 919 // XXX some type symbol's content may be needed in DWARF code, but they are not marked. 920 // XXX reference to runtime.addmoduledata may be generated later by the linker in plugin mode. 921 continue 922 } 923 924 s := l.addNewSym(istart+Sym(i), syms, name, ver, r.unit, t) 925 s.Attr.Set(sym.AttrReachable, l.Reachable.Has(istart+Sym(i))) 926 nr += r.NReloc(i) 927 } 928 return nr 929 } 930 931 // funcInfoSym records the sym.Symbol for a function, along with a copy 932 // of the corresponding goobj2.Sym and the index of its FuncInfo aux sym. 933 // We use this to delay populating FuncInfo until we can batch-allocate 934 // slices for their sub-objects. 935 type funcInfoSym struct { 936 s *sym.Symbol // sym.Symbol for a live function 937 osym goobj2.Sym // object file symbol data for that function 938 isym int // global symbol index of FuncInfo aux sym for func 939 } 940 941 // funcAllocInfo records totals/counts for all functions in an objfile; 942 // used to help with bulk allocation of sym.Symbol sub-objects. 943 type funcAllocInfo struct { 944 symPtr uint32 // number of *sym.Symbol's needed in file slices 945 inlCall uint32 // number of sym.InlinedCall's needed in inltree slices 946 pcData uint32 // number of sym.Pcdata's needed in pdata slices 947 fdOff uint32 // number of int64's needed in all Funcdataoff slices 948 } 949 950 // LoadSymbol loads a single symbol by name. 951 // This function should only be used by the host object loaders. 952 // NB: This function does NOT set the symbol as reachable. 953 func (l *Loader) LoadSymbol(name string, version int, syms *sym.Symbols) *sym.Symbol { 954 global := l.Lookup(name, version) 955 956 // If we're already loaded, bail. 957 if global != 0 && int(global) < len(l.Syms) && l.Syms[global] != nil { 958 return l.Syms[global] 959 } 960 961 // Read the symbol. 962 r, i := l.toLocal(global) 963 istart := l.startIndex(r) 964 965 osym := goobj2.Sym{} 966 osym.Read(r.Reader, r.SymOff(int(i))) 967 if l.symsByName[version][name] != istart+Sym(i) { 968 return nil 969 } 970 971 return l.addNewSym(istart+Sym(i), syms, name, version, r.unit, sym.AbiSymKindToSymKind[objabi.SymKind(osym.Type)]) 972 } 973 974 // LookupOrCreate looks up a symbol by name, and creates one if not found. 975 // Either way, it will also create a sym.Symbol for it, if not already. 976 // This should only be called when interacting with parts of the linker 977 // that still works on sym.Symbols (i.e. internal cgo linking, for now). 978 func (l *Loader) LookupOrCreate(name string, version int, syms *sym.Symbols) *sym.Symbol { 979 i := l.Lookup(name, version) 980 if i != 0 { 981 // symbol exists 982 if int(i) < len(l.Syms) && l.Syms[i] != nil { 983 return l.Syms[i] // already loaded 984 } 985 if l.IsExternal(i) { 986 panic("Can't load an external symbol.") 987 } 988 return l.LoadSymbol(name, version, syms) 989 } 990 i = l.AddExtSym(name, version) 991 s := syms.Newsym(name, version) 992 l.Syms[i] = s 993 return s 994 } 995 996 // Create creates a symbol with the specified name, returning a 997 // sym.Symbol object for it. This method is intended for static/hidden 998 // symbols discovered while loading host objects. We can see more than 999 // one instance of a given static symbol with the same name/version, 1000 // so we can't add them to the lookup tables "as is". Instead assign 1001 // them fictitious (unique) versions, starting at -1 and decreasing by 1002 // one for each newly created symbol, and record them in the 1003 // extStaticSyms hash. 1004 func (l *Loader) Create(name string, syms *sym.Symbols) *sym.Symbol { 1005 i := l.max + 1 1006 l.max++ 1007 if l.extStart == 0 { 1008 l.extStart = i 1009 } 1010 1011 // Assign a new unique negative version -- this is to mark the 1012 // symbol so that it can be skipped when ExtractSymbols is adding 1013 // ext syms to the sym.Symbols hash. 1014 l.anonVersion-- 1015 ver := l.anonVersion 1016 l.extSyms = append(l.extSyms, nameVer{name, ver}) 1017 l.growSyms(int(i)) 1018 s := syms.Newsym(name, ver) 1019 l.Syms[i] = s 1020 l.extStaticSyms[nameVer{name, ver}] = i 1021 1022 return s 1023 } 1024 1025 func loadObjFull(l *Loader, r *oReader) { 1026 lib := r.unit.Lib 1027 istart := l.startIndex(r) 1028 1029 resolveSymRef := func(s goobj2.SymRef) *sym.Symbol { 1030 i := l.resolve(r, s) 1031 return l.Syms[i] 1032 } 1033 1034 funcs := []funcInfoSym{} 1035 fdsyms := []*sym.Symbol{} 1036 var funcAllocCounts funcAllocInfo 1037 pcdataBase := r.PcdataBase() 1038 rslice := []Reloc{} 1039 for i, n := 0, r.NSym()+r.NNonpkgdef(); i < n; i++ { 1040 osym := goobj2.Sym{} 1041 osym.Read(r.Reader, r.SymOff(i)) 1042 name := strings.Replace(osym.Name, "\"\".", r.pkgprefix, -1) 1043 if name == "" { 1044 continue 1045 } 1046 ver := abiToVer(osym.ABI, r.version) 1047 dupok := osym.Dupok() 1048 if dupok { 1049 if dupsym := l.symsByName[ver][name]; dupsym != istart+Sym(i) { 1050 if l.Reachable.Has(dupsym) { 1051 // A dupok symbol is resolved to another package. We still need 1052 // to record its presence in the current package, as the trampoline 1053 // pass expects packages are laid out in dependency order. 1054 s := l.Syms[dupsym] 1055 if s.Type == sym.STEXT { 1056 lib.DupTextSyms = append(lib.DupTextSyms, s) 1057 } 1058 } 1059 continue 1060 } 1061 } 1062 1063 s := l.Syms[istart+Sym(i)] 1064 if s == nil { 1065 continue 1066 } 1067 if s.Name != name { // Sanity check. We can remove it in the final version. 1068 fmt.Println("name mismatch:", lib, i, s.Name, name) 1069 panic("name mismatch") 1070 } 1071 1072 local := osym.Local() 1073 makeTypelink := osym.Typelink() 1074 size := osym.Siz 1075 1076 // Symbol data 1077 s.P = r.Data(i) 1078 s.Attr.Set(sym.AttrReadOnly, r.ReadOnly()) 1079 1080 // Relocs 1081 relocs := l.relocs(r, i) 1082 rslice = relocs.ReadAll(rslice) 1083 batch := l.relocBatch 1084 s.R = batch[:relocs.Count:relocs.Count] 1085 l.relocBatch = batch[relocs.Count:] 1086 for j := range s.R { 1087 r := rslice[j] 1088 rs := r.Sym 1089 sz := r.Size 1090 rt := r.Type 1091 if rt == objabi.R_METHODOFF { 1092 if l.Reachable.Has(rs) { 1093 rt = objabi.R_ADDROFF 1094 } else { 1095 sz = 0 1096 rs = 0 1097 } 1098 } 1099 if rt == objabi.R_WEAKADDROFF && !l.Reachable.Has(rs) { 1100 rs = 0 1101 sz = 0 1102 } 1103 if rs != 0 && l.SymType(rs) == sym.SABIALIAS { 1104 rsrelocs := l.Relocs(rs) 1105 rs = rsrelocs.At(0).Sym 1106 } 1107 s.R[j] = sym.Reloc{ 1108 Off: r.Off, 1109 Siz: sz, 1110 Type: rt, 1111 Add: r.Add, 1112 Sym: l.Syms[rs], 1113 } 1114 } 1115 1116 // Aux symbol info 1117 isym := -1 1118 naux := r.NAux(i) 1119 for j := 0; j < naux; j++ { 1120 a := goobj2.Aux{} 1121 a.Read(r.Reader, r.AuxOff(i, j)) 1122 switch a.Type { 1123 case goobj2.AuxGotype: 1124 typ := resolveSymRef(a.Sym) 1125 if typ != nil { 1126 s.Gotype = typ 1127 } 1128 case goobj2.AuxFuncdata: 1129 fdsyms = append(fdsyms, resolveSymRef(a.Sym)) 1130 case goobj2.AuxFuncInfo: 1131 if a.Sym.PkgIdx != goobj2.PkgIdxSelf { 1132 panic("funcinfo symbol not defined in current package") 1133 } 1134 isym = int(a.Sym.SymIdx) 1135 case goobj2.AuxDwarfInfo, goobj2.AuxDwarfLoc, goobj2.AuxDwarfRanges, goobj2.AuxDwarfLines: 1136 // ignored for now 1137 default: 1138 panic("unknown aux type") 1139 } 1140 } 1141 1142 s.File = r.pkgprefix[:len(r.pkgprefix)-1] 1143 if dupok { 1144 s.Attr |= sym.AttrDuplicateOK 1145 } 1146 if s.Size < int64(size) { 1147 s.Size = int64(size) 1148 } 1149 s.Attr.Set(sym.AttrLocal, local) 1150 s.Attr.Set(sym.AttrMakeTypelink, makeTypelink) 1151 1152 if s.Type == sym.SDWARFINFO { 1153 // For DWARF symbols, replace `"".` to actual package prefix 1154 // in the symbol content. 1155 // TODO: maybe we should do this in the compiler and get rid 1156 // of this. 1157 patchDWARFName(s, r) 1158 } 1159 1160 if s.Type != sym.STEXT { 1161 continue 1162 } 1163 1164 if isym == -1 { 1165 continue 1166 } 1167 1168 // Record function sym and associated info for additional 1169 // processing in the loop below. 1170 fwis := funcInfoSym{s: s, isym: isym, osym: osym} 1171 funcs = append(funcs, fwis) 1172 1173 // Read the goobj2.FuncInfo for this text symbol so that we can 1174 // collect allocation counts. We'll read it again in the loop 1175 // below. 1176 b := r.Data(isym) 1177 info := goobj2.FuncInfo{} 1178 info.Read(b) 1179 funcAllocCounts.symPtr += uint32(len(info.File)) 1180 funcAllocCounts.pcData += uint32(len(info.Pcdata)) 1181 funcAllocCounts.inlCall += uint32(len(info.InlTree)) 1182 funcAllocCounts.fdOff += uint32(len(info.Funcdataoff)) 1183 } 1184 1185 // At this point we can do batch allocation of the sym.FuncInfo's, 1186 // along with the slices of sub-objects they use. 1187 fiBatch := make([]sym.FuncInfo, len(funcs)) 1188 inlCallBatch := make([]sym.InlinedCall, funcAllocCounts.inlCall) 1189 symPtrBatch := make([]*sym.Symbol, funcAllocCounts.symPtr) 1190 pcDataBatch := make([]sym.Pcdata, funcAllocCounts.pcData) 1191 fdOffBatch := make([]int64, funcAllocCounts.fdOff) 1192 1193 // Populate FuncInfo contents for func symbols. 1194 for fi := 0; fi < len(funcs); fi++ { 1195 s := funcs[fi].s 1196 isym := funcs[fi].isym 1197 osym := funcs[fi].osym 1198 1199 s.FuncInfo = &fiBatch[0] 1200 fiBatch = fiBatch[1:] 1201 1202 b := r.Data(isym) 1203 info := goobj2.FuncInfo{} 1204 info.Read(b) 1205 1206 if info.NoSplit != 0 { 1207 s.Attr |= sym.AttrNoSplit 1208 } 1209 if osym.ReflectMethod() { 1210 s.Attr |= sym.AttrReflectMethod 1211 } 1212 if r.Flags()&goobj2.ObjFlagShared != 0 { 1213 s.Attr |= sym.AttrShared 1214 } 1215 if osym.TopFrame() { 1216 s.Attr |= sym.AttrTopFrame 1217 } 1218 1219 pc := s.FuncInfo 1220 1221 if len(info.Funcdataoff) != 0 { 1222 nfd := len(info.Funcdataoff) 1223 pc.Funcdata = fdsyms[:nfd:nfd] 1224 fdsyms = fdsyms[nfd:] 1225 } 1226 1227 info.Pcdata = append(info.Pcdata, info.PcdataEnd) // for the ease of knowing where it ends 1228 pc.Args = int32(info.Args) 1229 pc.Locals = int32(info.Locals) 1230 1231 npc := len(info.Pcdata) - 1 // -1 as we appended one above 1232 pc.Pcdata = pcDataBatch[:npc:npc] 1233 pcDataBatch = pcDataBatch[npc:] 1234 1235 nfd := len(info.Funcdataoff) 1236 pc.Funcdataoff = fdOffBatch[:nfd:nfd] 1237 fdOffBatch = fdOffBatch[nfd:] 1238 1239 nsp := len(info.File) 1240 pc.File = symPtrBatch[:nsp:nsp] 1241 symPtrBatch = symPtrBatch[nsp:] 1242 1243 nic := len(info.InlTree) 1244 pc.InlTree = inlCallBatch[:nic:nic] 1245 inlCallBatch = inlCallBatch[nic:] 1246 1247 pc.Pcsp.P = r.BytesAt(pcdataBase+info.Pcsp, int(info.Pcfile-info.Pcsp)) 1248 pc.Pcfile.P = r.BytesAt(pcdataBase+info.Pcfile, int(info.Pcline-info.Pcfile)) 1249 pc.Pcline.P = r.BytesAt(pcdataBase+info.Pcline, int(info.Pcinline-info.Pcline)) 1250 pc.Pcinline.P = r.BytesAt(pcdataBase+info.Pcinline, int(info.Pcdata[0]-info.Pcinline)) 1251 for k := range pc.Pcdata { 1252 pc.Pcdata[k].P = r.BytesAt(pcdataBase+info.Pcdata[k], int(info.Pcdata[k+1]-info.Pcdata[k])) 1253 } 1254 for k := range pc.Funcdataoff { 1255 pc.Funcdataoff[k] = int64(info.Funcdataoff[k]) 1256 } 1257 for k := range pc.File { 1258 pc.File[k] = resolveSymRef(info.File[k]) 1259 } 1260 for k := range pc.InlTree { 1261 inl := &info.InlTree[k] 1262 pc.InlTree[k] = sym.InlinedCall{ 1263 Parent: inl.Parent, 1264 File: resolveSymRef(inl.File), 1265 Line: inl.Line, 1266 Func: l.SymName(l.resolve(r, inl.Func)), 1267 ParentPC: inl.ParentPC, 1268 } 1269 } 1270 1271 dupok := osym.Dupok() 1272 if !dupok { 1273 if s.Attr.OnList() { 1274 log.Fatalf("symbol %s listed multiple times", s.Name) 1275 } 1276 s.Attr.Set(sym.AttrOnList, true) 1277 lib.Textp = append(lib.Textp, s) 1278 } else { 1279 // there may be a dup in another package 1280 // put into a temp list and add to text later 1281 lib.DupTextSyms = append(lib.DupTextSyms, s) 1282 } 1283 } 1284 } 1285 1286 var emptyPkg = []byte(`"".`) 1287 1288 func patchDWARFName1(p []byte, r *oReader) ([]byte, int) { 1289 // This is kind of ugly. Really the package name should not 1290 // even be included here. 1291 if len(p) < 1 || p[0] != dwarf.DW_ABRV_FUNCTION { 1292 return p, -1 1293 } 1294 e := bytes.IndexByte(p, 0) 1295 if e == -1 { 1296 return p, -1 1297 } 1298 if !bytes.Contains(p[:e], emptyPkg) { 1299 return p, -1 1300 } 1301 pkgprefix := []byte(r.pkgprefix) 1302 patched := bytes.Replace(p[:e], emptyPkg, pkgprefix, -1) 1303 return append(patched, p[e:]...), e 1304 } 1305 1306 func patchDWARFName(s *sym.Symbol, r *oReader) { 1307 patched, e := patchDWARFName1(s.P, r) 1308 if e == -1 { 1309 return 1310 } 1311 s.P = patched 1312 s.Attr.Set(sym.AttrReadOnly, false) 1313 delta := int64(len(s.P)) - s.Size 1314 s.Size = int64(len(s.P)) 1315 for i := range s.R { 1316 r := &s.R[i] 1317 if r.Off > int32(e) { 1318 r.Off += int32(delta) 1319 } 1320 } 1321 } 1322 1323 // For debugging. 1324 func (l *Loader) Dump() { 1325 fmt.Println("objs") 1326 for _, obj := range l.objs { 1327 if obj.r != nil { 1328 fmt.Println(obj.i, obj.r.unit.Lib) 1329 } 1330 } 1331 fmt.Println("syms") 1332 for i, s := range l.Syms { 1333 if i == 0 { 1334 continue 1335 } 1336 if s != nil { 1337 fmt.Println(i, s, s.Type) 1338 } else { 1339 fmt.Println(i, l.SymName(Sym(i)), "<not loaded>") 1340 } 1341 } 1342 fmt.Println("overwrite:", l.overwrite) 1343 fmt.Println("symsByName") 1344 for name, i := range l.symsByName[0] { 1345 fmt.Println(i, name, 0) 1346 } 1347 for name, i := range l.symsByName[1] { 1348 fmt.Println(i, name, 1) 1349 } 1350 }