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

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

View as plain text