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

View as plain text