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