]> Cypherpunks.ru repositories - gostls13.git/blob - src/cmd/link/internal/loader/loader.go
[dev.link] all: merge branch 'master' into dev.link
[gostls13.git] / src / cmd / link / internal / loader / loader.go
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         "cmd/internal/bio"
10         "cmd/internal/dwarf"
11         "cmd/internal/goobj2"
12         "cmd/internal/obj"
13         "cmd/internal/objabi"
14         "cmd/internal/sys"
15         "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, "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.Syms[rs] != nil && l.Syms[rs].Type == 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 }