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(int64(ctxt.Arch.PtrSize))
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 filterReachableSEH := func(syms []loader.Sym) []loader.Sym {
1695 out := syms[:0]
1696 for _, s := range syms {
1697 if ldr.AttrReachable(s) {
1698 out = append(out, s)
1699 }
1700 }
1701 return out
1702 }
1703 sehp.pdata = filterReachableSEH(sehp.pdata)
1704 sehp.xdata = filterReachableSEH(sehp.xdata)
1705
1706
1707
1708
1709
1710
1711
1712 if ctxt.HeadType == objabi.Hdarwin {
1713 machosymorder(ctxt)
1714 }
1715 state.dynreloc(ctxt)
1716
1717
1718 state.makeRelroForSharedLib(ctxt)
1719
1720
1721
1722
1723
1724 lastSym := loader.Sym(ldr.NSym() - 1)
1725 ldr.SetSymAlign(lastSym, ldr.SymAlign(lastSym))
1726
1727
1728 var wg sync.WaitGroup
1729 for symn := range state.data {
1730 symn := sym.SymKind(symn)
1731 wg.Add(1)
1732 go func() {
1733 state.data[symn], state.dataMaxAlign[symn] = state.dodataSect(ctxt, symn, state.data[symn])
1734 wg.Done()
1735 }()
1736 }
1737 wg.Wait()
1738
1739 if ctxt.IsELF {
1740
1741
1742 syms := state.data[sym.SELFROSECT]
1743 reli, plti := -1, -1
1744 for i, s := range syms {
1745 switch ldr.SymName(s) {
1746 case ".rel.plt", ".rela.plt":
1747 plti = i
1748 case ".rel", ".rela":
1749 reli = i
1750 }
1751 }
1752 if reli >= 0 && plti >= 0 && plti != reli+1 {
1753 var first, second int
1754 if plti > reli {
1755 first, second = reli, plti
1756 } else {
1757 first, second = plti, reli
1758 }
1759 rel, plt := syms[reli], syms[plti]
1760 copy(syms[first+2:], syms[first+1:second])
1761 syms[first+0] = rel
1762 syms[first+1] = plt
1763
1764
1765
1766
1767
1768 ldr.SetSymAlign(rel, int32(ctxt.Arch.RegSize))
1769 ldr.SetSymAlign(plt, int32(ctxt.Arch.RegSize))
1770 }
1771 state.data[sym.SELFROSECT] = syms
1772 }
1773
1774 if ctxt.HeadType == objabi.Haix && ctxt.LinkMode == LinkExternal {
1775
1776
1777 ldr.SetSymAlign(ldr.Lookup("runtime.data", 0), state.dataMaxAlign[sym.SDATA])
1778 ldr.SetSymAlign(ldr.Lookup("runtime.bss", 0), state.dataMaxAlign[sym.SBSS])
1779 }
1780
1781
1782
1783 state.allocateDataSections(ctxt)
1784
1785 state.allocateSEHSections(ctxt)
1786
1787
1788
1789 state.allocateDwarfSections(ctxt)
1790
1791
1792 n := int16(1)
1793
1794 for _, sect := range Segtext.Sections {
1795 sect.Extnum = n
1796 n++
1797 }
1798 for _, sect := range Segrodata.Sections {
1799 sect.Extnum = n
1800 n++
1801 }
1802 for _, sect := range Segrelrodata.Sections {
1803 sect.Extnum = n
1804 n++
1805 }
1806 for _, sect := range Segdata.Sections {
1807 sect.Extnum = n
1808 n++
1809 }
1810 for _, sect := range Segdwarf.Sections {
1811 sect.Extnum = n
1812 n++
1813 }
1814 for _, sect := range Segpdata.Sections {
1815 sect.Extnum = n
1816 n++
1817 }
1818 for _, sect := range Segxdata.Sections {
1819 sect.Extnum = n
1820 n++
1821 }
1822 }
1823
1824
1825
1826
1827
1828 func (state *dodataState) allocateDataSectionForSym(seg *sym.Segment, s loader.Sym, rwx int) *sym.Section {
1829 ldr := state.ctxt.loader
1830 sname := ldr.SymName(s)
1831 if strings.HasPrefix(sname, "go:") {
1832 sname = ".go." + sname[len("go:"):]
1833 }
1834 sect := addsection(ldr, state.ctxt.Arch, seg, sname, rwx)
1835 sect.Align = symalign(ldr, s)
1836 state.datsize = Rnd(state.datsize, int64(sect.Align))
1837 sect.Vaddr = uint64(state.datsize)
1838 return sect
1839 }
1840
1841
1842
1843
1844
1845
1846 func (state *dodataState) allocateNamedDataSection(seg *sym.Segment, sName string, types []sym.SymKind, rwx int) *sym.Section {
1847 sect := addsection(state.ctxt.loader, state.ctxt.Arch, seg, sName, rwx)
1848 if len(types) == 0 {
1849 sect.Align = 1
1850 } else if len(types) == 1 {
1851 sect.Align = state.dataMaxAlign[types[0]]
1852 } else {
1853 for _, symn := range types {
1854 align := state.dataMaxAlign[symn]
1855 if sect.Align < align {
1856 sect.Align = align
1857 }
1858 }
1859 }
1860 state.datsize = Rnd(state.datsize, int64(sect.Align))
1861 sect.Vaddr = uint64(state.datsize)
1862 return sect
1863 }
1864
1865
1866
1867
1868
1869
1870
1871 func (state *dodataState) assignDsymsToSection(sect *sym.Section, syms []loader.Sym, forceType sym.SymKind, aligner func(state *dodataState, datsize int64, s loader.Sym) int64) {
1872 ldr := state.ctxt.loader
1873 for _, s := range syms {
1874 state.datsize = aligner(state, state.datsize, s)
1875 ldr.SetSymSect(s, sect)
1876 if forceType != sym.Sxxx {
1877 state.setSymType(s, forceType)
1878 }
1879 ldr.SetSymValue(s, int64(uint64(state.datsize)-sect.Vaddr))
1880 state.datsize += ldr.SymSize(s)
1881 }
1882 sect.Length = uint64(state.datsize) - sect.Vaddr
1883 }
1884
1885 func (state *dodataState) assignToSection(sect *sym.Section, symn sym.SymKind, forceType sym.SymKind) {
1886 state.assignDsymsToSection(sect, state.data[symn], forceType, aligndatsize)
1887 state.checkdatsize(symn)
1888 }
1889
1890
1891
1892
1893
1894
1895
1896 func (state *dodataState) allocateSingleSymSections(seg *sym.Segment, symn sym.SymKind, forceType sym.SymKind, rwx int) {
1897 ldr := state.ctxt.loader
1898 for _, s := range state.data[symn] {
1899 sect := state.allocateDataSectionForSym(seg, s, rwx)
1900 ldr.SetSymSect(s, sect)
1901 state.setSymType(s, forceType)
1902 ldr.SetSymValue(s, int64(uint64(state.datsize)-sect.Vaddr))
1903 state.datsize += ldr.SymSize(s)
1904 sect.Length = uint64(state.datsize) - sect.Vaddr
1905 }
1906 state.checkdatsize(symn)
1907 }
1908
1909
1910
1911
1912
1913
1914
1915
1916 func (state *dodataState) allocateNamedSectionAndAssignSyms(seg *sym.Segment, secName string, symn sym.SymKind, forceType sym.SymKind, rwx int) *sym.Section {
1917
1918 sect := state.allocateNamedDataSection(seg, secName, []sym.SymKind{symn}, rwx)
1919 state.assignDsymsToSection(sect, state.data[symn], forceType, aligndatsize)
1920 return sect
1921 }
1922
1923
1924
1925 func (state *dodataState) allocateDataSections(ctxt *Link) {
1926
1927
1928
1929
1930
1931
1932 writable := []sym.SymKind{
1933 sym.SBUILDINFO,
1934 sym.SFIPSINFO,
1935 sym.SELFSECT,
1936 sym.SMACHO,
1937 sym.SWINDOWS,
1938 }
1939 for _, symn := range writable {
1940 state.allocateSingleSymSections(&Segdata, symn, sym.SDATA, 06)
1941 }
1942 ldr := ctxt.loader
1943
1944
1945
1946
1947 if len(state.data[sym.SMODULEDATA]) > 0 {
1948 if len(state.data[sym.SMODULEDATA]) != 1 {
1949 Errorf("internal error: more than one SMODULEDATA symbol")
1950 }
1951 s := state.data[sym.SMODULEDATA][0]
1952 sect := addsection(ldr, ctxt.Arch, &Segdata, ".go.module", 06)
1953 sect.Align = symalign(ldr, s)
1954 state.datsize = Rnd(state.datsize, int64(sect.Align))
1955 sect.Vaddr = uint64(state.datsize)
1956 ldr.SetSymSect(s, sect)
1957 state.setSymType(s, sym.SDATA)
1958 ldr.SetSymValue(s, int64(uint64(state.datsize)-sect.Vaddr))
1959 state.datsize += ldr.SymSize(s)
1960 sect.Length = uint64(state.datsize) - sect.Vaddr
1961 state.checkdatsize(sym.SMODULEDATA)
1962 }
1963
1964
1965 if len(state.data[sym.SELFGOT]) > 0 {
1966 state.allocateNamedSectionAndAssignSyms(&Segdata, ".got", sym.SELFGOT, sym.SDATA, 06)
1967 }
1968 if len(state.data[sym.SMACHOGOT]) > 0 {
1969 state.allocateNamedSectionAndAssignSyms(&Segdata, ".got", sym.SMACHOGOT, sym.SDATA, 06)
1970 }
1971
1972
1973 sect := state.allocateNamedSectionAndAssignSyms(&Segdata, ".noptrdata", sym.SNOPTRDATA, sym.SDATA, 06)
1974 ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.noptrdata", 0), sect)
1975 ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.enoptrdata", 0), sect)
1976
1977 state.assignToSection(sect, sym.SNOPTRDATAFIPSSTART, sym.SDATA)
1978 state.assignToSection(sect, sym.SNOPTRDATAFIPS, sym.SDATA)
1979 state.assignToSection(sect, sym.SNOPTRDATAFIPSEND, sym.SDATA)
1980 state.assignToSection(sect, sym.SNOPTRDATAEND, sym.SDATA)
1981
1982 hasinitarr := ctxt.linkShared
1983
1984
1985 switch ctxt.BuildMode {
1986 case BuildModeCArchive, BuildModeCShared, BuildModeShared, BuildModePlugin:
1987 hasinitarr = true
1988 }
1989
1990 if ctxt.HeadType == objabi.Haix {
1991 if len(state.data[sym.SINITARR]) > 0 {
1992 Errorf("XCOFF format doesn't allow .init_array section")
1993 }
1994 }
1995
1996 if hasinitarr && len(state.data[sym.SINITARR]) > 0 {
1997 state.allocateNamedSectionAndAssignSyms(&Segdata, ".init_array", sym.SINITARR, sym.Sxxx, 06)
1998 }
1999
2000
2001 sect = state.allocateNamedSectionAndAssignSyms(&Segdata, ".data", sym.SDATA, sym.SDATA, 06)
2002 ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.data", 0), sect)
2003 ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.edata", 0), sect)
2004
2005 state.assignToSection(sect, sym.SDATAFIPSSTART, sym.SDATA)
2006 state.assignToSection(sect, sym.SDATAFIPS, sym.SDATA)
2007 state.assignToSection(sect, sym.SDATAFIPSEND, sym.SDATA)
2008 state.assignToSection(sect, sym.SDATAEND, sym.SDATA)
2009
2010 dataGcEnd := state.datsize - int64(sect.Vaddr)
2011
2012
2013
2014 state.assignToSection(sect, sym.SXCOFFTOC, sym.SDATA)
2015 state.checkdatsize(sym.SDATA)
2016 sect.Length = uint64(state.datsize) - sect.Vaddr
2017
2018
2019 sect = state.allocateNamedSectionAndAssignSyms(&Segdata, ".bss", sym.SBSS, sym.Sxxx, 06)
2020 ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.bss", 0), sect)
2021 ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.ebss", 0), sect)
2022 bssGcEnd := state.datsize - int64(sect.Vaddr)
2023
2024
2025 gcsToEmit := []struct {
2026 symName string
2027 symKind sym.SymKind
2028 gcEnd int64
2029 }{
2030 {"runtime.gcdata", sym.SDATA, dataGcEnd},
2031 {"runtime.gcbss", sym.SBSS, bssGcEnd},
2032 }
2033 for _, g := range gcsToEmit {
2034 var gc GCProg
2035 gc.Init(ctxt, g.symName)
2036 for _, s := range state.data[g.symKind] {
2037 gc.AddSym(s)
2038 }
2039 gc.End(g.gcEnd)
2040 }
2041
2042
2043 sect = state.allocateNamedSectionAndAssignSyms(&Segdata, ".noptrbss", sym.SNOPTRBSS, sym.Sxxx, 06)
2044 ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.noptrbss", 0), sect)
2045 ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.enoptrbss", 0), sect)
2046
2047
2048 gcmaskSym := ldr.LookupOrCreateSym("runtime.gcmask.*", 0)
2049 ldr.SetSymValue(gcmaskSym, int64(sect.Length))
2050 ldr.SetSymSect(gcmaskSym, sect)
2051 state.assignToSection(sect, sym.SGCMASK, sym.SNOPTRBSS)
2052 if ctxt.HeadType == objabi.Haix {
2053 xcoffUpdateOuterSize(ctxt, int64(sect.Length)-ldr.SymValue(gcmaskSym), sym.SGCMASK)
2054 }
2055
2056
2057
2058
2059 covCounterDataStartOff = sect.Length
2060 state.assignToSection(sect, sym.SCOVERAGE_COUNTER, sym.SNOPTRBSS)
2061 covCounterDataLen = sect.Length - covCounterDataStartOff
2062 ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.covctrs", 0), sect)
2063 ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.ecovctrs", 0), sect)
2064
2065
2066
2067
2068
2069 covCounterDataStartOff += covCounterDataLen % 4
2070 covCounterDataLen -= covCounterDataLen % 4
2071
2072
2073 if len(state.data[sym.SLIBFUZZER_8BIT_COUNTER]) > 0 {
2074 sect := state.allocateNamedSectionAndAssignSyms(&Segdata, ".go.fuzzcntrs", sym.SLIBFUZZER_8BIT_COUNTER, sym.Sxxx, 06)
2075 ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.__start___sancov_cntrs", 0), sect)
2076 ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.__stop___sancov_cntrs", 0), sect)
2077 ldr.SetSymSect(ldr.LookupOrCreateSym("internal/fuzz._counters", 0), sect)
2078 ldr.SetSymSect(ldr.LookupOrCreateSym("internal/fuzz._ecounters", 0), sect)
2079 }
2080
2081
2082 ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.end", 0), Segdata.Sections[len(Segdata.Sections)-1])
2083
2084 if len(state.data[sym.STLSBSS]) > 0 {
2085 var sect *sym.Section
2086
2087 if (ctxt.IsELF || ctxt.HeadType == objabi.Haix) && (ctxt.LinkMode == LinkExternal || !*FlagD) {
2088 sect = addsection(ldr, ctxt.Arch, &Segdata, ".tbss", 06)
2089 sect.Align = int32(ctxt.Arch.PtrSize)
2090
2091 sect.Vaddr = 0
2092 }
2093 state.datsize = 0
2094
2095 for _, s := range state.data[sym.STLSBSS] {
2096 state.datsize = aligndatsize(state, state.datsize, s)
2097 if sect != nil {
2098 ldr.SetSymSect(s, sect)
2099 }
2100 ldr.SetSymValue(s, state.datsize)
2101 state.datsize += ldr.SymSize(s)
2102 }
2103 state.checkdatsize(sym.STLSBSS)
2104
2105 if sect != nil {
2106 sect.Length = uint64(state.datsize)
2107 }
2108 }
2109
2110
2119 var segro *sym.Segment
2120 if ctxt.IsELF && ctxt.LinkMode == LinkInternal {
2121 segro = &Segrodata
2122 } else if ctxt.HeadType == objabi.Hwindows {
2123 segro = &Segrodata
2124 } else {
2125 segro = &Segtext
2126 }
2127
2128 state.datsize = 0
2129
2130
2131 if len(state.data[sym.STEXT]) != 0 {
2132 culprit := ldr.SymName(state.data[sym.STEXT][0])
2133 Errorf("dodata found an sym.STEXT symbol: %s", culprit)
2134 }
2135 state.allocateSingleSymSections(&Segtext, sym.SELFRXSECT, sym.SRODATA, 05)
2136 state.allocateSingleSymSections(&Segtext, sym.SMACHOPLT, sym.SRODATA, 05)
2137
2138
2139 sect = state.allocateNamedDataSection(segro, ".rodata", sym.ReadOnly, 04)
2140 ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.rodata", 0), sect)
2141 ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.erodata", 0), sect)
2142 for _, symn := range sym.ReadOnly {
2143 symnStartValue := state.datsize
2144 if len(state.data[symn]) != 0 {
2145 symnStartValue = aligndatsize(state, symnStartValue, state.data[symn][0])
2146 }
2147 state.assignToSection(sect, symn, sym.SRODATA)
2148 setCarrierSize(symn, state.datsize-symnStartValue)
2149 if ctxt.HeadType == objabi.Haix {
2150
2151
2152
2153
2154 xcoffUpdateOuterSize(ctxt, state.datsize-symnStartValue, symn)
2155 }
2156 }
2157
2158
2159 sect = state.allocateNamedSectionAndAssignSyms(segro, ".gopclntab", sym.SPCLNTAB, sym.SRODATA, 04)
2160 ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.pclntab", 0), sect)
2161 ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.pcheader", 0), sect)
2162 ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.funcnametab", 0), sect)
2163 ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.cutab", 0), sect)
2164 ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.filetab", 0), sect)
2165 ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.pctab", 0), sect)
2166 ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.functab", 0), sect)
2167 ldr.SetSymSect(ldr.LookupOrCreateSym("go:func.*", 0), sect)
2168 ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.epclntab", 0), sect)
2169 setCarrierSize(sym.SPCLNTAB, int64(sect.Length))
2170 if ctxt.HeadType == objabi.Haix {
2171 xcoffUpdateOuterSize(ctxt, int64(sect.Length), sym.SPCLNTAB)
2172 }
2173
2174
2175 state.allocateSingleSymSections(segro, sym.SELFROSECT, sym.SRODATA, 04)
2176
2177
2178
2179
2180
2181
2182
2183 relroPerm := 04
2184 genrelrosecname := func(suffix string) string {
2185 if suffix == "" {
2186 return ".rodata"
2187 }
2188 return suffix
2189 }
2190 segRelro := segro
2191
2192 if ctxt.UseRelro() {
2193 if ctxt.LinkMode == LinkExternal && !ctxt.IsAIX() && !ctxt.IsDarwin() {
2194
2195
2196
2197
2198
2199
2200 } else {
2201 segRelro = &Segrelrodata
2202
2203 state.datsize = 0
2204 }
2205
2206 relroPerm = 06
2207
2208 if !ctxt.IsDarwin() {
2209 genrelrosecname = func(suffix string) string {
2210 return ".data.rel.ro" + suffix
2211 }
2212 }
2213 }
2214
2215
2216
2217
2218 checkOuter := func(sect *sym.Section, symn sym.SymKind) {
2219 for _, s := range state.data[symn] {
2220 outer := ldr.OuterSym(s)
2221 if s != 0 && ldr.SymSect(outer) != nil && ldr.SymSect(outer) != sect {
2222 ctxt.Errorf(s, "s.Outer (%s) in different section from s, %s != %s", ldr.SymName(outer), ldr.SymSect(outer).Name, sect.Name)
2223 }
2224 }
2225 }
2226
2227
2228
2229 createRelroSect := func(name string, symn sym.SymKind) *sym.Section {
2230 sect := state.allocateNamedDataSection(segRelro, genrelrosecname(name), []sym.SymKind{symn}, relroPerm)
2231
2232 if symn == sym.STYPE {
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242 typesSym := ldr.Lookup("runtime.types", 0)
2243 if typesSym == 0 || ldr.SymSize(typesSym) == 0 {
2244 state.datsize += int64(ctxt.Arch.PtrSize)
2245 }
2246 }
2247
2248
2249 symnStartValue := state.datsize
2250 if len(state.data[symn]) > 0 {
2251 symnStartValue = aligndatsize(state, state.datsize, state.data[symn][0])
2252 }
2253
2254 checkOuter(sect, symn)
2255 state.assignToSection(sect, symn, sym.SRODATA)
2256 setCarrierSize(symn, state.datsize-symnStartValue)
2257 if ctxt.HeadType == objabi.Haix {
2258
2259
2260 xcoffUpdateOuterSize(ctxt, state.datsize-symnStartValue, symn)
2261 }
2262 sect.Length = uint64(state.datsize) - sect.Vaddr
2263 return sect
2264 }
2265
2266 if len(state.data[sym.SRODATARELRO]) > 0 {
2267 createRelroSect("", sym.SRODATARELRO)
2268 }
2269
2270 sect = createRelroSect(".go.type", sym.STYPE)
2271 ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.types", 0), sect)
2272 ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.etypes", 0), sect)
2273
2274 sect = createRelroSect(".go.func", sym.SGOFUNC)
2275
2276 state.allocateSingleSymSections(segRelro, sym.SELFRELROSECT, sym.SRODATA, relroPerm)
2277 state.allocateSingleSymSections(segRelro, sym.SMACHORELROSECT, sym.SRODATA, relroPerm)
2278
2279
2280 if state.datsize != int64(uint32(state.datsize)) {
2281 Errorf("read-only data segment too large: %d", state.datsize)
2282 }
2283
2284 siz := 0
2285 for symn := sym.SELFRXSECT; symn < sym.SFirstUnallocated; symn++ {
2286 siz += len(state.data[symn])
2287 }
2288 ctxt.datap = make([]loader.Sym, 0, siz)
2289 for symn := sym.SELFRXSECT; symn < sym.SFirstUnallocated; symn++ {
2290 ctxt.datap = append(ctxt.datap, state.data[symn]...)
2291 }
2292 }
2293
2294
2295
2296 func (state *dodataState) allocateDwarfSections(ctxt *Link) {
2297
2298 alignOne := func(state *dodataState, datsize int64, s loader.Sym) int64 { return datsize }
2299
2300 ldr := ctxt.loader
2301 for i := 0; i < len(dwarfp); i++ {
2302
2303 s := dwarfp[i].secSym()
2304 sect := state.allocateNamedDataSection(&Segdwarf, ldr.SymName(s), []sym.SymKind{}, 04)
2305 ldr.SetSymSect(s, sect)
2306 sect.Sym = s
2307 curType := ldr.SymType(s)
2308 state.setSymType(s, sym.SRODATA)
2309 ldr.SetSymValue(s, int64(uint64(state.datsize)-sect.Vaddr))
2310 state.datsize += ldr.SymSize(s)
2311
2312
2313 subSyms := dwarfp[i].subSyms()
2314 state.assignDsymsToSection(sect, subSyms, sym.SRODATA, alignOne)
2315
2316 for j := 0; j < len(subSyms); j++ {
2317 s := subSyms[j]
2318 if ctxt.HeadType == objabi.Haix && curType == sym.SDWARFLOC {
2319
2320
2321 addDwsectCUSize(".debug_loc", ldr.SymPkg(s), uint64(ldr.SymSize(s)))
2322 }
2323 }
2324 sect.Length = uint64(state.datsize) - sect.Vaddr
2325 checkSectSize(sect)
2326 }
2327 }
2328
2329
2330
2331 func (state *dodataState) allocateSEHSections(ctxt *Link) {
2332 if len(sehp.pdata) > 0 {
2333 sect := state.allocateNamedDataSection(&Segpdata, ".pdata", []sym.SymKind{}, 04)
2334 state.assignDsymsToSection(sect, sehp.pdata, sym.SRODATA, aligndatsize)
2335 state.checkdatsize(sym.SSEHSECT)
2336 }
2337 if len(sehp.xdata) > 0 {
2338 sect := state.allocateNamedDataSection(&Segxdata, ".xdata", []sym.SymKind{}, 04)
2339 state.assignDsymsToSection(sect, sehp.xdata, sym.SRODATA, aligndatsize)
2340 state.checkdatsize(sym.SSEHSECT)
2341 }
2342 }
2343
2344 type symNameSize struct {
2345 name string
2346 sz int64
2347 val int64
2348 sym loader.Sym
2349 isTypelink bool
2350 isItab bool
2351 typeStr string
2352 }
2353
2354 func (state *dodataState) dodataSect(ctxt *Link, symn sym.SymKind, syms []loader.Sym) (result []loader.Sym, maxAlign int32) {
2355 var head, tail, zerobase loader.Sym
2356 ldr := ctxt.loader
2357 sl := make([]symNameSize, len(syms))
2358
2359
2360
2361
2362
2363 sortBySize := symn != sym.SELFGOT
2364
2365 for k, s := range syms {
2366 ss := ldr.SymSize(s)
2367 sl[k] = symNameSize{sz: ss, sym: s}
2368 if !sortBySize {
2369 sl[k].name = ldr.SymName(s)
2370 }
2371 ds := int64(len(ldr.Data(s)))
2372 switch {
2373 case ss < ds:
2374 ctxt.Errorf(s, "initialize bounds (%d < %d)", ss, ds)
2375 case ss < 0:
2376 ctxt.Errorf(s, "negative size (%d bytes)", ss)
2377 case ss > cutoff:
2378 ctxt.Errorf(s, "symbol too large (%d bytes)", ss)
2379 }
2380
2381
2382
2383
2384 if (ctxt.DynlinkingGo() && ctxt.HeadType == objabi.Hdarwin) || (ctxt.HeadType == objabi.Haix && ctxt.LinkMode == LinkExternal) {
2385 switch ldr.SymName(s) {
2386 case "runtime.text", "runtime.bss", "runtime.data", "runtime.types", "runtime.rodata",
2387 "runtime.noptrdata", "runtime.noptrbss":
2388 head = s
2389 continue
2390 case "runtime.etext", "runtime.ebss", "runtime.edata", "runtime.etypes", "runtime.erodata",
2391 "runtime.enoptrdata", "runtime.enoptrbss":
2392 tail = s
2393 continue
2394 }
2395 } else if ctxt.HeadType == objabi.Haix && ldr.SymName(s) == "runtime.types" {
2396
2397
2398 head = s
2399 }
2400 }
2401 zerobase = ldr.Lookup("runtime.zerobase", 0)
2402
2403 sortHeadTail := func(si, sj loader.Sym) (less bool, matched bool) {
2404 switch {
2405 case si == head, sj == tail:
2406 return true, true
2407 case sj == head, si == tail:
2408 return false, true
2409 }
2410 return false, false
2411 }
2412
2413 sortFn := func(i, j int) bool {
2414 si, sj := sl[i].sym, sl[j].sym
2415 isz, jsz := sl[i].sz, sl[j].sz
2416 if ret, matched := sortHeadTail(si, sj); matched {
2417 return ret
2418 }
2419 if sortBySize {
2420 switch {
2421
2422
2423 case si == zerobase:
2424 return jsz != 0
2425 case sj == zerobase:
2426 return isz == 0
2427 case isz != jsz:
2428 return isz < jsz
2429 }
2430 } else {
2431 iname := sl[i].name
2432 jname := sl[j].name
2433 if iname != jname {
2434 return iname < jname
2435 }
2436 }
2437 return si < sj
2438 }
2439
2440
2441 switch symn {
2442 case sym.SPCLNTAB:
2443
2444
2445 case sym.STYPE:
2446
2447
2448
2449
2450
2451
2452 typeStar := ldr.Lookup("type:*", 0)
2453
2454
2455
2456
2457 for k := range sl {
2458 s := sl[k].sym
2459 sl[k].isItab = ldr.IsItab(s)
2460 if !sl[k].isItab {
2461 sl[k].isTypelink = ldr.IsTypelink(s)
2462 if sl[k].isTypelink {
2463 sl[k].typeStr = decodetypeStr(ldr, ctxt.Arch, s)
2464 }
2465 }
2466 }
2467
2468 sort.Slice(sl, func(i, j int) bool {
2469 si, sj := sl[i].sym, sl[j].sym
2470
2471
2472 if ret, matched := sortHeadTail(si, sj); matched {
2473 return ret
2474 }
2475 if typeStar != 0 {
2476
2477 if si == typeStar {
2478 return true
2479 } else if sj == typeStar {
2480 return false
2481 }
2482 }
2483
2484 iIsType := !sl[i].isItab
2485 jIsType := !sl[j].isItab
2486 if iIsType && jIsType {
2487 iIsTypelink := sl[i].isTypelink
2488 jIsTypelink := sl[j].isTypelink
2489
2490 if iIsTypelink && jIsTypelink {
2491
2492 return sl[i].typeStr < sl[j].typeStr
2493 } else if iIsTypelink {
2494
2495 return true
2496 } else if jIsTypelink {
2497
2498 return false
2499 }
2500 } else if iIsType {
2501
2502 return true
2503 } else if jIsType {
2504
2505 return false
2506 }
2507
2508
2509
2510 return sortFn(i, j)
2511 })
2512
2513
2514
2515
2516
2517
2518
2519
2520 typeLinkSize := int64(ctxt.Arch.PtrSize)
2521 i := 0
2522 for ; i < len(sl); i++ {
2523 si := sl[i].sym
2524 if si == head || si == typeStar {
2525 continue
2526 }
2527 if !sl[i].isTypelink {
2528 break
2529 }
2530 typeLinkSize = Rnd(typeLinkSize, int64(symalign(ldr, si)))
2531 typeLinkSize += sl[i].sz
2532 }
2533
2534
2535
2536 if ctxt.moduledataTypeDescOffset == 0 {
2537 Errorf("internal error: phase error: moduledataTypeDescOffset not set in dodataSect")
2538 } else {
2539 su := ldr.MakeSymbolUpdater(ctxt.Moduledata)
2540 su.SetUint(ctxt.Arch, ctxt.moduledataTypeDescOffset, uint64(typeLinkSize))
2541 }
2542
2543
2544 typeSize := typeLinkSize
2545 for ; i < len(sl); i++ {
2546 if sl[i].isItab {
2547 break
2548 }
2549 typeSize = Rnd(typeSize, int64(symalign(ldr, sl[i].sym)))
2550 typeSize += sl[i].sz
2551 }
2552
2553 if i < len(sl) {
2554 typeSize = Rnd(typeSize, int64(symalign(ldr, sl[i].sym)))
2555 }
2556
2557 if ctxt.moduledataItabOffset == 0 {
2558 Errorf("internal error: phase error: moduledataItabOffset not set in dodataSect")
2559 } else {
2560 su := ldr.MakeSymbolUpdater(ctxt.Moduledata)
2561 su.SetUint(ctxt.Arch, ctxt.moduledataItabOffset, uint64(typeSize))
2562 }
2563
2564 itabSize := int64(0)
2565 for ; i < len(sl); i++ {
2566 itabSize = Rnd(itabSize, int64(symalign(ldr, sl[i].sym)))
2567 itabSize += sl[i].sz
2568 }
2569
2570 if ctxt.moduledataItabSizeOffset == 0 {
2571 Errorf("internal error: phase error: moduledataItabSizeOffset not set in dodataSect")
2572 } else {
2573 su := ldr.MakeSymbolUpdater(ctxt.Moduledata)
2574 su.SetUint(ctxt.Arch, ctxt.moduledataItabSizeOffset, uint64(itabSize))
2575 }
2576
2577 default:
2578 sort.Slice(sl, sortFn)
2579 }
2580
2581
2582 syms = syms[:0]
2583 for k := range sl {
2584 s := sl[k].sym
2585 if s != head && s != tail {
2586 align := symalign(ldr, s)
2587 if maxAlign < align {
2588 maxAlign = align
2589 }
2590 }
2591 syms = append(syms, s)
2592 }
2593
2594 return syms, maxAlign
2595 }
2596
2597
2598
2599
2600
2601
2602 func (ctxt *Link) textbuildid() {
2603 if ctxt.IsELF || *flagBuildid == "" {
2604 return
2605 }
2606
2607 ldr := ctxt.loader
2608 s := ldr.CreateSymForUpdate("go:buildid", 0)
2609
2610
2611 data := "\xff Go build ID: " + strconv.Quote(*flagBuildid) + "\n \xff"
2612 s.SetType(sym.STEXT)
2613 s.SetData([]byte(data))
2614 s.SetSize(int64(len(data)))
2615
2616 ctxt.Textp = append(ctxt.Textp, 0)
2617 copy(ctxt.Textp[1:], ctxt.Textp)
2618 ctxt.Textp[0] = s.Sym()
2619 }
2620
2621 func (ctxt *Link) buildinfo() {
2622
2623
2624 ldr := ctxt.loader
2625 s := ldr.CreateSymForUpdate("go:buildinfo", 0)
2626 s.SetType(sym.SBUILDINFO)
2627 s.SetAlign(16)
2628
2629
2630
2631 const prefix = "\xff Go buildinf:"
2632
2633
2634
2635 data := make([]byte, 32)
2636 copy(data, prefix)
2637 data[len(prefix)] = byte(ctxt.Arch.PtrSize)
2638 data[len(prefix)+1] = 0
2639 if ctxt.Arch.ByteOrder == binary.BigEndian {
2640 data[len(prefix)+1] = 1
2641 }
2642 data[len(prefix)+1] |= 2
2643 data = appendString(data, strdata["runtime.buildVersion"])
2644 data = appendString(data, strdata["runtime.modinfo"])
2645
2646 for len(data)%16 != 0 {
2647 data = append(data, 0)
2648 }
2649 s.SetData(data)
2650 s.SetSize(int64(len(data)))
2651
2652
2653
2654
2655 sr := ldr.CreateSymForUpdate("go:buildinfo.ref", 0)
2656 sr.SetType(sym.SRODATA)
2657 sr.SetAlign(int32(ctxt.Arch.PtrSize))
2658 sr.AddAddr(ctxt.Arch, s.Sym())
2659 }
2660
2661
2662 func appendString(data []byte, s string) []byte {
2663 var v [binary.MaxVarintLen64]byte
2664 n := binary.PutUvarint(v[:], uint64(len(s)))
2665 data = append(data, v[:n]...)
2666 data = append(data, s...)
2667 return data
2668 }
2669
2670
2671 func (ctxt *Link) textaddress() {
2672 addsection(ctxt.loader, ctxt.Arch, &Segtext, ".text", 05)
2673
2674
2675
2676
2677 sect := Segtext.Sections[0]
2678
2679 sect.Align = int32(Funcalign)
2680
2681 ldr := ctxt.loader
2682
2683 if *flagRandLayout != 0 {
2684 r := rand.New(rand.NewSource(*flagRandLayout))
2685 textp := ctxt.Textp
2686 i := 0
2687
2688 if len(textp) > 0 && ldr.SymName(textp[0]) == "go:buildid" {
2689 i++
2690 }
2691
2692
2693
2694 for i < len(textp) && (ldr.SubSym(textp[i]) != 0 || ldr.AttrSubSymbol(textp[i])) {
2695 i++
2696 }
2697 textp = textp[i:]
2698 r.Shuffle(len(textp), func(i, j int) {
2699 textp[i], textp[j] = textp[j], textp[i]
2700 })
2701 }
2702
2703
2704
2705
2706 sort.SliceStable(ctxt.Textp, func(i, j int) bool {
2707 return ldr.SymType(ctxt.Textp[i]) < ldr.SymType(ctxt.Textp[j])
2708 })
2709
2710 text := ctxt.xdefine("runtime.text", sym.STEXT, 0)
2711 etext := ctxt.xdefine("runtime.etext", sym.STEXTEND, 0)
2712 ldr.SetSymSect(text, sect)
2713 if ctxt.IsAIX() && ctxt.IsExternal() {
2714
2715
2716
2717 u := ldr.MakeSymbolUpdater(text)
2718 u.SetAlign(sect.Align)
2719 u.SetSize(8)
2720 }
2721
2722 if (ctxt.DynlinkingGo() && ctxt.IsDarwin()) || (ctxt.IsAIX() && ctxt.IsExternal()) {
2723 ldr.SetSymSect(etext, sect)
2724 ctxt.Textp = append(ctxt.Textp, etext, 0)
2725 copy(ctxt.Textp[1:], ctxt.Textp)
2726 ctxt.Textp[0] = text
2727 }
2728
2729 start := uint64(Rnd(*FlagTextAddr, int64(Funcalign)))
2730 va := start
2731 n := 1
2732 sect.Vaddr = va
2733
2734 limit := thearch.TrampLimit
2735 if limit == 0 {
2736 limit = 1 << 63
2737 }
2738 if *FlagDebugTextSize != 0 {
2739 limit = uint64(*FlagDebugTextSize)
2740 }
2741 if *FlagDebugTramp > 1 {
2742 limit = 1
2743 }
2744
2745 if ctxt.IsAIX() && ctxt.IsExternal() {
2746
2747
2748
2749
2750
2751 limit = 1
2752 }
2753
2754
2755
2756 big := false
2757 for _, s := range ctxt.Textp {
2758 sect, n, va = assignAddress(ctxt, sect, n, s, va, false, big)
2759 if va-start >= limit {
2760 big = true
2761 break
2762 }
2763 }
2764
2765
2766
2767 if big {
2768
2769 for _, s := range ctxt.Textp {
2770 if s != text {
2771 resetAddress(ctxt, s)
2772 }
2773 }
2774 va = start
2775
2776 ntramps := 0
2777 var curPkg string
2778 for i, s := range ctxt.Textp {
2779
2780
2781
2782
2783
2784 if symPkg := ldr.SymPkg(s); symPkg != "" && curPkg != symPkg {
2785 curPkg = symPkg
2786 vaTmp := va
2787 for j := i; j < len(ctxt.Textp); j++ {
2788 curSym := ctxt.Textp[j]
2789 if symPkg := ldr.SymPkg(curSym); symPkg == "" || curPkg != symPkg {
2790 break
2791 }
2792
2793
2794 sect, n, vaTmp = assignAddress(ctxt, sect, n, curSym, vaTmp, false, false)
2795 vaTmp += maxSizeTrampolines(ctxt, ldr, curSym, false)
2796 }
2797 }
2798
2799
2800 if s != text {
2801 resetAddress(ctxt, s)
2802 }
2803
2804
2805 sect, n, va = assignAddress(ctxt, sect, n, s, va, false, big)
2806
2807
2808 trampoline(ctxt, s)
2809
2810
2811 for ; ntramps < len(ctxt.tramps); ntramps++ {
2812 tramp := ctxt.tramps[ntramps]
2813 if ctxt.IsAIX() && strings.HasPrefix(ldr.SymName(tramp), "runtime.text.") {
2814
2815 continue
2816 }
2817 sect, n, va = assignAddress(ctxt, sect, n, tramp, va, true, big)
2818 }
2819 }
2820
2821
2822 if ntramps != 0 {
2823 newtextp := make([]loader.Sym, 0, len(ctxt.Textp)+ntramps)
2824 i := 0
2825 for _, s := range ctxt.Textp {
2826 for ; i < ntramps && ldr.SymValue(ctxt.tramps[i]) < ldr.SymValue(s); i++ {
2827 newtextp = append(newtextp, ctxt.tramps[i])
2828 }
2829 newtextp = append(newtextp, s)
2830 }
2831 newtextp = append(newtextp, ctxt.tramps[i:ntramps]...)
2832
2833 ctxt.Textp = newtextp
2834 }
2835 }
2836
2837
2838
2839 sect.Length = va - sect.Vaddr + uint64(ctxt.Arch.MinLC)
2840 ldr.SetSymSect(etext, sect)
2841 if ldr.SymValue(etext) == 0 {
2842
2843
2844 ldr.SetSymValue(etext, int64(va))
2845 ldr.SetSymValue(text, int64(Segtext.Sections[0].Vaddr))
2846 }
2847 if ctxt.IsWindows() {
2848
2849
2850 collectSEH(ctxt)
2851 }
2852 }
2853
2854
2855 func assignAddress(ctxt *Link, sect *sym.Section, n int, s loader.Sym, va uint64, isTramp, big bool) (*sym.Section, int, uint64) {
2856 ldr := ctxt.loader
2857 if thearch.AssignAddress != nil {
2858 return thearch.AssignAddress(ldr, sect, n, s, va, isTramp)
2859 }
2860
2861 ldr.SetSymSect(s, sect)
2862 if ldr.AttrSubSymbol(s) {
2863 return sect, n, va
2864 }
2865
2866 align := ldr.SymAlign(s)
2867 align = max(align, int32(Funcalign))
2868 va = uint64(Rnd(int64(va), int64(align)))
2869 if sect.Align < align {
2870 sect.Align = align
2871 }
2872
2873 funcsize := uint64(abi.MINFUNC)
2874 if ldr.SymSize(s) > abi.MINFUNC {
2875 funcsize = uint64(ldr.SymSize(s))
2876 }
2877
2878
2879
2880
2881
2882 if big && splitTextSections(ctxt) && ldr.OuterSym(s) == 0 {
2883
2884
2885 var textSizelimit uint64 = thearch.TrampLimit
2886 if *FlagDebugTextSize != 0 {
2887 textSizelimit = uint64(*FlagDebugTextSize)
2888 }
2889
2890
2891
2892 if funcsize > textSizelimit {
2893 panic(fmt.Sprintf("error: text size limit %d less than text symbol %s size of %d", textSizelimit, ldr.SymName(s), funcsize))
2894 }
2895
2896 if va-sect.Vaddr+funcsize+maxSizeTrampolines(ctxt, ldr, s, isTramp) > textSizelimit {
2897 sectAlign := int32(thearch.Funcalign)
2898 if ctxt.IsPPC64() {
2899
2900
2901
2902
2903
2904
2905 const ppc64maxFuncalign = 64
2906 sectAlign = ppc64maxFuncalign
2907 va = uint64(Rnd(int64(va), ppc64maxFuncalign))
2908 }
2909
2910
2911 sect.Length = va - sect.Vaddr
2912
2913
2914 sect = addsection(ctxt.loader, ctxt.Arch, &Segtext, ".text", 05)
2915
2916 sect.Vaddr = va
2917 sect.Align = sectAlign
2918 ldr.SetSymSect(s, sect)
2919
2920
2921 ntext := ldr.CreateSymForUpdate(fmt.Sprintf("runtime.text.%d", n), 0)
2922 ntext.SetSect(sect)
2923 if ctxt.IsAIX() {
2924
2925
2926
2927 ntext.SetType(sym.STEXT)
2928 ntext.SetSize(int64(abi.MINFUNC))
2929 ntext.SetOnList(true)
2930 ntext.SetAlign(sectAlign)
2931 ctxt.tramps = append(ctxt.tramps, ntext.Sym())
2932
2933 ntext.SetValue(int64(va))
2934 va += uint64(ntext.Size())
2935
2936 if align := ldr.SymAlign(s); align != 0 {
2937 va = uint64(Rnd(int64(va), int64(align)))
2938 } else {
2939 va = uint64(Rnd(int64(va), int64(Funcalign)))
2940 }
2941 }
2942 n++
2943 }
2944 }
2945
2946 ldr.SetSymValue(s, 0)
2947 for sub := s; sub != 0; sub = ldr.SubSym(sub) {
2948 ldr.SetSymValue(sub, ldr.SymValue(sub)+int64(va))
2949 if ctxt.Debugvlog > 2 {
2950 fmt.Println("assign text address:", ldr.SymName(sub), ldr.SymValue(sub))
2951 }
2952 }
2953
2954 va += funcsize
2955
2956 return sect, n, va
2957 }
2958
2959 func resetAddress(ctxt *Link, s loader.Sym) {
2960 ldr := ctxt.loader
2961 if ldr.OuterSym(s) != 0 {
2962 return
2963 }
2964 oldv := ldr.SymValue(s)
2965 for sub := s; sub != 0; sub = ldr.SubSym(sub) {
2966 ldr.SetSymValue(sub, ldr.SymValue(sub)-oldv)
2967 }
2968 }
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986 func splitTextSections(ctxt *Link) bool {
2987 return (ctxt.IsARM() || ctxt.IsPPC64() || (ctxt.IsARM64() && ctxt.IsDarwin())) && ctxt.IsExternal()
2988 }
2989
2990
2991
2992
2993
2994 const wasmMinDataAddr = 4096 + 8192
2995
2996
2997
2998 func (ctxt *Link) address() []*sym.Segment {
2999 var order []*sym.Segment
3000
3001 va := uint64(*FlagTextAddr)
3002 order = append(order, &Segtext)
3003 Segtext.Rwx = 05
3004 Segtext.Vaddr = va
3005 for i, s := range Segtext.Sections {
3006 va = uint64(Rnd(int64(va), int64(s.Align)))
3007 s.Vaddr = va
3008 va += s.Length
3009
3010 if ctxt.IsWasm() && i == 0 && va < wasmMinDataAddr {
3011 va = wasmMinDataAddr
3012 }
3013 }
3014
3015 Segtext.Length = va - uint64(*FlagTextAddr)
3016
3017 if len(Segrodata.Sections) > 0 {
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028 va = uint64(Rnd(int64(va), *FlagRound))
3029
3030 order = append(order, &Segrodata)
3031 Segrodata.Rwx = 04
3032 Segrodata.Vaddr = va
3033 for _, s := range Segrodata.Sections {
3034 va = uint64(Rnd(int64(va), int64(s.Align)))
3035 s.Vaddr = va
3036 va += s.Length
3037 }
3038
3039 Segrodata.Length = va - Segrodata.Vaddr
3040 }
3041 if len(Segrelrodata.Sections) > 0 {
3042
3043
3044 va = uint64(Rnd(int64(va), *FlagRound))
3045 if ctxt.HeadType == objabi.Haix {
3046
3047 va += uint64(XCOFFDATABASE) - uint64(XCOFFTEXTBASE)
3048 }
3049
3050 order = append(order, &Segrelrodata)
3051 Segrelrodata.Rwx = 06
3052 Segrelrodata.Vaddr = va
3053 for _, s := range Segrelrodata.Sections {
3054 va = uint64(Rnd(int64(va), int64(s.Align)))
3055 s.Vaddr = va
3056 va += s.Length
3057 }
3058
3059 Segrelrodata.Length = va - Segrelrodata.Vaddr
3060 }
3061
3062 va = uint64(Rnd(int64(va), *FlagRound))
3063 if ctxt.HeadType == objabi.Haix && len(Segrelrodata.Sections) == 0 {
3064
3065
3066
3067 va += uint64(XCOFFDATABASE) - uint64(XCOFFTEXTBASE)
3068 }
3069 order = append(order, &Segdata)
3070 Segdata.Rwx = 06
3071 if *FlagDataAddr != -1 {
3072 Segdata.Vaddr = uint64(*FlagDataAddr)
3073 va = Segdata.Vaddr
3074 } else {
3075 Segdata.Vaddr = va
3076 }
3077 var data *sym.Section
3078 var noptr *sym.Section
3079 var bss *sym.Section
3080 var noptrbss *sym.Section
3081 var fuzzCounters *sym.Section
3082 for i, s := range Segdata.Sections {
3083 if (ctxt.IsELF || ctxt.HeadType == objabi.Haix) && s.Name == ".tbss" {
3084 continue
3085 }
3086 vlen := int64(s.Length)
3087 if i+1 < len(Segdata.Sections) && !((ctxt.IsELF || ctxt.HeadType == objabi.Haix) && Segdata.Sections[i+1].Name == ".tbss") {
3088 vlen = int64(Segdata.Sections[i+1].Vaddr - s.Vaddr)
3089 }
3090 s.Vaddr = va
3091 va += uint64(vlen)
3092 Segdata.Length = va - Segdata.Vaddr
3093 switch s.Name {
3094 case ".data":
3095 data = s
3096 case ".noptrdata":
3097 noptr = s
3098 case ".bss":
3099 bss = s
3100 case ".noptrbss":
3101 noptrbss = s
3102 case ".go.fuzzcntrs":
3103 fuzzCounters = s
3104 }
3105 }
3106
3107
3108
3109 Segdata.Filelen = bss.Vaddr - Segdata.Vaddr
3110
3111 if len(Segpdata.Sections) > 0 {
3112 va = uint64(Rnd(int64(va), *FlagRound))
3113 order = append(order, &Segpdata)
3114 Segpdata.Rwx = 04
3115 Segpdata.Vaddr = va
3116
3117
3118 for _, s := range Segpdata.Sections {
3119 va = uint64(Rnd(int64(va), int64(s.Align)))
3120 s.Vaddr = va
3121 va += s.Length
3122 }
3123 Segpdata.Length = va - Segpdata.Vaddr
3124 }
3125
3126 if len(Segxdata.Sections) > 0 {
3127 va = uint64(Rnd(int64(va), *FlagRound))
3128 order = append(order, &Segxdata)
3129 Segxdata.Rwx = 04
3130 Segxdata.Vaddr = va
3131
3132
3133 for _, s := range Segxdata.Sections {
3134 va = uint64(Rnd(int64(va), int64(s.Align)))
3135 s.Vaddr = va
3136 va += s.Length
3137 }
3138 Segxdata.Length = va - Segxdata.Vaddr
3139 }
3140
3141 va = uint64(Rnd(int64(va), *FlagRound))
3142 order = append(order, &Segdwarf)
3143 Segdwarf.Rwx = 06
3144 Segdwarf.Vaddr = va
3145 for i, s := range Segdwarf.Sections {
3146 vlen := int64(s.Length)
3147 if i+1 < len(Segdwarf.Sections) {
3148 vlen = int64(Segdwarf.Sections[i+1].Vaddr - s.Vaddr)
3149 }
3150 s.Vaddr = va
3151 va += uint64(vlen)
3152 if ctxt.HeadType == objabi.Hwindows {
3153 va = uint64(Rnd(int64(va), PEFILEALIGN))
3154 }
3155 Segdwarf.Length = va - Segdwarf.Vaddr
3156 }
3157
3158 ldr := ctxt.loader
3159 var (
3160 rodata = ldr.SymSect(ldr.LookupOrCreateSym("runtime.rodata", 0))
3161 pclntab = ldr.SymSect(ldr.LookupOrCreateSym("runtime.pclntab", 0))
3162 types = ldr.SymSect(ldr.LookupOrCreateSym("runtime.types", 0))
3163 )
3164
3165 for _, s := range ctxt.datap {
3166 if sect := ldr.SymSect(s); sect != nil {
3167 ldr.AddToSymValue(s, int64(sect.Vaddr))
3168 }
3169 v := ldr.SymValue(s)
3170 for sub := ldr.SubSym(s); sub != 0; sub = ldr.SubSym(sub) {
3171 ldr.AddToSymValue(sub, v)
3172 }
3173 }
3174
3175 for _, si := range dwarfp {
3176 for _, s := range si.syms {
3177 if sect := ldr.SymSect(s); sect != nil {
3178 ldr.AddToSymValue(s, int64(sect.Vaddr))
3179 }
3180 sub := ldr.SubSym(s)
3181 if sub != 0 {
3182 panic(fmt.Sprintf("unexpected sub-sym for %s %s", ldr.SymName(s), ldr.SymType(s).String()))
3183 }
3184 v := ldr.SymValue(s)
3185 for ; sub != 0; sub = ldr.SubSym(sub) {
3186 ldr.AddToSymValue(s, v)
3187 }
3188 }
3189 }
3190
3191 for _, s := range sehp.pdata {
3192 if sect := ldr.SymSect(s); sect != nil {
3193 ldr.AddToSymValue(s, int64(sect.Vaddr))
3194 }
3195 }
3196 for _, s := range sehp.xdata {
3197 if sect := ldr.SymSect(s); sect != nil {
3198 ldr.AddToSymValue(s, int64(sect.Vaddr))
3199 }
3200 }
3201
3202 if ctxt.BuildMode == BuildModeShared {
3203 s := ldr.LookupOrCreateSym("go:link.abihashbytes", 0)
3204 sect := ldr.SymSect(ldr.LookupOrCreateSym(".note.go.abihash", 0))
3205 ldr.SetSymSect(s, sect)
3206 ldr.SetSymValue(s, int64(sect.Vaddr+16))
3207 }
3208
3209
3210
3211 n := 1
3212 for _, sect := range Segtext.Sections[1:] {
3213 if sect.Name != ".text" {
3214 break
3215 }
3216 symname := fmt.Sprintf("runtime.text.%d", n)
3217 if ctxt.HeadType != objabi.Haix || ctxt.LinkMode != LinkExternal {
3218
3219
3220 ctxt.xdefine(symname, sym.STEXT, int64(sect.Vaddr))
3221 }
3222 n++
3223 }
3224
3225 ctxt.xdefine("runtime.rodata", sym.SRODATA, int64(rodata.Vaddr))
3226 ctxt.xdefine("runtime.erodata", sym.SRODATA, int64(rodata.Vaddr+rodata.Length))
3227 ctxt.xdefine("runtime.types", sym.SRODATA, int64(types.Vaddr))
3228 ctxt.xdefine("runtime.etypes", sym.SRODATA, int64(types.Vaddr+types.Length))
3229
3230 s := ldr.Lookup("runtime.gcdata", 0)
3231 ldr.SetAttrLocal(s, true)
3232 ctxt.xdefine("runtime.egcdata", sym.SRODATA, ldr.SymAddr(s)+ldr.SymSize(s))
3233 ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.egcdata", 0), ldr.SymSect(s))
3234
3235 s = ldr.LookupOrCreateSym("runtime.gcbss", 0)
3236 ldr.SetAttrLocal(s, true)
3237 ctxt.xdefine("runtime.egcbss", sym.SRODATA, ldr.SymAddr(s)+ldr.SymSize(s))
3238 ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.egcbss", 0), ldr.SymSect(s))
3239
3240 ctxt.xdefine("runtime.pclntab", sym.SRODATA, int64(pclntab.Vaddr))
3241 ctxt.defineInternal("runtime.pcheader", sym.SRODATA)
3242 ctxt.defineInternal("runtime.funcnametab", sym.SRODATA)
3243 ctxt.defineInternal("runtime.cutab", sym.SRODATA)
3244 ctxt.defineInternal("runtime.filetab", sym.SRODATA)
3245 ctxt.defineInternal("runtime.pctab", sym.SRODATA)
3246 ctxt.defineInternal("runtime.functab", sym.SRODATA)
3247 ctxt.defineInternal("go:func.*", sym.SRODATA)
3248 ctxt.xdefine("runtime.epclntab", sym.SRODATA, int64(pclntab.Vaddr+pclntab.Length))
3249 ctxt.xdefine("runtime.noptrdata", sym.SNOPTRDATA, int64(noptr.Vaddr))
3250 ctxt.xdefine("runtime.enoptrdata", sym.SNOPTRDATAEND, int64(noptr.Vaddr+noptr.Length))
3251 ctxt.xdefine("runtime.bss", sym.SBSS, int64(bss.Vaddr))
3252 ctxt.xdefine("runtime.ebss", sym.SBSS, int64(bss.Vaddr+bss.Length))
3253 ctxt.xdefine("runtime.data", sym.SDATA, int64(data.Vaddr))
3254 ctxt.xdefine("runtime.edata", sym.SDATAEND, int64(data.Vaddr+data.Length))
3255 ctxt.xdefine("runtime.noptrbss", sym.SNOPTRBSS, int64(noptrbss.Vaddr))
3256 ctxt.xdefine("runtime.enoptrbss", sym.SNOPTRBSS, int64(noptrbss.Vaddr+noptrbss.Length))
3257 s = ldr.Lookup("runtime.gcmask.*", 0)
3258 ctxt.xdefine("runtime.gcmask.*", sym.SGCMASK, int64(noptrbss.Vaddr+uint64(ldr.SymValue(s))))
3259 ctxt.xdefine("runtime.covctrs", sym.SCOVERAGE_COUNTER, int64(noptrbss.Vaddr+covCounterDataStartOff))
3260 ctxt.xdefine("runtime.ecovctrs", sym.SCOVERAGE_COUNTER, int64(noptrbss.Vaddr+covCounterDataStartOff+covCounterDataLen))
3261 ctxt.xdefine("runtime.end", sym.SBSS, int64(Segdata.Vaddr+Segdata.Length))
3262
3263 if fuzzCounters != nil {
3264 if *flagAsan {
3265
3266
3267
3268 fuzzCounters.Length = uint64(Rnd(int64(fuzzCounters.Length), 8))
3269 }
3270 ctxt.xdefine("runtime.__start___sancov_cntrs", sym.SLIBFUZZER_8BIT_COUNTER, int64(fuzzCounters.Vaddr))
3271 ctxt.xdefine("runtime.__stop___sancov_cntrs", sym.SLIBFUZZER_8BIT_COUNTER, int64(fuzzCounters.Vaddr+fuzzCounters.Length))
3272 ctxt.xdefine("internal/fuzz._counters", sym.SLIBFUZZER_8BIT_COUNTER, int64(fuzzCounters.Vaddr))
3273 ctxt.xdefine("internal/fuzz._ecounters", sym.SLIBFUZZER_8BIT_COUNTER, int64(fuzzCounters.Vaddr+fuzzCounters.Length))
3274 }
3275
3276 if ctxt.IsSolaris() {
3277
3278
3279
3280 etext := ldr.Lookup("runtime.etext", 0)
3281 edata := ldr.Lookup("runtime.edata", 0)
3282 end := ldr.Lookup("runtime.end", 0)
3283 ldr.SetSymExtname(etext, "runtime.etext")
3284 ldr.SetSymExtname(edata, "runtime.edata")
3285 ldr.SetSymExtname(end, "runtime.end")
3286 ctxt.xdefine("_etext", ldr.SymType(etext), ldr.SymValue(etext))
3287 ctxt.xdefine("_edata", ldr.SymType(edata), ldr.SymValue(edata))
3288 ctxt.xdefine("_end", ldr.SymType(end), ldr.SymValue(end))
3289 ldr.SetSymSect(ldr.Lookup("_etext", 0), ldr.SymSect(etext))
3290 ldr.SetSymSect(ldr.Lookup("_edata", 0), ldr.SymSect(edata))
3291 ldr.SetSymSect(ldr.Lookup("_end", 0), ldr.SymSect(end))
3292 }
3293
3294 if ctxt.IsPPC64() && ctxt.IsElf() {
3295
3296
3297
3298 tocAddr := int64(Segdata.Vaddr) + 0x8000
3299 if gotAddr := ldr.SymValue(ctxt.GOT); gotAddr != 0 {
3300 tocAddr = gotAddr + 0x8000
3301 }
3302 for i := range ctxt.DotTOC {
3303 if i >= sym.SymVerABICount && i < sym.SymVerStatic {
3304 continue
3305 }
3306 if toc := ldr.Lookup(".TOC.", i); toc != 0 {
3307 ldr.SetSymValue(toc, tocAddr)
3308 }
3309 }
3310 }
3311
3312 return order
3313 }
3314
3315
3316
3317 func (ctxt *Link) layout(order []*sym.Segment) uint64 {
3318 var prev *sym.Segment
3319 for _, seg := range order {
3320 if prev == nil {
3321 seg.Fileoff = uint64(HEADR)
3322 } else {
3323 switch ctxt.HeadType {
3324 default:
3325
3326
3327
3328
3329 seg.Fileoff = uint64(Rnd(int64(prev.Fileoff+prev.Filelen), *FlagRound))
3330 if seg.Vaddr%uint64(*FlagRound) != seg.Fileoff%uint64(*FlagRound) {
3331 Exitf("bad segment rounding (Vaddr=%#x Fileoff=%#x FlagRound=%#x)", seg.Vaddr, seg.Fileoff, *FlagRound)
3332 }
3333 case objabi.Hwindows:
3334 seg.Fileoff = prev.Fileoff + uint64(Rnd(int64(prev.Filelen), PEFILEALIGN))
3335 case objabi.Hplan9:
3336 seg.Fileoff = prev.Fileoff + prev.Filelen
3337 }
3338 }
3339 if seg != &Segdata {
3340
3341
3342 seg.Filelen = seg.Length
3343 }
3344 prev = seg
3345 }
3346 return prev.Fileoff + prev.Filelen
3347 }
3348
3349
3350 func (ctxt *Link) AddTramp(s *loader.SymbolBuilder, typ sym.SymKind) {
3351 s.SetType(typ)
3352 s.SetReachable(true)
3353 s.SetOnList(true)
3354 ctxt.tramps = append(ctxt.tramps, s.Sym())
3355 if *FlagDebugTramp > 0 && ctxt.Debugvlog > 0 {
3356 ctxt.Logf("trampoline %s inserted\n", s.Name())
3357 }
3358 }
3359
3360
3361
3362 func compressSyms(ctxt *Link, syms []loader.Sym) []byte {
3363 ldr := ctxt.loader
3364 var total int64
3365 for _, sym := range syms {
3366 total += ldr.SymSize(sym)
3367 }
3368
3369 var buf bytes.Buffer
3370 if ctxt.IsELF {
3371 switch ctxt.Arch.PtrSize {
3372 case 8:
3373 binary.Write(&buf, ctxt.Arch.ByteOrder, elf.Chdr64{
3374 Type: uint32(elf.COMPRESS_ZLIB),
3375 Size: uint64(total),
3376 Addralign: uint64(ctxt.Arch.Alignment),
3377 })
3378 case 4:
3379 binary.Write(&buf, ctxt.Arch.ByteOrder, elf.Chdr32{
3380 Type: uint32(elf.COMPRESS_ZLIB),
3381 Size: uint32(total),
3382 Addralign: uint32(ctxt.Arch.Alignment),
3383 })
3384 default:
3385 log.Fatalf("can't compress header size:%d", ctxt.Arch.PtrSize)
3386 }
3387 } else {
3388 buf.Write([]byte("ZLIB"))
3389 var sizeBytes [8]byte
3390 binary.BigEndian.PutUint64(sizeBytes[:], uint64(total))
3391 buf.Write(sizeBytes[:])
3392 }
3393
3394 var relocbuf []byte
3395
3396
3397
3398
3399
3400 z, err := zlib.NewWriterLevel(&buf, zlib.BestSpeed)
3401 if err != nil {
3402 log.Fatalf("NewWriterLevel failed: %s", err)
3403 }
3404 st := ctxt.makeRelocSymState()
3405 for _, s := range syms {
3406
3407
3408 P := ldr.Data(s)
3409 relocs := ldr.Relocs(s)
3410 if relocs.Count() != 0 {
3411 relocbuf = append(relocbuf[:0], P...)
3412 P = relocbuf
3413 st.relocsym(s, P)
3414 }
3415 if _, err := z.Write(P); err != nil {
3416 log.Fatalf("compression failed: %s", err)
3417 }
3418 for i := ldr.SymSize(s) - int64(len(P)); i > 0; {
3419 b := zeros[:]
3420 if i < int64(len(b)) {
3421 b = b[:i]
3422 }
3423 n, err := z.Write(b)
3424 if err != nil {
3425 log.Fatalf("compression failed: %s", err)
3426 }
3427 i -= int64(n)
3428 }
3429 }
3430 if err := z.Close(); err != nil {
3431 log.Fatalf("compression failed: %s", err)
3432 }
3433 if int64(buf.Len()) >= total {
3434
3435 return nil
3436 }
3437 return buf.Bytes()
3438 }
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448 func writeUleb128FixedLength(b []byte, v uint64, length int) error {
3449 for i := 0; i < length; i++ {
3450 c := uint8(v & 0x7f)
3451 v >>= 7
3452 if i < length-1 {
3453 c |= 0x80
3454 }
3455 b[i] = c
3456 }
3457 if v != 0 {
3458 return fmt.Errorf("writeUleb128FixedLength: length too small")
3459 }
3460 return nil
3461 }
3462
View as plain text