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

View as plain text