github.com/bir3/gocompiler@v0.3.205/src/cmd/link/internal/ld/elf.go (about)

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