1
2
3
4
5 package ld
6
7 import (
8 "cmd/internal/hash"
9 "cmd/internal/objabi"
10 "cmd/internal/sys"
11 "cmd/link/internal/loader"
12 "cmd/link/internal/sym"
13 "cmp"
14 "debug/elf"
15 "encoding/binary"
16 "encoding/hex"
17 "fmt"
18 "internal/buildcfg"
19 "os"
20 "path/filepath"
21 "runtime"
22 "slices"
23 "strings"
24 )
25
26
64
65
66
67
68
69
70
71
72 type ElfEhdr elf.Header64
73
74
75 type ElfShdr struct {
76 elf.Section64
77
78
79
80
81 nameString string
82
83
84
85 shnum elf.SectionIndex
86
87
88
89
90
91 link *ElfShdr
92 info *ElfShdr
93
94
95
96
97 relocSect *sym.Section
98 }
99
100
101 type ElfPhdr elf.ProgHeader
102
103 const (
104 ELF64HDRSIZE = 64
105 ELF64PHDRSIZE = 56
106 ELF64SHDRSIZE = 64
107 ELF64RELSIZE = 16
108 ELF64RELASIZE = 24
109 ELF64SYMSIZE = 24
110 ELF32HDRSIZE = 52
111 ELF32PHDRSIZE = 32
112 ELF32SHDRSIZE = 40
113 ELF32SYMSIZE = 16
114 ELF32RELSIZE = 8
115 )
116
117 var elfstrdat []byte
118
119
120
121
122
123 const ELFRESERVE = 4096
124
125 var (
126 Nelfsym = 1
127
128 elf64 bool
129
130
131 elfRelType string
132
133 ehdr ElfEhdr
134 phdr = make([]*ElfPhdr, 0, 8)
135 shdr = make([]*ElfShdr, 0, 64)
136 shdrSorted bool
137
138 interp string
139 )
140
141
142
143
144 type ELFArch struct {
145
146
147 Androiddynld string
148 Linuxdynld string
149 LinuxdynldMusl string
150 Freebsddynld string
151 Netbsddynld string
152 Openbsddynld string
153 Dragonflydynld string
154 Solarisdynld string
155
156 Reloc1 func(*Link, *OutBuf, *loader.Loader, loader.Sym, loader.ExtReloc, int, int64) bool
157 RelocSize uint32
158 SetupPLT func(ctxt *Link, ldr *loader.Loader, plt, gotplt *loader.SymbolBuilder, dynamic loader.Sym)
159
160
161
162
163 DynamicReadOnly bool
164 }
165
166 var buildinfo []byte
167
168
169
170 func Elfinit(ctxt *Link) {
171 ctxt.IsELF = true
172
173 if ctxt.Arch.InFamily(sys.AMD64, sys.ARM64, sys.Loong64, sys.MIPS64, sys.PPC64, sys.RISCV64, sys.S390X) {
174 elfRelType = ".rela"
175 } else {
176 elfRelType = ".rel"
177 }
178
179 switch ctxt.Arch.Family {
180
181 case sys.PPC64, sys.S390X:
182 if ctxt.Arch.ByteOrder == binary.BigEndian && ctxt.HeadType != objabi.Hopenbsd {
183 ehdr.Flags = 1
184 } else {
185 ehdr.Flags = 2
186 }
187 fallthrough
188 case sys.AMD64, sys.ARM64, sys.Loong64, sys.MIPS64, sys.RISCV64:
189 if ctxt.Arch.Family == sys.MIPS64 {
190 ehdr.Flags = 0x20000004
191 }
192 if ctxt.Arch.Family == sys.Loong64 {
193 ehdr.Flags = 0x43
194 }
195 if ctxt.Arch.Family == sys.RISCV64 {
196 ehdr.Flags = 0x4
197 }
198 elf64 = true
199
200 ehdr.Phoff = ELF64HDRSIZE
201 ehdr.Shoff = ELF64HDRSIZE
202 ehdr.Ehsize = ELF64HDRSIZE
203 ehdr.Phentsize = ELF64PHDRSIZE
204 ehdr.Shentsize = ELF64SHDRSIZE
205
206
207 case sys.ARM, sys.MIPS:
208 if ctxt.Arch.Family == sys.ARM {
209
210 if ctxt.HeadType == objabi.Hlinux || ctxt.HeadType == objabi.Hfreebsd || ctxt.HeadType == objabi.Hnetbsd {
211
212
213
214
215
216
217
218
219 ehdr.Flags = 0x5000002
220 }
221 } else if ctxt.Arch.Family == sys.MIPS {
222 ehdr.Flags = 0x50001004
223 }
224 fallthrough
225 default:
226 ehdr.Phoff = ELF32HDRSIZE
227
228 ehdr.Shoff = ELF32HDRSIZE
229 ehdr.Ehsize = ELF32HDRSIZE
230 ehdr.Phentsize = ELF32PHDRSIZE
231 ehdr.Shentsize = ELF32SHDRSIZE
232 }
233 }
234
235
236
237
238
239 func fixElfPhdr(e *ElfPhdr) {
240 frag := int(e.Vaddr & (e.Align - 1))
241
242 e.Off -= uint64(frag)
243 e.Vaddr -= uint64(frag)
244 e.Paddr -= uint64(frag)
245 e.Filesz += uint64(frag)
246 e.Memsz += uint64(frag)
247 }
248
249 func elf64phdr(out *OutBuf, e *ElfPhdr) {
250 if e.Type == elf.PT_LOAD {
251 fixElfPhdr(e)
252 }
253
254 out.Write32(uint32(e.Type))
255 out.Write32(uint32(e.Flags))
256 out.Write64(e.Off)
257 out.Write64(e.Vaddr)
258 out.Write64(e.Paddr)
259 out.Write64(e.Filesz)
260 out.Write64(e.Memsz)
261 out.Write64(e.Align)
262 }
263
264 func elf32phdr(out *OutBuf, e *ElfPhdr) {
265 if e.Type == elf.PT_LOAD {
266 fixElfPhdr(e)
267 }
268
269 out.Write32(uint32(e.Type))
270 out.Write32(uint32(e.Off))
271 out.Write32(uint32(e.Vaddr))
272 out.Write32(uint32(e.Paddr))
273 out.Write32(uint32(e.Filesz))
274 out.Write32(uint32(e.Memsz))
275 out.Write32(uint32(e.Flags))
276 out.Write32(uint32(e.Align))
277 }
278
279
280 func elfShdrShnum(e *ElfShdr) elf.SectionIndex {
281 if e.shnum == -1 {
282 Errorf("internal error: retrieved section index before it is set")
283 errorexit()
284 }
285 return e.shnum
286 }
287
288
289 func elfShdrOff(e *ElfShdr) uint64 {
290 if e.relocSect != nil {
291 if e.Off != 0 {
292 Errorf("internal error: ElfShdr relocSect == %p Off == %d", e.relocSect, e.Off)
293 errorexit()
294 }
295 return e.relocSect.Reloff
296 }
297 return e.Off
298 }
299
300
301 func elfShdrSize(e *ElfShdr) uint64 {
302 if e.relocSect != nil {
303 if e.Size != 0 {
304 Errorf("internal error: ElfShdr relocSect == %p Size == %d", e.relocSect, e.Size)
305 errorexit()
306 }
307 return e.relocSect.Rellen
308 }
309 return e.Size
310 }
311
312
313 func elfShdrLink(e *ElfShdr) uint32 {
314 if e.link != nil {
315 if e.Link != 0 {
316 Errorf("internal error: ElfShdr link == %p Link == %d", e.link, e.Link)
317 errorexit()
318 }
319 return uint32(elfShdrShnum(e.link))
320 }
321 return e.Link
322 }
323
324
325 func elfShdrInfo(e *ElfShdr) uint32 {
326 if e.info != nil {
327 if e.Info != 0 {
328 Errorf("internal error: ElfShdr info == %p Info == %d", e.info, e.Info)
329 errorexit()
330 }
331 return uint32(elfShdrShnum(e.info))
332 }
333 return e.Info
334 }
335
336 func elf64shdr(out *OutBuf, e *ElfShdr) {
337 out.Write32(e.Name)
338 out.Write32(e.Type)
339 out.Write64(e.Flags)
340 out.Write64(e.Addr)
341 out.Write64(elfShdrOff(e))
342 out.Write64(elfShdrSize(e))
343 out.Write32(elfShdrLink(e))
344 out.Write32(elfShdrInfo(e))
345 out.Write64(e.Addralign)
346 out.Write64(e.Entsize)
347 }
348
349 func elf32shdr(out *OutBuf, e *ElfShdr) {
350 out.Write32(e.Name)
351 out.Write32(e.Type)
352 out.Write32(uint32(e.Flags))
353 out.Write32(uint32(e.Addr))
354 out.Write32(uint32(elfShdrOff(e)))
355 out.Write32(uint32(elfShdrSize(e)))
356 out.Write32(elfShdrLink(e))
357 out.Write32(elfShdrInfo(e))
358 out.Write32(uint32(e.Addralign))
359 out.Write32(uint32(e.Entsize))
360 }
361
362 func elfwriteshdrs(out *OutBuf) uint32 {
363 if elf64 {
364 for _, sh := range shdr {
365 elf64shdr(out, sh)
366 }
367 return uint32(len(shdr)) * ELF64SHDRSIZE
368 }
369
370 for _, sh := range shdr {
371 elf32shdr(out, sh)
372 }
373 return uint32(len(shdr)) * ELF32SHDRSIZE
374 }
375
376
377
378
379
380 func elfSortShdrs(ctxt *Link) {
381 if ctxt.LinkMode != LinkExternal {
382
383 slices.SortStableFunc(shdr[1:], func(a, b *ElfShdr) int {
384 isAllocated := func(h *ElfShdr) bool {
385 return elf.SectionFlag(h.Flags)&elf.SHF_ALLOC != 0
386 }
387 if isAllocated(a) {
388 if isAllocated(b) {
389 if r := cmp.Compare(a.Addr, b.Addr); r != 0 {
390 return r
391 }
392
393
394 return cmp.Compare(a.Size, b.Size)
395 }
396
397 return -1
398 }
399 if isAllocated(b) {
400
401 return 1
402 }
403 return 0
404 })
405 }
406 for i, h := range shdr {
407 h.shnum = elf.SectionIndex(i)
408 }
409 shdrSorted = true
410 }
411
412
413
414
415 func elfWriteShstrtab(ctxt *Link) uint32 {
416
417 m := make(map[string]uint32, len(shdr))
418
419 m[""] = 0
420 ctxt.Out.WriteByte(0)
421 off := uint32(1)
422
423 writeString := func(s string) {
424 m[s] = off
425 ctxt.Out.WriteString(s)
426 ctxt.Out.WriteByte(0)
427 off += uint32(len(s)) + 1
428 }
429
430
431
432
433
434
435 for _, sh := range shdr {
436 if suffix, ok := strings.CutPrefix(sh.nameString, elfRelType); ok {
437 if _, found := m[suffix]; !found {
438 m[suffix] = off + uint32(len(elfRelType))
439 }
440 writeString(sh.nameString)
441 }
442 }
443
444 for _, sh := range shdr {
445 if shOff, ok := m[sh.nameString]; ok {
446 sh.Name = shOff
447 } else {
448 sh.Name = off
449 writeString(sh.nameString)
450 }
451 }
452
453 return off
454 }
455
456 func elfwritephdrs(out *OutBuf) uint32 {
457 if elf64 {
458 for i := 0; i < int(ehdr.Phnum); i++ {
459 elf64phdr(out, phdr[i])
460 }
461 return uint32(ehdr.Phnum) * ELF64PHDRSIZE
462 }
463
464 for i := 0; i < int(ehdr.Phnum); i++ {
465 elf32phdr(out, phdr[i])
466 }
467 return uint32(ehdr.Phnum) * ELF32PHDRSIZE
468 }
469
470 func newElfPhdr() *ElfPhdr {
471 e := new(ElfPhdr)
472 phdr = append(phdr, e)
473 ehdr.Phnum++
474 if elf64 {
475 ehdr.Shoff += ELF64PHDRSIZE
476 } else {
477 ehdr.Shoff += ELF32PHDRSIZE
478 }
479 return e
480 }
481
482 func newElfShdr(name string) *ElfShdr {
483 if shdrSorted {
484 Errorf("internal error: creating a section header after they were sorted")
485 errorexit()
486 }
487
488 e := &ElfShdr{
489 nameString: name,
490 shnum: -1,
491 }
492 shdr = append(shdr, e)
493 return e
494 }
495
496 func getElfEhdr() *ElfEhdr {
497 return &ehdr
498 }
499
500 func elf64writehdr(out *OutBuf) uint32 {
501 out.Write(ehdr.Ident[:])
502 out.Write16(ehdr.Type)
503 out.Write16(ehdr.Machine)
504 out.Write32(ehdr.Version)
505 out.Write64(ehdr.Entry)
506 out.Write64(ehdr.Phoff)
507 out.Write64(ehdr.Shoff)
508 out.Write32(ehdr.Flags)
509 out.Write16(ehdr.Ehsize)
510 out.Write16(ehdr.Phentsize)
511 out.Write16(ehdr.Phnum)
512 out.Write16(ehdr.Shentsize)
513 out.Write16(ehdr.Shnum)
514 out.Write16(ehdr.Shstrndx)
515 return ELF64HDRSIZE
516 }
517
518 func elf32writehdr(out *OutBuf) uint32 {
519 out.Write(ehdr.Ident[:])
520 out.Write16(ehdr.Type)
521 out.Write16(ehdr.Machine)
522 out.Write32(ehdr.Version)
523 out.Write32(uint32(ehdr.Entry))
524 out.Write32(uint32(ehdr.Phoff))
525 out.Write32(uint32(ehdr.Shoff))
526 out.Write32(ehdr.Flags)
527 out.Write16(ehdr.Ehsize)
528 out.Write16(ehdr.Phentsize)
529 out.Write16(ehdr.Phnum)
530 out.Write16(ehdr.Shentsize)
531 out.Write16(ehdr.Shnum)
532 out.Write16(ehdr.Shstrndx)
533 return ELF32HDRSIZE
534 }
535
536 func elfwritehdr(out *OutBuf) uint32 {
537 if elf64 {
538 return elf64writehdr(out)
539 }
540 return elf32writehdr(out)
541 }
542
543
544
545
546
547 func elfhash(name string) uint32 {
548 var h uint32
549 for i := 0; i < len(name); i++ {
550 h = (h << 4) + uint32(name[i])
551 if g := h & 0xf0000000; g != 0 {
552 h ^= g >> 24
553 }
554 h &= 0x0fffffff
555 }
556 return h
557 }
558
559 func elfWriteDynEntSym(ctxt *Link, s *loader.SymbolBuilder, tag elf.DynTag, t loader.Sym) {
560 Elfwritedynentsymplus(ctxt, s, tag, t, 0)
561 }
562
563 func Elfwritedynent(arch *sys.Arch, s *loader.SymbolBuilder, tag elf.DynTag, val uint64) {
564 if elf64 {
565 s.AddUint64(arch, uint64(tag))
566 s.AddUint64(arch, val)
567 } else {
568 s.AddUint32(arch, uint32(tag))
569 s.AddUint32(arch, uint32(val))
570 }
571 }
572
573 func Elfwritedynentsymplus(ctxt *Link, s *loader.SymbolBuilder, tag elf.DynTag, t loader.Sym, add int64) {
574 if elf64 {
575 s.AddUint64(ctxt.Arch, uint64(tag))
576 } else {
577 s.AddUint32(ctxt.Arch, uint32(tag))
578 }
579 s.AddAddrPlus(ctxt.Arch, t, add)
580 }
581
582 func elfwritedynentsymsize(ctxt *Link, s *loader.SymbolBuilder, tag elf.DynTag, t loader.Sym) {
583 if elf64 {
584 s.AddUint64(ctxt.Arch, uint64(tag))
585 } else {
586 s.AddUint32(ctxt.Arch, uint32(tag))
587 }
588 s.AddSize(ctxt.Arch, t)
589 }
590
591 func elfinterp(sh *ElfShdr, startva uint64, resoff uint64, p string) int {
592 interp = p
593 n := len(interp) + 1
594 sh.Addr = startva + resoff - uint64(n)
595 sh.Off = resoff - uint64(n)
596 sh.Size = uint64(n)
597
598 return n
599 }
600
601 func elfwriteinterp(out *OutBuf) int {
602 sh := elfshname(".interp")
603 out.SeekSet(int64(sh.Off))
604 out.WriteString(interp)
605 out.Write8(0)
606 return int(sh.Size)
607 }
608
609
610 const (
611
612 MIPS_FPABI_NONE = 0
613
614 MIPS_FPABI_ANY = 1
615
616 MIPS_FPABI_SINGLE = 2
617
618 MIPS_FPABI_SOFT = 3
619
620
621 MIPS_FPABI_HIST = 4
622
623 MIPS_FPABI_FPXX = 5
624
625 MIPS_FPABI_FP64 = 6
626
627 MIPS_FPABI_FP64A = 7
628 )
629
630 func elfMipsAbiFlags(sh *ElfShdr, startva uint64, resoff uint64) int {
631 n := 24
632 sh.Addr = startva + resoff - uint64(n)
633 sh.Off = resoff - uint64(n)
634 sh.Size = uint64(n)
635 sh.Type = uint32(elf.SHT_MIPS_ABIFLAGS)
636 sh.Flags = uint64(elf.SHF_ALLOC)
637
638 return n
639 }
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669 func elfWriteMipsAbiFlags(ctxt *Link) int {
670 sh := elfshname(".MIPS.abiflags")
671 ctxt.Out.SeekSet(int64(sh.Off))
672 ctxt.Out.Write16(0)
673 ctxt.Out.Write8(32)
674 ctxt.Out.Write8(1)
675 ctxt.Out.Write8(1)
676 ctxt.Out.Write8(1)
677 ctxt.Out.Write8(0)
678 if buildcfg.GOMIPS == "softfloat" {
679 ctxt.Out.Write8(MIPS_FPABI_SOFT)
680 } else {
681
682
683
684
685
686
687
688 ctxt.Out.Write8(MIPS_FPABI_ANY)
689 }
690 ctxt.Out.Write32(0)
691 ctxt.Out.Write32(0)
692 ctxt.Out.Write32(0)
693 ctxt.Out.Write32(0)
694 return int(sh.Size)
695 }
696
697 func elfnote(sh *ElfShdr, startva uint64, resoff uint64, sizes ...int) int {
698 n := resoff % 4
699
700
701 for _, sz := range sizes {
702 n += 3*4 + uint64(sz)
703 }
704
705 sh.Type = uint32(elf.SHT_NOTE)
706 sh.Flags = uint64(elf.SHF_ALLOC)
707 sh.Addralign = 4
708 sh.Addr = startva + resoff - n
709 sh.Off = resoff - n
710 sh.Size = n - resoff%4
711
712 return int(n)
713 }
714
715 func elfwritenotehdr(out *OutBuf, str string, namesz uint32, descsz uint32, tag uint32) *ElfShdr {
716 sh := elfshname(str)
717
718
719 out.SeekSet(int64(sh.Off))
720
721 out.Write32(namesz)
722 out.Write32(descsz)
723 out.Write32(tag)
724
725 return sh
726 }
727
728
729 const (
730 ELF_NOTE_NETBSD_NAMESZ = 7
731 ELF_NOTE_NETBSD_DESCSZ = 4
732 ELF_NOTE_NETBSD_TAG = 1
733 ELF_NOTE_NETBSD_VERSION = 700000000
734 )
735
736 var ELF_NOTE_NETBSD_NAME = []byte("NetBSD\x00")
737
738 func elfnetbsdsig(sh *ElfShdr, startva uint64, resoff uint64) int {
739 n := int(Rnd(ELF_NOTE_NETBSD_NAMESZ, 4) + Rnd(ELF_NOTE_NETBSD_DESCSZ, 4))
740 return elfnote(sh, startva, resoff, n)
741 }
742
743 func elfwritenetbsdsig(out *OutBuf) int {
744
745 sh := elfwritenotehdr(out, ".note.netbsd.ident", ELF_NOTE_NETBSD_NAMESZ, ELF_NOTE_NETBSD_DESCSZ, ELF_NOTE_NETBSD_TAG)
746
747 if sh == nil {
748 return 0
749 }
750
751
752 out.Write(ELF_NOTE_NETBSD_NAME)
753 out.Write8(0)
754 out.Write32(ELF_NOTE_NETBSD_VERSION)
755
756 return int(sh.Size)
757 }
758
759
760
761
762
763 func elfnetbsdpax(sh *ElfShdr, startva uint64, resoff uint64) int {
764 n := int(Rnd(4, 4) + Rnd(4, 4))
765 return elfnote(sh, startva, resoff, n)
766 }
767
768 func elfwritenetbsdpax(out *OutBuf) int {
769 sh := elfwritenotehdr(out, ".note.netbsd.pax", 4 , 4 , 0x03 )
770 if sh == nil {
771 return 0
772 }
773 out.Write([]byte("PaX\x00"))
774 out.Write32(0x20)
775 return int(sh.Size)
776 }
777
778
779 const (
780 ELF_NOTE_OPENBSD_NAMESZ = 8
781 ELF_NOTE_OPENBSD_DESCSZ = 4
782 ELF_NOTE_OPENBSD_TAG = 1
783 ELF_NOTE_OPENBSD_VERSION = 0
784 )
785
786 var ELF_NOTE_OPENBSD_NAME = []byte("OpenBSD\x00")
787
788 func elfopenbsdsig(sh *ElfShdr, startva uint64, resoff uint64) int {
789 n := ELF_NOTE_OPENBSD_NAMESZ + ELF_NOTE_OPENBSD_DESCSZ
790 return elfnote(sh, startva, resoff, n)
791 }
792
793 func elfwriteopenbsdsig(out *OutBuf) int {
794
795 sh := elfwritenotehdr(out, ".note.openbsd.ident", ELF_NOTE_OPENBSD_NAMESZ, ELF_NOTE_OPENBSD_DESCSZ, ELF_NOTE_OPENBSD_TAG)
796
797 if sh == nil {
798 return 0
799 }
800
801
802 out.Write(ELF_NOTE_OPENBSD_NAME)
803
804 out.Write32(ELF_NOTE_OPENBSD_VERSION)
805
806 return int(sh.Size)
807 }
808
809
810 const (
811 ELF_NOTE_FREEBSD_NAMESZ = 8
812 ELF_NOTE_FREEBSD_DESCSZ = 4
813 ELF_NOTE_FREEBSD_ABI_TAG = 1
814 ELF_NOTE_FREEBSD_NOINIT_TAG = 2
815 ELF_NOTE_FREEBSD_FEATURE_CTL_TAG = 4
816 ELF_NOTE_FREEBSD_VERSION = 1203000
817 ELF_NOTE_FREEBSD_FCTL_ASLR_DISABLE = 0x1
818 )
819
820 const ELF_NOTE_FREEBSD_NAME = "FreeBSD\x00"
821
822 func elffreebsdsig(sh *ElfShdr, startva uint64, resoff uint64) int {
823 n := ELF_NOTE_FREEBSD_NAMESZ + ELF_NOTE_FREEBSD_DESCSZ
824
825 return elfnote(sh, startva, resoff, n, n, n)
826 }
827
828
829
830
831
832
833
834 func elfwritefreebsdsig(out *OutBuf) int {
835 sh := elfshname(".note.tag")
836 if sh == nil {
837 return 0
838 }
839 out.SeekSet(int64(sh.Off))
840
841
842 out.Write32(ELF_NOTE_FREEBSD_NAMESZ)
843 out.Write32(ELF_NOTE_FREEBSD_DESCSZ)
844 out.Write32(ELF_NOTE_FREEBSD_ABI_TAG)
845 out.WriteString(ELF_NOTE_FREEBSD_NAME)
846 out.Write32(ELF_NOTE_FREEBSD_VERSION)
847
848
849 out.Write32(ELF_NOTE_FREEBSD_NAMESZ)
850 out.Write32(ELF_NOTE_FREEBSD_DESCSZ)
851 out.Write32(ELF_NOTE_FREEBSD_NOINIT_TAG)
852 out.WriteString(ELF_NOTE_FREEBSD_NAME)
853 out.Write32(0)
854
855
856 out.Write32(ELF_NOTE_FREEBSD_NAMESZ)
857 out.Write32(ELF_NOTE_FREEBSD_DESCSZ)
858 out.Write32(ELF_NOTE_FREEBSD_FEATURE_CTL_TAG)
859 out.WriteString(ELF_NOTE_FREEBSD_NAME)
860 if *flagRace {
861
862 out.Write32(ELF_NOTE_FREEBSD_FCTL_ASLR_DISABLE)
863 } else {
864 out.Write32(0)
865 }
866
867 return int(sh.Size)
868 }
869
870 func addbuildinfo(ctxt *Link) {
871 val := *flagHostBuildid
872 if val == "" || val == "none" {
873 return
874 }
875 if val == "gobuildid" {
876 buildID := *flagBuildid
877 if buildID == "" {
878 Exitf("-B gobuildid requires a Go build ID supplied via -buildid")
879 }
880
881 if ctxt.IsDarwin() {
882 buildinfo = uuidFromGoBuildId(buildID)
883 return
884 }
885
886 hashedBuildID := hash.Sum32([]byte(buildID))
887 buildinfo = hashedBuildID[:20]
888
889 return
890 }
891
892 if !strings.HasPrefix(val, "0x") {
893 Exitf("-B argument must start with 0x: %s", val)
894 }
895 ov := val
896 val = val[2:]
897
898 maxLen := 32
899 if ctxt.IsDarwin() {
900 maxLen = 16
901 }
902 if hex.DecodedLen(len(val)) > maxLen {
903 Exitf("-B option too long (max %d digits): %s", maxLen, ov)
904 }
905
906 b, err := hex.DecodeString(val)
907 if err != nil {
908 if err == hex.ErrLength {
909 Exitf("-B argument must have even number of digits: %s", ov)
910 }
911 if inv, ok := err.(hex.InvalidByteError); ok {
912 Exitf("-B argument contains invalid hex digit %c: %s", byte(inv), ov)
913 }
914 Exitf("-B argument contains invalid hex: %s", ov)
915 }
916
917 buildinfo = b
918 }
919
920
921 const (
922 ELF_NOTE_BUILDINFO_NAMESZ = 4
923 ELF_NOTE_BUILDINFO_TAG = 3
924 )
925
926 var ELF_NOTE_BUILDINFO_NAME = []byte("GNU\x00")
927
928 func elfbuildinfo(sh *ElfShdr, startva uint64, resoff uint64) int {
929 n := int(ELF_NOTE_BUILDINFO_NAMESZ + Rnd(int64(len(buildinfo)), 4))
930 return elfnote(sh, startva, resoff, n)
931 }
932
933 func elfgobuildid(sh *ElfShdr, startva uint64, resoff uint64) int {
934 n := len(ELF_NOTE_GO_NAME) + int(Rnd(int64(len(*flagBuildid)), 4))
935 return elfnote(sh, startva, resoff, n)
936 }
937
938 func elfwritebuildinfo(out *OutBuf) int {
939 sh := elfwritenotehdr(out, ".note.gnu.build-id", ELF_NOTE_BUILDINFO_NAMESZ, uint32(len(buildinfo)), ELF_NOTE_BUILDINFO_TAG)
940 if sh == nil {
941 return 0
942 }
943
944 out.Write(ELF_NOTE_BUILDINFO_NAME)
945 out.Write(buildinfo)
946 var zero = make([]byte, 4)
947 out.Write(zero[:int(Rnd(int64(len(buildinfo)), 4)-int64(len(buildinfo)))])
948
949 return int(sh.Size)
950 }
951
952 func elfwritegobuildid(out *OutBuf) int {
953 sh := elfwritenotehdr(out, ".note.go.buildid", uint32(len(ELF_NOTE_GO_NAME)), uint32(len(*flagBuildid)), ELF_NOTE_GOBUILDID_TAG)
954 if sh == nil {
955 return 0
956 }
957
958 out.Write(ELF_NOTE_GO_NAME)
959 out.Write([]byte(*flagBuildid))
960 var zero = make([]byte, 4)
961 out.Write(zero[:int(Rnd(int64(len(*flagBuildid)), 4)-int64(len(*flagBuildid)))])
962
963 return int(sh.Size)
964 }
965
966
967 const (
968 ELF_NOTE_GOPKGLIST_TAG = 1
969 ELF_NOTE_GOABIHASH_TAG = 2
970 ELF_NOTE_GODEPS_TAG = 3
971 ELF_NOTE_GOBUILDID_TAG = 4
972 )
973
974 var ELF_NOTE_GO_NAME = []byte("Go\x00\x00")
975
976 var elfverneed int
977
978 type Elfaux struct {
979 next *Elfaux
980 num int
981 vers string
982 }
983
984 type Elflib struct {
985 next *Elflib
986 aux *Elfaux
987 file string
988 }
989
990 func addelflib(list **Elflib, file string, vers string) *Elfaux {
991 var lib *Elflib
992
993 for lib = *list; lib != nil; lib = lib.next {
994 if lib.file == file {
995 goto havelib
996 }
997 }
998 lib = new(Elflib)
999 lib.next = *list
1000 lib.file = file
1001 *list = lib
1002
1003 havelib:
1004 for aux := lib.aux; aux != nil; aux = aux.next {
1005 if aux.vers == vers {
1006 return aux
1007 }
1008 }
1009 aux := new(Elfaux)
1010 aux.next = lib.aux
1011 aux.vers = vers
1012 lib.aux = aux
1013
1014 return aux
1015 }
1016
1017 func elfdynhash(ctxt *Link) {
1018 if !ctxt.IsELF {
1019 return
1020 }
1021
1022 nsym := Nelfsym
1023 ldr := ctxt.loader
1024 s := ldr.CreateSymForUpdate(".hash", 0)
1025 s.SetType(sym.SELFROSECT)
1026
1027 i := nsym
1028 nbucket := 1
1029 for i > 0 {
1030 nbucket++
1031 i >>= 1
1032 }
1033
1034 var needlib *Elflib
1035 need := make([]*Elfaux, nsym)
1036 chain := make([]uint32, nsym)
1037 buckets := make([]uint32, nbucket)
1038
1039 for _, sy := range ldr.DynidSyms() {
1040
1041 dynid := ldr.SymDynid(sy)
1042 if ldr.SymDynimpvers(sy) != "" {
1043 need[dynid] = addelflib(&needlib, ldr.SymDynimplib(sy), ldr.SymDynimpvers(sy))
1044 }
1045
1046 name := ldr.SymExtname(sy)
1047 hc := elfhash(name)
1048
1049 b := hc % uint32(nbucket)
1050 chain[dynid] = buckets[b]
1051 buckets[b] = uint32(dynid)
1052 }
1053
1054
1055 if ctxt.Arch.Family == sys.S390X {
1056 s.AddUint64(ctxt.Arch, uint64(nbucket))
1057 s.AddUint64(ctxt.Arch, uint64(nsym))
1058 for i := 0; i < nbucket; i++ {
1059 s.AddUint64(ctxt.Arch, uint64(buckets[i]))
1060 }
1061 for i := 0; i < nsym; i++ {
1062 s.AddUint64(ctxt.Arch, uint64(chain[i]))
1063 }
1064 } else {
1065 s.AddUint32(ctxt.Arch, uint32(nbucket))
1066 s.AddUint32(ctxt.Arch, uint32(nsym))
1067 for i := 0; i < nbucket; i++ {
1068 s.AddUint32(ctxt.Arch, buckets[i])
1069 }
1070 for i := 0; i < nsym; i++ {
1071 s.AddUint32(ctxt.Arch, chain[i])
1072 }
1073 }
1074
1075 dynstr := ldr.CreateSymForUpdate(".dynstr", 0)
1076
1077
1078 gnuVersionR := ldr.CreateSymForUpdate(".gnu.version_r", 0)
1079 s = gnuVersionR
1080 i = 2
1081 nfile := 0
1082 for l := needlib; l != nil; l = l.next {
1083 nfile++
1084
1085
1086 s.AddUint16(ctxt.Arch, 1)
1087 j := 0
1088 for x := l.aux; x != nil; x = x.next {
1089 j++
1090 }
1091 s.AddUint16(ctxt.Arch, uint16(j))
1092 s.AddUint32(ctxt.Arch, uint32(dynstr.Addstring(l.file)))
1093 s.AddUint32(ctxt.Arch, 16)
1094 if l.next != nil {
1095 s.AddUint32(ctxt.Arch, 16+uint32(j)*16)
1096 } else {
1097 s.AddUint32(ctxt.Arch, 0)
1098 }
1099
1100 for x := l.aux; x != nil; x = x.next {
1101 x.num = i
1102 i++
1103
1104
1105 s.AddUint32(ctxt.Arch, elfhash(x.vers))
1106 s.AddUint16(ctxt.Arch, 0)
1107 s.AddUint16(ctxt.Arch, uint16(x.num))
1108 s.AddUint32(ctxt.Arch, uint32(dynstr.Addstring(x.vers)))
1109 if x.next != nil {
1110 s.AddUint32(ctxt.Arch, 16)
1111 } else {
1112 s.AddUint32(ctxt.Arch, 0)
1113 }
1114 }
1115 }
1116
1117
1118 gnuVersion := ldr.CreateSymForUpdate(".gnu.version", 0)
1119 s = gnuVersion
1120
1121 for i := 0; i < nsym; i++ {
1122 if i == 0 {
1123 s.AddUint16(ctxt.Arch, 0)
1124 } else if need[i] == nil {
1125 s.AddUint16(ctxt.Arch, 1)
1126 } else {
1127 s.AddUint16(ctxt.Arch, uint16(need[i].num))
1128 }
1129 }
1130
1131 s = ldr.CreateSymForUpdate(".dynamic", 0)
1132
1133 var dtFlags1 elf.DynFlag1
1134 if *flagBindNow {
1135 dtFlags1 |= elf.DF_1_NOW
1136 Elfwritedynent(ctxt.Arch, s, elf.DT_FLAGS, uint64(elf.DF_BIND_NOW))
1137 }
1138 if ctxt.BuildMode == BuildModePIE {
1139 dtFlags1 |= elf.DF_1_PIE
1140 }
1141 Elfwritedynent(ctxt.Arch, s, elf.DT_FLAGS_1, uint64(dtFlags1))
1142
1143 elfverneed = nfile
1144 if elfverneed != 0 {
1145 elfWriteDynEntSym(ctxt, s, elf.DT_VERNEED, gnuVersionR.Sym())
1146 Elfwritedynent(ctxt.Arch, s, elf.DT_VERNEEDNUM, uint64(nfile))
1147 elfWriteDynEntSym(ctxt, s, elf.DT_VERSYM, gnuVersion.Sym())
1148 }
1149
1150 sy := ldr.CreateSymForUpdate(elfRelType+".plt", 0)
1151 if sy.Size() > 0 {
1152 if elfRelType == ".rela" {
1153 Elfwritedynent(ctxt.Arch, s, elf.DT_PLTREL, uint64(elf.DT_RELA))
1154 } else {
1155 Elfwritedynent(ctxt.Arch, s, elf.DT_PLTREL, uint64(elf.DT_REL))
1156 }
1157 elfwritedynentsymsize(ctxt, s, elf.DT_PLTRELSZ, sy.Sym())
1158 elfWriteDynEntSym(ctxt, s, elf.DT_JMPREL, sy.Sym())
1159 }
1160
1161 Elfwritedynent(ctxt.Arch, s, elf.DT_NULL, 0)
1162 }
1163
1164 func elfphload(seg *sym.Segment) *ElfPhdr {
1165 ph := newElfPhdr()
1166 ph.Type = elf.PT_LOAD
1167 if seg.Rwx&4 != 0 {
1168 ph.Flags |= elf.PF_R
1169 }
1170 if seg.Rwx&2 != 0 {
1171 ph.Flags |= elf.PF_W
1172 }
1173 if seg.Rwx&1 != 0 {
1174 ph.Flags |= elf.PF_X
1175 }
1176 ph.Vaddr = seg.Vaddr
1177 ph.Paddr = seg.Vaddr
1178 ph.Memsz = seg.Length
1179 ph.Off = seg.Fileoff
1180 ph.Filesz = seg.Filelen
1181 ph.Align = uint64(*FlagRound)
1182
1183 return ph
1184 }
1185
1186 func elfphrelro(seg *sym.Segment) {
1187 ph := newElfPhdr()
1188 ph.Type = elf.PT_GNU_RELRO
1189 ph.Flags = elf.PF_R
1190 ph.Vaddr = seg.Vaddr
1191 ph.Paddr = seg.Vaddr
1192 ph.Memsz = seg.Length
1193 ph.Off = seg.Fileoff
1194 ph.Filesz = seg.Filelen
1195 ph.Align = uint64(*FlagRound)
1196 }
1197
1198
1199 func elfshname(name string) *ElfShdr {
1200 for _, sh := range shdr {
1201 if sh.nameString == name {
1202 return sh
1203 }
1204 }
1205 return newElfShdr(name)
1206 }
1207
1208
1209
1210 func elfshnamedup(name string) *ElfShdr {
1211 return newElfShdr(name)
1212 }
1213
1214 func elfshalloc(sect *sym.Section) *ElfShdr {
1215 sh := elfshname(sect.Name)
1216 sect.Elfsect = sh
1217 return sh
1218 }
1219
1220 func elfshbits(linkmode LinkMode, sect *sym.Section) *ElfShdr {
1221 var sh *ElfShdr
1222
1223 if sect.Name == ".text" {
1224 if sect.Elfsect == nil {
1225 sect.Elfsect = elfshnamedup(sect.Name)
1226 }
1227 sh = sect.Elfsect.(*ElfShdr)
1228 } else {
1229 sh = elfshalloc(sect)
1230 }
1231
1232
1233
1234 if sh.Type == uint32(elf.SHT_NOTE) {
1235 if linkmode != LinkExternal {
1236
1237
1238
1239
1240
1241
1242
1243 Errorf("sh.Type == SHT_NOTE in elfshbits when linking internally")
1244 }
1245 sh.Addralign = uint64(sect.Align)
1246 sh.Size = sect.Length
1247 sh.Off = sect.Seg.Fileoff + sect.Vaddr - sect.Seg.Vaddr
1248 return sh
1249 }
1250 if sh.Type > 0 {
1251 return sh
1252 }
1253
1254 if sect.Vaddr < sect.Seg.Vaddr+sect.Seg.Filelen {
1255 switch sect.Name {
1256 case ".init_array":
1257 sh.Type = uint32(elf.SHT_INIT_ARRAY)
1258 default:
1259 sh.Type = uint32(elf.SHT_PROGBITS)
1260 }
1261 } else {
1262 sh.Type = uint32(elf.SHT_NOBITS)
1263 }
1264 sh.Flags = uint64(elf.SHF_ALLOC)
1265 if sect.Rwx&1 != 0 {
1266 sh.Flags |= uint64(elf.SHF_EXECINSTR)
1267 }
1268 if sect.Rwx&2 != 0 {
1269 sh.Flags |= uint64(elf.SHF_WRITE)
1270 }
1271 if sect.Name == ".tbss" {
1272 sh.Flags |= uint64(elf.SHF_TLS)
1273 sh.Type = uint32(elf.SHT_NOBITS)
1274 }
1275 if linkmode != LinkExternal {
1276 sh.Addr = sect.Vaddr
1277 }
1278
1279 if strings.HasPrefix(sect.Name, ".debug") || strings.HasPrefix(sect.Name, ".zdebug") {
1280 sh.Flags = 0
1281 sh.Addr = 0
1282 if sect.Compressed {
1283 sh.Flags |= uint64(elf.SHF_COMPRESSED)
1284 }
1285 }
1286
1287 sh.Addralign = uint64(sect.Align)
1288 sh.Size = sect.Length
1289 if sect.Name != ".tbss" {
1290 sh.Off = sect.Seg.Fileoff + sect.Vaddr - sect.Seg.Vaddr
1291 }
1292
1293 return sh
1294 }
1295
1296 func elfshreloc(arch *sys.Arch, sect *sym.Section) *ElfShdr {
1297
1298
1299 if sect.Vaddr >= sect.Seg.Vaddr+sect.Seg.Filelen {
1300 return nil
1301 }
1302 switch sect.Name {
1303 case ".shstrtab", ".tbss", ".gopclntab":
1304 return nil
1305 }
1306 if sect.Elfsect.(*ElfShdr).Type == uint32(elf.SHT_NOTE) {
1307 return nil
1308 }
1309
1310 typ := elf.SHT_REL
1311 if elfRelType == ".rela" {
1312 typ = elf.SHT_RELA
1313 }
1314
1315 sh := elfshname(elfRelType + sect.Name)
1316
1317
1318
1319 if sect.Name == ".text" {
1320 if sh.info != nil && sh.info != sect.Elfsect.(*ElfShdr) {
1321 sh = elfshnamedup(elfRelType + sect.Name)
1322 }
1323 }
1324
1325 sh.Type = uint32(typ)
1326 sh.Entsize = uint64(arch.RegSize) * 2
1327 if typ == elf.SHT_RELA {
1328 sh.Entsize += uint64(arch.RegSize)
1329 }
1330 sh.link = elfshname(".symtab")
1331 sh.info = sect.Elfsect.(*ElfShdr)
1332 sh.relocSect = sect
1333 sh.Addralign = uint64(arch.RegSize)
1334 return sh
1335 }
1336
1337 func elfrelocsect(ctxt *Link, out *OutBuf, sect *sym.Section, syms []loader.Sym) {
1338
1339
1340 if sect.Vaddr >= sect.Seg.Vaddr+sect.Seg.Filelen {
1341 return
1342 }
1343 if sect.Name == ".shstrtab" {
1344 return
1345 }
1346
1347 ldr := ctxt.loader
1348 for i, s := range syms {
1349 if !ldr.AttrReachable(s) {
1350 panic("should never happen")
1351 }
1352 if uint64(ldr.SymValue(s)) >= sect.Vaddr {
1353 syms = syms[i:]
1354 break
1355 }
1356 }
1357
1358 eaddr := sect.Vaddr + sect.Length
1359 for _, s := range syms {
1360 if !ldr.AttrReachable(s) {
1361 continue
1362 }
1363 if ldr.SymValue(s) >= int64(eaddr) {
1364 break
1365 }
1366
1367
1368
1369 relocs := ldr.Relocs(s)
1370 for ri := 0; ri < relocs.Count(); ri++ {
1371 r := relocs.At(ri)
1372 rr, ok := extreloc(ctxt, ldr, s, r)
1373 if !ok {
1374 continue
1375 }
1376 if rr.Xsym == 0 {
1377 ldr.Errorf(s, "missing xsym in relocation")
1378 continue
1379 }
1380 esr := ElfSymForReloc(ctxt, rr.Xsym)
1381 if esr == 0 {
1382 ldr.Errorf(s, "reloc %d (%s) to non-elf symbol %s (outer=%s) %d (%s)", r.Type(), sym.RelocName(ctxt.Arch, r.Type()), ldr.SymName(r.Sym()), ldr.SymName(rr.Xsym), ldr.SymType(r.Sym()), ldr.SymType(r.Sym()).String())
1383 }
1384 if !ldr.AttrReachable(rr.Xsym) {
1385 ldr.Errorf(s, "unreachable reloc %d (%s) target %v", r.Type(), sym.RelocName(ctxt.Arch, r.Type()), ldr.SymName(rr.Xsym))
1386 }
1387 if !thearch.ELF.Reloc1(ctxt, out, ldr, s, rr, ri, int64(uint64(ldr.SymValue(s)+int64(r.Off()))-sect.Vaddr)) {
1388 ldr.Errorf(s, "unsupported obj reloc %d (%s)/%d to %s", r.Type(), sym.RelocName(ctxt.Arch, r.Type()), r.Siz(), ldr.SymName(r.Sym()))
1389 }
1390 }
1391 }
1392
1393
1394 if uint64(out.Offset()) != sect.Reloff+sect.Rellen {
1395 panic(fmt.Sprintf("elfrelocsect: size mismatch %d != %d + %d", out.Offset(), sect.Reloff, sect.Rellen))
1396 }
1397 }
1398
1399 func elfEmitReloc(ctxt *Link) {
1400 for ctxt.Out.Offset()&7 != 0 {
1401 ctxt.Out.Write8(0)
1402 }
1403
1404 sizeExtRelocs(ctxt, thearch.ELF.RelocSize)
1405 relocSect, wg := relocSectFn(ctxt, elfrelocsect)
1406
1407 for _, sect := range Segtext.Sections {
1408 if sect.Name == ".text" {
1409 relocSect(ctxt, sect, ctxt.Textp)
1410 } else {
1411 relocSect(ctxt, sect, ctxt.datap)
1412 }
1413 }
1414
1415 for _, sect := range Segrodata.Sections {
1416 relocSect(ctxt, sect, ctxt.datap)
1417 }
1418 for _, sect := range Segrelrodata.Sections {
1419 relocSect(ctxt, sect, ctxt.datap)
1420 }
1421 for _, sect := range Segdata.Sections {
1422 relocSect(ctxt, sect, ctxt.datap)
1423 }
1424 for i := 0; i < len(Segdwarf.Sections); i++ {
1425 sect := Segdwarf.Sections[i]
1426 si := dwarfp[i]
1427 if si.secSym() != sect.Sym ||
1428 ctxt.loader.SymSect(si.secSym()) != sect {
1429 panic("inconsistency between dwarfp and Segdwarf")
1430 }
1431 relocSect(ctxt, sect, si.syms)
1432 }
1433 wg.Wait()
1434 }
1435
1436 func addgonote(ctxt *Link, sectionName string, tag uint32, desc []byte) {
1437 ldr := ctxt.loader
1438 s := ldr.CreateSymForUpdate(sectionName, 0)
1439 s.SetType(sym.SELFROSECT)
1440
1441 s.AddUint32(ctxt.Arch, uint32(len(ELF_NOTE_GO_NAME)))
1442
1443 s.AddUint32(ctxt.Arch, uint32(len(desc)))
1444
1445 s.AddUint32(ctxt.Arch, tag)
1446
1447 s.AddBytes(ELF_NOTE_GO_NAME)
1448 for len(s.Data())%4 != 0 {
1449 s.AddUint8(0)
1450 }
1451
1452 s.AddBytes(desc)
1453 for len(s.Data())%4 != 0 {
1454 s.AddUint8(0)
1455 }
1456 s.SetSize(int64(len(s.Data())))
1457 s.SetAlign(4)
1458 }
1459
1460 func (ctxt *Link) doelf() {
1461 ldr := ctxt.loader
1462
1463 if ctxt.IsExternal() {
1464 *FlagD = true
1465 }
1466
1467 if !*FlagD {
1468
1469 dynsym := ldr.CreateSymForUpdate(".dynsym", 0)
1470
1471 dynsym.SetType(sym.SELFROSECT)
1472 if elf64 {
1473 dynsym.SetSize(dynsym.Size() + ELF64SYMSIZE)
1474 } else {
1475 dynsym.SetSize(dynsym.Size() + ELF32SYMSIZE)
1476 }
1477
1478
1479 dynstr := ldr.CreateSymForUpdate(".dynstr", 0)
1480
1481 dynstr.SetType(sym.SELFROSECT)
1482 if dynstr.Size() == 0 {
1483 dynstr.Addstring("")
1484 }
1485
1486
1487 s := ldr.CreateSymForUpdate(elfRelType, 0)
1488 s.SetType(sym.SELFROSECT)
1489
1490
1491 got := ldr.CreateSymForUpdate(".got", 0)
1492 if ctxt.UseRelro() {
1493 got.SetType(sym.SELFRELROSECT)
1494 } else {
1495 got.SetType(sym.SELFGOT)
1496 }
1497
1498
1499 if ctxt.IsPPC64() {
1500 s := ldr.CreateSymForUpdate(".glink", 0)
1501 s.SetType(sym.SELFRXSECT)
1502 }
1503
1504
1505 hash := ldr.CreateSymForUpdate(".hash", 0)
1506 hash.SetType(sym.SELFROSECT)
1507
1508 gotplt := ldr.CreateSymForUpdate(".got.plt", 0)
1509 if ctxt.UseRelro() && *flagBindNow {
1510 gotplt.SetType(sym.SELFRELROSECT)
1511 } else {
1512 gotplt.SetType(sym.SELFSECT)
1513 }
1514
1515 plt := ldr.CreateSymForUpdate(".plt", 0)
1516 if ctxt.IsPPC64() {
1517
1518
1519 plt.SetType(sym.SELFSECT)
1520 } else {
1521 plt.SetType(sym.SELFRXSECT)
1522 }
1523
1524 s = ldr.CreateSymForUpdate(elfRelType+".plt", 0)
1525 s.SetType(sym.SELFROSECT)
1526
1527 s = ldr.CreateSymForUpdate(".gnu.version", 0)
1528 s.SetType(sym.SELFROSECT)
1529
1530 s = ldr.CreateSymForUpdate(".gnu.version_r", 0)
1531 s.SetType(sym.SELFROSECT)
1532
1533
1534 dynamic := ldr.CreateSymForUpdate(".dynamic", 0)
1535 switch {
1536 case thearch.ELF.DynamicReadOnly:
1537 dynamic.SetType(sym.SELFROSECT)
1538 case ctxt.UseRelro():
1539 dynamic.SetType(sym.SELFRELROSECT)
1540 default:
1541 dynamic.SetType(sym.SELFSECT)
1542 }
1543
1544 if ctxt.IsS390X() {
1545
1546 gotplt = got
1547 }
1548 thearch.ELF.SetupPLT(ctxt, ctxt.loader, plt, gotplt, dynamic.Sym())
1549
1550
1551 elfWriteDynEntSym(ctxt, dynamic, elf.DT_HASH, hash.Sym())
1552
1553 elfWriteDynEntSym(ctxt, dynamic, elf.DT_SYMTAB, dynsym.Sym())
1554 if elf64 {
1555 Elfwritedynent(ctxt.Arch, dynamic, elf.DT_SYMENT, ELF64SYMSIZE)
1556 } else {
1557 Elfwritedynent(ctxt.Arch, dynamic, elf.DT_SYMENT, ELF32SYMSIZE)
1558 }
1559 elfWriteDynEntSym(ctxt, dynamic, elf.DT_STRTAB, dynstr.Sym())
1560 elfwritedynentsymsize(ctxt, dynamic, elf.DT_STRSZ, dynstr.Sym())
1561 if elfRelType == ".rela" {
1562 rela := ldr.LookupOrCreateSym(".rela", 0)
1563 elfWriteDynEntSym(ctxt, dynamic, elf.DT_RELA, rela)
1564 elfwritedynentsymsize(ctxt, dynamic, elf.DT_RELASZ, rela)
1565 Elfwritedynent(ctxt.Arch, dynamic, elf.DT_RELAENT, ELF64RELASIZE)
1566 } else {
1567 rel := ldr.LookupOrCreateSym(".rel", 0)
1568 elfWriteDynEntSym(ctxt, dynamic, elf.DT_REL, rel)
1569 elfwritedynentsymsize(ctxt, dynamic, elf.DT_RELSZ, rel)
1570 Elfwritedynent(ctxt.Arch, dynamic, elf.DT_RELENT, ELF32RELSIZE)
1571 }
1572
1573 if rpath.val != "" {
1574 Elfwritedynent(ctxt.Arch, dynamic, elf.DT_RUNPATH, uint64(dynstr.Addstring(rpath.val)))
1575 }
1576
1577 if ctxt.IsPPC64() {
1578 elfWriteDynEntSym(ctxt, dynamic, elf.DT_PLTGOT, plt.Sym())
1579 } else {
1580 elfWriteDynEntSym(ctxt, dynamic, elf.DT_PLTGOT, gotplt.Sym())
1581 }
1582
1583 if ctxt.IsPPC64() {
1584 Elfwritedynent(ctxt.Arch, dynamic, elf.DT_PPC64_OPT, 0)
1585 }
1586
1587
1588
1589
1590
1591
1592 Elfwritedynent(ctxt.Arch, dynamic, elf.DT_DEBUG, 0)
1593 }
1594
1595 if ctxt.IsShared() {
1596
1597
1598 s := ldr.LookupOrCreateSym("go:link.abihashbytes", 0)
1599 sb := ldr.MakeSymbolUpdater(s)
1600 ldr.SetAttrLocal(s, true)
1601 sb.SetType(sym.SRODATA)
1602 ldr.SetAttrSpecial(s, true)
1603 sb.SetReachable(true)
1604 sb.SetSize(hash.Size32)
1605 slices.SortFunc(ctxt.Library, func(a, b *sym.Library) int {
1606 return strings.Compare(a.Pkg, b.Pkg)
1607 })
1608 h := hash.New32()
1609 for _, l := range ctxt.Library {
1610 h.Write(l.Fingerprint[:])
1611 }
1612 addgonote(ctxt, ".note.go.abihash", ELF_NOTE_GOABIHASH_TAG, h.Sum([]byte{}))
1613 addgonote(ctxt, ".note.go.pkg-list", ELF_NOTE_GOPKGLIST_TAG, pkglistfornote)
1614 var deplist []string
1615 for _, shlib := range ctxt.Shlibs {
1616 deplist = append(deplist, filepath.Base(shlib.Path))
1617 }
1618 addgonote(ctxt, ".note.go.deps", ELF_NOTE_GODEPS_TAG, []byte(strings.Join(deplist, "\n")))
1619 }
1620
1621 if ctxt.LinkMode == LinkExternal && *flagBuildid != "" {
1622 addgonote(ctxt, ".note.go.buildid", ELF_NOTE_GOBUILDID_TAG, []byte(*flagBuildid))
1623 }
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634 if ctxt.IsMIPS() {
1635 gnuattributes := ldr.CreateSymForUpdate(".gnu.attributes", 0)
1636 gnuattributes.SetType(sym.SELFROSECT)
1637 gnuattributes.SetReachable(true)
1638 gnuattributes.AddUint8('A')
1639 gnuattributes.AddUint32(ctxt.Arch, 15)
1640 gnuattributes.AddBytes([]byte("gnu\x00"))
1641 gnuattributes.AddUint8(1)
1642 gnuattributes.AddUint32(ctxt.Arch, 7)
1643 gnuattributes.AddUint8(4)
1644 if buildcfg.GOMIPS == "softfloat" {
1645 gnuattributes.AddUint8(MIPS_FPABI_SOFT)
1646 } else {
1647
1648
1649
1650 gnuattributes.AddUint8(MIPS_FPABI_ANY)
1651 }
1652 }
1653 }
1654
1655
1656 func shsym(sh *ElfShdr, ldr *loader.Loader, s loader.Sym) {
1657 if s == 0 {
1658 panic("bad symbol in shsym2")
1659 }
1660 addr := ldr.SymValue(s)
1661 if sh.Flags&uint64(elf.SHF_ALLOC) != 0 {
1662 sh.Addr = uint64(addr)
1663 }
1664 sh.Off = uint64(datoff(ldr, s, addr))
1665 sh.Size = uint64(ldr.SymSize(s))
1666 }
1667
1668 func phsh(ph *ElfPhdr, sh *ElfShdr) {
1669 ph.Vaddr = sh.Addr
1670 ph.Paddr = ph.Vaddr
1671 ph.Off = sh.Off
1672 ph.Filesz = sh.Size
1673 ph.Memsz = sh.Size
1674 ph.Align = sh.Addralign
1675 }
1676
1677 func Asmbelfsetup() {
1678
1679 elfshname("")
1680
1681 for _, sect := range Segtext.Sections {
1682
1683
1684 if sect.Name == ".text" {
1685 if sect.Elfsect == nil {
1686 sect.Elfsect = elfshnamedup(sect.Name)
1687 }
1688 } else {
1689 elfshalloc(sect)
1690 }
1691 }
1692 for _, sect := range Segrodata.Sections {
1693 elfshalloc(sect)
1694 }
1695 for _, sect := range Segrelrodata.Sections {
1696 elfshalloc(sect)
1697 }
1698 for _, sect := range Segdata.Sections {
1699 elfshalloc(sect)
1700 }
1701 for _, sect := range Segdwarf.Sections {
1702 elfshalloc(sect)
1703 }
1704 }
1705
1706 func asmbElf(ctxt *Link) {
1707 var symo int64
1708 symo = int64(Segdwarf.Fileoff + Segdwarf.Filelen)
1709 symo = Rnd(symo, int64(ctxt.Arch.PtrSize))
1710
1711 ldr := ctxt.loader
1712 eh := getElfEhdr()
1713 switch ctxt.Arch.Family {
1714 default:
1715 Exitf("unknown architecture in asmbelf: %v", ctxt.Arch.Family)
1716 case sys.MIPS, sys.MIPS64:
1717 eh.Machine = uint16(elf.EM_MIPS)
1718 case sys.Loong64:
1719 eh.Machine = uint16(elf.EM_LOONGARCH)
1720 case sys.ARM:
1721 eh.Machine = uint16(elf.EM_ARM)
1722 case sys.AMD64:
1723 eh.Machine = uint16(elf.EM_X86_64)
1724 case sys.ARM64:
1725 eh.Machine = uint16(elf.EM_AARCH64)
1726 case sys.I386:
1727 eh.Machine = uint16(elf.EM_386)
1728 case sys.PPC64:
1729 eh.Machine = uint16(elf.EM_PPC64)
1730 case sys.RISCV64:
1731 eh.Machine = uint16(elf.EM_RISCV)
1732 case sys.S390X:
1733 eh.Machine = uint16(elf.EM_S390)
1734 }
1735
1736 elfreserve := int64(ELFRESERVE)
1737
1738 numtext := int64(0)
1739 for _, sect := range Segtext.Sections {
1740 if sect.Name == ".text" {
1741 numtext++
1742 }
1743 }
1744
1745
1746
1747
1748
1749
1750 if numtext > 4 {
1751 elfreserve += elfreserve + numtext*64*2
1752 }
1753
1754 startva := *FlagTextAddr - int64(HEADR)
1755 resoff := elfreserve
1756
1757 var pph *ElfPhdr
1758 var pnote *ElfPhdr
1759 getpnote := func() *ElfPhdr {
1760 if pnote == nil {
1761 pnote = newElfPhdr()
1762 pnote.Type = elf.PT_NOTE
1763 pnote.Flags = elf.PF_R
1764 }
1765 return pnote
1766 }
1767 if *flagRace && ctxt.IsNetbsd() {
1768 sh := elfshname(".note.netbsd.pax")
1769 resoff -= int64(elfnetbsdpax(sh, uint64(startva), uint64(resoff)))
1770 phsh(getpnote(), sh)
1771 }
1772 if ctxt.LinkMode == LinkExternal {
1773
1774 eh.Phoff = 0
1775
1776 eh.Phentsize = 0
1777
1778 if ctxt.BuildMode == BuildModeShared {
1779 sh := elfshname(".note.go.pkg-list")
1780 sh.Type = uint32(elf.SHT_NOTE)
1781 sh = elfshname(".note.go.abihash")
1782 sh.Type = uint32(elf.SHT_NOTE)
1783 sh.Flags = uint64(elf.SHF_ALLOC)
1784 sh = elfshname(".note.go.deps")
1785 sh.Type = uint32(elf.SHT_NOTE)
1786 }
1787
1788 if *flagBuildid != "" {
1789 sh := elfshname(".note.go.buildid")
1790 sh.Type = uint32(elf.SHT_NOTE)
1791 sh.Flags = uint64(elf.SHF_ALLOC)
1792 }
1793
1794 goto elfobj
1795 }
1796
1797
1798 pph = newElfPhdr()
1799
1800 pph.Type = elf.PT_PHDR
1801 pph.Flags = elf.PF_R
1802 pph.Off = uint64(eh.Ehsize)
1803 pph.Vaddr = uint64(*FlagTextAddr) - uint64(HEADR) + pph.Off
1804 pph.Paddr = uint64(*FlagTextAddr) - uint64(HEADR) + pph.Off
1805 pph.Align = uint64(*FlagRound)
1806
1807
1808
1809 {
1810 o := int64(Segtext.Vaddr - pph.Vaddr)
1811 Segtext.Vaddr -= uint64(o)
1812 Segtext.Length += uint64(o)
1813 o = int64(Segtext.Fileoff - pph.Off)
1814 Segtext.Fileoff -= uint64(o)
1815 Segtext.Filelen += uint64(o)
1816 }
1817
1818 if !*FlagD {
1819
1820 sh := elfshname(".interp")
1821
1822 sh.Type = uint32(elf.SHT_PROGBITS)
1823 sh.Flags = uint64(elf.SHF_ALLOC)
1824 sh.Addralign = 1
1825
1826 if interpreter == "" && buildcfg.GOOS == runtime.GOOS && buildcfg.GOARCH == runtime.GOARCH && buildcfg.GO_LDSO != "" {
1827 interpreter = buildcfg.GO_LDSO
1828 }
1829
1830 if interpreter == "" {
1831 switch ctxt.HeadType {
1832 case objabi.Hlinux:
1833 if buildcfg.GOOS == "android" {
1834 interpreter = thearch.ELF.Androiddynld
1835 if interpreter == "" {
1836 Exitf("ELF interpreter not set")
1837 }
1838 } else {
1839 interpreter = thearch.ELF.Linuxdynld
1840
1841
1842
1843 if _, err := os.Stat(interpreter); err != nil {
1844 if musl := thearch.ELF.LinuxdynldMusl; musl != "" {
1845 if _, err := os.Stat(musl); err == nil {
1846 interpreter = musl
1847 }
1848 }
1849 }
1850 }
1851
1852 case objabi.Hfreebsd:
1853 interpreter = thearch.ELF.Freebsddynld
1854
1855 case objabi.Hnetbsd:
1856 interpreter = thearch.ELF.Netbsddynld
1857
1858 case objabi.Hopenbsd:
1859 interpreter = thearch.ELF.Openbsddynld
1860
1861 case objabi.Hdragonfly:
1862 interpreter = thearch.ELF.Dragonflydynld
1863
1864 case objabi.Hsolaris:
1865 interpreter = thearch.ELF.Solarisdynld
1866 }
1867 }
1868
1869 resoff -= int64(elfinterp(sh, uint64(startva), uint64(resoff), interpreter))
1870
1871 ph := newElfPhdr()
1872 ph.Type = elf.PT_INTERP
1873 ph.Flags = elf.PF_R
1874 phsh(ph, sh)
1875 }
1876
1877 if ctxt.HeadType == objabi.Hnetbsd || ctxt.HeadType == objabi.Hopenbsd || ctxt.HeadType == objabi.Hfreebsd {
1878 var sh *ElfShdr
1879 switch ctxt.HeadType {
1880 case objabi.Hnetbsd:
1881 sh = elfshname(".note.netbsd.ident")
1882 resoff -= int64(elfnetbsdsig(sh, uint64(startva), uint64(resoff)))
1883
1884 case objabi.Hopenbsd:
1885 sh = elfshname(".note.openbsd.ident")
1886 resoff -= int64(elfopenbsdsig(sh, uint64(startva), uint64(resoff)))
1887
1888 case objabi.Hfreebsd:
1889 sh = elfshname(".note.tag")
1890 resoff -= int64(elffreebsdsig(sh, uint64(startva), uint64(resoff)))
1891 }
1892
1893 pnotei := newElfPhdr()
1894 pnotei.Type = elf.PT_NOTE
1895 pnotei.Flags = elf.PF_R
1896 phsh(pnotei, sh)
1897 }
1898
1899 if len(buildinfo) > 0 {
1900 sh := elfshname(".note.gnu.build-id")
1901 resoff -= int64(elfbuildinfo(sh, uint64(startva), uint64(resoff)))
1902 phsh(getpnote(), sh)
1903 }
1904
1905 if *flagBuildid != "" {
1906 sh := elfshname(".note.go.buildid")
1907 resoff -= int64(elfgobuildid(sh, uint64(startva), uint64(resoff)))
1908 phsh(getpnote(), sh)
1909 }
1910
1911
1912
1913 elfphload(&Segtext)
1914 if len(Segrodata.Sections) > 0 {
1915 elfphload(&Segrodata)
1916 }
1917 if len(Segrelrodata.Sections) > 0 {
1918 elfphload(&Segrelrodata)
1919 elfphrelro(&Segrelrodata)
1920 }
1921 elfphload(&Segdata)
1922
1923
1924 if !*FlagD {
1925 sh := elfshname(".dynsym")
1926 sh.Type = uint32(elf.SHT_DYNSYM)
1927 sh.Flags = uint64(elf.SHF_ALLOC)
1928 if elf64 {
1929 sh.Entsize = ELF64SYMSIZE
1930 } else {
1931 sh.Entsize = ELF32SYMSIZE
1932 }
1933 sh.Addralign = uint64(ctxt.Arch.RegSize)
1934 sh.link = elfshname(".dynstr")
1935
1936
1937 s := ldr.Lookup(".dynsym", 0)
1938 i := uint32(0)
1939 for sub := s; sub != 0; sub = ldr.SubSym(sub) {
1940 i++
1941 if !ldr.AttrLocal(sub) {
1942 break
1943 }
1944 }
1945 sh.Info = i
1946 shsym(sh, ldr, s)
1947
1948 sh = elfshname(".dynstr")
1949 sh.Type = uint32(elf.SHT_STRTAB)
1950 sh.Flags = uint64(elf.SHF_ALLOC)
1951 sh.Addralign = 1
1952 shsym(sh, ldr, ldr.Lookup(".dynstr", 0))
1953
1954 if elfverneed != 0 {
1955 sh := elfshname(".gnu.version")
1956 sh.Type = uint32(elf.SHT_GNU_VERSYM)
1957 sh.Flags = uint64(elf.SHF_ALLOC)
1958 sh.Addralign = 2
1959 sh.link = elfshname(".dynsym")
1960 sh.Entsize = 2
1961 shsym(sh, ldr, ldr.Lookup(".gnu.version", 0))
1962
1963 sh = elfshname(".gnu.version_r")
1964 sh.Type = uint32(elf.SHT_GNU_VERNEED)
1965 sh.Flags = uint64(elf.SHF_ALLOC)
1966 sh.Addralign = uint64(ctxt.Arch.RegSize)
1967 sh.Info = uint32(elfverneed)
1968 sh.link = elfshname(".dynstr")
1969 shsym(sh, ldr, ldr.Lookup(".gnu.version_r", 0))
1970 }
1971
1972 if elfRelType == ".rela" {
1973 sh := elfshname(".rela.plt")
1974 sh.Type = uint32(elf.SHT_RELA)
1975 sh.Flags = uint64(elf.SHF_ALLOC)
1976 sh.Entsize = ELF64RELASIZE
1977 sh.Addralign = uint64(ctxt.Arch.RegSize)
1978 sh.link = elfshname(".dynsym")
1979 sh.info = elfshname(".plt")
1980 shsym(sh, ldr, ldr.Lookup(".rela.plt", 0))
1981
1982 sh = elfshname(".rela")
1983 sh.Type = uint32(elf.SHT_RELA)
1984 sh.Flags = uint64(elf.SHF_ALLOC)
1985 sh.Entsize = ELF64RELASIZE
1986 sh.Addralign = 8
1987 sh.link = elfshname(".dynsym")
1988 shsym(sh, ldr, ldr.Lookup(".rela", 0))
1989 } else {
1990 sh := elfshname(".rel.plt")
1991 sh.Type = uint32(elf.SHT_REL)
1992 sh.Flags = uint64(elf.SHF_ALLOC)
1993 sh.Entsize = ELF32RELSIZE
1994 sh.Addralign = 4
1995 sh.link = elfshname(".dynsym")
1996 shsym(sh, ldr, ldr.Lookup(".rel.plt", 0))
1997
1998 sh = elfshname(".rel")
1999 sh.Type = uint32(elf.SHT_REL)
2000 sh.Flags = uint64(elf.SHF_ALLOC)
2001 sh.Entsize = ELF32RELSIZE
2002 sh.Addralign = 4
2003 sh.link = elfshname(".dynsym")
2004 shsym(sh, ldr, ldr.Lookup(".rel", 0))
2005 }
2006
2007 if elf.Machine(eh.Machine) == elf.EM_PPC64 {
2008 sh := elfshname(".glink")
2009 sh.Type = uint32(elf.SHT_PROGBITS)
2010 sh.Flags = uint64(elf.SHF_ALLOC + elf.SHF_EXECINSTR)
2011 sh.Addralign = 4
2012 shsym(sh, ldr, ldr.Lookup(".glink", 0))
2013 }
2014
2015 sh = elfshname(".plt")
2016 sh.Type = uint32(elf.SHT_PROGBITS)
2017 sh.Flags = uint64(elf.SHF_ALLOC + elf.SHF_EXECINSTR)
2018 if elf.Machine(eh.Machine) == elf.EM_X86_64 {
2019 sh.Entsize = 16
2020 } else if elf.Machine(eh.Machine) == elf.EM_S390 {
2021 sh.Entsize = 32
2022 } else if elf.Machine(eh.Machine) == elf.EM_PPC64 {
2023
2024
2025 sh.Type = uint32(elf.SHT_NOBITS)
2026
2027 sh.Flags = uint64(elf.SHF_ALLOC + elf.SHF_WRITE)
2028 sh.Entsize = 8
2029 } else {
2030 sh.Entsize = 4
2031 }
2032 sh.Addralign = sh.Entsize
2033 shsym(sh, ldr, ldr.Lookup(".plt", 0))
2034
2035
2036
2037 if elf.Machine(eh.Machine) != elf.EM_PPC64 {
2038 sh := elfshname(".got")
2039 sh.Type = uint32(elf.SHT_PROGBITS)
2040 sh.Flags = uint64(elf.SHF_ALLOC + elf.SHF_WRITE)
2041 sh.Entsize = uint64(ctxt.Arch.RegSize)
2042 sh.Addralign = uint64(ctxt.Arch.RegSize)
2043 shsym(sh, ldr, ldr.Lookup(".got", 0))
2044
2045 sh = elfshname(".got.plt")
2046 sh.Type = uint32(elf.SHT_PROGBITS)
2047 sh.Flags = uint64(elf.SHF_ALLOC + elf.SHF_WRITE)
2048 sh.Entsize = uint64(ctxt.Arch.RegSize)
2049 sh.Addralign = uint64(ctxt.Arch.RegSize)
2050 shsym(sh, ldr, ldr.Lookup(".got.plt", 0))
2051 }
2052
2053 sh = elfshname(".hash")
2054 sh.Type = uint32(elf.SHT_HASH)
2055 sh.Flags = uint64(elf.SHF_ALLOC)
2056 sh.Entsize = 4
2057 sh.Addralign = uint64(ctxt.Arch.RegSize)
2058 sh.link = elfshname(".dynsym")
2059 shsym(sh, ldr, ldr.Lookup(".hash", 0))
2060
2061
2062 sh = elfshname(".dynamic")
2063
2064 sh.Type = uint32(elf.SHT_DYNAMIC)
2065 sh.Flags = uint64(elf.SHF_ALLOC + elf.SHF_WRITE)
2066 sh.Entsize = 2 * uint64(ctxt.Arch.RegSize)
2067 sh.Addralign = uint64(ctxt.Arch.RegSize)
2068 sh.link = elfshname(".dynstr")
2069 shsym(sh, ldr, ldr.Lookup(".dynamic", 0))
2070 ph := newElfPhdr()
2071 ph.Type = elf.PT_DYNAMIC
2072 ph.Flags = elf.PF_R + elf.PF_W
2073 phsh(ph, sh)
2074
2075
2076 tlssize := uint64(0)
2077 for _, sect := range Segdata.Sections {
2078 if sect.Name == ".tbss" {
2079 tlssize = sect.Length
2080 }
2081 }
2082 if tlssize != 0 {
2083 ph := newElfPhdr()
2084 ph.Type = elf.PT_TLS
2085 ph.Flags = elf.PF_R
2086 ph.Memsz = tlssize
2087 ph.Align = uint64(ctxt.Arch.RegSize)
2088 }
2089 }
2090
2091 if ctxt.HeadType == objabi.Hlinux || ctxt.HeadType == objabi.Hfreebsd {
2092 ph := newElfPhdr()
2093 ph.Type = elf.PT_GNU_STACK
2094 ph.Flags = elf.PF_W + elf.PF_R
2095 ph.Align = uint64(ctxt.Arch.RegSize)
2096 } else if ctxt.HeadType == objabi.Hopenbsd {
2097 ph := newElfPhdr()
2098 ph.Type = elf.PT_OPENBSD_NOBTCFI
2099 ph.Flags = elf.PF_X
2100 } else if ctxt.HeadType == objabi.Hsolaris {
2101 ph := newElfPhdr()
2102 ph.Type = elf.PT_SUNWSTACK
2103 ph.Flags = elf.PF_W + elf.PF_R
2104 }
2105
2106 elfobj:
2107 if ctxt.IsMIPS() {
2108 sh := elfshname(".MIPS.abiflags")
2109 sh.Type = uint32(elf.SHT_MIPS_ABIFLAGS)
2110 sh.Flags = uint64(elf.SHF_ALLOC)
2111 sh.Addralign = 8
2112 resoff -= int64(elfMipsAbiFlags(sh, uint64(startva), uint64(resoff)))
2113
2114 ph := newElfPhdr()
2115 ph.Type = elf.PT_MIPS_ABIFLAGS
2116 ph.Flags = elf.PF_R
2117 phsh(ph, sh)
2118
2119 sh = elfshname(".gnu.attributes")
2120 sh.Type = uint32(elf.SHT_GNU_ATTRIBUTES)
2121 sh.Addralign = 1
2122 ldr := ctxt.loader
2123 shsym(sh, ldr, ldr.Lookup(".gnu.attributes", 0))
2124 }
2125
2126
2127 if !*FlagS {
2128 elfshname(".symtab")
2129 elfshname(".strtab")
2130 }
2131 elfshname(".shstrtab")
2132
2133 for _, sect := range Segtext.Sections {
2134 elfshbits(ctxt.LinkMode, sect)
2135 }
2136 for _, sect := range Segrodata.Sections {
2137 elfshbits(ctxt.LinkMode, sect)
2138 }
2139 for _, sect := range Segrelrodata.Sections {
2140 elfshbits(ctxt.LinkMode, sect)
2141 }
2142 for _, sect := range Segdata.Sections {
2143 elfshbits(ctxt.LinkMode, sect)
2144 }
2145 for _, sect := range Segdwarf.Sections {
2146 elfshbits(ctxt.LinkMode, sect)
2147 }
2148
2149 if ctxt.LinkMode == LinkExternal {
2150 for _, sect := range Segtext.Sections {
2151 elfshreloc(ctxt.Arch, sect)
2152 }
2153 for _, sect := range Segrodata.Sections {
2154 elfshreloc(ctxt.Arch, sect)
2155 }
2156 for _, sect := range Segrelrodata.Sections {
2157 elfshreloc(ctxt.Arch, sect)
2158 }
2159 for _, sect := range Segdata.Sections {
2160 elfshreloc(ctxt.Arch, sect)
2161 }
2162 for _, si := range dwarfp {
2163 sect := ldr.SymSect(si.secSym())
2164 elfshreloc(ctxt.Arch, sect)
2165 }
2166
2167 sh := elfshname(".note.GNU-stack")
2168
2169 sh.Type = uint32(elf.SHT_PROGBITS)
2170 sh.Addralign = 1
2171 sh.Flags = 0
2172 }
2173
2174 elfSortShdrs(ctxt)
2175
2176 sh := elfshname(".shstrtab")
2177 eh.Shstrndx = uint16(elfShdrShnum(sh))
2178
2179 var shstrtabLen uint32
2180 ctxt.Out.SeekSet(symo)
2181 if *FlagS {
2182 shstrtabLen = elfWriteShstrtab(ctxt)
2183 } else {
2184 asmElfSym(ctxt)
2185 ctxt.Out.Write(elfstrdat)
2186 shstrtabLen = elfWriteShstrtab(ctxt)
2187 if ctxt.IsExternal() {
2188 elfEmitReloc(ctxt)
2189 }
2190 }
2191 ctxt.Out.SeekSet(0)
2192
2193 var shstroff uint64
2194 if !*FlagS {
2195 sh := elfshname(".symtab")
2196 sh.Type = uint32(elf.SHT_SYMTAB)
2197 sh.Off = uint64(symo)
2198 sh.Size = uint64(symSize)
2199 sh.Addralign = uint64(ctxt.Arch.RegSize)
2200 sh.Entsize = 8 + 2*uint64(ctxt.Arch.RegSize)
2201 sh.link = elfshname(".strtab")
2202 sh.Info = uint32(elfglobalsymndx)
2203
2204 sh = elfshname(".strtab")
2205 sh.Type = uint32(elf.SHT_STRTAB)
2206 sh.Off = uint64(symo) + uint64(symSize)
2207 sh.Size = uint64(len(elfstrdat))
2208 sh.Addralign = 1
2209 shstroff = sh.Off + sh.Size
2210 } else {
2211 shstroff = uint64(symo)
2212 }
2213
2214 sh = elfshname(".shstrtab")
2215 sh.Type = uint32(elf.SHT_STRTAB)
2216 sh.Off = shstroff
2217 sh.Size = uint64(shstrtabLen)
2218 sh.Addralign = 1
2219
2220
2221 copy(eh.Ident[:], elf.ELFMAG)
2222
2223 var osabi elf.OSABI
2224 switch ctxt.HeadType {
2225 case objabi.Hfreebsd:
2226 osabi = elf.ELFOSABI_FREEBSD
2227 case objabi.Hnetbsd:
2228 osabi = elf.ELFOSABI_NETBSD
2229 case objabi.Hopenbsd:
2230 osabi = elf.ELFOSABI_OPENBSD
2231 case objabi.Hdragonfly:
2232 osabi = elf.ELFOSABI_NONE
2233 }
2234 eh.Ident[elf.EI_OSABI] = byte(osabi)
2235
2236 if elf64 {
2237 eh.Ident[elf.EI_CLASS] = byte(elf.ELFCLASS64)
2238 } else {
2239 eh.Ident[elf.EI_CLASS] = byte(elf.ELFCLASS32)
2240 }
2241 if ctxt.Arch.ByteOrder == binary.BigEndian {
2242 eh.Ident[elf.EI_DATA] = byte(elf.ELFDATA2MSB)
2243 } else {
2244 eh.Ident[elf.EI_DATA] = byte(elf.ELFDATA2LSB)
2245 }
2246 eh.Ident[elf.EI_VERSION] = byte(elf.EV_CURRENT)
2247
2248 if ctxt.LinkMode == LinkExternal {
2249 eh.Type = uint16(elf.ET_REL)
2250 } else if ctxt.BuildMode == BuildModePIE {
2251 eh.Type = uint16(elf.ET_DYN)
2252 } else {
2253 eh.Type = uint16(elf.ET_EXEC)
2254 }
2255
2256 if ctxt.LinkMode != LinkExternal {
2257 eh.Entry = uint64(Entryvalue(ctxt))
2258 }
2259
2260 eh.Version = uint32(elf.EV_CURRENT)
2261
2262 if pph != nil {
2263 pph.Filesz = uint64(eh.Phnum) * uint64(eh.Phentsize)
2264 pph.Memsz = pph.Filesz
2265 }
2266
2267 if len(shdr) >= 0xffff {
2268 Errorf("too many ELF sections")
2269 }
2270 eh.Shnum = uint16(len(shdr))
2271
2272 ctxt.Out.SeekSet(0)
2273 a := int64(0)
2274 a += int64(elfwritehdr(ctxt.Out))
2275 a += int64(elfwritephdrs(ctxt.Out))
2276 a += int64(elfwriteshdrs(ctxt.Out))
2277 if !*FlagD {
2278 a += int64(elfwriteinterp(ctxt.Out))
2279 }
2280 if ctxt.IsMIPS() {
2281 a += int64(elfWriteMipsAbiFlags(ctxt))
2282 }
2283
2284 if ctxt.LinkMode != LinkExternal {
2285 if ctxt.HeadType == objabi.Hnetbsd {
2286 a += int64(elfwritenetbsdsig(ctxt.Out))
2287 }
2288 if ctxt.HeadType == objabi.Hopenbsd {
2289 a += int64(elfwriteopenbsdsig(ctxt.Out))
2290 }
2291 if ctxt.HeadType == objabi.Hfreebsd {
2292 a += int64(elfwritefreebsdsig(ctxt.Out))
2293 }
2294 if len(buildinfo) > 0 {
2295 a += int64(elfwritebuildinfo(ctxt.Out))
2296 }
2297 if *flagBuildid != "" {
2298 a += int64(elfwritegobuildid(ctxt.Out))
2299 }
2300 }
2301 if *flagRace && ctxt.IsNetbsd() {
2302 a += int64(elfwritenetbsdpax(ctxt.Out))
2303 }
2304
2305 if a > elfreserve {
2306 Errorf("ELFRESERVE too small: %d > %d with %d text sections", a, elfreserve, numtext)
2307 }
2308
2309
2310
2311 if a > int64(HEADR) {
2312 Errorf("HEADR too small: %d > %d with %d text sections", a, HEADR, numtext)
2313 }
2314 }
2315
2316 func elfadddynsym(ldr *loader.Loader, target *Target, syms *ArchSyms, s loader.Sym) {
2317 ldr.SetSymDynid(s, int32(Nelfsym))
2318 Nelfsym++
2319 d := ldr.MakeSymbolUpdater(syms.DynSym)
2320 name := ldr.SymExtname(s)
2321 dstru := ldr.MakeSymbolUpdater(syms.DynStr)
2322 st := ldr.SymType(s)
2323 cgoeStatic := ldr.AttrCgoExportStatic(s)
2324 cgoeDynamic := ldr.AttrCgoExportDynamic(s)
2325 cgoexp := (cgoeStatic || cgoeDynamic)
2326
2327 d.AddUint32(target.Arch, uint32(dstru.Addstring(name)))
2328
2329 if elf64 {
2330
2331 var t uint8
2332
2333 if cgoexp && st.IsText() {
2334 t = elf.ST_INFO(elf.STB_GLOBAL, elf.STT_FUNC)
2335 } else {
2336 t = elf.ST_INFO(elf.STB_GLOBAL, elf.STT_OBJECT)
2337 }
2338 d.AddUint8(t)
2339
2340
2341 d.AddUint8(0)
2342
2343
2344 if st == sym.SDYNIMPORT {
2345 d.AddUint16(target.Arch, uint16(elf.SHN_UNDEF))
2346 } else {
2347 d.AddUint16(target.Arch, 1)
2348 }
2349
2350
2351 if st == sym.SDYNIMPORT {
2352 d.AddUint64(target.Arch, 0)
2353 } else {
2354 d.AddAddrPlus(target.Arch, s, 0)
2355 }
2356
2357
2358 d.AddUint64(target.Arch, uint64(len(ldr.Data(s))))
2359
2360 dil := ldr.SymDynimplib(s)
2361
2362 if !cgoeDynamic && dil != "" && !seenlib[dil] {
2363 du := ldr.MakeSymbolUpdater(syms.Dynamic)
2364 Elfwritedynent(target.Arch, du, elf.DT_NEEDED, uint64(dstru.Addstring(dil)))
2365 seenlib[dil] = true
2366 }
2367 } else {
2368
2369
2370 if st == sym.SDYNIMPORT {
2371 d.AddUint32(target.Arch, 0)
2372 } else {
2373 d.AddAddrPlus(target.Arch, s, 0)
2374 }
2375
2376
2377 d.AddUint32(target.Arch, uint32(len(ldr.Data(s))))
2378
2379
2380 var t uint8
2381
2382
2383 if target.Arch.Family == sys.I386 && cgoexp && st.IsText() {
2384 t = elf.ST_INFO(elf.STB_GLOBAL, elf.STT_FUNC)
2385 } else if target.Arch.Family == sys.ARM && cgoeDynamic && st.IsText() {
2386 t = elf.ST_INFO(elf.STB_GLOBAL, elf.STT_FUNC)
2387 } else {
2388 t = elf.ST_INFO(elf.STB_GLOBAL, elf.STT_OBJECT)
2389 }
2390 d.AddUint8(t)
2391 d.AddUint8(0)
2392
2393
2394 if st == sym.SDYNIMPORT {
2395 d.AddUint16(target.Arch, uint16(elf.SHN_UNDEF))
2396 } else {
2397 d.AddUint16(target.Arch, 1)
2398 }
2399 }
2400 }
2401
View as plain text