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

     1  // Copyright 2009 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package ld
     6  
     7  import (
     8  	"cmd/internal/hash"
     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  	"slices"
    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("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("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 == "" || val == "none" {
   811  		return
   812  	}
   813  	if val == "gobuildid" {
   814  		buildID := *flagBuildid
   815  		if buildID == "" {
   816  			Exitf("-B gobuildid requires a Go build ID supplied via -buildid")
   817  		}
   818  
   819  		if ctxt.IsDarwin() {
   820  			buildinfo = uuidFromGoBuildId(buildID)
   821  			return
   822  		}
   823  
   824  		hashedBuildID := hash.Sum32([]byte(buildID))
   825  		buildinfo = hashedBuildID[:20]
   826  
   827  		return
   828  	}
   829  
   830  	if !strings.HasPrefix(val, "0x") {
   831  		Exitf("-B argument must start with 0x: %s", val)
   832  	}
   833  	ov := val
   834  	val = val[2:]
   835  
   836  	maxLen := 32
   837  	if ctxt.IsDarwin() {
   838  		maxLen = 16
   839  	}
   840  	if hex.DecodedLen(len(val)) > maxLen {
   841  		Exitf("-B option too long (max %d digits): %s", maxLen, ov)
   842  	}
   843  
   844  	b, err := hex.DecodeString(val)
   845  	if err != nil {
   846  		if err == hex.ErrLength {
   847  			Exitf("-B argument must have even number of digits: %s", ov)
   848  		}
   849  		if inv, ok := err.(hex.InvalidByteError); ok {
   850  			Exitf("-B argument contains invalid hex digit %c: %s", byte(inv), ov)
   851  		}
   852  		Exitf("-B argument contains invalid hex: %s", ov)
   853  	}
   854  
   855  	buildinfo = b
   856  }
   857  
   858  // Build info note
   859  const (
   860  	ELF_NOTE_BUILDINFO_NAMESZ = 4
   861  	ELF_NOTE_BUILDINFO_TAG    = 3
   862  )
   863  
   864  var ELF_NOTE_BUILDINFO_NAME = []byte("GNU\x00")
   865  
   866  func elfbuildinfo(sh *ElfShdr, startva uint64, resoff uint64) int {
   867  	n := int(ELF_NOTE_BUILDINFO_NAMESZ + Rnd(int64(len(buildinfo)), 4))
   868  	return elfnote(sh, startva, resoff, n)
   869  }
   870  
   871  func elfgobuildid(sh *ElfShdr, startva uint64, resoff uint64) int {
   872  	n := len(ELF_NOTE_GO_NAME) + int(Rnd(int64(len(*flagBuildid)), 4))
   873  	return elfnote(sh, startva, resoff, n)
   874  }
   875  
   876  func elfwritebuildinfo(out *OutBuf) int {
   877  	sh := elfwritenotehdr(out, ".note.gnu.build-id", ELF_NOTE_BUILDINFO_NAMESZ, uint32(len(buildinfo)), ELF_NOTE_BUILDINFO_TAG)
   878  	if sh == nil {
   879  		return 0
   880  	}
   881  
   882  	out.Write(ELF_NOTE_BUILDINFO_NAME)
   883  	out.Write(buildinfo)
   884  	var zero = make([]byte, 4)
   885  	out.Write(zero[:int(Rnd(int64(len(buildinfo)), 4)-int64(len(buildinfo)))])
   886  
   887  	return int(sh.Size)
   888  }
   889  
   890  func elfwritegobuildid(out *OutBuf) int {
   891  	sh := elfwritenotehdr(out, ".note.go.buildid", uint32(len(ELF_NOTE_GO_NAME)), uint32(len(*flagBuildid)), ELF_NOTE_GOBUILDID_TAG)
   892  	if sh == nil {
   893  		return 0
   894  	}
   895  
   896  	out.Write(ELF_NOTE_GO_NAME)
   897  	out.Write([]byte(*flagBuildid))
   898  	var zero = make([]byte, 4)
   899  	out.Write(zero[:int(Rnd(int64(len(*flagBuildid)), 4)-int64(len(*flagBuildid)))])
   900  
   901  	return int(sh.Size)
   902  }
   903  
   904  // Go specific notes
   905  const (
   906  	ELF_NOTE_GOPKGLIST_TAG = 1
   907  	ELF_NOTE_GOABIHASH_TAG = 2
   908  	ELF_NOTE_GODEPS_TAG    = 3
   909  	ELF_NOTE_GOBUILDID_TAG = 4
   910  )
   911  
   912  var ELF_NOTE_GO_NAME = []byte("Go\x00\x00")
   913  
   914  var elfverneed int
   915  
   916  type Elfaux struct {
   917  	next *Elfaux
   918  	num  int
   919  	vers string
   920  }
   921  
   922  type Elflib struct {
   923  	next *Elflib
   924  	aux  *Elfaux
   925  	file string
   926  }
   927  
   928  func addelflib(list **Elflib, file string, vers string) *Elfaux {
   929  	var lib *Elflib
   930  
   931  	for lib = *list; lib != nil; lib = lib.next {
   932  		if lib.file == file {
   933  			goto havelib
   934  		}
   935  	}
   936  	lib = new(Elflib)
   937  	lib.next = *list
   938  	lib.file = file
   939  	*list = lib
   940  
   941  havelib:
   942  	for aux := lib.aux; aux != nil; aux = aux.next {
   943  		if aux.vers == vers {
   944  			return aux
   945  		}
   946  	}
   947  	aux := new(Elfaux)
   948  	aux.next = lib.aux
   949  	aux.vers = vers
   950  	lib.aux = aux
   951  
   952  	return aux
   953  }
   954  
   955  func elfdynhash(ctxt *Link) {
   956  	if !ctxt.IsELF {
   957  		return
   958  	}
   959  
   960  	nsym := Nelfsym
   961  	ldr := ctxt.loader
   962  	s := ldr.CreateSymForUpdate(".hash", 0)
   963  	s.SetType(sym.SELFROSECT)
   964  
   965  	i := nsym
   966  	nbucket := 1
   967  	for i > 0 {
   968  		nbucket++
   969  		i >>= 1
   970  	}
   971  
   972  	var needlib *Elflib
   973  	need := make([]*Elfaux, nsym)
   974  	chain := make([]uint32, nsym)
   975  	buckets := make([]uint32, nbucket)
   976  
   977  	for _, sy := range ldr.DynidSyms() {
   978  
   979  		dynid := ldr.SymDynid(sy)
   980  		if ldr.SymDynimpvers(sy) != "" {
   981  			need[dynid] = addelflib(&needlib, ldr.SymDynimplib(sy), ldr.SymDynimpvers(sy))
   982  		}
   983  
   984  		name := ldr.SymExtname(sy)
   985  		hc := elfhash(name)
   986  
   987  		b := hc % uint32(nbucket)
   988  		chain[dynid] = buckets[b]
   989  		buckets[b] = uint32(dynid)
   990  	}
   991  
   992  	// s390x (ELF64) hash table entries are 8 bytes
   993  	if ctxt.Arch.Family == sys.S390X {
   994  		s.AddUint64(ctxt.Arch, uint64(nbucket))
   995  		s.AddUint64(ctxt.Arch, uint64(nsym))
   996  		for i := 0; i < nbucket; i++ {
   997  			s.AddUint64(ctxt.Arch, uint64(buckets[i]))
   998  		}
   999  		for i := 0; i < nsym; i++ {
  1000  			s.AddUint64(ctxt.Arch, uint64(chain[i]))
  1001  		}
  1002  	} else {
  1003  		s.AddUint32(ctxt.Arch, uint32(nbucket))
  1004  		s.AddUint32(ctxt.Arch, uint32(nsym))
  1005  		for i := 0; i < nbucket; i++ {
  1006  			s.AddUint32(ctxt.Arch, buckets[i])
  1007  		}
  1008  		for i := 0; i < nsym; i++ {
  1009  			s.AddUint32(ctxt.Arch, chain[i])
  1010  		}
  1011  	}
  1012  
  1013  	dynstr := ldr.CreateSymForUpdate(".dynstr", 0)
  1014  
  1015  	// version symbols
  1016  	gnuVersionR := ldr.CreateSymForUpdate(".gnu.version_r", 0)
  1017  	s = gnuVersionR
  1018  	i = 2
  1019  	nfile := 0
  1020  	for l := needlib; l != nil; l = l.next {
  1021  		nfile++
  1022  
  1023  		// header
  1024  		s.AddUint16(ctxt.Arch, 1) // table version
  1025  		j := 0
  1026  		for x := l.aux; x != nil; x = x.next {
  1027  			j++
  1028  		}
  1029  		s.AddUint16(ctxt.Arch, uint16(j))                        // aux count
  1030  		s.AddUint32(ctxt.Arch, uint32(dynstr.Addstring(l.file))) // file string offset
  1031  		s.AddUint32(ctxt.Arch, 16)                               // offset from header to first aux
  1032  		if l.next != nil {
  1033  			s.AddUint32(ctxt.Arch, 16+uint32(j)*16) // offset from this header to next
  1034  		} else {
  1035  			s.AddUint32(ctxt.Arch, 0)
  1036  		}
  1037  
  1038  		for x := l.aux; x != nil; x = x.next {
  1039  			x.num = i
  1040  			i++
  1041  
  1042  			// aux struct
  1043  			s.AddUint32(ctxt.Arch, elfhash(x.vers))                  // hash
  1044  			s.AddUint16(ctxt.Arch, 0)                                // flags
  1045  			s.AddUint16(ctxt.Arch, uint16(x.num))                    // other - index we refer to this by
  1046  			s.AddUint32(ctxt.Arch, uint32(dynstr.Addstring(x.vers))) // version string offset
  1047  			if x.next != nil {
  1048  				s.AddUint32(ctxt.Arch, 16) // offset from this aux to next
  1049  			} else {
  1050  				s.AddUint32(ctxt.Arch, 0)
  1051  			}
  1052  		}
  1053  	}
  1054  
  1055  	// version references
  1056  	gnuVersion := ldr.CreateSymForUpdate(".gnu.version", 0)
  1057  	s = gnuVersion
  1058  
  1059  	for i := 0; i < nsym; i++ {
  1060  		if i == 0 {
  1061  			s.AddUint16(ctxt.Arch, 0) // first entry - no symbol
  1062  		} else if need[i] == nil {
  1063  			s.AddUint16(ctxt.Arch, 1) // global
  1064  		} else {
  1065  			s.AddUint16(ctxt.Arch, uint16(need[i].num))
  1066  		}
  1067  	}
  1068  
  1069  	s = ldr.CreateSymForUpdate(".dynamic", 0)
  1070  
  1071  	var dtFlags1 elf.DynFlag1
  1072  	if *flagBindNow {
  1073  		dtFlags1 |= elf.DF_1_NOW
  1074  		Elfwritedynent(ctxt.Arch, s, elf.DT_FLAGS, uint64(elf.DF_BIND_NOW))
  1075  	}
  1076  	if ctxt.BuildMode == BuildModePIE {
  1077  		dtFlags1 |= elf.DF_1_PIE
  1078  	}
  1079  	Elfwritedynent(ctxt.Arch, s, elf.DT_FLAGS_1, uint64(dtFlags1))
  1080  
  1081  	elfverneed = nfile
  1082  	if elfverneed != 0 {
  1083  		elfWriteDynEntSym(ctxt, s, elf.DT_VERNEED, gnuVersionR.Sym())
  1084  		Elfwritedynent(ctxt.Arch, s, elf.DT_VERNEEDNUM, uint64(nfile))
  1085  		elfWriteDynEntSym(ctxt, s, elf.DT_VERSYM, gnuVersion.Sym())
  1086  	}
  1087  
  1088  	sy := ldr.CreateSymForUpdate(elfRelType+".plt", 0)
  1089  	if sy.Size() > 0 {
  1090  		if elfRelType == ".rela" {
  1091  			Elfwritedynent(ctxt.Arch, s, elf.DT_PLTREL, uint64(elf.DT_RELA))
  1092  		} else {
  1093  			Elfwritedynent(ctxt.Arch, s, elf.DT_PLTREL, uint64(elf.DT_REL))
  1094  		}
  1095  		elfwritedynentsymsize(ctxt, s, elf.DT_PLTRELSZ, sy.Sym())
  1096  		elfWriteDynEntSym(ctxt, s, elf.DT_JMPREL, sy.Sym())
  1097  	}
  1098  
  1099  	Elfwritedynent(ctxt.Arch, s, elf.DT_NULL, 0)
  1100  }
  1101  
  1102  func elfphload(seg *sym.Segment) *ElfPhdr {
  1103  	ph := newElfPhdr()
  1104  	ph.Type = elf.PT_LOAD
  1105  	if seg.Rwx&4 != 0 {
  1106  		ph.Flags |= elf.PF_R
  1107  	}
  1108  	if seg.Rwx&2 != 0 {
  1109  		ph.Flags |= elf.PF_W
  1110  	}
  1111  	if seg.Rwx&1 != 0 {
  1112  		ph.Flags |= elf.PF_X
  1113  	}
  1114  	ph.Vaddr = seg.Vaddr
  1115  	ph.Paddr = seg.Vaddr
  1116  	ph.Memsz = seg.Length
  1117  	ph.Off = seg.Fileoff
  1118  	ph.Filesz = seg.Filelen
  1119  	ph.Align = uint64(*FlagRound)
  1120  
  1121  	return ph
  1122  }
  1123  
  1124  func elfphrelro(seg *sym.Segment) {
  1125  	ph := newElfPhdr()
  1126  	ph.Type = elf.PT_GNU_RELRO
  1127  	ph.Flags = elf.PF_R
  1128  	ph.Vaddr = seg.Vaddr
  1129  	ph.Paddr = seg.Vaddr
  1130  	ph.Memsz = seg.Length
  1131  	ph.Off = seg.Fileoff
  1132  	ph.Filesz = seg.Filelen
  1133  	ph.Align = uint64(*FlagRound)
  1134  }
  1135  
  1136  func elfshname(name string) *ElfShdr {
  1137  	for i := 0; i < nelfstr; i++ {
  1138  		if name != elfstr[i].s {
  1139  			continue
  1140  		}
  1141  		off := elfstr[i].off
  1142  		for i = 0; i < int(ehdr.Shnum); i++ {
  1143  			sh := shdr[i]
  1144  			if sh.Name == uint32(off) {
  1145  				return sh
  1146  			}
  1147  		}
  1148  		return newElfShdr(int64(off))
  1149  	}
  1150  	Exitf("cannot find elf name %s", name)
  1151  	return nil
  1152  }
  1153  
  1154  // Create an ElfShdr for the section with name.
  1155  // Create a duplicate if one already exists with that name.
  1156  func elfshnamedup(name string) *ElfShdr {
  1157  	for i := 0; i < nelfstr; i++ {
  1158  		if name == elfstr[i].s {
  1159  			off := elfstr[i].off
  1160  			return newElfShdr(int64(off))
  1161  		}
  1162  	}
  1163  
  1164  	Errorf("cannot find elf name %s", name)
  1165  	errorexit()
  1166  	return nil
  1167  }
  1168  
  1169  func elfshalloc(sect *sym.Section) *ElfShdr {
  1170  	sh := elfshname(sect.Name)
  1171  	sect.Elfsect = sh
  1172  	return sh
  1173  }
  1174  
  1175  func elfshbits(linkmode LinkMode, sect *sym.Section) *ElfShdr {
  1176  	var sh *ElfShdr
  1177  
  1178  	if sect.Name == ".text" {
  1179  		if sect.Elfsect == nil {
  1180  			sect.Elfsect = elfshnamedup(sect.Name)
  1181  		}
  1182  		sh = sect.Elfsect.(*ElfShdr)
  1183  	} else {
  1184  		sh = elfshalloc(sect)
  1185  	}
  1186  
  1187  	// If this section has already been set up as a note, we assume type_ and
  1188  	// flags are already correct, but the other fields still need filling in.
  1189  	if sh.Type == uint32(elf.SHT_NOTE) {
  1190  		if linkmode != LinkExternal {
  1191  			// TODO(mwhudson): the approach here will work OK when
  1192  			// linking internally for notes that we want to be included
  1193  			// in a loadable segment (e.g. the abihash note) but not for
  1194  			// notes that we do not want to be mapped (e.g. the package
  1195  			// list note). The real fix is probably to define new values
  1196  			// for Symbol.Type corresponding to mapped and unmapped notes
  1197  			// and handle them in dodata().
  1198  			Errorf("sh.Type == SHT_NOTE in elfshbits when linking internally")
  1199  		}
  1200  		sh.Addralign = uint64(sect.Align)
  1201  		sh.Size = sect.Length
  1202  		sh.Off = sect.Seg.Fileoff + sect.Vaddr - sect.Seg.Vaddr
  1203  		return sh
  1204  	}
  1205  	if sh.Type > 0 {
  1206  		return sh
  1207  	}
  1208  
  1209  	if sect.Vaddr < sect.Seg.Vaddr+sect.Seg.Filelen {
  1210  		switch sect.Name {
  1211  		case ".init_array":
  1212  			sh.Type = uint32(elf.SHT_INIT_ARRAY)
  1213  		default:
  1214  			sh.Type = uint32(elf.SHT_PROGBITS)
  1215  		}
  1216  	} else {
  1217  		sh.Type = uint32(elf.SHT_NOBITS)
  1218  	}
  1219  	sh.Flags = uint64(elf.SHF_ALLOC)
  1220  	if sect.Rwx&1 != 0 {
  1221  		sh.Flags |= uint64(elf.SHF_EXECINSTR)
  1222  	}
  1223  	if sect.Rwx&2 != 0 {
  1224  		sh.Flags |= uint64(elf.SHF_WRITE)
  1225  	}
  1226  	if sect.Name == ".tbss" {
  1227  		sh.Flags |= uint64(elf.SHF_TLS)
  1228  		sh.Type = uint32(elf.SHT_NOBITS)
  1229  	}
  1230  	if linkmode != LinkExternal {
  1231  		sh.Addr = sect.Vaddr
  1232  	}
  1233  
  1234  	if strings.HasPrefix(sect.Name, ".debug") || strings.HasPrefix(sect.Name, ".zdebug") {
  1235  		sh.Flags = 0
  1236  		sh.Addr = 0
  1237  		if sect.Compressed {
  1238  			sh.Flags |= uint64(elf.SHF_COMPRESSED)
  1239  		}
  1240  	}
  1241  
  1242  	sh.Addralign = uint64(sect.Align)
  1243  	sh.Size = sect.Length
  1244  	if sect.Name != ".tbss" {
  1245  		sh.Off = sect.Seg.Fileoff + sect.Vaddr - sect.Seg.Vaddr
  1246  	}
  1247  
  1248  	return sh
  1249  }
  1250  
  1251  func elfshreloc(arch *sys.Arch, sect *sym.Section) *ElfShdr {
  1252  	// If main section is SHT_NOBITS, nothing to relocate.
  1253  	// Also nothing to relocate in .shstrtab or notes.
  1254  	if sect.Vaddr >= sect.Seg.Vaddr+sect.Seg.Filelen {
  1255  		return nil
  1256  	}
  1257  	if sect.Name == ".shstrtab" || sect.Name == ".tbss" {
  1258  		return nil
  1259  	}
  1260  	if sect.Elfsect.(*ElfShdr).Type == uint32(elf.SHT_NOTE) {
  1261  		return nil
  1262  	}
  1263  
  1264  	typ := elf.SHT_REL
  1265  	if elfRelType == ".rela" {
  1266  		typ = elf.SHT_RELA
  1267  	}
  1268  
  1269  	sh := elfshname(elfRelType + sect.Name)
  1270  	// There could be multiple text sections but each needs
  1271  	// its own .rela.text.
  1272  
  1273  	if sect.Name == ".text" {
  1274  		if sh.Info != 0 && sh.Info != uint32(sect.Elfsect.(*ElfShdr).shnum) {
  1275  			sh = elfshnamedup(elfRelType + sect.Name)
  1276  		}
  1277  	}
  1278  
  1279  	sh.Type = uint32(typ)
  1280  	sh.Entsize = uint64(arch.RegSize) * 2
  1281  	if typ == elf.SHT_RELA {
  1282  		sh.Entsize += uint64(arch.RegSize)
  1283  	}
  1284  	sh.Link = uint32(elfshname(".symtab").shnum)
  1285  	sh.Info = uint32(sect.Elfsect.(*ElfShdr).shnum)
  1286  	sh.Off = sect.Reloff
  1287  	sh.Size = sect.Rellen
  1288  	sh.Addralign = uint64(arch.RegSize)
  1289  	return sh
  1290  }
  1291  
  1292  func elfrelocsect(ctxt *Link, out *OutBuf, sect *sym.Section, syms []loader.Sym) {
  1293  	// If main section is SHT_NOBITS, nothing to relocate.
  1294  	// Also nothing to relocate in .shstrtab.
  1295  	if sect.Vaddr >= sect.Seg.Vaddr+sect.Seg.Filelen {
  1296  		return
  1297  	}
  1298  	if sect.Name == ".shstrtab" {
  1299  		return
  1300  	}
  1301  
  1302  	ldr := ctxt.loader
  1303  	for i, s := range syms {
  1304  		if !ldr.AttrReachable(s) {
  1305  			panic("should never happen")
  1306  		}
  1307  		if uint64(ldr.SymValue(s)) >= sect.Vaddr {
  1308  			syms = syms[i:]
  1309  			break
  1310  		}
  1311  	}
  1312  
  1313  	eaddr := sect.Vaddr + sect.Length
  1314  	for _, s := range syms {
  1315  		if !ldr.AttrReachable(s) {
  1316  			continue
  1317  		}
  1318  		if ldr.SymValue(s) >= int64(eaddr) {
  1319  			break
  1320  		}
  1321  
  1322  		// Compute external relocations on the go, and pass to
  1323  		// ELF.Reloc1 to stream out.
  1324  		relocs := ldr.Relocs(s)
  1325  		for ri := 0; ri < relocs.Count(); ri++ {
  1326  			r := relocs.At(ri)
  1327  			rr, ok := extreloc(ctxt, ldr, s, r)
  1328  			if !ok {
  1329  				continue
  1330  			}
  1331  			if rr.Xsym == 0 {
  1332  				ldr.Errorf(s, "missing xsym in relocation")
  1333  				continue
  1334  			}
  1335  			esr := ElfSymForReloc(ctxt, rr.Xsym)
  1336  			if esr == 0 {
  1337  				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())
  1338  			}
  1339  			if !ldr.AttrReachable(rr.Xsym) {
  1340  				ldr.Errorf(s, "unreachable reloc %d (%s) target %v", r.Type(), sym.RelocName(ctxt.Arch, r.Type()), ldr.SymName(rr.Xsym))
  1341  			}
  1342  			if !thearch.ELF.Reloc1(ctxt, out, ldr, s, rr, ri, int64(uint64(ldr.SymValue(s)+int64(r.Off()))-sect.Vaddr)) {
  1343  				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()))
  1344  			}
  1345  		}
  1346  	}
  1347  
  1348  	// sanity check
  1349  	if uint64(out.Offset()) != sect.Reloff+sect.Rellen {
  1350  		panic(fmt.Sprintf("elfrelocsect: size mismatch %d != %d + %d", out.Offset(), sect.Reloff, sect.Rellen))
  1351  	}
  1352  }
  1353  
  1354  func elfEmitReloc(ctxt *Link) {
  1355  	for ctxt.Out.Offset()&7 != 0 {
  1356  		ctxt.Out.Write8(0)
  1357  	}
  1358  
  1359  	sizeExtRelocs(ctxt, thearch.ELF.RelocSize)
  1360  	relocSect, wg := relocSectFn(ctxt, elfrelocsect)
  1361  
  1362  	for _, sect := range Segtext.Sections {
  1363  		if sect.Name == ".text" {
  1364  			relocSect(ctxt, sect, ctxt.Textp)
  1365  		} else {
  1366  			relocSect(ctxt, sect, ctxt.datap)
  1367  		}
  1368  	}
  1369  
  1370  	for _, sect := range Segrodata.Sections {
  1371  		relocSect(ctxt, sect, ctxt.datap)
  1372  	}
  1373  	for _, sect := range Segrelrodata.Sections {
  1374  		relocSect(ctxt, sect, ctxt.datap)
  1375  	}
  1376  	for _, sect := range Segdata.Sections {
  1377  		relocSect(ctxt, sect, ctxt.datap)
  1378  	}
  1379  	for i := 0; i < len(Segdwarf.Sections); i++ {
  1380  		sect := Segdwarf.Sections[i]
  1381  		si := dwarfp[i]
  1382  		if si.secSym() != loader.Sym(sect.Sym) ||
  1383  			ctxt.loader.SymSect(si.secSym()) != sect {
  1384  			panic("inconsistency between dwarfp and Segdwarf")
  1385  		}
  1386  		relocSect(ctxt, sect, si.syms)
  1387  	}
  1388  	wg.Wait()
  1389  }
  1390  
  1391  func addgonote(ctxt *Link, sectionName string, tag uint32, desc []byte) {
  1392  	ldr := ctxt.loader
  1393  	s := ldr.CreateSymForUpdate(sectionName, 0)
  1394  	s.SetType(sym.SELFROSECT)
  1395  	// namesz
  1396  	s.AddUint32(ctxt.Arch, uint32(len(ELF_NOTE_GO_NAME)))
  1397  	// descsz
  1398  	s.AddUint32(ctxt.Arch, uint32(len(desc)))
  1399  	// tag
  1400  	s.AddUint32(ctxt.Arch, tag)
  1401  	// name + padding
  1402  	s.AddBytes(ELF_NOTE_GO_NAME)
  1403  	for len(s.Data())%4 != 0 {
  1404  		s.AddUint8(0)
  1405  	}
  1406  	// desc + padding
  1407  	s.AddBytes(desc)
  1408  	for len(s.Data())%4 != 0 {
  1409  		s.AddUint8(0)
  1410  	}
  1411  	s.SetSize(int64(len(s.Data())))
  1412  	s.SetAlign(4)
  1413  }
  1414  
  1415  func (ctxt *Link) doelf() {
  1416  	ldr := ctxt.loader
  1417  
  1418  	/* predefine strings we need for section headers */
  1419  
  1420  	addshstr := func(s string) int {
  1421  		off := len(elfshstrdat)
  1422  		elfshstrdat = append(elfshstrdat, s...)
  1423  		elfshstrdat = append(elfshstrdat, 0)
  1424  		return off
  1425  	}
  1426  
  1427  	shstrtabAddstring := func(s string) {
  1428  		off := addshstr(s)
  1429  		elfsetstring(ctxt, 0, s, int(off))
  1430  	}
  1431  
  1432  	shstrtabAddstring("")
  1433  	shstrtabAddstring(".text")
  1434  	shstrtabAddstring(".noptrdata")
  1435  	shstrtabAddstring(".data")
  1436  	shstrtabAddstring(".bss")
  1437  	shstrtabAddstring(".noptrbss")
  1438  	shstrtabAddstring(".go.fuzzcntrs")
  1439  	shstrtabAddstring(".go.buildinfo")
  1440  	shstrtabAddstring(".go.fipsinfo")
  1441  	if ctxt.IsMIPS() {
  1442  		shstrtabAddstring(".MIPS.abiflags")
  1443  		shstrtabAddstring(".gnu.attributes")
  1444  	}
  1445  
  1446  	// generate .tbss section for dynamic internal linker or external
  1447  	// linking, so that various binutils could correctly calculate
  1448  	// PT_TLS size. See https://golang.org/issue/5200.
  1449  	if !*FlagD || ctxt.IsExternal() {
  1450  		shstrtabAddstring(".tbss")
  1451  	}
  1452  	if ctxt.IsNetbsd() {
  1453  		shstrtabAddstring(".note.netbsd.ident")
  1454  		if *flagRace {
  1455  			shstrtabAddstring(".note.netbsd.pax")
  1456  		}
  1457  	}
  1458  	if ctxt.IsOpenbsd() {
  1459  		shstrtabAddstring(".note.openbsd.ident")
  1460  	}
  1461  	if ctxt.IsFreebsd() {
  1462  		shstrtabAddstring(".note.tag")
  1463  	}
  1464  	if len(buildinfo) > 0 {
  1465  		shstrtabAddstring(".note.gnu.build-id")
  1466  	}
  1467  	if *flagBuildid != "" {
  1468  		shstrtabAddstring(".note.go.buildid")
  1469  	}
  1470  	shstrtabAddstring(".elfdata")
  1471  	shstrtabAddstring(".rodata")
  1472  	// See the comment about data.rel.ro.FOO section names in data.go.
  1473  	relro_prefix := ""
  1474  	if ctxt.UseRelro() {
  1475  		shstrtabAddstring(".data.rel.ro")
  1476  		relro_prefix = ".data.rel.ro"
  1477  	}
  1478  	shstrtabAddstring(relro_prefix + ".typelink")
  1479  	shstrtabAddstring(relro_prefix + ".itablink")
  1480  	shstrtabAddstring(relro_prefix + ".gosymtab")
  1481  	shstrtabAddstring(relro_prefix + ".gopclntab")
  1482  
  1483  	if ctxt.IsExternal() {
  1484  		*FlagD = true
  1485  
  1486  		shstrtabAddstring(elfRelType + ".text")
  1487  		shstrtabAddstring(elfRelType + ".rodata")
  1488  		shstrtabAddstring(elfRelType + relro_prefix + ".typelink")
  1489  		shstrtabAddstring(elfRelType + relro_prefix + ".itablink")
  1490  		shstrtabAddstring(elfRelType + relro_prefix + ".gosymtab")
  1491  		shstrtabAddstring(elfRelType + relro_prefix + ".gopclntab")
  1492  		shstrtabAddstring(elfRelType + ".noptrdata")
  1493  		shstrtabAddstring(elfRelType + ".data")
  1494  		if ctxt.UseRelro() {
  1495  			shstrtabAddstring(elfRelType + ".data.rel.ro")
  1496  		}
  1497  		shstrtabAddstring(elfRelType + ".go.buildinfo")
  1498  		shstrtabAddstring(elfRelType + ".go.fipsinfo")
  1499  		if ctxt.IsMIPS() {
  1500  			shstrtabAddstring(elfRelType + ".MIPS.abiflags")
  1501  			shstrtabAddstring(elfRelType + ".gnu.attributes")
  1502  		}
  1503  
  1504  		// add a .note.GNU-stack section to mark the stack as non-executable
  1505  		shstrtabAddstring(".note.GNU-stack")
  1506  
  1507  		if ctxt.IsShared() {
  1508  			shstrtabAddstring(".note.go.abihash")
  1509  			shstrtabAddstring(".note.go.pkg-list")
  1510  			shstrtabAddstring(".note.go.deps")
  1511  		}
  1512  	}
  1513  
  1514  	hasinitarr := ctxt.linkShared
  1515  
  1516  	/* shared library initializer */
  1517  	switch ctxt.BuildMode {
  1518  	case BuildModeCArchive, BuildModeCShared, BuildModeShared, BuildModePlugin:
  1519  		hasinitarr = true
  1520  	}
  1521  
  1522  	if hasinitarr {
  1523  		shstrtabAddstring(".init_array")
  1524  		shstrtabAddstring(elfRelType + ".init_array")
  1525  	}
  1526  
  1527  	if !*FlagS {
  1528  		shstrtabAddstring(".symtab")
  1529  		shstrtabAddstring(".strtab")
  1530  	}
  1531  	if !*FlagW {
  1532  		dwarfaddshstrings(ctxt, shstrtabAddstring)
  1533  	}
  1534  
  1535  	shstrtabAddstring(".shstrtab")
  1536  
  1537  	if !*FlagD { /* -d suppresses dynamic loader format */
  1538  		shstrtabAddstring(".interp")
  1539  		shstrtabAddstring(".hash")
  1540  		shstrtabAddstring(".got")
  1541  		if ctxt.IsPPC64() {
  1542  			shstrtabAddstring(".glink")
  1543  		}
  1544  		shstrtabAddstring(".got.plt")
  1545  		shstrtabAddstring(".dynamic")
  1546  		shstrtabAddstring(".dynsym")
  1547  		shstrtabAddstring(".dynstr")
  1548  		shstrtabAddstring(elfRelType)
  1549  		shstrtabAddstring(elfRelType + ".plt")
  1550  
  1551  		shstrtabAddstring(".plt")
  1552  		shstrtabAddstring(".gnu.version")
  1553  		shstrtabAddstring(".gnu.version_r")
  1554  
  1555  		/* dynamic symbol table - first entry all zeros */
  1556  		dynsym := ldr.CreateSymForUpdate(".dynsym", 0)
  1557  
  1558  		dynsym.SetType(sym.SELFROSECT)
  1559  		if elf64 {
  1560  			dynsym.SetSize(dynsym.Size() + ELF64SYMSIZE)
  1561  		} else {
  1562  			dynsym.SetSize(dynsym.Size() + ELF32SYMSIZE)
  1563  		}
  1564  
  1565  		/* dynamic string table */
  1566  		dynstr := ldr.CreateSymForUpdate(".dynstr", 0)
  1567  
  1568  		dynstr.SetType(sym.SELFROSECT)
  1569  		if dynstr.Size() == 0 {
  1570  			dynstr.Addstring("")
  1571  		}
  1572  
  1573  		/* relocation table */
  1574  		s := ldr.CreateSymForUpdate(elfRelType, 0)
  1575  		s.SetType(sym.SELFROSECT)
  1576  
  1577  		/* global offset table */
  1578  		got := ldr.CreateSymForUpdate(".got", 0)
  1579  		if ctxt.UseRelro() {
  1580  			got.SetType(sym.SELFRELROSECT)
  1581  		} else {
  1582  			got.SetType(sym.SELFGOT) // writable
  1583  		}
  1584  
  1585  		/* ppc64 glink resolver */
  1586  		if ctxt.IsPPC64() {
  1587  			s := ldr.CreateSymForUpdate(".glink", 0)
  1588  			s.SetType(sym.SELFRXSECT)
  1589  		}
  1590  
  1591  		/* hash */
  1592  		hash := ldr.CreateSymForUpdate(".hash", 0)
  1593  		hash.SetType(sym.SELFROSECT)
  1594  
  1595  		gotplt := ldr.CreateSymForUpdate(".got.plt", 0)
  1596  		if ctxt.UseRelro() && *flagBindNow {
  1597  			gotplt.SetType(sym.SELFRELROSECT)
  1598  		} else {
  1599  			gotplt.SetType(sym.SELFSECT) // writable
  1600  		}
  1601  
  1602  		plt := ldr.CreateSymForUpdate(".plt", 0)
  1603  		if ctxt.IsPPC64() {
  1604  			// In the ppc64 ABI, .plt is a data section
  1605  			// written by the dynamic linker.
  1606  			plt.SetType(sym.SELFSECT)
  1607  		} else {
  1608  			plt.SetType(sym.SELFRXSECT)
  1609  		}
  1610  
  1611  		s = ldr.CreateSymForUpdate(elfRelType+".plt", 0)
  1612  		s.SetType(sym.SELFROSECT)
  1613  
  1614  		s = ldr.CreateSymForUpdate(".gnu.version", 0)
  1615  		s.SetType(sym.SELFROSECT)
  1616  
  1617  		s = ldr.CreateSymForUpdate(".gnu.version_r", 0)
  1618  		s.SetType(sym.SELFROSECT)
  1619  
  1620  		/* define dynamic elf table */
  1621  		dynamic := ldr.CreateSymForUpdate(".dynamic", 0)
  1622  		switch {
  1623  		case thearch.ELF.DynamicReadOnly:
  1624  			dynamic.SetType(sym.SELFROSECT)
  1625  		case ctxt.UseRelro():
  1626  			dynamic.SetType(sym.SELFRELROSECT)
  1627  		default:
  1628  			dynamic.SetType(sym.SELFSECT)
  1629  		}
  1630  
  1631  		if ctxt.IsS390X() {
  1632  			// S390X uses .got instead of .got.plt
  1633  			gotplt = got
  1634  		}
  1635  		thearch.ELF.SetupPLT(ctxt, ctxt.loader, plt, gotplt, dynamic.Sym())
  1636  
  1637  		/*
  1638  		 * .dynamic table
  1639  		 */
  1640  		elfWriteDynEntSym(ctxt, dynamic, elf.DT_HASH, hash.Sym())
  1641  
  1642  		elfWriteDynEntSym(ctxt, dynamic, elf.DT_SYMTAB, dynsym.Sym())
  1643  		if elf64 {
  1644  			Elfwritedynent(ctxt.Arch, dynamic, elf.DT_SYMENT, ELF64SYMSIZE)
  1645  		} else {
  1646  			Elfwritedynent(ctxt.Arch, dynamic, elf.DT_SYMENT, ELF32SYMSIZE)
  1647  		}
  1648  		elfWriteDynEntSym(ctxt, dynamic, elf.DT_STRTAB, dynstr.Sym())
  1649  		elfwritedynentsymsize(ctxt, dynamic, elf.DT_STRSZ, dynstr.Sym())
  1650  		if elfRelType == ".rela" {
  1651  			rela := ldr.LookupOrCreateSym(".rela", 0)
  1652  			elfWriteDynEntSym(ctxt, dynamic, elf.DT_RELA, rela)
  1653  			elfwritedynentsymsize(ctxt, dynamic, elf.DT_RELASZ, rela)
  1654  			Elfwritedynent(ctxt.Arch, dynamic, elf.DT_RELAENT, ELF64RELASIZE)
  1655  		} else {
  1656  			rel := ldr.LookupOrCreateSym(".rel", 0)
  1657  			elfWriteDynEntSym(ctxt, dynamic, elf.DT_REL, rel)
  1658  			elfwritedynentsymsize(ctxt, dynamic, elf.DT_RELSZ, rel)
  1659  			Elfwritedynent(ctxt.Arch, dynamic, elf.DT_RELENT, ELF32RELSIZE)
  1660  		}
  1661  
  1662  		if rpath.val != "" {
  1663  			Elfwritedynent(ctxt.Arch, dynamic, elf.DT_RUNPATH, uint64(dynstr.Addstring(rpath.val)))
  1664  		}
  1665  
  1666  		if ctxt.IsPPC64() {
  1667  			elfWriteDynEntSym(ctxt, dynamic, elf.DT_PLTGOT, plt.Sym())
  1668  		} else {
  1669  			elfWriteDynEntSym(ctxt, dynamic, elf.DT_PLTGOT, gotplt.Sym())
  1670  		}
  1671  
  1672  		if ctxt.IsPPC64() {
  1673  			Elfwritedynent(ctxt.Arch, dynamic, elf.DT_PPC64_OPT, 0)
  1674  		}
  1675  
  1676  		// Solaris dynamic linker can't handle an empty .rela.plt if
  1677  		// DT_JMPREL is emitted so we have to defer generation of elf.DT_PLTREL,
  1678  		// DT_PLTRELSZ, and elf.DT_JMPREL dynamic entries until after we know the
  1679  		// size of .rel(a).plt section.
  1680  
  1681  		Elfwritedynent(ctxt.Arch, dynamic, elf.DT_DEBUG, 0)
  1682  	}
  1683  
  1684  	if ctxt.IsShared() {
  1685  		// The go.link.abihashbytes symbol will be pointed at the appropriate
  1686  		// part of the .note.go.abihash section in data.go:func address().
  1687  		s := ldr.LookupOrCreateSym("go:link.abihashbytes", 0)
  1688  		sb := ldr.MakeSymbolUpdater(s)
  1689  		ldr.SetAttrLocal(s, true)
  1690  		sb.SetType(sym.SRODATA)
  1691  		ldr.SetAttrSpecial(s, true)
  1692  		sb.SetReachable(true)
  1693  		sb.SetSize(hash.Size20)
  1694  		slices.SortFunc(ctxt.Library, func(a, b *sym.Library) int {
  1695  			return strings.Compare(a.Pkg, b.Pkg)
  1696  		})
  1697  		h := hash.New20()
  1698  		for _, l := range ctxt.Library {
  1699  			h.Write(l.Fingerprint[:])
  1700  		}
  1701  		addgonote(ctxt, ".note.go.abihash", ELF_NOTE_GOABIHASH_TAG, h.Sum([]byte{}))
  1702  		addgonote(ctxt, ".note.go.pkg-list", ELF_NOTE_GOPKGLIST_TAG, pkglistfornote)
  1703  		var deplist []string
  1704  		for _, shlib := range ctxt.Shlibs {
  1705  			deplist = append(deplist, filepath.Base(shlib.Path))
  1706  		}
  1707  		addgonote(ctxt, ".note.go.deps", ELF_NOTE_GODEPS_TAG, []byte(strings.Join(deplist, "\n")))
  1708  	}
  1709  
  1710  	if ctxt.LinkMode == LinkExternal && *flagBuildid != "" {
  1711  		addgonote(ctxt, ".note.go.buildid", ELF_NOTE_GOBUILDID_TAG, []byte(*flagBuildid))
  1712  	}
  1713  
  1714  	//type mipsGnuAttributes struct {
  1715  	//	version uint8   // 'A'
  1716  	//	length  uint32  // 15 including itself
  1717  	//	gnu     [4]byte // "gnu\0"
  1718  	//	tag     uint8   // 1:file, 2: section, 3: symbol, 1 here
  1719  	//	taglen  uint32  // tag length, including tag, 7 here
  1720  	//	tagfp   uint8   // 4
  1721  	//	fpAbi  uint8    // see .MIPS.abiflags
  1722  	//}
  1723  	if ctxt.IsMIPS() {
  1724  		gnuattributes := ldr.CreateSymForUpdate(".gnu.attributes", 0)
  1725  		gnuattributes.SetType(sym.SELFROSECT)
  1726  		gnuattributes.SetReachable(true)
  1727  		gnuattributes.AddUint8('A')               // version 'A'
  1728  		gnuattributes.AddUint32(ctxt.Arch, 15)    // length 15 including itself
  1729  		gnuattributes.AddBytes([]byte("gnu\x00")) // "gnu\0"
  1730  		gnuattributes.AddUint8(1)                 // 1:file, 2: section, 3: symbol, 1 here
  1731  		gnuattributes.AddUint32(ctxt.Arch, 7)     // tag length, including tag, 7 here
  1732  		gnuattributes.AddUint8(4)                 // 4 for FP, 8 for MSA
  1733  		if buildcfg.GOMIPS == "softfloat" {
  1734  			gnuattributes.AddUint8(MIPS_FPABI_SOFT)
  1735  		} else {
  1736  			// Note: MIPS_FPABI_ANY is bad naming: in fact it is MIPS I style FPR usage.
  1737  			//       It is not for 'ANY'.
  1738  			// TODO: switch to FPXX after be sure that no odd-number-fpr is used.
  1739  			gnuattributes.AddUint8(MIPS_FPABI_ANY)
  1740  		}
  1741  	}
  1742  }
  1743  
  1744  // Do not write DT_NULL.  elfdynhash will finish it.
  1745  func shsym(sh *ElfShdr, ldr *loader.Loader, s loader.Sym) {
  1746  	if s == 0 {
  1747  		panic("bad symbol in shsym2")
  1748  	}
  1749  	addr := ldr.SymValue(s)
  1750  	if sh.Flags&uint64(elf.SHF_ALLOC) != 0 {
  1751  		sh.Addr = uint64(addr)
  1752  	}
  1753  	sh.Off = uint64(datoff(ldr, s, addr))
  1754  	sh.Size = uint64(ldr.SymSize(s))
  1755  }
  1756  
  1757  func phsh(ph *ElfPhdr, sh *ElfShdr) {
  1758  	ph.Vaddr = sh.Addr
  1759  	ph.Paddr = ph.Vaddr
  1760  	ph.Off = sh.Off
  1761  	ph.Filesz = sh.Size
  1762  	ph.Memsz = sh.Size
  1763  	ph.Align = sh.Addralign
  1764  }
  1765  
  1766  func Asmbelfsetup() {
  1767  	/* This null SHdr must appear before all others */
  1768  	elfshname("")
  1769  
  1770  	for _, sect := range Segtext.Sections {
  1771  		// There could be multiple .text sections. Instead check the Elfsect
  1772  		// field to determine if already has an ElfShdr and if not, create one.
  1773  		if sect.Name == ".text" {
  1774  			if sect.Elfsect == nil {
  1775  				sect.Elfsect = elfshnamedup(sect.Name)
  1776  			}
  1777  		} else {
  1778  			elfshalloc(sect)
  1779  		}
  1780  	}
  1781  	for _, sect := range Segrodata.Sections {
  1782  		elfshalloc(sect)
  1783  	}
  1784  	for _, sect := range Segrelrodata.Sections {
  1785  		elfshalloc(sect)
  1786  	}
  1787  	for _, sect := range Segdata.Sections {
  1788  		elfshalloc(sect)
  1789  	}
  1790  	for _, sect := range Segdwarf.Sections {
  1791  		elfshalloc(sect)
  1792  	}
  1793  }
  1794  
  1795  func asmbElf(ctxt *Link) {
  1796  	var symo int64
  1797  	symo = int64(Segdwarf.Fileoff + Segdwarf.Filelen)
  1798  	symo = Rnd(symo, int64(ctxt.Arch.PtrSize))
  1799  	ctxt.Out.SeekSet(symo)
  1800  	if *FlagS {
  1801  		ctxt.Out.Write(elfshstrdat)
  1802  	} else {
  1803  		ctxt.Out.SeekSet(symo)
  1804  		asmElfSym(ctxt)
  1805  		ctxt.Out.Write(elfstrdat)
  1806  		ctxt.Out.Write(elfshstrdat)
  1807  		if ctxt.IsExternal() {
  1808  			elfEmitReloc(ctxt)
  1809  		}
  1810  	}
  1811  	ctxt.Out.SeekSet(0)
  1812  
  1813  	ldr := ctxt.loader
  1814  	eh := getElfEhdr()
  1815  	switch ctxt.Arch.Family {
  1816  	default:
  1817  		Exitf("unknown architecture in asmbelf: %v", ctxt.Arch.Family)
  1818  	case sys.MIPS, sys.MIPS64:
  1819  		eh.Machine = uint16(elf.EM_MIPS)
  1820  	case sys.Loong64:
  1821  		eh.Machine = uint16(elf.EM_LOONGARCH)
  1822  	case sys.ARM:
  1823  		eh.Machine = uint16(elf.EM_ARM)
  1824  	case sys.AMD64:
  1825  		eh.Machine = uint16(elf.EM_X86_64)
  1826  	case sys.ARM64:
  1827  		eh.Machine = uint16(elf.EM_AARCH64)
  1828  	case sys.I386:
  1829  		eh.Machine = uint16(elf.EM_386)
  1830  	case sys.PPC64:
  1831  		eh.Machine = uint16(elf.EM_PPC64)
  1832  	case sys.RISCV64:
  1833  		eh.Machine = uint16(elf.EM_RISCV)
  1834  	case sys.S390X:
  1835  		eh.Machine = uint16(elf.EM_S390)
  1836  	}
  1837  
  1838  	elfreserve := int64(ELFRESERVE)
  1839  
  1840  	numtext := int64(0)
  1841  	for _, sect := range Segtext.Sections {
  1842  		if sect.Name == ".text" {
  1843  			numtext++
  1844  		}
  1845  	}
  1846  
  1847  	// If there are multiple text sections, extra space is needed
  1848  	// in the elfreserve for the additional .text and .rela.text
  1849  	// section headers.  It can handle 4 extra now. Headers are
  1850  	// 64 bytes.
  1851  
  1852  	if numtext > 4 {
  1853  		elfreserve += elfreserve + numtext*64*2
  1854  	}
  1855  
  1856  	startva := *FlagTextAddr - int64(HEADR)
  1857  	resoff := elfreserve
  1858  
  1859  	var pph *ElfPhdr
  1860  	var pnote *ElfPhdr
  1861  	getpnote := func() *ElfPhdr {
  1862  		if pnote == nil {
  1863  			pnote = newElfPhdr()
  1864  			pnote.Type = elf.PT_NOTE
  1865  			pnote.Flags = elf.PF_R
  1866  		}
  1867  		return pnote
  1868  	}
  1869  	if *flagRace && ctxt.IsNetbsd() {
  1870  		sh := elfshname(".note.netbsd.pax")
  1871  		resoff -= int64(elfnetbsdpax(sh, uint64(startva), uint64(resoff)))
  1872  		phsh(getpnote(), sh)
  1873  	}
  1874  	if ctxt.LinkMode == LinkExternal {
  1875  		/* skip program headers */
  1876  		eh.Phoff = 0
  1877  
  1878  		eh.Phentsize = 0
  1879  
  1880  		if ctxt.BuildMode == BuildModeShared {
  1881  			sh := elfshname(".note.go.pkg-list")
  1882  			sh.Type = uint32(elf.SHT_NOTE)
  1883  			sh = elfshname(".note.go.abihash")
  1884  			sh.Type = uint32(elf.SHT_NOTE)
  1885  			sh.Flags = uint64(elf.SHF_ALLOC)
  1886  			sh = elfshname(".note.go.deps")
  1887  			sh.Type = uint32(elf.SHT_NOTE)
  1888  		}
  1889  
  1890  		if *flagBuildid != "" {
  1891  			sh := elfshname(".note.go.buildid")
  1892  			sh.Type = uint32(elf.SHT_NOTE)
  1893  			sh.Flags = uint64(elf.SHF_ALLOC)
  1894  		}
  1895  
  1896  		goto elfobj
  1897  	}
  1898  
  1899  	/* program header info */
  1900  	pph = newElfPhdr()
  1901  
  1902  	pph.Type = elf.PT_PHDR
  1903  	pph.Flags = elf.PF_R
  1904  	pph.Off = uint64(eh.Ehsize)
  1905  	pph.Vaddr = uint64(*FlagTextAddr) - uint64(HEADR) + pph.Off
  1906  	pph.Paddr = uint64(*FlagTextAddr) - uint64(HEADR) + pph.Off
  1907  	pph.Align = uint64(*FlagRound)
  1908  
  1909  	/*
  1910  	 * PHDR must be in a loaded segment. Adjust the text
  1911  	 * segment boundaries downwards to include it.
  1912  	 */
  1913  	{
  1914  		o := int64(Segtext.Vaddr - pph.Vaddr)
  1915  		Segtext.Vaddr -= uint64(o)
  1916  		Segtext.Length += uint64(o)
  1917  		o = int64(Segtext.Fileoff - pph.Off)
  1918  		Segtext.Fileoff -= uint64(o)
  1919  		Segtext.Filelen += uint64(o)
  1920  	}
  1921  
  1922  	if !*FlagD { /* -d suppresses dynamic loader format */
  1923  		/* interpreter */
  1924  		sh := elfshname(".interp")
  1925  
  1926  		sh.Type = uint32(elf.SHT_PROGBITS)
  1927  		sh.Flags = uint64(elf.SHF_ALLOC)
  1928  		sh.Addralign = 1
  1929  
  1930  		if interpreter == "" && buildcfg.GOOS == runtime.GOOS && buildcfg.GOARCH == runtime.GOARCH && buildcfg.GO_LDSO != "" {
  1931  			interpreter = buildcfg.GO_LDSO
  1932  		}
  1933  
  1934  		if interpreter == "" {
  1935  			switch ctxt.HeadType {
  1936  			case objabi.Hlinux:
  1937  				if buildcfg.GOOS == "android" {
  1938  					interpreter = thearch.ELF.Androiddynld
  1939  					if interpreter == "" {
  1940  						Exitf("ELF interpreter not set")
  1941  					}
  1942  				} else {
  1943  					interpreter = thearch.ELF.Linuxdynld
  1944  					// If interpreter does not exist, try musl instead.
  1945  					// This lets the same cmd/link binary work on
  1946  					// both glibc-based and musl-based systems.
  1947  					if _, err := os.Stat(interpreter); err != nil {
  1948  						if musl := thearch.ELF.LinuxdynldMusl; musl != "" {
  1949  							if _, err := os.Stat(musl); err == nil {
  1950  								interpreter = musl
  1951  							}
  1952  						}
  1953  					}
  1954  				}
  1955  
  1956  			case objabi.Hfreebsd:
  1957  				interpreter = thearch.ELF.Freebsddynld
  1958  
  1959  			case objabi.Hnetbsd:
  1960  				interpreter = thearch.ELF.Netbsddynld
  1961  
  1962  			case objabi.Hopenbsd:
  1963  				interpreter = thearch.ELF.Openbsddynld
  1964  
  1965  			case objabi.Hdragonfly:
  1966  				interpreter = thearch.ELF.Dragonflydynld
  1967  
  1968  			case objabi.Hsolaris:
  1969  				interpreter = thearch.ELF.Solarisdynld
  1970  			}
  1971  		}
  1972  
  1973  		resoff -= int64(elfinterp(sh, uint64(startva), uint64(resoff), interpreter))
  1974  
  1975  		ph := newElfPhdr()
  1976  		ph.Type = elf.PT_INTERP
  1977  		ph.Flags = elf.PF_R
  1978  		phsh(ph, sh)
  1979  	}
  1980  
  1981  	if ctxt.HeadType == objabi.Hnetbsd || ctxt.HeadType == objabi.Hopenbsd || ctxt.HeadType == objabi.Hfreebsd {
  1982  		var sh *ElfShdr
  1983  		switch ctxt.HeadType {
  1984  		case objabi.Hnetbsd:
  1985  			sh = elfshname(".note.netbsd.ident")
  1986  			resoff -= int64(elfnetbsdsig(sh, uint64(startva), uint64(resoff)))
  1987  
  1988  		case objabi.Hopenbsd:
  1989  			sh = elfshname(".note.openbsd.ident")
  1990  			resoff -= int64(elfopenbsdsig(sh, uint64(startva), uint64(resoff)))
  1991  
  1992  		case objabi.Hfreebsd:
  1993  			sh = elfshname(".note.tag")
  1994  			resoff -= int64(elffreebsdsig(sh, uint64(startva), uint64(resoff)))
  1995  		}
  1996  		// NetBSD, OpenBSD and FreeBSD require ident in an independent segment.
  1997  		pnotei := newElfPhdr()
  1998  		pnotei.Type = elf.PT_NOTE
  1999  		pnotei.Flags = elf.PF_R
  2000  		phsh(pnotei, sh)
  2001  	}
  2002  
  2003  	if len(buildinfo) > 0 {
  2004  		sh := elfshname(".note.gnu.build-id")
  2005  		resoff -= int64(elfbuildinfo(sh, uint64(startva), uint64(resoff)))
  2006  		phsh(getpnote(), sh)
  2007  	}
  2008  
  2009  	if *flagBuildid != "" {
  2010  		sh := elfshname(".note.go.buildid")
  2011  		resoff -= int64(elfgobuildid(sh, uint64(startva), uint64(resoff)))
  2012  		phsh(getpnote(), sh)
  2013  	}
  2014  
  2015  	// Additions to the reserved area must be above this line.
  2016  
  2017  	elfphload(&Segtext)
  2018  	if len(Segrodata.Sections) > 0 {
  2019  		elfphload(&Segrodata)
  2020  	}
  2021  	if len(Segrelrodata.Sections) > 0 {
  2022  		elfphload(&Segrelrodata)
  2023  		elfphrelro(&Segrelrodata)
  2024  	}
  2025  	elfphload(&Segdata)
  2026  
  2027  	/* Dynamic linking sections */
  2028  	if !*FlagD {
  2029  		sh := elfshname(".dynsym")
  2030  		sh.Type = uint32(elf.SHT_DYNSYM)
  2031  		sh.Flags = uint64(elf.SHF_ALLOC)
  2032  		if elf64 {
  2033  			sh.Entsize = ELF64SYMSIZE
  2034  		} else {
  2035  			sh.Entsize = ELF32SYMSIZE
  2036  		}
  2037  		sh.Addralign = uint64(ctxt.Arch.RegSize)
  2038  		sh.Link = uint32(elfshname(".dynstr").shnum)
  2039  
  2040  		// sh.info is the index of first non-local symbol (number of local symbols)
  2041  		s := ldr.Lookup(".dynsym", 0)
  2042  		i := uint32(0)
  2043  		for sub := s; sub != 0; sub = ldr.SubSym(sub) {
  2044  			i++
  2045  			if !ldr.AttrLocal(sub) {
  2046  				break
  2047  			}
  2048  		}
  2049  		sh.Info = i
  2050  		shsym(sh, ldr, s)
  2051  
  2052  		sh = elfshname(".dynstr")
  2053  		sh.Type = uint32(elf.SHT_STRTAB)
  2054  		sh.Flags = uint64(elf.SHF_ALLOC)
  2055  		sh.Addralign = 1
  2056  		shsym(sh, ldr, ldr.Lookup(".dynstr", 0))
  2057  
  2058  		if elfverneed != 0 {
  2059  			sh := elfshname(".gnu.version")
  2060  			sh.Type = uint32(elf.SHT_GNU_VERSYM)
  2061  			sh.Flags = uint64(elf.SHF_ALLOC)
  2062  			sh.Addralign = 2
  2063  			sh.Link = uint32(elfshname(".dynsym").shnum)
  2064  			sh.Entsize = 2
  2065  			shsym(sh, ldr, ldr.Lookup(".gnu.version", 0))
  2066  
  2067  			sh = elfshname(".gnu.version_r")
  2068  			sh.Type = uint32(elf.SHT_GNU_VERNEED)
  2069  			sh.Flags = uint64(elf.SHF_ALLOC)
  2070  			sh.Addralign = uint64(ctxt.Arch.RegSize)
  2071  			sh.Info = uint32(elfverneed)
  2072  			sh.Link = uint32(elfshname(".dynstr").shnum)
  2073  			shsym(sh, ldr, ldr.Lookup(".gnu.version_r", 0))
  2074  		}
  2075  
  2076  		if elfRelType == ".rela" {
  2077  			sh := elfshname(".rela.plt")
  2078  			sh.Type = uint32(elf.SHT_RELA)
  2079  			sh.Flags = uint64(elf.SHF_ALLOC)
  2080  			sh.Entsize = ELF64RELASIZE
  2081  			sh.Addralign = uint64(ctxt.Arch.RegSize)
  2082  			sh.Link = uint32(elfshname(".dynsym").shnum)
  2083  			sh.Info = uint32(elfshname(".plt").shnum)
  2084  			shsym(sh, ldr, ldr.Lookup(".rela.plt", 0))
  2085  
  2086  			sh = elfshname(".rela")
  2087  			sh.Type = uint32(elf.SHT_RELA)
  2088  			sh.Flags = uint64(elf.SHF_ALLOC)
  2089  			sh.Entsize = ELF64RELASIZE
  2090  			sh.Addralign = 8
  2091  			sh.Link = uint32(elfshname(".dynsym").shnum)
  2092  			shsym(sh, ldr, ldr.Lookup(".rela", 0))
  2093  		} else {
  2094  			sh := elfshname(".rel.plt")
  2095  			sh.Type = uint32(elf.SHT_REL)
  2096  			sh.Flags = uint64(elf.SHF_ALLOC)
  2097  			sh.Entsize = ELF32RELSIZE
  2098  			sh.Addralign = 4
  2099  			sh.Link = uint32(elfshname(".dynsym").shnum)
  2100  			shsym(sh, ldr, ldr.Lookup(".rel.plt", 0))
  2101  
  2102  			sh = elfshname(".rel")
  2103  			sh.Type = uint32(elf.SHT_REL)
  2104  			sh.Flags = uint64(elf.SHF_ALLOC)
  2105  			sh.Entsize = ELF32RELSIZE
  2106  			sh.Addralign = 4
  2107  			sh.Link = uint32(elfshname(".dynsym").shnum)
  2108  			shsym(sh, ldr, ldr.Lookup(".rel", 0))
  2109  		}
  2110  
  2111  		if elf.Machine(eh.Machine) == elf.EM_PPC64 {
  2112  			sh := elfshname(".glink")
  2113  			sh.Type = uint32(elf.SHT_PROGBITS)
  2114  			sh.Flags = uint64(elf.SHF_ALLOC + elf.SHF_EXECINSTR)
  2115  			sh.Addralign = 4
  2116  			shsym(sh, ldr, ldr.Lookup(".glink", 0))
  2117  		}
  2118  
  2119  		sh = elfshname(".plt")
  2120  		sh.Type = uint32(elf.SHT_PROGBITS)
  2121  		sh.Flags = uint64(elf.SHF_ALLOC + elf.SHF_EXECINSTR)
  2122  		if elf.Machine(eh.Machine) == elf.EM_X86_64 {
  2123  			sh.Entsize = 16
  2124  		} else if elf.Machine(eh.Machine) == elf.EM_S390 {
  2125  			sh.Entsize = 32
  2126  		} else if elf.Machine(eh.Machine) == elf.EM_PPC64 {
  2127  			// On ppc64, this is just a table of addresses
  2128  			// filled by the dynamic linker
  2129  			sh.Type = uint32(elf.SHT_NOBITS)
  2130  
  2131  			sh.Flags = uint64(elf.SHF_ALLOC + elf.SHF_WRITE)
  2132  			sh.Entsize = 8
  2133  		} else {
  2134  			sh.Entsize = 4
  2135  		}
  2136  		sh.Addralign = sh.Entsize
  2137  		shsym(sh, ldr, ldr.Lookup(".plt", 0))
  2138  
  2139  		// On ppc64, .got comes from the input files, so don't
  2140  		// create it here, and .got.plt is not used.
  2141  		if elf.Machine(eh.Machine) != elf.EM_PPC64 {
  2142  			sh := elfshname(".got")
  2143  			sh.Type = uint32(elf.SHT_PROGBITS)
  2144  			sh.Flags = uint64(elf.SHF_ALLOC + elf.SHF_WRITE)
  2145  			sh.Entsize = uint64(ctxt.Arch.RegSize)
  2146  			sh.Addralign = uint64(ctxt.Arch.RegSize)
  2147  			shsym(sh, ldr, ldr.Lookup(".got", 0))
  2148  
  2149  			sh = elfshname(".got.plt")
  2150  			sh.Type = uint32(elf.SHT_PROGBITS)
  2151  			sh.Flags = uint64(elf.SHF_ALLOC + elf.SHF_WRITE)
  2152  			sh.Entsize = uint64(ctxt.Arch.RegSize)
  2153  			sh.Addralign = uint64(ctxt.Arch.RegSize)
  2154  			shsym(sh, ldr, ldr.Lookup(".got.plt", 0))
  2155  		}
  2156  
  2157  		sh = elfshname(".hash")
  2158  		sh.Type = uint32(elf.SHT_HASH)
  2159  		sh.Flags = uint64(elf.SHF_ALLOC)
  2160  		sh.Entsize = 4
  2161  		sh.Addralign = uint64(ctxt.Arch.RegSize)
  2162  		sh.Link = uint32(elfshname(".dynsym").shnum)
  2163  		shsym(sh, ldr, ldr.Lookup(".hash", 0))
  2164  
  2165  		/* sh and elf.PT_DYNAMIC for .dynamic section */
  2166  		sh = elfshname(".dynamic")
  2167  
  2168  		sh.Type = uint32(elf.SHT_DYNAMIC)
  2169  		sh.Flags = uint64(elf.SHF_ALLOC + elf.SHF_WRITE)
  2170  		sh.Entsize = 2 * uint64(ctxt.Arch.RegSize)
  2171  		sh.Addralign = uint64(ctxt.Arch.RegSize)
  2172  		sh.Link = uint32(elfshname(".dynstr").shnum)
  2173  		shsym(sh, ldr, ldr.Lookup(".dynamic", 0))
  2174  		ph := newElfPhdr()
  2175  		ph.Type = elf.PT_DYNAMIC
  2176  		ph.Flags = elf.PF_R + elf.PF_W
  2177  		phsh(ph, sh)
  2178  
  2179  		/*
  2180  		 * Thread-local storage segment (really just size).
  2181  		 */
  2182  		tlssize := uint64(0)
  2183  		for _, sect := range Segdata.Sections {
  2184  			if sect.Name == ".tbss" {
  2185  				tlssize = sect.Length
  2186  			}
  2187  		}
  2188  		if tlssize != 0 {
  2189  			ph := newElfPhdr()
  2190  			ph.Type = elf.PT_TLS
  2191  			ph.Flags = elf.PF_R
  2192  			ph.Memsz = tlssize
  2193  			ph.Align = uint64(ctxt.Arch.RegSize)
  2194  		}
  2195  	}
  2196  
  2197  	if ctxt.HeadType == objabi.Hlinux || ctxt.HeadType == objabi.Hfreebsd {
  2198  		ph := newElfPhdr()
  2199  		ph.Type = elf.PT_GNU_STACK
  2200  		ph.Flags = elf.PF_W + elf.PF_R
  2201  		ph.Align = uint64(ctxt.Arch.RegSize)
  2202  	} else if ctxt.HeadType == objabi.Hopenbsd {
  2203  		ph := newElfPhdr()
  2204  		ph.Type = elf.PT_OPENBSD_NOBTCFI
  2205  		ph.Flags = elf.PF_X
  2206  	} else if ctxt.HeadType == objabi.Hsolaris {
  2207  		ph := newElfPhdr()
  2208  		ph.Type = elf.PT_SUNWSTACK
  2209  		ph.Flags = elf.PF_W + elf.PF_R
  2210  	}
  2211  
  2212  elfobj:
  2213  	sh := elfshname(".shstrtab")
  2214  	eh.Shstrndx = uint16(sh.shnum)
  2215  
  2216  	if ctxt.IsMIPS() {
  2217  		sh = elfshname(".MIPS.abiflags")
  2218  		sh.Type = uint32(elf.SHT_MIPS_ABIFLAGS)
  2219  		sh.Flags = uint64(elf.SHF_ALLOC)
  2220  		sh.Addralign = 8
  2221  		resoff -= int64(elfMipsAbiFlags(sh, uint64(startva), uint64(resoff)))
  2222  
  2223  		ph := newElfPhdr()
  2224  		ph.Type = elf.PT_MIPS_ABIFLAGS
  2225  		ph.Flags = elf.PF_R
  2226  		phsh(ph, sh)
  2227  
  2228  		sh = elfshname(".gnu.attributes")
  2229  		sh.Type = uint32(elf.SHT_GNU_ATTRIBUTES)
  2230  		sh.Addralign = 1
  2231  		ldr := ctxt.loader
  2232  		shsym(sh, ldr, ldr.Lookup(".gnu.attributes", 0))
  2233  	}
  2234  
  2235  	// put these sections early in the list
  2236  	if !*FlagS {
  2237  		elfshname(".symtab")
  2238  		elfshname(".strtab")
  2239  	}
  2240  	elfshname(".shstrtab")
  2241  
  2242  	for _, sect := range Segtext.Sections {
  2243  		elfshbits(ctxt.LinkMode, sect)
  2244  	}
  2245  	for _, sect := range Segrodata.Sections {
  2246  		elfshbits(ctxt.LinkMode, sect)
  2247  	}
  2248  	for _, sect := range Segrelrodata.Sections {
  2249  		elfshbits(ctxt.LinkMode, sect)
  2250  	}
  2251  	for _, sect := range Segdata.Sections {
  2252  		elfshbits(ctxt.LinkMode, sect)
  2253  	}
  2254  	for _, sect := range Segdwarf.Sections {
  2255  		elfshbits(ctxt.LinkMode, sect)
  2256  	}
  2257  
  2258  	if ctxt.LinkMode == LinkExternal {
  2259  		for _, sect := range Segtext.Sections {
  2260  			elfshreloc(ctxt.Arch, sect)
  2261  		}
  2262  		for _, sect := range Segrodata.Sections {
  2263  			elfshreloc(ctxt.Arch, sect)
  2264  		}
  2265  		for _, sect := range Segrelrodata.Sections {
  2266  			elfshreloc(ctxt.Arch, sect)
  2267  		}
  2268  		for _, sect := range Segdata.Sections {
  2269  			elfshreloc(ctxt.Arch, sect)
  2270  		}
  2271  		for _, si := range dwarfp {
  2272  			sect := ldr.SymSect(si.secSym())
  2273  			elfshreloc(ctxt.Arch, sect)
  2274  		}
  2275  		// add a .note.GNU-stack section to mark the stack as non-executable
  2276  		sh := elfshname(".note.GNU-stack")
  2277  
  2278  		sh.Type = uint32(elf.SHT_PROGBITS)
  2279  		sh.Addralign = 1
  2280  		sh.Flags = 0
  2281  	}
  2282  
  2283  	var shstroff uint64
  2284  	if !*FlagS {
  2285  		sh := elfshname(".symtab")
  2286  		sh.Type = uint32(elf.SHT_SYMTAB)
  2287  		sh.Off = uint64(symo)
  2288  		sh.Size = uint64(symSize)
  2289  		sh.Addralign = uint64(ctxt.Arch.RegSize)
  2290  		sh.Entsize = 8 + 2*uint64(ctxt.Arch.RegSize)
  2291  		sh.Link = uint32(elfshname(".strtab").shnum)
  2292  		sh.Info = uint32(elfglobalsymndx)
  2293  
  2294  		sh = elfshname(".strtab")
  2295  		sh.Type = uint32(elf.SHT_STRTAB)
  2296  		sh.Off = uint64(symo) + uint64(symSize)
  2297  		sh.Size = uint64(len(elfstrdat))
  2298  		sh.Addralign = 1
  2299  		shstroff = sh.Off + sh.Size
  2300  	} else {
  2301  		shstroff = uint64(symo)
  2302  	}
  2303  
  2304  	sh = elfshname(".shstrtab")
  2305  	sh.Type = uint32(elf.SHT_STRTAB)
  2306  	sh.Off = shstroff
  2307  	sh.Size = uint64(len(elfshstrdat))
  2308  	sh.Addralign = 1
  2309  
  2310  	/* Main header */
  2311  	copy(eh.Ident[:], elf.ELFMAG)
  2312  
  2313  	var osabi elf.OSABI
  2314  	switch ctxt.HeadType {
  2315  	case objabi.Hfreebsd:
  2316  		osabi = elf.ELFOSABI_FREEBSD
  2317  	case objabi.Hnetbsd:
  2318  		osabi = elf.ELFOSABI_NETBSD
  2319  	case objabi.Hopenbsd:
  2320  		osabi = elf.ELFOSABI_OPENBSD
  2321  	case objabi.Hdragonfly:
  2322  		osabi = elf.ELFOSABI_NONE
  2323  	}
  2324  	eh.Ident[elf.EI_OSABI] = byte(osabi)
  2325  
  2326  	if elf64 {
  2327  		eh.Ident[elf.EI_CLASS] = byte(elf.ELFCLASS64)
  2328  	} else {
  2329  		eh.Ident[elf.EI_CLASS] = byte(elf.ELFCLASS32)
  2330  	}
  2331  	if ctxt.Arch.ByteOrder == binary.BigEndian {
  2332  		eh.Ident[elf.EI_DATA] = byte(elf.ELFDATA2MSB)
  2333  	} else {
  2334  		eh.Ident[elf.EI_DATA] = byte(elf.ELFDATA2LSB)
  2335  	}
  2336  	eh.Ident[elf.EI_VERSION] = byte(elf.EV_CURRENT)
  2337  
  2338  	if ctxt.LinkMode == LinkExternal {
  2339  		eh.Type = uint16(elf.ET_REL)
  2340  	} else if ctxt.BuildMode == BuildModePIE {
  2341  		eh.Type = uint16(elf.ET_DYN)
  2342  	} else {
  2343  		eh.Type = uint16(elf.ET_EXEC)
  2344  	}
  2345  
  2346  	if ctxt.LinkMode != LinkExternal {
  2347  		eh.Entry = uint64(Entryvalue(ctxt))
  2348  	}
  2349  
  2350  	eh.Version = uint32(elf.EV_CURRENT)
  2351  
  2352  	if pph != nil {
  2353  		pph.Filesz = uint64(eh.Phnum) * uint64(eh.Phentsize)
  2354  		pph.Memsz = pph.Filesz
  2355  	}
  2356  
  2357  	ctxt.Out.SeekSet(0)
  2358  	a := int64(0)
  2359  	a += int64(elfwritehdr(ctxt.Out))
  2360  	a += int64(elfwritephdrs(ctxt.Out))
  2361  	a += int64(elfwriteshdrs(ctxt.Out))
  2362  	if !*FlagD {
  2363  		a += int64(elfwriteinterp(ctxt.Out))
  2364  	}
  2365  	if ctxt.IsMIPS() {
  2366  		a += int64(elfWriteMipsAbiFlags(ctxt))
  2367  	}
  2368  
  2369  	if ctxt.LinkMode != LinkExternal {
  2370  		if ctxt.HeadType == objabi.Hnetbsd {
  2371  			a += int64(elfwritenetbsdsig(ctxt.Out))
  2372  		}
  2373  		if ctxt.HeadType == objabi.Hopenbsd {
  2374  			a += int64(elfwriteopenbsdsig(ctxt.Out))
  2375  		}
  2376  		if ctxt.HeadType == objabi.Hfreebsd {
  2377  			a += int64(elfwritefreebsdsig(ctxt.Out))
  2378  		}
  2379  		if len(buildinfo) > 0 {
  2380  			a += int64(elfwritebuildinfo(ctxt.Out))
  2381  		}
  2382  		if *flagBuildid != "" {
  2383  			a += int64(elfwritegobuildid(ctxt.Out))
  2384  		}
  2385  	}
  2386  	if *flagRace && ctxt.IsNetbsd() {
  2387  		a += int64(elfwritenetbsdpax(ctxt.Out))
  2388  	}
  2389  
  2390  	if a > elfreserve {
  2391  		Errorf("ELFRESERVE too small: %d > %d with %d text sections", a, elfreserve, numtext)
  2392  	}
  2393  
  2394  	// Verify the amount of space allocated for the elf header is sufficient.  The file offsets are
  2395  	// already computed in layout, so we could spill into another section.
  2396  	if a > int64(HEADR) {
  2397  		Errorf("HEADR too small: %d > %d with %d text sections", a, HEADR, numtext)
  2398  	}
  2399  }
  2400  
  2401  func elfadddynsym(ldr *loader.Loader, target *Target, syms *ArchSyms, s loader.Sym) {
  2402  	ldr.SetSymDynid(s, int32(Nelfsym))
  2403  	Nelfsym++
  2404  	d := ldr.MakeSymbolUpdater(syms.DynSym)
  2405  	name := ldr.SymExtname(s)
  2406  	dstru := ldr.MakeSymbolUpdater(syms.DynStr)
  2407  	st := ldr.SymType(s)
  2408  	cgoeStatic := ldr.AttrCgoExportStatic(s)
  2409  	cgoeDynamic := ldr.AttrCgoExportDynamic(s)
  2410  	cgoexp := (cgoeStatic || cgoeDynamic)
  2411  
  2412  	d.AddUint32(target.Arch, uint32(dstru.Addstring(name)))
  2413  
  2414  	if elf64 {
  2415  
  2416  		/* type */
  2417  		var t uint8
  2418  
  2419  		if cgoexp && st.IsText() {
  2420  			t = elf.ST_INFO(elf.STB_GLOBAL, elf.STT_FUNC)
  2421  		} else {
  2422  			t = elf.ST_INFO(elf.STB_GLOBAL, elf.STT_OBJECT)
  2423  		}
  2424  		d.AddUint8(t)
  2425  
  2426  		/* reserved */
  2427  		d.AddUint8(0)
  2428  
  2429  		/* section where symbol is defined */
  2430  		if st == sym.SDYNIMPORT {
  2431  			d.AddUint16(target.Arch, uint16(elf.SHN_UNDEF))
  2432  		} else {
  2433  			d.AddUint16(target.Arch, 1)
  2434  		}
  2435  
  2436  		/* value */
  2437  		if st == sym.SDYNIMPORT {
  2438  			d.AddUint64(target.Arch, 0)
  2439  		} else {
  2440  			d.AddAddrPlus(target.Arch, s, 0)
  2441  		}
  2442  
  2443  		/* size of object */
  2444  		d.AddUint64(target.Arch, uint64(len(ldr.Data(s))))
  2445  
  2446  		dil := ldr.SymDynimplib(s)
  2447  
  2448  		if !cgoeDynamic && dil != "" && !seenlib[dil] {
  2449  			du := ldr.MakeSymbolUpdater(syms.Dynamic)
  2450  			Elfwritedynent(target.Arch, du, elf.DT_NEEDED, uint64(dstru.Addstring(dil)))
  2451  			seenlib[dil] = true
  2452  		}
  2453  	} else {
  2454  
  2455  		/* value */
  2456  		if st == sym.SDYNIMPORT {
  2457  			d.AddUint32(target.Arch, 0)
  2458  		} else {
  2459  			d.AddAddrPlus(target.Arch, s, 0)
  2460  		}
  2461  
  2462  		/* size of object */
  2463  		d.AddUint32(target.Arch, uint32(len(ldr.Data(s))))
  2464  
  2465  		/* type */
  2466  		var t uint8
  2467  
  2468  		// TODO(mwhudson): presumably the behavior should actually be the same on both arm and 386.
  2469  		if target.Arch.Family == sys.I386 && cgoexp && st.IsText() {
  2470  			t = elf.ST_INFO(elf.STB_GLOBAL, elf.STT_FUNC)
  2471  		} else if target.Arch.Family == sys.ARM && cgoeDynamic && st.IsText() {
  2472  			t = elf.ST_INFO(elf.STB_GLOBAL, elf.STT_FUNC)
  2473  		} else {
  2474  			t = elf.ST_INFO(elf.STB_GLOBAL, elf.STT_OBJECT)
  2475  		}
  2476  		d.AddUint8(t)
  2477  		d.AddUint8(0)
  2478  
  2479  		/* shndx */
  2480  		if st == sym.SDYNIMPORT {
  2481  			d.AddUint16(target.Arch, uint16(elf.SHN_UNDEF))
  2482  		} else {
  2483  			d.AddUint16(target.Arch, 1)
  2484  		}
  2485  	}
  2486  }
  2487  

View as plain text