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