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