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