1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
10 "cmd/link/internal/loader"
11 "cmd/link/internal/sym"
25 * $FreeBSD: src/sys/sys/elf32.h,v 1.8.14.1 2005/12/30 22:13:58 marcel Exp $
26 * $FreeBSD: src/sys/sys/elf64.h,v 1.10.14.1 2005/12/30 22:13:58 marcel Exp $
27 * $FreeBSD: src/sys/sys/elf_common.h,v 1.15.8.1 2005/12/30 22:13:58 marcel Exp $
28 * $FreeBSD: src/sys/alpha/include/elf.h,v 1.14 2003/09/25 01:10:22 peter Exp $
29 * $FreeBSD: src/sys/amd64/include/elf.h,v 1.18 2004/08/03 08:21:48 dfr Exp $
30 * $FreeBSD: src/sys/arm/include/elf.h,v 1.5.2.1 2006/06/30 21:42:52 cognet Exp $
31 * $FreeBSD: src/sys/i386/include/elf.h,v 1.16 2004/08/02 19:12:17 dfr Exp $
32 * $FreeBSD: src/sys/powerpc/include/elf.h,v 1.7 2004/11/02 09:47:01 ssouhlal Exp $
33 * $FreeBSD: src/sys/sparc64/include/elf.h,v 1.12 2003/09/25 01:10:26 peter Exp $
35 * Copyright (c) 1996-1998 John D. Polstra. All rights reserved.
36 * Copyright (c) 2001 David E. O'Brien
37 * Portions Copyright 2009 The Go Authors. All rights reserved.
39 * Redistribution and use in source and binary forms, with or without
40 * modification, are permitted provided that the following conditions
42 * 1. Redistributions of source code must retain the above copyright
43 * notice, this list of conditions and the following disclaimer.
44 * 2. Redistributions in binary form must reproduce the above copyright
45 * notice, this list of conditions and the following disclaimer in the
46 * documentation and/or other materials provided with the distribution.
48 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
49 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
63 * ELF definitions that are independent of architecture or word size.
67 * Note header. The ".note" section contains an array of notes. Each
68 * begins with this header, aligned to a word boundary. Immediately
69 * following the note header is n_namesz bytes of name, padded to the
70 * next word boundary. Then comes n_descsz bytes of descriptor, again
71 * padded to a word boundary. The values of n_namesz and n_descsz do
72 * not include the padding.
80 /* For accessing the fields of r_info. */
82 /* For constructing r_info from field values. */
88 ARM_MAGIC_TRAMP_NUMBER = 0x5c000003
92 * Symbol table entries.
95 /* For accessing the fields of st_info. */
97 /* For constructing st_info from field values. */
99 /* For accessing the fields of st_other. */
104 type ElfEhdr elf.Header64
109 type ElfShdr struct {
111 shnum elf.SectionIndex
117 type ElfPhdr elf.ProgHeader
119 /* For accessing the fields of r_info. */
121 /* For constructing r_info from field values. */
124 * Symbol table entries.
127 /* For accessing the fields of st_info. */
129 /* For constructing st_info from field values. */
131 /* For accessing the fields of st_other. */
134 * Go linker interface
151 * The interface uses the 64-bit structures always,
152 * to avoid code duplication. The writers know how to
153 * marshal a 32-bit representation from the 64-bit structure.
159 * Total amount of space to reserve at the start of the file
160 * for Header, PHeaders, SHeaders, and interp.
162 * On FreeBSD, cannot be larger than a page.
169 * We use the 64-bit data structures on both 32- and 64-bit machines
170 * in order to write the code just once. The 64-bit data structure is
171 * written in the 32-bit format on the 32-bit machines.
181 // Either ".rel" or ".rela" depending on which type of relocation the
182 // target platform uses.
192 type Elfstring struct {
197 var elfstr [100]Elfstring
204 Initialize the global variable that describes the ELF header. It will be updated as
205 we write section and prog headers.
207 func Elfinit(ctxt *Link) {
210 if ctxt.Arch.InFamily(sys.AMD64, sys.ARM64, sys.MIPS64, sys.PPC64, sys.RISCV64, sys.S390X) {
216 switch ctxt.Arch.Family {
217 // 64-bit architectures
218 case sys.PPC64, sys.S390X:
219 if ctxt.Arch.ByteOrder == binary.BigEndian {
220 ehdr.Flags = 1 /* Version 1 ABI */
222 ehdr.Flags = 2 /* Version 2 ABI */
225 case sys.AMD64, sys.ARM64, sys.MIPS64, sys.RISCV64:
226 if ctxt.Arch.Family == sys.MIPS64 {
227 ehdr.Flags = 0x20000004 /* MIPS 3 CPIC */
229 if ctxt.Arch.Family == sys.RISCV64 {
230 ehdr.Flags = 0x4 /* RISCV Float ABI Double */
234 ehdr.Phoff = ELF64HDRSIZE /* Must be ELF64HDRSIZE: first PHdr must follow ELF header */
235 ehdr.Shoff = ELF64HDRSIZE /* Will move as we add PHeaders */
236 ehdr.Ehsize = ELF64HDRSIZE /* Must be ELF64HDRSIZE */
237 ehdr.Phentsize = ELF64PHDRSIZE /* Must be ELF64PHDRSIZE */
238 ehdr.Shentsize = ELF64SHDRSIZE /* Must be ELF64SHDRSIZE */
240 // 32-bit architectures
241 case sys.ARM, sys.MIPS:
242 if ctxt.Arch.Family == sys.ARM {
243 // we use EABI on linux/arm, freebsd/arm, netbsd/arm.
244 if ctxt.HeadType == objabi.Hlinux || ctxt.HeadType == objabi.Hfreebsd || ctxt.HeadType == objabi.Hnetbsd {
245 // We set a value here that makes no indication of which
246 // float ABI the object uses, because this is information
247 // used by the dynamic linker to compare executables and
248 // shared libraries -- so it only matters for cgo calls, and
249 // the information properly comes from the object files
250 // produced by the host C compiler. parseArmAttributes in
251 // ldelf.go reads that information and updates this field as
253 ehdr.Flags = 0x5000002 // has entry point, Version5 EABI
255 } else if ctxt.Arch.Family == sys.MIPS {
256 ehdr.Flags = 0x50001004 /* MIPS 32 CPIC O32*/
260 ehdr.Phoff = ELF32HDRSIZE
261 /* Must be ELF32HDRSIZE: first PHdr must follow ELF header */
262 ehdr.Shoff = ELF32HDRSIZE /* Will move as we add PHeaders */
263 ehdr.Ehsize = ELF32HDRSIZE /* Must be ELF32HDRSIZE */
264 ehdr.Phentsize = ELF32PHDRSIZE /* Must be ELF32PHDRSIZE */
265 ehdr.Shentsize = ELF32SHDRSIZE /* Must be ELF32SHDRSIZE */
269 // Make sure PT_LOAD is aligned properly and
270 // that there is no gap,
271 // correct ELF loaders will do this implicitly,
272 // but buggy ELF loaders like the one in some
273 // versions of QEMU and UPX won't.
274 func fixElfPhdr(e *ElfPhdr) {
275 frag := int(e.Vaddr & (e.Align - 1))
277 e.Off -= uint64(frag)
278 e.Vaddr -= uint64(frag)
279 e.Paddr -= uint64(frag)
280 e.Filesz += uint64(frag)
281 e.Memsz += uint64(frag)
284 func elf64phdr(out *OutBuf, e *ElfPhdr) {
285 if e.Type == elf.PT_LOAD {
289 out.Write32(uint32(e.Type))
290 out.Write32(uint32(e.Flags))
294 out.Write64(e.Filesz)
299 func elf32phdr(out *OutBuf, e *ElfPhdr) {
300 if e.Type == elf.PT_LOAD {
304 out.Write32(uint32(e.Type))
305 out.Write32(uint32(e.Off))
306 out.Write32(uint32(e.Vaddr))
307 out.Write32(uint32(e.Paddr))
308 out.Write32(uint32(e.Filesz))
309 out.Write32(uint32(e.Memsz))
310 out.Write32(uint32(e.Flags))
311 out.Write32(uint32(e.Align))
314 func elf64shdr(out *OutBuf, e *ElfShdr) {
316 out.Write32(uint32(e.Type))
317 out.Write64(uint64(e.Flags))
323 out.Write64(e.Addralign)
324 out.Write64(e.Entsize)
327 func elf32shdr(out *OutBuf, e *ElfShdr) {
329 out.Write32(uint32(e.Type))
330 out.Write32(uint32(e.Flags))
331 out.Write32(uint32(e.Addr))
332 out.Write32(uint32(e.Off))
333 out.Write32(uint32(e.Size))
336 out.Write32(uint32(e.Addralign))
337 out.Write32(uint32(e.Entsize))
340 func elfwriteshdrs(out *OutBuf) uint32 {
342 for i := 0; i < int(ehdr.Shnum); i++ {
343 elf64shdr(out, shdr[i])
345 return uint32(ehdr.Shnum) * ELF64SHDRSIZE
348 for i := 0; i < int(ehdr.Shnum); i++ {
349 elf32shdr(out, shdr[i])
351 return uint32(ehdr.Shnum) * ELF32SHDRSIZE
354 func elfsetstring(ctxt *Link, s loader.Sym, str string, off int) {
355 if nelfstr >= len(elfstr) {
356 ctxt.Errorf(s, "too many elf strings")
360 elfstr[nelfstr].s = str
361 elfstr[nelfstr].off = off
365 func elfwritephdrs(out *OutBuf) uint32 {
367 for i := 0; i < int(ehdr.Phnum); i++ {
368 elf64phdr(out, phdr[i])
370 return uint32(ehdr.Phnum) * ELF64PHDRSIZE
373 for i := 0; i < int(ehdr.Phnum); i++ {
374 elf32phdr(out, phdr[i])
376 return uint32(ehdr.Phnum) * ELF32PHDRSIZE
379 func newElfPhdr() *ElfPhdr {
381 if ehdr.Phnum >= NSECT {
382 Errorf(nil, "too many phdrs")
388 ehdr.Shoff += ELF64PHDRSIZE
390 ehdr.Shoff += ELF32PHDRSIZE
395 func newElfShdr(name int64) *ElfShdr {
397 e.Name = uint32(name)
398 e.shnum = elf.SectionIndex(ehdr.Shnum)
399 if ehdr.Shnum >= NSECT {
400 Errorf(nil, "too many shdrs")
409 func getElfEhdr() *ElfEhdr {
413 func elf64writehdr(out *OutBuf) uint32 {
414 out.Write(ehdr.Ident[:])
415 out.Write16(uint16(ehdr.Type))
416 out.Write16(uint16(ehdr.Machine))
417 out.Write32(uint32(ehdr.Version))
418 out.Write64(ehdr.Entry)
419 out.Write64(ehdr.Phoff)
420 out.Write64(ehdr.Shoff)
421 out.Write32(ehdr.Flags)
422 out.Write16(ehdr.Ehsize)
423 out.Write16(ehdr.Phentsize)
424 out.Write16(ehdr.Phnum)
425 out.Write16(ehdr.Shentsize)
426 out.Write16(ehdr.Shnum)
427 out.Write16(ehdr.Shstrndx)
431 func elf32writehdr(out *OutBuf) uint32 {
432 out.Write(ehdr.Ident[:])
433 out.Write16(uint16(ehdr.Type))
434 out.Write16(uint16(ehdr.Machine))
435 out.Write32(uint32(ehdr.Version))
436 out.Write32(uint32(ehdr.Entry))
437 out.Write32(uint32(ehdr.Phoff))
438 out.Write32(uint32(ehdr.Shoff))
439 out.Write32(ehdr.Flags)
440 out.Write16(ehdr.Ehsize)
441 out.Write16(ehdr.Phentsize)
442 out.Write16(ehdr.Phnum)
443 out.Write16(ehdr.Shentsize)
444 out.Write16(ehdr.Shnum)
445 out.Write16(ehdr.Shstrndx)
449 func elfwritehdr(out *OutBuf) uint32 {
451 return elf64writehdr(out)
453 return elf32writehdr(out)
456 /* Taken directly from the definition document for ELF64 */
457 func elfhash(name string) uint32 {
459 for i := 0; i < len(name); i++ {
460 h = (h << 4) + uint32(name[i])
461 if g := h & 0xf0000000; g != 0 {
469 func elfWriteDynEntSym(ctxt *Link, s *loader.SymbolBuilder, tag elf.DynTag, t loader.Sym) {
470 Elfwritedynentsymplus(ctxt, s, tag, t, 0)
473 func Elfwritedynent(arch *sys.Arch, s *loader.SymbolBuilder, tag elf.DynTag, val uint64) {
475 s.AddUint64(arch, uint64(tag))
476 s.AddUint64(arch, val)
478 s.AddUint32(arch, uint32(tag))
479 s.AddUint32(arch, uint32(val))
483 func elfwritedynentsym(ctxt *Link, s *loader.SymbolBuilder, tag elf.DynTag, t loader.Sym) {
484 Elfwritedynentsymplus(ctxt, s, tag, t, 0)
487 func Elfwritedynentsymplus(ctxt *Link, s *loader.SymbolBuilder, tag elf.DynTag, t loader.Sym, add int64) {
489 s.AddUint64(ctxt.Arch, uint64(tag))
491 s.AddUint32(ctxt.Arch, uint32(tag))
493 s.AddAddrPlus(ctxt.Arch, t, add)
496 func elfwritedynentsymsize(ctxt *Link, s *loader.SymbolBuilder, tag elf.DynTag, t loader.Sym) {
498 s.AddUint64(ctxt.Arch, uint64(tag))
500 s.AddUint32(ctxt.Arch, uint32(tag))
502 s.AddSize(ctxt.Arch, t)
505 func elfinterp(sh *ElfShdr, startva uint64, resoff uint64, p string) int {
508 sh.Addr = startva + resoff - uint64(n)
509 sh.Off = resoff - uint64(n)
515 func elfwriteinterp(out *OutBuf) int {
516 sh := elfshname(".interp")
517 out.SeekSet(int64(sh.Off))
518 out.WriteString(interp)
523 // member of .gnu.attributes of MIPS for fpAbi
525 // No floating point is present in the module (default)
527 // FP code in the module uses the FP32 ABI for a 32-bit ABI
529 // FP code in the module only uses single precision ABI
530 MIPS_FPABI_SINGLE = 2
531 // FP code in the module uses soft-float ABI
533 // FP code in the module assumes an FPU with FR=1 and has 12
534 // callee-saved doubles. Historic, no longer supported.
536 // FP code in the module uses the FPXX ABI
538 // FP code in the module uses the FP64 ABI
540 // FP code in the module uses the FP64A ABI
544 func elfMipsAbiFlags(sh *ElfShdr, startva uint64, resoff uint64) int {
546 sh.Addr = startva + resoff - uint64(n)
547 sh.Off = resoff - uint64(n)
549 sh.Type = uint32(elf.SHT_MIPS_ABIFLAGS)
550 sh.Flags = uint64(elf.SHF_ALLOC)
557 // /* Version of flags structure. */
559 // /* The level of the ISA: 1-5, 32, 64. */
560 // uint8_t isa_level;
561 // /* The revision of ISA: 0 for MIPS V and below, 1-n otherwise. */
563 // /* The size of general purpose registers. */
565 // /* The size of co-processor 1 registers. */
566 // uint8_t cpr1_size;
567 // /* The size of co-processor 2 registers. */
568 // uint8_t cpr2_size;
569 // /* The floating-point ABI. */
571 // /* Processor-specific extension. */
573 // /* Mask of ASEs used. */
575 // /* Mask of general flags. */
578 //} Elf_Internal_ABIFlags_v0;
579 func elfWriteMipsAbiFlags(ctxt *Link) int {
580 sh := elfshname(".MIPS.abiflags")
581 ctxt.Out.SeekSet(int64(sh.Off))
582 ctxt.Out.Write16(0) // version
583 ctxt.Out.Write8(32) // isaLevel
584 ctxt.Out.Write8(1) // isaRev
585 ctxt.Out.Write8(1) // gprSize
586 ctxt.Out.Write8(1) // cpr1Size
587 ctxt.Out.Write8(0) // cpr2Size
588 if buildcfg.GOMIPS == "softfloat" {
589 ctxt.Out.Write8(MIPS_FPABI_SOFT) // fpAbi
591 // Go cannot make sure non odd-number-fpr is used (ie, in load a double from memory).
592 // So, we mark the object is MIPS I style paired float/double register scheme,
593 // aka MIPS_FPABI_ANY. If we mark the object as FPXX, the kernel may use FR=1 mode,
594 // then we meet some problem.
595 // Note: MIPS_FPABI_ANY is bad naming: in fact it is MIPS I style FPR usage.
596 // It is not for 'ANY'.
597 // TODO: switch to FPXX after be sure that no odd-number-fpr is used.
598 ctxt.Out.Write8(MIPS_FPABI_ANY) // fpAbi
600 ctxt.Out.Write32(0) // isaExt
601 ctxt.Out.Write32(0) // ases
602 ctxt.Out.Write32(0) // flags1
603 ctxt.Out.Write32(0) // flags2
607 func elfnote(sh *ElfShdr, startva uint64, resoff uint64, sz int) int {
608 n := 3*4 + uint64(sz) + resoff%4
610 sh.Type = uint32(elf.SHT_NOTE)
611 sh.Flags = uint64(elf.SHF_ALLOC)
613 sh.Addr = startva + resoff - n
615 sh.Size = n - resoff%4
620 func elfwritenotehdr(out *OutBuf, str string, namesz uint32, descsz uint32, tag uint32) *ElfShdr {
623 // Write Elf_Note header.
624 out.SeekSet(int64(sh.Off))
633 // NetBSD Signature (as per sys/exec_elf.h)
635 ELF_NOTE_NETBSD_NAMESZ = 7
636 ELF_NOTE_NETBSD_DESCSZ = 4
637 ELF_NOTE_NETBSD_TAG = 1
638 ELF_NOTE_NETBSD_VERSION = 700000000 /* NetBSD 7.0 */
641 var ELF_NOTE_NETBSD_NAME = []byte("NetBSD\x00")
643 func elfnetbsdsig(sh *ElfShdr, startva uint64, resoff uint64) int {
644 n := int(Rnd(ELF_NOTE_NETBSD_NAMESZ, 4) + Rnd(ELF_NOTE_NETBSD_DESCSZ, 4))
645 return elfnote(sh, startva, resoff, n)
648 func elfwritenetbsdsig(out *OutBuf) int {
649 // Write Elf_Note header.
650 sh := elfwritenotehdr(out, ".note.netbsd.ident", ELF_NOTE_NETBSD_NAMESZ, ELF_NOTE_NETBSD_DESCSZ, ELF_NOTE_NETBSD_TAG)
656 // Followed by NetBSD string and version.
657 out.Write(ELF_NOTE_NETBSD_NAME)
659 out.Write32(ELF_NOTE_NETBSD_VERSION)
664 // The race detector can't handle ASLR (address space layout randomization).
665 // ASLR is on by default for NetBSD, so we turn the ASLR off explicitly
666 // using a magic elf Note when building race binaries.
668 func elfnetbsdpax(sh *ElfShdr, startva uint64, resoff uint64) int {
669 n := int(Rnd(4, 4) + Rnd(4, 4))
670 return elfnote(sh, startva, resoff, n)
673 func elfwritenetbsdpax(out *OutBuf) int {
674 sh := elfwritenotehdr(out, ".note.netbsd.pax", 4 /* length of PaX\x00 */, 4 /* length of flags */, 0x03 /* PaX type */)
678 out.Write([]byte("PaX\x00"))
679 out.Write32(0x20) // 0x20 = Force disable ASLR
685 ELF_NOTE_OPENBSD_NAMESZ = 8
686 ELF_NOTE_OPENBSD_DESCSZ = 4
687 ELF_NOTE_OPENBSD_TAG = 1
688 ELF_NOTE_OPENBSD_VERSION = 0
691 var ELF_NOTE_OPENBSD_NAME = []byte("OpenBSD\x00")
693 func elfopenbsdsig(sh *ElfShdr, startva uint64, resoff uint64) int {
694 n := ELF_NOTE_OPENBSD_NAMESZ + ELF_NOTE_OPENBSD_DESCSZ
695 return elfnote(sh, startva, resoff, n)
698 func elfwriteopenbsdsig(out *OutBuf) int {
699 // Write Elf_Note header.
700 sh := elfwritenotehdr(out, ".note.openbsd.ident", ELF_NOTE_OPENBSD_NAMESZ, ELF_NOTE_OPENBSD_DESCSZ, ELF_NOTE_OPENBSD_TAG)
706 // Followed by OpenBSD string and version.
707 out.Write(ELF_NOTE_OPENBSD_NAME)
709 out.Write32(ELF_NOTE_OPENBSD_VERSION)
714 func addbuildinfo(val string) {
715 if !strings.HasPrefix(val, "0x") {
716 Exitf("-B argument must start with 0x: %s", val)
723 if hex.DecodedLen(len(val)) > maxLen {
724 Exitf("-B option too long (max %d digits): %s", maxLen, ov)
727 b, err := hex.DecodeString(val)
729 if err == hex.ErrLength {
730 Exitf("-B argument must have even number of digits: %s", ov)
732 if inv, ok := err.(hex.InvalidByteError); ok {
733 Exitf("-B argument contains invalid hex digit %c: %s", byte(inv), ov)
735 Exitf("-B argument contains invalid hex: %s", ov)
743 ELF_NOTE_BUILDINFO_NAMESZ = 4
744 ELF_NOTE_BUILDINFO_TAG = 3
747 var ELF_NOTE_BUILDINFO_NAME = []byte("GNU\x00")
749 func elfbuildinfo(sh *ElfShdr, startva uint64, resoff uint64) int {
750 n := int(ELF_NOTE_BUILDINFO_NAMESZ + Rnd(int64(len(buildinfo)), 4))
751 return elfnote(sh, startva, resoff, n)
754 func elfgobuildid(sh *ElfShdr, startva uint64, resoff uint64) int {
755 n := len(ELF_NOTE_GO_NAME) + int(Rnd(int64(len(*flagBuildid)), 4))
756 return elfnote(sh, startva, resoff, n)
759 func elfwritebuildinfo(out *OutBuf) int {
760 sh := elfwritenotehdr(out, ".note.gnu.build-id", ELF_NOTE_BUILDINFO_NAMESZ, uint32(len(buildinfo)), ELF_NOTE_BUILDINFO_TAG)
765 out.Write(ELF_NOTE_BUILDINFO_NAME)
767 var zero = make([]byte, 4)
768 out.Write(zero[:int(Rnd(int64(len(buildinfo)), 4)-int64(len(buildinfo)))])
773 func elfwritegobuildid(out *OutBuf) int {
774 sh := elfwritenotehdr(out, ".note.go.buildid", uint32(len(ELF_NOTE_GO_NAME)), uint32(len(*flagBuildid)), ELF_NOTE_GOBUILDID_TAG)
779 out.Write(ELF_NOTE_GO_NAME)
780 out.Write([]byte(*flagBuildid))
781 var zero = make([]byte, 4)
782 out.Write(zero[:int(Rnd(int64(len(*flagBuildid)), 4)-int64(len(*flagBuildid)))])
789 ELF_NOTE_GOPKGLIST_TAG = 1
790 ELF_NOTE_GOABIHASH_TAG = 2
791 ELF_NOTE_GODEPS_TAG = 3
792 ELF_NOTE_GOBUILDID_TAG = 4
795 var ELF_NOTE_GO_NAME = []byte("Go\x00\x00")
811 func addelflib(list **Elflib, file string, vers string) *Elfaux {
814 for lib = *list; lib != nil; lib = lib.next {
815 if lib.file == file {
825 for aux := lib.aux; aux != nil; aux = aux.next {
826 if aux.vers == vers {
838 func elfdynhash(ctxt *Link) {
845 s := ldr.CreateSymForUpdate(".hash", 0)
846 s.SetType(sym.SELFROSECT)
856 need := make([]*Elfaux, nsym)
857 chain := make([]uint32, nsym)
858 buckets := make([]uint32, nbucket)
860 for _, sy := range ldr.DynidSyms() {
862 dynid := ldr.SymDynid(sy)
863 if ldr.SymDynimpvers(sy) != "" {
864 need[dynid] = addelflib(&needlib, ldr.SymDynimplib(sy), ldr.SymDynimpvers(sy))
867 name := ldr.SymExtname(sy)
870 b := hc % uint32(nbucket)
871 chain[dynid] = buckets[b]
872 buckets[b] = uint32(dynid)
875 // s390x (ELF64) hash table entries are 8 bytes
876 if ctxt.Arch.Family == sys.S390X {
877 s.AddUint64(ctxt.Arch, uint64(nbucket))
878 s.AddUint64(ctxt.Arch, uint64(nsym))
879 for i := 0; i < nbucket; i++ {
880 s.AddUint64(ctxt.Arch, uint64(buckets[i]))
882 for i := 0; i < nsym; i++ {
883 s.AddUint64(ctxt.Arch, uint64(chain[i]))
886 s.AddUint32(ctxt.Arch, uint32(nbucket))
887 s.AddUint32(ctxt.Arch, uint32(nsym))
888 for i := 0; i < nbucket; i++ {
889 s.AddUint32(ctxt.Arch, buckets[i])
891 for i := 0; i < nsym; i++ {
892 s.AddUint32(ctxt.Arch, chain[i])
896 dynstr := ldr.CreateSymForUpdate(".dynstr", 0)
899 gnuVersionR := ldr.CreateSymForUpdate(".gnu.version_r", 0)
903 for l := needlib; l != nil; l = l.next {
907 s.AddUint16(ctxt.Arch, 1) // table version
909 for x := l.aux; x != nil; x = x.next {
912 s.AddUint16(ctxt.Arch, uint16(j)) // aux count
913 s.AddUint32(ctxt.Arch, uint32(dynstr.Addstring(l.file))) // file string offset
914 s.AddUint32(ctxt.Arch, 16) // offset from header to first aux
916 s.AddUint32(ctxt.Arch, 16+uint32(j)*16) // offset from this header to next
918 s.AddUint32(ctxt.Arch, 0)
921 for x := l.aux; x != nil; x = x.next {
926 s.AddUint32(ctxt.Arch, elfhash(x.vers)) // hash
927 s.AddUint16(ctxt.Arch, 0) // flags
928 s.AddUint16(ctxt.Arch, uint16(x.num)) // other - index we refer to this by
929 s.AddUint32(ctxt.Arch, uint32(dynstr.Addstring(x.vers))) // version string offset
931 s.AddUint32(ctxt.Arch, 16) // offset from this aux to next
933 s.AddUint32(ctxt.Arch, 0)
938 // version references
939 gnuVersion := ldr.CreateSymForUpdate(".gnu.version", 0)
942 for i := 0; i < nsym; i++ {
944 s.AddUint16(ctxt.Arch, 0) // first entry - no symbol
945 } else if need[i] == nil {
946 s.AddUint16(ctxt.Arch, 1) // global
948 s.AddUint16(ctxt.Arch, uint16(need[i].num))
952 s = ldr.CreateSymForUpdate(".dynamic", 0)
955 elfWriteDynEntSym(ctxt, s, elf.DT_VERNEED, gnuVersionR.Sym())
956 Elfwritedynent(ctxt.Arch, s, elf.DT_VERNEEDNUM, uint64(nfile))
957 elfWriteDynEntSym(ctxt, s, elf.DT_VERSYM, gnuVersion.Sym())
960 sy := ldr.CreateSymForUpdate(elfRelType+".plt", 0)
962 if elfRelType == ".rela" {
963 Elfwritedynent(ctxt.Arch, s, elf.DT_PLTREL, uint64(elf.DT_RELA))
965 Elfwritedynent(ctxt.Arch, s, elf.DT_PLTREL, uint64(elf.DT_REL))
967 elfwritedynentsymsize(ctxt, s, elf.DT_PLTRELSZ, sy.Sym())
968 elfWriteDynEntSym(ctxt, s, elf.DT_JMPREL, sy.Sym())
971 Elfwritedynent(ctxt.Arch, s, elf.DT_NULL, 0)
974 func elfphload(seg *sym.Segment) *ElfPhdr {
976 ph.Type = elf.PT_LOAD
988 ph.Memsz = seg.Length
990 ph.Filesz = seg.Filelen
991 ph.Align = uint64(*FlagRound)
996 func elfphrelro(seg *sym.Segment) {
998 ph.Type = elf.PT_GNU_RELRO
1000 ph.Paddr = seg.Vaddr
1001 ph.Memsz = seg.Length
1002 ph.Off = seg.Fileoff
1003 ph.Filesz = seg.Filelen
1004 ph.Align = uint64(*FlagRound)
1007 func elfshname(name string) *ElfShdr {
1008 for i := 0; i < nelfstr; i++ {
1009 if name != elfstr[i].s {
1012 off := elfstr[i].off
1013 for i = 0; i < int(ehdr.Shnum); i++ {
1015 if sh.Name == uint32(off) {
1019 return newElfShdr(int64(off))
1021 Exitf("cannot find elf name %s", name)
1025 // Create an ElfShdr for the section with name.
1026 // Create a duplicate if one already exists with that name
1027 func elfshnamedup(name string) *ElfShdr {
1028 for i := 0; i < nelfstr; i++ {
1029 if name == elfstr[i].s {
1030 off := elfstr[i].off
1031 return newElfShdr(int64(off))
1035 Errorf(nil, "cannot find elf name %s", name)
1040 func elfshalloc(sect *sym.Section) *ElfShdr {
1041 sh := elfshname(sect.Name)
1046 func elfshbits(linkmode LinkMode, sect *sym.Section) *ElfShdr {
1049 if sect.Name == ".text" {
1050 if sect.Elfsect == nil {
1051 sect.Elfsect = elfshnamedup(sect.Name)
1053 sh = sect.Elfsect.(*ElfShdr)
1055 sh = elfshalloc(sect)
1058 // If this section has already been set up as a note, we assume type_ and
1059 // flags are already correct, but the other fields still need filling in.
1060 if sh.Type == uint32(elf.SHT_NOTE) {
1061 if linkmode != LinkExternal {
1062 // TODO(mwhudson): the approach here will work OK when
1063 // linking internally for notes that we want to be included
1064 // in a loadable segment (e.g. the abihash note) but not for
1065 // notes that we do not want to be mapped (e.g. the package
1066 // list note). The real fix is probably to define new values
1067 // for Symbol.Type corresponding to mapped and unmapped notes
1068 // and handle them in dodata().
1069 Errorf(nil, "sh.Type == SHT_NOTE in elfshbits when linking internally")
1071 sh.Addralign = uint64(sect.Align)
1072 sh.Size = sect.Length
1073 sh.Off = sect.Seg.Fileoff + sect.Vaddr - sect.Seg.Vaddr
1080 if sect.Vaddr < sect.Seg.Vaddr+sect.Seg.Filelen {
1081 sh.Type = uint32(elf.SHT_PROGBITS)
1083 sh.Type = uint32(elf.SHT_NOBITS)
1085 sh.Flags = uint64(elf.SHF_ALLOC)
1086 if sect.Rwx&1 != 0 {
1087 sh.Flags |= uint64(elf.SHF_EXECINSTR)
1089 if sect.Rwx&2 != 0 {
1090 sh.Flags |= uint64(elf.SHF_WRITE)
1092 if sect.Name == ".tbss" {
1093 sh.Flags |= uint64(elf.SHF_TLS)
1094 sh.Type = uint32(elf.SHT_NOBITS)
1096 if strings.HasPrefix(sect.Name, ".debug") || strings.HasPrefix(sect.Name, ".zdebug") {
1100 if linkmode != LinkExternal {
1101 sh.Addr = sect.Vaddr
1103 sh.Addralign = uint64(sect.Align)
1104 sh.Size = sect.Length
1105 if sect.Name != ".tbss" {
1106 sh.Off = sect.Seg.Fileoff + sect.Vaddr - sect.Seg.Vaddr
1112 func elfshreloc(arch *sys.Arch, sect *sym.Section) *ElfShdr {
1113 // If main section is SHT_NOBITS, nothing to relocate.
1114 // Also nothing to relocate in .shstrtab or notes.
1115 if sect.Vaddr >= sect.Seg.Vaddr+sect.Seg.Filelen {
1118 if sect.Name == ".shstrtab" || sect.Name == ".tbss" {
1121 if sect.Elfsect.(*ElfShdr).Type == uint32(elf.SHT_NOTE) {
1126 if elfRelType == ".rela" {
1130 sh := elfshname(elfRelType + sect.Name)
1131 // There could be multiple text sections but each needs
1132 // its own .rela.text.
1134 if sect.Name == ".text" {
1135 if sh.Info != 0 && sh.Info != uint32(sect.Elfsect.(*ElfShdr).shnum) {
1136 sh = elfshnamedup(elfRelType + sect.Name)
1140 sh.Type = uint32(typ)
1141 sh.Entsize = uint64(arch.RegSize) * 2
1142 if typ == elf.SHT_RELA {
1143 sh.Entsize += uint64(arch.RegSize)
1145 sh.Link = uint32(elfshname(".symtab").shnum)
1146 sh.Info = uint32(sect.Elfsect.(*ElfShdr).shnum)
1147 sh.Off = sect.Reloff
1148 sh.Size = sect.Rellen
1149 sh.Addralign = uint64(arch.RegSize)
1153 func elfrelocsect(ctxt *Link, out *OutBuf, sect *sym.Section, syms []loader.Sym) {
1154 // If main section is SHT_NOBITS, nothing to relocate.
1155 // Also nothing to relocate in .shstrtab.
1156 if sect.Vaddr >= sect.Seg.Vaddr+sect.Seg.Filelen {
1159 if sect.Name == ".shstrtab" {
1164 for i, s := range syms {
1165 if !ldr.AttrReachable(s) {
1166 panic("should never happen")
1168 if uint64(ldr.SymValue(s)) >= sect.Vaddr {
1174 eaddr := int32(sect.Vaddr + sect.Length)
1175 for _, s := range syms {
1176 if !ldr.AttrReachable(s) {
1179 if ldr.SymValue(s) >= int64(eaddr) {
1183 // Compute external relocations on the go, and pass to Elfreloc1
1185 relocs := ldr.Relocs(s)
1186 for ri := 0; ri < relocs.Count(); ri++ {
1188 rr, ok := extreloc(ctxt, ldr, s, r)
1193 ldr.Errorf(s, "missing xsym in relocation")
1196 esr := ElfSymForReloc(ctxt, rr.Xsym)
1198 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())
1200 if !ldr.AttrReachable(rr.Xsym) {
1201 ldr.Errorf(s, "unreachable reloc %d (%s) target %v", r.Type(), sym.RelocName(ctxt.Arch, r.Type()), ldr.SymName(rr.Xsym))
1203 if !thearch.Elfreloc1(ctxt, out, ldr, s, rr, ri, int64(uint64(ldr.SymValue(s)+int64(r.Off()))-sect.Vaddr)) {
1204 ldr.Errorf(s, "unsupported obj reloc %d (%s)/%d to %s", r.Type(), sym.RelocName(ctxt.Arch, r.Type()), r.Siz(), ldr.SymName(r.Sym()))
1210 if uint64(out.Offset()) != sect.Reloff+sect.Rellen {
1211 panic(fmt.Sprintf("elfrelocsect: size mismatch %d != %d + %d", out.Offset(), sect.Reloff, sect.Rellen))
1215 func elfEmitReloc(ctxt *Link) {
1216 for ctxt.Out.Offset()&7 != 0 {
1220 sizeExtRelocs(ctxt, thearch.ElfrelocSize)
1221 relocSect, wg := relocSectFn(ctxt, elfrelocsect)
1223 for _, sect := range Segtext.Sections {
1224 if sect.Name == ".text" {
1225 relocSect(ctxt, sect, ctxt.Textp)
1227 relocSect(ctxt, sect, ctxt.datap)
1231 for _, sect := range Segrodata.Sections {
1232 relocSect(ctxt, sect, ctxt.datap)
1234 for _, sect := range Segrelrodata.Sections {
1235 relocSect(ctxt, sect, ctxt.datap)
1237 for _, sect := range Segdata.Sections {
1238 relocSect(ctxt, sect, ctxt.datap)
1240 for i := 0; i < len(Segdwarf.Sections); i++ {
1241 sect := Segdwarf.Sections[i]
1243 if si.secSym() != loader.Sym(sect.Sym) ||
1244 ctxt.loader.SymSect(si.secSym()) != sect {
1245 panic("inconsistency between dwarfp and Segdwarf")
1247 relocSect(ctxt, sect, si.syms)
1252 func addgonote(ctxt *Link, sectionName string, tag uint32, desc []byte) {
1254 s := ldr.CreateSymForUpdate(sectionName, 0)
1255 s.SetType(sym.SELFROSECT)
1257 s.AddUint32(ctxt.Arch, uint32(len(ELF_NOTE_GO_NAME)))
1259 s.AddUint32(ctxt.Arch, uint32(len(desc)))
1261 s.AddUint32(ctxt.Arch, tag)
1263 s.AddBytes(ELF_NOTE_GO_NAME)
1264 for len(s.Data())%4 != 0 {
1269 for len(s.Data())%4 != 0 {
1272 s.SetSize(int64(len(s.Data())))
1276 func (ctxt *Link) doelf() {
1279 /* predefine strings we need for section headers */
1280 shstrtab := ldr.CreateSymForUpdate(".shstrtab", 0)
1282 shstrtab.SetType(sym.SELFROSECT)
1284 shstrtab.Addstring("")
1285 shstrtab.Addstring(".text")
1286 shstrtab.Addstring(".noptrdata")
1287 shstrtab.Addstring(".data")
1288 shstrtab.Addstring(".bss")
1289 shstrtab.Addstring(".noptrbss")
1290 shstrtab.Addstring("__libfuzzer_extra_counters")
1291 shstrtab.Addstring(".go.buildinfo")
1293 shstrtab.Addstring(".MIPS.abiflags")
1294 shstrtab.Addstring(".gnu.attributes")
1297 // generate .tbss section for dynamic internal linker or external
1298 // linking, so that various binutils could correctly calculate
1299 // PT_TLS size. See https://golang.org/issue/5200.
1300 if !*FlagD || ctxt.IsExternal() {
1301 shstrtab.Addstring(".tbss")
1303 if ctxt.IsNetbsd() {
1304 shstrtab.Addstring(".note.netbsd.ident")
1306 shstrtab.Addstring(".note.netbsd.pax")
1309 if ctxt.IsOpenbsd() {
1310 shstrtab.Addstring(".note.openbsd.ident")
1312 if len(buildinfo) > 0 {
1313 shstrtab.Addstring(".note.gnu.build-id")
1315 if *flagBuildid != "" {
1316 shstrtab.Addstring(".note.go.buildid")
1318 shstrtab.Addstring(".elfdata")
1319 shstrtab.Addstring(".rodata")
1320 // See the comment about data.rel.ro.FOO section names in data.go.
1322 if ctxt.UseRelro() {
1323 shstrtab.Addstring(".data.rel.ro")
1324 relro_prefix = ".data.rel.ro"
1326 shstrtab.Addstring(relro_prefix + ".typelink")
1327 shstrtab.Addstring(relro_prefix + ".itablink")
1328 shstrtab.Addstring(relro_prefix + ".gosymtab")
1329 shstrtab.Addstring(relro_prefix + ".gopclntab")
1331 if ctxt.IsExternal() {
1334 shstrtab.Addstring(elfRelType + ".text")
1335 shstrtab.Addstring(elfRelType + ".rodata")
1336 shstrtab.Addstring(elfRelType + relro_prefix + ".typelink")
1337 shstrtab.Addstring(elfRelType + relro_prefix + ".itablink")
1338 shstrtab.Addstring(elfRelType + relro_prefix + ".gosymtab")
1339 shstrtab.Addstring(elfRelType + relro_prefix + ".gopclntab")
1340 shstrtab.Addstring(elfRelType + ".noptrdata")
1341 shstrtab.Addstring(elfRelType + ".data")
1342 if ctxt.UseRelro() {
1343 shstrtab.Addstring(elfRelType + ".data.rel.ro")
1345 shstrtab.Addstring(elfRelType + ".go.buildinfo")
1347 shstrtab.Addstring(elfRelType + ".MIPS.abiflags")
1348 shstrtab.Addstring(elfRelType + ".gnu.attributes")
1351 // add a .note.GNU-stack section to mark the stack as non-executable
1352 shstrtab.Addstring(".note.GNU-stack")
1354 if ctxt.IsShared() {
1355 shstrtab.Addstring(".note.go.abihash")
1356 shstrtab.Addstring(".note.go.pkg-list")
1357 shstrtab.Addstring(".note.go.deps")
1361 hasinitarr := ctxt.linkShared
1363 /* shared library initializer */
1364 switch ctxt.BuildMode {
1365 case BuildModeCArchive, BuildModeCShared, BuildModeShared, BuildModePlugin:
1370 shstrtab.Addstring(".init_array")
1371 shstrtab.Addstring(elfRelType + ".init_array")
1375 shstrtab.Addstring(".symtab")
1376 shstrtab.Addstring(".strtab")
1377 dwarfaddshstrings(ctxt, shstrtab)
1380 shstrtab.Addstring(".shstrtab")
1382 if !*FlagD { /* -d suppresses dynamic loader format */
1383 shstrtab.Addstring(".interp")
1384 shstrtab.Addstring(".hash")
1385 shstrtab.Addstring(".got")
1387 shstrtab.Addstring(".glink")
1389 shstrtab.Addstring(".got.plt")
1390 shstrtab.Addstring(".dynamic")
1391 shstrtab.Addstring(".dynsym")
1392 shstrtab.Addstring(".dynstr")
1393 shstrtab.Addstring(elfRelType)
1394 shstrtab.Addstring(elfRelType + ".plt")
1396 shstrtab.Addstring(".plt")
1397 shstrtab.Addstring(".gnu.version")
1398 shstrtab.Addstring(".gnu.version_r")
1400 /* dynamic symbol table - first entry all zeros */
1401 dynsym := ldr.CreateSymForUpdate(".dynsym", 0)
1403 dynsym.SetType(sym.SELFROSECT)
1405 dynsym.SetSize(dynsym.Size() + ELF64SYMSIZE)
1407 dynsym.SetSize(dynsym.Size() + ELF32SYMSIZE)
1410 /* dynamic string table */
1411 dynstr := ldr.CreateSymForUpdate(".dynstr", 0)
1413 dynstr.SetType(sym.SELFROSECT)
1414 if dynstr.Size() == 0 {
1415 dynstr.Addstring("")
1418 /* relocation table */
1419 s := ldr.CreateSymForUpdate(elfRelType, 0)
1420 s.SetType(sym.SELFROSECT)
1422 /* global offset table */
1423 got := ldr.CreateSymForUpdate(".got", 0)
1424 got.SetType(sym.SELFGOT) // writable
1426 /* ppc64 glink resolver */
1428 s := ldr.CreateSymForUpdate(".glink", 0)
1429 s.SetType(sym.SELFRXSECT)
1433 hash := ldr.CreateSymForUpdate(".hash", 0)
1434 hash.SetType(sym.SELFROSECT)
1436 gotplt := ldr.CreateSymForUpdate(".got.plt", 0)
1437 gotplt.SetType(sym.SELFSECT) // writable
1439 plt := ldr.CreateSymForUpdate(".plt", 0)
1441 // In the ppc64 ABI, .plt is a data section
1442 // written by the dynamic linker.
1443 plt.SetType(sym.SELFSECT)
1445 plt.SetType(sym.SELFRXSECT)
1448 s = ldr.CreateSymForUpdate(elfRelType+".plt", 0)
1449 s.SetType(sym.SELFROSECT)
1451 s = ldr.CreateSymForUpdate(".gnu.version", 0)
1452 s.SetType(sym.SELFROSECT)
1454 s = ldr.CreateSymForUpdate(".gnu.version_r", 0)
1455 s.SetType(sym.SELFROSECT)
1457 /* define dynamic elf table */
1458 dynamic := ldr.CreateSymForUpdate(".dynamic", 0)
1459 dynamic.SetType(sym.SELFSECT) // writable
1462 // S390X uses .got instead of .got.plt
1465 thearch.Elfsetupplt(ctxt, plt, gotplt, dynamic.Sym())
1470 elfwritedynentsym(ctxt, dynamic, elf.DT_HASH, hash.Sym())
1472 elfwritedynentsym(ctxt, dynamic, elf.DT_SYMTAB, dynsym.Sym())
1474 Elfwritedynent(ctxt.Arch, dynamic, elf.DT_SYMENT, ELF64SYMSIZE)
1476 Elfwritedynent(ctxt.Arch, dynamic, elf.DT_SYMENT, ELF32SYMSIZE)
1478 elfwritedynentsym(ctxt, dynamic, elf.DT_STRTAB, dynstr.Sym())
1479 elfwritedynentsymsize(ctxt, dynamic, elf.DT_STRSZ, dynstr.Sym())
1480 if elfRelType == ".rela" {
1481 rela := ldr.LookupOrCreateSym(".rela", 0)
1482 elfwritedynentsym(ctxt, dynamic, elf.DT_RELA, rela)
1483 elfwritedynentsymsize(ctxt, dynamic, elf.DT_RELASZ, rela)
1484 Elfwritedynent(ctxt.Arch, dynamic, elf.DT_RELAENT, ELF64RELASIZE)
1486 rel := ldr.LookupOrCreateSym(".rel", 0)
1487 elfwritedynentsym(ctxt, dynamic, elf.DT_REL, rel)
1488 elfwritedynentsymsize(ctxt, dynamic, elf.DT_RELSZ, rel)
1489 Elfwritedynent(ctxt.Arch, dynamic, elf.DT_RELENT, ELF32RELSIZE)
1492 if rpath.val != "" {
1493 Elfwritedynent(ctxt.Arch, dynamic, elf.DT_RUNPATH, uint64(dynstr.Addstring(rpath.val)))
1497 elfwritedynentsym(ctxt, dynamic, elf.DT_PLTGOT, plt.Sym())
1499 elfwritedynentsym(ctxt, dynamic, elf.DT_PLTGOT, gotplt.Sym())
1503 Elfwritedynent(ctxt.Arch, dynamic, elf.DT_PPC64_OPT, 0)
1506 // Solaris dynamic linker can't handle an empty .rela.plt if
1507 // DT_JMPREL is emitted so we have to defer generation of elf.DT_PLTREL,
1508 // DT_PLTRELSZ, and elf.DT_JMPREL dynamic entries until after we know the
1509 // size of .rel(a).plt section.
1510 Elfwritedynent(ctxt.Arch, dynamic, elf.DT_DEBUG, 0)
1513 if ctxt.IsShared() {
1514 // The go.link.abihashbytes symbol will be pointed at the appropriate
1515 // part of the .note.go.abihash section in data.go:func address().
1516 s := ldr.LookupOrCreateSym("go.link.abihashbytes", 0)
1517 sb := ldr.MakeSymbolUpdater(s)
1518 ldr.SetAttrLocal(s, true)
1519 sb.SetType(sym.SRODATA)
1520 ldr.SetAttrSpecial(s, true)
1521 sb.SetReachable(true)
1522 sb.SetSize(sha1.Size)
1524 sort.Sort(byPkg(ctxt.Library))
1526 for _, l := range ctxt.Library {
1527 h.Write(l.Fingerprint[:])
1529 addgonote(ctxt, ".note.go.abihash", ELF_NOTE_GOABIHASH_TAG, h.Sum([]byte{}))
1530 addgonote(ctxt, ".note.go.pkg-list", ELF_NOTE_GOPKGLIST_TAG, pkglistfornote)
1531 var deplist []string
1532 for _, shlib := range ctxt.Shlibs {
1533 deplist = append(deplist, filepath.Base(shlib.Path))
1535 addgonote(ctxt, ".note.go.deps", ELF_NOTE_GODEPS_TAG, []byte(strings.Join(deplist, "\n")))
1538 if ctxt.LinkMode == LinkExternal && *flagBuildid != "" {
1539 addgonote(ctxt, ".note.go.buildid", ELF_NOTE_GOBUILDID_TAG, []byte(*flagBuildid))
1542 //type mipsGnuAttributes struct {
1543 // version uint8 // 'A'
1544 // length uint32 // 15 including itself
1545 // gnu [4]byte // "gnu\0"
1546 // tag uint8 // 1:file, 2: section, 3: symbol, 1 here
1547 // taglen uint32 // tag length, including tag, 7 here
1549 // fpAbi uint8 // see .MIPS.abiflags
1552 gnuattributes := ldr.CreateSymForUpdate(".gnu.attributes", 0)
1553 gnuattributes.SetType(sym.SELFROSECT)
1554 gnuattributes.SetReachable(true)
1555 gnuattributes.AddUint8('A') // version 'A'
1556 gnuattributes.AddUint32(ctxt.Arch, 15) // length 15 including itself
1557 gnuattributes.AddBytes([]byte("gnu\x00")) // "gnu\0"
1558 gnuattributes.AddUint8(1) // 1:file, 2: section, 3: symbol, 1 here
1559 gnuattributes.AddUint32(ctxt.Arch, 7) // tag length, including tag, 7 here
1560 gnuattributes.AddUint8(4) // 4 for FP, 8 for MSA
1561 if buildcfg.GOMIPS == "softfloat" {
1562 gnuattributes.AddUint8(MIPS_FPABI_SOFT)
1564 // Note: MIPS_FPABI_ANY is bad naming: in fact it is MIPS I style FPR usage.
1565 // It is not for 'ANY'.
1566 // TODO: switch to FPXX after be sure that no odd-number-fpr is used.
1567 gnuattributes.AddUint8(MIPS_FPABI_ANY)
1572 // Do not write DT_NULL. elfdynhash will finish it.
1573 func shsym(sh *ElfShdr, ldr *loader.Loader, s loader.Sym) {
1575 panic("bad symbol in shsym2")
1577 addr := ldr.SymValue(s)
1578 if sh.Flags&uint64(elf.SHF_ALLOC) != 0 {
1579 sh.Addr = uint64(addr)
1581 sh.Off = uint64(datoff(ldr, s, addr))
1582 sh.Size = uint64(ldr.SymSize(s))
1585 func phsh(ph *ElfPhdr, sh *ElfShdr) {
1591 ph.Align = sh.Addralign
1594 func Asmbelfsetup() {
1595 /* This null SHdr must appear before all others */
1598 for _, sect := range Segtext.Sections {
1599 // There could be multiple .text sections. Instead check the Elfsect
1600 // field to determine if already has an ElfShdr and if not, create one.
1601 if sect.Name == ".text" {
1602 if sect.Elfsect == nil {
1603 sect.Elfsect = elfshnamedup(sect.Name)
1609 for _, sect := range Segrodata.Sections {
1612 for _, sect := range Segrelrodata.Sections {
1615 for _, sect := range Segdata.Sections {
1618 for _, sect := range Segdwarf.Sections {
1623 func asmbElf(ctxt *Link) {
1626 symo = int64(Segdwarf.Fileoff + Segdwarf.Filelen)
1627 symo = Rnd(symo, int64(ctxt.Arch.PtrSize))
1628 ctxt.Out.SeekSet(symo)
1630 ctxt.Out.Write(Elfstrdat)
1631 if ctxt.IsExternal() {
1639 switch ctxt.Arch.Family {
1641 Exitf("unknown architecture in asmbelf: %v", ctxt.Arch.Family)
1642 case sys.MIPS, sys.MIPS64:
1643 eh.Machine = uint16(elf.EM_MIPS)
1645 eh.Machine = uint16(elf.EM_ARM)
1647 eh.Machine = uint16(elf.EM_X86_64)
1649 eh.Machine = uint16(elf.EM_AARCH64)
1651 eh.Machine = uint16(elf.EM_386)
1653 eh.Machine = uint16(elf.EM_PPC64)
1655 eh.Machine = uint16(elf.EM_RISCV)
1657 eh.Machine = uint16(elf.EM_S390)
1660 elfreserve := int64(ELFRESERVE)
1663 for _, sect := range Segtext.Sections {
1664 if sect.Name == ".text" {
1669 // If there are multiple text sections, extra space is needed
1670 // in the elfreserve for the additional .text and .rela.text
1671 // section headers. It can handle 4 extra now. Headers are
1675 elfreserve += elfreserve + numtext*64*2
1678 startva := *FlagTextAddr - int64(HEADR)
1679 resoff := elfreserve
1683 if *flagRace && ctxt.IsNetbsd() {
1684 sh := elfshname(".note.netbsd.pax")
1685 resoff -= int64(elfnetbsdpax(sh, uint64(startva), uint64(resoff)))
1686 pnote = newElfPhdr()
1687 pnote.Type = elf.PT_NOTE
1688 pnote.Flags = elf.PF_R
1691 if ctxt.LinkMode == LinkExternal {
1692 /* skip program headers */
1697 if ctxt.BuildMode == BuildModeShared {
1698 sh := elfshname(".note.go.pkg-list")
1699 sh.Type = uint32(elf.SHT_NOTE)
1700 sh = elfshname(".note.go.abihash")
1701 sh.Type = uint32(elf.SHT_NOTE)
1702 sh.Flags = uint64(elf.SHF_ALLOC)
1703 sh = elfshname(".note.go.deps")
1704 sh.Type = uint32(elf.SHT_NOTE)
1707 if *flagBuildid != "" {
1708 sh := elfshname(".note.go.buildid")
1709 sh.Type = uint32(elf.SHT_NOTE)
1710 sh.Flags = uint64(elf.SHF_ALLOC)
1716 /* program header info */
1719 pph.Type = elf.PT_PHDR
1720 pph.Flags = elf.PF_R
1721 pph.Off = uint64(eh.Ehsize)
1722 pph.Vaddr = uint64(*FlagTextAddr) - uint64(HEADR) + pph.Off
1723 pph.Paddr = uint64(*FlagTextAddr) - uint64(HEADR) + pph.Off
1724 pph.Align = uint64(*FlagRound)
1727 * PHDR must be in a loaded segment. Adjust the text
1728 * segment boundaries downwards to include it.
1731 o := int64(Segtext.Vaddr - pph.Vaddr)
1732 Segtext.Vaddr -= uint64(o)
1733 Segtext.Length += uint64(o)
1734 o = int64(Segtext.Fileoff - pph.Off)
1735 Segtext.Fileoff -= uint64(o)
1736 Segtext.Filelen += uint64(o)
1739 if !*FlagD { /* -d suppresses dynamic loader format */
1741 sh := elfshname(".interp")
1743 sh.Type = uint32(elf.SHT_PROGBITS)
1744 sh.Flags = uint64(elf.SHF_ALLOC)
1747 if interpreter == "" && buildcfg.GO_LDSO != "" {
1748 interpreter = buildcfg.GO_LDSO
1751 if interpreter == "" {
1752 switch ctxt.HeadType {
1754 if buildcfg.GOOS == "android" {
1755 interpreter = thearch.Androiddynld
1756 if interpreter == "" {
1757 Exitf("ELF interpreter not set")
1760 interpreter = thearch.Linuxdynld
1763 case objabi.Hfreebsd:
1764 interpreter = thearch.Freebsddynld
1766 case objabi.Hnetbsd:
1767 interpreter = thearch.Netbsddynld
1769 case objabi.Hopenbsd:
1770 interpreter = thearch.Openbsddynld
1772 case objabi.Hdragonfly:
1773 interpreter = thearch.Dragonflydynld
1775 case objabi.Hsolaris:
1776 interpreter = thearch.Solarisdynld
1780 resoff -= int64(elfinterp(sh, uint64(startva), uint64(resoff), interpreter))
1783 ph.Type = elf.PT_INTERP
1789 if ctxt.HeadType == objabi.Hnetbsd || ctxt.HeadType == objabi.Hopenbsd {
1791 switch ctxt.HeadType {
1792 case objabi.Hnetbsd:
1793 sh = elfshname(".note.netbsd.ident")
1794 resoff -= int64(elfnetbsdsig(sh, uint64(startva), uint64(resoff)))
1796 case objabi.Hopenbsd:
1797 sh = elfshname(".note.openbsd.ident")
1798 resoff -= int64(elfopenbsdsig(sh, uint64(startva), uint64(resoff)))
1801 pnote = newElfPhdr()
1802 pnote.Type = elf.PT_NOTE
1803 pnote.Flags = elf.PF_R
1807 if len(buildinfo) > 0 {
1808 sh := elfshname(".note.gnu.build-id")
1809 resoff -= int64(elfbuildinfo(sh, uint64(startva), uint64(resoff)))
1812 pnote = newElfPhdr()
1813 pnote.Type = elf.PT_NOTE
1814 pnote.Flags = elf.PF_R
1820 if *flagBuildid != "" {
1821 sh := elfshname(".note.go.buildid")
1822 resoff -= int64(elfgobuildid(sh, uint64(startva), uint64(resoff)))
1824 pnote := newElfPhdr()
1825 pnote.Type = elf.PT_NOTE
1826 pnote.Flags = elf.PF_R
1830 // Additions to the reserved area must be above this line.
1833 if len(Segrodata.Sections) > 0 {
1834 elfphload(&Segrodata)
1836 if len(Segrelrodata.Sections) > 0 {
1837 elfphload(&Segrelrodata)
1838 elfphrelro(&Segrelrodata)
1842 /* Dynamic linking sections */
1844 sh := elfshname(".dynsym")
1845 sh.Type = uint32(elf.SHT_DYNSYM)
1846 sh.Flags = uint64(elf.SHF_ALLOC)
1848 sh.Entsize = ELF64SYMSIZE
1850 sh.Entsize = ELF32SYMSIZE
1852 sh.Addralign = uint64(ctxt.Arch.RegSize)
1853 sh.Link = uint32(elfshname(".dynstr").shnum)
1855 // sh.info is the index of first non-local symbol (number of local symbols)
1856 s := ldr.Lookup(".dynsym", 0)
1858 for sub := s; sub != 0; sub = ldr.SubSym(sub) {
1860 if !ldr.AttrLocal(sub) {
1867 sh = elfshname(".dynstr")
1868 sh.Type = uint32(elf.SHT_STRTAB)
1869 sh.Flags = uint64(elf.SHF_ALLOC)
1871 shsym(sh, ldr, ldr.Lookup(".dynstr", 0))
1873 if elfverneed != 0 {
1874 sh := elfshname(".gnu.version")
1875 sh.Type = uint32(elf.SHT_GNU_VERSYM)
1876 sh.Flags = uint64(elf.SHF_ALLOC)
1878 sh.Link = uint32(elfshname(".dynsym").shnum)
1880 shsym(sh, ldr, ldr.Lookup(".gnu.version", 0))
1882 sh = elfshname(".gnu.version_r")
1883 sh.Type = uint32(elf.SHT_GNU_VERNEED)
1884 sh.Flags = uint64(elf.SHF_ALLOC)
1885 sh.Addralign = uint64(ctxt.Arch.RegSize)
1886 sh.Info = uint32(elfverneed)
1887 sh.Link = uint32(elfshname(".dynstr").shnum)
1888 shsym(sh, ldr, ldr.Lookup(".gnu.version_r", 0))
1891 if elfRelType == ".rela" {
1892 sh := elfshname(".rela.plt")
1893 sh.Type = uint32(elf.SHT_RELA)
1894 sh.Flags = uint64(elf.SHF_ALLOC)
1895 sh.Entsize = ELF64RELASIZE
1896 sh.Addralign = uint64(ctxt.Arch.RegSize)
1897 sh.Link = uint32(elfshname(".dynsym").shnum)
1898 sh.Info = uint32(elfshname(".plt").shnum)
1899 shsym(sh, ldr, ldr.Lookup(".rela.plt", 0))
1901 sh = elfshname(".rela")
1902 sh.Type = uint32(elf.SHT_RELA)
1903 sh.Flags = uint64(elf.SHF_ALLOC)
1904 sh.Entsize = ELF64RELASIZE
1906 sh.Link = uint32(elfshname(".dynsym").shnum)
1907 shsym(sh, ldr, ldr.Lookup(".rela", 0))
1909 sh := elfshname(".rel.plt")
1910 sh.Type = uint32(elf.SHT_REL)
1911 sh.Flags = uint64(elf.SHF_ALLOC)
1912 sh.Entsize = ELF32RELSIZE
1914 sh.Link = uint32(elfshname(".dynsym").shnum)
1915 shsym(sh, ldr, ldr.Lookup(".rel.plt", 0))
1917 sh = elfshname(".rel")
1918 sh.Type = uint32(elf.SHT_REL)
1919 sh.Flags = uint64(elf.SHF_ALLOC)
1920 sh.Entsize = ELF32RELSIZE
1922 sh.Link = uint32(elfshname(".dynsym").shnum)
1923 shsym(sh, ldr, ldr.Lookup(".rel", 0))
1926 if elf.Machine(eh.Machine) == elf.EM_PPC64 {
1927 sh := elfshname(".glink")
1928 sh.Type = uint32(elf.SHT_PROGBITS)
1929 sh.Flags = uint64(elf.SHF_ALLOC + elf.SHF_EXECINSTR)
1931 shsym(sh, ldr, ldr.Lookup(".glink", 0))
1934 sh = elfshname(".plt")
1935 sh.Type = uint32(elf.SHT_PROGBITS)
1936 sh.Flags = uint64(elf.SHF_ALLOC + elf.SHF_EXECINSTR)
1937 if elf.Machine(eh.Machine) == elf.EM_X86_64 {
1939 } else if elf.Machine(eh.Machine) == elf.EM_S390 {
1941 } else if elf.Machine(eh.Machine) == elf.EM_PPC64 {
1942 // On ppc64, this is just a table of addresses
1943 // filled by the dynamic linker
1944 sh.Type = uint32(elf.SHT_NOBITS)
1946 sh.Flags = uint64(elf.SHF_ALLOC + elf.SHF_WRITE)
1951 sh.Addralign = sh.Entsize
1952 shsym(sh, ldr, ldr.Lookup(".plt", 0))
1954 // On ppc64, .got comes from the input files, so don't
1955 // create it here, and .got.plt is not used.
1956 if elf.Machine(eh.Machine) != elf.EM_PPC64 {
1957 sh := elfshname(".got")
1958 sh.Type = uint32(elf.SHT_PROGBITS)
1959 sh.Flags = uint64(elf.SHF_ALLOC + elf.SHF_WRITE)
1960 sh.Entsize = uint64(ctxt.Arch.RegSize)
1961 sh.Addralign = uint64(ctxt.Arch.RegSize)
1962 shsym(sh, ldr, ldr.Lookup(".got", 0))
1964 sh = elfshname(".got.plt")
1965 sh.Type = uint32(elf.SHT_PROGBITS)
1966 sh.Flags = uint64(elf.SHF_ALLOC + elf.SHF_WRITE)
1967 sh.Entsize = uint64(ctxt.Arch.RegSize)
1968 sh.Addralign = uint64(ctxt.Arch.RegSize)
1969 shsym(sh, ldr, ldr.Lookup(".got.plt", 0))
1972 sh = elfshname(".hash")
1973 sh.Type = uint32(elf.SHT_HASH)
1974 sh.Flags = uint64(elf.SHF_ALLOC)
1976 sh.Addralign = uint64(ctxt.Arch.RegSize)
1977 sh.Link = uint32(elfshname(".dynsym").shnum)
1978 shsym(sh, ldr, ldr.Lookup(".hash", 0))
1980 /* sh and elf.PT_DYNAMIC for .dynamic section */
1981 sh = elfshname(".dynamic")
1983 sh.Type = uint32(elf.SHT_DYNAMIC)
1984 sh.Flags = uint64(elf.SHF_ALLOC + elf.SHF_WRITE)
1985 sh.Entsize = 2 * uint64(ctxt.Arch.RegSize)
1986 sh.Addralign = uint64(ctxt.Arch.RegSize)
1987 sh.Link = uint32(elfshname(".dynstr").shnum)
1988 shsym(sh, ldr, ldr.Lookup(".dynamic", 0))
1990 ph.Type = elf.PT_DYNAMIC
1991 ph.Flags = elf.PF_R + elf.PF_W
1995 * Thread-local storage segment (really just size).
1997 tlssize := uint64(0)
1998 for _, sect := range Segdata.Sections {
1999 if sect.Name == ".tbss" {
2000 tlssize = sect.Length
2005 ph.Type = elf.PT_TLS
2008 ph.Align = uint64(ctxt.Arch.RegSize)
2012 if ctxt.HeadType == objabi.Hlinux {
2014 ph.Type = elf.PT_GNU_STACK
2015 ph.Flags = elf.PF_W + elf.PF_R
2016 ph.Align = uint64(ctxt.Arch.RegSize)
2019 ph.Type = elf.PT_PAX_FLAGS
2020 ph.Flags = 0x2a00 // mprotect, randexec, emutramp disabled
2021 ph.Align = uint64(ctxt.Arch.RegSize)
2022 } else if ctxt.HeadType == objabi.Hsolaris {
2024 ph.Type = elf.PT_SUNWSTACK
2025 ph.Flags = elf.PF_W + elf.PF_R
2029 sh := elfshname(".shstrtab")
2030 sh.Type = uint32(elf.SHT_STRTAB)
2032 shsym(sh, ldr, ldr.Lookup(".shstrtab", 0))
2033 eh.Shstrndx = uint16(sh.shnum)
2036 sh = elfshname(".MIPS.abiflags")
2037 sh.Type = uint32(elf.SHT_MIPS_ABIFLAGS)
2038 sh.Flags = uint64(elf.SHF_ALLOC)
2040 resoff -= int64(elfMipsAbiFlags(sh, uint64(startva), uint64(resoff)))
2043 ph.Type = elf.PT_MIPS_ABIFLAGS
2047 sh = elfshname(".gnu.attributes")
2048 sh.Type = uint32(elf.SHT_GNU_ATTRIBUTES)
2051 shsym(sh, ldr, ldr.Lookup(".gnu.attributes", 0))
2054 // put these sections early in the list
2056 elfshname(".symtab")
2057 elfshname(".strtab")
2060 for _, sect := range Segtext.Sections {
2061 elfshbits(ctxt.LinkMode, sect)
2063 for _, sect := range Segrodata.Sections {
2064 elfshbits(ctxt.LinkMode, sect)
2066 for _, sect := range Segrelrodata.Sections {
2067 elfshbits(ctxt.LinkMode, sect)
2069 for _, sect := range Segdata.Sections {
2070 elfshbits(ctxt.LinkMode, sect)
2072 for _, sect := range Segdwarf.Sections {
2073 elfshbits(ctxt.LinkMode, sect)
2076 if ctxt.LinkMode == LinkExternal {
2077 for _, sect := range Segtext.Sections {
2078 elfshreloc(ctxt.Arch, sect)
2080 for _, sect := range Segrodata.Sections {
2081 elfshreloc(ctxt.Arch, sect)
2083 for _, sect := range Segrelrodata.Sections {
2084 elfshreloc(ctxt.Arch, sect)
2086 for _, sect := range Segdata.Sections {
2087 elfshreloc(ctxt.Arch, sect)
2089 for _, si := range dwarfp {
2090 sect := ldr.SymSect(si.secSym())
2091 elfshreloc(ctxt.Arch, sect)
2093 // add a .note.GNU-stack section to mark the stack as non-executable
2094 sh := elfshname(".note.GNU-stack")
2096 sh.Type = uint32(elf.SHT_PROGBITS)
2102 sh := elfshname(".symtab")
2103 sh.Type = uint32(elf.SHT_SYMTAB)
2104 sh.Off = uint64(symo)
2105 sh.Size = uint64(symSize)
2106 sh.Addralign = uint64(ctxt.Arch.RegSize)
2107 sh.Entsize = 8 + 2*uint64(ctxt.Arch.RegSize)
2108 sh.Link = uint32(elfshname(".strtab").shnum)
2109 sh.Info = uint32(elfglobalsymndx)
2111 sh = elfshname(".strtab")
2112 sh.Type = uint32(elf.SHT_STRTAB)
2113 sh.Off = uint64(symo) + uint64(symSize)
2114 sh.Size = uint64(len(Elfstrdat))
2119 copy(eh.Ident[:], elf.ELFMAG)
2122 switch ctxt.HeadType {
2123 case objabi.Hfreebsd:
2124 osabi = elf.ELFOSABI_FREEBSD
2125 case objabi.Hnetbsd:
2126 osabi = elf.ELFOSABI_NETBSD
2127 case objabi.Hopenbsd:
2128 osabi = elf.ELFOSABI_OPENBSD
2129 case objabi.Hdragonfly:
2130 osabi = elf.ELFOSABI_NONE
2132 eh.Ident[elf.EI_OSABI] = byte(osabi)
2135 eh.Ident[elf.EI_CLASS] = byte(elf.ELFCLASS64)
2137 eh.Ident[elf.EI_CLASS] = byte(elf.ELFCLASS32)
2139 if ctxt.Arch.ByteOrder == binary.BigEndian {
2140 eh.Ident[elf.EI_DATA] = byte(elf.ELFDATA2MSB)
2142 eh.Ident[elf.EI_DATA] = byte(elf.ELFDATA2LSB)
2144 eh.Ident[elf.EI_VERSION] = byte(elf.EV_CURRENT)
2146 if ctxt.LinkMode == LinkExternal {
2147 eh.Type = uint16(elf.ET_REL)
2148 } else if ctxt.BuildMode == BuildModePIE {
2149 eh.Type = uint16(elf.ET_DYN)
2151 eh.Type = uint16(elf.ET_EXEC)
2154 if ctxt.LinkMode != LinkExternal {
2155 eh.Entry = uint64(Entryvalue(ctxt))
2158 eh.Version = uint32(elf.EV_CURRENT)
2161 pph.Filesz = uint64(eh.Phnum) * uint64(eh.Phentsize)
2162 pph.Memsz = pph.Filesz
2167 a += int64(elfwritehdr(ctxt.Out))
2168 a += int64(elfwritephdrs(ctxt.Out))
2169 a += int64(elfwriteshdrs(ctxt.Out))
2171 a += int64(elfwriteinterp(ctxt.Out))
2174 a += int64(elfWriteMipsAbiFlags(ctxt))
2177 if ctxt.LinkMode != LinkExternal {
2178 if ctxt.HeadType == objabi.Hnetbsd {
2179 a += int64(elfwritenetbsdsig(ctxt.Out))
2181 if ctxt.HeadType == objabi.Hopenbsd {
2182 a += int64(elfwriteopenbsdsig(ctxt.Out))
2184 if len(buildinfo) > 0 {
2185 a += int64(elfwritebuildinfo(ctxt.Out))
2187 if *flagBuildid != "" {
2188 a += int64(elfwritegobuildid(ctxt.Out))
2191 if *flagRace && ctxt.IsNetbsd() {
2192 a += int64(elfwritenetbsdpax(ctxt.Out))
2196 Errorf(nil, "ELFRESERVE too small: %d > %d with %d text sections", a, elfreserve, numtext)
2199 // Verify the amount of space allocated for the elf header is sufficient. The file offsets are
2200 // already computed in layout, so we could spill into another section.
2201 if a > int64(HEADR) {
2202 Errorf(nil, "HEADR too small: %d > %d with %d text sections", a, HEADR, numtext)
2206 func elfadddynsym(ldr *loader.Loader, target *Target, syms *ArchSyms, s loader.Sym) {
2207 ldr.SetSymDynid(s, int32(Nelfsym))
2209 d := ldr.MakeSymbolUpdater(syms.DynSym)
2210 name := ldr.SymExtname(s)
2211 dstru := ldr.MakeSymbolUpdater(syms.DynStr)
2212 st := ldr.SymType(s)
2213 cgoeStatic := ldr.AttrCgoExportStatic(s)
2214 cgoeDynamic := ldr.AttrCgoExportDynamic(s)
2215 cgoexp := (cgoeStatic || cgoeDynamic)
2217 d.AddUint32(target.Arch, uint32(dstru.Addstring(name)))
2224 if cgoexp && st == sym.STEXT {
2225 t = elf.ST_INFO(elf.STB_GLOBAL, elf.STT_FUNC)
2227 t = elf.ST_INFO(elf.STB_GLOBAL, elf.STT_OBJECT)
2234 /* section where symbol is defined */
2235 if st == sym.SDYNIMPORT {
2236 d.AddUint16(target.Arch, uint16(elf.SHN_UNDEF))
2238 d.AddUint16(target.Arch, 1)
2242 if st == sym.SDYNIMPORT {
2243 d.AddUint64(target.Arch, 0)
2245 d.AddAddrPlus(target.Arch, s, 0)
2248 /* size of object */
2249 d.AddUint64(target.Arch, uint64(len(ldr.Data(s))))
2251 dil := ldr.SymDynimplib(s)
2253 if target.Arch.Family == sys.AMD64 && !cgoeDynamic && dil != "" && !seenlib[dil] {
2254 du := ldr.MakeSymbolUpdater(syms.Dynamic)
2255 Elfwritedynent(target.Arch, du, elf.DT_NEEDED, uint64(dstru.Addstring(dil)))
2261 if st == sym.SDYNIMPORT {
2262 d.AddUint32(target.Arch, 0)
2264 d.AddAddrPlus(target.Arch, s, 0)
2267 /* size of object */
2268 d.AddUint32(target.Arch, uint32(len(ldr.Data(s))))
2273 // TODO(mwhudson): presumably the behavior should actually be the same on both arm and 386.
2274 if target.Arch.Family == sys.I386 && cgoexp && st == sym.STEXT {
2275 t = elf.ST_INFO(elf.STB_GLOBAL, elf.STT_FUNC)
2276 } else if target.Arch.Family == sys.ARM && cgoeDynamic && st == sym.STEXT {
2277 t = elf.ST_INFO(elf.STB_GLOBAL, elf.STT_FUNC)
2279 t = elf.ST_INFO(elf.STB_GLOBAL, elf.STT_OBJECT)
2285 if st == sym.SDYNIMPORT {
2286 d.AddUint16(target.Arch, uint16(elf.SHN_UNDEF))
2288 d.AddUint16(target.Arch, 1)