1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 package ld
32
33 import (
34 "bytes"
35 "debug/elf"
36 "debug/macho"
37 "encoding/base64"
38 "encoding/binary"
39 "fmt"
40 "internal/buildcfg"
41 "io"
42 "log"
43 "os"
44 "os/exec"
45 "path/filepath"
46 "runtime"
47 "sort"
48 "strings"
49 "sync"
50
51 "cmd/internal/bio"
52 "cmd/internal/goobj"
53 "cmd/internal/notsha256"
54 "cmd/internal/objabi"
55 "cmd/internal/sys"
56 "cmd/link/internal/loadelf"
57 "cmd/link/internal/loader"
58 "cmd/link/internal/loadmacho"
59 "cmd/link/internal/loadpe"
60 "cmd/link/internal/loadxcoff"
61 "cmd/link/internal/sym"
62 )
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99 type ArchSyms struct {
100 Rel loader.Sym
101 Rela loader.Sym
102 RelPLT loader.Sym
103 RelaPLT loader.Sym
104
105 LinkEditGOT loader.Sym
106 LinkEditPLT loader.Sym
107
108 TOC loader.Sym
109 DotTOC []loader.Sym
110
111 GOT loader.Sym
112 PLT loader.Sym
113 GOTPLT loader.Sym
114
115 Tlsg loader.Sym
116 Tlsoffset int
117
118 Dynamic loader.Sym
119 DynSym loader.Sym
120 DynStr loader.Sym
121
122 unreachableMethod loader.Sym
123
124
125
126 mainInittasks loader.Sym
127 }
128
129
130 func (ctxt *Link) mkArchSym(name string, ver int, ls *loader.Sym) {
131 *ls = ctxt.loader.LookupOrCreateSym(name, ver)
132 ctxt.loader.SetAttrReachable(*ls, true)
133 }
134
135
136
137 func (ctxt *Link) mkArchSymVec(name string, ver int, ls []loader.Sym) {
138 ls[ver] = ctxt.loader.LookupOrCreateSym(name, ver)
139 ctxt.loader.SetAttrReachable(ls[ver], true)
140 }
141
142
143
144 func (ctxt *Link) setArchSyms() {
145 ctxt.mkArchSym(".got", 0, &ctxt.GOT)
146 ctxt.mkArchSym(".plt", 0, &ctxt.PLT)
147 ctxt.mkArchSym(".got.plt", 0, &ctxt.GOTPLT)
148 ctxt.mkArchSym(".dynamic", 0, &ctxt.Dynamic)
149 ctxt.mkArchSym(".dynsym", 0, &ctxt.DynSym)
150 ctxt.mkArchSym(".dynstr", 0, &ctxt.DynStr)
151 ctxt.mkArchSym("runtime.unreachableMethod", abiInternalVer, &ctxt.unreachableMethod)
152
153 if ctxt.IsPPC64() {
154 ctxt.mkArchSym("TOC", 0, &ctxt.TOC)
155
156 ctxt.DotTOC = make([]loader.Sym, ctxt.MaxVersion()+1)
157 for i := 0; i <= ctxt.MaxVersion(); i++ {
158 if i >= sym.SymVerABICount && i < sym.SymVerStatic {
159 continue
160 }
161 ctxt.mkArchSymVec(".TOC.", i, ctxt.DotTOC)
162 }
163 }
164 if ctxt.IsElf() {
165 ctxt.mkArchSym(".rel", 0, &ctxt.Rel)
166 ctxt.mkArchSym(".rela", 0, &ctxt.Rela)
167 ctxt.mkArchSym(".rel.plt", 0, &ctxt.RelPLT)
168 ctxt.mkArchSym(".rela.plt", 0, &ctxt.RelaPLT)
169 }
170 if ctxt.IsDarwin() {
171 ctxt.mkArchSym(".linkedit.got", 0, &ctxt.LinkEditGOT)
172 ctxt.mkArchSym(".linkedit.plt", 0, &ctxt.LinkEditPLT)
173 }
174 }
175
176 type Arch struct {
177 Funcalign int
178 Maxalign int
179 Minalign int
180 Dwarfregsp int
181 Dwarfreglr int
182
183
184
185
186
187 TrampLimit uint64
188
189
190
191
192
193 CodePad []byte
194
195
196 Plan9Magic uint32
197 Plan9_64Bit bool
198
199 Adddynrel func(*Target, *loader.Loader, *ArchSyms, loader.Sym, loader.Reloc, int) bool
200 Archinit func(*Link)
201
202
203
204
205
206
207
208
209
210
211 Archreloc func(*Target, *loader.Loader, *ArchSyms, loader.Reloc, loader.Sym,
212 int64) (relocatedOffset int64, nExtReloc int, ok bool)
213
214
215
216
217
218
219
220
221 Archrelocvariant func(target *Target, ldr *loader.Loader, rel loader.Reloc,
222 rv sym.RelocVariant, sym loader.Sym, offset int64, data []byte) (relocatedOffset int64)
223
224
225
226 Trampoline func(ctxt *Link, ldr *loader.Loader, ri int, rs, s loader.Sym)
227
228
229
230
231
232
233
234
235 Asmb func(*Link, *loader.Loader)
236 Asmb2 func(*Link, *loader.Loader)
237
238
239
240
241 Extreloc func(*Target, *loader.Loader, loader.Reloc, loader.Sym) (loader.ExtReloc, bool)
242
243 Gentext func(*Link, *loader.Loader)
244 Machoreloc1 func(*sys.Arch, *OutBuf, *loader.Loader, loader.Sym, loader.ExtReloc, int64) bool
245 MachorelocSize uint32
246 PEreloc1 func(*sys.Arch, *OutBuf, *loader.Loader, loader.Sym, loader.ExtReloc, int64) bool
247 Xcoffreloc1 func(*sys.Arch, *OutBuf, *loader.Loader, loader.Sym, loader.ExtReloc, int64) bool
248
249
250
251 GenSymsLate func(*Link, *loader.Loader)
252
253
254
255
256
257
258
259 TLSIEtoLE func(P []byte, off, size int)
260
261
262 AssignAddress func(ldr *loader.Loader, sect *sym.Section, n int, s loader.Sym, va uint64, isTramp bool) (*sym.Section, int, uint64)
263
264
265 ELF ELFArch
266 }
267
268 var (
269 thearch Arch
270 lcSize int32
271 rpath Rpath
272 spSize int32
273 symSize int32
274 )
275
276 const (
277 MINFUNC = 16
278 )
279
280
281
282 var abiInternalVer = sym.SymVerABIInternal
283
284
285
286 func (ctxt *Link) DynlinkingGo() bool {
287 if !ctxt.Loaded {
288 panic("DynlinkingGo called before all symbols loaded")
289 }
290 return ctxt.BuildMode == BuildModeShared || ctxt.linkShared || ctxt.BuildMode == BuildModePlugin || ctxt.canUsePlugins
291 }
292
293
294 func (ctxt *Link) CanUsePlugins() bool {
295 if !ctxt.Loaded {
296 panic("CanUsePlugins called before all symbols loaded")
297 }
298 return ctxt.canUsePlugins
299 }
300
301
302 func (ctxt *Link) NeedCodeSign() bool {
303 return ctxt.IsDarwin() && ctxt.IsARM64()
304 }
305
306 var (
307 dynlib []string
308 ldflag []string
309 havedynamic int
310 Funcalign int
311 iscgo bool
312 elfglobalsymndx int
313 interpreter string
314
315 debug_s bool
316 HEADR int32
317
318 nerrors int
319 liveness int64
320
321
322 checkStrictDups int
323 strictDupMsgCount int
324 )
325
326 var (
327 Segtext sym.Segment
328 Segrodata sym.Segment
329 Segrelrodata sym.Segment
330 Segdata sym.Segment
331 Segdwarf sym.Segment
332 Segpdata sym.Segment
333 Segxdata sym.Segment
334
335 Segments = []*sym.Segment{&Segtext, &Segrodata, &Segrelrodata, &Segdata, &Segdwarf, &Segpdata, &Segxdata}
336 )
337
338 const pkgdef = "__.PKGDEF"
339
340 var (
341
342
343
344 externalobj = false
345
346
347
348
349 dynimportfail []string
350
351
352
353
354
355 preferlinkext []string
356
357
358
359 unknownObjFormat = false
360
361 theline string
362 )
363
364 func Lflag(ctxt *Link, arg string) {
365 ctxt.Libdir = append(ctxt.Libdir, arg)
366 }
367
368
374 func mayberemoveoutfile() {
375 if fi, err := os.Lstat(*flagOutfile); err == nil && !fi.Mode().IsRegular() {
376 return
377 }
378 os.Remove(*flagOutfile)
379 }
380
381 func libinit(ctxt *Link) {
382 Funcalign = thearch.Funcalign
383
384
385 suffix := ""
386
387 suffixsep := ""
388 if *flagInstallSuffix != "" {
389 suffixsep = "_"
390 suffix = *flagInstallSuffix
391 } else if *flagRace {
392 suffixsep = "_"
393 suffix = "race"
394 } else if *flagMsan {
395 suffixsep = "_"
396 suffix = "msan"
397 } else if *flagAsan {
398 suffixsep = "_"
399 suffix = "asan"
400 }
401
402 if buildcfg.GOROOT != "" {
403 Lflag(ctxt, filepath.Join(buildcfg.GOROOT, "pkg", fmt.Sprintf("%s_%s%s%s", buildcfg.GOOS, buildcfg.GOARCH, suffixsep, suffix)))
404 }
405
406 mayberemoveoutfile()
407
408 if err := ctxt.Out.Open(*flagOutfile); err != nil {
409 Exitf("cannot create %s: %v", *flagOutfile, err)
410 }
411
412 if *flagEntrySymbol == "" {
413 switch ctxt.BuildMode {
414 case BuildModeCShared, BuildModeCArchive:
415 *flagEntrySymbol = fmt.Sprintf("_rt0_%s_%s_lib", buildcfg.GOARCH, buildcfg.GOOS)
416 case BuildModeExe, BuildModePIE:
417 *flagEntrySymbol = fmt.Sprintf("_rt0_%s_%s", buildcfg.GOARCH, buildcfg.GOOS)
418 case BuildModeShared, BuildModePlugin:
419
420 default:
421 Errorf(nil, "unknown *flagEntrySymbol for buildmode %v", ctxt.BuildMode)
422 }
423 }
424 }
425
426 func exitIfErrors() {
427 if nerrors != 0 || checkStrictDups > 1 && strictDupMsgCount > 0 {
428 mayberemoveoutfile()
429 Exit(2)
430 }
431
432 }
433
434 func errorexit() {
435 exitIfErrors()
436 Exit(0)
437 }
438
439 func loadinternal(ctxt *Link, name string) *sym.Library {
440 zerofp := goobj.FingerprintType{}
441 if ctxt.linkShared && ctxt.PackageShlib != nil {
442 if shlib := ctxt.PackageShlib[name]; shlib != "" {
443 return addlibpath(ctxt, "internal", "internal", "", name, shlib, zerofp)
444 }
445 }
446 if ctxt.PackageFile != nil {
447 if pname := ctxt.PackageFile[name]; pname != "" {
448 return addlibpath(ctxt, "internal", "internal", pname, name, "", zerofp)
449 }
450 ctxt.Logf("loadinternal: cannot find %s\n", name)
451 return nil
452 }
453
454 for _, libdir := range ctxt.Libdir {
455 if ctxt.linkShared {
456 shlibname := filepath.Join(libdir, name+".shlibname")
457 if ctxt.Debugvlog != 0 {
458 ctxt.Logf("searching for %s.a in %s\n", name, shlibname)
459 }
460 if _, err := os.Stat(shlibname); err == nil {
461 return addlibpath(ctxt, "internal", "internal", "", name, shlibname, zerofp)
462 }
463 }
464 pname := filepath.Join(libdir, name+".a")
465 if ctxt.Debugvlog != 0 {
466 ctxt.Logf("searching for %s.a in %s\n", name, pname)
467 }
468 if _, err := os.Stat(pname); err == nil {
469 return addlibpath(ctxt, "internal", "internal", pname, name, "", zerofp)
470 }
471 }
472
473 if name == "runtime" {
474 Exitf("error: unable to find runtime.a")
475 }
476 ctxt.Logf("warning: unable to find %s.a\n", name)
477 return nil
478 }
479
480
481 func (ctxt *Link) extld() []string {
482 if len(flagExtld) == 0 {
483
484
485
486 switch buildcfg.GOOS {
487 case "darwin", "freebsd", "openbsd":
488 flagExtld = []string{"clang"}
489 default:
490 flagExtld = []string{"gcc"}
491 }
492 }
493 return flagExtld
494 }
495
496
497
498 func (ctxt *Link) findLibPathCmd(cmd, libname string) string {
499 extld := ctxt.extld()
500 name, args := extld[0], extld[1:]
501 args = append(args, hostlinkArchArgs(ctxt.Arch)...)
502 args = append(args, cmd)
503 if ctxt.Debugvlog != 0 {
504 ctxt.Logf("%s %v\n", extld, args)
505 }
506 out, err := exec.Command(name, args...).Output()
507 if err != nil {
508 if ctxt.Debugvlog != 0 {
509 ctxt.Logf("not using a %s file because compiler failed\n%v\n%s\n", libname, err, out)
510 }
511 return "none"
512 }
513 return strings.TrimSpace(string(out))
514 }
515
516
517
518 func (ctxt *Link) findLibPath(libname string) string {
519 return ctxt.findLibPathCmd("--print-file-name="+libname, libname)
520 }
521
522 func (ctxt *Link) loadlib() {
523 var flags uint32
524 switch *FlagStrictDups {
525 case 0:
526
527 case 1, 2:
528 flags |= loader.FlagStrictDups
529 default:
530 log.Fatalf("invalid -strictdups flag value %d", *FlagStrictDups)
531 }
532 ctxt.loader = loader.NewLoader(flags, &ctxt.ErrorReporter.ErrorReporter)
533 ctxt.ErrorReporter.SymName = func(s loader.Sym) string {
534 return ctxt.loader.SymName(s)
535 }
536
537
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
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
567
568
569
570 iscgo = ctxt.LibraryByPkg["runtime/cgo"] != nil
571
572
573
574 ctxt.canUsePlugins = ctxt.LibraryByPkg["plugin"] != nil && iscgo
575
576
577 determineLinkMode(ctxt)
578
579 if ctxt.LinkMode == LinkExternal && !iscgo && !(buildcfg.GOOS == "darwin" && ctxt.BuildMode != BuildModePlugin && ctxt.Arch.Family == sys.AMD64) {
580
581
582
583
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
598 ctxt.loader.LoadSyms(ctxt.Arch)
599
600
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
611 ctxt.loadcgodirectives()
612
613
614 hostobjs(ctxt)
615 hostlinksetup(ctxt)
616
617 if ctxt.LinkMode == LinkInternal && len(hostobj) != 0 {
618
619
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
636
637
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
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
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
675 ctxt.Loaded = true
676
677 strictDupMsgCount = ctxt.loader.NStrictDupMsgs()
678 }
679
680
681
682
683
684
685
686
687 func loadWindowsHostArchives(ctxt *Link) {
688 any := true
689 for i := 0; any && i < 2; i++ {
690
691
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
710
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
726
727
728
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
742
743 if err := loadpe.PostProcessImports(); err != nil {
744 Errorf(nil, "%v", err)
745 }
746
747
748
749
750
756 }
757
758
759
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
770
771 for symIdx := range hostObjSyms {
772 if l.SymType(symIdx) == sym.SHOSTOBJ {
773
774
775
776
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
789
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
805 if ctxt.HeadType == objabi.Hwindows {
806 Peinit(ctxt)
807 }
808
809 if ctxt.LinkMode == LinkExternal {
810
811
812 *FlagTextAddr = 0
813 }
814
815
816
817
818
819
820
821
822
823
824
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
838
839
840 if buildcfg.GOOS != "android" {
841 tlsg := ctxt.loader.LookupOrCreateSym("runtime.tlsg", 0)
842 sb := ctxt.loader.MakeSymbolUpdater(tlsg)
843
844
845
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
868
869
870
871
872 mdsb.SetSize(0)
873
874
875
876 if ctxt.Arch.Family == sys.ARM {
877 goarm := ctxt.loader.LookupOrCreateSym("runtime.goarm", 0)
878 sb := ctxt.loader.MakeSymbolUpdater(goarm)
879 sb.SetType(sym.SDATA)
880 sb.SetSize(0)
881 sb.AddUint8(uint8(buildcfg.GOARM.Version))
882
883 goarmsoftfp := ctxt.loader.LookupOrCreateSym("runtime.goarmsoftfp", 0)
884 sb2 := ctxt.loader.MakeSymbolUpdater(goarmsoftfp)
885 sb2.SetType(sym.SDATA)
886 sb2.SetSize(0)
887 if buildcfg.GOARM.SoftFloat {
888 sb2.AddUint8(1)
889 } else {
890 sb2.AddUint8(0)
891 }
892 }
893
894
895
896
897 memProfile := ctxt.loader.Lookup("runtime.MemProfile", abiInternalVer)
898 if memProfile != 0 && !ctxt.loader.AttrReachable(memProfile) && !ctxt.DynlinkingGo() {
899 memProfSym := ctxt.loader.LookupOrCreateSym("runtime.disableMemoryProfiling", 0)
900 sb := ctxt.loader.MakeSymbolUpdater(memProfSym)
901 sb.SetType(sym.SDATA)
902 sb.SetSize(0)
903 sb.AddUint8(1)
904 }
905 } else {
906
907
908 moduledata = ctxt.loader.LookupOrCreateSym("local.moduledata", 0)
909 mdsb = ctxt.loader.MakeSymbolUpdater(moduledata)
910 ctxt.loader.SetAttrLocal(moduledata, true)
911 }
912
913
914 mdsb.SetType(sym.SNOPTRDATA)
915 ctxt.loader.SetAttrReachable(moduledata, true)
916 ctxt.Moduledata = moduledata
917
918 if ctxt.Arch == sys.Arch386 && ctxt.HeadType != objabi.Hwindows {
919 if (ctxt.BuildMode == BuildModeCArchive && ctxt.IsELF) || ctxt.BuildMode == BuildModeCShared || ctxt.BuildMode == BuildModePIE || ctxt.DynlinkingGo() {
920 got := ctxt.loader.LookupOrCreateSym("_GLOBAL_OFFSET_TABLE_", 0)
921 sb := ctxt.loader.MakeSymbolUpdater(got)
922 sb.SetType(sym.SDYNIMPORT)
923 ctxt.loader.SetAttrReachable(got, true)
924 }
925 }
926
927
928
929
930
931
932
933 ctxt.Library = postorder(ctxt.Library)
934 intlibs := []bool{}
935 for _, lib := range ctxt.Library {
936 intlibs = append(intlibs, isRuntimeDepPkg(lib.Pkg))
937 }
938 ctxt.Textp = ctxt.loader.AssignTextSymbolOrder(ctxt.Library, intlibs, ctxt.Textp)
939 }
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954 func (ctxt *Link) mangleTypeSym() {
955 if ctxt.BuildMode != BuildModeShared && !ctxt.linkShared && ctxt.BuildMode != BuildModePlugin && !ctxt.CanUsePlugins() {
956 return
957 }
958
959 ldr := ctxt.loader
960 for s := loader.Sym(1); s < loader.Sym(ldr.NSym()); s++ {
961 if !ldr.AttrReachable(s) && !ctxt.linkShared {
962
963
964
965
966
967 continue
968 }
969 name := ldr.SymName(s)
970 newName := typeSymbolMangle(name)
971 if newName != name {
972 ldr.SetSymExtname(s, newName)
973
974
975
976
977
978
979 dup := ldr.Lookup(newName, ldr.SymVersion(s))
980 if dup != 0 {
981 st := ldr.SymType(s)
982 dt := ldr.SymType(dup)
983 if st == sym.Sxxx && dt != sym.Sxxx {
984 ldr.CopySym(dup, s)
985 }
986 }
987 }
988 }
989 }
990
991
992
993
994
995
996
997 func typeSymbolMangle(name string) string {
998 isType := strings.HasPrefix(name, "type:")
999 if !isType && !strings.Contains(name, "@") {
1000
1001 return name
1002 }
1003 if strings.HasPrefix(name, "type:runtime.") {
1004 return name
1005 }
1006 if strings.HasPrefix(name, "go:string.") {
1007
1008
1009 return name
1010 }
1011 if len(name) <= 14 && !strings.Contains(name, "@") {
1012 return name
1013 }
1014 if isType {
1015 hash := notsha256.Sum256([]byte(name[5:]))
1016 prefix := "type:"
1017 if name[5] == '.' {
1018 prefix = "type:."
1019 }
1020 return prefix + base64.StdEncoding.EncodeToString(hash[:6])
1021 }
1022
1023 i := strings.IndexByte(name, '[')
1024 j := strings.LastIndexByte(name, ']')
1025 if j == -1 || j <= i {
1026 j = len(name)
1027 }
1028 hash := notsha256.Sum256([]byte(name[i+1 : j]))
1029 return name[:i+1] + base64.StdEncoding.EncodeToString(hash[:6]) + name[j:]
1030 }
1031
1032
1036 func nextar(bp *bio.Reader, off int64, a *ArHdr) int64 {
1037 if off&1 != 0 {
1038 off++
1039 }
1040 bp.MustSeek(off, 0)
1041 var buf [SAR_HDR]byte
1042 if n, err := io.ReadFull(bp, buf[:]); err != nil {
1043 if n == 0 && err != io.EOF {
1044 return -1
1045 }
1046 return 0
1047 }
1048
1049 a.name = artrim(buf[0:16])
1050 a.date = artrim(buf[16:28])
1051 a.uid = artrim(buf[28:34])
1052 a.gid = artrim(buf[34:40])
1053 a.mode = artrim(buf[40:48])
1054 a.size = artrim(buf[48:58])
1055 a.fmag = artrim(buf[58:60])
1056
1057 arsize := atolwhex(a.size)
1058 if arsize&1 != 0 {
1059 arsize++
1060 }
1061 return arsize + SAR_HDR
1062 }
1063
1064 func loadobjfile(ctxt *Link, lib *sym.Library) {
1065 pkg := objabi.PathToPrefix(lib.Pkg)
1066
1067 if ctxt.Debugvlog > 1 {
1068 ctxt.Logf("ldobj: %s (%s)\n", lib.File, pkg)
1069 }
1070 f, err := bio.Open(lib.File)
1071 if err != nil {
1072 Exitf("cannot open file %s: %v", lib.File, err)
1073 }
1074 defer f.Close()
1075 defer func() {
1076 if pkg == "main" && !lib.Main {
1077 Exitf("%s: not package main", lib.File)
1078 }
1079 }()
1080
1081 for i := 0; i < len(ARMAG); i++ {
1082 if c, err := f.ReadByte(); err == nil && c == ARMAG[i] {
1083 continue
1084 }
1085
1086
1087 l := f.MustSeek(0, 2)
1088 f.MustSeek(0, 0)
1089 ldobj(ctxt, f, lib, l, lib.File, lib.File)
1090 return
1091 }
1092
1093
1105 var arhdr ArHdr
1106 off := f.Offset()
1107 for {
1108 l := nextar(f, off, &arhdr)
1109 if l == 0 {
1110 break
1111 }
1112 if l < 0 {
1113 Exitf("%s: malformed archive", lib.File)
1114 }
1115 off += l
1116
1117
1118
1119
1120
1121 if arhdr.name == pkgdef {
1122 continue
1123 }
1124
1125 if arhdr.name == "dynimportfail" {
1126 dynimportfail = append(dynimportfail, lib.Pkg)
1127 }
1128 if arhdr.name == "preferlinkext" {
1129
1130
1131 if ctxt.LinkMode == LinkAuto {
1132 preferlinkext = append(preferlinkext, lib.Pkg)
1133 }
1134 }
1135
1136
1137
1138
1139 if len(arhdr.name) < 16 {
1140 if ext := filepath.Ext(arhdr.name); ext != ".o" && ext != ".syso" {
1141 continue
1142 }
1143 }
1144
1145 pname := fmt.Sprintf("%s(%s)", lib.File, arhdr.name)
1146 l = atolwhex(arhdr.size)
1147 ldobj(ctxt, f, lib, l, pname, lib.File)
1148 }
1149 }
1150
1151 type Hostobj struct {
1152 ld func(*Link, *bio.Reader, string, int64, string)
1153 pkg string
1154 pn string
1155 file string
1156 off int64
1157 length int64
1158 }
1159
1160 var hostobj []Hostobj
1161
1162
1163
1164 var internalpkg = []string{
1165 "crypto/internal/boring",
1166 "crypto/internal/boring/syso",
1167 "crypto/x509",
1168 "net",
1169 "os/user",
1170 "runtime/cgo",
1171 "runtime/race",
1172 "runtime/race/internal/amd64v1",
1173 "runtime/race/internal/amd64v3",
1174 "runtime/msan",
1175 "runtime/asan",
1176 }
1177
1178 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 {
1179 isinternal := false
1180 for _, intpkg := range internalpkg {
1181 if pkg == intpkg {
1182 isinternal = true
1183 break
1184 }
1185 }
1186
1187
1188
1189
1190
1191
1192
1193 if headType == objabi.Hdragonfly {
1194 if pkg == "net" || pkg == "os/user" {
1195 isinternal = false
1196 }
1197 }
1198
1199 if !isinternal {
1200 externalobj = true
1201 }
1202
1203 hostobj = append(hostobj, Hostobj{})
1204 h := &hostobj[len(hostobj)-1]
1205 h.ld = ld
1206 h.pkg = pkg
1207 h.pn = pn
1208 h.file = file
1209 h.off = f.Offset()
1210 h.length = length
1211 return h
1212 }
1213
1214 func hostobjs(ctxt *Link) {
1215 if ctxt.LinkMode != LinkInternal {
1216 return
1217 }
1218 var h *Hostobj
1219
1220 for i := 0; i < len(hostobj); i++ {
1221 h = &hostobj[i]
1222 f, err := bio.Open(h.file)
1223 if err != nil {
1224 Exitf("cannot reopen %s: %v", h.pn, err)
1225 }
1226 f.MustSeek(h.off, 0)
1227 if h.ld == nil {
1228 Errorf(nil, "%s: unrecognized object file format", h.pn)
1229 continue
1230 }
1231 h.ld(ctxt, f, h.pkg, h.length, h.pn)
1232 if *flagCaptureHostObjs != "" {
1233 captureHostObj(h)
1234 }
1235 f.Close()
1236 }
1237 }
1238
1239 func hostlinksetup(ctxt *Link) {
1240 if ctxt.LinkMode != LinkExternal {
1241 return
1242 }
1243
1244
1245
1246
1247 debug_s = *FlagS
1248 *FlagS = false
1249
1250
1251 if *flagTmpdir == "" {
1252 dir, err := os.MkdirTemp("", "go-link-")
1253 if err != nil {
1254 log.Fatal(err)
1255 }
1256 *flagTmpdir = dir
1257 ownTmpDir = true
1258 AtExit(func() {
1259 os.RemoveAll(*flagTmpdir)
1260 })
1261 }
1262
1263
1264 if err := ctxt.Out.Close(); err != nil {
1265 Exitf("error closing output file")
1266 }
1267 mayberemoveoutfile()
1268
1269 p := filepath.Join(*flagTmpdir, "go.o")
1270 if err := ctxt.Out.Open(p); err != nil {
1271 Exitf("cannot create %s: %v", p, err)
1272 }
1273 }
1274
1275
1276
1277 func (ctxt *Link) hostobjCopy() (paths []string) {
1278 var wg sync.WaitGroup
1279 sema := make(chan struct{}, runtime.NumCPU())
1280 for i, h := range hostobj {
1281 h := h
1282 dst := filepath.Join(*flagTmpdir, fmt.Sprintf("%06d.o", i))
1283 paths = append(paths, dst)
1284 if ctxt.Debugvlog != 0 {
1285 ctxt.Logf("host obj copy: %s from pkg %s -> %s\n", h.pn, h.pkg, dst)
1286 }
1287
1288 wg.Add(1)
1289 go func() {
1290 sema <- struct{}{}
1291 defer func() {
1292 <-sema
1293 wg.Done()
1294 }()
1295 f, err := os.Open(h.file)
1296 if err != nil {
1297 Exitf("cannot reopen %s: %v", h.pn, err)
1298 }
1299 defer f.Close()
1300 if _, err := f.Seek(h.off, 0); err != nil {
1301 Exitf("cannot seek %s: %v", h.pn, err)
1302 }
1303
1304 w, err := os.Create(dst)
1305 if err != nil {
1306 Exitf("cannot create %s: %v", dst, err)
1307 }
1308 if _, err := io.CopyN(w, f, h.length); err != nil {
1309 Exitf("cannot write %s: %v", dst, err)
1310 }
1311 if err := w.Close(); err != nil {
1312 Exitf("cannot close %s: %v", dst, err)
1313 }
1314 }()
1315 }
1316 wg.Wait()
1317 return paths
1318 }
1319
1320
1321
1322
1323
1324 func writeGDBLinkerScript() string {
1325 name := "fix_debug_gdb_scripts.ld"
1326 path := filepath.Join(*flagTmpdir, name)
1327 src := `SECTIONS
1328 {
1329 .debug_gdb_scripts BLOCK(__section_alignment__) (NOLOAD) :
1330 {
1331 *(.debug_gdb_scripts)
1332 }
1333 }
1334 INSERT AFTER .debug_types;
1335 `
1336 err := os.WriteFile(path, []byte(src), 0666)
1337 if err != nil {
1338 Errorf(nil, "WriteFile %s failed: %v", name, err)
1339 }
1340 return path
1341 }
1342
1343
1344 func (ctxt *Link) archive() {
1345 if ctxt.BuildMode != BuildModeCArchive {
1346 return
1347 }
1348
1349 exitIfErrors()
1350
1351 if *flagExtar == "" {
1352 *flagExtar = "ar"
1353 }
1354
1355 mayberemoveoutfile()
1356
1357
1358
1359 if err := ctxt.Out.Close(); err != nil {
1360 Exitf("error closing %v", *flagOutfile)
1361 }
1362
1363 argv := []string{*flagExtar, "-q", "-c", "-s"}
1364 if ctxt.HeadType == objabi.Haix {
1365 argv = append(argv, "-X64")
1366 }
1367 argv = append(argv, *flagOutfile)
1368 argv = append(argv, filepath.Join(*flagTmpdir, "go.o"))
1369 argv = append(argv, ctxt.hostobjCopy()...)
1370
1371 if ctxt.Debugvlog != 0 {
1372 ctxt.Logf("archive: %s\n", strings.Join(argv, " "))
1373 }
1374
1375
1376
1377
1378
1379
1380 if syscallExecSupported && !ownTmpDir {
1381 runAtExitFuncs()
1382 ctxt.execArchive(argv)
1383 panic("should not get here")
1384 }
1385
1386
1387 if out, err := exec.Command(argv[0], argv[1:]...).CombinedOutput(); err != nil {
1388 Exitf("running %s failed: %v\n%s", argv[0], err, out)
1389 }
1390 }
1391
1392 func (ctxt *Link) hostlink() {
1393 if ctxt.LinkMode != LinkExternal || nerrors > 0 {
1394 return
1395 }
1396 if ctxt.BuildMode == BuildModeCArchive {
1397 return
1398 }
1399
1400 var argv []string
1401 argv = append(argv, ctxt.extld()...)
1402 argv = append(argv, hostlinkArchArgs(ctxt.Arch)...)
1403
1404 if *FlagS || debug_s {
1405 if ctxt.HeadType == objabi.Hdarwin {
1406
1407
1408
1409 } else {
1410 argv = append(argv, "-s")
1411 }
1412 }
1413
1414
1415
1416 combineDwarf := ctxt.IsDarwin() && !*FlagW && machoPlatform == PLATFORM_MACOS
1417
1418 switch ctxt.HeadType {
1419 case objabi.Hdarwin:
1420 if combineDwarf {
1421
1422
1423 argv = append(argv, "-Wl,-headerpad,1144")
1424 }
1425 if ctxt.DynlinkingGo() && buildcfg.GOOS != "ios" {
1426
1427
1428
1429
1430
1431 argv = append(argv, "-Wl,-flat_namespace", "-Wl,-bind_at_load")
1432 }
1433 if !combineDwarf {
1434 argv = append(argv, "-Wl,-S")
1435 if debug_s {
1436
1437
1438
1439 argv = append(argv, "-Wl,-x")
1440 }
1441 }
1442 case objabi.Hopenbsd:
1443 argv = append(argv, "-Wl,-nopie")
1444 argv = append(argv, "-pthread")
1445 if ctxt.Arch.InFamily(sys.ARM64) {
1446
1447
1448
1449 argv = append(argv, "-Wl,--no-execute-only")
1450 }
1451 case objabi.Hwindows:
1452 if windowsgui {
1453 argv = append(argv, "-mwindows")
1454 } else {
1455 argv = append(argv, "-mconsole")
1456 }
1457
1458
1459 argv = append(argv, "-Wl,--tsaware")
1460
1461
1462 argv = append(argv, "-Wl,--nxcompat")
1463
1464 argv = append(argv, fmt.Sprintf("-Wl,--major-os-version=%d", PeMinimumTargetMajorVersion))
1465 argv = append(argv, fmt.Sprintf("-Wl,--minor-os-version=%d", PeMinimumTargetMinorVersion))
1466 argv = append(argv, fmt.Sprintf("-Wl,--major-subsystem-version=%d", PeMinimumTargetMajorVersion))
1467 argv = append(argv, fmt.Sprintf("-Wl,--minor-subsystem-version=%d", PeMinimumTargetMinorVersion))
1468 case objabi.Haix:
1469 argv = append(argv, "-pthread")
1470
1471
1472 argv = append(argv, "-Wl,-bnoobjreorder")
1473
1474
1475 argv = append(argv, "-mcmodel=large")
1476 argv = append(argv, "-Wl,-bbigtoc")
1477 }
1478
1479
1480
1481
1482 if ctxt.IsPPC64() && ctxt.IsElf() && buildcfg.GOPPC64 >= 10 {
1483 if !linkerFlagSupported(ctxt.Arch, argv[0], "", "-mcpu=power10") {
1484 Exitf("The external toolchain does not support -mcpu=power10. " +
1485 " This is required to externally link GOPPC64 >= power10")
1486 }
1487 }
1488
1489
1490 addASLRargs := func(argv []string, val bool) []string {
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506 var dbopt string
1507 var heopt string
1508 dbon := "--dynamicbase"
1509 heon := "--high-entropy-va"
1510 dboff := "--disable-dynamicbase"
1511 heoff := "--disable-high-entropy-va"
1512 if val {
1513 dbopt = dbon
1514 heopt = heon
1515 } else {
1516
1517 newer := linkerFlagSupported(ctxt.Arch, argv[0], "", "-Wl,"+dboff)
1518 if newer {
1519
1520 dbopt = dboff
1521 heopt = heoff
1522 } else {
1523
1524
1525 dbopt = ""
1526 heopt = ""
1527 }
1528 }
1529 if dbopt != "" {
1530 argv = append(argv, "-Wl,"+dbopt)
1531 }
1532
1533 if ctxt.Arch.PtrSize >= 8 && heopt != "" {
1534 argv = append(argv, "-Wl,"+heopt)
1535 }
1536 return argv
1537 }
1538
1539 switch ctxt.BuildMode {
1540 case BuildModeExe:
1541 if ctxt.HeadType == objabi.Hdarwin {
1542 if machoPlatform == PLATFORM_MACOS && ctxt.IsAMD64() {
1543 argv = append(argv, "-Wl,-no_pie")
1544 }
1545 }
1546 if *flagRace && ctxt.HeadType == objabi.Hwindows {
1547
1548
1549
1550
1551 argv = addASLRargs(argv, false)
1552 }
1553 case BuildModePIE:
1554 switch ctxt.HeadType {
1555 case objabi.Hdarwin, objabi.Haix:
1556 case objabi.Hwindows:
1557 if *flagAslr && *flagRace {
1558
1559
1560
1561 *flagAslr = false
1562 }
1563 argv = addASLRargs(argv, *flagAslr)
1564 default:
1565
1566 if ctxt.UseRelro() {
1567 argv = append(argv, "-Wl,-z,relro")
1568 }
1569 argv = append(argv, "-pie")
1570 }
1571 case BuildModeCShared:
1572 if ctxt.HeadType == objabi.Hdarwin {
1573 argv = append(argv, "-dynamiclib")
1574 } else {
1575 if ctxt.UseRelro() {
1576 argv = append(argv, "-Wl,-z,relro")
1577 }
1578 argv = append(argv, "-shared")
1579 if ctxt.HeadType == objabi.Hwindows {
1580 argv = addASLRargs(argv, *flagAslr)
1581 } else {
1582
1583
1584 argv = append(argv, "-Wl,-z,nodelete")
1585
1586 argv = append(argv, "-Wl,-Bsymbolic")
1587 }
1588 }
1589 case BuildModeShared:
1590 if ctxt.UseRelro() {
1591 argv = append(argv, "-Wl,-z,relro")
1592 }
1593 argv = append(argv, "-shared")
1594 case BuildModePlugin:
1595 if ctxt.HeadType == objabi.Hdarwin {
1596 argv = append(argv, "-dynamiclib")
1597 } else {
1598 if ctxt.UseRelro() {
1599 argv = append(argv, "-Wl,-z,relro")
1600 }
1601 argv = append(argv, "-shared")
1602 }
1603 }
1604
1605 var altLinker string
1606 if ctxt.IsELF && ctxt.DynlinkingGo() {
1607
1608
1609
1610 argv = append(argv, "-Wl,-z,now")
1611
1612
1613
1614
1615 argv = append(argv, "-Wl,-z,nocopyreloc")
1616
1617 if buildcfg.GOOS == "android" {
1618
1619 altLinker = "lld"
1620 }
1621
1622 if ctxt.Arch.InFamily(sys.ARM64) && buildcfg.GOOS == "linux" {
1623
1624
1625
1626
1627
1628 altLinker = "gold"
1629
1630
1631
1632
1633 name, args := flagExtld[0], flagExtld[1:]
1634 args = append(args, "-fuse-ld=gold", "-Wl,--version")
1635 cmd := exec.Command(name, args...)
1636 if out, err := cmd.CombinedOutput(); err == nil {
1637 if !bytes.Contains(out, []byte("GNU gold")) {
1638 log.Fatalf("ARM64 external linker must be gold (issue #15696, 22040), but is not: %s", out)
1639 }
1640 }
1641 }
1642 }
1643 if ctxt.Arch.Family == sys.ARM64 && buildcfg.GOOS == "freebsd" {
1644
1645 altLinker = "bfd"
1646
1647
1648 name, args := flagExtld[0], flagExtld[1:]
1649 args = append(args, "-fuse-ld=bfd", "-Wl,--version")
1650 cmd := exec.Command(name, args...)
1651 if out, err := cmd.CombinedOutput(); err == nil {
1652 if !bytes.Contains(out, []byte("GNU ld")) {
1653 log.Fatalf("ARM64 external linker must be ld.bfd (issue #35197), please install devel/binutils")
1654 }
1655 }
1656 }
1657 if altLinker != "" {
1658 argv = append(argv, "-fuse-ld="+altLinker)
1659 }
1660
1661 if ctxt.IsELF && len(buildinfo) > 0 {
1662 argv = append(argv, fmt.Sprintf("-Wl,--build-id=0x%x", buildinfo))
1663 }
1664
1665
1666
1667
1668
1669
1670
1671 outopt := *flagOutfile
1672 if buildcfg.GOOS == "windows" && runtime.GOOS == "windows" && filepath.Ext(outopt) == "" {
1673 outopt += "."
1674 }
1675 argv = append(argv, "-o")
1676 argv = append(argv, outopt)
1677
1678 if rpath.val != "" {
1679 argv = append(argv, fmt.Sprintf("-Wl,-rpath,%s", rpath.val))
1680 }
1681
1682 if *flagInterpreter != "" {
1683
1684
1685
1686
1687 argv = append(argv, fmt.Sprintf("-Wl,--dynamic-linker,%s", *flagInterpreter))
1688 }
1689
1690
1691 if ctxt.IsELF {
1692 if ctxt.DynlinkingGo() || ctxt.BuildMode == BuildModeCShared || !linkerFlagSupported(ctxt.Arch, argv[0], altLinker, "-Wl,--export-dynamic-symbol=main") {
1693 argv = append(argv, "-rdynamic")
1694 } else {
1695 var exports []string
1696 ctxt.loader.ForAllCgoExportDynamic(func(s loader.Sym) {
1697 exports = append(exports, "-Wl,--export-dynamic-symbol="+ctxt.loader.SymExtname(s))
1698 })
1699 sort.Strings(exports)
1700 argv = append(argv, exports...)
1701 }
1702 }
1703 if ctxt.HeadType == objabi.Haix {
1704 fileName := xcoffCreateExportFile(ctxt)
1705 argv = append(argv, "-Wl,-bE:"+fileName)
1706 }
1707
1708 const unusedArguments = "-Qunused-arguments"
1709 if linkerFlagSupported(ctxt.Arch, argv[0], altLinker, unusedArguments) {
1710 argv = append(argv, unusedArguments)
1711 }
1712
1713 if ctxt.IsWindows() {
1714
1715
1716
1717
1718 const noTimeStamp = "-Wl,--no-insert-timestamp"
1719 if linkerFlagSupported(ctxt.Arch, argv[0], altLinker, noTimeStamp) {
1720 argv = append(argv, noTimeStamp)
1721 }
1722 }
1723
1724 const compressDWARF = "-Wl,--compress-debug-sections=zlib"
1725 if ctxt.compressDWARF && linkerFlagSupported(ctxt.Arch, argv[0], altLinker, compressDWARF) {
1726 argv = append(argv, compressDWARF)
1727 }
1728
1729 argv = append(argv, filepath.Join(*flagTmpdir, "go.o"))
1730 argv = append(argv, ctxt.hostobjCopy()...)
1731 if ctxt.HeadType == objabi.Haix {
1732
1733
1734 argv = append(argv, "-nostartfiles")
1735 argv = append(argv, "/lib/crt0_64.o")
1736
1737 extld := ctxt.extld()
1738 name, args := extld[0], extld[1:]
1739
1740 getPathFile := func(file string) string {
1741 args := append(args, "-maix64", "--print-file-name="+file)
1742 out, err := exec.Command(name, args...).CombinedOutput()
1743 if err != nil {
1744 log.Fatalf("running %s failed: %v\n%s", extld, err, out)
1745 }
1746 return strings.Trim(string(out), "\n")
1747 }
1748
1749
1750
1751 crtcxa := getPathFile("crtcxa_64.o")
1752 if !filepath.IsAbs(crtcxa) {
1753 crtcxa = getPathFile("crtcxa.o")
1754 }
1755 crtdbase := getPathFile("crtdbase_64.o")
1756 if !filepath.IsAbs(crtdbase) {
1757 crtdbase = getPathFile("crtdbase.o")
1758 }
1759 argv = append(argv, crtcxa)
1760 argv = append(argv, crtdbase)
1761 }
1762
1763 if ctxt.linkShared {
1764 seenDirs := make(map[string]bool)
1765 seenLibs := make(map[string]bool)
1766 addshlib := func(path string) {
1767 dir, base := filepath.Split(path)
1768 if !seenDirs[dir] {
1769 argv = append(argv, "-L"+dir)
1770 if !rpath.set {
1771 argv = append(argv, "-Wl,-rpath="+dir)
1772 }
1773 seenDirs[dir] = true
1774 }
1775 base = strings.TrimSuffix(base, ".so")
1776 base = strings.TrimPrefix(base, "lib")
1777 if !seenLibs[base] {
1778 argv = append(argv, "-l"+base)
1779 seenLibs[base] = true
1780 }
1781 }
1782 for _, shlib := range ctxt.Shlibs {
1783 addshlib(shlib.Path)
1784 for _, dep := range shlib.Deps {
1785 if dep == "" {
1786 continue
1787 }
1788 libpath := findshlib(ctxt, dep)
1789 if libpath != "" {
1790 addshlib(libpath)
1791 }
1792 }
1793 }
1794 }
1795
1796
1797
1798
1799
1800
1801
1802
1803 checkStatic := func(arg string) {
1804 if ctxt.IsELF && arg == "-static" {
1805 for i := range argv {
1806 if argv[i] == "-rdynamic" || strings.HasPrefix(argv[i], "-Wl,--dynamic-linker,") {
1807 argv[i] = "-static"
1808 }
1809 }
1810 }
1811 }
1812
1813 for _, p := range ldflag {
1814 argv = append(argv, p)
1815 checkStatic(p)
1816 }
1817
1818
1819
1820
1821
1822
1823
1824
1825 if ctxt.BuildMode == BuildModeExe && !ctxt.linkShared && !(ctxt.IsDarwin() && ctxt.IsARM64()) {
1826
1827 for _, nopie := range []string{"-no-pie", "-nopie"} {
1828 if linkerFlagSupported(ctxt.Arch, argv[0], altLinker, nopie) {
1829 argv = append(argv, nopie)
1830 break
1831 }
1832 }
1833 }
1834
1835 for _, p := range flagExtldflags {
1836 argv = append(argv, p)
1837 checkStatic(p)
1838 }
1839 if ctxt.HeadType == objabi.Hwindows {
1840
1841
1842 extld := ctxt.extld()
1843 name, args := extld[0], extld[1:]
1844 args = append(args, trimLinkerArgv(flagExtldflags)...)
1845 args = append(args, "-Wl,--version")
1846 cmd := exec.Command(name, args...)
1847 usingLLD := false
1848 if out, err := cmd.CombinedOutput(); err == nil {
1849 if bytes.Contains(out, []byte("LLD ")) {
1850 usingLLD = true
1851 }
1852 }
1853
1854
1855
1856 if !usingLLD {
1857 p := writeGDBLinkerScript()
1858 argv = append(argv, "-Wl,-T,"+p)
1859 }
1860 if *flagRace {
1861 if p := ctxt.findLibPath("libsynchronization.a"); p != "libsynchronization.a" {
1862 argv = append(argv, "-lsynchronization")
1863 }
1864 }
1865
1866
1867 argv = append(argv, "-Wl,--start-group", "-lmingwex", "-lmingw32", "-Wl,--end-group")
1868 argv = append(argv, peimporteddlls()...)
1869 }
1870
1871 argv = ctxt.passLongArgsInResponseFile(argv, altLinker)
1872
1873 if ctxt.Debugvlog != 0 {
1874 ctxt.Logf("host link:")
1875 for _, v := range argv {
1876 ctxt.Logf(" %q", v)
1877 }
1878 ctxt.Logf("\n")
1879 }
1880
1881 out, err := exec.Command(argv[0], argv[1:]...).CombinedOutput()
1882 if err != nil {
1883 Exitf("running %s failed: %v\n%s", argv[0], err, out)
1884 }
1885
1886
1887
1888 var save [][]byte
1889 var skipLines int
1890 for _, line := range bytes.SplitAfter(out, []byte("\n")) {
1891
1892 if bytes.Contains(line, []byte("ld: warning: text-based stub file")) {
1893 continue
1894 }
1895
1896 if skipLines > 0 {
1897 skipLines--
1898 continue
1899 }
1900
1901
1902 if bytes.Contains(line, []byte("ld: 0711-783")) {
1903 skipLines = 2
1904 continue
1905 }
1906
1907 save = append(save, line)
1908 }
1909 out = bytes.Join(save, nil)
1910
1911 if len(out) > 0 {
1912
1913
1914 if ctxt.IsDarwin() && ctxt.IsAMD64() {
1915 const noPieWarning = "ld: warning: -no_pie is deprecated when targeting new OS versions\n"
1916 if i := bytes.Index(out, []byte(noPieWarning)); i >= 0 {
1917
1918 out = append(out[:i], out[i+len(noPieWarning):]...)
1919 }
1920 }
1921 if ctxt.IsDarwin() {
1922 const bindAtLoadWarning = "ld: warning: -bind_at_load is deprecated on macOS\n"
1923 if i := bytes.Index(out, []byte(bindAtLoadWarning)); i >= 0 {
1924
1925
1926
1927
1928 out = append(out[:i], out[i+len(bindAtLoadWarning):]...)
1929 }
1930 }
1931 ctxt.Logf("%s", out)
1932 }
1933
1934 if combineDwarf {
1935
1936 var cc []string
1937 cc = append(cc, ctxt.extld()...)
1938 cc = append(cc, hostlinkArchArgs(ctxt.Arch)...)
1939 cc = append(cc, "--print-prog-name", "dsymutil")
1940 out, err := exec.Command(cc[0], cc[1:]...).CombinedOutput()
1941 if err != nil {
1942 Exitf("%s: finding dsymutil failed: %v\n%s", os.Args[0], err, out)
1943 }
1944 dsymutilCmd := strings.TrimSuffix(string(out), "\n")
1945
1946 cc[len(cc)-1] = "strip"
1947 out, err = exec.Command(cc[0], cc[1:]...).CombinedOutput()
1948 if err != nil {
1949 Exitf("%s: finding strip failed: %v\n%s", os.Args[0], err, out)
1950 }
1951 stripCmd := strings.TrimSuffix(string(out), "\n")
1952
1953 dsym := filepath.Join(*flagTmpdir, "go.dwarf")
1954 cmd := exec.Command(dsymutilCmd, "-f", *flagOutfile, "-o", dsym)
1955
1956
1957 cmd.Env = append(os.Environ(), "DSYMUTIL_REPRODUCER_PATH="+*flagTmpdir)
1958 if ctxt.Debugvlog != 0 {
1959 ctxt.Logf("host link dsymutil:")
1960 for _, v := range cmd.Args {
1961 ctxt.Logf(" %q", v)
1962 }
1963 ctxt.Logf("\n")
1964 }
1965 if out, err := cmd.CombinedOutput(); err != nil {
1966 Exitf("%s: running dsymutil failed: %v\n%s", os.Args[0], err, out)
1967 }
1968
1969
1970 var stripArgs = []string{"-S"}
1971 if debug_s {
1972
1973
1974
1975 stripArgs = append(stripArgs, "-x")
1976 }
1977 stripArgs = append(stripArgs, *flagOutfile)
1978 if ctxt.Debugvlog != 0 {
1979 ctxt.Logf("host link strip: %q", stripCmd)
1980 for _, v := range stripArgs {
1981 ctxt.Logf(" %q", v)
1982 }
1983 ctxt.Logf("\n")
1984 }
1985 if out, err := exec.Command(stripCmd, stripArgs...).CombinedOutput(); err != nil {
1986 Exitf("%s: running strip failed: %v\n%s", os.Args[0], err, out)
1987 }
1988
1989 if _, err := os.Stat(dsym); os.IsNotExist(err) {
1990 return
1991 }
1992
1993 combinedOutput := *flagOutfile + "~"
1994 exef, err := os.Open(*flagOutfile)
1995 if err != nil {
1996 Exitf("%s: combining dwarf failed: %v", os.Args[0], err)
1997 }
1998 defer exef.Close()
1999 exem, err := macho.NewFile(exef)
2000 if err != nil {
2001 Exitf("%s: parsing Mach-O header failed: %v", os.Args[0], err)
2002 }
2003 if err := machoCombineDwarf(ctxt, exef, exem, dsym, combinedOutput); err != nil {
2004 Exitf("%s: combining dwarf failed: %v", os.Args[0], err)
2005 }
2006 os.Remove(*flagOutfile)
2007 if err := os.Rename(combinedOutput, *flagOutfile); err != nil {
2008 Exitf("%s: %v", os.Args[0], err)
2009 }
2010 }
2011 if ctxt.NeedCodeSign() {
2012 err := machoCodeSign(ctxt, *flagOutfile)
2013 if err != nil {
2014 Exitf("%s: code signing failed: %v", os.Args[0], err)
2015 }
2016 }
2017 }
2018
2019
2020
2021 func (ctxt *Link) passLongArgsInResponseFile(argv []string, altLinker string) []string {
2022 c := 0
2023 for _, arg := range argv {
2024 c += len(arg)
2025 }
2026
2027 if c < sys.ExecArgLengthLimit {
2028 return argv
2029 }
2030
2031
2032 response := filepath.Join(*flagTmpdir, "response")
2033 if err := os.WriteFile(response, nil, 0644); err != nil {
2034 log.Fatalf("failed while testing response file: %v", err)
2035 }
2036 if !linkerFlagSupported(ctxt.Arch, argv[0], altLinker, "@"+response) {
2037 if ctxt.Debugvlog != 0 {
2038 ctxt.Logf("not using response file because linker does not support one")
2039 }
2040 return argv
2041 }
2042
2043 var buf bytes.Buffer
2044 for _, arg := range argv[1:] {
2045
2046 fmt.Fprintf(&buf, "%q\n", arg)
2047 }
2048 if err := os.WriteFile(response, buf.Bytes(), 0644); err != nil {
2049 log.Fatalf("failed while writing response file: %v", err)
2050 }
2051 if ctxt.Debugvlog != 0 {
2052 ctxt.Logf("response file %s contents:\n%s", response, buf.Bytes())
2053 }
2054 return []string{
2055 argv[0],
2056 "@" + response,
2057 }
2058 }
2059
2060 var createTrivialCOnce sync.Once
2061
2062 func linkerFlagSupported(arch *sys.Arch, linker, altLinker, flag string) bool {
2063 createTrivialCOnce.Do(func() {
2064 src := filepath.Join(*flagTmpdir, "trivial.c")
2065 if err := os.WriteFile(src, []byte("int main() { return 0; }"), 0666); err != nil {
2066 Errorf(nil, "WriteFile trivial.c failed: %v", err)
2067 }
2068 })
2069
2070 flags := hostlinkArchArgs(arch)
2071
2072 moreFlags := trimLinkerArgv(append(flagExtldflags, ldflag...))
2073 flags = append(flags, moreFlags...)
2074
2075 if altLinker != "" {
2076 flags = append(flags, "-fuse-ld="+altLinker)
2077 }
2078 trivialPath := filepath.Join(*flagTmpdir, "trivial.c")
2079 outPath := filepath.Join(*flagTmpdir, "a.out")
2080 flags = append(flags, "-o", outPath, flag, trivialPath)
2081
2082 cmd := exec.Command(linker, flags...)
2083 cmd.Env = append([]string{"LC_ALL=C"}, os.Environ()...)
2084 out, err := cmd.CombinedOutput()
2085
2086
2087 return err == nil && !bytes.Contains(out, []byte("unrecognized")) && !bytes.Contains(out, []byte("unknown"))
2088 }
2089
2090
2091
2092 func trimLinkerArgv(argv []string) []string {
2093 flagsWithNextArgSkip := []string{
2094 "-F",
2095 "-l",
2096 "-L",
2097 "-framework",
2098 "-Wl,-framework",
2099 "-Wl,-rpath",
2100 "-Wl,-undefined",
2101 }
2102 flagsWithNextArgKeep := []string{
2103 "-arch",
2104 "-isysroot",
2105 "--sysroot",
2106 "-target",
2107 }
2108 prefixesToKeep := []string{
2109 "-f",
2110 "-m",
2111 "-p",
2112 "-Wl,",
2113 "-arch",
2114 "-isysroot",
2115 "--sysroot",
2116 "-target",
2117 }
2118
2119 var flags []string
2120 keep := false
2121 skip := false
2122 for _, f := range argv {
2123 if keep {
2124 flags = append(flags, f)
2125 keep = false
2126 } else if skip {
2127 skip = false
2128 } else if f == "" || f[0] != '-' {
2129 } else if contains(flagsWithNextArgSkip, f) {
2130 skip = true
2131 } else if contains(flagsWithNextArgKeep, f) {
2132 flags = append(flags, f)
2133 keep = true
2134 } else {
2135 for _, p := range prefixesToKeep {
2136 if strings.HasPrefix(f, p) {
2137 flags = append(flags, f)
2138 break
2139 }
2140 }
2141 }
2142 }
2143 return flags
2144 }
2145
2146
2147
2148 func hostlinkArchArgs(arch *sys.Arch) []string {
2149 switch arch.Family {
2150 case sys.I386:
2151 return []string{"-m32"}
2152 case sys.AMD64:
2153 if buildcfg.GOOS == "darwin" {
2154 return []string{"-arch", "x86_64", "-m64"}
2155 }
2156 return []string{"-m64"}
2157 case sys.S390X:
2158 return []string{"-m64"}
2159 case sys.ARM:
2160 return []string{"-marm"}
2161 case sys.ARM64:
2162 if buildcfg.GOOS == "darwin" {
2163 return []string{"-arch", "arm64"}
2164 }
2165 case sys.Loong64:
2166 return []string{"-mabi=lp64d"}
2167 case sys.MIPS64:
2168 return []string{"-mabi=64"}
2169 case sys.MIPS:
2170 return []string{"-mabi=32"}
2171 case sys.PPC64:
2172 if buildcfg.GOOS == "aix" {
2173 return []string{"-maix64"}
2174 } else {
2175 return []string{"-m64"}
2176 }
2177
2178 }
2179 return nil
2180 }
2181
2182 var wantHdr = objabi.HeaderString()
2183
2184
2185
2186
2187 func ldobj(ctxt *Link, f *bio.Reader, lib *sym.Library, length int64, pn string, file string) *Hostobj {
2188 pkg := objabi.PathToPrefix(lib.Pkg)
2189
2190 eof := f.Offset() + length
2191 start := f.Offset()
2192 c1 := bgetc(f)
2193 c2 := bgetc(f)
2194 c3 := bgetc(f)
2195 c4 := bgetc(f)
2196 f.MustSeek(start, 0)
2197
2198 unit := &sym.CompilationUnit{Lib: lib}
2199 lib.Units = append(lib.Units, unit)
2200
2201 magic := uint32(c1)<<24 | uint32(c2)<<16 | uint32(c3)<<8 | uint32(c4)
2202 if magic == 0x7f454c46 {
2203 ldelf := func(ctxt *Link, f *bio.Reader, pkg string, length int64, pn string) {
2204 textp, flags, err := loadelf.Load(ctxt.loader, ctxt.Arch, ctxt.IncVersion(), f, pkg, length, pn, ehdr.Flags)
2205 if err != nil {
2206 Errorf(nil, "%v", err)
2207 return
2208 }
2209 ehdr.Flags = flags
2210 ctxt.Textp = append(ctxt.Textp, textp...)
2211 }
2212 return ldhostobj(ldelf, ctxt.HeadType, f, pkg, length, pn, file)
2213 }
2214
2215 if magic&^1 == 0xfeedface || magic&^0x01000000 == 0xcefaedfe {
2216 ldmacho := func(ctxt *Link, f *bio.Reader, pkg string, length int64, pn string) {
2217 textp, err := loadmacho.Load(ctxt.loader, ctxt.Arch, ctxt.IncVersion(), f, pkg, length, pn)
2218 if err != nil {
2219 Errorf(nil, "%v", err)
2220 return
2221 }
2222 ctxt.Textp = append(ctxt.Textp, textp...)
2223 }
2224 return ldhostobj(ldmacho, ctxt.HeadType, f, pkg, length, pn, file)
2225 }
2226
2227 switch c1<<8 | c2 {
2228 case 0x4c01,
2229 0x6486,
2230 0xc401,
2231 0x64aa:
2232 ldpe := func(ctxt *Link, f *bio.Reader, pkg string, length int64, pn string) {
2233 ls, err := loadpe.Load(ctxt.loader, ctxt.Arch, ctxt.IncVersion(), f, pkg, length, pn)
2234 if err != nil {
2235 Errorf(nil, "%v", err)
2236 return
2237 }
2238 if len(ls.Resources) != 0 {
2239 setpersrc(ctxt, ls.Resources)
2240 }
2241 if ls.PData != 0 {
2242 sehp.pdata = append(sehp.pdata, ls.PData)
2243 }
2244 if ls.XData != 0 {
2245 sehp.xdata = append(sehp.xdata, ls.XData)
2246 }
2247 ctxt.Textp = append(ctxt.Textp, ls.Textp...)
2248 }
2249 return ldhostobj(ldpe, ctxt.HeadType, f, pkg, length, pn, file)
2250 }
2251
2252 if c1 == 0x01 && (c2 == 0xD7 || c2 == 0xF7) {
2253 ldxcoff := func(ctxt *Link, f *bio.Reader, pkg string, length int64, pn string) {
2254 textp, err := loadxcoff.Load(ctxt.loader, ctxt.Arch, ctxt.IncVersion(), f, pkg, length, pn)
2255 if err != nil {
2256 Errorf(nil, "%v", err)
2257 return
2258 }
2259 ctxt.Textp = append(ctxt.Textp, textp...)
2260 }
2261 return ldhostobj(ldxcoff, ctxt.HeadType, f, pkg, length, pn, file)
2262 }
2263
2264 if c1 != 'g' || c2 != 'o' || c3 != ' ' || c4 != 'o' {
2265
2266
2267
2268 unknownObjFormat = true
2269 return ldhostobj(nil, ctxt.HeadType, f, pkg, length, pn, file)
2270 }
2271
2272
2273 line, err := f.ReadString('\n')
2274 if err != nil {
2275 Errorf(nil, "truncated object file: %s: %v", pn, err)
2276 return nil
2277 }
2278
2279 if !strings.HasPrefix(line, "go object ") {
2280 if strings.HasSuffix(pn, ".go") {
2281 Exitf("%s: uncompiled .go source file", pn)
2282 return nil
2283 }
2284
2285 if line == ctxt.Arch.Name {
2286
2287 Errorf(nil, "%s: stale object file", pn)
2288 return nil
2289 }
2290
2291 Errorf(nil, "%s: not an object file: @%d %q", pn, start, line)
2292 return nil
2293 }
2294
2295
2296 if line != wantHdr {
2297 Errorf(nil, "%s: linked object header mismatch:\nhave %q\nwant %q\n", pn, line, wantHdr)
2298 }
2299
2300
2301
2302
2303
2304
2305
2306
2307 import0 := f.Offset()
2308
2309 c1 = '\n'
2310 c2 = bgetc(f)
2311 c3 = bgetc(f)
2312 markers := 0
2313 for {
2314 if c1 == '\n' {
2315 if markers%2 == 0 && c2 == '!' && c3 == '\n' {
2316 break
2317 }
2318 if c2 == '$' && c3 == '$' {
2319 markers++
2320 }
2321 }
2322
2323 c1 = c2
2324 c2 = c3
2325 c3 = bgetc(f)
2326 if c3 == -1 {
2327 Errorf(nil, "truncated object file: %s", pn)
2328 return nil
2329 }
2330 }
2331
2332 import1 := f.Offset()
2333
2334 f.MustSeek(import0, 0)
2335 ldpkg(ctxt, f, lib, import1-import0-2, pn)
2336 f.MustSeek(import1, 0)
2337
2338 fingerprint := ctxt.loader.Preload(ctxt.IncVersion(), f, lib, unit, eof-f.Offset())
2339 if !fingerprint.IsZero() {
2340
2341
2342
2343
2344
2345 if lib.Fingerprint.IsZero() {
2346 lib.Fingerprint = fingerprint
2347 }
2348 checkFingerprint(lib, fingerprint, lib.Srcref, lib.Fingerprint)
2349 }
2350
2351 addImports(ctxt, lib, pn)
2352 return nil
2353 }
2354
2355
2356
2357
2358
2359 func symbolsAreUnresolved(ctxt *Link, want []string) []bool {
2360 returnAllUndefs := -1
2361 undefs, _ := ctxt.loader.UndefinedRelocTargets(returnAllUndefs)
2362 seen := make(map[loader.Sym]struct{})
2363 rval := make([]bool, len(want))
2364 wantm := make(map[string]int)
2365 for k, w := range want {
2366 wantm[w] = k
2367 }
2368 count := 0
2369 for _, s := range undefs {
2370 if _, ok := seen[s]; ok {
2371 continue
2372 }
2373 seen[s] = struct{}{}
2374 if k, ok := wantm[ctxt.loader.SymName(s)]; ok {
2375 rval[k] = true
2376 count++
2377 if count == len(want) {
2378 return rval
2379 }
2380 }
2381 }
2382 return rval
2383 }
2384
2385
2386
2387
2388 func hostObject(ctxt *Link, objname string, path string) {
2389 if ctxt.Debugvlog > 1 {
2390 ctxt.Logf("hostObject(%s)\n", path)
2391 }
2392 objlib := sym.Library{
2393 Pkg: objname,
2394 }
2395 f, err := bio.Open(path)
2396 if err != nil {
2397 Exitf("cannot open host object %q file %s: %v", objname, path, err)
2398 }
2399 defer f.Close()
2400 h := ldobj(ctxt, f, &objlib, 0, path, path)
2401 if h.ld == nil {
2402 Exitf("unrecognized object file format in %s", path)
2403 }
2404 h.file = path
2405 h.length = f.MustSeek(0, 2)
2406 f.MustSeek(h.off, 0)
2407 h.ld(ctxt, f, h.pkg, h.length, h.pn)
2408 if *flagCaptureHostObjs != "" {
2409 captureHostObj(h)
2410 }
2411 }
2412
2413 func checkFingerprint(lib *sym.Library, libfp goobj.FingerprintType, src string, srcfp goobj.FingerprintType) {
2414 if libfp != srcfp {
2415 Exitf("fingerprint mismatch: %s has %x, import from %s expecting %x", lib, libfp, src, srcfp)
2416 }
2417 }
2418
2419 func readelfsymboldata(ctxt *Link, f *elf.File, sym *elf.Symbol) []byte {
2420 data := make([]byte, sym.Size)
2421 sect := f.Sections[sym.Section]
2422 if sect.Type != elf.SHT_PROGBITS && sect.Type != elf.SHT_NOTE {
2423 Errorf(nil, "reading %s from non-data section", sym.Name)
2424 }
2425 n, err := sect.ReadAt(data, int64(sym.Value-sect.Addr))
2426 if uint64(n) != sym.Size {
2427 Errorf(nil, "reading contents of %s: %v", sym.Name, err)
2428 }
2429 return data
2430 }
2431
2432 func readwithpad(r io.Reader, sz int32) ([]byte, error) {
2433 data := make([]byte, Rnd(int64(sz), 4))
2434 _, err := io.ReadFull(r, data)
2435 if err != nil {
2436 return nil, err
2437 }
2438 data = data[:sz]
2439 return data, nil
2440 }
2441
2442 func readnote(f *elf.File, name []byte, typ int32) ([]byte, error) {
2443 for _, sect := range f.Sections {
2444 if sect.Type != elf.SHT_NOTE {
2445 continue
2446 }
2447 r := sect.Open()
2448 for {
2449 var namesize, descsize, noteType int32
2450 err := binary.Read(r, f.ByteOrder, &namesize)
2451 if err != nil {
2452 if err == io.EOF {
2453 break
2454 }
2455 return nil, fmt.Errorf("read namesize failed: %v", err)
2456 }
2457 err = binary.Read(r, f.ByteOrder, &descsize)
2458 if err != nil {
2459 return nil, fmt.Errorf("read descsize failed: %v", err)
2460 }
2461 err = binary.Read(r, f.ByteOrder, ¬eType)
2462 if err != nil {
2463 return nil, fmt.Errorf("read type failed: %v", err)
2464 }
2465 noteName, err := readwithpad(r, namesize)
2466 if err != nil {
2467 return nil, fmt.Errorf("read name failed: %v", err)
2468 }
2469 desc, err := readwithpad(r, descsize)
2470 if err != nil {
2471 return nil, fmt.Errorf("read desc failed: %v", err)
2472 }
2473 if string(name) == string(noteName) && typ == noteType {
2474 return desc, nil
2475 }
2476 }
2477 }
2478 return nil, nil
2479 }
2480
2481 func findshlib(ctxt *Link, shlib string) string {
2482 if filepath.IsAbs(shlib) {
2483 return shlib
2484 }
2485 for _, libdir := range ctxt.Libdir {
2486 libpath := filepath.Join(libdir, shlib)
2487 if _, err := os.Stat(libpath); err == nil {
2488 return libpath
2489 }
2490 }
2491 Errorf(nil, "cannot find shared library: %s", shlib)
2492 return ""
2493 }
2494
2495 func ldshlibsyms(ctxt *Link, shlib string) {
2496 var libpath string
2497 if filepath.IsAbs(shlib) {
2498 libpath = shlib
2499 shlib = filepath.Base(shlib)
2500 } else {
2501 libpath = findshlib(ctxt, shlib)
2502 if libpath == "" {
2503 return
2504 }
2505 }
2506 for _, processedlib := range ctxt.Shlibs {
2507 if processedlib.Path == libpath {
2508 return
2509 }
2510 }
2511 if ctxt.Debugvlog > 1 {
2512 ctxt.Logf("ldshlibsyms: found library with name %s at %s\n", shlib, libpath)
2513 }
2514
2515 f, err := elf.Open(libpath)
2516 if err != nil {
2517 Errorf(nil, "cannot open shared library: %s", libpath)
2518 return
2519 }
2520
2521
2522
2523
2524 hash, err := readnote(f, ELF_NOTE_GO_NAME, ELF_NOTE_GOABIHASH_TAG)
2525 if err != nil {
2526 Errorf(nil, "cannot read ABI hash from shared library %s: %v", libpath, err)
2527 return
2528 }
2529
2530 depsbytes, err := readnote(f, ELF_NOTE_GO_NAME, ELF_NOTE_GODEPS_TAG)
2531 if err != nil {
2532 Errorf(nil, "cannot read dep list from shared library %s: %v", libpath, err)
2533 return
2534 }
2535 var deps []string
2536 for _, dep := range strings.Split(string(depsbytes), "\n") {
2537 if dep == "" {
2538 continue
2539 }
2540 if !filepath.IsAbs(dep) {
2541
2542
2543
2544 abs := filepath.Join(filepath.Dir(libpath), dep)
2545 if _, err := os.Stat(abs); err == nil {
2546 dep = abs
2547 }
2548 }
2549 deps = append(deps, dep)
2550 }
2551
2552 syms, err := f.DynamicSymbols()
2553 if err != nil {
2554 Errorf(nil, "cannot read symbols from shared library: %s", libpath)
2555 return
2556 }
2557
2558 for _, elfsym := range syms {
2559 if elf.ST_TYPE(elfsym.Info) == elf.STT_NOTYPE || elf.ST_TYPE(elfsym.Info) == elf.STT_SECTION {
2560 continue
2561 }
2562
2563
2564
2565 ver := 0
2566 symname := elfsym.Name
2567 if elf.ST_TYPE(elfsym.Info) == elf.STT_FUNC && strings.HasPrefix(elfsym.Name, "type:") {
2568 ver = abiInternalVer
2569 } else if buildcfg.Experiment.RegabiWrappers && elf.ST_TYPE(elfsym.Info) == elf.STT_FUNC {
2570
2571 if strings.HasSuffix(elfsym.Name, ".abiinternal") {
2572 ver = sym.SymVerABIInternal
2573 symname = strings.TrimSuffix(elfsym.Name, ".abiinternal")
2574 } else if strings.HasSuffix(elfsym.Name, ".abi0") {
2575 ver = 0
2576 symname = strings.TrimSuffix(elfsym.Name, ".abi0")
2577 }
2578 }
2579
2580 l := ctxt.loader
2581 s := l.LookupOrCreateSym(symname, ver)
2582
2583
2584
2585
2586
2587 if l.SymType(s) != 0 && l.SymType(s) != sym.SDYNIMPORT {
2588 continue
2589 }
2590 su := l.MakeSymbolUpdater(s)
2591 su.SetType(sym.SDYNIMPORT)
2592 l.SetSymElfType(s, elf.ST_TYPE(elfsym.Info))
2593 su.SetSize(int64(elfsym.Size))
2594 if elfsym.Section != elf.SHN_UNDEF {
2595
2596 l.SetSymPkg(s, libpath)
2597
2598
2599
2600 sname := l.SymName(s)
2601 if strings.HasPrefix(sname, "type:") && !strings.HasPrefix(sname, "type:.") {
2602 su.SetData(readelfsymboldata(ctxt, f, &elfsym))
2603 }
2604 }
2605
2606 if symname != elfsym.Name {
2607 l.SetSymExtname(s, elfsym.Name)
2608 }
2609 }
2610 ctxt.Shlibs = append(ctxt.Shlibs, Shlib{Path: libpath, Hash: hash, Deps: deps, File: f})
2611 }
2612
2613 func addsection(ldr *loader.Loader, arch *sys.Arch, seg *sym.Segment, name string, rwx int) *sym.Section {
2614 sect := ldr.NewSection()
2615 sect.Rwx = uint8(rwx)
2616 sect.Name = name
2617 sect.Seg = seg
2618 sect.Align = int32(arch.PtrSize)
2619 seg.Sections = append(seg.Sections, sect)
2620 return sect
2621 }
2622
2623 func usage() {
2624 fmt.Fprintf(os.Stderr, "usage: link [options] main.o\n")
2625 objabi.Flagprint(os.Stderr)
2626 Exit(2)
2627 }
2628
2629 type SymbolType int8
2630
2631 const (
2632
2633 TextSym SymbolType = 'T'
2634 DataSym SymbolType = 'D'
2635 BSSSym SymbolType = 'B'
2636 UndefinedSym SymbolType = 'U'
2637 TLSSym SymbolType = 't'
2638 FrameSym SymbolType = 'm'
2639 ParamSym SymbolType = 'p'
2640 AutoSym SymbolType = 'a'
2641
2642
2643 DeletedAutoSym = 'x'
2644 )
2645
2646
2647 func (ctxt *Link) defineInternal(p string, t sym.SymKind) loader.Sym {
2648 s := ctxt.loader.CreateSymForUpdate(p, 0)
2649 s.SetType(t)
2650 s.SetSpecial(true)
2651 s.SetLocal(true)
2652 return s.Sym()
2653 }
2654
2655 func (ctxt *Link) xdefine(p string, t sym.SymKind, v int64) loader.Sym {
2656 s := ctxt.defineInternal(p, t)
2657 ctxt.loader.SetSymValue(s, v)
2658 return s
2659 }
2660
2661 func datoff(ldr *loader.Loader, s loader.Sym, addr int64) int64 {
2662 if uint64(addr) >= Segdata.Vaddr {
2663 return int64(uint64(addr) - Segdata.Vaddr + Segdata.Fileoff)
2664 }
2665 if uint64(addr) >= Segtext.Vaddr {
2666 return int64(uint64(addr) - Segtext.Vaddr + Segtext.Fileoff)
2667 }
2668 ldr.Errorf(s, "invalid datoff %#x", addr)
2669 return 0
2670 }
2671
2672 func Entryvalue(ctxt *Link) int64 {
2673 a := *flagEntrySymbol
2674 if a[0] >= '0' && a[0] <= '9' {
2675 return atolwhex(a)
2676 }
2677 ldr := ctxt.loader
2678 s := ldr.Lookup(a, 0)
2679 if s == 0 {
2680 Errorf(nil, "missing entry symbol %q", a)
2681 return 0
2682 }
2683 st := ldr.SymType(s)
2684 if st == 0 {
2685 return *FlagTextAddr
2686 }
2687 if !ctxt.IsAIX() && st != sym.STEXT {
2688 ldr.Errorf(s, "entry not text")
2689 }
2690 return ldr.SymValue(s)
2691 }
2692
2693 func (ctxt *Link) callgraph() {
2694 if !*FlagC {
2695 return
2696 }
2697
2698 ldr := ctxt.loader
2699 for _, s := range ctxt.Textp {
2700 relocs := ldr.Relocs(s)
2701 for i := 0; i < relocs.Count(); i++ {
2702 r := relocs.At(i)
2703 rs := r.Sym()
2704 if rs == 0 {
2705 continue
2706 }
2707 if r.Type().IsDirectCall() && ldr.SymType(rs) == sym.STEXT {
2708 ctxt.Logf("%s calls %s\n", ldr.SymName(s), ldr.SymName(rs))
2709 }
2710 }
2711 }
2712 }
2713
2714 func Rnd(v int64, r int64) int64 {
2715 if r <= 0 {
2716 return v
2717 }
2718 v += r - 1
2719 c := v % r
2720 if c < 0 {
2721 c += r
2722 }
2723 v -= c
2724 return v
2725 }
2726
2727 func bgetc(r *bio.Reader) int {
2728 c, err := r.ReadByte()
2729 if err != nil {
2730 if err != io.EOF {
2731 log.Fatalf("reading input: %v", err)
2732 }
2733 return -1
2734 }
2735 return int(c)
2736 }
2737
2738 type markKind uint8
2739 const (
2740 _ markKind = iota
2741 visiting
2742 visited
2743 )
2744
2745 func postorder(libs []*sym.Library) []*sym.Library {
2746 order := make([]*sym.Library, 0, len(libs))
2747 mark := make(map[*sym.Library]markKind, len(libs))
2748 for _, lib := range libs {
2749 dfs(lib, mark, &order)
2750 }
2751 return order
2752 }
2753
2754 func dfs(lib *sym.Library, mark map[*sym.Library]markKind, order *[]*sym.Library) {
2755 if mark[lib] == visited {
2756 return
2757 }
2758 if mark[lib] == visiting {
2759 panic("found import cycle while visiting " + lib.Pkg)
2760 }
2761 mark[lib] = visiting
2762 for _, i := range lib.Imports {
2763 dfs(i, mark, order)
2764 }
2765 mark[lib] = visited
2766 *order = append(*order, lib)
2767 }
2768
2769 func ElfSymForReloc(ctxt *Link, s loader.Sym) int32 {
2770
2771
2772 les := ctxt.loader.SymLocalElfSym(s)
2773 if les != 0 {
2774 return les
2775 } else {
2776 return ctxt.loader.SymElfSym(s)
2777 }
2778 }
2779
2780 func AddGotSym(target *Target, ldr *loader.Loader, syms *ArchSyms, s loader.Sym, elfRelocTyp uint32) {
2781 if ldr.SymGot(s) >= 0 {
2782 return
2783 }
2784
2785 Adddynsym(ldr, target, syms, s)
2786 got := ldr.MakeSymbolUpdater(syms.GOT)
2787 ldr.SetGot(s, int32(got.Size()))
2788 got.AddUint(target.Arch, 0)
2789
2790 if target.IsElf() {
2791 if target.Arch.PtrSize == 8 {
2792 rela := ldr.MakeSymbolUpdater(syms.Rela)
2793 rela.AddAddrPlus(target.Arch, got.Sym(), int64(ldr.SymGot(s)))
2794 rela.AddUint64(target.Arch, elf.R_INFO(uint32(ldr.SymDynid(s)), elfRelocTyp))
2795 rela.AddUint64(target.Arch, 0)
2796 } else {
2797 rel := ldr.MakeSymbolUpdater(syms.Rel)
2798 rel.AddAddrPlus(target.Arch, got.Sym(), int64(ldr.SymGot(s)))
2799 rel.AddUint32(target.Arch, elf.R_INFO32(uint32(ldr.SymDynid(s)), elfRelocTyp))
2800 }
2801 } else if target.IsDarwin() {
2802 leg := ldr.MakeSymbolUpdater(syms.LinkEditGOT)
2803 leg.AddUint32(target.Arch, uint32(ldr.SymDynid(s)))
2804 if target.IsPIE() && target.IsInternal() {
2805
2806
2807
2808 MachoAddBind(int64(ldr.SymGot(s)), s)
2809 }
2810 } else {
2811 ldr.Errorf(s, "addgotsym: unsupported binary format")
2812 }
2813 }
2814
2815 var hostobjcounter int
2816
2817
2818
2819
2820
2821
2822 func captureHostObj(h *Hostobj) {
2823
2824 ofile := fmt.Sprintf("captured-obj-%d.o", hostobjcounter)
2825 ifile := fmt.Sprintf("captured-obj-%d.txt", hostobjcounter)
2826 hostobjcounter++
2827 opath := filepath.Join(*flagCaptureHostObjs, ofile)
2828 ipath := filepath.Join(*flagCaptureHostObjs, ifile)
2829
2830
2831 info := fmt.Sprintf("pkg: %s\npn: %s\nfile: %s\noff: %d\nlen: %d\n",
2832 h.pkg, h.pn, h.file, h.off, h.length)
2833 if err := os.WriteFile(ipath, []byte(info), 0666); err != nil {
2834 log.Fatalf("error writing captured host obj info %s: %v", ipath, err)
2835 }
2836
2837 readObjData := func() []byte {
2838 inf, err := os.Open(h.file)
2839 if err != nil {
2840 log.Fatalf("capturing host obj: open failed on %s: %v", h.pn, err)
2841 }
2842 res := make([]byte, h.length)
2843 if n, err := inf.ReadAt(res, h.off); err != nil || n != int(h.length) {
2844 log.Fatalf("capturing host obj: readat failed on %s: %v", h.pn, err)
2845 }
2846 return res
2847 }
2848
2849
2850 if err := os.WriteFile(opath, readObjData(), 0666); err != nil {
2851 log.Fatalf("error writing captured host object %s: %v", opath, err)
2852 }
2853
2854 fmt.Fprintf(os.Stderr, "link: info: captured host object %s to %s\n",
2855 h.file, opath)
2856 }
2857
View as plain text