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

     1  // Inferno utils/8l/asm.c
     2  // https://bitbucket.org/inferno-os/inferno-os/src/master/utils/8l/asm.c
     3  //
     4  //	Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
     5  //	Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
     6  //	Portions Copyright © 1997-1999 Vita Nuova Limited
     7  //	Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
     8  //	Portions Copyright © 2004,2006 Bruce Ellis
     9  //	Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
    10  //	Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
    11  //	Portions Copyright © 2009 The Go Authors. All rights reserved.
    12  //
    13  // Permission is hereby granted, free of charge, to any person obtaining a copy
    14  // of this software and associated documentation files (the "Software"), to deal
    15  // in the Software without restriction, including without limitation the rights
    16  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    17  // copies of the Software, and to permit persons to whom the Software is
    18  // furnished to do so, subject to the following conditions:
    19  //
    20  // The above copyright notice and this permission notice shall be included in
    21  // all copies or substantial portions of the Software.
    22  //
    23  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    24  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    25  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
    26  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    27  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    28  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    29  // THE SOFTWARE.
    30  
    31  package ld
    32  
    33  import (
    34  	"bytes"
    35  	"debug/elf"
    36  	"debug/macho"
    37  	"encoding/base64"
    38  	"encoding/binary"
    39  	"fmt"
    40  	"internal/buildcfg"
    41  	"io"
    42  	"log"
    43  	"os"
    44  	"os/exec"
    45  	"path/filepath"
    46  	"runtime"
    47  	"slices"
    48  	"sort"
    49  	"strings"
    50  	"sync"
    51  	"time"
    52  
    53  	"cmd/internal/bio"
    54  	"cmd/internal/goobj"
    55  	"cmd/internal/hash"
    56  	"cmd/internal/objabi"
    57  	"cmd/internal/sys"
    58  	"cmd/link/internal/loadelf"
    59  	"cmd/link/internal/loader"
    60  	"cmd/link/internal/loadmacho"
    61  	"cmd/link/internal/loadpe"
    62  	"cmd/link/internal/loadxcoff"
    63  	"cmd/link/internal/sym"
    64  )
    65  
    66  // Data layout and relocation.
    67  
    68  // Derived from Inferno utils/6l/l.h
    69  // https://bitbucket.org/inferno-os/inferno-os/src/master/utils/6l/l.h
    70  //
    71  //	Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
    72  //	Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
    73  //	Portions Copyright © 1997-1999 Vita Nuova Limited
    74  //	Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
    75  //	Portions Copyright © 2004,2006 Bruce Ellis
    76  //	Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
    77  //	Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
    78  //	Portions Copyright © 2009 The Go Authors. All rights reserved.
    79  //
    80  // Permission is hereby granted, free of charge, to any person obtaining a copy
    81  // of this software and associated documentation files (the "Software"), to deal
    82  // in the Software without restriction, including without limitation the rights
    83  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    84  // copies of the Software, and to permit persons to whom the Software is
    85  // furnished to do so, subject to the following conditions:
    86  //
    87  // The above copyright notice and this permission notice shall be included in
    88  // all copies or substantial portions of the Software.
    89  //
    90  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    91  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    92  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
    93  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    94  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    95  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    96  // THE SOFTWARE.
    97  
    98  // ArchSyms holds a number of architecture specific symbols used during
    99  // relocation.  Rather than allowing them universal access to all symbols,
   100  // we keep a subset for relocation application.
   101  type ArchSyms struct {
   102  	Rel     loader.Sym
   103  	Rela    loader.Sym
   104  	RelPLT  loader.Sym
   105  	RelaPLT loader.Sym
   106  
   107  	LinkEditGOT loader.Sym
   108  	LinkEditPLT loader.Sym
   109  
   110  	TOC    loader.Sym
   111  	DotTOC []loader.Sym // for each version
   112  
   113  	GOT    loader.Sym
   114  	PLT    loader.Sym
   115  	GOTPLT loader.Sym
   116  
   117  	Tlsg      loader.Sym
   118  	Tlsoffset int
   119  
   120  	Dynamic loader.Sym
   121  	DynSym  loader.Sym
   122  	DynStr  loader.Sym
   123  
   124  	unreachableMethod loader.Sym
   125  
   126  	// Symbol containing a list of all the inittasks that need
   127  	// to be run at startup.
   128  	mainInittasks loader.Sym
   129  }
   130  
   131  // mkArchSym is a helper for setArchSyms, to set up a special symbol.
   132  func (ctxt *Link) mkArchSym(name string, ver int, ls *loader.Sym) {
   133  	*ls = ctxt.loader.LookupOrCreateSym(name, ver)
   134  	ctxt.loader.SetAttrReachable(*ls, true)
   135  }
   136  
   137  // mkArchSymVec is similar to  setArchSyms, but operates on elements within
   138  // a slice, where each element corresponds to some symbol version.
   139  func (ctxt *Link) mkArchSymVec(name string, ver int, ls []loader.Sym) {
   140  	ls[ver] = ctxt.loader.LookupOrCreateSym(name, ver)
   141  	ctxt.loader.SetAttrReachable(ls[ver], true)
   142  }
   143  
   144  // setArchSyms sets up the ArchSyms structure, and must be called before
   145  // relocations are applied.
   146  func (ctxt *Link) setArchSyms() {
   147  	ctxt.mkArchSym(".got", 0, &ctxt.GOT)
   148  	ctxt.mkArchSym(".plt", 0, &ctxt.PLT)
   149  	ctxt.mkArchSym(".got.plt", 0, &ctxt.GOTPLT)
   150  	ctxt.mkArchSym(".dynamic", 0, &ctxt.Dynamic)
   151  	ctxt.mkArchSym(".dynsym", 0, &ctxt.DynSym)
   152  	ctxt.mkArchSym(".dynstr", 0, &ctxt.DynStr)
   153  	ctxt.mkArchSym("runtime.unreachableMethod", abiInternalVer, &ctxt.unreachableMethod)
   154  
   155  	if ctxt.IsPPC64() {
   156  		ctxt.mkArchSym("TOC", 0, &ctxt.TOC)
   157  
   158  		ctxt.DotTOC = make([]loader.Sym, ctxt.MaxVersion()+1)
   159  		for i := 0; i <= ctxt.MaxVersion(); i++ {
   160  			if i >= sym.SymVerABICount && i < sym.SymVerStatic { // these versions are not used currently
   161  				continue
   162  			}
   163  			ctxt.mkArchSymVec(".TOC.", i, ctxt.DotTOC)
   164  		}
   165  	}
   166  	if ctxt.IsElf() {
   167  		ctxt.mkArchSym(".rel", 0, &ctxt.Rel)
   168  		ctxt.mkArchSym(".rela", 0, &ctxt.Rela)
   169  		ctxt.mkArchSym(".rel.plt", 0, &ctxt.RelPLT)
   170  		ctxt.mkArchSym(".rela.plt", 0, &ctxt.RelaPLT)
   171  	}
   172  	if ctxt.IsDarwin() {
   173  		ctxt.mkArchSym(".linkedit.got", 0, &ctxt.LinkEditGOT)
   174  		ctxt.mkArchSym(".linkedit.plt", 0, &ctxt.LinkEditPLT)
   175  	}
   176  }
   177  
   178  type Arch struct {
   179  	Funcalign  int
   180  	Maxalign   int
   181  	Minalign   int
   182  	Dwarfregsp int
   183  	Dwarfreglr int
   184  
   185  	// Threshold of total text size, used for trampoline insertion. If the total
   186  	// text size is smaller than TrampLimit, we won't need to insert trampolines.
   187  	// It is pretty close to the offset range of a direct CALL machine instruction.
   188  	// We leave some room for extra stuff like PLT stubs.
   189  	TrampLimit uint64
   190  
   191  	// Empty spaces between codeblocks will be padded with this value.
   192  	// For example an architecture might want to pad with a trap instruction to
   193  	// catch wayward programs. Architectures that do not define a padding value
   194  	// are padded with zeros.
   195  	CodePad []byte
   196  
   197  	// Plan 9 variables.
   198  	Plan9Magic  uint32
   199  	Plan9_64Bit bool
   200  
   201  	Adddynrel func(*Target, *loader.Loader, *ArchSyms, loader.Sym, loader.Reloc, int) bool
   202  	Archinit  func(*Link)
   203  	// Archreloc is an arch-specific hook that assists in relocation processing
   204  	// (invoked by 'relocsym'); it handles target-specific relocation tasks.
   205  	// Here "rel" is the current relocation being examined, "sym" is the symbol
   206  	// containing the chunk of data to which the relocation applies, and "off"
   207  	// is the contents of the to-be-relocated data item (from sym.P). Return
   208  	// value is the appropriately relocated value (to be written back to the
   209  	// same spot in sym.P), number of external _host_ relocations needed (i.e.
   210  	// ELF/Mach-O/etc. relocations, not Go relocations, this must match ELF.Reloc1,
   211  	// etc.), and a boolean indicating success/failure (a failing value indicates
   212  	// a fatal error).
   213  	Archreloc func(*Target, *loader.Loader, *ArchSyms, loader.Reloc, loader.Sym,
   214  		int64) (relocatedOffset int64, nExtReloc int, ok bool)
   215  	// Archrelocvariant is a second arch-specific hook used for
   216  	// relocation processing; it handles relocations where r.Type is
   217  	// insufficient to describe the relocation (r.Variant !=
   218  	// sym.RV_NONE). Here "rel" is the relocation being applied, "sym"
   219  	// is the symbol containing the chunk of data to which the
   220  	// relocation applies, and "off" is the contents of the
   221  	// to-be-relocated data item (from sym.P). Return is an updated
   222  	// offset value.
   223  	Archrelocvariant func(target *Target, ldr *loader.Loader, rel loader.Reloc,
   224  		rv sym.RelocVariant, sym loader.Sym, offset int64, data []byte) (relocatedOffset int64)
   225  
   226  	// Generate a trampoline for a call from s to rs if necessary. ri is
   227  	// index of the relocation.
   228  	Trampoline func(ctxt *Link, ldr *loader.Loader, ri int, rs, s loader.Sym)
   229  
   230  	// Assembling the binary breaks into two phases, writing the code/data/
   231  	// dwarf information (which is rather generic), and some more architecture
   232  	// specific work like setting up the elf headers/dynamic relocations, etc.
   233  	// The phases are called "Asmb" and "Asmb2". Asmb2 needs to be defined for
   234  	// every architecture, but only if architecture has an Asmb function will
   235  	// it be used for assembly.  Otherwise a generic assembly Asmb function is
   236  	// used.
   237  	Asmb  func(*Link, *loader.Loader)
   238  	Asmb2 func(*Link, *loader.Loader)
   239  
   240  	// Extreloc is an arch-specific hook that converts a Go relocation to an
   241  	// external relocation. Return the external relocation and whether it is
   242  	// needed.
   243  	Extreloc func(*Target, *loader.Loader, loader.Reloc, loader.Sym) (loader.ExtReloc, bool)
   244  
   245  	Gentext        func(*Link, *loader.Loader) // Generate text before addressing has been performed.
   246  	Machoreloc1    func(*sys.Arch, *OutBuf, *loader.Loader, loader.Sym, loader.ExtReloc, int64) bool
   247  	MachorelocSize uint32 // size of an Mach-O relocation record, must match Machoreloc1.
   248  	PEreloc1       func(*sys.Arch, *OutBuf, *loader.Loader, loader.Sym, loader.ExtReloc, int64) bool
   249  	Xcoffreloc1    func(*sys.Arch, *OutBuf, *loader.Loader, loader.Sym, loader.ExtReloc, int64) bool
   250  
   251  	// Generate additional symbols for the native symbol table just prior to
   252  	// code generation.
   253  	GenSymsLate func(*Link, *loader.Loader)
   254  
   255  	// TLSIEtoLE converts a TLS Initial Executable relocation to
   256  	// a TLS Local Executable relocation.
   257  	//
   258  	// This is possible when a TLS IE relocation refers to a local
   259  	// symbol in an executable, which is typical when internally
   260  	// linking PIE binaries.
   261  	TLSIEtoLE func(P []byte, off, size int)
   262  
   263  	// optional override for assignAddress
   264  	AssignAddress func(ldr *loader.Loader, sect *sym.Section, n int, s loader.Sym, va uint64, isTramp bool) (*sym.Section, int, uint64)
   265  
   266  	// ELF specific information.
   267  	ELF ELFArch
   268  }
   269  
   270  var (
   271  	thearch Arch
   272  	lcSize  int32
   273  	rpath   Rpath
   274  	spSize  int32
   275  	symSize int32
   276  )
   277  
   278  // Symbol version of ABIInternal symbols. It is sym.SymVerABIInternal if ABI wrappers
   279  // are used, 0 otherwise.
   280  var abiInternalVer = sym.SymVerABIInternal
   281  
   282  // DynlinkingGo reports whether we are producing Go code that can live
   283  // in separate shared libraries linked together at runtime.
   284  func (ctxt *Link) DynlinkingGo() bool {
   285  	if !ctxt.Loaded {
   286  		panic("DynlinkingGo called before all symbols loaded")
   287  	}
   288  	return ctxt.BuildMode == BuildModeShared || ctxt.linkShared || ctxt.BuildMode == BuildModePlugin || ctxt.canUsePlugins
   289  }
   290  
   291  // CanUsePlugins reports whether a plugins can be used
   292  func (ctxt *Link) CanUsePlugins() bool {
   293  	if !ctxt.Loaded {
   294  		panic("CanUsePlugins called before all symbols loaded")
   295  	}
   296  	return ctxt.canUsePlugins
   297  }
   298  
   299  // NeedCodeSign reports whether we need to code-sign the output binary.
   300  func (ctxt *Link) NeedCodeSign() bool {
   301  	return ctxt.IsDarwin() && ctxt.IsARM64()
   302  }
   303  
   304  var (
   305  	dynlib          []string
   306  	ldflag          []string
   307  	havedynamic     int
   308  	Funcalign       int
   309  	iscgo           bool
   310  	elfglobalsymndx int
   311  	interpreter     string
   312  
   313  	debug_s bool // backup old value of debug['s']
   314  	HEADR   int32
   315  
   316  	nerrors  int
   317  	liveness int64 // size of liveness data (funcdata), printed if -v
   318  
   319  	// See -strictdups command line flag.
   320  	checkStrictDups   int // 0=off 1=warning 2=error
   321  	strictDupMsgCount int
   322  )
   323  
   324  var (
   325  	Segtext      sym.Segment
   326  	Segrodata    sym.Segment
   327  	Segrelrodata sym.Segment
   328  	Segdata      sym.Segment
   329  	Segdwarf     sym.Segment
   330  	Segpdata     sym.Segment // windows-only
   331  	Segxdata     sym.Segment // windows-only
   332  
   333  	Segments = []*sym.Segment{&Segtext, &Segrodata, &Segrelrodata, &Segdata, &Segdwarf, &Segpdata, &Segxdata}
   334  )
   335  
   336  const pkgdef = "__.PKGDEF"
   337  
   338  var (
   339  	// externalobj is set to true if we see an object compiled by
   340  	// the host compiler that is not from a package that is known
   341  	// to support internal linking mode.
   342  	externalobj = false
   343  
   344  	// dynimportfail is a list of packages for which generating
   345  	// the dynimport file, _cgo_import.go, failed. If there are
   346  	// any of these objects, we must link externally. Issue 52863.
   347  	dynimportfail []string
   348  
   349  	// preferlinkext is a list of packages for which the Go command
   350  	// noticed use of peculiar C flags. If we see any of these,
   351  	// default to linking externally unless overridden by the
   352  	// user. See issues #58619, #58620, and #58848.
   353  	preferlinkext []string
   354  
   355  	// unknownObjFormat is set to true if we see an object whose
   356  	// format we don't recognize.
   357  	unknownObjFormat = false
   358  
   359  	theline string
   360  )
   361  
   362  func Lflag(ctxt *Link, arg string) {
   363  	ctxt.Libdir = append(ctxt.Libdir, arg)
   364  }
   365  
   366  /*
   367   * Unix doesn't like it when we write to a running (or, sometimes,
   368   * recently run) binary, so remove the output file before writing it.
   369   * On Windows 7, remove() can force a subsequent create() to fail.
   370   * S_ISREG() does not exist on Plan 9.
   371   */
   372  func mayberemoveoutfile() {
   373  	if fi, err := os.Lstat(*flagOutfile); err == nil && !fi.Mode().IsRegular() {
   374  		return
   375  	}
   376  	os.Remove(*flagOutfile)
   377  }
   378  
   379  func libinit(ctxt *Link) {
   380  	Funcalign = thearch.Funcalign
   381  
   382  	// add goroot to the end of the libdir list.
   383  	suffix := ""
   384  
   385  	suffixsep := ""
   386  	if *flagInstallSuffix != "" {
   387  		suffixsep = "_"
   388  		suffix = *flagInstallSuffix
   389  	} else if *flagRace {
   390  		suffixsep = "_"
   391  		suffix = "race"
   392  	} else if *flagMsan {
   393  		suffixsep = "_"
   394  		suffix = "msan"
   395  	} else if *flagAsan {
   396  		suffixsep = "_"
   397  		suffix = "asan"
   398  	}
   399  
   400  	if buildcfg.GOROOT != "" {
   401  		Lflag(ctxt, filepath.Join(buildcfg.GOROOT, "pkg", fmt.Sprintf("%s_%s%s%s", buildcfg.GOOS, buildcfg.GOARCH, suffixsep, suffix)))
   402  	}
   403  
   404  	mayberemoveoutfile()
   405  
   406  	if err := ctxt.Out.Open(*flagOutfile); err != nil {
   407  		Exitf("cannot create %s: %v", *flagOutfile, err)
   408  	}
   409  
   410  	if *flagEntrySymbol == "" {
   411  		switch ctxt.BuildMode {
   412  		case BuildModeCShared, BuildModeCArchive:
   413  			*flagEntrySymbol = fmt.Sprintf("_rt0_%s_%s_lib", buildcfg.GOARCH, buildcfg.GOOS)
   414  		case BuildModeExe, BuildModePIE:
   415  			*flagEntrySymbol = fmt.Sprintf("_rt0_%s_%s", buildcfg.GOARCH, buildcfg.GOOS)
   416  		case BuildModeShared, BuildModePlugin:
   417  			// No *flagEntrySymbol for -buildmode=shared and plugin
   418  		default:
   419  			Errorf("unknown *flagEntrySymbol for buildmode %v", ctxt.BuildMode)
   420  		}
   421  	}
   422  }
   423  
   424  func exitIfErrors() {
   425  	if nerrors != 0 || checkStrictDups > 1 && strictDupMsgCount > 0 {
   426  		mayberemoveoutfile()
   427  		Exit(2)
   428  	}
   429  
   430  }
   431  
   432  func errorexit() {
   433  	exitIfErrors()
   434  	Exit(0)
   435  }
   436  
   437  func loadinternal(ctxt *Link, name string) *sym.Library {
   438  	zerofp := goobj.FingerprintType{}
   439  	if ctxt.linkShared && ctxt.PackageShlib != nil {
   440  		if shlib := ctxt.PackageShlib[name]; shlib != "" {
   441  			return addlibpath(ctxt, "internal", "internal", "", name, shlib, zerofp)
   442  		}
   443  	}
   444  	if ctxt.PackageFile != nil {
   445  		if pname := ctxt.PackageFile[name]; pname != "" {
   446  			return addlibpath(ctxt, "internal", "internal", pname, name, "", zerofp)
   447  		}
   448  		ctxt.Logf("loadinternal: cannot find %s\n", name)
   449  		return nil
   450  	}
   451  
   452  	for _, libdir := range ctxt.Libdir {
   453  		if ctxt.linkShared {
   454  			shlibname := filepath.Join(libdir, name+".shlibname")
   455  			if ctxt.Debugvlog != 0 {
   456  				ctxt.Logf("searching for %s.a in %s\n", name, shlibname)
   457  			}
   458  			if _, err := os.Stat(shlibname); err == nil {
   459  				return addlibpath(ctxt, "internal", "internal", "", name, shlibname, zerofp)
   460  			}
   461  		}
   462  		pname := filepath.Join(libdir, name+".a")
   463  		if ctxt.Debugvlog != 0 {
   464  			ctxt.Logf("searching for %s.a in %s\n", name, pname)
   465  		}
   466  		if _, err := os.Stat(pname); err == nil {
   467  			return addlibpath(ctxt, "internal", "internal", pname, name, "", zerofp)
   468  		}
   469  	}
   470  
   471  	if name == "runtime" {
   472  		Exitf("error: unable to find runtime.a")
   473  	}
   474  	ctxt.Logf("warning: unable to find %s.a\n", name)
   475  	return nil
   476  }
   477  
   478  // extld returns the current external linker.
   479  func (ctxt *Link) extld() []string {
   480  	if len(flagExtld) == 0 {
   481  		// Return the default external linker for the platform.
   482  		// This only matters when link tool is called directly without explicit -extld,
   483  		// go tool already passes the correct linker in other cases.
   484  		switch buildcfg.GOOS {
   485  		case "darwin", "freebsd", "openbsd":
   486  			flagExtld = []string{"clang"}
   487  		default:
   488  			flagExtld = []string{"gcc"}
   489  		}
   490  	}
   491  	return flagExtld
   492  }
   493  
   494  // findLibPathCmd uses cmd command to find gcc library libname.
   495  // It returns library full path if found, or "none" if not found.
   496  func (ctxt *Link) findLibPathCmd(cmd, libname string) string {
   497  	extld := ctxt.extld()
   498  	name, args := extld[0], extld[1:]
   499  	args = append(args, hostlinkArchArgs(ctxt.Arch)...)
   500  	args = append(args, cmd)
   501  	if ctxt.Debugvlog != 0 {
   502  		ctxt.Logf("%s %v\n", extld, args)
   503  	}
   504  	out, err := exec.Command(name, args...).Output()
   505  	if err != nil {
   506  		if ctxt.Debugvlog != 0 {
   507  			ctxt.Logf("not using a %s file because compiler failed\n%v\n%s\n", libname, err, out)
   508  		}
   509  		return "none"
   510  	}
   511  	return strings.TrimSpace(string(out))
   512  }
   513  
   514  // findLibPath searches for library libname.
   515  // It returns library full path if found, or "none" if not found.
   516  func (ctxt *Link) findLibPath(libname string) string {
   517  	return ctxt.findLibPathCmd("--print-file-name="+libname, libname)
   518  }
   519  
   520  func (ctxt *Link) loadlib() {
   521  	var flags uint32
   522  	if *flagCheckLinkname {
   523  		flags |= loader.FlagCheckLinkname
   524  	}
   525  	switch *FlagStrictDups {
   526  	case 0:
   527  		// nothing to do
   528  	case 1, 2:
   529  		flags |= loader.FlagStrictDups
   530  	default:
   531  		log.Fatalf("invalid -strictdups flag value %d", *FlagStrictDups)
   532  	}
   533  	ctxt.loader = loader.NewLoader(flags, &ctxt.ErrorReporter.ErrorReporter)
   534  	ctxt.ErrorReporter.SymName = func(s loader.Sym) string {
   535  		return ctxt.loader.SymName(s)
   536  	}
   537  
   538  	// ctxt.Library grows during the loop, so not a range loop.
   539  	i := 0
   540  	for ; i < len(ctxt.Library); i++ {
   541  		lib := ctxt.Library[i]
   542  		if lib.Shlib == "" {
   543  			if ctxt.Debugvlog > 1 {
   544  				ctxt.Logf("autolib: %s (from %s)\n", lib.File, lib.Objref)
   545  			}
   546  			loadobjfile(ctxt, lib)
   547  		}
   548  	}
   549  
   550  	// load internal packages, if not already
   551  	if *flagRace {
   552  		loadinternal(ctxt, "runtime/race")
   553  	}
   554  	if *flagMsan {
   555  		loadinternal(ctxt, "runtime/msan")
   556  	}
   557  	if *flagAsan {
   558  		loadinternal(ctxt, "runtime/asan")
   559  	}
   560  	loadinternal(ctxt, "runtime")
   561  	for ; i < len(ctxt.Library); i++ {
   562  		lib := ctxt.Library[i]
   563  		if lib.Shlib == "" {
   564  			loadobjfile(ctxt, lib)
   565  		}
   566  	}
   567  	// At this point, the Go objects are "preloaded". Not all the symbols are
   568  	// added to the symbol table (only defined package symbols are). Looking
   569  	// up symbol by name may not get expected result.
   570  
   571  	iscgo = ctxt.LibraryByPkg["runtime/cgo"] != nil
   572  
   573  	// Plugins a require cgo support to function. Similarly, plugins may require additional
   574  	// internal linker support on some platforms which may not be implemented.
   575  	ctxt.canUsePlugins = ctxt.LibraryByPkg["plugin"] != nil && iscgo
   576  
   577  	// We now have enough information to determine the link mode.
   578  	determineLinkMode(ctxt)
   579  
   580  	if ctxt.LinkMode == LinkExternal && !iscgo && !(buildcfg.GOOS == "darwin" && ctxt.BuildMode != BuildModePlugin && ctxt.Arch.Family == sys.AMD64) {
   581  		// This indicates a user requested -linkmode=external.
   582  		// The startup code uses an import of runtime/cgo to decide
   583  		// whether to initialize the TLS.  So give it one. This could
   584  		// be handled differently but it's an unusual case.
   585  		if lib := loadinternal(ctxt, "runtime/cgo"); lib != nil && lib.Shlib == "" {
   586  			if ctxt.BuildMode == BuildModeShared || ctxt.linkShared {
   587  				Exitf("cannot implicitly include runtime/cgo in a shared library")
   588  			}
   589  			for ; i < len(ctxt.Library); i++ {
   590  				lib := ctxt.Library[i]
   591  				if lib.Shlib == "" {
   592  					loadobjfile(ctxt, lib)
   593  				}
   594  			}
   595  		}
   596  	}
   597  
   598  	// Add non-package symbols and references of externally defined symbols.
   599  	ctxt.loader.LoadSyms(ctxt.Arch)
   600  
   601  	// Load symbols from shared libraries, after all Go object symbols are loaded.
   602  	for _, lib := range ctxt.Library {
   603  		if lib.Shlib != "" {
   604  			if ctxt.Debugvlog > 1 {
   605  				ctxt.Logf("autolib: %s (from %s)\n", lib.Shlib, lib.Objref)
   606  			}
   607  			ldshlibsyms(ctxt, lib.Shlib)
   608  		}
   609  	}
   610  
   611  	// Process cgo directives (has to be done before host object loading).
   612  	ctxt.loadcgodirectives()
   613  
   614  	// Conditionally load host objects, or setup for external linking.
   615  	hostobjs(ctxt)
   616  	hostlinksetup(ctxt)
   617  
   618  	if ctxt.LinkMode == LinkInternal && len(hostobj) != 0 {
   619  		// If we have any undefined symbols in external
   620  		// objects, try to read them from the libgcc file.
   621  		any := false
   622  		undefs, froms := ctxt.loader.UndefinedRelocTargets(1)
   623  		if len(undefs) > 0 {
   624  			any = true
   625  			if ctxt.Debugvlog > 1 {
   626  				ctxt.Logf("loadlib: first unresolved is %s [%d] from %s [%d]\n",
   627  					ctxt.loader.SymName(undefs[0]), undefs[0],
   628  					ctxt.loader.SymName(froms[0]), froms[0])
   629  			}
   630  		}
   631  		if any {
   632  			if *flagLibGCC == "" {
   633  				*flagLibGCC = ctxt.findLibPathCmd("--print-libgcc-file-name", "libgcc")
   634  			}
   635  			if runtime.GOOS == "openbsd" && *flagLibGCC == "libgcc.a" {
   636  				// On OpenBSD `clang --print-libgcc-file-name` returns "libgcc.a".
   637  				// In this case we fail to load libgcc.a and can encounter link
   638  				// errors - see if we can find libcompiler_rt.a instead.
   639  				*flagLibGCC = ctxt.findLibPathCmd("--print-file-name=libcompiler_rt.a", "libcompiler_rt")
   640  			}
   641  			if ctxt.HeadType == objabi.Hwindows {
   642  				loadWindowsHostArchives(ctxt)
   643  			}
   644  			if *flagLibGCC != "none" {
   645  				hostArchive(ctxt, *flagLibGCC)
   646  			}
   647  			// For glibc systems, the linker setup used by GCC
   648  			// looks like
   649  			//
   650  			//  GROUP ( /lib/x86_64-linux-gnu/libc.so.6
   651  			//      /usr/lib/x86_64-linux-gnu/libc_nonshared.a
   652  			//      AS_NEEDED ( /lib64/ld-linux-x86-64.so.2 ) )
   653  			//
   654  			// where libc_nonshared.a contains a small set of
   655  			// symbols including "__stack_chk_fail_local" and a
   656  			// few others. Thus if we are doing internal linking
   657  			// and "__stack_chk_fail_local" is unresolved (most
   658  			// likely due to the use of -fstack-protector), try
   659  			// loading libc_nonshared.a to resolve it.
   660  			//
   661  			// On Alpine Linux (musl-based), the library providing
   662  			// this symbol is called libssp_nonshared.a.
   663  			isunresolved := symbolsAreUnresolved(ctxt, []string{"__stack_chk_fail_local"})
   664  			if isunresolved[0] {
   665  				if p := ctxt.findLibPath("libc_nonshared.a"); p != "none" {
   666  					hostArchive(ctxt, p)
   667  				}
   668  				if p := ctxt.findLibPath("libssp_nonshared.a"); p != "none" {
   669  					hostArchive(ctxt, p)
   670  				}
   671  			}
   672  		}
   673  	}
   674  
   675  	loadfips(ctxt)
   676  
   677  	// We've loaded all the code now.
   678  	ctxt.Loaded = true
   679  
   680  	strictDupMsgCount = ctxt.loader.NStrictDupMsgs()
   681  }
   682  
   683  // loadWindowsHostArchives loads in host archives and objects when
   684  // doing internal linking on windows. Older toolchains seem to require
   685  // just a single pass through the various archives, but some modern
   686  // toolchains when linking a C program with mingw pass library paths
   687  // multiple times to the linker, e.g. "... -lmingwex -lmingw32 ...
   688  // -lmingwex -lmingw32 ...". To accommodate this behavior, we make two
   689  // passes over the host archives below.
   690  func loadWindowsHostArchives(ctxt *Link) {
   691  	any := true
   692  	for i := 0; any && i < 2; i++ {
   693  		// Link crt2.o (if present) to resolve "atexit" when
   694  		// using LLVM-based compilers.
   695  		isunresolved := symbolsAreUnresolved(ctxt, []string{"atexit"})
   696  		if isunresolved[0] {
   697  			if p := ctxt.findLibPath("crt2.o"); p != "none" {
   698  				hostObject(ctxt, "crt2", p)
   699  			}
   700  		}
   701  		if *flagRace {
   702  			if p := ctxt.findLibPath("libsynchronization.a"); p != "none" {
   703  				hostArchive(ctxt, p)
   704  			}
   705  		}
   706  		if p := ctxt.findLibPath("libmingwex.a"); p != "none" {
   707  			hostArchive(ctxt, p)
   708  		}
   709  		if p := ctxt.findLibPath("libmingw32.a"); p != "none" {
   710  			hostArchive(ctxt, p)
   711  		}
   712  		// Link libmsvcrt.a to resolve '__acrt_iob_func' symbol
   713  		// (see https://golang.org/issue/23649 for details).
   714  		if p := ctxt.findLibPath("libmsvcrt.a"); p != "none" {
   715  			hostArchive(ctxt, p)
   716  		}
   717  		any = false
   718  		undefs, froms := ctxt.loader.UndefinedRelocTargets(1)
   719  		if len(undefs) > 0 {
   720  			any = true
   721  			if ctxt.Debugvlog > 1 {
   722  				ctxt.Logf("loadWindowsHostArchives: remaining unresolved is %s [%d] from %s [%d]\n",
   723  					ctxt.loader.SymName(undefs[0]), undefs[0],
   724  					ctxt.loader.SymName(froms[0]), froms[0])
   725  			}
   726  		}
   727  	}
   728  	// If needed, create the __CTOR_LIST__ and __DTOR_LIST__
   729  	// symbols (referenced by some of the mingw support library
   730  	// routines). Creation of these symbols is normally done by the
   731  	// linker if not already present.
   732  	want := []string{"__CTOR_LIST__", "__DTOR_LIST__"}
   733  	isunresolved := symbolsAreUnresolved(ctxt, want)
   734  	for k, w := range want {
   735  		if isunresolved[k] {
   736  			sb := ctxt.loader.CreateSymForUpdate(w, 0)
   737  			sb.SetType(sym.SDATA)
   738  			sb.AddUint64(ctxt.Arch, 0)
   739  			sb.SetReachable(true)
   740  			ctxt.loader.SetAttrSpecial(sb.Sym(), true)
   741  		}
   742  	}
   743  
   744  	// Fix up references to DLL import symbols now that we're done
   745  	// pulling in new objects.
   746  	if err := loadpe.PostProcessImports(); err != nil {
   747  		Errorf("%v", err)
   748  	}
   749  
   750  	// TODO: maybe do something similar to peimporteddlls to collect
   751  	// all lib names and try link them all to final exe just like
   752  	// libmingwex.a and libmingw32.a:
   753  	/*
   754  		for:
   755  		#cgo windows LDFLAGS: -lmsvcrt -lm
   756  		import:
   757  		libmsvcrt.a libm.a
   758  	*/
   759  }
   760  
   761  // loadcgodirectives reads the previously discovered cgo directives, creating
   762  // symbols in preparation for host object loading or use later in the link.
   763  func (ctxt *Link) loadcgodirectives() {
   764  	l := ctxt.loader
   765  	hostObjSyms := make(map[loader.Sym]struct{})
   766  	for _, d := range ctxt.cgodata {
   767  		setCgoAttr(ctxt, d.file, d.pkg, d.directives, hostObjSyms)
   768  	}
   769  	ctxt.cgodata = nil
   770  
   771  	if ctxt.LinkMode == LinkInternal {
   772  		// Drop all the cgo_import_static declarations.
   773  		// Turns out we won't be needing them.
   774  		for symIdx := range hostObjSyms {
   775  			if l.SymType(symIdx) == sym.SHOSTOBJ {
   776  				// If a symbol was marked both
   777  				// cgo_import_static and cgo_import_dynamic,
   778  				// then we want to make it cgo_import_dynamic
   779  				// now.
   780  				su := l.MakeSymbolUpdater(symIdx)
   781  				if l.SymExtname(symIdx) != "" && l.SymDynimplib(symIdx) != "" && !(l.AttrCgoExportStatic(symIdx) || l.AttrCgoExportDynamic(symIdx)) {
   782  					su.SetType(sym.SDYNIMPORT)
   783  				} else {
   784  					su.SetType(0)
   785  				}
   786  			}
   787  		}
   788  	}
   789  }
   790  
   791  // Set up flags and special symbols depending on the platform build mode.
   792  // This version works with loader.Loader.
   793  func (ctxt *Link) linksetup() {
   794  	switch ctxt.BuildMode {
   795  	case BuildModeCShared, BuildModePlugin:
   796  		symIdx := ctxt.loader.LookupOrCreateSym("runtime.islibrary", 0)
   797  		sb := ctxt.loader.MakeSymbolUpdater(symIdx)
   798  		sb.SetType(sym.SNOPTRDATA)
   799  		sb.AddUint8(1)
   800  	case BuildModeCArchive:
   801  		symIdx := ctxt.loader.LookupOrCreateSym("runtime.isarchive", 0)
   802  		sb := ctxt.loader.MakeSymbolUpdater(symIdx)
   803  		sb.SetType(sym.SNOPTRDATA)
   804  		sb.AddUint8(1)
   805  	}
   806  
   807  	// Recalculate pe parameters now that we have ctxt.LinkMode set.
   808  	if ctxt.HeadType == objabi.Hwindows {
   809  		Peinit(ctxt)
   810  	}
   811  
   812  	if ctxt.LinkMode == LinkExternal {
   813  		// When external linking, we are creating an object file. The
   814  		// absolute address is irrelevant.
   815  		*FlagTextAddr = 0
   816  	}
   817  
   818  	// If there are no dynamic libraries needed, gcc disables dynamic linking.
   819  	// Because of this, glibc's dynamic ELF loader occasionally (like in version 2.13)
   820  	// assumes that a dynamic binary always refers to at least one dynamic library.
   821  	// Rather than be a source of test cases for glibc, disable dynamic linking
   822  	// the same way that gcc would.
   823  	//
   824  	// Exception: on OS X, programs such as Shark only work with dynamic
   825  	// binaries, so leave it enabled on OS X (Mach-O) binaries.
   826  	// Also leave it enabled on Solaris which doesn't support
   827  	// statically linked binaries.
   828  	if ctxt.BuildMode == BuildModeExe {
   829  		if havedynamic == 0 && ctxt.HeadType != objabi.Hdarwin && ctxt.HeadType != objabi.Hsolaris {
   830  			*FlagD = true
   831  		}
   832  	}
   833  
   834  	if ctxt.LinkMode == LinkExternal && ctxt.Arch.Family == sys.PPC64 && buildcfg.GOOS != "aix" {
   835  		toc := ctxt.loader.LookupOrCreateSym(".TOC.", 0)
   836  		sb := ctxt.loader.MakeSymbolUpdater(toc)
   837  		sb.SetType(sym.SDYNIMPORT)
   838  	}
   839  
   840  	// The Android Q linker started to complain about underalignment of the our TLS
   841  	// section. We don't actually use the section on android, so don't
   842  	// generate it.
   843  	if buildcfg.GOOS != "android" {
   844  		tlsg := ctxt.loader.LookupOrCreateSym("runtime.tlsg", 0)
   845  		sb := ctxt.loader.MakeSymbolUpdater(tlsg)
   846  
   847  		// runtime.tlsg is used for external linking on platforms that do not define
   848  		// a variable to hold g in assembly (currently only intel).
   849  		if sb.Type() == 0 {
   850  			sb.SetType(sym.STLSBSS)
   851  			sb.SetSize(int64(ctxt.Arch.PtrSize))
   852  		} else if sb.Type() != sym.SDYNIMPORT {
   853  			Errorf("runtime declared tlsg variable %v", sb.Type())
   854  		}
   855  		ctxt.loader.SetAttrReachable(tlsg, true)
   856  		ctxt.Tlsg = tlsg
   857  	}
   858  
   859  	var moduledata loader.Sym
   860  	var mdsb *loader.SymbolBuilder
   861  	if ctxt.BuildMode == BuildModePlugin {
   862  		moduledata = ctxt.loader.LookupOrCreateSym("local.pluginmoduledata", 0)
   863  		mdsb = ctxt.loader.MakeSymbolUpdater(moduledata)
   864  		ctxt.loader.SetAttrLocal(moduledata, true)
   865  	} else {
   866  		moduledata = ctxt.loader.LookupOrCreateSym("runtime.firstmoduledata", 0)
   867  		mdsb = ctxt.loader.MakeSymbolUpdater(moduledata)
   868  	}
   869  	if mdsb.Type() != 0 && mdsb.Type() != sym.SDYNIMPORT {
   870  		// If the module (toolchain-speak for "executable or shared
   871  		// library") we are linking contains the runtime package, it
   872  		// will define the runtime.firstmoduledata symbol and we
   873  		// truncate it back to 0 bytes so we can define its entire
   874  		// contents in symtab.go:symtab().
   875  		mdsb.SetSize(0)
   876  
   877  		// In addition, on ARM, the runtime depends on the linker
   878  		// recording the value of GOARM.
   879  		if ctxt.Arch.Family == sys.ARM {
   880  			goarm := ctxt.loader.LookupOrCreateSym("runtime.goarm", 0)
   881  			sb := ctxt.loader.MakeSymbolUpdater(goarm)
   882  			sb.SetType(sym.SDATA)
   883  			sb.SetSize(0)
   884  			sb.AddUint8(uint8(buildcfg.GOARM.Version))
   885  
   886  			goarmsoftfp := ctxt.loader.LookupOrCreateSym("runtime.goarmsoftfp", 0)
   887  			sb2 := ctxt.loader.MakeSymbolUpdater(goarmsoftfp)
   888  			sb2.SetType(sym.SDATA)
   889  			sb2.SetSize(0)
   890  			if buildcfg.GOARM.SoftFloat {
   891  				sb2.AddUint8(1)
   892  			} else {
   893  				sb2.AddUint8(0)
   894  			}
   895  		}
   896  
   897  		// Set runtime.disableMemoryProfiling bool if
   898  		// runtime.memProfileInternal is not retained in the binary after
   899  		// deadcode (and we're not dynamically linking).
   900  		memProfile := ctxt.loader.Lookup("runtime.memProfileInternal", abiInternalVer)
   901  		if memProfile != 0 && !ctxt.loader.AttrReachable(memProfile) && !ctxt.DynlinkingGo() {
   902  			memProfSym := ctxt.loader.LookupOrCreateSym("runtime.disableMemoryProfiling", 0)
   903  			sb := ctxt.loader.MakeSymbolUpdater(memProfSym)
   904  			sb.SetType(sym.SDATA)
   905  			sb.SetSize(0)
   906  			sb.AddUint8(1) // true bool
   907  		}
   908  	} else {
   909  		// If OTOH the module does not contain the runtime package,
   910  		// create a local symbol for the moduledata.
   911  		moduledata = ctxt.loader.LookupOrCreateSym("local.moduledata", 0)
   912  		mdsb = ctxt.loader.MakeSymbolUpdater(moduledata)
   913  		ctxt.loader.SetAttrLocal(moduledata, true)
   914  	}
   915  	// In all cases way we mark the moduledata as noptrdata to hide it from
   916  	// the GC.
   917  	mdsb.SetType(sym.SNOPTRDATA)
   918  	ctxt.loader.SetAttrReachable(moduledata, true)
   919  	ctxt.Moduledata = moduledata
   920  
   921  	if ctxt.Arch == sys.Arch386 && ctxt.HeadType != objabi.Hwindows {
   922  		if (ctxt.BuildMode == BuildModeCArchive && ctxt.IsELF) || ctxt.BuildMode == BuildModeCShared || ctxt.BuildMode == BuildModePIE || ctxt.DynlinkingGo() {
   923  			got := ctxt.loader.LookupOrCreateSym("_GLOBAL_OFFSET_TABLE_", 0)
   924  			sb := ctxt.loader.MakeSymbolUpdater(got)
   925  			sb.SetType(sym.SDYNIMPORT)
   926  			ctxt.loader.SetAttrReachable(got, true)
   927  		}
   928  	}
   929  
   930  	// DWARF-gen and other phases require that the unit Textp slices
   931  	// be populated, so that it can walk the functions in each unit.
   932  	// Call into the loader to do this (requires that we collect the
   933  	// set of internal libraries first). NB: might be simpler if we
   934  	// moved isRuntimeDepPkg to cmd/internal and then did the test in
   935  	// loader.AssignTextSymbolOrder.
   936  	ctxt.Library = postorder(ctxt.Library)
   937  	intlibs := []bool{}
   938  	for _, lib := range ctxt.Library {
   939  		intlibs = append(intlibs, isRuntimeDepPkg(lib.Pkg))
   940  	}
   941  	ctxt.Textp = ctxt.loader.AssignTextSymbolOrder(ctxt.Library, intlibs, ctxt.Textp)
   942  }
   943  
   944  // mangleTypeSym shortens the names of symbols that represent Go types
   945  // if they are visible in the symbol table.
   946  //
   947  // As the names of these symbols are derived from the string of
   948  // the type, they can run to many kilobytes long. So we shorten
   949  // them using a SHA-1 when the name appears in the final binary.
   950  // This also removes characters that upset external linkers.
   951  //
   952  // These are the symbols that begin with the prefix 'type.' and
   953  // contain run-time type information used by the runtime and reflect
   954  // packages. All Go binaries contain these symbols, but only
   955  // those programs loaded dynamically in multiple parts need these
   956  // symbols to have entries in the symbol table.
   957  func (ctxt *Link) mangleTypeSym() {
   958  	if ctxt.BuildMode != BuildModeShared && !ctxt.linkShared && ctxt.BuildMode != BuildModePlugin && !ctxt.CanUsePlugins() {
   959  		return
   960  	}
   961  
   962  	ldr := ctxt.loader
   963  	for s := loader.Sym(1); s < loader.Sym(ldr.NSym()); s++ {
   964  		if !ldr.AttrReachable(s) && !ctxt.linkShared {
   965  			// If -linkshared, the GCProg generation code may need to reach
   966  			// out to the shared library for the type descriptor's data, even
   967  			// the type descriptor itself is not actually needed at run time
   968  			// (therefore not reachable). We still need to mangle its name,
   969  			// so it is consistent with the one stored in the shared library.
   970  			continue
   971  		}
   972  		name := ldr.SymName(s)
   973  		newName := typeSymbolMangle(name)
   974  		if newName != name {
   975  			ldr.SetSymExtname(s, newName)
   976  
   977  			// When linking against a shared library, the Go object file may
   978  			// have reference to the original symbol name whereas the shared
   979  			// library provides a symbol with the mangled name. We need to
   980  			// copy the payload of mangled to original.
   981  			// XXX maybe there is a better way to do this.
   982  			dup := ldr.Lookup(newName, ldr.SymVersion(s))
   983  			if dup != 0 {
   984  				st := ldr.SymType(s)
   985  				dt := ldr.SymType(dup)
   986  				if st == sym.Sxxx && dt != sym.Sxxx {
   987  					ldr.CopySym(dup, s)
   988  				}
   989  			}
   990  		}
   991  	}
   992  }
   993  
   994  // typeSymbolMangle mangles the given symbol name into something shorter.
   995  //
   996  // Keep the type:. prefix, which parts of the linker (like the
   997  // DWARF generator) know means the symbol is not decodable.
   998  // Leave type:runtime. symbols alone, because other parts of
   999  // the linker manipulates them.
  1000  func typeSymbolMangle(name string) string {
  1001  	isType := strings.HasPrefix(name, "type:")
  1002  	if !isType && !strings.Contains(name, "@") {
  1003  		// Issue 58800: instantiated symbols may include a type name, which may contain "@"
  1004  		return name
  1005  	}
  1006  	if strings.HasPrefix(name, "type:runtime.") {
  1007  		return name
  1008  	}
  1009  	if strings.HasPrefix(name, "go:string.") {
  1010  		// String symbols will be grouped to a single go:string.* symbol.
  1011  		// No need to mangle individual symbol names.
  1012  		return name
  1013  	}
  1014  	if len(name) <= 14 && !strings.Contains(name, "@") { // Issue 19529
  1015  		return name
  1016  	}
  1017  	if isType {
  1018  		hb := hash.Sum20([]byte(name[5:]))
  1019  		prefix := "type:"
  1020  		if name[5] == '.' {
  1021  			prefix = "type:."
  1022  		}
  1023  		return prefix + base64.StdEncoding.EncodeToString(hb[:6])
  1024  	}
  1025  	// instantiated symbol, replace type name in []
  1026  	i := strings.IndexByte(name, '[')
  1027  	j := strings.LastIndexByte(name, ']')
  1028  	if j == -1 || j <= i {
  1029  		j = len(name)
  1030  	}
  1031  	hb := hash.Sum20([]byte(name[i+1 : j]))
  1032  	return name[:i+1] + base64.StdEncoding.EncodeToString(hb[:6]) + name[j:]
  1033  }
  1034  
  1035  /*
  1036   * look for the next file in an archive.
  1037   * adapted from libmach.
  1038   */
  1039  func nextar(bp *bio.Reader, off int64, a *ArHdr) int64 {
  1040  	if off&1 != 0 {
  1041  		off++
  1042  	}
  1043  	bp.MustSeek(off, 0)
  1044  	var buf [SAR_HDR]byte
  1045  	if n, err := io.ReadFull(bp, buf[:]); err != nil {
  1046  		if n == 0 && err != io.EOF {
  1047  			return -1
  1048  		}
  1049  		return 0
  1050  	}
  1051  
  1052  	a.name = artrim(buf[0:16])
  1053  	a.date = artrim(buf[16:28])
  1054  	a.uid = artrim(buf[28:34])
  1055  	a.gid = artrim(buf[34:40])
  1056  	a.mode = artrim(buf[40:48])
  1057  	a.size = artrim(buf[48:58])
  1058  	a.fmag = artrim(buf[58:60])
  1059  
  1060  	arsize := atolwhex(a.size)
  1061  	if arsize&1 != 0 {
  1062  		arsize++
  1063  	}
  1064  	return arsize + SAR_HDR
  1065  }
  1066  
  1067  func loadobjfile(ctxt *Link, lib *sym.Library) {
  1068  	pkg := objabi.PathToPrefix(lib.Pkg)
  1069  
  1070  	if ctxt.Debugvlog > 1 {
  1071  		ctxt.Logf("ldobj: %s (%s)\n", lib.File, pkg)
  1072  	}
  1073  	f, err := bio.Open(lib.File)
  1074  	if err != nil {
  1075  		Exitf("cannot open file %s: %v", lib.File, err)
  1076  	}
  1077  	defer f.Close()
  1078  	defer func() {
  1079  		if pkg == "main" && !lib.Main {
  1080  			Exitf("%s: not package main", lib.File)
  1081  		}
  1082  	}()
  1083  
  1084  	for i := 0; i < len(ARMAG); i++ {
  1085  		if c, err := f.ReadByte(); err == nil && c == ARMAG[i] {
  1086  			continue
  1087  		}
  1088  
  1089  		/* load it as a regular file */
  1090  		l := f.MustSeek(0, 2)
  1091  		f.MustSeek(0, 0)
  1092  		ldobj(ctxt, f, lib, l, lib.File, lib.File)
  1093  		return
  1094  	}
  1095  
  1096  	/*
  1097  	 * load all the object files from the archive now.
  1098  	 * this gives us sequential file access and keeps us
  1099  	 * from needing to come back later to pick up more
  1100  	 * objects.  it breaks the usual C archive model, but
  1101  	 * this is Go, not C.  the common case in Go is that
  1102  	 * we need to load all the objects, and then we throw away
  1103  	 * the individual symbols that are unused.
  1104  	 *
  1105  	 * loading every object will also make it possible to
  1106  	 * load foreign objects not referenced by __.PKGDEF.
  1107  	 */
  1108  	var arhdr ArHdr
  1109  	off := f.Offset()
  1110  	for {
  1111  		l := nextar(f, off, &arhdr)
  1112  		if l == 0 {
  1113  			break
  1114  		}
  1115  		if l < 0 {
  1116  			Exitf("%s: malformed archive", lib.File)
  1117  		}
  1118  		off += l
  1119  
  1120  		// __.PKGDEF isn't a real Go object file, and it's
  1121  		// absent in -linkobj builds anyway. Skipping it
  1122  		// ensures consistency between -linkobj and normal
  1123  		// build modes.
  1124  		if arhdr.name == pkgdef {
  1125  			continue
  1126  		}
  1127  
  1128  		if arhdr.name == "dynimportfail" {
  1129  			dynimportfail = append(dynimportfail, lib.Pkg)
  1130  		}
  1131  		if arhdr.name == "preferlinkext" {
  1132  			// Ignore this directive if -linkmode has been
  1133  			// set explicitly.
  1134  			if ctxt.LinkMode == LinkAuto {
  1135  				preferlinkext = append(preferlinkext, lib.Pkg)
  1136  			}
  1137  		}
  1138  
  1139  		// Skip other special (non-object-file) sections that
  1140  		// build tools may have added. Such sections must have
  1141  		// short names so that the suffix is not truncated.
  1142  		if len(arhdr.name) < 16 {
  1143  			if ext := filepath.Ext(arhdr.name); ext != ".o" && ext != ".syso" {
  1144  				continue
  1145  			}
  1146  		}
  1147  
  1148  		pname := fmt.Sprintf("%s(%s)", lib.File, arhdr.name)
  1149  		l = atolwhex(arhdr.size)
  1150  		ldobj(ctxt, f, lib, l, pname, lib.File)
  1151  	}
  1152  }
  1153  
  1154  type Hostobj struct {
  1155  	ld     func(*Link, *bio.Reader, string, int64, string)
  1156  	pkg    string
  1157  	pn     string
  1158  	file   string
  1159  	off    int64
  1160  	length int64
  1161  }
  1162  
  1163  var hostobj []Hostobj
  1164  
  1165  // These packages can use internal linking mode.
  1166  // Others trigger external mode.
  1167  var internalpkg = []string{
  1168  	"crypto/internal/boring",
  1169  	"crypto/internal/boring/syso",
  1170  	"crypto/x509",
  1171  	"net",
  1172  	"os/user",
  1173  	"runtime/cgo",
  1174  	"runtime/race",
  1175  	"runtime/race/internal/amd64v1",
  1176  	"runtime/race/internal/amd64v3",
  1177  	"runtime/msan",
  1178  	"runtime/asan",
  1179  }
  1180  
  1181  func ldhostobj(ld func(*Link, *bio.Reader, string, int64, string), headType objabi.HeadType, f *bio.Reader, pkg string, length int64, pn string, file string) *Hostobj {
  1182  	isinternal := false
  1183  	for _, intpkg := range internalpkg {
  1184  		if pkg == intpkg {
  1185  			isinternal = true
  1186  			break
  1187  		}
  1188  	}
  1189  
  1190  	// DragonFly declares errno with __thread, which results in a symbol
  1191  	// type of R_386_TLS_GD or R_X86_64_TLSGD. The Go linker does not
  1192  	// currently know how to handle TLS relocations, hence we have to
  1193  	// force external linking for any libraries that link in code that
  1194  	// uses errno. This can be removed if the Go linker ever supports
  1195  	// these relocation types.
  1196  	if headType == objabi.Hdragonfly {
  1197  		if pkg == "net" || pkg == "os/user" {
  1198  			isinternal = false
  1199  		}
  1200  	}
  1201  
  1202  	if !isinternal {
  1203  		externalobj = true
  1204  	}
  1205  
  1206  	hostobj = append(hostobj, Hostobj{})
  1207  	h := &hostobj[len(hostobj)-1]
  1208  	h.ld = ld
  1209  	h.pkg = pkg
  1210  	h.pn = pn
  1211  	h.file = file
  1212  	h.off = f.Offset()
  1213  	h.length = length
  1214  	return h
  1215  }
  1216  
  1217  func hostobjs(ctxt *Link) {
  1218  	if ctxt.LinkMode != LinkInternal {
  1219  		return
  1220  	}
  1221  	var h *Hostobj
  1222  
  1223  	for i := 0; i < len(hostobj); i++ {
  1224  		h = &hostobj[i]
  1225  		f, err := bio.Open(h.file)
  1226  		if err != nil {
  1227  			Exitf("cannot reopen %s: %v", h.pn, err)
  1228  		}
  1229  		f.MustSeek(h.off, 0)
  1230  		if h.ld == nil {
  1231  			Errorf("%s: unrecognized object file format", h.pn)
  1232  			continue
  1233  		}
  1234  		h.ld(ctxt, f, h.pkg, h.length, h.pn)
  1235  		if *flagCaptureHostObjs != "" {
  1236  			captureHostObj(h)
  1237  		}
  1238  		f.Close()
  1239  	}
  1240  }
  1241  
  1242  func hostlinksetup(ctxt *Link) {
  1243  	if ctxt.LinkMode != LinkExternal {
  1244  		return
  1245  	}
  1246  
  1247  	// For external link, record that we need to tell the external linker -s,
  1248  	// and turn off -s internally: the external linker needs the symbol
  1249  	// information for its final link.
  1250  	debug_s = *FlagS
  1251  	*FlagS = false
  1252  
  1253  	// create temporary directory and arrange cleanup
  1254  	if *flagTmpdir == "" {
  1255  		dir, err := os.MkdirTemp("", "go-link-")
  1256  		if err != nil {
  1257  			log.Fatal(err)
  1258  		}
  1259  		*flagTmpdir = dir
  1260  		ownTmpDir = true
  1261  		AtExit(func() {
  1262  			os.RemoveAll(*flagTmpdir)
  1263  		})
  1264  	}
  1265  
  1266  	// change our output to temporary object file
  1267  	if err := ctxt.Out.Close(); err != nil {
  1268  		Exitf("error closing output file")
  1269  	}
  1270  	mayberemoveoutfile()
  1271  
  1272  	p := filepath.Join(*flagTmpdir, "go.o")
  1273  	if err := ctxt.Out.Open(p); err != nil {
  1274  		Exitf("cannot create %s: %v", p, err)
  1275  	}
  1276  }
  1277  
  1278  // cleanTimeStamps resets the timestamps for the specified list of
  1279  // existing files to the Unix epoch (1970-01-01 00:00:00 +0000 UTC).
  1280  // We take this step in order to help preserve reproducible builds;
  1281  // this seems to be primarily needed for external linking on Darwin
  1282  // with later versions of xcode, which (unfortunately) seem to want to
  1283  // incorporate object file times into the final output file's build
  1284  // ID. See issue 64947 for the unpleasant details.
  1285  func cleanTimeStamps(files []string) {
  1286  	epocht := time.Unix(0, 0)
  1287  	for _, f := range files {
  1288  		if err := os.Chtimes(f, epocht, epocht); err != nil {
  1289  			Exitf("cannot chtimes %s: %v", f, err)
  1290  		}
  1291  	}
  1292  }
  1293  
  1294  // hostobjCopy creates a copy of the object files in hostobj in a
  1295  // temporary directory.
  1296  func (ctxt *Link) hostobjCopy() (paths []string) {
  1297  	var wg sync.WaitGroup
  1298  	sema := make(chan struct{}, runtime.NumCPU()) // limit open file descriptors
  1299  	for i, h := range hostobj {
  1300  		h := h
  1301  		dst := filepath.Join(*flagTmpdir, fmt.Sprintf("%06d.o", i))
  1302  		paths = append(paths, dst)
  1303  		if ctxt.Debugvlog != 0 {
  1304  			ctxt.Logf("host obj copy: %s from pkg %s -> %s\n", h.pn, h.pkg, dst)
  1305  		}
  1306  
  1307  		wg.Add(1)
  1308  		go func() {
  1309  			sema <- struct{}{}
  1310  			defer func() {
  1311  				<-sema
  1312  				wg.Done()
  1313  			}()
  1314  			f, err := os.Open(h.file)
  1315  			if err != nil {
  1316  				Exitf("cannot reopen %s: %v", h.pn, err)
  1317  			}
  1318  			defer f.Close()
  1319  			if _, err := f.Seek(h.off, 0); err != nil {
  1320  				Exitf("cannot seek %s: %v", h.pn, err)
  1321  			}
  1322  
  1323  			w, err := os.Create(dst)
  1324  			if err != nil {
  1325  				Exitf("cannot create %s: %v", dst, err)
  1326  			}
  1327  			if _, err := io.CopyN(w, f, h.length); err != nil {
  1328  				Exitf("cannot write %s: %v", dst, err)
  1329  			}
  1330  			if err := w.Close(); err != nil {
  1331  				Exitf("cannot close %s: %v", dst, err)
  1332  			}
  1333  		}()
  1334  	}
  1335  	wg.Wait()
  1336  	return paths
  1337  }
  1338  
  1339  // writeGDBLinkerScript creates gcc linker script file in temp
  1340  // directory. writeGDBLinkerScript returns created file path.
  1341  // The script is used to work around gcc bug
  1342  // (see https://golang.org/issue/20183 for details).
  1343  func writeGDBLinkerScript() string {
  1344  	name := "fix_debug_gdb_scripts.ld"
  1345  	path := filepath.Join(*flagTmpdir, name)
  1346  	src := `SECTIONS
  1347  {
  1348    .debug_gdb_scripts BLOCK(__section_alignment__) (NOLOAD) :
  1349    {
  1350      *(.debug_gdb_scripts)
  1351    }
  1352  }
  1353  INSERT AFTER .debug_types;
  1354  `
  1355  	err := os.WriteFile(path, []byte(src), 0666)
  1356  	if err != nil {
  1357  		Errorf("WriteFile %s failed: %v", name, err)
  1358  	}
  1359  	return path
  1360  }
  1361  
  1362  type machoUpdateFunc func(ctxt *Link, exef *os.File, exem *macho.File, outexe string) error
  1363  
  1364  // archive builds a .a archive from the hostobj object files.
  1365  func (ctxt *Link) archive() {
  1366  	if ctxt.BuildMode != BuildModeCArchive {
  1367  		return
  1368  	}
  1369  
  1370  	exitIfErrors()
  1371  
  1372  	if *flagExtar == "" {
  1373  		const printProgName = "--print-prog-name=ar"
  1374  		cc := ctxt.extld()
  1375  		*flagExtar = "ar"
  1376  		if linkerFlagSupported(ctxt.Arch, cc[0], "", printProgName) {
  1377  			*flagExtar = ctxt.findExtLinkTool("ar")
  1378  		}
  1379  	}
  1380  
  1381  	mayberemoveoutfile()
  1382  
  1383  	// Force the buffer to flush here so that external
  1384  	// tools will see a complete file.
  1385  	if err := ctxt.Out.Close(); err != nil {
  1386  		Exitf("error closing %v", *flagOutfile)
  1387  	}
  1388  
  1389  	argv := []string{*flagExtar, "-q", "-c", "-s"}
  1390  	if ctxt.HeadType == objabi.Haix {
  1391  		argv = append(argv, "-X64")
  1392  	}
  1393  	godotopath := filepath.Join(*flagTmpdir, "go.o")
  1394  	cleanTimeStamps([]string{godotopath})
  1395  	hostObjCopyPaths := ctxt.hostobjCopy()
  1396  	cleanTimeStamps(hostObjCopyPaths)
  1397  
  1398  	argv = append(argv, *flagOutfile)
  1399  	argv = append(argv, godotopath)
  1400  	argv = append(argv, hostObjCopyPaths...)
  1401  
  1402  	if ctxt.Debugvlog != 0 {
  1403  		ctxt.Logf("archive: %s\n", strings.Join(argv, " "))
  1404  	}
  1405  
  1406  	// If supported, use syscall.Exec() to invoke the archive command,
  1407  	// which should be the final remaining step needed for the link.
  1408  	// This will reduce peak RSS for the link (and speed up linking of
  1409  	// large applications), since when the archive command runs we
  1410  	// won't be holding onto all of the linker's live memory.
  1411  	if syscallExecSupported && !ownTmpDir {
  1412  		runAtExitFuncs()
  1413  		ctxt.execArchive(argv)
  1414  		panic("should not get here")
  1415  	}
  1416  
  1417  	// Otherwise invoke 'ar' in the usual way (fork + exec).
  1418  	if out, err := exec.Command(argv[0], argv[1:]...).CombinedOutput(); err != nil {
  1419  		Exitf("running %s failed: %v\n%s", argv[0], err, out)
  1420  	}
  1421  }
  1422  
  1423  func (ctxt *Link) hostlink() {
  1424  	if ctxt.LinkMode != LinkExternal || nerrors > 0 {
  1425  		return
  1426  	}
  1427  	if ctxt.BuildMode == BuildModeCArchive {
  1428  		return
  1429  	}
  1430  
  1431  	var argv []string
  1432  	argv = append(argv, ctxt.extld()...)
  1433  	argv = append(argv, hostlinkArchArgs(ctxt.Arch)...)
  1434  
  1435  	if *FlagS || debug_s {
  1436  		if ctxt.HeadType == objabi.Hdarwin {
  1437  			// Recent versions of macOS print
  1438  			//	ld: warning: option -s is obsolete and being ignored
  1439  			// so do not pass any arguments (but we strip symbols below).
  1440  		} else {
  1441  			argv = append(argv, "-s")
  1442  		}
  1443  	}
  1444  
  1445  	// On darwin, whether to combine DWARF into executable.
  1446  	// Only macOS supports unmapped segments such as our __DWARF segment.
  1447  	combineDwarf := ctxt.IsDarwin() && !*FlagW && machoPlatform == PLATFORM_MACOS
  1448  
  1449  	switch ctxt.HeadType {
  1450  	case objabi.Hdarwin:
  1451  		if combineDwarf {
  1452  			// Leave room for DWARF combining.
  1453  			// -headerpad is incompatible with -fembed-bitcode.
  1454  			argv = append(argv, "-Wl,-headerpad,1144")
  1455  		}
  1456  		if ctxt.DynlinkingGo() && buildcfg.GOOS != "ios" {
  1457  			// -flat_namespace is deprecated on iOS.
  1458  			// It is useful for supporting plugins. We don't support plugins on iOS.
  1459  			// -flat_namespace may cause the dynamic linker to hang at forkExec when
  1460  			// resolving a lazy binding. See issue 38824.
  1461  			// Force eager resolution to work around.
  1462  			argv = append(argv, "-Wl,-flat_namespace", "-Wl,-bind_at_load")
  1463  		}
  1464  		if !combineDwarf {
  1465  			argv = append(argv, "-Wl,-S") // suppress STAB (symbolic debugging) symbols
  1466  			if debug_s {
  1467  				// We are generating a binary with symbol table suppressed.
  1468  				// Suppress local symbols. We need to keep dynamically exported
  1469  				// and referenced symbols so the dynamic linker can resolve them.
  1470  				argv = append(argv, "-Wl,-x")
  1471  			}
  1472  		}
  1473  		if *flagHostBuildid == "none" {
  1474  			argv = append(argv, "-Wl,-no_uuid")
  1475  		}
  1476  	case objabi.Hopenbsd:
  1477  		argv = append(argv, "-pthread")
  1478  		if ctxt.BuildMode != BuildModePIE {
  1479  			argv = append(argv, "-Wl,-nopie")
  1480  		}
  1481  		if linkerFlagSupported(ctxt.Arch, argv[0], "", "-Wl,-z,nobtcfi") {
  1482  			// -Wl,-z,nobtcfi is only supported on OpenBSD 7.4+, remove guard
  1483  			// when OpenBSD 7.5 is released and 7.3 is no longer supported.
  1484  			argv = append(argv, "-Wl,-z,nobtcfi")
  1485  		}
  1486  		if ctxt.Arch.InFamily(sys.ARM64) {
  1487  			// Disable execute-only on openbsd/arm64 - the Go arm64 assembler
  1488  			// currently stores constants in the text section rather than in rodata.
  1489  			// See issue #59615.
  1490  			argv = append(argv, "-Wl,--no-execute-only")
  1491  		}
  1492  	case objabi.Hwindows:
  1493  		if windowsgui {
  1494  			argv = append(argv, "-mwindows")
  1495  		} else {
  1496  			argv = append(argv, "-mconsole")
  1497  		}
  1498  		// Mark as having awareness of terminal services, to avoid
  1499  		// ancient compatibility hacks.
  1500  		argv = append(argv, "-Wl,--tsaware")
  1501  
  1502  		// Enable DEP
  1503  		argv = append(argv, "-Wl,--nxcompat")
  1504  
  1505  		argv = append(argv, fmt.Sprintf("-Wl,--major-os-version=%d", PeMinimumTargetMajorVersion))
  1506  		argv = append(argv, fmt.Sprintf("-Wl,--minor-os-version=%d", PeMinimumTargetMinorVersion))
  1507  		argv = append(argv, fmt.Sprintf("-Wl,--major-subsystem-version=%d", PeMinimumTargetMajorVersion))
  1508  		argv = append(argv, fmt.Sprintf("-Wl,--minor-subsystem-version=%d", PeMinimumTargetMinorVersion))
  1509  	case objabi.Haix:
  1510  		argv = append(argv, "-pthread")
  1511  		// prevent ld to reorder .text functions to keep the same
  1512  		// first/last functions for moduledata.
  1513  		argv = append(argv, "-Wl,-bnoobjreorder")
  1514  		// mcmodel=large is needed for every gcc generated files, but
  1515  		// ld still need -bbigtoc in order to allow larger TOC.
  1516  		argv = append(argv, "-mcmodel=large")
  1517  		argv = append(argv, "-Wl,-bbigtoc")
  1518  	}
  1519  
  1520  	// On PPC64, verify the external toolchain supports Power10. This is needed when
  1521  	// PC relative relocations might be generated by Go. Only targets compiling ELF
  1522  	// binaries might generate these relocations.
  1523  	if ctxt.IsPPC64() && ctxt.IsElf() && buildcfg.GOPPC64 >= 10 {
  1524  		if !linkerFlagSupported(ctxt.Arch, argv[0], "", "-mcpu=power10") {
  1525  			Exitf("The external toolchain does not support -mcpu=power10. " +
  1526  				" This is required to externally link GOPPC64 >= power10")
  1527  		}
  1528  	}
  1529  
  1530  	// Enable/disable ASLR on Windows.
  1531  	addASLRargs := func(argv []string, val bool) []string {
  1532  		// Old/ancient versions of GCC support "--dynamicbase" and
  1533  		// "--high-entropy-va" but don't enable it by default. In
  1534  		// addition, they don't accept "--disable-dynamicbase" or
  1535  		// "--no-dynamicbase", so the only way to disable ASLR is to
  1536  		// not pass any flags at all.
  1537  		//
  1538  		// More modern versions of GCC (and also clang) enable ASLR
  1539  		// by default. With these compilers, however you can turn it
  1540  		// off if you want using "--disable-dynamicbase" or
  1541  		// "--no-dynamicbase".
  1542  		//
  1543  		// The strategy below is to try using "--disable-dynamicbase";
  1544  		// if this succeeds, then assume we're working with more
  1545  		// modern compilers and act accordingly. If it fails, assume
  1546  		// an ancient compiler with ancient defaults.
  1547  		var dbopt string
  1548  		var heopt string
  1549  		dbon := "--dynamicbase"
  1550  		heon := "--high-entropy-va"
  1551  		dboff := "--disable-dynamicbase"
  1552  		heoff := "--disable-high-entropy-va"
  1553  		if val {
  1554  			dbopt = dbon
  1555  			heopt = heon
  1556  		} else {
  1557  			// Test to see whether "--disable-dynamicbase" works.
  1558  			newer := linkerFlagSupported(ctxt.Arch, argv[0], "", "-Wl,"+dboff)
  1559  			if newer {
  1560  				// Newer compiler, which supports both on/off options.
  1561  				dbopt = dboff
  1562  				heopt = heoff
  1563  			} else {
  1564  				// older toolchain: we have to say nothing in order to
  1565  				// get a no-ASLR binary.
  1566  				dbopt = ""
  1567  				heopt = ""
  1568  			}
  1569  		}
  1570  		if dbopt != "" {
  1571  			argv = append(argv, "-Wl,"+dbopt)
  1572  		}
  1573  		// enable high-entropy ASLR on 64-bit.
  1574  		if ctxt.Arch.PtrSize >= 8 && heopt != "" {
  1575  			argv = append(argv, "-Wl,"+heopt)
  1576  		}
  1577  		return argv
  1578  	}
  1579  
  1580  	switch ctxt.BuildMode {
  1581  	case BuildModeExe:
  1582  		if ctxt.HeadType == objabi.Hdarwin {
  1583  			if machoPlatform == PLATFORM_MACOS && ctxt.IsAMD64() {
  1584  				argv = append(argv, "-Wl,-no_pie")
  1585  			}
  1586  		}
  1587  		if *flagRace && ctxt.HeadType == objabi.Hwindows {
  1588  			// Current windows/amd64 race detector tsan support
  1589  			// library can't handle PIE mode (see #53539 for more details).
  1590  			// For now, explicitly disable PIE (since some compilers
  1591  			// default to it) if -race is in effect.
  1592  			argv = addASLRargs(argv, false)
  1593  		}
  1594  	case BuildModePIE:
  1595  		switch ctxt.HeadType {
  1596  		case objabi.Hdarwin, objabi.Haix:
  1597  		case objabi.Hwindows:
  1598  			if *flagAslr && *flagRace {
  1599  				// Current windows/amd64 race detector tsan support
  1600  				// library can't handle PIE mode (see #53539 for more details).
  1601  				// Disable alsr if -race in effect.
  1602  				*flagAslr = false
  1603  			}
  1604  			argv = addASLRargs(argv, *flagAslr)
  1605  		default:
  1606  			// ELF.
  1607  			if ctxt.UseRelro() {
  1608  				argv = append(argv, "-Wl,-z,relro")
  1609  			}
  1610  			argv = append(argv, "-pie")
  1611  		}
  1612  	case BuildModeCShared:
  1613  		if ctxt.HeadType == objabi.Hdarwin {
  1614  			argv = append(argv, "-dynamiclib")
  1615  		} else {
  1616  			if ctxt.UseRelro() {
  1617  				argv = append(argv, "-Wl,-z,relro")
  1618  			}
  1619  			argv = append(argv, "-shared")
  1620  			if ctxt.HeadType == objabi.Hwindows {
  1621  				argv = addASLRargs(argv, *flagAslr)
  1622  			} else {
  1623  				// Pass -z nodelete to mark the shared library as
  1624  				// non-closeable: a dlclose will do nothing.
  1625  				argv = append(argv, "-Wl,-z,nodelete")
  1626  				// Only pass Bsymbolic on non-Windows.
  1627  				argv = append(argv, "-Wl,-Bsymbolic")
  1628  			}
  1629  		}
  1630  	case BuildModeShared:
  1631  		if ctxt.UseRelro() {
  1632  			argv = append(argv, "-Wl,-z,relro")
  1633  		}
  1634  		argv = append(argv, "-shared")
  1635  	case BuildModePlugin:
  1636  		if ctxt.HeadType == objabi.Hdarwin {
  1637  			argv = append(argv, "-dynamiclib")
  1638  		} else {
  1639  			if ctxt.UseRelro() {
  1640  				argv = append(argv, "-Wl,-z,relro")
  1641  			}
  1642  			argv = append(argv, "-shared")
  1643  		}
  1644  	}
  1645  
  1646  	var altLinker string
  1647  	if ctxt.IsELF && (ctxt.DynlinkingGo() || *flagBindNow) {
  1648  		// For ELF targets, when producing dynamically linked Go code
  1649  		// or when immediate binding is explicitly requested,
  1650  		// we force all symbol resolution to be done at program startup
  1651  		// because lazy PLT resolution can use large amounts of stack at
  1652  		// times we cannot allow it to do so.
  1653  		argv = append(argv, "-Wl,-z,now")
  1654  	}
  1655  
  1656  	if ctxt.IsELF && ctxt.DynlinkingGo() {
  1657  		// Do not let the host linker generate COPY relocations. These
  1658  		// can move symbols out of sections that rely on stable offsets
  1659  		// from the beginning of the section (like sym.STYPE).
  1660  		argv = append(argv, "-Wl,-z,nocopyreloc")
  1661  
  1662  		if buildcfg.GOOS == "android" {
  1663  			// Use lld to avoid errors from default linker (issue #38838)
  1664  			altLinker = "lld"
  1665  		}
  1666  
  1667  		if ctxt.Arch.InFamily(sys.ARM64) && buildcfg.GOOS == "linux" {
  1668  			// On ARM64, the GNU linker will fail with
  1669  			// -znocopyreloc if it thinks a COPY relocation is
  1670  			// required. Switch to gold.
  1671  			// https://sourceware.org/bugzilla/show_bug.cgi?id=19962
  1672  			// https://go.dev/issue/22040
  1673  			altLinker = "gold"
  1674  
  1675  			// If gold is not installed, gcc will silently switch
  1676  			// back to ld.bfd. So we parse the version information
  1677  			// and provide a useful error if gold is missing.
  1678  			name, args := flagExtld[0], flagExtld[1:]
  1679  			args = append(args, "-fuse-ld=gold", "-Wl,--version")
  1680  			cmd := exec.Command(name, args...)
  1681  			if out, err := cmd.CombinedOutput(); err == nil {
  1682  				if !bytes.Contains(out, []byte("GNU gold")) {
  1683  					log.Fatalf("ARM64 external linker must be gold (issue #15696, 22040), but is not: %s", out)
  1684  				}
  1685  			}
  1686  		}
  1687  	}
  1688  	if ctxt.Arch.Family == sys.ARM64 && buildcfg.GOOS == "freebsd" {
  1689  		// Switch to ld.bfd on freebsd/arm64.
  1690  		altLinker = "bfd"
  1691  
  1692  		// Provide a useful error if ld.bfd is missing.
  1693  		name, args := flagExtld[0], flagExtld[1:]
  1694  		args = append(args, "-fuse-ld=bfd", "-Wl,--version")
  1695  		cmd := exec.Command(name, args...)
  1696  		if out, err := cmd.CombinedOutput(); err == nil {
  1697  			if !bytes.Contains(out, []byte("GNU ld")) {
  1698  				log.Fatalf("ARM64 external linker must be ld.bfd (issue #35197), please install devel/binutils")
  1699  			}
  1700  		}
  1701  	}
  1702  	if altLinker != "" {
  1703  		argv = append(argv, "-fuse-ld="+altLinker)
  1704  	}
  1705  
  1706  	if ctxt.IsELF && linkerFlagSupported(ctxt.Arch, argv[0], "", "-Wl,--build-id=0x1234567890abcdef") { // Solaris ld doesn't support --build-id.
  1707  		if len(buildinfo) > 0 {
  1708  			argv = append(argv, fmt.Sprintf("-Wl,--build-id=0x%x", buildinfo))
  1709  		} else if *flagHostBuildid == "none" {
  1710  			argv = append(argv, "-Wl,--build-id=none")
  1711  		}
  1712  	}
  1713  
  1714  	// On Windows, given -o foo, GCC will append ".exe" to produce
  1715  	// "foo.exe".  We have decided that we want to honor the -o
  1716  	// option. To make this work, we append a '.' so that GCC
  1717  	// will decide that the file already has an extension. We
  1718  	// only want to do this when producing a Windows output file
  1719  	// on a Windows host.
  1720  	outopt := *flagOutfile
  1721  	if buildcfg.GOOS == "windows" && runtime.GOOS == "windows" && filepath.Ext(outopt) == "" {
  1722  		outopt += "."
  1723  	}
  1724  	argv = append(argv, "-o")
  1725  	argv = append(argv, outopt)
  1726  
  1727  	if rpath.val != "" {
  1728  		argv = append(argv, fmt.Sprintf("-Wl,-rpath,%s", rpath.val))
  1729  	}
  1730  
  1731  	if *flagInterpreter != "" {
  1732  		// Many linkers support both -I and the --dynamic-linker flags
  1733  		// to set the ELF interpreter, but lld only supports
  1734  		// --dynamic-linker so prefer that (ld on very old Solaris only
  1735  		// supports -I but that seems less important).
  1736  		argv = append(argv, fmt.Sprintf("-Wl,--dynamic-linker,%s", *flagInterpreter))
  1737  	}
  1738  
  1739  	// Force global symbols to be exported for dlopen, etc.
  1740  	if ctxt.IsELF {
  1741  		if ctxt.DynlinkingGo() || ctxt.BuildMode == BuildModeCShared || !linkerFlagSupported(ctxt.Arch, argv[0], altLinker, "-Wl,--export-dynamic-symbol=main") {
  1742  			argv = append(argv, "-rdynamic")
  1743  		} else {
  1744  			var exports []string
  1745  			ctxt.loader.ForAllCgoExportDynamic(func(s loader.Sym) {
  1746  				exports = append(exports, "-Wl,--export-dynamic-symbol="+ctxt.loader.SymExtname(s))
  1747  			})
  1748  			sort.Strings(exports)
  1749  			argv = append(argv, exports...)
  1750  		}
  1751  	}
  1752  	if ctxt.HeadType == objabi.Haix {
  1753  		fileName := xcoffCreateExportFile(ctxt)
  1754  		argv = append(argv, "-Wl,-bE:"+fileName)
  1755  	}
  1756  
  1757  	const unusedArguments = "-Qunused-arguments"
  1758  	if linkerFlagSupported(ctxt.Arch, argv[0], altLinker, unusedArguments) {
  1759  		argv = append(argv, unusedArguments)
  1760  	}
  1761  
  1762  	if ctxt.IsWindows() {
  1763  		// Suppress generation of the PE file header timestamp,
  1764  		// so as to avoid spurious build ID differences between
  1765  		// linked binaries that are otherwise identical other than
  1766  		// the date/time they were linked.
  1767  		const noTimeStamp = "-Wl,--no-insert-timestamp"
  1768  		if linkerFlagSupported(ctxt.Arch, argv[0], altLinker, noTimeStamp) {
  1769  			argv = append(argv, noTimeStamp)
  1770  		}
  1771  	}
  1772  
  1773  	const compressDWARF = "-Wl,--compress-debug-sections=zlib"
  1774  	if ctxt.compressDWARF && linkerFlagSupported(ctxt.Arch, argv[0], altLinker, compressDWARF) {
  1775  		argv = append(argv, compressDWARF)
  1776  	}
  1777  
  1778  	hostObjCopyPaths := ctxt.hostobjCopy()
  1779  	cleanTimeStamps(hostObjCopyPaths)
  1780  	godotopath := filepath.Join(*flagTmpdir, "go.o")
  1781  	cleanTimeStamps([]string{godotopath})
  1782  
  1783  	argv = append(argv, godotopath)
  1784  	argv = append(argv, hostObjCopyPaths...)
  1785  	if ctxt.HeadType == objabi.Haix {
  1786  		// We want to have C files after Go files to remove
  1787  		// trampolines csects made by ld.
  1788  		argv = append(argv, "-nostartfiles")
  1789  		argv = append(argv, "/lib/crt0_64.o")
  1790  
  1791  		extld := ctxt.extld()
  1792  		name, args := extld[0], extld[1:]
  1793  		// Get starting files.
  1794  		getPathFile := func(file string) string {
  1795  			args := append(args, "-maix64", "--print-file-name="+file)
  1796  			out, err := exec.Command(name, args...).CombinedOutput()
  1797  			if err != nil {
  1798  				log.Fatalf("running %s failed: %v\n%s", extld, err, out)
  1799  			}
  1800  			return strings.Trim(string(out), "\n")
  1801  		}
  1802  		// Since GCC version 11, the 64-bit version of GCC starting files
  1803  		// are now suffixed by "_64". Even under "-maix64" multilib directory
  1804  		// "crtcxa.o" is 32-bit.
  1805  		crtcxa := getPathFile("crtcxa_64.o")
  1806  		if !filepath.IsAbs(crtcxa) {
  1807  			crtcxa = getPathFile("crtcxa.o")
  1808  		}
  1809  		crtdbase := getPathFile("crtdbase_64.o")
  1810  		if !filepath.IsAbs(crtdbase) {
  1811  			crtdbase = getPathFile("crtdbase.o")
  1812  		}
  1813  		argv = append(argv, crtcxa)
  1814  		argv = append(argv, crtdbase)
  1815  	}
  1816  
  1817  	if ctxt.linkShared {
  1818  		seenDirs := make(map[string]bool)
  1819  		seenLibs := make(map[string]bool)
  1820  		addshlib := func(path string) {
  1821  			dir, base := filepath.Split(path)
  1822  			if !seenDirs[dir] {
  1823  				argv = append(argv, "-L"+dir)
  1824  				if !rpath.set {
  1825  					argv = append(argv, "-Wl,-rpath="+dir)
  1826  				}
  1827  				seenDirs[dir] = true
  1828  			}
  1829  			base = strings.TrimSuffix(base, ".so")
  1830  			base = strings.TrimPrefix(base, "lib")
  1831  			if !seenLibs[base] {
  1832  				argv = append(argv, "-l"+base)
  1833  				seenLibs[base] = true
  1834  			}
  1835  		}
  1836  		for _, shlib := range ctxt.Shlibs {
  1837  			addshlib(shlib.Path)
  1838  			for _, dep := range shlib.Deps {
  1839  				if dep == "" {
  1840  					continue
  1841  				}
  1842  				libpath := findshlib(ctxt, dep)
  1843  				if libpath != "" {
  1844  					addshlib(libpath)
  1845  				}
  1846  			}
  1847  		}
  1848  	}
  1849  
  1850  	// clang, unlike GCC, passes -rdynamic to the linker
  1851  	// even when linking with -static, causing a linker
  1852  	// error when using GNU ld. So take out -rdynamic if
  1853  	// we added it. We do it in this order, rather than
  1854  	// only adding -rdynamic later, so that -extldflags
  1855  	// can override -rdynamic without using -static.
  1856  	// Similarly for -Wl,--dynamic-linker.
  1857  	checkStatic := func(arg string) {
  1858  		if ctxt.IsELF && arg == "-static" {
  1859  			for i := range argv {
  1860  				if argv[i] == "-rdynamic" || strings.HasPrefix(argv[i], "-Wl,--dynamic-linker,") {
  1861  					argv[i] = "-static"
  1862  				}
  1863  			}
  1864  		}
  1865  	}
  1866  
  1867  	for _, p := range ldflag {
  1868  		argv = append(argv, p)
  1869  		checkStatic(p)
  1870  	}
  1871  
  1872  	// When building a program with the default -buildmode=exe the
  1873  	// gc compiler generates code requires DT_TEXTREL in a
  1874  	// position independent executable (PIE). On systems where the
  1875  	// toolchain creates PIEs by default, and where DT_TEXTREL
  1876  	// does not work, the resulting programs will not run. See
  1877  	// issue #17847. To avoid this problem pass -no-pie to the
  1878  	// toolchain if it is supported.
  1879  	if ctxt.BuildMode == BuildModeExe && !ctxt.linkShared && !(ctxt.IsDarwin() && ctxt.IsARM64()) {
  1880  		// GCC uses -no-pie, clang uses -nopie.
  1881  		for _, nopie := range []string{"-no-pie", "-nopie"} {
  1882  			if linkerFlagSupported(ctxt.Arch, argv[0], altLinker, nopie) {
  1883  				argv = append(argv, nopie)
  1884  				break
  1885  			}
  1886  		}
  1887  	}
  1888  
  1889  	for _, p := range flagExtldflags {
  1890  		argv = append(argv, p)
  1891  		checkStatic(p)
  1892  	}
  1893  	if ctxt.HeadType == objabi.Hwindows {
  1894  		// Determine which linker we're using. Add in the extldflags in
  1895  		// case used has specified "-fuse-ld=...".
  1896  		extld := ctxt.extld()
  1897  		name, args := extld[0], extld[1:]
  1898  		args = append(args, trimLinkerArgv(flagExtldflags)...)
  1899  		args = append(args, "-Wl,--version")
  1900  		cmd := exec.Command(name, args...)
  1901  		usingLLD := false
  1902  		if out, err := cmd.CombinedOutput(); err == nil {
  1903  			if bytes.Contains(out, []byte("LLD ")) {
  1904  				usingLLD = true
  1905  			}
  1906  		}
  1907  
  1908  		// use gcc linker script to work around gcc bug
  1909  		// (see https://golang.org/issue/20183 for details).
  1910  		if !usingLLD {
  1911  			p := writeGDBLinkerScript()
  1912  			argv = append(argv, "-Wl,-T,"+p)
  1913  		}
  1914  		if *flagRace {
  1915  			if p := ctxt.findLibPath("libsynchronization.a"); p != "libsynchronization.a" {
  1916  				argv = append(argv, "-lsynchronization")
  1917  			}
  1918  		}
  1919  		// libmingw32 and libmingwex have some inter-dependencies,
  1920  		// so must use linker groups.
  1921  		argv = append(argv, "-Wl,--start-group", "-lmingwex", "-lmingw32", "-Wl,--end-group")
  1922  		argv = append(argv, peimporteddlls()...)
  1923  	}
  1924  
  1925  	argv = ctxt.passLongArgsInResponseFile(argv, altLinker)
  1926  
  1927  	if ctxt.Debugvlog != 0 {
  1928  		ctxt.Logf("host link:")
  1929  		for _, v := range argv {
  1930  			ctxt.Logf(" %q", v)
  1931  		}
  1932  		ctxt.Logf("\n")
  1933  	}
  1934  
  1935  	cmd := exec.Command(argv[0], argv[1:]...)
  1936  	out, err := cmd.CombinedOutput()
  1937  	if err != nil {
  1938  		Exitf("running %s failed: %v\n%s\n%s", argv[0], err, cmd, out)
  1939  	}
  1940  
  1941  	// Filter out useless linker warnings caused by bugs outside Go.
  1942  	// See also cmd/go/internal/work/exec.go's gccld method.
  1943  	var save [][]byte
  1944  	var skipLines int
  1945  	for _, line := range bytes.SplitAfter(out, []byte("\n")) {
  1946  		// golang.org/issue/26073 - Apple Xcode bug
  1947  		if bytes.Contains(line, []byte("ld: warning: text-based stub file")) {
  1948  			continue
  1949  		}
  1950  
  1951  		if skipLines > 0 {
  1952  			skipLines--
  1953  			continue
  1954  		}
  1955  
  1956  		// Remove TOC overflow warning on AIX.
  1957  		if bytes.Contains(line, []byte("ld: 0711-783")) {
  1958  			skipLines = 2
  1959  			continue
  1960  		}
  1961  
  1962  		save = append(save, line)
  1963  	}
  1964  	out = bytes.Join(save, nil)
  1965  
  1966  	if len(out) > 0 {
  1967  		// always print external output even if the command is successful, so that we don't
  1968  		// swallow linker warnings (see https://golang.org/issue/17935).
  1969  		if ctxt.IsDarwin() && ctxt.IsAMD64() {
  1970  			const noPieWarning = "ld: warning: -no_pie is deprecated when targeting new OS versions\n"
  1971  			if i := bytes.Index(out, []byte(noPieWarning)); i >= 0 {
  1972  				// swallow -no_pie deprecation warning, issue 54482
  1973  				out = append(out[:i], out[i+len(noPieWarning):]...)
  1974  			}
  1975  		}
  1976  		if ctxt.IsDarwin() {
  1977  			const bindAtLoadWarning = "ld: warning: -bind_at_load is deprecated on macOS\n"
  1978  			if i := bytes.Index(out, []byte(bindAtLoadWarning)); i >= 0 {
  1979  				// -bind_at_load is deprecated with ld-prime, but needed for
  1980  				// correctness with older versions of ld64. Swallow the warning.
  1981  				// TODO: maybe pass -bind_at_load conditionally based on C
  1982  				// linker version.
  1983  				out = append(out[:i], out[i+len(bindAtLoadWarning):]...)
  1984  			}
  1985  		}
  1986  		ctxt.Logf("%s", out)
  1987  	}
  1988  
  1989  	// Helper for updating a Macho binary in some way (shared between
  1990  	// dwarf combining and UUID update).
  1991  	updateMachoOutFile := func(op string, updateFunc machoUpdateFunc) {
  1992  		// For os.Rename to work reliably, must be in same directory as outfile.
  1993  		rewrittenOutput := *flagOutfile + "~"
  1994  		exef, err := os.Open(*flagOutfile)
  1995  		if err != nil {
  1996  			Exitf("%s: %s failed: %v", os.Args[0], op, err)
  1997  		}
  1998  		defer exef.Close()
  1999  		exem, err := macho.NewFile(exef)
  2000  		if err != nil {
  2001  			Exitf("%s: parsing Mach-O header failed: %v", os.Args[0], err)
  2002  		}
  2003  		if err := updateFunc(ctxt, exef, exem, rewrittenOutput); err != nil {
  2004  			Exitf("%s: %s failed: %v", os.Args[0], op, err)
  2005  		}
  2006  		os.Remove(*flagOutfile)
  2007  		if err := os.Rename(rewrittenOutput, *flagOutfile); err != nil {
  2008  			Exitf("%s: %v", os.Args[0], err)
  2009  		}
  2010  	}
  2011  
  2012  	uuidUpdated := false
  2013  	if combineDwarf {
  2014  		// Find "dsymutils" and "strip" tools using CC --print-prog-name.
  2015  		dsymutilCmd := ctxt.findExtLinkTool("dsymutil")
  2016  		stripCmd := ctxt.findExtLinkTool("strip")
  2017  
  2018  		dsym := filepath.Join(*flagTmpdir, "go.dwarf")
  2019  		cmd := exec.Command(dsymutilCmd, "-f", *flagOutfile, "-o", dsym)
  2020  		// dsymutil may not clean up its temp directory at exit.
  2021  		// Set DSYMUTIL_REPRODUCER_PATH to work around. see issue 59026.
  2022  		// dsymutil (Apple LLVM version 16.0.0) deletes the directory
  2023  		// even if it is not empty. We still need our tmpdir, so give a
  2024  		// subdirectory to dsymutil.
  2025  		dsymDir := filepath.Join(*flagTmpdir, "dsymutil")
  2026  		err := os.MkdirAll(dsymDir, 0777)
  2027  		if err != nil {
  2028  			Exitf("fail to create temp dir: %v", err)
  2029  		}
  2030  		cmd.Env = append(os.Environ(), "DSYMUTIL_REPRODUCER_PATH="+dsymDir)
  2031  		if ctxt.Debugvlog != 0 {
  2032  			ctxt.Logf("host link dsymutil:")
  2033  			for _, v := range cmd.Args {
  2034  				ctxt.Logf(" %q", v)
  2035  			}
  2036  			ctxt.Logf("\n")
  2037  		}
  2038  		if out, err := cmd.CombinedOutput(); err != nil {
  2039  			Exitf("%s: running dsymutil failed: %v\n%s\n%s", os.Args[0], err, cmd, out)
  2040  		}
  2041  		// Remove STAB (symbolic debugging) symbols after we are done with them (by dsymutil).
  2042  		// They contain temporary file paths and make the build not reproducible.
  2043  		var stripArgs = []string{"-S"}
  2044  		if debug_s {
  2045  			// We are generating a binary with symbol table suppressed.
  2046  			// Suppress local symbols. We need to keep dynamically exported
  2047  			// and referenced symbols so the dynamic linker can resolve them.
  2048  			stripArgs = append(stripArgs, "-x")
  2049  		}
  2050  		stripArgs = append(stripArgs, *flagOutfile)
  2051  		if ctxt.Debugvlog != 0 {
  2052  			ctxt.Logf("host link strip: %q", stripCmd)
  2053  			for _, v := range stripArgs {
  2054  				ctxt.Logf(" %q", v)
  2055  			}
  2056  			ctxt.Logf("\n")
  2057  		}
  2058  		cmd = exec.Command(stripCmd, stripArgs...)
  2059  		if out, err := cmd.CombinedOutput(); err != nil {
  2060  			Exitf("%s: running strip failed: %v\n%s\n%s", os.Args[0], err, cmd, out)
  2061  		}
  2062  		// Skip combining if `dsymutil` didn't generate a file. See #11994.
  2063  		if _, err := os.Stat(dsym); err == nil {
  2064  			updateMachoOutFile("combining dwarf",
  2065  				func(ctxt *Link, exef *os.File, exem *macho.File, outexe string) error {
  2066  					return machoCombineDwarf(ctxt, exef, exem, dsym, outexe)
  2067  				})
  2068  			uuidUpdated = true
  2069  		}
  2070  	}
  2071  	if ctxt.IsDarwin() && !uuidUpdated && len(buildinfo) > 0 {
  2072  		updateMachoOutFile("rewriting uuid",
  2073  			func(ctxt *Link, exef *os.File, exem *macho.File, outexe string) error {
  2074  				return machoRewriteUuid(ctxt, exef, exem, outexe)
  2075  			})
  2076  	}
  2077  	hostlinkfips(ctxt, *flagOutfile, *flagFipso)
  2078  	if ctxt.NeedCodeSign() {
  2079  		err := machoCodeSign(ctxt, *flagOutfile)
  2080  		if err != nil {
  2081  			Exitf("%s: code signing failed: %v", os.Args[0], err)
  2082  		}
  2083  	}
  2084  }
  2085  
  2086  // passLongArgsInResponseFile writes the arguments into a file if they
  2087  // are very long.
  2088  func (ctxt *Link) passLongArgsInResponseFile(argv []string, altLinker string) []string {
  2089  	c := 0
  2090  	for _, arg := range argv {
  2091  		c += len(arg)
  2092  	}
  2093  
  2094  	if c < sys.ExecArgLengthLimit {
  2095  		return argv
  2096  	}
  2097  
  2098  	// Only use response files if they are supported.
  2099  	response := filepath.Join(*flagTmpdir, "response")
  2100  	if err := os.WriteFile(response, nil, 0644); err != nil {
  2101  		log.Fatalf("failed while testing response file: %v", err)
  2102  	}
  2103  	if !linkerFlagSupported(ctxt.Arch, argv[0], altLinker, "@"+response) {
  2104  		if ctxt.Debugvlog != 0 {
  2105  			ctxt.Logf("not using response file because linker does not support one")
  2106  		}
  2107  		return argv
  2108  	}
  2109  
  2110  	var buf bytes.Buffer
  2111  	for _, arg := range argv[1:] {
  2112  		// The external linker response file supports quoted strings.
  2113  		fmt.Fprintf(&buf, "%q\n", arg)
  2114  	}
  2115  	if err := os.WriteFile(response, buf.Bytes(), 0644); err != nil {
  2116  		log.Fatalf("failed while writing response file: %v", err)
  2117  	}
  2118  	if ctxt.Debugvlog != 0 {
  2119  		ctxt.Logf("response file %s contents:\n%s", response, buf.Bytes())
  2120  	}
  2121  	return []string{
  2122  		argv[0],
  2123  		"@" + response,
  2124  	}
  2125  }
  2126  
  2127  var createTrivialCOnce sync.Once
  2128  
  2129  func linkerFlagSupported(arch *sys.Arch, linker, altLinker, flag string) bool {
  2130  	createTrivialCOnce.Do(func() {
  2131  		src := filepath.Join(*flagTmpdir, "trivial.c")
  2132  		if err := os.WriteFile(src, []byte("int main() { return 0; }"), 0666); err != nil {
  2133  			Errorf("WriteFile trivial.c failed: %v", err)
  2134  		}
  2135  	})
  2136  
  2137  	flags := hostlinkArchArgs(arch)
  2138  
  2139  	moreFlags := trimLinkerArgv(append(ldflag, flagExtldflags...))
  2140  	flags = append(flags, moreFlags...)
  2141  
  2142  	if altLinker != "" {
  2143  		flags = append(flags, "-fuse-ld="+altLinker)
  2144  	}
  2145  	trivialPath := filepath.Join(*flagTmpdir, "trivial.c")
  2146  	outPath := filepath.Join(*flagTmpdir, "a.out")
  2147  	flags = append(flags, "-o", outPath, flag, trivialPath)
  2148  
  2149  	cmd := exec.Command(linker, flags...)
  2150  	cmd.Env = append([]string{"LC_ALL=C"}, os.Environ()...)
  2151  	out, err := cmd.CombinedOutput()
  2152  	// GCC says "unrecognized command line option ‘-no-pie’"
  2153  	// clang says "unknown argument: '-no-pie'"
  2154  	return err == nil && !bytes.Contains(out, []byte("unrecognized")) && !bytes.Contains(out, []byte("unknown"))
  2155  }
  2156  
  2157  // trimLinkerArgv returns a new copy of argv that does not include flags
  2158  // that are not relevant for testing whether some linker option works.
  2159  func trimLinkerArgv(argv []string) []string {
  2160  	flagsWithNextArgSkip := []string{
  2161  		"-F",
  2162  		"-l",
  2163  		"-L",
  2164  		"-framework",
  2165  		"-Wl,-framework",
  2166  		"-Wl,-rpath",
  2167  		"-Wl,-undefined",
  2168  	}
  2169  	flagsWithNextArgKeep := []string{
  2170  		"-arch",
  2171  		"-isysroot",
  2172  		"--sysroot",
  2173  		"-target",
  2174  	}
  2175  	prefixesToKeep := []string{
  2176  		"-f",
  2177  		"-m",
  2178  		"-p",
  2179  		"-Wl,",
  2180  		"-arch",
  2181  		"-isysroot",
  2182  		"--sysroot",
  2183  		"-target",
  2184  	}
  2185  
  2186  	var flags []string
  2187  	keep := false
  2188  	skip := false
  2189  	for _, f := range argv {
  2190  		if keep {
  2191  			flags = append(flags, f)
  2192  			keep = false
  2193  		} else if skip {
  2194  			skip = false
  2195  		} else if f == "" || f[0] != '-' {
  2196  		} else if slices.Contains(flagsWithNextArgSkip, f) {
  2197  			skip = true
  2198  		} else if slices.Contains(flagsWithNextArgKeep, f) {
  2199  			flags = append(flags, f)
  2200  			keep = true
  2201  		} else {
  2202  			for _, p := range prefixesToKeep {
  2203  				if strings.HasPrefix(f, p) {
  2204  					flags = append(flags, f)
  2205  					break
  2206  				}
  2207  			}
  2208  		}
  2209  	}
  2210  	return flags
  2211  }
  2212  
  2213  // hostlinkArchArgs returns arguments to pass to the external linker
  2214  // based on the architecture.
  2215  func hostlinkArchArgs(arch *sys.Arch) []string {
  2216  	switch arch.Family {
  2217  	case sys.I386:
  2218  		return []string{"-m32"}
  2219  	case sys.AMD64:
  2220  		if buildcfg.GOOS == "darwin" {
  2221  			return []string{"-arch", "x86_64", "-m64"}
  2222  		}
  2223  		return []string{"-m64"}
  2224  	case sys.S390X:
  2225  		return []string{"-m64"}
  2226  	case sys.ARM:
  2227  		return []string{"-marm"}
  2228  	case sys.ARM64:
  2229  		if buildcfg.GOOS == "darwin" {
  2230  			return []string{"-arch", "arm64"}
  2231  		}
  2232  	case sys.Loong64:
  2233  		return []string{"-mabi=lp64d"}
  2234  	case sys.MIPS64:
  2235  		return []string{"-mabi=64"}
  2236  	case sys.MIPS:
  2237  		return []string{"-mabi=32"}
  2238  	case sys.PPC64:
  2239  		if buildcfg.GOOS == "aix" {
  2240  			return []string{"-maix64"}
  2241  		} else {
  2242  			return []string{"-m64"}
  2243  		}
  2244  
  2245  	}
  2246  	return nil
  2247  }
  2248  
  2249  var wantHdr = objabi.HeaderString()
  2250  
  2251  // ldobj loads an input object. If it is a host object (an object
  2252  // compiled by a non-Go compiler) it returns the Hostobj pointer. If
  2253  // it is a Go object, it returns nil.
  2254  func ldobj(ctxt *Link, f *bio.Reader, lib *sym.Library, length int64, pn string, file string) *Hostobj {
  2255  	pkg := objabi.PathToPrefix(lib.Pkg)
  2256  
  2257  	eof := f.Offset() + length
  2258  	start := f.Offset()
  2259  	c1 := bgetc(f)
  2260  	c2 := bgetc(f)
  2261  	c3 := bgetc(f)
  2262  	c4 := bgetc(f)
  2263  	f.MustSeek(start, 0)
  2264  
  2265  	unit := &sym.CompilationUnit{Lib: lib}
  2266  	lib.Units = append(lib.Units, unit)
  2267  
  2268  	magic := uint32(c1)<<24 | uint32(c2)<<16 | uint32(c3)<<8 | uint32(c4)
  2269  	if magic == 0x7f454c46 { // \x7F E L F
  2270  		ldelf := func(ctxt *Link, f *bio.Reader, pkg string, length int64, pn string) {
  2271  			textp, flags, err := loadelf.Load(ctxt.loader, ctxt.Arch, ctxt.IncVersion(), f, pkg, length, pn, ehdr.Flags)
  2272  			if err != nil {
  2273  				Errorf("%v", err)
  2274  				return
  2275  			}
  2276  			ehdr.Flags = flags
  2277  			ctxt.Textp = append(ctxt.Textp, textp...)
  2278  		}
  2279  		return ldhostobj(ldelf, ctxt.HeadType, f, pkg, length, pn, file)
  2280  	}
  2281  
  2282  	if magic&^1 == 0xfeedface || magic&^0x01000000 == 0xcefaedfe {
  2283  		ldmacho := func(ctxt *Link, f *bio.Reader, pkg string, length int64, pn string) {
  2284  			textp, err := loadmacho.Load(ctxt.loader, ctxt.Arch, ctxt.IncVersion(), f, pkg, length, pn)
  2285  			if err != nil {
  2286  				Errorf("%v", err)
  2287  				return
  2288  			}
  2289  			ctxt.Textp = append(ctxt.Textp, textp...)
  2290  		}
  2291  		return ldhostobj(ldmacho, ctxt.HeadType, f, pkg, length, pn, file)
  2292  	}
  2293  
  2294  	switch c1<<8 | c2 {
  2295  	case 0x4c01, // 386
  2296  		0x6486, // amd64
  2297  		0xc401, // arm
  2298  		0x64aa: // arm64
  2299  		ldpe := func(ctxt *Link, f *bio.Reader, pkg string, length int64, pn string) {
  2300  			ls, err := loadpe.Load(ctxt.loader, ctxt.Arch, ctxt.IncVersion(), f, pkg, length, pn)
  2301  			if err != nil {
  2302  				Errorf("%v", err)
  2303  				return
  2304  			}
  2305  			if len(ls.Resources) != 0 {
  2306  				setpersrc(ctxt, ls.Resources)
  2307  			}
  2308  			if ls.PData != 0 {
  2309  				sehp.pdata = append(sehp.pdata, ls.PData)
  2310  			}
  2311  			if ls.XData != 0 {
  2312  				sehp.xdata = append(sehp.xdata, ls.XData)
  2313  			}
  2314  			ctxt.Textp = append(ctxt.Textp, ls.Textp...)
  2315  		}
  2316  		return ldhostobj(ldpe, ctxt.HeadType, f, pkg, length, pn, file)
  2317  	}
  2318  
  2319  	if c1 == 0x01 && (c2 == 0xD7 || c2 == 0xF7) {
  2320  		ldxcoff := func(ctxt *Link, f *bio.Reader, pkg string, length int64, pn string) {
  2321  			textp, err := loadxcoff.Load(ctxt.loader, ctxt.Arch, ctxt.IncVersion(), f, pkg, length, pn)
  2322  			if err != nil {
  2323  				Errorf("%v", err)
  2324  				return
  2325  			}
  2326  			ctxt.Textp = append(ctxt.Textp, textp...)
  2327  		}
  2328  		return ldhostobj(ldxcoff, ctxt.HeadType, f, pkg, length, pn, file)
  2329  	}
  2330  
  2331  	if c1 != 'g' || c2 != 'o' || c3 != ' ' || c4 != 'o' {
  2332  		// An unrecognized object is just passed to the external linker.
  2333  		// If we try to read symbols from this object, we will
  2334  		// report an error at that time.
  2335  		unknownObjFormat = true
  2336  		return ldhostobj(nil, ctxt.HeadType, f, pkg, length, pn, file)
  2337  	}
  2338  
  2339  	/* check the header */
  2340  	line, err := f.ReadString('\n')
  2341  	if err != nil {
  2342  		Errorf("truncated object file: %s: %v", pn, err)
  2343  		return nil
  2344  	}
  2345  
  2346  	if !strings.HasPrefix(line, "go object ") {
  2347  		if strings.HasSuffix(pn, ".go") {
  2348  			Exitf("%s: uncompiled .go source file", pn)
  2349  			return nil
  2350  		}
  2351  
  2352  		if line == ctxt.Arch.Name {
  2353  			// old header format: just $GOOS
  2354  			Errorf("%s: stale object file", pn)
  2355  			return nil
  2356  		}
  2357  
  2358  		Errorf("%s: not an object file: @%d %q", pn, start, line)
  2359  		return nil
  2360  	}
  2361  
  2362  	// First, check that the basic GOOS, GOARCH, and Version match.
  2363  	if line != wantHdr {
  2364  		Errorf("%s: linked object header mismatch:\nhave %q\nwant %q\n", pn, line, wantHdr)
  2365  	}
  2366  
  2367  	// Skip over exports and other info -- ends with \n!\n.
  2368  	//
  2369  	// Note: It's possible for "\n!\n" to appear within the binary
  2370  	// package export data format. To avoid truncating the package
  2371  	// definition prematurely (issue 21703), we keep track of
  2372  	// how many "$$" delimiters we've seen.
  2373  
  2374  	import0 := f.Offset()
  2375  
  2376  	c1 = '\n' // the last line ended in \n
  2377  	c2 = bgetc(f)
  2378  	c3 = bgetc(f)
  2379  	markers := 0
  2380  	for {
  2381  		if c1 == '\n' {
  2382  			if markers%2 == 0 && c2 == '!' && c3 == '\n' {
  2383  				break
  2384  			}
  2385  			if c2 == '$' && c3 == '$' {
  2386  				markers++
  2387  			}
  2388  		}
  2389  
  2390  		c1 = c2
  2391  		c2 = c3
  2392  		c3 = bgetc(f)
  2393  		if c3 == -1 {
  2394  			Errorf("truncated object file: %s", pn)
  2395  			return nil
  2396  		}
  2397  	}
  2398  
  2399  	import1 := f.Offset()
  2400  
  2401  	f.MustSeek(import0, 0)
  2402  	ldpkg(ctxt, f, lib, import1-import0-2, pn) // -2 for !\n
  2403  	f.MustSeek(import1, 0)
  2404  
  2405  	fingerprint := ctxt.loader.Preload(ctxt.IncVersion(), f, lib, unit, eof-f.Offset())
  2406  	if !fingerprint.IsZero() { // Assembly objects don't have fingerprints. Ignore them.
  2407  		// Check fingerprint, to ensure the importing and imported packages
  2408  		// have consistent view of symbol indices.
  2409  		// Normally the go command should ensure this. But in case something
  2410  		// goes wrong, it could lead to obscure bugs like run-time crash.
  2411  		// Check it here to be sure.
  2412  		if lib.Fingerprint.IsZero() { // Not yet imported. Update its fingerprint.
  2413  			lib.Fingerprint = fingerprint
  2414  		}
  2415  		checkFingerprint(lib, fingerprint, lib.Srcref, lib.Fingerprint)
  2416  	}
  2417  
  2418  	addImports(ctxt, lib, pn)
  2419  	return nil
  2420  }
  2421  
  2422  // symbolsAreUnresolved scans through the loader's list of unresolved
  2423  // symbols and checks to see whether any of them match the names of the
  2424  // symbols in 'want'. Return value is a list of bools, with list[K] set
  2425  // to true if there is an unresolved reference to the symbol in want[K].
  2426  func symbolsAreUnresolved(ctxt *Link, want []string) []bool {
  2427  	returnAllUndefs := -1
  2428  	undefs, _ := ctxt.loader.UndefinedRelocTargets(returnAllUndefs)
  2429  	seen := make(map[loader.Sym]struct{})
  2430  	rval := make([]bool, len(want))
  2431  	wantm := make(map[string]int)
  2432  	for k, w := range want {
  2433  		wantm[w] = k
  2434  	}
  2435  	count := 0
  2436  	for _, s := range undefs {
  2437  		if _, ok := seen[s]; ok {
  2438  			continue
  2439  		}
  2440  		seen[s] = struct{}{}
  2441  		if k, ok := wantm[ctxt.loader.SymName(s)]; ok {
  2442  			rval[k] = true
  2443  			count++
  2444  			if count == len(want) {
  2445  				return rval
  2446  			}
  2447  		}
  2448  	}
  2449  	return rval
  2450  }
  2451  
  2452  // hostObject reads a single host object file (compare to "hostArchive").
  2453  // This is used as part of internal linking when we need to pull in
  2454  // files such as "crt?.o".
  2455  func hostObject(ctxt *Link, objname string, path string) {
  2456  	if ctxt.Debugvlog > 1 {
  2457  		ctxt.Logf("hostObject(%s)\n", path)
  2458  	}
  2459  	objlib := sym.Library{
  2460  		Pkg: objname,
  2461  	}
  2462  	f, err := bio.Open(path)
  2463  	if err != nil {
  2464  		Exitf("cannot open host object %q file %s: %v", objname, path, err)
  2465  	}
  2466  	defer f.Close()
  2467  	h := ldobj(ctxt, f, &objlib, 0, path, path)
  2468  	if h.ld == nil {
  2469  		Exitf("unrecognized object file format in %s", path)
  2470  	}
  2471  	h.file = path
  2472  	h.length = f.MustSeek(0, 2)
  2473  	f.MustSeek(h.off, 0)
  2474  	h.ld(ctxt, f, h.pkg, h.length, h.pn)
  2475  	if *flagCaptureHostObjs != "" {
  2476  		captureHostObj(h)
  2477  	}
  2478  }
  2479  
  2480  func checkFingerprint(lib *sym.Library, libfp goobj.FingerprintType, src string, srcfp goobj.FingerprintType) {
  2481  	if libfp != srcfp {
  2482  		Exitf("fingerprint mismatch: %s has %x, import from %s expecting %x", lib, libfp, src, srcfp)
  2483  	}
  2484  }
  2485  
  2486  func readelfsymboldata(ctxt *Link, f *elf.File, sym *elf.Symbol) []byte {
  2487  	data := make([]byte, sym.Size)
  2488  	sect := f.Sections[sym.Section]
  2489  	if sect.Type != elf.SHT_PROGBITS && sect.Type != elf.SHT_NOTE {
  2490  		Errorf("reading %s from non-data section", sym.Name)
  2491  	}
  2492  	n, err := sect.ReadAt(data, int64(sym.Value-sect.Addr))
  2493  	if uint64(n) != sym.Size {
  2494  		Errorf("reading contents of %s: %v", sym.Name, err)
  2495  	}
  2496  	return data
  2497  }
  2498  
  2499  func readwithpad(r io.Reader, sz int32) ([]byte, error) {
  2500  	data := make([]byte, Rnd(int64(sz), 4))
  2501  	_, err := io.ReadFull(r, data)
  2502  	if err != nil {
  2503  		return nil, err
  2504  	}
  2505  	data = data[:sz]
  2506  	return data, nil
  2507  }
  2508  
  2509  func readnote(f *elf.File, name []byte, typ int32) ([]byte, error) {
  2510  	for _, sect := range f.Sections {
  2511  		if sect.Type != elf.SHT_NOTE {
  2512  			continue
  2513  		}
  2514  		r := sect.Open()
  2515  		for {
  2516  			var namesize, descsize, noteType int32
  2517  			err := binary.Read(r, f.ByteOrder, &namesize)
  2518  			if err != nil {
  2519  				if err == io.EOF {
  2520  					break
  2521  				}
  2522  				return nil, fmt.Errorf("read namesize failed: %v", err)
  2523  			}
  2524  			err = binary.Read(r, f.ByteOrder, &descsize)
  2525  			if err != nil {
  2526  				return nil, fmt.Errorf("read descsize failed: %v", err)
  2527  			}
  2528  			err = binary.Read(r, f.ByteOrder, &noteType)
  2529  			if err != nil {
  2530  				return nil, fmt.Errorf("read type failed: %v", err)
  2531  			}
  2532  			noteName, err := readwithpad(r, namesize)
  2533  			if err != nil {
  2534  				return nil, fmt.Errorf("read name failed: %v", err)
  2535  			}
  2536  			desc, err := readwithpad(r, descsize)
  2537  			if err != nil {
  2538  				return nil, fmt.Errorf("read desc failed: %v", err)
  2539  			}
  2540  			if string(name) == string(noteName) && typ == noteType {
  2541  				return desc, nil
  2542  			}
  2543  		}
  2544  	}
  2545  	return nil, nil
  2546  }
  2547  
  2548  func findshlib(ctxt *Link, shlib string) string {
  2549  	if filepath.IsAbs(shlib) {
  2550  		return shlib
  2551  	}
  2552  	for _, libdir := range ctxt.Libdir {
  2553  		libpath := filepath.Join(libdir, shlib)
  2554  		if _, err := os.Stat(libpath); err == nil {
  2555  			return libpath
  2556  		}
  2557  	}
  2558  	Errorf("cannot find shared library: %s", shlib)
  2559  	return ""
  2560  }
  2561  
  2562  func ldshlibsyms(ctxt *Link, shlib string) {
  2563  	var libpath string
  2564  	if filepath.IsAbs(shlib) {
  2565  		libpath = shlib
  2566  		shlib = filepath.Base(shlib)
  2567  	} else {
  2568  		libpath = findshlib(ctxt, shlib)
  2569  		if libpath == "" {
  2570  			return
  2571  		}
  2572  	}
  2573  	for _, processedlib := range ctxt.Shlibs {
  2574  		if processedlib.Path == libpath {
  2575  			return
  2576  		}
  2577  	}
  2578  	if ctxt.Debugvlog > 1 {
  2579  		ctxt.Logf("ldshlibsyms: found library with name %s at %s\n", shlib, libpath)
  2580  	}
  2581  
  2582  	f, err := elf.Open(libpath)
  2583  	if err != nil {
  2584  		Errorf("cannot open shared library: %s", libpath)
  2585  		return
  2586  	}
  2587  	// Keep the file open as decodetypeGcprog needs to read from it.
  2588  	// TODO: fix. Maybe mmap the file.
  2589  	//defer f.Close()
  2590  
  2591  	hash, err := readnote(f, ELF_NOTE_GO_NAME, ELF_NOTE_GOABIHASH_TAG)
  2592  	if err != nil {
  2593  		Errorf("cannot read ABI hash from shared library %s: %v", libpath, err)
  2594  		return
  2595  	}
  2596  
  2597  	depsbytes, err := readnote(f, ELF_NOTE_GO_NAME, ELF_NOTE_GODEPS_TAG)
  2598  	if err != nil {
  2599  		Errorf("cannot read dep list from shared library %s: %v", libpath, err)
  2600  		return
  2601  	}
  2602  	var deps []string
  2603  	for _, dep := range strings.Split(string(depsbytes), "\n") {
  2604  		if dep == "" {
  2605  			continue
  2606  		}
  2607  		if !filepath.IsAbs(dep) {
  2608  			// If the dep can be interpreted as a path relative to the shlib
  2609  			// in which it was found, do that. Otherwise, we will leave it
  2610  			// to be resolved by libdir lookup.
  2611  			abs := filepath.Join(filepath.Dir(libpath), dep)
  2612  			if _, err := os.Stat(abs); err == nil {
  2613  				dep = abs
  2614  			}
  2615  		}
  2616  		deps = append(deps, dep)
  2617  	}
  2618  
  2619  	syms, err := f.DynamicSymbols()
  2620  	if err != nil {
  2621  		Errorf("cannot read symbols from shared library: %s", libpath)
  2622  		return
  2623  	}
  2624  
  2625  	for _, elfsym := range syms {
  2626  		if elf.ST_TYPE(elfsym.Info) == elf.STT_NOTYPE || elf.ST_TYPE(elfsym.Info) == elf.STT_SECTION {
  2627  			continue
  2628  		}
  2629  
  2630  		// Symbols whose names start with "type:" are compiler generated,
  2631  		// so make functions with that prefix internal.
  2632  		ver := 0
  2633  		symname := elfsym.Name // (unmangled) symbol name
  2634  		if elf.ST_TYPE(elfsym.Info) == elf.STT_FUNC && strings.HasPrefix(elfsym.Name, "type:") {
  2635  			ver = abiInternalVer
  2636  		} else if buildcfg.Experiment.RegabiWrappers && elf.ST_TYPE(elfsym.Info) == elf.STT_FUNC {
  2637  			// Demangle the ABI name. Keep in sync with symtab.go:mangleABIName.
  2638  			if strings.HasSuffix(elfsym.Name, ".abiinternal") {
  2639  				ver = sym.SymVerABIInternal
  2640  				symname = strings.TrimSuffix(elfsym.Name, ".abiinternal")
  2641  			} else if strings.HasSuffix(elfsym.Name, ".abi0") {
  2642  				ver = 0
  2643  				symname = strings.TrimSuffix(elfsym.Name, ".abi0")
  2644  			}
  2645  		}
  2646  
  2647  		l := ctxt.loader
  2648  		s := l.LookupOrCreateSym(symname, ver)
  2649  
  2650  		// Because loadlib above loads all .a files before loading
  2651  		// any shared libraries, any non-dynimport symbols we find
  2652  		// that duplicate symbols already loaded should be ignored
  2653  		// (the symbols from the .a files "win").
  2654  		if l.SymType(s) != 0 && l.SymType(s) != sym.SDYNIMPORT {
  2655  			continue
  2656  		}
  2657  		su := l.MakeSymbolUpdater(s)
  2658  		su.SetType(sym.SDYNIMPORT)
  2659  		l.SetSymElfType(s, elf.ST_TYPE(elfsym.Info))
  2660  		su.SetSize(int64(elfsym.Size))
  2661  		if elfsym.Section != elf.SHN_UNDEF {
  2662  			// Set .File for the library that actually defines the symbol.
  2663  			l.SetSymPkg(s, libpath)
  2664  
  2665  			// The decodetype_* functions in decodetype.go need access to
  2666  			// the type data.
  2667  			sname := l.SymName(s)
  2668  			if strings.HasPrefix(sname, "type:") && !strings.HasPrefix(sname, "type:.") {
  2669  				su.SetData(readelfsymboldata(ctxt, f, &elfsym))
  2670  			}
  2671  		}
  2672  
  2673  		if symname != elfsym.Name {
  2674  			l.SetSymExtname(s, elfsym.Name)
  2675  		}
  2676  	}
  2677  	ctxt.Shlibs = append(ctxt.Shlibs, Shlib{Path: libpath, Hash: hash, Deps: deps, File: f})
  2678  }
  2679  
  2680  func addsection(ldr *loader.Loader, arch *sys.Arch, seg *sym.Segment, name string, rwx int) *sym.Section {
  2681  	sect := ldr.NewSection()
  2682  	sect.Rwx = uint8(rwx)
  2683  	sect.Name = name
  2684  	sect.Seg = seg
  2685  	sect.Align = int32(arch.PtrSize) // everything is at least pointer-aligned
  2686  	seg.Sections = append(seg.Sections, sect)
  2687  	return sect
  2688  }
  2689  
  2690  func usage() {
  2691  	fmt.Fprintf(os.Stderr, "usage: link [options] main.o\n")
  2692  	objabi.Flagprint(os.Stderr)
  2693  	Exit(2)
  2694  }
  2695  
  2696  type SymbolType int8 // TODO: after genasmsym is gone, maybe rename to plan9typeChar or something
  2697  
  2698  const (
  2699  	// see also https://9p.io/magic/man2html/1/nm
  2700  	TextSym      SymbolType = 'T'
  2701  	DataSym      SymbolType = 'D'
  2702  	BSSSym       SymbolType = 'B'
  2703  	UndefinedSym SymbolType = 'U'
  2704  	TLSSym       SymbolType = 't'
  2705  	FrameSym     SymbolType = 'm'
  2706  	ParamSym     SymbolType = 'p'
  2707  	AutoSym      SymbolType = 'a'
  2708  
  2709  	// Deleted auto (not a real sym, just placeholder for type)
  2710  	DeletedAutoSym = 'x'
  2711  )
  2712  
  2713  // defineInternal defines a symbol used internally by the go runtime.
  2714  func (ctxt *Link) defineInternal(p string, t sym.SymKind) loader.Sym {
  2715  	s := ctxt.loader.CreateSymForUpdate(p, 0)
  2716  	s.SetType(t)
  2717  	s.SetSpecial(true)
  2718  	s.SetLocal(true)
  2719  	return s.Sym()
  2720  }
  2721  
  2722  func (ctxt *Link) xdefine(p string, t sym.SymKind, v int64) loader.Sym {
  2723  	s := ctxt.defineInternal(p, t)
  2724  	ctxt.loader.SetSymValue(s, v)
  2725  	return s
  2726  }
  2727  
  2728  func datoff(ldr *loader.Loader, s loader.Sym, addr int64) int64 {
  2729  	if uint64(addr) >= Segdata.Vaddr {
  2730  		return int64(uint64(addr) - Segdata.Vaddr + Segdata.Fileoff)
  2731  	}
  2732  	if uint64(addr) >= Segtext.Vaddr {
  2733  		return int64(uint64(addr) - Segtext.Vaddr + Segtext.Fileoff)
  2734  	}
  2735  	ldr.Errorf(s, "invalid datoff %#x", addr)
  2736  	return 0
  2737  }
  2738  
  2739  func Entryvalue(ctxt *Link) int64 {
  2740  	a := *flagEntrySymbol
  2741  	if a[0] >= '0' && a[0] <= '9' {
  2742  		return atolwhex(a)
  2743  	}
  2744  	ldr := ctxt.loader
  2745  	s := ldr.Lookup(a, 0)
  2746  	if s == 0 {
  2747  		Errorf("missing entry symbol %q", a)
  2748  		return 0
  2749  	}
  2750  	st := ldr.SymType(s)
  2751  	if st == 0 {
  2752  		return *FlagTextAddr
  2753  	}
  2754  	if !ctxt.IsAIX() && !st.IsText() {
  2755  		ldr.Errorf(s, "entry not text")
  2756  	}
  2757  	return ldr.SymValue(s)
  2758  }
  2759  
  2760  func (ctxt *Link) callgraph() {
  2761  	if !*FlagC {
  2762  		return
  2763  	}
  2764  
  2765  	ldr := ctxt.loader
  2766  	for _, s := range ctxt.Textp {
  2767  		relocs := ldr.Relocs(s)
  2768  		for i := 0; i < relocs.Count(); i++ {
  2769  			r := relocs.At(i)
  2770  			rs := r.Sym()
  2771  			if rs == 0 {
  2772  				continue
  2773  			}
  2774  			if r.Type().IsDirectCall() && ldr.SymType(rs).IsText() {
  2775  				ctxt.Logf("%s calls %s\n", ldr.SymName(s), ldr.SymName(rs))
  2776  			}
  2777  		}
  2778  	}
  2779  }
  2780  
  2781  func Rnd(v int64, r int64) int64 {
  2782  	if r <= 0 {
  2783  		return v
  2784  	}
  2785  	v += r - 1
  2786  	c := v % r
  2787  	if c < 0 {
  2788  		c += r
  2789  	}
  2790  	v -= c
  2791  	return v
  2792  }
  2793  
  2794  func bgetc(r *bio.Reader) int {
  2795  	c, err := r.ReadByte()
  2796  	if err != nil {
  2797  		if err != io.EOF {
  2798  			log.Fatalf("reading input: %v", err)
  2799  		}
  2800  		return -1
  2801  	}
  2802  	return int(c)
  2803  }
  2804  
  2805  type markKind uint8 // for postorder traversal
  2806  const (
  2807  	_ markKind = iota
  2808  	visiting
  2809  	visited
  2810  )
  2811  
  2812  func postorder(libs []*sym.Library) []*sym.Library {
  2813  	order := make([]*sym.Library, 0, len(libs)) // hold the result
  2814  	mark := make(map[*sym.Library]markKind, len(libs))
  2815  	for _, lib := range libs {
  2816  		dfs(lib, mark, &order)
  2817  	}
  2818  	return order
  2819  }
  2820  
  2821  func dfs(lib *sym.Library, mark map[*sym.Library]markKind, order *[]*sym.Library) {
  2822  	if mark[lib] == visited {
  2823  		return
  2824  	}
  2825  	if mark[lib] == visiting {
  2826  		panic("found import cycle while visiting " + lib.Pkg)
  2827  	}
  2828  	mark[lib] = visiting
  2829  	for _, i := range lib.Imports {
  2830  		dfs(i, mark, order)
  2831  	}
  2832  	mark[lib] = visited
  2833  	*order = append(*order, lib)
  2834  }
  2835  
  2836  func ElfSymForReloc(ctxt *Link, s loader.Sym) int32 {
  2837  	// If putelfsym created a local version of this symbol, use that in all
  2838  	// relocations.
  2839  	les := ctxt.loader.SymLocalElfSym(s)
  2840  	if les != 0 {
  2841  		return les
  2842  	} else {
  2843  		return ctxt.loader.SymElfSym(s)
  2844  	}
  2845  }
  2846  
  2847  func AddGotSym(target *Target, ldr *loader.Loader, syms *ArchSyms, s loader.Sym, elfRelocTyp uint32) {
  2848  	if ldr.SymGot(s) >= 0 {
  2849  		return
  2850  	}
  2851  
  2852  	Adddynsym(ldr, target, syms, s)
  2853  	got := ldr.MakeSymbolUpdater(syms.GOT)
  2854  	ldr.SetGot(s, int32(got.Size()))
  2855  	got.AddUint(target.Arch, 0)
  2856  
  2857  	if target.IsElf() {
  2858  		if target.Arch.PtrSize == 8 {
  2859  			rela := ldr.MakeSymbolUpdater(syms.Rela)
  2860  			rela.AddAddrPlus(target.Arch, got.Sym(), int64(ldr.SymGot(s)))
  2861  			rela.AddUint64(target.Arch, elf.R_INFO(uint32(ldr.SymDynid(s)), elfRelocTyp))
  2862  			rela.AddUint64(target.Arch, 0)
  2863  		} else {
  2864  			rel := ldr.MakeSymbolUpdater(syms.Rel)
  2865  			rel.AddAddrPlus(target.Arch, got.Sym(), int64(ldr.SymGot(s)))
  2866  			rel.AddUint32(target.Arch, elf.R_INFO32(uint32(ldr.SymDynid(s)), elfRelocTyp))
  2867  		}
  2868  	} else if target.IsDarwin() {
  2869  		leg := ldr.MakeSymbolUpdater(syms.LinkEditGOT)
  2870  		leg.AddUint32(target.Arch, uint32(ldr.SymDynid(s)))
  2871  		if target.IsPIE() && target.IsInternal() {
  2872  			// Mach-O relocations are a royal pain to lay out.
  2873  			// They use a compact stateful bytecode representation.
  2874  			// Here we record what are needed and encode them later.
  2875  			MachoAddBind(int64(ldr.SymGot(s)), s)
  2876  		}
  2877  	} else {
  2878  		ldr.Errorf(s, "addgotsym: unsupported binary format")
  2879  	}
  2880  }
  2881  
  2882  var hostobjcounter int
  2883  
  2884  // captureHostObj writes out the content of a host object (pulled from
  2885  // an archive or loaded from a *.o file directly) to a directory
  2886  // specified via the linker's "-capturehostobjs" debugging flag. This
  2887  // is intended to make it easier for a developer to inspect the actual
  2888  // object feeding into "CGO internal" link step.
  2889  func captureHostObj(h *Hostobj) {
  2890  	// Form paths for info file and obj file.
  2891  	ofile := fmt.Sprintf("captured-obj-%d.o", hostobjcounter)
  2892  	ifile := fmt.Sprintf("captured-obj-%d.txt", hostobjcounter)
  2893  	hostobjcounter++
  2894  	opath := filepath.Join(*flagCaptureHostObjs, ofile)
  2895  	ipath := filepath.Join(*flagCaptureHostObjs, ifile)
  2896  
  2897  	// Write the info file.
  2898  	info := fmt.Sprintf("pkg: %s\npn: %s\nfile: %s\noff: %d\nlen: %d\n",
  2899  		h.pkg, h.pn, h.file, h.off, h.length)
  2900  	if err := os.WriteFile(ipath, []byte(info), 0666); err != nil {
  2901  		log.Fatalf("error writing captured host obj info %s: %v", ipath, err)
  2902  	}
  2903  
  2904  	readObjData := func() []byte {
  2905  		inf, err := os.Open(h.file)
  2906  		if err != nil {
  2907  			log.Fatalf("capturing host obj: open failed on %s: %v", h.pn, err)
  2908  		}
  2909  		defer inf.Close()
  2910  		res := make([]byte, h.length)
  2911  		if n, err := inf.ReadAt(res, h.off); err != nil || n != int(h.length) {
  2912  			log.Fatalf("capturing host obj: readat failed on %s: %v", h.pn, err)
  2913  		}
  2914  		return res
  2915  	}
  2916  
  2917  	// Write the object file.
  2918  	if err := os.WriteFile(opath, readObjData(), 0666); err != nil {
  2919  		log.Fatalf("error writing captured host object %s: %v", opath, err)
  2920  	}
  2921  
  2922  	fmt.Fprintf(os.Stderr, "link: info: captured host object %s to %s\n",
  2923  		h.file, opath)
  2924  }
  2925  
  2926  // findExtLinkTool invokes the external linker CC with --print-prog-name
  2927  // passing the name of the tool we're interested in, such as "strip",
  2928  // "ar", or "dsymutil", and returns the path passed back from the command.
  2929  func (ctxt *Link) findExtLinkTool(toolname string) string {
  2930  	var cc []string
  2931  	cc = append(cc, ctxt.extld()...)
  2932  	cc = append(cc, hostlinkArchArgs(ctxt.Arch)...)
  2933  	cc = append(cc, "--print-prog-name", toolname)
  2934  	out, err := exec.Command(cc[0], cc[1:]...).CombinedOutput()
  2935  	if err != nil {
  2936  		Exitf("%s: finding %s failed: %v\n%s", os.Args[0], toolname, err, out)
  2937  	}
  2938  	cmdpath := strings.TrimRight(string(out), "\r\n")
  2939  	return cmdpath
  2940  }
  2941  

View as plain text