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