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