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