github.com/tidwall/go@v0.0.0-20170415222209-6694a6888b7d/src/cmd/link/internal/ld/lib.go (about)

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