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