github.com/miolini/go@v0.0.0-20160405192216-fca68c8cb408/src/cmd/link/internal/ld/lib.go (about)

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