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