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