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