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