github.com/epfl-dcsl/gotee@v0.0.0-20200909122901-014b35f5e5e9/src/cmd/link/internal/ld/elf.go (about)

     1  // Copyright 2009 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package ld
     6  
     7  import (
     8  	"cmd/internal/objabi"
     9  	"cmd/internal/sys"
    10  	"cmd/link/internal/sym"
    11  	"crypto/sha1"
    12  	"encoding/binary"
    13  	"encoding/hex"
    14  	"io"
    15  	"io/ioutil"
    16  	"log"
    17  	"os"
    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  const (
    81  	EI_MAG0              = 0
    82  	EI_MAG1              = 1
    83  	EI_MAG2              = 2
    84  	EI_MAG3              = 3
    85  	EI_CLASS             = 4
    86  	EI_DATA              = 5
    87  	EI_VERSION           = 6
    88  	EI_OSABI             = 7
    89  	EI_ABIVERSION        = 8
    90  	OLD_EI_BRAND         = 8
    91  	EI_PAD               = 9
    92  	EI_NIDENT            = 16
    93  	ELFMAG0              = 0x7f
    94  	ELFMAG1              = 'E'
    95  	ELFMAG2              = 'L'
    96  	ELFMAG3              = 'F'
    97  	SELFMAG              = 4
    98  	EV_NONE              = 0
    99  	EV_CURRENT           = 1
   100  	ELFCLASSNONE         = 0
   101  	ELFCLASS32           = 1
   102  	ELFCLASS64           = 2
   103  	ELFDATANONE          = 0
   104  	ELFDATA2LSB          = 1
   105  	ELFDATA2MSB          = 2
   106  	ELFOSABI_NONE        = 0
   107  	ELFOSABI_HPUX        = 1
   108  	ELFOSABI_NETBSD      = 2
   109  	ELFOSABI_LINUX       = 3
   110  	ELFOSABI_HURD        = 4
   111  	ELFOSABI_86OPEN      = 5
   112  	ELFOSABI_SOLARIS     = 6
   113  	ELFOSABI_AIX         = 7
   114  	ELFOSABI_IRIX        = 8
   115  	ELFOSABI_FREEBSD     = 9
   116  	ELFOSABI_TRU64       = 10
   117  	ELFOSABI_MODESTO     = 11
   118  	ELFOSABI_OPENBSD     = 12
   119  	ELFOSABI_OPENVMS     = 13
   120  	ELFOSABI_NSK         = 14
   121  	ELFOSABI_ARM         = 97
   122  	ELFOSABI_STANDALONE  = 255
   123  	ELFOSABI_SYSV        = ELFOSABI_NONE
   124  	ELFOSABI_MONTEREY    = ELFOSABI_AIX
   125  	ET_NONE              = 0
   126  	ET_REL               = 1
   127  	ET_EXEC              = 2
   128  	ET_DYN               = 3
   129  	ET_CORE              = 4
   130  	ET_LOOS              = 0xfe00
   131  	ET_HIOS              = 0xfeff
   132  	ET_LOPROC            = 0xff00
   133  	ET_HIPROC            = 0xffff
   134  	EM_NONE              = 0
   135  	EM_M32               = 1
   136  	EM_SPARC             = 2
   137  	EM_386               = 3
   138  	EM_68K               = 4
   139  	EM_88K               = 5
   140  	EM_860               = 7
   141  	EM_MIPS              = 8
   142  	EM_S370              = 9
   143  	EM_MIPS_RS3_LE       = 10
   144  	EM_PARISC            = 15
   145  	EM_VPP500            = 17
   146  	EM_SPARC32PLUS       = 18
   147  	EM_960               = 19
   148  	EM_PPC               = 20
   149  	EM_PPC64             = 21
   150  	EM_S390              = 22
   151  	EM_V800              = 36
   152  	EM_FR20              = 37
   153  	EM_RH32              = 38
   154  	EM_RCE               = 39
   155  	EM_ARM               = 40
   156  	EM_SH                = 42
   157  	EM_SPARCV9           = 43
   158  	EM_TRICORE           = 44
   159  	EM_ARC               = 45
   160  	EM_H8_300            = 46
   161  	EM_H8_300H           = 47
   162  	EM_H8S               = 48
   163  	EM_H8_500            = 49
   164  	EM_IA_64             = 50
   165  	EM_MIPS_X            = 51
   166  	EM_COLDFIRE          = 52
   167  	EM_68HC12            = 53
   168  	EM_MMA               = 54
   169  	EM_PCP               = 55
   170  	EM_NCPU              = 56
   171  	EM_NDR1              = 57
   172  	EM_STARCORE          = 58
   173  	EM_ME16              = 59
   174  	EM_ST100             = 60
   175  	EM_TINYJ             = 61
   176  	EM_X86_64            = 62
   177  	EM_AARCH64           = 183
   178  	EM_486               = 6
   179  	EM_MIPS_RS4_BE       = 10
   180  	EM_ALPHA_STD         = 41
   181  	EM_ALPHA             = 0x9026
   182  	SHN_UNDEF            = 0
   183  	SHN_LORESERVE        = 0xff00
   184  	SHN_LOPROC           = 0xff00
   185  	SHN_HIPROC           = 0xff1f
   186  	SHN_LOOS             = 0xff20
   187  	SHN_HIOS             = 0xff3f
   188  	SHN_ABS              = 0xfff1
   189  	SHN_COMMON           = 0xfff2
   190  	SHN_XINDEX           = 0xffff
   191  	SHN_HIRESERVE        = 0xffff
   192  	SHT_NULL             = 0
   193  	SHT_PROGBITS         = 1
   194  	SHT_SYMTAB           = 2
   195  	SHT_STRTAB           = 3
   196  	SHT_RELA             = 4
   197  	SHT_HASH             = 5
   198  	SHT_DYNAMIC          = 6
   199  	SHT_NOTE             = 7
   200  	SHT_NOBITS           = 8
   201  	SHT_REL              = 9
   202  	SHT_SHLIB            = 10
   203  	SHT_DYNSYM           = 11
   204  	SHT_INIT_ARRAY       = 14
   205  	SHT_FINI_ARRAY       = 15
   206  	SHT_PREINIT_ARRAY    = 16
   207  	SHT_GROUP            = 17
   208  	SHT_SYMTAB_SHNDX     = 18
   209  	SHT_LOOS             = 0x60000000
   210  	SHT_HIOS             = 0x6fffffff
   211  	SHT_GNU_VERDEF       = 0x6ffffffd
   212  	SHT_GNU_VERNEED      = 0x6ffffffe
   213  	SHT_GNU_VERSYM       = 0x6fffffff
   214  	SHT_LOPROC           = 0x70000000
   215  	SHT_ARM_ATTRIBUTES   = 0x70000003
   216  	SHT_HIPROC           = 0x7fffffff
   217  	SHT_LOUSER           = 0x80000000
   218  	SHT_HIUSER           = 0xffffffff
   219  	SHF_WRITE            = 0x1
   220  	SHF_ALLOC            = 0x2
   221  	SHF_EXECINSTR        = 0x4
   222  	SHF_MERGE            = 0x10
   223  	SHF_STRINGS          = 0x20
   224  	SHF_INFO_LINK        = 0x40
   225  	SHF_LINK_ORDER       = 0x80
   226  	SHF_OS_NONCONFORMING = 0x100
   227  	SHF_GROUP            = 0x200
   228  	SHF_TLS              = 0x400
   229  	SHF_MASKOS           = 0x0ff00000
   230  	SHF_MASKPROC         = 0xf0000000
   231  	PT_NULL              = 0
   232  	PT_LOAD              = 1
   233  	PT_DYNAMIC           = 2
   234  	PT_INTERP            = 3
   235  	PT_NOTE              = 4
   236  	PT_SHLIB             = 5
   237  	PT_PHDR              = 6
   238  	PT_TLS               = 7
   239  	PT_LOOS              = 0x60000000
   240  	PT_HIOS              = 0x6fffffff
   241  	PT_LOPROC            = 0x70000000
   242  	PT_HIPROC            = 0x7fffffff
   243  	PT_GNU_STACK         = 0x6474e551
   244  	PT_GNU_RELRO         = 0x6474e552
   245  	PT_PAX_FLAGS         = 0x65041580
   246  	PT_SUNWSTACK         = 0x6ffffffb
   247  	PF_X                 = 0x1
   248  	PF_W                 = 0x2
   249  	PF_R                 = 0x4
   250  	PF_MASKOS            = 0x0ff00000
   251  	PF_MASKPROC          = 0xf0000000
   252  	DT_NULL              = 0
   253  	DT_NEEDED            = 1
   254  	DT_PLTRELSZ          = 2
   255  	DT_PLTGOT            = 3
   256  	DT_HASH              = 4
   257  	DT_STRTAB            = 5
   258  	DT_SYMTAB            = 6
   259  	DT_RELA              = 7
   260  	DT_RELASZ            = 8
   261  	DT_RELAENT           = 9
   262  	DT_STRSZ             = 10
   263  	DT_SYMENT            = 11
   264  	DT_INIT              = 12
   265  	DT_FINI              = 13
   266  	DT_SONAME            = 14
   267  	DT_RPATH             = 15
   268  	DT_SYMBOLIC          = 16
   269  	DT_REL               = 17
   270  	DT_RELSZ             = 18
   271  	DT_RELENT            = 19
   272  	DT_PLTREL            = 20
   273  	DT_DEBUG             = 21
   274  	DT_TEXTREL           = 22
   275  	DT_JMPREL            = 23
   276  	DT_BIND_NOW          = 24
   277  	DT_INIT_ARRAY        = 25
   278  	DT_FINI_ARRAY        = 26
   279  	DT_INIT_ARRAYSZ      = 27
   280  	DT_FINI_ARRAYSZ      = 28
   281  	DT_RUNPATH           = 29
   282  	DT_FLAGS             = 30
   283  	DT_ENCODING          = 32
   284  	DT_PREINIT_ARRAY     = 32
   285  	DT_PREINIT_ARRAYSZ   = 33
   286  	DT_LOOS              = 0x6000000d
   287  	DT_HIOS              = 0x6ffff000
   288  	DT_LOPROC            = 0x70000000
   289  	DT_HIPROC            = 0x7fffffff
   290  	DT_VERNEED           = 0x6ffffffe
   291  	DT_VERNEEDNUM        = 0x6fffffff
   292  	DT_VERSYM            = 0x6ffffff0
   293  	DT_PPC64_GLINK       = DT_LOPROC + 0
   294  	DT_PPC64_OPT         = DT_LOPROC + 3
   295  	DF_ORIGIN            = 0x0001
   296  	DF_SYMBOLIC          = 0x0002
   297  	DF_TEXTREL           = 0x0004
   298  	DF_BIND_NOW          = 0x0008
   299  	DF_STATIC_TLS        = 0x0010
   300  	NT_PRSTATUS          = 1
   301  	NT_FPREGSET          = 2
   302  	NT_PRPSINFO          = 3
   303  	STB_LOCAL            = 0
   304  	STB_GLOBAL           = 1
   305  	STB_WEAK             = 2
   306  	STB_LOOS             = 10
   307  	STB_HIOS             = 12
   308  	STB_LOPROC           = 13
   309  	STB_HIPROC           = 15
   310  	STT_NOTYPE           = 0
   311  	STT_OBJECT           = 1
   312  	STT_FUNC             = 2
   313  	STT_SECTION          = 3
   314  	STT_FILE             = 4
   315  	STT_COMMON           = 5
   316  	STT_TLS              = 6
   317  	STT_LOOS             = 10
   318  	STT_HIOS             = 12
   319  	STT_LOPROC           = 13
   320  	STT_HIPROC           = 15
   321  	STV_DEFAULT          = 0x0
   322  	STV_INTERNAL         = 0x1
   323  	STV_HIDDEN           = 0x2
   324  	STV_PROTECTED        = 0x3
   325  	STN_UNDEF            = 0
   326  )
   327  
   328  /* For accessing the fields of r_info. */
   329  
   330  /* For constructing r_info from field values. */
   331  
   332  /*
   333   * Relocation types.
   334   */
   335  const (
   336  	ARM_MAGIC_TRAMP_NUMBER = 0x5c000003
   337  )
   338  
   339  /*
   340   * Symbol table entries.
   341   */
   342  
   343  /* For accessing the fields of st_info. */
   344  
   345  /* For constructing st_info from field values. */
   346  
   347  /* For accessing the fields of st_other. */
   348  
   349  /*
   350   * ELF header.
   351   */
   352  type ElfEhdr struct {
   353  	ident     [EI_NIDENT]uint8
   354  	type_     uint16
   355  	machine   uint16
   356  	version   uint32
   357  	entry     uint64
   358  	phoff     uint64
   359  	shoff     uint64
   360  	flags     uint32
   361  	ehsize    uint16
   362  	phentsize uint16
   363  	phnum     uint16
   364  	shentsize uint16
   365  	shnum     uint16
   366  	shstrndx  uint16
   367  }
   368  
   369  /*
   370   * Section header.
   371   */
   372  type ElfShdr struct {
   373  	name      uint32
   374  	type_     uint32
   375  	flags     uint64
   376  	addr      uint64
   377  	off       uint64
   378  	size      uint64
   379  	link      uint32
   380  	info      uint32
   381  	addralign uint64
   382  	entsize   uint64
   383  	shnum     int
   384  }
   385  
   386  /*
   387   * Program header.
   388   */
   389  type ElfPhdr struct {
   390  	type_  uint32
   391  	flags  uint32
   392  	off    uint64
   393  	vaddr  uint64
   394  	paddr  uint64
   395  	filesz uint64
   396  	memsz  uint64
   397  	align  uint64
   398  }
   399  
   400  /* For accessing the fields of r_info. */
   401  
   402  /* For constructing r_info from field values. */
   403  
   404  /*
   405   * Symbol table entries.
   406   */
   407  
   408  /* For accessing the fields of st_info. */
   409  
   410  /* For constructing st_info from field values. */
   411  
   412  /* For accessing the fields of st_other. */
   413  
   414  /*
   415   * Go linker interface
   416   */
   417  const (
   418  	ELF64HDRSIZE  = 64
   419  	ELF64PHDRSIZE = 56
   420  	ELF64SHDRSIZE = 64
   421  	ELF64RELSIZE  = 16
   422  	ELF64RELASIZE = 24
   423  	ELF64SYMSIZE  = 24
   424  	ELF32HDRSIZE  = 52
   425  	ELF32PHDRSIZE = 32
   426  	ELF32SHDRSIZE = 40
   427  	ELF32SYMSIZE  = 16
   428  	ELF32RELSIZE  = 8
   429  )
   430  
   431  /*
   432   * The interface uses the 64-bit structures always,
   433   * to avoid code duplication.  The writers know how to
   434   * marshal a 32-bit representation from the 64-bit structure.
   435   */
   436  
   437  var Elfstrdat []byte
   438  
   439  /*
   440   * Total amount of space to reserve at the start of the file
   441   * for Header, PHeaders, SHeaders, and interp.
   442   * May waste some.
   443   * On FreeBSD, cannot be larger than a page.
   444   */
   445  const (
   446  	ELFRESERVE = 4096
   447  )
   448  
   449  /*
   450   * We use the 64-bit data structures on both 32- and 64-bit machines
   451   * in order to write the code just once.  The 64-bit data structure is
   452   * written in the 32-bit format on the 32-bit machines.
   453   */
   454  const (
   455  	NSECT = 400
   456  )
   457  
   458  var (
   459  	Nelfsym = 1
   460  
   461  	elf64 bool
   462  	// Either ".rel" or ".rela" depending on which type of relocation the
   463  	// target platform uses.
   464  	elfRelType string
   465  
   466  	ehdr ElfEhdr
   467  	phdr [NSECT]*ElfPhdr
   468  	shdr [NSECT]*ElfShdr
   469  
   470  	interp string
   471  )
   472  
   473  type Elfstring struct {
   474  	s   string
   475  	off int
   476  }
   477  
   478  var elfstr [100]Elfstring
   479  
   480  var nelfstr int
   481  
   482  var buildinfo []byte
   483  
   484  /*
   485   Initialize the global variable that describes the ELF header. It will be updated as
   486   we write section and prog headers.
   487  */
   488  func Elfinit(ctxt *Link) {
   489  	ctxt.IsELF = true
   490  
   491  	if ctxt.Arch.InFamily(sys.AMD64, sys.ARM64, sys.MIPS64, sys.PPC64, sys.S390X) {
   492  		elfRelType = ".rela"
   493  	} else {
   494  		elfRelType = ".rel"
   495  	}
   496  
   497  	switch ctxt.Arch.Family {
   498  	// 64-bit architectures
   499  	case sys.PPC64, sys.S390X:
   500  		if ctxt.Arch.ByteOrder == binary.BigEndian {
   501  			ehdr.flags = 1 /* Version 1 ABI */
   502  		} else {
   503  			ehdr.flags = 2 /* Version 2 ABI */
   504  		}
   505  		fallthrough
   506  	case sys.AMD64, sys.ARM64, sys.MIPS64:
   507  		if ctxt.Arch.Family == sys.MIPS64 {
   508  			ehdr.flags = 0x20000004 /* MIPS 3 CPIC */
   509  		}
   510  		elf64 = true
   511  
   512  		ehdr.phoff = ELF64HDRSIZE      /* Must be be ELF64HDRSIZE: first PHdr must follow ELF header */
   513  		ehdr.shoff = ELF64HDRSIZE      /* Will move as we add PHeaders */
   514  		ehdr.ehsize = ELF64HDRSIZE     /* Must be ELF64HDRSIZE */
   515  		ehdr.phentsize = ELF64PHDRSIZE /* Must be ELF64PHDRSIZE */
   516  		ehdr.shentsize = ELF64SHDRSIZE /* Must be ELF64SHDRSIZE */
   517  
   518  	// 32-bit architectures
   519  	case sys.ARM, sys.MIPS:
   520  		if ctxt.Arch.Family == sys.ARM {
   521  			// we use EABI on linux/arm, freebsd/arm, netbsd/arm.
   522  			if ctxt.HeadType == objabi.Hlinux || ctxt.HeadType == objabi.Hfreebsd || ctxt.HeadType == objabi.Hnetbsd {
   523  				// We set a value here that makes no indication of which
   524  				// float ABI the object uses, because this is information
   525  				// used by the dynamic linker to compare executables and
   526  				// shared libraries -- so it only matters for cgo calls, and
   527  				// the information properly comes from the object files
   528  				// produced by the host C compiler. parseArmAttributes in
   529  				// ldelf.go reads that information and updates this field as
   530  				// appropriate.
   531  				ehdr.flags = 0x5000002 // has entry point, Version5 EABI
   532  			}
   533  		} else if ctxt.Arch.Family == sys.MIPS {
   534  			ehdr.flags = 0x50001004 /* MIPS 32 CPIC O32*/
   535  		}
   536  		fallthrough
   537  	default:
   538  		ehdr.phoff = ELF32HDRSIZE
   539  		/* Must be be ELF32HDRSIZE: first PHdr must follow ELF header */
   540  		ehdr.shoff = ELF32HDRSIZE      /* Will move as we add PHeaders */
   541  		ehdr.ehsize = ELF32HDRSIZE     /* Must be ELF32HDRSIZE */
   542  		ehdr.phentsize = ELF32PHDRSIZE /* Must be ELF32PHDRSIZE */
   543  		ehdr.shentsize = ELF32SHDRSIZE /* Must be ELF32SHDRSIZE */
   544  	}
   545  }
   546  
   547  // Make sure PT_LOAD is aligned properly and
   548  // that there is no gap,
   549  // correct ELF loaders will do this implicitly,
   550  // but buggy ELF loaders like the one in some
   551  // versions of QEMU and UPX won't.
   552  func fixElfPhdr(e *ElfPhdr) {
   553  	frag := int(e.vaddr & (e.align - 1))
   554  
   555  	e.off -= uint64(frag)
   556  	e.vaddr -= uint64(frag)
   557  	e.paddr -= uint64(frag)
   558  	e.filesz += uint64(frag)
   559  	e.memsz += uint64(frag)
   560  }
   561  
   562  func elf64phdr(out *OutBuf, e *ElfPhdr) {
   563  	if e.type_ == PT_LOAD {
   564  		fixElfPhdr(e)
   565  	}
   566  
   567  	out.Write32(e.type_)
   568  	out.Write32(e.flags)
   569  	out.Write64(e.off)
   570  	out.Write64(e.vaddr)
   571  	out.Write64(e.paddr)
   572  	out.Write64(e.filesz)
   573  	out.Write64(e.memsz)
   574  	out.Write64(e.align)
   575  }
   576  
   577  func elf32phdr(out *OutBuf, e *ElfPhdr) {
   578  	if e.type_ == PT_LOAD {
   579  		fixElfPhdr(e)
   580  	}
   581  
   582  	out.Write32(e.type_)
   583  	out.Write32(uint32(e.off))
   584  	out.Write32(uint32(e.vaddr))
   585  	out.Write32(uint32(e.paddr))
   586  	out.Write32(uint32(e.filesz))
   587  	out.Write32(uint32(e.memsz))
   588  	out.Write32(e.flags)
   589  	out.Write32(uint32(e.align))
   590  }
   591  
   592  func elf64shdr(out *OutBuf, e *ElfShdr) {
   593  	out.Write32(e.name)
   594  	out.Write32(e.type_)
   595  	out.Write64(e.flags)
   596  	out.Write64(e.addr)
   597  	out.Write64(e.off)
   598  	out.Write64(e.size)
   599  	out.Write32(e.link)
   600  	out.Write32(e.info)
   601  	out.Write64(e.addralign)
   602  	out.Write64(e.entsize)
   603  }
   604  
   605  func elf32shdr(out *OutBuf, e *ElfShdr) {
   606  	out.Write32(e.name)
   607  	out.Write32(e.type_)
   608  	out.Write32(uint32(e.flags))
   609  	out.Write32(uint32(e.addr))
   610  	out.Write32(uint32(e.off))
   611  	out.Write32(uint32(e.size))
   612  	out.Write32(e.link)
   613  	out.Write32(e.info)
   614  	out.Write32(uint32(e.addralign))
   615  	out.Write32(uint32(e.entsize))
   616  }
   617  
   618  func elfwriteshdrs(out *OutBuf) uint32 {
   619  	if elf64 {
   620  		for i := 0; i < int(ehdr.shnum); i++ {
   621  			elf64shdr(out, shdr[i])
   622  		}
   623  		return uint32(ehdr.shnum) * ELF64SHDRSIZE
   624  	}
   625  
   626  	for i := 0; i < int(ehdr.shnum); i++ {
   627  		elf32shdr(out, shdr[i])
   628  	}
   629  	return uint32(ehdr.shnum) * ELF32SHDRSIZE
   630  }
   631  
   632  func elfsetstring(s *sym.Symbol, str string, off int) {
   633  	if nelfstr >= len(elfstr) {
   634  		Errorf(s, "too many elf strings")
   635  		errorexit()
   636  	}
   637  
   638  	elfstr[nelfstr].s = str
   639  	elfstr[nelfstr].off = off
   640  	nelfstr++
   641  }
   642  
   643  func elfwritephdrs(out *OutBuf) uint32 {
   644  	if elf64 {
   645  		for i := 0; i < int(ehdr.phnum); i++ {
   646  			elf64phdr(out, phdr[i])
   647  		}
   648  		return uint32(ehdr.phnum) * ELF64PHDRSIZE
   649  	}
   650  
   651  	for i := 0; i < int(ehdr.phnum); i++ {
   652  		elf32phdr(out, phdr[i])
   653  	}
   654  	return uint32(ehdr.phnum) * ELF32PHDRSIZE
   655  }
   656  
   657  func newElfPhdr() *ElfPhdr {
   658  	e := new(ElfPhdr)
   659  	if ehdr.phnum >= NSECT {
   660  		Errorf(nil, "too many phdrs")
   661  	} else {
   662  		phdr[ehdr.phnum] = e
   663  		ehdr.phnum++
   664  	}
   665  	if elf64 {
   666  		ehdr.shoff += ELF64PHDRSIZE
   667  	} else {
   668  		ehdr.shoff += ELF32PHDRSIZE
   669  	}
   670  	return e
   671  }
   672  
   673  func newElfShdr(name int64) *ElfShdr {
   674  	e := new(ElfShdr)
   675  	e.name = uint32(name)
   676  	e.shnum = int(ehdr.shnum)
   677  	if ehdr.shnum >= NSECT {
   678  		Errorf(nil, "too many shdrs")
   679  	} else {
   680  		shdr[ehdr.shnum] = e
   681  		ehdr.shnum++
   682  	}
   683  
   684  	return e
   685  }
   686  
   687  func getElfEhdr() *ElfEhdr {
   688  	return &ehdr
   689  }
   690  
   691  func elf64writehdr(out *OutBuf) uint32 {
   692  	out.Write(ehdr.ident[:])
   693  	out.Write16(ehdr.type_)
   694  	out.Write16(ehdr.machine)
   695  	out.Write32(ehdr.version)
   696  	out.Write64(ehdr.entry)
   697  	out.Write64(ehdr.phoff)
   698  	out.Write64(ehdr.shoff)
   699  	out.Write32(ehdr.flags)
   700  	out.Write16(ehdr.ehsize)
   701  	out.Write16(ehdr.phentsize)
   702  	out.Write16(ehdr.phnum)
   703  	out.Write16(ehdr.shentsize)
   704  	out.Write16(ehdr.shnum)
   705  	out.Write16(ehdr.shstrndx)
   706  	return ELF64HDRSIZE
   707  }
   708  
   709  func elf32writehdr(out *OutBuf) uint32 {
   710  	out.Write(ehdr.ident[:])
   711  	out.Write16(ehdr.type_)
   712  	out.Write16(ehdr.machine)
   713  	out.Write32(ehdr.version)
   714  	out.Write32(uint32(ehdr.entry))
   715  	out.Write32(uint32(ehdr.phoff))
   716  	out.Write32(uint32(ehdr.shoff))
   717  	out.Write32(ehdr.flags)
   718  	out.Write16(ehdr.ehsize)
   719  	out.Write16(ehdr.phentsize)
   720  	out.Write16(ehdr.phnum)
   721  	out.Write16(ehdr.shentsize)
   722  	out.Write16(ehdr.shnum)
   723  	out.Write16(ehdr.shstrndx)
   724  	return ELF32HDRSIZE
   725  }
   726  
   727  func elfwritehdr(out *OutBuf) uint32 {
   728  	if elf64 {
   729  		return elf64writehdr(out)
   730  	}
   731  	return elf32writehdr(out)
   732  }
   733  
   734  /* Taken directly from the definition document for ELF64 */
   735  func elfhash(name string) uint32 {
   736  	var h uint32
   737  	for i := 0; i < len(name); i++ {
   738  		h = (h << 4) + uint32(name[i])
   739  		if g := h & 0xf0000000; g != 0 {
   740  			h ^= g >> 24
   741  		}
   742  		h &= 0x0fffffff
   743  	}
   744  	return h
   745  }
   746  
   747  func Elfwritedynent(ctxt *Link, s *sym.Symbol, tag int, val uint64) {
   748  	if elf64 {
   749  		s.AddUint64(ctxt.Arch, uint64(tag))
   750  		s.AddUint64(ctxt.Arch, val)
   751  	} else {
   752  		s.AddUint32(ctxt.Arch, uint32(tag))
   753  		s.AddUint32(ctxt.Arch, uint32(val))
   754  	}
   755  }
   756  
   757  func elfwritedynentsym(ctxt *Link, s *sym.Symbol, tag int, t *sym.Symbol) {
   758  	Elfwritedynentsymplus(ctxt, s, tag, t, 0)
   759  }
   760  
   761  func Elfwritedynentsymplus(ctxt *Link, s *sym.Symbol, tag int, t *sym.Symbol, add int64) {
   762  	if elf64 {
   763  		s.AddUint64(ctxt.Arch, uint64(tag))
   764  	} else {
   765  		s.AddUint32(ctxt.Arch, uint32(tag))
   766  	}
   767  	s.AddAddrPlus(ctxt.Arch, t, add)
   768  }
   769  
   770  func elfwritedynentsymsize(ctxt *Link, s *sym.Symbol, tag int, t *sym.Symbol) {
   771  	if elf64 {
   772  		s.AddUint64(ctxt.Arch, uint64(tag))
   773  	} else {
   774  		s.AddUint32(ctxt.Arch, uint32(tag))
   775  	}
   776  	s.AddSize(ctxt.Arch, t)
   777  }
   778  
   779  func elfinterp(sh *ElfShdr, startva uint64, resoff uint64, p string) int {
   780  	interp = p
   781  	n := len(interp) + 1
   782  	sh.addr = startva + resoff - uint64(n)
   783  	sh.off = resoff - uint64(n)
   784  	sh.size = uint64(n)
   785  
   786  	return n
   787  }
   788  
   789  func elfwriteinterp(out *OutBuf) int {
   790  	sh := elfshname(".interp")
   791  	out.SeekSet(int64(sh.off))
   792  	out.WriteString(interp)
   793  	out.Write8(0)
   794  	return int(sh.size)
   795  }
   796  
   797  func elfnote(sh *ElfShdr, startva uint64, resoff uint64, sz int, alloc bool) int {
   798  	n := 3*4 + uint64(sz) + resoff%4
   799  
   800  	sh.type_ = SHT_NOTE
   801  	if alloc {
   802  		sh.flags = SHF_ALLOC
   803  	}
   804  	sh.addralign = 4
   805  	sh.addr = startva + resoff - n
   806  	sh.off = resoff - n
   807  	sh.size = n - resoff%4
   808  
   809  	return int(n)
   810  }
   811  
   812  func elfwritenotehdr(out *OutBuf, str string, namesz uint32, descsz uint32, tag uint32) *ElfShdr {
   813  	sh := elfshname(str)
   814  
   815  	// Write Elf_Note header.
   816  	out.SeekSet(int64(sh.off))
   817  
   818  	out.Write32(namesz)
   819  	out.Write32(descsz)
   820  	out.Write32(tag)
   821  
   822  	return sh
   823  }
   824  
   825  // NetBSD Signature (as per sys/exec_elf.h)
   826  const (
   827  	ELF_NOTE_NETBSD_NAMESZ  = 7
   828  	ELF_NOTE_NETBSD_DESCSZ  = 4
   829  	ELF_NOTE_NETBSD_TAG     = 1
   830  	ELF_NOTE_NETBSD_VERSION = 599000000 /* NetBSD 5.99 */
   831  )
   832  
   833  var ELF_NOTE_NETBSD_NAME = []byte("NetBSD\x00")
   834  
   835  func elfnetbsdsig(sh *ElfShdr, startva uint64, resoff uint64) int {
   836  	n := int(Rnd(ELF_NOTE_NETBSD_NAMESZ, 4) + Rnd(ELF_NOTE_NETBSD_DESCSZ, 4))
   837  	return elfnote(sh, startva, resoff, n, true)
   838  }
   839  
   840  func elfwritenetbsdsig(out *OutBuf) int {
   841  	// Write Elf_Note header.
   842  	sh := elfwritenotehdr(out, ".note.netbsd.ident", ELF_NOTE_NETBSD_NAMESZ, ELF_NOTE_NETBSD_DESCSZ, ELF_NOTE_NETBSD_TAG)
   843  
   844  	if sh == nil {
   845  		return 0
   846  	}
   847  
   848  	// Followed by NetBSD string and version.
   849  	out.Write(ELF_NOTE_NETBSD_NAME)
   850  	out.Write8(0)
   851  	out.Write32(ELF_NOTE_NETBSD_VERSION)
   852  
   853  	return int(sh.size)
   854  }
   855  
   856  // OpenBSD Signature
   857  const (
   858  	ELF_NOTE_OPENBSD_NAMESZ  = 8
   859  	ELF_NOTE_OPENBSD_DESCSZ  = 4
   860  	ELF_NOTE_OPENBSD_TAG     = 1
   861  	ELF_NOTE_OPENBSD_VERSION = 0
   862  )
   863  
   864  var ELF_NOTE_OPENBSD_NAME = []byte("OpenBSD\x00")
   865  
   866  func elfopenbsdsig(sh *ElfShdr, startva uint64, resoff uint64) int {
   867  	n := ELF_NOTE_OPENBSD_NAMESZ + ELF_NOTE_OPENBSD_DESCSZ
   868  	return elfnote(sh, startva, resoff, n, true)
   869  }
   870  
   871  func elfwriteopenbsdsig(out *OutBuf) int {
   872  	// Write Elf_Note header.
   873  	sh := elfwritenotehdr(out, ".note.openbsd.ident", ELF_NOTE_OPENBSD_NAMESZ, ELF_NOTE_OPENBSD_DESCSZ, ELF_NOTE_OPENBSD_TAG)
   874  
   875  	if sh == nil {
   876  		return 0
   877  	}
   878  
   879  	// Followed by OpenBSD string and version.
   880  	out.Write(ELF_NOTE_OPENBSD_NAME)
   881  
   882  	out.Write32(ELF_NOTE_OPENBSD_VERSION)
   883  
   884  	return int(sh.size)
   885  }
   886  
   887  func addbuildinfo(val string) {
   888  	if !strings.HasPrefix(val, "0x") {
   889  		Exitf("-B argument must start with 0x: %s", val)
   890  	}
   891  
   892  	ov := val
   893  	val = val[2:]
   894  
   895  	const maxLen = 32
   896  	if hex.DecodedLen(len(val)) > maxLen {
   897  		Exitf("-B option too long (max %d digits): %s", maxLen, ov)
   898  	}
   899  
   900  	b, err := hex.DecodeString(val)
   901  	if err != nil {
   902  		if err == hex.ErrLength {
   903  			Exitf("-B argument must have even number of digits: %s", ov)
   904  		}
   905  		if inv, ok := err.(hex.InvalidByteError); ok {
   906  			Exitf("-B argument contains invalid hex digit %c: %s", byte(inv), ov)
   907  		}
   908  		Exitf("-B argument contains invalid hex: %s", ov)
   909  	}
   910  
   911  	buildinfo = b
   912  }
   913  
   914  // Build info note
   915  const (
   916  	ELF_NOTE_BUILDINFO_NAMESZ = 4
   917  	ELF_NOTE_BUILDINFO_TAG    = 3
   918  )
   919  
   920  var ELF_NOTE_BUILDINFO_NAME = []byte("GNU\x00")
   921  
   922  func elfbuildinfo(sh *ElfShdr, startva uint64, resoff uint64) int {
   923  	n := int(ELF_NOTE_BUILDINFO_NAMESZ + Rnd(int64(len(buildinfo)), 4))
   924  	return elfnote(sh, startva, resoff, n, true)
   925  }
   926  
   927  func elfgobuildid(sh *ElfShdr, startva uint64, resoff uint64) int {
   928  	n := len(ELF_NOTE_GO_NAME) + int(Rnd(int64(len(*flagBuildid)), 4))
   929  	return elfnote(sh, startva, resoff, n, true)
   930  }
   931  
   932  func elfwritebuildinfo(out *OutBuf) int {
   933  	sh := elfwritenotehdr(out, ".note.gnu.build-id", ELF_NOTE_BUILDINFO_NAMESZ, uint32(len(buildinfo)), ELF_NOTE_BUILDINFO_TAG)
   934  	if sh == nil {
   935  		return 0
   936  	}
   937  
   938  	out.Write(ELF_NOTE_BUILDINFO_NAME)
   939  	out.Write(buildinfo)
   940  	var zero = make([]byte, 4)
   941  	out.Write(zero[:int(Rnd(int64(len(buildinfo)), 4)-int64(len(buildinfo)))])
   942  
   943  	return int(sh.size)
   944  }
   945  
   946  func elfwritegobuildid(out *OutBuf) int {
   947  	sh := elfwritenotehdr(out, ".note.go.buildid", uint32(len(ELF_NOTE_GO_NAME)), uint32(len(*flagBuildid)), ELF_NOTE_GOBUILDID_TAG)
   948  	if sh == nil {
   949  		return 0
   950  	}
   951  
   952  	out.Write(ELF_NOTE_GO_NAME)
   953  	out.Write([]byte(*flagBuildid))
   954  	var zero = make([]byte, 4)
   955  	out.Write(zero[:int(Rnd(int64(len(*flagBuildid)), 4)-int64(len(*flagBuildid)))])
   956  
   957  	return int(sh.size)
   958  }
   959  
   960  // Go specific notes
   961  const (
   962  	ELF_NOTE_GOPKGLIST_TAG = 1
   963  	ELF_NOTE_GOABIHASH_TAG = 2
   964  	ELF_NOTE_GODEPS_TAG    = 3
   965  	ELF_NOTE_GOBUILDID_TAG = 4
   966  )
   967  
   968  var ELF_NOTE_GO_NAME = []byte("Go\x00\x00")
   969  
   970  var elfverneed int
   971  
   972  type Elfaux struct {
   973  	next *Elfaux
   974  	num  int
   975  	vers string
   976  }
   977  
   978  type Elflib struct {
   979  	next *Elflib
   980  	aux  *Elfaux
   981  	file string
   982  }
   983  
   984  func addelflib(list **Elflib, file string, vers string) *Elfaux {
   985  	var lib *Elflib
   986  
   987  	for lib = *list; lib != nil; lib = lib.next {
   988  		if lib.file == file {
   989  			goto havelib
   990  		}
   991  	}
   992  	lib = new(Elflib)
   993  	lib.next = *list
   994  	lib.file = file
   995  	*list = lib
   996  
   997  havelib:
   998  	for aux := lib.aux; aux != nil; aux = aux.next {
   999  		if aux.vers == vers {
  1000  			return aux
  1001  		}
  1002  	}
  1003  	aux := new(Elfaux)
  1004  	aux.next = lib.aux
  1005  	aux.vers = vers
  1006  	lib.aux = aux
  1007  
  1008  	return aux
  1009  }
  1010  
  1011  func elfdynhash(ctxt *Link) {
  1012  	if !ctxt.IsELF {
  1013  		return
  1014  	}
  1015  
  1016  	nsym := Nelfsym
  1017  	s := ctxt.Syms.Lookup(".hash", 0)
  1018  	s.Type = sym.SELFROSECT
  1019  	s.Attr |= sym.AttrReachable
  1020  
  1021  	i := nsym
  1022  	nbucket := 1
  1023  	for i > 0 {
  1024  		nbucket++
  1025  		i >>= 1
  1026  	}
  1027  
  1028  	var needlib *Elflib
  1029  	need := make([]*Elfaux, nsym)
  1030  	chain := make([]uint32, nsym)
  1031  	buckets := make([]uint32, nbucket)
  1032  
  1033  	for _, sy := range ctxt.Syms.Allsym {
  1034  		if sy.Dynid <= 0 {
  1035  			continue
  1036  		}
  1037  
  1038  		if sy.Dynimpvers != "" {
  1039  			need[sy.Dynid] = addelflib(&needlib, sy.Dynimplib, sy.Dynimpvers)
  1040  		}
  1041  
  1042  		name := sy.Extname
  1043  		hc := elfhash(name)
  1044  
  1045  		b := hc % uint32(nbucket)
  1046  		chain[sy.Dynid] = buckets[b]
  1047  		buckets[b] = uint32(sy.Dynid)
  1048  	}
  1049  
  1050  	// s390x (ELF64) hash table entries are 8 bytes
  1051  	if ctxt.Arch.Family == sys.S390X {
  1052  		s.AddUint64(ctxt.Arch, uint64(nbucket))
  1053  		s.AddUint64(ctxt.Arch, uint64(nsym))
  1054  		for i := 0; i < nbucket; i++ {
  1055  			s.AddUint64(ctxt.Arch, uint64(buckets[i]))
  1056  		}
  1057  		for i := 0; i < nsym; i++ {
  1058  			s.AddUint64(ctxt.Arch, uint64(chain[i]))
  1059  		}
  1060  	} else {
  1061  		s.AddUint32(ctxt.Arch, uint32(nbucket))
  1062  		s.AddUint32(ctxt.Arch, uint32(nsym))
  1063  		for i := 0; i < nbucket; i++ {
  1064  			s.AddUint32(ctxt.Arch, buckets[i])
  1065  		}
  1066  		for i := 0; i < nsym; i++ {
  1067  			s.AddUint32(ctxt.Arch, chain[i])
  1068  		}
  1069  	}
  1070  
  1071  	// version symbols
  1072  	dynstr := ctxt.Syms.Lookup(".dynstr", 0)
  1073  
  1074  	s = ctxt.Syms.Lookup(".gnu.version_r", 0)
  1075  	i = 2
  1076  	nfile := 0
  1077  	for l := needlib; l != nil; l = l.next {
  1078  		nfile++
  1079  
  1080  		// header
  1081  		s.AddUint16(ctxt.Arch, 1) // table version
  1082  		j := 0
  1083  		for x := l.aux; x != nil; x = x.next {
  1084  			j++
  1085  		}
  1086  		s.AddUint16(ctxt.Arch, uint16(j))                         // aux count
  1087  		s.AddUint32(ctxt.Arch, uint32(Addstring(dynstr, l.file))) // file string offset
  1088  		s.AddUint32(ctxt.Arch, 16)                                // offset from header to first aux
  1089  		if l.next != nil {
  1090  			s.AddUint32(ctxt.Arch, 16+uint32(j)*16) // offset from this header to next
  1091  		} else {
  1092  			s.AddUint32(ctxt.Arch, 0)
  1093  		}
  1094  
  1095  		for x := l.aux; x != nil; x = x.next {
  1096  			x.num = i
  1097  			i++
  1098  
  1099  			// aux struct
  1100  			s.AddUint32(ctxt.Arch, elfhash(x.vers))                   // hash
  1101  			s.AddUint16(ctxt.Arch, 0)                                 // flags
  1102  			s.AddUint16(ctxt.Arch, uint16(x.num))                     // other - index we refer to this by
  1103  			s.AddUint32(ctxt.Arch, uint32(Addstring(dynstr, x.vers))) // version string offset
  1104  			if x.next != nil {
  1105  				s.AddUint32(ctxt.Arch, 16) // offset from this aux to next
  1106  			} else {
  1107  				s.AddUint32(ctxt.Arch, 0)
  1108  			}
  1109  		}
  1110  	}
  1111  
  1112  	// version references
  1113  	s = ctxt.Syms.Lookup(".gnu.version", 0)
  1114  
  1115  	for i := 0; i < nsym; i++ {
  1116  		if i == 0 {
  1117  			s.AddUint16(ctxt.Arch, 0) // first entry - no symbol
  1118  		} else if need[i] == nil {
  1119  			s.AddUint16(ctxt.Arch, 1) // global
  1120  		} else {
  1121  			s.AddUint16(ctxt.Arch, uint16(need[i].num))
  1122  		}
  1123  	}
  1124  
  1125  	s = ctxt.Syms.Lookup(".dynamic", 0)
  1126  	elfverneed = nfile
  1127  	if elfverneed != 0 {
  1128  		elfwritedynentsym(ctxt, s, DT_VERNEED, ctxt.Syms.Lookup(".gnu.version_r", 0))
  1129  		Elfwritedynent(ctxt, s, DT_VERNEEDNUM, uint64(nfile))
  1130  		elfwritedynentsym(ctxt, s, DT_VERSYM, ctxt.Syms.Lookup(".gnu.version", 0))
  1131  	}
  1132  
  1133  	sy := ctxt.Syms.Lookup(elfRelType+".plt", 0)
  1134  	if sy.Size > 0 {
  1135  		if elfRelType == ".rela" {
  1136  			Elfwritedynent(ctxt, s, DT_PLTREL, DT_RELA)
  1137  		} else {
  1138  			Elfwritedynent(ctxt, s, DT_PLTREL, DT_REL)
  1139  		}
  1140  		elfwritedynentsymsize(ctxt, s, DT_PLTRELSZ, sy)
  1141  		elfwritedynentsym(ctxt, s, DT_JMPREL, sy)
  1142  	}
  1143  
  1144  	Elfwritedynent(ctxt, s, DT_NULL, 0)
  1145  }
  1146  
  1147  func elfphload(seg *sym.Segment) *ElfPhdr {
  1148  	ph := newElfPhdr()
  1149  	ph.type_ = PT_LOAD
  1150  	if seg.Rwx&4 != 0 {
  1151  		ph.flags |= PF_R
  1152  	}
  1153  	if seg.Rwx&2 != 0 {
  1154  		ph.flags |= PF_W
  1155  	}
  1156  	if seg.Rwx&1 != 0 {
  1157  		ph.flags |= PF_X
  1158  	}
  1159  	ph.vaddr = seg.Vaddr
  1160  	ph.paddr = seg.Vaddr
  1161  	ph.memsz = seg.Length
  1162  	ph.off = seg.Fileoff
  1163  	ph.filesz = seg.Filelen
  1164  	ph.align = uint64(*FlagRound)
  1165  
  1166  	return ph
  1167  }
  1168  
  1169  func elfphrelro(seg *sym.Segment) {
  1170  	ph := newElfPhdr()
  1171  	ph.type_ = PT_GNU_RELRO
  1172  	ph.vaddr = seg.Vaddr
  1173  	ph.paddr = seg.Vaddr
  1174  	ph.memsz = seg.Length
  1175  	ph.off = seg.Fileoff
  1176  	ph.filesz = seg.Filelen
  1177  	ph.align = uint64(*FlagRound)
  1178  }
  1179  
  1180  func elfshname(name string) *ElfShdr {
  1181  	for i := 0; i < nelfstr; i++ {
  1182  		if name != elfstr[i].s {
  1183  			continue
  1184  		}
  1185  		off := elfstr[i].off
  1186  		for i = 0; i < int(ehdr.shnum); i++ {
  1187  			sh := shdr[i]
  1188  			if sh.name == uint32(off) {
  1189  				return sh
  1190  			}
  1191  		}
  1192  		return newElfShdr(int64(off))
  1193  	}
  1194  	Exitf("cannot find elf name %s", name)
  1195  	return nil
  1196  }
  1197  
  1198  // Create an ElfShdr for the section with name.
  1199  // Create a duplicate if one already exists with that name
  1200  func elfshnamedup(name string) *ElfShdr {
  1201  	for i := 0; i < nelfstr; i++ {
  1202  		if name == elfstr[i].s {
  1203  			off := elfstr[i].off
  1204  			return newElfShdr(int64(off))
  1205  		}
  1206  	}
  1207  
  1208  	Errorf(nil, "cannot find elf name %s", name)
  1209  	errorexit()
  1210  	return nil
  1211  }
  1212  
  1213  func elfshalloc(sect *sym.Section) *ElfShdr {
  1214  	sh := elfshname(sect.Name)
  1215  	sect.Elfsect = sh
  1216  	return sh
  1217  }
  1218  
  1219  func elfshbits(linkmode LinkMode, sect *sym.Section) *ElfShdr {
  1220  	var sh *ElfShdr
  1221  
  1222  	if sect.Name == ".text" {
  1223  		if sect.Elfsect == nil {
  1224  			sect.Elfsect = elfshnamedup(sect.Name)
  1225  		}
  1226  		sh = sect.Elfsect.(*ElfShdr)
  1227  	} else {
  1228  		sh = elfshalloc(sect)
  1229  	}
  1230  
  1231  	// If this section has already been set up as a note, we assume type_ and
  1232  	// flags are already correct, but the other fields still need filling in.
  1233  	if sh.type_ == SHT_NOTE {
  1234  		if linkmode != LinkExternal {
  1235  			// TODO(mwhudson): the approach here will work OK when
  1236  			// linking internally for notes that we want to be included
  1237  			// in a loadable segment (e.g. the abihash note) but not for
  1238  			// notes that we do not want to be mapped (e.g. the package
  1239  			// list note). The real fix is probably to define new values
  1240  			// for Symbol.Type corresponding to mapped and unmapped notes
  1241  			// and handle them in dodata().
  1242  			Errorf(nil, "sh.type_ == SHT_NOTE in elfshbits when linking internally")
  1243  		}
  1244  		sh.addralign = uint64(sect.Align)
  1245  		sh.size = sect.Length
  1246  		sh.off = sect.Seg.Fileoff + sect.Vaddr - sect.Seg.Vaddr
  1247  		return sh
  1248  	}
  1249  	if sh.type_ > 0 {
  1250  		return sh
  1251  	}
  1252  
  1253  	if sect.Vaddr < sect.Seg.Vaddr+sect.Seg.Filelen {
  1254  		sh.type_ = SHT_PROGBITS
  1255  	} else {
  1256  		sh.type_ = SHT_NOBITS
  1257  	}
  1258  	sh.flags = SHF_ALLOC
  1259  	if sect.Rwx&1 != 0 {
  1260  		sh.flags |= SHF_EXECINSTR
  1261  	}
  1262  	if sect.Rwx&2 != 0 {
  1263  		sh.flags |= SHF_WRITE
  1264  	}
  1265  	if sect.Name == ".tbss" {
  1266  		sh.flags |= SHF_TLS
  1267  		sh.type_ = SHT_NOBITS
  1268  	}
  1269  	if strings.HasPrefix(sect.Name, ".debug") {
  1270  		sh.flags = 0
  1271  	}
  1272  
  1273  	if linkmode != LinkExternal {
  1274  		sh.addr = sect.Vaddr
  1275  	}
  1276  	sh.addralign = uint64(sect.Align)
  1277  	sh.size = sect.Length
  1278  	if sect.Name != ".tbss" {
  1279  		sh.off = sect.Seg.Fileoff + sect.Vaddr - sect.Seg.Vaddr
  1280  	}
  1281  
  1282  	return sh
  1283  }
  1284  
  1285  func elfshreloc(arch *sys.Arch, sect *sym.Section) *ElfShdr {
  1286  	// If main section is SHT_NOBITS, nothing to relocate.
  1287  	// Also nothing to relocate in .shstrtab or notes.
  1288  	if sect.Vaddr >= sect.Seg.Vaddr+sect.Seg.Filelen {
  1289  		return nil
  1290  	}
  1291  	if sect.Name == ".shstrtab" || sect.Name == ".tbss" {
  1292  		return nil
  1293  	}
  1294  	if sect.Elfsect.(*ElfShdr).type_ == SHT_NOTE {
  1295  		return nil
  1296  	}
  1297  
  1298  	var typ int
  1299  	if elfRelType == ".rela" {
  1300  		typ = SHT_RELA
  1301  	} else {
  1302  		typ = SHT_REL
  1303  	}
  1304  
  1305  	sh := elfshname(elfRelType + sect.Name)
  1306  	// There could be multiple text sections but each needs
  1307  	// its own .rela.text.
  1308  
  1309  	if sect.Name == ".text" {
  1310  		if sh.info != 0 && sh.info != uint32(sect.Elfsect.(*ElfShdr).shnum) {
  1311  			sh = elfshnamedup(elfRelType + sect.Name)
  1312  		}
  1313  	}
  1314  
  1315  	sh.type_ = uint32(typ)
  1316  	sh.entsize = uint64(arch.RegSize) * 2
  1317  	if typ == SHT_RELA {
  1318  		sh.entsize += uint64(arch.RegSize)
  1319  	}
  1320  	sh.link = uint32(elfshname(".symtab").shnum)
  1321  	sh.info = uint32(sect.Elfsect.(*ElfShdr).shnum)
  1322  	sh.off = sect.Reloff
  1323  	sh.size = sect.Rellen
  1324  	sh.addralign = uint64(arch.RegSize)
  1325  	return sh
  1326  }
  1327  
  1328  func elfrelocsect(ctxt *Link, sect *sym.Section, syms []*sym.Symbol) {
  1329  	// If main section is SHT_NOBITS, nothing to relocate.
  1330  	// Also nothing to relocate in .shstrtab.
  1331  	if sect.Vaddr >= sect.Seg.Vaddr+sect.Seg.Filelen {
  1332  		return
  1333  	}
  1334  	if sect.Name == ".shstrtab" {
  1335  		return
  1336  	}
  1337  
  1338  	sect.Reloff = uint64(ctxt.Out.Offset())
  1339  	for i, s := range syms {
  1340  		if !s.Attr.Reachable() {
  1341  			continue
  1342  		}
  1343  		if uint64(s.Value) >= sect.Vaddr {
  1344  			syms = syms[i:]
  1345  			break
  1346  		}
  1347  	}
  1348  
  1349  	eaddr := int32(sect.Vaddr + sect.Length)
  1350  	for _, s := range syms {
  1351  		if !s.Attr.Reachable() {
  1352  			continue
  1353  		}
  1354  		if s.Value >= int64(eaddr) {
  1355  			break
  1356  		}
  1357  		for ri := 0; ri < len(s.R); ri++ {
  1358  			r := &s.R[ri]
  1359  			if r.Done {
  1360  				continue
  1361  			}
  1362  			if r.Xsym == nil {
  1363  				Errorf(s, "missing xsym in relocation %#v %#v", r.Sym.Name, s)
  1364  				continue
  1365  			}
  1366  			if r.Xsym.ElfsymForReloc() == 0 {
  1367  				Errorf(s, "reloc %d (%s) to non-elf symbol %s (outer=%s) %d (%s)", r.Type, sym.RelocName(ctxt.Arch, r.Type), r.Sym.Name, r.Xsym.Name, r.Sym.Type, r.Sym.Type)
  1368  			}
  1369  			if !r.Xsym.Attr.Reachable() {
  1370  				Errorf(s, "unreachable reloc %d (%s) target %v", r.Type, sym.RelocName(ctxt.Arch, r.Type), r.Xsym.Name)
  1371  			}
  1372  			if !Thearch.Elfreloc1(ctxt, r, int64(uint64(s.Value+int64(r.Off))-sect.Vaddr)) {
  1373  				Errorf(s, "unsupported obj reloc %d (%s)/%d to %s", r.Type, sym.RelocName(ctxt.Arch, r.Type), r.Siz, r.Sym.Name)
  1374  			}
  1375  		}
  1376  	}
  1377  
  1378  	sect.Rellen = uint64(ctxt.Out.Offset()) - sect.Reloff
  1379  }
  1380  
  1381  func Elfemitreloc(ctxt *Link) {
  1382  	for ctxt.Out.Offset()&7 != 0 {
  1383  		ctxt.Out.Write8(0)
  1384  	}
  1385  
  1386  	for _, sect := range Segtext.Sections {
  1387  		if sect.Name == ".text" {
  1388  			elfrelocsect(ctxt, sect, ctxt.Textp)
  1389  		} else {
  1390  			elfrelocsect(ctxt, sect, datap)
  1391  		}
  1392  	}
  1393  
  1394  	for _, sect := range Segrodata.Sections {
  1395  		elfrelocsect(ctxt, sect, datap)
  1396  	}
  1397  	for _, sect := range Segrelrodata.Sections {
  1398  		elfrelocsect(ctxt, sect, datap)
  1399  	}
  1400  	for _, sect := range Segdata.Sections {
  1401  		elfrelocsect(ctxt, sect, datap)
  1402  	}
  1403  	for _, sect := range Segdwarf.Sections {
  1404  		elfrelocsect(ctxt, sect, dwarfp)
  1405  	}
  1406  }
  1407  
  1408  func addgonote(ctxt *Link, sectionName string, tag uint32, desc []byte) {
  1409  	s := ctxt.Syms.Lookup(sectionName, 0)
  1410  	s.Attr |= sym.AttrReachable
  1411  	s.Type = sym.SELFROSECT
  1412  	// namesz
  1413  	s.AddUint32(ctxt.Arch, uint32(len(ELF_NOTE_GO_NAME)))
  1414  	// descsz
  1415  	s.AddUint32(ctxt.Arch, uint32(len(desc)))
  1416  	// tag
  1417  	s.AddUint32(ctxt.Arch, tag)
  1418  	// name + padding
  1419  	s.P = append(s.P, ELF_NOTE_GO_NAME...)
  1420  	for len(s.P)%4 != 0 {
  1421  		s.P = append(s.P, 0)
  1422  	}
  1423  	// desc + padding
  1424  	s.P = append(s.P, desc...)
  1425  	for len(s.P)%4 != 0 {
  1426  		s.P = append(s.P, 0)
  1427  	}
  1428  	s.Size = int64(len(s.P))
  1429  	s.Align = 4
  1430  }
  1431  
  1432  func (ctxt *Link) doelf() {
  1433  	if !ctxt.IsELF {
  1434  		return
  1435  	}
  1436  
  1437  	/* predefine strings we need for section headers */
  1438  	shstrtab := ctxt.Syms.Lookup(".shstrtab", 0)
  1439  
  1440  	shstrtab.Type = sym.SELFROSECT
  1441  	shstrtab.Attr |= sym.AttrReachable
  1442  
  1443  	Addstring(shstrtab, "")
  1444  	Addstring(shstrtab, ".text")
  1445  	Addstring(shstrtab, ".noptrdata")
  1446  	Addstring(shstrtab, ".data")
  1447  	Addstring(shstrtab, ".bss")
  1448  	Addstring(shstrtab, ".noptrbss")
  1449  
  1450  	// generate .tbss section for dynamic internal linker or external
  1451  	// linking, so that various binutils could correctly calculate
  1452  	// PT_TLS size. See https://golang.org/issue/5200.
  1453  	if !*FlagD || ctxt.LinkMode == LinkExternal {
  1454  		Addstring(shstrtab, ".tbss")
  1455  	}
  1456  	if ctxt.HeadType == objabi.Hnetbsd {
  1457  		Addstring(shstrtab, ".note.netbsd.ident")
  1458  	}
  1459  	if ctxt.HeadType == objabi.Hopenbsd {
  1460  		Addstring(shstrtab, ".note.openbsd.ident")
  1461  	}
  1462  	if len(buildinfo) > 0 {
  1463  		Addstring(shstrtab, ".note.gnu.build-id")
  1464  	}
  1465  	if *flagBuildid != "" {
  1466  		Addstring(shstrtab, ".note.go.buildid")
  1467  	}
  1468  	Addstring(shstrtab, ".elfdata")
  1469  	Addstring(shstrtab, ".rodata")
  1470  	// See the comment about data.rel.ro.FOO section names in data.go.
  1471  	relro_prefix := ""
  1472  	if ctxt.UseRelro() {
  1473  		Addstring(shstrtab, ".data.rel.ro")
  1474  		relro_prefix = ".data.rel.ro"
  1475  	}
  1476  	Addstring(shstrtab, relro_prefix+".typelink")
  1477  	Addstring(shstrtab, relro_prefix+".itablink")
  1478  	Addstring(shstrtab, relro_prefix+".gosymtab")
  1479  	Addstring(shstrtab, relro_prefix+".gopclntab")
  1480  
  1481  	if ctxt.LinkMode == LinkExternal {
  1482  		*FlagD = true
  1483  
  1484  		Addstring(shstrtab, elfRelType+".text")
  1485  		Addstring(shstrtab, elfRelType+".rodata")
  1486  		Addstring(shstrtab, elfRelType+relro_prefix+".typelink")
  1487  		Addstring(shstrtab, elfRelType+relro_prefix+".itablink")
  1488  		Addstring(shstrtab, elfRelType+relro_prefix+".gosymtab")
  1489  		Addstring(shstrtab, elfRelType+relro_prefix+".gopclntab")
  1490  		Addstring(shstrtab, elfRelType+".noptrdata")
  1491  		Addstring(shstrtab, elfRelType+".data")
  1492  		if ctxt.UseRelro() {
  1493  			Addstring(shstrtab, elfRelType+".data.rel.ro")
  1494  		}
  1495  
  1496  		// add a .note.GNU-stack section to mark the stack as non-executable
  1497  		Addstring(shstrtab, ".note.GNU-stack")
  1498  
  1499  		if ctxt.BuildMode == BuildModeShared {
  1500  			Addstring(shstrtab, ".note.go.abihash")
  1501  			Addstring(shstrtab, ".note.go.pkg-list")
  1502  			Addstring(shstrtab, ".note.go.deps")
  1503  		}
  1504  	}
  1505  
  1506  	hasinitarr := ctxt.linkShared
  1507  
  1508  	/* shared library initializer */
  1509  	switch ctxt.BuildMode {
  1510  	case BuildModeCArchive, BuildModeCShared, BuildModeShared, BuildModePlugin:
  1511  		hasinitarr = true
  1512  	}
  1513  
  1514  	if hasinitarr {
  1515  		Addstring(shstrtab, ".init_array")
  1516  		Addstring(shstrtab, elfRelType+".init_array")
  1517  	}
  1518  
  1519  	if !*FlagS {
  1520  		Addstring(shstrtab, ".symtab")
  1521  		Addstring(shstrtab, ".strtab")
  1522  		dwarfaddshstrings(ctxt, shstrtab)
  1523  	}
  1524  
  1525  	Addstring(shstrtab, ".shstrtab")
  1526  
  1527  	if !*FlagD { /* -d suppresses dynamic loader format */
  1528  		Addstring(shstrtab, ".interp")
  1529  		Addstring(shstrtab, ".hash")
  1530  		Addstring(shstrtab, ".got")
  1531  		if ctxt.Arch.Family == sys.PPC64 {
  1532  			Addstring(shstrtab, ".glink")
  1533  		}
  1534  		Addstring(shstrtab, ".got.plt")
  1535  		Addstring(shstrtab, ".dynamic")
  1536  		Addstring(shstrtab, ".dynsym")
  1537  		Addstring(shstrtab, ".dynstr")
  1538  		Addstring(shstrtab, elfRelType)
  1539  		Addstring(shstrtab, elfRelType+".plt")
  1540  
  1541  		Addstring(shstrtab, ".plt")
  1542  		Addstring(shstrtab, ".gnu.version")
  1543  		Addstring(shstrtab, ".gnu.version_r")
  1544  
  1545  		/* dynamic symbol table - first entry all zeros */
  1546  		s := ctxt.Syms.Lookup(".dynsym", 0)
  1547  
  1548  		s.Type = sym.SELFROSECT
  1549  		s.Attr |= sym.AttrReachable
  1550  		if elf64 {
  1551  			s.Size += ELF64SYMSIZE
  1552  		} else {
  1553  			s.Size += ELF32SYMSIZE
  1554  		}
  1555  
  1556  		/* dynamic string table */
  1557  		s = ctxt.Syms.Lookup(".dynstr", 0)
  1558  
  1559  		s.Type = sym.SELFROSECT
  1560  		s.Attr |= sym.AttrReachable
  1561  		if s.Size == 0 {
  1562  			Addstring(s, "")
  1563  		}
  1564  		dynstr := s
  1565  
  1566  		/* relocation table */
  1567  		s = ctxt.Syms.Lookup(elfRelType, 0)
  1568  		s.Attr |= sym.AttrReachable
  1569  		s.Type = sym.SELFROSECT
  1570  
  1571  		/* global offset table */
  1572  		s = ctxt.Syms.Lookup(".got", 0)
  1573  
  1574  		s.Attr |= sym.AttrReachable
  1575  		s.Type = sym.SELFGOT // writable
  1576  
  1577  		/* ppc64 glink resolver */
  1578  		if ctxt.Arch.Family == sys.PPC64 {
  1579  			s := ctxt.Syms.Lookup(".glink", 0)
  1580  			s.Attr |= sym.AttrReachable
  1581  			s.Type = sym.SELFRXSECT
  1582  		}
  1583  
  1584  		/* hash */
  1585  		s = ctxt.Syms.Lookup(".hash", 0)
  1586  
  1587  		s.Attr |= sym.AttrReachable
  1588  		s.Type = sym.SELFROSECT
  1589  
  1590  		s = ctxt.Syms.Lookup(".got.plt", 0)
  1591  		s.Attr |= sym.AttrReachable
  1592  		s.Type = sym.SELFSECT // writable
  1593  
  1594  		s = ctxt.Syms.Lookup(".plt", 0)
  1595  
  1596  		s.Attr |= sym.AttrReachable
  1597  		if ctxt.Arch.Family == sys.PPC64 {
  1598  			// In the ppc64 ABI, .plt is a data section
  1599  			// written by the dynamic linker.
  1600  			s.Type = sym.SELFSECT
  1601  		} else {
  1602  			s.Type = sym.SELFRXSECT
  1603  		}
  1604  
  1605  		Thearch.Elfsetupplt(ctxt)
  1606  
  1607  		s = ctxt.Syms.Lookup(elfRelType+".plt", 0)
  1608  		s.Attr |= sym.AttrReachable
  1609  		s.Type = sym.SELFROSECT
  1610  
  1611  		s = ctxt.Syms.Lookup(".gnu.version", 0)
  1612  		s.Attr |= sym.AttrReachable
  1613  		s.Type = sym.SELFROSECT
  1614  
  1615  		s = ctxt.Syms.Lookup(".gnu.version_r", 0)
  1616  		s.Attr |= sym.AttrReachable
  1617  		s.Type = sym.SELFROSECT
  1618  
  1619  		/* define dynamic elf table */
  1620  		s = ctxt.Syms.Lookup(".dynamic", 0)
  1621  
  1622  		s.Attr |= sym.AttrReachable
  1623  		s.Type = sym.SELFSECT // writable
  1624  
  1625  		/*
  1626  		 * .dynamic table
  1627  		 */
  1628  		elfwritedynentsym(ctxt, s, DT_HASH, ctxt.Syms.Lookup(".hash", 0))
  1629  
  1630  		elfwritedynentsym(ctxt, s, DT_SYMTAB, ctxt.Syms.Lookup(".dynsym", 0))
  1631  		if elf64 {
  1632  			Elfwritedynent(ctxt, s, DT_SYMENT, ELF64SYMSIZE)
  1633  		} else {
  1634  			Elfwritedynent(ctxt, s, DT_SYMENT, ELF32SYMSIZE)
  1635  		}
  1636  		elfwritedynentsym(ctxt, s, DT_STRTAB, ctxt.Syms.Lookup(".dynstr", 0))
  1637  		elfwritedynentsymsize(ctxt, s, DT_STRSZ, ctxt.Syms.Lookup(".dynstr", 0))
  1638  		if elfRelType == ".rela" {
  1639  			elfwritedynentsym(ctxt, s, DT_RELA, ctxt.Syms.Lookup(".rela", 0))
  1640  			elfwritedynentsymsize(ctxt, s, DT_RELASZ, ctxt.Syms.Lookup(".rela", 0))
  1641  			Elfwritedynent(ctxt, s, DT_RELAENT, ELF64RELASIZE)
  1642  		} else {
  1643  			elfwritedynentsym(ctxt, s, DT_REL, ctxt.Syms.Lookup(".rel", 0))
  1644  			elfwritedynentsymsize(ctxt, s, DT_RELSZ, ctxt.Syms.Lookup(".rel", 0))
  1645  			Elfwritedynent(ctxt, s, DT_RELENT, ELF32RELSIZE)
  1646  		}
  1647  
  1648  		if rpath.val != "" {
  1649  			Elfwritedynent(ctxt, s, DT_RUNPATH, uint64(Addstring(dynstr, rpath.val)))
  1650  		}
  1651  
  1652  		if ctxt.Arch.Family == sys.PPC64 {
  1653  			elfwritedynentsym(ctxt, s, DT_PLTGOT, ctxt.Syms.Lookup(".plt", 0))
  1654  		} else if ctxt.Arch.Family == sys.S390X {
  1655  			elfwritedynentsym(ctxt, s, DT_PLTGOT, ctxt.Syms.Lookup(".got", 0))
  1656  		} else {
  1657  			elfwritedynentsym(ctxt, s, DT_PLTGOT, ctxt.Syms.Lookup(".got.plt", 0))
  1658  		}
  1659  
  1660  		if ctxt.Arch.Family == sys.PPC64 {
  1661  			Elfwritedynent(ctxt, s, DT_PPC64_OPT, 0)
  1662  		}
  1663  
  1664  		// Solaris dynamic linker can't handle an empty .rela.plt if
  1665  		// DT_JMPREL is emitted so we have to defer generation of DT_PLTREL,
  1666  		// DT_PLTRELSZ, and DT_JMPREL dynamic entries until after we know the
  1667  		// size of .rel(a).plt section.
  1668  		Elfwritedynent(ctxt, s, DT_DEBUG, 0)
  1669  	}
  1670  
  1671  	if ctxt.BuildMode == BuildModeShared {
  1672  		// The go.link.abihashbytes symbol will be pointed at the appropriate
  1673  		// part of the .note.go.abihash section in data.go:func address().
  1674  		s := ctxt.Syms.Lookup("go.link.abihashbytes", 0)
  1675  		s.Attr |= sym.AttrLocal
  1676  		s.Type = sym.SRODATA
  1677  		s.Attr |= sym.AttrSpecial
  1678  		s.Attr |= sym.AttrReachable
  1679  		s.Size = int64(sha1.Size)
  1680  
  1681  		sort.Sort(byPkg(ctxt.Library))
  1682  		h := sha1.New()
  1683  		for _, l := range ctxt.Library {
  1684  			io.WriteString(h, l.Hash)
  1685  		}
  1686  		addgonote(ctxt, ".note.go.abihash", ELF_NOTE_GOABIHASH_TAG, h.Sum([]byte{}))
  1687  		addgonote(ctxt, ".note.go.pkg-list", ELF_NOTE_GOPKGLIST_TAG, pkglistfornote)
  1688  		var deplist []string
  1689  		for _, shlib := range ctxt.Shlibs {
  1690  			deplist = append(deplist, filepath.Base(shlib.Path))
  1691  		}
  1692  		addgonote(ctxt, ".note.go.deps", ELF_NOTE_GODEPS_TAG, []byte(strings.Join(deplist, "\n")))
  1693  	}
  1694  
  1695  	if ctxt.LinkMode == LinkExternal && *flagBuildid != "" {
  1696  		addgonote(ctxt, ".note.go.buildid", ELF_NOTE_GOBUILDID_TAG, []byte(*flagBuildid))
  1697  	}
  1698  
  1699  	if *Lkenclave != "" {
  1700  		Addstring(shstrtab, ".encl")
  1701  		encl, err := ioutil.ReadFile(*Lkenclave)
  1702  		if err != nil {
  1703  			log.Fatalf(err.Error())
  1704  		}
  1705  		if err = os.Remove(*Lkenclave); err != nil {
  1706  			log.Fatalf(err.Error())
  1707  		}
  1708  		addgonote(ctxt, ".encl", 5, encl)
  1709  	}
  1710  }
  1711  
  1712  // Do not write DT_NULL.  elfdynhash will finish it.
  1713  func shsym(sh *ElfShdr, s *sym.Symbol) {
  1714  	addr := Symaddr(s)
  1715  	if sh.flags&SHF_ALLOC != 0 {
  1716  		sh.addr = uint64(addr)
  1717  	}
  1718  	sh.off = uint64(datoff(s, addr))
  1719  	sh.size = uint64(s.Size)
  1720  }
  1721  
  1722  func phsh(ph *ElfPhdr, sh *ElfShdr) {
  1723  	ph.vaddr = sh.addr
  1724  	ph.paddr = ph.vaddr
  1725  	ph.off = sh.off
  1726  	ph.filesz = sh.size
  1727  	ph.memsz = sh.size
  1728  	ph.align = sh.addralign
  1729  }
  1730  
  1731  func Asmbelfsetup() {
  1732  	/* This null SHdr must appear before all others */
  1733  	elfshname("")
  1734  
  1735  	for _, sect := range Segtext.Sections {
  1736  		// There could be multiple .text sections. Instead check the Elfsect
  1737  		// field to determine if already has an ElfShdr and if not, create one.
  1738  		if sect.Name == ".text" {
  1739  			if sect.Elfsect == nil {
  1740  				sect.Elfsect = elfshnamedup(sect.Name)
  1741  			}
  1742  		} else {
  1743  			elfshalloc(sect)
  1744  		}
  1745  	}
  1746  	for _, sect := range Segrodata.Sections {
  1747  		elfshalloc(sect)
  1748  	}
  1749  	for _, sect := range Segrelrodata.Sections {
  1750  		elfshalloc(sect)
  1751  	}
  1752  	for _, sect := range Segdata.Sections {
  1753  		elfshalloc(sect)
  1754  	}
  1755  	for _, sect := range Segdwarf.Sections {
  1756  		elfshalloc(sect)
  1757  	}
  1758  }
  1759  
  1760  func Asmbelf(ctxt *Link, symo int64) {
  1761  	eh := getElfEhdr()
  1762  	switch ctxt.Arch.Family {
  1763  	default:
  1764  		Exitf("unknown architecture in asmbelf: %v", ctxt.Arch.Family)
  1765  	case sys.MIPS, sys.MIPS64:
  1766  		eh.machine = EM_MIPS
  1767  	case sys.ARM:
  1768  		eh.machine = EM_ARM
  1769  	case sys.AMD64:
  1770  		eh.machine = EM_X86_64
  1771  	case sys.ARM64:
  1772  		eh.machine = EM_AARCH64
  1773  	case sys.I386:
  1774  		eh.machine = EM_386
  1775  	case sys.PPC64:
  1776  		eh.machine = EM_PPC64
  1777  	case sys.S390X:
  1778  		eh.machine = EM_S390
  1779  	}
  1780  
  1781  	elfreserve := int64(ELFRESERVE)
  1782  
  1783  	numtext := int64(0)
  1784  	for _, sect := range Segtext.Sections {
  1785  		if sect.Name == ".text" {
  1786  			numtext++
  1787  		}
  1788  	}
  1789  
  1790  	// If there are multiple text sections, extra space is needed
  1791  	// in the elfreserve for the additional .text and .rela.text
  1792  	// section headers.  It can handle 4 extra now. Headers are
  1793  	// 64 bytes.
  1794  
  1795  	if numtext > 4 {
  1796  		elfreserve += elfreserve + numtext*64*2
  1797  	}
  1798  
  1799  	startva := *FlagTextAddr - int64(HEADR)
  1800  	resoff := elfreserve
  1801  
  1802  	var pph *ElfPhdr
  1803  	var pnote *ElfPhdr
  1804  	if ctxt.LinkMode == LinkExternal {
  1805  		/* skip program headers */
  1806  		eh.phoff = 0
  1807  
  1808  		eh.phentsize = 0
  1809  
  1810  		if ctxt.BuildMode == BuildModeShared {
  1811  			sh := elfshname(".note.go.pkg-list")
  1812  			sh.type_ = SHT_NOTE
  1813  			sh = elfshname(".note.go.abihash")
  1814  			sh.type_ = SHT_NOTE
  1815  			sh.flags = SHF_ALLOC
  1816  			sh = elfshname(".note.go.deps")
  1817  			sh.type_ = SHT_NOTE
  1818  		}
  1819  
  1820  		if *flagBuildid != "" {
  1821  			sh := elfshname(".note.go.buildid")
  1822  			sh.type_ = SHT_NOTE
  1823  			sh.flags = SHF_ALLOC
  1824  		}
  1825  
  1826  		if *Lkenclave != "" {
  1827  			sh := elfshname(".encl")
  1828  			sh.type_ = SHT_NOTE
  1829  			sh.flags = SHF_ALLOC
  1830  		}
  1831  
  1832  		goto elfobj
  1833  	}
  1834  
  1835  	/* program header info */
  1836  	pph = newElfPhdr()
  1837  
  1838  	pph.type_ = PT_PHDR
  1839  	pph.flags = PF_R
  1840  	pph.off = uint64(eh.ehsize)
  1841  	pph.vaddr = uint64(*FlagTextAddr) - uint64(HEADR) + pph.off
  1842  	pph.paddr = uint64(*FlagTextAddr) - uint64(HEADR) + pph.off
  1843  	pph.align = uint64(*FlagRound)
  1844  
  1845  	/*
  1846  	 * PHDR must be in a loaded segment. Adjust the text
  1847  	 * segment boundaries downwards to include it.
  1848  	 * Except on NaCl where it must not be loaded.
  1849  	 */
  1850  	if ctxt.HeadType != objabi.Hnacl {
  1851  		o := int64(Segtext.Vaddr - pph.vaddr)
  1852  		Segtext.Vaddr -= uint64(o)
  1853  		Segtext.Length += uint64(o)
  1854  		o = int64(Segtext.Fileoff - pph.off)
  1855  		Segtext.Fileoff -= uint64(o)
  1856  		Segtext.Filelen += uint64(o)
  1857  	}
  1858  
  1859  	if !*FlagD { /* -d suppresses dynamic loader format */
  1860  		/* interpreter */
  1861  		sh := elfshname(".interp")
  1862  
  1863  		sh.type_ = SHT_PROGBITS
  1864  		sh.flags = SHF_ALLOC
  1865  		sh.addralign = 1
  1866  		if interpreter == "" {
  1867  			switch ctxt.HeadType {
  1868  			case objabi.Hlinux:
  1869  				interpreter = Thearch.Linuxdynld
  1870  
  1871  			case objabi.Hfreebsd:
  1872  				interpreter = Thearch.Freebsddynld
  1873  
  1874  			case objabi.Hnetbsd:
  1875  				interpreter = Thearch.Netbsddynld
  1876  
  1877  			case objabi.Hopenbsd:
  1878  				interpreter = Thearch.Openbsddynld
  1879  
  1880  			case objabi.Hdragonfly:
  1881  				interpreter = Thearch.Dragonflydynld
  1882  
  1883  			case objabi.Hsolaris:
  1884  				interpreter = Thearch.Solarisdynld
  1885  			}
  1886  		}
  1887  
  1888  		resoff -= int64(elfinterp(sh, uint64(startva), uint64(resoff), interpreter))
  1889  
  1890  		ph := newElfPhdr()
  1891  		ph.type_ = PT_INTERP
  1892  		ph.flags = PF_R
  1893  		phsh(ph, sh)
  1894  	}
  1895  
  1896  	pnote = nil
  1897  	if ctxt.HeadType == objabi.Hnetbsd || ctxt.HeadType == objabi.Hopenbsd {
  1898  		var sh *ElfShdr
  1899  		switch ctxt.HeadType {
  1900  		case objabi.Hnetbsd:
  1901  			sh = elfshname(".note.netbsd.ident")
  1902  			resoff -= int64(elfnetbsdsig(sh, uint64(startva), uint64(resoff)))
  1903  
  1904  		case objabi.Hopenbsd:
  1905  			sh = elfshname(".note.openbsd.ident")
  1906  			resoff -= int64(elfopenbsdsig(sh, uint64(startva), uint64(resoff)))
  1907  		}
  1908  
  1909  		pnote = newElfPhdr()
  1910  		pnote.type_ = PT_NOTE
  1911  		pnote.flags = PF_R
  1912  		phsh(pnote, sh)
  1913  	}
  1914  
  1915  	if len(buildinfo) > 0 {
  1916  		sh := elfshname(".note.gnu.build-id")
  1917  		resoff -= int64(elfbuildinfo(sh, uint64(startva), uint64(resoff)))
  1918  
  1919  		if pnote == nil {
  1920  			pnote = newElfPhdr()
  1921  			pnote.type_ = PT_NOTE
  1922  			pnote.flags = PF_R
  1923  		}
  1924  
  1925  		phsh(pnote, sh)
  1926  	}
  1927  
  1928  	if *flagBuildid != "" {
  1929  		sh := elfshname(".note.go.buildid")
  1930  		resoff -= int64(elfgobuildid(sh, uint64(startva), uint64(resoff)))
  1931  
  1932  		pnote := newElfPhdr()
  1933  		pnote.type_ = PT_NOTE
  1934  		pnote.flags = PF_R
  1935  		phsh(pnote, sh)
  1936  	}
  1937  
  1938  	// Additions to the reserved area must be above this line.
  1939  
  1940  	elfphload(&Segtext)
  1941  	if len(Segrodata.Sections) > 0 {
  1942  		elfphload(&Segrodata)
  1943  	}
  1944  	if len(Segrelrodata.Sections) > 0 {
  1945  		elfphload(&Segrelrodata)
  1946  		elfphrelro(&Segrelrodata)
  1947  	}
  1948  	elfphload(&Segdata)
  1949  
  1950  	/* Dynamic linking sections */
  1951  	if !*FlagD {
  1952  		sh := elfshname(".dynsym")
  1953  		sh.type_ = SHT_DYNSYM
  1954  		sh.flags = SHF_ALLOC
  1955  		if elf64 {
  1956  			sh.entsize = ELF64SYMSIZE
  1957  		} else {
  1958  			sh.entsize = ELF32SYMSIZE
  1959  		}
  1960  		sh.addralign = uint64(ctxt.Arch.RegSize)
  1961  		sh.link = uint32(elfshname(".dynstr").shnum)
  1962  
  1963  		// sh->info = index of first non-local symbol (number of local symbols)
  1964  		shsym(sh, ctxt.Syms.Lookup(".dynsym", 0))
  1965  
  1966  		sh = elfshname(".dynstr")
  1967  		sh.type_ = SHT_STRTAB
  1968  		sh.flags = SHF_ALLOC
  1969  		sh.addralign = 1
  1970  		shsym(sh, ctxt.Syms.Lookup(".dynstr", 0))
  1971  
  1972  		if elfverneed != 0 {
  1973  			sh := elfshname(".gnu.version")
  1974  			sh.type_ = SHT_GNU_VERSYM
  1975  			sh.flags = SHF_ALLOC
  1976  			sh.addralign = 2
  1977  			sh.link = uint32(elfshname(".dynsym").shnum)
  1978  			sh.entsize = 2
  1979  			shsym(sh, ctxt.Syms.Lookup(".gnu.version", 0))
  1980  
  1981  			sh = elfshname(".gnu.version_r")
  1982  			sh.type_ = SHT_GNU_VERNEED
  1983  			sh.flags = SHF_ALLOC
  1984  			sh.addralign = uint64(ctxt.Arch.RegSize)
  1985  			sh.info = uint32(elfverneed)
  1986  			sh.link = uint32(elfshname(".dynstr").shnum)
  1987  			shsym(sh, ctxt.Syms.Lookup(".gnu.version_r", 0))
  1988  		}
  1989  
  1990  		if elfRelType == ".rela" {
  1991  			sh := elfshname(".rela.plt")
  1992  			sh.type_ = SHT_RELA
  1993  			sh.flags = SHF_ALLOC
  1994  			sh.entsize = ELF64RELASIZE
  1995  			sh.addralign = uint64(ctxt.Arch.RegSize)
  1996  			sh.link = uint32(elfshname(".dynsym").shnum)
  1997  			sh.info = uint32(elfshname(".plt").shnum)
  1998  			shsym(sh, ctxt.Syms.Lookup(".rela.plt", 0))
  1999  
  2000  			sh = elfshname(".rela")
  2001  			sh.type_ = SHT_RELA
  2002  			sh.flags = SHF_ALLOC
  2003  			sh.entsize = ELF64RELASIZE
  2004  			sh.addralign = 8
  2005  			sh.link = uint32(elfshname(".dynsym").shnum)
  2006  			shsym(sh, ctxt.Syms.Lookup(".rela", 0))
  2007  		} else {
  2008  			sh := elfshname(".rel.plt")
  2009  			sh.type_ = SHT_REL
  2010  			sh.flags = SHF_ALLOC
  2011  			sh.entsize = ELF32RELSIZE
  2012  			sh.addralign = 4
  2013  			sh.link = uint32(elfshname(".dynsym").shnum)
  2014  			shsym(sh, ctxt.Syms.Lookup(".rel.plt", 0))
  2015  
  2016  			sh = elfshname(".rel")
  2017  			sh.type_ = SHT_REL
  2018  			sh.flags = SHF_ALLOC
  2019  			sh.entsize = ELF32RELSIZE
  2020  			sh.addralign = 4
  2021  			sh.link = uint32(elfshname(".dynsym").shnum)
  2022  			shsym(sh, ctxt.Syms.Lookup(".rel", 0))
  2023  		}
  2024  
  2025  		if eh.machine == EM_PPC64 {
  2026  			sh := elfshname(".glink")
  2027  			sh.type_ = SHT_PROGBITS
  2028  			sh.flags = SHF_ALLOC + SHF_EXECINSTR
  2029  			sh.addralign = 4
  2030  			shsym(sh, ctxt.Syms.Lookup(".glink", 0))
  2031  		}
  2032  
  2033  		sh = elfshname(".plt")
  2034  		sh.type_ = SHT_PROGBITS
  2035  		sh.flags = SHF_ALLOC + SHF_EXECINSTR
  2036  		if eh.machine == EM_X86_64 {
  2037  			sh.entsize = 16
  2038  		} else if eh.machine == EM_S390 {
  2039  			sh.entsize = 32
  2040  		} else if eh.machine == EM_PPC64 {
  2041  			// On ppc64, this is just a table of addresses
  2042  			// filled by the dynamic linker
  2043  			sh.type_ = SHT_NOBITS
  2044  
  2045  			sh.flags = SHF_ALLOC + SHF_WRITE
  2046  			sh.entsize = 8
  2047  		} else {
  2048  			sh.entsize = 4
  2049  		}
  2050  		sh.addralign = sh.entsize
  2051  		shsym(sh, ctxt.Syms.Lookup(".plt", 0))
  2052  
  2053  		// On ppc64, .got comes from the input files, so don't
  2054  		// create it here, and .got.plt is not used.
  2055  		if eh.machine != EM_PPC64 {
  2056  			sh := elfshname(".got")
  2057  			sh.type_ = SHT_PROGBITS
  2058  			sh.flags = SHF_ALLOC + SHF_WRITE
  2059  			sh.entsize = uint64(ctxt.Arch.RegSize)
  2060  			sh.addralign = uint64(ctxt.Arch.RegSize)
  2061  			shsym(sh, ctxt.Syms.Lookup(".got", 0))
  2062  
  2063  			sh = elfshname(".got.plt")
  2064  			sh.type_ = SHT_PROGBITS
  2065  			sh.flags = SHF_ALLOC + SHF_WRITE
  2066  			sh.entsize = uint64(ctxt.Arch.RegSize)
  2067  			sh.addralign = uint64(ctxt.Arch.RegSize)
  2068  			shsym(sh, ctxt.Syms.Lookup(".got.plt", 0))
  2069  		}
  2070  
  2071  		sh = elfshname(".hash")
  2072  		sh.type_ = SHT_HASH
  2073  		sh.flags = SHF_ALLOC
  2074  		sh.entsize = 4
  2075  		sh.addralign = uint64(ctxt.Arch.RegSize)
  2076  		sh.link = uint32(elfshname(".dynsym").shnum)
  2077  		shsym(sh, ctxt.Syms.Lookup(".hash", 0))
  2078  
  2079  		/* sh and PT_DYNAMIC for .dynamic section */
  2080  		sh = elfshname(".dynamic")
  2081  
  2082  		sh.type_ = SHT_DYNAMIC
  2083  		sh.flags = SHF_ALLOC + SHF_WRITE
  2084  		sh.entsize = 2 * uint64(ctxt.Arch.RegSize)
  2085  		sh.addralign = uint64(ctxt.Arch.RegSize)
  2086  		sh.link = uint32(elfshname(".dynstr").shnum)
  2087  		shsym(sh, ctxt.Syms.Lookup(".dynamic", 0))
  2088  		ph := newElfPhdr()
  2089  		ph.type_ = PT_DYNAMIC
  2090  		ph.flags = PF_R + PF_W
  2091  		phsh(ph, sh)
  2092  
  2093  		/*
  2094  		 * Thread-local storage segment (really just size).
  2095  		 */
  2096  		tlssize := uint64(0)
  2097  		for _, sect := range Segdata.Sections {
  2098  			if sect.Name == ".tbss" {
  2099  				tlssize = sect.Length
  2100  			}
  2101  		}
  2102  		if tlssize != 0 {
  2103  			ph := newElfPhdr()
  2104  			ph.type_ = PT_TLS
  2105  			ph.flags = PF_R
  2106  			ph.memsz = tlssize
  2107  			ph.align = uint64(ctxt.Arch.RegSize)
  2108  		}
  2109  	}
  2110  
  2111  	if ctxt.HeadType == objabi.Hlinux {
  2112  		ph := newElfPhdr()
  2113  		ph.type_ = PT_GNU_STACK
  2114  		ph.flags = PF_W + PF_R
  2115  		ph.align = uint64(ctxt.Arch.RegSize)
  2116  
  2117  		ph = newElfPhdr()
  2118  		ph.type_ = PT_PAX_FLAGS
  2119  		ph.flags = 0x2a00 // mprotect, randexec, emutramp disabled
  2120  		ph.align = uint64(ctxt.Arch.RegSize)
  2121  	} else if ctxt.HeadType == objabi.Hsolaris {
  2122  		ph := newElfPhdr()
  2123  		ph.type_ = PT_SUNWSTACK
  2124  		ph.flags = PF_W + PF_R
  2125  	}
  2126  
  2127  elfobj:
  2128  	sh := elfshname(".shstrtab")
  2129  	sh.type_ = SHT_STRTAB
  2130  	sh.addralign = 1
  2131  	shsym(sh, ctxt.Syms.Lookup(".shstrtab", 0))
  2132  	eh.shstrndx = uint16(sh.shnum)
  2133  
  2134  	// put these sections early in the list
  2135  	if !*FlagS {
  2136  		elfshname(".symtab")
  2137  		elfshname(".strtab")
  2138  	}
  2139  
  2140  	for _, sect := range Segtext.Sections {
  2141  		elfshbits(ctxt.LinkMode, sect)
  2142  	}
  2143  	for _, sect := range Segrodata.Sections {
  2144  		elfshbits(ctxt.LinkMode, sect)
  2145  	}
  2146  	for _, sect := range Segrelrodata.Sections {
  2147  		elfshbits(ctxt.LinkMode, sect)
  2148  	}
  2149  	for _, sect := range Segdata.Sections {
  2150  		elfshbits(ctxt.LinkMode, sect)
  2151  	}
  2152  	for _, sect := range Segdwarf.Sections {
  2153  		elfshbits(ctxt.LinkMode, sect)
  2154  	}
  2155  
  2156  	if ctxt.LinkMode == LinkExternal {
  2157  		for _, sect := range Segtext.Sections {
  2158  			elfshreloc(ctxt.Arch, sect)
  2159  		}
  2160  		for _, sect := range Segrodata.Sections {
  2161  			elfshreloc(ctxt.Arch, sect)
  2162  		}
  2163  		for _, sect := range Segrelrodata.Sections {
  2164  			elfshreloc(ctxt.Arch, sect)
  2165  		}
  2166  		for _, sect := range Segdata.Sections {
  2167  			elfshreloc(ctxt.Arch, sect)
  2168  		}
  2169  		for _, s := range dwarfp {
  2170  			if len(s.R) > 0 || s.Type == sym.SDWARFINFO || s.Type == sym.SDWARFLOC {
  2171  				elfshreloc(ctxt.Arch, s.Sect)
  2172  			}
  2173  		}
  2174  		// add a .note.GNU-stack section to mark the stack as non-executable
  2175  		sh := elfshname(".note.GNU-stack")
  2176  
  2177  		sh.type_ = SHT_PROGBITS
  2178  		sh.addralign = 1
  2179  		sh.flags = 0
  2180  	}
  2181  
  2182  	if !*FlagS {
  2183  		sh := elfshname(".symtab")
  2184  		sh.type_ = SHT_SYMTAB
  2185  		sh.off = uint64(symo)
  2186  		sh.size = uint64(Symsize)
  2187  		sh.addralign = uint64(ctxt.Arch.RegSize)
  2188  		sh.entsize = 8 + 2*uint64(ctxt.Arch.RegSize)
  2189  		sh.link = uint32(elfshname(".strtab").shnum)
  2190  		sh.info = uint32(elfglobalsymndx)
  2191  
  2192  		sh = elfshname(".strtab")
  2193  		sh.type_ = SHT_STRTAB
  2194  		sh.off = uint64(symo) + uint64(Symsize)
  2195  		sh.size = uint64(len(Elfstrdat))
  2196  		sh.addralign = 1
  2197  	}
  2198  
  2199  	/* Main header */
  2200  	eh.ident[EI_MAG0] = '\177'
  2201  
  2202  	eh.ident[EI_MAG1] = 'E'
  2203  	eh.ident[EI_MAG2] = 'L'
  2204  	eh.ident[EI_MAG3] = 'F'
  2205  	if ctxt.HeadType == objabi.Hfreebsd {
  2206  		eh.ident[EI_OSABI] = ELFOSABI_FREEBSD
  2207  	} else if ctxt.HeadType == objabi.Hnetbsd {
  2208  		eh.ident[EI_OSABI] = ELFOSABI_NETBSD
  2209  	} else if ctxt.HeadType == objabi.Hopenbsd {
  2210  		eh.ident[EI_OSABI] = ELFOSABI_OPENBSD
  2211  	} else if ctxt.HeadType == objabi.Hdragonfly {
  2212  		eh.ident[EI_OSABI] = ELFOSABI_NONE
  2213  	}
  2214  	if elf64 {
  2215  		eh.ident[EI_CLASS] = ELFCLASS64
  2216  	} else {
  2217  		eh.ident[EI_CLASS] = ELFCLASS32
  2218  	}
  2219  	if ctxt.Arch.ByteOrder == binary.BigEndian {
  2220  		eh.ident[EI_DATA] = ELFDATA2MSB
  2221  	} else {
  2222  		eh.ident[EI_DATA] = ELFDATA2LSB
  2223  	}
  2224  	eh.ident[EI_VERSION] = EV_CURRENT
  2225  
  2226  	if ctxt.LinkMode == LinkExternal {
  2227  		eh.type_ = ET_REL
  2228  	} else if ctxt.BuildMode == BuildModePIE {
  2229  		eh.type_ = ET_DYN
  2230  	} else {
  2231  		eh.type_ = ET_EXEC
  2232  	}
  2233  
  2234  	if ctxt.LinkMode != LinkExternal {
  2235  		eh.entry = uint64(Entryvalue(ctxt))
  2236  	}
  2237  
  2238  	eh.version = EV_CURRENT
  2239  
  2240  	if pph != nil {
  2241  		pph.filesz = uint64(eh.phnum) * uint64(eh.phentsize)
  2242  		pph.memsz = pph.filesz
  2243  	}
  2244  
  2245  	ctxt.Out.SeekSet(0)
  2246  	a := int64(0)
  2247  	a += int64(elfwritehdr(ctxt.Out))
  2248  	a += int64(elfwritephdrs(ctxt.Out))
  2249  	a += int64(elfwriteshdrs(ctxt.Out))
  2250  	if !*FlagD {
  2251  		a += int64(elfwriteinterp(ctxt.Out))
  2252  	}
  2253  	if ctxt.LinkMode != LinkExternal {
  2254  		if ctxt.HeadType == objabi.Hnetbsd {
  2255  			a += int64(elfwritenetbsdsig(ctxt.Out))
  2256  		}
  2257  		if ctxt.HeadType == objabi.Hopenbsd {
  2258  			a += int64(elfwriteopenbsdsig(ctxt.Out))
  2259  		}
  2260  		if len(buildinfo) > 0 {
  2261  			a += int64(elfwritebuildinfo(ctxt.Out))
  2262  		}
  2263  		if *flagBuildid != "" {
  2264  			a += int64(elfwritegobuildid(ctxt.Out))
  2265  		}
  2266  	}
  2267  
  2268  	if a > elfreserve {
  2269  		Errorf(nil, "ELFRESERVE too small: %d > %d with %d text sections", a, elfreserve, numtext)
  2270  	}
  2271  }
  2272  
  2273  func elfadddynsym(ctxt *Link, s *sym.Symbol) {
  2274  	if elf64 {
  2275  		s.Dynid = int32(Nelfsym)
  2276  		Nelfsym++
  2277  
  2278  		d := ctxt.Syms.Lookup(".dynsym", 0)
  2279  
  2280  		name := s.Extname
  2281  		d.AddUint32(ctxt.Arch, uint32(Addstring(ctxt.Syms.Lookup(".dynstr", 0), name)))
  2282  
  2283  		/* type */
  2284  		t := STB_GLOBAL << 4
  2285  
  2286  		if s.Attr.CgoExport() && s.Type == sym.STEXT {
  2287  			t |= STT_FUNC
  2288  		} else {
  2289  			t |= STT_OBJECT
  2290  		}
  2291  		d.AddUint8(uint8(t))
  2292  
  2293  		/* reserved */
  2294  		d.AddUint8(0)
  2295  
  2296  		/* section where symbol is defined */
  2297  		if s.Type == sym.SDYNIMPORT {
  2298  			d.AddUint16(ctxt.Arch, SHN_UNDEF)
  2299  		} else {
  2300  			d.AddUint16(ctxt.Arch, 1)
  2301  		}
  2302  
  2303  		/* value */
  2304  		if s.Type == sym.SDYNIMPORT {
  2305  			d.AddUint64(ctxt.Arch, 0)
  2306  		} else {
  2307  			d.AddAddr(ctxt.Arch, s)
  2308  		}
  2309  
  2310  		/* size of object */
  2311  		d.AddUint64(ctxt.Arch, uint64(s.Size))
  2312  
  2313  		if ctxt.Arch.Family == sys.AMD64 && !s.Attr.CgoExportDynamic() && s.Dynimplib != "" && !seenlib[s.Dynimplib] {
  2314  			Elfwritedynent(ctxt, ctxt.Syms.Lookup(".dynamic", 0), DT_NEEDED, uint64(Addstring(ctxt.Syms.Lookup(".dynstr", 0), s.Dynimplib)))
  2315  		}
  2316  	} else {
  2317  		s.Dynid = int32(Nelfsym)
  2318  		Nelfsym++
  2319  
  2320  		d := ctxt.Syms.Lookup(".dynsym", 0)
  2321  
  2322  		/* name */
  2323  		name := s.Extname
  2324  
  2325  		d.AddUint32(ctxt.Arch, uint32(Addstring(ctxt.Syms.Lookup(".dynstr", 0), name)))
  2326  
  2327  		/* value */
  2328  		if s.Type == sym.SDYNIMPORT {
  2329  			d.AddUint32(ctxt.Arch, 0)
  2330  		} else {
  2331  			d.AddAddr(ctxt.Arch, s)
  2332  		}
  2333  
  2334  		/* size of object */
  2335  		d.AddUint32(ctxt.Arch, uint32(s.Size))
  2336  
  2337  		/* type */
  2338  		t := STB_GLOBAL << 4
  2339  
  2340  		// TODO(mwhudson): presumably the behavior should actually be the same on both arm and 386.
  2341  		if ctxt.Arch.Family == sys.I386 && s.Attr.CgoExport() && s.Type == sym.STEXT {
  2342  			t |= STT_FUNC
  2343  		} else if ctxt.Arch.Family == sys.ARM && s.Attr.CgoExportDynamic() && s.Type == sym.STEXT {
  2344  			t |= STT_FUNC
  2345  		} else {
  2346  			t |= STT_OBJECT
  2347  		}
  2348  		d.AddUint8(uint8(t))
  2349  		d.AddUint8(0)
  2350  
  2351  		/* shndx */
  2352  		if s.Type == sym.SDYNIMPORT {
  2353  			d.AddUint16(ctxt.Arch, SHN_UNDEF)
  2354  		} else {
  2355  			d.AddUint16(ctxt.Arch, 1)
  2356  		}
  2357  	}
  2358  }
  2359  
  2360  func ELF32_R_SYM(info uint32) uint32 {
  2361  	return info >> 8
  2362  }
  2363  
  2364  func ELF32_R_TYPE(info uint32) uint32 {
  2365  	return uint32(uint8(info))
  2366  }
  2367  
  2368  func ELF32_R_INFO(sym uint32, type_ uint32) uint32 {
  2369  	return sym<<8 | type_
  2370  }
  2371  
  2372  func ELF32_ST_BIND(info uint8) uint8 {
  2373  	return info >> 4
  2374  }
  2375  
  2376  func ELF32_ST_TYPE(info uint8) uint8 {
  2377  	return info & 0xf
  2378  }
  2379  
  2380  func ELF32_ST_INFO(bind uint8, type_ uint8) uint8 {
  2381  	return bind<<4 | type_&0xf
  2382  }
  2383  
  2384  func ELF32_ST_VISIBILITY(oth uint8) uint8 {
  2385  	return oth & 3
  2386  }
  2387  
  2388  func ELF64_R_SYM(info uint64) uint32 {
  2389  	return uint32(info >> 32)
  2390  }
  2391  
  2392  func ELF64_R_TYPE(info uint64) uint32 {
  2393  	return uint32(info)
  2394  }
  2395  
  2396  func ELF64_R_INFO(sym uint32, type_ uint32) uint64 {
  2397  	return uint64(sym)<<32 | uint64(type_)
  2398  }
  2399  
  2400  func ELF64_ST_BIND(info uint8) uint8 {
  2401  	return info >> 4
  2402  }
  2403  
  2404  func ELF64_ST_TYPE(info uint8) uint8 {
  2405  	return info & 0xf
  2406  }
  2407  
  2408  func ELF64_ST_INFO(bind uint8, type_ uint8) uint8 {
  2409  	return bind<<4 | type_&0xf
  2410  }
  2411  
  2412  func ELF64_ST_VISIBILITY(oth uint8) uint8 {
  2413  	return oth & 3
  2414  }