...
Run Format

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

View as plain text