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