github.com/rsc/tmp@v0.0.0-20240517235954-6deaab19748b/bootstrap/internal/ld/lib.go (about)

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