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

View as plain text