1  
     2  
     3  
     4  
     5  
     6  
     7  
     8  
     9  
    10  
    11  
    12  
    13  
    14  
    15  
    16  
    17  
    18  
    19  
    20  
    21  
    22  
    23  
    24  
    25  
    26  
    27  
    28  
    29  
    30  
    31  package ld
    32  
    33  import (
    34  	"bytes"
    35  	"debug/elf"
    36  	"debug/macho"
    37  	"encoding/base64"
    38  	"encoding/binary"
    39  	"fmt"
    40  	"internal/buildcfg"
    41  	"io"
    42  	"log"
    43  	"os"
    44  	"os/exec"
    45  	"path/filepath"
    46  	"runtime"
    47  	"slices"
    48  	"sort"
    49  	"strings"
    50  	"sync"
    51  	"time"
    52  
    53  	"cmd/internal/bio"
    54  	"cmd/internal/goobj"
    55  	"cmd/internal/hash"
    56  	"cmd/internal/objabi"
    57  	"cmd/internal/sys"
    58  	"cmd/link/internal/loadelf"
    59  	"cmd/link/internal/loader"
    60  	"cmd/link/internal/loadmacho"
    61  	"cmd/link/internal/loadpe"
    62  	"cmd/link/internal/loadxcoff"
    63  	"cmd/link/internal/sym"
    64  )
    65  
    66  
    67  
    68  
    69  
    70  
    71  
    72  
    73  
    74  
    75  
    76  
    77  
    78  
    79  
    80  
    81  
    82  
    83  
    84  
    85  
    86  
    87  
    88  
    89  
    90  
    91  
    92  
    93  
    94  
    95  
    96  
    97  
    98  
    99  
   100  
   101  type ArchSyms struct {
   102  	Rel     loader.Sym
   103  	Rela    loader.Sym
   104  	RelPLT  loader.Sym
   105  	RelaPLT loader.Sym
   106  
   107  	LinkEditGOT loader.Sym
   108  	LinkEditPLT loader.Sym
   109  
   110  	TOC    loader.Sym
   111  	DotTOC []loader.Sym 
   112  
   113  	GOT    loader.Sym
   114  	PLT    loader.Sym
   115  	GOTPLT loader.Sym
   116  
   117  	Tlsg      loader.Sym
   118  	Tlsoffset int
   119  
   120  	Dynamic loader.Sym
   121  	DynSym  loader.Sym
   122  	DynStr  loader.Sym
   123  
   124  	unreachableMethod loader.Sym
   125  
   126  	
   127  	
   128  	mainInittasks loader.Sym
   129  }
   130  
   131  
   132  func (ctxt *Link) mkArchSym(name string, ver int, ls *loader.Sym) {
   133  	*ls = ctxt.loader.LookupOrCreateSym(name, ver)
   134  	ctxt.loader.SetAttrReachable(*ls, true)
   135  }
   136  
   137  
   138  
   139  func (ctxt *Link) mkArchSymVec(name string, ver int, ls []loader.Sym) {
   140  	ls[ver] = ctxt.loader.LookupOrCreateSym(name, ver)
   141  	ctxt.loader.SetAttrReachable(ls[ver], true)
   142  }
   143  
   144  
   145  
   146  func (ctxt *Link) setArchSyms() {
   147  	ctxt.mkArchSym(".got", 0, &ctxt.GOT)
   148  	ctxt.mkArchSym(".plt", 0, &ctxt.PLT)
   149  	ctxt.mkArchSym(".got.plt", 0, &ctxt.GOTPLT)
   150  	ctxt.mkArchSym(".dynamic", 0, &ctxt.Dynamic)
   151  	ctxt.mkArchSym(".dynsym", 0, &ctxt.DynSym)
   152  	ctxt.mkArchSym(".dynstr", 0, &ctxt.DynStr)
   153  	ctxt.mkArchSym("runtime.unreachableMethod", abiInternalVer, &ctxt.unreachableMethod)
   154  
   155  	if ctxt.IsPPC64() {
   156  		ctxt.mkArchSym("TOC", 0, &ctxt.TOC)
   157  
   158  		ctxt.DotTOC = make([]loader.Sym, ctxt.MaxVersion()+1)
   159  		for i := 0; i <= ctxt.MaxVersion(); i++ {
   160  			if i >= sym.SymVerABICount && i < sym.SymVerStatic { 
   161  				continue
   162  			}
   163  			ctxt.mkArchSymVec(".TOC.", i, ctxt.DotTOC)
   164  		}
   165  	}
   166  	if ctxt.IsElf() {
   167  		ctxt.mkArchSym(".rel", 0, &ctxt.Rel)
   168  		ctxt.mkArchSym(".rela", 0, &ctxt.Rela)
   169  		ctxt.mkArchSym(".rel.plt", 0, &ctxt.RelPLT)
   170  		ctxt.mkArchSym(".rela.plt", 0, &ctxt.RelaPLT)
   171  	}
   172  	if ctxt.IsDarwin() {
   173  		ctxt.mkArchSym(".linkedit.got", 0, &ctxt.LinkEditGOT)
   174  		ctxt.mkArchSym(".linkedit.plt", 0, &ctxt.LinkEditPLT)
   175  	}
   176  }
   177  
   178  type Arch struct {
   179  	Funcalign  int
   180  	Maxalign   int
   181  	Minalign   int
   182  	Dwarfregsp int
   183  	Dwarfreglr int
   184  
   185  	
   186  	
   187  	
   188  	
   189  	TrampLimit uint64
   190  
   191  	
   192  	
   193  	
   194  	
   195  	CodePad []byte
   196  
   197  	
   198  	Plan9Magic  uint32
   199  	Plan9_64Bit bool
   200  
   201  	Adddynrel func(*Target, *loader.Loader, *ArchSyms, loader.Sym, loader.Reloc, int) bool
   202  	Archinit  func(*Link)
   203  	
   204  	
   205  	
   206  	
   207  	
   208  	
   209  	
   210  	
   211  	
   212  	
   213  	Archreloc func(*Target, *loader.Loader, *ArchSyms, loader.Reloc, loader.Sym,
   214  		int64) (relocatedOffset int64, nExtReloc int, ok bool)
   215  	
   216  	
   217  	
   218  	
   219  	
   220  	
   221  	
   222  	
   223  	Archrelocvariant func(target *Target, ldr *loader.Loader, rel loader.Reloc,
   224  		rv sym.RelocVariant, sym loader.Sym, offset int64, data []byte) (relocatedOffset int64)
   225  
   226  	
   227  	
   228  	Trampoline func(ctxt *Link, ldr *loader.Loader, ri int, rs, s loader.Sym)
   229  
   230  	
   231  	
   232  	
   233  	
   234  	
   235  	
   236  	
   237  	Asmb  func(*Link, *loader.Loader)
   238  	Asmb2 func(*Link, *loader.Loader)
   239  
   240  	
   241  	
   242  	
   243  	Extreloc func(*Target, *loader.Loader, loader.Reloc, loader.Sym) (loader.ExtReloc, bool)
   244  
   245  	Gentext        func(*Link, *loader.Loader) 
   246  	Machoreloc1    func(*sys.Arch, *OutBuf, *loader.Loader, loader.Sym, loader.ExtReloc, int64) bool
   247  	MachorelocSize uint32 
   248  	PEreloc1       func(*sys.Arch, *OutBuf, *loader.Loader, loader.Sym, loader.ExtReloc, int64) bool
   249  	Xcoffreloc1    func(*sys.Arch, *OutBuf, *loader.Loader, loader.Sym, loader.ExtReloc, int64) bool
   250  
   251  	
   252  	
   253  	GenSymsLate func(*Link, *loader.Loader)
   254  
   255  	
   256  	
   257  	
   258  	
   259  	
   260  	
   261  	TLSIEtoLE func(P []byte, off, size int)
   262  
   263  	
   264  	AssignAddress func(ldr *loader.Loader, sect *sym.Section, n int, s loader.Sym, va uint64, isTramp bool) (*sym.Section, int, uint64)
   265  
   266  	
   267  	ELF ELFArch
   268  }
   269  
   270  var (
   271  	thearch Arch
   272  	lcSize  int32
   273  	rpath   Rpath
   274  	spSize  int32
   275  	symSize int32
   276  )
   277  
   278  
   279  
   280  var abiInternalVer = sym.SymVerABIInternal
   281  
   282  
   283  
   284  func (ctxt *Link) DynlinkingGo() bool {
   285  	if !ctxt.Loaded {
   286  		panic("DynlinkingGo called before all symbols loaded")
   287  	}
   288  	return ctxt.BuildMode == BuildModeShared || ctxt.linkShared || ctxt.BuildMode == BuildModePlugin || ctxt.canUsePlugins
   289  }
   290  
   291  
   292  func (ctxt *Link) CanUsePlugins() bool {
   293  	if !ctxt.Loaded {
   294  		panic("CanUsePlugins called before all symbols loaded")
   295  	}
   296  	return ctxt.canUsePlugins
   297  }
   298  
   299  
   300  func (ctxt *Link) NeedCodeSign() bool {
   301  	return ctxt.IsDarwin() && ctxt.IsARM64()
   302  }
   303  
   304  var (
   305  	dynlib          []string
   306  	ldflag          []string
   307  	havedynamic     int
   308  	Funcalign       int
   309  	iscgo           bool
   310  	elfglobalsymndx int
   311  	interpreter     string
   312  
   313  	debug_s bool 
   314  	HEADR   int32
   315  
   316  	nerrors  int
   317  	liveness int64 
   318  
   319  	
   320  	checkStrictDups   int 
   321  	strictDupMsgCount int
   322  )
   323  
   324  var (
   325  	Segtext      sym.Segment
   326  	Segrodata    sym.Segment
   327  	Segrelrodata sym.Segment
   328  	Segdata      sym.Segment
   329  	Segdwarf     sym.Segment
   330  	Segpdata     sym.Segment 
   331  	Segxdata     sym.Segment 
   332  
   333  	Segments = []*sym.Segment{&Segtext, &Segrodata, &Segrelrodata, &Segdata, &Segdwarf, &Segpdata, &Segxdata}
   334  )
   335  
   336  const pkgdef = "__.PKGDEF"
   337  
   338  var (
   339  	
   340  	
   341  	
   342  	externalobj = false
   343  
   344  	
   345  	
   346  	
   347  	dynimportfail []string
   348  
   349  	
   350  	
   351  	
   352  	
   353  	preferlinkext []string
   354  
   355  	
   356  	
   357  	unknownObjFormat = false
   358  
   359  	theline string
   360  )
   361  
   362  func Lflag(ctxt *Link, arg string) {
   363  	ctxt.Libdir = append(ctxt.Libdir, arg)
   364  }
   365  
   366  
   372  func mayberemoveoutfile() {
   373  	if fi, err := os.Lstat(*flagOutfile); err == nil && !fi.Mode().IsRegular() {
   374  		return
   375  	}
   376  	os.Remove(*flagOutfile)
   377  }
   378  
   379  func libinit(ctxt *Link) {
   380  	if *FlagFuncAlign != 0 {
   381  		Funcalign = *FlagFuncAlign
   382  	} else {
   383  		Funcalign = thearch.Funcalign
   384  	}
   385  
   386  	
   387  	suffix := ""
   388  
   389  	suffixsep := ""
   390  	if *flagInstallSuffix != "" {
   391  		suffixsep = "_"
   392  		suffix = *flagInstallSuffix
   393  	} else if *flagRace {
   394  		suffixsep = "_"
   395  		suffix = "race"
   396  	} else if *flagMsan {
   397  		suffixsep = "_"
   398  		suffix = "msan"
   399  	} else if *flagAsan {
   400  		suffixsep = "_"
   401  		suffix = "asan"
   402  	}
   403  
   404  	if buildcfg.GOROOT != "" {
   405  		Lflag(ctxt, filepath.Join(buildcfg.GOROOT, "pkg", fmt.Sprintf("%s_%s%s%s", buildcfg.GOOS, buildcfg.GOARCH, suffixsep, suffix)))
   406  	}
   407  
   408  	mayberemoveoutfile()
   409  
   410  	if err := ctxt.Out.Open(*flagOutfile); err != nil {
   411  		Exitf("cannot create %s: %v", *flagOutfile, err)
   412  	}
   413  
   414  	if *flagEntrySymbol == "" {
   415  		switch ctxt.BuildMode {
   416  		case BuildModeCShared, BuildModeCArchive:
   417  			*flagEntrySymbol = fmt.Sprintf("_rt0_%s_%s_lib", buildcfg.GOARCH, buildcfg.GOOS)
   418  		case BuildModeExe, BuildModePIE:
   419  			*flagEntrySymbol = fmt.Sprintf("_rt0_%s_%s", buildcfg.GOARCH, buildcfg.GOOS)
   420  		case BuildModeShared, BuildModePlugin:
   421  			
   422  		default:
   423  			Errorf("unknown *flagEntrySymbol for buildmode %v", ctxt.BuildMode)
   424  		}
   425  	}
   426  }
   427  
   428  func exitIfErrors() {
   429  	if nerrors != 0 || checkStrictDups > 1 && strictDupMsgCount > 0 {
   430  		mayberemoveoutfile()
   431  		Exit(2)
   432  	}
   433  
   434  }
   435  
   436  func errorexit() {
   437  	exitIfErrors()
   438  	Exit(0)
   439  }
   440  
   441  func loadinternal(ctxt *Link, name string) *sym.Library {
   442  	zerofp := goobj.FingerprintType{}
   443  	if ctxt.linkShared && ctxt.PackageShlib != nil {
   444  		if shlib := ctxt.PackageShlib[name]; shlib != "" {
   445  			return addlibpath(ctxt, "internal", "internal", "", name, shlib, zerofp)
   446  		}
   447  	}
   448  	if ctxt.PackageFile != nil {
   449  		if pname := ctxt.PackageFile[name]; pname != "" {
   450  			return addlibpath(ctxt, "internal", "internal", pname, name, "", zerofp)
   451  		}
   452  		ctxt.Logf("loadinternal: cannot find %s\n", name)
   453  		return nil
   454  	}
   455  
   456  	for _, libdir := range ctxt.Libdir {
   457  		if ctxt.linkShared {
   458  			shlibname := filepath.Join(libdir, name+".shlibname")
   459  			if ctxt.Debugvlog != 0 {
   460  				ctxt.Logf("searching for %s.a in %s\n", name, shlibname)
   461  			}
   462  			if _, err := os.Stat(shlibname); err == nil {
   463  				return addlibpath(ctxt, "internal", "internal", "", name, shlibname, zerofp)
   464  			}
   465  		}
   466  		pname := filepath.Join(libdir, name+".a")
   467  		if ctxt.Debugvlog != 0 {
   468  			ctxt.Logf("searching for %s.a in %s\n", name, pname)
   469  		}
   470  		if _, err := os.Stat(pname); err == nil {
   471  			return addlibpath(ctxt, "internal", "internal", pname, name, "", zerofp)
   472  		}
   473  	}
   474  
   475  	if name == "runtime" {
   476  		Exitf("error: unable to find runtime.a")
   477  	}
   478  	ctxt.Logf("warning: unable to find %s.a\n", name)
   479  	return nil
   480  }
   481  
   482  
   483  func (ctxt *Link) extld() []string {
   484  	if len(flagExtld) == 0 {
   485  		
   486  		
   487  		
   488  		switch buildcfg.GOOS {
   489  		case "darwin", "freebsd", "openbsd":
   490  			flagExtld = []string{"clang"}
   491  		default:
   492  			flagExtld = []string{"gcc"}
   493  		}
   494  	}
   495  	return flagExtld
   496  }
   497  
   498  
   499  
   500  func (ctxt *Link) findLibPathCmd(cmd, libname string) string {
   501  	extld := ctxt.extld()
   502  	name, args := extld[0], extld[1:]
   503  	args = append(args, hostlinkArchArgs(ctxt.Arch)...)
   504  	args = append(args, cmd)
   505  	if ctxt.Debugvlog != 0 {
   506  		ctxt.Logf("%s %v\n", extld, args)
   507  	}
   508  	out, err := exec.Command(name, args...).Output()
   509  	if err != nil {
   510  		if ctxt.Debugvlog != 0 {
   511  			ctxt.Logf("not using a %s file because compiler failed\n%v\n%s\n", libname, err, out)
   512  		}
   513  		return "none"
   514  	}
   515  	return strings.TrimSpace(string(out))
   516  }
   517  
   518  
   519  
   520  func (ctxt *Link) findLibPath(libname string) string {
   521  	return ctxt.findLibPathCmd("--print-file-name="+libname, libname)
   522  }
   523  
   524  func (ctxt *Link) loadlib() {
   525  	var flags uint32
   526  	if *flagCheckLinkname {
   527  		flags |= loader.FlagCheckLinkname
   528  	}
   529  	switch *FlagStrictDups {
   530  	case 0:
   531  		
   532  	case 1, 2:
   533  		flags |= loader.FlagStrictDups
   534  	default:
   535  		log.Fatalf("invalid -strictdups flag value %d", *FlagStrictDups)
   536  	}
   537  	ctxt.loader = loader.NewLoader(flags, &ctxt.ErrorReporter.ErrorReporter)
   538  	ctxt.ErrorReporter.SymName = func(s loader.Sym) string {
   539  		return ctxt.loader.SymName(s)
   540  	}
   541  
   542  	
   543  	i := 0
   544  	for ; i < len(ctxt.Library); i++ {
   545  		lib := ctxt.Library[i]
   546  		if lib.Shlib == "" {
   547  			if ctxt.Debugvlog > 1 {
   548  				ctxt.Logf("autolib: %s (from %s)\n", lib.File, lib.Objref)
   549  			}
   550  			loadobjfile(ctxt, lib)
   551  		}
   552  	}
   553  
   554  	
   555  	if *flagRace {
   556  		loadinternal(ctxt, "runtime/race")
   557  	}
   558  	if *flagMsan {
   559  		loadinternal(ctxt, "runtime/msan")
   560  	}
   561  	if *flagAsan {
   562  		loadinternal(ctxt, "runtime/asan")
   563  	}
   564  	loadinternal(ctxt, "runtime")
   565  	for ; i < len(ctxt.Library); i++ {
   566  		lib := ctxt.Library[i]
   567  		if lib.Shlib == "" {
   568  			loadobjfile(ctxt, lib)
   569  		}
   570  	}
   571  	
   572  	
   573  	
   574  
   575  	iscgo = ctxt.LibraryByPkg["runtime/cgo"] != nil
   576  
   577  	
   578  	
   579  	ctxt.canUsePlugins = ctxt.LibraryByPkg["plugin"] != nil && iscgo
   580  
   581  	
   582  	determineLinkMode(ctxt)
   583  
   584  	if ctxt.LinkMode == LinkExternal && !iscgo && !(buildcfg.GOOS == "darwin" && ctxt.BuildMode != BuildModePlugin && ctxt.Arch.Family == sys.AMD64) {
   585  		
   586  		
   587  		
   588  		
   589  		if lib := loadinternal(ctxt, "runtime/cgo"); lib != nil && lib.Shlib == "" {
   590  			if ctxt.BuildMode == BuildModeShared || ctxt.linkShared {
   591  				Exitf("cannot implicitly include runtime/cgo in a shared library")
   592  			}
   593  			for ; i < len(ctxt.Library); i++ {
   594  				lib := ctxt.Library[i]
   595  				if lib.Shlib == "" {
   596  					loadobjfile(ctxt, lib)
   597  				}
   598  			}
   599  		}
   600  	}
   601  
   602  	
   603  	ctxt.loader.LoadSyms(ctxt.Arch)
   604  
   605  	
   606  	for _, lib := range ctxt.Library {
   607  		if lib.Shlib != "" {
   608  			if ctxt.Debugvlog > 1 {
   609  				ctxt.Logf("autolib: %s (from %s)\n", lib.Shlib, lib.Objref)
   610  			}
   611  			ldshlibsyms(ctxt, lib.Shlib)
   612  		}
   613  	}
   614  
   615  	
   616  	ctxt.loadcgodirectives()
   617  
   618  	
   619  	hostobjs(ctxt)
   620  	hostlinksetup(ctxt)
   621  
   622  	if ctxt.LinkMode == LinkInternal && len(hostobj) != 0 {
   623  		
   624  		
   625  		any := false
   626  		undefs, froms := ctxt.loader.UndefinedRelocTargets(1)
   627  		if len(undefs) > 0 {
   628  			any = true
   629  			if ctxt.Debugvlog > 1 {
   630  				ctxt.Logf("loadlib: first unresolved is %s [%d] from %s [%d]\n",
   631  					ctxt.loader.SymName(undefs[0]), undefs[0],
   632  					ctxt.loader.SymName(froms[0]), froms[0])
   633  			}
   634  		}
   635  		if any {
   636  			if *flagLibGCC == "" {
   637  				*flagLibGCC = ctxt.findLibPathCmd("--print-libgcc-file-name", "libgcc")
   638  			}
   639  			if runtime.GOOS == "freebsd" && strings.HasPrefix(filepath.Base(*flagLibGCC), "libclang_rt.builtins") {
   640  				
   641  				
   642  				
   643  				
   644  				*flagLibGCC = ctxt.findLibPathCmd("--print-file-name=libcompiler_rt.a", "libcompiler_rt")
   645  			}
   646  			if runtime.GOOS == "openbsd" && *flagLibGCC == "libgcc.a" {
   647  				
   648  				
   649  				
   650  				*flagLibGCC = ctxt.findLibPathCmd("--print-file-name=libcompiler_rt.a", "libcompiler_rt")
   651  			}
   652  			if ctxt.HeadType == objabi.Hwindows {
   653  				loadWindowsHostArchives(ctxt)
   654  			}
   655  			if *flagLibGCC != "none" {
   656  				hostArchive(ctxt, *flagLibGCC)
   657  			}
   658  			
   659  			
   660  			
   661  			
   662  			
   663  			
   664  			
   665  			
   666  			
   667  			
   668  			
   669  			
   670  			
   671  			
   672  			
   673  			
   674  			isunresolved := symbolsAreUnresolved(ctxt, []string{"__stack_chk_fail_local"})
   675  			if isunresolved[0] {
   676  				if p := ctxt.findLibPath("libc_nonshared.a"); p != "none" {
   677  					hostArchive(ctxt, p)
   678  				}
   679  				if p := ctxt.findLibPath("libssp_nonshared.a"); p != "none" {
   680  					hostArchive(ctxt, p)
   681  				}
   682  			}
   683  		}
   684  	}
   685  
   686  	loadfips(ctxt)
   687  
   688  	
   689  	ctxt.Loaded = true
   690  
   691  	strictDupMsgCount = ctxt.loader.NStrictDupMsgs()
   692  }
   693  
   694  
   695  
   696  
   697  
   698  
   699  
   700  
   701  func loadWindowsHostArchives(ctxt *Link) {
   702  	any := true
   703  	for i := 0; any && i < 2; i++ {
   704  		
   705  		
   706  		isunresolved := symbolsAreUnresolved(ctxt, []string{"atexit"})
   707  		if isunresolved[0] {
   708  			if p := ctxt.findLibPath("crt2.o"); p != "none" {
   709  				hostObject(ctxt, "crt2", p)
   710  			}
   711  		}
   712  		if *flagRace {
   713  			if p := ctxt.findLibPath("libsynchronization.a"); p != "none" {
   714  				hostArchive(ctxt, p)
   715  			}
   716  		}
   717  		if p := ctxt.findLibPath("libmingwex.a"); p != "none" {
   718  			hostArchive(ctxt, p)
   719  		}
   720  		if p := ctxt.findLibPath("libmingw32.a"); p != "none" {
   721  			hostArchive(ctxt, p)
   722  		}
   723  		
   724  		
   725  		if p := ctxt.findLibPath("libmsvcrt.a"); p != "none" {
   726  			hostArchive(ctxt, p)
   727  		}
   728  		any = false
   729  		undefs, froms := ctxt.loader.UndefinedRelocTargets(1)
   730  		if len(undefs) > 0 {
   731  			any = true
   732  			if ctxt.Debugvlog > 1 {
   733  				ctxt.Logf("loadWindowsHostArchives: remaining unresolved is %s [%d] from %s [%d]\n",
   734  					ctxt.loader.SymName(undefs[0]), undefs[0],
   735  					ctxt.loader.SymName(froms[0]), froms[0])
   736  			}
   737  		}
   738  	}
   739  	
   740  	
   741  	
   742  	
   743  	want := []string{"__CTOR_LIST__", "__DTOR_LIST__"}
   744  	isunresolved := symbolsAreUnresolved(ctxt, want)
   745  	for k, w := range want {
   746  		if isunresolved[k] {
   747  			sb := ctxt.loader.CreateSymForUpdate(w, 0)
   748  			sb.SetType(sym.SDATA)
   749  			sb.AddUint64(ctxt.Arch, 0)
   750  			sb.SetReachable(true)
   751  			ctxt.loader.SetAttrSpecial(sb.Sym(), true)
   752  		}
   753  	}
   754  
   755  	
   756  	
   757  	if err := loadpe.PostProcessImports(); err != nil {
   758  		Errorf("%v", err)
   759  	}
   760  
   761  	
   762  	
   763  	
   764  	
   770  }
   771  
   772  
   773  
   774  func (ctxt *Link) loadcgodirectives() {
   775  	l := ctxt.loader
   776  	hostObjSyms := make(map[loader.Sym]struct{})
   777  	for _, d := range ctxt.cgodata {
   778  		setCgoAttr(ctxt, d.file, d.pkg, d.directives, hostObjSyms)
   779  	}
   780  	ctxt.cgodata = nil
   781  
   782  	if ctxt.LinkMode == LinkInternal {
   783  		
   784  		
   785  		for symIdx := range hostObjSyms {
   786  			if l.SymType(symIdx) == sym.SHOSTOBJ {
   787  				
   788  				
   789  				
   790  				
   791  				su := l.MakeSymbolUpdater(symIdx)
   792  				if l.SymExtname(symIdx) != "" && l.SymDynimplib(symIdx) != "" && !(l.AttrCgoExportStatic(symIdx) || l.AttrCgoExportDynamic(symIdx)) {
   793  					su.SetType(sym.SDYNIMPORT)
   794  				} else {
   795  					su.SetType(0)
   796  				}
   797  			}
   798  		}
   799  	}
   800  }
   801  
   802  
   803  
   804  func (ctxt *Link) linksetup() {
   805  	switch ctxt.BuildMode {
   806  	case BuildModeCShared, BuildModePlugin:
   807  		symIdx := ctxt.loader.LookupOrCreateSym("runtime.islibrary", 0)
   808  		sb := ctxt.loader.MakeSymbolUpdater(symIdx)
   809  		sb.SetType(sym.SNOPTRDATA)
   810  		sb.AddUint8(1)
   811  	case BuildModeCArchive:
   812  		symIdx := ctxt.loader.LookupOrCreateSym("runtime.isarchive", 0)
   813  		sb := ctxt.loader.MakeSymbolUpdater(symIdx)
   814  		sb.SetType(sym.SNOPTRDATA)
   815  		sb.AddUint8(1)
   816  	}
   817  
   818  	
   819  	if ctxt.HeadType == objabi.Hwindows {
   820  		Peinit(ctxt)
   821  	}
   822  
   823  	if ctxt.LinkMode == LinkExternal {
   824  		
   825  		
   826  		*FlagTextAddr = 0
   827  	}
   828  
   829  	
   830  	
   831  	
   832  	
   833  	
   834  	
   835  	
   836  	
   837  	
   838  	
   839  	if ctxt.BuildMode == BuildModeExe {
   840  		if havedynamic == 0 && ctxt.HeadType != objabi.Hdarwin && ctxt.HeadType != objabi.Hsolaris {
   841  			*FlagD = true
   842  		}
   843  	}
   844  
   845  	if ctxt.LinkMode == LinkExternal && ctxt.Arch.Family == sys.PPC64 && buildcfg.GOOS != "aix" {
   846  		toc := ctxt.loader.LookupOrCreateSym(".TOC.", 0)
   847  		sb := ctxt.loader.MakeSymbolUpdater(toc)
   848  		sb.SetType(sym.SDYNIMPORT)
   849  	}
   850  
   851  	
   852  	
   853  	
   854  	if buildcfg.GOOS != "android" {
   855  		tlsg := ctxt.loader.LookupOrCreateSym("runtime.tlsg", 0)
   856  		sb := ctxt.loader.MakeSymbolUpdater(tlsg)
   857  
   858  		
   859  		
   860  		if sb.Type() == 0 {
   861  			sb.SetType(sym.STLSBSS)
   862  			sb.SetSize(int64(ctxt.Arch.PtrSize))
   863  		} else if sb.Type() != sym.SDYNIMPORT {
   864  			Errorf("runtime declared tlsg variable %v", sb.Type())
   865  		}
   866  		ctxt.loader.SetAttrReachable(tlsg, true)
   867  		ctxt.Tlsg = tlsg
   868  	}
   869  
   870  	var moduledata loader.Sym
   871  	var mdsb *loader.SymbolBuilder
   872  	if ctxt.BuildMode == BuildModePlugin {
   873  		moduledata = ctxt.loader.LookupOrCreateSym("local.pluginmoduledata", 0)
   874  		mdsb = ctxt.loader.MakeSymbolUpdater(moduledata)
   875  		ctxt.loader.SetAttrLocal(moduledata, true)
   876  	} else {
   877  		moduledata = ctxt.loader.LookupOrCreateSym("runtime.firstmoduledata", 0)
   878  		mdsb = ctxt.loader.MakeSymbolUpdater(moduledata)
   879  	}
   880  	if mdsb.Type() != 0 && mdsb.Type() != sym.SDYNIMPORT {
   881  		
   882  		
   883  		
   884  		
   885  		
   886  		mdsb.SetSize(0)
   887  
   888  		
   889  		
   890  		if ctxt.Arch.Family == sys.ARM {
   891  			goarm := ctxt.loader.LookupOrCreateSym("runtime.goarm", 0)
   892  			sb := ctxt.loader.MakeSymbolUpdater(goarm)
   893  			sb.SetType(sym.SNOPTRDATA)
   894  			sb.SetSize(0)
   895  			sb.AddUint8(uint8(buildcfg.GOARM.Version))
   896  
   897  			goarmsoftfp := ctxt.loader.LookupOrCreateSym("runtime.goarmsoftfp", 0)
   898  			sb2 := ctxt.loader.MakeSymbolUpdater(goarmsoftfp)
   899  			sb2.SetType(sym.SNOPTRDATA)
   900  			sb2.SetSize(0)
   901  			if buildcfg.GOARM.SoftFloat {
   902  				sb2.AddUint8(1)
   903  			} else {
   904  				sb2.AddUint8(0)
   905  			}
   906  		}
   907  
   908  		
   909  		
   910  		
   911  		memProfile := ctxt.loader.Lookup("runtime.memProfileInternal", abiInternalVer)
   912  		if memProfile != 0 && !ctxt.loader.AttrReachable(memProfile) && !ctxt.DynlinkingGo() {
   913  			memProfSym := ctxt.loader.LookupOrCreateSym("runtime.disableMemoryProfiling", 0)
   914  			sb := ctxt.loader.MakeSymbolUpdater(memProfSym)
   915  			sb.SetType(sym.SNOPTRDATA)
   916  			sb.SetSize(0)
   917  			sb.AddUint8(1) 
   918  		}
   919  	} else {
   920  		
   921  		
   922  		moduledata = ctxt.loader.LookupOrCreateSym("local.moduledata", 0)
   923  		mdsb = ctxt.loader.MakeSymbolUpdater(moduledata)
   924  		ctxt.loader.SetAttrLocal(moduledata, true)
   925  	}
   926  	
   927  	
   928  	mdsb.SetType(sym.SNOPTRDATA)
   929  	ctxt.loader.SetAttrReachable(moduledata, true)
   930  	ctxt.Moduledata = moduledata
   931  
   932  	if ctxt.Arch == sys.Arch386 && ctxt.HeadType != objabi.Hwindows {
   933  		if (ctxt.BuildMode == BuildModeCArchive && ctxt.IsELF) || ctxt.BuildMode == BuildModeCShared || ctxt.BuildMode == BuildModePIE || ctxt.DynlinkingGo() {
   934  			got := ctxt.loader.LookupOrCreateSym("_GLOBAL_OFFSET_TABLE_", 0)
   935  			sb := ctxt.loader.MakeSymbolUpdater(got)
   936  			sb.SetType(sym.SDYNIMPORT)
   937  			ctxt.loader.SetAttrReachable(got, true)
   938  		}
   939  	}
   940  
   941  	
   942  	
   943  	
   944  	
   945  	
   946  	
   947  	ctxt.Library = postorder(ctxt.Library)
   948  	intlibs := []bool{}
   949  	for _, lib := range ctxt.Library {
   950  		intlibs = append(intlibs, isRuntimeDepPkg(lib.Pkg))
   951  	}
   952  	ctxt.Textp = ctxt.loader.AssignTextSymbolOrder(ctxt.Library, intlibs, ctxt.Textp)
   953  }
   954  
   955  
   956  
   957  
   958  
   959  
   960  
   961  
   962  
   963  
   964  
   965  
   966  
   967  
   968  func (ctxt *Link) mangleTypeSym() {
   969  	if ctxt.BuildMode != BuildModeShared && !ctxt.linkShared && ctxt.BuildMode != BuildModePlugin && !ctxt.CanUsePlugins() {
   970  		return
   971  	}
   972  
   973  	ldr := ctxt.loader
   974  	for s := loader.Sym(1); s < loader.Sym(ldr.NSym()); s++ {
   975  		if !ldr.AttrReachable(s) && !ctxt.linkShared {
   976  			
   977  			
   978  			
   979  			
   980  			
   981  			continue
   982  		}
   983  		name := ldr.SymName(s)
   984  		newName := typeSymbolMangle(name)
   985  		if newName != name {
   986  			ldr.SetSymExtname(s, newName)
   987  
   988  			
   989  			
   990  			
   991  			
   992  			
   993  			dup := ldr.Lookup(newName, ldr.SymVersion(s))
   994  			if dup != 0 {
   995  				st := ldr.SymType(s)
   996  				dt := ldr.SymType(dup)
   997  				if st == sym.Sxxx && dt != sym.Sxxx {
   998  					ldr.CopySym(dup, s)
   999  				}
  1000  			}
  1001  		}
  1002  	}
  1003  }
  1004  
  1005  
  1006  
  1007  
  1008  
  1009  
  1010  
  1011  func typeSymbolMangle(name string) string {
  1012  	isType := strings.HasPrefix(name, "type:")
  1013  	if !isType && !strings.Contains(name, "@") {
  1014  		
  1015  		return name
  1016  	}
  1017  	if strings.HasPrefix(name, "type:runtime.") {
  1018  		return name
  1019  	}
  1020  	if strings.HasPrefix(name, "go:string.") {
  1021  		
  1022  		
  1023  		return name
  1024  	}
  1025  	if len(name) <= 14 && !strings.Contains(name, "@") { 
  1026  		return name
  1027  	}
  1028  	if isType {
  1029  		hb := hash.Sum32([]byte(name[5:]))
  1030  		prefix := "type:"
  1031  		if name[5] == '.' {
  1032  			prefix = "type:."
  1033  		}
  1034  		return prefix + base64.StdEncoding.EncodeToString(hb[:6])
  1035  	}
  1036  	
  1037  	i := strings.IndexByte(name, '[')
  1038  	j := strings.LastIndexByte(name, ']')
  1039  	if j == -1 || j <= i {
  1040  		j = len(name)
  1041  	}
  1042  	hb := hash.Sum32([]byte(name[i+1 : j]))
  1043  	return name[:i+1] + base64.StdEncoding.EncodeToString(hb[:6]) + name[j:]
  1044  }
  1045  
  1046  
  1050  func nextar(bp *bio.Reader, off int64, a *ArHdr) int64 {
  1051  	if off&1 != 0 {
  1052  		off++
  1053  	}
  1054  	bp.MustSeek(off, 0)
  1055  	var buf [SAR_HDR]byte
  1056  	if n, err := io.ReadFull(bp, buf[:]); err != nil {
  1057  		if n == 0 && err != io.EOF {
  1058  			return -1
  1059  		}
  1060  		return 0
  1061  	}
  1062  
  1063  	a.name = artrim(buf[0:16])
  1064  	a.date = artrim(buf[16:28])
  1065  	a.uid = artrim(buf[28:34])
  1066  	a.gid = artrim(buf[34:40])
  1067  	a.mode = artrim(buf[40:48])
  1068  	a.size = artrim(buf[48:58])
  1069  	a.fmag = artrim(buf[58:60])
  1070  
  1071  	arsize := atolwhex(a.size)
  1072  	if arsize&1 != 0 {
  1073  		arsize++
  1074  	}
  1075  	return arsize + SAR_HDR
  1076  }
  1077  
  1078  func loadobjfile(ctxt *Link, lib *sym.Library) {
  1079  	pkg := objabi.PathToPrefix(lib.Pkg)
  1080  
  1081  	if ctxt.Debugvlog > 1 {
  1082  		ctxt.Logf("ldobj: %s (%s)\n", lib.File, pkg)
  1083  	}
  1084  	f, err := bio.Open(lib.File)
  1085  	if err != nil {
  1086  		Exitf("cannot open file %s: %v", lib.File, err)
  1087  	}
  1088  	defer f.Close()
  1089  	defer func() {
  1090  		if pkg == "main" && !lib.Main {
  1091  			Exitf("%s: not package main", lib.File)
  1092  		}
  1093  	}()
  1094  
  1095  	for i := 0; i < len(ARMAG); i++ {
  1096  		if c, err := f.ReadByte(); err == nil && c == ARMAG[i] {
  1097  			continue
  1098  		}
  1099  
  1100  		
  1101  		l := f.MustSeek(0, 2)
  1102  		f.MustSeek(0, 0)
  1103  		ldobj(ctxt, f, lib, l, lib.File, lib.File)
  1104  		return
  1105  	}
  1106  
  1107  	
  1119  	var arhdr ArHdr
  1120  	off := f.Offset()
  1121  	for {
  1122  		l := nextar(f, off, &arhdr)
  1123  		if l == 0 {
  1124  			break
  1125  		}
  1126  		if l < 0 {
  1127  			Exitf("%s: malformed archive", lib.File)
  1128  		}
  1129  		off += l
  1130  
  1131  		
  1132  		
  1133  		
  1134  		
  1135  		if arhdr.name == pkgdef {
  1136  			continue
  1137  		}
  1138  
  1139  		if arhdr.name == "dynimportfail" {
  1140  			dynimportfail = append(dynimportfail, lib.Pkg)
  1141  		}
  1142  		if arhdr.name == "preferlinkext" {
  1143  			
  1144  			
  1145  			if ctxt.LinkMode == LinkAuto {
  1146  				preferlinkext = append(preferlinkext, lib.Pkg)
  1147  			}
  1148  		}
  1149  
  1150  		
  1151  		
  1152  		
  1153  		if len(arhdr.name) < 16 {
  1154  			if ext := filepath.Ext(arhdr.name); ext != ".o" && ext != ".syso" {
  1155  				continue
  1156  			}
  1157  		}
  1158  
  1159  		pname := fmt.Sprintf("%s(%s)", lib.File, arhdr.name)
  1160  		l = atolwhex(arhdr.size)
  1161  		ldobj(ctxt, f, lib, l, pname, lib.File)
  1162  	}
  1163  }
  1164  
  1165  type Hostobj struct {
  1166  	ld     func(*Link, *bio.Reader, string, int64, string)
  1167  	pkg    string
  1168  	pn     string
  1169  	file   string
  1170  	off    int64
  1171  	length int64
  1172  }
  1173  
  1174  var hostobj []Hostobj
  1175  
  1176  
  1177  
  1178  var internalpkg = []string{
  1179  	"crypto/internal/boring",
  1180  	"crypto/internal/boring/syso",
  1181  	"crypto/x509",
  1182  	"net",
  1183  	"os/user",
  1184  	"runtime/cgo",
  1185  	"runtime/race",
  1186  	"runtime/race/internal/amd64v1",
  1187  	"runtime/race/internal/amd64v3",
  1188  	"runtime/msan",
  1189  	"runtime/asan",
  1190  }
  1191  
  1192  func ldhostobj(ld func(*Link, *bio.Reader, string, int64, string), headType objabi.HeadType, f *bio.Reader, pkg string, length int64, pn string, file string) *Hostobj {
  1193  	isinternal := false
  1194  	for _, intpkg := range internalpkg {
  1195  		if pkg == intpkg {
  1196  			isinternal = true
  1197  			break
  1198  		}
  1199  	}
  1200  
  1201  	
  1202  	
  1203  	
  1204  	
  1205  	
  1206  	
  1207  	if headType == objabi.Hdragonfly {
  1208  		if pkg == "net" || pkg == "os/user" {
  1209  			isinternal = false
  1210  		}
  1211  	}
  1212  
  1213  	if !isinternal {
  1214  		externalobj = true
  1215  	}
  1216  
  1217  	hostobj = append(hostobj, Hostobj{})
  1218  	h := &hostobj[len(hostobj)-1]
  1219  	h.ld = ld
  1220  	h.pkg = pkg
  1221  	h.pn = pn
  1222  	h.file = file
  1223  	h.off = f.Offset()
  1224  	h.length = length
  1225  	return h
  1226  }
  1227  
  1228  func hostobjs(ctxt *Link) {
  1229  	if ctxt.LinkMode != LinkInternal {
  1230  		return
  1231  	}
  1232  	var h *Hostobj
  1233  
  1234  	for i := 0; i < len(hostobj); i++ {
  1235  		h = &hostobj[i]
  1236  		f, err := bio.Open(h.file)
  1237  		if err != nil {
  1238  			Exitf("cannot reopen %s: %v", h.pn, err)
  1239  		}
  1240  		f.MustSeek(h.off, 0)
  1241  		if h.ld == nil {
  1242  			Errorf("%s: unrecognized object file format", h.pn)
  1243  			continue
  1244  		}
  1245  		h.ld(ctxt, f, h.pkg, h.length, h.pn)
  1246  		if *flagCaptureHostObjs != "" {
  1247  			captureHostObj(h)
  1248  		}
  1249  		f.Close()
  1250  	}
  1251  }
  1252  
  1253  func hostlinksetup(ctxt *Link) {
  1254  	if ctxt.LinkMode != LinkExternal {
  1255  		return
  1256  	}
  1257  
  1258  	
  1259  	
  1260  	
  1261  	debug_s = *FlagS
  1262  	*FlagS = false
  1263  
  1264  	
  1265  	if *flagTmpdir == "" {
  1266  		dir, err := os.MkdirTemp("", "go-link-")
  1267  		if err != nil {
  1268  			log.Fatal(err)
  1269  		}
  1270  		*flagTmpdir = dir
  1271  		ownTmpDir = true
  1272  		AtExit(func() {
  1273  			os.RemoveAll(*flagTmpdir)
  1274  		})
  1275  	}
  1276  
  1277  	
  1278  	if err := ctxt.Out.Close(); err != nil {
  1279  		Exitf("error closing output file")
  1280  	}
  1281  	mayberemoveoutfile()
  1282  
  1283  	p := filepath.Join(*flagTmpdir, "go.o")
  1284  	if err := ctxt.Out.Open(p); err != nil {
  1285  		Exitf("cannot create %s: %v", p, err)
  1286  	}
  1287  }
  1288  
  1289  
  1290  
  1291  
  1292  
  1293  
  1294  
  1295  
  1296  func cleanTimeStamps(files []string) {
  1297  	epocht := time.Unix(0, 0)
  1298  	for _, f := range files {
  1299  		if err := os.Chtimes(f, epocht, epocht); err != nil {
  1300  			Exitf("cannot chtimes %s: %v", f, err)
  1301  		}
  1302  	}
  1303  }
  1304  
  1305  
  1306  
  1307  func (ctxt *Link) hostobjCopy() (paths []string) {
  1308  	var wg sync.WaitGroup
  1309  	sema := make(chan struct{}, runtime.NumCPU()) 
  1310  	for i, h := range hostobj {
  1311  		h := h
  1312  		dst := filepath.Join(*flagTmpdir, fmt.Sprintf("%06d.o", i))
  1313  		paths = append(paths, dst)
  1314  		if ctxt.Debugvlog != 0 {
  1315  			ctxt.Logf("host obj copy: %s from pkg %s -> %s\n", h.pn, h.pkg, dst)
  1316  		}
  1317  
  1318  		wg.Add(1)
  1319  		go func() {
  1320  			sema <- struct{}{}
  1321  			defer func() {
  1322  				<-sema
  1323  				wg.Done()
  1324  			}()
  1325  			f, err := os.Open(h.file)
  1326  			if err != nil {
  1327  				Exitf("cannot reopen %s: %v", h.pn, err)
  1328  			}
  1329  			defer f.Close()
  1330  			if _, err := f.Seek(h.off, 0); err != nil {
  1331  				Exitf("cannot seek %s: %v", h.pn, err)
  1332  			}
  1333  
  1334  			w, err := os.Create(dst)
  1335  			if err != nil {
  1336  				Exitf("cannot create %s: %v", dst, err)
  1337  			}
  1338  			if _, err := io.CopyN(w, f, h.length); err != nil {
  1339  				Exitf("cannot write %s: %v", dst, err)
  1340  			}
  1341  			if err := w.Close(); err != nil {
  1342  				Exitf("cannot close %s: %v", dst, err)
  1343  			}
  1344  		}()
  1345  	}
  1346  	wg.Wait()
  1347  	return paths
  1348  }
  1349  
  1350  
  1351  
  1352  
  1353  
  1354  func writeGDBLinkerScript() string {
  1355  	name := "fix_debug_gdb_scripts.ld"
  1356  	path := filepath.Join(*flagTmpdir, name)
  1357  	src := `SECTIONS
  1358  {
  1359    .debug_gdb_scripts BLOCK(__section_alignment__) (NOLOAD) :
  1360    {
  1361      *(.debug_gdb_scripts)
  1362    }
  1363  }
  1364  INSERT AFTER .debug_types;
  1365  `
  1366  	err := os.WriteFile(path, []byte(src), 0666)
  1367  	if err != nil {
  1368  		Errorf("WriteFile %s failed: %v", name, err)
  1369  	}
  1370  	return path
  1371  }
  1372  
  1373  type machoUpdateFunc func(ctxt *Link, exef *os.File, exem *macho.File, outexe string) error
  1374  
  1375  
  1376  func (ctxt *Link) archive() {
  1377  	if ctxt.BuildMode != BuildModeCArchive {
  1378  		return
  1379  	}
  1380  
  1381  	exitIfErrors()
  1382  
  1383  	if *flagExtar == "" {
  1384  		const printProgName = "--print-prog-name=ar"
  1385  		cc := ctxt.extld()
  1386  		*flagExtar = "ar"
  1387  		if linkerFlagSupported(ctxt.Arch, cc[0], "", printProgName) {
  1388  			*flagExtar = ctxt.findExtLinkTool("ar")
  1389  		}
  1390  	}
  1391  
  1392  	mayberemoveoutfile()
  1393  
  1394  	
  1395  	
  1396  	if err := ctxt.Out.Close(); err != nil {
  1397  		Exitf("error closing %v", *flagOutfile)
  1398  	}
  1399  
  1400  	argv := []string{*flagExtar, "-q", "-c", "-s"}
  1401  	if ctxt.HeadType == objabi.Haix {
  1402  		argv = append(argv, "-X64")
  1403  	}
  1404  	godotopath := filepath.Join(*flagTmpdir, "go.o")
  1405  	cleanTimeStamps([]string{godotopath})
  1406  	hostObjCopyPaths := ctxt.hostobjCopy()
  1407  	cleanTimeStamps(hostObjCopyPaths)
  1408  
  1409  	argv = append(argv, *flagOutfile)
  1410  	argv = append(argv, godotopath)
  1411  	argv = append(argv, hostObjCopyPaths...)
  1412  
  1413  	if ctxt.Debugvlog != 0 {
  1414  		ctxt.Logf("archive: %s\n", strings.Join(argv, " "))
  1415  	}
  1416  
  1417  	
  1418  	
  1419  	
  1420  	
  1421  	
  1422  	if syscallExecSupported && !ownTmpDir {
  1423  		runAtExitFuncs()
  1424  		ctxt.execArchive(argv)
  1425  		panic("should not get here")
  1426  	}
  1427  
  1428  	
  1429  	if out, err := exec.Command(argv[0], argv[1:]...).CombinedOutput(); err != nil {
  1430  		Exitf("running %s failed: %v\n%s", argv[0], err, out)
  1431  	}
  1432  }
  1433  
  1434  func (ctxt *Link) hostlink() {
  1435  	if ctxt.LinkMode != LinkExternal || nerrors > 0 {
  1436  		return
  1437  	}
  1438  	if ctxt.BuildMode == BuildModeCArchive {
  1439  		return
  1440  	}
  1441  
  1442  	var argv []string
  1443  	argv = append(argv, ctxt.extld()...)
  1444  	argv = append(argv, hostlinkArchArgs(ctxt.Arch)...)
  1445  
  1446  	if *FlagS || debug_s {
  1447  		if ctxt.HeadType == objabi.Hdarwin {
  1448  			
  1449  			
  1450  			
  1451  		} else {
  1452  			argv = append(argv, "-s")
  1453  		}
  1454  	} else if *FlagW {
  1455  		if !ctxt.IsAIX() && !ctxt.IsSolaris() { 
  1456  			argv = append(argv, "-Wl,-S") 
  1457  		}
  1458  	}
  1459  
  1460  	
  1461  	
  1462  	combineDwarf := ctxt.IsDarwin() && !*FlagW && machoPlatform == PLATFORM_MACOS
  1463  
  1464  	var isMSVC bool 
  1465  	wlPrefix := "-Wl,--"
  1466  
  1467  	switch ctxt.HeadType {
  1468  	case objabi.Hdarwin:
  1469  		if combineDwarf {
  1470  			
  1471  			
  1472  			argv = append(argv, "-Wl,-headerpad,1144")
  1473  		}
  1474  		if ctxt.DynlinkingGo() && buildcfg.GOOS != "ios" {
  1475  			
  1476  			
  1477  			
  1478  			
  1479  			
  1480  			argv = append(argv, "-Wl,-flat_namespace", "-Wl,-bind_at_load")
  1481  		}
  1482  		if !combineDwarf {
  1483  			argv = append(argv, "-Wl,-S") 
  1484  			if debug_s {
  1485  				
  1486  				
  1487  				
  1488  				argv = append(argv, "-Wl,-x")
  1489  			}
  1490  		}
  1491  		if *flagHostBuildid == "none" {
  1492  			argv = append(argv, "-Wl,-no_uuid")
  1493  		}
  1494  	case objabi.Hopenbsd:
  1495  		argv = append(argv, "-pthread")
  1496  		if ctxt.BuildMode != BuildModePIE {
  1497  			argv = append(argv, "-Wl,-nopie")
  1498  		}
  1499  		if linkerFlagSupported(ctxt.Arch, argv[0], "", "-Wl,-z,nobtcfi") {
  1500  			
  1501  			
  1502  			argv = append(argv, "-Wl,-z,nobtcfi")
  1503  		}
  1504  		if ctxt.Arch.InFamily(sys.ARM64) {
  1505  			
  1506  			
  1507  			
  1508  			argv = append(argv, "-Wl,--no-execute-only")
  1509  		}
  1510  	case objabi.Hwindows:
  1511  		isMSVC = ctxt.isMSVC()
  1512  		if isMSVC {
  1513  			
  1514  			
  1515  			
  1516  			
  1517  			wlPrefix = "-Wl,-"
  1518  		}
  1519  
  1520  		if windowsgui {
  1521  			argv = append(argv, "-mwindows")
  1522  		} else {
  1523  			argv = append(argv, "-mconsole")
  1524  		}
  1525  		
  1526  		
  1527  
  1528  		argv = append(argv, wlPrefix+"tsaware")
  1529  
  1530  		
  1531  		argv = append(argv, wlPrefix+"nxcompat")
  1532  
  1533  		if !isMSVC {
  1534  			argv = append(argv, fmt.Sprintf("-Wl,--major-os-version=%d", PeMinimumTargetMajorVersion))
  1535  			argv = append(argv, fmt.Sprintf("-Wl,--minor-os-version=%d", PeMinimumTargetMinorVersion))
  1536  			argv = append(argv, fmt.Sprintf("-Wl,--major-subsystem-version=%d", PeMinimumTargetMajorVersion))
  1537  			argv = append(argv, fmt.Sprintf("-Wl,--minor-subsystem-version=%d", PeMinimumTargetMinorVersion))
  1538  		}
  1539  	case objabi.Haix:
  1540  		argv = append(argv, "-pthread")
  1541  		
  1542  		
  1543  		argv = append(argv, "-Wl,-bnoobjreorder")
  1544  		
  1545  		
  1546  		argv = append(argv, "-mcmodel=large")
  1547  		argv = append(argv, "-Wl,-bbigtoc")
  1548  	}
  1549  
  1550  	
  1551  	
  1552  	
  1553  	if ctxt.IsPPC64() && ctxt.IsElf() && buildcfg.GOPPC64 >= 10 {
  1554  		if !linkerFlagSupported(ctxt.Arch, argv[0], "", "-mcpu=power10") {
  1555  			Exitf("The external toolchain does not support -mcpu=power10. " +
  1556  				" This is required to externally link GOPPC64 >= power10")
  1557  		}
  1558  	}
  1559  
  1560  	
  1561  	addASLRargs := func(argv []string, val bool) []string {
  1562  		
  1563  		
  1564  		
  1565  		
  1566  		
  1567  		
  1568  		
  1569  		
  1570  		
  1571  		
  1572  		
  1573  		
  1574  		
  1575  		
  1576  		
  1577  		var dbopt string
  1578  		var heopt string
  1579  		dbon := wlPrefix + "dynamicbase"
  1580  		heon := wlPrefix + "high-entropy-va"
  1581  		dboff := wlPrefix + "disable-dynamicbase"
  1582  		heoff := wlPrefix + "disable-high-entropy-va"
  1583  		if isMSVC {
  1584  			heon = wlPrefix + "highentropyva"
  1585  			heoff = wlPrefix + "highentropyva:no"
  1586  			dboff = wlPrefix + "dynamicbase:no"
  1587  		}
  1588  		if val {
  1589  			dbopt = dbon
  1590  			heopt = heon
  1591  		} else {
  1592  			
  1593  			newer := linkerFlagSupported(ctxt.Arch, argv[0], "", dboff)
  1594  			if newer {
  1595  				
  1596  				dbopt = dboff
  1597  				heopt = heoff
  1598  			} else {
  1599  				
  1600  				
  1601  				dbopt = ""
  1602  				heopt = ""
  1603  			}
  1604  		}
  1605  		if dbopt != "" {
  1606  			argv = append(argv, dbopt)
  1607  		}
  1608  		
  1609  		if ctxt.Arch.PtrSize >= 8 && heopt != "" {
  1610  			argv = append(argv, heopt)
  1611  		}
  1612  		return argv
  1613  	}
  1614  
  1615  	switch ctxt.BuildMode {
  1616  	case BuildModeExe:
  1617  		if ctxt.HeadType == objabi.Hdarwin {
  1618  			if machoPlatform == PLATFORM_MACOS && ctxt.IsAMD64() {
  1619  				argv = append(argv, "-Wl,-no_pie")
  1620  			}
  1621  		}
  1622  		if *flagRace && ctxt.HeadType == objabi.Hwindows {
  1623  			
  1624  			
  1625  			
  1626  			
  1627  			argv = addASLRargs(argv, false)
  1628  		}
  1629  	case BuildModePIE:
  1630  		switch ctxt.HeadType {
  1631  		case objabi.Hdarwin, objabi.Haix:
  1632  		case objabi.Hwindows:
  1633  			if *flagAslr && *flagRace {
  1634  				
  1635  				
  1636  				
  1637  				*flagAslr = false
  1638  			}
  1639  			argv = addASLRargs(argv, *flagAslr)
  1640  		default:
  1641  			
  1642  			if ctxt.UseRelro() {
  1643  				argv = append(argv, "-Wl,-z,relro")
  1644  			}
  1645  			argv = append(argv, "-pie")
  1646  		}
  1647  	case BuildModeCShared:
  1648  		if ctxt.HeadType == objabi.Hdarwin {
  1649  			argv = append(argv, "-dynamiclib")
  1650  		} else {
  1651  			if ctxt.UseRelro() {
  1652  				argv = append(argv, "-Wl,-z,relro")
  1653  			}
  1654  			argv = append(argv, "-shared")
  1655  			if ctxt.HeadType == objabi.Hwindows {
  1656  				argv = addASLRargs(argv, *flagAslr)
  1657  			} else {
  1658  				
  1659  				
  1660  				argv = append(argv, "-Wl,-z,nodelete")
  1661  				
  1662  				argv = append(argv, "-Wl,-Bsymbolic")
  1663  			}
  1664  		}
  1665  	case BuildModeShared:
  1666  		if ctxt.UseRelro() {
  1667  			argv = append(argv, "-Wl,-z,relro")
  1668  		}
  1669  		argv = append(argv, "-shared")
  1670  	case BuildModePlugin:
  1671  		if ctxt.HeadType == objabi.Hdarwin {
  1672  			argv = append(argv, "-dynamiclib")
  1673  		} else {
  1674  			if ctxt.UseRelro() {
  1675  				argv = append(argv, "-Wl,-z,relro")
  1676  			}
  1677  			argv = append(argv, "-shared")
  1678  		}
  1679  	}
  1680  
  1681  	var altLinker string
  1682  	if ctxt.IsELF && (ctxt.DynlinkingGo() || *flagBindNow) {
  1683  		
  1684  		
  1685  		
  1686  		
  1687  		
  1688  		argv = append(argv, "-Wl,-z,now")
  1689  	}
  1690  
  1691  	if ctxt.IsELF && ctxt.DynlinkingGo() {
  1692  		
  1693  		
  1694  		
  1695  		argv = append(argv, "-Wl,-z,nocopyreloc")
  1696  
  1697  		if buildcfg.GOOS == "android" {
  1698  			
  1699  			altLinker = "lld"
  1700  		}
  1701  
  1702  		if ctxt.Arch.InFamily(sys.ARM64) && buildcfg.GOOS == "linux" {
  1703  			
  1704  			
  1705  			
  1706  			
  1707  			
  1708  			altLinker = "gold"
  1709  
  1710  			
  1711  			
  1712  			
  1713  			name, args := flagExtld[0], flagExtld[1:]
  1714  			args = append(args, "-fuse-ld=gold", "-Wl,--version")
  1715  			cmd := exec.Command(name, args...)
  1716  			if out, err := cmd.CombinedOutput(); err == nil {
  1717  				if !bytes.Contains(out, []byte("GNU gold")) {
  1718  					log.Fatalf("ARM64 external linker must be gold (issue #15696, 22040), but is not: %s", out)
  1719  				}
  1720  			}
  1721  		}
  1722  	}
  1723  	if ctxt.Arch.Family == sys.ARM64 && buildcfg.GOOS == "freebsd" {
  1724  		
  1725  		altLinker = "bfd"
  1726  
  1727  		
  1728  		name, args := flagExtld[0], flagExtld[1:]
  1729  		args = append(args, "-fuse-ld=bfd", "-Wl,--version")
  1730  		cmd := exec.Command(name, args...)
  1731  		if out, err := cmd.CombinedOutput(); err == nil {
  1732  			if !bytes.Contains(out, []byte("GNU ld")) {
  1733  				log.Fatalf("ARM64 external linker must be ld.bfd (issue #35197), please install devel/binutils")
  1734  			}
  1735  		}
  1736  	}
  1737  	if altLinker != "" {
  1738  		argv = append(argv, "-fuse-ld="+altLinker)
  1739  	}
  1740  
  1741  	if ctxt.IsELF && linkerFlagSupported(ctxt.Arch, argv[0], "", "-Wl,--build-id=0x1234567890abcdef") { 
  1742  		if len(buildinfo) > 0 {
  1743  			argv = append(argv, fmt.Sprintf("-Wl,--build-id=0x%x", buildinfo))
  1744  		} else if *flagHostBuildid == "none" {
  1745  			argv = append(argv, "-Wl,--build-id=none")
  1746  		}
  1747  	}
  1748  
  1749  	
  1750  	
  1751  	
  1752  	
  1753  	
  1754  	
  1755  	outopt := *flagOutfile
  1756  	if buildcfg.GOOS == "windows" && runtime.GOOS == "windows" && filepath.Ext(outopt) == "" {
  1757  		outopt += "."
  1758  	}
  1759  	argv = append(argv, "-o")
  1760  	argv = append(argv, outopt)
  1761  
  1762  	if rpath.val != "" {
  1763  		argv = append(argv, fmt.Sprintf("-Wl,-rpath,%s", rpath.val))
  1764  	}
  1765  
  1766  	if *flagInterpreter != "" {
  1767  		
  1768  		
  1769  		
  1770  		
  1771  		argv = append(argv, fmt.Sprintf("-Wl,--dynamic-linker,%s", *flagInterpreter))
  1772  	}
  1773  
  1774  	
  1775  	switch {
  1776  	case ctxt.IsELF:
  1777  		if ctxt.DynlinkingGo() || ctxt.BuildMode == BuildModeCShared || !linkerFlagSupported(ctxt.Arch, argv[0], altLinker, "-Wl,--export-dynamic-symbol=main") {
  1778  			argv = append(argv, "-rdynamic")
  1779  		} else {
  1780  			var exports []string
  1781  			ctxt.loader.ForAllCgoExportDynamic(func(s loader.Sym) {
  1782  				exports = append(exports, "-Wl,--export-dynamic-symbol="+ctxt.loader.SymExtname(s))
  1783  			})
  1784  			sort.Strings(exports)
  1785  			argv = append(argv, exports...)
  1786  		}
  1787  	case ctxt.IsAIX():
  1788  		fileName := xcoffCreateExportFile(ctxt)
  1789  		argv = append(argv, "-Wl,-bE:"+fileName)
  1790  	case ctxt.IsWindows() && !slices.Contains(flagExtldflags, wlPrefix+"export-all-symbols"):
  1791  		fileName := peCreateExportFile(ctxt, filepath.Base(outopt))
  1792  		prefix := ""
  1793  		if isMSVC {
  1794  			prefix = "-Wl,-def:"
  1795  		}
  1796  		argv = append(argv, prefix+fileName)
  1797  	}
  1798  
  1799  	const unusedArguments = "-Qunused-arguments"
  1800  	if linkerFlagSupported(ctxt.Arch, argv[0], altLinker, unusedArguments) {
  1801  		argv = append(argv, unusedArguments)
  1802  	}
  1803  
  1804  	if ctxt.IsWindows() {
  1805  		
  1806  		
  1807  		
  1808  		
  1809  		const noTimeStamp = "-Wl,--no-insert-timestamp"
  1810  		if linkerFlagSupported(ctxt.Arch, argv[0], altLinker, noTimeStamp) {
  1811  			argv = append(argv, noTimeStamp)
  1812  		}
  1813  	}
  1814  
  1815  	const compressDWARF = "-Wl,--compress-debug-sections=zlib"
  1816  	if ctxt.compressDWARF && linkerFlagSupported(ctxt.Arch, argv[0], altLinker, compressDWARF) {
  1817  		argv = append(argv, compressDWARF)
  1818  	}
  1819  
  1820  	hostObjCopyPaths := ctxt.hostobjCopy()
  1821  	cleanTimeStamps(hostObjCopyPaths)
  1822  	godotopath := filepath.Join(*flagTmpdir, "go.o")
  1823  	cleanTimeStamps([]string{godotopath})
  1824  
  1825  	argv = append(argv, godotopath)
  1826  	argv = append(argv, hostObjCopyPaths...)
  1827  	if ctxt.HeadType == objabi.Haix {
  1828  		
  1829  		
  1830  		argv = append(argv, "-nostartfiles")
  1831  		argv = append(argv, "/lib/crt0_64.o")
  1832  
  1833  		extld := ctxt.extld()
  1834  		name, args := extld[0], extld[1:]
  1835  		
  1836  		getPathFile := func(file string) string {
  1837  			args := append(args, "-maix64", "--print-file-name="+file)
  1838  			out, err := exec.Command(name, args...).CombinedOutput()
  1839  			if err != nil {
  1840  				log.Fatalf("running %s failed: %v\n%s", extld, err, out)
  1841  			}
  1842  			return strings.Trim(string(out), "\n")
  1843  		}
  1844  		
  1845  		
  1846  		
  1847  		crtcxa := getPathFile("crtcxa_64.o")
  1848  		if !filepath.IsAbs(crtcxa) {
  1849  			crtcxa = getPathFile("crtcxa.o")
  1850  		}
  1851  		crtdbase := getPathFile("crtdbase_64.o")
  1852  		if !filepath.IsAbs(crtdbase) {
  1853  			crtdbase = getPathFile("crtdbase.o")
  1854  		}
  1855  		argv = append(argv, crtcxa)
  1856  		argv = append(argv, crtdbase)
  1857  	}
  1858  
  1859  	if ctxt.linkShared {
  1860  		seenDirs := make(map[string]bool)
  1861  		seenLibs := make(map[string]bool)
  1862  		addshlib := func(path string) {
  1863  			dir, base := filepath.Split(path)
  1864  			if !seenDirs[dir] {
  1865  				argv = append(argv, "-L"+dir)
  1866  				if !rpath.set {
  1867  					argv = append(argv, "-Wl,-rpath="+dir)
  1868  				}
  1869  				seenDirs[dir] = true
  1870  			}
  1871  			base = strings.TrimSuffix(base, ".so")
  1872  			base = strings.TrimPrefix(base, "lib")
  1873  			if !seenLibs[base] {
  1874  				argv = append(argv, "-l"+base)
  1875  				seenLibs[base] = true
  1876  			}
  1877  		}
  1878  		for _, shlib := range ctxt.Shlibs {
  1879  			addshlib(shlib.Path)
  1880  			for _, dep := range shlib.Deps {
  1881  				if dep == "" {
  1882  					continue
  1883  				}
  1884  				libpath := findshlib(ctxt, dep)
  1885  				if libpath != "" {
  1886  					addshlib(libpath)
  1887  				}
  1888  			}
  1889  		}
  1890  	}
  1891  
  1892  	
  1893  	
  1894  	
  1895  	
  1896  	
  1897  	
  1898  	
  1899  	checkStatic := func(arg string) {
  1900  		if ctxt.IsELF && arg == "-static" {
  1901  			for i := range argv {
  1902  				if argv[i] == "-rdynamic" || strings.HasPrefix(argv[i], "-Wl,--dynamic-linker,") {
  1903  					argv[i] = "-static"
  1904  				}
  1905  			}
  1906  		}
  1907  	}
  1908  
  1909  	for _, p := range ldflag {
  1910  		argv = append(argv, p)
  1911  		checkStatic(p)
  1912  	}
  1913  
  1914  	
  1915  	
  1916  	
  1917  	
  1918  	
  1919  	
  1920  	
  1921  	if ctxt.BuildMode == BuildModeExe && !ctxt.linkShared && !(ctxt.IsDarwin() && ctxt.IsARM64()) {
  1922  		
  1923  		for _, nopie := range []string{"-no-pie", "-nopie"} {
  1924  			if linkerFlagSupported(ctxt.Arch, argv[0], altLinker, nopie) {
  1925  				argv = append(argv, nopie)
  1926  				break
  1927  			}
  1928  		}
  1929  	}
  1930  
  1931  	for _, p := range flagExtldflags {
  1932  		argv = append(argv, p)
  1933  		checkStatic(p)
  1934  	}
  1935  	if ctxt.HeadType == objabi.Hwindows {
  1936  		
  1937  		
  1938  		extld := ctxt.extld()
  1939  		name, args := extld[0], extld[1:]
  1940  		args = append(args, trimLinkerArgv(flagExtldflags)...)
  1941  		args = append(args, "-Wl,--version")
  1942  		cmd := exec.Command(name, args...)
  1943  		usingLLD := false
  1944  		if out, err := cmd.CombinedOutput(); err == nil {
  1945  			if bytes.Contains(out, []byte("LLD ")) {
  1946  				usingLLD = true
  1947  			}
  1948  		}
  1949  
  1950  		
  1951  		
  1952  		if !usingLLD {
  1953  			p := writeGDBLinkerScript()
  1954  			argv = append(argv, "-Wl,-T,"+p)
  1955  		}
  1956  		if *flagRace {
  1957  			
  1958  			
  1959  			
  1960  			
  1961  			if isMSVC || ctxt.findLibPath("libsynchronization.a") != "libsynchronization.a" {
  1962  				argv = append(argv, "-lsynchronization")
  1963  			}
  1964  		}
  1965  		if !isMSVC {
  1966  			
  1967  			
  1968  			argv = append(argv, "-Wl,--start-group", "-lmingwex", "-lmingw32", "-Wl,--end-group")
  1969  		}
  1970  		argv = append(argv, peimporteddlls()...)
  1971  	}
  1972  
  1973  	argv = ctxt.passLongArgsInResponseFile(argv, altLinker)
  1974  
  1975  	if ctxt.Debugvlog != 0 {
  1976  		ctxt.Logf("host link:")
  1977  		for _, v := range argv {
  1978  			ctxt.Logf(" %q", v)
  1979  		}
  1980  		ctxt.Logf("\n")
  1981  	}
  1982  
  1983  	cmd := exec.Command(argv[0], argv[1:]...)
  1984  	out, err := cmd.CombinedOutput()
  1985  	if err != nil {
  1986  		Exitf("running %s failed: %v\n%s\n%s", argv[0], err, cmd, out)
  1987  	}
  1988  
  1989  	
  1990  	
  1991  	var save [][]byte
  1992  	var skipLines int
  1993  	for _, line := range bytes.SplitAfter(out, []byte("\n")) {
  1994  		
  1995  		if bytes.Contains(line, []byte("ld: warning: text-based stub file")) {
  1996  			continue
  1997  		}
  1998  
  1999  		if skipLines > 0 {
  2000  			skipLines--
  2001  			continue
  2002  		}
  2003  
  2004  		
  2005  		if bytes.Contains(line, []byte("ld: 0711-783")) {
  2006  			skipLines = 2
  2007  			continue
  2008  		}
  2009  
  2010  		save = append(save, line)
  2011  	}
  2012  	out = bytes.Join(save, nil)
  2013  
  2014  	if len(out) > 0 {
  2015  		
  2016  		
  2017  		if ctxt.IsDarwin() && ctxt.IsAMD64() {
  2018  			const noPieWarning = "ld: warning: -no_pie is deprecated when targeting new OS versions\n"
  2019  			if i := bytes.Index(out, []byte(noPieWarning)); i >= 0 {
  2020  				
  2021  				out = append(out[:i], out[i+len(noPieWarning):]...)
  2022  			}
  2023  		}
  2024  		if ctxt.IsDarwin() {
  2025  			const bindAtLoadWarning = "ld: warning: -bind_at_load is deprecated on macOS\n"
  2026  			if i := bytes.Index(out, []byte(bindAtLoadWarning)); i >= 0 {
  2027  				
  2028  				
  2029  				
  2030  				
  2031  				out = append(out[:i], out[i+len(bindAtLoadWarning):]...)
  2032  			}
  2033  		}
  2034  		ctxt.Logf("%s", out)
  2035  	}
  2036  
  2037  	
  2038  	
  2039  	updateMachoOutFile := func(op string, updateFunc machoUpdateFunc) {
  2040  		
  2041  		rewrittenOutput := *flagOutfile + "~"
  2042  		exef, err := os.Open(*flagOutfile)
  2043  		if err != nil {
  2044  			Exitf("%s: %s failed: %v", os.Args[0], op, err)
  2045  		}
  2046  		defer exef.Close()
  2047  		exem, err := macho.NewFile(exef)
  2048  		if err != nil {
  2049  			Exitf("%s: parsing Mach-O header failed: %v", os.Args[0], err)
  2050  		}
  2051  		if err := updateFunc(ctxt, exef, exem, rewrittenOutput); err != nil {
  2052  			Exitf("%s: %s failed: %v", os.Args[0], op, err)
  2053  		}
  2054  		os.Remove(*flagOutfile)
  2055  		if err := os.Rename(rewrittenOutput, *flagOutfile); err != nil {
  2056  			Exitf("%s: %v", os.Args[0], err)
  2057  		}
  2058  	}
  2059  
  2060  	uuidUpdated := false
  2061  	if combineDwarf {
  2062  		
  2063  		dsymutilCmd := ctxt.findExtLinkTool("dsymutil")
  2064  		stripCmd := ctxt.findExtLinkTool("strip")
  2065  
  2066  		dsym := filepath.Join(*flagTmpdir, "go.dwarf")
  2067  		cmd := exec.Command(dsymutilCmd, "-f", *flagOutfile, "-o", dsym)
  2068  		
  2069  		
  2070  		
  2071  		
  2072  		
  2073  		dsymDir := filepath.Join(*flagTmpdir, "dsymutil")
  2074  		err := os.MkdirAll(dsymDir, 0777)
  2075  		if err != nil {
  2076  			Exitf("fail to create temp dir: %v", err)
  2077  		}
  2078  		cmd.Env = append(os.Environ(), "DSYMUTIL_REPRODUCER_PATH="+dsymDir)
  2079  		if ctxt.Debugvlog != 0 {
  2080  			ctxt.Logf("host link dsymutil:")
  2081  			for _, v := range cmd.Args {
  2082  				ctxt.Logf(" %q", v)
  2083  			}
  2084  			ctxt.Logf("\n")
  2085  		}
  2086  		if out, err := cmd.CombinedOutput(); err != nil {
  2087  			Exitf("%s: running dsymutil failed: %v\n%s\n%s", os.Args[0], err, cmd, out)
  2088  		}
  2089  		
  2090  		
  2091  		var stripArgs = []string{"-S"}
  2092  		if debug_s {
  2093  			
  2094  			
  2095  			
  2096  			stripArgs = append(stripArgs, "-x")
  2097  		}
  2098  		stripArgs = append(stripArgs, *flagOutfile)
  2099  		if ctxt.Debugvlog != 0 {
  2100  			ctxt.Logf("host link strip: %q", stripCmd)
  2101  			for _, v := range stripArgs {
  2102  				ctxt.Logf(" %q", v)
  2103  			}
  2104  			ctxt.Logf("\n")
  2105  		}
  2106  		cmd = exec.Command(stripCmd, stripArgs...)
  2107  		if out, err := cmd.CombinedOutput(); err != nil {
  2108  			Exitf("%s: running strip failed: %v\n%s\n%s", os.Args[0], err, cmd, out)
  2109  		}
  2110  		
  2111  		if _, err := os.Stat(dsym); err == nil {
  2112  			updateMachoOutFile("combining dwarf",
  2113  				func(ctxt *Link, exef *os.File, exem *macho.File, outexe string) error {
  2114  					return machoCombineDwarf(ctxt, exef, exem, dsym, outexe)
  2115  				})
  2116  			uuidUpdated = true
  2117  		}
  2118  	}
  2119  	if ctxt.IsDarwin() && !uuidUpdated && len(buildinfo) > 0 {
  2120  		updateMachoOutFile("rewriting uuid",
  2121  			func(ctxt *Link, exef *os.File, exem *macho.File, outexe string) error {
  2122  				return machoRewriteUuid(ctxt, exef, exem, outexe)
  2123  			})
  2124  	}
  2125  	hostlinkfips(ctxt, *flagOutfile, *flagFipso)
  2126  	if ctxt.NeedCodeSign() {
  2127  		err := machoCodeSign(ctxt, *flagOutfile)
  2128  		if err != nil {
  2129  			Exitf("%s: code signing failed: %v", os.Args[0], err)
  2130  		}
  2131  	}
  2132  }
  2133  
  2134  
  2135  
  2136  func (ctxt *Link) passLongArgsInResponseFile(argv []string, altLinker string) []string {
  2137  	c := 0
  2138  	for _, arg := range argv {
  2139  		c += len(arg)
  2140  	}
  2141  
  2142  	if c < sys.ExecArgLengthLimit {
  2143  		return argv
  2144  	}
  2145  
  2146  	
  2147  	response := filepath.Join(*flagTmpdir, "response")
  2148  	if err := os.WriteFile(response, nil, 0644); err != nil {
  2149  		log.Fatalf("failed while testing response file: %v", err)
  2150  	}
  2151  	if !linkerFlagSupported(ctxt.Arch, argv[0], altLinker, "@"+response) {
  2152  		if ctxt.Debugvlog != 0 {
  2153  			ctxt.Logf("not using response file because linker does not support one")
  2154  		}
  2155  		return argv
  2156  	}
  2157  
  2158  	var buf bytes.Buffer
  2159  	for _, arg := range argv[1:] {
  2160  		
  2161  		fmt.Fprintf(&buf, "%q\n", arg)
  2162  	}
  2163  	if err := os.WriteFile(response, buf.Bytes(), 0644); err != nil {
  2164  		log.Fatalf("failed while writing response file: %v", err)
  2165  	}
  2166  	if ctxt.Debugvlog != 0 {
  2167  		ctxt.Logf("response file %s contents:\n%s", response, buf.Bytes())
  2168  	}
  2169  	return []string{
  2170  		argv[0],
  2171  		"@" + response,
  2172  	}
  2173  }
  2174  
  2175  var createTrivialCOnce sync.Once
  2176  
  2177  func linkerFlagSupported(arch *sys.Arch, linker, altLinker, flag string) bool {
  2178  	createTrivialCOnce.Do(func() {
  2179  		src := filepath.Join(*flagTmpdir, "trivial.c")
  2180  		if err := os.WriteFile(src, []byte("int main() { return 0; }"), 0666); err != nil {
  2181  			Errorf("WriteFile trivial.c failed: %v", err)
  2182  		}
  2183  	})
  2184  
  2185  	flags := hostlinkArchArgs(arch)
  2186  
  2187  	moreFlags := trimLinkerArgv(append(ldflag, flagExtldflags...))
  2188  	flags = append(flags, moreFlags...)
  2189  
  2190  	if altLinker != "" {
  2191  		flags = append(flags, "-fuse-ld="+altLinker)
  2192  	}
  2193  	trivialPath := filepath.Join(*flagTmpdir, "trivial.c")
  2194  	outPath := filepath.Join(*flagTmpdir, "a.out")
  2195  	flags = append(flags, "-o", outPath, flag, trivialPath)
  2196  
  2197  	cmd := exec.Command(linker, flags...)
  2198  	cmd.Env = append([]string{"LC_ALL=C"}, os.Environ()...)
  2199  	out, err := cmd.CombinedOutput()
  2200  	
  2201  	
  2202  	return err == nil && !bytes.Contains(out, []byte("unrecognized")) && !bytes.Contains(out, []byte("unknown"))
  2203  }
  2204  
  2205  
  2206  
  2207  func trimLinkerArgv(argv []string) []string {
  2208  	flagsWithNextArgSkip := []string{
  2209  		"-F",
  2210  		"-l",
  2211  		"-L",
  2212  		"-framework",
  2213  		"-Wl,-framework",
  2214  		"-Wl,-rpath",
  2215  		"-Wl,-undefined",
  2216  	}
  2217  	flagsWithNextArgKeep := []string{
  2218  		"-arch",
  2219  		"-isysroot",
  2220  		"--sysroot",
  2221  		"-target",
  2222  		"--target",
  2223  	}
  2224  	prefixesToKeep := []string{
  2225  		"-f",
  2226  		"-m",
  2227  		"-p",
  2228  		"-Wl,",
  2229  		"-arch",
  2230  		"-isysroot",
  2231  		"--sysroot",
  2232  		"-target",
  2233  		"--target",
  2234  	}
  2235  
  2236  	var flags []string
  2237  	keep := false
  2238  	skip := false
  2239  	for _, f := range argv {
  2240  		if keep {
  2241  			flags = append(flags, f)
  2242  			keep = false
  2243  		} else if skip {
  2244  			skip = false
  2245  		} else if f == "" || f[0] != '-' {
  2246  		} else if slices.Contains(flagsWithNextArgSkip, f) {
  2247  			skip = true
  2248  		} else if slices.Contains(flagsWithNextArgKeep, f) {
  2249  			flags = append(flags, f)
  2250  			keep = true
  2251  		} else {
  2252  			for _, p := range prefixesToKeep {
  2253  				if strings.HasPrefix(f, p) {
  2254  					flags = append(flags, f)
  2255  					break
  2256  				}
  2257  			}
  2258  		}
  2259  	}
  2260  	return flags
  2261  }
  2262  
  2263  
  2264  
  2265  func hostlinkArchArgs(arch *sys.Arch) []string {
  2266  	switch arch.Family {
  2267  	case sys.I386:
  2268  		return []string{"-m32"}
  2269  	case sys.AMD64:
  2270  		if buildcfg.GOOS == "darwin" {
  2271  			return []string{"-arch", "x86_64", "-m64"}
  2272  		}
  2273  		return []string{"-m64"}
  2274  	case sys.S390X:
  2275  		return []string{"-m64"}
  2276  	case sys.ARM:
  2277  		return []string{"-marm"}
  2278  	case sys.ARM64:
  2279  		if buildcfg.GOOS == "darwin" {
  2280  			return []string{"-arch", "arm64"}
  2281  		}
  2282  	case sys.Loong64:
  2283  		return []string{"-mabi=lp64d"}
  2284  	case sys.MIPS64:
  2285  		return []string{"-mabi=64"}
  2286  	case sys.MIPS:
  2287  		return []string{"-mabi=32"}
  2288  	case sys.PPC64:
  2289  		if buildcfg.GOOS == "aix" {
  2290  			return []string{"-maix64"}
  2291  		} else {
  2292  			return []string{"-m64"}
  2293  		}
  2294  
  2295  	}
  2296  	return nil
  2297  }
  2298  
  2299  var wantHdr = objabi.HeaderString()
  2300  
  2301  
  2302  
  2303  
  2304  func ldobj(ctxt *Link, f *bio.Reader, lib *sym.Library, length int64, pn string, file string) *Hostobj {
  2305  	pkg := objabi.PathToPrefix(lib.Pkg)
  2306  
  2307  	eof := f.Offset() + length
  2308  	start := f.Offset()
  2309  	c1 := bgetc(f)
  2310  	c2 := bgetc(f)
  2311  	c3 := bgetc(f)
  2312  	c4 := bgetc(f)
  2313  	f.MustSeek(start, 0)
  2314  
  2315  	unit := &sym.CompilationUnit{Lib: lib}
  2316  	lib.Units = append(lib.Units, unit)
  2317  
  2318  	magic := uint32(c1)<<24 | uint32(c2)<<16 | uint32(c3)<<8 | uint32(c4)
  2319  	if magic == 0x7f454c46 { 
  2320  		ldelf := func(ctxt *Link, f *bio.Reader, pkg string, length int64, pn string) {
  2321  			textp, flags, err := loadelf.Load(ctxt.loader, ctxt.Arch, ctxt.IncVersion(), f, pkg, length, pn, ehdr.Flags)
  2322  			if err != nil {
  2323  				Errorf("%v", err)
  2324  				return
  2325  			}
  2326  			ehdr.Flags = flags
  2327  			ctxt.Textp = append(ctxt.Textp, textp...)
  2328  		}
  2329  		return ldhostobj(ldelf, ctxt.HeadType, f, pkg, length, pn, file)
  2330  	}
  2331  
  2332  	if magic&^1 == 0xfeedface || magic&^0x01000000 == 0xcefaedfe {
  2333  		ldmacho := func(ctxt *Link, f *bio.Reader, pkg string, length int64, pn string) {
  2334  			textp, err := loadmacho.Load(ctxt.loader, ctxt.Arch, ctxt.IncVersion(), f, pkg, length, pn)
  2335  			if err != nil {
  2336  				Errorf("%v", err)
  2337  				return
  2338  			}
  2339  			ctxt.Textp = append(ctxt.Textp, textp...)
  2340  		}
  2341  		return ldhostobj(ldmacho, ctxt.HeadType, f, pkg, length, pn, file)
  2342  	}
  2343  
  2344  	switch c1<<8 | c2 {
  2345  	case 0x4c01, 
  2346  		0x6486, 
  2347  		0xc401, 
  2348  		0x64aa: 
  2349  		ldpe := func(ctxt *Link, f *bio.Reader, pkg string, length int64, pn string) {
  2350  			ls, err := loadpe.Load(ctxt.loader, ctxt.Arch, ctxt.IncVersion(), f, pkg, length, pn)
  2351  			if err != nil {
  2352  				Errorf("%v", err)
  2353  				return
  2354  			}
  2355  			if len(ls.Resources) != 0 {
  2356  				setpersrc(ctxt, ls.Resources)
  2357  			}
  2358  			if ls.PData != 0 {
  2359  				sehp.pdata = append(sehp.pdata, ls.PData)
  2360  			}
  2361  			if ls.XData != 0 {
  2362  				sehp.xdata = append(sehp.xdata, ls.XData)
  2363  			}
  2364  			ctxt.Textp = append(ctxt.Textp, ls.Textp...)
  2365  		}
  2366  		return ldhostobj(ldpe, ctxt.HeadType, f, pkg, length, pn, file)
  2367  	}
  2368  
  2369  	if c1 == 0x01 && (c2 == 0xD7 || c2 == 0xF7) {
  2370  		ldxcoff := func(ctxt *Link, f *bio.Reader, pkg string, length int64, pn string) {
  2371  			textp, err := loadxcoff.Load(ctxt.loader, ctxt.Arch, ctxt.IncVersion(), f, pkg, length, pn)
  2372  			if err != nil {
  2373  				Errorf("%v", err)
  2374  				return
  2375  			}
  2376  			ctxt.Textp = append(ctxt.Textp, textp...)
  2377  		}
  2378  		return ldhostobj(ldxcoff, ctxt.HeadType, f, pkg, length, pn, file)
  2379  	}
  2380  
  2381  	if c1 != 'g' || c2 != 'o' || c3 != ' ' || c4 != 'o' {
  2382  		
  2383  		
  2384  		
  2385  		unknownObjFormat = true
  2386  		return ldhostobj(nil, ctxt.HeadType, f, pkg, length, pn, file)
  2387  	}
  2388  
  2389  	
  2390  	line, err := f.ReadString('\n')
  2391  	if err != nil {
  2392  		Errorf("truncated object file: %s: %v", pn, err)
  2393  		return nil
  2394  	}
  2395  
  2396  	if !strings.HasPrefix(line, "go object ") {
  2397  		if strings.HasSuffix(pn, ".go") {
  2398  			Exitf("%s: uncompiled .go source file", pn)
  2399  			return nil
  2400  		}
  2401  
  2402  		if line == ctxt.Arch.Name {
  2403  			
  2404  			Errorf("%s: stale object file", pn)
  2405  			return nil
  2406  		}
  2407  
  2408  		Errorf("%s: not an object file: @%d %q", pn, start, line)
  2409  		return nil
  2410  	}
  2411  
  2412  	
  2413  	if line != wantHdr {
  2414  		Errorf("%s: linked object header mismatch:\nhave %q\nwant %q\n", pn, line, wantHdr)
  2415  	}
  2416  
  2417  	
  2418  	
  2419  	
  2420  	
  2421  	
  2422  	
  2423  
  2424  	import0 := f.Offset()
  2425  
  2426  	c1 = '\n' 
  2427  	c2 = bgetc(f)
  2428  	c3 = bgetc(f)
  2429  	markers := 0
  2430  	for {
  2431  		if c1 == '\n' {
  2432  			if markers%2 == 0 && c2 == '!' && c3 == '\n' {
  2433  				break
  2434  			}
  2435  			if c2 == '$' && c3 == '$' {
  2436  				markers++
  2437  			}
  2438  		}
  2439  
  2440  		c1 = c2
  2441  		c2 = c3
  2442  		c3 = bgetc(f)
  2443  		if c3 == -1 {
  2444  			Errorf("truncated object file: %s", pn)
  2445  			return nil
  2446  		}
  2447  	}
  2448  
  2449  	import1 := f.Offset()
  2450  
  2451  	f.MustSeek(import0, 0)
  2452  	ldpkg(ctxt, f, lib, import1-import0-2, pn) 
  2453  	f.MustSeek(import1, 0)
  2454  
  2455  	fingerprint := ctxt.loader.Preload(ctxt.IncVersion(), f, lib, unit, eof-f.Offset())
  2456  	if !fingerprint.IsZero() { 
  2457  		
  2458  		
  2459  		
  2460  		
  2461  		
  2462  		if lib.Fingerprint.IsZero() { 
  2463  			lib.Fingerprint = fingerprint
  2464  		}
  2465  		checkFingerprint(lib, fingerprint, lib.Srcref, lib.Fingerprint)
  2466  	}
  2467  
  2468  	addImports(ctxt, lib, pn)
  2469  	return nil
  2470  }
  2471  
  2472  
  2473  
  2474  
  2475  
  2476  func symbolsAreUnresolved(ctxt *Link, want []string) []bool {
  2477  	returnAllUndefs := -1
  2478  	undefs, _ := ctxt.loader.UndefinedRelocTargets(returnAllUndefs)
  2479  	seen := make(map[loader.Sym]struct{})
  2480  	rval := make([]bool, len(want))
  2481  	wantm := make(map[string]int)
  2482  	for k, w := range want {
  2483  		wantm[w] = k
  2484  	}
  2485  	count := 0
  2486  	for _, s := range undefs {
  2487  		if _, ok := seen[s]; ok {
  2488  			continue
  2489  		}
  2490  		seen[s] = struct{}{}
  2491  		if k, ok := wantm[ctxt.loader.SymName(s)]; ok {
  2492  			rval[k] = true
  2493  			count++
  2494  			if count == len(want) {
  2495  				return rval
  2496  			}
  2497  		}
  2498  	}
  2499  	return rval
  2500  }
  2501  
  2502  
  2503  
  2504  
  2505  func hostObject(ctxt *Link, objname string, path string) {
  2506  	if ctxt.Debugvlog > 1 {
  2507  		ctxt.Logf("hostObject(%s)\n", path)
  2508  	}
  2509  	objlib := sym.Library{
  2510  		Pkg: objname,
  2511  	}
  2512  	f, err := bio.Open(path)
  2513  	if err != nil {
  2514  		Exitf("cannot open host object %q file %s: %v", objname, path, err)
  2515  	}
  2516  	defer f.Close()
  2517  	h := ldobj(ctxt, f, &objlib, 0, path, path)
  2518  	if h.ld == nil {
  2519  		Exitf("unrecognized object file format in %s", path)
  2520  	}
  2521  	h.file = path
  2522  	h.length = f.MustSeek(0, 2)
  2523  	f.MustSeek(h.off, 0)
  2524  	h.ld(ctxt, f, h.pkg, h.length, h.pn)
  2525  	if *flagCaptureHostObjs != "" {
  2526  		captureHostObj(h)
  2527  	}
  2528  }
  2529  
  2530  func checkFingerprint(lib *sym.Library, libfp goobj.FingerprintType, src string, srcfp goobj.FingerprintType) {
  2531  	if libfp != srcfp {
  2532  		Exitf("fingerprint mismatch: %s has %x, import from %s expecting %x", lib, libfp, src, srcfp)
  2533  	}
  2534  }
  2535  
  2536  func readelfsymboldata(ctxt *Link, f *elf.File, sym *elf.Symbol) []byte {
  2537  	data := make([]byte, sym.Size)
  2538  	sect := f.Sections[sym.Section]
  2539  	if sect.Type != elf.SHT_PROGBITS && sect.Type != elf.SHT_NOTE {
  2540  		Errorf("reading %s from non-data section", sym.Name)
  2541  	}
  2542  	n, err := sect.ReadAt(data, int64(sym.Value-sect.Addr))
  2543  	if uint64(n) != sym.Size {
  2544  		Errorf("reading contents of %s: %v", sym.Name, err)
  2545  	}
  2546  	return data
  2547  }
  2548  
  2549  func readwithpad(r io.Reader, sz int32) ([]byte, error) {
  2550  	data := make([]byte, Rnd(int64(sz), 4))
  2551  	_, err := io.ReadFull(r, data)
  2552  	if err != nil {
  2553  		return nil, err
  2554  	}
  2555  	data = data[:sz]
  2556  	return data, nil
  2557  }
  2558  
  2559  func readnote(f *elf.File, name []byte, typ int32) ([]byte, error) {
  2560  	for _, sect := range f.Sections {
  2561  		if sect.Type != elf.SHT_NOTE {
  2562  			continue
  2563  		}
  2564  		r := sect.Open()
  2565  		for {
  2566  			var namesize, descsize, noteType int32
  2567  			err := binary.Read(r, f.ByteOrder, &namesize)
  2568  			if err != nil {
  2569  				if err == io.EOF {
  2570  					break
  2571  				}
  2572  				return nil, fmt.Errorf("read namesize failed: %v", err)
  2573  			}
  2574  			err = binary.Read(r, f.ByteOrder, &descsize)
  2575  			if err != nil {
  2576  				return nil, fmt.Errorf("read descsize failed: %v", err)
  2577  			}
  2578  			err = binary.Read(r, f.ByteOrder, ¬eType)
  2579  			if err != nil {
  2580  				return nil, fmt.Errorf("read type failed: %v", err)
  2581  			}
  2582  			noteName, err := readwithpad(r, namesize)
  2583  			if err != nil {
  2584  				return nil, fmt.Errorf("read name failed: %v", err)
  2585  			}
  2586  			desc, err := readwithpad(r, descsize)
  2587  			if err != nil {
  2588  				return nil, fmt.Errorf("read desc failed: %v", err)
  2589  			}
  2590  			if string(name) == string(noteName) && typ == noteType {
  2591  				return desc, nil
  2592  			}
  2593  		}
  2594  	}
  2595  	return nil, nil
  2596  }
  2597  
  2598  func findshlib(ctxt *Link, shlib string) string {
  2599  	if filepath.IsAbs(shlib) {
  2600  		return shlib
  2601  	}
  2602  	for _, libdir := range ctxt.Libdir {
  2603  		libpath := filepath.Join(libdir, shlib)
  2604  		if _, err := os.Stat(libpath); err == nil {
  2605  			return libpath
  2606  		}
  2607  	}
  2608  	Errorf("cannot find shared library: %s", shlib)
  2609  	return ""
  2610  }
  2611  
  2612  func ldshlibsyms(ctxt *Link, shlib string) {
  2613  	var libpath string
  2614  	if filepath.IsAbs(shlib) {
  2615  		libpath = shlib
  2616  		shlib = filepath.Base(shlib)
  2617  	} else {
  2618  		libpath = findshlib(ctxt, shlib)
  2619  		if libpath == "" {
  2620  			return
  2621  		}
  2622  	}
  2623  	for _, processedlib := range ctxt.Shlibs {
  2624  		if processedlib.Path == libpath {
  2625  			return
  2626  		}
  2627  	}
  2628  	if ctxt.Debugvlog > 1 {
  2629  		ctxt.Logf("ldshlibsyms: found library with name %s at %s\n", shlib, libpath)
  2630  	}
  2631  
  2632  	f, err := elf.Open(libpath)
  2633  	if err != nil {
  2634  		Errorf("cannot open shared library: %s", libpath)
  2635  		return
  2636  	}
  2637  	
  2638  	
  2639  	
  2640  
  2641  	hash, err := readnote(f, ELF_NOTE_GO_NAME, ELF_NOTE_GOABIHASH_TAG)
  2642  	if err != nil {
  2643  		Errorf("cannot read ABI hash from shared library %s: %v", libpath, err)
  2644  		return
  2645  	}
  2646  
  2647  	depsbytes, err := readnote(f, ELF_NOTE_GO_NAME, ELF_NOTE_GODEPS_TAG)
  2648  	if err != nil {
  2649  		Errorf("cannot read dep list from shared library %s: %v", libpath, err)
  2650  		return
  2651  	}
  2652  	var deps []string
  2653  	for _, dep := range strings.Split(string(depsbytes), "\n") {
  2654  		if dep == "" {
  2655  			continue
  2656  		}
  2657  		if !filepath.IsAbs(dep) {
  2658  			
  2659  			
  2660  			
  2661  			abs := filepath.Join(filepath.Dir(libpath), dep)
  2662  			if _, err := os.Stat(abs); err == nil {
  2663  				dep = abs
  2664  			}
  2665  		}
  2666  		deps = append(deps, dep)
  2667  	}
  2668  
  2669  	syms, err := f.DynamicSymbols()
  2670  	if err != nil {
  2671  		Errorf("cannot read symbols from shared library: %s", libpath)
  2672  		return
  2673  	}
  2674  
  2675  	symAddr := map[string]uint64{}
  2676  	for _, elfsym := range syms {
  2677  		if elf.ST_TYPE(elfsym.Info) == elf.STT_NOTYPE || elf.ST_TYPE(elfsym.Info) == elf.STT_SECTION {
  2678  			continue
  2679  		}
  2680  
  2681  		
  2682  		
  2683  		ver := 0
  2684  		symname := elfsym.Name 
  2685  		if elf.ST_TYPE(elfsym.Info) == elf.STT_FUNC && strings.HasPrefix(elfsym.Name, "type:") {
  2686  			ver = abiInternalVer
  2687  		} else if buildcfg.Experiment.RegabiWrappers && elf.ST_TYPE(elfsym.Info) == elf.STT_FUNC {
  2688  			
  2689  			if strings.HasSuffix(elfsym.Name, ".abiinternal") {
  2690  				ver = sym.SymVerABIInternal
  2691  				symname = strings.TrimSuffix(elfsym.Name, ".abiinternal")
  2692  			} else if strings.HasSuffix(elfsym.Name, ".abi0") {
  2693  				ver = 0
  2694  				symname = strings.TrimSuffix(elfsym.Name, ".abi0")
  2695  			}
  2696  		}
  2697  
  2698  		l := ctxt.loader
  2699  		s := l.LookupOrCreateSym(symname, ver)
  2700  
  2701  		
  2702  		
  2703  		
  2704  		
  2705  		if l.SymType(s) != 0 && l.SymType(s) != sym.SDYNIMPORT {
  2706  			continue
  2707  		}
  2708  		su := l.MakeSymbolUpdater(s)
  2709  		su.SetType(sym.SDYNIMPORT)
  2710  		l.SetSymElfType(s, elf.ST_TYPE(elfsym.Info))
  2711  		su.SetSize(int64(elfsym.Size))
  2712  		if elfsym.Section != elf.SHN_UNDEF {
  2713  			
  2714  			l.SetSymPkg(s, libpath)
  2715  
  2716  			
  2717  			
  2718  			sname := l.SymName(s)
  2719  			if strings.HasPrefix(sname, "type:") && !strings.HasPrefix(sname, "type:.") {
  2720  				su.SetData(readelfsymboldata(ctxt, f, &elfsym))
  2721  			}
  2722  		}
  2723  
  2724  		if symname != elfsym.Name {
  2725  			l.SetSymExtname(s, elfsym.Name)
  2726  		}
  2727  		symAddr[elfsym.Name] = elfsym.Value
  2728  	}
  2729  
  2730  	
  2731  	
  2732  	
  2733  	relocTarget := map[uint64]string{}
  2734  	addends := false
  2735  	sect := f.SectionByType(elf.SHT_REL)
  2736  	if sect == nil {
  2737  		sect = f.SectionByType(elf.SHT_RELA)
  2738  		if sect == nil {
  2739  			log.Fatalf("can't find SHT_REL or SHT_RELA section of %s", shlib)
  2740  		}
  2741  		addends = true
  2742  	}
  2743  	
  2744  	data, err := sect.Data()
  2745  	if err != nil {
  2746  		log.Fatalf("can't read relocation section of %s: %v", shlib, err)
  2747  	}
  2748  	bo := f.ByteOrder
  2749  	for len(data) > 0 {
  2750  		var off, idx uint64
  2751  		var addend int64
  2752  		switch f.Class {
  2753  		case elf.ELFCLASS64:
  2754  			off = bo.Uint64(data)
  2755  			info := bo.Uint64(data[8:])
  2756  			data = data[16:]
  2757  			if addends {
  2758  				addend = int64(bo.Uint64(data))
  2759  				data = data[8:]
  2760  			}
  2761  
  2762  			idx = info >> 32
  2763  			typ := info & 0xffff
  2764  			
  2765  			
  2766  			switch typ {
  2767  			case uint64(elf.R_X86_64_64):
  2768  			case uint64(elf.R_AARCH64_ABS64):
  2769  			case uint64(elf.R_LARCH_64):
  2770  			case uint64(elf.R_390_64):
  2771  			case uint64(elf.R_PPC64_ADDR64):
  2772  			default:
  2773  				continue
  2774  			}
  2775  		case elf.ELFCLASS32:
  2776  			off = uint64(bo.Uint32(data))
  2777  			info := bo.Uint32(data[4:])
  2778  			data = data[8:]
  2779  			if addends {
  2780  				addend = int64(int32(bo.Uint32(data)))
  2781  				data = data[4:]
  2782  			}
  2783  
  2784  			idx = uint64(info >> 8)
  2785  			typ := info & 0xff
  2786  			
  2787  			switch typ {
  2788  			case uint32(elf.R_386_32):
  2789  			case uint32(elf.R_ARM_ABS32):
  2790  			default:
  2791  				continue
  2792  			}
  2793  		default:
  2794  			log.Fatalf("unknown bit size %s", f.Class)
  2795  		}
  2796  		if addend != 0 {
  2797  			continue
  2798  		}
  2799  		relocTarget[off] = syms[idx-1].Name
  2800  	}
  2801  
  2802  	ctxt.Shlibs = append(ctxt.Shlibs, Shlib{Path: libpath, Hash: hash, Deps: deps, File: f, symAddr: symAddr, relocTarget: relocTarget})
  2803  }
  2804  
  2805  func addsection(ldr *loader.Loader, arch *sys.Arch, seg *sym.Segment, name string, rwx int) *sym.Section {
  2806  	sect := ldr.NewSection()
  2807  	sect.Rwx = uint8(rwx)
  2808  	sect.Name = name
  2809  	sect.Seg = seg
  2810  	sect.Align = int32(arch.PtrSize) 
  2811  	seg.Sections = append(seg.Sections, sect)
  2812  	return sect
  2813  }
  2814  
  2815  func usage() {
  2816  	fmt.Fprintf(os.Stderr, "usage: link [options] main.o\n")
  2817  	objabi.Flagprint(os.Stderr)
  2818  	Exit(2)
  2819  }
  2820  
  2821  type SymbolType int8 
  2822  
  2823  const (
  2824  	
  2825  	TextSym      SymbolType = 'T'
  2826  	DataSym      SymbolType = 'D'
  2827  	BSSSym       SymbolType = 'B'
  2828  	UndefinedSym SymbolType = 'U'
  2829  	TLSSym       SymbolType = 't'
  2830  	FrameSym     SymbolType = 'm'
  2831  	ParamSym     SymbolType = 'p'
  2832  	AutoSym      SymbolType = 'a'
  2833  
  2834  	
  2835  	DeletedAutoSym = 'x'
  2836  )
  2837  
  2838  
  2839  func (ctxt *Link) defineInternal(p string, t sym.SymKind) loader.Sym {
  2840  	s := ctxt.loader.CreateSymForUpdate(p, 0)
  2841  	s.SetType(t)
  2842  	s.SetSpecial(true)
  2843  	s.SetLocal(true)
  2844  	return s.Sym()
  2845  }
  2846  
  2847  func (ctxt *Link) xdefine(p string, t sym.SymKind, v int64) loader.Sym {
  2848  	s := ctxt.defineInternal(p, t)
  2849  	ctxt.loader.SetSymValue(s, v)
  2850  	return s
  2851  }
  2852  
  2853  func datoff(ldr *loader.Loader, s loader.Sym, addr int64) int64 {
  2854  	if uint64(addr) >= Segdata.Vaddr {
  2855  		return int64(uint64(addr) - Segdata.Vaddr + Segdata.Fileoff)
  2856  	}
  2857  	if uint64(addr) >= Segtext.Vaddr {
  2858  		return int64(uint64(addr) - Segtext.Vaddr + Segtext.Fileoff)
  2859  	}
  2860  	ldr.Errorf(s, "invalid datoff %#x", addr)
  2861  	return 0
  2862  }
  2863  
  2864  func Entryvalue(ctxt *Link) int64 {
  2865  	a := *flagEntrySymbol
  2866  	if a[0] >= '0' && a[0] <= '9' {
  2867  		return atolwhex(a)
  2868  	}
  2869  	ldr := ctxt.loader
  2870  	s := ldr.Lookup(a, 0)
  2871  	if s == 0 {
  2872  		Errorf("missing entry symbol %q", a)
  2873  		return 0
  2874  	}
  2875  	st := ldr.SymType(s)
  2876  	if st == 0 {
  2877  		return *FlagTextAddr
  2878  	}
  2879  	if !ctxt.IsAIX() && !st.IsText() {
  2880  		ldr.Errorf(s, "entry not text")
  2881  	}
  2882  	return ldr.SymValue(s)
  2883  }
  2884  
  2885  func (ctxt *Link) callgraph() {
  2886  	if !*FlagC {
  2887  		return
  2888  	}
  2889  
  2890  	ldr := ctxt.loader
  2891  	for _, s := range ctxt.Textp {
  2892  		relocs := ldr.Relocs(s)
  2893  		for i := 0; i < relocs.Count(); i++ {
  2894  			r := relocs.At(i)
  2895  			rs := r.Sym()
  2896  			if rs == 0 {
  2897  				continue
  2898  			}
  2899  			if r.Type().IsDirectCall() && ldr.SymType(rs).IsText() {
  2900  				ctxt.Logf("%s calls %s\n", ldr.SymName(s), ldr.SymName(rs))
  2901  			}
  2902  		}
  2903  	}
  2904  }
  2905  
  2906  func Rnd(v int64, r int64) int64 {
  2907  	if r <= 0 {
  2908  		return v
  2909  	}
  2910  	v += r - 1
  2911  	c := v % r
  2912  	if c < 0 {
  2913  		c += r
  2914  	}
  2915  	v -= c
  2916  	return v
  2917  }
  2918  
  2919  func bgetc(r *bio.Reader) int {
  2920  	c, err := r.ReadByte()
  2921  	if err != nil {
  2922  		if err != io.EOF {
  2923  			log.Fatalf("reading input: %v", err)
  2924  		}
  2925  		return -1
  2926  	}
  2927  	return int(c)
  2928  }
  2929  
  2930  type markKind uint8 
  2931  const (
  2932  	_ markKind = iota
  2933  	visiting
  2934  	visited
  2935  )
  2936  
  2937  func postorder(libs []*sym.Library) []*sym.Library {
  2938  	order := make([]*sym.Library, 0, len(libs)) 
  2939  	mark := make(map[*sym.Library]markKind, len(libs))
  2940  	for _, lib := range libs {
  2941  		dfs(lib, mark, &order)
  2942  	}
  2943  	return order
  2944  }
  2945  
  2946  func dfs(lib *sym.Library, mark map[*sym.Library]markKind, order *[]*sym.Library) {
  2947  	if mark[lib] == visited {
  2948  		return
  2949  	}
  2950  	if mark[lib] == visiting {
  2951  		panic("found import cycle while visiting " + lib.Pkg)
  2952  	}
  2953  	mark[lib] = visiting
  2954  	for _, i := range lib.Imports {
  2955  		dfs(i, mark, order)
  2956  	}
  2957  	mark[lib] = visited
  2958  	*order = append(*order, lib)
  2959  }
  2960  
  2961  func ElfSymForReloc(ctxt *Link, s loader.Sym) int32 {
  2962  	
  2963  	
  2964  	les := ctxt.loader.SymLocalElfSym(s)
  2965  	if les != 0 {
  2966  		return les
  2967  	} else {
  2968  		return ctxt.loader.SymElfSym(s)
  2969  	}
  2970  }
  2971  
  2972  func AddGotSym(target *Target, ldr *loader.Loader, syms *ArchSyms, s loader.Sym, elfRelocTyp uint32) {
  2973  	if ldr.SymGot(s) >= 0 {
  2974  		return
  2975  	}
  2976  
  2977  	Adddynsym(ldr, target, syms, s)
  2978  	got := ldr.MakeSymbolUpdater(syms.GOT)
  2979  	ldr.SetGot(s, int32(got.Size()))
  2980  	got.AddUint(target.Arch, 0)
  2981  
  2982  	if target.IsElf() {
  2983  		if target.Arch.PtrSize == 8 {
  2984  			rela := ldr.MakeSymbolUpdater(syms.Rela)
  2985  			rela.AddAddrPlus(target.Arch, got.Sym(), int64(ldr.SymGot(s)))
  2986  			rela.AddUint64(target.Arch, elf.R_INFO(uint32(ldr.SymDynid(s)), elfRelocTyp))
  2987  			rela.AddUint64(target.Arch, 0)
  2988  		} else {
  2989  			rel := ldr.MakeSymbolUpdater(syms.Rel)
  2990  			rel.AddAddrPlus(target.Arch, got.Sym(), int64(ldr.SymGot(s)))
  2991  			rel.AddUint32(target.Arch, elf.R_INFO32(uint32(ldr.SymDynid(s)), elfRelocTyp))
  2992  		}
  2993  	} else if target.IsDarwin() {
  2994  		leg := ldr.MakeSymbolUpdater(syms.LinkEditGOT)
  2995  		leg.AddUint32(target.Arch, uint32(ldr.SymDynid(s)))
  2996  		if target.IsPIE() && target.IsInternal() {
  2997  			
  2998  			
  2999  			
  3000  			MachoAddBind(int64(ldr.SymGot(s)), s)
  3001  		}
  3002  	} else {
  3003  		ldr.Errorf(s, "addgotsym: unsupported binary format")
  3004  	}
  3005  }
  3006  
  3007  var hostobjcounter int
  3008  
  3009  
  3010  
  3011  
  3012  
  3013  
  3014  func captureHostObj(h *Hostobj) {
  3015  	
  3016  	ofile := fmt.Sprintf("captured-obj-%d.o", hostobjcounter)
  3017  	ifile := fmt.Sprintf("captured-obj-%d.txt", hostobjcounter)
  3018  	hostobjcounter++
  3019  	opath := filepath.Join(*flagCaptureHostObjs, ofile)
  3020  	ipath := filepath.Join(*flagCaptureHostObjs, ifile)
  3021  
  3022  	
  3023  	info := fmt.Sprintf("pkg: %s\npn: %s\nfile: %s\noff: %d\nlen: %d\n",
  3024  		h.pkg, h.pn, h.file, h.off, h.length)
  3025  	if err := os.WriteFile(ipath, []byte(info), 0666); err != nil {
  3026  		log.Fatalf("error writing captured host obj info %s: %v", ipath, err)
  3027  	}
  3028  
  3029  	readObjData := func() []byte {
  3030  		inf, err := os.Open(h.file)
  3031  		if err != nil {
  3032  			log.Fatalf("capturing host obj: open failed on %s: %v", h.pn, err)
  3033  		}
  3034  		defer inf.Close()
  3035  		res := make([]byte, h.length)
  3036  		if n, err := inf.ReadAt(res, h.off); err != nil || n != int(h.length) {
  3037  			log.Fatalf("capturing host obj: readat failed on %s: %v", h.pn, err)
  3038  		}
  3039  		return res
  3040  	}
  3041  
  3042  	
  3043  	if err := os.WriteFile(opath, readObjData(), 0666); err != nil {
  3044  		log.Fatalf("error writing captured host object %s: %v", opath, err)
  3045  	}
  3046  
  3047  	fmt.Fprintf(os.Stderr, "link: info: captured host object %s to %s\n",
  3048  		h.file, opath)
  3049  }
  3050  
  3051  
  3052  
  3053  
  3054  func (ctxt *Link) findExtLinkTool(toolname string) string {
  3055  	var cc []string
  3056  	cc = append(cc, ctxt.extld()...)
  3057  	cc = append(cc, hostlinkArchArgs(ctxt.Arch)...)
  3058  	cc = append(cc, "--print-prog-name", toolname)
  3059  	out, err := exec.Command(cc[0], cc[1:]...).CombinedOutput()
  3060  	if err != nil {
  3061  		Exitf("%s: finding %s failed: %v\n%s", os.Args[0], toolname, err, out)
  3062  	}
  3063  	cmdpath := strings.TrimRight(string(out), "\r\n")
  3064  	return cmdpath
  3065  }
  3066  
  3067  
  3068  
  3069  func (ctxt *Link) isMSVC() bool {
  3070  	extld := ctxt.extld()
  3071  	name, args := extld[0], extld[1:]
  3072  	args = append(args, trimLinkerArgv(flagExtldflags)...)
  3073  	args = append(args, "--version")
  3074  	cmd := exec.Command(name, args...)
  3075  	if out, err := cmd.CombinedOutput(); err == nil {
  3076  		if bytes.Contains(out, []byte("-msvc\n")) || bytes.Contains(out, []byte("-msvc\r")) {
  3077  			return true
  3078  		}
  3079  	}
  3080  	return false
  3081  }
  3082  
View as plain text