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