1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32 package ld
33
34 import (
35 "bytes"
36 "cmd/internal/gcprog"
37 "cmd/internal/objabi"
38 "cmd/internal/sys"
39 "cmd/link/internal/loader"
40 "cmd/link/internal/sym"
41 "compress/zlib"
42 "debug/elf"
43 "encoding/binary"
44 "fmt"
45 "log"
46 "os"
47 "sort"
48 "strconv"
49 "strings"
50 "sync"
51 "sync/atomic"
52 )
53
54
55 func isRuntimeDepPkg(pkg string) bool {
56 switch pkg {
57 case "runtime",
58 "sync/atomic",
59 "internal/abi",
60 "internal/bytealg",
61 "internal/cpu":
62 return true
63 }
64 return strings.HasPrefix(pkg, "runtime/internal/") && !strings.HasSuffix(pkg, "_test")
65 }
66
67
68
69
70 func maxSizeTrampolines(ctxt *Link, ldr *loader.Loader, s loader.Sym, isTramp bool) uint64 {
71
72
73 if thearch.Trampoline == nil || isTramp {
74 return 0
75 }
76
77 n := uint64(0)
78 relocs := ldr.Relocs(s)
79 for ri := 0; ri < relocs.Count(); ri++ {
80 r := relocs.At(ri)
81 if r.Type().IsDirectCallOrJump() {
82 n++
83 }
84 }
85
86 if ctxt.IsPPC64() {
87 return n * 16
88 }
89 if ctxt.IsARM64() {
90 return n * 12
91 }
92 panic("unreachable")
93 }
94
95
96
97
98
99 func trampoline(ctxt *Link, s loader.Sym) {
100 if thearch.Trampoline == nil {
101 return
102 }
103
104 ldr := ctxt.loader
105 relocs := ldr.Relocs(s)
106 for ri := 0; ri < relocs.Count(); ri++ {
107 r := relocs.At(ri)
108 rt := r.Type()
109 if !rt.IsDirectCallOrJump() && !isPLTCall(rt) {
110 continue
111 }
112 rs := r.Sym()
113 if !ldr.AttrReachable(rs) || ldr.SymType(rs) == sym.Sxxx {
114 continue
115 }
116 rs = ldr.ResolveABIAlias(rs)
117 if ldr.SymValue(rs) == 0 && (ldr.SymType(rs) != sym.SDYNIMPORT && ldr.SymType(rs) != sym.SUNDEFEXT) {
118 if ldr.SymPkg(s) != "" && ldr.SymPkg(rs) == ldr.SymPkg(s) {
119
120
121
122 continue
123 }
124 if isRuntimeDepPkg(ldr.SymPkg(s)) && isRuntimeDepPkg(ldr.SymPkg(rs)) {
125 continue
126 }
127 }
128
129 thearch.Trampoline(ctxt, ldr, ri, rs, s)
130 }
131 }
132
133
134
135 func isPLTCall(rt objabi.RelocType) bool {
136 const pcrel = 1
137 switch rt {
138
139 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_AARCH64_CALL26),
140 objabi.ElfRelocOffset + objabi.RelocType(elf.R_AARCH64_JUMP26),
141 objabi.MachoRelocOffset + MACHO_ARM64_RELOC_BRANCH26*2 + pcrel:
142 return true
143
144
145 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_ARM_CALL),
146 objabi.ElfRelocOffset + objabi.RelocType(elf.R_ARM_PC24),
147 objabi.ElfRelocOffset + objabi.RelocType(elf.R_ARM_JUMP24):
148 return true
149 }
150
151 return false
152 }
153
154
155
156
157 func FoldSubSymbolOffset(ldr *loader.Loader, s loader.Sym) (loader.Sym, int64) {
158 outer := ldr.OuterSym(s)
159 off := int64(0)
160 if outer != 0 {
161 off += ldr.SymValue(s) - ldr.SymValue(outer)
162 s = outer
163 }
164 return s, off
165 }
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183 func (st *relocSymState) relocsym(s loader.Sym, P []byte) {
184 ldr := st.ldr
185 relocs := ldr.Relocs(s)
186 if relocs.Count() == 0 {
187 return
188 }
189 target := st.target
190 syms := st.syms
191 nExtReloc := 0
192 for ri := 0; ri < relocs.Count(); ri++ {
193 r := relocs.At(ri)
194 off := r.Off()
195 siz := int32(r.Siz())
196 rs := r.Sym()
197 rs = ldr.ResolveABIAlias(rs)
198 rt := r.Type()
199 weak := r.Weak()
200 if off < 0 || off+siz > int32(len(P)) {
201 rname := ""
202 if rs != 0 {
203 rname = ldr.SymName(rs)
204 }
205 st.err.Errorf(s, "invalid relocation %s: %d+%d not in [%d,%d)", rname, off, siz, 0, len(P))
206 continue
207 }
208 if siz == 0 {
209 continue
210 }
211
212 var rst sym.SymKind
213 if rs != 0 {
214 rst = ldr.SymType(rs)
215 }
216
217 if rs != 0 && ((rst == sym.Sxxx && !ldr.AttrVisibilityHidden(rs)) || rst == sym.SXREF) {
218
219
220 if target.IsShared() || target.IsPlugin() {
221 if ldr.SymName(rs) == "main.main" || (!target.IsPlugin() && ldr.SymName(rs) == "main..inittask") {
222 sb := ldr.MakeSymbolUpdater(rs)
223 sb.SetType(sym.SDYNIMPORT)
224 } else if strings.HasPrefix(ldr.SymName(rs), "go.info.") {
225
226
227 continue
228 }
229 } else {
230 st.err.errorUnresolved(ldr, s, rs)
231 continue
232 }
233 }
234
235 if rt >= objabi.ElfRelocOffset {
236 continue
237 }
238
239
240
241 if !target.IsAIX() && !target.IsDarwin() && !target.IsSolaris() && !target.IsOpenbsd() && rs != 0 && rst == sym.SDYNIMPORT && !target.IsDynlinkingGo() && !ldr.AttrSubSymbol(rs) {
242 if !(target.IsPPC64() && target.IsExternal() && ldr.SymName(rs) == ".TOC.") {
243 st.err.Errorf(s, "unhandled relocation for %s (type %d (%s) rtype %d (%s))", ldr.SymName(rs), rst, rst, rt, sym.RelocName(target.Arch, rt))
244 }
245 }
246 if rs != 0 && rst != sym.STLSBSS && !weak && rt != objabi.R_METHODOFF && !ldr.AttrReachable(rs) {
247 st.err.Errorf(s, "unreachable sym in relocation: %s", ldr.SymName(rs))
248 }
249
250 var rv sym.RelocVariant
251 if target.IsPPC64() || target.IsS390X() {
252 rv = ldr.RelocVariant(s, ri)
253 }
254
255
256 if target.IsS390X() {
257 switch rt {
258 case objabi.R_PCRELDBL:
259 rt = objabi.R_PCREL
260 rv = sym.RV_390_DBL
261 case objabi.R_CALL:
262 rv = sym.RV_390_DBL
263 }
264 }
265
266 var o int64
267 switch rt {
268 default:
269 switch siz {
270 default:
271 st.err.Errorf(s, "bad reloc size %#x for %s", uint32(siz), ldr.SymName(rs))
272 case 1:
273 o = int64(P[off])
274 case 2:
275 o = int64(target.Arch.ByteOrder.Uint16(P[off:]))
276 case 4:
277 o = int64(target.Arch.ByteOrder.Uint32(P[off:]))
278 case 8:
279 o = int64(target.Arch.ByteOrder.Uint64(P[off:]))
280 }
281 out, n, ok := thearch.Archreloc(target, ldr, syms, r, s, o)
282 if target.IsExternal() {
283 nExtReloc += n
284 }
285 if ok {
286 o = out
287 } else {
288 st.err.Errorf(s, "unknown reloc to %v: %d (%s)", ldr.SymName(rs), rt, sym.RelocName(target.Arch, rt))
289 }
290 case objabi.R_TLS_LE:
291 if target.IsExternal() && target.IsElf() {
292 nExtReloc++
293 o = 0
294 if !target.IsAMD64() {
295 o = r.Add()
296 }
297 break
298 }
299
300 if target.IsElf() && target.IsARM() {
301
302
303
304
305
306
307
308 o = 8 + ldr.SymValue(rs)
309 } else if target.IsElf() || target.IsPlan9() || target.IsDarwin() {
310 o = int64(syms.Tlsoffset) + r.Add()
311 } else if target.IsWindows() {
312 o = r.Add()
313 } else {
314 log.Fatalf("unexpected R_TLS_LE relocation for %v", target.HeadType)
315 }
316 case objabi.R_TLS_IE:
317 if target.IsExternal() && target.IsElf() {
318 nExtReloc++
319 o = 0
320 if !target.IsAMD64() {
321 o = r.Add()
322 }
323 if target.Is386() {
324 nExtReloc++
325 }
326 break
327 }
328 if target.IsPIE() && target.IsElf() {
329
330
331 if thearch.TLSIEtoLE == nil {
332 log.Fatalf("internal linking of TLS IE not supported on %v", target.Arch.Family)
333 }
334 thearch.TLSIEtoLE(P, int(off), int(siz))
335 o = int64(syms.Tlsoffset)
336 } else {
337 log.Fatalf("cannot handle R_TLS_IE (sym %s) when linking internally", ldr.SymName(s))
338 }
339 case objabi.R_ADDR:
340 if weak && !ldr.AttrReachable(rs) {
341
342 rs = syms.unreachableMethod
343 rs = ldr.ResolveABIAlias(rs)
344 }
345 if target.IsExternal() {
346 nExtReloc++
347
348
349 rs := rs
350 rs, off := FoldSubSymbolOffset(ldr, rs)
351 xadd := r.Add() + off
352 rst := ldr.SymType(rs)
353 if rst != sym.SHOSTOBJ && rst != sym.SDYNIMPORT && rst != sym.SUNDEFEXT && ldr.SymSect(rs) == nil {
354 st.err.Errorf(s, "missing section for relocation target %s", ldr.SymName(rs))
355 }
356
357 o = xadd
358 if target.IsElf() {
359 if target.IsAMD64() {
360 o = 0
361 }
362 } else if target.IsDarwin() {
363 if ldr.SymType(rs) != sym.SHOSTOBJ {
364 o += ldr.SymValue(rs)
365 }
366 } else if target.IsWindows() {
367
368 } else if target.IsAIX() {
369 o = ldr.SymValue(rs) + xadd
370 } else {
371 st.err.Errorf(s, "unhandled pcrel relocation to %s on %v", ldr.SymName(rs), target.HeadType)
372 }
373
374 break
375 }
376
377
378
379
380
381 if target.IsAIX() && rst != sym.SDYNIMPORT {
382
383
384
385
386
387 if ldr.SymSect(s).Seg == &Segdata {
388 Xcoffadddynrel(target, ldr, syms, s, r, ri)
389 }
390 }
391
392 o = ldr.SymValue(rs) + r.Add()
393
394
395
396
397
398
399 if int32(o) < 0 && target.Arch.PtrSize > 4 && siz == 4 {
400 st.err.Errorf(s, "non-pc-relative relocation address for %s is too big: %#x (%#x + %#x)", ldr.SymName(rs), uint64(o), ldr.SymValue(rs), r.Add())
401 errorexit()
402 }
403 case objabi.R_DWARFSECREF:
404 if ldr.SymSect(rs) == nil {
405 st.err.Errorf(s, "missing DWARF section for relocation target %s", ldr.SymName(rs))
406 }
407
408 if target.IsExternal() {
409
410
411
412
413
414 if !target.IsDarwin() {
415 nExtReloc++
416 }
417
418 xadd := r.Add() + ldr.SymValue(rs) - int64(ldr.SymSect(rs).Vaddr)
419
420 o = xadd
421 if target.IsElf() && target.IsAMD64() {
422 o = 0
423 }
424 break
425 }
426 o = ldr.SymValue(rs) + r.Add() - int64(ldr.SymSect(rs).Vaddr)
427 case objabi.R_METHODOFF:
428 if !ldr.AttrReachable(rs) {
429
430
431 o = -1
432 break
433 }
434 fallthrough
435 case objabi.R_ADDROFF:
436 if weak && !ldr.AttrReachable(rs) {
437 continue
438 }
439
440
441 if ldr.SymSect(rs).Name == ".text" {
442 o = ldr.SymValue(rs) - int64(Segtext.Sections[0].Vaddr) + r.Add()
443 } else {
444 o = ldr.SymValue(rs) - int64(ldr.SymSect(rs).Vaddr) + r.Add()
445 }
446
447 case objabi.R_ADDRCUOFF:
448
449
450 o = ldr.SymValue(rs) + r.Add() - ldr.SymValue(loader.Sym(ldr.SymUnit(rs).Textp[0]))
451
452
453 case objabi.R_GOTPCREL:
454 if target.IsDynlinkingGo() && target.IsDarwin() && rs != 0 {
455 nExtReloc++
456 o = r.Add()
457 break
458 }
459 if target.Is386() && target.IsExternal() && target.IsELF {
460 nExtReloc++
461 }
462 fallthrough
463 case objabi.R_CALL, objabi.R_PCREL:
464 if target.IsExternal() && rs != 0 && rst == sym.SUNDEFEXT {
465
466 nExtReloc++
467 o = 0
468 break
469 }
470 if target.IsExternal() && rs != 0 && (ldr.SymSect(rs) != ldr.SymSect(s) || rt == objabi.R_GOTPCREL) {
471 nExtReloc++
472
473
474 rs := rs
475 rs, off := FoldSubSymbolOffset(ldr, rs)
476 xadd := r.Add() + off - int64(siz)
477 rst := ldr.SymType(rs)
478 if rst != sym.SHOSTOBJ && rst != sym.SDYNIMPORT && ldr.SymSect(rs) == nil {
479 st.err.Errorf(s, "missing section for relocation target %s", ldr.SymName(rs))
480 }
481
482 o = xadd
483 if target.IsElf() {
484 if target.IsAMD64() {
485 o = 0
486 }
487 } else if target.IsDarwin() {
488 if rt == objabi.R_CALL {
489 if target.IsExternal() && rst == sym.SDYNIMPORT {
490 if target.IsAMD64() {
491
492 o += int64(siz)
493 }
494 } else {
495 if rst != sym.SHOSTOBJ {
496 o += int64(uint64(ldr.SymValue(rs)) - ldr.SymSect(rs).Vaddr)
497 }
498 o -= int64(off)
499 }
500 } else {
501 o += int64(siz)
502 }
503 } else if target.IsWindows() && target.IsAMD64() {
504
505
506 o += int64(siz)
507 } else {
508 st.err.Errorf(s, "unhandled pcrel relocation to %s on %v", ldr.SymName(rs), target.HeadType)
509 }
510
511 break
512 }
513
514 o = 0
515 if rs != 0 {
516 o = ldr.SymValue(rs)
517 }
518
519 o += r.Add() - (ldr.SymValue(s) + int64(off) + int64(siz))
520 case objabi.R_SIZE:
521 o = ldr.SymSize(rs) + r.Add()
522
523 case objabi.R_XCOFFREF:
524 if !target.IsAIX() {
525 st.err.Errorf(s, "find XCOFF R_REF on non-XCOFF files")
526 }
527 if !target.IsExternal() {
528 st.err.Errorf(s, "find XCOFF R_REF with internal linking")
529 }
530 nExtReloc++
531 continue
532
533 case objabi.R_DWARFFILEREF:
534
535 continue
536
537 case objabi.R_CONST:
538 o = r.Add()
539
540 case objabi.R_GOTOFF:
541 o = ldr.SymValue(rs) + r.Add() - ldr.SymValue(syms.GOT)
542 }
543
544 if target.IsPPC64() || target.IsS390X() {
545 if rv != sym.RV_NONE {
546 o = thearch.Archrelocvariant(target, ldr, r, rv, s, o, P)
547 }
548 }
549
550 switch siz {
551 default:
552 st.err.Errorf(s, "bad reloc size %#x for %s", uint32(siz), ldr.SymName(rs))
553 case 1:
554 P[off] = byte(int8(o))
555 case 2:
556 if o != int64(int16(o)) {
557 st.err.Errorf(s, "relocation address for %s is too big: %#x", ldr.SymName(rs), o)
558 }
559 target.Arch.ByteOrder.PutUint16(P[off:], uint16(o))
560 case 4:
561 if rt == objabi.R_PCREL || rt == objabi.R_CALL {
562 if o != int64(int32(o)) {
563 st.err.Errorf(s, "pc-relative relocation address for %s is too big: %#x", ldr.SymName(rs), o)
564 }
565 } else {
566 if o != int64(int32(o)) && o != int64(uint32(o)) {
567 st.err.Errorf(s, "non-pc-relative relocation address for %s is too big: %#x", ldr.SymName(rs), uint64(o))
568 }
569 }
570 target.Arch.ByteOrder.PutUint32(P[off:], uint32(o))
571 case 8:
572 target.Arch.ByteOrder.PutUint64(P[off:], uint64(o))
573 }
574 }
575 if target.IsExternal() {
576
577
578 atomic.AddUint32(&ldr.SymSect(s).Relcount, uint32(nExtReloc))
579 }
580 }
581
582
583 func extreloc(ctxt *Link, ldr *loader.Loader, s loader.Sym, r loader.Reloc) (loader.ExtReloc, bool) {
584 var rr loader.ExtReloc
585 target := &ctxt.Target
586 siz := int32(r.Siz())
587 if siz == 0 {
588 return rr, false
589 }
590
591 rt := r.Type()
592 if rt >= objabi.ElfRelocOffset {
593 return rr, false
594 }
595 rr.Type = rt
596 rr.Size = uint8(siz)
597
598
599 if target.IsS390X() {
600 switch rt {
601 case objabi.R_PCRELDBL:
602 rt = objabi.R_PCREL
603 }
604 }
605
606 switch rt {
607 default:
608 return thearch.Extreloc(target, ldr, r, s)
609
610 case objabi.R_TLS_LE, objabi.R_TLS_IE:
611 if target.IsElf() {
612 rs := ldr.ResolveABIAlias(r.Sym())
613 rr.Xsym = rs
614 if rr.Xsym == 0 {
615 rr.Xsym = ctxt.Tlsg
616 }
617 rr.Xadd = r.Add()
618 break
619 }
620 return rr, false
621
622 case objabi.R_ADDR:
623
624 rs := ldr.ResolveABIAlias(r.Sym())
625 if r.Weak() && !ldr.AttrReachable(rs) {
626 rs = ctxt.ArchSyms.unreachableMethod
627 rs = ldr.ResolveABIAlias(rs)
628 }
629 rs, off := FoldSubSymbolOffset(ldr, rs)
630 rr.Xadd = r.Add() + off
631 rr.Xsym = rs
632
633 case objabi.R_DWARFSECREF:
634
635
636
637
638
639 if target.IsDarwin() {
640 return rr, false
641 }
642 rs := ldr.ResolveABIAlias(r.Sym())
643 rr.Xsym = loader.Sym(ldr.SymSect(rs).Sym)
644 rr.Xadd = r.Add() + ldr.SymValue(rs) - int64(ldr.SymSect(rs).Vaddr)
645
646
647 case objabi.R_GOTPCREL, objabi.R_CALL, objabi.R_PCREL:
648 rs := ldr.ResolveABIAlias(r.Sym())
649 if rt == objabi.R_GOTPCREL && target.IsDynlinkingGo() && target.IsDarwin() && rs != 0 {
650 rr.Xadd = r.Add()
651 rr.Xadd -= int64(siz)
652 rr.Xsym = rs
653 break
654 }
655 if rs != 0 && ldr.SymType(rs) == sym.SUNDEFEXT {
656
657 rr.Xadd = 0
658 if target.IsElf() {
659 rr.Xadd -= int64(siz)
660 }
661 rr.Xsym = rs
662 break
663 }
664 if rs != 0 && (ldr.SymSect(rs) != ldr.SymSect(s) || rt == objabi.R_GOTPCREL) {
665
666 rs := rs
667 rs, off := FoldSubSymbolOffset(ldr, rs)
668 rr.Xadd = r.Add() + off
669 rr.Xadd -= int64(siz)
670 rr.Xsym = rs
671 break
672 }
673 return rr, false
674
675 case objabi.R_XCOFFREF:
676 return ExtrelocSimple(ldr, r), true
677
678
679 case objabi.R_ADDROFF, objabi.R_METHODOFF, objabi.R_ADDRCUOFF,
680 objabi.R_SIZE, objabi.R_CONST, objabi.R_GOTOFF:
681 return rr, false
682 }
683 return rr, true
684 }
685
686
687
688 func ExtrelocSimple(ldr *loader.Loader, r loader.Reloc) loader.ExtReloc {
689 var rr loader.ExtReloc
690 rs := ldr.ResolveABIAlias(r.Sym())
691 rr.Xsym = rs
692 rr.Xadd = r.Add()
693 rr.Type = r.Type()
694 rr.Size = r.Siz()
695 return rr
696 }
697
698
699
700 func ExtrelocViaOuterSym(ldr *loader.Loader, r loader.Reloc, s loader.Sym) loader.ExtReloc {
701
702 var rr loader.ExtReloc
703 rs := ldr.ResolveABIAlias(r.Sym())
704 rs, off := FoldSubSymbolOffset(ldr, rs)
705 rr.Xadd = r.Add() + off
706 rst := ldr.SymType(rs)
707 if rst != sym.SHOSTOBJ && rst != sym.SDYNIMPORT && rst != sym.SUNDEFEXT && ldr.SymSect(rs) == nil {
708 ldr.Errorf(s, "missing section for %s", ldr.SymName(rs))
709 }
710 rr.Xsym = rs
711 rr.Type = r.Type()
712 rr.Size = r.Siz()
713 return rr
714 }
715
716
717
718
719
720
721
722
723 type relocSymState struct {
724 target *Target
725 ldr *loader.Loader
726 err *ErrorReporter
727 syms *ArchSyms
728 }
729
730
731
732
733 func (ctxt *Link) makeRelocSymState() *relocSymState {
734 return &relocSymState{
735 target: &ctxt.Target,
736 ldr: ctxt.loader,
737 err: &ctxt.ErrorReporter,
738 syms: &ctxt.ArchSyms,
739 }
740 }
741
742 func windynrelocsym(ctxt *Link, rel *loader.SymbolBuilder, s loader.Sym) {
743 var su *loader.SymbolBuilder
744 relocs := ctxt.loader.Relocs(s)
745 for ri := 0; ri < relocs.Count(); ri++ {
746 r := relocs.At(ri)
747 if r.IsMarker() {
748 continue
749 }
750 targ := r.Sym()
751 if targ == 0 {
752 continue
753 }
754 if !ctxt.loader.AttrReachable(targ) {
755 if r.Weak() {
756 continue
757 }
758 ctxt.Errorf(s, "dynamic relocation to unreachable symbol %s",
759 ctxt.loader.SymName(targ))
760 }
761
762 tplt := ctxt.loader.SymPlt(targ)
763 tgot := ctxt.loader.SymGot(targ)
764 if tplt == -2 && tgot != -2 {
765 tplt := int32(rel.Size())
766 ctxt.loader.SetPlt(targ, tplt)
767
768 if su == nil {
769 su = ctxt.loader.MakeSymbolUpdater(s)
770 }
771 r.SetSym(rel.Sym())
772 r.SetAdd(int64(tplt))
773
774
775 switch ctxt.Arch.Family {
776 default:
777 ctxt.Errorf(s, "unsupported arch %v", ctxt.Arch.Family)
778 return
779 case sys.I386:
780 rel.AddUint8(0xff)
781 rel.AddUint8(0x25)
782 rel.AddAddrPlus(ctxt.Arch, targ, 0)
783 rel.AddUint8(0x90)
784 rel.AddUint8(0x90)
785 case sys.AMD64:
786 rel.AddUint8(0xff)
787 rel.AddUint8(0x24)
788 rel.AddUint8(0x25)
789 rel.AddAddrPlus4(ctxt.Arch, targ, 0)
790 rel.AddUint8(0x90)
791 }
792 } else if tplt >= 0 {
793 if su == nil {
794 su = ctxt.loader.MakeSymbolUpdater(s)
795 }
796 r.SetSym(rel.Sym())
797 r.SetAdd(int64(tplt))
798 }
799 }
800 }
801
802
803
804 func (ctxt *Link) windynrelocsyms() {
805 if !(ctxt.IsWindows() && iscgo && ctxt.IsInternal()) {
806 return
807 }
808
809 rel := ctxt.loader.CreateSymForUpdate(".rel", 0)
810 rel.SetType(sym.STEXT)
811
812 for _, s := range ctxt.Textp {
813 windynrelocsym(ctxt, rel, s)
814 }
815
816 ctxt.Textp = append(ctxt.Textp, rel.Sym())
817 }
818
819 func dynrelocsym(ctxt *Link, s loader.Sym) {
820 target := &ctxt.Target
821 ldr := ctxt.loader
822 syms := &ctxt.ArchSyms
823 relocs := ldr.Relocs(s)
824 for ri := 0; ri < relocs.Count(); ri++ {
825 r := relocs.At(ri)
826 if r.IsMarker() {
827 continue
828 }
829 rSym := r.Sym()
830 if r.Weak() && !ldr.AttrReachable(rSym) {
831 continue
832 }
833 if ctxt.BuildMode == BuildModePIE && ctxt.LinkMode == LinkInternal {
834
835
836
837 thearch.Adddynrel(target, ldr, syms, s, r, ri)
838 continue
839 }
840
841 if rSym != 0 && ldr.SymType(rSym) == sym.SDYNIMPORT || r.Type() >= objabi.ElfRelocOffset {
842 if rSym != 0 && !ldr.AttrReachable(rSym) {
843 ctxt.Errorf(s, "dynamic relocation to unreachable symbol %s", ldr.SymName(rSym))
844 }
845 if !thearch.Adddynrel(target, ldr, syms, s, r, ri) {
846 ctxt.Errorf(s, "unsupported dynamic relocation for symbol %s (type=%d (%s) stype=%d (%s))", ldr.SymName(rSym), r.Type(), sym.RelocName(ctxt.Arch, r.Type()), ldr.SymType(rSym), ldr.SymType(rSym))
847 }
848 }
849 }
850 }
851
852 func (state *dodataState) dynreloc(ctxt *Link) {
853 if ctxt.HeadType == objabi.Hwindows {
854 return
855 }
856
857
858 if *FlagD {
859 return
860 }
861
862 for _, s := range ctxt.Textp {
863 dynrelocsym(ctxt, s)
864 }
865 for _, syms := range state.data {
866 for _, s := range syms {
867 dynrelocsym(ctxt, s)
868 }
869 }
870 if ctxt.IsELF {
871 elfdynhash(ctxt)
872 }
873 }
874
875 func CodeblkPad(ctxt *Link, out *OutBuf, addr int64, size int64, pad []byte) {
876 writeBlocks(ctxt, out, ctxt.outSem, ctxt.loader, ctxt.Textp, addr, size, pad)
877 }
878
879 const blockSize = 1 << 20
880
881
882
883
884
885
886 func writeBlocks(ctxt *Link, out *OutBuf, sem chan int, ldr *loader.Loader, syms []loader.Sym, addr, size int64, pad []byte) {
887 for i, s := range syms {
888 if ldr.SymValue(s) >= addr && !ldr.AttrSubSymbol(s) {
889 syms = syms[i:]
890 break
891 }
892 }
893
894 var wg sync.WaitGroup
895 max, lastAddr, written := int64(blockSize), addr+size, int64(0)
896 for addr < lastAddr {
897
898 idx := -1
899 for i, s := range syms {
900 if ldr.AttrSubSymbol(s) {
901 continue
902 }
903
904
905
906 end := ldr.SymValue(s) + ldr.SymSize(s)
907 if end > lastAddr {
908 break
909 }
910
911
912 idx = i
913
914
915 if end > addr+max {
916 break
917 }
918 }
919
920
921 if idx < 0 {
922 break
923 }
924
925
926
927
928
929
930 length := int64(0)
931 if idx+1 < len(syms) {
932
933
934
935 next := syms[idx+1]
936 for ldr.AttrSubSymbol(next) {
937 idx++
938 next = syms[idx+1]
939 }
940 length = ldr.SymValue(next) - addr
941 }
942 if length == 0 || length > lastAddr-addr {
943 length = lastAddr - addr
944 }
945
946
947 if o, err := out.View(uint64(out.Offset() + written)); err == nil {
948 sem <- 1
949 wg.Add(1)
950 go func(o *OutBuf, ldr *loader.Loader, syms []loader.Sym, addr, size int64, pad []byte) {
951 writeBlock(ctxt, o, ldr, syms, addr, size, pad)
952 wg.Done()
953 <-sem
954 }(o, ldr, syms, addr, length, pad)
955 } else {
956 writeBlock(ctxt, out, ldr, syms, addr, length, pad)
957 }
958
959
960 if idx != -1 {
961 syms = syms[idx+1:]
962 }
963 written += length
964 addr += length
965 }
966 wg.Wait()
967 }
968
969 func writeBlock(ctxt *Link, out *OutBuf, ldr *loader.Loader, syms []loader.Sym, addr, size int64, pad []byte) {
970
971 st := ctxt.makeRelocSymState()
972
973
974
975
976
977 eaddr := addr + size
978 for _, s := range syms {
979 if ldr.AttrSubSymbol(s) {
980 continue
981 }
982 val := ldr.SymValue(s)
983 if val >= eaddr {
984 break
985 }
986 if val < addr {
987 ldr.Errorf(s, "phase error: addr=%#x but sym=%#x type=%v sect=%v", addr, val, ldr.SymType(s), ldr.SymSect(s).Name)
988 errorexit()
989 }
990 if addr < val {
991 out.WriteStringPad("", int(val-addr), pad)
992 addr = val
993 }
994 P := out.WriteSym(ldr, s)
995 st.relocsym(s, P)
996 if f, ok := ctxt.generatorSyms[s]; ok {
997 f(ctxt, s)
998 }
999 addr += int64(len(P))
1000 siz := ldr.SymSize(s)
1001 if addr < val+siz {
1002 out.WriteStringPad("", int(val+siz-addr), pad)
1003 addr = val + siz
1004 }
1005 if addr != val+siz {
1006 ldr.Errorf(s, "phase error: addr=%#x value+size=%#x", addr, val+siz)
1007 errorexit()
1008 }
1009 if val+siz >= eaddr {
1010 break
1011 }
1012 }
1013
1014 if addr < eaddr {
1015 out.WriteStringPad("", int(eaddr-addr), pad)
1016 }
1017 }
1018
1019 type writeFn func(*Link, *OutBuf, int64, int64)
1020
1021
1022 func writeParallel(wg *sync.WaitGroup, fn writeFn, ctxt *Link, seek, vaddr, length uint64) {
1023 if out, err := ctxt.Out.View(seek); err != nil {
1024 ctxt.Out.SeekSet(int64(seek))
1025 fn(ctxt, ctxt.Out, int64(vaddr), int64(length))
1026 } else {
1027 wg.Add(1)
1028 go func() {
1029 defer wg.Done()
1030 fn(ctxt, out, int64(vaddr), int64(length))
1031 }()
1032 }
1033 }
1034
1035 func datblk(ctxt *Link, out *OutBuf, addr, size int64) {
1036 writeDatblkToOutBuf(ctxt, out, addr, size)
1037 }
1038
1039
1040 func DatblkBytes(ctxt *Link, addr int64, size int64) []byte {
1041 buf := make([]byte, size)
1042 out := &OutBuf{heap: buf}
1043 writeDatblkToOutBuf(ctxt, out, addr, size)
1044 return buf
1045 }
1046
1047 func writeDatblkToOutBuf(ctxt *Link, out *OutBuf, addr int64, size int64) {
1048 writeBlocks(ctxt, out, ctxt.outSem, ctxt.loader, ctxt.datap, addr, size, zeros[:])
1049 }
1050
1051 func dwarfblk(ctxt *Link, out *OutBuf, addr int64, size int64) {
1052
1053
1054
1055
1056
1057
1058 n := 0
1059 for i := range dwarfp {
1060 n += len(dwarfp[i].syms)
1061 }
1062 syms := make([]loader.Sym, 0, n)
1063 for i := range dwarfp {
1064 syms = append(syms, dwarfp[i].syms...)
1065 }
1066 writeBlocks(ctxt, out, ctxt.outSem, ctxt.loader, syms, addr, size, zeros[:])
1067 }
1068
1069 var zeros [512]byte
1070
1071 var (
1072 strdata = make(map[string]string)
1073 strnames []string
1074 )
1075
1076 func addstrdata1(ctxt *Link, arg string) {
1077 eq := strings.Index(arg, "=")
1078 dot := strings.LastIndex(arg[:eq+1], ".")
1079 if eq < 0 || dot < 0 {
1080 Exitf("-X flag requires argument of the form importpath.name=value")
1081 }
1082 pkg := arg[:dot]
1083 if ctxt.BuildMode == BuildModePlugin && pkg == "main" {
1084 pkg = *flagPluginPath
1085 }
1086 pkg = objabi.PathToPrefix(pkg)
1087 name := pkg + arg[dot:eq]
1088 value := arg[eq+1:]
1089 if _, ok := strdata[name]; !ok {
1090 strnames = append(strnames, name)
1091 }
1092 strdata[name] = value
1093 }
1094
1095
1096 func addstrdata(arch *sys.Arch, l *loader.Loader, name, value string) {
1097 s := l.Lookup(name, 0)
1098 if s == 0 {
1099 return
1100 }
1101 if goType := l.SymGoType(s); goType == 0 {
1102 return
1103 } else if typeName := l.SymName(goType); typeName != "type.string" {
1104 Errorf(nil, "%s: cannot set with -X: not a var of type string (%s)", name, typeName)
1105 return
1106 }
1107 if !l.AttrReachable(s) {
1108 return
1109 }
1110 bld := l.MakeSymbolUpdater(s)
1111 if bld.Type() == sym.SBSS {
1112 bld.SetType(sym.SDATA)
1113 }
1114
1115 p := fmt.Sprintf("%s.str", name)
1116 sbld := l.CreateSymForUpdate(p, 0)
1117 sbld.Addstring(value)
1118 sbld.SetType(sym.SRODATA)
1119
1120 bld.SetSize(0)
1121 bld.SetData(make([]byte, 0, arch.PtrSize*2))
1122 bld.SetReadOnly(false)
1123 bld.ResetRelocs()
1124 bld.AddAddrPlus(arch, sbld.Sym(), 0)
1125 bld.AddUint(arch, uint64(len(value)))
1126 }
1127
1128 func (ctxt *Link) dostrdata() {
1129 for _, name := range strnames {
1130 addstrdata(ctxt.Arch, ctxt.loader, name, strdata[name])
1131 }
1132 }
1133
1134
1135
1136 func addgostring(ctxt *Link, ldr *loader.Loader, s *loader.SymbolBuilder, symname, str string) {
1137 sdata := ldr.CreateSymForUpdate(symname, 0)
1138 if sdata.Type() != sym.Sxxx {
1139 ctxt.Errorf(s.Sym(), "duplicate symname in addgostring: %s", symname)
1140 }
1141 sdata.SetLocal(true)
1142 sdata.SetType(sym.SRODATA)
1143 sdata.SetSize(int64(len(str)))
1144 sdata.SetData([]byte(str))
1145 s.AddAddr(ctxt.Arch, sdata.Sym())
1146 s.AddUint(ctxt.Arch, uint64(len(str)))
1147 }
1148
1149 func addinitarrdata(ctxt *Link, ldr *loader.Loader, s loader.Sym) {
1150 p := ldr.SymName(s) + ".ptr"
1151 sp := ldr.CreateSymForUpdate(p, 0)
1152 sp.SetType(sym.SINITARR)
1153 sp.SetSize(0)
1154 sp.SetDuplicateOK(true)
1155 sp.AddAddr(ctxt.Arch, s)
1156 }
1157
1158
1159 func symalign(ldr *loader.Loader, s loader.Sym) int32 {
1160 min := int32(thearch.Minalign)
1161 align := ldr.SymAlign(s)
1162 if align >= min {
1163 return align
1164 } else if align != 0 {
1165 return min
1166 }
1167
1168 sname := ldr.SymName(s)
1169 if strings.HasPrefix(sname, "go.string.") || strings.HasPrefix(sname, "type..namedata.") {
1170
1171
1172 return min
1173 }
1174 align = int32(thearch.Maxalign)
1175 ssz := ldr.SymSize(s)
1176 for int64(align) > ssz && align > min {
1177 align >>= 1
1178 }
1179 ldr.SetSymAlign(s, align)
1180 return align
1181 }
1182
1183 func aligndatsize(state *dodataState, datsize int64, s loader.Sym) int64 {
1184 return Rnd(datsize, int64(symalign(state.ctxt.loader, s)))
1185 }
1186
1187 const debugGCProg = false
1188
1189 type GCProg struct {
1190 ctxt *Link
1191 sym *loader.SymbolBuilder
1192 w gcprog.Writer
1193 }
1194
1195 func (p *GCProg) Init(ctxt *Link, name string) {
1196 p.ctxt = ctxt
1197 p.sym = ctxt.loader.CreateSymForUpdate(name, 0)
1198 p.w.Init(p.writeByte())
1199 if debugGCProg {
1200 fmt.Fprintf(os.Stderr, "ld: start GCProg %s\n", name)
1201 p.w.Debug(os.Stderr)
1202 }
1203 }
1204
1205 func (p *GCProg) writeByte() func(x byte) {
1206 return func(x byte) {
1207 p.sym.AddUint8(x)
1208 }
1209 }
1210
1211 func (p *GCProg) End(size int64) {
1212 p.w.ZeroUntil(size / int64(p.ctxt.Arch.PtrSize))
1213 p.w.End()
1214 if debugGCProg {
1215 fmt.Fprintf(os.Stderr, "ld: end GCProg\n")
1216 }
1217 }
1218
1219 func (p *GCProg) AddSym(s loader.Sym) {
1220 ldr := p.ctxt.loader
1221 typ := ldr.SymGoType(s)
1222
1223
1224
1225 if typ == 0 {
1226 switch ldr.SymName(s) {
1227 case "runtime.data", "runtime.edata", "runtime.bss", "runtime.ebss":
1228
1229
1230
1231 return
1232 }
1233 p.ctxt.Errorf(p.sym.Sym(), "missing Go type information for global symbol %s: size %d", ldr.SymName(s), ldr.SymSize(s))
1234 return
1235 }
1236
1237 ptrsize := int64(p.ctxt.Arch.PtrSize)
1238 typData := ldr.Data(typ)
1239 nptr := decodetypePtrdata(p.ctxt.Arch, typData) / ptrsize
1240
1241 if debugGCProg {
1242 fmt.Fprintf(os.Stderr, "gcprog sym: %s at %d (ptr=%d+%d)\n", ldr.SymName(s), ldr.SymValue(s), ldr.SymValue(s)/ptrsize, nptr)
1243 }
1244
1245 sval := ldr.SymValue(s)
1246 if decodetypeUsegcprog(p.ctxt.Arch, typData) == 0 {
1247
1248 mask := decodetypeGcmask(p.ctxt, typ)
1249 for i := int64(0); i < nptr; i++ {
1250 if (mask[i/8]>>uint(i%8))&1 != 0 {
1251 p.w.Ptr(sval/ptrsize + i)
1252 }
1253 }
1254 return
1255 }
1256
1257
1258 prog := decodetypeGcprog(p.ctxt, typ)
1259 p.w.ZeroUntil(sval / ptrsize)
1260 p.w.Append(prog[4:], nptr)
1261 }
1262
1263
1264
1265 const cutoff = 2e9
1266
1267 func (state *dodataState) checkdatsize(symn sym.SymKind) {
1268 if state.datsize > cutoff {
1269 Errorf(nil, "too much data in section %v (over %v bytes)", symn, cutoff)
1270 }
1271 }
1272
1273
1274 func fixZeroSizedSymbols(ctxt *Link) {
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298 if !(ctxt.DynlinkingGo() && ctxt.HeadType == objabi.Hdarwin) && !(ctxt.HeadType == objabi.Haix && ctxt.LinkMode == LinkExternal) {
1299 return
1300 }
1301
1302 ldr := ctxt.loader
1303 bss := ldr.CreateSymForUpdate("runtime.bss", 0)
1304 bss.SetSize(8)
1305 ldr.SetAttrSpecial(bss.Sym(), false)
1306
1307 ebss := ldr.CreateSymForUpdate("runtime.ebss", 0)
1308 ldr.SetAttrSpecial(ebss.Sym(), false)
1309
1310 data := ldr.CreateSymForUpdate("runtime.data", 0)
1311 data.SetSize(8)
1312 ldr.SetAttrSpecial(data.Sym(), false)
1313
1314 edata := ldr.CreateSymForUpdate("runtime.edata", 0)
1315 ldr.SetAttrSpecial(edata.Sym(), false)
1316
1317 if ctxt.HeadType == objabi.Haix {
1318
1319 edata.SetType(sym.SXCOFFTOC)
1320 }
1321
1322 types := ldr.CreateSymForUpdate("runtime.types", 0)
1323 types.SetType(sym.STYPE)
1324 types.SetSize(8)
1325 ldr.SetAttrSpecial(types.Sym(), false)
1326
1327 etypes := ldr.CreateSymForUpdate("runtime.etypes", 0)
1328 etypes.SetType(sym.SFUNCTAB)
1329 ldr.SetAttrSpecial(etypes.Sym(), false)
1330
1331 if ctxt.HeadType == objabi.Haix {
1332 rodata := ldr.CreateSymForUpdate("runtime.rodata", 0)
1333 rodata.SetType(sym.SSTRING)
1334 rodata.SetSize(8)
1335 ldr.SetAttrSpecial(rodata.Sym(), false)
1336
1337 erodata := ldr.CreateSymForUpdate("runtime.erodata", 0)
1338 ldr.SetAttrSpecial(erodata.Sym(), false)
1339 }
1340 }
1341
1342
1343 func (state *dodataState) makeRelroForSharedLib(target *Link) {
1344 if !target.UseRelro() {
1345 return
1346 }
1347
1348
1349
1350
1351 ldr := target.loader
1352 for _, symnro := range sym.ReadOnly {
1353 symnrelro := sym.RelROMap[symnro]
1354
1355 ro := []loader.Sym{}
1356 relro := state.data[symnrelro]
1357
1358 for _, s := range state.data[symnro] {
1359 relocs := ldr.Relocs(s)
1360 isRelro := relocs.Count() > 0
1361 switch state.symType(s) {
1362 case sym.STYPE, sym.STYPERELRO, sym.SGOFUNCRELRO:
1363
1364
1365
1366 isRelro = true
1367 case sym.SFUNCTAB:
1368 if ldr.SymName(s) == "runtime.etypes" {
1369
1370
1371 isRelro = true
1372 }
1373 }
1374 if isRelro {
1375 state.setSymType(s, symnrelro)
1376 if outer := ldr.OuterSym(s); outer != 0 {
1377 state.setSymType(outer, symnrelro)
1378 }
1379 relro = append(relro, s)
1380 } else {
1381 ro = append(ro, s)
1382 }
1383 }
1384
1385
1386
1387
1388
1389 for _, s := range relro {
1390 if outer := ldr.OuterSym(s); outer != 0 {
1391 st := state.symType(s)
1392 ost := state.symType(outer)
1393 if st != ost {
1394 state.ctxt.Errorf(s, "inconsistent types for symbol and its Outer %s (%v != %v)",
1395 ldr.SymName(outer), st, ost)
1396 }
1397 }
1398 }
1399
1400 state.data[symnro] = ro
1401 state.data[symnrelro] = relro
1402 }
1403 }
1404
1405
1406
1407
1408 type dodataState struct {
1409
1410 ctxt *Link
1411
1412 data [sym.SXREF][]loader.Sym
1413
1414 dataMaxAlign [sym.SXREF]int32
1415
1416 symGroupType []sym.SymKind
1417
1418 datsize int64
1419 }
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433 func (state *dodataState) symType(s loader.Sym) sym.SymKind {
1434 if int(s) < len(state.symGroupType) {
1435 if override := state.symGroupType[s]; override != 0 {
1436 return override
1437 }
1438 }
1439 return state.ctxt.loader.SymType(s)
1440 }
1441
1442
1443 func (state *dodataState) setSymType(s loader.Sym, kind sym.SymKind) {
1444 if s == 0 {
1445 panic("bad")
1446 }
1447 if int(s) < len(state.symGroupType) {
1448 state.symGroupType[s] = kind
1449 } else {
1450 su := state.ctxt.loader.MakeSymbolUpdater(s)
1451 su.SetType(kind)
1452 }
1453 }
1454
1455 func (ctxt *Link) dodata(symGroupType []sym.SymKind) {
1456
1457
1458 fixZeroSizedSymbols(ctxt)
1459
1460
1461 state := dodataState{ctxt: ctxt, symGroupType: symGroupType}
1462 ldr := ctxt.loader
1463 for s := loader.Sym(1); s < loader.Sym(ldr.NSym()); s++ {
1464 if !ldr.AttrReachable(s) || ldr.AttrSpecial(s) || ldr.AttrSubSymbol(s) ||
1465 !ldr.TopLevelSym(s) {
1466 continue
1467 }
1468
1469 st := state.symType(s)
1470
1471 if st <= sym.STEXT || st >= sym.SXREF {
1472 continue
1473 }
1474 state.data[st] = append(state.data[st], s)
1475
1476
1477 if ldr.AttrOnList(s) {
1478 log.Fatalf("symbol %s listed multiple times", ldr.SymName(s))
1479 }
1480 ldr.SetAttrOnList(s, true)
1481 }
1482
1483
1484
1485
1486
1487
1488
1489 if ctxt.HeadType == objabi.Hdarwin {
1490 machosymorder(ctxt)
1491 }
1492 state.dynreloc(ctxt)
1493
1494
1495 state.makeRelroForSharedLib(ctxt)
1496
1497
1498
1499
1500
1501 lastSym := loader.Sym(ldr.NSym() - 1)
1502 ldr.SetSymAlign(lastSym, ldr.SymAlign(lastSym))
1503
1504
1505 var wg sync.WaitGroup
1506 for symn := range state.data {
1507 symn := sym.SymKind(symn)
1508 wg.Add(1)
1509 go func() {
1510 state.data[symn], state.dataMaxAlign[symn] = state.dodataSect(ctxt, symn, state.data[symn])
1511 wg.Done()
1512 }()
1513 }
1514 wg.Wait()
1515
1516 if ctxt.IsELF {
1517
1518
1519 syms := state.data[sym.SELFROSECT]
1520 reli, plti := -1, -1
1521 for i, s := range syms {
1522 switch ldr.SymName(s) {
1523 case ".rel.plt", ".rela.plt":
1524 plti = i
1525 case ".rel", ".rela":
1526 reli = i
1527 }
1528 }
1529 if reli >= 0 && plti >= 0 && plti != reli+1 {
1530 var first, second int
1531 if plti > reli {
1532 first, second = reli, plti
1533 } else {
1534 first, second = plti, reli
1535 }
1536 rel, plt := syms[reli], syms[plti]
1537 copy(syms[first+2:], syms[first+1:second])
1538 syms[first+0] = rel
1539 syms[first+1] = plt
1540
1541
1542
1543
1544
1545 ldr.SetSymAlign(rel, int32(ctxt.Arch.RegSize))
1546 ldr.SetSymAlign(plt, int32(ctxt.Arch.RegSize))
1547 }
1548 state.data[sym.SELFROSECT] = syms
1549 }
1550
1551 if ctxt.HeadType == objabi.Haix && ctxt.LinkMode == LinkExternal {
1552
1553
1554 ldr.SetSymAlign(ldr.Lookup("runtime.data", 0), state.dataMaxAlign[sym.SDATA])
1555 ldr.SetSymAlign(ldr.Lookup("runtime.bss", 0), state.dataMaxAlign[sym.SBSS])
1556 }
1557
1558
1559
1560 state.allocateDataSections(ctxt)
1561
1562
1563
1564 state.allocateDwarfSections(ctxt)
1565
1566
1567 n := int16(1)
1568
1569 for _, sect := range Segtext.Sections {
1570 sect.Extnum = n
1571 n++
1572 }
1573 for _, sect := range Segrodata.Sections {
1574 sect.Extnum = n
1575 n++
1576 }
1577 for _, sect := range Segrelrodata.Sections {
1578 sect.Extnum = n
1579 n++
1580 }
1581 for _, sect := range Segdata.Sections {
1582 sect.Extnum = n
1583 n++
1584 }
1585 for _, sect := range Segdwarf.Sections {
1586 sect.Extnum = n
1587 n++
1588 }
1589 }
1590
1591
1592
1593
1594
1595 func (state *dodataState) allocateDataSectionForSym(seg *sym.Segment, s loader.Sym, rwx int) *sym.Section {
1596 ldr := state.ctxt.loader
1597 sname := ldr.SymName(s)
1598 sect := addsection(ldr, state.ctxt.Arch, seg, sname, rwx)
1599 sect.Align = symalign(ldr, s)
1600 state.datsize = Rnd(state.datsize, int64(sect.Align))
1601 sect.Vaddr = uint64(state.datsize)
1602 return sect
1603 }
1604
1605
1606
1607
1608
1609
1610 func (state *dodataState) allocateNamedDataSection(seg *sym.Segment, sName string, types []sym.SymKind, rwx int) *sym.Section {
1611 sect := addsection(state.ctxt.loader, state.ctxt.Arch, seg, sName, rwx)
1612 if len(types) == 0 {
1613 sect.Align = 1
1614 } else if len(types) == 1 {
1615 sect.Align = state.dataMaxAlign[types[0]]
1616 } else {
1617 for _, symn := range types {
1618 align := state.dataMaxAlign[symn]
1619 if sect.Align < align {
1620 sect.Align = align
1621 }
1622 }
1623 }
1624 state.datsize = Rnd(state.datsize, int64(sect.Align))
1625 sect.Vaddr = uint64(state.datsize)
1626 return sect
1627 }
1628
1629
1630
1631
1632
1633
1634
1635 func (state *dodataState) assignDsymsToSection(sect *sym.Section, syms []loader.Sym, forceType sym.SymKind, aligner func(state *dodataState, datsize int64, s loader.Sym) int64) {
1636 ldr := state.ctxt.loader
1637 for _, s := range syms {
1638 state.datsize = aligner(state, state.datsize, s)
1639 ldr.SetSymSect(s, sect)
1640 if forceType != sym.Sxxx {
1641 state.setSymType(s, forceType)
1642 }
1643 ldr.SetSymValue(s, int64(uint64(state.datsize)-sect.Vaddr))
1644 state.datsize += ldr.SymSize(s)
1645 }
1646 sect.Length = uint64(state.datsize) - sect.Vaddr
1647 }
1648
1649 func (state *dodataState) assignToSection(sect *sym.Section, symn sym.SymKind, forceType sym.SymKind) {
1650 state.assignDsymsToSection(sect, state.data[symn], forceType, aligndatsize)
1651 state.checkdatsize(symn)
1652 }
1653
1654
1655
1656
1657
1658
1659
1660 func (state *dodataState) allocateSingleSymSections(seg *sym.Segment, symn sym.SymKind, forceType sym.SymKind, rwx int) {
1661 ldr := state.ctxt.loader
1662 for _, s := range state.data[symn] {
1663 sect := state.allocateDataSectionForSym(seg, s, rwx)
1664 ldr.SetSymSect(s, sect)
1665 state.setSymType(s, forceType)
1666 ldr.SetSymValue(s, int64(uint64(state.datsize)-sect.Vaddr))
1667 state.datsize += ldr.SymSize(s)
1668 sect.Length = uint64(state.datsize) - sect.Vaddr
1669 }
1670 state.checkdatsize(symn)
1671 }
1672
1673
1674
1675
1676
1677
1678
1679
1680 func (state *dodataState) allocateNamedSectionAndAssignSyms(seg *sym.Segment, secName string, symn sym.SymKind, forceType sym.SymKind, rwx int) *sym.Section {
1681
1682 sect := state.allocateNamedDataSection(seg, secName, []sym.SymKind{symn}, rwx)
1683 state.assignDsymsToSection(sect, state.data[symn], forceType, aligndatsize)
1684 return sect
1685 }
1686
1687
1688
1689 func (state *dodataState) allocateDataSections(ctxt *Link) {
1690
1691
1692
1693
1694
1695
1696 writable := []sym.SymKind{
1697 sym.SBUILDINFO,
1698 sym.SELFSECT,
1699 sym.SMACHO,
1700 sym.SMACHOGOT,
1701 sym.SWINDOWS,
1702 }
1703 for _, symn := range writable {
1704 state.allocateSingleSymSections(&Segdata, symn, sym.SDATA, 06)
1705 }
1706 ldr := ctxt.loader
1707
1708
1709 if len(state.data[sym.SELFGOT]) > 0 {
1710 sect := state.allocateNamedSectionAndAssignSyms(&Segdata, ".got", sym.SELFGOT, sym.SDATA, 06)
1711 if ctxt.IsPPC64() {
1712 for _, s := range state.data[sym.SELFGOT] {
1713
1714
1715 toc := ldr.Lookup(".TOC.", int(ldr.SymVersion(s)))
1716 if toc != 0 {
1717 ldr.SetSymSect(toc, sect)
1718 ldr.AddInteriorSym(s, toc)
1719 ldr.SetSymValue(toc, 0x8000)
1720 }
1721 }
1722 }
1723 }
1724
1725
1726 sect := state.allocateNamedSectionAndAssignSyms(&Segdata, ".noptrdata", sym.SNOPTRDATA, sym.SDATA, 06)
1727 ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.noptrdata", 0), sect)
1728 ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.enoptrdata", 0), sect)
1729
1730 hasinitarr := ctxt.linkShared
1731
1732
1733 switch ctxt.BuildMode {
1734 case BuildModeCArchive, BuildModeCShared, BuildModeShared, BuildModePlugin:
1735 hasinitarr = true
1736 }
1737
1738 if ctxt.HeadType == objabi.Haix {
1739 if len(state.data[sym.SINITARR]) > 0 {
1740 Errorf(nil, "XCOFF format doesn't allow .init_array section")
1741 }
1742 }
1743
1744 if hasinitarr && len(state.data[sym.SINITARR]) > 0 {
1745 state.allocateNamedSectionAndAssignSyms(&Segdata, ".init_array", sym.SINITARR, sym.Sxxx, 06)
1746 }
1747
1748
1749 sect = state.allocateNamedSectionAndAssignSyms(&Segdata, ".data", sym.SDATA, sym.SDATA, 06)
1750 ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.data", 0), sect)
1751 ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.edata", 0), sect)
1752 dataGcEnd := state.datsize - int64(sect.Vaddr)
1753
1754
1755
1756 state.assignToSection(sect, sym.SXCOFFTOC, sym.SDATA)
1757 state.checkdatsize(sym.SDATA)
1758 sect.Length = uint64(state.datsize) - sect.Vaddr
1759
1760
1761 sect = state.allocateNamedSectionAndAssignSyms(&Segdata, ".bss", sym.SBSS, sym.Sxxx, 06)
1762 ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.bss", 0), sect)
1763 ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.ebss", 0), sect)
1764 bssGcEnd := state.datsize - int64(sect.Vaddr)
1765
1766
1767 gcsToEmit := []struct {
1768 symName string
1769 symKind sym.SymKind
1770 gcEnd int64
1771 }{
1772 {"runtime.gcdata", sym.SDATA, dataGcEnd},
1773 {"runtime.gcbss", sym.SBSS, bssGcEnd},
1774 }
1775 for _, g := range gcsToEmit {
1776 var gc GCProg
1777 gc.Init(ctxt, g.symName)
1778 for _, s := range state.data[g.symKind] {
1779 gc.AddSym(s)
1780 }
1781 gc.End(g.gcEnd)
1782 }
1783
1784
1785 sect = state.allocateNamedSectionAndAssignSyms(&Segdata, ".noptrbss", sym.SNOPTRBSS, sym.Sxxx, 06)
1786 ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.noptrbss", 0), sect)
1787 ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.enoptrbss", 0), sect)
1788 ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.end", 0), sect)
1789
1790
1791 if len(state.data[sym.SLIBFUZZER_EXTRA_COUNTER]) > 0 {
1792 state.allocateNamedSectionAndAssignSyms(&Segdata, "__libfuzzer_extra_counters", sym.SLIBFUZZER_EXTRA_COUNTER, sym.Sxxx, 06)
1793 }
1794
1795 if len(state.data[sym.STLSBSS]) > 0 {
1796 var sect *sym.Section
1797
1798 if (ctxt.IsELF || ctxt.HeadType == objabi.Haix) && (ctxt.LinkMode == LinkExternal || !*FlagD) {
1799 sect = addsection(ldr, ctxt.Arch, &Segdata, ".tbss", 06)
1800 sect.Align = int32(ctxt.Arch.PtrSize)
1801
1802 sect.Vaddr = 0
1803 }
1804 state.datsize = 0
1805
1806 for _, s := range state.data[sym.STLSBSS] {
1807 state.datsize = aligndatsize(state, state.datsize, s)
1808 if sect != nil {
1809 ldr.SetSymSect(s, sect)
1810 }
1811 ldr.SetSymValue(s, state.datsize)
1812 state.datsize += ldr.SymSize(s)
1813 }
1814 state.checkdatsize(sym.STLSBSS)
1815
1816 if sect != nil {
1817 sect.Length = uint64(state.datsize)
1818 }
1819 }
1820
1821
1830 var segro *sym.Segment
1831 if ctxt.IsELF && ctxt.LinkMode == LinkInternal {
1832 segro = &Segrodata
1833 } else if ctxt.HeadType == objabi.Hwindows {
1834 segro = &Segrodata
1835 } else {
1836 segro = &Segtext
1837 }
1838
1839 state.datsize = 0
1840
1841
1842 if len(state.data[sym.STEXT]) != 0 {
1843 culprit := ldr.SymName(state.data[sym.STEXT][0])
1844 Errorf(nil, "dodata found an sym.STEXT symbol: %s", culprit)
1845 }
1846 state.allocateSingleSymSections(&Segtext, sym.SELFRXSECT, sym.SRODATA, 05)
1847 state.allocateSingleSymSections(&Segtext, sym.SMACHOPLT, sym.SRODATA, 05)
1848
1849
1850 sect = state.allocateNamedDataSection(segro, ".rodata", sym.ReadOnly, 04)
1851 ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.rodata", 0), sect)
1852 ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.erodata", 0), sect)
1853 if !ctxt.UseRelro() {
1854 ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.types", 0), sect)
1855 ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.etypes", 0), sect)
1856 }
1857 for _, symn := range sym.ReadOnly {
1858 symnStartValue := state.datsize
1859 state.assignToSection(sect, symn, sym.SRODATA)
1860 setCarrierSize(symn, state.datsize-symnStartValue)
1861 if ctxt.HeadType == objabi.Haix {
1862
1863
1864
1865
1866 xcoffUpdateOuterSize(ctxt, state.datsize-symnStartValue, symn)
1867 }
1868 }
1869
1870
1871 state.allocateSingleSymSections(segro, sym.SELFROSECT, sym.SRODATA, 04)
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883 const relroPerm = 06
1884 const fallbackPerm = 04
1885 relroSecPerm := fallbackPerm
1886 genrelrosecname := func(suffix string) string {
1887 if suffix == "" {
1888 return ".rodata"
1889 }
1890 return suffix
1891 }
1892 seg := segro
1893
1894 if ctxt.UseRelro() {
1895 segrelro := &Segrelrodata
1896 if ctxt.LinkMode == LinkExternal && !ctxt.IsAIX() && !ctxt.IsDarwin() {
1897
1898
1899
1900
1901
1902
1903 segrelro = segro
1904 } else {
1905
1906 state.datsize = 0
1907 }
1908
1909 if !ctxt.IsDarwin() {
1910 genrelrosecname = func(suffix string) string {
1911 return ".data.rel.ro" + suffix
1912 }
1913 }
1914
1915 relroReadOnly := []sym.SymKind{}
1916 for _, symnro := range sym.ReadOnly {
1917 symn := sym.RelROMap[symnro]
1918 relroReadOnly = append(relroReadOnly, symn)
1919 }
1920 seg = segrelro
1921 relroSecPerm = relroPerm
1922
1923
1924 sect = state.allocateNamedDataSection(segrelro, genrelrosecname(""), relroReadOnly, relroSecPerm)
1925
1926 ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.types", 0), sect)
1927 ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.etypes", 0), sect)
1928
1929 for i, symnro := range sym.ReadOnly {
1930 if i == 0 && symnro == sym.STYPE && ctxt.HeadType != objabi.Haix {
1931
1932
1933
1934
1935 state.datsize++
1936 }
1937
1938 symn := sym.RelROMap[symnro]
1939 symnStartValue := state.datsize
1940
1941 for _, s := range state.data[symn] {
1942 outer := ldr.OuterSym(s)
1943 if s != 0 && ldr.SymSect(outer) != nil && ldr.SymSect(outer) != sect {
1944 ctxt.Errorf(s, "s.Outer (%s) in different section from s, %s != %s", ldr.SymName(outer), ldr.SymSect(outer).Name, sect.Name)
1945 }
1946 }
1947 state.assignToSection(sect, symn, sym.SRODATA)
1948 setCarrierSize(symn, state.datsize-symnStartValue)
1949 if ctxt.HeadType == objabi.Haix {
1950
1951
1952
1953
1954 xcoffUpdateOuterSize(ctxt, state.datsize-symnStartValue, symn)
1955 }
1956 }
1957
1958 sect.Length = uint64(state.datsize) - sect.Vaddr
1959 }
1960
1961
1962 sect = state.allocateNamedDataSection(seg, genrelrosecname(".typelink"), []sym.SymKind{sym.STYPELINK}, relroSecPerm)
1963
1964 typelink := ldr.CreateSymForUpdate("runtime.typelink", 0)
1965 ldr.SetSymSect(typelink.Sym(), sect)
1966 typelink.SetType(sym.SRODATA)
1967 state.datsize += typelink.Size()
1968 state.checkdatsize(sym.STYPELINK)
1969 sect.Length = uint64(state.datsize) - sect.Vaddr
1970
1971
1972 sect = state.allocateNamedDataSection(seg, genrelrosecname(".itablink"), []sym.SymKind{sym.SITABLINK}, relroSecPerm)
1973
1974 itablink := ldr.CreateSymForUpdate("runtime.itablink", 0)
1975 ldr.SetSymSect(itablink.Sym(), sect)
1976 itablink.SetType(sym.SRODATA)
1977 state.datsize += itablink.Size()
1978 state.checkdatsize(sym.SITABLINK)
1979 sect.Length = uint64(state.datsize) - sect.Vaddr
1980
1981
1982 sect = state.allocateNamedSectionAndAssignSyms(seg, genrelrosecname(".gosymtab"), sym.SSYMTAB, sym.SRODATA, relroSecPerm)
1983 ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.symtab", 0), sect)
1984 ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.esymtab", 0), sect)
1985
1986
1987 sect = state.allocateNamedSectionAndAssignSyms(seg, genrelrosecname(".gopclntab"), sym.SPCLNTAB, sym.SRODATA, relroSecPerm)
1988 ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.pclntab", 0), sect)
1989 ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.pcheader", 0), sect)
1990 ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.funcnametab", 0), sect)
1991 ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.cutab", 0), sect)
1992 ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.filetab", 0), sect)
1993 ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.pctab", 0), sect)
1994 ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.functab", 0), sect)
1995 ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.epclntab", 0), sect)
1996 setCarrierSize(sym.SPCLNTAB, int64(sect.Length))
1997 if ctxt.HeadType == objabi.Haix {
1998 xcoffUpdateOuterSize(ctxt, int64(sect.Length), sym.SPCLNTAB)
1999 }
2000
2001
2002 if state.datsize != int64(uint32(state.datsize)) {
2003 Errorf(nil, "read-only data segment too large: %d", state.datsize)
2004 }
2005
2006 siz := 0
2007 for symn := sym.SELFRXSECT; symn < sym.SXREF; symn++ {
2008 siz += len(state.data[symn])
2009 }
2010 ctxt.datap = make([]loader.Sym, 0, siz)
2011 for symn := sym.SELFRXSECT; symn < sym.SXREF; symn++ {
2012 ctxt.datap = append(ctxt.datap, state.data[symn]...)
2013 }
2014 }
2015
2016
2017
2018 func (state *dodataState) allocateDwarfSections(ctxt *Link) {
2019
2020 alignOne := func(state *dodataState, datsize int64, s loader.Sym) int64 { return datsize }
2021
2022 ldr := ctxt.loader
2023 for i := 0; i < len(dwarfp); i++ {
2024
2025 s := dwarfp[i].secSym()
2026 sect := state.allocateNamedDataSection(&Segdwarf, ldr.SymName(s), []sym.SymKind{}, 04)
2027 ldr.SetSymSect(s, sect)
2028 sect.Sym = sym.LoaderSym(s)
2029 curType := ldr.SymType(s)
2030 state.setSymType(s, sym.SRODATA)
2031 ldr.SetSymValue(s, int64(uint64(state.datsize)-sect.Vaddr))
2032 state.datsize += ldr.SymSize(s)
2033
2034
2035 subSyms := dwarfp[i].subSyms()
2036 state.assignDsymsToSection(sect, subSyms, sym.SRODATA, alignOne)
2037
2038 for j := 0; j < len(subSyms); j++ {
2039 s := subSyms[j]
2040 if ctxt.HeadType == objabi.Haix && curType == sym.SDWARFLOC {
2041
2042
2043 addDwsectCUSize(".debug_loc", ldr.SymPkg(s), uint64(ldr.SymSize(s)))
2044 }
2045 }
2046 sect.Length = uint64(state.datsize) - sect.Vaddr
2047 state.checkdatsize(curType)
2048 }
2049 }
2050
2051 type symNameSize struct {
2052 name string
2053 sz int64
2054 val int64
2055 sym loader.Sym
2056 }
2057
2058 func (state *dodataState) dodataSect(ctxt *Link, symn sym.SymKind, syms []loader.Sym) (result []loader.Sym, maxAlign int32) {
2059 var head, tail loader.Sym
2060 ldr := ctxt.loader
2061 sl := make([]symNameSize, len(syms))
2062 for k, s := range syms {
2063 ss := ldr.SymSize(s)
2064 sl[k] = symNameSize{name: ldr.SymName(s), sz: ss, sym: s}
2065 ds := int64(len(ldr.Data(s)))
2066 switch {
2067 case ss < ds:
2068 ctxt.Errorf(s, "initialize bounds (%d < %d)", ss, ds)
2069 case ss < 0:
2070 ctxt.Errorf(s, "negative size (%d bytes)", ss)
2071 case ss > cutoff:
2072 ctxt.Errorf(s, "symbol too large (%d bytes)", ss)
2073 }
2074
2075
2076
2077
2078 if (ctxt.DynlinkingGo() && ctxt.HeadType == objabi.Hdarwin) || (ctxt.HeadType == objabi.Haix && ctxt.LinkMode == LinkExternal) {
2079 switch ldr.SymName(s) {
2080 case "runtime.text", "runtime.bss", "runtime.data", "runtime.types", "runtime.rodata":
2081 head = s
2082 continue
2083 case "runtime.etext", "runtime.ebss", "runtime.edata", "runtime.etypes", "runtime.erodata":
2084 tail = s
2085 continue
2086 }
2087 }
2088 }
2089
2090
2091
2092
2093
2094 checkSize := symn != sym.SELFGOT
2095
2096
2097 if symn != sym.SPCLNTAB {
2098 sort.Slice(sl, func(i, j int) bool {
2099 si, sj := sl[i].sym, sl[j].sym
2100 switch {
2101 case si == head, sj == tail:
2102 return true
2103 case sj == head, si == tail:
2104 return false
2105 }
2106 if checkSize {
2107 isz := sl[i].sz
2108 jsz := sl[j].sz
2109 if isz != jsz {
2110 return isz < jsz
2111 }
2112 }
2113 iname := sl[i].name
2114 jname := sl[j].name
2115 if iname != jname {
2116 return iname < jname
2117 }
2118 return si < sj
2119 })
2120 } else {
2121
2122
2123 for k, s := range syms {
2124 sl[k].val = ldr.SymValue(s)
2125 }
2126 sort.Slice(sl, func(i, j int) bool { return sl[i].val < sl[j].val })
2127 }
2128
2129
2130 syms = syms[:0]
2131 for k := range sl {
2132 s := sl[k].sym
2133 if s != head && s != tail {
2134 align := symalign(ldr, s)
2135 if maxAlign < align {
2136 maxAlign = align
2137 }
2138 }
2139 syms = append(syms, s)
2140 }
2141
2142 return syms, maxAlign
2143 }
2144
2145
2146
2147
2148
2149
2150 func (ctxt *Link) textbuildid() {
2151 if ctxt.IsELF || ctxt.BuildMode == BuildModePlugin || *flagBuildid == "" {
2152 return
2153 }
2154
2155 ldr := ctxt.loader
2156 s := ldr.CreateSymForUpdate("go.buildid", 0)
2157
2158
2159 data := "\xff Go build ID: " + strconv.Quote(*flagBuildid) + "\n \xff"
2160 s.SetType(sym.STEXT)
2161 s.SetData([]byte(data))
2162 s.SetSize(int64(len(data)))
2163
2164 ctxt.Textp = append(ctxt.Textp, 0)
2165 copy(ctxt.Textp[1:], ctxt.Textp)
2166 ctxt.Textp[0] = s.Sym()
2167 }
2168
2169 func (ctxt *Link) buildinfo() {
2170 if ctxt.linkShared || ctxt.BuildMode == BuildModePlugin {
2171
2172
2173
2174
2175 return
2176 }
2177
2178 ldr := ctxt.loader
2179 s := ldr.CreateSymForUpdate(".go.buildinfo", 0)
2180
2181
2182 s.SetNotInSymbolTable(!ctxt.IsAIX())
2183 s.SetType(sym.SBUILDINFO)
2184 s.SetAlign(16)
2185
2186
2187 const prefix = "\xff Go buildinf:"
2188 data := make([]byte, 32)
2189 copy(data, prefix)
2190 data[len(prefix)] = byte(ctxt.Arch.PtrSize)
2191 data[len(prefix)+1] = 0
2192 if ctxt.Arch.ByteOrder == binary.BigEndian {
2193 data[len(prefix)+1] = 1
2194 }
2195 s.SetData(data)
2196 s.SetSize(int64(len(data)))
2197 r, _ := s.AddRel(objabi.R_ADDR)
2198 r.SetOff(16)
2199 r.SetSiz(uint8(ctxt.Arch.PtrSize))
2200 r.SetSym(ldr.LookupOrCreateSym("runtime.buildVersion", 0))
2201 r, _ = s.AddRel(objabi.R_ADDR)
2202 r.SetOff(16 + int32(ctxt.Arch.PtrSize))
2203 r.SetSiz(uint8(ctxt.Arch.PtrSize))
2204 r.SetSym(ldr.LookupOrCreateSym("runtime.modinfo", 0))
2205 }
2206
2207
2208 func (ctxt *Link) textaddress() {
2209 addsection(ctxt.loader, ctxt.Arch, &Segtext, ".text", 05)
2210
2211
2212
2213
2214 sect := Segtext.Sections[0]
2215
2216 sect.Align = int32(Funcalign)
2217
2218 ldr := ctxt.loader
2219
2220 text := ctxt.xdefine("runtime.text", sym.STEXT, 0)
2221 etext := ctxt.xdefine("runtime.etext", sym.STEXT, 0)
2222 ldr.SetSymSect(text, sect)
2223 if ctxt.IsAIX() && ctxt.IsExternal() {
2224
2225
2226
2227 u := ldr.MakeSymbolUpdater(text)
2228 u.SetAlign(sect.Align)
2229 u.SetSize(8)
2230 }
2231
2232 if (ctxt.DynlinkingGo() && ctxt.IsDarwin()) || (ctxt.IsAIX() && ctxt.IsExternal()) {
2233 ldr.SetSymSect(etext, sect)
2234 ctxt.Textp = append(ctxt.Textp, etext, 0)
2235 copy(ctxt.Textp[1:], ctxt.Textp)
2236 ctxt.Textp[0] = text
2237 }
2238
2239 start := uint64(Rnd(*FlagTextAddr, int64(Funcalign)))
2240 va := start
2241 n := 1
2242 sect.Vaddr = va
2243
2244 limit := thearch.TrampLimit
2245 if limit == 0 {
2246 limit = 1 << 63
2247 }
2248 if *FlagDebugTextSize != 0 {
2249 limit = uint64(*FlagDebugTextSize)
2250 }
2251 if *FlagDebugTramp > 1 {
2252 limit = 1
2253 }
2254
2255 if ctxt.IsAIX() && ctxt.IsExternal() {
2256
2257
2258
2259
2260
2261 limit = 1
2262 }
2263
2264
2265
2266 big := false
2267 for _, s := range ctxt.Textp {
2268 sect, n, va = assignAddress(ctxt, sect, n, s, va, false, big)
2269 if va-start >= limit {
2270 big = true
2271 break
2272 }
2273 }
2274
2275
2276
2277 if big {
2278
2279 for _, s := range ctxt.Textp {
2280 if ldr.OuterSym(s) != 0 || s == text {
2281 continue
2282 }
2283 oldv := ldr.SymValue(s)
2284 for sub := s; sub != 0; sub = ldr.SubSym(sub) {
2285 ldr.SetSymValue(sub, ldr.SymValue(sub)-oldv)
2286 }
2287 }
2288 va = start
2289
2290 ntramps := 0
2291 for _, s := range ctxt.Textp {
2292 sect, n, va = assignAddress(ctxt, sect, n, s, va, false, big)
2293
2294 trampoline(ctxt, s)
2295
2296
2297 for ; ntramps < len(ctxt.tramps); ntramps++ {
2298 tramp := ctxt.tramps[ntramps]
2299 if ctxt.IsAIX() && strings.HasPrefix(ldr.SymName(tramp), "runtime.text.") {
2300
2301 continue
2302 }
2303 sect, n, va = assignAddress(ctxt, sect, n, tramp, va, true, big)
2304 }
2305 }
2306
2307
2308 if ntramps != 0 {
2309 newtextp := make([]loader.Sym, 0, len(ctxt.Textp)+ntramps)
2310 i := 0
2311 for _, s := range ctxt.Textp {
2312 for ; i < ntramps && ldr.SymValue(ctxt.tramps[i]) < ldr.SymValue(s); i++ {
2313 newtextp = append(newtextp, ctxt.tramps[i])
2314 }
2315 newtextp = append(newtextp, s)
2316 }
2317 newtextp = append(newtextp, ctxt.tramps[i:ntramps]...)
2318
2319 ctxt.Textp = newtextp
2320 }
2321 }
2322
2323 sect.Length = va - sect.Vaddr
2324 ldr.SetSymSect(etext, sect)
2325 if ldr.SymValue(etext) == 0 {
2326
2327
2328 ldr.SetSymValue(etext, int64(va))
2329 ldr.SetSymValue(text, int64(Segtext.Sections[0].Vaddr))
2330 }
2331 }
2332
2333
2334 func assignAddress(ctxt *Link, sect *sym.Section, n int, s loader.Sym, va uint64, isTramp, big bool) (*sym.Section, int, uint64) {
2335 ldr := ctxt.loader
2336 if thearch.AssignAddress != nil {
2337 return thearch.AssignAddress(ldr, sect, n, s, va, isTramp)
2338 }
2339
2340 ldr.SetSymSect(s, sect)
2341 if ldr.AttrSubSymbol(s) {
2342 return sect, n, va
2343 }
2344
2345 align := ldr.SymAlign(s)
2346 if align == 0 {
2347 align = int32(Funcalign)
2348 }
2349 va = uint64(Rnd(int64(va), int64(align)))
2350 if sect.Align < align {
2351 sect.Align = align
2352 }
2353
2354 funcsize := uint64(MINFUNC)
2355 if ldr.SymSize(s) > MINFUNC {
2356 funcsize = uint64(ldr.SymSize(s))
2357 }
2358
2359
2360
2361
2362
2363 if big && splitTextSections(ctxt) && ldr.OuterSym(s) == 0 {
2364
2365
2366 var textSizelimit uint64 = thearch.TrampLimit
2367 if *FlagDebugTextSize != 0 {
2368 textSizelimit = uint64(*FlagDebugTextSize)
2369 }
2370
2371
2372
2373 if funcsize > textSizelimit {
2374 panic(fmt.Sprintf("error: text size limit %d less than text symbol %s size of %d", textSizelimit, ldr.SymName(s), funcsize))
2375 }
2376
2377 if va-sect.Vaddr+funcsize+maxSizeTrampolines(ctxt, ldr, s, isTramp) > textSizelimit {
2378 sectAlign := int32(thearch.Funcalign)
2379 if ctxt.IsPPC64() {
2380
2381
2382
2383
2384
2385
2386 const ppc64maxFuncalign = 64
2387 sectAlign = ppc64maxFuncalign
2388 va = uint64(Rnd(int64(va), ppc64maxFuncalign))
2389 }
2390
2391
2392 sect.Length = va - sect.Vaddr
2393
2394
2395 sect = addsection(ctxt.loader, ctxt.Arch, &Segtext, ".text", 05)
2396
2397 sect.Vaddr = va
2398 sect.Align = sectAlign
2399 ldr.SetSymSect(s, sect)
2400
2401
2402 ntext := ldr.CreateSymForUpdate(fmt.Sprintf("runtime.text.%d", n), 0)
2403 ntext.SetSect(sect)
2404 if ctxt.IsAIX() {
2405
2406
2407
2408 ntext.SetType(sym.STEXT)
2409 ntext.SetSize(int64(MINFUNC))
2410 ntext.SetOnList(true)
2411 ntext.SetAlign(sectAlign)
2412 ctxt.tramps = append(ctxt.tramps, ntext.Sym())
2413
2414 ntext.SetValue(int64(va))
2415 va += uint64(ntext.Size())
2416
2417 if align := ldr.SymAlign(s); align != 0 {
2418 va = uint64(Rnd(int64(va), int64(align)))
2419 } else {
2420 va = uint64(Rnd(int64(va), int64(Funcalign)))
2421 }
2422 }
2423 n++
2424 }
2425 }
2426
2427 ldr.SetSymValue(s, 0)
2428 for sub := s; sub != 0; sub = ldr.SubSym(sub) {
2429 ldr.SetSymValue(sub, ldr.SymValue(sub)+int64(va))
2430 if ctxt.Debugvlog > 2 {
2431 fmt.Println("assign text address:", ldr.SymName(sub), ldr.SymValue(sub))
2432 }
2433 }
2434
2435 va += funcsize
2436
2437 return sect, n, va
2438 }
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449 func splitTextSections(ctxt *Link) bool {
2450 return (ctxt.IsPPC64() || (ctxt.IsARM64() && ctxt.IsDarwin())) && ctxt.IsExternal()
2451 }
2452
2453
2454
2455 func (ctxt *Link) address() []*sym.Segment {
2456 var order []*sym.Segment
2457
2458 va := uint64(*FlagTextAddr)
2459 order = append(order, &Segtext)
2460 Segtext.Rwx = 05
2461 Segtext.Vaddr = va
2462 for _, s := range Segtext.Sections {
2463 va = uint64(Rnd(int64(va), int64(s.Align)))
2464 s.Vaddr = va
2465 va += s.Length
2466 }
2467
2468 Segtext.Length = va - uint64(*FlagTextAddr)
2469
2470 if len(Segrodata.Sections) > 0 {
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484 va = uint64(Rnd(int64(va), int64(*FlagRound)))
2485
2486 order = append(order, &Segrodata)
2487 Segrodata.Rwx = 04
2488 Segrodata.Vaddr = va
2489 for _, s := range Segrodata.Sections {
2490 va = uint64(Rnd(int64(va), int64(s.Align)))
2491 s.Vaddr = va
2492 va += s.Length
2493 }
2494
2495 Segrodata.Length = va - Segrodata.Vaddr
2496 }
2497 if len(Segrelrodata.Sections) > 0 {
2498
2499
2500 va = uint64(Rnd(int64(va), int64(*FlagRound)))
2501 if ctxt.HeadType == objabi.Haix {
2502
2503 va += uint64(XCOFFDATABASE) - uint64(XCOFFTEXTBASE)
2504 }
2505
2506 order = append(order, &Segrelrodata)
2507 Segrelrodata.Rwx = 06
2508 Segrelrodata.Vaddr = va
2509 for _, s := range Segrelrodata.Sections {
2510 va = uint64(Rnd(int64(va), int64(s.Align)))
2511 s.Vaddr = va
2512 va += s.Length
2513 }
2514
2515 Segrelrodata.Length = va - Segrelrodata.Vaddr
2516 }
2517
2518 va = uint64(Rnd(int64(va), int64(*FlagRound)))
2519 if ctxt.HeadType == objabi.Haix && len(Segrelrodata.Sections) == 0 {
2520
2521
2522
2523 va += uint64(XCOFFDATABASE) - uint64(XCOFFTEXTBASE)
2524 }
2525 order = append(order, &Segdata)
2526 Segdata.Rwx = 06
2527 Segdata.Vaddr = va
2528 var data *sym.Section
2529 var noptr *sym.Section
2530 var bss *sym.Section
2531 var noptrbss *sym.Section
2532 for i, s := range Segdata.Sections {
2533 if (ctxt.IsELF || ctxt.HeadType == objabi.Haix) && s.Name == ".tbss" {
2534 continue
2535 }
2536 vlen := int64(s.Length)
2537 if i+1 < len(Segdata.Sections) && !((ctxt.IsELF || ctxt.HeadType == objabi.Haix) && Segdata.Sections[i+1].Name == ".tbss") {
2538 vlen = int64(Segdata.Sections[i+1].Vaddr - s.Vaddr)
2539 }
2540 s.Vaddr = va
2541 va += uint64(vlen)
2542 Segdata.Length = va - Segdata.Vaddr
2543 if s.Name == ".data" {
2544 data = s
2545 }
2546 if s.Name == ".noptrdata" {
2547 noptr = s
2548 }
2549 if s.Name == ".bss" {
2550 bss = s
2551 }
2552 if s.Name == ".noptrbss" {
2553 noptrbss = s
2554 }
2555 }
2556
2557
2558
2559 Segdata.Filelen = bss.Vaddr - Segdata.Vaddr
2560
2561 va = uint64(Rnd(int64(va), int64(*FlagRound)))
2562 order = append(order, &Segdwarf)
2563 Segdwarf.Rwx = 06
2564 Segdwarf.Vaddr = va
2565 for i, s := range Segdwarf.Sections {
2566 vlen := int64(s.Length)
2567 if i+1 < len(Segdwarf.Sections) {
2568 vlen = int64(Segdwarf.Sections[i+1].Vaddr - s.Vaddr)
2569 }
2570 s.Vaddr = va
2571 va += uint64(vlen)
2572 if ctxt.HeadType == objabi.Hwindows {
2573 va = uint64(Rnd(int64(va), PEFILEALIGN))
2574 }
2575 Segdwarf.Length = va - Segdwarf.Vaddr
2576 }
2577
2578 ldr := ctxt.loader
2579 var (
2580 rodata = ldr.SymSect(ldr.LookupOrCreateSym("runtime.rodata", 0))
2581 symtab = ldr.SymSect(ldr.LookupOrCreateSym("runtime.symtab", 0))
2582 pclntab = ldr.SymSect(ldr.LookupOrCreateSym("runtime.pclntab", 0))
2583 types = ldr.SymSect(ldr.LookupOrCreateSym("runtime.types", 0))
2584 )
2585
2586 for _, s := range ctxt.datap {
2587 if sect := ldr.SymSect(s); sect != nil {
2588 ldr.AddToSymValue(s, int64(sect.Vaddr))
2589 }
2590 v := ldr.SymValue(s)
2591 for sub := ldr.SubSym(s); sub != 0; sub = ldr.SubSym(sub) {
2592 ldr.AddToSymValue(sub, v)
2593 }
2594 }
2595
2596 for _, si := range dwarfp {
2597 for _, s := range si.syms {
2598 if sect := ldr.SymSect(s); sect != nil {
2599 ldr.AddToSymValue(s, int64(sect.Vaddr))
2600 }
2601 sub := ldr.SubSym(s)
2602 if sub != 0 {
2603 panic(fmt.Sprintf("unexpected sub-sym for %s %s", ldr.SymName(s), ldr.SymType(s).String()))
2604 }
2605 v := ldr.SymValue(s)
2606 for ; sub != 0; sub = ldr.SubSym(sub) {
2607 ldr.AddToSymValue(s, v)
2608 }
2609 }
2610 }
2611
2612 if ctxt.BuildMode == BuildModeShared {
2613 s := ldr.LookupOrCreateSym("go.link.abihashbytes", 0)
2614 sect := ldr.SymSect(ldr.LookupOrCreateSym(".note.go.abihash", 0))
2615 ldr.SetSymSect(s, sect)
2616 ldr.SetSymValue(s, int64(sect.Vaddr+16))
2617 }
2618
2619
2620
2621 n := 1
2622 for _, sect := range Segtext.Sections[1:] {
2623 if sect.Name != ".text" {
2624 break
2625 }
2626 symname := fmt.Sprintf("runtime.text.%d", n)
2627 if ctxt.HeadType != objabi.Haix || ctxt.LinkMode != LinkExternal {
2628
2629
2630 ctxt.xdefine(symname, sym.STEXT, int64(sect.Vaddr))
2631 }
2632 n++
2633 }
2634
2635 ctxt.xdefine("runtime.rodata", sym.SRODATA, int64(rodata.Vaddr))
2636 ctxt.xdefine("runtime.erodata", sym.SRODATA, int64(rodata.Vaddr+rodata.Length))
2637 ctxt.xdefine("runtime.types", sym.SRODATA, int64(types.Vaddr))
2638 ctxt.xdefine("runtime.etypes", sym.SRODATA, int64(types.Vaddr+types.Length))
2639
2640 s := ldr.Lookup("runtime.gcdata", 0)
2641 ldr.SetAttrLocal(s, true)
2642 ctxt.xdefine("runtime.egcdata", sym.SRODATA, ldr.SymAddr(s)+ldr.SymSize(s))
2643 ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.egcdata", 0), ldr.SymSect(s))
2644
2645 s = ldr.LookupOrCreateSym("runtime.gcbss", 0)
2646 ldr.SetAttrLocal(s, true)
2647 ctxt.xdefine("runtime.egcbss", sym.SRODATA, ldr.SymAddr(s)+ldr.SymSize(s))
2648 ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.egcbss", 0), ldr.SymSect(s))
2649
2650 ctxt.xdefine("runtime.symtab", sym.SRODATA, int64(symtab.Vaddr))
2651 ctxt.xdefine("runtime.esymtab", sym.SRODATA, int64(symtab.Vaddr+symtab.Length))
2652 ctxt.xdefine("runtime.pclntab", sym.SRODATA, int64(pclntab.Vaddr))
2653 ctxt.defineInternal("runtime.pcheader", sym.SRODATA)
2654 ctxt.defineInternal("runtime.funcnametab", sym.SRODATA)
2655 ctxt.defineInternal("runtime.cutab", sym.SRODATA)
2656 ctxt.defineInternal("runtime.filetab", sym.SRODATA)
2657 ctxt.defineInternal("runtime.pctab", sym.SRODATA)
2658 ctxt.defineInternal("runtime.functab", sym.SRODATA)
2659 ctxt.xdefine("runtime.epclntab", sym.SRODATA, int64(pclntab.Vaddr+pclntab.Length))
2660 ctxt.xdefine("runtime.noptrdata", sym.SNOPTRDATA, int64(noptr.Vaddr))
2661 ctxt.xdefine("runtime.enoptrdata", sym.SNOPTRDATA, int64(noptr.Vaddr+noptr.Length))
2662 ctxt.xdefine("runtime.bss", sym.SBSS, int64(bss.Vaddr))
2663 ctxt.xdefine("runtime.ebss", sym.SBSS, int64(bss.Vaddr+bss.Length))
2664 ctxt.xdefine("runtime.data", sym.SDATA, int64(data.Vaddr))
2665 ctxt.xdefine("runtime.edata", sym.SDATA, int64(data.Vaddr+data.Length))
2666 ctxt.xdefine("runtime.noptrbss", sym.SNOPTRBSS, int64(noptrbss.Vaddr))
2667 ctxt.xdefine("runtime.enoptrbss", sym.SNOPTRBSS, int64(noptrbss.Vaddr+noptrbss.Length))
2668 ctxt.xdefine("runtime.end", sym.SBSS, int64(Segdata.Vaddr+Segdata.Length))
2669
2670 if ctxt.IsSolaris() {
2671
2672
2673
2674 etext := ldr.Lookup("runtime.etext", 0)
2675 edata := ldr.Lookup("runtime.edata", 0)
2676 end := ldr.Lookup("runtime.end", 0)
2677 ldr.SetSymExtname(etext, "runtime.etext")
2678 ldr.SetSymExtname(edata, "runtime.edata")
2679 ldr.SetSymExtname(end, "runtime.end")
2680 ctxt.xdefine("_etext", ldr.SymType(etext), ldr.SymValue(etext))
2681 ctxt.xdefine("_edata", ldr.SymType(edata), ldr.SymValue(edata))
2682 ctxt.xdefine("_end", ldr.SymType(end), ldr.SymValue(end))
2683 ldr.SetSymSect(ldr.Lookup("_etext", 0), ldr.SymSect(etext))
2684 ldr.SetSymSect(ldr.Lookup("_edata", 0), ldr.SymSect(edata))
2685 ldr.SetSymSect(ldr.Lookup("_end", 0), ldr.SymSect(end))
2686 }
2687
2688 return order
2689 }
2690
2691
2692
2693 func (ctxt *Link) layout(order []*sym.Segment) uint64 {
2694 var prev *sym.Segment
2695 for _, seg := range order {
2696 if prev == nil {
2697 seg.Fileoff = uint64(HEADR)
2698 } else {
2699 switch ctxt.HeadType {
2700 default:
2701
2702
2703
2704
2705 seg.Fileoff = uint64(Rnd(int64(prev.Fileoff+prev.Filelen), int64(*FlagRound)))
2706 if seg.Vaddr%uint64(*FlagRound) != seg.Fileoff%uint64(*FlagRound) {
2707 Exitf("bad segment rounding (Vaddr=%#x Fileoff=%#x FlagRound=%#x)", seg.Vaddr, seg.Fileoff, *FlagRound)
2708 }
2709 case objabi.Hwindows:
2710 seg.Fileoff = prev.Fileoff + uint64(Rnd(int64(prev.Filelen), PEFILEALIGN))
2711 case objabi.Hplan9:
2712 seg.Fileoff = prev.Fileoff + prev.Filelen
2713 }
2714 }
2715 if seg != &Segdata {
2716
2717
2718 seg.Filelen = seg.Length
2719 }
2720 prev = seg
2721 }
2722 return prev.Fileoff + prev.Filelen
2723 }
2724
2725
2726 func (ctxt *Link) AddTramp(s *loader.SymbolBuilder) {
2727 s.SetType(sym.STEXT)
2728 s.SetReachable(true)
2729 s.SetOnList(true)
2730 ctxt.tramps = append(ctxt.tramps, s.Sym())
2731 if *FlagDebugTramp > 0 && ctxt.Debugvlog > 0 {
2732 ctxt.Logf("trampoline %s inserted\n", s.Name())
2733 }
2734 }
2735
2736
2737
2738 func compressSyms(ctxt *Link, syms []loader.Sym) []byte {
2739 ldr := ctxt.loader
2740 var total int64
2741 for _, sym := range syms {
2742 total += ldr.SymSize(sym)
2743 }
2744
2745 var buf bytes.Buffer
2746 buf.Write([]byte("ZLIB"))
2747 var sizeBytes [8]byte
2748 binary.BigEndian.PutUint64(sizeBytes[:], uint64(total))
2749 buf.Write(sizeBytes[:])
2750
2751 var relocbuf []byte
2752
2753
2754
2755
2756
2757 z, err := zlib.NewWriterLevel(&buf, zlib.BestSpeed)
2758 if err != nil {
2759 log.Fatalf("NewWriterLevel failed: %s", err)
2760 }
2761 st := ctxt.makeRelocSymState()
2762 for _, s := range syms {
2763
2764
2765 P := ldr.Data(s)
2766 relocs := ldr.Relocs(s)
2767 if relocs.Count() != 0 {
2768 relocbuf = append(relocbuf[:0], P...)
2769 P = relocbuf
2770 st.relocsym(s, P)
2771 }
2772 if _, err := z.Write(P); err != nil {
2773 log.Fatalf("compression failed: %s", err)
2774 }
2775 for i := ldr.SymSize(s) - int64(len(P)); i > 0; {
2776 b := zeros[:]
2777 if i < int64(len(b)) {
2778 b = b[:i]
2779 }
2780 n, err := z.Write(b)
2781 if err != nil {
2782 log.Fatalf("compression failed: %s", err)
2783 }
2784 i -= int64(n)
2785 }
2786 }
2787 if err := z.Close(); err != nil {
2788 log.Fatalf("compression failed: %s", err)
2789 }
2790 if int64(buf.Len()) >= total {
2791
2792 return nil
2793 }
2794 return buf.Bytes()
2795 }
2796
View as plain text