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

View as plain text