Source file src/cmd/link/internal/ld/elf.go

     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.
     4  
     5  package ld
     6  
     7  import (
     8  	"cmd/internal/hash"
     9  	"cmd/internal/objabi"
    10  	"cmd/internal/sys"
    11  	"cmd/link/internal/loader"
    12  	"cmd/link/internal/sym"
    13  	"cmp"
    14  	"debug/elf"
    15  	"encoding/binary"
    16  	"encoding/hex"
    17  	"fmt"
    18  	"internal/buildcfg"
    19  	"os"
    20  	"path/filepath"
    21  	"runtime"
    22  	"slices"
    23  	"strings"
    24  )
    25  
    26  /*
    27   * Derived from:
    28   * $FreeBSD: src/sys/sys/elf32.h,v 1.8.14.1 2005/12/30 22:13:58 marcel Exp $
    29   * $FreeBSD: src/sys/sys/elf64.h,v 1.10.14.1 2005/12/30 22:13:58 marcel Exp $
    30   * $FreeBSD: src/sys/sys/elf_common.h,v 1.15.8.1 2005/12/30 22:13:58 marcel Exp $
    31   * $FreeBSD: src/sys/alpha/include/elf.h,v 1.14 2003/09/25 01:10:22 peter Exp $
    32   * $FreeBSD: src/sys/amd64/include/elf.h,v 1.18 2004/08/03 08:21:48 dfr Exp $
    33   * $FreeBSD: src/sys/arm/include/elf.h,v 1.5.2.1 2006/06/30 21:42:52 cognet Exp $
    34   * $FreeBSD: src/sys/i386/include/elf.h,v 1.16 2004/08/02 19:12:17 dfr Exp $
    35   * $FreeBSD: src/sys/powerpc/include/elf.h,v 1.7 2004/11/02 09:47:01 ssouhlal Exp $
    36   * $FreeBSD: src/sys/sparc64/include/elf.h,v 1.12 2003/09/25 01:10:26 peter Exp $
    37   *
    38   * Copyright (c) 1996-1998 John D. Polstra.  All rights reserved.
    39   * Copyright (c) 2001 David E. O'Brien
    40   * Portions Copyright 2009 The Go Authors. All rights reserved.
    41   *
    42   * Redistribution and use in source and binary forms, with or without
    43   * modification, are permitted provided that the following conditions
    44   * are met:
    45   * 1. Redistributions of source code must retain the above copyright
    46   *    notice, this list of conditions and the following disclaimer.
    47   * 2. Redistributions in binary form must reproduce the above copyright
    48   *    notice, this list of conditions and the following disclaimer in the
    49   *    documentation and/or other materials provided with the distribution.
    50   *
    51   * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
    52   * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    53   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    54   * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
    55   * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    56   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
    57   * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    58   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
    59   * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
    60   * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    61   * SUCH DAMAGE.
    62   *
    63   */
    64  
    65  // ELF definitions that are independent of architecture or word size.
    66  
    67  // We use the 64-bit data structures on both 32- and 64-bit machines
    68  // in order to write the code just once. The 64-bit data structure is
    69  // written in the 32-bit format on the 32-bit machines.
    70  
    71  // ElfEhdr is the ELF file header.
    72  type ElfEhdr elf.Header64
    73  
    74  // ElfShdr is an ELF section table entry.
    75  type ElfShdr struct {
    76  	elf.Section64
    77  
    78  	// nameString is the section name as a string.
    79  	// This is not to be confused with Name,
    80  	// inherited from elf.Section64, which is an offset.
    81  	nameString string
    82  
    83  	// The section index, set by elfSortShdrs.
    84  	// Don't read this directly, use elfShdrShnum.
    85  	shnum elf.SectionIndex
    86  
    87  	// Because we don't compute the final section number
    88  	// until late in the link, when the link and info fields
    89  	// hold section indexes, we store pointers, and fetch
    90  	// the final section index when we write them out.
    91  	link *ElfShdr
    92  	info *ElfShdr
    93  
    94  	// We compute the section offsets of reloc sections
    95  	// after we create the ELF section header.
    96  	// This field lets us fetch the section offset and size.
    97  	relocSect *sym.Section
    98  }
    99  
   100  // ElfPhdr is the ELF program, or segment, header.
   101  type ElfPhdr elf.ProgHeader
   102  
   103  const (
   104  	ELF64HDRSIZE  = 64
   105  	ELF64PHDRSIZE = 56
   106  	ELF64SHDRSIZE = 64
   107  	ELF64RELSIZE  = 16
   108  	ELF64RELASIZE = 24
   109  	ELF64SYMSIZE  = 24
   110  	ELF32HDRSIZE  = 52
   111  	ELF32PHDRSIZE = 32
   112  	ELF32SHDRSIZE = 40
   113  	ELF32SYMSIZE  = 16
   114  	ELF32RELSIZE  = 8
   115  )
   116  
   117  var elfstrdat []byte
   118  
   119  // ELFRESERVE is the total amount of space to reserve at the
   120  // start of the file for Header, PHeaders, SHeaders, and interp.
   121  // May waste some space.
   122  // On FreeBSD, cannot be larger than a page.
   123  const ELFRESERVE = 4096
   124  
   125  var (
   126  	Nelfsym = 1
   127  
   128  	elf64 bool
   129  	// Either ".rel" or ".rela" depending on which type of relocation the
   130  	// target platform uses.
   131  	elfRelType string
   132  
   133  	ehdr       ElfEhdr
   134  	phdr       = make([]*ElfPhdr, 0, 8)
   135  	shdr       = make([]*ElfShdr, 0, 64)
   136  	shdrSorted bool
   137  
   138  	interp string
   139  )
   140  
   141  // ELFArch includes target-specific hooks for ELF targets.
   142  // This is initialized by the target-specific Init function
   143  // called by the linker's main function in cmd/link/main.go.
   144  type ELFArch struct {
   145  	// TODO: Document these fields.
   146  
   147  	Androiddynld   string
   148  	Linuxdynld     string
   149  	LinuxdynldMusl string
   150  	Freebsddynld   string
   151  	Netbsddynld    string
   152  	Openbsddynld   string
   153  	Dragonflydynld string
   154  	Solarisdynld   string
   155  
   156  	Reloc1    func(*Link, *OutBuf, *loader.Loader, loader.Sym, loader.ExtReloc, int, int64) bool
   157  	RelocSize uint32 // size of an ELF relocation record, must match Reloc1.
   158  	SetupPLT  func(ctxt *Link, ldr *loader.Loader, plt, gotplt *loader.SymbolBuilder, dynamic loader.Sym)
   159  
   160  	// DynamicReadOnly can be set to true to make the .dynamic
   161  	// section read-only. By default it is writable.
   162  	// This is used by MIPS targets.
   163  	DynamicReadOnly bool
   164  }
   165  
   166  var buildinfo []byte
   167  
   168  // Elfinit initializes the global ehdr variable that holds the ELF header.
   169  // It will be updated as write section and program headers.
   170  func Elfinit(ctxt *Link) {
   171  	ctxt.IsELF = true
   172  
   173  	if ctxt.Arch.InFamily(sys.AMD64, sys.ARM64, sys.Loong64, sys.MIPS64, sys.PPC64, sys.RISCV64, sys.S390X) {
   174  		elfRelType = ".rela"
   175  	} else {
   176  		elfRelType = ".rel"
   177  	}
   178  
   179  	switch ctxt.Arch.Family {
   180  	// 64-bit architectures
   181  	case sys.AMD64, sys.ARM64, sys.Loong64, sys.MIPS64, sys.PPC64, sys.RISCV64, sys.S390X:
   182  		if ctxt.Arch.Family == sys.MIPS64 {
   183  			ehdr.Flags = 0x20000004 // MIPS 3 CPIC
   184  		}
   185  		if ctxt.Arch.Family == sys.Loong64 {
   186  			ehdr.Flags = 0x43 // DOUBLE_FLOAT, OBJABI_V1
   187  		}
   188  		if ctxt.Arch.Family == sys.RISCV64 {
   189  			ehdr.Flags = 0x4 // RISCV Float ABI Double
   190  		}
   191  		if ctxt.Arch.Family == sys.S390X {
   192  			ehdr.Flags = 1 // Version 1 ABI
   193  		}
   194  		if ctxt.Arch.Family == sys.PPC64 {
   195  			ehdr.Flags = 2 // Version 2 ABI
   196  		}
   197  		elf64 = true
   198  
   199  		ehdr.Phoff = ELF64HDRSIZE      // Must be ELF64HDRSIZE: first PHdr must follow ELF header
   200  		ehdr.Shoff = ELF64HDRSIZE      // Will move as we add PHeaders
   201  		ehdr.Ehsize = ELF64HDRSIZE     // Must be ELF64HDRSIZE
   202  		ehdr.Phentsize = ELF64PHDRSIZE // Must be ELF64PHDRSIZE
   203  		ehdr.Shentsize = ELF64SHDRSIZE // Must be ELF64SHDRSIZE
   204  
   205  	// 32-bit architectures
   206  	case sys.ARM, sys.MIPS:
   207  		if ctxt.Arch.Family == sys.ARM {
   208  			// we use EABI on linux/arm, freebsd/arm, netbsd/arm.
   209  			if ctxt.HeadType == objabi.Hlinux || ctxt.HeadType == objabi.Hfreebsd || ctxt.HeadType == objabi.Hnetbsd {
   210  				// We set a value here that makes no indication of which
   211  				// float ABI the object uses, because this is information
   212  				// used by the dynamic linker to compare executables and
   213  				// shared libraries -- so it only matters for cgo calls, and
   214  				// the information properly comes from the object files
   215  				// produced by the host C compiler. parseArmAttributes in
   216  				// ldelf.go reads that information and updates this field as
   217  				// appropriate.
   218  				ehdr.Flags = 0x5000002 // has entry point, Version5 EABI
   219  			}
   220  		} else if ctxt.Arch.Family == sys.MIPS {
   221  			ehdr.Flags = 0x50001004 // MIPS 32 CPIC O32
   222  		}
   223  		fallthrough
   224  	default:
   225  		ehdr.Phoff = ELF32HDRSIZE
   226  		// Must be ELF32HDRSIZE: first PHdr must follow ELF header
   227  		ehdr.Shoff = ELF32HDRSIZE      // Will move as we add PHeaders
   228  		ehdr.Ehsize = ELF32HDRSIZE     // Must be ELF32HDRSIZE
   229  		ehdr.Phentsize = ELF32PHDRSIZE // Must be ELF32PHDRSIZE
   230  		ehdr.Shentsize = ELF32SHDRSIZE // Must be ELF32SHDRSIZE
   231  	}
   232  }
   233  
   234  // fixElfPhdr makes sure PT_LOAD is aligned properly and that there is no gap.
   235  // Correct ELF loaders will do this implicitly,
   236  // but buggy ELF loaders like the one in some
   237  // versions of QEMU and UPX won't.
   238  func fixElfPhdr(e *ElfPhdr) {
   239  	frag := int(e.Vaddr & (e.Align - 1))
   240  
   241  	e.Off -= uint64(frag)
   242  	e.Vaddr -= uint64(frag)
   243  	e.Paddr -= uint64(frag)
   244  	e.Filesz += uint64(frag)
   245  	e.Memsz += uint64(frag)
   246  }
   247  
   248  func elf64phdr(out *OutBuf, e *ElfPhdr) {
   249  	if e.Type == elf.PT_LOAD {
   250  		fixElfPhdr(e)
   251  	}
   252  
   253  	out.Write32(uint32(e.Type))
   254  	out.Write32(uint32(e.Flags))
   255  	out.Write64(e.Off)
   256  	out.Write64(e.Vaddr)
   257  	out.Write64(e.Paddr)
   258  	out.Write64(e.Filesz)
   259  	out.Write64(e.Memsz)
   260  	out.Write64(e.Align)
   261  }
   262  
   263  func elf32phdr(out *OutBuf, e *ElfPhdr) {
   264  	if e.Type == elf.PT_LOAD {
   265  		fixElfPhdr(e)
   266  	}
   267  
   268  	out.Write32(uint32(e.Type))
   269  	out.Write32(uint32(e.Off))
   270  	out.Write32(uint32(e.Vaddr))
   271  	out.Write32(uint32(e.Paddr))
   272  	out.Write32(uint32(e.Filesz))
   273  	out.Write32(uint32(e.Memsz))
   274  	out.Write32(uint32(e.Flags))
   275  	out.Write32(uint32(e.Align))
   276  }
   277  
   278  // elfShdrShnum returns the section index of an ElfShdr.
   279  func elfShdrShnum(e *ElfShdr) elf.SectionIndex {
   280  	if e.shnum == -1 {
   281  		Errorf("internal error: retrieved section index before it is set")
   282  		errorexit()
   283  	}
   284  	return e.shnum
   285  }
   286  
   287  // elfShdrOff returns the section offset for an ElfShdr.
   288  func elfShdrOff(e *ElfShdr) uint64 {
   289  	if e.relocSect != nil {
   290  		if e.Off != 0 {
   291  			Errorf("internal error: ElfShdr relocSect == %p Off == %d", e.relocSect, e.Off)
   292  			errorexit()
   293  		}
   294  		return e.relocSect.Reloff
   295  	}
   296  	return e.Off
   297  }
   298  
   299  // elfShdrSize returns the section size for an ElfShdr.
   300  func elfShdrSize(e *ElfShdr) uint64 {
   301  	if e.relocSect != nil {
   302  		if e.Size != 0 {
   303  			Errorf("internal error: ElfShdr relocSect == %p Size == %d", e.relocSect, e.Size)
   304  			errorexit()
   305  		}
   306  		return e.relocSect.Rellen
   307  	}
   308  	return e.Size
   309  }
   310  
   311  // elfShdrLink returns the link value for an ElfShdr.
   312  func elfShdrLink(e *ElfShdr) uint32 {
   313  	if e.link != nil {
   314  		if e.Link != 0 {
   315  			Errorf("internal error: ElfShdr link == %p Link == %d", e.link, e.Link)
   316  			errorexit()
   317  		}
   318  		return uint32(elfShdrShnum(e.link))
   319  	}
   320  	return e.Link
   321  }
   322  
   323  // elfShdrInfo returns the info value for an ElfShdr.
   324  func elfShdrInfo(e *ElfShdr) uint32 {
   325  	if e.info != nil {
   326  		if e.Info != 0 {
   327  			Errorf("internal error: ElfShdr info == %p Info == %d", e.info, e.Info)
   328  			errorexit()
   329  		}
   330  		return uint32(elfShdrShnum(e.info))
   331  	}
   332  	return e.Info
   333  }
   334  
   335  func elf64shdr(out *OutBuf, e *ElfShdr) {
   336  	out.Write32(e.Name)
   337  	out.Write32(e.Type)
   338  	out.Write64(e.Flags)
   339  	out.Write64(e.Addr)
   340  	out.Write64(elfShdrOff(e))
   341  	out.Write64(elfShdrSize(e))
   342  	out.Write32(elfShdrLink(e))
   343  	out.Write32(elfShdrInfo(e))
   344  	out.Write64(e.Addralign)
   345  	out.Write64(e.Entsize)
   346  }
   347  
   348  func elf32shdr(out *OutBuf, e *ElfShdr) {
   349  	out.Write32(e.Name)
   350  	out.Write32(e.Type)
   351  	out.Write32(uint32(e.Flags))
   352  	out.Write32(uint32(e.Addr))
   353  	out.Write32(uint32(elfShdrOff(e)))
   354  	out.Write32(uint32(elfShdrSize(e)))
   355  	out.Write32(elfShdrLink(e))
   356  	out.Write32(elfShdrInfo(e))
   357  	out.Write32(uint32(e.Addralign))
   358  	out.Write32(uint32(e.Entsize))
   359  }
   360  
   361  func elfwriteshdrs(out *OutBuf) uint32 {
   362  	if elf64 {
   363  		for _, sh := range shdr {
   364  			elf64shdr(out, sh)
   365  		}
   366  		return uint32(len(shdr)) * ELF64SHDRSIZE
   367  	}
   368  
   369  	for _, sh := range shdr {
   370  		elf32shdr(out, sh)
   371  	}
   372  	return uint32(len(shdr)) * ELF32SHDRSIZE
   373  }
   374  
   375  // elfSortShdrs sorts the section headers so that allocated sections
   376  // are first, in address order. This isn't required for correctness,
   377  // but it makes the ELF file easier for humans to read.
   378  // We only do this for an executable, not an object file.
   379  func elfSortShdrs(ctxt *Link) {
   380  	if ctxt.LinkMode != LinkExternal {
   381  		// Use [1:] to leave the empty section header zero in place.
   382  		slices.SortStableFunc(shdr[1:], func(a, b *ElfShdr) int {
   383  			isAllocated := func(h *ElfShdr) bool {
   384  				return elf.SectionFlag(h.Flags)&elf.SHF_ALLOC != 0
   385  			}
   386  			if isAllocated(a) {
   387  				if isAllocated(b) {
   388  					if r := cmp.Compare(a.Addr, b.Addr); r != 0 {
   389  						return r
   390  					}
   391  					// With same address, sort smallest
   392  					// section first.
   393  					return cmp.Compare(a.Size, b.Size)
   394  				}
   395  				// Allocated before unallocated.
   396  				return -1
   397  			}
   398  			if isAllocated(b) {
   399  				// Allocated before unallocated.
   400  				return 1
   401  			}
   402  			return 0
   403  		})
   404  	}
   405  	for i, h := range shdr {
   406  		h.shnum = elf.SectionIndex(i)
   407  	}
   408  	shdrSorted = true
   409  }
   410  
   411  // elfWriteShstrtab writes out the ELF section string table.
   412  // It also sets the Name field of the section headers.
   413  // It returns the length of the string table.
   414  func elfWriteShstrtab(ctxt *Link) uint32 {
   415  	// Map from section name to shstrtab offset.
   416  	m := make(map[string]uint32, len(shdr))
   417  
   418  	m[""] = 0
   419  	ctxt.Out.WriteByte(0)
   420  	off := uint32(1)
   421  
   422  	writeString := func(s string) {
   423  		m[s] = off
   424  		ctxt.Out.WriteString(s)
   425  		ctxt.Out.WriteByte(0)
   426  		off += uint32(len(s)) + 1
   427  	}
   428  
   429  	// As a minor optimization, do the relocation sections first,
   430  	// as they may let us reuse the suffix.
   431  	// That is, the offset for ".text" can point into ".rel.text".
   432  	// We don't do a full suffix search as the relocation sections
   433  	// are likely to be the only match.
   434  	for _, sh := range shdr {
   435  		if suffix, ok := strings.CutPrefix(sh.nameString, elfRelType); ok {
   436  			if _, found := m[suffix]; !found {
   437  				m[suffix] = off + uint32(len(elfRelType))
   438  			}
   439  			writeString(sh.nameString)
   440  		}
   441  	}
   442  
   443  	for _, sh := range shdr {
   444  		if shOff, ok := m[sh.nameString]; ok {
   445  			sh.Name = shOff
   446  		} else {
   447  			sh.Name = off
   448  			writeString(sh.nameString)
   449  		}
   450  	}
   451  
   452  	return off
   453  }
   454  
   455  func elfwritephdrs(out *OutBuf) uint32 {
   456  	if elf64 {
   457  		for i := 0; i < int(ehdr.Phnum); i++ {
   458  			elf64phdr(out, phdr[i])
   459  		}
   460  		return uint32(ehdr.Phnum) * ELF64PHDRSIZE
   461  	}
   462  
   463  	for i := 0; i < int(ehdr.Phnum); i++ {
   464  		elf32phdr(out, phdr[i])
   465  	}
   466  	return uint32(ehdr.Phnum) * ELF32PHDRSIZE
   467  }
   468  
   469  func newElfPhdr() *ElfPhdr {
   470  	e := new(ElfPhdr)
   471  	phdr = append(phdr, e)
   472  	ehdr.Phnum++
   473  	if elf64 {
   474  		ehdr.Shoff += ELF64PHDRSIZE
   475  	} else {
   476  		ehdr.Shoff += ELF32PHDRSIZE
   477  	}
   478  	return e
   479  }
   480  
   481  func newElfShdr(name string) *ElfShdr {
   482  	if shdrSorted {
   483  		Errorf("internal error: creating a section header after they were sorted")
   484  		errorexit()
   485  	}
   486  
   487  	e := &ElfShdr{
   488  		nameString: name,
   489  		shnum:      -1, // make invalid for now, set by elfSortShdrs
   490  	}
   491  	shdr = append(shdr, e)
   492  	return e
   493  }
   494  
   495  func getElfEhdr() *ElfEhdr {
   496  	return &ehdr
   497  }
   498  
   499  func elf64writehdr(out *OutBuf) uint32 {
   500  	out.Write(ehdr.Ident[:])
   501  	out.Write16(ehdr.Type)
   502  	out.Write16(ehdr.Machine)
   503  	out.Write32(ehdr.Version)
   504  	out.Write64(ehdr.Entry)
   505  	out.Write64(ehdr.Phoff)
   506  	out.Write64(ehdr.Shoff)
   507  	out.Write32(ehdr.Flags)
   508  	out.Write16(ehdr.Ehsize)
   509  	out.Write16(ehdr.Phentsize)
   510  	out.Write16(ehdr.Phnum)
   511  	out.Write16(ehdr.Shentsize)
   512  	out.Write16(ehdr.Shnum)
   513  	out.Write16(ehdr.Shstrndx)
   514  	return ELF64HDRSIZE
   515  }
   516  
   517  func elf32writehdr(out *OutBuf) uint32 {
   518  	out.Write(ehdr.Ident[:])
   519  	out.Write16(ehdr.Type)
   520  	out.Write16(ehdr.Machine)
   521  	out.Write32(ehdr.Version)
   522  	out.Write32(uint32(ehdr.Entry))
   523  	out.Write32(uint32(ehdr.Phoff))
   524  	out.Write32(uint32(ehdr.Shoff))
   525  	out.Write32(ehdr.Flags)
   526  	out.Write16(ehdr.Ehsize)
   527  	out.Write16(ehdr.Phentsize)
   528  	out.Write16(ehdr.Phnum)
   529  	out.Write16(ehdr.Shentsize)
   530  	out.Write16(ehdr.Shnum)
   531  	out.Write16(ehdr.Shstrndx)
   532  	return ELF32HDRSIZE
   533  }
   534  
   535  func elfwritehdr(out *OutBuf) uint32 {
   536  	if elf64 {
   537  		return elf64writehdr(out)
   538  	}
   539  	return elf32writehdr(out)
   540  }
   541  
   542  // elfhash is the dynamic symbol hash function .
   543  // This is taken directly from the definition document for ELF,
   544  // except that instead of finishing with "h &^= g" we just write
   545  // "h &= 0xfffffff", which results in the same value.
   546  func elfhash(name string) uint32 {
   547  	var h uint32
   548  	for i := 0; i < len(name); i++ {
   549  		h = (h << 4) + uint32(name[i])
   550  		if g := h & 0xf0000000; g != 0 {
   551  			h ^= g >> 24
   552  		}
   553  		h &= 0x0fffffff
   554  	}
   555  	return h
   556  }
   557  
   558  func elfWriteDynEntSym(ctxt *Link, s *loader.SymbolBuilder, tag elf.DynTag, t loader.Sym) {
   559  	Elfwritedynentsymplus(ctxt, s, tag, t, 0)
   560  }
   561  
   562  func Elfwritedynent(arch *sys.Arch, s *loader.SymbolBuilder, tag elf.DynTag, val uint64) {
   563  	if elf64 {
   564  		s.AddUint64(arch, uint64(tag))
   565  		s.AddUint64(arch, val)
   566  	} else {
   567  		s.AddUint32(arch, uint32(tag))
   568  		s.AddUint32(arch, uint32(val))
   569  	}
   570  }
   571  
   572  func Elfwritedynentsymplus(ctxt *Link, s *loader.SymbolBuilder, tag elf.DynTag, t loader.Sym, add int64) {
   573  	if elf64 {
   574  		s.AddUint64(ctxt.Arch, uint64(tag))
   575  	} else {
   576  		s.AddUint32(ctxt.Arch, uint32(tag))
   577  	}
   578  	s.AddAddrPlus(ctxt.Arch, t, add)
   579  }
   580  
   581  func elfwritedynentsymsize(ctxt *Link, s *loader.SymbolBuilder, tag elf.DynTag, t loader.Sym) {
   582  	if elf64 {
   583  		s.AddUint64(ctxt.Arch, uint64(tag))
   584  	} else {
   585  		s.AddUint32(ctxt.Arch, uint32(tag))
   586  	}
   587  	s.AddSize(ctxt.Arch, t)
   588  }
   589  
   590  func elfinterp(sh *ElfShdr, startva uint64, resoff uint64, p string) int {
   591  	interp = p
   592  	n := len(interp) + 1
   593  	sh.Addr = startva + resoff - uint64(n)
   594  	sh.Off = resoff - uint64(n)
   595  	sh.Size = uint64(n)
   596  
   597  	return n
   598  }
   599  
   600  func elfwriteinterp(out *OutBuf) int {
   601  	sh := elfshname(".interp")
   602  	out.SeekSet(int64(sh.Off))
   603  	out.WriteString(interp)
   604  	out.Write8(0)
   605  	return int(sh.Size)
   606  }
   607  
   608  // member of .gnu.attributes of MIPS for fpAbi
   609  const (
   610  	// No floating point is present in the module (default)
   611  	MIPS_FPABI_NONE = 0
   612  	// FP code in the module uses the FP32 ABI for a 32-bit ABI
   613  	MIPS_FPABI_ANY = 1
   614  	// FP code in the module only uses single precision ABI
   615  	MIPS_FPABI_SINGLE = 2
   616  	// FP code in the module uses soft-float ABI
   617  	MIPS_FPABI_SOFT = 3
   618  	// FP code in the module assumes an FPU with FR=1 and has 12
   619  	// callee-saved doubles. Historic, no longer supported.
   620  	MIPS_FPABI_HIST = 4
   621  	// FP code in the module uses the FPXX  ABI
   622  	MIPS_FPABI_FPXX = 5
   623  	// FP code in the module uses the FP64  ABI
   624  	MIPS_FPABI_FP64 = 6
   625  	// FP code in the module uses the FP64A ABI
   626  	MIPS_FPABI_FP64A = 7
   627  )
   628  
   629  func elfMipsAbiFlags(sh *ElfShdr, startva uint64, resoff uint64) int {
   630  	n := 24
   631  	sh.Addr = startva + resoff - uint64(n)
   632  	sh.Off = resoff - uint64(n)
   633  	sh.Size = uint64(n)
   634  	sh.Type = uint32(elf.SHT_MIPS_ABIFLAGS)
   635  	sh.Flags = uint64(elf.SHF_ALLOC)
   636  
   637  	return n
   638  }
   639  
   640  // elfWriteMipsAbiFlags writes the .MIPS.abiflags section.
   641  //
   642  // Layout is given by this C definition:
   643  //
   644  //	typedef struct
   645  //	{
   646  //	  /* Version of flags structure.  */
   647  //	  uint16_t version;
   648  //	  /* The level of the ISA: 1-5, 32, 64.  */
   649  //	  uint8_t isa_level;
   650  //	  /* The revision of ISA: 0 for MIPS V and below, 1-n otherwise.  */
   651  //	  uint8_t isa_rev;
   652  //	  /* The size of general purpose registers.  */
   653  //	  uint8_t gpr_size;
   654  //	  /* The size of co-processor 1 registers.  */
   655  //	  uint8_t cpr1_size;
   656  //	  /* The size of co-processor 2 registers.  */
   657  //	  uint8_t cpr2_size;
   658  //	  /* The floating-point ABI.  */
   659  //	  uint8_t fp_abi;
   660  //	  /* Processor-specific extension.  */
   661  //	  uint32_t isa_ext;
   662  //	  /* Mask of ASEs used.  */
   663  //	  uint32_t ases;
   664  //	  /* Mask of general flags.  */
   665  //	  uint32_t flags1;
   666  //	  uint32_t flags2;
   667  //	} Elf_Internal_ABIFlags_v0;
   668  func elfWriteMipsAbiFlags(ctxt *Link) int {
   669  	sh := elfshname(".MIPS.abiflags")
   670  	ctxt.Out.SeekSet(int64(sh.Off))
   671  	ctxt.Out.Write16(0) // version
   672  	ctxt.Out.Write8(32) // isaLevel
   673  	ctxt.Out.Write8(1)  // isaRev
   674  	ctxt.Out.Write8(1)  // gprSize
   675  	ctxt.Out.Write8(1)  // cpr1Size
   676  	ctxt.Out.Write8(0)  // cpr2Size
   677  	if buildcfg.GOMIPS == "softfloat" {
   678  		ctxt.Out.Write8(MIPS_FPABI_SOFT) // fpAbi
   679  	} else {
   680  		// Go cannot make sure non odd-number-fpr is used (ie, in load a double from memory).
   681  		// So, we mark the object is MIPS I style paired float/double register scheme,
   682  		// aka MIPS_FPABI_ANY. If we mark the object as FPXX, the kernel may use FR=1 mode,
   683  		// then we meet some problem.
   684  		// Note: MIPS_FPABI_ANY is bad naming: in fact it is MIPS I style FPR usage.
   685  		//       It is not for 'ANY'.
   686  		// TODO: switch to FPXX after be sure that no odd-number-fpr is used.
   687  		ctxt.Out.Write8(MIPS_FPABI_ANY) // fpAbi
   688  	}
   689  	ctxt.Out.Write32(0) // isaExt
   690  	ctxt.Out.Write32(0) // ases
   691  	ctxt.Out.Write32(0) // flags1
   692  	ctxt.Out.Write32(0) // flags2
   693  	return int(sh.Size)
   694  }
   695  
   696  func elfnote(sh *ElfShdr, startva uint64, resoff uint64, sizes ...int) int {
   697  	n := resoff % 4
   698  	// if section contains multiple notes (as is the case with FreeBSD signature),
   699  	// multiple note sizes can be specified
   700  	for _, sz := range sizes {
   701  		n += 3*4 + uint64(sz)
   702  	}
   703  
   704  	sh.Type = uint32(elf.SHT_NOTE)
   705  	sh.Flags = uint64(elf.SHF_ALLOC)
   706  	sh.Addralign = 4
   707  	sh.Addr = startva + resoff - n
   708  	sh.Off = resoff - n
   709  	sh.Size = n - resoff%4
   710  
   711  	return int(n)
   712  }
   713  
   714  func elfwritenotehdr(out *OutBuf, str string, namesz uint32, descsz uint32, tag uint32) *ElfShdr {
   715  	sh := elfshname(str)
   716  
   717  	// Write Elf_Note header.
   718  	out.SeekSet(int64(sh.Off))
   719  
   720  	out.Write32(namesz)
   721  	out.Write32(descsz)
   722  	out.Write32(tag)
   723  
   724  	return sh
   725  }
   726  
   727  // NetBSD Signature (as per sys/exec_elf.h)
   728  const (
   729  	ELF_NOTE_NETBSD_NAMESZ  = 7
   730  	ELF_NOTE_NETBSD_DESCSZ  = 4
   731  	ELF_NOTE_NETBSD_TAG     = 1
   732  	ELF_NOTE_NETBSD_VERSION = 700000000 // NetBSD 7.0
   733  )
   734  
   735  var ELF_NOTE_NETBSD_NAME = []byte("NetBSD\x00")
   736  
   737  func elfnetbsdsig(sh *ElfShdr, startva uint64, resoff uint64) int {
   738  	n := int(Rnd(ELF_NOTE_NETBSD_NAMESZ, 4) + Rnd(ELF_NOTE_NETBSD_DESCSZ, 4))
   739  	return elfnote(sh, startva, resoff, n)
   740  }
   741  
   742  func elfwritenetbsdsig(out *OutBuf) int {
   743  	// Write Elf_Note header.
   744  	sh := elfwritenotehdr(out, ".note.netbsd.ident", ELF_NOTE_NETBSD_NAMESZ, ELF_NOTE_NETBSD_DESCSZ, ELF_NOTE_NETBSD_TAG)
   745  
   746  	if sh == nil {
   747  		return 0
   748  	}
   749  
   750  	// Followed by NetBSD string and version.
   751  	out.Write(ELF_NOTE_NETBSD_NAME)
   752  	out.Write8(0)
   753  	out.Write32(ELF_NOTE_NETBSD_VERSION)
   754  
   755  	return int(sh.Size)
   756  }
   757  
   758  // The race detector can't handle ASLR (address space layout randomization).
   759  // ASLR is on by default for NetBSD, so we turn the ASLR off explicitly
   760  // using a magic elf Note when building race binaries.
   761  
   762  func elfnetbsdpax(sh *ElfShdr, startva uint64, resoff uint64) int {
   763  	n := int(Rnd(4, 4) + Rnd(4, 4))
   764  	return elfnote(sh, startva, resoff, n)
   765  }
   766  
   767  func elfwritenetbsdpax(out *OutBuf) int {
   768  	sh := elfwritenotehdr(out, ".note.netbsd.pax", 4 /* length of PaX\x00 */, 4 /* length of flags */, 0x03 /* PaX type */)
   769  	if sh == nil {
   770  		return 0
   771  	}
   772  	out.Write([]byte("PaX\x00"))
   773  	out.Write32(0x20) // 0x20 = Force disable ASLR
   774  	return int(sh.Size)
   775  }
   776  
   777  // OpenBSD Signature
   778  const (
   779  	ELF_NOTE_OPENBSD_NAMESZ  = 8
   780  	ELF_NOTE_OPENBSD_DESCSZ  = 4
   781  	ELF_NOTE_OPENBSD_TAG     = 1
   782  	ELF_NOTE_OPENBSD_VERSION = 0
   783  )
   784  
   785  var ELF_NOTE_OPENBSD_NAME = []byte("OpenBSD\x00")
   786  
   787  func elfopenbsdsig(sh *ElfShdr, startva uint64, resoff uint64) int {
   788  	n := ELF_NOTE_OPENBSD_NAMESZ + ELF_NOTE_OPENBSD_DESCSZ
   789  	return elfnote(sh, startva, resoff, n)
   790  }
   791  
   792  func elfwriteopenbsdsig(out *OutBuf) int {
   793  	// Write Elf_Note header.
   794  	sh := elfwritenotehdr(out, ".note.openbsd.ident", ELF_NOTE_OPENBSD_NAMESZ, ELF_NOTE_OPENBSD_DESCSZ, ELF_NOTE_OPENBSD_TAG)
   795  
   796  	if sh == nil {
   797  		return 0
   798  	}
   799  
   800  	// Followed by OpenBSD string and version.
   801  	out.Write(ELF_NOTE_OPENBSD_NAME)
   802  
   803  	out.Write32(ELF_NOTE_OPENBSD_VERSION)
   804  
   805  	return int(sh.Size)
   806  }
   807  
   808  // FreeBSD Signature (as per sys/elf_common.h)
   809  const (
   810  	ELF_NOTE_FREEBSD_NAMESZ            = 8
   811  	ELF_NOTE_FREEBSD_DESCSZ            = 4
   812  	ELF_NOTE_FREEBSD_ABI_TAG           = 1
   813  	ELF_NOTE_FREEBSD_NOINIT_TAG        = 2
   814  	ELF_NOTE_FREEBSD_FEATURE_CTL_TAG   = 4
   815  	ELF_NOTE_FREEBSD_VERSION           = 1203000 // 12.3-RELEASE
   816  	ELF_NOTE_FREEBSD_FCTL_ASLR_DISABLE = 0x1
   817  )
   818  
   819  const ELF_NOTE_FREEBSD_NAME = "FreeBSD\x00"
   820  
   821  func elffreebsdsig(sh *ElfShdr, startva uint64, resoff uint64) int {
   822  	n := ELF_NOTE_FREEBSD_NAMESZ + ELF_NOTE_FREEBSD_DESCSZ
   823  	// FreeBSD signature section contains 3 equally sized notes
   824  	return elfnote(sh, startva, resoff, n, n, n)
   825  }
   826  
   827  // elfwritefreebsdsig writes FreeBSD .note section.
   828  //
   829  // See https://www.netbsd.org/docs/kernel/elf-notes.html for the description of
   830  // a Note element format and
   831  // https://github.com/freebsd/freebsd-src/blob/main/sys/sys/elf_common.h#L790
   832  // for the FreeBSD-specific values.
   833  func elfwritefreebsdsig(out *OutBuf) int {
   834  	sh := elfshname(".note.tag")
   835  	if sh == nil {
   836  		return 0
   837  	}
   838  	out.SeekSet(int64(sh.Off))
   839  
   840  	// NT_FREEBSD_ABI_TAG
   841  	out.Write32(ELF_NOTE_FREEBSD_NAMESZ)
   842  	out.Write32(ELF_NOTE_FREEBSD_DESCSZ)
   843  	out.Write32(ELF_NOTE_FREEBSD_ABI_TAG)
   844  	out.WriteString(ELF_NOTE_FREEBSD_NAME)
   845  	out.Write32(ELF_NOTE_FREEBSD_VERSION)
   846  
   847  	// NT_FREEBSD_NOINIT_TAG
   848  	out.Write32(ELF_NOTE_FREEBSD_NAMESZ)
   849  	out.Write32(ELF_NOTE_FREEBSD_DESCSZ)
   850  	out.Write32(ELF_NOTE_FREEBSD_NOINIT_TAG)
   851  	out.WriteString(ELF_NOTE_FREEBSD_NAME)
   852  	out.Write32(0)
   853  
   854  	// NT_FREEBSD_FEATURE_CTL
   855  	out.Write32(ELF_NOTE_FREEBSD_NAMESZ)
   856  	out.Write32(ELF_NOTE_FREEBSD_DESCSZ)
   857  	out.Write32(ELF_NOTE_FREEBSD_FEATURE_CTL_TAG)
   858  	out.WriteString(ELF_NOTE_FREEBSD_NAME)
   859  	if *flagRace {
   860  		// The race detector can't handle ASLR, turn the ASLR off when compiling with -race.
   861  		out.Write32(ELF_NOTE_FREEBSD_FCTL_ASLR_DISABLE)
   862  	} else {
   863  		out.Write32(0)
   864  	}
   865  
   866  	return int(sh.Size)
   867  }
   868  
   869  func addbuildinfo(ctxt *Link) {
   870  	val := *flagHostBuildid
   871  	if val == "" || val == "none" {
   872  		return
   873  	}
   874  	if val == "gobuildid" {
   875  		buildID := *flagBuildid
   876  		if buildID == "" {
   877  			Exitf("-B gobuildid requires a Go build ID supplied via -buildid")
   878  		}
   879  
   880  		if ctxt.IsDarwin() {
   881  			buildinfo = uuidFromHash(hash.Sum32([]byte(buildID)))
   882  			return
   883  		}
   884  
   885  		hashedBuildID := hash.Sum32([]byte(buildID))
   886  		buildinfo = hashedBuildID[:20]
   887  
   888  		return
   889  	}
   890  
   891  	if !strings.HasPrefix(val, "0x") {
   892  		Exitf("-B argument must start with 0x: %s", val)
   893  	}
   894  	ov := val
   895  	val = val[2:]
   896  
   897  	maxLen := 32
   898  	if ctxt.IsDarwin() {
   899  		maxLen = 16
   900  	}
   901  	if hex.DecodedLen(len(val)) > maxLen {
   902  		Exitf("-B option too long (max %d digits): %s", maxLen, ov)
   903  	}
   904  
   905  	b, err := hex.DecodeString(val)
   906  	if err != nil {
   907  		if err == hex.ErrLength {
   908  			Exitf("-B argument must have even number of digits: %s", ov)
   909  		}
   910  		if inv, ok := err.(hex.InvalidByteError); ok {
   911  			Exitf("-B argument contains invalid hex digit %c: %s", byte(inv), ov)
   912  		}
   913  		Exitf("-B argument contains invalid hex: %s", ov)
   914  	}
   915  
   916  	buildinfo = b
   917  }
   918  
   919  // Build info note
   920  const (
   921  	ELF_NOTE_BUILDINFO_NAMESZ = 4
   922  	ELF_NOTE_BUILDINFO_TAG    = 3
   923  )
   924  
   925  var ELF_NOTE_BUILDINFO_NAME = []byte("GNU\x00")
   926  
   927  func elfbuildinfo(sh *ElfShdr, startva uint64, resoff uint64) int {
   928  	n := int(ELF_NOTE_BUILDINFO_NAMESZ + Rnd(int64(len(buildinfo)), 4))
   929  	return elfnote(sh, startva, resoff, n)
   930  }
   931  
   932  func elfgobuildid(sh *ElfShdr, startva uint64, resoff uint64) int {
   933  	n := len(ELF_NOTE_GO_NAME) + int(Rnd(int64(len(*flagBuildid)), 4))
   934  	return elfnote(sh, startva, resoff, n)
   935  }
   936  
   937  func elfwritebuildinfo(out *OutBuf) int {
   938  	sh := elfwritenotehdr(out, ".note.gnu.build-id", ELF_NOTE_BUILDINFO_NAMESZ, uint32(len(buildinfo)), ELF_NOTE_BUILDINFO_TAG)
   939  	if sh == nil {
   940  		return 0
   941  	}
   942  
   943  	out.Write(ELF_NOTE_BUILDINFO_NAME)
   944  	out.Write(buildinfo)
   945  	var zero = make([]byte, 4)
   946  	out.Write(zero[:int(Rnd(int64(len(buildinfo)), 4)-int64(len(buildinfo)))])
   947  
   948  	return int(sh.Size)
   949  }
   950  
   951  func elfwritegobuildid(out *OutBuf) int {
   952  	sh := elfwritenotehdr(out, ".note.go.buildid", uint32(len(ELF_NOTE_GO_NAME)), uint32(len(*flagBuildid)), ELF_NOTE_GOBUILDID_TAG)
   953  	if sh == nil {
   954  		return 0
   955  	}
   956  
   957  	out.Write(ELF_NOTE_GO_NAME)
   958  	out.Write([]byte(*flagBuildid))
   959  	var zero = make([]byte, 4)
   960  	out.Write(zero[:int(Rnd(int64(len(*flagBuildid)), 4)-int64(len(*flagBuildid)))])
   961  
   962  	return int(sh.Size)
   963  }
   964  
   965  // Go specific notes
   966  const (
   967  	ELF_NOTE_GOPKGLIST_TAG = 1
   968  	ELF_NOTE_GOABIHASH_TAG = 2
   969  	ELF_NOTE_GODEPS_TAG    = 3
   970  	ELF_NOTE_GOBUILDID_TAG = 4
   971  )
   972  
   973  var ELF_NOTE_GO_NAME = []byte("Go\x00\x00")
   974  
   975  var elfverneed int
   976  
   977  type Elfaux struct {
   978  	next *Elfaux
   979  	num  int
   980  	vers string
   981  }
   982  
   983  type Elflib struct {
   984  	next *Elflib
   985  	aux  *Elfaux
   986  	file string
   987  }
   988  
   989  func addelflib(list **Elflib, file string, vers string) *Elfaux {
   990  	var lib *Elflib
   991  
   992  	for lib = *list; lib != nil; lib = lib.next {
   993  		if lib.file == file {
   994  			goto havelib
   995  		}
   996  	}
   997  	lib = new(Elflib)
   998  	lib.next = *list
   999  	lib.file = file
  1000  	*list = lib
  1001  
  1002  havelib:
  1003  	for aux := lib.aux; aux != nil; aux = aux.next {
  1004  		if aux.vers == vers {
  1005  			return aux
  1006  		}
  1007  	}
  1008  	aux := new(Elfaux)
  1009  	aux.next = lib.aux
  1010  	aux.vers = vers
  1011  	lib.aux = aux
  1012  
  1013  	return aux
  1014  }
  1015  
  1016  func elfdynhash(ctxt *Link) {
  1017  	if !ctxt.IsELF {
  1018  		return
  1019  	}
  1020  
  1021  	nsym := Nelfsym
  1022  	ldr := ctxt.loader
  1023  	s := ldr.CreateSymForUpdate(".hash", 0)
  1024  	s.SetType(sym.SELFROSECT)
  1025  
  1026  	i := nsym
  1027  	nbucket := 1
  1028  	for i > 0 {
  1029  		nbucket++
  1030  		i >>= 1
  1031  	}
  1032  
  1033  	var needlib *Elflib
  1034  	need := make([]*Elfaux, nsym)
  1035  	chain := make([]uint32, nsym)
  1036  	buckets := make([]uint32, nbucket)
  1037  
  1038  	for _, sy := range ldr.DynidSyms() {
  1039  
  1040  		dynid := ldr.SymDynid(sy)
  1041  		if ldr.SymDynimpvers(sy) != "" {
  1042  			need[dynid] = addelflib(&needlib, ldr.SymDynimplib(sy), ldr.SymDynimpvers(sy))
  1043  		}
  1044  
  1045  		name := ldr.SymExtname(sy)
  1046  		hc := elfhash(name)
  1047  
  1048  		b := hc % uint32(nbucket)
  1049  		chain[dynid] = buckets[b]
  1050  		buckets[b] = uint32(dynid)
  1051  	}
  1052  
  1053  	// s390x (ELF64) hash table entries are 8 bytes
  1054  	if ctxt.Arch.Family == sys.S390X {
  1055  		s.AddUint64(ctxt.Arch, uint64(nbucket))
  1056  		s.AddUint64(ctxt.Arch, uint64(nsym))
  1057  		for i := 0; i < nbucket; i++ {
  1058  			s.AddUint64(ctxt.Arch, uint64(buckets[i]))
  1059  		}
  1060  		for i := 0; i < nsym; i++ {
  1061  			s.AddUint64(ctxt.Arch, uint64(chain[i]))
  1062  		}
  1063  	} else {
  1064  		s.AddUint32(ctxt.Arch, uint32(nbucket))
  1065  		s.AddUint32(ctxt.Arch, uint32(nsym))
  1066  		for i := 0; i < nbucket; i++ {
  1067  			s.AddUint32(ctxt.Arch, buckets[i])
  1068  		}
  1069  		for i := 0; i < nsym; i++ {
  1070  			s.AddUint32(ctxt.Arch, chain[i])
  1071  		}
  1072  	}
  1073  
  1074  	dynstr := ldr.CreateSymForUpdate(".dynstr", 0)
  1075  
  1076  	// version symbols
  1077  	gnuVersionR := ldr.CreateSymForUpdate(".gnu.version_r", 0)
  1078  	s = gnuVersionR
  1079  	i = 2
  1080  	nfile := 0
  1081  	for l := needlib; l != nil; l = l.next {
  1082  		nfile++
  1083  
  1084  		// header
  1085  		s.AddUint16(ctxt.Arch, 1) // table version
  1086  		j := 0
  1087  		for x := l.aux; x != nil; x = x.next {
  1088  			j++
  1089  		}
  1090  		s.AddUint16(ctxt.Arch, uint16(j))                        // aux count
  1091  		s.AddUint32(ctxt.Arch, uint32(dynstr.Addstring(l.file))) // file string offset
  1092  		s.AddUint32(ctxt.Arch, 16)                               // offset from header to first aux
  1093  		if l.next != nil {
  1094  			s.AddUint32(ctxt.Arch, 16+uint32(j)*16) // offset from this header to next
  1095  		} else {
  1096  			s.AddUint32(ctxt.Arch, 0)
  1097  		}
  1098  
  1099  		for x := l.aux; x != nil; x = x.next {
  1100  			x.num = i
  1101  			i++
  1102  
  1103  			// aux struct
  1104  			s.AddUint32(ctxt.Arch, elfhash(x.vers))                  // hash
  1105  			s.AddUint16(ctxt.Arch, 0)                                // flags
  1106  			s.AddUint16(ctxt.Arch, uint16(x.num))                    // other - index we refer to this by
  1107  			s.AddUint32(ctxt.Arch, uint32(dynstr.Addstring(x.vers))) // version string offset
  1108  			if x.next != nil {
  1109  				s.AddUint32(ctxt.Arch, 16) // offset from this aux to next
  1110  			} else {
  1111  				s.AddUint32(ctxt.Arch, 0)
  1112  			}
  1113  		}
  1114  	}
  1115  
  1116  	// version references
  1117  	gnuVersion := ldr.CreateSymForUpdate(".gnu.version", 0)
  1118  	s = gnuVersion
  1119  
  1120  	for i := 0; i < nsym; i++ {
  1121  		if i == 0 {
  1122  			s.AddUint16(ctxt.Arch, 0) // first entry - no symbol
  1123  		} else if need[i] == nil {
  1124  			s.AddUint16(ctxt.Arch, 1) // global
  1125  		} else {
  1126  			s.AddUint16(ctxt.Arch, uint16(need[i].num))
  1127  		}
  1128  	}
  1129  
  1130  	s = ldr.CreateSymForUpdate(".dynamic", 0)
  1131  
  1132  	var dtFlags1 elf.DynFlag1
  1133  	if *flagBindNow {
  1134  		dtFlags1 |= elf.DF_1_NOW
  1135  		Elfwritedynent(ctxt.Arch, s, elf.DT_FLAGS, uint64(elf.DF_BIND_NOW))
  1136  	}
  1137  	if ctxt.BuildMode == BuildModePIE {
  1138  		dtFlags1 |= elf.DF_1_PIE
  1139  	}
  1140  	Elfwritedynent(ctxt.Arch, s, elf.DT_FLAGS_1, uint64(dtFlags1))
  1141  
  1142  	elfverneed = nfile
  1143  	if elfverneed != 0 {
  1144  		elfWriteDynEntSym(ctxt, s, elf.DT_VERNEED, gnuVersionR.Sym())
  1145  		Elfwritedynent(ctxt.Arch, s, elf.DT_VERNEEDNUM, uint64(nfile))
  1146  		elfWriteDynEntSym(ctxt, s, elf.DT_VERSYM, gnuVersion.Sym())
  1147  	}
  1148  
  1149  	sy := ldr.CreateSymForUpdate(elfRelType+".plt", 0)
  1150  	if sy.Size() > 0 {
  1151  		if elfRelType == ".rela" {
  1152  			Elfwritedynent(ctxt.Arch, s, elf.DT_PLTREL, uint64(elf.DT_RELA))
  1153  		} else {
  1154  			Elfwritedynent(ctxt.Arch, s, elf.DT_PLTREL, uint64(elf.DT_REL))
  1155  		}
  1156  		elfwritedynentsymsize(ctxt, s, elf.DT_PLTRELSZ, sy.Sym())
  1157  		elfWriteDynEntSym(ctxt, s, elf.DT_JMPREL, sy.Sym())
  1158  	}
  1159  
  1160  	Elfwritedynent(ctxt.Arch, s, elf.DT_NULL, 0)
  1161  }
  1162  
  1163  func elfphload(seg *sym.Segment) *ElfPhdr {
  1164  	ph := newElfPhdr()
  1165  	ph.Type = elf.PT_LOAD
  1166  	if seg.Rwx&4 != 0 {
  1167  		ph.Flags |= elf.PF_R
  1168  	}
  1169  	if seg.Rwx&2 != 0 {
  1170  		ph.Flags |= elf.PF_W
  1171  	}
  1172  	if seg.Rwx&1 != 0 {
  1173  		ph.Flags |= elf.PF_X
  1174  	}
  1175  	ph.Vaddr = seg.Vaddr
  1176  	ph.Paddr = seg.Vaddr
  1177  	ph.Memsz = seg.Length
  1178  	ph.Off = seg.Fileoff
  1179  	ph.Filesz = seg.Filelen
  1180  	ph.Align = uint64(*FlagRound)
  1181  
  1182  	return ph
  1183  }
  1184  
  1185  func elfphrelro(seg *sym.Segment) {
  1186  	ph := newElfPhdr()
  1187  	ph.Type = elf.PT_GNU_RELRO
  1188  	ph.Flags = elf.PF_R
  1189  	ph.Vaddr = seg.Vaddr
  1190  	ph.Paddr = seg.Vaddr
  1191  	ph.Memsz = seg.Length
  1192  	ph.Off = seg.Fileoff
  1193  	ph.Filesz = seg.Filelen
  1194  	ph.Align = uint64(*FlagRound)
  1195  }
  1196  
  1197  // elfshname finds or creates a section given its name.
  1198  func elfshname(name string) *ElfShdr {
  1199  	for _, sh := range shdr {
  1200  		if sh.nameString == name {
  1201  			return sh
  1202  		}
  1203  	}
  1204  	return newElfShdr(name)
  1205  }
  1206  
  1207  // elfshnamedup creates a new section with a given name.
  1208  // If there is an existing section with this name, it creates a duplicate.
  1209  func elfshnamedup(name string) *ElfShdr {
  1210  	return newElfShdr(name)
  1211  }
  1212  
  1213  func elfshalloc(sect *sym.Section) *ElfShdr {
  1214  	sh := elfshname(sect.Name)
  1215  	sect.Elfsect = sh
  1216  	return sh
  1217  }
  1218  
  1219  func elfshbits(linkmode LinkMode, sect *sym.Section) *ElfShdr {
  1220  	var sh *ElfShdr
  1221  
  1222  	if sect.Name == ".text" {
  1223  		if sect.Elfsect == nil {
  1224  			sect.Elfsect = elfshnamedup(sect.Name)
  1225  		}
  1226  		sh = sect.Elfsect.(*ElfShdr)
  1227  	} else {
  1228  		sh = elfshalloc(sect)
  1229  	}
  1230  
  1231  	// If this section has already been set up as a note, we assume type_ and
  1232  	// flags are already correct, but the other fields still need filling in.
  1233  	if sh.Type == uint32(elf.SHT_NOTE) {
  1234  		if linkmode != LinkExternal {
  1235  			// TODO(mwhudson): the approach here will work OK when
  1236  			// linking internally for notes that we want to be included
  1237  			// in a loadable segment (e.g. the abihash note) but not for
  1238  			// notes that we do not want to be mapped (e.g. the package
  1239  			// list note). The real fix is probably to define new values
  1240  			// for Symbol.Type corresponding to mapped and unmapped notes
  1241  			// and handle them in dodata().
  1242  			Errorf("sh.Type == SHT_NOTE in elfshbits when linking internally")
  1243  		}
  1244  		sh.Addralign = uint64(sect.Align)
  1245  		sh.Size = sect.Length
  1246  		sh.Off = sect.Seg.Fileoff + sect.Vaddr - sect.Seg.Vaddr
  1247  		return sh
  1248  	}
  1249  	if sh.Type > 0 {
  1250  		return sh
  1251  	}
  1252  
  1253  	if sect.Vaddr < sect.Seg.Vaddr+sect.Seg.Filelen {
  1254  		switch sect.Name {
  1255  		case ".init_array":
  1256  			sh.Type = uint32(elf.SHT_INIT_ARRAY)
  1257  		default:
  1258  			sh.Type = uint32(elf.SHT_PROGBITS)
  1259  		}
  1260  	} else {
  1261  		sh.Type = uint32(elf.SHT_NOBITS)
  1262  	}
  1263  	sh.Flags = uint64(elf.SHF_ALLOC)
  1264  	if sect.Rwx&1 != 0 {
  1265  		sh.Flags |= uint64(elf.SHF_EXECINSTR)
  1266  	}
  1267  	if sect.Rwx&2 != 0 {
  1268  		sh.Flags |= uint64(elf.SHF_WRITE)
  1269  	}
  1270  	if sect.Name == ".tbss" {
  1271  		sh.Flags |= uint64(elf.SHF_TLS)
  1272  		sh.Type = uint32(elf.SHT_NOBITS)
  1273  	}
  1274  	if linkmode != LinkExternal {
  1275  		sh.Addr = sect.Vaddr
  1276  	}
  1277  
  1278  	if strings.HasPrefix(sect.Name, ".debug") || strings.HasPrefix(sect.Name, ".zdebug") {
  1279  		sh.Flags = 0
  1280  		sh.Addr = 0
  1281  		if sect.Compressed {
  1282  			sh.Flags |= uint64(elf.SHF_COMPRESSED)
  1283  		}
  1284  	}
  1285  
  1286  	sh.Addralign = uint64(sect.Align)
  1287  	sh.Size = sect.Length
  1288  	if sect.Name != ".tbss" {
  1289  		sh.Off = sect.Seg.Fileoff + sect.Vaddr - sect.Seg.Vaddr
  1290  	}
  1291  
  1292  	return sh
  1293  }
  1294  
  1295  func elfshreloc(arch *sys.Arch, sect *sym.Section) *ElfShdr {
  1296  	// If main section is SHT_NOBITS, nothing to relocate.
  1297  	// Also nothing to relocate in .shstrtab or notes or .gopclntab.
  1298  	if sect.Vaddr >= sect.Seg.Vaddr+sect.Seg.Filelen {
  1299  		return nil
  1300  	}
  1301  	switch sect.Name {
  1302  	case ".shstrtab", ".tbss", ".gopclntab":
  1303  		return nil
  1304  	}
  1305  	if sect.Elfsect.(*ElfShdr).Type == uint32(elf.SHT_NOTE) {
  1306  		return nil
  1307  	}
  1308  
  1309  	typ := elf.SHT_REL
  1310  	if elfRelType == ".rela" {
  1311  		typ = elf.SHT_RELA
  1312  	}
  1313  
  1314  	sh := elfshname(elfRelType + sect.Name)
  1315  	// There could be multiple text sections but each needs
  1316  	// its own .rela.text.
  1317  
  1318  	if sect.Name == ".text" {
  1319  		if sh.info != nil && sh.info != sect.Elfsect.(*ElfShdr) {
  1320  			sh = elfshnamedup(elfRelType + sect.Name)
  1321  		}
  1322  	}
  1323  
  1324  	sh.Type = uint32(typ)
  1325  	sh.Entsize = uint64(arch.RegSize) * 2
  1326  	if typ == elf.SHT_RELA {
  1327  		sh.Entsize += uint64(arch.RegSize)
  1328  	}
  1329  	sh.link = elfshname(".symtab")
  1330  	sh.info = sect.Elfsect.(*ElfShdr)
  1331  	sh.relocSect = sect
  1332  	sh.Addralign = uint64(arch.RegSize)
  1333  	return sh
  1334  }
  1335  
  1336  func elfrelocsect(ctxt *Link, out *OutBuf, sect *sym.Section, syms []loader.Sym) {
  1337  	// If main section is SHT_NOBITS, nothing to relocate.
  1338  	// Also nothing to relocate in .shstrtab.
  1339  	if sect.Vaddr >= sect.Seg.Vaddr+sect.Seg.Filelen {
  1340  		return
  1341  	}
  1342  	if sect.Name == ".shstrtab" {
  1343  		return
  1344  	}
  1345  
  1346  	ldr := ctxt.loader
  1347  	for i, s := range syms {
  1348  		if !ldr.AttrReachable(s) {
  1349  			panic("should never happen")
  1350  		}
  1351  		if uint64(ldr.SymValue(s)) >= sect.Vaddr {
  1352  			syms = syms[i:]
  1353  			break
  1354  		}
  1355  	}
  1356  
  1357  	eaddr := sect.Vaddr + sect.Length
  1358  	for _, s := range syms {
  1359  		if !ldr.AttrReachable(s) {
  1360  			continue
  1361  		}
  1362  		if ldr.SymValue(s) >= int64(eaddr) {
  1363  			break
  1364  		}
  1365  
  1366  		// Compute external relocations on the go, and pass to
  1367  		// ELF.Reloc1 to stream out.
  1368  		relocs := ldr.Relocs(s)
  1369  		for ri := 0; ri < relocs.Count(); ri++ {
  1370  			r := relocs.At(ri)
  1371  			rr, ok := extreloc(ctxt, ldr, s, r)
  1372  			if !ok {
  1373  				continue
  1374  			}
  1375  			if rr.Xsym == 0 {
  1376  				ldr.Errorf(s, "missing xsym in relocation")
  1377  				continue
  1378  			}
  1379  			esr := ElfSymForReloc(ctxt, rr.Xsym)
  1380  			if esr == 0 {
  1381  				ldr.Errorf(s, "reloc %d (%s) to non-elf symbol %s (outer=%s) %d (%s)", r.Type(), sym.RelocName(ctxt.Arch, r.Type()), ldr.SymName(r.Sym()), ldr.SymName(rr.Xsym), ldr.SymType(r.Sym()), ldr.SymType(r.Sym()).String())
  1382  			}
  1383  			if !ldr.AttrReachable(rr.Xsym) {
  1384  				ldr.Errorf(s, "unreachable reloc %d (%s) target %v", r.Type(), sym.RelocName(ctxt.Arch, r.Type()), ldr.SymName(rr.Xsym))
  1385  			}
  1386  			if !thearch.ELF.Reloc1(ctxt, out, ldr, s, rr, ri, int64(uint64(ldr.SymValue(s)+int64(r.Off()))-sect.Vaddr)) {
  1387  				ldr.Errorf(s, "unsupported obj reloc %d (%s)/%d to %s", r.Type(), sym.RelocName(ctxt.Arch, r.Type()), r.Siz(), ldr.SymName(r.Sym()))
  1388  			}
  1389  		}
  1390  	}
  1391  
  1392  	// sanity check
  1393  	if uint64(out.Offset()) != sect.Reloff+sect.Rellen {
  1394  		panic(fmt.Sprintf("elfrelocsect: size mismatch %d != %d + %d", out.Offset(), sect.Reloff, sect.Rellen))
  1395  	}
  1396  }
  1397  
  1398  func elfEmitReloc(ctxt *Link) {
  1399  	for ctxt.Out.Offset()&7 != 0 {
  1400  		ctxt.Out.Write8(0)
  1401  	}
  1402  
  1403  	sizeExtRelocs(ctxt, thearch.ELF.RelocSize)
  1404  	relocSect, wg := relocSectFn(ctxt, elfrelocsect)
  1405  
  1406  	for _, sect := range Segtext.Sections {
  1407  		if sect.Name == ".text" {
  1408  			relocSect(ctxt, sect, ctxt.Textp)
  1409  		} else {
  1410  			relocSect(ctxt, sect, ctxt.datap)
  1411  		}
  1412  	}
  1413  
  1414  	for _, sect := range Segrodata.Sections {
  1415  		relocSect(ctxt, sect, ctxt.datap)
  1416  	}
  1417  	for _, sect := range Segrelrodata.Sections {
  1418  		relocSect(ctxt, sect, ctxt.datap)
  1419  	}
  1420  	for _, sect := range Segdata.Sections {
  1421  		relocSect(ctxt, sect, ctxt.datap)
  1422  	}
  1423  	for i := 0; i < len(Segdwarf.Sections); i++ {
  1424  		sect := Segdwarf.Sections[i]
  1425  		si := dwarfp[i]
  1426  		if si.secSym() != sect.Sym ||
  1427  			ctxt.loader.SymSect(si.secSym()) != sect {
  1428  			panic("inconsistency between dwarfp and Segdwarf")
  1429  		}
  1430  		relocSect(ctxt, sect, si.syms)
  1431  	}
  1432  	wg.Wait()
  1433  }
  1434  
  1435  func addgonote(ctxt *Link, sectionName string, tag uint32, desc []byte) {
  1436  	ldr := ctxt.loader
  1437  	s := ldr.CreateSymForUpdate(sectionName, 0)
  1438  	s.SetType(sym.SELFROSECT)
  1439  	// namesz
  1440  	s.AddUint32(ctxt.Arch, uint32(len(ELF_NOTE_GO_NAME)))
  1441  	// descsz
  1442  	s.AddUint32(ctxt.Arch, uint32(len(desc)))
  1443  	// tag
  1444  	s.AddUint32(ctxt.Arch, tag)
  1445  	// name + padding
  1446  	s.AddBytes(ELF_NOTE_GO_NAME)
  1447  	for len(s.Data())%4 != 0 {
  1448  		s.AddUint8(0)
  1449  	}
  1450  	// desc + padding
  1451  	s.AddBytes(desc)
  1452  	for len(s.Data())%4 != 0 {
  1453  		s.AddUint8(0)
  1454  	}
  1455  	s.SetSize(int64(len(s.Data())))
  1456  	s.SetAlign(4)
  1457  }
  1458  
  1459  func (ctxt *Link) doelf() {
  1460  	ldr := ctxt.loader
  1461  
  1462  	if ctxt.IsExternal() {
  1463  		*FlagD = true
  1464  	}
  1465  
  1466  	if !*FlagD { // -d suppresses dynamic loader format
  1467  		// dynamic symbol table - first entry all zeros
  1468  		dynsym := ldr.CreateSymForUpdate(".dynsym", 0)
  1469  
  1470  		dynsym.SetType(sym.SELFROSECT)
  1471  		if elf64 {
  1472  			dynsym.SetSize(dynsym.Size() + ELF64SYMSIZE)
  1473  		} else {
  1474  			dynsym.SetSize(dynsym.Size() + ELF32SYMSIZE)
  1475  		}
  1476  
  1477  		// dynamic string table
  1478  		dynstr := ldr.CreateSymForUpdate(".dynstr", 0)
  1479  
  1480  		dynstr.SetType(sym.SELFROSECT)
  1481  		if dynstr.Size() == 0 {
  1482  			dynstr.Addstring("")
  1483  		}
  1484  
  1485  		// relocation table
  1486  		s := ldr.CreateSymForUpdate(elfRelType, 0)
  1487  		s.SetType(sym.SELFROSECT)
  1488  
  1489  		// global offset table
  1490  		got := ldr.CreateSymForUpdate(".got", 0)
  1491  		if ctxt.UseRelro() {
  1492  			got.SetType(sym.SELFRELROSECT)
  1493  		} else {
  1494  			got.SetType(sym.SELFGOT) // writable
  1495  		}
  1496  
  1497  		// ppc64 glink resolver
  1498  		if ctxt.IsPPC64() {
  1499  			s := ldr.CreateSymForUpdate(".glink", 0)
  1500  			s.SetType(sym.SELFRXSECT)
  1501  		}
  1502  
  1503  		// hash
  1504  		hash := ldr.CreateSymForUpdate(".hash", 0)
  1505  		hash.SetType(sym.SELFROSECT)
  1506  
  1507  		gotplt := ldr.CreateSymForUpdate(".got.plt", 0)
  1508  		if ctxt.UseRelro() && *flagBindNow {
  1509  			gotplt.SetType(sym.SELFRELROSECT)
  1510  		} else {
  1511  			gotplt.SetType(sym.SELFSECT) // writable
  1512  		}
  1513  
  1514  		plt := ldr.CreateSymForUpdate(".plt", 0)
  1515  		if ctxt.IsPPC64() {
  1516  			// In the ppc64 ABI, .plt is a data section
  1517  			// written by the dynamic linker.
  1518  			plt.SetType(sym.SELFSECT)
  1519  		} else {
  1520  			plt.SetType(sym.SELFRXSECT)
  1521  		}
  1522  
  1523  		s = ldr.CreateSymForUpdate(elfRelType+".plt", 0)
  1524  		s.SetType(sym.SELFROSECT)
  1525  
  1526  		s = ldr.CreateSymForUpdate(".gnu.version", 0)
  1527  		s.SetType(sym.SELFROSECT)
  1528  
  1529  		s = ldr.CreateSymForUpdate(".gnu.version_r", 0)
  1530  		s.SetType(sym.SELFROSECT)
  1531  
  1532  		// define dynamic elf table
  1533  		dynamic := ldr.CreateSymForUpdate(".dynamic", 0)
  1534  		switch {
  1535  		case thearch.ELF.DynamicReadOnly:
  1536  			dynamic.SetType(sym.SELFROSECT)
  1537  		case ctxt.UseRelro():
  1538  			dynamic.SetType(sym.SELFRELROSECT)
  1539  		default:
  1540  			dynamic.SetType(sym.SELFSECT)
  1541  		}
  1542  
  1543  		thearch.ELF.SetupPLT(ctxt, ctxt.loader, plt, gotplt, dynamic.Sym())
  1544  
  1545  		// .dynamic table
  1546  		elfWriteDynEntSym(ctxt, dynamic, elf.DT_HASH, hash.Sym())
  1547  
  1548  		elfWriteDynEntSym(ctxt, dynamic, elf.DT_SYMTAB, dynsym.Sym())
  1549  		if elf64 {
  1550  			Elfwritedynent(ctxt.Arch, dynamic, elf.DT_SYMENT, ELF64SYMSIZE)
  1551  		} else {
  1552  			Elfwritedynent(ctxt.Arch, dynamic, elf.DT_SYMENT, ELF32SYMSIZE)
  1553  		}
  1554  		elfWriteDynEntSym(ctxt, dynamic, elf.DT_STRTAB, dynstr.Sym())
  1555  		elfwritedynentsymsize(ctxt, dynamic, elf.DT_STRSZ, dynstr.Sym())
  1556  		if elfRelType == ".rela" {
  1557  			rela := ldr.LookupOrCreateSym(".rela", 0)
  1558  			elfWriteDynEntSym(ctxt, dynamic, elf.DT_RELA, rela)
  1559  			elfwritedynentsymsize(ctxt, dynamic, elf.DT_RELASZ, rela)
  1560  			Elfwritedynent(ctxt.Arch, dynamic, elf.DT_RELAENT, ELF64RELASIZE)
  1561  		} else {
  1562  			rel := ldr.LookupOrCreateSym(".rel", 0)
  1563  			elfWriteDynEntSym(ctxt, dynamic, elf.DT_REL, rel)
  1564  			elfwritedynentsymsize(ctxt, dynamic, elf.DT_RELSZ, rel)
  1565  			Elfwritedynent(ctxt.Arch, dynamic, elf.DT_RELENT, ELF32RELSIZE)
  1566  		}
  1567  
  1568  		if rpath.val != "" {
  1569  			Elfwritedynent(ctxt.Arch, dynamic, elf.DT_RUNPATH, uint64(dynstr.Addstring(rpath.val)))
  1570  		}
  1571  
  1572  		if ctxt.IsPPC64() {
  1573  			elfWriteDynEntSym(ctxt, dynamic, elf.DT_PLTGOT, plt.Sym())
  1574  		} else {
  1575  			elfWriteDynEntSym(ctxt, dynamic, elf.DT_PLTGOT, gotplt.Sym())
  1576  		}
  1577  
  1578  		if ctxt.IsPPC64() {
  1579  			Elfwritedynent(ctxt.Arch, dynamic, elf.DT_PPC64_OPT, 0)
  1580  		}
  1581  
  1582  		// Solaris dynamic linker can't handle an empty .rela.plt if
  1583  		// DT_JMPREL is emitted so we have to defer generation of elf.DT_PLTREL,
  1584  		// DT_PLTRELSZ, and elf.DT_JMPREL dynamic entries until after we know the
  1585  		// size of .rel(a).plt section.
  1586  
  1587  		Elfwritedynent(ctxt.Arch, dynamic, elf.DT_DEBUG, 0)
  1588  	}
  1589  
  1590  	if ctxt.IsShared() {
  1591  		// The go.link.abihashbytes symbol will be pointed at the appropriate
  1592  		// part of the .note.go.abihash section in data.go:func address().
  1593  		s := ldr.LookupOrCreateSym("go:link.abihashbytes", 0)
  1594  		sb := ldr.MakeSymbolUpdater(s)
  1595  		ldr.SetAttrLocal(s, true)
  1596  		sb.SetType(sym.SRODATA)
  1597  		ldr.SetAttrSpecial(s, true)
  1598  		sb.SetReachable(true)
  1599  		sb.SetSize(hash.Size32)
  1600  		slices.SortFunc(ctxt.Library, func(a, b *sym.Library) int {
  1601  			return strings.Compare(a.Pkg, b.Pkg)
  1602  		})
  1603  		h := hash.New32()
  1604  		for _, l := range ctxt.Library {
  1605  			h.Write(l.Fingerprint[:])
  1606  		}
  1607  		addgonote(ctxt, ".note.go.abihash", ELF_NOTE_GOABIHASH_TAG, h.Sum([]byte{}))
  1608  		addgonote(ctxt, ".note.go.pkg-list", ELF_NOTE_GOPKGLIST_TAG, pkglistfornote)
  1609  		var deplist []string
  1610  		for _, shlib := range ctxt.Shlibs {
  1611  			deplist = append(deplist, filepath.Base(shlib.Path))
  1612  		}
  1613  		addgonote(ctxt, ".note.go.deps", ELF_NOTE_GODEPS_TAG, []byte(strings.Join(deplist, "\n")))
  1614  	}
  1615  
  1616  	if ctxt.LinkMode == LinkExternal && *flagBuildid != "" {
  1617  		addgonote(ctxt, ".note.go.buildid", ELF_NOTE_GOBUILDID_TAG, []byte(*flagBuildid))
  1618  	}
  1619  
  1620  	//type mipsGnuAttributes struct {
  1621  	//	version uint8   // 'A'
  1622  	//	length  uint32  // 15 including itself
  1623  	//	gnu     [4]byte // "gnu\0"
  1624  	//	tag     uint8   // 1:file, 2: section, 3: symbol, 1 here
  1625  	//	taglen  uint32  // tag length, including tag, 7 here
  1626  	//	tagfp   uint8   // 4
  1627  	//	fpAbi  uint8    // see .MIPS.abiflags
  1628  	//}
  1629  	if ctxt.IsMIPS() {
  1630  		gnuattributes := ldr.CreateSymForUpdate(".gnu.attributes", 0)
  1631  		gnuattributes.SetType(sym.SELFROSECT)
  1632  		gnuattributes.SetReachable(true)
  1633  		gnuattributes.AddUint8('A')               // version 'A'
  1634  		gnuattributes.AddUint32(ctxt.Arch, 15)    // length 15 including itself
  1635  		gnuattributes.AddBytes([]byte("gnu\x00")) // "gnu\0"
  1636  		gnuattributes.AddUint8(1)                 // 1:file, 2: section, 3: symbol, 1 here
  1637  		gnuattributes.AddUint32(ctxt.Arch, 7)     // tag length, including tag, 7 here
  1638  		gnuattributes.AddUint8(4)                 // 4 for FP, 8 for MSA
  1639  		if buildcfg.GOMIPS == "softfloat" {
  1640  			gnuattributes.AddUint8(MIPS_FPABI_SOFT)
  1641  		} else {
  1642  			// Note: MIPS_FPABI_ANY is bad naming: in fact it is MIPS I style FPR usage.
  1643  			//       It is not for 'ANY'.
  1644  			// TODO: switch to FPXX after be sure that no odd-number-fpr is used.
  1645  			gnuattributes.AddUint8(MIPS_FPABI_ANY)
  1646  		}
  1647  	}
  1648  }
  1649  
  1650  // shsym fills in fields of sh where s contains the contents of the section.
  1651  func shsym(sh *ElfShdr, ldr *loader.Loader, s loader.Sym) {
  1652  	if s == 0 {
  1653  		panic("bad symbol in shsym2")
  1654  	}
  1655  	addr := ldr.SymValue(s)
  1656  	if sh.Flags&uint64(elf.SHF_ALLOC) != 0 {
  1657  		sh.Addr = uint64(addr)
  1658  	}
  1659  	sh.Off = uint64(datoff(ldr, s, addr))
  1660  	sh.Size = uint64(ldr.SymSize(s))
  1661  }
  1662  
  1663  func phsh(ph *ElfPhdr, sh *ElfShdr) {
  1664  	ph.Vaddr = sh.Addr
  1665  	ph.Paddr = ph.Vaddr
  1666  	ph.Off = sh.Off
  1667  	ph.Filesz = sh.Size
  1668  	ph.Memsz = sh.Size
  1669  	ph.Align = sh.Addralign
  1670  }
  1671  
  1672  func Asmbelfsetup() {
  1673  	// This null SHdr must appear before all others.
  1674  	elfshname("")
  1675  
  1676  	for _, sect := range Segtext.Sections {
  1677  		// There could be multiple .text sections. Instead check the Elfsect
  1678  		// field to determine if already has an ElfShdr and if not, create one.
  1679  		if sect.Name == ".text" {
  1680  			if sect.Elfsect == nil {
  1681  				sect.Elfsect = elfshnamedup(sect.Name)
  1682  			}
  1683  		} else {
  1684  			elfshalloc(sect)
  1685  		}
  1686  	}
  1687  	for _, sect := range Segrodata.Sections {
  1688  		elfshalloc(sect)
  1689  	}
  1690  	for _, sect := range Segrelrodata.Sections {
  1691  		elfshalloc(sect)
  1692  	}
  1693  	for _, sect := range Segdata.Sections {
  1694  		elfshalloc(sect)
  1695  	}
  1696  	for _, sect := range Segdwarf.Sections {
  1697  		elfshalloc(sect)
  1698  	}
  1699  }
  1700  
  1701  func asmbElf(ctxt *Link) {
  1702  	var symo int64
  1703  	symo = int64(Segdwarf.Fileoff + Segdwarf.Filelen)
  1704  	symo = Rnd(symo, int64(ctxt.Arch.PtrSize))
  1705  
  1706  	ldr := ctxt.loader
  1707  	eh := getElfEhdr()
  1708  	switch ctxt.Arch.Family {
  1709  	default:
  1710  		Exitf("unknown architecture in asmbelf: %v", ctxt.Arch.Family)
  1711  	case sys.MIPS, sys.MIPS64:
  1712  		eh.Machine = uint16(elf.EM_MIPS)
  1713  	case sys.Loong64:
  1714  		eh.Machine = uint16(elf.EM_LOONGARCH)
  1715  	case sys.ARM:
  1716  		eh.Machine = uint16(elf.EM_ARM)
  1717  	case sys.AMD64:
  1718  		eh.Machine = uint16(elf.EM_X86_64)
  1719  	case sys.ARM64:
  1720  		eh.Machine = uint16(elf.EM_AARCH64)
  1721  	case sys.I386:
  1722  		eh.Machine = uint16(elf.EM_386)
  1723  	case sys.PPC64:
  1724  		eh.Machine = uint16(elf.EM_PPC64)
  1725  	case sys.RISCV64:
  1726  		eh.Machine = uint16(elf.EM_RISCV)
  1727  	case sys.S390X:
  1728  		eh.Machine = uint16(elf.EM_S390)
  1729  	}
  1730  
  1731  	elfreserve := int64(ELFRESERVE)
  1732  
  1733  	numtext := int64(0)
  1734  	for _, sect := range Segtext.Sections {
  1735  		if sect.Name == ".text" {
  1736  			numtext++
  1737  		}
  1738  	}
  1739  
  1740  	// If there are multiple text sections, extra space is needed
  1741  	// in the elfreserve for the additional .text and .rela.text
  1742  	// section headers.  It can handle 4 extra now. Headers are
  1743  	// 64 bytes.
  1744  
  1745  	if numtext > 4 {
  1746  		elfreserve += elfreserve + numtext*64*2
  1747  	}
  1748  
  1749  	startva := *FlagTextAddr - int64(HEADR)
  1750  	resoff := elfreserve
  1751  
  1752  	var pph *ElfPhdr
  1753  	var pnote *ElfPhdr
  1754  	getpnote := func() *ElfPhdr {
  1755  		if pnote == nil {
  1756  			pnote = newElfPhdr()
  1757  			pnote.Type = elf.PT_NOTE
  1758  			pnote.Flags = elf.PF_R
  1759  		}
  1760  		return pnote
  1761  	}
  1762  	if *flagRace && ctxt.IsNetbsd() {
  1763  		sh := elfshname(".note.netbsd.pax")
  1764  		resoff -= int64(elfnetbsdpax(sh, uint64(startva), uint64(resoff)))
  1765  		phsh(getpnote(), sh)
  1766  	}
  1767  	if ctxt.LinkMode == LinkExternal {
  1768  		// skip program headers
  1769  		eh.Phoff = 0
  1770  
  1771  		eh.Phentsize = 0
  1772  
  1773  		if ctxt.BuildMode == BuildModeShared {
  1774  			sh := elfshname(".note.go.pkg-list")
  1775  			sh.Type = uint32(elf.SHT_NOTE)
  1776  			sh = elfshname(".note.go.abihash")
  1777  			sh.Type = uint32(elf.SHT_NOTE)
  1778  			sh.Flags = uint64(elf.SHF_ALLOC)
  1779  			sh = elfshname(".note.go.deps")
  1780  			sh.Type = uint32(elf.SHT_NOTE)
  1781  		}
  1782  
  1783  		if *flagBuildid != "" {
  1784  			sh := elfshname(".note.go.buildid")
  1785  			sh.Type = uint32(elf.SHT_NOTE)
  1786  			sh.Flags = uint64(elf.SHF_ALLOC)
  1787  		}
  1788  
  1789  		goto elfobj
  1790  	}
  1791  
  1792  	// program header info
  1793  	pph = newElfPhdr()
  1794  
  1795  	pph.Type = elf.PT_PHDR
  1796  	pph.Flags = elf.PF_R
  1797  	pph.Off = uint64(eh.Ehsize)
  1798  	pph.Vaddr = uint64(*FlagTextAddr) - uint64(HEADR) + pph.Off
  1799  	pph.Paddr = uint64(*FlagTextAddr) - uint64(HEADR) + pph.Off
  1800  	pph.Align = uint64(*FlagRound)
  1801  
  1802  	// PHDR must be in a loaded segment. Adjust the text
  1803  	// segment boundaries downwards to include it.
  1804  	{
  1805  		o := int64(Segtext.Vaddr - pph.Vaddr)
  1806  		Segtext.Vaddr -= uint64(o)
  1807  		Segtext.Length += uint64(o)
  1808  		o = int64(Segtext.Fileoff - pph.Off)
  1809  		Segtext.Fileoff -= uint64(o)
  1810  		Segtext.Filelen += uint64(o)
  1811  	}
  1812  
  1813  	if !*FlagD { // -d suppresses dynamic loader format
  1814  		// interpreter
  1815  		sh := elfshname(".interp")
  1816  
  1817  		sh.Type = uint32(elf.SHT_PROGBITS)
  1818  		sh.Flags = uint64(elf.SHF_ALLOC)
  1819  		sh.Addralign = 1
  1820  
  1821  		if interpreter == "" && buildcfg.GOOS == runtime.GOOS && buildcfg.GOARCH == runtime.GOARCH && buildcfg.GO_LDSO != "" {
  1822  			interpreter = buildcfg.GO_LDSO
  1823  		}
  1824  
  1825  		if interpreter == "" {
  1826  			switch ctxt.HeadType {
  1827  			case objabi.Hlinux:
  1828  				if buildcfg.GOOS == "android" {
  1829  					interpreter = thearch.ELF.Androiddynld
  1830  					if interpreter == "" {
  1831  						Exitf("ELF interpreter not set")
  1832  					}
  1833  				} else {
  1834  					interpreter = thearch.ELF.Linuxdynld
  1835  					// If interpreter does not exist, try musl instead.
  1836  					// This lets the same cmd/link binary work on
  1837  					// both glibc-based and musl-based systems.
  1838  					if _, err := os.Stat(interpreter); err != nil {
  1839  						if musl := thearch.ELF.LinuxdynldMusl; musl != "" {
  1840  							if _, err := os.Stat(musl); err == nil {
  1841  								interpreter = musl
  1842  							}
  1843  						}
  1844  					}
  1845  				}
  1846  
  1847  			case objabi.Hfreebsd:
  1848  				interpreter = thearch.ELF.Freebsddynld
  1849  
  1850  			case objabi.Hnetbsd:
  1851  				interpreter = thearch.ELF.Netbsddynld
  1852  
  1853  			case objabi.Hopenbsd:
  1854  				interpreter = thearch.ELF.Openbsddynld
  1855  
  1856  			case objabi.Hdragonfly:
  1857  				interpreter = thearch.ELF.Dragonflydynld
  1858  
  1859  			case objabi.Hsolaris:
  1860  				interpreter = thearch.ELF.Solarisdynld
  1861  			}
  1862  		}
  1863  
  1864  		resoff -= int64(elfinterp(sh, uint64(startva), uint64(resoff), interpreter))
  1865  
  1866  		ph := newElfPhdr()
  1867  		ph.Type = elf.PT_INTERP
  1868  		ph.Flags = elf.PF_R
  1869  		phsh(ph, sh)
  1870  	}
  1871  
  1872  	if ctxt.HeadType == objabi.Hnetbsd || ctxt.HeadType == objabi.Hopenbsd || ctxt.HeadType == objabi.Hfreebsd {
  1873  		var sh *ElfShdr
  1874  		switch ctxt.HeadType {
  1875  		case objabi.Hnetbsd:
  1876  			sh = elfshname(".note.netbsd.ident")
  1877  			resoff -= int64(elfnetbsdsig(sh, uint64(startva), uint64(resoff)))
  1878  
  1879  		case objabi.Hopenbsd:
  1880  			sh = elfshname(".note.openbsd.ident")
  1881  			resoff -= int64(elfopenbsdsig(sh, uint64(startva), uint64(resoff)))
  1882  
  1883  		case objabi.Hfreebsd:
  1884  			sh = elfshname(".note.tag")
  1885  			resoff -= int64(elffreebsdsig(sh, uint64(startva), uint64(resoff)))
  1886  		}
  1887  		// NetBSD, OpenBSD and FreeBSD require ident in an independent segment.
  1888  		pnotei := newElfPhdr()
  1889  		pnotei.Type = elf.PT_NOTE
  1890  		pnotei.Flags = elf.PF_R
  1891  		phsh(pnotei, sh)
  1892  	}
  1893  
  1894  	if len(buildinfo) > 0 {
  1895  		sh := elfshname(".note.gnu.build-id")
  1896  		resoff -= int64(elfbuildinfo(sh, uint64(startva), uint64(resoff)))
  1897  		phsh(getpnote(), sh)
  1898  	}
  1899  
  1900  	if *flagBuildid != "" {
  1901  		sh := elfshname(".note.go.buildid")
  1902  		resoff -= int64(elfgobuildid(sh, uint64(startva), uint64(resoff)))
  1903  		phsh(getpnote(), sh)
  1904  	}
  1905  
  1906  	// Additions to the reserved area must be above this line.
  1907  
  1908  	elfphload(&Segtext)
  1909  	if len(Segrodata.Sections) > 0 {
  1910  		elfphload(&Segrodata)
  1911  	}
  1912  	if len(Segrelrodata.Sections) > 0 {
  1913  		elfphload(&Segrelrodata)
  1914  		elfphrelro(&Segrelrodata)
  1915  	}
  1916  	elfphload(&Segdata)
  1917  
  1918  	// Dynamic linking sections
  1919  	if !*FlagD {
  1920  		sh := elfshname(".dynsym")
  1921  		sh.Type = uint32(elf.SHT_DYNSYM)
  1922  		sh.Flags = uint64(elf.SHF_ALLOC)
  1923  		if elf64 {
  1924  			sh.Entsize = ELF64SYMSIZE
  1925  		} else {
  1926  			sh.Entsize = ELF32SYMSIZE
  1927  		}
  1928  		sh.Addralign = uint64(ctxt.Arch.RegSize)
  1929  		sh.link = elfshname(".dynstr")
  1930  
  1931  		// sh.Info is the index of first non-local symbol (number of local symbols)
  1932  		s := ldr.Lookup(".dynsym", 0)
  1933  		i := uint32(0)
  1934  		for sub := s; sub != 0; sub = ldr.SubSym(sub) {
  1935  			i++
  1936  			if !ldr.AttrLocal(sub) {
  1937  				break
  1938  			}
  1939  		}
  1940  		sh.Info = i
  1941  		shsym(sh, ldr, s)
  1942  
  1943  		sh = elfshname(".dynstr")
  1944  		sh.Type = uint32(elf.SHT_STRTAB)
  1945  		sh.Flags = uint64(elf.SHF_ALLOC)
  1946  		sh.Addralign = 1
  1947  		shsym(sh, ldr, ldr.Lookup(".dynstr", 0))
  1948  
  1949  		if elfverneed != 0 {
  1950  			sh := elfshname(".gnu.version")
  1951  			sh.Type = uint32(elf.SHT_GNU_VERSYM)
  1952  			sh.Flags = uint64(elf.SHF_ALLOC)
  1953  			sh.Addralign = 2
  1954  			sh.link = elfshname(".dynsym")
  1955  			sh.Entsize = 2
  1956  			shsym(sh, ldr, ldr.Lookup(".gnu.version", 0))
  1957  
  1958  			sh = elfshname(".gnu.version_r")
  1959  			sh.Type = uint32(elf.SHT_GNU_VERNEED)
  1960  			sh.Flags = uint64(elf.SHF_ALLOC)
  1961  			sh.Addralign = uint64(ctxt.Arch.RegSize)
  1962  			sh.Info = uint32(elfverneed)
  1963  			sh.link = elfshname(".dynstr")
  1964  			shsym(sh, ldr, ldr.Lookup(".gnu.version_r", 0))
  1965  		}
  1966  
  1967  		if elfRelType == ".rela" {
  1968  			sh := elfshname(".rela.plt")
  1969  			sh.Type = uint32(elf.SHT_RELA)
  1970  			sh.Flags = uint64(elf.SHF_ALLOC)
  1971  			sh.Entsize = ELF64RELASIZE
  1972  			sh.Addralign = uint64(ctxt.Arch.RegSize)
  1973  			sh.link = elfshname(".dynsym")
  1974  			sh.info = elfshname(".plt")
  1975  			shsym(sh, ldr, ldr.Lookup(".rela.plt", 0))
  1976  
  1977  			sh = elfshname(".rela")
  1978  			sh.Type = uint32(elf.SHT_RELA)
  1979  			sh.Flags = uint64(elf.SHF_ALLOC)
  1980  			sh.Entsize = ELF64RELASIZE
  1981  			sh.Addralign = 8
  1982  			sh.link = elfshname(".dynsym")
  1983  			shsym(sh, ldr, ldr.Lookup(".rela", 0))
  1984  		} else {
  1985  			sh := elfshname(".rel.plt")
  1986  			sh.Type = uint32(elf.SHT_REL)
  1987  			sh.Flags = uint64(elf.SHF_ALLOC)
  1988  			sh.Entsize = ELF32RELSIZE
  1989  			sh.Addralign = 4
  1990  			sh.link = elfshname(".dynsym")
  1991  			shsym(sh, ldr, ldr.Lookup(".rel.plt", 0))
  1992  
  1993  			sh = elfshname(".rel")
  1994  			sh.Type = uint32(elf.SHT_REL)
  1995  			sh.Flags = uint64(elf.SHF_ALLOC)
  1996  			sh.Entsize = ELF32RELSIZE
  1997  			sh.Addralign = 4
  1998  			sh.link = elfshname(".dynsym")
  1999  			shsym(sh, ldr, ldr.Lookup(".rel", 0))
  2000  		}
  2001  
  2002  		if elf.Machine(eh.Machine) == elf.EM_PPC64 {
  2003  			sh := elfshname(".glink")
  2004  			sh.Type = uint32(elf.SHT_PROGBITS)
  2005  			sh.Flags = uint64(elf.SHF_ALLOC + elf.SHF_EXECINSTR)
  2006  			sh.Addralign = 4
  2007  			shsym(sh, ldr, ldr.Lookup(".glink", 0))
  2008  		}
  2009  
  2010  		sh = elfshname(".plt")
  2011  		sh.Type = uint32(elf.SHT_PROGBITS)
  2012  		sh.Flags = uint64(elf.SHF_ALLOC + elf.SHF_EXECINSTR)
  2013  		if elf.Machine(eh.Machine) == elf.EM_X86_64 {
  2014  			sh.Entsize = 16
  2015  		} else if elf.Machine(eh.Machine) == elf.EM_S390 {
  2016  			sh.Entsize = 32
  2017  		} else if elf.Machine(eh.Machine) == elf.EM_PPC64 {
  2018  			// On ppc64, this is just a table of addresses
  2019  			// filled by the dynamic linker
  2020  			sh.Type = uint32(elf.SHT_NOBITS)
  2021  
  2022  			sh.Flags = uint64(elf.SHF_ALLOC + elf.SHF_WRITE)
  2023  			sh.Entsize = 8
  2024  		} else {
  2025  			sh.Entsize = 4
  2026  		}
  2027  		sh.Addralign = sh.Entsize
  2028  		shsym(sh, ldr, ldr.Lookup(".plt", 0))
  2029  
  2030  		// On ppc64, .got comes from the input files, so don't
  2031  		// create it here, and .got.plt is not used.
  2032  		if elf.Machine(eh.Machine) != elf.EM_PPC64 {
  2033  			sh := elfshname(".got")
  2034  			sh.Type = uint32(elf.SHT_PROGBITS)
  2035  			sh.Flags = uint64(elf.SHF_ALLOC + elf.SHF_WRITE)
  2036  			sh.Entsize = uint64(ctxt.Arch.RegSize)
  2037  			sh.Addralign = uint64(ctxt.Arch.RegSize)
  2038  			shsym(sh, ldr, ldr.Lookup(".got", 0))
  2039  
  2040  			sh = elfshname(".got.plt")
  2041  			sh.Type = uint32(elf.SHT_PROGBITS)
  2042  			sh.Flags = uint64(elf.SHF_ALLOC + elf.SHF_WRITE)
  2043  			sh.Entsize = uint64(ctxt.Arch.RegSize)
  2044  			sh.Addralign = uint64(ctxt.Arch.RegSize)
  2045  			shsym(sh, ldr, ldr.Lookup(".got.plt", 0))
  2046  		}
  2047  
  2048  		sh = elfshname(".hash")
  2049  		sh.Type = uint32(elf.SHT_HASH)
  2050  		sh.Flags = uint64(elf.SHF_ALLOC)
  2051  		sh.Entsize = 4
  2052  		sh.Addralign = uint64(ctxt.Arch.RegSize)
  2053  		sh.link = elfshname(".dynsym")
  2054  		shsym(sh, ldr, ldr.Lookup(".hash", 0))
  2055  
  2056  		// sh and elf.PT_DYNAMIC for .dynamic section
  2057  		sh = elfshname(".dynamic")
  2058  
  2059  		sh.Type = uint32(elf.SHT_DYNAMIC)
  2060  		sh.Flags = uint64(elf.SHF_ALLOC + elf.SHF_WRITE)
  2061  		sh.Entsize = 2 * uint64(ctxt.Arch.RegSize)
  2062  		sh.Addralign = uint64(ctxt.Arch.RegSize)
  2063  		sh.link = elfshname(".dynstr")
  2064  		shsym(sh, ldr, ldr.Lookup(".dynamic", 0))
  2065  		ph := newElfPhdr()
  2066  		ph.Type = elf.PT_DYNAMIC
  2067  		ph.Flags = elf.PF_R + elf.PF_W
  2068  		phsh(ph, sh)
  2069  
  2070  		// Thread-local storage segment (really just size).
  2071  		tlssize := uint64(0)
  2072  		for _, sect := range Segdata.Sections {
  2073  			if sect.Name == ".tbss" {
  2074  				tlssize = sect.Length
  2075  			}
  2076  		}
  2077  		if tlssize != 0 {
  2078  			ph := newElfPhdr()
  2079  			ph.Type = elf.PT_TLS
  2080  			ph.Flags = elf.PF_R
  2081  			ph.Memsz = tlssize
  2082  			ph.Align = uint64(ctxt.Arch.RegSize)
  2083  		}
  2084  	}
  2085  
  2086  	if ctxt.HeadType == objabi.Hlinux || ctxt.HeadType == objabi.Hfreebsd {
  2087  		ph := newElfPhdr()
  2088  		ph.Type = elf.PT_GNU_STACK
  2089  		ph.Flags = elf.PF_W + elf.PF_R
  2090  		ph.Align = uint64(ctxt.Arch.RegSize)
  2091  	} else if ctxt.HeadType == objabi.Hopenbsd {
  2092  		ph := newElfPhdr()
  2093  		ph.Type = elf.PT_OPENBSD_NOBTCFI
  2094  		ph.Flags = elf.PF_X
  2095  	} else if ctxt.HeadType == objabi.Hsolaris {
  2096  		ph := newElfPhdr()
  2097  		ph.Type = elf.PT_SUNWSTACK
  2098  		ph.Flags = elf.PF_W + elf.PF_R
  2099  	}
  2100  
  2101  elfobj:
  2102  	if ctxt.IsMIPS() {
  2103  		sh := elfshname(".MIPS.abiflags")
  2104  		sh.Type = uint32(elf.SHT_MIPS_ABIFLAGS)
  2105  		sh.Flags = uint64(elf.SHF_ALLOC)
  2106  		sh.Addralign = 8
  2107  		resoff -= int64(elfMipsAbiFlags(sh, uint64(startva), uint64(resoff)))
  2108  
  2109  		ph := newElfPhdr()
  2110  		ph.Type = elf.PT_MIPS_ABIFLAGS
  2111  		ph.Flags = elf.PF_R
  2112  		phsh(ph, sh)
  2113  
  2114  		sh = elfshname(".gnu.attributes")
  2115  		sh.Type = uint32(elf.SHT_GNU_ATTRIBUTES)
  2116  		sh.Addralign = 1
  2117  		ldr := ctxt.loader
  2118  		shsym(sh, ldr, ldr.Lookup(".gnu.attributes", 0))
  2119  	}
  2120  
  2121  	// put these sections early in the list
  2122  	if !*FlagS {
  2123  		elfshname(".symtab")
  2124  		elfshname(".strtab")
  2125  	}
  2126  	elfshname(".shstrtab")
  2127  
  2128  	for _, sect := range Segtext.Sections {
  2129  		elfshbits(ctxt.LinkMode, sect)
  2130  	}
  2131  	for _, sect := range Segrodata.Sections {
  2132  		elfshbits(ctxt.LinkMode, sect)
  2133  	}
  2134  	for _, sect := range Segrelrodata.Sections {
  2135  		elfshbits(ctxt.LinkMode, sect)
  2136  	}
  2137  	for _, sect := range Segdata.Sections {
  2138  		elfshbits(ctxt.LinkMode, sect)
  2139  	}
  2140  	for _, sect := range Segdwarf.Sections {
  2141  		elfshbits(ctxt.LinkMode, sect)
  2142  	}
  2143  
  2144  	if ctxt.LinkMode == LinkExternal {
  2145  		for _, sect := range Segtext.Sections {
  2146  			elfshreloc(ctxt.Arch, sect)
  2147  		}
  2148  		for _, sect := range Segrodata.Sections {
  2149  			elfshreloc(ctxt.Arch, sect)
  2150  		}
  2151  		for _, sect := range Segrelrodata.Sections {
  2152  			elfshreloc(ctxt.Arch, sect)
  2153  		}
  2154  		for _, sect := range Segdata.Sections {
  2155  			elfshreloc(ctxt.Arch, sect)
  2156  		}
  2157  		for _, si := range dwarfp {
  2158  			sect := ldr.SymSect(si.secSym())
  2159  			elfshreloc(ctxt.Arch, sect)
  2160  		}
  2161  		// add a .note.GNU-stack section to mark the stack as non-executable
  2162  		sh := elfshname(".note.GNU-stack")
  2163  
  2164  		sh.Type = uint32(elf.SHT_PROGBITS)
  2165  		sh.Addralign = 1
  2166  		sh.Flags = 0
  2167  	}
  2168  
  2169  	elfSortShdrs(ctxt)
  2170  
  2171  	sh := elfshname(".shstrtab")
  2172  	eh.Shstrndx = uint16(elfShdrShnum(sh))
  2173  
  2174  	var shstrtabLen uint32
  2175  	ctxt.Out.SeekSet(symo)
  2176  	if *FlagS {
  2177  		shstrtabLen = elfWriteShstrtab(ctxt)
  2178  	} else {
  2179  		asmElfSym(ctxt)
  2180  		ctxt.Out.Write(elfstrdat)
  2181  		shstrtabLen = elfWriteShstrtab(ctxt)
  2182  		if ctxt.IsExternal() {
  2183  			elfEmitReloc(ctxt)
  2184  		}
  2185  	}
  2186  	ctxt.Out.SeekSet(0)
  2187  
  2188  	var shstroff uint64
  2189  	if !*FlagS {
  2190  		sh := elfshname(".symtab")
  2191  		sh.Type = uint32(elf.SHT_SYMTAB)
  2192  		sh.Off = uint64(symo)
  2193  		sh.Size = uint64(symSize)
  2194  		sh.Addralign = uint64(ctxt.Arch.RegSize)
  2195  		sh.Entsize = 8 + 2*uint64(ctxt.Arch.RegSize)
  2196  		sh.link = elfshname(".strtab")
  2197  		sh.Info = uint32(elfglobalsymndx)
  2198  
  2199  		sh = elfshname(".strtab")
  2200  		sh.Type = uint32(elf.SHT_STRTAB)
  2201  		sh.Off = uint64(symo) + uint64(symSize)
  2202  		sh.Size = uint64(len(elfstrdat))
  2203  		sh.Addralign = 1
  2204  		shstroff = sh.Off + sh.Size
  2205  	} else {
  2206  		shstroff = uint64(symo)
  2207  	}
  2208  
  2209  	sh = elfshname(".shstrtab")
  2210  	sh.Type = uint32(elf.SHT_STRTAB)
  2211  	sh.Off = shstroff
  2212  	sh.Size = uint64(shstrtabLen)
  2213  	sh.Addralign = 1
  2214  
  2215  	// Main header
  2216  	copy(eh.Ident[:], elf.ELFMAG)
  2217  
  2218  	var osabi elf.OSABI
  2219  	switch ctxt.HeadType {
  2220  	case objabi.Hfreebsd:
  2221  		osabi = elf.ELFOSABI_FREEBSD
  2222  	case objabi.Hnetbsd:
  2223  		osabi = elf.ELFOSABI_NETBSD
  2224  	case objabi.Hopenbsd:
  2225  		osabi = elf.ELFOSABI_OPENBSD
  2226  	case objabi.Hdragonfly:
  2227  		osabi = elf.ELFOSABI_NONE
  2228  	}
  2229  	eh.Ident[elf.EI_OSABI] = byte(osabi)
  2230  
  2231  	if elf64 {
  2232  		eh.Ident[elf.EI_CLASS] = byte(elf.ELFCLASS64)
  2233  	} else {
  2234  		eh.Ident[elf.EI_CLASS] = byte(elf.ELFCLASS32)
  2235  	}
  2236  	if ctxt.Arch.ByteOrder == binary.BigEndian {
  2237  		eh.Ident[elf.EI_DATA] = byte(elf.ELFDATA2MSB)
  2238  	} else {
  2239  		eh.Ident[elf.EI_DATA] = byte(elf.ELFDATA2LSB)
  2240  	}
  2241  	eh.Ident[elf.EI_VERSION] = byte(elf.EV_CURRENT)
  2242  
  2243  	if ctxt.LinkMode == LinkExternal {
  2244  		eh.Type = uint16(elf.ET_REL)
  2245  	} else if ctxt.BuildMode == BuildModePIE {
  2246  		eh.Type = uint16(elf.ET_DYN)
  2247  	} else {
  2248  		eh.Type = uint16(elf.ET_EXEC)
  2249  	}
  2250  
  2251  	if ctxt.LinkMode != LinkExternal {
  2252  		eh.Entry = uint64(Entryvalue(ctxt))
  2253  	}
  2254  
  2255  	eh.Version = uint32(elf.EV_CURRENT)
  2256  
  2257  	if pph != nil {
  2258  		pph.Filesz = uint64(eh.Phnum) * uint64(eh.Phentsize)
  2259  		pph.Memsz = pph.Filesz
  2260  	}
  2261  
  2262  	if len(shdr) >= 0xffff {
  2263  		Errorf("too many ELF sections")
  2264  	}
  2265  	eh.Shnum = uint16(len(shdr))
  2266  
  2267  	ctxt.Out.SeekSet(0)
  2268  	a := int64(0)
  2269  	a += int64(elfwritehdr(ctxt.Out))
  2270  	a += int64(elfwritephdrs(ctxt.Out))
  2271  	a += int64(elfwriteshdrs(ctxt.Out))
  2272  	if !*FlagD {
  2273  		a += int64(elfwriteinterp(ctxt.Out))
  2274  	}
  2275  	if ctxt.IsMIPS() {
  2276  		a += int64(elfWriteMipsAbiFlags(ctxt))
  2277  	}
  2278  
  2279  	if ctxt.LinkMode != LinkExternal {
  2280  		if ctxt.HeadType == objabi.Hnetbsd {
  2281  			a += int64(elfwritenetbsdsig(ctxt.Out))
  2282  		}
  2283  		if ctxt.HeadType == objabi.Hopenbsd {
  2284  			a += int64(elfwriteopenbsdsig(ctxt.Out))
  2285  		}
  2286  		if ctxt.HeadType == objabi.Hfreebsd {
  2287  			a += int64(elfwritefreebsdsig(ctxt.Out))
  2288  		}
  2289  		if len(buildinfo) > 0 {
  2290  			a += int64(elfwritebuildinfo(ctxt.Out))
  2291  		}
  2292  		if *flagBuildid != "" {
  2293  			a += int64(elfwritegobuildid(ctxt.Out))
  2294  		}
  2295  	}
  2296  	if *flagRace && ctxt.IsNetbsd() {
  2297  		a += int64(elfwritenetbsdpax(ctxt.Out))
  2298  	}
  2299  
  2300  	if a > elfreserve {
  2301  		Errorf("ELFRESERVE too small: %d > %d with %d text sections", a, elfreserve, numtext)
  2302  	}
  2303  
  2304  	// Verify the amount of space allocated for the elf header is sufficient.  The file offsets are
  2305  	// already computed in layout, so we could spill into another section.
  2306  	if a > int64(HEADR) {
  2307  		Errorf("HEADR too small: %d > %d with %d text sections", a, HEADR, numtext)
  2308  	}
  2309  }
  2310  
  2311  func elfadddynsym(ldr *loader.Loader, target *Target, syms *ArchSyms, s loader.Sym) {
  2312  	ldr.SetSymDynid(s, int32(Nelfsym))
  2313  	Nelfsym++
  2314  	d := ldr.MakeSymbolUpdater(syms.DynSym)
  2315  	name := ldr.SymExtname(s)
  2316  	dstru := ldr.MakeSymbolUpdater(syms.DynStr)
  2317  	st := ldr.SymType(s)
  2318  	cgoeStatic := ldr.AttrCgoExportStatic(s)
  2319  	cgoeDynamic := ldr.AttrCgoExportDynamic(s)
  2320  	cgoexp := (cgoeStatic || cgoeDynamic)
  2321  
  2322  	d.AddUint32(target.Arch, uint32(dstru.Addstring(name)))
  2323  
  2324  	if elf64 {
  2325  		// type
  2326  		var t uint8
  2327  
  2328  		if cgoexp && st.IsText() {
  2329  			t = elf.ST_INFO(elf.STB_GLOBAL, elf.STT_FUNC)
  2330  		} else {
  2331  			t = elf.ST_INFO(elf.STB_GLOBAL, elf.STT_OBJECT)
  2332  		}
  2333  		d.AddUint8(t)
  2334  
  2335  		// reserved
  2336  		d.AddUint8(0)
  2337  
  2338  		// section where symbol is defined
  2339  		if st == sym.SDYNIMPORT {
  2340  			d.AddUint16(target.Arch, uint16(elf.SHN_UNDEF))
  2341  		} else {
  2342  			d.AddUint16(target.Arch, 1)
  2343  		}
  2344  
  2345  		// value
  2346  		if st == sym.SDYNIMPORT {
  2347  			d.AddUint64(target.Arch, 0)
  2348  		} else {
  2349  			d.AddAddrPlus(target.Arch, s, 0)
  2350  		}
  2351  
  2352  		// size of object
  2353  		d.AddUint64(target.Arch, uint64(len(ldr.Data(s))))
  2354  
  2355  		dil := ldr.SymDynimplib(s)
  2356  
  2357  		if !cgoeDynamic && dil != "" && !seenlib[dil] {
  2358  			du := ldr.MakeSymbolUpdater(syms.Dynamic)
  2359  			Elfwritedynent(target.Arch, du, elf.DT_NEEDED, uint64(dstru.Addstring(dil)))
  2360  			seenlib[dil] = true
  2361  		}
  2362  	} else {
  2363  
  2364  		// value
  2365  		if st == sym.SDYNIMPORT {
  2366  			d.AddUint32(target.Arch, 0)
  2367  		} else {
  2368  			d.AddAddrPlus(target.Arch, s, 0)
  2369  		}
  2370  
  2371  		// size of object
  2372  		d.AddUint32(target.Arch, uint32(len(ldr.Data(s))))
  2373  
  2374  		// type
  2375  		var t uint8
  2376  
  2377  		// TODO(mwhudson): presumably the behavior should actually be the same on both arm and 386.
  2378  		if target.Arch.Family == sys.I386 && cgoexp && st.IsText() {
  2379  			t = elf.ST_INFO(elf.STB_GLOBAL, elf.STT_FUNC)
  2380  		} else if target.Arch.Family == sys.ARM && cgoeDynamic && st.IsText() {
  2381  			t = elf.ST_INFO(elf.STB_GLOBAL, elf.STT_FUNC)
  2382  		} else {
  2383  			t = elf.ST_INFO(elf.STB_GLOBAL, elf.STT_OBJECT)
  2384  		}
  2385  		d.AddUint8(t)
  2386  		d.AddUint8(0)
  2387  
  2388  		// shndx
  2389  		if st == sym.SDYNIMPORT {
  2390  			d.AddUint16(target.Arch, uint16(elf.SHN_UNDEF))
  2391  		} else {
  2392  			d.AddUint16(target.Arch, 1)
  2393  		}
  2394  	}
  2395  }
  2396  

View as plain text