1// Inferno utils/8l/asm.c
2// https://bitbucket.org/inferno-os/inferno-os/src/master/utils/8l/asm.c
3//
4//	Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
5//	Portions Copyright © 1995-1997 C H Forsyth ([email protected])
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 ([email protected])
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
31package ld
32
33import (
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	"sort"
48	"strings"
49	"sync"
50	"time"
51
52	"cmd/internal/bio"
53	"cmd/internal/goobj"
54	"cmd/internal/notsha256"
55	"cmd/internal/objabi"
56	"cmd/internal/sys"
57	"cmd/link/internal/loadelf"
58	"cmd/link/internal/loader"
59	"cmd/link/internal/loadmacho"
60	"cmd/link/internal/loadpe"
61	"cmd/link/internal/loadxcoff"
62	"cmd/link/internal/sym"
63)
64
65// Data layout and relocation.
66
67// Derived from Inferno utils/6l/l.h
68// https://bitbucket.org/inferno-os/inferno-os/src/master/utils/6l/l.h
69//
70//	Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
71//	Portions Copyright © 1995-1997 C H Forsyth ([email protected])
72//	Portions Copyright © 1997-1999 Vita Nuova Limited
73//	Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
74//	Portions Copyright © 2004,2006 Bruce Ellis
75//	Portions Copyright © 2005-2007 C H Forsyth ([email protected])
76//	Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
77//	Portions Copyright © 2009 The Go Authors. All rights reserved.
78//
79// Permission is hereby granted, free of charge, to any person obtaining a copy
80// of this software and associated documentation files (the "Software"), to deal
81// in the Software without restriction, including without limitation the rights
82// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
83// copies of the Software, and to permit persons to whom the Software is
84// furnished to do so, subject to the following conditions:
85//
86// The above copyright notice and this permission notice shall be included in
87// all copies or substantial portions of the Software.
88//
89// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
90// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
91// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
92// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
93// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
94// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
95// THE SOFTWARE.
96
97// ArchSyms holds a number of architecture specific symbols used during
98// relocation.  Rather than allowing them universal access to all symbols,
99// we keep a subset for relocation application.
100type ArchSyms struct {
101	Rel     loader.Sym
102	Rela    loader.Sym
103	RelPLT  loader.Sym
104	RelaPLT loader.Sym
105
106	LinkEditGOT loader.Sym
107	LinkEditPLT loader.Sym
108
109	TOC    loader.Sym
110	DotTOC []loader.Sym // for each version
111
112	GOT    loader.Sym
113	PLT    loader.Sym
114	GOTPLT loader.Sym
115
116	Tlsg      loader.Sym
117	Tlsoffset int
118
119	Dynamic loader.Sym
120	DynSym  loader.Sym
121	DynStr  loader.Sym
122
123	unreachableMethod loader.Sym
124
125	// Symbol containing a list of all the inittasks that need
126	// to be run at startup.
127	mainInittasks loader.Sym
128}
129
130// mkArchSym is a helper for setArchSyms, to set up a special symbol.
131func (ctxt *Link) mkArchSym(name string, ver int, ls *loader.Sym) {
132	*ls = ctxt.loader.LookupOrCreateSym(name, ver)
133	ctxt.loader.SetAttrReachable(*ls, true)
134}
135
136// mkArchSymVec is similar to  setArchSyms, but operates on elements within
137// a slice, where each element corresponds to some symbol version.
138func (ctxt *Link) mkArchSymVec(name string, ver int, ls []loader.Sym) {
139	ls[ver] = ctxt.loader.LookupOrCreateSym(name, ver)
140	ctxt.loader.SetAttrReachable(ls[ver], true)
141}
142
143// setArchSyms sets up the ArchSyms structure, and must be called before
144// relocations are applied.
145func (ctxt *Link) setArchSyms() {
146	ctxt.mkArchSym(".got", 0, &ctxt.GOT)
147	ctxt.mkArchSym(".plt", 0, &ctxt.PLT)
148	ctxt.mkArchSym(".got.plt", 0, &ctxt.GOTPLT)
149	ctxt.mkArchSym(".dynamic", 0, &ctxt.Dynamic)
150	ctxt.mkArchSym(".dynsym", 0, &ctxt.DynSym)
151	ctxt.mkArchSym(".dynstr", 0, &ctxt.DynStr)
152	ctxt.mkArchSym("runtime.unreachableMethod", abiInternalVer, &ctxt.unreachableMethod)
153
154	if ctxt.IsPPC64() {
155		ctxt.mkArchSym("TOC", 0, &ctxt.TOC)
156
157		ctxt.DotTOC = make([]loader.Sym, ctxt.MaxVersion()+1)
158		for i := 0; i <= ctxt.MaxVersion(); i++ {
159			if i >= sym.SymVerABICount && i < sym.SymVerStatic { // these versions are not used currently
160				continue
161			}
162			ctxt.mkArchSymVec(".TOC.", i, ctxt.DotTOC)
163		}
164	}
165	if ctxt.IsElf() {
166		ctxt.mkArchSym(".rel", 0, &ctxt.Rel)
167		ctxt.mkArchSym(".rela", 0, &ctxt.Rela)
168		ctxt.mkArchSym(".rel.plt", 0, &ctxt.RelPLT)
169		ctxt.mkArchSym(".rela.plt", 0, &ctxt.RelaPLT)
170	}
171	if ctxt.IsDarwin() {
172		ctxt.mkArchSym(".linkedit.got", 0, &ctxt.LinkEditGOT)
173		ctxt.mkArchSym(".linkedit.plt", 0, &ctxt.LinkEditPLT)
174	}
175}
176
177type Arch struct {
178	Funcalign  int
179	Maxalign   int
180	Minalign   int
181	Dwarfregsp int
182	Dwarfreglr int
183
184	// Threshold of total text size, used for trampoline insertion. If the total
185	// text size is smaller than TrampLimit, we won't need to insert trampolines.
186	// It is pretty close to the offset range of a direct CALL machine instruction.
187	// We leave some room for extra stuff like PLT stubs.
188	TrampLimit uint64
189
190	// Empty spaces between codeblocks will be padded with this value.
191	// For example an architecture might want to pad with a trap instruction to
192	// catch wayward programs. Architectures that do not define a padding value
193	// are padded with zeros.
194	CodePad []byte
195
196	// Plan 9 variables.
197	Plan9Magic  uint32
198	Plan9_64Bit bool
199
200	Adddynrel func(*Target, *loader.Loader, *ArchSyms, loader.Sym, loader.Reloc, int) bool
201	Archinit  func(*Link)
202	// Archreloc is an arch-specific hook that assists in relocation processing
203	// (invoked by 'relocsym'); it handles target-specific relocation tasks.
204	// Here "rel" is the current relocation being examined, "sym" is the symbol
205	// containing the chunk of data to which the relocation applies, and "off"
206	// is the contents of the to-be-relocated data item (from sym.P). Return
207	// value is the appropriately relocated value (to be written back to the
208	// same spot in sym.P), number of external _host_ relocations needed (i.e.
209	// ELF/Mach-O/etc. relocations, not Go relocations, this must match ELF.Reloc1,
210	// etc.), and a boolean indicating success/failure (a failing value indicates
211	// a fatal error).
212	Archreloc func(*Target, *loader.Loader, *ArchSyms, loader.Reloc, loader.Sym,
213		int64) (relocatedOffset int64, nExtReloc int, ok bool)
214	// Archrelocvariant is a second arch-specific hook used for
215	// relocation processing; it handles relocations where r.Type is
216	// insufficient to describe the relocation (r.Variant !=
217	// sym.RV_NONE). Here "rel" is the relocation being applied, "sym"
218	// is the symbol containing the chunk of data to which the
219	// relocation applies, and "off" is the contents of the
220	// to-be-relocated data item (from sym.P). Return is an updated
221	// offset value.
222	Archrelocvariant func(target *Target, ldr *loader.Loader, rel loader.Reloc,
223		rv sym.RelocVariant, sym loader.Sym, offset int64, data []byte) (relocatedOffset int64)
224
225	// Generate a trampoline for a call from s to rs if necessary. ri is
226	// index of the relocation.
227	Trampoline func(ctxt *Link, ldr *loader.Loader, ri int, rs, s loader.Sym)
228
229	// Assembling the binary breaks into two phases, writing the code/data/
230	// dwarf information (which is rather generic), and some more architecture
231	// specific work like setting up the elf headers/dynamic relocations, etc.
232	// The phases are called "Asmb" and "Asmb2". Asmb2 needs to be defined for
233	// every architecture, but only if architecture has an Asmb function will
234	// it be used for assembly.  Otherwise a generic assembly Asmb function is
235	// used.
236	Asmb  func(*Link, *loader.Loader)
237	Asmb2 func(*Link, *loader.Loader)
238
239	// Extreloc is an arch-specific hook that converts a Go relocation to an
240	// external relocation. Return the external relocation and whether it is
241	// needed.
242	Extreloc func(*Target, *loader.Loader, loader.Reloc, loader.Sym) (loader.ExtReloc, bool)
243
244	Gentext        func(*Link, *loader.Loader) // Generate text before addressing has been performed.
245	Machoreloc1    func(*sys.Arch, *OutBuf, *loader.Loader, loader.Sym, loader.ExtReloc, int64) bool
246	MachorelocSize uint32 // size of an Mach-O relocation record, must match Machoreloc1.
247	PEreloc1       func(*sys.Arch, *OutBuf, *loader.Loader, loader.Sym, loader.ExtReloc, int64) bool
248	Xcoffreloc1    func(*sys.Arch, *OutBuf, *loader.Loader, loader.Sym, loader.ExtReloc, int64) bool
249
250	// Generate additional symbols for the native symbol table just prior to
251	// code generation.
252	GenSymsLate func(*Link, *loader.Loader)
253
254	// TLSIEtoLE converts a TLS Initial Executable relocation to
255	// a TLS Local Executable relocation.
256	//
257	// This is possible when a TLS IE relocation refers to a local
258	// symbol in an executable, which is typical when internally
259	// linking PIE binaries.
260	TLSIEtoLE func(P []byte, off, size int)
261
262	// optional override for assignAddress
263	AssignAddress func(ldr *loader.Loader, sect *sym.Section, n int, s loader.Sym, va uint64, isTramp bool) (*sym.Section, int, uint64)
264
265	// ELF specific information.
266	ELF ELFArch
267}
268
269var (
270	thearch Arch
271	lcSize  int32
272	rpath   Rpath
273	spSize  int32
274	symSize int32
275)
276
277// Symbol version of ABIInternal symbols. It is sym.SymVerABIInternal if ABI wrappers
278// are used, 0 otherwise.
279var abiInternalVer = sym.SymVerABIInternal
280
281// DynlinkingGo reports whether we are producing Go code that can live
282// in separate shared libraries linked together at runtime.
283func (ctxt *Link) DynlinkingGo() bool {
284	if !ctxt.Loaded {
285		panic("DynlinkingGo called before all symbols loaded")
286	}
287	return ctxt.BuildMode == BuildModeShared || ctxt.linkShared || ctxt.BuildMode == BuildModePlugin || ctxt.canUsePlugins
288}
289
290// CanUsePlugins reports whether a plugins can be used
291func (ctxt *Link) CanUsePlugins() bool {
292	if !ctxt.Loaded {
293		panic("CanUsePlugins called before all symbols loaded")
294	}
295	return ctxt.canUsePlugins
296}
297
298// NeedCodeSign reports whether we need to code-sign the output binary.
299func (ctxt *Link) NeedCodeSign() bool {
300	return ctxt.IsDarwin() && ctxt.IsARM64()
301}
302
303var (
304	dynlib          []string
305	ldflag          []string
306	havedynamic     int
307	Funcalign       int
308	iscgo           bool
309	elfglobalsymndx int
310	interpreter     string
311
312	debug_s bool // backup old value of debug['s']
313	HEADR   int32
314
315	nerrors  int
316	liveness int64 // size of liveness data (funcdata), printed if -v
317
318	// See -strictdups command line flag.
319	checkStrictDups   int // 0=off 1=warning 2=error
320	strictDupMsgCount int
321)
322
323var (
324	Segtext      sym.Segment
325	Segrodata    sym.Segment
326	Segrelrodata sym.Segment
327	Segdata      sym.Segment
328	Segdwarf     sym.Segment
329	Segpdata     sym.Segment // windows-only
330	Segxdata     sym.Segment // windows-only
331
332	Segments = []*sym.Segment{&Segtext, &Segrodata, &Segrelrodata, &Segdata, &Segdwarf, &Segpdata, &Segxdata}
333)
334
335const pkgdef = "__.PKGDEF"
336
337var (
338	// externalobj is set to true if we see an object compiled by
339	// the host compiler that is not from a package that is known
340	// to support internal linking mode.
341	externalobj = false
342
343	// dynimportfail is a list of packages for which generating
344	// the dynimport file, _cgo_import.go, failed. If there are
345	// any of these objects, we must link externally. Issue 52863.
346	dynimportfail []string
347
348	// preferlinkext is a list of packages for which the Go command
349	// noticed use of peculiar C flags. If we see any of these,
350	// default to linking externally unless overridden by the
351	// user. See issues #58619, #58620, and #58848.
352	preferlinkext []string
353
354	// unknownObjFormat is set to true if we see an object whose
355	// format we don't recognize.
356	unknownObjFormat = false
357
358	theline string
359)
360
361func Lflag(ctxt *Link, arg string) {
362	ctxt.Libdir = append(ctxt.Libdir, arg)
363}
364
365/*
366 * Unix doesn't like it when we write to a running (or, sometimes,
367 * recently run) binary, so remove the output file before writing it.
368 * On Windows 7, remove() can force a subsequent create() to fail.
369 * S_ISREG() does not exist on Plan 9.
370 */
371func mayberemoveoutfile() {
372	if fi, err := os.Lstat(*flagOutfile); err == nil && !fi.Mode().IsRegular() {
373		return
374	}
375	os.Remove(*flagOutfile)
376}
377
378func libinit(ctxt *Link) {
379	Funcalign = thearch.Funcalign
380
381	// add goroot to the end of the libdir list.
382	suffix := ""
383
384	suffixsep := ""
385	if *flagInstallSuffix != "" {
386		suffixsep = "_"
387		suffix = *flagInstallSuffix
388	} else if *flagRace {
389		suffixsep = "_"
390		suffix = "race"
391	} else if *flagMsan {
392		suffixsep = "_"
393		suffix = "msan"
394	} else if *flagAsan {
395		suffixsep = "_"
396		suffix = "asan"
397	}
398
399	if buildcfg.GOROOT != "" {
400		Lflag(ctxt, filepath.Join(buildcfg.GOROOT, "pkg", fmt.Sprintf("%s_%s%s%s", buildcfg.GOOS, buildcfg.GOARCH, suffixsep, suffix)))
401	}
402
403	mayberemoveoutfile()
404
405	if err := ctxt.Out.Open(*flagOutfile); err != nil {
406		Exitf("cannot create %s: %v", *flagOutfile, err)
407	}
408
409	if *flagEntrySymbol == "" {
410		switch ctxt.BuildMode {
411		case BuildModeCShared, BuildModeCArchive:
412			*flagEntrySymbol = fmt.Sprintf("_rt0_%s_%s_lib", buildcfg.GOARCH, buildcfg.GOOS)
413		case BuildModeExe, BuildModePIE:
414			*flagEntrySymbol = fmt.Sprintf("_rt0_%s_%s", buildcfg.GOARCH, buildcfg.GOOS)
415		case BuildModeShared, BuildModePlugin:
416			// No *flagEntrySymbol for -buildmode=shared and plugin
417		default:
418			Errorf(nil, "unknown *flagEntrySymbol for buildmode %v", ctxt.BuildMode)
419		}
420	}
421}
422
423func exitIfErrors() {
424	if nerrors != 0 || checkStrictDups > 1 && strictDupMsgCount > 0 {
425		mayberemoveoutfile()
426		Exit(2)
427	}
428
429}
430
431func errorexit() {
432	exitIfErrors()
433	Exit(0)
434}
435
436func loadinternal(ctxt *Link, name string) *sym.Library {
437	zerofp := goobj.FingerprintType{}
438	if ctxt.linkShared && ctxt.PackageShlib != nil {
439		if shlib := ctxt.PackageShlib[name]; shlib != "" {
440			return addlibpath(ctxt, "internal", "internal", "", name, shlib, zerofp)
441		}
442	}
443	if ctxt.PackageFile != nil {
444		if pname := ctxt.PackageFile[name]; pname != "" {
445			return addlibpath(ctxt, "internal", "internal", pname, name, "", zerofp)
446		}
447		ctxt.Logf("loadinternal: cannot find %s\n", name)
448		return nil
449	}
450
451	for _, libdir := range ctxt.Libdir {
452		if ctxt.linkShared {
453			shlibname := filepath.Join(libdir, name+".shlibname")
454			if ctxt.Debugvlog != 0 {
455				ctxt.Logf("searching for %s.a in %s\n", name, shlibname)
456			}
457			if _, err := os.Stat(shlibname); err == nil {
458				return addlibpath(ctxt, "internal", "internal", "", name, shlibname, zerofp)
459			}
460		}
461		pname := filepath.Join(libdir, name+".a")
462		if ctxt.Debugvlog != 0 {
463			ctxt.Logf("searching for %s.a in %s\n", name, pname)
464		}
465		if _, err := os.Stat(pname); err == nil {
466			return addlibpath(ctxt, "internal", "internal", pname, name, "", zerofp)
467		}
468	}
469
470	if name == "runtime" {
471		Exitf("error: unable to find runtime.a")
472	}
473	ctxt.Logf("warning: unable to find %s.a\n", name)
474	return nil
475}
476
477// extld returns the current external linker.
478func (ctxt *Link) extld() []string {
479	if len(flagExtld) == 0 {
480		// Return the default external linker for the platform.
481		// This only matters when link tool is called directly without explicit -extld,
482		// go tool already passes the correct linker in other cases.
483		switch buildcfg.GOOS {
484		case "darwin", "freebsd", "openbsd":
485			flagExtld = []string{"clang"}
486		default:
487			flagExtld = []string{"gcc"}
488		}
489	}
490	return flagExtld
491}
492
493// findLibPathCmd uses cmd command to find gcc library libname.
494// It returns library full path if found, or "none" if not found.
495func (ctxt *Link) findLibPathCmd(cmd, libname string) string {
496	extld := ctxt.extld()
497	name, args := extld[0], extld[1:]
498	args = append(args, hostlinkArchArgs(ctxt.Arch)...)
499	args = append(args, cmd)
500	if ctxt.Debugvlog != 0 {
501		ctxt.Logf("%s %v\n", extld, args)
502	}
503	out, err := exec.Command(name, args...).Output()
504	if err != nil {
505		if ctxt.Debugvlog != 0 {
506			ctxt.Logf("not using a %s file because compiler failed\n%v\n%s\n", libname, err, out)
507		}
508		return "none"
509	}
510	return strings.TrimSpace(string(out))
511}
512
513// findLibPath searches for library libname.
514// It returns library full path if found, or "none" if not found.
515func (ctxt *Link) findLibPath(libname string) string {
516	return ctxt.findLibPathCmd("--print-file-name="+libname, libname)
517}
518
519func (ctxt *Link) loadlib() {
520	var flags uint32
521	if *flagCheckLinkname {
522		flags |= loader.FlagCheckLinkname
523	}
524	switch *FlagStrictDups {
525	case 0:
526		// nothing to do
527	case 1, 2:
528		flags |= loader.FlagStrictDups
529	default:
530		log.Fatalf("invalid -strictdups flag value %d", *FlagStrictDups)
531	}
532	ctxt.loader = loader.NewLoader(flags, &ctxt.ErrorReporter.ErrorReporter)
533	ctxt.ErrorReporter.SymName = func(s loader.Sym) string {
534		return ctxt.loader.SymName(s)
535	}
536
537	// ctxt.Library grows during the loop, so not a range loop.
538	i := 0
539	for ; i < len(ctxt.Library); i++ {
540		lib := ctxt.Library[i]
541		if lib.Shlib == "" {
542			if ctxt.Debugvlog > 1 {
543				ctxt.Logf("autolib: %s (from %s)\n", lib.File, lib.Objref)
544			}
545			loadobjfile(ctxt, lib)
546		}
547	}
548
549	// load internal packages, if not already
550	if *flagRace {
551		loadinternal(ctxt, "runtime/race")
552	}
553	if *flagMsan {
554		loadinternal(ctxt, "runtime/msan")
555	}
556	if *flagAsan {
557		loadinternal(ctxt, "runtime/asan")
558	}
559	loadinternal(ctxt, "runtime")
560	for ; i < len(ctxt.Library); i++ {
561		lib := ctxt.Library[i]
562		if lib.Shlib == "" {
563			loadobjfile(ctxt, lib)
564		}
565	}
566	// At this point, the Go objects are "preloaded". Not all the symbols are
567	// added to the symbol table (only defined package symbols are). Looking
568	// up symbol by name may not get expected result.
569
570	iscgo = ctxt.LibraryByPkg["runtime/cgo"] != nil
571
572	// Plugins a require cgo support to function. Similarly, plugins may require additional
573	// internal linker support on some platforms which may not be implemented.
574	ctxt.canUsePlugins = ctxt.LibraryByPkg["plugin"] != nil && iscgo
575
576	// We now have enough information to determine the link mode.
577	determineLinkMode(ctxt)
578
579	if ctxt.LinkMode == LinkExternal && !iscgo && !(buildcfg.GOOS == "darwin" && ctxt.BuildMode != BuildModePlugin && ctxt.Arch.Family == sys.AMD64) {
580		// This indicates a user requested -linkmode=external.
581		// The startup code uses an import of runtime/cgo to decide
582		// whether to initialize the TLS.  So give it one. This could
583		// be handled differently but it's an unusual case.
584		if lib := loadinternal(ctxt, "runtime/cgo"); lib != nil && lib.Shlib == "" {
585			if ctxt.BuildMode == BuildModeShared || ctxt.linkShared {
586				Exitf("cannot implicitly include runtime/cgo in a shared library")
587			}
588			for ; i < len(ctxt.Library); i++ {
589				lib := ctxt.Library[i]
590				if lib.Shlib == "" {
591					loadobjfile(ctxt, lib)
592				}
593			}
594		}
595	}
596
597	// Add non-package symbols and references of externally defined symbols.
598	ctxt.loader.LoadSyms(ctxt.Arch)
599
600	// Load symbols from shared libraries, after all Go object symbols are loaded.
601	for _, lib := range ctxt.Library {
602		if lib.Shlib != "" {
603			if ctxt.Debugvlog > 1 {
604				ctxt.Logf("autolib: %s (from %s)\n", lib.Shlib, lib.Objref)
605			}
606			ldshlibsyms(ctxt, lib.Shlib)
607		}
608	}
609
610	// Process cgo directives (has to be done before host object loading).
611	ctxt.loadcgodirectives()
612
613	// Conditionally load host objects, or setup for external linking.
614	hostobjs(ctxt)
615	hostlinksetup(ctxt)
616
617	if ctxt.LinkMode == LinkInternal && len(hostobj) != 0 {
618		// If we have any undefined symbols in external
619		// objects, try to read them from the libgcc file.
620		any := false
621		undefs, froms := ctxt.loader.UndefinedRelocTargets(1)
622		if len(undefs) > 0 {
623			any = true
624			if ctxt.Debugvlog > 1 {
625				ctxt.Logf("loadlib: first unresolved is %s [%d] from %s [%d]\n",
626					ctxt.loader.SymName(undefs[0]), undefs[0],
627					ctxt.loader.SymName(froms[0]), froms[0])
628			}
629		}
630		if any {
631			if *flagLibGCC == "" {
632				*flagLibGCC = ctxt.findLibPathCmd("--print-libgcc-file-name", "libgcc")
633			}
634			if runtime.GOOS == "openbsd" && *flagLibGCC == "libgcc.a" {
635				// On OpenBSD `clang --print-libgcc-file-name` returns "libgcc.a".
636				// In this case we fail to load libgcc.a and can encounter link
637				// errors - see if we can find libcompiler_rt.a instead.
638				*flagLibGCC = ctxt.findLibPathCmd("--print-file-name=libcompiler_rt.a", "libcompiler_rt")
639			}
640			if ctxt.HeadType == objabi.Hwindows {
641				loadWindowsHostArchives(ctxt)
642			}
643			if *flagLibGCC != "none" {
644				hostArchive(ctxt, *flagLibGCC)
645			}
646			// For glibc systems, the linker setup used by GCC
647			// looks like
648			//
649			//  GROUP ( /lib/x86_64-linux-gnu/libc.so.6
650			//      /usr/lib/x86_64-linux-gnu/libc_nonshared.a
651			//      AS_NEEDED ( /lib64/ld-linux-x86-64.so.2 ) )
652			//
653			// where libc_nonshared.a contains a small set of
654			// symbols including "__stack_chk_fail_local" and a
655			// few others. Thus if we are doing internal linking
656			// and "__stack_chk_fail_local" is unresolved (most
657			// likely due to the use of -fstack-protector), try
658			// loading libc_nonshared.a to resolve it.
659			//
660			// On Alpine Linux (musl-based), the library providing
661			// this symbol is called libssp_nonshared.a.
662			isunresolved := symbolsAreUnresolved(ctxt, []string{"__stack_chk_fail_local"})
663			if isunresolved[0] {
664				if p := ctxt.findLibPath("libc_nonshared.a"); p != "none" {
665					hostArchive(ctxt, p)
666				}
667				if p := ctxt.findLibPath("libssp_nonshared.a"); p != "none" {
668					hostArchive(ctxt, p)
669				}
670			}
671		}
672	}
673
674	// We've loaded all the code now.
675	ctxt.Loaded = true
676
677	strictDupMsgCount = ctxt.loader.NStrictDupMsgs()
678}
679
680// loadWindowsHostArchives loads in host archives and objects when
681// doing internal linking on windows. Older toolchains seem to require
682// just a single pass through the various archives, but some modern
683// toolchains when linking a C program with mingw pass library paths
684// multiple times to the linker, e.g. "... -lmingwex -lmingw32 ...
685// -lmingwex -lmingw32 ...". To accommodate this behavior, we make two
686// passes over the host archives below.
687func loadWindowsHostArchives(ctxt *Link) {
688	any := true
689	for i := 0; any && i < 2; i++ {
690		// Link crt2.o (if present) to resolve "atexit" when
691		// using LLVM-based compilers.
692		isunresolved := symbolsAreUnresolved(ctxt, []string{"atexit"})
693		if isunresolved[0] {
694			if p := ctxt.findLibPath("crt2.o"); p != "none" {
695				hostObject(ctxt, "crt2", p)
696			}
697		}
698		if *flagRace {
699			if p := ctxt.findLibPath("libsynchronization.a"); p != "none" {
700				hostArchive(ctxt, p)
701			}
702		}
703		if p := ctxt.findLibPath("libmingwex.a"); p != "none" {
704			hostArchive(ctxt, p)
705		}
706		if p := ctxt.findLibPath("libmingw32.a"); p != "none" {
707			hostArchive(ctxt, p)
708		}
709		// Link libmsvcrt.a to resolve '__acrt_iob_func' symbol
710		// (see https://golang.org/issue/23649 for details).
711		if p := ctxt.findLibPath("libmsvcrt.a"); p != "none" {
712			hostArchive(ctxt, p)
713		}
714		any = false
715		undefs, froms := ctxt.loader.UndefinedRelocTargets(1)
716		if len(undefs) > 0 {
717			any = true
718			if ctxt.Debugvlog > 1 {
719				ctxt.Logf("loadWindowsHostArchives: remaining unresolved is %s [%d] from %s [%d]\n",
720					ctxt.loader.SymName(undefs[0]), undefs[0],
721					ctxt.loader.SymName(froms[0]), froms[0])
722			}
723		}
724	}
725	// If needed, create the __CTOR_LIST__ and __DTOR_LIST__
726	// symbols (referenced by some of the mingw support library
727	// routines). Creation of these symbols is normally done by the
728	// linker if not already present.
729	want := []string{"__CTOR_LIST__", "__DTOR_LIST__"}
730	isunresolved := symbolsAreUnresolved(ctxt, want)
731	for k, w := range want {
732		if isunresolved[k] {
733			sb := ctxt.loader.CreateSymForUpdate(w, 0)
734			sb.SetType(sym.SDATA)
735			sb.AddUint64(ctxt.Arch, 0)
736			sb.SetReachable(true)
737			ctxt.loader.SetAttrSpecial(sb.Sym(), true)
738		}
739	}
740
741	// Fix up references to DLL import symbols now that we're done
742	// pulling in new objects.
743	if err := loadpe.PostProcessImports(); err != nil {
744		Errorf(nil, "%v", err)
745	}
746
747	// TODO: maybe do something similar to peimporteddlls to collect
748	// all lib names and try link them all to final exe just like
749	// libmingwex.a and libmingw32.a:
750	/*
751		for:
752		#cgo windows LDFLAGS: -lmsvcrt -lm
753		import:
754		libmsvcrt.a libm.a
755	*/
756}
757
758// loadcgodirectives reads the previously discovered cgo directives, creating
759// symbols in preparation for host object loading or use later in the link.
760func (ctxt *Link) loadcgodirectives() {
761	l := ctxt.loader
762	hostObjSyms := make(map[loader.Sym]struct{})
763	for _, d := range ctxt.cgodata {
764		setCgoAttr(ctxt, d.file, d.pkg, d.directives, hostObjSyms)
765	}
766	ctxt.cgodata = nil
767
768	if ctxt.LinkMode == LinkInternal {
769		// Drop all the cgo_import_static declarations.
770		// Turns out we won't be needing them.
771		for symIdx := range hostObjSyms {
772			if l.SymType(symIdx) == sym.SHOSTOBJ {
773				// If a symbol was marked both
774				// cgo_import_static and cgo_import_dynamic,
775				// then we want to make it cgo_import_dynamic
776				// now.
777				su := l.MakeSymbolUpdater(symIdx)
778				if l.SymExtname(symIdx) != "" && l.SymDynimplib(symIdx) != "" && !(l.AttrCgoExportStatic(symIdx) || l.AttrCgoExportDynamic(symIdx)) {
779					su.SetType(sym.SDYNIMPORT)
780				} else {
781					su.SetType(0)
782				}
783			}
784		}
785	}
786}
787
788// Set up flags and special symbols depending on the platform build mode.
789// This version works with loader.Loader.
790func (ctxt *Link) linksetup() {
791	switch ctxt.BuildMode {
792	case BuildModeCShared, BuildModePlugin:
793		symIdx := ctxt.loader.LookupOrCreateSym("runtime.islibrary", 0)
794		sb := ctxt.loader.MakeSymbolUpdater(symIdx)
795		sb.SetType(sym.SNOPTRDATA)
796		sb.AddUint8(1)
797	case BuildModeCArchive:
798		symIdx := ctxt.loader.LookupOrCreateSym("runtime.isarchive", 0)
799		sb := ctxt.loader.MakeSymbolUpdater(symIdx)
800		sb.SetType(sym.SNOPTRDATA)
801		sb.AddUint8(1)
802	}
803
804	// Recalculate pe parameters now that we have ctxt.LinkMode set.
805	if ctxt.HeadType == objabi.Hwindows {
806		Peinit(ctxt)
807	}
808
809	if ctxt.LinkMode == LinkExternal {
810		// When external linking, we are creating an object file. The
811		// absolute address is irrelevant.
812		*FlagTextAddr = 0
813	}
814
815	// If there are no dynamic libraries needed, gcc disables dynamic linking.
816	// Because of this, glibc's dynamic ELF loader occasionally (like in version 2.13)
817	// assumes that a dynamic binary always refers to at least one dynamic library.
818	// Rather than be a source of test cases for glibc, disable dynamic linking
819	// the same way that gcc would.
820	//
821	// Exception: on OS X, programs such as Shark only work with dynamic
822	// binaries, so leave it enabled on OS X (Mach-O) binaries.
823	// Also leave it enabled on Solaris which doesn't support
824	// statically linked binaries.
825	if ctxt.BuildMode == BuildModeExe {
826		if havedynamic == 0 && ctxt.HeadType != objabi.Hdarwin && ctxt.HeadType != objabi.Hsolaris {
827			*FlagD = true
828		}
829	}
830
831	if ctxt.LinkMode == LinkExternal && ctxt.Arch.Family == sys.PPC64 && buildcfg.GOOS != "aix" {
832		toc := ctxt.loader.LookupOrCreateSym(".TOC.", 0)
833		sb := ctxt.loader.MakeSymbolUpdater(toc)
834		sb.SetType(sym.SDYNIMPORT)
835	}
836
837	// The Android Q linker started to complain about underalignment of the our TLS
838	// section. We don't actually use the section on android, so don't
839	// generate it.
840	if buildcfg.GOOS != "android" {
841		tlsg := ctxt.loader.LookupOrCreateSym("runtime.tlsg", 0)
842		sb := ctxt.loader.MakeSymbolUpdater(tlsg)
843
844		// runtime.tlsg is used for external linking on platforms that do not define
845		// a variable to hold g in assembly (currently only intel).
846		if sb.Type() == 0 {
847			sb.SetType(sym.STLSBSS)
848			sb.SetSize(int64(ctxt.Arch.PtrSize))
849		} else if sb.Type() != sym.SDYNIMPORT {
850			Errorf(nil, "runtime declared tlsg variable %v", sb.Type())
851		}
852		ctxt.loader.SetAttrReachable(tlsg, true)
853		ctxt.Tlsg = tlsg
854	}
855
856	var moduledata loader.Sym
857	var mdsb *loader.SymbolBuilder
858	if ctxt.BuildMode == BuildModePlugin {
859		moduledata = ctxt.loader.LookupOrCreateSym("local.pluginmoduledata", 0)
860		mdsb = ctxt.loader.MakeSymbolUpdater(moduledata)
861		ctxt.loader.SetAttrLocal(moduledata, true)
862	} else {
863		moduledata = ctxt.loader.LookupOrCreateSym("runtime.firstmoduledata", 0)
864		mdsb = ctxt.loader.MakeSymbolUpdater(moduledata)
865	}
866	if mdsb.Type() != 0 && mdsb.Type() != sym.SDYNIMPORT {
867		// If the module (toolchain-speak for "executable or shared
868		// library") we are linking contains the runtime package, it
869		// will define the runtime.firstmoduledata symbol and we
870		// truncate it back to 0 bytes so we can define its entire
871		// contents in symtab.go:symtab().
872		mdsb.SetSize(0)
873
874		// In addition, on ARM, the runtime depends on the linker
875		// recording the value of GOARM.
876		if ctxt.Arch.Family == sys.ARM {
877			goarm := ctxt.loader.LookupOrCreateSym("runtime.goarm", 0)
878			sb := ctxt.loader.MakeSymbolUpdater(goarm)
879			sb.SetType(sym.SDATA)
880			sb.SetSize(0)
881			sb.AddUint8(uint8(buildcfg.GOARM.Version))
882
883			goarmsoftfp := ctxt.loader.LookupOrCreateSym("runtime.goarmsoftfp", 0)
884			sb2 := ctxt.loader.MakeSymbolUpdater(goarmsoftfp)
885			sb2.SetType(sym.SDATA)
886			sb2.SetSize(0)
887			if buildcfg.GOARM.SoftFloat {
888				sb2.AddUint8(1)
889			} else {
890				sb2.AddUint8(0)
891			}
892		}
893
894		// Set runtime.disableMemoryProfiling bool if
895		// runtime.memProfileInternal is not retained in the binary after
896		// deadcode (and we're not dynamically linking).
897		memProfile := ctxt.loader.Lookup("runtime.memProfileInternal", abiInternalVer)
898		if memProfile != 0 && !ctxt.loader.AttrReachable(memProfile) && !ctxt.DynlinkingGo() {
899			memProfSym := ctxt.loader.LookupOrCreateSym("runtime.disableMemoryProfiling", 0)
900			sb := ctxt.loader.MakeSymbolUpdater(memProfSym)
901			sb.SetType(sym.SDATA)
902			sb.SetSize(0)
903			sb.AddUint8(1) // true bool
904		}
905	} else {
906		// If OTOH the module does not contain the runtime package,
907		// create a local symbol for the moduledata.
908		moduledata = ctxt.loader.LookupOrCreateSym("local.moduledata", 0)
909		mdsb = ctxt.loader.MakeSymbolUpdater(moduledata)
910		ctxt.loader.SetAttrLocal(moduledata, true)
911	}
912	// In all cases way we mark the moduledata as noptrdata to hide it from
913	// the GC.
914	mdsb.SetType(sym.SNOPTRDATA)
915	ctxt.loader.SetAttrReachable(moduledata, true)
916	ctxt.Moduledata = moduledata
917
918	if ctxt.Arch == sys.Arch386 && ctxt.HeadType != objabi.Hwindows {
919		if (ctxt.BuildMode == BuildModeCArchive && ctxt.IsELF) || ctxt.BuildMode == BuildModeCShared || ctxt.BuildMode == BuildModePIE || ctxt.DynlinkingGo() {
920			got := ctxt.loader.LookupOrCreateSym("_GLOBAL_OFFSET_TABLE_", 0)
921			sb := ctxt.loader.MakeSymbolUpdater(got)
922			sb.SetType(sym.SDYNIMPORT)
923			ctxt.loader.SetAttrReachable(got, true)
924		}
925	}
926
927	// DWARF-gen and other phases require that the unit Textp slices
928	// be populated, so that it can walk the functions in each unit.
929	// Call into the loader to do this (requires that we collect the
930	// set of internal libraries first). NB: might be simpler if we
931	// moved isRuntimeDepPkg to cmd/internal and then did the test in
932	// loader.AssignTextSymbolOrder.
933	ctxt.Library = postorder(ctxt.Library)
934	intlibs := []bool{}
935	for _, lib := range ctxt.Library {
936		intlibs = append(intlibs, isRuntimeDepPkg(lib.Pkg))
937	}
938	ctxt.Textp = ctxt.loader.AssignTextSymbolOrder(ctxt.Library, intlibs, ctxt.Textp)
939}
940
941// mangleTypeSym shortens the names of symbols that represent Go types
942// if they are visible in the symbol table.
943//
944// As the names of these symbols are derived from the string of
945// the type, they can run to many kilobytes long. So we shorten
946// them using a SHA-1 when the name appears in the final binary.
947// This also removes characters that upset external linkers.
948//
949// These are the symbols that begin with the prefix 'type.' and
950// contain run-time type information used by the runtime and reflect
951// packages. All Go binaries contain these symbols, but only
952// those programs loaded dynamically in multiple parts need these
953// symbols to have entries in the symbol table.
954func (ctxt *Link) mangleTypeSym() {
955	if ctxt.BuildMode != BuildModeShared && !ctxt.linkShared && ctxt.BuildMode != BuildModePlugin && !ctxt.CanUsePlugins() {
956		return
957	}
958
959	ldr := ctxt.loader
960	for s := loader.Sym(1); s < loader.Sym(ldr.NSym()); s++ {
961		if !ldr.AttrReachable(s) && !ctxt.linkShared {
962			// If -linkshared, the GCProg generation code may need to reach
963			// out to the shared library for the type descriptor's data, even
964			// the type descriptor itself is not actually needed at run time
965			// (therefore not reachable). We still need to mangle its name,
966			// so it is consistent with the one stored in the shared library.
967			continue
968		}
969		name := ldr.SymName(s)
970		newName := typeSymbolMangle(name)
971		if newName != name {
972			ldr.SetSymExtname(s, newName)
973
974			// When linking against a shared library, the Go object file may
975			// have reference to the original symbol name whereas the shared
976			// library provides a symbol with the mangled name. We need to
977			// copy the payload of mangled to original.
978			// XXX maybe there is a better way to do this.
979			dup := ldr.Lookup(newName, ldr.SymVersion(s))
980			if dup != 0 {
981				st := ldr.SymType(s)
982				dt := ldr.SymType(dup)
983				if st == sym.Sxxx && dt != sym.Sxxx {
984					ldr.CopySym(dup, s)
985				}
986			}
987		}
988	}
989}
990
991// typeSymbolMangle mangles the given symbol name into something shorter.
992//
993// Keep the type:. prefix, which parts of the linker (like the
994// DWARF generator) know means the symbol is not decodable.
995// Leave type:runtime. symbols alone, because other parts of
996// the linker manipulates them.
997func typeSymbolMangle(name string) string {
998	isType := strings.HasPrefix(name, "type:")
999	if !isType && !strings.Contains(name, "@") {
1000		// Issue 58800: instantiated symbols may include a type name, which may contain "@"
1001		return name
1002	}
1003	if strings.HasPrefix(name, "type:runtime.") {
1004		return name
1005	}
1006	if strings.HasPrefix(name, "go:string.") {
1007		// String symbols will be grouped to a single go:string.* symbol.
1008		// No need to mangle individual symbol names.
1009		return name
1010	}
1011	if len(name) <= 14 && !strings.Contains(name, "@") { // Issue 19529
1012		return name
1013	}
1014	if isType {
1015		hash := notsha256.Sum256([]byte(name[5:]))
1016		prefix := "type:"
1017		if name[5] == '.' {
1018			prefix = "type:."
1019		}
1020		return prefix + base64.StdEncoding.EncodeToString(hash[:6])
1021	}
1022	// instantiated symbol, replace type name in []
1023	i := strings.IndexByte(name, '[')
1024	j := strings.LastIndexByte(name, ']')
1025	if j == -1 || j <= i {
1026		j = len(name)
1027	}
1028	hash := notsha256.Sum256([]byte(name[i+1 : j]))
1029	return name[:i+1] + base64.StdEncoding.EncodeToString(hash[:6]) + name[j:]
1030}
1031
1032/*
1033 * look for the next file in an archive.
1034 * adapted from libmach.
1035 */
1036func nextar(bp *bio.Reader, off int64, a *ArHdr) int64 {
1037	if off&1 != 0 {
1038		off++
1039	}
1040	bp.MustSeek(off, 0)
1041	var buf [SAR_HDR]byte
1042	if n, err := io.ReadFull(bp, buf[:]); err != nil {
1043		if n == 0 && err != io.EOF {
1044			return -1
1045		}
1046		return 0
1047	}
1048
1049	a.name = artrim(buf[0:16])
1050	a.date = artrim(buf[16:28])
1051	a.uid = artrim(buf[28:34])
1052	a.gid = artrim(buf[34:40])
1053	a.mode = artrim(buf[40:48])
1054	a.size = artrim(buf[48:58])
1055	a.fmag = artrim(buf[58:60])
1056
1057	arsize := atolwhex(a.size)
1058	if arsize&1 != 0 {
1059		arsize++
1060	}
1061	return arsize + SAR_HDR
1062}
1063
1064func loadobjfile(ctxt *Link, lib *sym.Library) {
1065	pkg := objabi.PathToPrefix(lib.Pkg)
1066
1067	if ctxt.Debugvlog > 1 {
1068		ctxt.Logf("ldobj: %s (%s)\n", lib.File, pkg)
1069	}
1070	f, err := bio.Open(lib.File)
1071	if err != nil {
1072		Exitf("cannot open file %s: %v", lib.File, err)
1073	}
1074	defer f.Close()
1075	defer func() {
1076		if pkg == "main" && !lib.Main {
1077			Exitf("%s: not package main", lib.File)
1078		}
1079	}()
1080
1081	for i := 0; i < len(ARMAG); i++ {
1082		if c, err := f.ReadByte(); err == nil && c == ARMAG[i] {
1083			continue
1084		}
1085
1086		/* load it as a regular file */
1087		l := f.MustSeek(0, 2)
1088		f.MustSeek(0, 0)
1089		ldobj(ctxt, f, lib, l, lib.File, lib.File)
1090		return
1091	}
1092
1093	/*
1094	 * load all the object files from the archive now.
1095	 * this gives us sequential file access and keeps us
1096	 * from needing to come back later to pick up more
1097	 * objects.  it breaks the usual C archive model, but
1098	 * this is Go, not C.  the common case in Go is that
1099	 * we need to load all the objects, and then we throw away
1100	 * the individual symbols that are unused.
1101	 *
1102	 * loading every object will also make it possible to
1103	 * load foreign objects not referenced by __.PKGDEF.
1104	 */
1105	var arhdr ArHdr
1106	off := f.Offset()
1107	for {
1108		l := nextar(f, off, &arhdr)
1109		if l == 0 {
1110			break
1111		}
1112		if l < 0 {
1113			Exitf("%s: malformed archive", lib.File)
1114		}
1115		off += l
1116
1117		// __.PKGDEF isn't a real Go object file, and it's
1118		// absent in -linkobj builds anyway. Skipping it
1119		// ensures consistency between -linkobj and normal
1120		// build modes.
1121		if arhdr.name == pkgdef {
1122			continue
1123		}
1124
1125		if arhdr.name == "dynimportfail" {
1126			dynimportfail = append(dynimportfail, lib.Pkg)
1127		}
1128		if arhdr.name == "preferlinkext" {
1129			// Ignore this directive if -linkmode has been
1130			// set explicitly.
1131			if ctxt.LinkMode == LinkAuto {
1132				preferlinkext = append(preferlinkext, lib.Pkg)
1133			}
1134		}
1135
1136		// Skip other special (non-object-file) sections that
1137		// build tools may have added. Such sections must have
1138		// short names so that the suffix is not truncated.
1139		if len(arhdr.name) < 16 {
1140			if ext := filepath.Ext(arhdr.name); ext != ".o" && ext != ".syso" {
1141				continue
1142			}
1143		}
1144
1145		pname := fmt.Sprintf("%s(%s)", lib.File, arhdr.name)
1146		l = atolwhex(arhdr.size)
1147		ldobj(ctxt, f, lib, l, pname, lib.File)
1148	}
1149}
1150
1151type Hostobj struct {
1152	ld     func(*Link, *bio.Reader, string, int64, string)
1153	pkg    string
1154	pn     string
1155	file   string
1156	off    int64
1157	length int64
1158}
1159
1160var hostobj []Hostobj
1161
1162// These packages can use internal linking mode.
1163// Others trigger external mode.
1164var internalpkg = []string{
1165	"crypto/internal/boring",
1166	"crypto/internal/boring/syso",
1167	"crypto/x509",
1168	"net",
1169	"os/user",
1170	"runtime/cgo",
1171	"runtime/race",
1172	"runtime/race/internal/amd64v1",
1173	"runtime/race/internal/amd64v3",
1174	"runtime/msan",
1175	"runtime/asan",
1176}
1177
1178func ldhostobj(ld func(*Link, *bio.Reader, string, int64, string), headType objabi.HeadType, f *bio.Reader, pkg string, length int64, pn string, file string) *Hostobj {
1179	isinternal := false
1180	for _, intpkg := range internalpkg {
1181		if pkg == intpkg {
1182			isinternal = true
1183			break
1184		}
1185	}
1186
1187	// DragonFly declares errno with __thread, which results in a symbol
1188	// type of R_386_TLS_GD or R_X86_64_TLSGD. The Go linker does not
1189	// currently know how to handle TLS relocations, hence we have to
1190	// force external linking for any libraries that link in code that
1191	// uses errno. This can be removed if the Go linker ever supports
1192	// these relocation types.
1193	if headType == objabi.Hdragonfly {
1194		if pkg == "net" || pkg == "os/user" {
1195			isinternal = false
1196		}
1197	}
1198
1199	if !isinternal {
1200		externalobj = true
1201	}
1202
1203	hostobj = append(hostobj, Hostobj{})
1204	h := &hostobj[len(hostobj)-1]
1205	h.ld = ld
1206	h.pkg = pkg
1207	h.pn = pn
1208	h.file = file
1209	h.off = f.Offset()
1210	h.length = length
1211	return h
1212}
1213
1214func hostobjs(ctxt *Link) {
1215	if ctxt.LinkMode != LinkInternal {
1216		return
1217	}
1218	var h *Hostobj
1219
1220	for i := 0; i < len(hostobj); i++ {
1221		h = &hostobj[i]
1222		f, err := bio.Open(h.file)
1223		if err != nil {
1224			Exitf("cannot reopen %s: %v", h.pn, err)
1225		}
1226		f.MustSeek(h.off, 0)
1227		if h.ld == nil {
1228			Errorf(nil, "%s: unrecognized object file format", h.pn)
1229			continue
1230		}
1231		h.ld(ctxt, f, h.pkg, h.length, h.pn)
1232		if *flagCaptureHostObjs != "" {
1233			captureHostObj(h)
1234		}
1235		f.Close()
1236	}
1237}
1238
1239func hostlinksetup(ctxt *Link) {
1240	if ctxt.LinkMode != LinkExternal {
1241		return
1242	}
1243
1244	// For external link, record that we need to tell the external linker -s,
1245	// and turn off -s internally: the external linker needs the symbol
1246	// information for its final link.
1247	debug_s = *FlagS
1248	*FlagS = false
1249
1250	// create temporary directory and arrange cleanup
1251	if *flagTmpdir == "" {
1252		dir, err := os.MkdirTemp("", "go-link-")
1253		if err != nil {
1254			log.Fatal(err)
1255		}
1256		*flagTmpdir = dir
1257		ownTmpDir = true
1258		AtExit(func() {
1259			os.RemoveAll(*flagTmpdir)
1260		})
1261	}
1262
1263	// change our output to temporary object file
1264	if err := ctxt.Out.Close(); err != nil {
1265		Exitf("error closing output file")
1266	}
1267	mayberemoveoutfile()
1268
1269	p := filepath.Join(*flagTmpdir, "go.o")
1270	if err := ctxt.Out.Open(p); err != nil {
1271		Exitf("cannot create %s: %v", p, err)
1272	}
1273}
1274
1275// cleanTimeStamps resets the timestamps for the specified list of
1276// existing files to the Unix epoch (1970-01-01 00:00:00 +0000 UTC).
1277// We take this step in order to help preserve reproducible builds;
1278// this seems to be primarily needed for external linking on on Darwin
1279// with later versions of xcode, which (unfortunately) seem to want to
1280// incorporate object file times into the final output file's build
1281// ID. See issue 64947 for the unpleasant details.
1282func cleanTimeStamps(files []string) {
1283	epocht := time.Unix(0, 0)
1284	for _, f := range files {
1285		if err := os.Chtimes(f, epocht, epocht); err != nil {
1286			Exitf("cannot chtimes %s: %v", f, err)
1287		}
1288	}
1289}
1290
1291// hostobjCopy creates a copy of the object files in hostobj in a
1292// temporary directory.
1293func (ctxt *Link) hostobjCopy() (paths []string) {
1294	var wg sync.WaitGroup
1295	sema := make(chan struct{}, runtime.NumCPU()) // limit open file descriptors
1296	for i, h := range hostobj {
1297		h := h
1298		dst := filepath.Join(*flagTmpdir, fmt.Sprintf("%06d.o", i))
1299		paths = append(paths, dst)
1300		if ctxt.Debugvlog != 0 {
1301			ctxt.Logf("host obj copy: %s from pkg %s -> %s\n", h.pn, h.pkg, dst)
1302		}
1303
1304		wg.Add(1)
1305		go func() {
1306			sema <- struct{}{}
1307			defer func() {
1308				<-sema
1309				wg.Done()
1310			}()
1311			f, err := os.Open(h.file)
1312			if err != nil {
1313				Exitf("cannot reopen %s: %v", h.pn, err)
1314			}
1315			defer f.Close()
1316			if _, err := f.Seek(h.off, 0); err != nil {
1317				Exitf("cannot seek %s: %v", h.pn, err)
1318			}
1319
1320			w, err := os.Create(dst)
1321			if err != nil {
1322				Exitf("cannot create %s: %v", dst, err)
1323			}
1324			if _, err := io.CopyN(w, f, h.length); err != nil {
1325				Exitf("cannot write %s: %v", dst, err)
1326			}
1327			if err := w.Close(); err != nil {
1328				Exitf("cannot close %s: %v", dst, err)
1329			}
1330		}()
1331	}
1332	wg.Wait()
1333	return paths
1334}
1335
1336// writeGDBLinkerScript creates gcc linker script file in temp
1337// directory. writeGDBLinkerScript returns created file path.
1338// The script is used to work around gcc bug
1339// (see https://golang.org/issue/20183 for details).
1340func writeGDBLinkerScript() string {
1341	name := "fix_debug_gdb_scripts.ld"
1342	path := filepath.Join(*flagTmpdir, name)
1343	src := `SECTIONS
1344{
1345  .debug_gdb_scripts BLOCK(__section_alignment__) (NOLOAD) :
1346  {
1347    *(.debug_gdb_scripts)
1348  }
1349}
1350INSERT AFTER .debug_types;
1351`
1352	err := os.WriteFile(path, []byte(src), 0666)
1353	if err != nil {
1354		Errorf(nil, "WriteFile %s failed: %v", name, err)
1355	}
1356	return path
1357}
1358
1359type machoUpdateFunc func(ctxt *Link, exef *os.File, exem *macho.File, outexe string) error
1360
1361// archive builds a .a archive from the hostobj object files.
1362func (ctxt *Link) archive() {
1363	if ctxt.BuildMode != BuildModeCArchive {
1364		return
1365	}
1366
1367	exitIfErrors()
1368
1369	if *flagExtar == "" {
1370		const printProgName = "--print-prog-name=ar"
1371		cc := ctxt.extld()
1372		*flagExtar = "ar"
1373		if linkerFlagSupported(ctxt.Arch, cc[0], "", printProgName) {
1374			*flagExtar = ctxt.findExtLinkTool("ar")
1375		}
1376	}
1377
1378	mayberemoveoutfile()
1379
1380	// Force the buffer to flush here so that external
1381	// tools will see a complete file.
1382	if err := ctxt.Out.Close(); err != nil {
1383		Exitf("error closing %v", *flagOutfile)
1384	}
1385
1386	argv := []string{*flagExtar, "-q", "-c", "-s"}
1387	if ctxt.HeadType == objabi.Haix {
1388		argv = append(argv, "-X64")
1389	}
1390	godotopath := filepath.Join(*flagTmpdir, "go.o")
1391	cleanTimeStamps([]string{godotopath})
1392	hostObjCopyPaths := ctxt.hostobjCopy()
1393	cleanTimeStamps(hostObjCopyPaths)
1394
1395	argv = append(argv, *flagOutfile)
1396	argv = append(argv, godotopath)
1397	argv = append(argv, hostObjCopyPaths...)
1398
1399	if ctxt.Debugvlog != 0 {
1400		ctxt.Logf("archive: %s\n", strings.Join(argv, " "))
1401	}
1402
1403	// If supported, use syscall.Exec() to invoke the archive command,
1404	// which should be the final remaining step needed for the link.
1405	// This will reduce peak RSS for the link (and speed up linking of
1406	// large applications), since when the archive command runs we
1407	// won't be holding onto all of the linker's live memory.
1408	if syscallExecSupported && !ownTmpDir {
1409		runAtExitFuncs()
1410		ctxt.execArchive(argv)
1411		panic("should not get here")
1412	}
1413
1414	// Otherwise invoke 'ar' in the usual way (fork + exec).
1415	if out, err := exec.Command(argv[0], argv[1:]...).CombinedOutput(); err != nil {
1416		Exitf("running %s failed: %v\n%s", argv[0], err, out)
1417	}
1418}
1419
1420func (ctxt *Link) hostlink() {
1421	if ctxt.LinkMode != LinkExternal || nerrors > 0 {
1422		return
1423	}
1424	if ctxt.BuildMode == BuildModeCArchive {
1425		return
1426	}
1427
1428	var argv []string
1429	argv = append(argv, ctxt.extld()...)
1430	argv = append(argv, hostlinkArchArgs(ctxt.Arch)...)
1431
1432	if *FlagS || debug_s {
1433		if ctxt.HeadType == objabi.Hdarwin {
1434			// Recent versions of macOS print
1435			//	ld: warning: option -s is obsolete and being ignored
1436			// so do not pass any arguments (but we strip symbols below).
1437		} else {
1438			argv = append(argv, "-s")
1439		}
1440	}
1441
1442	// On darwin, whether to combine DWARF into executable.
1443	// Only macOS supports unmapped segments such as our __DWARF segment.
1444	combineDwarf := ctxt.IsDarwin() && !*FlagW && machoPlatform == PLATFORM_MACOS
1445
1446	switch ctxt.HeadType {
1447	case objabi.Hdarwin:
1448		if combineDwarf {
1449			// Leave room for DWARF combining.
1450			// -headerpad is incompatible with -fembed-bitcode.
1451			argv = append(argv, "-Wl,-headerpad,1144")
1452		}
1453		if ctxt.DynlinkingGo() && buildcfg.GOOS != "ios" {
1454			// -flat_namespace is deprecated on iOS.
1455			// It is useful for supporting plugins. We don't support plugins on iOS.
1456			// -flat_namespace may cause the dynamic linker to hang at forkExec when
1457			// resolving a lazy binding. See issue 38824.
1458			// Force eager resolution to work around.
1459			argv = append(argv, "-Wl,-flat_namespace", "-Wl,-bind_at_load")
1460		}
1461		if !combineDwarf {
1462			argv = append(argv, "-Wl,-S") // suppress STAB (symbolic debugging) symbols
1463			if debug_s {
1464				// We are generating a binary with symbol table suppressed.
1465				// Suppress local symbols. We need to keep dynamically exported
1466				// and referenced symbols so the dynamic linker can resolve them.
1467				argv = append(argv, "-Wl,-x")
1468			}
1469		}
1470	case objabi.Hopenbsd:
1471		argv = append(argv, "-pthread")
1472		if ctxt.BuildMode != BuildModePIE {
1473			argv = append(argv, "-Wl,-nopie")
1474		}
1475		if linkerFlagSupported(ctxt.Arch, argv[0], "", "-Wl,-z,nobtcfi") {
1476			// -Wl,-z,nobtcfi is only supported on OpenBSD 7.4+, remove guard
1477			// when OpenBSD 7.5 is released and 7.3 is no longer supported.
1478			argv = append(argv, "-Wl,-z,nobtcfi")
1479		}
1480		if ctxt.Arch.InFamily(sys.ARM64) {
1481			// Disable execute-only on openbsd/arm64 - the Go arm64 assembler
1482			// currently stores constants in the text section rather than in rodata.
1483			// See issue #59615.
1484			argv = append(argv, "-Wl,--no-execute-only")
1485		}
1486	case objabi.Hwindows:
1487		if windowsgui {
1488			argv = append(argv, "-mwindows")
1489		} else {
1490			argv = append(argv, "-mconsole")
1491		}
1492		// Mark as having awareness of terminal services, to avoid
1493		// ancient compatibility hacks.
1494		argv = append(argv, "-Wl,--tsaware")
1495
1496		// Enable DEP
1497		argv = append(argv, "-Wl,--nxcompat")
1498
1499		argv = append(argv, fmt.Sprintf("-Wl,--major-os-version=%d", PeMinimumTargetMajorVersion))
1500		argv = append(argv, fmt.Sprintf("-Wl,--minor-os-version=%d", PeMinimumTargetMinorVersion))
1501		argv = append(argv, fmt.Sprintf("-Wl,--major-subsystem-version=%d", PeMinimumTargetMajorVersion))
1502		argv = append(argv, fmt.Sprintf("-Wl,--minor-subsystem-version=%d", PeMinimumTargetMinorVersion))
1503	case objabi.Haix:
1504		argv = append(argv, "-pthread")
1505		// prevent ld to reorder .text functions to keep the same
1506		// first/last functions for moduledata.
1507		argv = append(argv, "-Wl,-bnoobjreorder")
1508		// mcmodel=large is needed for every gcc generated files, but
1509		// ld still need -bbigtoc in order to allow larger TOC.
1510		argv = append(argv, "-mcmodel=large")
1511		argv = append(argv, "-Wl,-bbigtoc")
1512	}
1513
1514	// On PPC64, verify the external toolchain supports Power10. This is needed when
1515	// PC relative relocations might be generated by Go. Only targets compiling ELF
1516	// binaries might generate these relocations.
1517	if ctxt.IsPPC64() && ctxt.IsElf() && buildcfg.GOPPC64 >= 10 {
1518		if !linkerFlagSupported(ctxt.Arch, argv[0], "", "-mcpu=power10") {
1519			Exitf("The external toolchain does not support -mcpu=power10. " +
1520				" This is required to externally link GOPPC64 >= power10")
1521		}
1522	}
1523
1524	// Enable/disable ASLR on Windows.
1525	addASLRargs := func(argv []string, val bool) []string {
1526		// Old/ancient versions of GCC support "--dynamicbase" and
1527		// "--high-entropy-va" but don't enable it by default. In
1528		// addition, they don't accept "--disable-dynamicbase" or
1529		// "--no-dynamicbase", so the only way to disable ASLR is to
1530		// not pass any flags at all.
1531		//
1532		// More modern versions of GCC (and also clang) enable ASLR
1533		// by default. With these compilers, however you can turn it
1534		// off if you want using "--disable-dynamicbase" or
1535		// "--no-dynamicbase".
1536		//
1537		// The strategy below is to try using "--disable-dynamicbase";
1538		// if this succeeds, then assume we're working with more
1539		// modern compilers and act accordingly. If it fails, assume
1540		// an ancient compiler with ancient defaults.
1541		var dbopt string
1542		var heopt string
1543		dbon := "--dynamicbase"
1544		heon := "--high-entropy-va"
1545		dboff := "--disable-dynamicbase"
1546		heoff := "--disable-high-entropy-va"
1547		if val {
1548			dbopt = dbon
1549			heopt = heon
1550		} else {
1551			// Test to see whether "--disable-dynamicbase" works.
1552			newer := linkerFlagSupported(ctxt.Arch, argv[0], "", "-Wl,"+dboff)
1553			if newer {
1554				// Newer compiler, which supports both on/off options.
1555				dbopt = dboff
1556				heopt = heoff
1557			} else {
1558				// older toolchain: we have to say nothing in order to
1559				// get a no-ASLR binary.
1560				dbopt = ""
1561				heopt = ""
1562			}
1563		}
1564		if dbopt != "" {
1565			argv = append(argv, "-Wl,"+dbopt)
1566		}
1567		// enable high-entropy ASLR on 64-bit.
1568		if ctxt.Arch.PtrSize >= 8 && heopt != "" {
1569			argv = append(argv, "-Wl,"+heopt)
1570		}
1571		return argv
1572	}
1573
1574	switch ctxt.BuildMode {
1575	case BuildModeExe:
1576		if ctxt.HeadType == objabi.Hdarwin {
1577			if machoPlatform == PLATFORM_MACOS && ctxt.IsAMD64() {
1578				argv = append(argv, "-Wl,-no_pie")
1579			}
1580		}
1581		if *flagRace && ctxt.HeadType == objabi.Hwindows {
1582			// Current windows/amd64 race detector tsan support
1583			// library can't handle PIE mode (see #53539 for more details).
1584			// For now, explicitly disable PIE (since some compilers
1585			// default to it) if -race is in effect.
1586			argv = addASLRargs(argv, false)
1587		}
1588	case BuildModePIE:
1589		switch ctxt.HeadType {
1590		case objabi.Hdarwin, objabi.Haix:
1591		case objabi.Hwindows:
1592			if *flagAslr && *flagRace {
1593				// Current windows/amd64 race detector tsan support
1594				// library can't handle PIE mode (see #53539 for more details).
1595				// Disable alsr if -race in effect.
1596				*flagAslr = false
1597			}
1598			argv = addASLRargs(argv, *flagAslr)
1599		default:
1600			// ELF.
1601			if ctxt.UseRelro() {
1602				argv = append(argv, "-Wl,-z,relro")
1603			}
1604			argv = append(argv, "-pie")
1605		}
1606	case BuildModeCShared:
1607		if ctxt.HeadType == objabi.Hdarwin {
1608			argv = append(argv, "-dynamiclib")
1609		} else {
1610			if ctxt.UseRelro() {
1611				argv = append(argv, "-Wl,-z,relro")
1612			}
1613			argv = append(argv, "-shared")
1614			if ctxt.HeadType == objabi.Hwindows {
1615				argv = addASLRargs(argv, *flagAslr)
1616			} else {
1617				// Pass -z nodelete to mark the shared library as
1618				// non-closeable: a dlclose will do nothing.
1619				argv = append(argv, "-Wl,-z,nodelete")
1620				// Only pass Bsymbolic on non-Windows.
1621				argv = append(argv, "-Wl,-Bsymbolic")
1622			}
1623		}
1624	case BuildModeShared:
1625		if ctxt.UseRelro() {
1626			argv = append(argv, "-Wl,-z,relro")
1627		}
1628		argv = append(argv, "-shared")
1629	case BuildModePlugin:
1630		if ctxt.HeadType == objabi.Hdarwin {
1631			argv = append(argv, "-dynamiclib")
1632		} else {
1633			if ctxt.UseRelro() {
1634				argv = append(argv, "-Wl,-z,relro")
1635			}
1636			argv = append(argv, "-shared")
1637		}
1638	}
1639
1640	var altLinker string
1641	if ctxt.IsELF && (ctxt.DynlinkingGo() || *flagBindNow) {
1642		// For ELF targets, when producing dynamically linked Go code
1643		// or when immediate binding is explicitly requested,
1644		// we force all symbol resolution to be done at program startup
1645		// because lazy PLT resolution can use large amounts of stack at
1646		// times we cannot allow it to do so.
1647		argv = append(argv, "-Wl,-z,now")
1648	}
1649
1650	if ctxt.IsELF && ctxt.DynlinkingGo() {
1651		// Do not let the host linker generate COPY relocations. These
1652		// can move symbols out of sections that rely on stable offsets
1653		// from the beginning of the section (like sym.STYPE).
1654		argv = append(argv, "-Wl,-z,nocopyreloc")
1655
1656		if buildcfg.GOOS == "android" {
1657			// Use lld to avoid errors from default linker (issue #38838)
1658			altLinker = "lld"
1659		}
1660
1661		if ctxt.Arch.InFamily(sys.ARM64) && buildcfg.GOOS == "linux" {
1662			// On ARM64, the GNU linker will fail with
1663			// -znocopyreloc if it thinks a COPY relocation is
1664			// required. Switch to gold.
1665			// https://sourceware.org/bugzilla/show_bug.cgi?id=19962
1666			// https://go.dev/issue/22040
1667			altLinker = "gold"
1668
1669			// If gold is not installed, gcc will silently switch
1670			// back to ld.bfd. So we parse the version information
1671			// and provide a useful error if gold is missing.
1672			name, args := flagExtld[0], flagExtld[1:]
1673			args = append(args, "-fuse-ld=gold", "-Wl,--version")
1674			cmd := exec.Command(name, args...)
1675			if out, err := cmd.CombinedOutput(); err == nil {
1676				if !bytes.Contains(out, []byte("GNU gold")) {
1677					log.Fatalf("ARM64 external linker must be gold (issue #15696, 22040), but is not: %s", out)
1678				}
1679			}
1680		}
1681	}
1682	if ctxt.Arch.Family == sys.ARM64 && buildcfg.GOOS == "freebsd" {
1683		// Switch to ld.bfd on freebsd/arm64.
1684		altLinker = "bfd"
1685
1686		// Provide a useful error if ld.bfd is missing.
1687		name, args := flagExtld[0], flagExtld[1:]
1688		args = append(args, "-fuse-ld=bfd", "-Wl,--version")
1689		cmd := exec.Command(name, args...)
1690		if out, err := cmd.CombinedOutput(); err == nil {
1691			if !bytes.Contains(out, []byte("GNU ld")) {
1692				log.Fatalf("ARM64 external linker must be ld.bfd (issue #35197), please install devel/binutils")
1693			}
1694		}
1695	}
1696	if altLinker != "" {
1697		argv = append(argv, "-fuse-ld="+altLinker)
1698	}
1699
1700	if ctxt.IsELF && len(buildinfo) > 0 {
1701		argv = append(argv, fmt.Sprintf("-Wl,--build-id=0x%x", buildinfo))
1702	}
1703
1704	// On Windows, given -o foo, GCC will append ".exe" to produce
1705	// "foo.exe".  We have decided that we want to honor the -o
1706	// option. To make this work, we append a '.' so that GCC
1707	// will decide that the file already has an extension. We
1708	// only want to do this when producing a Windows output file
1709	// on a Windows host.
1710	outopt := *flagOutfile
1711	if buildcfg.GOOS == "windows" && runtime.GOOS == "windows" && filepath.Ext(outopt) == "" {
1712		outopt += "."
1713	}
1714	argv = append(argv, "-o")
1715	argv = append(argv, outopt)
1716
1717	if rpath.val != "" {
1718		argv = append(argv, fmt.Sprintf("-Wl,-rpath,%s", rpath.val))
1719	}
1720
1721	if *flagInterpreter != "" {
1722		// Many linkers support both -I and the --dynamic-linker flags
1723		// to set the ELF interpreter, but lld only supports
1724		// --dynamic-linker so prefer that (ld on very old Solaris only
1725		// supports -I but that seems less important).
1726		argv = append(argv, fmt.Sprintf("-Wl,--dynamic-linker,%s", *flagInterpreter))
1727	}
1728
1729	// Force global symbols to be exported for dlopen, etc.
1730	if ctxt.IsELF {
1731		if ctxt.DynlinkingGo() || ctxt.BuildMode == BuildModeCShared || !linkerFlagSupported(ctxt.Arch, argv[0], altLinker, "-Wl,--export-dynamic-symbol=main") {
1732			argv = append(argv, "-rdynamic")
1733		} else {
1734			var exports []string
1735			ctxt.loader.ForAllCgoExportDynamic(func(s loader.Sym) {
1736				exports = append(exports, "-Wl,--export-dynamic-symbol="+ctxt.loader.SymExtname(s))
1737			})
1738			sort.Strings(exports)
1739			argv = append(argv, exports...)
1740		}
1741	}
1742	if ctxt.HeadType == objabi.Haix {
1743		fileName := xcoffCreateExportFile(ctxt)
1744		argv = append(argv, "-Wl,-bE:"+fileName)
1745	}
1746
1747	const unusedArguments = "-Qunused-arguments"
1748	if linkerFlagSupported(ctxt.Arch, argv[0], altLinker, unusedArguments) {
1749		argv = append(argv, unusedArguments)
1750	}
1751
1752	if ctxt.IsWindows() {
1753		// Suppress generation of the PE file header timestamp,
1754		// so as to avoid spurious build ID differences between
1755		// linked binaries that are otherwise identical other than
1756		// the date/time they were linked.
1757		const noTimeStamp = "-Wl,--no-insert-timestamp"
1758		if linkerFlagSupported(ctxt.Arch, argv[0], altLinker, noTimeStamp) {
1759			argv = append(argv, noTimeStamp)
1760		}
1761	}
1762
1763	const compressDWARF = "-Wl,--compress-debug-sections=zlib"
1764	if ctxt.compressDWARF && linkerFlagSupported(ctxt.Arch, argv[0], altLinker, compressDWARF) {
1765		argv = append(argv, compressDWARF)
1766	}
1767
1768	hostObjCopyPaths := ctxt.hostobjCopy()
1769	cleanTimeStamps(hostObjCopyPaths)
1770	godotopath := filepath.Join(*flagTmpdir, "go.o")
1771	cleanTimeStamps([]string{godotopath})
1772
1773	argv = append(argv, godotopath)
1774	argv = append(argv, hostObjCopyPaths...)
1775	if ctxt.HeadType == objabi.Haix {
1776		// We want to have C files after Go files to remove
1777		// trampolines csects made by ld.
1778		argv = append(argv, "-nostartfiles")
1779		argv = append(argv, "/lib/crt0_64.o")
1780
1781		extld := ctxt.extld()
1782		name, args := extld[0], extld[1:]
1783		// Get starting files.
1784		getPathFile := func(file string) string {
1785			args := append(args, "-maix64", "--print-file-name="+file)
1786			out, err := exec.Command(name, args...).CombinedOutput()
1787			if err != nil {
1788				log.Fatalf("running %s failed: %v\n%s", extld, err, out)
1789			}
1790			return strings.Trim(string(out), "\n")
1791		}
1792		// Since GCC version 11, the 64-bit version of GCC starting files
1793		// are now suffixed by "_64". Even under "-maix64" multilib directory
1794		// "crtcxa.o" is 32-bit.
1795		crtcxa := getPathFile("crtcxa_64.o")
1796		if !filepath.IsAbs(crtcxa) {
1797			crtcxa = getPathFile("crtcxa.o")
1798		}
1799		crtdbase := getPathFile("crtdbase_64.o")
1800		if !filepath.IsAbs(crtdbase) {
1801			crtdbase = getPathFile("crtdbase.o")
1802		}
1803		argv = append(argv, crtcxa)
1804		argv = append(argv, crtdbase)
1805	}
1806
1807	if ctxt.linkShared {
1808		seenDirs := make(map[string]bool)
1809		seenLibs := make(map[string]bool)
1810		addshlib := func(path string) {
1811			dir, base := filepath.Split(path)
1812			if !seenDirs[dir] {
1813				argv = append(argv, "-L"+dir)
1814				if !rpath.set {
1815					argv = append(argv, "-Wl,-rpath="+dir)
1816				}
1817				seenDirs[dir] = true
1818			}
1819			base = strings.TrimSuffix(base, ".so")
1820			base = strings.TrimPrefix(base, "lib")
1821			if !seenLibs[base] {
1822				argv = append(argv, "-l"+base)
1823				seenLibs[base] = true
1824			}
1825		}
1826		for _, shlib := range ctxt.Shlibs {
1827			addshlib(shlib.Path)
1828			for _, dep := range shlib.Deps {
1829				if dep == "" {
1830					continue
1831				}
1832				libpath := findshlib(ctxt, dep)
1833				if libpath != "" {
1834					addshlib(libpath)
1835				}
1836			}
1837		}
1838	}
1839
1840	// clang, unlike GCC, passes -rdynamic to the linker
1841	// even when linking with -static, causing a linker
1842	// error when using GNU ld. So take out -rdynamic if
1843	// we added it. We do it in this order, rather than
1844	// only adding -rdynamic later, so that -extldflags
1845	// can override -rdynamic without using -static.
1846	// Similarly for -Wl,--dynamic-linker.
1847	checkStatic := func(arg string) {
1848		if ctxt.IsELF && arg == "-static" {
1849			for i := range argv {
1850				if argv[i] == "-rdynamic" || strings.HasPrefix(argv[i], "-Wl,--dynamic-linker,") {
1851					argv[i] = "-static"
1852				}
1853			}
1854		}
1855	}
1856
1857	for _, p := range ldflag {
1858		argv = append(argv, p)
1859		checkStatic(p)
1860	}
1861
1862	// When building a program with the default -buildmode=exe the
1863	// gc compiler generates code requires DT_TEXTREL in a
1864	// position independent executable (PIE). On systems where the
1865	// toolchain creates PIEs by default, and where DT_TEXTREL
1866	// does not work, the resulting programs will not run. See
1867	// issue #17847. To avoid this problem pass -no-pie to the
1868	// toolchain if it is supported.
1869	if ctxt.BuildMode == BuildModeExe && !ctxt.linkShared && !(ctxt.IsDarwin() && ctxt.IsARM64()) {
1870		// GCC uses -no-pie, clang uses -nopie.
1871		for _, nopie := range []string{"-no-pie", "-nopie"} {
1872			if linkerFlagSupported(ctxt.Arch, argv[0], altLinker, nopie) {
1873				argv = append(argv, nopie)
1874				break
1875			}
1876		}
1877	}
1878
1879	for _, p := range flagExtldflags {
1880		argv = append(argv, p)
1881		checkStatic(p)
1882	}
1883	if ctxt.HeadType == objabi.Hwindows {
1884		// Determine which linker we're using. Add in the extldflags in
1885		// case used has specified "-fuse-ld=...".
1886		extld := ctxt.extld()
1887		name, args := extld[0], extld[1:]
1888		args = append(args, trimLinkerArgv(flagExtldflags)...)
1889		args = append(args, "-Wl,--version")
1890		cmd := exec.Command(name, args...)
1891		usingLLD := false
1892		if out, err := cmd.CombinedOutput(); err == nil {
1893			if bytes.Contains(out, []byte("LLD ")) {
1894				usingLLD = true
1895			}
1896		}
1897
1898		// use gcc linker script to work around gcc bug
1899		// (see https://golang.org/issue/20183 for details).
1900		if !usingLLD {
1901			p := writeGDBLinkerScript()
1902			argv = append(argv, "-Wl,-T,"+p)
1903		}
1904		if *flagRace {
1905			if p := ctxt.findLibPath("libsynchronization.a"); p != "libsynchronization.a" {
1906				argv = append(argv, "-lsynchronization")
1907			}
1908		}
1909		// libmingw32 and libmingwex have some inter-dependencies,
1910		// so must use linker groups.
1911		argv = append(argv, "-Wl,--start-group", "-lmingwex", "-lmingw32", "-Wl,--end-group")
1912		argv = append(argv, peimporteddlls()...)
1913	}
1914
1915	argv = ctxt.passLongArgsInResponseFile(argv, altLinker)
1916
1917	if ctxt.Debugvlog != 0 {
1918		ctxt.Logf("host link:")
1919		for _, v := range argv {
1920			ctxt.Logf(" %q", v)
1921		}
1922		ctxt.Logf("\n")
1923	}
1924
1925	cmd := exec.Command(argv[0], argv[1:]...)
1926	out, err := cmd.CombinedOutput()
1927	if err != nil {
1928		Exitf("running %s failed: %v\n%s\n%s", argv[0], err, cmd, out)
1929	}
1930
1931	// Filter out useless linker warnings caused by bugs outside Go.
1932	// See also cmd/go/internal/work/exec.go's gccld method.
1933	var save [][]byte
1934	var skipLines int
1935	for _, line := range bytes.SplitAfter(out, []byte("\n")) {
1936		// golang.org/issue/26073 - Apple Xcode bug
1937		if bytes.Contains(line, []byte("ld: warning: text-based stub file")) {
1938			continue
1939		}
1940
1941		if skipLines > 0 {
1942			skipLines--
1943			continue
1944		}
1945
1946		// Remove TOC overflow warning on AIX.
1947		if bytes.Contains(line, []byte("ld: 0711-783")) {
1948			skipLines = 2
1949			continue
1950		}
1951
1952		save = append(save, line)
1953	}
1954	out = bytes.Join(save, nil)
1955
1956	if len(out) > 0 {
1957		// always print external output even if the command is successful, so that we don't
1958		// swallow linker warnings (see https://golang.org/issue/17935).
1959		if ctxt.IsDarwin() && ctxt.IsAMD64() {
1960			const noPieWarning = "ld: warning: -no_pie is deprecated when targeting new OS versions\n"
1961			if i := bytes.Index(out, []byte(noPieWarning)); i >= 0 {
1962				// swallow -no_pie deprecation warning, issue 54482
1963				out = append(out[:i], out[i+len(noPieWarning):]...)
1964			}
1965		}
1966		if ctxt.IsDarwin() {
1967			const bindAtLoadWarning = "ld: warning: -bind_at_load is deprecated on macOS\n"
1968			if i := bytes.Index(out, []byte(bindAtLoadWarning)); i >= 0 {
1969				// -bind_at_load is deprecated with ld-prime, but needed for
1970				// correctness with older versions of ld64. Swallow the warning.
1971				// TODO: maybe pass -bind_at_load conditionally based on C
1972				// linker version.
1973				out = append(out[:i], out[i+len(bindAtLoadWarning):]...)
1974			}
1975		}
1976		ctxt.Logf("%s", out)
1977	}
1978
1979	// Helper for updating a Macho binary in some way (shared between
1980	// dwarf combining and UUID update).
1981	updateMachoOutFile := func(op string, updateFunc machoUpdateFunc) {
1982		// For os.Rename to work reliably, must be in same directory as outfile.
1983		rewrittenOutput := *flagOutfile + "~"
1984		exef, err := os.Open(*flagOutfile)
1985		if err != nil {
1986			Exitf("%s: %s failed: %v", os.Args[0], op, err)
1987		}
1988		defer exef.Close()
1989		exem, err := macho.NewFile(exef)
1990		if err != nil {
1991			Exitf("%s: parsing Mach-O header failed: %v", os.Args[0], err)
1992		}
1993		if err := updateFunc(ctxt, exef, exem, rewrittenOutput); err != nil {
1994			Exitf("%s: %s failed: %v", os.Args[0], op, err)
1995		}
1996		os.Remove(*flagOutfile)
1997		if err := os.Rename(rewrittenOutput, *flagOutfile); err != nil {
1998			Exitf("%s: %v", os.Args[0], err)
1999		}
2000	}
2001
2002	uuidUpdated := false
2003	if combineDwarf {
2004		// Find "dsymutils" and "strip" tools using CC --print-prog-name.
2005		dsymutilCmd := ctxt.findExtLinkTool("dsymutil")
2006		stripCmd := ctxt.findExtLinkTool("strip")
2007
2008		dsym := filepath.Join(*flagTmpdir, "go.dwarf")
2009		cmd := exec.Command(dsymutilCmd, "-f", *flagOutfile, "-o", dsym)
2010		// dsymutil may not clean up its temp directory at exit.
2011		// Set DSYMUTIL_REPRODUCER_PATH to work around. see issue 59026.
2012		// dsymutil (Apple LLVM version 16.0.0) deletes the directory
2013		// even if it is not empty. We still need our tmpdir, so give a
2014		// subdirectory to dsymutil.
2015		dsymDir := filepath.Join(*flagTmpdir, "dsymutil")
2016		err := os.MkdirAll(dsymDir, 0777)
2017		if err != nil {
2018			Exitf("fail to create temp dir: %v", err)
2019		}
2020		cmd.Env = append(os.Environ(), "DSYMUTIL_REPRODUCER_PATH="+dsymDir)
2021		if ctxt.Debugvlog != 0 {
2022			ctxt.Logf("host link dsymutil:")
2023			for _, v := range cmd.Args {
2024				ctxt.Logf(" %q", v)
2025			}
2026			ctxt.Logf("\n")
2027		}
2028		if out, err := cmd.CombinedOutput(); err != nil {
2029			Exitf("%s: running dsymutil failed: %v\n%s\n%s", os.Args[0], err, cmd, out)
2030		}
2031		// Remove STAB (symbolic debugging) symbols after we are done with them (by dsymutil).
2032		// They contain temporary file paths and make the build not reproducible.
2033		var stripArgs = []string{"-S"}
2034		if debug_s {
2035			// We are generating a binary with symbol table suppressed.
2036			// Suppress local symbols. We need to keep dynamically exported
2037			// and referenced symbols so the dynamic linker can resolve them.
2038			stripArgs = append(stripArgs, "-x")
2039		}
2040		stripArgs = append(stripArgs, *flagOutfile)
2041		if ctxt.Debugvlog != 0 {
2042			ctxt.Logf("host link strip: %q", stripCmd)
2043			for _, v := range stripArgs {
2044				ctxt.Logf(" %q", v)
2045			}
2046			ctxt.Logf("\n")
2047		}
2048		cmd = exec.Command(stripCmd, stripArgs...)
2049		if out, err := cmd.CombinedOutput(); err != nil {
2050			Exitf("%s: running strip failed: %v\n%s\n%s", os.Args[0], err, cmd, out)
2051		}
2052		// Skip combining if `dsymutil` didn't generate a file. See #11994.
2053		if _, err := os.Stat(dsym); err == nil {
2054			updateMachoOutFile("combining dwarf",
2055				func(ctxt *Link, exef *os.File, exem *macho.File, outexe string) error {
2056					return machoCombineDwarf(ctxt, exef, exem, dsym, outexe)
2057				})
2058			uuidUpdated = true
2059		}
2060	}
2061	if ctxt.IsDarwin() && !uuidUpdated && *flagBuildid != "" {
2062		updateMachoOutFile("rewriting uuid",
2063			func(ctxt *Link, exef *os.File, exem *macho.File, outexe string) error {
2064				return machoRewriteUuid(ctxt, exef, exem, outexe)
2065			})
2066	}
2067	if ctxt.NeedCodeSign() {
2068		err := machoCodeSign(ctxt, *flagOutfile)
2069		if err != nil {
2070			Exitf("%s: code signing failed: %v", os.Args[0], err)
2071		}
2072	}
2073}
2074
2075// passLongArgsInResponseFile writes the arguments into a file if they
2076// are very long.
2077func (ctxt *Link) passLongArgsInResponseFile(argv []string, altLinker string) []string {
2078	c := 0
2079	for _, arg := range argv {
2080		c += len(arg)
2081	}
2082
2083	if c < sys.ExecArgLengthLimit {
2084		return argv
2085	}
2086
2087	// Only use response files if they are supported.
2088	response := filepath.Join(*flagTmpdir, "response")
2089	if err := os.WriteFile(response, nil, 0644); err != nil {
2090		log.Fatalf("failed while testing response file: %v", err)
2091	}
2092	if !linkerFlagSupported(ctxt.Arch, argv[0], altLinker, "@"+response) {
2093		if ctxt.Debugvlog != 0 {
2094			ctxt.Logf("not using response file because linker does not support one")
2095		}
2096		return argv
2097	}
2098
2099	var buf bytes.Buffer
2100	for _, arg := range argv[1:] {
2101		// The external linker response file supports quoted strings.
2102		fmt.Fprintf(&buf, "%q\n", arg)
2103	}
2104	if err := os.WriteFile(response, buf.Bytes(), 0644); err != nil {
2105		log.Fatalf("failed while writing response file: %v", err)
2106	}
2107	if ctxt.Debugvlog != 0 {
2108		ctxt.Logf("response file %s contents:\n%s", response, buf.Bytes())
2109	}
2110	return []string{
2111		argv[0],
2112		"@" + response,
2113	}
2114}
2115
2116var createTrivialCOnce sync.Once
2117
2118func linkerFlagSupported(arch *sys.Arch, linker, altLinker, flag string) bool {
2119	createTrivialCOnce.Do(func() {
2120		src := filepath.Join(*flagTmpdir, "trivial.c")
2121		if err := os.WriteFile(src, []byte("int main() { return 0; }"), 0666); err != nil {
2122			Errorf(nil, "WriteFile trivial.c failed: %v", err)
2123		}
2124	})
2125
2126	flags := hostlinkArchArgs(arch)
2127
2128	moreFlags := trimLinkerArgv(append(flagExtldflags, ldflag...))
2129	flags = append(flags, moreFlags...)
2130
2131	if altLinker != "" {
2132		flags = append(flags, "-fuse-ld="+altLinker)
2133	}
2134	trivialPath := filepath.Join(*flagTmpdir, "trivial.c")
2135	outPath := filepath.Join(*flagTmpdir, "a.out")
2136	flags = append(flags, "-o", outPath, flag, trivialPath)
2137
2138	cmd := exec.Command(linker, flags...)
2139	cmd.Env = append([]string{"LC_ALL=C"}, os.Environ()...)
2140	out, err := cmd.CombinedOutput()
2141	// GCC says "unrecognized command line option ‘-no-pie’"
2142	// clang says "unknown argument: '-no-pie'"
2143	return err == nil && !bytes.Contains(out, []byte("unrecognized")) && !bytes.Contains(out, []byte("unknown"))
2144}
2145
2146// trimLinkerArgv returns a new copy of argv that does not include flags
2147// that are not relevant for testing whether some linker option works.
2148func trimLinkerArgv(argv []string) []string {
2149	flagsWithNextArgSkip := []string{
2150		"-F",
2151		"-l",
2152		"-L",
2153		"-framework",
2154		"-Wl,-framework",
2155		"-Wl,-rpath",
2156		"-Wl,-undefined",
2157	}
2158	flagsWithNextArgKeep := []string{
2159		"-arch",
2160		"-isysroot",
2161		"--sysroot",
2162		"-target",
2163	}
2164	prefixesToKeep := []string{
2165		"-f",
2166		"-m",
2167		"-p",
2168		"-Wl,",
2169		"-arch",
2170		"-isysroot",
2171		"--sysroot",
2172		"-target",
2173	}
2174
2175	var flags []string
2176	keep := false
2177	skip := false
2178	for _, f := range argv {
2179		if keep {
2180			flags = append(flags, f)
2181			keep = false
2182		} else if skip {
2183			skip = false
2184		} else if f == "" || f[0] != '-' {
2185		} else if contains(flagsWithNextArgSkip, f) {
2186			skip = true
2187		} else if contains(flagsWithNextArgKeep, f) {
2188			flags = append(flags, f)
2189			keep = true
2190		} else {
2191			for _, p := range prefixesToKeep {
2192				if strings.HasPrefix(f, p) {
2193					flags = append(flags, f)
2194					break
2195				}
2196			}
2197		}
2198	}
2199	return flags
2200}
2201
2202// hostlinkArchArgs returns arguments to pass to the external linker
2203// based on the architecture.
2204func hostlinkArchArgs(arch *sys.Arch) []string {
2205	switch arch.Family {
2206	case sys.I386:
2207		return []string{"-m32"}
2208	case sys.AMD64:
2209		if buildcfg.GOOS == "darwin" {
2210			return []string{"-arch", "x86_64", "-m64"}
2211		}
2212		return []string{"-m64"}
2213	case sys.S390X:
2214		return []string{"-m64"}
2215	case sys.ARM:
2216		return []string{"-marm"}
2217	case sys.ARM64:
2218		if buildcfg.GOOS == "darwin" {
2219			return []string{"-arch", "arm64"}
2220		}
2221	case sys.Loong64:
2222		return []string{"-mabi=lp64d"}
2223	case sys.MIPS64:
2224		return []string{"-mabi=64"}
2225	case sys.MIPS:
2226		return []string{"-mabi=32"}
2227	case sys.PPC64:
2228		if buildcfg.GOOS == "aix" {
2229			return []string{"-maix64"}
2230		} else {
2231			return []string{"-m64"}
2232		}
2233
2234	}
2235	return nil
2236}
2237
2238var wantHdr = objabi.HeaderString()
2239
2240// ldobj loads an input object. If it is a host object (an object
2241// compiled by a non-Go compiler) it returns the Hostobj pointer. If
2242// it is a Go object, it returns nil.
2243func ldobj(ctxt *Link, f *bio.Reader, lib *sym.Library, length int64, pn string, file string) *Hostobj {
2244	pkg := objabi.PathToPrefix(lib.Pkg)
2245
2246	eof := f.Offset() + length
2247	start := f.Offset()
2248	c1 := bgetc(f)
2249	c2 := bgetc(f)
2250	c3 := bgetc(f)
2251	c4 := bgetc(f)
2252	f.MustSeek(start, 0)
2253
2254	unit := &sym.CompilationUnit{Lib: lib}
2255	lib.Units = append(lib.Units, unit)
2256
2257	magic := uint32(c1)<<24 | uint32(c2)<<16 | uint32(c3)<<8 | uint32(c4)
2258	if magic == 0x7f454c46 { // \x7F E L F
2259		ldelf := func(ctxt *Link, f *bio.Reader, pkg string, length int64, pn string) {
2260			textp, flags, err := loadelf.Load(ctxt.loader, ctxt.Arch, ctxt.IncVersion(), f, pkg, length, pn, ehdr.Flags)
2261			if err != nil {
2262				Errorf(nil, "%v", err)
2263				return
2264			}
2265			ehdr.Flags = flags
2266			ctxt.Textp = append(ctxt.Textp, textp...)
2267		}
2268		return ldhostobj(ldelf, ctxt.HeadType, f, pkg, length, pn, file)
2269	}
2270
2271	if magic&^1 == 0xfeedface || magic&^0x01000000 == 0xcefaedfe {
2272		ldmacho := func(ctxt *Link, f *bio.Reader, pkg string, length int64, pn string) {
2273			textp, err := loadmacho.Load(ctxt.loader, ctxt.Arch, ctxt.IncVersion(), f, pkg, length, pn)
2274			if err != nil {
2275				Errorf(nil, "%v", err)
2276				return
2277			}
2278			ctxt.Textp = append(ctxt.Textp, textp...)
2279		}
2280		return ldhostobj(ldmacho, ctxt.HeadType, f, pkg, length, pn, file)
2281	}
2282
2283	switch c1<<8 | c2 {
2284	case 0x4c01, // 386
2285		0x6486, // amd64
2286		0xc401, // arm
2287		0x64aa: // arm64
2288		ldpe := func(ctxt *Link, f *bio.Reader, pkg string, length int64, pn string) {
2289			ls, err := loadpe.Load(ctxt.loader, ctxt.Arch, ctxt.IncVersion(), f, pkg, length, pn)
2290			if err != nil {
2291				Errorf(nil, "%v", err)
2292				return
2293			}
2294			if len(ls.Resources) != 0 {
2295				setpersrc(ctxt, ls.Resources)
2296			}
2297			if ls.PData != 0 {
2298				sehp.pdata = append(sehp.pdata, ls.PData)
2299			}
2300			if ls.XData != 0 {
2301				sehp.xdata = append(sehp.xdata, ls.XData)
2302			}
2303			ctxt.Textp = append(ctxt.Textp, ls.Textp...)
2304		}
2305		return ldhostobj(ldpe, ctxt.HeadType, f, pkg, length, pn, file)
2306	}
2307
2308	if c1 == 0x01 && (c2 == 0xD7 || c2 == 0xF7) {
2309		ldxcoff := func(ctxt *Link, f *bio.Reader, pkg string, length int64, pn string) {
2310			textp, err := loadxcoff.Load(ctxt.loader, ctxt.Arch, ctxt.IncVersion(), f, pkg, length, pn)
2311			if err != nil {
2312				Errorf(nil, "%v", err)
2313				return
2314			}
2315			ctxt.Textp = append(ctxt.Textp, textp...)
2316		}
2317		return ldhostobj(ldxcoff, ctxt.HeadType, f, pkg, length, pn, file)
2318	}
2319
2320	if c1 != 'g' || c2 != 'o' || c3 != ' ' || c4 != 'o' {
2321		// An unrecognized object is just passed to the external linker.
2322		// If we try to read symbols from this object, we will
2323		// report an error at that time.
2324		unknownObjFormat = true
2325		return ldhostobj(nil, ctxt.HeadType, f, pkg, length, pn, file)
2326	}
2327
2328	/* check the header */
2329	line, err := f.ReadString('\n')
2330	if err != nil {
2331		Errorf(nil, "truncated object file: %s: %v", pn, err)
2332		return nil
2333	}
2334
2335	if !strings.HasPrefix(line, "go object ") {
2336		if strings.HasSuffix(pn, ".go") {
2337			Exitf("%s: uncompiled .go source file", pn)
2338			return nil
2339		}
2340
2341		if line == ctxt.Arch.Name {
2342			// old header format: just $GOOS
2343			Errorf(nil, "%s: stale object file", pn)
2344			return nil
2345		}
2346
2347		Errorf(nil, "%s: not an object file: @%d %q", pn, start, line)
2348		return nil
2349	}
2350
2351	// First, check that the basic GOOS, GOARCH, and Version match.
2352	if line != wantHdr {
2353		Errorf(nil, "%s: linked object header mismatch:\nhave %q\nwant %q\n", pn, line, wantHdr)
2354	}
2355
2356	// Skip over exports and other info -- ends with \n!\n.
2357	//
2358	// Note: It's possible for "\n!\n" to appear within the binary
2359	// package export data format. To avoid truncating the package
2360	// definition prematurely (issue 21703), we keep track of
2361	// how many "$$" delimiters we've seen.
2362
2363	import0 := f.Offset()
2364
2365	c1 = '\n' // the last line ended in \n
2366	c2 = bgetc(f)
2367	c3 = bgetc(f)
2368	markers := 0
2369	for {
2370		if c1 == '\n' {
2371			if markers%2 == 0 && c2 == '!' && c3 == '\n' {
2372				break
2373			}
2374			if c2 == '$' && c3 == '$' {
2375				markers++
2376			}
2377		}
2378
2379		c1 = c2
2380		c2 = c3
2381		c3 = bgetc(f)
2382		if c3 == -1 {
2383			Errorf(nil, "truncated object file: %s", pn)
2384			return nil
2385		}
2386	}
2387
2388	import1 := f.Offset()
2389
2390	f.MustSeek(import0, 0)
2391	ldpkg(ctxt, f, lib, import1-import0-2, pn) // -2 for !\n
2392	f.MustSeek(import1, 0)
2393
2394	fingerprint := ctxt.loader.Preload(ctxt.IncVersion(), f, lib, unit, eof-f.Offset())
2395	if !fingerprint.IsZero() { // Assembly objects don't have fingerprints. Ignore them.
2396		// Check fingerprint, to ensure the importing and imported packages
2397		// have consistent view of symbol indices.
2398		// Normally the go command should ensure this. But in case something
2399		// goes wrong, it could lead to obscure bugs like run-time crash.
2400		// Check it here to be sure.
2401		if lib.Fingerprint.IsZero() { // Not yet imported. Update its fingerprint.
2402			lib.Fingerprint = fingerprint
2403		}
2404		checkFingerprint(lib, fingerprint, lib.Srcref, lib.Fingerprint)
2405	}
2406
2407	addImports(ctxt, lib, pn)
2408	return nil
2409}
2410
2411// symbolsAreUnresolved scans through the loader's list of unresolved
2412// symbols and checks to see whether any of them match the names of the
2413// symbols in 'want'. Return value is a list of bools, with list[K] set
2414// to true if there is an unresolved reference to the symbol in want[K].
2415func symbolsAreUnresolved(ctxt *Link, want []string) []bool {
2416	returnAllUndefs := -1
2417	undefs, _ := ctxt.loader.UndefinedRelocTargets(returnAllUndefs)
2418	seen := make(map[loader.Sym]struct{})
2419	rval := make([]bool, len(want))
2420	wantm := make(map[string]int)
2421	for k, w := range want {
2422		wantm[w] = k
2423	}
2424	count := 0
2425	for _, s := range undefs {
2426		if _, ok := seen[s]; ok {
2427			continue
2428		}
2429		seen[s] = struct{}{}
2430		if k, ok := wantm[ctxt.loader.SymName(s)]; ok {
2431			rval[k] = true
2432			count++
2433			if count == len(want) {
2434				return rval
2435			}
2436		}
2437	}
2438	return rval
2439}
2440
2441// hostObject reads a single host object file (compare to "hostArchive").
2442// This is used as part of internal linking when we need to pull in
2443// files such as "crt?.o".
2444func hostObject(ctxt *Link, objname string, path string) {
2445	if ctxt.Debugvlog > 1 {
2446		ctxt.Logf("hostObject(%s)\n", path)
2447	}
2448	objlib := sym.Library{
2449		Pkg: objname,
2450	}
2451	f, err := bio.Open(path)
2452	if err != nil {
2453		Exitf("cannot open host object %q file %s: %v", objname, path, err)
2454	}
2455	defer f.Close()
2456	h := ldobj(ctxt, f, &objlib, 0, path, path)
2457	if h.ld == nil {
2458		Exitf("unrecognized object file format in %s", path)
2459	}
2460	h.file = path
2461	h.length = f.MustSeek(0, 2)
2462	f.MustSeek(h.off, 0)
2463	h.ld(ctxt, f, h.pkg, h.length, h.pn)
2464	if *flagCaptureHostObjs != "" {
2465		captureHostObj(h)
2466	}
2467}
2468
2469func checkFingerprint(lib *sym.Library, libfp goobj.FingerprintType, src string, srcfp goobj.FingerprintType) {
2470	if libfp != srcfp {
2471		Exitf("fingerprint mismatch: %s has %x, import from %s expecting %x", lib, libfp, src, srcfp)
2472	}
2473}
2474
2475func readelfsymboldata(ctxt *Link, f *elf.File, sym *elf.Symbol) []byte {
2476	data := make([]byte, sym.Size)
2477	sect := f.Sections[sym.Section]
2478	if sect.Type != elf.SHT_PROGBITS && sect.Type != elf.SHT_NOTE {
2479		Errorf(nil, "reading %s from non-data section", sym.Name)
2480	}
2481	n, err := sect.ReadAt(data, int64(sym.Value-sect.Addr))
2482	if uint64(n) != sym.Size {
2483		Errorf(nil, "reading contents of %s: %v", sym.Name, err)
2484	}
2485	return data
2486}
2487
2488func readwithpad(r io.Reader, sz int32) ([]byte, error) {
2489	data := make([]byte, Rnd(int64(sz), 4))
2490	_, err := io.ReadFull(r, data)
2491	if err != nil {
2492		return nil, err
2493	}
2494	data = data[:sz]
2495	return data, nil
2496}
2497
2498func readnote(f *elf.File, name []byte, typ int32) ([]byte, error) {
2499	for _, sect := range f.Sections {
2500		if sect.Type != elf.SHT_NOTE {
2501			continue
2502		}
2503		r := sect.Open()
2504		for {
2505			var namesize, descsize, noteType int32
2506			err := binary.Read(r, f.ByteOrder, &namesize)
2507			if err != nil {
2508				if err == io.EOF {
2509					break
2510				}
2511				return nil, fmt.Errorf("read namesize failed: %v", err)
2512			}
2513			err = binary.Read(r, f.ByteOrder, &descsize)
2514			if err != nil {
2515				return nil, fmt.Errorf("read descsize failed: %v", err)
2516			}
2517			err = binary.Read(r, f.ByteOrder, &noteType)
2518			if err != nil {
2519				return nil, fmt.Errorf("read type failed: %v", err)
2520			}
2521			noteName, err := readwithpad(r, namesize)
2522			if err != nil {
2523				return nil, fmt.Errorf("read name failed: %v", err)
2524			}
2525			desc, err := readwithpad(r, descsize)
2526			if err != nil {
2527				return nil, fmt.Errorf("read desc failed: %v", err)
2528			}
2529			if string(name) == string(noteName) && typ == noteType {
2530				return desc, nil
2531			}
2532		}
2533	}
2534	return nil, nil
2535}
2536
2537func findshlib(ctxt *Link, shlib string) string {
2538	if filepath.IsAbs(shlib) {
2539		return shlib
2540	}
2541	for _, libdir := range ctxt.Libdir {
2542		libpath := filepath.Join(libdir, shlib)
2543		if _, err := os.Stat(libpath); err == nil {
2544			return libpath
2545		}
2546	}
2547	Errorf(nil, "cannot find shared library: %s", shlib)
2548	return ""
2549}
2550
2551func ldshlibsyms(ctxt *Link, shlib string) {
2552	var libpath string
2553	if filepath.IsAbs(shlib) {
2554		libpath = shlib
2555		shlib = filepath.Base(shlib)
2556	} else {
2557		libpath = findshlib(ctxt, shlib)
2558		if libpath == "" {
2559			return
2560		}
2561	}
2562	for _, processedlib := range ctxt.Shlibs {
2563		if processedlib.Path == libpath {
2564			return
2565		}
2566	}
2567	if ctxt.Debugvlog > 1 {
2568		ctxt.Logf("ldshlibsyms: found library with name %s at %s\n", shlib, libpath)
2569	}
2570
2571	f, err := elf.Open(libpath)
2572	if err != nil {
2573		Errorf(nil, "cannot open shared library: %s", libpath)
2574		return
2575	}
2576	// Keep the file open as decodetypeGcprog needs to read from it.
2577	// TODO: fix. Maybe mmap the file.
2578	//defer f.Close()
2579
2580	hash, err := readnote(f, ELF_NOTE_GO_NAME, ELF_NOTE_GOABIHASH_TAG)
2581	if err != nil {
2582		Errorf(nil, "cannot read ABI hash from shared library %s: %v", libpath, err)
2583		return
2584	}
2585
2586	depsbytes, err := readnote(f, ELF_NOTE_GO_NAME, ELF_NOTE_GODEPS_TAG)
2587	if err != nil {
2588		Errorf(nil, "cannot read dep list from shared library %s: %v", libpath, err)
2589		return
2590	}
2591	var deps []string
2592	for _, dep := range strings.Split(string(depsbytes), "\n") {
2593		if dep == "" {
2594			continue
2595		}
2596		if !filepath.IsAbs(dep) {
2597			// If the dep can be interpreted as a path relative to the shlib
2598			// in which it was found, do that. Otherwise, we will leave it
2599			// to be resolved by libdir lookup.
2600			abs := filepath.Join(filepath.Dir(libpath), dep)
2601			if _, err := os.Stat(abs); err == nil {
2602				dep = abs
2603			}
2604		}
2605		deps = append(deps, dep)
2606	}
2607
2608	syms, err := f.DynamicSymbols()
2609	if err != nil {
2610		Errorf(nil, "cannot read symbols from shared library: %s", libpath)
2611		return
2612	}
2613
2614	for _, elfsym := range syms {
2615		if elf.ST_TYPE(elfsym.Info) == elf.STT_NOTYPE || elf.ST_TYPE(elfsym.Info) == elf.STT_SECTION {
2616			continue
2617		}
2618
2619		// Symbols whose names start with "type:" are compiler generated,
2620		// so make functions with that prefix internal.
2621		ver := 0
2622		symname := elfsym.Name // (unmangled) symbol name
2623		if elf.ST_TYPE(elfsym.Info) == elf.STT_FUNC && strings.HasPrefix(elfsym.Name, "type:") {
2624			ver = abiInternalVer
2625		} else if buildcfg.Experiment.RegabiWrappers && elf.ST_TYPE(elfsym.Info) == elf.STT_FUNC {
2626			// Demangle the ABI name. Keep in sync with symtab.go:mangleABIName.
2627			if strings.HasSuffix(elfsym.Name, ".abiinternal") {
2628				ver = sym.SymVerABIInternal
2629				symname = strings.TrimSuffix(elfsym.Name, ".abiinternal")
2630			} else if strings.HasSuffix(elfsym.Name, ".abi0") {
2631				ver = 0
2632				symname = strings.TrimSuffix(elfsym.Name, ".abi0")
2633			}
2634		}
2635
2636		l := ctxt.loader
2637		s := l.LookupOrCreateSym(symname, ver)
2638
2639		// Because loadlib above loads all .a files before loading
2640		// any shared libraries, any non-dynimport symbols we find
2641		// that duplicate symbols already loaded should be ignored
2642		// (the symbols from the .a files "win").
2643		if l.SymType(s) != 0 && l.SymType(s) != sym.SDYNIMPORT {
2644			continue
2645		}
2646		su := l.MakeSymbolUpdater(s)
2647		su.SetType(sym.SDYNIMPORT)
2648		l.SetSymElfType(s, elf.ST_TYPE(elfsym.Info))
2649		su.SetSize(int64(elfsym.Size))
2650		if elfsym.Section != elf.SHN_UNDEF {
2651			// Set .File for the library that actually defines the symbol.
2652			l.SetSymPkg(s, libpath)
2653
2654			// The decodetype_* functions in decodetype.go need access to
2655			// the type data.
2656			sname := l.SymName(s)
2657			if strings.HasPrefix(sname, "type:") && !strings.HasPrefix(sname, "type:.") {
2658				su.SetData(readelfsymboldata(ctxt, f, &elfsym))
2659			}
2660		}
2661
2662		if symname != elfsym.Name {
2663			l.SetSymExtname(s, elfsym.Name)
2664		}
2665	}
2666	ctxt.Shlibs = append(ctxt.Shlibs, Shlib{Path: libpath, Hash: hash, Deps: deps, File: f})
2667}
2668
2669func addsection(ldr *loader.Loader, arch *sys.Arch, seg *sym.Segment, name string, rwx int) *sym.Section {
2670	sect := ldr.NewSection()
2671	sect.Rwx = uint8(rwx)
2672	sect.Name = name
2673	sect.Seg = seg
2674	sect.Align = int32(arch.PtrSize) // everything is at least pointer-aligned
2675	seg.Sections = append(seg.Sections, sect)
2676	return sect
2677}
2678
2679func usage() {
2680	fmt.Fprintf(os.Stderr, "usage: link [options] main.o\n")
2681	objabi.Flagprint(os.Stderr)
2682	Exit(2)
2683}
2684
2685type SymbolType int8 // TODO: after genasmsym is gone, maybe rename to plan9typeChar or something
2686
2687const (
2688	// see also https://9p.io/magic/man2html/1/nm
2689	TextSym      SymbolType = 'T'
2690	DataSym      SymbolType = 'D'
2691	BSSSym       SymbolType = 'B'
2692	UndefinedSym SymbolType = 'U'
2693	TLSSym       SymbolType = 't'
2694	FrameSym     SymbolType = 'm'
2695	ParamSym     SymbolType = 'p'
2696	AutoSym      SymbolType = 'a'
2697
2698	// Deleted auto (not a real sym, just placeholder for type)
2699	DeletedAutoSym = 'x'
2700)
2701
2702// defineInternal defines a symbol used internally by the go runtime.
2703func (ctxt *Link) defineInternal(p string, t sym.SymKind) loader.Sym {
2704	s := ctxt.loader.CreateSymForUpdate(p, 0)
2705	s.SetType(t)
2706	s.SetSpecial(true)
2707	s.SetLocal(true)
2708	return s.Sym()
2709}
2710
2711func (ctxt *Link) xdefine(p string, t sym.SymKind, v int64) loader.Sym {
2712	s := ctxt.defineInternal(p, t)
2713	ctxt.loader.SetSymValue(s, v)
2714	return s
2715}
2716
2717func datoff(ldr *loader.Loader, s loader.Sym, addr int64) int64 {
2718	if uint64(addr) >= Segdata.Vaddr {
2719		return int64(uint64(addr) - Segdata.Vaddr + Segdata.Fileoff)
2720	}
2721	if uint64(addr) >= Segtext.Vaddr {
2722		return int64(uint64(addr) - Segtext.Vaddr + Segtext.Fileoff)
2723	}
2724	ldr.Errorf(s, "invalid datoff %#x", addr)
2725	return 0
2726}
2727
2728func Entryvalue(ctxt *Link) int64 {
2729	a := *flagEntrySymbol
2730	if a[0] >= '0' && a[0] <= '9' {
2731		return atolwhex(a)
2732	}
2733	ldr := ctxt.loader
2734	s := ldr.Lookup(a, 0)
2735	if s == 0 {
2736		Errorf(nil, "missing entry symbol %q", a)
2737		return 0
2738	}
2739	st := ldr.SymType(s)
2740	if st == 0 {
2741		return *FlagTextAddr
2742	}
2743	if !ctxt.IsAIX() && st != sym.STEXT {
2744		ldr.Errorf(s, "entry not text")
2745	}
2746	return ldr.SymValue(s)
2747}
2748
2749func (ctxt *Link) callgraph() {
2750	if !*FlagC {
2751		return
2752	}
2753
2754	ldr := ctxt.loader
2755	for _, s := range ctxt.Textp {
2756		relocs := ldr.Relocs(s)
2757		for i := 0; i < relocs.Count(); i++ {
2758			r := relocs.At(i)
2759			rs := r.Sym()
2760			if rs == 0 {
2761				continue
2762			}
2763			if r.Type().IsDirectCall() && ldr.SymType(rs) == sym.STEXT {
2764				ctxt.Logf("%s calls %s\n", ldr.SymName(s), ldr.SymName(rs))
2765			}
2766		}
2767	}
2768}
2769
2770func Rnd(v int64, r int64) int64 {
2771	if r <= 0 {
2772		return v
2773	}
2774	v += r - 1
2775	c := v % r
2776	if c < 0 {
2777		c += r
2778	}
2779	v -= c
2780	return v
2781}
2782
2783func bgetc(r *bio.Reader) int {
2784	c, err := r.ReadByte()
2785	if err != nil {
2786		if err != io.EOF {
2787			log.Fatalf("reading input: %v", err)
2788		}
2789		return -1
2790	}
2791	return int(c)
2792}
2793
2794type markKind uint8 // for postorder traversal
2795const (
2796	_ markKind = iota
2797	visiting
2798	visited
2799)
2800
2801func postorder(libs []*sym.Library) []*sym.Library {
2802	order := make([]*sym.Library, 0, len(libs)) // hold the result
2803	mark := make(map[*sym.Library]markKind, len(libs))
2804	for _, lib := range libs {
2805		dfs(lib, mark, &order)
2806	}
2807	return order
2808}
2809
2810func dfs(lib *sym.Library, mark map[*sym.Library]markKind, order *[]*sym.Library) {
2811	if mark[lib] == visited {
2812		return
2813	}
2814	if mark[lib] == visiting {
2815		panic("found import cycle while visiting " + lib.Pkg)
2816	}
2817	mark[lib] = visiting
2818	for _, i := range lib.Imports {
2819		dfs(i, mark, order)
2820	}
2821	mark[lib] = visited
2822	*order = append(*order, lib)
2823}
2824
2825func ElfSymForReloc(ctxt *Link, s loader.Sym) int32 {
2826	// If putelfsym created a local version of this symbol, use that in all
2827	// relocations.
2828	les := ctxt.loader.SymLocalElfSym(s)
2829	if les != 0 {
2830		return les
2831	} else {
2832		return ctxt.loader.SymElfSym(s)
2833	}
2834}
2835
2836func AddGotSym(target *Target, ldr *loader.Loader, syms *ArchSyms, s loader.Sym, elfRelocTyp uint32) {
2837	if ldr.SymGot(s) >= 0 {
2838		return
2839	}
2840
2841	Adddynsym(ldr, target, syms, s)
2842	got := ldr.MakeSymbolUpdater(syms.GOT)
2843	ldr.SetGot(s, int32(got.Size()))
2844	got.AddUint(target.Arch, 0)
2845
2846	if target.IsElf() {
2847		if target.Arch.PtrSize == 8 {
2848			rela := ldr.MakeSymbolUpdater(syms.Rela)
2849			rela.AddAddrPlus(target.Arch, got.Sym(), int64(ldr.SymGot(s)))
2850			rela.AddUint64(target.Arch, elf.R_INFO(uint32(ldr.SymDynid(s)), elfRelocTyp))
2851			rela.AddUint64(target.Arch, 0)
2852		} else {
2853			rel := ldr.MakeSymbolUpdater(syms.Rel)
2854			rel.AddAddrPlus(target.Arch, got.Sym(), int64(ldr.SymGot(s)))
2855			rel.AddUint32(target.Arch, elf.R_INFO32(uint32(ldr.SymDynid(s)), elfRelocTyp))
2856		}
2857	} else if target.IsDarwin() {
2858		leg := ldr.MakeSymbolUpdater(syms.LinkEditGOT)
2859		leg.AddUint32(target.Arch, uint32(ldr.SymDynid(s)))
2860		if target.IsPIE() && target.IsInternal() {
2861			// Mach-O relocations are a royal pain to lay out.
2862			// They use a compact stateful bytecode representation.
2863			// Here we record what are needed and encode them later.
2864			MachoAddBind(int64(ldr.SymGot(s)), s)
2865		}
2866	} else {
2867		ldr.Errorf(s, "addgotsym: unsupported binary format")
2868	}
2869}
2870
2871var hostobjcounter int
2872
2873// captureHostObj writes out the content of a host object (pulled from
2874// an archive or loaded from a *.o file directly) to a directory
2875// specified via the linker's "-capturehostobjs" debugging flag. This
2876// is intended to make it easier for a developer to inspect the actual
2877// object feeding into "CGO internal" link step.
2878func captureHostObj(h *Hostobj) {
2879	// Form paths for info file and obj file.
2880	ofile := fmt.Sprintf("captured-obj-%d.o", hostobjcounter)
2881	ifile := fmt.Sprintf("captured-obj-%d.txt", hostobjcounter)
2882	hostobjcounter++
2883	opath := filepath.Join(*flagCaptureHostObjs, ofile)
2884	ipath := filepath.Join(*flagCaptureHostObjs, ifile)
2885
2886	// Write the info file.
2887	info := fmt.Sprintf("pkg: %s\npn: %s\nfile: %s\noff: %d\nlen: %d\n",
2888		h.pkg, h.pn, h.file, h.off, h.length)
2889	if err := os.WriteFile(ipath, []byte(info), 0666); err != nil {
2890		log.Fatalf("error writing captured host obj info %s: %v", ipath, err)
2891	}
2892
2893	readObjData := func() []byte {
2894		inf, err := os.Open(h.file)
2895		if err != nil {
2896			log.Fatalf("capturing host obj: open failed on %s: %v", h.pn, err)
2897		}
2898		defer inf.Close()
2899		res := make([]byte, h.length)
2900		if n, err := inf.ReadAt(res, h.off); err != nil || n != int(h.length) {
2901			log.Fatalf("capturing host obj: readat failed on %s: %v", h.pn, err)
2902		}
2903		return res
2904	}
2905
2906	// Write the object file.
2907	if err := os.WriteFile(opath, readObjData(), 0666); err != nil {
2908		log.Fatalf("error writing captured host object %s: %v", opath, err)
2909	}
2910
2911	fmt.Fprintf(os.Stderr, "link: info: captured host object %s to %s\n",
2912		h.file, opath)
2913}
2914
2915// findExtLinkTool invokes the external linker CC with --print-prog-name
2916// passing the name of the tool we're interested in, such as "strip",
2917// "ar", or "dsymutil", and returns the path passed back from the command.
2918func (ctxt *Link) findExtLinkTool(toolname string) string {
2919	var cc []string
2920	cc = append(cc, ctxt.extld()...)
2921	cc = append(cc, hostlinkArchArgs(ctxt.Arch)...)
2922	cc = append(cc, "--print-prog-name", toolname)
2923	out, err := exec.Command(cc[0], cc[1:]...).CombinedOutput()
2924	if err != nil {
2925		Exitf("%s: finding %s failed: %v\n%s", os.Args[0], toolname, err, out)
2926	}
2927	cmdpath := strings.TrimRight(string(out), "\r\n")
2928	return cmdpath
2929}
2930