...
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  	out, err := exec.Command(argv[0], argv[1:]...).CombinedOutput()
  1327  	if err != nil {
  1328  		Exitf("running %s failed: %v\n%s", argv[0], err, out)
  1329  	}
  1330  
  1331  	// Filter out useless linker warnings caused by bugs outside Go.
  1332  	// See also cmd/go/internal/work/exec.go's gccld method.
  1333  	var save [][]byte
  1334  	for _, line := range bytes.SplitAfter(out, []byte("\n")) {
  1335  		// golang.org/issue/26073 - Apple Xcode bug
  1336  		if bytes.Contains(line, []byte("ld: warning: text-based stub file")) {
  1337  			continue
  1338  		}
  1339  		save = append(save, line)
  1340  	}
  1341  	out = bytes.Join(save, nil)
  1342  
  1343  	if len(out) > 0 {
  1344  		// always print external output even if the command is successful, so that we don't
  1345  		// swallow linker warnings (see https://golang.org/issue/17935).
  1346  		ctxt.Logf("%s", out)
  1347  	}
  1348  
  1349  	if !*FlagS && !*FlagW && !debug_s && ctxt.HeadType == objabi.Hdarwin {
  1350  		dsym := filepath.Join(*flagTmpdir, "go.dwarf")
  1351  		if out, err := exec.Command("dsymutil", "-f", *flagOutfile, "-o", dsym).CombinedOutput(); err != nil {
  1352  			Exitf("%s: running dsymutil failed: %v\n%s", os.Args[0], err, out)
  1353  		}
  1354  		// Skip combining if `dsymutil` didn't generate a file. See #11994.
  1355  		if _, err := os.Stat(dsym); os.IsNotExist(err) {
  1356  			return
  1357  		}
  1358  		// For os.Rename to work reliably, must be in same directory as outfile.
  1359  		combinedOutput := *flagOutfile + "~"
  1360  		isIOS, err := machoCombineDwarf(ctxt, *flagOutfile, dsym, combinedOutput)
  1361  		if err != nil {
  1362  			Exitf("%s: combining dwarf failed: %v", os.Args[0], err)
  1363  		}
  1364  		if !isIOS {
  1365  			os.Remove(*flagOutfile)
  1366  			if err := os.Rename(combinedOutput, *flagOutfile); err != nil {
  1367  				Exitf("%s: %v", os.Args[0], err)
  1368  			}
  1369  		}
  1370  	}
  1371  }
  1372  
  1373  var createTrivialCOnce sync.Once
  1374  
  1375  func linkerFlagSupported(linker, flag string) bool {
  1376  	createTrivialCOnce.Do(func() {
  1377  		src := filepath.Join(*flagTmpdir, "trivial.c")
  1378  		if err := ioutil.WriteFile(src, []byte("int main() { return 0; }"), 0666); err != nil {
  1379  			Errorf(nil, "WriteFile trivial.c failed: %v", err)
  1380  		}
  1381  	})
  1382  
  1383  	cmd := exec.Command(linker, flag, "trivial.c")
  1384  	cmd.Dir = *flagTmpdir
  1385  	cmd.Env = append([]string{"LC_ALL=C"}, os.Environ()...)
  1386  	out, err := cmd.CombinedOutput()
  1387  	// GCC says "unrecognized command line option ‘-no-pie’"
  1388  	// clang says "unknown argument: '-no-pie'"
  1389  	return err == nil && !bytes.Contains(out, []byte("unrecognized")) && !bytes.Contains(out, []byte("unknown"))
  1390  }
  1391  
  1392  // hostlinkArchArgs returns arguments to pass to the external linker
  1393  // based on the architecture.
  1394  func hostlinkArchArgs(arch *sys.Arch) []string {
  1395  	switch arch.Family {
  1396  	case sys.I386:
  1397  		return []string{"-m32"}
  1398  	case sys.AMD64, sys.PPC64, sys.S390X:
  1399  		return []string{"-m64"}
  1400  	case sys.ARM:
  1401  		return []string{"-marm"}
  1402  	case sys.ARM64:
  1403  		// nothing needed
  1404  	case sys.MIPS64:
  1405  		return []string{"-mabi=64"}
  1406  	case sys.MIPS:
  1407  		return []string{"-mabi=32"}
  1408  	}
  1409  	return nil
  1410  }
  1411  
  1412  // ldobj loads an input object. If it is a host object (an object
  1413  // compiled by a non-Go compiler) it returns the Hostobj pointer. If
  1414  // it is a Go object, it returns nil.
  1415  func ldobj(ctxt *Link, f *bio.Reader, lib *sym.Library, length int64, pn string, file string) *Hostobj {
  1416  	pkg := objabi.PathToPrefix(lib.Pkg)
  1417  
  1418  	eof := f.Offset() + length
  1419  	start := f.Offset()
  1420  	c1 := bgetc(f)
  1421  	c2 := bgetc(f)
  1422  	c3 := bgetc(f)
  1423  	c4 := bgetc(f)
  1424  	f.Seek(start, 0)
  1425  
  1426  	magic := uint32(c1)<<24 | uint32(c2)<<16 | uint32(c3)<<8 | uint32(c4)
  1427  	if magic == 0x7f454c46 { // \x7F E L F
  1428  		ldelf := func(ctxt *Link, f *bio.Reader, pkg string, length int64, pn string) {
  1429  			textp, flags, err := loadelf.Load(ctxt.Arch, ctxt.Syms, f, pkg, length, pn, ehdr.flags)
  1430  			if err != nil {
  1431  				Errorf(nil, "%v", err)
  1432  				return
  1433  			}
  1434  			ehdr.flags = flags
  1435  			ctxt.Textp = append(ctxt.Textp, textp...)
  1436  		}
  1437  		return ldhostobj(ldelf, ctxt.HeadType, f, pkg, length, pn, file)
  1438  	}
  1439  
  1440  	if magic&^1 == 0xfeedface || magic&^0x01000000 == 0xcefaedfe {
  1441  		ldmacho := func(ctxt *Link, f *bio.Reader, pkg string, length int64, pn string) {
  1442  			textp, err := loadmacho.Load(ctxt.Arch, ctxt.Syms, f, pkg, length, pn)
  1443  			if err != nil {
  1444  				Errorf(nil, "%v", err)
  1445  				return
  1446  			}
  1447  			ctxt.Textp = append(ctxt.Textp, textp...)
  1448  		}
  1449  		return ldhostobj(ldmacho, ctxt.HeadType, f, pkg, length, pn, file)
  1450  	}
  1451  
  1452  	if c1 == 0x4c && c2 == 0x01 || c1 == 0x64 && c2 == 0x86 {
  1453  		ldpe := func(ctxt *Link, f *bio.Reader, pkg string, length int64, pn string) {
  1454  			textp, rsrc, err := loadpe.Load(ctxt.Arch, ctxt.Syms, f, pkg, length, pn)
  1455  			if err != nil {
  1456  				Errorf(nil, "%v", err)
  1457  				return
  1458  			}
  1459  			if rsrc != nil {
  1460  				setpersrc(ctxt, rsrc)
  1461  			}
  1462  			ctxt.Textp = append(ctxt.Textp, textp...)
  1463  		}
  1464  		return ldhostobj(ldpe, ctxt.HeadType, f, pkg, length, pn, file)
  1465  	}
  1466  
  1467  	/* check the header */
  1468  	line, err := f.ReadString('\n')
  1469  	if err != nil {
  1470  		Errorf(nil, "truncated object file: %s: %v", pn, err)
  1471  		return nil
  1472  	}
  1473  
  1474  	if !strings.HasPrefix(line, "go object ") {
  1475  		if strings.HasSuffix(pn, ".go") {
  1476  			Exitf("%s: uncompiled .go source file", pn)
  1477  			return nil
  1478  		}
  1479  
  1480  		if line == ctxt.Arch.Name {
  1481  			// old header format: just $GOOS
  1482  			Errorf(nil, "%s: stale object file", pn)
  1483  			return nil
  1484  		}
  1485  
  1486  		Errorf(nil, "%s: not an object file", pn)
  1487  		return nil
  1488  	}
  1489  
  1490  	// First, check that the basic GOOS, GOARCH, and Version match.
  1491  	t := fmt.Sprintf("%s %s %s ", objabi.GOOS, objabi.GOARCH, objabi.Version)
  1492  
  1493  	line = strings.TrimRight(line, "\n")
  1494  	if !strings.HasPrefix(line[10:]+" ", t) && !*flagF {
  1495  		Errorf(nil, "%s: object is [%s] expected [%s]", pn, line[10:], t)
  1496  		return nil
  1497  	}
  1498  
  1499  	// Second, check that longer lines match each other exactly,
  1500  	// so that the Go compiler and write additional information
  1501  	// that must be the same from run to run.
  1502  	if len(line) >= len(t)+10 {
  1503  		if theline == "" {
  1504  			theline = line[10:]
  1505  		} else if theline != line[10:] {
  1506  			Errorf(nil, "%s: object is [%s] expected [%s]", pn, line[10:], theline)
  1507  			return nil
  1508  		}
  1509  	}
  1510  
  1511  	// Skip over exports and other info -- ends with \n!\n.
  1512  	//
  1513  	// Note: It's possible for "\n!\n" to appear within the binary
  1514  	// package export data format. To avoid truncating the package
  1515  	// definition prematurely (issue 21703), we keep keep track of
  1516  	// how many "$$" delimiters we've seen.
  1517  
  1518  	import0 := f.Offset()
  1519  
  1520  	c1 = '\n' // the last line ended in \n
  1521  	c2 = bgetc(f)
  1522  	c3 = bgetc(f)
  1523  	markers := 0
  1524  	for {
  1525  		if c1 == '\n' {
  1526  			if markers%2 == 0 && c2 == '!' && c3 == '\n' {
  1527  				break
  1528  			}
  1529  			if c2 == '$' && c3 == '$' {
  1530  				markers++
  1531  			}
  1532  		}
  1533  
  1534  		c1 = c2
  1535  		c2 = c3
  1536  		c3 = bgetc(f)
  1537  		if c3 == -1 {
  1538  			Errorf(nil, "truncated object file: %s", pn)
  1539  			return nil
  1540  		}
  1541  	}
  1542  
  1543  	import1 := f.Offset()
  1544  
  1545  	f.Seek(import0, 0)
  1546  	ldpkg(ctxt, f, lib, import1-import0-2, pn) // -2 for !\n
  1547  	f.Seek(import1, 0)
  1548  
  1549  	objfile.Load(ctxt.Arch, ctxt.Syms, f, lib, eof-f.Offset(), pn)
  1550  	addImports(ctxt, lib, pn)
  1551  	return nil
  1552  }
  1553  
  1554  func readelfsymboldata(ctxt *Link, f *elf.File, sym *elf.Symbol) []byte {
  1555  	data := make([]byte, sym.Size)
  1556  	sect := f.Sections[sym.Section]
  1557  	if sect.Type != elf.SHT_PROGBITS && sect.Type != elf.SHT_NOTE {
  1558  		Errorf(nil, "reading %s from non-data section", sym.Name)
  1559  	}
  1560  	n, err := sect.ReadAt(data, int64(sym.Value-sect.Addr))
  1561  	if uint64(n) != sym.Size {
  1562  		Errorf(nil, "reading contents of %s: %v", sym.Name, err)
  1563  	}
  1564  	return data
  1565  }
  1566  
  1567  func readwithpad(r io.Reader, sz int32) ([]byte, error) {
  1568  	data := make([]byte, Rnd(int64(sz), 4))
  1569  	_, err := io.ReadFull(r, data)
  1570  	if err != nil {
  1571  		return nil, err
  1572  	}
  1573  	data = data[:sz]
  1574  	return data, nil
  1575  }
  1576  
  1577  func readnote(f *elf.File, name []byte, typ int32) ([]byte, error) {
  1578  	for _, sect := range f.Sections {
  1579  		if sect.Type != elf.SHT_NOTE {
  1580  			continue
  1581  		}
  1582  		r := sect.Open()
  1583  		for {
  1584  			var namesize, descsize, noteType int32
  1585  			err := binary.Read(r, f.ByteOrder, &namesize)
  1586  			if err != nil {
  1587  				if err == io.EOF {
  1588  					break
  1589  				}
  1590  				return nil, fmt.Errorf("read namesize failed: %v", err)
  1591  			}
  1592  			err = binary.Read(r, f.ByteOrder, &descsize)
  1593  			if err != nil {
  1594  				return nil, fmt.Errorf("read descsize failed: %v", err)
  1595  			}
  1596  			err = binary.Read(r, f.ByteOrder, &noteType)
  1597  			if err != nil {
  1598  				return nil, fmt.Errorf("read type failed: %v", err)
  1599  			}
  1600  			noteName, err := readwithpad(r, namesize)
  1601  			if err != nil {
  1602  				return nil, fmt.Errorf("read name failed: %v", err)
  1603  			}
  1604  			desc, err := readwithpad(r, descsize)
  1605  			if err != nil {
  1606  				return nil, fmt.Errorf("read desc failed: %v", err)
  1607  			}
  1608  			if string(name) == string(noteName) && typ == noteType {
  1609  				return desc, nil
  1610  			}
  1611  		}
  1612  	}
  1613  	return nil, nil
  1614  }
  1615  
  1616  func findshlib(ctxt *Link, shlib string) string {
  1617  	if filepath.IsAbs(shlib) {
  1618  		return shlib
  1619  	}
  1620  	for _, libdir := range ctxt.Libdir {
  1621  		libpath := filepath.Join(libdir, shlib)
  1622  		if _, err := os.Stat(libpath); err == nil {
  1623  			return libpath
  1624  		}
  1625  	}
  1626  	Errorf(nil, "cannot find shared library: %s", shlib)
  1627  	return ""
  1628  }
  1629  
  1630  func ldshlibsyms(ctxt *Link, shlib string) {
  1631  	var libpath string
  1632  	if filepath.IsAbs(shlib) {
  1633  		libpath = shlib
  1634  		shlib = filepath.Base(shlib)
  1635  	} else {
  1636  		libpath = findshlib(ctxt, shlib)
  1637  		if libpath == "" {
  1638  			return
  1639  		}
  1640  	}
  1641  	for _, processedlib := range ctxt.Shlibs {
  1642  		if processedlib.Path == libpath {
  1643  			return
  1644  		}
  1645  	}
  1646  	if ctxt.Debugvlog > 1 {
  1647  		ctxt.Logf("%5.2f ldshlibsyms: found library with name %s at %s\n", Cputime(), shlib, libpath)
  1648  	}
  1649  
  1650  	f, err := elf.Open(libpath)
  1651  	if err != nil {
  1652  		Errorf(nil, "cannot open shared library: %s", libpath)
  1653  		return
  1654  	}
  1655  	defer f.Close()
  1656  
  1657  	hash, err := readnote(f, ELF_NOTE_GO_NAME, ELF_NOTE_GOABIHASH_TAG)
  1658  	if err != nil {
  1659  		Errorf(nil, "cannot read ABI hash from shared library %s: %v", libpath, err)
  1660  		return
  1661  	}
  1662  
  1663  	depsbytes, err := readnote(f, ELF_NOTE_GO_NAME, ELF_NOTE_GODEPS_TAG)
  1664  	if err != nil {
  1665  		Errorf(nil, "cannot read dep list from shared library %s: %v", libpath, err)
  1666  		return
  1667  	}
  1668  	var deps []string
  1669  	for _, dep := range strings.Split(string(depsbytes), "\n") {
  1670  		if dep == "" {
  1671  			continue
  1672  		}
  1673  		if !filepath.IsAbs(dep) {
  1674  			// If the dep can be interpreted as a path relative to the shlib
  1675  			// in which it was found, do that. Otherwise, we will leave it
  1676  			// to be resolved by libdir lookup.
  1677  			abs := filepath.Join(filepath.Dir(libpath), dep)
  1678  			if _, err := os.Stat(abs); err == nil {
  1679  				dep = abs
  1680  			}
  1681  		}
  1682  		deps = append(deps, dep)
  1683  	}
  1684  
  1685  	syms, err := f.DynamicSymbols()
  1686  	if err != nil {
  1687  		Errorf(nil, "cannot read symbols from shared library: %s", libpath)
  1688  		return
  1689  	}
  1690  	gcdataLocations := make(map[uint64]*sym.Symbol)
  1691  	for _, elfsym := range syms {
  1692  		if elf.ST_TYPE(elfsym.Info) == elf.STT_NOTYPE || elf.ST_TYPE(elfsym.Info) == elf.STT_SECTION {
  1693  			continue
  1694  		}
  1695  		lsym := ctxt.Syms.Lookup(elfsym.Name, 0)
  1696  		// Because loadlib above loads all .a files before loading any shared
  1697  		// libraries, any non-dynimport symbols we find that duplicate symbols
  1698  		// already loaded should be ignored (the symbols from the .a files
  1699  		// "win").
  1700  		if lsym.Type != 0 && lsym.Type != sym.SDYNIMPORT {
  1701  			continue
  1702  		}
  1703  		lsym.Type = sym.SDYNIMPORT
  1704  		lsym.ElfType = elf.ST_TYPE(elfsym.Info)
  1705  		lsym.Size = int64(elfsym.Size)
  1706  		if elfsym.Section != elf.SHN_UNDEF {
  1707  			// Set .File for the library that actually defines the symbol.
  1708  			lsym.File = libpath
  1709  			// The decodetype_* functions in decodetype.go need access to
  1710  			// the type data.
  1711  			if strings.HasPrefix(lsym.Name, "type.") && !strings.HasPrefix(lsym.Name, "type..") {
  1712  				lsym.P = readelfsymboldata(ctxt, f, &elfsym)
  1713  				gcdataLocations[elfsym.Value+2*uint64(ctxt.Arch.PtrSize)+8+1*uint64(ctxt.Arch.PtrSize)] = lsym
  1714  			}
  1715  		}
  1716  	}
  1717  	gcdataAddresses := make(map[*sym.Symbol]uint64)
  1718  	if ctxt.Arch.Family == sys.ARM64 {
  1719  		for _, sect := range f.Sections {
  1720  			if sect.Type == elf.SHT_RELA {
  1721  				var rela elf.Rela64
  1722  				rdr := sect.Open()
  1723  				for {
  1724  					err := binary.Read(rdr, f.ByteOrder, &rela)
  1725  					if err == io.EOF {
  1726  						break
  1727  					} else if err != nil {
  1728  						Errorf(nil, "reading relocation failed %v", err)
  1729  						return
  1730  					}
  1731  					t := elf.R_AARCH64(rela.Info & 0xffff)
  1732  					if t != elf.R_AARCH64_RELATIVE {
  1733  						continue
  1734  					}
  1735  					if lsym, ok := gcdataLocations[rela.Off]; ok {
  1736  						gcdataAddresses[lsym] = uint64(rela.Addend)
  1737  					}
  1738  				}
  1739  			}
  1740  		}
  1741  	}
  1742  
  1743  	ctxt.Shlibs = append(ctxt.Shlibs, Shlib{Path: libpath, Hash: hash, Deps: deps, File: f, gcdataAddresses: gcdataAddresses})
  1744  }
  1745  
  1746  func addsection(arch *sys.Arch, seg *sym.Segment, name string, rwx int) *sym.Section {
  1747  	sect := new(sym.Section)
  1748  	sect.Rwx = uint8(rwx)
  1749  	sect.Name = name
  1750  	sect.Seg = seg
  1751  	sect.Align = int32(arch.PtrSize) // everything is at least pointer-aligned
  1752  	seg.Sections = append(seg.Sections, sect)
  1753  	return sect
  1754  }
  1755  
  1756  func Le16(b []byte) uint16 {
  1757  	return uint16(b[0]) | uint16(b[1])<<8
  1758  }
  1759  
  1760  func Le32(b []byte) uint32 {
  1761  	return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
  1762  }
  1763  
  1764  func Le64(b []byte) uint64 {
  1765  	return uint64(Le32(b)) | uint64(Le32(b[4:]))<<32
  1766  }
  1767  
  1768  func Be16(b []byte) uint16 {
  1769  	return uint16(b[0])<<8 | uint16(b[1])
  1770  }
  1771  
  1772  func Be32(b []byte) uint32 {
  1773  	return uint32(b[0])<<24 | uint32(b[1])<<16 | uint32(b[2])<<8 | uint32(b[3])
  1774  }
  1775  
  1776  type chain struct {
  1777  	sym   *sym.Symbol
  1778  	up    *chain
  1779  	limit int // limit on entry to sym
  1780  }
  1781  
  1782  var morestack *sym.Symbol
  1783  
  1784  // TODO: Record enough information in new object files to
  1785  // allow stack checks here.
  1786  
  1787  func haslinkregister(ctxt *Link) bool {
  1788  	return ctxt.FixedFrameSize() != 0
  1789  }
  1790  
  1791  func callsize(ctxt *Link) int {
  1792  	if haslinkregister(ctxt) {
  1793  		return 0
  1794  	}
  1795  	return ctxt.Arch.RegSize
  1796  }
  1797  
  1798  func (ctxt *Link) dostkcheck() {
  1799  	var ch chain
  1800  
  1801  	morestack = ctxt.Syms.Lookup("runtime.morestack", 0)
  1802  
  1803  	// Every splitting function ensures that there are at least StackLimit
  1804  	// bytes available below SP when the splitting prologue finishes.
  1805  	// If the splitting function calls F, then F begins execution with
  1806  	// at least StackLimit - callsize() bytes available.
  1807  	// Check that every function behaves correctly with this amount
  1808  	// of stack, following direct calls in order to piece together chains
  1809  	// of non-splitting functions.
  1810  	ch.up = nil
  1811  
  1812  	ch.limit = objabi.StackLimit - callsize(ctxt)
  1813  
  1814  	// Check every function, but do the nosplit functions in a first pass,
  1815  	// to make the printed failure chains as short as possible.
  1816  	for _, s := range ctxt.Textp {
  1817  		// runtime.racesymbolizethunk is called from gcc-compiled C
  1818  		// code running on the operating system thread stack.
  1819  		// It uses more than the usual amount of stack but that's okay.
  1820  		if s.Name == "runtime.racesymbolizethunk" {
  1821  			continue
  1822  		}
  1823  
  1824  		if s.Attr.NoSplit() {
  1825  			ch.sym = s
  1826  			stkcheck(ctxt, &ch, 0)
  1827  		}
  1828  	}
  1829  
  1830  	for _, s := range ctxt.Textp {
  1831  		if !s.Attr.NoSplit() {
  1832  			ch.sym = s
  1833  			stkcheck(ctxt, &ch, 0)
  1834  		}
  1835  	}
  1836  }
  1837  
  1838  func stkcheck(ctxt *Link, up *chain, depth int) int {
  1839  	limit := up.limit
  1840  	s := up.sym
  1841  
  1842  	// Don't duplicate work: only need to consider each
  1843  	// function at top of safe zone once.
  1844  	top := limit == objabi.StackLimit-callsize(ctxt)
  1845  	if top {
  1846  		if s.Attr.StackCheck() {
  1847  			return 0
  1848  		}
  1849  		s.Attr |= sym.AttrStackCheck
  1850  	}
  1851  
  1852  	if depth > 100 {
  1853  		Errorf(s, "nosplit stack check too deep")
  1854  		stkbroke(ctxt, up, 0)
  1855  		return -1
  1856  	}
  1857  
  1858  	if s.Attr.External() || s.FuncInfo == nil {
  1859  		// external function.
  1860  		// should never be called directly.
  1861  		// onlyctxt.Diagnose the direct caller.
  1862  		// TODO(mwhudson): actually think about this.
  1863  		// TODO(khr): disabled for now. Calls to external functions can only happen on the g0 stack.
  1864  		// See the trampolines in src/runtime/sys_darwin_$ARCH.go.
  1865  		if depth == 1 && s.Type != sym.SXREF && !ctxt.DynlinkingGo() &&
  1866  			ctxt.BuildMode != BuildModeCArchive && ctxt.BuildMode != BuildModePIE && ctxt.BuildMode != BuildModeCShared && ctxt.BuildMode != BuildModePlugin {
  1867  			//Errorf(s, "call to external function")
  1868  		}
  1869  		return -1
  1870  	}
  1871  
  1872  	if limit < 0 {
  1873  		stkbroke(ctxt, up, limit)
  1874  		return -1
  1875  	}
  1876  
  1877  	// morestack looks like it calls functions,
  1878  	// but it switches the stack pointer first.
  1879  	if s == morestack {
  1880  		return 0
  1881  	}
  1882  
  1883  	var ch chain
  1884  	ch.up = up
  1885  
  1886  	if !s.Attr.NoSplit() {
  1887  		// Ensure we have enough stack to call morestack.
  1888  		ch.limit = limit - callsize(ctxt)
  1889  		ch.sym = morestack
  1890  		if stkcheck(ctxt, &ch, depth+1) < 0 {
  1891  			return -1
  1892  		}
  1893  		if !top {
  1894  			return 0
  1895  		}
  1896  		// Raise limit to allow frame.
  1897  		locals := int32(0)
  1898  		if s.FuncInfo != nil {
  1899  			locals = s.FuncInfo.Locals
  1900  		}
  1901  		limit = int(objabi.StackLimit+locals) + int(ctxt.FixedFrameSize())
  1902  	}
  1903  
  1904  	// Walk through sp adjustments in function, consuming relocs.
  1905  	ri := 0
  1906  
  1907  	endr := len(s.R)
  1908  	var ch1 chain
  1909  	var pcsp Pciter
  1910  	var r *sym.Reloc
  1911  	for pciterinit(ctxt, &pcsp, &s.FuncInfo.Pcsp); pcsp.done == 0; pciternext(&pcsp) {
  1912  		// pcsp.value is in effect for [pcsp.pc, pcsp.nextpc).
  1913  
  1914  		// Check stack size in effect for this span.
  1915  		if int32(limit)-pcsp.value < 0 {
  1916  			stkbroke(ctxt, up, int(int32(limit)-pcsp.value))
  1917  			return -1
  1918  		}
  1919  
  1920  		// Process calls in this span.
  1921  		for ; ri < endr && uint32(s.R[ri].Off) < pcsp.nextpc; ri++ {
  1922  			r = &s.R[ri]
  1923  			switch r.Type {
  1924  			// Direct call.
  1925  			case objabi.R_CALL, objabi.R_CALLARM, objabi.R_CALLARM64, objabi.R_CALLPOWER, objabi.R_CALLMIPS:
  1926  				ch.limit = int(int32(limit) - pcsp.value - int32(callsize(ctxt)))
  1927  				ch.sym = r.Sym
  1928  				if stkcheck(ctxt, &ch, depth+1) < 0 {
  1929  					return -1
  1930  				}
  1931  
  1932  			// Indirect call. Assume it is a call to a splitting function,
  1933  			// so we have to make sure it can call morestack.
  1934  			// Arrange the data structures to report both calls, so that
  1935  			// if there is an error, stkprint shows all the steps involved.
  1936  			case objabi.R_CALLIND:
  1937  				ch.limit = int(int32(limit) - pcsp.value - int32(callsize(ctxt)))
  1938  
  1939  				ch.sym = nil
  1940  				ch1.limit = ch.limit - callsize(ctxt) // for morestack in called prologue
  1941  				ch1.up = &ch
  1942  				ch1.sym = morestack
  1943  				if stkcheck(ctxt, &ch1, depth+2) < 0 {
  1944  					return -1
  1945  				}
  1946  			}
  1947  		}
  1948  	}
  1949  
  1950  	return 0
  1951  }
  1952  
  1953  func stkbroke(ctxt *Link, ch *chain, limit int) {
  1954  	Errorf(ch.sym, "nosplit stack overflow")
  1955  	stkprint(ctxt, ch, limit)
  1956  }
  1957  
  1958  func stkprint(ctxt *Link, ch *chain, limit int) {
  1959  	var name string
  1960  
  1961  	if ch.sym != nil {
  1962  		name = ch.sym.Name
  1963  		if ch.sym.Attr.NoSplit() {
  1964  			name += " (nosplit)"
  1965  		}
  1966  	} else {
  1967  		name = "function pointer"
  1968  	}
  1969  
  1970  	if ch.up == nil {
  1971  		// top of chain.  ch->sym != nil.
  1972  		if ch.sym.Attr.NoSplit() {
  1973  			fmt.Printf("\t%d\tassumed on entry to %s\n", ch.limit, name)
  1974  		} else {
  1975  			fmt.Printf("\t%d\tguaranteed after split check in %s\n", ch.limit, name)
  1976  		}
  1977  	} else {
  1978  		stkprint(ctxt, ch.up, ch.limit+callsize(ctxt))
  1979  		if !haslinkregister(ctxt) {
  1980  			fmt.Printf("\t%d\ton entry to %s\n", ch.limit, name)
  1981  		}
  1982  	}
  1983  
  1984  	if ch.limit != limit {
  1985  		fmt.Printf("\t%d\tafter %s uses %d\n", limit, name, ch.limit-limit)
  1986  	}
  1987  }
  1988  
  1989  func usage() {
  1990  	fmt.Fprintf(os.Stderr, "usage: link [options] main.o\n")
  1991  	objabi.Flagprint(os.Stderr)
  1992  	Exit(2)
  1993  }
  1994  
  1995  type SymbolType int8
  1996  
  1997  const (
  1998  	// see also https://9p.io/magic/man2html/1/nm
  1999  	TextSym      SymbolType = 'T'
  2000  	DataSym      SymbolType = 'D'
  2001  	BSSSym       SymbolType = 'B'
  2002  	UndefinedSym SymbolType = 'U'
  2003  	TLSSym       SymbolType = 't'
  2004  	FrameSym     SymbolType = 'm'
  2005  	ParamSym     SymbolType = 'p'
  2006  	AutoSym      SymbolType = 'a'
  2007  
  2008  	// Deleted auto (not a real sym, just placeholder for type)
  2009  	DeletedAutoSym = 'x'
  2010  )
  2011  
  2012  func genasmsym(ctxt *Link, put func(*Link, *sym.Symbol, string, SymbolType, int64, *sym.Symbol)) {
  2013  	// These symbols won't show up in the first loop below because we
  2014  	// skip sym.STEXT symbols. Normal sym.STEXT symbols are emitted by walking textp.
  2015  	s := ctxt.Syms.Lookup("runtime.text", 0)
  2016  	if s.Type == sym.STEXT {
  2017  		// We've already included this symbol in ctxt.Textp
  2018  		// if ctxt.DynlinkingGo() && ctxt.HeadType == objabi.Hdarwin.
  2019  		// See data.go:/textaddress
  2020  		if !(ctxt.DynlinkingGo() && ctxt.HeadType == objabi.Hdarwin) {
  2021  			put(ctxt, s, s.Name, TextSym, s.Value, nil)
  2022  		}
  2023  	}
  2024  
  2025  	n := 0
  2026  
  2027  	// Generate base addresses for all text sections if there are multiple
  2028  	for _, sect := range Segtext.Sections {
  2029  		if n == 0 {
  2030  			n++
  2031  			continue
  2032  		}
  2033  		if sect.Name != ".text" {
  2034  			break
  2035  		}
  2036  		s = ctxt.Syms.ROLookup(fmt.Sprintf("runtime.text.%d", n), 0)
  2037  		if s == nil {
  2038  			break
  2039  		}
  2040  		if s.Type == sym.STEXT {
  2041  			put(ctxt, s, s.Name, TextSym, s.Value, nil)
  2042  		}
  2043  		n++
  2044  	}
  2045  
  2046  	s = ctxt.Syms.Lookup("runtime.etext", 0)
  2047  	if s.Type == sym.STEXT {
  2048  		// We've already included this symbol in ctxt.Textp
  2049  		// if ctxt.DynlinkingGo() && ctxt.HeadType == objabi.Hdarwin.
  2050  		// See data.go:/textaddress
  2051  		if !(ctxt.DynlinkingGo() && ctxt.HeadType == objabi.Hdarwin) {
  2052  			put(ctxt, s, s.Name, TextSym, s.Value, nil)
  2053  		}
  2054  	}
  2055  
  2056  	for _, s := range ctxt.Syms.Allsym {
  2057  		if s.Attr.NotInSymbolTable() {
  2058  			continue
  2059  		}
  2060  		if (s.Name == "" || s.Name[0] == '.') && s.Version == 0 && s.Name != ".rathole" && s.Name != ".TOC." {
  2061  			continue
  2062  		}
  2063  		switch s.Type {
  2064  		case sym.SCONST,
  2065  			sym.SRODATA,
  2066  			sym.SSYMTAB,
  2067  			sym.SPCLNTAB,
  2068  			sym.SINITARR,
  2069  			sym.SDATA,
  2070  			sym.SNOPTRDATA,
  2071  			sym.SELFROSECT,
  2072  			sym.SMACHOGOT,
  2073  			sym.STYPE,
  2074  			sym.SSTRING,
  2075  			sym.SGOSTRING,
  2076  			sym.SGOFUNC,
  2077  			sym.SGCBITS,
  2078  			sym.STYPERELRO,
  2079  			sym.SSTRINGRELRO,
  2080  			sym.SGOSTRINGRELRO,
  2081  			sym.SGOFUNCRELRO,
  2082  			sym.SGCBITSRELRO,
  2083  			sym.SRODATARELRO,
  2084  			sym.STYPELINK,
  2085  			sym.SITABLINK,
  2086  			sym.SWINDOWS:
  2087  			if !s.Attr.Reachable() {
  2088  				continue
  2089  			}
  2090  			put(ctxt, s, s.Name, DataSym, Symaddr(s), s.Gotype)
  2091  
  2092  		case sym.SBSS, sym.SNOPTRBSS:
  2093  			if !s.Attr.Reachable() {
  2094  				continue
  2095  			}
  2096  			if len(s.P) > 0 {
  2097  				Errorf(s, "should not be bss (size=%d type=%v special=%v)", len(s.P), s.Type, s.Attr.Special())
  2098  			}
  2099  			put(ctxt, s, s.Name, BSSSym, Symaddr(s), s.Gotype)
  2100  
  2101  		case sym.SHOSTOBJ:
  2102  			if ctxt.HeadType == objabi.Hwindows || ctxt.IsELF {
  2103  				put(ctxt, s, s.Name, UndefinedSym, s.Value, nil)
  2104  			}
  2105  
  2106  		case sym.SDYNIMPORT:
  2107  			if !s.Attr.Reachable() {
  2108  				continue
  2109  			}
  2110  			put(ctxt, s, s.Extname, UndefinedSym, 0, nil)
  2111  
  2112  		case sym.STLSBSS:
  2113  			if ctxt.LinkMode == LinkExternal {
  2114  				put(ctxt, s, s.Name, TLSSym, Symaddr(s), s.Gotype)
  2115  			}
  2116  		}
  2117  	}
  2118  
  2119  	var off int32
  2120  	for _, s := range ctxt.Textp {
  2121  		put(ctxt, s, s.Name, TextSym, s.Value, s.Gotype)
  2122  
  2123  		locals := int32(0)
  2124  		if s.FuncInfo != nil {
  2125  			locals = s.FuncInfo.Locals
  2126  		}
  2127  		// NOTE(ality): acid can't produce a stack trace without .frame symbols
  2128  		put(ctxt, nil, ".frame", FrameSym, int64(locals)+int64(ctxt.Arch.PtrSize), nil)
  2129  
  2130  		if s.FuncInfo == nil {
  2131  			continue
  2132  		}
  2133  		for _, a := range s.FuncInfo.Autom {
  2134  			if a.Name == objabi.A_DELETED_AUTO {
  2135  				put(ctxt, nil, "", DeletedAutoSym, 0, a.Gotype)
  2136  				continue
  2137  			}
  2138  
  2139  			// Emit a or p according to actual offset, even if label is wrong.
  2140  			// This avoids negative offsets, which cannot be encoded.
  2141  			if a.Name != objabi.A_AUTO && a.Name != objabi.A_PARAM {
  2142  				continue
  2143  			}
  2144  
  2145  			// compute offset relative to FP
  2146  			if a.Name == objabi.A_PARAM {
  2147  				off = a.Aoffset
  2148  			} else {
  2149  				off = a.Aoffset - int32(ctxt.Arch.PtrSize)
  2150  			}
  2151  
  2152  			// FP
  2153  			if off >= 0 {
  2154  				put(ctxt, nil, a.Asym.Name, ParamSym, int64(off), a.Gotype)
  2155  				continue
  2156  			}
  2157  
  2158  			// SP
  2159  			if off <= int32(-ctxt.Arch.PtrSize) {
  2160  				put(ctxt, nil, a.Asym.Name, AutoSym, -(int64(off) + int64(ctxt.Arch.PtrSize)), a.Gotype)
  2161  				continue
  2162  			}
  2163  			// Otherwise, off is addressing the saved program counter.
  2164  			// Something underhanded is going on. Say nothing.
  2165  		}
  2166  	}
  2167  
  2168  	if ctxt.Debugvlog != 0 || *flagN {
  2169  		ctxt.Logf("%5.2f symsize = %d\n", Cputime(), uint32(Symsize))
  2170  	}
  2171  }
  2172  
  2173  func Symaddr(s *sym.Symbol) int64 {
  2174  	if !s.Attr.Reachable() {
  2175  		Errorf(s, "unreachable symbol in symaddr")
  2176  	}
  2177  	return s.Value
  2178  }
  2179  
  2180  func (ctxt *Link) xdefine(p string, t sym.SymKind, v int64) {
  2181  	s := ctxt.Syms.Lookup(p, 0)
  2182  	s.Type = t
  2183  	s.Value = v
  2184  	s.Attr |= sym.AttrReachable
  2185  	s.Attr |= sym.AttrSpecial
  2186  	s.Attr |= sym.AttrLocal
  2187  }
  2188  
  2189  func datoff(s *sym.Symbol, addr int64) int64 {
  2190  	if uint64(addr) >= Segdata.Vaddr {
  2191  		return int64(uint64(addr) - Segdata.Vaddr + Segdata.Fileoff)
  2192  	}
  2193  	if uint64(addr) >= Segtext.Vaddr {
  2194  		return int64(uint64(addr) - Segtext.Vaddr + Segtext.Fileoff)
  2195  	}
  2196  	Errorf(s, "invalid datoff %#x", addr)
  2197  	return 0
  2198  }
  2199  
  2200  func Entryvalue(ctxt *Link) int64 {
  2201  	a := *flagEntrySymbol
  2202  	if a[0] >= '0' && a[0] <= '9' {
  2203  		return atolwhex(a)
  2204  	}
  2205  	s := ctxt.Syms.Lookup(a, 0)
  2206  	if s.Type == 0 {
  2207  		return *FlagTextAddr
  2208  	}
  2209  	if s.Type != sym.STEXT {
  2210  		Errorf(s, "entry not text")
  2211  	}
  2212  	return s.Value
  2213  }
  2214  
  2215  func undefsym(ctxt *Link, s *sym.Symbol) {
  2216  	var r *sym.Reloc
  2217  
  2218  	for i := 0; i < len(s.R); i++ {
  2219  		r = &s.R[i]
  2220  		if r.Sym == nil { // happens for some external ARM relocs
  2221  			continue
  2222  		}
  2223  		// TODO(mwhudson): the test of VisibilityHidden here probably doesn't make
  2224  		// sense and should be removed when someone has thought about it properly.
  2225  		if (r.Sym.Type == sym.Sxxx || r.Sym.Type == sym.SXREF) && !r.Sym.Attr.VisibilityHidden() {
  2226  			Errorf(s, "undefined: %q", r.Sym.Name)
  2227  		}
  2228  		if !r.Sym.Attr.Reachable() && r.Type != objabi.R_WEAKADDROFF {
  2229  			Errorf(s, "relocation target %q", r.Sym.Name)
  2230  		}
  2231  	}
  2232  }
  2233  
  2234  func (ctxt *Link) undef() {
  2235  	// undefsym performs checks (almost) identical to checks
  2236  	// that report undefined relocations in relocsym.
  2237  	// Both undefsym and relocsym can report same symbol as undefined,
  2238  	// which results in error message duplication (see #10978).
  2239  	//
  2240  	// The undef is run after Arch.Asmb and could detect some
  2241  	// programming errors there, but if object being linked is already
  2242  	// failed with errors, it is better to avoid duplicated errors.
  2243  	if nerrors > 0 {
  2244  		return
  2245  	}
  2246  
  2247  	for _, s := range ctxt.Textp {
  2248  		undefsym(ctxt, s)
  2249  	}
  2250  	for _, s := range datap {
  2251  		undefsym(ctxt, s)
  2252  	}
  2253  	if nerrors > 0 {
  2254  		errorexit()
  2255  	}
  2256  }
  2257  
  2258  func (ctxt *Link) callgraph() {
  2259  	if !*FlagC {
  2260  		return
  2261  	}
  2262  
  2263  	var i int
  2264  	var r *sym.Reloc
  2265  	for _, s := range ctxt.Textp {
  2266  		for i = 0; i < len(s.R); i++ {
  2267  			r = &s.R[i]
  2268  			if r.Sym == nil {
  2269  				continue
  2270  			}
  2271  			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 {
  2272  				ctxt.Logf("%s calls %s\n", s.Name, r.Sym.Name)
  2273  			}
  2274  		}
  2275  	}
  2276  }
  2277  
  2278  func Rnd(v int64, r int64) int64 {
  2279  	if r <= 0 {
  2280  		return v
  2281  	}
  2282  	v += r - 1
  2283  	c := v % r
  2284  	if c < 0 {
  2285  		c += r
  2286  	}
  2287  	v -= c
  2288  	return v
  2289  }
  2290  
  2291  func bgetc(r *bio.Reader) int {
  2292  	c, err := r.ReadByte()
  2293  	if err != nil {
  2294  		if err != io.EOF {
  2295  			log.Fatalf("reading input: %v", err)
  2296  		}
  2297  		return -1
  2298  	}
  2299  	return int(c)
  2300  }
  2301  
  2302  type markKind uint8 // for postorder traversal
  2303  const (
  2304  	_ markKind = iota
  2305  	visiting
  2306  	visited
  2307  )
  2308  
  2309  func postorder(libs []*sym.Library) []*sym.Library {
  2310  	order := make([]*sym.Library, 0, len(libs)) // hold the result
  2311  	mark := make(map[*sym.Library]markKind, len(libs))
  2312  	for _, lib := range libs {
  2313  		dfs(lib, mark, &order)
  2314  	}
  2315  	return order
  2316  }
  2317  
  2318  func dfs(lib *sym.Library, mark map[*sym.Library]markKind, order *[]*sym.Library) {
  2319  	if mark[lib] == visited {
  2320  		return
  2321  	}
  2322  	if mark[lib] == visiting {
  2323  		panic("found import cycle while visiting " + lib.Pkg)
  2324  	}
  2325  	mark[lib] = visiting
  2326  	for _, i := range lib.Imports {
  2327  		dfs(i, mark, order)
  2328  	}
  2329  	mark[lib] = visited
  2330  	*order = append(*order, lib)
  2331  }
  2332  

View as plain text