...

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

View as plain text