Black Lives Matter. Support the Equal Justice Initiative.

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

Documentation: cmd/link/internal/ld

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