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