...
Run Format

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

Documentation: cmd/link/internal/ld

     1  // Inferno utils/8l/asm.c
     2  // https://bitbucket.org/inferno-os/inferno-os/src/default/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  	"bufio"
    35  	"bytes"
    36  	"cmd/internal/bio"
    37  	"cmd/internal/objabi"
    38  	"cmd/internal/sys"
    39  	"cmd/link/internal/loadelf"
    40  	"cmd/link/internal/loadmacho"
    41  	"cmd/link/internal/loadpe"
    42  	"cmd/link/internal/objfile"
    43  	"cmd/link/internal/sym"
    44  	"crypto/sha1"
    45  	"debug/elf"
    46  	"encoding/base64"
    47  	"encoding/binary"
    48  	"encoding/hex"
    49  	"fmt"
    50  	"io"
    51  	"io/ioutil"
    52  	"log"
    53  	"os"
    54  	"os/exec"
    55  	"path/filepath"
    56  	"runtime"
    57  	"strings"
    58  	"sync"
    59  )
    60  
    61  // Data layout and relocation.
    62  
    63  // Derived from Inferno utils/6l/l.h
    64  // https://bitbucket.org/inferno-os/inferno-os/src/default/utils/6l/l.h
    65  //
    66  //	Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
    67  //	Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
    68  //	Portions Copyright © 1997-1999 Vita Nuova Limited
    69  //	Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
    70  //	Portions Copyright © 2004,2006 Bruce Ellis
    71  //	Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
    72  //	Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
    73  //	Portions Copyright © 2009 The Go Authors. All rights reserved.
    74  //
    75  // Permission is hereby granted, free of charge, to any person obtaining a copy
    76  // of this software and associated documentation files (the "Software"), to deal
    77  // in the Software without restriction, including without limitation the rights
    78  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    79  // copies of the Software, and to permit persons to whom the Software is
    80  // furnished to do so, subject to the following conditions:
    81  //
    82  // The above copyright notice and this permission notice shall be included in
    83  // all copies or substantial portions of the Software.
    84  //
    85  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    86  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    87  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
    88  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    89  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    90  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    91  // THE SOFTWARE.
    92  
    93  type Arch struct {
    94  	Funcalign        int
    95  	Maxalign         int
    96  	Minalign         int
    97  	Dwarfregsp       int
    98  	Dwarfreglr       int
    99  	Linuxdynld       string
   100  	Freebsddynld     string
   101  	Netbsddynld      string
   102  	Openbsddynld     string
   103  	Dragonflydynld   string
   104  	Solarisdynld     string
   105  	Adddynrel        func(*Link, *sym.Symbol, *sym.Reloc) bool
   106  	Archinit         func(*Link)
   107  	Archreloc        func(*Link, *sym.Reloc, *sym.Symbol, *int64) bool
   108  	Archrelocvariant func(*Link, *sym.Reloc, *sym.Symbol, int64) int64
   109  	Trampoline       func(*Link, *sym.Reloc, *sym.Symbol)
   110  	Asmb             func(*Link)
   111  	Elfreloc1        func(*Link, *sym.Reloc, int64) bool
   112  	Elfsetupplt      func(*Link)
   113  	Gentext          func(*Link)
   114  	Machoreloc1      func(*sys.Arch, *OutBuf, *sym.Symbol, *sym.Reloc, int64) bool
   115  	PEreloc1         func(*sys.Arch, *OutBuf, *sym.Symbol, *sym.Reloc, int64) bool
   116  
   117  	// TLSIEtoLE converts a TLS Initial Executable relocation to
   118  	// a TLS Local Executable relocation.
   119  	//
   120  	// This is possible when a TLS IE relocation refers to a local
   121  	// symbol in an executable, which is typical when internally
   122  	// linking PIE binaries.
   123  	TLSIEtoLE func(s *sym.Symbol, off, size int)
   124  
   125  	// optional override for assignAddress
   126  	AssignAddress func(ctxt *Link, sect *sym.Section, n int, s *sym.Symbol, va uint64, isTramp bool) (*sym.Section, int, uint64)
   127  }
   128  
   129  var (
   130  	thearch Arch
   131  	Lcsize  int32
   132  	rpath   Rpath
   133  	Spsize  int32
   134  	Symsize int32
   135  )
   136  
   137  const (
   138  	MINFUNC = 16 // minimum size for a function
   139  )
   140  
   141  // DynlinkingGo returns whether we are producing Go code that can live
   142  // in separate shared libraries linked together at runtime.
   143  func (ctxt *Link) DynlinkingGo() bool {
   144  	if !ctxt.Loaded {
   145  		panic("DynlinkingGo called before all symbols loaded")
   146  	}
   147  	return ctxt.BuildMode == BuildModeShared || ctxt.linkShared || ctxt.BuildMode == BuildModePlugin || ctxt.CanUsePlugins()
   148  }
   149  
   150  // CanUsePlugins returns whether a plugins can be used
   151  func (ctxt *Link) CanUsePlugins() bool {
   152  	return ctxt.Syms.ROLookup("plugin.Open", 0) != nil
   153  }
   154  
   155  // UseRelro returns whether to make use of "read only relocations" aka
   156  // relro.
   157  func (ctxt *Link) UseRelro() bool {
   158  	switch ctxt.BuildMode {
   159  	case BuildModeCArchive, BuildModeCShared, BuildModeShared, BuildModePIE, BuildModePlugin:
   160  		return ctxt.IsELF
   161  	default:
   162  		return ctxt.linkShared
   163  	}
   164  }
   165  
   166  var (
   167  	dynexp          []*sym.Symbol
   168  	dynlib          []string
   169  	ldflag          []string
   170  	havedynamic     int
   171  	Funcalign       int
   172  	iscgo           bool
   173  	elfglobalsymndx int
   174  	interpreter     string
   175  
   176  	debug_s bool // backup old value of debug['s']
   177  	HEADR   int32
   178  
   179  	nerrors  int
   180  	liveness int64
   181  )
   182  
   183  var (
   184  	Segtext      sym.Segment
   185  	Segrodata    sym.Segment
   186  	Segrelrodata sym.Segment
   187  	Segdata      sym.Segment
   188  	Segdwarf     sym.Segment
   189  )
   190  
   191  const pkgdef = "__.PKGDEF"
   192  
   193  var (
   194  	// Set if we see an object compiled by the host compiler that is not
   195  	// from a package that is known to support internal linking mode.
   196  	externalobj = false
   197  	theline     string
   198  )
   199  
   200  func Lflag(ctxt *Link, arg string) {
   201  	ctxt.Libdir = append(ctxt.Libdir, arg)
   202  }
   203  
   204  /*
   205   * Unix doesn't like it when we write to a running (or, sometimes,
   206   * recently run) binary, so remove the output file before writing it.
   207   * On Windows 7, remove() can force a subsequent create() to fail.
   208   * S_ISREG() does not exist on Plan 9.
   209   */
   210  func mayberemoveoutfile() {
   211  	if fi, err := os.Lstat(*flagOutfile); err == nil && !fi.Mode().IsRegular() {
   212  		return
   213  	}
   214  	os.Remove(*flagOutfile)
   215  }
   216  
   217  func libinit(ctxt *Link) {
   218  	Funcalign = thearch.Funcalign
   219  
   220  	// add goroot to the end of the libdir list.
   221  	suffix := ""
   222  
   223  	suffixsep := ""
   224  	if *flagInstallSuffix != "" {
   225  		suffixsep = "_"
   226  		suffix = *flagInstallSuffix
   227  	} else if *flagRace {
   228  		suffixsep = "_"
   229  		suffix = "race"
   230  	} else if *flagMsan {
   231  		suffixsep = "_"
   232  		suffix = "msan"
   233  	}
   234  
   235  	Lflag(ctxt, filepath.Join(objabi.GOROOT, "pkg", fmt.Sprintf("%s_%s%s%s", objabi.GOOS, objabi.GOARCH, suffixsep, suffix)))
   236  
   237  	mayberemoveoutfile()
   238  	f, err := os.OpenFile(*flagOutfile, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0775)
   239  	if err != nil {
   240  		Exitf("cannot create %s: %v", *flagOutfile, err)
   241  	}
   242  
   243  	ctxt.Out.w = bufio.NewWriter(f)
   244  	ctxt.Out.f = f
   245  
   246  	if *flagEntrySymbol == "" {
   247  		switch ctxt.BuildMode {
   248  		case BuildModeCShared, BuildModeCArchive:
   249  			*flagEntrySymbol = fmt.Sprintf("_rt0_%s_%s_lib", objabi.GOARCH, objabi.GOOS)
   250  		case BuildModeExe, BuildModePIE:
   251  			*flagEntrySymbol = fmt.Sprintf("_rt0_%s_%s", objabi.GOARCH, objabi.GOOS)
   252  		case BuildModeShared, BuildModePlugin:
   253  			// No *flagEntrySymbol for -buildmode=shared and plugin
   254  		default:
   255  			Errorf(nil, "unknown *flagEntrySymbol for buildmode %v", ctxt.BuildMode)
   256  		}
   257  	}
   258  }
   259  
   260  func errorexit() {
   261  	if nerrors != 0 {
   262  		Exit(2)
   263  	}
   264  	Exit(0)
   265  }
   266  
   267  func loadinternal(ctxt *Link, name string) *sym.Library {
   268  	if ctxt.linkShared && ctxt.PackageShlib != nil {
   269  		if shlib := ctxt.PackageShlib[name]; shlib != "" {
   270  			return addlibpath(ctxt, "internal", "internal", "", name, shlib)
   271  		}
   272  	}
   273  	if ctxt.PackageFile != nil {
   274  		if pname := ctxt.PackageFile[name]; pname != "" {
   275  			return addlibpath(ctxt, "internal", "internal", pname, name, "")
   276  		}
   277  		ctxt.Logf("loadinternal: cannot find %s\n", name)
   278  		return nil
   279  	}
   280  
   281  	for _, libdir := range ctxt.Libdir {
   282  		if ctxt.linkShared {
   283  			shlibname := filepath.Join(libdir, name+".shlibname")
   284  			if ctxt.Debugvlog != 0 {
   285  				ctxt.Logf("searching for %s.a in %s\n", name, shlibname)
   286  			}
   287  			if _, err := os.Stat(shlibname); err == nil {
   288  				return addlibpath(ctxt, "internal", "internal", "", name, shlibname)
   289  			}
   290  		}
   291  		pname := filepath.Join(libdir, name+".a")
   292  		if ctxt.Debugvlog != 0 {
   293  			ctxt.Logf("searching for %s.a in %s\n", name, pname)
   294  		}
   295  		if _, err := os.Stat(pname); err == nil {
   296  			return addlibpath(ctxt, "internal", "internal", pname, name, "")
   297  		}
   298  	}
   299  
   300  	ctxt.Logf("warning: unable to find %s.a\n", name)
   301  	return nil
   302  }
   303  
   304  // findLibPathCmd uses cmd command to find gcc library libname.
   305  // It returns library full path if found, or "none" if not found.
   306  func (ctxt *Link) findLibPathCmd(cmd, libname string) string {
   307  	if *flagExtld == "" {
   308  		*flagExtld = "gcc"
   309  	}
   310  	args := hostlinkArchArgs(ctxt.Arch)
   311  	args = append(args, cmd)
   312  	if ctxt.Debugvlog != 0 {
   313  		ctxt.Logf("%s %v\n", *flagExtld, args)
   314  	}
   315  	out, err := exec.Command(*flagExtld, args...).Output()
   316  	if err != nil {
   317  		if ctxt.Debugvlog != 0 {
   318  			ctxt.Logf("not using a %s file because compiler failed\n%v\n%s\n", libname, err, out)
   319  		}
   320  		return "none"
   321  	}
   322  	return strings.TrimSpace(string(out))
   323  }
   324  
   325  // findLibPath searches for library libname.
   326  // It returns library full path if found, or "none" if not found.
   327  func (ctxt *Link) findLibPath(libname string) string {
   328  	return ctxt.findLibPathCmd("--print-file-name="+libname, libname)
   329  }
   330  
   331  func (ctxt *Link) loadlib() {
   332  	switch ctxt.BuildMode {
   333  	case BuildModeCShared, BuildModePlugin:
   334  		s := ctxt.Syms.Lookup("runtime.islibrary", 0)
   335  		s.Attr |= sym.AttrDuplicateOK
   336  		s.AddUint8(1)
   337  	case BuildModeCArchive:
   338  		s := ctxt.Syms.Lookup("runtime.isarchive", 0)
   339  		s.Attr |= sym.AttrDuplicateOK
   340  		s.AddUint8(1)
   341  	}
   342  
   343  	loadinternal(ctxt, "runtime")
   344  	if ctxt.Arch.Family == sys.ARM {
   345  		loadinternal(ctxt, "math")
   346  	}
   347  	if *flagRace {
   348  		loadinternal(ctxt, "runtime/race")
   349  	}
   350  	if *flagMsan {
   351  		loadinternal(ctxt, "runtime/msan")
   352  	}
   353  
   354  	// ctxt.Library grows during the loop, so not a range loop.
   355  	for i := 0; i < len(ctxt.Library); i++ {
   356  		lib := ctxt.Library[i]
   357  		if lib.Shlib == "" {
   358  			if ctxt.Debugvlog > 1 {
   359  				ctxt.Logf("%5.2f autolib: %s (from %s)\n", Cputime(), lib.File, lib.Objref)
   360  			}
   361  			loadobjfile(ctxt, lib)
   362  		}
   363  	}
   364  
   365  	for _, lib := range ctxt.Library {
   366  		if lib.Shlib != "" {
   367  			if ctxt.Debugvlog > 1 {
   368  				ctxt.Logf("%5.2f autolib: %s (from %s)\n", Cputime(), lib.Shlib, lib.Objref)
   369  			}
   370  			ldshlibsyms(ctxt, lib.Shlib)
   371  		}
   372  	}
   373  
   374  	iscgo = ctxt.Syms.ROLookup("x_cgo_init", 0) != nil
   375  
   376  	// We now have enough information to determine the link mode.
   377  	determineLinkMode(ctxt)
   378  
   379  	// Recalculate pe parameters now that we have ctxt.LinkMode set.
   380  	if ctxt.HeadType == objabi.Hwindows {
   381  		Peinit(ctxt)
   382  	}
   383  
   384  	if ctxt.HeadType == objabi.Hdarwin && ctxt.LinkMode == LinkExternal {
   385  		*FlagTextAddr = 0
   386  	}
   387  
   388  	if ctxt.LinkMode == LinkExternal && ctxt.Arch.Family == sys.PPC64 {
   389  		toc := ctxt.Syms.Lookup(".TOC.", 0)
   390  		toc.Type = sym.SDYNIMPORT
   391  	}
   392  
   393  	if ctxt.LinkMode == LinkExternal && !iscgo && ctxt.LibraryByPkg["runtime/cgo"] == nil && !(objabi.GOOS == "darwin" && (ctxt.Arch.Family == sys.AMD64 || ctxt.Arch.Family == sys.I386)) {
   394  		// This indicates a user requested -linkmode=external.
   395  		// The startup code uses an import of runtime/cgo to decide
   396  		// whether to initialize the TLS.  So give it one. This could
   397  		// be handled differently but it's an unusual case.
   398  		if lib := loadinternal(ctxt, "runtime/cgo"); lib != nil {
   399  			if lib.Shlib != "" {
   400  				ldshlibsyms(ctxt, lib.Shlib)
   401  			} else {
   402  				if ctxt.BuildMode == BuildModeShared || ctxt.linkShared {
   403  					Exitf("cannot implicitly include runtime/cgo in a shared library")
   404  				}
   405  				loadobjfile(ctxt, lib)
   406  			}
   407  		}
   408  	}
   409  
   410  	if ctxt.LinkMode == LinkInternal {
   411  		// Drop all the cgo_import_static declarations.
   412  		// Turns out we won't be needing them.
   413  		for _, s := range ctxt.Syms.Allsym {
   414  			if s.Type == sym.SHOSTOBJ {
   415  				// If a symbol was marked both
   416  				// cgo_import_static and cgo_import_dynamic,
   417  				// then we want to make it cgo_import_dynamic
   418  				// now.
   419  				if s.Extname != "" && s.Dynimplib() != "" && !s.Attr.CgoExport() {
   420  					s.Type = sym.SDYNIMPORT
   421  				} else {
   422  					s.Type = 0
   423  				}
   424  			}
   425  		}
   426  	}
   427  
   428  	tlsg := ctxt.Syms.Lookup("runtime.tlsg", 0)
   429  
   430  	// runtime.tlsg is used for external linking on platforms that do not define
   431  	// a variable to hold g in assembly (currently only intel).
   432  	if tlsg.Type == 0 {
   433  		tlsg.Type = sym.STLSBSS
   434  		tlsg.Size = int64(ctxt.Arch.PtrSize)
   435  	} else if tlsg.Type != sym.SDYNIMPORT {
   436  		Errorf(nil, "runtime declared tlsg variable %v", tlsg.Type)
   437  	}
   438  	tlsg.Attr |= sym.AttrReachable
   439  	ctxt.Tlsg = tlsg
   440  
   441  	var moduledata *sym.Symbol
   442  	if ctxt.BuildMode == BuildModePlugin {
   443  		moduledata = ctxt.Syms.Lookup("local.pluginmoduledata", 0)
   444  		moduledata.Attr |= sym.AttrLocal
   445  	} else {
   446  		moduledata = ctxt.Syms.Lookup("runtime.firstmoduledata", 0)
   447  	}
   448  	if moduledata.Type != 0 && moduledata.Type != sym.SDYNIMPORT {
   449  		// If the module (toolchain-speak for "executable or shared
   450  		// library") we are linking contains the runtime package, it
   451  		// will define the runtime.firstmoduledata symbol and we
   452  		// truncate it back to 0 bytes so we can define its entire
   453  		// contents in symtab.go:symtab().
   454  		moduledata.Size = 0
   455  
   456  		// In addition, on ARM, the runtime depends on the linker
   457  		// recording the value of GOARM.
   458  		if ctxt.Arch.Family == sys.ARM {
   459  			s := ctxt.Syms.Lookup("runtime.goarm", 0)
   460  			s.Type = sym.SDATA
   461  			s.Size = 0
   462  			s.AddUint8(uint8(objabi.GOARM))
   463  		}
   464  
   465  		if objabi.Framepointer_enabled(objabi.GOOS, objabi.GOARCH) {
   466  			s := ctxt.Syms.Lookup("runtime.framepointer_enabled", 0)
   467  			s.Type = sym.SDATA
   468  			s.Size = 0
   469  			s.AddUint8(1)
   470  		}
   471  	} else {
   472  		// If OTOH the module does not contain the runtime package,
   473  		// create a local symbol for the moduledata.
   474  		moduledata = ctxt.Syms.Lookup("local.moduledata", 0)
   475  		moduledata.Attr |= sym.AttrLocal
   476  	}
   477  	// In all cases way we mark the moduledata as noptrdata to hide it from
   478  	// the GC.
   479  	moduledata.Type = sym.SNOPTRDATA
   480  	moduledata.Attr |= sym.AttrReachable
   481  	ctxt.Moduledata = moduledata
   482  
   483  	// Now that we know the link mode, trim the dynexp list.
   484  	x := sym.AttrCgoExportDynamic
   485  
   486  	if ctxt.LinkMode == LinkExternal {
   487  		x = sym.AttrCgoExportStatic
   488  	}
   489  	w := 0
   490  	for i := range dynexp {
   491  		if dynexp[i].Attr&x != 0 {
   492  			dynexp[w] = dynexp[i]
   493  			w++
   494  		}
   495  	}
   496  	dynexp = dynexp[:w]
   497  
   498  	// In internal link mode, read the host object files.
   499  	if ctxt.LinkMode == LinkInternal {
   500  		hostobjs(ctxt)
   501  
   502  		// If we have any undefined symbols in external
   503  		// objects, try to read them from the libgcc file.
   504  		any := false
   505  		for _, s := range ctxt.Syms.Allsym {
   506  			for _, r := range s.R {
   507  				if r.Sym != nil && r.Sym.Type == sym.SXREF && r.Sym.Name != ".got" {
   508  					any = true
   509  					break
   510  				}
   511  			}
   512  		}
   513  		if any {
   514  			if *flagLibGCC == "" {
   515  				*flagLibGCC = ctxt.findLibPathCmd("--print-libgcc-file-name", "libgcc")
   516  			}
   517  			if *flagLibGCC != "none" {
   518  				hostArchive(ctxt, *flagLibGCC)
   519  			}
   520  			if ctxt.HeadType == objabi.Hwindows {
   521  				if p := ctxt.findLibPath("libmingwex.a"); p != "none" {
   522  					hostArchive(ctxt, p)
   523  				}
   524  				if p := ctxt.findLibPath("libmingw32.a"); p != "none" {
   525  					hostArchive(ctxt, p)
   526  				}
   527  				// TODO: maybe do something similar to peimporteddlls to collect all lib names
   528  				// and try link them all to final exe just like libmingwex.a and libmingw32.a:
   529  				/*
   530  					for:
   531  					#cgo windows LDFLAGS: -lmsvcrt -lm
   532  					import:
   533  					libmsvcrt.a libm.a
   534  				*/
   535  			}
   536  		}
   537  	} else {
   538  		hostlinksetup(ctxt)
   539  	}
   540  
   541  	// We've loaded all the code now.
   542  	ctxt.Loaded = true
   543  
   544  	// If there are no dynamic libraries needed, gcc disables dynamic linking.
   545  	// Because of this, glibc's dynamic ELF loader occasionally (like in version 2.13)
   546  	// assumes that a dynamic binary always refers to at least one dynamic library.
   547  	// Rather than be a source of test cases for glibc, disable dynamic linking
   548  	// the same way that gcc would.
   549  	//
   550  	// Exception: on OS X, programs such as Shark only work with dynamic
   551  	// binaries, so leave it enabled on OS X (Mach-O) binaries.
   552  	// Also leave it enabled on Solaris which doesn't support
   553  	// statically linked binaries.
   554  	if ctxt.BuildMode == BuildModeExe {
   555  		if havedynamic == 0 && ctxt.HeadType != objabi.Hdarwin && ctxt.HeadType != objabi.Hsolaris {
   556  			*FlagD = true
   557  		}
   558  	}
   559  
   560  	// If type. symbols are visible in the symbol table, rename them
   561  	// using a SHA-1 prefix. This reduces binary size (the full
   562  	// string of a type symbol can be multiple kilobytes) and removes
   563  	// characters that upset external linkers.
   564  	//
   565  	// Keep the type.. prefix, which parts of the linker (like the
   566  	// DWARF generator) know means the symbol is not decodable.
   567  	//
   568  	// Leave type.runtime. symbols alone, because other parts of
   569  	// the linker manipulates them, and also symbols whose names
   570  	// would not be shortened by this process.
   571  	if typeSymbolMangling(ctxt) {
   572  		*FlagW = true // disable DWARF generation
   573  		for _, s := range ctxt.Syms.Allsym {
   574  			newName := typeSymbolMangle(s.Name)
   575  			if newName != s.Name {
   576  				ctxt.Syms.Rename(s.Name, newName, int(s.Version))
   577  			}
   578  		}
   579  	}
   580  
   581  	// If package versioning is required, generate a hash of the
   582  	// packages used in the link.
   583  	if ctxt.BuildMode == BuildModeShared || ctxt.BuildMode == BuildModePlugin || ctxt.CanUsePlugins() {
   584  		for _, lib := range ctxt.Library {
   585  			if lib.Shlib == "" {
   586  				genhash(ctxt, lib)
   587  			}
   588  		}
   589  	}
   590  
   591  	if ctxt.Arch == sys.Arch386 {
   592  		if (ctxt.BuildMode == BuildModeCArchive && ctxt.IsELF) || (ctxt.BuildMode == BuildModeCShared && ctxt.HeadType != objabi.Hwindows) || ctxt.BuildMode == BuildModePIE || ctxt.DynlinkingGo() {
   593  			got := ctxt.Syms.Lookup("_GLOBAL_OFFSET_TABLE_", 0)
   594  			got.Type = sym.SDYNIMPORT
   595  			got.Attr |= sym.AttrReachable
   596  		}
   597  	}
   598  
   599  	importcycles()
   600  
   601  	// put symbols into Textp
   602  	// do it in postorder so that packages are laid down in dependency order
   603  	// internal first, then everything else
   604  	ctxt.Library = postorder(ctxt.Library)
   605  	for _, doInternal := range [2]bool{true, false} {
   606  		for _, lib := range ctxt.Library {
   607  			if isRuntimeDepPkg(lib.Pkg) != doInternal {
   608  				continue
   609  			}
   610  			ctxt.Textp = append(ctxt.Textp, lib.Textp...)
   611  			for _, s := range lib.DupTextSyms {
   612  				if !s.Attr.OnList() {
   613  					ctxt.Textp = append(ctxt.Textp, s)
   614  					s.Attr |= sym.AttrOnList
   615  					// dupok symbols may be defined in multiple packages. its
   616  					// associated package is chosen sort of arbitrarily (the
   617  					// first containing package that the linker loads). canonicalize
   618  					// it here to the package with which it will be laid down
   619  					// in text.
   620  					s.File = objabi.PathToPrefix(lib.Pkg)
   621  				}
   622  			}
   623  		}
   624  	}
   625  
   626  	if len(ctxt.Shlibs) > 0 {
   627  		// We might have overwritten some functions above (this tends to happen for the
   628  		// autogenerated type equality/hashing functions) and we don't want to generated
   629  		// pcln table entries for these any more so remove them from Textp.
   630  		textp := make([]*sym.Symbol, 0, len(ctxt.Textp))
   631  		for _, s := range ctxt.Textp {
   632  			if s.Type != sym.SDYNIMPORT {
   633  				textp = append(textp, s)
   634  			}
   635  		}
   636  		ctxt.Textp = textp
   637  	}
   638  }
   639  
   640  // typeSymbolMangling reports whether the linker should shorten the
   641  // names of symbols that represent Go types.
   642  //
   643  // As the names of these symbols are derived from the string of
   644  // the type, they can run to many kilobytes long. So we shorten
   645  // them using a SHA-1 when the name appears in the final binary.
   646  //
   647  // These are the symbols that begin with the prefix 'type.' and
   648  // contain run-time type information used by the runtime and reflect
   649  // packages. All Go binaries contain these symbols, but only only
   650  // those programs loaded dynamically in multiple parts need these
   651  // symbols to have entries in the symbol table.
   652  func typeSymbolMangling(ctxt *Link) bool {
   653  	return ctxt.BuildMode == BuildModeShared || ctxt.linkShared || ctxt.BuildMode == BuildModePlugin || ctxt.Syms.ROLookup("plugin.Open", 0) != nil
   654  }
   655  
   656  // typeSymbolMangle mangles the given symbol name into something shorter.
   657  func typeSymbolMangle(name string) string {
   658  	if !strings.HasPrefix(name, "type.") {
   659  		return name
   660  	}
   661  	if strings.HasPrefix(name, "type.runtime.") {
   662  		return name
   663  	}
   664  	if len(name) <= 14 && !strings.Contains(name, "@") { // Issue 19529
   665  		return name
   666  	}
   667  	hash := sha1.Sum([]byte(name))
   668  	prefix := "type."
   669  	if name[5] == '.' {
   670  		prefix = "type.."
   671  	}
   672  	return prefix + base64.StdEncoding.EncodeToString(hash[:6])
   673  }
   674  
   675  /*
   676   * look for the next file in an archive.
   677   * adapted from libmach.
   678   */
   679  func nextar(bp *bio.Reader, off int64, a *ArHdr) int64 {
   680  	if off&1 != 0 {
   681  		off++
   682  	}
   683  	bp.Seek(off, 0)
   684  	var buf [SAR_HDR]byte
   685  	if n, err := io.ReadFull(bp, buf[:]); err != nil {
   686  		if n == 0 && err != io.EOF {
   687  			return -1
   688  		}
   689  		return 0
   690  	}
   691  
   692  	a.name = artrim(buf[0:16])
   693  	a.date = artrim(buf[16:28])
   694  	a.uid = artrim(buf[28:34])
   695  	a.gid = artrim(buf[34:40])
   696  	a.mode = artrim(buf[40:48])
   697  	a.size = artrim(buf[48:58])
   698  	a.fmag = artrim(buf[58:60])
   699  
   700  	arsize := atolwhex(a.size)
   701  	if arsize&1 != 0 {
   702  		arsize++
   703  	}
   704  	return arsize + SAR_HDR
   705  }
   706  
   707  func genhash(ctxt *Link, lib *sym.Library) {
   708  	f, err := bio.Open(lib.File)
   709  	if err != nil {
   710  		Errorf(nil, "cannot open file %s for hash generation: %v", lib.File, err)
   711  		return
   712  	}
   713  	defer f.Close()
   714  
   715  	var magbuf [len(ARMAG)]byte
   716  	if _, err := io.ReadFull(f, magbuf[:]); err != nil {
   717  		Exitf("file %s too short", lib.File)
   718  	}
   719  
   720  	if string(magbuf[:]) != ARMAG {
   721  		Exitf("%s is not an archive file", lib.File)
   722  	}
   723  
   724  	var arhdr ArHdr
   725  	l := nextar(f, f.Offset(), &arhdr)
   726  	if l <= 0 {
   727  		Errorf(nil, "%s: short read on archive file symbol header", lib.File)
   728  		return
   729  	}
   730  	if arhdr.name != pkgdef {
   731  		Errorf(nil, "%s: missing package data entry", lib.File)
   732  		return
   733  	}
   734  
   735  	h := sha1.New()
   736  
   737  	// To compute the hash of a package, we hash the first line of
   738  	// __.PKGDEF (which contains the toolchain version and any
   739  	// GOEXPERIMENT flags) and the export data (which is between
   740  	// the first two occurrences of "\n$$").
   741  
   742  	pkgDefBytes := make([]byte, atolwhex(arhdr.size))
   743  	_, err = io.ReadFull(f, pkgDefBytes)
   744  	if err != nil {
   745  		Errorf(nil, "%s: error reading package data: %v", lib.File, err)
   746  		return
   747  	}
   748  	firstEOL := bytes.IndexByte(pkgDefBytes, '\n')
   749  	if firstEOL < 0 {
   750  		Errorf(nil, "cannot parse package data of %s for hash generation, no newline found", lib.File)
   751  		return
   752  	}
   753  	firstDoubleDollar := bytes.Index(pkgDefBytes, []byte("\n$$"))
   754  	if firstDoubleDollar < 0 {
   755  		Errorf(nil, "cannot parse package data of %s for hash generation, no \\n$$ found", lib.File)
   756  		return
   757  	}
   758  	secondDoubleDollar := bytes.Index(pkgDefBytes[firstDoubleDollar+1:], []byte("\n$$"))
   759  	if secondDoubleDollar < 0 {
   760  		Errorf(nil, "cannot parse package data of %s for hash generation, only one \\n$$ found", lib.File)
   761  		return
   762  	}
   763  	h.Write(pkgDefBytes[0:firstEOL])
   764  	h.Write(pkgDefBytes[firstDoubleDollar : firstDoubleDollar+secondDoubleDollar])
   765  	lib.Hash = hex.EncodeToString(h.Sum(nil))
   766  }
   767  
   768  func loadobjfile(ctxt *Link, lib *sym.Library) {
   769  	pkg := objabi.PathToPrefix(lib.Pkg)
   770  
   771  	if ctxt.Debugvlog > 1 {
   772  		ctxt.Logf("%5.2f ldobj: %s (%s)\n", Cputime(), lib.File, pkg)
   773  	}
   774  	f, err := bio.Open(lib.File)
   775  	if err != nil {
   776  		Exitf("cannot open file %s: %v", lib.File, err)
   777  	}
   778  	defer f.Close()
   779  	defer func() {
   780  		if pkg == "main" && !lib.Main {
   781  			Exitf("%s: not package main", lib.File)
   782  		}
   783  
   784  		// Ideally, we'd check that *all* object files within
   785  		// the archive were marked safe, but here we settle
   786  		// for *any*.
   787  		//
   788  		// Historically, cmd/link only checked the __.PKGDEF
   789  		// file, which in turn came from the first object
   790  		// file, typically produced by cmd/compile. The
   791  		// remaining object files are normally produced by
   792  		// cmd/asm, which doesn't support marking files as
   793  		// safe anyway. So at least in practice, this matches
   794  		// how safe mode has always worked.
   795  		if *flagU && !lib.Safe {
   796  			Exitf("%s: load of unsafe package %s", lib.File, pkg)
   797  		}
   798  	}()
   799  
   800  	for i := 0; i < len(ARMAG); i++ {
   801  		if c, err := f.ReadByte(); err == nil && c == ARMAG[i] {
   802  			continue
   803  		}
   804  
   805  		/* load it as a regular file */
   806  		l := f.Seek(0, 2)
   807  		f.Seek(0, 0)
   808  		ldobj(ctxt, f, lib, l, lib.File, lib.File)
   809  		return
   810  	}
   811  
   812  	/*
   813  	 * load all the object files from the archive now.
   814  	 * this gives us sequential file access and keeps us
   815  	 * from needing to come back later to pick up more
   816  	 * objects.  it breaks the usual C archive model, but
   817  	 * this is Go, not C.  the common case in Go is that
   818  	 * we need to load all the objects, and then we throw away
   819  	 * the individual symbols that are unused.
   820  	 *
   821  	 * loading every object will also make it possible to
   822  	 * load foreign objects not referenced by __.PKGDEF.
   823  	 */
   824  	var arhdr ArHdr
   825  	off := f.Offset()
   826  	for {
   827  		l := nextar(f, off, &arhdr)
   828  		if l == 0 {
   829  			break
   830  		}
   831  		if l < 0 {
   832  			Exitf("%s: malformed archive", lib.File)
   833  		}
   834  		off += l
   835  
   836  		// __.PKGDEF isn't a real Go object file, and it's
   837  		// absent in -linkobj builds anyway. Skipping it
   838  		// ensures consistency between -linkobj and normal
   839  		// build modes.
   840  		if arhdr.name == pkgdef {
   841  			continue
   842  		}
   843  
   844  		pname := fmt.Sprintf("%s(%s)", lib.File, arhdr.name)
   845  		l = atolwhex(arhdr.size)
   846  		ldobj(ctxt, f, lib, l, pname, lib.File)
   847  	}
   848  }
   849  
   850  type Hostobj struct {
   851  	ld     func(*Link, *bio.Reader, string, int64, string)
   852  	pkg    string
   853  	pn     string
   854  	file   string
   855  	off    int64
   856  	length int64
   857  }
   858  
   859  var hostobj []Hostobj
   860  
   861  // These packages can use internal linking mode.
   862  // Others trigger external mode.
   863  var internalpkg = []string{
   864  	"crypto/x509",
   865  	"net",
   866  	"os/user",
   867  	"runtime/cgo",
   868  	"runtime/race",
   869  	"runtime/msan",
   870  }
   871  
   872  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 {
   873  	isinternal := false
   874  	for _, intpkg := range internalpkg {
   875  		if pkg == intpkg {
   876  			isinternal = true
   877  			break
   878  		}
   879  	}
   880  
   881  	// DragonFly declares errno with __thread, which results in a symbol
   882  	// type of R_386_TLS_GD or R_X86_64_TLSGD. The Go linker does not
   883  	// currently know how to handle TLS relocations, hence we have to
   884  	// force external linking for any libraries that link in code that
   885  	// uses errno. This can be removed if the Go linker ever supports
   886  	// these relocation types.
   887  	if headType == objabi.Hdragonfly {
   888  		if pkg == "net" || pkg == "os/user" {
   889  			isinternal = false
   890  		}
   891  	}
   892  
   893  	if !isinternal {
   894  		externalobj = true
   895  	}
   896  
   897  	hostobj = append(hostobj, Hostobj{})
   898  	h := &hostobj[len(hostobj)-1]
   899  	h.ld = ld
   900  	h.pkg = pkg
   901  	h.pn = pn
   902  	h.file = file
   903  	h.off = f.Offset()
   904  	h.length = length
   905  	return h
   906  }
   907  
   908  func hostobjs(ctxt *Link) {
   909  	var h *Hostobj
   910  
   911  	for i := 0; i < len(hostobj); i++ {
   912  		h = &hostobj[i]
   913  		f, err := bio.Open(h.file)
   914  		if err != nil {
   915  			Exitf("cannot reopen %s: %v", h.pn, err)
   916  		}
   917  
   918  		f.Seek(h.off, 0)
   919  		h.ld(ctxt, f, h.pkg, h.length, h.pn)
   920  		f.Close()
   921  	}
   922  }
   923  
   924  func hostlinksetup(ctxt *Link) {
   925  	if ctxt.LinkMode != LinkExternal {
   926  		return
   927  	}
   928  
   929  	// For external link, record that we need to tell the external linker -s,
   930  	// and turn off -s internally: the external linker needs the symbol
   931  	// information for its final link.
   932  	debug_s = *FlagS
   933  	*FlagS = false
   934  
   935  	// create temporary directory and arrange cleanup
   936  	if *flagTmpdir == "" {
   937  		dir, err := ioutil.TempDir("", "go-link-")
   938  		if err != nil {
   939  			log.Fatal(err)
   940  		}
   941  		*flagTmpdir = dir
   942  		AtExit(func() {
   943  			ctxt.Out.f.Close()
   944  			os.RemoveAll(*flagTmpdir)
   945  		})
   946  	}
   947  
   948  	// change our output to temporary object file
   949  	ctxt.Out.f.Close()
   950  	mayberemoveoutfile()
   951  
   952  	p := filepath.Join(*flagTmpdir, "go.o")
   953  	var err error
   954  	f, err := os.OpenFile(p, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0775)
   955  	if err != nil {
   956  		Exitf("cannot create %s: %v", p, err)
   957  	}
   958  
   959  	ctxt.Out.w = bufio.NewWriter(f)
   960  	ctxt.Out.f = f
   961  	ctxt.Out.off = 0
   962  }
   963  
   964  // hostobjCopy creates a copy of the object files in hostobj in a
   965  // temporary directory.
   966  func hostobjCopy() (paths []string) {
   967  	var wg sync.WaitGroup
   968  	sema := make(chan struct{}, runtime.NumCPU()) // limit open file descriptors
   969  	for i, h := range hostobj {
   970  		h := h
   971  		dst := filepath.Join(*flagTmpdir, fmt.Sprintf("%06d.o", i))
   972  		paths = append(paths, dst)
   973  
   974  		wg.Add(1)
   975  		go func() {
   976  			sema <- struct{}{}
   977  			defer func() {
   978  				<-sema
   979  				wg.Done()
   980  			}()
   981  			f, err := os.Open(h.file)
   982  			if err != nil {
   983  				Exitf("cannot reopen %s: %v", h.pn, err)
   984  			}
   985  			if _, err := f.Seek(h.off, 0); err != nil {
   986  				Exitf("cannot seek %s: %v", h.pn, err)
   987  			}
   988  
   989  			w, err := os.Create(dst)
   990  			if err != nil {
   991  				Exitf("cannot create %s: %v", dst, err)
   992  			}
   993  			if _, err := io.CopyN(w, f, h.length); err != nil {
   994  				Exitf("cannot write %s: %v", dst, err)
   995  			}
   996  			if err := w.Close(); err != nil {
   997  				Exitf("cannot close %s: %v", dst, err)
   998  			}
   999  		}()
  1000  	}
  1001  	wg.Wait()
  1002  	return paths
  1003  }
  1004  
  1005  // writeGDBLinkerScript creates gcc linker script file in temp
  1006  // directory. writeGDBLinkerScript returns created file path.
  1007  // The script is used to work around gcc bug
  1008  // (see https://golang.org/issue/20183 for details).
  1009  func writeGDBLinkerScript() string {
  1010  	name := "fix_debug_gdb_scripts.ld"
  1011  	path := filepath.Join(*flagTmpdir, name)
  1012  	src := `SECTIONS
  1013  {
  1014    .debug_gdb_scripts BLOCK(__section_alignment__) (NOLOAD) :
  1015    {
  1016      *(.debug_gdb_scripts)
  1017    }
  1018  }
  1019  INSERT AFTER .debug_types;
  1020  `
  1021  	err := ioutil.WriteFile(path, []byte(src), 0666)
  1022  	if err != nil {
  1023  		Errorf(nil, "WriteFile %s failed: %v", name, err)
  1024  	}
  1025  	return path
  1026  }
  1027  
  1028  // archive builds a .a archive from the hostobj object files.
  1029  func (ctxt *Link) archive() {
  1030  	if ctxt.BuildMode != BuildModeCArchive {
  1031  		return
  1032  	}
  1033  
  1034  	if *flagExtar == "" {
  1035  		*flagExtar = "ar"
  1036  	}
  1037  
  1038  	mayberemoveoutfile()
  1039  
  1040  	// Force the buffer to flush here so that external
  1041  	// tools will see a complete file.
  1042  	ctxt.Out.Flush()
  1043  	if err := ctxt.Out.f.Close(); err != nil {
  1044  		Exitf("close: %v", err)
  1045  	}
  1046  	ctxt.Out.f = nil
  1047  
  1048  	argv := []string{*flagExtar, "-q", "-c", "-s", *flagOutfile}
  1049  	argv = append(argv, filepath.Join(*flagTmpdir, "go.o"))
  1050  	argv = append(argv, hostobjCopy()...)
  1051  
  1052  	if ctxt.Debugvlog != 0 {
  1053  		ctxt.Logf("archive: %s\n", strings.Join(argv, " "))
  1054  	}
  1055  
  1056  	if out, err := exec.Command(argv[0], argv[1:]...).CombinedOutput(); err != nil {
  1057  		Exitf("running %s failed: %v\n%s", argv[0], err, out)
  1058  	}
  1059  }
  1060  
  1061  func (ctxt *Link) hostlink() {
  1062  	if ctxt.LinkMode != LinkExternal || nerrors > 0 {
  1063  		return
  1064  	}
  1065  	if ctxt.BuildMode == BuildModeCArchive {
  1066  		return
  1067  	}
  1068  
  1069  	if *flagExtld == "" {
  1070  		*flagExtld = "gcc"
  1071  	}
  1072  
  1073  	var argv []string
  1074  	argv = append(argv, *flagExtld)
  1075  	argv = append(argv, hostlinkArchArgs(ctxt.Arch)...)
  1076  
  1077  	if *FlagS || debug_s {
  1078  		if ctxt.HeadType == objabi.Hdarwin {
  1079  			// Recent versions of macOS print
  1080  			//	ld: warning: option -s is obsolete and being ignored
  1081  			// so do not pass any arguments.
  1082  		} else {
  1083  			argv = append(argv, "-s")
  1084  		}
  1085  	}
  1086  
  1087  	switch ctxt.HeadType {
  1088  	case objabi.Hdarwin:
  1089  		argv = append(argv, "-Wl,-headerpad,1144")
  1090  		if ctxt.DynlinkingGo() {
  1091  			argv = append(argv, "-Wl,-flat_namespace")
  1092  		}
  1093  		if ctxt.BuildMode == BuildModeExe && !ctxt.Arch.InFamily(sys.ARM64) {
  1094  			argv = append(argv, "-Wl,-no_pie")
  1095  		}
  1096  	case objabi.Hopenbsd:
  1097  		argv = append(argv, "-Wl,-nopie")
  1098  	case objabi.Hwindows:
  1099  		if windowsgui {
  1100  			argv = append(argv, "-mwindows")
  1101  		} else {
  1102  			argv = append(argv, "-mconsole")
  1103  		}
  1104  	}
  1105  
  1106  	switch ctxt.BuildMode {
  1107  	case BuildModeExe:
  1108  		if ctxt.HeadType == objabi.Hdarwin {
  1109  			if ctxt.Arch.Family == sys.ARM64 {
  1110  				// __PAGEZERO segment size determined empirically.
  1111  				// XCode 9.0.1 successfully uploads an iOS app with this value.
  1112  				argv = append(argv, "-Wl,-pagezero_size,100000000")
  1113  			} else {
  1114  				argv = append(argv, "-Wl,-pagezero_size,4000000")
  1115  			}
  1116  		}
  1117  	case BuildModePIE:
  1118  		// ELF.
  1119  		if ctxt.HeadType != objabi.Hdarwin {
  1120  			if ctxt.UseRelro() {
  1121  				argv = append(argv, "-Wl,-z,relro")
  1122  			}
  1123  			argv = append(argv, "-pie")
  1124  		}
  1125  	case BuildModeCShared:
  1126  		if ctxt.HeadType == objabi.Hdarwin {
  1127  			argv = append(argv, "-dynamiclib")
  1128  			if ctxt.Arch.Family != sys.AMD64 {
  1129  				argv = append(argv, "-Wl,-read_only_relocs,suppress")
  1130  			}
  1131  		} else {
  1132  			// ELF.
  1133  			argv = append(argv, "-Wl,-Bsymbolic")
  1134  			if ctxt.UseRelro() {
  1135  				argv = append(argv, "-Wl,-z,relro")
  1136  			}
  1137  			argv = append(argv, "-shared")
  1138  			if ctxt.HeadType != objabi.Hwindows {
  1139  				// Pass -z nodelete to mark the shared library as
  1140  				// non-closeable: a dlclose will do nothing.
  1141  				argv = append(argv, "-Wl,-z,nodelete")
  1142  			}
  1143  		}
  1144  	case BuildModeShared:
  1145  		if ctxt.UseRelro() {
  1146  			argv = append(argv, "-Wl,-z,relro")
  1147  		}
  1148  		argv = append(argv, "-shared")
  1149  	case BuildModePlugin:
  1150  		if ctxt.HeadType == objabi.Hdarwin {
  1151  			argv = append(argv, "-dynamiclib")
  1152  		} else {
  1153  			if ctxt.UseRelro() {
  1154  				argv = append(argv, "-Wl,-z,relro")
  1155  			}
  1156  			argv = append(argv, "-shared")
  1157  		}
  1158  	}
  1159  
  1160  	if ctxt.IsELF && ctxt.DynlinkingGo() {
  1161  		// We force all symbol resolution to be done at program startup
  1162  		// because lazy PLT resolution can use large amounts of stack at
  1163  		// times we cannot allow it to do so.
  1164  		argv = append(argv, "-Wl,-znow")
  1165  
  1166  		// Do not let the host linker generate COPY relocations. These
  1167  		// can move symbols out of sections that rely on stable offsets
  1168  		// from the beginning of the section (like sym.STYPE).
  1169  		argv = append(argv, "-Wl,-znocopyreloc")
  1170  
  1171  		if ctxt.Arch.InFamily(sys.ARM, sys.ARM64) {
  1172  			// On ARM, the GNU linker will generate COPY relocations
  1173  			// even with -znocopyreloc set.
  1174  			// https://sourceware.org/bugzilla/show_bug.cgi?id=19962
  1175  			//
  1176  			// On ARM64, the GNU linker will fail instead of
  1177  			// generating COPY relocations.
  1178  			//
  1179  			// In both cases, switch to gold.
  1180  			argv = append(argv, "-fuse-ld=gold")
  1181  
  1182  			// If gold is not installed, gcc will silently switch
  1183  			// back to ld.bfd. So we parse the version information
  1184  			// and provide a useful error if gold is missing.
  1185  			cmd := exec.Command(*flagExtld, "-fuse-ld=gold", "-Wl,--version")
  1186  			if out, err := cmd.CombinedOutput(); err == nil {
  1187  				if !bytes.Contains(out, []byte("GNU gold")) {
  1188  					log.Fatalf("ARM external linker must be gold (issue #15696), but is not: %s", out)
  1189  				}
  1190  			}
  1191  		}
  1192  	}
  1193  
  1194  	if ctxt.IsELF && len(buildinfo) > 0 {
  1195  		argv = append(argv, fmt.Sprintf("-Wl,--build-id=0x%x", buildinfo))
  1196  	}
  1197  
  1198  	// On Windows, given -o foo, GCC will append ".exe" to produce
  1199  	// "foo.exe".  We have decided that we want to honor the -o
  1200  	// option. To make this work, we append a '.' so that GCC
  1201  	// will decide that the file already has an extension. We
  1202  	// only want to do this when producing a Windows output file
  1203  	// on a Windows host.
  1204  	outopt := *flagOutfile
  1205  	if objabi.GOOS == "windows" && runtime.GOOS == "windows" && filepath.Ext(outopt) == "" {
  1206  		outopt += "."
  1207  	}
  1208  	argv = append(argv, "-o")
  1209  	argv = append(argv, outopt)
  1210  
  1211  	if rpath.val != "" {
  1212  		argv = append(argv, fmt.Sprintf("-Wl,-rpath,%s", rpath.val))
  1213  	}
  1214  
  1215  	// Force global symbols to be exported for dlopen, etc.
  1216  	if ctxt.IsELF {
  1217  		argv = append(argv, "-rdynamic")
  1218  	}
  1219  
  1220  	if strings.Contains(argv[0], "clang") {
  1221  		argv = append(argv, "-Qunused-arguments")
  1222  	}
  1223  
  1224  	const compressDWARF = "-Wl,--compress-debug-sections=zlib-gnu"
  1225  	if ctxt.compressDWARF && linkerFlagSupported(argv[0], compressDWARF) {
  1226  		argv = append(argv, compressDWARF)
  1227  	}
  1228  
  1229  	argv = append(argv, filepath.Join(*flagTmpdir, "go.o"))
  1230  	argv = append(argv, hostobjCopy()...)
  1231  
  1232  	if ctxt.linkShared {
  1233  		seenDirs := make(map[string]bool)
  1234  		seenLibs := make(map[string]bool)
  1235  		addshlib := func(path string) {
  1236  			dir, base := filepath.Split(path)
  1237  			if !seenDirs[dir] {
  1238  				argv = append(argv, "-L"+dir)
  1239  				if !rpath.set {
  1240  					argv = append(argv, "-Wl,-rpath="+dir)
  1241  				}
  1242  				seenDirs[dir] = true
  1243  			}
  1244  			base = strings.TrimSuffix(base, ".so")
  1245  			base = strings.TrimPrefix(base, "lib")
  1246  			if !seenLibs[base] {
  1247  				argv = append(argv, "-l"+base)
  1248  				seenLibs[base] = true
  1249  			}
  1250  		}
  1251  		for _, shlib := range ctxt.Shlibs {
  1252  			addshlib(shlib.Path)
  1253  			for _, dep := range shlib.Deps {
  1254  				if dep == "" {
  1255  					continue
  1256  				}
  1257  				libpath := findshlib(ctxt, dep)
  1258  				if libpath != "" {
  1259  					addshlib(libpath)
  1260  				}
  1261  			}
  1262  		}
  1263  	}
  1264  
  1265  	// clang, unlike GCC, passes -rdynamic to the linker
  1266  	// even when linking with -static, causing a linker
  1267  	// error when using GNU ld. So take out -rdynamic if
  1268  	// we added it. We do it in this order, rather than
  1269  	// only adding -rdynamic later, so that -*extldflags
  1270  	// can override -rdynamic without using -static.
  1271  	checkStatic := func(arg string) {
  1272  		if ctxt.IsELF && arg == "-static" {
  1273  			for i := range argv {
  1274  				if argv[i] == "-rdynamic" {
  1275  					argv[i] = "-static"
  1276  				}
  1277  			}
  1278  		}
  1279  	}
  1280  
  1281  	for _, p := range ldflag {
  1282  		argv = append(argv, p)
  1283  		checkStatic(p)
  1284  	}
  1285  
  1286  	// When building a program with the default -buildmode=exe the
  1287  	// gc compiler generates code requires DT_TEXTREL in a
  1288  	// position independent executable (PIE). On systems where the
  1289  	// toolchain creates PIEs by default, and where DT_TEXTREL
  1290  	// does not work, the resulting programs will not run. See
  1291  	// issue #17847. To avoid this problem pass -no-pie to the
  1292  	// toolchain if it is supported.
  1293  	if ctxt.BuildMode == BuildModeExe && !ctxt.linkShared {
  1294  		// GCC uses -no-pie, clang uses -nopie.
  1295  		for _, nopie := range []string{"-no-pie", "-nopie"} {
  1296  			if linkerFlagSupported(argv[0], nopie) {
  1297  				argv = append(argv, nopie)
  1298  				break
  1299  			}
  1300  		}
  1301  	}
  1302  
  1303  	for _, p := range strings.Fields(*flagExtldflags) {
  1304  		argv = append(argv, p)
  1305  		checkStatic(p)
  1306  	}
  1307  	if ctxt.HeadType == objabi.Hwindows {
  1308  		// use gcc linker script to work around gcc bug
  1309  		// (see https://golang.org/issue/20183 for details).
  1310  		p := writeGDBLinkerScript()
  1311  		argv = append(argv, "-Wl,-T,"+p)
  1312  		// libmingw32 and libmingwex have some inter-dependencies,
  1313  		// so must use linker groups.
  1314  		argv = append(argv, "-Wl,--start-group", "-lmingwex", "-lmingw32", "-Wl,--end-group")
  1315  		argv = append(argv, peimporteddlls()...)
  1316  	}
  1317  
  1318  	if ctxt.Debugvlog != 0 {
  1319  		ctxt.Logf("%5.2f host link:", Cputime())
  1320  		for _, v := range argv {
  1321  			ctxt.Logf(" %q", v)
  1322  		}
  1323  		ctxt.Logf("\n")
  1324  	}
  1325  
  1326  	if out, err := exec.Command(argv[0], argv[1:]...).CombinedOutput(); err != nil {
  1327  		Exitf("running %s failed: %v\n%s", argv[0], err, out)
  1328  	} else if len(out) > 0 {
  1329  		// always print external output even if the command is successful, so that we don't
  1330  		// swallow linker warnings (see https://golang.org/issue/17935).
  1331  		ctxt.Logf("%s", out)
  1332  	}
  1333  
  1334  	if !*FlagS && !*FlagW && !debug_s && ctxt.HeadType == objabi.Hdarwin {
  1335  		dsym := filepath.Join(*flagTmpdir, "go.dwarf")
  1336  		if out, err := exec.Command("dsymutil", "-f", *flagOutfile, "-o", dsym).CombinedOutput(); err != nil {
  1337  			Exitf("%s: running dsymutil failed: %v\n%s", os.Args[0], err, out)
  1338  		}
  1339  		// Skip combining if `dsymutil` didn't generate a file. See #11994.
  1340  		if _, err := os.Stat(dsym); os.IsNotExist(err) {
  1341  			return
  1342  		}
  1343  		// For os.Rename to work reliably, must be in same directory as outfile.
  1344  		combinedOutput := *flagOutfile + "~"
  1345  		isIOS, err := machoCombineDwarf(ctxt, *flagOutfile, dsym, combinedOutput)
  1346  		if err != nil {
  1347  			Exitf("%s: combining dwarf failed: %v", os.Args[0], err)
  1348  		}
  1349  		if !isIOS {
  1350  			os.Remove(*flagOutfile)
  1351  			if err := os.Rename(combinedOutput, *flagOutfile); err != nil {
  1352  				Exitf("%s: %v", os.Args[0], err)
  1353  			}
  1354  		}
  1355  	}
  1356  }
  1357  
  1358  var createTrivialCOnce sync.Once
  1359  
  1360  func linkerFlagSupported(linker, flag string) bool {
  1361  	createTrivialCOnce.Do(func() {
  1362  		src := filepath.Join(*flagTmpdir, "trivial.c")
  1363  		if err := ioutil.WriteFile(src, []byte("int main() { return 0; }"), 0666); err != nil {
  1364  			Errorf(nil, "WriteFile trivial.c failed: %v", err)
  1365  		}
  1366  	})
  1367  
  1368  	cmd := exec.Command(linker, flag, "trivial.c")
  1369  	cmd.Dir = *flagTmpdir
  1370  	cmd.Env = append([]string{"LC_ALL=C"}, os.Environ()...)
  1371  	out, err := cmd.CombinedOutput()
  1372  	// GCC says "unrecognized command line option ‘-no-pie’"
  1373  	// clang says "unknown argument: '-no-pie'"
  1374  	return err == nil && !bytes.Contains(out, []byte("unrecognized")) && !bytes.Contains(out, []byte("unknown"))
  1375  }
  1376  
  1377  // hostlinkArchArgs returns arguments to pass to the external linker
  1378  // based on the architecture.
  1379  func hostlinkArchArgs(arch *sys.Arch) []string {
  1380  	switch arch.Family {
  1381  	case sys.I386:
  1382  		return []string{"-m32"}
  1383  	case sys.AMD64, sys.PPC64, sys.S390X:
  1384  		return []string{"-m64"}
  1385  	case sys.ARM:
  1386  		return []string{"-marm"}
  1387  	case sys.ARM64:
  1388  		// nothing needed
  1389  	case sys.MIPS64:
  1390  		return []string{"-mabi=64"}
  1391  	case sys.MIPS:
  1392  		return []string{"-mabi=32"}
  1393  	}
  1394  	return nil
  1395  }
  1396  
  1397  // ldobj loads an input object. If it is a host object (an object
  1398  // compiled by a non-Go compiler) it returns the Hostobj pointer. If
  1399  // it is a Go object, it returns nil.
  1400  func ldobj(ctxt *Link, f *bio.Reader, lib *sym.Library, length int64, pn string, file string) *Hostobj {
  1401  	pkg := objabi.PathToPrefix(lib.Pkg)
  1402  
  1403  	eof := f.Offset() + length
  1404  	start := f.Offset()
  1405  	c1 := bgetc(f)
  1406  	c2 := bgetc(f)
  1407  	c3 := bgetc(f)
  1408  	c4 := bgetc(f)
  1409  	f.Seek(start, 0)
  1410  
  1411  	magic := uint32(c1)<<24 | uint32(c2)<<16 | uint32(c3)<<8 | uint32(c4)
  1412  	if magic == 0x7f454c46 { // \x7F E L F
  1413  		ldelf := func(ctxt *Link, f *bio.Reader, pkg string, length int64, pn string) {
  1414  			textp, flags, err := loadelf.Load(ctxt.Arch, ctxt.Syms, f, pkg, length, pn, ehdr.flags)
  1415  			if err != nil {
  1416  				Errorf(nil, "%v", err)
  1417  				return
  1418  			}
  1419  			ehdr.flags = flags
  1420  			ctxt.Textp = append(ctxt.Textp, textp...)
  1421  		}
  1422  		return ldhostobj(ldelf, ctxt.HeadType, f, pkg, length, pn, file)
  1423  	}
  1424  
  1425  	if magic&^1 == 0xfeedface || magic&^0x01000000 == 0xcefaedfe {
  1426  		ldmacho := func(ctxt *Link, f *bio.Reader, pkg string, length int64, pn string) {
  1427  			textp, err := loadmacho.Load(ctxt.Arch, ctxt.Syms, f, pkg, length, pn)
  1428  			if err != nil {
  1429  				Errorf(nil, "%v", err)
  1430  				return
  1431  			}
  1432  			ctxt.Textp = append(ctxt.Textp, textp...)
  1433  		}
  1434  		return ldhostobj(ldmacho, ctxt.HeadType, f, pkg, length, pn, file)
  1435  	}
  1436  
  1437  	if c1 == 0x4c && c2 == 0x01 || c1 == 0x64 && c2 == 0x86 {
  1438  		ldpe := func(ctxt *Link, f *bio.Reader, pkg string, length int64, pn string) {
  1439  			textp, rsrc, err := loadpe.Load(ctxt.Arch, ctxt.Syms, f, pkg, length, pn)
  1440  			if err != nil {
  1441  				Errorf(nil, "%v", err)
  1442  				return
  1443  			}
  1444  			if rsrc != nil {
  1445  				setpersrc(ctxt, rsrc)
  1446  			}
  1447  			ctxt.Textp = append(ctxt.Textp, textp...)
  1448  		}
  1449  		return ldhostobj(ldpe, ctxt.HeadType, f, pkg, length, pn, file)
  1450  	}
  1451  
  1452  	/* check the header */
  1453  	line, err := f.ReadString('\n')
  1454  	if err != nil {
  1455  		Errorf(nil, "truncated object file: %s: %v", pn, err)
  1456  		return nil
  1457  	}
  1458  
  1459  	if !strings.HasPrefix(line, "go object ") {
  1460  		if strings.HasSuffix(pn, ".go") {
  1461  			Exitf("%s: uncompiled .go source file", pn)
  1462  			return nil
  1463  		}
  1464  
  1465  		if line == ctxt.Arch.Name {
  1466  			// old header format: just $GOOS
  1467  			Errorf(nil, "%s: stale object file", pn)
  1468  			return nil
  1469  		}
  1470  
  1471  		Errorf(nil, "%s: not an object file", pn)
  1472  		return nil
  1473  	}
  1474  
  1475  	// First, check that the basic GOOS, GOARCH, and Version match.
  1476  	t := fmt.Sprintf("%s %s %s ", objabi.GOOS, objabi.GOARCH, objabi.Version)
  1477  
  1478  	line = strings.TrimRight(line, "\n")
  1479  	if !strings.HasPrefix(line[10:]+" ", t) && !*flagF {
  1480  		Errorf(nil, "%s: object is [%s] expected [%s]", pn, line[10:], t)
  1481  		return nil
  1482  	}
  1483  
  1484  	// Second, check that longer lines match each other exactly,
  1485  	// so that the Go compiler and write additional information
  1486  	// that must be the same from run to run.
  1487  	if len(line) >= len(t)+10 {
  1488  		if theline == "" {
  1489  			theline = line[10:]
  1490  		} else if theline != line[10:] {
  1491  			Errorf(nil, "%s: object is [%s] expected [%s]", pn, line[10:], theline)
  1492  			return nil
  1493  		}
  1494  	}
  1495  
  1496  	// Skip over exports and other info -- ends with \n!\n.
  1497  	//
  1498  	// Note: It's possible for "\n!\n" to appear within the binary
  1499  	// package export data format. To avoid truncating the package
  1500  	// definition prematurely (issue 21703), we keep keep track of
  1501  	// how many "$$" delimiters we've seen.
  1502  
  1503  	import0 := f.Offset()
  1504  
  1505  	c1 = '\n' // the last line ended in \n
  1506  	c2 = bgetc(f)
  1507  	c3 = bgetc(f)
  1508  	markers := 0
  1509  	for {
  1510  		if c1 == '\n' {
  1511  			if markers%2 == 0 && c2 == '!' && c3 == '\n' {
  1512  				break
  1513  			}
  1514  			if c2 == '$' && c3 == '$' {
  1515  				markers++
  1516  			}
  1517  		}
  1518  
  1519  		c1 = c2
  1520  		c2 = c3
  1521  		c3 = bgetc(f)
  1522  		if c3 == -1 {
  1523  			Errorf(nil, "truncated object file: %s", pn)
  1524  			return nil
  1525  		}
  1526  	}
  1527  
  1528  	import1 := f.Offset()
  1529  
  1530  	f.Seek(import0, 0)
  1531  	ldpkg(ctxt, f, lib, import1-import0-2, pn) // -2 for !\n
  1532  	f.Seek(import1, 0)
  1533  
  1534  	objfile.Load(ctxt.Arch, ctxt.Syms, f, lib, eof-f.Offset(), pn)
  1535  	addImports(ctxt, lib, pn)
  1536  	return nil
  1537  }
  1538  
  1539  func readelfsymboldata(ctxt *Link, f *elf.File, sym *elf.Symbol) []byte {
  1540  	data := make([]byte, sym.Size)
  1541  	sect := f.Sections[sym.Section]
  1542  	if sect.Type != elf.SHT_PROGBITS && sect.Type != elf.SHT_NOTE {
  1543  		Errorf(nil, "reading %s from non-data section", sym.Name)
  1544  	}
  1545  	n, err := sect.ReadAt(data, int64(sym.Value-sect.Addr))
  1546  	if uint64(n) != sym.Size {
  1547  		Errorf(nil, "reading contents of %s: %v", sym.Name, err)
  1548  	}
  1549  	return data
  1550  }
  1551  
  1552  func readwithpad(r io.Reader, sz int32) ([]byte, error) {
  1553  	data := make([]byte, Rnd(int64(sz), 4))
  1554  	_, err := io.ReadFull(r, data)
  1555  	if err != nil {
  1556  		return nil, err
  1557  	}
  1558  	data = data[:sz]
  1559  	return data, nil
  1560  }
  1561  
  1562  func readnote(f *elf.File, name []byte, typ int32) ([]byte, error) {
  1563  	for _, sect := range f.Sections {
  1564  		if sect.Type != elf.SHT_NOTE {
  1565  			continue
  1566  		}
  1567  		r := sect.Open()
  1568  		for {
  1569  			var namesize, descsize, noteType int32
  1570  			err := binary.Read(r, f.ByteOrder, &namesize)
  1571  			if err != nil {
  1572  				if err == io.EOF {
  1573  					break
  1574  				}
  1575  				return nil, fmt.Errorf("read namesize failed: %v", err)
  1576  			}
  1577  			err = binary.Read(r, f.ByteOrder, &descsize)
  1578  			if err != nil {
  1579  				return nil, fmt.Errorf("read descsize failed: %v", err)
  1580  			}
  1581  			err = binary.Read(r, f.ByteOrder, &noteType)
  1582  			if err != nil {
  1583  				return nil, fmt.Errorf("read type failed: %v", err)
  1584  			}
  1585  			noteName, err := readwithpad(r, namesize)
  1586  			if err != nil {
  1587  				return nil, fmt.Errorf("read name failed: %v", err)
  1588  			}
  1589  			desc, err := readwithpad(r, descsize)
  1590  			if err != nil {
  1591  				return nil, fmt.Errorf("read desc failed: %v", err)
  1592  			}
  1593  			if string(name) == string(noteName) && typ == noteType {
  1594  				return desc, nil
  1595  			}
  1596  		}
  1597  	}
  1598  	return nil, nil
  1599  }
  1600  
  1601  func findshlib(ctxt *Link, shlib string) string {
  1602  	if filepath.IsAbs(shlib) {
  1603  		return shlib
  1604  	}
  1605  	for _, libdir := range ctxt.Libdir {
  1606  		libpath := filepath.Join(libdir, shlib)
  1607  		if _, err := os.Stat(libpath); err == nil {
  1608  			return libpath
  1609  		}
  1610  	}
  1611  	Errorf(nil, "cannot find shared library: %s", shlib)
  1612  	return ""
  1613  }
  1614  
  1615  func ldshlibsyms(ctxt *Link, shlib string) {
  1616  	var libpath string
  1617  	if filepath.IsAbs(shlib) {
  1618  		libpath = shlib
  1619  		shlib = filepath.Base(shlib)
  1620  	} else {
  1621  		libpath = findshlib(ctxt, shlib)
  1622  		if libpath == "" {
  1623  			return
  1624  		}
  1625  	}
  1626  	for _, processedlib := range ctxt.Shlibs {
  1627  		if processedlib.Path == libpath {
  1628  			return
  1629  		}
  1630  	}
  1631  	if ctxt.Debugvlog > 1 {
  1632  		ctxt.Logf("%5.2f ldshlibsyms: found library with name %s at %s\n", Cputime(), shlib, libpath)
  1633  	}
  1634  
  1635  	f, err := elf.Open(libpath)
  1636  	if err != nil {
  1637  		Errorf(nil, "cannot open shared library: %s", libpath)
  1638  		return
  1639  	}
  1640  	defer f.Close()
  1641  
  1642  	hash, err := readnote(f, ELF_NOTE_GO_NAME, ELF_NOTE_GOABIHASH_TAG)
  1643  	if err != nil {
  1644  		Errorf(nil, "cannot read ABI hash from shared library %s: %v", libpath, err)
  1645  		return
  1646  	}
  1647  
  1648  	depsbytes, err := readnote(f, ELF_NOTE_GO_NAME, ELF_NOTE_GODEPS_TAG)
  1649  	if err != nil {
  1650  		Errorf(nil, "cannot read dep list from shared library %s: %v", libpath, err)
  1651  		return
  1652  	}
  1653  	var deps []string
  1654  	for _, dep := range strings.Split(string(depsbytes), "\n") {
  1655  		if dep == "" {
  1656  			continue
  1657  		}
  1658  		if !filepath.IsAbs(dep) {
  1659  			// If the dep can be interpreted as a path relative to the shlib
  1660  			// in which it was found, do that. Otherwise, we will leave it
  1661  			// to be resolved by libdir lookup.
  1662  			abs := filepath.Join(filepath.Dir(libpath), dep)
  1663  			if _, err := os.Stat(abs); err == nil {
  1664  				dep = abs
  1665  			}
  1666  		}
  1667  		deps = append(deps, dep)
  1668  	}
  1669  
  1670  	syms, err := f.DynamicSymbols()
  1671  	if err != nil {
  1672  		Errorf(nil, "cannot read symbols from shared library: %s", libpath)
  1673  		return
  1674  	}
  1675  	gcdataLocations := make(map[uint64]*sym.Symbol)
  1676  	for _, elfsym := range syms {
  1677  		if elf.ST_TYPE(elfsym.Info) == elf.STT_NOTYPE || elf.ST_TYPE(elfsym.Info) == elf.STT_SECTION {
  1678  			continue
  1679  		}
  1680  		lsym := ctxt.Syms.Lookup(elfsym.Name, 0)
  1681  		// Because loadlib above loads all .a files before loading any shared
  1682  		// libraries, any non-dynimport symbols we find that duplicate symbols
  1683  		// already loaded should be ignored (the symbols from the .a files
  1684  		// "win").
  1685  		if lsym.Type != 0 && lsym.Type != sym.SDYNIMPORT {
  1686  			continue
  1687  		}
  1688  		lsym.Type = sym.SDYNIMPORT
  1689  		lsym.ElfType = elf.ST_TYPE(elfsym.Info)
  1690  		lsym.Size = int64(elfsym.Size)
  1691  		if elfsym.Section != elf.SHN_UNDEF {
  1692  			// Set .File for the library that actually defines the symbol.
  1693  			lsym.File = libpath
  1694  			// The decodetype_* functions in decodetype.go need access to
  1695  			// the type data.
  1696  			if strings.HasPrefix(lsym.Name, "type.") && !strings.HasPrefix(lsym.Name, "type..") {
  1697  				lsym.P = readelfsymboldata(ctxt, f, &elfsym)
  1698  				gcdataLocations[elfsym.Value+2*uint64(ctxt.Arch.PtrSize)+8+1*uint64(ctxt.Arch.PtrSize)] = lsym
  1699  			}
  1700  		}
  1701  	}
  1702  	gcdataAddresses := make(map[*sym.Symbol]uint64)
  1703  	if ctxt.Arch.Family == sys.ARM64 {
  1704  		for _, sect := range f.Sections {
  1705  			if sect.Type == elf.SHT_RELA {
  1706  				var rela elf.Rela64
  1707  				rdr := sect.Open()
  1708  				for {
  1709  					err := binary.Read(rdr, f.ByteOrder, &rela)
  1710  					if err == io.EOF {
  1711  						break
  1712  					} else if err != nil {
  1713  						Errorf(nil, "reading relocation failed %v", err)
  1714  						return
  1715  					}
  1716  					t := elf.R_AARCH64(rela.Info & 0xffff)
  1717  					if t != elf.R_AARCH64_RELATIVE {
  1718  						continue
  1719  					}
  1720  					if lsym, ok := gcdataLocations[rela.Off]; ok {
  1721  						gcdataAddresses[lsym] = uint64(rela.Addend)
  1722  					}
  1723  				}
  1724  			}
  1725  		}
  1726  	}
  1727  
  1728  	ctxt.Shlibs = append(ctxt.Shlibs, Shlib{Path: libpath, Hash: hash, Deps: deps, File: f, gcdataAddresses: gcdataAddresses})
  1729  }
  1730  
  1731  func addsection(arch *sys.Arch, seg *sym.Segment, name string, rwx int) *sym.Section {
  1732  	sect := new(sym.Section)
  1733  	sect.Rwx = uint8(rwx)
  1734  	sect.Name = name
  1735  	sect.Seg = seg
  1736  	sect.Align = int32(arch.PtrSize) // everything is at least pointer-aligned
  1737  	seg.Sections = append(seg.Sections, sect)
  1738  	return sect
  1739  }
  1740  
  1741  func Le16(b []byte) uint16 {
  1742  	return uint16(b[0]) | uint16(b[1])<<8
  1743  }
  1744  
  1745  func Le32(b []byte) uint32 {
  1746  	return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
  1747  }
  1748  
  1749  func Le64(b []byte) uint64 {
  1750  	return uint64(Le32(b)) | uint64(Le32(b[4:]))<<32
  1751  }
  1752  
  1753  func Be16(b []byte) uint16 {
  1754  	return uint16(b[0])<<8 | uint16(b[1])
  1755  }
  1756  
  1757  func Be32(b []byte) uint32 {
  1758  	return uint32(b[0])<<24 | uint32(b[1])<<16 | uint32(b[2])<<8 | uint32(b[3])
  1759  }
  1760  
  1761  type chain struct {
  1762  	sym   *sym.Symbol
  1763  	up    *chain
  1764  	limit int // limit on entry to sym
  1765  }
  1766  
  1767  var morestack *sym.Symbol
  1768  
  1769  // TODO: Record enough information in new object files to
  1770  // allow stack checks here.
  1771  
  1772  func haslinkregister(ctxt *Link) bool {
  1773  	return ctxt.FixedFrameSize() != 0
  1774  }
  1775  
  1776  func callsize(ctxt *Link) int {
  1777  	if haslinkregister(ctxt) {
  1778  		return 0
  1779  	}
  1780  	return ctxt.Arch.RegSize
  1781  }
  1782  
  1783  func (ctxt *Link) dostkcheck() {
  1784  	var ch chain
  1785  
  1786  	morestack = ctxt.Syms.Lookup("runtime.morestack", 0)
  1787  
  1788  	// Every splitting function ensures that there are at least StackLimit
  1789  	// bytes available below SP when the splitting prologue finishes.
  1790  	// If the splitting function calls F, then F begins execution with
  1791  	// at least StackLimit - callsize() bytes available.
  1792  	// Check that every function behaves correctly with this amount
  1793  	// of stack, following direct calls in order to piece together chains
  1794  	// of non-splitting functions.
  1795  	ch.up = nil
  1796  
  1797  	ch.limit = objabi.StackLimit - callsize(ctxt)
  1798  
  1799  	// Check every function, but do the nosplit functions in a first pass,
  1800  	// to make the printed failure chains as short as possible.
  1801  	for _, s := range ctxt.Textp {
  1802  		// runtime.racesymbolizethunk is called from gcc-compiled C
  1803  		// code running on the operating system thread stack.
  1804  		// It uses more than the usual amount of stack but that's okay.
  1805  		if s.Name == "runtime.racesymbolizethunk" {
  1806  			continue
  1807  		}
  1808  
  1809  		if s.Attr.NoSplit() {
  1810  			ch.sym = s
  1811  			stkcheck(ctxt, &ch, 0)
  1812  		}
  1813  	}
  1814  
  1815  	for _, s := range ctxt.Textp {
  1816  		if !s.Attr.NoSplit() {
  1817  			ch.sym = s
  1818  			stkcheck(ctxt, &ch, 0)
  1819  		}
  1820  	}
  1821  }
  1822  
  1823  func stkcheck(ctxt *Link, up *chain, depth int) int {
  1824  	limit := up.limit
  1825  	s := up.sym
  1826  
  1827  	// Don't duplicate work: only need to consider each
  1828  	// function at top of safe zone once.
  1829  	top := limit == objabi.StackLimit-callsize(ctxt)
  1830  	if top {
  1831  		if s.Attr.StackCheck() {
  1832  			return 0
  1833  		}
  1834  		s.Attr |= sym.AttrStackCheck
  1835  	}
  1836  
  1837  	if depth > 100 {
  1838  		Errorf(s, "nosplit stack check too deep")
  1839  		stkbroke(ctxt, up, 0)
  1840  		return -1
  1841  	}
  1842  
  1843  	if s.Attr.External() || s.FuncInfo == nil {
  1844  		// external function.
  1845  		// should never be called directly.
  1846  		// onlyctxt.Diagnose the direct caller.
  1847  		// TODO(mwhudson): actually think about this.
  1848  		// TODO(khr): disabled for now. Calls to external functions can only happen on the g0 stack.
  1849  		// See the trampolines in src/runtime/sys_darwin_$ARCH.go.
  1850  		if depth == 1 && s.Type != sym.SXREF && !ctxt.DynlinkingGo() &&
  1851  			ctxt.BuildMode != BuildModeCArchive && ctxt.BuildMode != BuildModePIE && ctxt.BuildMode != BuildModeCShared && ctxt.BuildMode != BuildModePlugin {
  1852  			//Errorf(s, "call to external function")
  1853  		}
  1854  		return -1
  1855  	}
  1856  
  1857  	if limit < 0 {
  1858  		stkbroke(ctxt, up, limit)
  1859  		return -1
  1860  	}
  1861  
  1862  	// morestack looks like it calls functions,
  1863  	// but it switches the stack pointer first.
  1864  	if s == morestack {
  1865  		return 0
  1866  	}
  1867  
  1868  	var ch chain
  1869  	ch.up = up
  1870  
  1871  	if !s.Attr.NoSplit() {
  1872  		// Ensure we have enough stack to call morestack.
  1873  		ch.limit = limit - callsize(ctxt)
  1874  		ch.sym = morestack
  1875  		if stkcheck(ctxt, &ch, depth+1) < 0 {
  1876  			return -1
  1877  		}
  1878  		if !top {
  1879  			return 0
  1880  		}
  1881  		// Raise limit to allow frame.
  1882  		locals := int32(0)
  1883  		if s.FuncInfo != nil {
  1884  			locals = s.FuncInfo.Locals
  1885  		}
  1886  		limit = int(objabi.StackLimit+locals) + int(ctxt.FixedFrameSize())
  1887  	}
  1888  
  1889  	// Walk through sp adjustments in function, consuming relocs.
  1890  	ri := 0
  1891  
  1892  	endr := len(s.R)
  1893  	var ch1 chain
  1894  	var pcsp Pciter
  1895  	var r *sym.Reloc
  1896  	for pciterinit(ctxt, &pcsp, &s.FuncInfo.Pcsp); pcsp.done == 0; pciternext(&pcsp) {
  1897  		// pcsp.value is in effect for [pcsp.pc, pcsp.nextpc).
  1898  
  1899  		// Check stack size in effect for this span.
  1900  		if int32(limit)-pcsp.value < 0 {
  1901  			stkbroke(ctxt, up, int(int32(limit)-pcsp.value))
  1902  			return -1
  1903  		}
  1904  
  1905  		// Process calls in this span.
  1906  		for ; ri < endr && uint32(s.R[ri].Off) < pcsp.nextpc; ri++ {
  1907  			r = &s.R[ri]
  1908  			switch r.Type {
  1909  			// Direct call.
  1910  			case objabi.R_CALL, objabi.R_CALLARM, objabi.R_CALLARM64, objabi.R_CALLPOWER, objabi.R_CALLMIPS:
  1911  				ch.limit = int(int32(limit) - pcsp.value - int32(callsize(ctxt)))
  1912  				ch.sym = r.Sym
  1913  				if stkcheck(ctxt, &ch, depth+1) < 0 {
  1914  					return -1
  1915  				}
  1916  
  1917  			// Indirect call. Assume it is a call to a splitting function,
  1918  			// so we have to make sure it can call morestack.
  1919  			// Arrange the data structures to report both calls, so that
  1920  			// if there is an error, stkprint shows all the steps involved.
  1921  			case objabi.R_CALLIND:
  1922  				ch.limit = int(int32(limit) - pcsp.value - int32(callsize(ctxt)))
  1923  
  1924  				ch.sym = nil
  1925  				ch1.limit = ch.limit - callsize(ctxt) // for morestack in called prologue
  1926  				ch1.up = &ch
  1927  				ch1.sym = morestack
  1928  				if stkcheck(ctxt, &ch1, depth+2) < 0 {
  1929  					return -1
  1930  				}
  1931  			}
  1932  		}
  1933  	}
  1934  
  1935  	return 0
  1936  }
  1937  
  1938  func stkbroke(ctxt *Link, ch *chain, limit int) {
  1939  	Errorf(ch.sym, "nosplit stack overflow")
  1940  	stkprint(ctxt, ch, limit)
  1941  }
  1942  
  1943  func stkprint(ctxt *Link, ch *chain, limit int) {
  1944  	var name string
  1945  
  1946  	if ch.sym != nil {
  1947  		name = ch.sym.Name
  1948  		if ch.sym.Attr.NoSplit() {
  1949  			name += " (nosplit)"
  1950  		}
  1951  	} else {
  1952  		name = "function pointer"
  1953  	}
  1954  
  1955  	if ch.up == nil {
  1956  		// top of chain.  ch->sym != nil.
  1957  		if ch.sym.Attr.NoSplit() {
  1958  			fmt.Printf("\t%d\tassumed on entry to %s\n", ch.limit, name)
  1959  		} else {
  1960  			fmt.Printf("\t%d\tguaranteed after split check in %s\n", ch.limit, name)
  1961  		}
  1962  	} else {
  1963  		stkprint(ctxt, ch.up, ch.limit+callsize(ctxt))
  1964  		if !haslinkregister(ctxt) {
  1965  			fmt.Printf("\t%d\ton entry to %s\n", ch.limit, name)
  1966  		}
  1967  	}
  1968  
  1969  	if ch.limit != limit {
  1970  		fmt.Printf("\t%d\tafter %s uses %d\n", limit, name, ch.limit-limit)
  1971  	}
  1972  }
  1973  
  1974  func usage() {
  1975  	fmt.Fprintf(os.Stderr, "usage: link [options] main.o\n")
  1976  	objabi.Flagprint(os.Stderr)
  1977  	Exit(2)
  1978  }
  1979  
  1980  type SymbolType int8
  1981  
  1982  const (
  1983  	// see also https://9p.io/magic/man2html/1/nm
  1984  	TextSym      SymbolType = 'T'
  1985  	DataSym      SymbolType = 'D'
  1986  	BSSSym       SymbolType = 'B'
  1987  	UndefinedSym SymbolType = 'U'
  1988  	TLSSym       SymbolType = 't'
  1989  	FrameSym     SymbolType = 'm'
  1990  	ParamSym     SymbolType = 'p'
  1991  	AutoSym      SymbolType = 'a'
  1992  
  1993  	// Deleted auto (not a real sym, just placeholder for type)
  1994  	DeletedAutoSym = 'x'
  1995  )
  1996  
  1997  func genasmsym(ctxt *Link, put func(*Link, *sym.Symbol, string, SymbolType, int64, *sym.Symbol)) {
  1998  	// These symbols won't show up in the first loop below because we
  1999  	// skip sym.STEXT symbols. Normal sym.STEXT symbols are emitted by walking textp.
  2000  	s := ctxt.Syms.Lookup("runtime.text", 0)
  2001  	if s.Type == sym.STEXT {
  2002  		// We've already included this symbol in ctxt.Textp
  2003  		// if ctxt.DynlinkingGo() && ctxt.HeadType == objabi.Hdarwin.
  2004  		// See data.go:/textaddress
  2005  		if !(ctxt.DynlinkingGo() && ctxt.HeadType == objabi.Hdarwin) {
  2006  			put(ctxt, s, s.Name, TextSym, s.Value, nil)
  2007  		}
  2008  	}
  2009  
  2010  	n := 0
  2011  
  2012  	// Generate base addresses for all text sections if there are multiple
  2013  	for _, sect := range Segtext.Sections {
  2014  		if n == 0 {
  2015  			n++
  2016  			continue
  2017  		}
  2018  		if sect.Name != ".text" {
  2019  			break
  2020  		}
  2021  		s = ctxt.Syms.ROLookup(fmt.Sprintf("runtime.text.%d", n), 0)
  2022  		if s == nil {
  2023  			break
  2024  		}
  2025  		if s.Type == sym.STEXT {
  2026  			put(ctxt, s, s.Name, TextSym, s.Value, nil)
  2027  		}
  2028  		n++
  2029  	}
  2030  
  2031  	s = ctxt.Syms.Lookup("runtime.etext", 0)
  2032  	if s.Type == sym.STEXT {
  2033  		// We've already included this symbol in ctxt.Textp
  2034  		// if ctxt.DynlinkingGo() && ctxt.HeadType == objabi.Hdarwin.
  2035  		// See data.go:/textaddress
  2036  		if !(ctxt.DynlinkingGo() && ctxt.HeadType == objabi.Hdarwin) {
  2037  			put(ctxt, s, s.Name, TextSym, s.Value, nil)
  2038  		}
  2039  	}
  2040  
  2041  	for _, s := range ctxt.Syms.Allsym {
  2042  		if s.Attr.NotInSymbolTable() {
  2043  			continue
  2044  		}
  2045  		if (s.Name == "" || s.Name[0] == '.') && s.Version == 0 && s.Name != ".rathole" && s.Name != ".TOC." {
  2046  			continue
  2047  		}
  2048  		switch s.Type {
  2049  		case sym.SCONST,
  2050  			sym.SRODATA,
  2051  			sym.SSYMTAB,
  2052  			sym.SPCLNTAB,
  2053  			sym.SINITARR,
  2054  			sym.SDATA,
  2055  			sym.SNOPTRDATA,
  2056  			sym.SELFROSECT,
  2057  			sym.SMACHOGOT,
  2058  			sym.STYPE,
  2059  			sym.SSTRING,
  2060  			sym.SGOSTRING,
  2061  			sym.SGOFUNC,
  2062  			sym.SGCBITS,
  2063  			sym.STYPERELRO,
  2064  			sym.SSTRINGRELRO,
  2065  			sym.SGOSTRINGRELRO,
  2066  			sym.SGOFUNCRELRO,
  2067  			sym.SGCBITSRELRO,
  2068  			sym.SRODATARELRO,
  2069  			sym.STYPELINK,
  2070  			sym.SITABLINK,
  2071  			sym.SWINDOWS:
  2072  			if !s.Attr.Reachable() {
  2073  				continue
  2074  			}
  2075  			put(ctxt, s, s.Name, DataSym, Symaddr(s), s.Gotype)
  2076  
  2077  		case sym.SBSS, sym.SNOPTRBSS:
  2078  			if !s.Attr.Reachable() {
  2079  				continue
  2080  			}
  2081  			if len(s.P) > 0 {
  2082  				Errorf(s, "should not be bss (size=%d type=%v special=%v)", len(s.P), s.Type, s.Attr.Special())
  2083  			}
  2084  			put(ctxt, s, s.Name, BSSSym, Symaddr(s), s.Gotype)
  2085  
  2086  		case sym.SHOSTOBJ:
  2087  			if ctxt.HeadType == objabi.Hwindows || ctxt.IsELF {
  2088  				put(ctxt, s, s.Name, UndefinedSym, s.Value, nil)
  2089  			}
  2090  
  2091  		case sym.SDYNIMPORT:
  2092  			if !s.Attr.Reachable() {
  2093  				continue
  2094  			}
  2095  			put(ctxt, s, s.Extname, UndefinedSym, 0, nil)
  2096  
  2097  		case sym.STLSBSS:
  2098  			if ctxt.LinkMode == LinkExternal {
  2099  				put(ctxt, s, s.Name, TLSSym, Symaddr(s), s.Gotype)
  2100  			}
  2101  		}
  2102  	}
  2103  
  2104  	var off int32
  2105  	for _, s := range ctxt.Textp {
  2106  		put(ctxt, s, s.Name, TextSym, s.Value, s.Gotype)
  2107  
  2108  		locals := int32(0)
  2109  		if s.FuncInfo != nil {
  2110  			locals = s.FuncInfo.Locals
  2111  		}
  2112  		// NOTE(ality): acid can't produce a stack trace without .frame symbols
  2113  		put(ctxt, nil, ".frame", FrameSym, int64(locals)+int64(ctxt.Arch.PtrSize), nil)
  2114  
  2115  		if s.FuncInfo == nil {
  2116  			continue
  2117  		}
  2118  		for _, a := range s.FuncInfo.Autom {
  2119  			if a.Name == objabi.A_DELETED_AUTO {
  2120  				put(ctxt, nil, "", DeletedAutoSym, 0, a.Gotype)
  2121  				continue
  2122  			}
  2123  
  2124  			// Emit a or p according to actual offset, even if label is wrong.
  2125  			// This avoids negative offsets, which cannot be encoded.
  2126  			if a.Name != objabi.A_AUTO && a.Name != objabi.A_PARAM {
  2127  				continue
  2128  			}
  2129  
  2130  			// compute offset relative to FP
  2131  			if a.Name == objabi.A_PARAM {
  2132  				off = a.Aoffset
  2133  			} else {
  2134  				off = a.Aoffset - int32(ctxt.Arch.PtrSize)
  2135  			}
  2136  
  2137  			// FP
  2138  			if off >= 0 {
  2139  				put(ctxt, nil, a.Asym.Name, ParamSym, int64(off), a.Gotype)
  2140  				continue
  2141  			}
  2142  
  2143  			// SP
  2144  			if off <= int32(-ctxt.Arch.PtrSize) {
  2145  				put(ctxt, nil, a.Asym.Name, AutoSym, -(int64(off) + int64(ctxt.Arch.PtrSize)), a.Gotype)
  2146  				continue
  2147  			}
  2148  			// Otherwise, off is addressing the saved program counter.
  2149  			// Something underhanded is going on. Say nothing.
  2150  		}
  2151  	}
  2152  
  2153  	if ctxt.Debugvlog != 0 || *flagN {
  2154  		ctxt.Logf("%5.2f symsize = %d\n", Cputime(), uint32(Symsize))
  2155  	}
  2156  }
  2157  
  2158  func Symaddr(s *sym.Symbol) int64 {
  2159  	if !s.Attr.Reachable() {
  2160  		Errorf(s, "unreachable symbol in symaddr")
  2161  	}
  2162  	return s.Value
  2163  }
  2164  
  2165  func (ctxt *Link) xdefine(p string, t sym.SymKind, v int64) {
  2166  	s := ctxt.Syms.Lookup(p, 0)
  2167  	s.Type = t
  2168  	s.Value = v
  2169  	s.Attr |= sym.AttrReachable
  2170  	s.Attr |= sym.AttrSpecial
  2171  	s.Attr |= sym.AttrLocal
  2172  }
  2173  
  2174  func datoff(s *sym.Symbol, addr int64) int64 {
  2175  	if uint64(addr) >= Segdata.Vaddr {
  2176  		return int64(uint64(addr) - Segdata.Vaddr + Segdata.Fileoff)
  2177  	}
  2178  	if uint64(addr) >= Segtext.Vaddr {
  2179  		return int64(uint64(addr) - Segtext.Vaddr + Segtext.Fileoff)
  2180  	}
  2181  	Errorf(s, "invalid datoff %#x", addr)
  2182  	return 0
  2183  }
  2184  
  2185  func Entryvalue(ctxt *Link) int64 {
  2186  	a := *flagEntrySymbol
  2187  	if a[0] >= '0' && a[0] <= '9' {
  2188  		return atolwhex(a)
  2189  	}
  2190  	s := ctxt.Syms.Lookup(a, 0)
  2191  	if s.Type == 0 {
  2192  		return *FlagTextAddr
  2193  	}
  2194  	if s.Type != sym.STEXT {
  2195  		Errorf(s, "entry not text")
  2196  	}
  2197  	return s.Value
  2198  }
  2199  
  2200  func undefsym(ctxt *Link, s *sym.Symbol) {
  2201  	var r *sym.Reloc
  2202  
  2203  	for i := 0; i < len(s.R); i++ {
  2204  		r = &s.R[i]
  2205  		if r.Sym == nil { // happens for some external ARM relocs
  2206  			continue
  2207  		}
  2208  		// TODO(mwhudson): the test of VisibilityHidden here probably doesn't make
  2209  		// sense and should be removed when someone has thought about it properly.
  2210  		if (r.Sym.Type == sym.Sxxx || r.Sym.Type == sym.SXREF) && !r.Sym.Attr.VisibilityHidden() {
  2211  			Errorf(s, "undefined: %q", r.Sym.Name)
  2212  		}
  2213  		if !r.Sym.Attr.Reachable() && r.Type != objabi.R_WEAKADDROFF {
  2214  			Errorf(s, "relocation target %q", r.Sym.Name)
  2215  		}
  2216  	}
  2217  }
  2218  
  2219  func (ctxt *Link) undef() {
  2220  	// undefsym performs checks (almost) identical to checks
  2221  	// that report undefined relocations in relocsym.
  2222  	// Both undefsym and relocsym can report same symbol as undefined,
  2223  	// which results in error message duplication (see #10978).
  2224  	//
  2225  	// The undef is run after Arch.Asmb and could detect some
  2226  	// programming errors there, but if object being linked is already
  2227  	// failed with errors, it is better to avoid duplicated errors.
  2228  	if nerrors > 0 {
  2229  		return
  2230  	}
  2231  
  2232  	for _, s := range ctxt.Textp {
  2233  		undefsym(ctxt, s)
  2234  	}
  2235  	for _, s := range datap {
  2236  		undefsym(ctxt, s)
  2237  	}
  2238  	if nerrors > 0 {
  2239  		errorexit()
  2240  	}
  2241  }
  2242  
  2243  func (ctxt *Link) callgraph() {
  2244  	if !*FlagC {
  2245  		return
  2246  	}
  2247  
  2248  	var i int
  2249  	var r *sym.Reloc
  2250  	for _, s := range ctxt.Textp {
  2251  		for i = 0; i < len(s.R); i++ {
  2252  			r = &s.R[i]
  2253  			if r.Sym == nil {
  2254  				continue
  2255  			}
  2256  			if (r.Type == objabi.R_CALL || r.Type == objabi.R_CALLARM || r.Type == objabi.R_CALLPOWER || r.Type == objabi.R_CALLMIPS) && r.Sym.Type == sym.STEXT {
  2257  				ctxt.Logf("%s calls %s\n", s.Name, r.Sym.Name)
  2258  			}
  2259  		}
  2260  	}
  2261  }
  2262  
  2263  func Rnd(v int64, r int64) int64 {
  2264  	if r <= 0 {
  2265  		return v
  2266  	}
  2267  	v += r - 1
  2268  	c := v % r
  2269  	if c < 0 {
  2270  		c += r
  2271  	}
  2272  	v -= c
  2273  	return v
  2274  }
  2275  
  2276  func bgetc(r *bio.Reader) int {
  2277  	c, err := r.ReadByte()
  2278  	if err != nil {
  2279  		if err != io.EOF {
  2280  			log.Fatalf("reading input: %v", err)
  2281  		}
  2282  		return -1
  2283  	}
  2284  	return int(c)
  2285  }
  2286  
  2287  type markKind uint8 // for postorder traversal
  2288  const (
  2289  	_ markKind = iota
  2290  	visiting
  2291  	visited
  2292  )
  2293  
  2294  func postorder(libs []*sym.Library) []*sym.Library {
  2295  	order := make([]*sym.Library, 0, len(libs)) // hold the result
  2296  	mark := make(map[*sym.Library]markKind, len(libs))
  2297  	for _, lib := range libs {
  2298  		dfs(lib, mark, &order)
  2299  	}
  2300  	return order
  2301  }
  2302  
  2303  func dfs(lib *sym.Library, mark map[*sym.Library]markKind, order *[]*sym.Library) {
  2304  	if mark[lib] == visited {
  2305  		return
  2306  	}
  2307  	if mark[lib] == visiting {
  2308  		panic("found import cycle while visiting " + lib.Pkg)
  2309  	}
  2310  	mark[lib] = visiting
  2311  	for _, i := range lib.Imports {
  2312  		dfs(i, mark, order)
  2313  	}
  2314  	mark[lib] = visited
  2315  	*order = append(*order, lib)
  2316  }
  2317  

View as plain text