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