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