...
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  			defer f.Close()
   986  			if _, err := f.Seek(h.off, 0); err != nil {
   987  				Exitf("cannot seek %s: %v", h.pn, err)
   988  			}
   989  
   990  			w, err := os.Create(dst)
   991  			if err != nil {
   992  				Exitf("cannot create %s: %v", dst, err)
   993  			}
   994  			if _, err := io.CopyN(w, f, h.length); err != nil {
   995  				Exitf("cannot write %s: %v", dst, err)
   996  			}
   997  			if err := w.Close(); err != nil {
   998  				Exitf("cannot close %s: %v", dst, err)
   999  			}
  1000  		}()
  1001  	}
  1002  	wg.Wait()
  1003  	return paths
  1004  }
  1005  
  1006  // writeGDBLinkerScript creates gcc linker script file in temp
  1007  // directory. writeGDBLinkerScript returns created file path.
  1008  // The script is used to work around gcc bug
  1009  // (see https://golang.org/issue/20183 for details).
  1010  func writeGDBLinkerScript() string {
  1011  	name := "fix_debug_gdb_scripts.ld"
  1012  	path := filepath.Join(*flagTmpdir, name)
  1013  	src := `SECTIONS
  1014  {
  1015    .debug_gdb_scripts BLOCK(__section_alignment__) (NOLOAD) :
  1016    {
  1017      *(.debug_gdb_scripts)
  1018    }
  1019  }
  1020  INSERT AFTER .debug_types;
  1021  `
  1022  	err := ioutil.WriteFile(path, []byte(src), 0666)
  1023  	if err != nil {
  1024  		Errorf(nil, "WriteFile %s failed: %v", name, err)
  1025  	}
  1026  	return path
  1027  }
  1028  
  1029  // archive builds a .a archive from the hostobj object files.
  1030  func (ctxt *Link) archive() {
  1031  	if ctxt.BuildMode != BuildModeCArchive {
  1032  		return
  1033  	}
  1034  
  1035  	if *flagExtar == "" {
  1036  		*flagExtar = "ar"
  1037  	}
  1038  
  1039  	mayberemoveoutfile()
  1040  
  1041  	// Force the buffer to flush here so that external
  1042  	// tools will see a complete file.
  1043  	ctxt.Out.Flush()
  1044  	if err := ctxt.Out.f.Close(); err != nil {
  1045  		Exitf("close: %v", err)
  1046  	}
  1047  	ctxt.Out.f = nil
  1048  
  1049  	argv := []string{*flagExtar, "-q", "-c", "-s", *flagOutfile}
  1050  	argv = append(argv, filepath.Join(*flagTmpdir, "go.o"))
  1051  	argv = append(argv, hostobjCopy()...)
  1052  
  1053  	if ctxt.Debugvlog != 0 {
  1054  		ctxt.Logf("archive: %s\n", strings.Join(argv, " "))
  1055  	}
  1056  
  1057  	if out, err := exec.Command(argv[0], argv[1:]...).CombinedOutput(); err != nil {
  1058  		Exitf("running %s failed: %v\n%s", argv[0], err, out)
  1059  	}
  1060  }
  1061  
  1062  func (ctxt *Link) hostlink() {
  1063  	if ctxt.LinkMode != LinkExternal || nerrors > 0 {
  1064  		return
  1065  	}
  1066  	if ctxt.BuildMode == BuildModeCArchive {
  1067  		return
  1068  	}
  1069  
  1070  	if *flagExtld == "" {
  1071  		*flagExtld = "gcc"
  1072  	}
  1073  
  1074  	var argv []string
  1075  	argv = append(argv, *flagExtld)
  1076  	argv = append(argv, hostlinkArchArgs(ctxt.Arch)...)
  1077  
  1078  	if *FlagS || debug_s {
  1079  		if ctxt.HeadType == objabi.Hdarwin {
  1080  			// Recent versions of macOS print
  1081  			//	ld: warning: option -s is obsolete and being ignored
  1082  			// so do not pass any arguments.
  1083  		} else {
  1084  			argv = append(argv, "-s")
  1085  		}
  1086  	}
  1087  
  1088  	switch ctxt.HeadType {
  1089  	case objabi.Hdarwin:
  1090  		argv = append(argv, "-Wl,-headerpad,1144")
  1091  		if ctxt.DynlinkingGo() {
  1092  			argv = append(argv, "-Wl,-flat_namespace")
  1093  		}
  1094  		if ctxt.BuildMode == BuildModeExe && !ctxt.Arch.InFamily(sys.ARM64) {
  1095  			argv = append(argv, "-Wl,-no_pie")
  1096  		}
  1097  	case objabi.Hopenbsd:
  1098  		argv = append(argv, "-Wl,-nopie")
  1099  	case objabi.Hwindows:
  1100  		if windowsgui {
  1101  			argv = append(argv, "-mwindows")
  1102  		} else {
  1103  			argv = append(argv, "-mconsole")
  1104  		}
  1105  	}
  1106  
  1107  	switch ctxt.BuildMode {
  1108  	case BuildModeExe:
  1109  		if ctxt.HeadType == objabi.Hdarwin {
  1110  			if ctxt.Arch.Family == sys.ARM64 {
  1111  				// __PAGEZERO segment size determined empirically.
  1112  				// XCode 9.0.1 successfully uploads an iOS app with this value.
  1113  				argv = append(argv, "-Wl,-pagezero_size,100000000")
  1114  			} else {
  1115  				argv = append(argv, "-Wl,-pagezero_size,4000000")
  1116  			}
  1117  		}
  1118  	case BuildModePIE:
  1119  		// ELF.
  1120  		if ctxt.HeadType != objabi.Hdarwin {
  1121  			if ctxt.UseRelro() {
  1122  				argv = append(argv, "-Wl,-z,relro")
  1123  			}
  1124  			argv = append(argv, "-pie")
  1125  		}
  1126  	case BuildModeCShared:
  1127  		if ctxt.HeadType == objabi.Hdarwin {
  1128  			argv = append(argv, "-dynamiclib")
  1129  			if ctxt.Arch.Family != sys.AMD64 {
  1130  				argv = append(argv, "-Wl,-read_only_relocs,suppress")
  1131  			}
  1132  		} else {
  1133  			// ELF.
  1134  			argv = append(argv, "-Wl,-Bsymbolic")
  1135  			if ctxt.UseRelro() {
  1136  				argv = append(argv, "-Wl,-z,relro")
  1137  			}
  1138  			argv = append(argv, "-shared")
  1139  			if ctxt.HeadType != objabi.Hwindows {
  1140  				// Pass -z nodelete to mark the shared library as
  1141  				// non-closeable: a dlclose will do nothing.
  1142  				argv = append(argv, "-Wl,-z,nodelete")
  1143  			}
  1144  		}
  1145  	case BuildModeShared:
  1146  		if ctxt.UseRelro() {
  1147  			argv = append(argv, "-Wl,-z,relro")
  1148  		}
  1149  		argv = append(argv, "-shared")
  1150  	case BuildModePlugin:
  1151  		if ctxt.HeadType == objabi.Hdarwin {
  1152  			argv = append(argv, "-dynamiclib")
  1153  		} else {
  1154  			if ctxt.UseRelro() {
  1155  				argv = append(argv, "-Wl,-z,relro")
  1156  			}
  1157  			argv = append(argv, "-shared")
  1158  		}
  1159  	}
  1160  
  1161  	if ctxt.IsELF && ctxt.DynlinkingGo() {
  1162  		// We force all symbol resolution to be done at program startup
  1163  		// because lazy PLT resolution can use large amounts of stack at
  1164  		// times we cannot allow it to do so.
  1165  		argv = append(argv, "-Wl,-znow")
  1166  
  1167  		// Do not let the host linker generate COPY relocations. These
  1168  		// can move symbols out of sections that rely on stable offsets
  1169  		// from the beginning of the section (like sym.STYPE).
  1170  		argv = append(argv, "-Wl,-znocopyreloc")
  1171  
  1172  		if ctxt.Arch.InFamily(sys.ARM, sys.ARM64) {
  1173  			// On ARM, the GNU linker will generate COPY relocations
  1174  			// even with -znocopyreloc set.
  1175  			// https://sourceware.org/bugzilla/show_bug.cgi?id=19962
  1176  			//
  1177  			// On ARM64, the GNU linker will fail instead of
  1178  			// generating COPY relocations.
  1179  			//
  1180  			// In both cases, switch to gold.
  1181  			argv = append(argv, "-fuse-ld=gold")
  1182  
  1183  			// If gold is not installed, gcc will silently switch
  1184  			// back to ld.bfd. So we parse the version information
  1185  			// and provide a useful error if gold is missing.
  1186  			cmd := exec.Command(*flagExtld, "-fuse-ld=gold", "-Wl,--version")
  1187  			if out, err := cmd.CombinedOutput(); err == nil {
  1188  				if !bytes.Contains(out, []byte("GNU gold")) {
  1189  					log.Fatalf("ARM external linker must be gold (issue #15696), but is not: %s", out)
  1190  				}
  1191  			}
  1192  		}
  1193  	}
  1194  
  1195  	if ctxt.IsELF && len(buildinfo) > 0 {
  1196  		argv = append(argv, fmt.Sprintf("-Wl,--build-id=0x%x", buildinfo))
  1197  	}
  1198  
  1199  	// On Windows, given -o foo, GCC will append ".exe" to produce
  1200  	// "foo.exe".  We have decided that we want to honor the -o
  1201  	// option. To make this work, we append a '.' so that GCC
  1202  	// will decide that the file already has an extension. We
  1203  	// only want to do this when producing a Windows output file
  1204  	// on a Windows host.
  1205  	outopt := *flagOutfile
  1206  	if objabi.GOOS == "windows" && runtime.GOOS == "windows" && filepath.Ext(outopt) == "" {
  1207  		outopt += "."
  1208  	}
  1209  	argv = append(argv, "-o")
  1210  	argv = append(argv, outopt)
  1211  
  1212  	if rpath.val != "" {
  1213  		argv = append(argv, fmt.Sprintf("-Wl,-rpath,%s", rpath.val))
  1214  	}
  1215  
  1216  	// Force global symbols to be exported for dlopen, etc.
  1217  	if ctxt.IsELF {
  1218  		argv = append(argv, "-rdynamic")
  1219  	}
  1220  
  1221  	if strings.Contains(argv[0], "clang") {
  1222  		argv = append(argv, "-Qunused-arguments")
  1223  	}
  1224  
  1225  	const compressDWARF = "-Wl,--compress-debug-sections=zlib-gnu"
  1226  	if ctxt.compressDWARF && linkerFlagSupported(argv[0], compressDWARF) {
  1227  		argv = append(argv, compressDWARF)
  1228  	}
  1229  
  1230  	argv = append(argv, filepath.Join(*flagTmpdir, "go.o"))
  1231  	argv = append(argv, hostobjCopy()...)
  1232  
  1233  	if ctxt.linkShared {
  1234  		seenDirs := make(map[string]bool)
  1235  		seenLibs := make(map[string]bool)
  1236  		addshlib := func(path string) {
  1237  			dir, base := filepath.Split(path)
  1238  			if !seenDirs[dir] {
  1239  				argv = append(argv, "-L"+dir)
  1240  				if !rpath.set {
  1241  					argv = append(argv, "-Wl,-rpath="+dir)
  1242  				}
  1243  				seenDirs[dir] = true
  1244  			}
  1245  			base = strings.TrimSuffix(base, ".so")
  1246  			base = strings.TrimPrefix(base, "lib")
  1247  			if !seenLibs[base] {
  1248  				argv = append(argv, "-l"+base)
  1249  				seenLibs[base] = true
  1250  			}
  1251  		}
  1252  		for _, shlib := range ctxt.Shlibs {
  1253  			addshlib(shlib.Path)
  1254  			for _, dep := range shlib.Deps {
  1255  				if dep == "" {
  1256  					continue
  1257  				}
  1258  				libpath := findshlib(ctxt, dep)
  1259  				if libpath != "" {
  1260  					addshlib(libpath)
  1261  				}
  1262  			}
  1263  		}
  1264  	}
  1265  
  1266  	// clang, unlike GCC, passes -rdynamic to the linker
  1267  	// even when linking with -static, causing a linker
  1268  	// error when using GNU ld. So take out -rdynamic if
  1269  	// we added it. We do it in this order, rather than
  1270  	// only adding -rdynamic later, so that -*extldflags
  1271  	// can override -rdynamic without using -static.
  1272  	checkStatic := func(arg string) {
  1273  		if ctxt.IsELF && arg == "-static" {
  1274  			for i := range argv {
  1275  				if argv[i] == "-rdynamic" {
  1276  					argv[i] = "-static"
  1277  				}
  1278  			}
  1279  		}
  1280  	}
  1281  
  1282  	for _, p := range ldflag {
  1283  		argv = append(argv, p)
  1284  		checkStatic(p)
  1285  	}
  1286  
  1287  	// When building a program with the default -buildmode=exe the
  1288  	// gc compiler generates code requires DT_TEXTREL in a
  1289  	// position independent executable (PIE). On systems where the
  1290  	// toolchain creates PIEs by default, and where DT_TEXTREL
  1291  	// does not work, the resulting programs will not run. See
  1292  	// issue #17847. To avoid this problem pass -no-pie to the
  1293  	// toolchain if it is supported.
  1294  	if ctxt.BuildMode == BuildModeExe && !ctxt.linkShared {
  1295  		// GCC uses -no-pie, clang uses -nopie.
  1296  		for _, nopie := range []string{"-no-pie", "-nopie"} {
  1297  			if linkerFlagSupported(argv[0], nopie) {
  1298  				argv = append(argv, nopie)
  1299  				break
  1300  			}
  1301  		}
  1302  	}
  1303  
  1304  	for _, p := range strings.Fields(*flagExtldflags) {
  1305  		argv = append(argv, p)
  1306  		checkStatic(p)
  1307  	}
  1308  	if ctxt.HeadType == objabi.Hwindows {
  1309  		// use gcc linker script to work around gcc bug
  1310  		// (see https://golang.org/issue/20183 for details).
  1311  		p := writeGDBLinkerScript()
  1312  		argv = append(argv, "-Wl,-T,"+p)
  1313  		// libmingw32 and libmingwex have some inter-dependencies,
  1314  		// so must use linker groups.
  1315  		argv = append(argv, "-Wl,--start-group", "-lmingwex", "-lmingw32", "-Wl,--end-group")
  1316  		argv = append(argv, peimporteddlls()...)
  1317  	}
  1318  
  1319  	if ctxt.Debugvlog != 0 {
  1320  		ctxt.Logf("%5.2f host link:", Cputime())
  1321  		for _, v := range argv {
  1322  			ctxt.Logf(" %q", v)
  1323  		}
  1324  		ctxt.Logf("\n")
  1325  	}
  1326  
  1327  	out, err := exec.Command(argv[0], argv[1:]...).CombinedOutput()
  1328  	if err != nil {
  1329  		Exitf("running %s failed: %v\n%s", argv[0], err, out)
  1330  	}
  1331  
  1332  	// Filter out useless linker warnings caused by bugs outside Go.
  1333  	// See also cmd/go/internal/work/exec.go's gccld method.
  1334  	var save [][]byte
  1335  	for _, line := range bytes.SplitAfter(out, []byte("\n")) {
  1336  		// golang.org/issue/26073 - Apple Xcode bug
  1337  		if bytes.Contains(line, []byte("ld: warning: text-based stub file")) {
  1338  			continue
  1339  		}
  1340  		save = append(save, line)
  1341  	}
  1342  	out = bytes.Join(save, nil)
  1343  
  1344  	if len(out) > 0 {
  1345  		// always print external output even if the command is successful, so that we don't
  1346  		// swallow linker warnings (see https://golang.org/issue/17935).
  1347  		ctxt.Logf("%s", out)
  1348  	}
  1349  
  1350  	if !*FlagS && !*FlagW && !debug_s && ctxt.HeadType == objabi.Hdarwin {
  1351  		dsym := filepath.Join(*flagTmpdir, "go.dwarf")
  1352  		if out, err := exec.Command("dsymutil", "-f", *flagOutfile, "-o", dsym).CombinedOutput(); err != nil {
  1353  			Exitf("%s: running dsymutil failed: %v\n%s", os.Args[0], err, out)
  1354  		}
  1355  		// Skip combining if `dsymutil` didn't generate a file. See #11994.
  1356  		if _, err := os.Stat(dsym); os.IsNotExist(err) {
  1357  			return
  1358  		}
  1359  		// For os.Rename to work reliably, must be in same directory as outfile.
  1360  		combinedOutput := *flagOutfile + "~"
  1361  		isIOS, err := machoCombineDwarf(ctxt, *flagOutfile, dsym, combinedOutput)
  1362  		if err != nil {
  1363  			Exitf("%s: combining dwarf failed: %v", os.Args[0], err)
  1364  		}
  1365  		if !isIOS {
  1366  			os.Remove(*flagOutfile)
  1367  			if err := os.Rename(combinedOutput, *flagOutfile); err != nil {
  1368  				Exitf("%s: %v", os.Args[0], err)
  1369  			}
  1370  		}
  1371  	}
  1372  }
  1373  
  1374  var createTrivialCOnce sync.Once
  1375  
  1376  func linkerFlagSupported(linker, flag string) bool {
  1377  	createTrivialCOnce.Do(func() {
  1378  		src := filepath.Join(*flagTmpdir, "trivial.c")
  1379  		if err := ioutil.WriteFile(src, []byte("int main() { return 0; }"), 0666); err != nil {
  1380  			Errorf(nil, "WriteFile trivial.c failed: %v", err)
  1381  		}
  1382  	})
  1383  
  1384  	cmd := exec.Command(linker, flag, "trivial.c")
  1385  	cmd.Dir = *flagTmpdir
  1386  	cmd.Env = append([]string{"LC_ALL=C"}, os.Environ()...)
  1387  	out, err := cmd.CombinedOutput()
  1388  	// GCC says "unrecognized command line option ‘-no-pie’"
  1389  	// clang says "unknown argument: '-no-pie'"
  1390  	return err == nil && !bytes.Contains(out, []byte("unrecognized")) && !bytes.Contains(out, []byte("unknown"))
  1391  }
  1392  
  1393  // hostlinkArchArgs returns arguments to pass to the external linker
  1394  // based on the architecture.
  1395  func hostlinkArchArgs(arch *sys.Arch) []string {
  1396  	switch arch.Family {
  1397  	case sys.I386:
  1398  		return []string{"-m32"}
  1399  	case sys.AMD64, sys.PPC64, sys.S390X:
  1400  		return []string{"-m64"}
  1401  	case sys.ARM:
  1402  		return []string{"-marm"}
  1403  	case sys.ARM64:
  1404  		// nothing needed
  1405  	case sys.MIPS64:
  1406  		return []string{"-mabi=64"}
  1407  	case sys.MIPS:
  1408  		return []string{"-mabi=32"}
  1409  	}
  1410  	return nil
  1411  }
  1412  
  1413  // ldobj loads an input object. If it is a host object (an object
  1414  // compiled by a non-Go compiler) it returns the Hostobj pointer. If
  1415  // it is a Go object, it returns nil.
  1416  func ldobj(ctxt *Link, f *bio.Reader, lib *sym.Library, length int64, pn string, file string) *Hostobj {
  1417  	pkg := objabi.PathToPrefix(lib.Pkg)
  1418  
  1419  	eof := f.Offset() + length
  1420  	start := f.Offset()
  1421  	c1 := bgetc(f)
  1422  	c2 := bgetc(f)
  1423  	c3 := bgetc(f)
  1424  	c4 := bgetc(f)
  1425  	f.Seek(start, 0)
  1426  
  1427  	magic := uint32(c1)<<24 | uint32(c2)<<16 | uint32(c3)<<8 | uint32(c4)
  1428  	if magic == 0x7f454c46 { // \x7F E L F
  1429  		ldelf := func(ctxt *Link, f *bio.Reader, pkg string, length int64, pn string) {
  1430  			textp, flags, err := loadelf.Load(ctxt.Arch, ctxt.Syms, f, pkg, length, pn, ehdr.flags)
  1431  			if err != nil {
  1432  				Errorf(nil, "%v", err)
  1433  				return
  1434  			}
  1435  			ehdr.flags = flags
  1436  			ctxt.Textp = append(ctxt.Textp, textp...)
  1437  		}
  1438  		return ldhostobj(ldelf, ctxt.HeadType, f, pkg, length, pn, file)
  1439  	}
  1440  
  1441  	if magic&^1 == 0xfeedface || magic&^0x01000000 == 0xcefaedfe {
  1442  		ldmacho := func(ctxt *Link, f *bio.Reader, pkg string, length int64, pn string) {
  1443  			textp, err := loadmacho.Load(ctxt.Arch, ctxt.Syms, f, pkg, length, pn)
  1444  			if err != nil {
  1445  				Errorf(nil, "%v", err)
  1446  				return
  1447  			}
  1448  			ctxt.Textp = append(ctxt.Textp, textp...)
  1449  		}
  1450  		return ldhostobj(ldmacho, ctxt.HeadType, f, pkg, length, pn, file)
  1451  	}
  1452  
  1453  	if c1 == 0x4c && c2 == 0x01 || c1 == 0x64 && c2 == 0x86 {
  1454  		ldpe := func(ctxt *Link, f *bio.Reader, pkg string, length int64, pn string) {
  1455  			textp, rsrc, err := loadpe.Load(ctxt.Arch, ctxt.Syms, f, pkg, length, pn)
  1456  			if err != nil {
  1457  				Errorf(nil, "%v", err)
  1458  				return
  1459  			}
  1460  			if rsrc != nil {
  1461  				setpersrc(ctxt, rsrc)
  1462  			}
  1463  			ctxt.Textp = append(ctxt.Textp, textp...)
  1464  		}
  1465  		return ldhostobj(ldpe, ctxt.HeadType, f, pkg, length, pn, file)
  1466  	}
  1467  
  1468  	/* check the header */
  1469  	line, err := f.ReadString('\n')
  1470  	if err != nil {
  1471  		Errorf(nil, "truncated object file: %s: %v", pn, err)
  1472  		return nil
  1473  	}
  1474  
  1475  	if !strings.HasPrefix(line, "go object ") {
  1476  		if strings.HasSuffix(pn, ".go") {
  1477  			Exitf("%s: uncompiled .go source file", pn)
  1478  			return nil
  1479  		}
  1480  
  1481  		if line == ctxt.Arch.Name {
  1482  			// old header format: just $GOOS
  1483  			Errorf(nil, "%s: stale object file", pn)
  1484  			return nil
  1485  		}
  1486  
  1487  		Errorf(nil, "%s: not an object file", pn)
  1488  		return nil
  1489  	}
  1490  
  1491  	// First, check that the basic GOOS, GOARCH, and Version match.
  1492  	t := fmt.Sprintf("%s %s %s ", objabi.GOOS, objabi.GOARCH, objabi.Version)
  1493  
  1494  	line = strings.TrimRight(line, "\n")
  1495  	if !strings.HasPrefix(line[10:]+" ", t) && !*flagF {
  1496  		Errorf(nil, "%s: object is [%s] expected [%s]", pn, line[10:], t)
  1497  		return nil
  1498  	}
  1499  
  1500  	// Second, check that longer lines match each other exactly,
  1501  	// so that the Go compiler and write additional information
  1502  	// that must be the same from run to run.
  1503  	if len(line) >= len(t)+10 {
  1504  		if theline == "" {
  1505  			theline = line[10:]
  1506  		} else if theline != line[10:] {
  1507  			Errorf(nil, "%s: object is [%s] expected [%s]", pn, line[10:], theline)
  1508  			return nil
  1509  		}
  1510  	}
  1511  
  1512  	// Skip over exports and other info -- ends with \n!\n.
  1513  	//
  1514  	// Note: It's possible for "\n!\n" to appear within the binary
  1515  	// package export data format. To avoid truncating the package
  1516  	// definition prematurely (issue 21703), we keep keep track of
  1517  	// how many "$$" delimiters we've seen.
  1518  
  1519  	import0 := f.Offset()
  1520  
  1521  	c1 = '\n' // the last line ended in \n
  1522  	c2 = bgetc(f)
  1523  	c3 = bgetc(f)
  1524  	markers := 0
  1525  	for {
  1526  		if c1 == '\n' {
  1527  			if markers%2 == 0 && c2 == '!' && c3 == '\n' {
  1528  				break
  1529  			}
  1530  			if c2 == '$' && c3 == '$' {
  1531  				markers++
  1532  			}
  1533  		}
  1534  
  1535  		c1 = c2
  1536  		c2 = c3
  1537  		c3 = bgetc(f)
  1538  		if c3 == -1 {
  1539  			Errorf(nil, "truncated object file: %s", pn)
  1540  			return nil
  1541  		}
  1542  	}
  1543  
  1544  	import1 := f.Offset()
  1545  
  1546  	f.Seek(import0, 0)
  1547  	ldpkg(ctxt, f, lib, import1-import0-2, pn) // -2 for !\n
  1548  	f.Seek(import1, 0)
  1549  
  1550  	objfile.Load(ctxt.Arch, ctxt.Syms, f, lib, eof-f.Offset(), pn)
  1551  	addImports(ctxt, lib, pn)
  1552  	return nil
  1553  }
  1554  
  1555  func readelfsymboldata(ctxt *Link, f *elf.File, sym *elf.Symbol) []byte {
  1556  	data := make([]byte, sym.Size)
  1557  	sect := f.Sections[sym.Section]
  1558  	if sect.Type != elf.SHT_PROGBITS && sect.Type != elf.SHT_NOTE {
  1559  		Errorf(nil, "reading %s from non-data section", sym.Name)
  1560  	}
  1561  	n, err := sect.ReadAt(data, int64(sym.Value-sect.Addr))
  1562  	if uint64(n) != sym.Size {
  1563  		Errorf(nil, "reading contents of %s: %v", sym.Name, err)
  1564  	}
  1565  	return data
  1566  }
  1567  
  1568  func readwithpad(r io.Reader, sz int32) ([]byte, error) {
  1569  	data := make([]byte, Rnd(int64(sz), 4))
  1570  	_, err := io.ReadFull(r, data)
  1571  	if err != nil {
  1572  		return nil, err
  1573  	}
  1574  	data = data[:sz]
  1575  	return data, nil
  1576  }
  1577  
  1578  func readnote(f *elf.File, name []byte, typ int32) ([]byte, error) {
  1579  	for _, sect := range f.Sections {
  1580  		if sect.Type != elf.SHT_NOTE {
  1581  			continue
  1582  		}
  1583  		r := sect.Open()
  1584  		for {
  1585  			var namesize, descsize, noteType int32
  1586  			err := binary.Read(r, f.ByteOrder, &namesize)
  1587  			if err != nil {
  1588  				if err == io.EOF {
  1589  					break
  1590  				}
  1591  				return nil, fmt.Errorf("read namesize failed: %v", err)
  1592  			}
  1593  			err = binary.Read(r, f.ByteOrder, &descsize)
  1594  			if err != nil {
  1595  				return nil, fmt.Errorf("read descsize failed: %v", err)
  1596  			}
  1597  			err = binary.Read(r, f.ByteOrder, &noteType)
  1598  			if err != nil {
  1599  				return nil, fmt.Errorf("read type failed: %v", err)
  1600  			}
  1601  			noteName, err := readwithpad(r, namesize)
  1602  			if err != nil {
  1603  				return nil, fmt.Errorf("read name failed: %v", err)
  1604  			}
  1605  			desc, err := readwithpad(r, descsize)
  1606  			if err != nil {
  1607  				return nil, fmt.Errorf("read desc failed: %v", err)
  1608  			}
  1609  			if string(name) == string(noteName) && typ == noteType {
  1610  				return desc, nil
  1611  			}
  1612  		}
  1613  	}
  1614  	return nil, nil
  1615  }
  1616  
  1617  func findshlib(ctxt *Link, shlib string) string {
  1618  	if filepath.IsAbs(shlib) {
  1619  		return shlib
  1620  	}
  1621  	for _, libdir := range ctxt.Libdir {
  1622  		libpath := filepath.Join(libdir, shlib)
  1623  		if _, err := os.Stat(libpath); err == nil {
  1624  			return libpath
  1625  		}
  1626  	}
  1627  	Errorf(nil, "cannot find shared library: %s", shlib)
  1628  	return ""
  1629  }
  1630  
  1631  func ldshlibsyms(ctxt *Link, shlib string) {
  1632  	var libpath string
  1633  	if filepath.IsAbs(shlib) {
  1634  		libpath = shlib
  1635  		shlib = filepath.Base(shlib)
  1636  	} else {
  1637  		libpath = findshlib(ctxt, shlib)
  1638  		if libpath == "" {
  1639  			return
  1640  		}
  1641  	}
  1642  	for _, processedlib := range ctxt.Shlibs {
  1643  		if processedlib.Path == libpath {
  1644  			return
  1645  		}
  1646  	}
  1647  	if ctxt.Debugvlog > 1 {
  1648  		ctxt.Logf("%5.2f ldshlibsyms: found library with name %s at %s\n", Cputime(), shlib, libpath)
  1649  	}
  1650  
  1651  	f, err := elf.Open(libpath)
  1652  	if err != nil {
  1653  		Errorf(nil, "cannot open shared library: %s", libpath)
  1654  		return
  1655  	}
  1656  	defer f.Close()
  1657  
  1658  	hash, err := readnote(f, ELF_NOTE_GO_NAME, ELF_NOTE_GOABIHASH_TAG)
  1659  	if err != nil {
  1660  		Errorf(nil, "cannot read ABI hash from shared library %s: %v", libpath, err)
  1661  		return
  1662  	}
  1663  
  1664  	depsbytes, err := readnote(f, ELF_NOTE_GO_NAME, ELF_NOTE_GODEPS_TAG)
  1665  	if err != nil {
  1666  		Errorf(nil, "cannot read dep list from shared library %s: %v", libpath, err)
  1667  		return
  1668  	}
  1669  	var deps []string
  1670  	for _, dep := range strings.Split(string(depsbytes), "\n") {
  1671  		if dep == "" {
  1672  			continue
  1673  		}
  1674  		if !filepath.IsAbs(dep) {
  1675  			// If the dep can be interpreted as a path relative to the shlib
  1676  			// in which it was found, do that. Otherwise, we will leave it
  1677  			// to be resolved by libdir lookup.
  1678  			abs := filepath.Join(filepath.Dir(libpath), dep)
  1679  			if _, err := os.Stat(abs); err == nil {
  1680  				dep = abs
  1681  			}
  1682  		}
  1683  		deps = append(deps, dep)
  1684  	}
  1685  
  1686  	syms, err := f.DynamicSymbols()
  1687  	if err != nil {
  1688  		Errorf(nil, "cannot read symbols from shared library: %s", libpath)
  1689  		return
  1690  	}
  1691  	gcdataLocations := make(map[uint64]*sym.Symbol)
  1692  	for _, elfsym := range syms {
  1693  		if elf.ST_TYPE(elfsym.Info) == elf.STT_NOTYPE || elf.ST_TYPE(elfsym.Info) == elf.STT_SECTION {
  1694  			continue
  1695  		}
  1696  		lsym := ctxt.Syms.Lookup(elfsym.Name, 0)
  1697  		// Because loadlib above loads all .a files before loading any shared
  1698  		// libraries, any non-dynimport symbols we find that duplicate symbols
  1699  		// already loaded should be ignored (the symbols from the .a files
  1700  		// "win").
  1701  		if lsym.Type != 0 && lsym.Type != sym.SDYNIMPORT {
  1702  			continue
  1703  		}
  1704  		lsym.Type = sym.SDYNIMPORT
  1705  		lsym.ElfType = elf.ST_TYPE(elfsym.Info)
  1706  		lsym.Size = int64(elfsym.Size)
  1707  		if elfsym.Section != elf.SHN_UNDEF {
  1708  			// Set .File for the library that actually defines the symbol.
  1709  			lsym.File = libpath
  1710  			// The decodetype_* functions in decodetype.go need access to
  1711  			// the type data.
  1712  			if strings.HasPrefix(lsym.Name, "type.") && !strings.HasPrefix(lsym.Name, "type..") {
  1713  				lsym.P = readelfsymboldata(ctxt, f, &elfsym)
  1714  				gcdataLocations[elfsym.Value+2*uint64(ctxt.Arch.PtrSize)+8+1*uint64(ctxt.Arch.PtrSize)] = lsym
  1715  			}
  1716  		}
  1717  	}
  1718  	gcdataAddresses := make(map[*sym.Symbol]uint64)
  1719  	if ctxt.Arch.Family == sys.ARM64 {
  1720  		for _, sect := range f.Sections {
  1721  			if sect.Type == elf.SHT_RELA {
  1722  				var rela elf.Rela64
  1723  				rdr := sect.Open()
  1724  				for {
  1725  					err := binary.Read(rdr, f.ByteOrder, &rela)
  1726  					if err == io.EOF {
  1727  						break
  1728  					} else if err != nil {
  1729  						Errorf(nil, "reading relocation failed %v", err)
  1730  						return
  1731  					}
  1732  					t := elf.R_AARCH64(rela.Info & 0xffff)
  1733  					if t != elf.R_AARCH64_RELATIVE {
  1734  						continue
  1735  					}
  1736  					if lsym, ok := gcdataLocations[rela.Off]; ok {
  1737  						gcdataAddresses[lsym] = uint64(rela.Addend)
  1738  					}
  1739  				}
  1740  			}
  1741  		}
  1742  	}
  1743  
  1744  	ctxt.Shlibs = append(ctxt.Shlibs, Shlib{Path: libpath, Hash: hash, Deps: deps, File: f, gcdataAddresses: gcdataAddresses})
  1745  }
  1746  
  1747  func addsection(arch *sys.Arch, seg *sym.Segment, name string, rwx int) *sym.Section {
  1748  	sect := new(sym.Section)
  1749  	sect.Rwx = uint8(rwx)
  1750  	sect.Name = name
  1751  	sect.Seg = seg
  1752  	sect.Align = int32(arch.PtrSize) // everything is at least pointer-aligned
  1753  	seg.Sections = append(seg.Sections, sect)
  1754  	return sect
  1755  }
  1756  
  1757  func Le16(b []byte) uint16 {
  1758  	return uint16(b[0]) | uint16(b[1])<<8
  1759  }
  1760  
  1761  func Le32(b []byte) uint32 {
  1762  	return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
  1763  }
  1764  
  1765  func Le64(b []byte) uint64 {
  1766  	return uint64(Le32(b)) | uint64(Le32(b[4:]))<<32
  1767  }
  1768  
  1769  func Be16(b []byte) uint16 {
  1770  	return uint16(b[0])<<8 | uint16(b[1])
  1771  }
  1772  
  1773  func Be32(b []byte) uint32 {
  1774  	return uint32(b[0])<<24 | uint32(b[1])<<16 | uint32(b[2])<<8 | uint32(b[3])
  1775  }
  1776  
  1777  type chain struct {
  1778  	sym   *sym.Symbol
  1779  	up    *chain
  1780  	limit int // limit on entry to sym
  1781  }
  1782  
  1783  var morestack *sym.Symbol
  1784  
  1785  // TODO: Record enough information in new object files to
  1786  // allow stack checks here.
  1787  
  1788  func haslinkregister(ctxt *Link) bool {
  1789  	return ctxt.FixedFrameSize() != 0
  1790  }
  1791  
  1792  func callsize(ctxt *Link) int {
  1793  	if haslinkregister(ctxt) {
  1794  		return 0
  1795  	}
  1796  	return ctxt.Arch.RegSize
  1797  }
  1798  
  1799  func (ctxt *Link) dostkcheck() {
  1800  	var ch chain
  1801  
  1802  	morestack = ctxt.Syms.Lookup("runtime.morestack", 0)
  1803  
  1804  	// Every splitting function ensures that there are at least StackLimit
  1805  	// bytes available below SP when the splitting prologue finishes.
  1806  	// If the splitting function calls F, then F begins execution with
  1807  	// at least StackLimit - callsize() bytes available.
  1808  	// Check that every function behaves correctly with this amount
  1809  	// of stack, following direct calls in order to piece together chains
  1810  	// of non-splitting functions.
  1811  	ch.up = nil
  1812  
  1813  	ch.limit = objabi.StackLimit - callsize(ctxt)
  1814  
  1815  	// Check every function, but do the nosplit functions in a first pass,
  1816  	// to make the printed failure chains as short as possible.
  1817  	for _, s := range ctxt.Textp {
  1818  		// runtime.racesymbolizethunk is called from gcc-compiled C
  1819  		// code running on the operating system thread stack.
  1820  		// It uses more than the usual amount of stack but that's okay.
  1821  		if s.Name == "runtime.racesymbolizethunk" {
  1822  			continue
  1823  		}
  1824  
  1825  		if s.Attr.NoSplit() {
  1826  			ch.sym = s
  1827  			stkcheck(ctxt, &ch, 0)
  1828  		}
  1829  	}
  1830  
  1831  	for _, s := range ctxt.Textp {
  1832  		if !s.Attr.NoSplit() {
  1833  			ch.sym = s
  1834  			stkcheck(ctxt, &ch, 0)
  1835  		}
  1836  	}
  1837  }
  1838  
  1839  func stkcheck(ctxt *Link, up *chain, depth int) int {
  1840  	limit := up.limit
  1841  	s := up.sym
  1842  
  1843  	// Don't duplicate work: only need to consider each
  1844  	// function at top of safe zone once.
  1845  	top := limit == objabi.StackLimit-callsize(ctxt)
  1846  	if top {
  1847  		if s.Attr.StackCheck() {
  1848  			return 0
  1849  		}
  1850  		s.Attr |= sym.AttrStackCheck
  1851  	}
  1852  
  1853  	if depth > 100 {
  1854  		Errorf(s, "nosplit stack check too deep")
  1855  		stkbroke(ctxt, up, 0)
  1856  		return -1
  1857  	}
  1858  
  1859  	if s.Attr.External() || s.FuncInfo == nil {
  1860  		// external function.
  1861  		// should never be called directly.
  1862  		// onlyctxt.Diagnose the direct caller.
  1863  		// TODO(mwhudson): actually think about this.
  1864  		// TODO(khr): disabled for now. Calls to external functions can only happen on the g0 stack.
  1865  		// See the trampolines in src/runtime/sys_darwin_$ARCH.go.
  1866  		if depth == 1 && s.Type != sym.SXREF && !ctxt.DynlinkingGo() &&
  1867  			ctxt.BuildMode != BuildModeCArchive && ctxt.BuildMode != BuildModePIE && ctxt.BuildMode != BuildModeCShared && ctxt.BuildMode != BuildModePlugin {
  1868  			//Errorf(s, "call to external function")
  1869  		}
  1870  		return -1
  1871  	}
  1872  
  1873  	if limit < 0 {
  1874  		stkbroke(ctxt, up, limit)
  1875  		return -1
  1876  	}
  1877  
  1878  	// morestack looks like it calls functions,
  1879  	// but it switches the stack pointer first.
  1880  	if s == morestack {
  1881  		return 0
  1882  	}
  1883  
  1884  	var ch chain
  1885  	ch.up = up
  1886  
  1887  	if !s.Attr.NoSplit() {
  1888  		// Ensure we have enough stack to call morestack.
  1889  		ch.limit = limit - callsize(ctxt)
  1890  		ch.sym = morestack
  1891  		if stkcheck(ctxt, &ch, depth+1) < 0 {
  1892  			return -1
  1893  		}
  1894  		if !top {
  1895  			return 0
  1896  		}
  1897  		// Raise limit to allow frame.
  1898  		locals := int32(0)
  1899  		if s.FuncInfo != nil {
  1900  			locals = s.FuncInfo.Locals
  1901  		}
  1902  		limit = int(objabi.StackLimit+locals) + int(ctxt.FixedFrameSize())
  1903  	}
  1904  
  1905  	// Walk through sp adjustments in function, consuming relocs.
  1906  	ri := 0
  1907  
  1908  	endr := len(s.R)
  1909  	var ch1 chain
  1910  	var pcsp Pciter
  1911  	var r *sym.Reloc
  1912  	for pciterinit(ctxt, &pcsp, &s.FuncInfo.Pcsp); pcsp.done == 0; pciternext(&pcsp) {
  1913  		// pcsp.value is in effect for [pcsp.pc, pcsp.nextpc).
  1914  
  1915  		// Check stack size in effect for this span.
  1916  		if int32(limit)-pcsp.value < 0 {
  1917  			stkbroke(ctxt, up, int(int32(limit)-pcsp.value))
  1918  			return -1
  1919  		}
  1920  
  1921  		// Process calls in this span.
  1922  		for ; ri < endr && uint32(s.R[ri].Off) < pcsp.nextpc; ri++ {
  1923  			r = &s.R[ri]
  1924  			switch r.Type {
  1925  			// Direct call.
  1926  			case objabi.R_CALL, objabi.R_CALLARM, objabi.R_CALLARM64, objabi.R_CALLPOWER, objabi.R_CALLMIPS:
  1927  				ch.limit = int(int32(limit) - pcsp.value - int32(callsize(ctxt)))
  1928  				ch.sym = r.Sym
  1929  				if stkcheck(ctxt, &ch, depth+1) < 0 {
  1930  					return -1
  1931  				}
  1932  
  1933  			// Indirect call. Assume it is a call to a splitting function,
  1934  			// so we have to make sure it can call morestack.
  1935  			// Arrange the data structures to report both calls, so that
  1936  			// if there is an error, stkprint shows all the steps involved.
  1937  			case objabi.R_CALLIND:
  1938  				ch.limit = int(int32(limit) - pcsp.value - int32(callsize(ctxt)))
  1939  
  1940  				ch.sym = nil
  1941  				ch1.limit = ch.limit - callsize(ctxt) // for morestack in called prologue
  1942  				ch1.up = &ch
  1943  				ch1.sym = morestack
  1944  				if stkcheck(ctxt, &ch1, depth+2) < 0 {
  1945  					return -1
  1946  				}
  1947  			}
  1948  		}
  1949  	}
  1950  
  1951  	return 0
  1952  }
  1953  
  1954  func stkbroke(ctxt *Link, ch *chain, limit int) {
  1955  	Errorf(ch.sym, "nosplit stack overflow")
  1956  	stkprint(ctxt, ch, limit)
  1957  }
  1958  
  1959  func stkprint(ctxt *Link, ch *chain, limit int) {
  1960  	var name string
  1961  
  1962  	if ch.sym != nil {
  1963  		name = ch.sym.Name
  1964  		if ch.sym.Attr.NoSplit() {
  1965  			name += " (nosplit)"
  1966  		}
  1967  	} else {
  1968  		name = "function pointer"
  1969  	}
  1970  
  1971  	if ch.up == nil {
  1972  		// top of chain.  ch->sym != nil.
  1973  		if ch.sym.Attr.NoSplit() {
  1974  			fmt.Printf("\t%d\tassumed on entry to %s\n", ch.limit, name)
  1975  		} else {
  1976  			fmt.Printf("\t%d\tguaranteed after split check in %s\n", ch.limit, name)
  1977  		}
  1978  	} else {
  1979  		stkprint(ctxt, ch.up, ch.limit+callsize(ctxt))
  1980  		if !haslinkregister(ctxt) {
  1981  			fmt.Printf("\t%d\ton entry to %s\n", ch.limit, name)
  1982  		}
  1983  	}
  1984  
  1985  	if ch.limit != limit {
  1986  		fmt.Printf("\t%d\tafter %s uses %d\n", limit, name, ch.limit-limit)
  1987  	}
  1988  }
  1989  
  1990  func usage() {
  1991  	fmt.Fprintf(os.Stderr, "usage: link [options] main.o\n")
  1992  	objabi.Flagprint(os.Stderr)
  1993  	Exit(2)
  1994  }
  1995  
  1996  type SymbolType int8
  1997  
  1998  const (
  1999  	// see also https://9p.io/magic/man2html/1/nm
  2000  	TextSym      SymbolType = 'T'
  2001  	DataSym      SymbolType = 'D'
  2002  	BSSSym       SymbolType = 'B'
  2003  	UndefinedSym SymbolType = 'U'
  2004  	TLSSym       SymbolType = 't'
  2005  	FrameSym     SymbolType = 'm'
  2006  	ParamSym     SymbolType = 'p'
  2007  	AutoSym      SymbolType = 'a'
  2008  
  2009  	// Deleted auto (not a real sym, just placeholder for type)
  2010  	DeletedAutoSym = 'x'
  2011  )
  2012  
  2013  func genasmsym(ctxt *Link, put func(*Link, *sym.Symbol, string, SymbolType, int64, *sym.Symbol)) {
  2014  	// These symbols won't show up in the first loop below because we
  2015  	// skip sym.STEXT symbols. Normal sym.STEXT symbols are emitted by walking textp.
  2016  	s := ctxt.Syms.Lookup("runtime.text", 0)
  2017  	if s.Type == sym.STEXT {
  2018  		// We've already included this symbol in ctxt.Textp
  2019  		// if ctxt.DynlinkingGo() && ctxt.HeadType == objabi.Hdarwin.
  2020  		// See data.go:/textaddress
  2021  		if !(ctxt.DynlinkingGo() && ctxt.HeadType == objabi.Hdarwin) {
  2022  			put(ctxt, s, s.Name, TextSym, s.Value, nil)
  2023  		}
  2024  	}
  2025  
  2026  	n := 0
  2027  
  2028  	// Generate base addresses for all text sections if there are multiple
  2029  	for _, sect := range Segtext.Sections {
  2030  		if n == 0 {
  2031  			n++
  2032  			continue
  2033  		}
  2034  		if sect.Name != ".text" {
  2035  			break
  2036  		}
  2037  		s = ctxt.Syms.ROLookup(fmt.Sprintf("runtime.text.%d", n), 0)
  2038  		if s == nil {
  2039  			break
  2040  		}
  2041  		if s.Type == sym.STEXT {
  2042  			put(ctxt, s, s.Name, TextSym, s.Value, nil)
  2043  		}
  2044  		n++
  2045  	}
  2046  
  2047  	s = ctxt.Syms.Lookup("runtime.etext", 0)
  2048  	if s.Type == sym.STEXT {
  2049  		// We've already included this symbol in ctxt.Textp
  2050  		// if ctxt.DynlinkingGo() && ctxt.HeadType == objabi.Hdarwin.
  2051  		// See data.go:/textaddress
  2052  		if !(ctxt.DynlinkingGo() && ctxt.HeadType == objabi.Hdarwin) {
  2053  			put(ctxt, s, s.Name, TextSym, s.Value, nil)
  2054  		}
  2055  	}
  2056  
  2057  	for _, s := range ctxt.Syms.Allsym {
  2058  		if s.Attr.NotInSymbolTable() {
  2059  			continue
  2060  		}
  2061  		if (s.Name == "" || s.Name[0] == '.') && s.Version == 0 && s.Name != ".rathole" && s.Name != ".TOC." {
  2062  			continue
  2063  		}
  2064  		switch s.Type {
  2065  		case sym.SCONST,
  2066  			sym.SRODATA,
  2067  			sym.SSYMTAB,
  2068  			sym.SPCLNTAB,
  2069  			sym.SINITARR,
  2070  			sym.SDATA,
  2071  			sym.SNOPTRDATA,
  2072  			sym.SELFROSECT,
  2073  			sym.SMACHOGOT,
  2074  			sym.STYPE,
  2075  			sym.SSTRING,
  2076  			sym.SGOSTRING,
  2077  			sym.SGOFUNC,
  2078  			sym.SGCBITS,
  2079  			sym.STYPERELRO,
  2080  			sym.SSTRINGRELRO,
  2081  			sym.SGOSTRINGRELRO,
  2082  			sym.SGOFUNCRELRO,
  2083  			sym.SGCBITSRELRO,
  2084  			sym.SRODATARELRO,
  2085  			sym.STYPELINK,
  2086  			sym.SITABLINK,
  2087  			sym.SWINDOWS:
  2088  			if !s.Attr.Reachable() {
  2089  				continue
  2090  			}
  2091  			put(ctxt, s, s.Name, DataSym, Symaddr(s), s.Gotype)
  2092  
  2093  		case sym.SBSS, sym.SNOPTRBSS:
  2094  			if !s.Attr.Reachable() {
  2095  				continue
  2096  			}
  2097  			if len(s.P) > 0 {
  2098  				Errorf(s, "should not be bss (size=%d type=%v special=%v)", len(s.P), s.Type, s.Attr.Special())
  2099  			}
  2100  			put(ctxt, s, s.Name, BSSSym, Symaddr(s), s.Gotype)
  2101  
  2102  		case sym.SHOSTOBJ:
  2103  			if ctxt.HeadType == objabi.Hwindows || ctxt.IsELF {
  2104  				put(ctxt, s, s.Name, UndefinedSym, s.Value, nil)
  2105  			}
  2106  
  2107  		case sym.SDYNIMPORT:
  2108  			if !s.Attr.Reachable() {
  2109  				continue
  2110  			}
  2111  			put(ctxt, s, s.Extname, UndefinedSym, 0, nil)
  2112  
  2113  		case sym.STLSBSS:
  2114  			if ctxt.LinkMode == LinkExternal {
  2115  				put(ctxt, s, s.Name, TLSSym, Symaddr(s), s.Gotype)
  2116  			}
  2117  		}
  2118  	}
  2119  
  2120  	var off int32
  2121  	for _, s := range ctxt.Textp {
  2122  		put(ctxt, s, s.Name, TextSym, s.Value, s.Gotype)
  2123  
  2124  		locals := int32(0)
  2125  		if s.FuncInfo != nil {
  2126  			locals = s.FuncInfo.Locals
  2127  		}
  2128  		// NOTE(ality): acid can't produce a stack trace without .frame symbols
  2129  		put(ctxt, nil, ".frame", FrameSym, int64(locals)+int64(ctxt.Arch.PtrSize), nil)
  2130  
  2131  		if s.FuncInfo == nil {
  2132  			continue
  2133  		}
  2134  		for _, a := range s.FuncInfo.Autom {
  2135  			if a.Name == objabi.A_DELETED_AUTO {
  2136  				put(ctxt, nil, "", DeletedAutoSym, 0, a.Gotype)
  2137  				continue
  2138  			}
  2139  
  2140  			// Emit a or p according to actual offset, even if label is wrong.
  2141  			// This avoids negative offsets, which cannot be encoded.
  2142  			if a.Name != objabi.A_AUTO && a.Name != objabi.A_PARAM {
  2143  				continue
  2144  			}
  2145  
  2146  			// compute offset relative to FP
  2147  			if a.Name == objabi.A_PARAM {
  2148  				off = a.Aoffset
  2149  			} else {
  2150  				off = a.Aoffset - int32(ctxt.Arch.PtrSize)
  2151  			}
  2152  
  2153  			// FP
  2154  			if off >= 0 {
  2155  				put(ctxt, nil, a.Asym.Name, ParamSym, int64(off), a.Gotype)
  2156  				continue
  2157  			}
  2158  
  2159  			// SP
  2160  			if off <= int32(-ctxt.Arch.PtrSize) {
  2161  				put(ctxt, nil, a.Asym.Name, AutoSym, -(int64(off) + int64(ctxt.Arch.PtrSize)), a.Gotype)
  2162  				continue
  2163  			}
  2164  			// Otherwise, off is addressing the saved program counter.
  2165  			// Something underhanded is going on. Say nothing.
  2166  		}
  2167  	}
  2168  
  2169  	if ctxt.Debugvlog != 0 || *flagN {
  2170  		ctxt.Logf("%5.2f symsize = %d\n", Cputime(), uint32(Symsize))
  2171  	}
  2172  }
  2173  
  2174  func Symaddr(s *sym.Symbol) int64 {
  2175  	if !s.Attr.Reachable() {
  2176  		Errorf(s, "unreachable symbol in symaddr")
  2177  	}
  2178  	return s.Value
  2179  }
  2180  
  2181  func (ctxt *Link) xdefine(p string, t sym.SymKind, v int64) {
  2182  	s := ctxt.Syms.Lookup(p, 0)
  2183  	s.Type = t
  2184  	s.Value = v
  2185  	s.Attr |= sym.AttrReachable
  2186  	s.Attr |= sym.AttrSpecial
  2187  	s.Attr |= sym.AttrLocal
  2188  }
  2189  
  2190  func datoff(s *sym.Symbol, addr int64) int64 {
  2191  	if uint64(addr) >= Segdata.Vaddr {
  2192  		return int64(uint64(addr) - Segdata.Vaddr + Segdata.Fileoff)
  2193  	}
  2194  	if uint64(addr) >= Segtext.Vaddr {
  2195  		return int64(uint64(addr) - Segtext.Vaddr + Segtext.Fileoff)
  2196  	}
  2197  	Errorf(s, "invalid datoff %#x", addr)
  2198  	return 0
  2199  }
  2200  
  2201  func Entryvalue(ctxt *Link) int64 {
  2202  	a := *flagEntrySymbol
  2203  	if a[0] >= '0' && a[0] <= '9' {
  2204  		return atolwhex(a)
  2205  	}
  2206  	s := ctxt.Syms.Lookup(a, 0)
  2207  	if s.Type == 0 {
  2208  		return *FlagTextAddr
  2209  	}
  2210  	if s.Type != sym.STEXT {
  2211  		Errorf(s, "entry not text")
  2212  	}
  2213  	return s.Value
  2214  }
  2215  
  2216  func undefsym(ctxt *Link, s *sym.Symbol) {
  2217  	var r *sym.Reloc
  2218  
  2219  	for i := 0; i < len(s.R); i++ {
  2220  		r = &s.R[i]
  2221  		if r.Sym == nil { // happens for some external ARM relocs
  2222  			continue
  2223  		}
  2224  		// TODO(mwhudson): the test of VisibilityHidden here probably doesn't make
  2225  		// sense and should be removed when someone has thought about it properly.
  2226  		if (r.Sym.Type == sym.Sxxx || r.Sym.Type == sym.SXREF) && !r.Sym.Attr.VisibilityHidden() {
  2227  			Errorf(s, "undefined: %q", r.Sym.Name)
  2228  		}
  2229  		if !r.Sym.Attr.Reachable() && r.Type != objabi.R_WEAKADDROFF {
  2230  			Errorf(s, "relocation target %q", r.Sym.Name)
  2231  		}
  2232  	}
  2233  }
  2234  
  2235  func (ctxt *Link) undef() {
  2236  	// undefsym performs checks (almost) identical to checks
  2237  	// that report undefined relocations in relocsym.
  2238  	// Both undefsym and relocsym can report same symbol as undefined,
  2239  	// which results in error message duplication (see #10978).
  2240  	//
  2241  	// The undef is run after Arch.Asmb and could detect some
  2242  	// programming errors there, but if object being linked is already
  2243  	// failed with errors, it is better to avoid duplicated errors.
  2244  	if nerrors > 0 {
  2245  		return
  2246  	}
  2247  
  2248  	for _, s := range ctxt.Textp {
  2249  		undefsym(ctxt, s)
  2250  	}
  2251  	for _, s := range datap {
  2252  		undefsym(ctxt, s)
  2253  	}
  2254  	if nerrors > 0 {
  2255  		errorexit()
  2256  	}
  2257  }
  2258  
  2259  func (ctxt *Link) callgraph() {
  2260  	if !*FlagC {
  2261  		return
  2262  	}
  2263  
  2264  	var i int
  2265  	var r *sym.Reloc
  2266  	for _, s := range ctxt.Textp {
  2267  		for i = 0; i < len(s.R); i++ {
  2268  			r = &s.R[i]
  2269  			if r.Sym == nil {
  2270  				continue
  2271  			}
  2272  			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 {
  2273  				ctxt.Logf("%s calls %s\n", s.Name, r.Sym.Name)
  2274  			}
  2275  		}
  2276  	}
  2277  }
  2278  
  2279  func Rnd(v int64, r int64) int64 {
  2280  	if r <= 0 {
  2281  		return v
  2282  	}
  2283  	v += r - 1
  2284  	c := v % r
  2285  	if c < 0 {
  2286  		c += r
  2287  	}
  2288  	v -= c
  2289  	return v
  2290  }
  2291  
  2292  func bgetc(r *bio.Reader) int {
  2293  	c, err := r.ReadByte()
  2294  	if err != nil {
  2295  		if err != io.EOF {
  2296  			log.Fatalf("reading input: %v", err)
  2297  		}
  2298  		return -1
  2299  	}
  2300  	return int(c)
  2301  }
  2302  
  2303  type markKind uint8 // for postorder traversal
  2304  const (
  2305  	_ markKind = iota
  2306  	visiting
  2307  	visited
  2308  )
  2309  
  2310  func postorder(libs []*sym.Library) []*sym.Library {
  2311  	order := make([]*sym.Library, 0, len(libs)) // hold the result
  2312  	mark := make(map[*sym.Library]markKind, len(libs))
  2313  	for _, lib := range libs {
  2314  		dfs(lib, mark, &order)
  2315  	}
  2316  	return order
  2317  }
  2318  
  2319  func dfs(lib *sym.Library, mark map[*sym.Library]markKind, order *[]*sym.Library) {
  2320  	if mark[lib] == visited {
  2321  		return
  2322  	}
  2323  	if mark[lib] == visiting {
  2324  		panic("found import cycle while visiting " + lib.Pkg)
  2325  	}
  2326  	mark[lib] = visiting
  2327  	for _, i := range lib.Imports {
  2328  		dfs(i, mark, order)
  2329  	}
  2330  	mark[lib] = visited
  2331  	*order = append(*order, lib)
  2332  }
  2333  

View as plain text