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