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