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