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