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 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, out *OutBuf, seek, vaddr, length uint64) {
1185 if out.isMmapped() {
1186 out := 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 out.SeekSet(int64(seek))
1194 fn(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, 0)
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
2790
2791 var maxAlign int32
2792 if splitTextSections(ctxt) {
2793 for _, s := range ctxt.Textp {
2794 maxAlign = max(maxAlign, ldr.SymAlign(s))
2795 }
2796 }
2797
2798 ntramps := 0
2799 var curPkg string
2800 for i, s := range ctxt.Textp {
2801
2802
2803
2804
2805
2806 if symPkg := ldr.SymPkg(s); symPkg != "" && curPkg != symPkg {
2807 curPkg = symPkg
2808 vaTmp := va
2809 for j := i; j < len(ctxt.Textp); j++ {
2810 curSym := ctxt.Textp[j]
2811 if symPkg := ldr.SymPkg(curSym); symPkg == "" || curPkg != symPkg {
2812 break
2813 }
2814
2815
2816 sect, n, vaTmp = assignAddress(ctxt, sect, n, curSym, vaTmp, false, false, 0)
2817 vaTmp += maxSizeTrampolines(ctxt, ldr, curSym, false)
2818 }
2819 }
2820
2821
2822 if s != text {
2823 resetAddress(ctxt, s)
2824 }
2825
2826
2827 sect, n, va = assignAddress(ctxt, sect, n, s, va, false, big, maxAlign)
2828
2829
2830 trampoline(ctxt, s)
2831
2832
2833 for ; ntramps < len(ctxt.tramps); ntramps++ {
2834 tramp := ctxt.tramps[ntramps]
2835 if ctxt.IsAIX() && strings.HasPrefix(ldr.SymName(tramp), "runtime.text.") {
2836
2837 continue
2838 }
2839 sect, n, va = assignAddress(ctxt, sect, n, tramp, va, true, big, maxAlign)
2840 }
2841 }
2842
2843
2844 if ntramps != 0 {
2845 newtextp := make([]loader.Sym, 0, len(ctxt.Textp)+ntramps)
2846 i := 0
2847 for _, s := range ctxt.Textp {
2848 for ; i < ntramps && ldr.SymValue(ctxt.tramps[i]) < ldr.SymValue(s); i++ {
2849 newtextp = append(newtextp, ctxt.tramps[i])
2850 }
2851 newtextp = append(newtextp, s)
2852 }
2853 newtextp = append(newtextp, ctxt.tramps[i:ntramps]...)
2854
2855 ctxt.Textp = newtextp
2856 }
2857 }
2858
2859
2860
2861 sect.Length = va - sect.Vaddr + uint64(ctxt.Arch.MinLC)
2862 ldr.SetSymSect(etext, sect)
2863 if ldr.SymValue(etext) == 0 {
2864
2865
2866 ldr.SetSymValue(etext, int64(va))
2867 ldr.SetSymValue(text, int64(Segtext.Sections[0].Vaddr))
2868 }
2869 if ctxt.IsWindows() {
2870
2871
2872 collectSEH(ctxt)
2873 }
2874 }
2875
2876
2877
2878
2879 func assignAddress(ctxt *Link, sect *sym.Section, n int, s loader.Sym, va uint64, isTramp, big bool, maxAlign int32) (*sym.Section, int, uint64) {
2880 ldr := ctxt.loader
2881 if thearch.AssignAddress != nil {
2882 return thearch.AssignAddress(ldr, sect, n, s, va, isTramp)
2883 }
2884
2885 ldr.SetSymSect(s, sect)
2886 if ldr.AttrSubSymbol(s) {
2887 return sect, n, va
2888 }
2889
2890 align := ldr.SymAlign(s)
2891 align = max(align, int32(Funcalign))
2892 va = uint64(Rnd(int64(va), int64(align)))
2893 if sect.Align < align {
2894 sect.Align = align
2895 }
2896
2897 funcsize := uint64(abi.MINFUNC)
2898 if ldr.SymSize(s) > abi.MINFUNC {
2899 funcsize = uint64(ldr.SymSize(s))
2900 }
2901
2902
2903
2904
2905
2906 if big && splitTextSections(ctxt) && ldr.OuterSym(s) == 0 {
2907
2908
2909 var textSizelimit uint64 = thearch.TrampLimit
2910 if *FlagDebugTextSize != 0 {
2911 textSizelimit = uint64(*FlagDebugTextSize)
2912 }
2913
2914
2915
2916 if funcsize > textSizelimit {
2917 panic(fmt.Sprintf("error: text size limit %d less than text symbol %s size of %d", textSizelimit, ldr.SymName(s), funcsize))
2918 }
2919
2920 if va-sect.Vaddr+funcsize+maxSizeTrampolines(ctxt, ldr, s, isTramp) > textSizelimit {
2921
2922
2923
2924
2925
2926 sectAlign := max(int32(thearch.Funcalign), maxAlign)
2927 if ctxt.IsPPC64() {
2928
2929
2930 const ppc64maxFuncalign = 64
2931 sectAlign = max(sectAlign, ppc64maxFuncalign)
2932 }
2933 va = uint64(Rnd(int64(va), int64(sectAlign)))
2934
2935
2936 sect.Length = va - sect.Vaddr
2937
2938
2939 sect = addsection(ctxt.loader, ctxt.Arch, &Segtext, ".text", 05)
2940
2941 sect.Vaddr = va
2942 sect.Align = sectAlign
2943 ldr.SetSymSect(s, sect)
2944
2945
2946 ntext := ldr.CreateSymForUpdate(fmt.Sprintf("runtime.text.%d", n), 0)
2947 ntext.SetSect(sect)
2948 if ctxt.IsAIX() {
2949
2950
2951
2952 ntext.SetType(sym.STEXT)
2953 ntext.SetSize(int64(abi.MINFUNC))
2954 ntext.SetOnList(true)
2955 ntext.SetAlign(sectAlign)
2956 ctxt.tramps = append(ctxt.tramps, ntext.Sym())
2957
2958 ntext.SetValue(int64(va))
2959 va += uint64(ntext.Size())
2960
2961 if align := ldr.SymAlign(s); align != 0 {
2962 va = uint64(Rnd(int64(va), int64(align)))
2963 } else {
2964 va = uint64(Rnd(int64(va), int64(Funcalign)))
2965 }
2966 }
2967 n++
2968 }
2969 }
2970
2971 ldr.SetSymValue(s, 0)
2972 for sub := s; sub != 0; sub = ldr.SubSym(sub) {
2973 ldr.SetSymValue(sub, ldr.SymValue(sub)+int64(va))
2974 if ctxt.Debugvlog > 2 {
2975 fmt.Println("assign text address:", ldr.SymName(sub), ldr.SymValue(sub))
2976 }
2977 }
2978
2979 va += funcsize
2980
2981 return sect, n, va
2982 }
2983
2984 func resetAddress(ctxt *Link, s loader.Sym) {
2985 ldr := ctxt.loader
2986 if ldr.OuterSym(s) != 0 {
2987 return
2988 }
2989 oldv := ldr.SymValue(s)
2990 for sub := s; sub != 0; sub = ldr.SubSym(sub) {
2991 ldr.SetSymValue(sub, ldr.SymValue(sub)-oldv)
2992 }
2993 }
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011 func splitTextSections(ctxt *Link) bool {
3012 return (ctxt.IsARM() || ctxt.IsPPC64() || (ctxt.IsARM64() && ctxt.IsDarwin())) && ctxt.IsExternal()
3013 }
3014
3015
3016
3017
3018
3019 const wasmMinDataAddr = 4096 + 8192
3020
3021
3022
3023 func (ctxt *Link) address() []*sym.Segment {
3024 var order []*sym.Segment
3025
3026 va := uint64(*FlagTextAddr)
3027 order = append(order, &Segtext)
3028 Segtext.Rwx = 05
3029 Segtext.Vaddr = va
3030 for i, s := range Segtext.Sections {
3031 va = uint64(Rnd(int64(va), int64(s.Align)))
3032 s.Vaddr = va
3033 va += s.Length
3034 if ctxt.IsWasm() && i == 0 {
3035
3036
3037
3038
3039
3040 va = wasmMinDataAddr
3041 }
3042 }
3043 Segtext.Length = va - uint64(*FlagTextAddr)
3044
3045 if len(Segrodata.Sections) > 0 {
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056 va = uint64(Rnd(int64(va), *FlagRound))
3057
3058 order = append(order, &Segrodata)
3059 Segrodata.Rwx = 04
3060 Segrodata.Vaddr = va
3061 for _, s := range Segrodata.Sections {
3062 va = uint64(Rnd(int64(va), int64(s.Align)))
3063 s.Vaddr = va
3064 va += s.Length
3065 }
3066
3067 Segrodata.Length = va - Segrodata.Vaddr
3068 }
3069 if len(Segrelrodata.Sections) > 0 {
3070
3071
3072 va = uint64(Rnd(int64(va), *FlagRound))
3073 if ctxt.HeadType == objabi.Haix {
3074
3075 va += uint64(XCOFFDATABASE) - uint64(XCOFFTEXTBASE)
3076 }
3077
3078 order = append(order, &Segrelrodata)
3079 Segrelrodata.Rwx = 06
3080 Segrelrodata.Vaddr = va
3081 for _, s := range Segrelrodata.Sections {
3082 va = uint64(Rnd(int64(va), int64(s.Align)))
3083 s.Vaddr = va
3084 va += s.Length
3085 }
3086
3087 Segrelrodata.Length = va - Segrelrodata.Vaddr
3088 }
3089
3090 va = uint64(Rnd(int64(va), *FlagRound))
3091 if ctxt.HeadType == objabi.Haix && len(Segrelrodata.Sections) == 0 {
3092
3093
3094
3095 va += uint64(XCOFFDATABASE) - uint64(XCOFFTEXTBASE)
3096 }
3097 order = append(order, &Segdata)
3098 Segdata.Rwx = 06
3099 if *FlagDataAddr != -1 {
3100 Segdata.Vaddr = uint64(*FlagDataAddr)
3101 va = Segdata.Vaddr
3102 } else {
3103 Segdata.Vaddr = va
3104 }
3105 var data *sym.Section
3106 var noptr *sym.Section
3107 var bss *sym.Section
3108 var noptrbss *sym.Section
3109 var fuzzCounters *sym.Section
3110 for i, s := range Segdata.Sections {
3111 if (ctxt.IsELF || ctxt.HeadType == objabi.Haix) && s.Name == ".tbss" {
3112 continue
3113 }
3114 vlen := int64(s.Length)
3115 if i+1 < len(Segdata.Sections) && !((ctxt.IsELF || ctxt.HeadType == objabi.Haix) && Segdata.Sections[i+1].Name == ".tbss") {
3116 vlen = int64(Segdata.Sections[i+1].Vaddr - s.Vaddr)
3117 }
3118 s.Vaddr = va
3119 va += uint64(vlen)
3120 Segdata.Length = va - Segdata.Vaddr
3121 switch s.Name {
3122 case ".data":
3123 data = s
3124 case ".noptrdata":
3125 noptr = s
3126 case ".bss":
3127 bss = s
3128 case ".noptrbss":
3129 noptrbss = s
3130 case ".go.fuzzcntrs":
3131 fuzzCounters = s
3132 }
3133 }
3134
3135
3136
3137 Segdata.Filelen = bss.Vaddr - Segdata.Vaddr
3138
3139 if len(Segpdata.Sections) > 0 {
3140 va = uint64(Rnd(int64(va), *FlagRound))
3141 order = append(order, &Segpdata)
3142 Segpdata.Rwx = 04
3143 Segpdata.Vaddr = va
3144
3145
3146 for _, s := range Segpdata.Sections {
3147 va = uint64(Rnd(int64(va), int64(s.Align)))
3148 s.Vaddr = va
3149 va += s.Length
3150 }
3151 Segpdata.Length = va - Segpdata.Vaddr
3152 }
3153
3154 if len(Segxdata.Sections) > 0 {
3155 va = uint64(Rnd(int64(va), *FlagRound))
3156 order = append(order, &Segxdata)
3157 Segxdata.Rwx = 04
3158 Segxdata.Vaddr = va
3159
3160
3161 for _, s := range Segxdata.Sections {
3162 va = uint64(Rnd(int64(va), int64(s.Align)))
3163 s.Vaddr = va
3164 va += s.Length
3165 }
3166 Segxdata.Length = va - Segxdata.Vaddr
3167 }
3168
3169 va = uint64(Rnd(int64(va), *FlagRound))
3170 order = append(order, &Segdwarf)
3171 Segdwarf.Rwx = 06
3172 Segdwarf.Vaddr = va
3173 for i, s := range Segdwarf.Sections {
3174 vlen := int64(s.Length)
3175 if i+1 < len(Segdwarf.Sections) {
3176 vlen = int64(Segdwarf.Sections[i+1].Vaddr - s.Vaddr)
3177 }
3178 s.Vaddr = va
3179 va += uint64(vlen)
3180 if ctxt.HeadType == objabi.Hwindows {
3181 va = uint64(Rnd(int64(va), PEFILEALIGN))
3182 }
3183 Segdwarf.Length = va - Segdwarf.Vaddr
3184 }
3185
3186 ldr := ctxt.loader
3187 var (
3188 rodata = ldr.SymSect(ldr.LookupOrCreateSym("runtime.rodata", 0))
3189 pclntab = ldr.SymSect(ldr.LookupOrCreateSym("runtime.pclntab", 0))
3190 types = ldr.SymSect(ldr.LookupOrCreateSym("runtime.types", 0))
3191 )
3192
3193 for _, s := range ctxt.datap {
3194 if sect := ldr.SymSect(s); sect != nil {
3195 ldr.AddToSymValue(s, int64(sect.Vaddr))
3196 }
3197 v := ldr.SymValue(s)
3198 for sub := ldr.SubSym(s); sub != 0; sub = ldr.SubSym(sub) {
3199 ldr.AddToSymValue(sub, v)
3200 }
3201 }
3202
3203 for _, si := range dwarfp {
3204 for _, s := range si.syms {
3205 if sect := ldr.SymSect(s); sect != nil {
3206 ldr.AddToSymValue(s, int64(sect.Vaddr))
3207 }
3208 sub := ldr.SubSym(s)
3209 if sub != 0 {
3210 panic(fmt.Sprintf("unexpected sub-sym for %s %s", ldr.SymName(s), ldr.SymType(s).String()))
3211 }
3212 v := ldr.SymValue(s)
3213 for ; sub != 0; sub = ldr.SubSym(sub) {
3214 ldr.AddToSymValue(s, v)
3215 }
3216 }
3217 }
3218
3219 for _, s := range sehp.pdata {
3220 if sect := ldr.SymSect(s); sect != nil {
3221 ldr.AddToSymValue(s, int64(sect.Vaddr))
3222 }
3223 }
3224 for _, s := range sehp.xdata {
3225 if sect := ldr.SymSect(s); sect != nil {
3226 ldr.AddToSymValue(s, int64(sect.Vaddr))
3227 }
3228 }
3229
3230 if ctxt.BuildMode == BuildModeShared {
3231 s := ldr.LookupOrCreateSym("go:link.abihashbytes", 0)
3232 sect := ldr.SymSect(ldr.LookupOrCreateSym(".note.go.abihash", 0))
3233 ldr.SetSymSect(s, sect)
3234 ldr.SetSymValue(s, int64(sect.Vaddr+16))
3235 }
3236
3237
3238
3239 n := 1
3240 for _, sect := range Segtext.Sections[1:] {
3241 if sect.Name != ".text" {
3242 break
3243 }
3244 symname := fmt.Sprintf("runtime.text.%d", n)
3245 if ctxt.HeadType != objabi.Haix || ctxt.LinkMode != LinkExternal {
3246
3247
3248 ctxt.xdefine(symname, sym.STEXT, int64(sect.Vaddr))
3249 }
3250 n++
3251 }
3252
3253 ctxt.xdefine("runtime.rodata", sym.SRODATA, int64(rodata.Vaddr))
3254 ctxt.xdefine("runtime.erodata", sym.SRODATA, int64(rodata.Vaddr+rodata.Length))
3255 ctxt.xdefine("runtime.types", sym.SRODATA, int64(types.Vaddr))
3256 ctxt.xdefine("runtime.etypes", sym.SRODATA, int64(types.Vaddr+types.Length))
3257
3258 s := ldr.Lookup("runtime.gcdata", 0)
3259 ldr.SetAttrLocal(s, true)
3260 ctxt.xdefine("runtime.egcdata", sym.SRODATA, ldr.SymAddr(s)+ldr.SymSize(s))
3261 ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.egcdata", 0), ldr.SymSect(s))
3262
3263 s = ldr.LookupOrCreateSym("runtime.gcbss", 0)
3264 ldr.SetAttrLocal(s, true)
3265 ctxt.xdefine("runtime.egcbss", sym.SRODATA, ldr.SymAddr(s)+ldr.SymSize(s))
3266 ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.egcbss", 0), ldr.SymSect(s))
3267
3268 ctxt.xdefine("runtime.pclntab", sym.SRODATA, int64(pclntab.Vaddr))
3269 ctxt.defineInternal("runtime.pcheader", sym.SRODATA)
3270 ctxt.defineInternal("runtime.funcnametab", sym.SRODATA)
3271 ctxt.defineInternal("runtime.cutab", sym.SRODATA)
3272 ctxt.defineInternal("runtime.filetab", sym.SRODATA)
3273 ctxt.defineInternal("runtime.pctab", sym.SRODATA)
3274 ctxt.defineInternal("runtime.functab", sym.SRODATA)
3275 ctxt.defineInternal("go:func.*", sym.SRODATA)
3276 ctxt.xdefine("runtime.epclntab", sym.SRODATA, int64(pclntab.Vaddr+pclntab.Length))
3277 ctxt.xdefine("runtime.noptrdata", sym.SNOPTRDATA, int64(noptr.Vaddr))
3278 ctxt.xdefine("runtime.enoptrdata", sym.SNOPTRDATAEND, int64(noptr.Vaddr+noptr.Length))
3279 ctxt.xdefine("runtime.bss", sym.SBSS, int64(bss.Vaddr))
3280 ctxt.xdefine("runtime.ebss", sym.SBSS, int64(bss.Vaddr+bss.Length))
3281 ctxt.xdefine("runtime.data", sym.SDATA, int64(data.Vaddr))
3282 ctxt.xdefine("runtime.edata", sym.SDATAEND, int64(data.Vaddr+data.Length))
3283 ctxt.xdefine("runtime.noptrbss", sym.SNOPTRBSS, int64(noptrbss.Vaddr))
3284 ctxt.xdefine("runtime.enoptrbss", sym.SNOPTRBSS, int64(noptrbss.Vaddr+noptrbss.Length))
3285 s = ldr.Lookup("runtime.gcmask.*", 0)
3286 ctxt.xdefine("runtime.gcmask.*", sym.SGCMASK, int64(noptrbss.Vaddr+uint64(ldr.SymValue(s))))
3287 ctxt.xdefine("runtime.covctrs", sym.SCOVERAGE_COUNTER, int64(noptrbss.Vaddr+covCounterDataStartOff))
3288 ctxt.xdefine("runtime.ecovctrs", sym.SCOVERAGE_COUNTER, int64(noptrbss.Vaddr+covCounterDataStartOff+covCounterDataLen))
3289 ctxt.xdefine("runtime.end", sym.SBSS, int64(Segdata.Vaddr+Segdata.Length))
3290
3291 if fuzzCounters != nil {
3292 if *flagAsan {
3293
3294
3295
3296 fuzzCounters.Length = uint64(Rnd(int64(fuzzCounters.Length), 8))
3297 }
3298 ctxt.xdefine("runtime.__start___sancov_cntrs", sym.SLIBFUZZER_8BIT_COUNTER, int64(fuzzCounters.Vaddr))
3299 ctxt.xdefine("runtime.__stop___sancov_cntrs", sym.SLIBFUZZER_8BIT_COUNTER, int64(fuzzCounters.Vaddr+fuzzCounters.Length))
3300 ctxt.xdefine("internal/fuzz._counters", sym.SLIBFUZZER_8BIT_COUNTER, int64(fuzzCounters.Vaddr))
3301 ctxt.xdefine("internal/fuzz._ecounters", sym.SLIBFUZZER_8BIT_COUNTER, int64(fuzzCounters.Vaddr+fuzzCounters.Length))
3302 }
3303
3304 if ctxt.IsSolaris() {
3305
3306
3307
3308 etext := ldr.Lookup("runtime.etext", 0)
3309 edata := ldr.Lookup("runtime.edata", 0)
3310 end := ldr.Lookup("runtime.end", 0)
3311 ldr.SetSymExtname(etext, "runtime.etext")
3312 ldr.SetSymExtname(edata, "runtime.edata")
3313 ldr.SetSymExtname(end, "runtime.end")
3314 ctxt.xdefine("_etext", ldr.SymType(etext), ldr.SymValue(etext))
3315 ctxt.xdefine("_edata", ldr.SymType(edata), ldr.SymValue(edata))
3316 ctxt.xdefine("_end", ldr.SymType(end), ldr.SymValue(end))
3317 ldr.SetSymSect(ldr.Lookup("_etext", 0), ldr.SymSect(etext))
3318 ldr.SetSymSect(ldr.Lookup("_edata", 0), ldr.SymSect(edata))
3319 ldr.SetSymSect(ldr.Lookup("_end", 0), ldr.SymSect(end))
3320 }
3321
3322 if ctxt.IsPPC64() && ctxt.IsElf() {
3323
3324
3325
3326 tocAddr := int64(Segdata.Vaddr) + 0x8000
3327 if gotAddr := ldr.SymValue(ctxt.GOT); gotAddr != 0 {
3328 tocAddr = gotAddr + 0x8000
3329 }
3330 for i := range ctxt.DotTOC {
3331 if i >= sym.SymVerABICount && i < sym.SymVerStatic {
3332 continue
3333 }
3334 if toc := ldr.Lookup(".TOC.", i); toc != 0 {
3335 ldr.SetSymValue(toc, tocAddr)
3336 }
3337 }
3338 }
3339
3340 if ctxt.IsDarwin() {
3341
3342
3343
3344 machosymtab(ctxt)
3345 if *FlagSplitDWARF && ctxt.IsInternal() {
3346
3347 symtabSz := ldr.SymSize(ldr.Lookup(".machosymtab", 0))
3348 symstrSz := ldr.SymSize(ldr.Lookup(".machosymstr", 0))
3349 off := Rnd(symtabSz+symstrSz, *FlagRound)
3350 Segdwarf.Vaddr += uint64(off)
3351 for _, s := range Segdwarf.Sections {
3352 s.Vaddr += uint64(off)
3353 }
3354 for _, si := range dwarfp {
3355 for _, s := range si.syms {
3356 ldr.AddToSymValue(s, off)
3357 }
3358 }
3359 }
3360 }
3361
3362 return order
3363 }
3364
3365
3366
3367 func (ctxt *Link) layout(order []*sym.Segment) uint64 {
3368 var prev *sym.Segment
3369 for _, seg := range order {
3370 if seg == &Segdwarf && *FlagSplitDWARF && ctxt.IsInternal() {
3371
3372
3373 ldr := ctxt.loader
3374 symtabSz := ldr.SymSize(ldr.Lookup(".machosymtab", 0))
3375 symstrSz := ldr.SymSize(ldr.Lookup(".machosymstr", 0))
3376 off := Rnd(int64(HEADR), *FlagRound)
3377 seg.Fileoff = uint64(Rnd(off+symtabSz+symstrSz, *FlagRound))
3378 seg.Filelen = seg.Length
3379 continue
3380 }
3381 if prev == nil {
3382 seg.Fileoff = uint64(HEADR)
3383 } else {
3384 switch ctxt.HeadType {
3385 default:
3386
3387
3388
3389
3390 seg.Fileoff = uint64(Rnd(int64(prev.Fileoff+prev.Filelen), *FlagRound))
3391 if seg.Vaddr%uint64(*FlagRound) != seg.Fileoff%uint64(*FlagRound) {
3392 Exitf("bad segment rounding (Vaddr=%#x Fileoff=%#x FlagRound=%#x)", seg.Vaddr, seg.Fileoff, *FlagRound)
3393 }
3394 case objabi.Hwindows:
3395 seg.Fileoff = prev.Fileoff + uint64(Rnd(int64(prev.Filelen), PEFILEALIGN))
3396 case objabi.Hplan9:
3397 seg.Fileoff = prev.Fileoff + prev.Filelen
3398 }
3399 }
3400 if seg != &Segdata {
3401
3402
3403 seg.Filelen = seg.Length
3404 }
3405 prev = seg
3406 }
3407 return prev.Fileoff + prev.Filelen
3408 }
3409
3410
3411 func (ctxt *Link) AddTramp(s *loader.SymbolBuilder, typ sym.SymKind) {
3412 s.SetType(typ)
3413 s.SetReachable(true)
3414 s.SetOnList(true)
3415 ctxt.tramps = append(ctxt.tramps, s.Sym())
3416 if *FlagDebugTramp > 0 && ctxt.Debugvlog > 0 {
3417 ctxt.Logf("trampoline %s inserted\n", s.Name())
3418 }
3419 }
3420
3421
3422
3423 func (ctxt *Link) AddDwarfDirectTrampoline(s, target loader.Sym, addend int64, ownerCU *sym.CompilationUnit) {
3424 if ownerCU == nil {
3425
3426
3427 return
3428 }
3429 if ownerCU.DWInfo == nil {
3430
3431
3432 return
3433 }
3434 switch ctxt.loader.SymType(target) {
3435 case sym.SDYNIMPORT, sym.SUNDEFEXT:
3436
3437
3438 return
3439 }
3440 ctxt.dwarfTrampolines = append(ctxt.dwarfTrampolines, dwarfTrampoline{
3441 sym: s,
3442 target: target,
3443 addend: addend,
3444 ownerCU: ownerCU,
3445 })
3446 }
3447
3448
3449
3450 func compressSyms(ctxt *Link, syms []loader.Sym) []byte {
3451 ldr := ctxt.loader
3452 var total int64
3453 for _, sym := range syms {
3454 total += ldr.SymSize(sym)
3455 }
3456
3457 var buf bytes.Buffer
3458 if ctxt.IsELF {
3459 switch ctxt.Arch.PtrSize {
3460 case 8:
3461 binary.Write(&buf, ctxt.Arch.ByteOrder, elf.Chdr64{
3462 Type: uint32(elf.COMPRESS_ZLIB),
3463 Size: uint64(total),
3464 Addralign: uint64(ctxt.Arch.Alignment),
3465 })
3466 case 4:
3467 binary.Write(&buf, ctxt.Arch.ByteOrder, elf.Chdr32{
3468 Type: uint32(elf.COMPRESS_ZLIB),
3469 Size: uint32(total),
3470 Addralign: uint32(ctxt.Arch.Alignment),
3471 })
3472 default:
3473 log.Fatalf("can't compress header size:%d", ctxt.Arch.PtrSize)
3474 }
3475 } else {
3476 buf.Write([]byte("ZLIB"))
3477 var sizeBytes [8]byte
3478 binary.BigEndian.PutUint64(sizeBytes[:], uint64(total))
3479 buf.Write(sizeBytes[:])
3480 }
3481
3482 var relocbuf []byte
3483
3484
3485
3486
3487
3488 z, err := zlib.NewWriterLevel(&buf, zlib.BestSpeed)
3489 if err != nil {
3490 log.Fatalf("NewWriterLevel failed: %s", err)
3491 }
3492 st := ctxt.makeRelocSymState()
3493 for _, s := range syms {
3494
3495
3496 P := ldr.Data(s)
3497 relocs := ldr.Relocs(s)
3498 if relocs.Count() != 0 {
3499 relocbuf = append(relocbuf[:0], P...)
3500 P = relocbuf
3501 st.relocsym(s, P)
3502 }
3503 if _, err := z.Write(P); err != nil {
3504 log.Fatalf("compression failed: %s", err)
3505 }
3506 for i := ldr.SymSize(s) - int64(len(P)); i > 0; {
3507 b := zeros[:]
3508 if i < int64(len(b)) {
3509 b = b[:i]
3510 }
3511 n, err := z.Write(b)
3512 if err != nil {
3513 log.Fatalf("compression failed: %s", err)
3514 }
3515 i -= int64(n)
3516 }
3517 }
3518 if err := z.Close(); err != nil {
3519 log.Fatalf("compression failed: %s", err)
3520 }
3521 if int64(buf.Len()) >= total {
3522
3523 return nil
3524 }
3525 return buf.Bytes()
3526 }
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536 func writeUleb128FixedLength(b []byte, v uint64, length int) error {
3537 for i := 0; i < length; i++ {
3538 c := uint8(v & 0x7f)
3539 v >>= 7
3540 if i < length-1 {
3541 c |= 0x80
3542 }
3543 b[i] = c
3544 }
3545 if v != 0 {
3546 return fmt.Errorf("writeUleb128FixedLength: length too small")
3547 }
3548 return nil
3549 }
3550
View as plain text