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

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

View as plain text