github.com/bir3/gocompiler@v0.3.205/src/cmd/link/internal/ld/lib.go (about)

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