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