1
2
3
4
5 package loader
6
7 import (
8 "bytes"
9 "cmd/internal/bio"
10 "cmd/internal/goobj"
11 "cmd/internal/obj"
12 "cmd/internal/objabi"
13 "cmd/internal/sys"
14 "cmd/link/internal/sym"
15 "debug/elf"
16 "fmt"
17 "internal/abi"
18 "io"
19 "log"
20 "math/bits"
21 "os"
22 "sort"
23 "strings"
24 )
25
26 var _ = fmt.Print
27
28
29
30 type Sym = sym.LoaderSym
31
32
33
34 type Relocs struct {
35 rs []goobj.Reloc
36
37 li uint32
38 r *oReader
39 l *Loader
40 }
41
42
43 type ExtReloc struct {
44 Xsym Sym
45 Xadd int64
46 Type objabi.RelocType
47 Size uint8
48 }
49
50
51
52 type Reloc struct {
53 *goobj.Reloc
54 r *oReader
55 l *Loader
56 }
57
58 func (rel Reloc) Type() objabi.RelocType { return objabi.RelocType(rel.Reloc.Type()) &^ objabi.R_WEAK }
59 func (rel Reloc) Weak() bool { return objabi.RelocType(rel.Reloc.Type())&objabi.R_WEAK != 0 }
60 func (rel Reloc) SetType(t objabi.RelocType) { rel.Reloc.SetType(uint16(t)) }
61 func (rel Reloc) Sym() Sym { return rel.l.resolve(rel.r, rel.Reloc.Sym()) }
62 func (rel Reloc) SetSym(s Sym) { rel.Reloc.SetSym(goobj.SymRef{PkgIdx: 0, SymIdx: uint32(s)}) }
63 func (rel Reloc) IsMarker() bool { return rel.Siz() == 0 }
64
65
66
67 type Aux struct {
68 *goobj.Aux
69 r *oReader
70 l *Loader
71 }
72
73 func (a Aux) Sym() Sym { return a.l.resolve(a.r, a.Aux.Sym()) }
74
75
76
77 type oReader struct {
78 *goobj.Reader
79 unit *sym.CompilationUnit
80 version int
81 pkgprefix string
82 syms []Sym
83 pkg []uint32
84 ndef int
85 nhashed64def int
86 nhasheddef int
87 objidx uint32
88 }
89
90
91
92 func (r *oReader) NAlldef() int { return r.ndef + r.nhashed64def + r.nhasheddef + r.NNonpkgdef() }
93
94
95
96
97
98
99 type objSym struct {
100 objidx uint32
101 s uint32
102 }
103
104 type nameVer struct {
105 name string
106 v int
107 }
108
109 type Bitmap []uint32
110
111
112 func (bm Bitmap) Set(i Sym) {
113 n, r := uint(i)/32, uint(i)%32
114 bm[n] |= 1 << r
115 }
116
117
118 func (bm Bitmap) Unset(i Sym) {
119 n, r := uint(i)/32, uint(i)%32
120 bm[n] &^= (1 << r)
121 }
122
123
124 func (bm Bitmap) Has(i Sym) bool {
125 n, r := uint(i)/32, uint(i)%32
126 return bm[n]&(1<<r) != 0
127 }
128
129
130 func (bm Bitmap) Len() int {
131 return len(bm) * 32
132 }
133
134
135 func (bm Bitmap) Count() int {
136 s := 0
137 for _, x := range bm {
138 s += bits.OnesCount32(x)
139 }
140 return s
141 }
142
143 func MakeBitmap(n int) Bitmap {
144 return make(Bitmap, (n+31)/32)
145 }
146
147
148
149 func growBitmap(reqLen int, b Bitmap) Bitmap {
150 curLen := b.Len()
151 if reqLen > curLen {
152 b = append(b, MakeBitmap(reqLen+1-curLen)...)
153 }
154 return b
155 }
156
157 type symAndSize struct {
158 sym Sym
159 size uint32
160 }
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181 type Loader struct {
182 objs []*oReader
183 extStart Sym
184 builtinSyms []Sym
185
186 objSyms []objSym
187
188 symsByName [2]map[string]Sym
189 extStaticSyms map[nameVer]Sym
190
191 extReader *oReader
192 payloadBatch []extSymPayload
193 payloads []*extSymPayload
194 values []int64
195
196 sects []*sym.Section
197 symSects []uint16
198
199 align []uint8
200
201 deferReturnTramp map[Sym]bool
202
203 objByPkg map[string]uint32
204
205 anonVersion int
206
207
208
209
210
211
212 attrReachable Bitmap
213 attrOnList Bitmap
214 attrLocal Bitmap
215 attrNotInSymbolTable Bitmap
216 attrUsedInIface Bitmap
217 attrSpecial Bitmap
218 attrVisibilityHidden Bitmap
219 attrDuplicateOK Bitmap
220 attrShared Bitmap
221 attrExternal Bitmap
222 generatedSyms Bitmap
223
224 attrReadOnly map[Sym]bool
225 attrCgoExportDynamic map[Sym]struct{}
226 attrCgoExportStatic map[Sym]struct{}
227
228
229 outer []Sym
230 sub map[Sym]Sym
231
232 dynimplib map[Sym]string
233 dynimpvers map[Sym]string
234 localentry map[Sym]uint8
235 extname map[Sym]string
236 elfType map[Sym]elf.SymType
237 elfSym map[Sym]int32
238 localElfSym map[Sym]int32
239 symPkg map[Sym]string
240 plt map[Sym]int32
241 got map[Sym]int32
242 dynid map[Sym]int32
243
244 relocVariant map[relocId]sym.RelocVariant
245
246
247
248
249 Reachparent []Sym
250
251
252 CgoExports map[string]Sym
253
254 WasmExports []Sym
255
256
257
258
259
260 sizeFixups []symAndSize
261
262 flags uint32
263
264 strictDupMsgs int
265
266 errorReporter *ErrorReporter
267
268 npkgsyms int
269 nhashedsyms int
270 }
271
272 const (
273 pkgDef = iota
274 hashed64Def
275 hashedDef
276 nonPkgDef
277 nonPkgRef
278 )
279
280
281 const (
282 nilObj = iota
283 extObj
284 goObjStart
285 )
286
287
288
289 type extSymPayload struct {
290 name string
291 size int64
292 ver int
293 kind sym.SymKind
294 objidx uint32
295 relocs []goobj.Reloc
296 data []byte
297 auxs []goobj.Aux
298 }
299
300 const (
301
302 FlagStrictDups = 1 << iota
303 FlagCheckLinkname
304 )
305
306 func NewLoader(flags uint32, reporter *ErrorReporter) *Loader {
307 nbuiltin := goobj.NBuiltin()
308 extReader := &oReader{objidx: extObj}
309 ldr := &Loader{
310 objs: []*oReader{nil, extReader},
311 objSyms: make([]objSym, 1, 1),
312 extReader: extReader,
313 symsByName: [2]map[string]Sym{make(map[string]Sym, 80000), make(map[string]Sym, 50000)},
314 objByPkg: make(map[string]uint32),
315 sub: make(map[Sym]Sym),
316 dynimplib: make(map[Sym]string),
317 dynimpvers: make(map[Sym]string),
318 localentry: make(map[Sym]uint8),
319 extname: make(map[Sym]string),
320 attrReadOnly: make(map[Sym]bool),
321 elfType: make(map[Sym]elf.SymType),
322 elfSym: make(map[Sym]int32),
323 localElfSym: make(map[Sym]int32),
324 symPkg: make(map[Sym]string),
325 plt: make(map[Sym]int32),
326 got: make(map[Sym]int32),
327 dynid: make(map[Sym]int32),
328 attrCgoExportDynamic: make(map[Sym]struct{}),
329 attrCgoExportStatic: make(map[Sym]struct{}),
330 deferReturnTramp: make(map[Sym]bool),
331 extStaticSyms: make(map[nameVer]Sym),
332 builtinSyms: make([]Sym, nbuiltin),
333 flags: flags,
334 errorReporter: reporter,
335 sects: []*sym.Section{nil},
336 }
337 reporter.ldr = ldr
338 return ldr
339 }
340
341
342 func (l *Loader) addObj(pkg string, r *oReader) {
343 pkg = objabi.PathToPrefix(pkg)
344 if _, ok := l.objByPkg[pkg]; !ok {
345 l.objByPkg[pkg] = r.objidx
346 }
347 l.objs = append(l.objs, r)
348 }
349
350
351
352 func (st *loadState) addSym(name string, ver int, r *oReader, li uint32, kind int, osym *goobj.Sym) Sym {
353 l := st.l
354 if l.extStart != 0 {
355 panic("addSym called after external symbol is created")
356 }
357 i := Sym(len(l.objSyms))
358 if int(i) != len(l.objSyms) {
359 panic("too many symbols")
360 }
361 addToGlobal := func() {
362 l.objSyms = append(l.objSyms, objSym{r.objidx, li})
363 }
364 if name == "" && kind != hashed64Def && kind != hashedDef {
365 addToGlobal()
366 return i
367 }
368 if ver == r.version {
369
370
371
372 addToGlobal()
373 return i
374 }
375 switch kind {
376 case pkgDef:
377
378
379
380
381
382 l.symsByName[ver][name] = i
383 addToGlobal()
384 return i
385 case hashed64Def, hashedDef:
386
387
388
389
390 var checkHash func() (symAndSize, bool)
391 var addToHashMap func(symAndSize)
392 var h64 uint64
393 var h *goobj.HashType
394 if kind == hashed64Def {
395 checkHash = func() (symAndSize, bool) {
396 h64 = r.Hash64(li - uint32(r.ndef))
397 s, existed := st.hashed64Syms[h64]
398 return s, existed
399 }
400 addToHashMap = func(ss symAndSize) { st.hashed64Syms[h64] = ss }
401 } else {
402 checkHash = func() (symAndSize, bool) {
403 h = r.Hash(li - uint32(r.ndef+r.nhashed64def))
404 s, existed := st.hashedSyms[*h]
405 return s, existed
406 }
407 addToHashMap = func(ss symAndSize) { st.hashedSyms[*h] = ss }
408 }
409 siz := osym.Siz()
410 if s, existed := checkHash(); existed {
411
412
413
414
415
416
417
418
419
420 if siz > s.size {
421
422 l.objSyms[s.sym] = objSym{r.objidx, li}
423 addToHashMap(symAndSize{s.sym, siz})
424 }
425 return s.sym
426 }
427 addToHashMap(symAndSize{i, siz})
428 addToGlobal()
429 return i
430 }
431
432
433
434 oldi, existed := l.symsByName[ver][name]
435 if !existed {
436 l.symsByName[ver][name] = i
437 addToGlobal()
438 return i
439 }
440
441
442
443
444 oldsz := l.SymSize(oldi)
445 sz := int64(r.Sym(li).Siz())
446 if osym.Dupok() {
447 if l.flags&FlagStrictDups != 0 {
448 l.checkdup(name, r, li, oldi)
449 }
450 if oldsz < sz {
451
452 l.objSyms[oldi] = objSym{r.objidx, li}
453 }
454 return oldi
455 }
456 oldr, oldli := l.toLocal(oldi)
457 oldsym := oldr.Sym(oldli)
458 if oldsym.Dupok() {
459 return oldi
460 }
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487 oldtyp := sym.AbiSymKindToSymKind[objabi.SymKind(oldsym.Type())]
488 newtyp := sym.AbiSymKindToSymKind[objabi.SymKind(osym.Type())]
489 newIsText := newtyp.IsText()
490 oldHasContent := oldr.DataSize(oldli) != 0
491 newHasContent := r.DataSize(li) != 0
492 oldIsBSS := oldtyp.IsData() && !oldHasContent
493 newIsBSS := newtyp.IsData() && !newHasContent
494 switch {
495 case newIsText && oldIsBSS,
496 newHasContent && oldIsBSS,
497 newIsBSS && oldIsBSS && sz > oldsz:
498
499 l.objSyms[oldi] = objSym{r.objidx, li}
500 if oldsz > sz {
501
502
503
504
505
506
507
508
509
510 l.sizeFixups = append(l.sizeFixups, symAndSize{oldi, uint32(oldsz)})
511 }
512 case newIsBSS:
513
514 if sz > oldsz {
515
516 l.sizeFixups = append(l.sizeFixups, symAndSize{oldi, uint32(sz)})
517 }
518 default:
519 log.Fatalf("duplicated definition of symbol %s, from %s (type %s size %d) and %s (type %s size %d)", name, r.unit.Lib.Pkg, newtyp, sz, oldr.unit.Lib.Pkg, oldtyp, oldsz)
520 }
521 return oldi
522 }
523
524
525
526 func (l *Loader) newExtSym(name string, ver int) Sym {
527 i := Sym(len(l.objSyms))
528 if int(i) != len(l.objSyms) {
529 panic("too many symbols")
530 }
531 if l.extStart == 0 {
532 l.extStart = i
533 }
534 l.growValues(int(i) + 1)
535 l.growOuter(int(i) + 1)
536 l.growAttrBitmaps(int(i) + 1)
537 pi := l.newPayload(name, ver)
538 l.objSyms = append(l.objSyms, objSym{l.extReader.objidx, uint32(pi)})
539 l.extReader.syms = append(l.extReader.syms, i)
540 return i
541 }
542
543
544
545
546 func (l *Loader) LookupOrCreateSym(name string, ver int) Sym {
547 i := l.Lookup(name, ver)
548 if i != 0 {
549 return i
550 }
551 i = l.newExtSym(name, ver)
552 static := ver >= sym.SymVerStatic || ver < 0
553 if static {
554 l.extStaticSyms[nameVer{name, ver}] = i
555 } else {
556 l.symsByName[ver][name] = i
557 }
558 return i
559 }
560
561
562
563
564 func (l *Loader) AddCgoExport(s Sym) {
565 if l.CgoExports == nil {
566 l.CgoExports = make(map[string]Sym)
567 }
568 l.CgoExports[l.SymName(s)] = s
569 }
570
571
572
573
574
575 func (l *Loader) LookupOrCreateCgoExport(name string, ver int) Sym {
576 if ver >= sym.SymVerStatic {
577 return l.LookupOrCreateSym(name, ver)
578 }
579 if ver != 0 {
580 panic("ver must be 0 or a static version")
581 }
582
583 if s, ok := l.CgoExports[name]; ok {
584 return s
585 }
586
587
588 return l.LookupOrCreateSym(name, 0)
589 }
590
591 func (l *Loader) IsExternal(i Sym) bool {
592 r, _ := l.toLocal(i)
593 return l.isExtReader(r)
594 }
595
596 func (l *Loader) isExtReader(r *oReader) bool {
597 return r == l.extReader
598 }
599
600
601
602
603 func (l *Loader) extIndex(i Sym) Sym {
604 _, li := l.toLocal(i)
605 return Sym(li)
606 }
607
608
609
610 func (l *Loader) newPayload(name string, ver int) int {
611 pi := len(l.payloads)
612 pp := l.allocPayload()
613 pp.name = name
614 pp.ver = ver
615 l.payloads = append(l.payloads, pp)
616 l.growExtAttrBitmaps()
617 return pi
618 }
619
620
621
622
623 func (l *Loader) getPayload(i Sym) *extSymPayload {
624 if !l.IsExternal(i) {
625 panic(fmt.Sprintf("bogus symbol index %d in getPayload", i))
626 }
627 pi := l.extIndex(i)
628 return l.payloads[pi]
629 }
630
631
632 func (l *Loader) allocPayload() *extSymPayload {
633 batch := l.payloadBatch
634 if len(batch) == 0 {
635 batch = make([]extSymPayload, 1000)
636 }
637 p := &batch[0]
638 l.payloadBatch = batch[1:]
639 return p
640 }
641
642 func (ms *extSymPayload) Grow(siz int64) {
643 if int64(int(siz)) != siz {
644 log.Fatalf("symgrow size %d too long", siz)
645 }
646 if int64(len(ms.data)) >= siz {
647 return
648 }
649 if cap(ms.data) < int(siz) {
650 cl := len(ms.data)
651 ms.data = append(ms.data, make([]byte, int(siz)+1-cl)...)
652 ms.data = ms.data[0:cl]
653 }
654 ms.data = ms.data[:siz]
655 }
656
657
658 func (l *Loader) toGlobal(r *oReader, i uint32) Sym {
659 return r.syms[i]
660 }
661
662
663 func (l *Loader) toLocal(i Sym) (*oReader, uint32) {
664 return l.objs[l.objSyms[i].objidx], l.objSyms[i].s
665 }
666
667
668 func (l *Loader) resolve(r *oReader, s goobj.SymRef) Sym {
669 var rr *oReader
670 switch p := s.PkgIdx; p {
671 case goobj.PkgIdxInvalid:
672
673
674
675 if l.isExtReader(r) {
676 return Sym(s.SymIdx)
677 }
678 if s.SymIdx != 0 {
679 panic("bad sym ref")
680 }
681 return 0
682 case goobj.PkgIdxHashed64:
683 i := int(s.SymIdx) + r.ndef
684 return r.syms[i]
685 case goobj.PkgIdxHashed:
686 i := int(s.SymIdx) + r.ndef + r.nhashed64def
687 return r.syms[i]
688 case goobj.PkgIdxNone:
689 i := int(s.SymIdx) + r.ndef + r.nhashed64def + r.nhasheddef
690 return r.syms[i]
691 case goobj.PkgIdxBuiltin:
692 if bi := l.builtinSyms[s.SymIdx]; bi != 0 {
693 return bi
694 }
695 l.reportMissingBuiltin(int(s.SymIdx), r.unit.Lib.Pkg)
696 return 0
697 case goobj.PkgIdxSelf:
698 rr = r
699 default:
700 rr = l.objs[r.pkg[p]]
701 }
702 return l.toGlobal(rr, s.SymIdx)
703 }
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722 func (l *Loader) reportMissingBuiltin(bsym int, reflib string) {
723 bname, _ := goobj.BuiltinName(bsym)
724 log.Fatalf("reference to undefined builtin %q from package %q",
725 bname, reflib)
726 }
727
728
729
730
731 func (l *Loader) Lookup(name string, ver int) Sym {
732 if ver >= sym.SymVerStatic || ver < 0 {
733 return l.extStaticSyms[nameVer{name, ver}]
734 }
735 return l.symsByName[ver][name]
736 }
737
738
739 func (l *Loader) checkdup(name string, r *oReader, li uint32, dup Sym) {
740 p := r.Data(li)
741 rdup, ldup := l.toLocal(dup)
742 pdup := rdup.Data(ldup)
743 reason := "same length but different contents"
744 if len(p) != len(pdup) {
745 reason = fmt.Sprintf("new length %d != old length %d", len(p), len(pdup))
746 } else if bytes.Equal(p, pdup) {
747
748 szdup := l.SymSize(dup)
749 sz := int64(r.Sym(li).Siz())
750 if szdup == sz {
751 return
752 }
753 reason = fmt.Sprintf("different sizes: new size %d != old size %d",
754 sz, szdup)
755 }
756 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)
757
758
759
760
761
762
763 allowed := strings.HasPrefix(name, "go:info.go.interface") ||
764 strings.HasPrefix(name, "go:info.go.builtin") ||
765 strings.HasPrefix(name, "go:debuglines")
766 if !allowed {
767 l.strictDupMsgs++
768 }
769 }
770
771 func (l *Loader) NStrictDupMsgs() int { return l.strictDupMsgs }
772
773
774 func (l *Loader) NSym() int {
775 return len(l.objSyms)
776 }
777
778
779 func (l *Loader) NDef() int {
780 return int(l.extStart)
781 }
782
783
784 func (l *Loader) NReachableSym() int {
785 return l.attrReachable.Count()
786 }
787
788
789 func (l *Loader) SymName(i Sym) string {
790 if l.IsExternal(i) {
791 pp := l.getPayload(i)
792 return pp.name
793 }
794 r, li := l.toLocal(i)
795 if r == nil {
796 return "?"
797 }
798 return r.Sym(li).Name(r.Reader)
799 }
800
801
802 func (l *Loader) SymVersion(i Sym) int {
803 if l.IsExternal(i) {
804 pp := l.getPayload(i)
805 return pp.ver
806 }
807 r, li := l.toLocal(i)
808 return int(abiToVer(r.Sym(li).ABI(), r.version))
809 }
810
811 func (l *Loader) IsFileLocal(i Sym) bool {
812 return l.SymVersion(i) >= sym.SymVerStatic
813 }
814
815
816
817 func (l *Loader) IsFromAssembly(i Sym) bool {
818 if l.IsExternal(i) {
819 pp := l.getPayload(i)
820 if pp.objidx != 0 {
821 r := l.objs[pp.objidx]
822 return r.FromAssembly()
823 }
824 return false
825 }
826 r, _ := l.toLocal(i)
827 return r.FromAssembly()
828 }
829
830
831 func (l *Loader) SymType(i Sym) sym.SymKind {
832 if l.IsExternal(i) {
833 pp := l.getPayload(i)
834 if pp != nil {
835 return pp.kind
836 }
837 return 0
838 }
839 r, li := l.toLocal(i)
840 return sym.AbiSymKindToSymKind[objabi.SymKind(r.Sym(li).Type())]
841 }
842
843
844 func (l *Loader) SymAttr(i Sym) uint8 {
845 if l.IsExternal(i) {
846
847
848
849 return 0
850 }
851 r, li := l.toLocal(i)
852 return r.Sym(li).Flag()
853 }
854
855
856 func (l *Loader) SymSize(i Sym) int64 {
857 if l.IsExternal(i) {
858 pp := l.getPayload(i)
859 return pp.size
860 }
861 r, li := l.toLocal(i)
862 return int64(r.Sym(li).Siz())
863 }
864
865
866
867
868 func (l *Loader) AttrReachable(i Sym) bool {
869 return l.attrReachable.Has(i)
870 }
871
872
873
874 func (l *Loader) SetAttrReachable(i Sym, v bool) {
875 if v {
876 l.attrReachable.Set(i)
877 } else {
878 l.attrReachable.Unset(i)
879 }
880 }
881
882
883
884
885
886 func (l *Loader) AttrOnList(i Sym) bool {
887 return l.attrOnList.Has(i)
888 }
889
890
891
892 func (l *Loader) SetAttrOnList(i Sym, v bool) {
893 if v {
894 l.attrOnList.Set(i)
895 } else {
896 l.attrOnList.Unset(i)
897 }
898 }
899
900
901
902
903 func (l *Loader) AttrLocal(i Sym) bool {
904 return l.attrLocal.Has(i)
905 }
906
907
908 func (l *Loader) SetAttrLocal(i Sym, v bool) {
909 if v {
910 l.attrLocal.Set(i)
911 } else {
912 l.attrLocal.Unset(i)
913 }
914 }
915
916
917
918 func (l *Loader) AttrUsedInIface(i Sym) bool {
919 return l.attrUsedInIface.Has(i)
920 }
921
922 func (l *Loader) SetAttrUsedInIface(i Sym, v bool) {
923 if v {
924 l.attrUsedInIface.Set(i)
925 } else {
926 l.attrUsedInIface.Unset(i)
927 }
928 }
929
930
931 func (l *Loader) SymAddr(i Sym) int64 {
932 if !l.AttrReachable(i) {
933 panic("unreachable symbol in symaddr")
934 }
935 return l.values[i]
936 }
937
938
939
940 func (l *Loader) AttrNotInSymbolTable(i Sym) bool {
941 return l.attrNotInSymbolTable.Has(i)
942 }
943
944
945
946 func (l *Loader) SetAttrNotInSymbolTable(i Sym, v bool) {
947 if v {
948 l.attrNotInSymbolTable.Set(i)
949 } else {
950 l.attrNotInSymbolTable.Unset(i)
951 }
952 }
953
954
955
956
957
958 func (l *Loader) AttrVisibilityHidden(i Sym) bool {
959 if !l.IsExternal(i) {
960 return false
961 }
962 return l.attrVisibilityHidden.Has(l.extIndex(i))
963 }
964
965
966
967 func (l *Loader) SetAttrVisibilityHidden(i Sym, v bool) {
968 if !l.IsExternal(i) {
969 panic("tried to set visibility attr on non-external symbol")
970 }
971 if v {
972 l.attrVisibilityHidden.Set(l.extIndex(i))
973 } else {
974 l.attrVisibilityHidden.Unset(l.extIndex(i))
975 }
976 }
977
978
979
980 func (l *Loader) AttrDuplicateOK(i Sym) bool {
981 if !l.IsExternal(i) {
982
983
984
985 r, li := l.toLocal(i)
986 return r.Sym(li).Dupok()
987 }
988 return l.attrDuplicateOK.Has(l.extIndex(i))
989 }
990
991
992
993 func (l *Loader) SetAttrDuplicateOK(i Sym, v bool) {
994 if !l.IsExternal(i) {
995 panic("tried to set dupok attr on non-external symbol")
996 }
997 if v {
998 l.attrDuplicateOK.Set(l.extIndex(i))
999 } else {
1000 l.attrDuplicateOK.Unset(l.extIndex(i))
1001 }
1002 }
1003
1004
1005 func (l *Loader) AttrShared(i Sym) bool {
1006 if !l.IsExternal(i) {
1007
1008
1009
1010 r, _ := l.toLocal(i)
1011 return r.Shared()
1012 }
1013 return l.attrShared.Has(l.extIndex(i))
1014 }
1015
1016
1017
1018 func (l *Loader) SetAttrShared(i Sym, v bool) {
1019 if !l.IsExternal(i) {
1020 panic(fmt.Sprintf("tried to set shared attr on non-external symbol %d %s", i, l.SymName(i)))
1021 }
1022 if v {
1023 l.attrShared.Set(l.extIndex(i))
1024 } else {
1025 l.attrShared.Unset(l.extIndex(i))
1026 }
1027 }
1028
1029
1030
1031 func (l *Loader) AttrExternal(i Sym) bool {
1032 if !l.IsExternal(i) {
1033 return false
1034 }
1035 return l.attrExternal.Has(l.extIndex(i))
1036 }
1037
1038
1039
1040 func (l *Loader) SetAttrExternal(i Sym, v bool) {
1041 if !l.IsExternal(i) {
1042 panic(fmt.Sprintf("tried to set external attr on non-external symbol %q", l.SymName(i)))
1043 }
1044 if v {
1045 l.attrExternal.Set(l.extIndex(i))
1046 } else {
1047 l.attrExternal.Unset(l.extIndex(i))
1048 }
1049 }
1050
1051
1052
1053
1054 func (l *Loader) AttrSpecial(i Sym) bool {
1055 return l.attrSpecial.Has(i)
1056 }
1057
1058
1059
1060 func (l *Loader) SetAttrSpecial(i Sym, v bool) {
1061 if v {
1062 l.attrSpecial.Set(i)
1063 } else {
1064 l.attrSpecial.Unset(i)
1065 }
1066 }
1067
1068
1069
1070
1071 func (l *Loader) AttrCgoExportDynamic(i Sym) bool {
1072 _, ok := l.attrCgoExportDynamic[i]
1073 return ok
1074 }
1075
1076
1077
1078 func (l *Loader) SetAttrCgoExportDynamic(i Sym, v bool) {
1079 if v {
1080 l.attrCgoExportDynamic[i] = struct{}{}
1081 } else {
1082 delete(l.attrCgoExportDynamic, i)
1083 }
1084 }
1085
1086
1087
1088 func (l *Loader) ForAllCgoExportDynamic(f func(Sym)) {
1089 for s := range l.attrCgoExportDynamic {
1090 f(s)
1091 }
1092 }
1093
1094
1095
1096
1097 func (l *Loader) AttrCgoExportStatic(i Sym) bool {
1098 _, ok := l.attrCgoExportStatic[i]
1099 return ok
1100 }
1101
1102
1103
1104 func (l *Loader) SetAttrCgoExportStatic(i Sym, v bool) {
1105 if v {
1106 l.attrCgoExportStatic[i] = struct{}{}
1107 } else {
1108 delete(l.attrCgoExportStatic, i)
1109 }
1110 }
1111
1112
1113
1114
1115 func (l *Loader) IsGeneratedSym(i Sym) bool {
1116 if !l.IsExternal(i) {
1117 return false
1118 }
1119 return l.generatedSyms.Has(l.extIndex(i))
1120 }
1121
1122
1123
1124
1125 func (l *Loader) SetIsGeneratedSym(i Sym, v bool) {
1126 if !l.IsExternal(i) {
1127 panic("only external symbols can be generated")
1128 }
1129 if v {
1130 l.generatedSyms.Set(l.extIndex(i))
1131 } else {
1132 l.generatedSyms.Unset(l.extIndex(i))
1133 }
1134 }
1135
1136 func (l *Loader) AttrCgoExport(i Sym) bool {
1137 return l.AttrCgoExportDynamic(i) || l.AttrCgoExportStatic(i)
1138 }
1139
1140
1141
1142 func (l *Loader) AttrReadOnly(i Sym) bool {
1143 if v, ok := l.attrReadOnly[i]; ok {
1144 return v
1145 }
1146 if l.IsExternal(i) {
1147 pp := l.getPayload(i)
1148 if pp.objidx != 0 {
1149 return l.objs[pp.objidx].ReadOnly()
1150 }
1151 return false
1152 }
1153 r, _ := l.toLocal(i)
1154 return r.ReadOnly()
1155 }
1156
1157
1158
1159 func (l *Loader) SetAttrReadOnly(i Sym, v bool) {
1160 l.attrReadOnly[i] = v
1161 }
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185 func (l *Loader) AttrSubSymbol(i Sym) bool {
1186
1187
1188 o := l.OuterSym(i)
1189 if o == 0 {
1190 return false
1191 }
1192 return l.SubSym(o) != 0
1193 }
1194
1195
1196
1197
1198
1199
1200 func (l *Loader) IsReflectMethod(i Sym) bool {
1201 return l.SymAttr(i)&goobj.SymFlagReflectMethod != 0
1202 }
1203
1204
1205 func (l *Loader) IsNoSplit(i Sym) bool {
1206 return l.SymAttr(i)&goobj.SymFlagNoSplit != 0
1207 }
1208
1209
1210 func (l *Loader) IsGoType(i Sym) bool {
1211 return l.SymAttr(i)&goobj.SymFlagGoType != 0
1212 }
1213
1214
1215 func (l *Loader) IsTypelink(i Sym) bool {
1216 return l.SymAttr(i)&goobj.SymFlagTypelink != 0
1217 }
1218
1219
1220 func (l *Loader) IsItab(i Sym) bool {
1221 if l.IsExternal(i) {
1222 return false
1223 }
1224 r, li := l.toLocal(i)
1225 return r.Sym(li).IsItab()
1226 }
1227
1228
1229 func (l *Loader) IsDict(i Sym) bool {
1230 if l.IsExternal(i) {
1231 return false
1232 }
1233 r, li := l.toLocal(i)
1234 return r.Sym(li).IsDict()
1235 }
1236
1237
1238 func (l *Loader) IsPkgInit(i Sym) bool {
1239 if l.IsExternal(i) {
1240 return false
1241 }
1242 r, li := l.toLocal(i)
1243 return r.Sym(li).IsPkgInit()
1244 }
1245
1246
1247 func (l *Loader) IsDeferReturnTramp(i Sym) bool {
1248 return l.deferReturnTramp[i]
1249 }
1250
1251
1252 func (l *Loader) SetIsDeferReturnTramp(i Sym, v bool) {
1253 l.deferReturnTramp[i] = v
1254 }
1255
1256
1257 func (l *Loader) growValues(reqLen int) {
1258 curLen := len(l.values)
1259 if reqLen > curLen {
1260 l.values = append(l.values, make([]int64, reqLen+1-curLen)...)
1261 }
1262 }
1263
1264
1265 func (l *Loader) SymValue(i Sym) int64 {
1266 return l.values[i]
1267 }
1268
1269
1270 func (l *Loader) SetSymValue(i Sym, val int64) {
1271 l.values[i] = val
1272 }
1273
1274
1275 func (l *Loader) AddToSymValue(i Sym, val int64) {
1276 l.values[i] += val
1277 }
1278
1279
1280 func (l *Loader) Data(i Sym) []byte {
1281 if l.IsExternal(i) {
1282 pp := l.getPayload(i)
1283 if pp != nil {
1284 return pp.data
1285 }
1286 return nil
1287 }
1288 r, li := l.toLocal(i)
1289 return r.Data(li)
1290 }
1291
1292
1293 func (l *Loader) DataString(i Sym) string {
1294 if l.IsExternal(i) {
1295 pp := l.getPayload(i)
1296 return string(pp.data)
1297 }
1298 r, li := l.toLocal(i)
1299 return r.DataString(li)
1300 }
1301
1302
1303
1304
1305 func (l *Loader) FreeData(i Sym) {
1306 if l.IsExternal(i) {
1307 pp := l.getPayload(i)
1308 if pp != nil {
1309 pp.data = nil
1310 }
1311 }
1312 }
1313
1314
1315 func (l *Loader) SymAlign(i Sym) int32 {
1316 if int(i) >= len(l.align) {
1317
1318
1319
1320 return 0
1321 }
1322
1323
1324
1325 abits := l.align[i]
1326 if abits == 0 {
1327 return 0
1328 }
1329 return int32(1 << (abits - 1))
1330 }
1331
1332
1333 func (l *Loader) SetSymAlign(i Sym, align int32) {
1334
1335 if align < 0 || align&(align-1) != 0 {
1336 panic("bad alignment value")
1337 }
1338 if int(i) >= len(l.align) {
1339 l.align = append(l.align, make([]uint8, l.NSym()-len(l.align))...)
1340 }
1341 if align == 0 {
1342 l.align[i] = 0
1343 }
1344 l.align[i] = uint8(bits.Len32(uint32(align)))
1345 }
1346
1347
1348 func (l *Loader) SymSect(i Sym) *sym.Section {
1349 if int(i) >= len(l.symSects) {
1350
1351
1352
1353 return nil
1354 }
1355 return l.sects[l.symSects[i]]
1356 }
1357
1358
1359 func (l *Loader) SetSymSect(i Sym, sect *sym.Section) {
1360 if int(i) >= len(l.symSects) {
1361 l.symSects = append(l.symSects, make([]uint16, l.NSym()-len(l.symSects))...)
1362 }
1363 l.symSects[i] = sect.Index
1364 }
1365
1366
1367 func (l *Loader) NewSection() *sym.Section {
1368 sect := new(sym.Section)
1369 idx := len(l.sects)
1370 if idx != int(uint16(idx)) {
1371 panic("too many sections created")
1372 }
1373 sect.Index = uint16(idx)
1374 l.sects = append(l.sects, sect)
1375 return sect
1376 }
1377
1378
1379
1380
1381 func (l *Loader) SymDynimplib(i Sym) string {
1382 return l.dynimplib[i]
1383 }
1384
1385
1386 func (l *Loader) SetSymDynimplib(i Sym, value string) {
1387
1388 if i >= Sym(len(l.objSyms)) || i == 0 {
1389 panic("bad symbol index in SetDynimplib")
1390 }
1391 if value == "" {
1392 delete(l.dynimplib, i)
1393 } else {
1394 l.dynimplib[i] = value
1395 }
1396 }
1397
1398
1399
1400
1401 func (l *Loader) SymDynimpvers(i Sym) string {
1402 return l.dynimpvers[i]
1403 }
1404
1405
1406 func (l *Loader) SetSymDynimpvers(i Sym, value string) {
1407
1408 if i >= Sym(len(l.objSyms)) || i == 0 {
1409 panic("bad symbol index in SetDynimpvers")
1410 }
1411 if value == "" {
1412 delete(l.dynimpvers, i)
1413 } else {
1414 l.dynimpvers[i] = value
1415 }
1416 }
1417
1418
1419
1420 func (l *Loader) SymExtname(i Sym) string {
1421 if s, ok := l.extname[i]; ok {
1422 return s
1423 }
1424 return l.SymName(i)
1425 }
1426
1427
1428 func (l *Loader) SetSymExtname(i Sym, value string) {
1429
1430 if i >= Sym(len(l.objSyms)) || i == 0 {
1431 panic("bad symbol index in SetExtname")
1432 }
1433 if value == "" {
1434 delete(l.extname, i)
1435 } else {
1436 l.extname[i] = value
1437 }
1438 }
1439
1440
1441
1442
1443
1444 func (l *Loader) SymElfType(i Sym) elf.SymType {
1445 if et, ok := l.elfType[i]; ok {
1446 return et
1447 }
1448 return elf.STT_NOTYPE
1449 }
1450
1451
1452 func (l *Loader) SetSymElfType(i Sym, et elf.SymType) {
1453
1454 if i >= Sym(len(l.objSyms)) || i == 0 {
1455 panic("bad symbol index in SetSymElfType")
1456 }
1457 if et == elf.STT_NOTYPE {
1458 delete(l.elfType, i)
1459 } else {
1460 l.elfType[i] = et
1461 }
1462 }
1463
1464
1465
1466 func (l *Loader) SymElfSym(i Sym) int32 {
1467 return l.elfSym[i]
1468 }
1469
1470
1471 func (l *Loader) SetSymElfSym(i Sym, es int32) {
1472 if i == 0 {
1473 panic("bad sym index")
1474 }
1475 if es == 0 {
1476 delete(l.elfSym, i)
1477 } else {
1478 l.elfSym[i] = es
1479 }
1480 }
1481
1482
1483
1484 func (l *Loader) SymLocalElfSym(i Sym) int32 {
1485 return l.localElfSym[i]
1486 }
1487
1488
1489 func (l *Loader) SetSymLocalElfSym(i Sym, es int32) {
1490 if i == 0 {
1491 panic("bad sym index")
1492 }
1493 if es == 0 {
1494 delete(l.localElfSym, i)
1495 } else {
1496 l.localElfSym[i] = es
1497 }
1498 }
1499
1500
1501 func (l *Loader) SymPlt(s Sym) int32 {
1502 if v, ok := l.plt[s]; ok {
1503 return v
1504 }
1505 return -1
1506 }
1507
1508
1509 func (l *Loader) SetPlt(i Sym, v int32) {
1510 if i >= Sym(len(l.objSyms)) || i == 0 {
1511 panic("bad symbol for SetPlt")
1512 }
1513 if v == -1 {
1514 delete(l.plt, i)
1515 } else {
1516 l.plt[i] = v
1517 }
1518 }
1519
1520
1521 func (l *Loader) SymGot(s Sym) int32 {
1522 if v, ok := l.got[s]; ok {
1523 return v
1524 }
1525 return -1
1526 }
1527
1528
1529 func (l *Loader) SetGot(i Sym, v int32) {
1530 if i >= Sym(len(l.objSyms)) || i == 0 {
1531 panic("bad symbol for SetGot")
1532 }
1533 if v == -1 {
1534 delete(l.got, i)
1535 } else {
1536 l.got[i] = v
1537 }
1538 }
1539
1540
1541 func (l *Loader) SymDynid(i Sym) int32 {
1542 if s, ok := l.dynid[i]; ok {
1543 return s
1544 }
1545 return -1
1546 }
1547
1548
1549 func (l *Loader) SetSymDynid(i Sym, val int32) {
1550
1551 if i >= Sym(len(l.objSyms)) || i == 0 {
1552 panic("bad symbol index in SetSymDynid")
1553 }
1554 if val == -1 {
1555 delete(l.dynid, i)
1556 } else {
1557 l.dynid[i] = val
1558 }
1559 }
1560
1561
1562
1563
1564 func (l *Loader) DynidSyms() []Sym {
1565 sl := make([]Sym, 0, len(l.dynid))
1566 for s := range l.dynid {
1567 sl = append(sl, s)
1568 }
1569 sort.Slice(sl, func(i, j int) bool { return sl[i] < sl[j] })
1570 return sl
1571 }
1572
1573
1574
1575
1576
1577
1578
1579 func (l *Loader) SymGoType(i Sym) Sym { return l.aux1(i, goobj.AuxGotype) }
1580
1581
1582
1583 func (l *Loader) SymUnit(i Sym) *sym.CompilationUnit {
1584 if l.IsExternal(i) {
1585 pp := l.getPayload(i)
1586 if pp.objidx != 0 {
1587 r := l.objs[pp.objidx]
1588 return r.unit
1589 }
1590 return nil
1591 }
1592 r, _ := l.toLocal(i)
1593 return r.unit
1594 }
1595
1596
1597
1598
1599
1600
1601 func (l *Loader) SymPkg(i Sym) string {
1602 if f, ok := l.symPkg[i]; ok {
1603 return f
1604 }
1605 if l.IsExternal(i) {
1606 pp := l.getPayload(i)
1607 if pp.objidx != 0 {
1608 r := l.objs[pp.objidx]
1609 return r.unit.Lib.Pkg
1610 }
1611 return ""
1612 }
1613 r, _ := l.toLocal(i)
1614 return r.unit.Lib.Pkg
1615 }
1616
1617
1618
1619
1620 func (l *Loader) SetSymPkg(i Sym, pkg string) {
1621
1622 if i >= Sym(len(l.objSyms)) || i == 0 {
1623 panic("bad symbol index in SetSymPkg")
1624 }
1625 l.symPkg[i] = pkg
1626 }
1627
1628
1629
1630
1631
1632 func (l *Loader) SymLocalentry(i Sym) uint8 {
1633 return l.localentry[i]
1634 }
1635
1636
1637 func (l *Loader) SetSymLocalentry(i Sym, value uint8) {
1638
1639 if i >= Sym(len(l.objSyms)) || i == 0 {
1640 panic("bad symbol index in SetSymLocalentry")
1641 }
1642 if value == 0 {
1643 delete(l.localentry, i)
1644 } else {
1645 l.localentry[i] = value
1646 }
1647 }
1648
1649
1650 func (l *Loader) NAux(i Sym) int {
1651 if l.IsExternal(i) {
1652 return 0
1653 }
1654 r, li := l.toLocal(i)
1655 return r.NAux(li)
1656 }
1657
1658
1659 func (l *Loader) Aux(i Sym, j int) Aux {
1660 if l.IsExternal(i) {
1661 return Aux{}
1662 }
1663 r, li := l.toLocal(i)
1664 if j >= r.NAux(li) {
1665 return Aux{}
1666 }
1667 return Aux{r.Aux(li, j), r, l}
1668 }
1669
1670
1671
1672
1673
1674
1675
1676 func (l *Loader) WasmImportSym(fnSymIdx Sym) Sym {
1677 if !l.SymType(fnSymIdx).IsText() {
1678 log.Fatalf("error: non-function sym %d/%s t=%s passed to WasmImportSym", fnSymIdx, l.SymName(fnSymIdx), l.SymType(fnSymIdx).String())
1679 }
1680 return l.aux1(fnSymIdx, goobj.AuxWasmImport)
1681 }
1682
1683 func (l *Loader) WasmTypeSym(s Sym) Sym {
1684 return l.aux1(s, goobj.AuxWasmType)
1685 }
1686
1687
1688
1689 func (l *Loader) SEHUnwindSym(fnSymIdx Sym) Sym {
1690 if !l.SymType(fnSymIdx).IsText() {
1691 log.Fatalf("error: non-function sym %d/%s t=%s passed to SEHUnwindSym", fnSymIdx, l.SymName(fnSymIdx), l.SymType(fnSymIdx).String())
1692 }
1693
1694 return l.aux1(fnSymIdx, goobj.AuxSehUnwindInfo)
1695 }
1696
1697
1698
1699
1700
1701
1702 func (l *Loader) GetFuncDwarfAuxSyms(fnSymIdx Sym) (auxDwarfInfo, auxDwarfLoc, auxDwarfRanges, auxDwarfLines Sym) {
1703 if !l.SymType(fnSymIdx).IsText() {
1704 log.Fatalf("error: non-function sym %d/%s t=%s passed to GetFuncDwarfAuxSyms", fnSymIdx, l.SymName(fnSymIdx), l.SymType(fnSymIdx).String())
1705 }
1706 r, auxs := l.auxs(fnSymIdx)
1707
1708 for i := range auxs {
1709 a := &auxs[i]
1710 switch a.Type() {
1711 case goobj.AuxDwarfInfo:
1712 auxDwarfInfo = l.resolve(r, a.Sym())
1713 if l.SymType(auxDwarfInfo) != sym.SDWARFFCN {
1714 panic("aux dwarf info sym with wrong type")
1715 }
1716 case goobj.AuxDwarfLoc:
1717 auxDwarfLoc = l.resolve(r, a.Sym())
1718 if l.SymType(auxDwarfLoc) != sym.SDWARFLOC {
1719 panic("aux dwarf loc sym with wrong type")
1720 }
1721 case goobj.AuxDwarfRanges:
1722 auxDwarfRanges = l.resolve(r, a.Sym())
1723 if l.SymType(auxDwarfRanges) != sym.SDWARFRANGE {
1724 panic("aux dwarf ranges sym with wrong type")
1725 }
1726 case goobj.AuxDwarfLines:
1727 auxDwarfLines = l.resolve(r, a.Sym())
1728 if l.SymType(auxDwarfLines) != sym.SDWARFLINES {
1729 panic("aux dwarf lines sym with wrong type")
1730 }
1731 }
1732 }
1733 return
1734 }
1735
1736 func (l *Loader) GetVarDwarfAuxSym(i Sym) Sym {
1737 aux := l.aux1(i, goobj.AuxDwarfInfo)
1738 if aux != 0 && l.SymType(aux) != sym.SDWARFVAR {
1739 fmt.Println(l.SymName(i), l.SymType(i), l.SymType(aux), sym.SDWARFVAR)
1740 panic("aux dwarf info sym with wrong type")
1741 }
1742 return aux
1743 }
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759 func (l *Loader) AddInteriorSym(container Sym, interior Sym) {
1760
1761
1762 if len(l.Data(interior)) != 0 {
1763 panic("unexpected non-empty interior symbol")
1764 }
1765
1766 if l.AttrNotInSymbolTable(interior) {
1767 panic("interior symbol must be in symtab")
1768 }
1769
1770 if l.OuterSym(container) != 0 {
1771 panic("outer has outer itself")
1772 }
1773
1774 if l.SubSym(interior) != 0 {
1775 panic("sub set for subsym")
1776 }
1777
1778 if l.OuterSym(interior) != 0 {
1779 panic("outer already set for subsym")
1780 }
1781 l.sub[interior] = l.sub[container]
1782 l.sub[container] = interior
1783 l.outer[interior] = container
1784 }
1785
1786
1787 func (l *Loader) OuterSym(i Sym) Sym {
1788 return l.outer[i]
1789 }
1790
1791
1792 func (l *Loader) SubSym(i Sym) Sym {
1793 return l.sub[i]
1794 }
1795
1796
1797 func (l *Loader) growOuter(reqLen int) {
1798 curLen := len(l.outer)
1799 if reqLen > curLen {
1800 l.outer = append(l.outer, make([]Sym, reqLen-curLen)...)
1801 }
1802 }
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815 func (l *Loader) SetCarrierSym(s Sym, c Sym) {
1816 if c == 0 {
1817 panic("invalid carrier in SetCarrierSym")
1818 }
1819 if s == 0 {
1820 panic("invalid sub-symbol in SetCarrierSym")
1821 }
1822
1823
1824
1825 if len(l.Data(c)) != 0 {
1826 panic("unexpected non-empty carrier symbol")
1827 }
1828 l.outer[s] = c
1829
1830
1831 if l.outer[c] != 0 {
1832 panic("invalid nested carrier sym")
1833 }
1834 }
1835
1836
1837 func (l *Loader) InitReachable() {
1838 l.growAttrBitmaps(l.NSym() + 1)
1839 }
1840
1841 type symWithVal struct {
1842 s Sym
1843 v int64
1844 }
1845 type bySymValue []symWithVal
1846
1847 func (s bySymValue) Len() int { return len(s) }
1848 func (s bySymValue) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
1849 func (s bySymValue) Less(i, j int) bool { return s[i].v < s[j].v }
1850
1851
1852
1853
1854 func (l *Loader) SortSub(s Sym) Sym {
1855
1856 if s == 0 || l.sub[s] == 0 {
1857 return s
1858 }
1859
1860
1861
1862
1863 sl := []symWithVal{}
1864 for ss := l.sub[s]; ss != 0; ss = l.sub[ss] {
1865 sl = append(sl, symWithVal{s: ss, v: l.SymValue(ss)})
1866 }
1867 sort.Stable(bySymValue(sl))
1868
1869
1870 ns := Sym(0)
1871 for i := len(sl) - 1; i >= 0; i-- {
1872 s := sl[i].s
1873 l.sub[s] = ns
1874 ns = s
1875 }
1876
1877
1878 l.sub[s] = sl[0].s
1879 return sl[0].s
1880 }
1881
1882
1883 func (l *Loader) SortSyms(ss []Sym) {
1884 sort.SliceStable(ss, func(i, j int) bool { return l.SymValue(ss[i]) < l.SymValue(ss[j]) })
1885 }
1886
1887
1888 func (l *Loader) growAttrBitmaps(reqLen int) {
1889 if reqLen > l.attrReachable.Len() {
1890
1891 l.attrReachable = growBitmap(reqLen, l.attrReachable)
1892 l.attrOnList = growBitmap(reqLen, l.attrOnList)
1893 l.attrLocal = growBitmap(reqLen, l.attrLocal)
1894 l.attrNotInSymbolTable = growBitmap(reqLen, l.attrNotInSymbolTable)
1895 l.attrUsedInIface = growBitmap(reqLen, l.attrUsedInIface)
1896 l.attrSpecial = growBitmap(reqLen, l.attrSpecial)
1897 }
1898 l.growExtAttrBitmaps()
1899 }
1900
1901 func (l *Loader) growExtAttrBitmaps() {
1902
1903 extReqLen := len(l.payloads)
1904 if extReqLen > l.attrVisibilityHidden.Len() {
1905 l.attrVisibilityHidden = growBitmap(extReqLen, l.attrVisibilityHidden)
1906 l.attrDuplicateOK = growBitmap(extReqLen, l.attrDuplicateOK)
1907 l.attrShared = growBitmap(extReqLen, l.attrShared)
1908 l.attrExternal = growBitmap(extReqLen, l.attrExternal)
1909 l.generatedSyms = growBitmap(extReqLen, l.generatedSyms)
1910 }
1911 }
1912
1913 func (relocs *Relocs) Count() int { return len(relocs.rs) }
1914
1915
1916 func (relocs *Relocs) At(j int) Reloc {
1917 if relocs.l.isExtReader(relocs.r) {
1918 return Reloc{&relocs.rs[j], relocs.r, relocs.l}
1919 }
1920 return Reloc{&relocs.rs[j], relocs.r, relocs.l}
1921 }
1922
1923
1924 func (l *Loader) Relocs(i Sym) Relocs {
1925 r, li := l.toLocal(i)
1926 if r == nil {
1927 panic(fmt.Sprintf("trying to get oreader for invalid sym %d\n\n", i))
1928 }
1929 return l.relocs(r, li)
1930 }
1931
1932
1933 func (l *Loader) relocs(r *oReader, li uint32) Relocs {
1934 var rs []goobj.Reloc
1935 if l.isExtReader(r) {
1936 pp := l.payloads[li]
1937 rs = pp.relocs
1938 } else {
1939 rs = r.Relocs(li)
1940 }
1941 return Relocs{
1942 rs: rs,
1943 li: li,
1944 r: r,
1945 l: l,
1946 }
1947 }
1948
1949 func (l *Loader) auxs(i Sym) (*oReader, []goobj.Aux) {
1950 if l.IsExternal(i) {
1951 pp := l.getPayload(i)
1952 return l.objs[pp.objidx], pp.auxs
1953 } else {
1954 r, li := l.toLocal(i)
1955 return r, r.Auxs(li)
1956 }
1957 }
1958
1959
1960 func (l *Loader) aux1(i Sym, t uint8) Sym {
1961 r, auxs := l.auxs(i)
1962 for j := range auxs {
1963 a := &auxs[j]
1964 if a.Type() == t {
1965 return l.resolve(r, a.Sym())
1966 }
1967 }
1968 return 0
1969 }
1970
1971 func (l *Loader) Pcsp(i Sym) Sym { return l.aux1(i, goobj.AuxPcsp) }
1972
1973
1974
1975 func (l *Loader) PcdataAuxs(i Sym, tmp []Sym) (pcsp, pcfile, pcline, pcinline Sym, pcdata []Sym) {
1976 pcdata = tmp[:0]
1977 r, auxs := l.auxs(i)
1978 for j := range auxs {
1979 a := &auxs[j]
1980 switch a.Type() {
1981 case goobj.AuxPcsp:
1982 pcsp = l.resolve(r, a.Sym())
1983 case goobj.AuxPcline:
1984 pcline = l.resolve(r, a.Sym())
1985 case goobj.AuxPcfile:
1986 pcfile = l.resolve(r, a.Sym())
1987 case goobj.AuxPcinline:
1988 pcinline = l.resolve(r, a.Sym())
1989 case goobj.AuxPcdata:
1990 pcdata = append(pcdata, l.resolve(r, a.Sym()))
1991 }
1992 }
1993 return
1994 }
1995
1996
1997 func (l *Loader) NumPcdata(i Sym) int {
1998 n := 0
1999 _, auxs := l.auxs(i)
2000 for j := range auxs {
2001 a := &auxs[j]
2002 if a.Type() == goobj.AuxPcdata {
2003 n++
2004 }
2005 }
2006 return n
2007 }
2008
2009
2010
2011 func (l *Loader) Funcdata(i Sym, tmp []Sym) []Sym {
2012 fd := tmp[:0]
2013 r, auxs := l.auxs(i)
2014 for j := range auxs {
2015 a := &auxs[j]
2016 if a.Type() == goobj.AuxFuncdata {
2017 fd = append(fd, l.resolve(r, a.Sym()))
2018 }
2019 }
2020 return fd
2021 }
2022
2023
2024 func (l *Loader) NumFuncdata(i Sym) int {
2025 n := 0
2026 _, auxs := l.auxs(i)
2027 for j := range auxs {
2028 a := &auxs[j]
2029 if a.Type() == goobj.AuxFuncdata {
2030 n++
2031 }
2032 }
2033 return n
2034 }
2035
2036
2037 type FuncInfo struct {
2038 l *Loader
2039 r *oReader
2040 data []byte
2041 lengths goobj.FuncInfoLengths
2042 }
2043
2044 func (fi *FuncInfo) Valid() bool { return fi.r != nil }
2045
2046 func (fi *FuncInfo) Args() int {
2047 return int((*goobj.FuncInfo)(nil).ReadArgs(fi.data))
2048 }
2049
2050 func (fi *FuncInfo) Locals() int {
2051 return int((*goobj.FuncInfo)(nil).ReadLocals(fi.data))
2052 }
2053
2054 func (fi *FuncInfo) FuncID() abi.FuncID {
2055 return (*goobj.FuncInfo)(nil).ReadFuncID(fi.data)
2056 }
2057
2058 func (fi *FuncInfo) FuncFlag() abi.FuncFlag {
2059 return (*goobj.FuncInfo)(nil).ReadFuncFlag(fi.data)
2060 }
2061
2062 func (fi *FuncInfo) StartLine() int32 {
2063 return (*goobj.FuncInfo)(nil).ReadStartLine(fi.data)
2064 }
2065
2066
2067
2068 func (fi *FuncInfo) Preload() {
2069 fi.lengths = (*goobj.FuncInfo)(nil).ReadFuncInfoLengths(fi.data)
2070 }
2071
2072 func (fi *FuncInfo) NumFile() uint32 {
2073 if !fi.lengths.Initialized {
2074 panic("need to call Preload first")
2075 }
2076 return fi.lengths.NumFile
2077 }
2078
2079 func (fi *FuncInfo) File(k int) goobj.CUFileIndex {
2080 if !fi.lengths.Initialized {
2081 panic("need to call Preload first")
2082 }
2083 return (*goobj.FuncInfo)(nil).ReadFile(fi.data, fi.lengths.FileOff, uint32(k))
2084 }
2085
2086
2087
2088
2089 func (fi *FuncInfo) TopFrame() bool {
2090 return (fi.FuncFlag() & abi.FuncFlagTopFrame) != 0
2091 }
2092
2093 type InlTreeNode struct {
2094 Parent int32
2095 File goobj.CUFileIndex
2096 Line int32
2097 Func Sym
2098 ParentPC int32
2099 }
2100
2101 func (fi *FuncInfo) NumInlTree() uint32 {
2102 if !fi.lengths.Initialized {
2103 panic("need to call Preload first")
2104 }
2105 return fi.lengths.NumInlTree
2106 }
2107
2108 func (fi *FuncInfo) InlTree(k int) InlTreeNode {
2109 if !fi.lengths.Initialized {
2110 panic("need to call Preload first")
2111 }
2112 node := (*goobj.FuncInfo)(nil).ReadInlTree(fi.data, fi.lengths.InlTreeOff, uint32(k))
2113 return InlTreeNode{
2114 Parent: node.Parent,
2115 File: node.File,
2116 Line: node.Line,
2117 Func: fi.l.resolve(fi.r, node.Func),
2118 ParentPC: node.ParentPC,
2119 }
2120 }
2121
2122 func (l *Loader) FuncInfo(i Sym) FuncInfo {
2123 r, auxs := l.auxs(i)
2124 for j := range auxs {
2125 a := &auxs[j]
2126 if a.Type() == goobj.AuxFuncInfo {
2127 b := r.Data(a.Sym().SymIdx)
2128 return FuncInfo{l, r, b, goobj.FuncInfoLengths{}}
2129 }
2130 }
2131 return FuncInfo{}
2132 }
2133
2134
2135
2136
2137
2138
2139 func (l *Loader) Preload(localSymVersion int, f *bio.Reader, lib *sym.Library, unit *sym.CompilationUnit, length int64) goobj.FingerprintType {
2140 roObject, readonly, err := f.Slice(uint64(length))
2141 if err != nil {
2142 log.Fatal("cannot read object file:", err)
2143 }
2144 r := goobj.NewReaderFromBytes(roObject, readonly)
2145 if r == nil {
2146 if len(roObject) >= 8 && bytes.Equal(roObject[:8], []byte("\x00go114ld")) {
2147 log.Fatalf("found object file %s in old format", f.File().Name())
2148 }
2149 panic("cannot read object file")
2150 }
2151 pkgprefix := objabi.PathToPrefix(lib.Pkg) + "."
2152 ndef := r.NSym()
2153 nhashed64def := r.NHashed64def()
2154 nhasheddef := r.NHasheddef()
2155 or := &oReader{
2156 Reader: r,
2157 unit: unit,
2158 version: localSymVersion,
2159 pkgprefix: pkgprefix,
2160 syms: make([]Sym, ndef+nhashed64def+nhasheddef+r.NNonpkgdef()+r.NNonpkgref()),
2161 ndef: ndef,
2162 nhasheddef: nhasheddef,
2163 nhashed64def: nhashed64def,
2164 objidx: uint32(len(l.objs)),
2165 }
2166
2167 if r.Unlinkable() {
2168 log.Fatalf("link: unlinkable object (from package %s) - compiler requires -p flag", lib.Pkg)
2169 }
2170
2171
2172 lib.Autolib = append(lib.Autolib, r.Autolib()...)
2173
2174
2175 nfile := r.NFile()
2176 unit.FileTable = make([]string, nfile)
2177 for i := range unit.FileTable {
2178 unit.FileTable[i] = r.File(i)
2179 }
2180
2181 l.addObj(lib.Pkg, or)
2182
2183
2184 f.MustSeek(length, io.SeekCurrent)
2185
2186 return r.Fingerprint()
2187 }
2188
2189
2190 type loadState struct {
2191 l *Loader
2192 hashed64Syms map[uint64]symAndSize
2193 hashedSyms map[goobj.HashType]symAndSize
2194
2195 linknameVarRefs []linknameVarRef
2196 }
2197
2198 type linknameVarRef struct {
2199 pkg string
2200 name string
2201 sym Sym
2202 }
2203
2204
2205 func (st *loadState) preloadSyms(r *oReader, kind int) {
2206 l := st.l
2207 var start, end uint32
2208 switch kind {
2209 case pkgDef:
2210 start = 0
2211 end = uint32(r.ndef)
2212 case hashed64Def:
2213 start = uint32(r.ndef)
2214 end = uint32(r.ndef + r.nhashed64def)
2215 case hashedDef:
2216 start = uint32(r.ndef + r.nhashed64def)
2217 end = uint32(r.ndef + r.nhashed64def + r.nhasheddef)
2218 case nonPkgDef:
2219 start = uint32(r.ndef + r.nhashed64def + r.nhasheddef)
2220 end = uint32(r.ndef + r.nhashed64def + r.nhasheddef + r.NNonpkgdef())
2221 default:
2222 panic("preloadSyms: bad kind")
2223 }
2224 l.growAttrBitmaps(len(l.objSyms) + int(end-start))
2225 loadingRuntimePkg := r.unit.Lib.Pkg == "runtime"
2226 for i := start; i < end; i++ {
2227 osym := r.Sym(i)
2228 var name string
2229 var v int
2230 if kind != hashed64Def && kind != hashedDef {
2231 name = osym.Name(r.Reader)
2232 v = abiToVer(osym.ABI(), r.version)
2233 }
2234 gi := st.addSym(name, v, r, i, kind, osym)
2235 r.syms[i] = gi
2236 if kind == nonPkgDef && osym.IsLinkname() && r.DataSize(i) == 0 && strings.Contains(name, ".") {
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247 st.linknameVarRefs = append(st.linknameVarRefs, linknameVarRef{r.unit.Lib.Pkg, name, gi})
2248 }
2249 if osym.Local() {
2250 l.SetAttrLocal(gi, true)
2251 }
2252 if osym.UsedInIface() {
2253 l.SetAttrUsedInIface(gi, true)
2254 }
2255 if strings.HasPrefix(name, "runtime.") ||
2256 (loadingRuntimePkg && strings.HasPrefix(name, "type:")) {
2257 if bi := goobj.BuiltinIdx(name, int(osym.ABI())); bi != -1 {
2258
2259 l.builtinSyms[bi] = gi
2260 }
2261 }
2262 if a := int32(osym.Align()); a != 0 && a > l.SymAlign(gi) {
2263 l.SetSymAlign(gi, a)
2264 }
2265 if osym.WasmExport() {
2266 l.WasmExports = append(l.WasmExports, gi)
2267 }
2268 }
2269 }
2270
2271
2272
2273 func (l *Loader) LoadSyms(arch *sys.Arch) {
2274
2275
2276
2277 var symSize, hashedSize, hashed64Size int
2278 for _, r := range l.objs[goObjStart:] {
2279 symSize += r.ndef + r.nhasheddef/2 + r.nhashed64def/2 + r.NNonpkgdef()
2280 hashedSize += r.nhasheddef / 2
2281 hashed64Size += r.nhashed64def / 2
2282 }
2283
2284 l.objSyms = make([]objSym, 1, symSize)
2285
2286 st := loadState{
2287 l: l,
2288 hashed64Syms: make(map[uint64]symAndSize, hashed64Size),
2289 hashedSyms: make(map[goobj.HashType]symAndSize, hashedSize),
2290 }
2291
2292 for _, r := range l.objs[goObjStart:] {
2293 st.preloadSyms(r, pkgDef)
2294 }
2295 l.npkgsyms = l.NSym()
2296 for _, r := range l.objs[goObjStart:] {
2297 st.preloadSyms(r, hashed64Def)
2298 st.preloadSyms(r, hashedDef)
2299 st.preloadSyms(r, nonPkgDef)
2300 }
2301 for _, sf := range l.sizeFixups {
2302 pp := l.cloneToExternal(sf.sym)
2303 pp.size = int64(sf.size)
2304 }
2305 for _, vr := range st.linknameVarRefs {
2306 l.checkLinkname(vr.pkg, vr.name, vr.sym)
2307 }
2308 l.nhashedsyms = len(st.hashed64Syms) + len(st.hashedSyms)
2309 for _, r := range l.objs[goObjStart:] {
2310 loadObjRefs(l, r, arch)
2311 }
2312 l.values = make([]int64, l.NSym(), l.NSym()+1000)
2313 l.outer = make([]Sym, l.NSym(), l.NSym()+1000)
2314 }
2315
2316 func loadObjRefs(l *Loader, r *oReader, arch *sys.Arch) {
2317
2318 ndef := uint32(r.NAlldef())
2319 for i, n := uint32(0), uint32(r.NNonpkgref()); i < n; i++ {
2320 osym := r.Sym(ndef + i)
2321 name := osym.Name(r.Reader)
2322 v := abiToVer(osym.ABI(), r.version)
2323 gi := l.LookupOrCreateSym(name, v)
2324 r.syms[ndef+i] = gi
2325 if osym.IsLinkname() {
2326
2327
2328
2329
2330 l.checkLinkname(r.unit.Lib.Pkg, name, gi)
2331 }
2332 if osym.Local() {
2333 l.SetAttrLocal(gi, true)
2334 }
2335 if osym.UsedInIface() {
2336 l.SetAttrUsedInIface(gi, true)
2337 }
2338 }
2339
2340
2341 npkg := r.NPkg()
2342 r.pkg = make([]uint32, npkg)
2343 for i := 1; i < npkg; i++ {
2344 pkg := r.Pkg(i)
2345 objidx, ok := l.objByPkg[pkg]
2346 if !ok {
2347 log.Fatalf("%v: reference to nonexistent package %s", r.unit.Lib, pkg)
2348 }
2349 r.pkg[i] = objidx
2350 }
2351
2352
2353 for i, n := 0, r.NRefFlags(); i < n; i++ {
2354 rf := r.RefFlags(i)
2355 gi := l.resolve(r, rf.Sym())
2356 if rf.Flag2()&goobj.SymFlagUsedInIface != 0 {
2357 l.SetAttrUsedInIface(gi, true)
2358 }
2359 }
2360 }
2361
2362 func abiToVer(abi uint16, localSymVersion int) int {
2363 var v int
2364 if abi == goobj.SymABIstatic {
2365
2366 v = localSymVersion
2367 } else if abiver := sym.ABIToVersion(obj.ABI(abi)); abiver != -1 {
2368
2369 v = abiver
2370 } else {
2371 log.Fatalf("invalid symbol ABI: %d", abi)
2372 }
2373 return v
2374 }
2375
2376
2377
2378
2379
2380
2381
2382 var blockedLinknames = map[string][]string{
2383
2384 "runtime.coroswitch": {"iter"},
2385 "runtime.newcoro": {"iter"},
2386
2387 "go:fipsinfo": {"crypto/internal/fips140/check"},
2388
2389
2390 "crypto/internal/fips140.fatal": {"crypto/internal/fips140"},
2391 "crypto/internal/fips140.getIndicator": {"crypto/internal/fips140"},
2392 "crypto/internal/fips140.setIndicator": {"crypto/internal/fips140"},
2393 "crypto/internal/sysrand.fatal": {"crypto/internal/sysrand"},
2394 "crypto/rand.fatal": {"crypto/rand"},
2395 "internal/runtime/maps.errNilAssign": {"internal/runtime/maps"},
2396 "internal/runtime/maps.fatal": {"internal/runtime/maps"},
2397 "internal/runtime/maps.newarray": {"internal/runtime/maps"},
2398 "internal/runtime/maps.newobject": {"internal/runtime/maps"},
2399 "internal/runtime/maps.typedmemclr": {"internal/runtime/maps"},
2400 "internal/runtime/maps.typedmemmove": {"internal/runtime/maps"},
2401 "internal/sync.fatal": {"internal/sync"},
2402 "internal/sync.runtime_canSpin": {"internal/sync"},
2403 "internal/sync.runtime_doSpin": {"internal/sync"},
2404 "internal/sync.runtime_nanotime": {"internal/sync"},
2405 "internal/sync.runtime_Semrelease": {"internal/sync"},
2406 "internal/sync.runtime_SemacquireMutex": {"internal/sync"},
2407 "internal/sync.throw": {"internal/sync"},
2408 "internal/synctest.Run": {"internal/synctest"},
2409 "internal/synctest.Wait": {"internal/synctest"},
2410 "internal/synctest.acquire": {"internal/synctest"},
2411 "internal/synctest.release": {"internal/synctest"},
2412 "internal/synctest.inBubble": {"internal/synctest"},
2413 "runtime.getStaticuint64s": {"reflect"},
2414 "sync.runtime_SemacquireWaitGroup": {"sync"},
2415 "time.runtimeNow": {"time"},
2416 "time.runtimeNano": {"time"},
2417
2418
2419 "runtime.mapaccess1": {"runtime"},
2420 "runtime.mapaccess1_fast32": {"runtime"},
2421 "runtime.mapaccess1_fast64": {"runtime"},
2422 "runtime.mapaccess1_faststr": {"runtime"},
2423 "runtime.mapdelete_fast32": {"runtime"},
2424 "runtime.mapdelete_fast64": {"runtime"},
2425 "runtime.mapdelete_faststr": {"runtime"},
2426
2427
2428 "internal/cpu.riscvHWProbe": {"internal/cpu"},
2429 "internal/runtime/cgroup.throw": {"internal/runtime/cgroup"},
2430 "internal/runtime/maps.typeString": {"internal/runtime/maps"},
2431 "internal/synctest.IsInBubble": {"internal/synctest"},
2432 "internal/synctest.associate": {"internal/synctest"},
2433 "internal/synctest.disassociate": {"internal/synctest"},
2434 "internal/synctest.isAssociated": {"internal/synctest"},
2435 "runtime/trace.runtime_readTrace": {"runtime/trace"},
2436 "runtime/trace.runtime_traceClockUnitsPerSecond": {"runtime/trace"},
2437 "sync_test.runtime_blockUntilEmptyCleanupQueue": {"sync_test"},
2438 "time.runtimeIsBubbled": {"time"},
2439 "unique.runtime_blockUntilEmptyCleanupQueue": {"unique"},
2440
2441 "net.newWindowsFile": {"net"},
2442 "testing/synctest.testingSynctestTest": {"testing/synctest"},
2443 }
2444
2445
2446 func (l *Loader) checkLinkname(pkg, name string, s Sym) {
2447 if l.flags&FlagCheckLinkname == 0 {
2448 return
2449 }
2450
2451 error := func() {
2452 log.Fatalf("%s: invalid reference to %s", pkg, name)
2453 }
2454 pkgs, ok := blockedLinknames[name]
2455 if ok {
2456 for _, p := range pkgs {
2457 if pkg == p {
2458 return
2459 }
2460
2461
2462 if strings.HasPrefix(pkg, "crypto/internal/fips140/v") {
2463 parts := strings.Split(pkg, "/")
2464 parts = append(parts[:3], parts[4:]...)
2465 pkg := strings.Join(parts, "/")
2466 if pkg == p {
2467 return
2468 }
2469 }
2470 }
2471 error()
2472 }
2473 r, li := l.toLocal(s)
2474 if r == l.extReader {
2475 return
2476 }
2477 if !r.Std() {
2478 return
2479 }
2480 if r.unit.Lib.Pkg == pkg {
2481 return
2482 }
2483 osym := r.Sym(li)
2484 if osym.IsLinkname() || osym.ABIWrapper() {
2485
2486
2487
2488
2489
2490 return
2491 }
2492 error()
2493 }
2494
2495
2496
2497
2498
2499 func (l *Loader) TopLevelSym(s Sym) bool {
2500 return topLevelSym(l.SymName(s), l.SymType(s))
2501 }
2502
2503
2504
2505
2506
2507 func topLevelSym(sname string, skind sym.SymKind) bool {
2508 if sname != "" {
2509 return true
2510 }
2511 switch skind {
2512 case sym.SDWARFFCN, sym.SDWARFABSFCN, sym.SDWARFTYPE, sym.SDWARFCONST, sym.SDWARFCUINFO, sym.SDWARFRANGE, sym.SDWARFLOC, sym.SDWARFLINES, sym.SGOFUNC:
2513 return true
2514 default:
2515 return false
2516 }
2517 }
2518
2519
2520
2521
2522
2523
2524
2525
2526 func (l *Loader) cloneToExternal(symIdx Sym) *extSymPayload {
2527 if l.IsExternal(symIdx) {
2528 panic("sym is already external, no need for clone")
2529 }
2530
2531
2532 r, li := l.toLocal(symIdx)
2533 osym := r.Sym(li)
2534 sname := osym.Name(r.Reader)
2535 sver := abiToVer(osym.ABI(), r.version)
2536 skind := sym.AbiSymKindToSymKind[objabi.SymKind(osym.Type())]
2537
2538
2539 pi := l.newPayload(sname, sver)
2540 pp := l.payloads[pi]
2541 pp.kind = skind
2542 pp.ver = sver
2543 pp.size = int64(osym.Siz())
2544 pp.objidx = r.objidx
2545
2546
2547
2548 if li < uint32(r.NAlldef()) {
2549
2550
2551 relocs := l.Relocs(symIdx)
2552 pp.relocs = make([]goobj.Reloc, relocs.Count())
2553 for i := range pp.relocs {
2554
2555
2556 rel := relocs.At(i)
2557 pp.relocs[i].Set(rel.Off(), rel.Siz(), uint16(rel.Type()), rel.Add(), goobj.SymRef{PkgIdx: 0, SymIdx: uint32(rel.Sym())})
2558 }
2559
2560
2561 pp.data = r.Data(li)
2562 }
2563
2564
2565
2566 auxs := r.Auxs(li)
2567 pp.auxs = auxs
2568
2569
2570
2571
2572 l.objSyms[symIdx] = objSym{l.extReader.objidx, uint32(pi)}
2573 l.extReader.syms = append(l.extReader.syms, symIdx)
2574
2575
2576 l.SetAttrDuplicateOK(symIdx, r.Sym(li).Dupok())
2577 l.SetAttrShared(symIdx, r.Shared())
2578
2579 return pp
2580 }
2581
2582
2583
2584
2585
2586
2587
2588 func (l *Loader) CopySym(src, dst Sym) {
2589 if !l.IsExternal(dst) {
2590 panic("dst is not external")
2591 }
2592 if !l.IsExternal(src) {
2593 panic("src is not external")
2594 }
2595 l.payloads[l.extIndex(dst)] = l.payloads[l.extIndex(src)]
2596 l.SetSymPkg(dst, l.SymPkg(src))
2597
2598 }
2599
2600
2601
2602 func (l *Loader) CreateExtSym(name string, ver int) Sym {
2603 return l.newExtSym(name, ver)
2604 }
2605
2606
2607
2608 func (l *Loader) CreateStaticSym(name string) Sym {
2609
2610
2611 l.anonVersion--
2612 return l.newExtSym(name, l.anonVersion)
2613 }
2614
2615 func (l *Loader) FreeSym(i Sym) {
2616 if l.IsExternal(i) {
2617 pp := l.getPayload(i)
2618 *pp = extSymPayload{}
2619 }
2620 }
2621
2622
2623
2624 type relocId struct {
2625 sym Sym
2626 ridx int
2627 }
2628
2629
2630
2631 func (l *Loader) SetRelocVariant(s Sym, ri int, v sym.RelocVariant) {
2632
2633 if relocs := l.Relocs(s); ri >= relocs.Count() {
2634 panic("invalid relocation ID")
2635 }
2636 if l.relocVariant == nil {
2637 l.relocVariant = make(map[relocId]sym.RelocVariant)
2638 }
2639 if v != 0 {
2640 l.relocVariant[relocId{s, ri}] = v
2641 } else {
2642 delete(l.relocVariant, relocId{s, ri})
2643 }
2644 }
2645
2646
2647
2648 func (l *Loader) RelocVariant(s Sym, ri int) sym.RelocVariant {
2649 return l.relocVariant[relocId{s, ri}]
2650 }
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662 func (l *Loader) UndefinedRelocTargets(limit int) ([]Sym, []Sym) {
2663 result, fromr := []Sym{}, []Sym{}
2664 outerloop:
2665 for si := Sym(1); si < Sym(len(l.objSyms)); si++ {
2666 relocs := l.Relocs(si)
2667 for ri := 0; ri < relocs.Count(); ri++ {
2668 r := relocs.At(ri)
2669 rs := r.Sym()
2670 if rs != 0 && l.SymType(rs) == sym.SXREF && l.SymName(rs) != ".got" {
2671 result = append(result, rs)
2672 fromr = append(fromr, si)
2673 if limit != -1 && len(result) >= limit {
2674 break outerloop
2675 }
2676 }
2677 }
2678 }
2679 return result, fromr
2680 }
2681
2682
2683
2684
2685
2686 func (l *Loader) AssignTextSymbolOrder(libs []*sym.Library, intlibs []bool, extsyms []Sym) []Sym {
2687
2688
2689 for _, lib := range libs {
2690 if len(lib.Textp) != 0 {
2691 panic("expected empty Textp slice for library")
2692 }
2693 if len(lib.DupTextSyms) != 0 {
2694 panic("expected empty DupTextSyms slice for library")
2695 }
2696 }
2697
2698
2699
2700
2701
2702
2703 assignedToUnit := MakeBitmap(l.NSym() + 1)
2704
2705
2706 textp := []Sym{}
2707 for _, sym := range extsyms {
2708 if !l.attrReachable.Has(sym) {
2709 continue
2710 }
2711 textp = append(textp, sym)
2712 }
2713
2714
2715
2716 for _, r := range l.objs[goObjStart:] {
2717 lib := r.unit.Lib
2718 for i, n := uint32(0), uint32(r.NAlldef()); i < n; i++ {
2719 gi := l.toGlobal(r, i)
2720 if !l.attrReachable.Has(gi) {
2721 continue
2722 }
2723 osym := r.Sym(i)
2724 st := sym.AbiSymKindToSymKind[objabi.SymKind(osym.Type())]
2725 if !st.IsText() {
2726 continue
2727 }
2728 dupok := osym.Dupok()
2729 if r2, i2 := l.toLocal(gi); r2 != r || i2 != i {
2730
2731
2732
2733
2734 lib.DupTextSyms = append(lib.DupTextSyms, sym.LoaderSym(gi))
2735 continue
2736 }
2737 if dupok {
2738 lib.DupTextSyms = append(lib.DupTextSyms, sym.LoaderSym(gi))
2739 continue
2740 }
2741
2742 lib.Textp = append(lib.Textp, sym.LoaderSym(gi))
2743 }
2744 }
2745
2746
2747 for _, doInternal := range [2]bool{true, false} {
2748 for idx, lib := range libs {
2749 if intlibs[idx] != doInternal {
2750 continue
2751 }
2752 lists := [2][]sym.LoaderSym{lib.Textp, lib.DupTextSyms}
2753 for i, list := range lists {
2754 for _, s := range list {
2755 sym := Sym(s)
2756 if !assignedToUnit.Has(sym) {
2757 textp = append(textp, sym)
2758 unit := l.SymUnit(sym)
2759 if unit != nil {
2760 unit.Textp = append(unit.Textp, s)
2761 assignedToUnit.Set(sym)
2762 }
2763
2764
2765
2766
2767
2768 if i == 1 && l.SymPkg(sym) != lib.Pkg {
2769 l.SetSymPkg(sym, lib.Pkg)
2770 }
2771 }
2772 }
2773 }
2774 lib.Textp = nil
2775 lib.DupTextSyms = nil
2776 }
2777 }
2778
2779 return textp
2780 }
2781
2782
2783 type ErrorReporter struct {
2784 ldr *Loader
2785 AfterErrorAction func()
2786 }
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796 func (reporter *ErrorReporter) Errorf(s Sym, format string, args ...interface{}) {
2797 if s != 0 && reporter.ldr.SymName(s) != "" {
2798
2799
2800 format = strings.ReplaceAll(reporter.ldr.SymName(s), "%", "%%") + ": " + format
2801 } else {
2802 format = fmt.Sprintf("sym %d: %s", s, format)
2803 }
2804 format += "\n"
2805 fmt.Fprintf(os.Stderr, format, args...)
2806 reporter.AfterErrorAction()
2807 }
2808
2809
2810 func (l *Loader) GetErrorReporter() *ErrorReporter {
2811 return l.errorReporter
2812 }
2813
2814
2815 func (l *Loader) Errorf(s Sym, format string, args ...interface{}) {
2816 l.errorReporter.Errorf(s, format, args...)
2817 }
2818
2819
2820 func (l *Loader) Stat() string {
2821 s := fmt.Sprintf("%d symbols, %d reachable\n", l.NSym(), l.NReachableSym())
2822 s += fmt.Sprintf("\t%d package symbols, %d hashed symbols, %d non-package symbols, %d external symbols\n",
2823 l.npkgsyms, l.nhashedsyms, int(l.extStart)-l.npkgsyms-l.nhashedsyms, l.NSym()-int(l.extStart))
2824 return s
2825 }
2826
2827
2828 func (l *Loader) Dump() {
2829 fmt.Println("objs")
2830 for _, r := range l.objs[goObjStart:] {
2831 if r != nil {
2832 fmt.Println(r.unit.Lib)
2833 }
2834 }
2835 fmt.Println("extStart:", l.extStart)
2836 fmt.Println("Nsyms:", len(l.objSyms))
2837 fmt.Println("syms")
2838 for i := Sym(1); i < Sym(len(l.objSyms)); i++ {
2839 pi := ""
2840 if l.IsExternal(i) {
2841 pi = fmt.Sprintf("<ext %d>", l.extIndex(i))
2842 }
2843 sect := ""
2844 if l.SymSect(i) != nil {
2845 sect = l.SymSect(i).Name
2846 }
2847 fmt.Printf("%v %v %v %v %x %v\n", i, l.SymName(i), l.SymType(i), pi, l.SymValue(i), sect)
2848 }
2849 fmt.Println("symsByName")
2850 for name, i := range l.symsByName[0] {
2851 fmt.Println(i, name, 0)
2852 }
2853 for name, i := range l.symsByName[1] {
2854 fmt.Println(i, name, 1)
2855 }
2856 fmt.Println("payloads:")
2857 for i := range l.payloads {
2858 pp := l.payloads[i]
2859 fmt.Println(i, pp.name, pp.ver, pp.kind)
2860 }
2861 }
2862
View as plain text