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