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