Source file src/pkg/cmd/link/internal/ld/main.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 "cmd/internal/objabi"
36 "cmd/internal/sys"
37 "cmd/link/internal/sym"
38 "flag"
39 "log"
40 "os"
41 "runtime"
42 "runtime/pprof"
43 "strings"
44 )
45
46 var (
47 pkglistfornote []byte
48 windowsgui bool
49 )
50
51 func init() {
52 flag.Var(&rpath, "r", "set the ELF dynamic linker search `path` to dir1:dir2:...")
53 }
54
55
56 var (
57 flagBuildid = flag.String("buildid", "", "record `id` as Go toolchain build id")
58
59 flagOutfile = flag.String("o", "", "write output to `file`")
60 flagPluginPath = flag.String("pluginpath", "", "full path name for plugin")
61
62 flagInstallSuffix = flag.String("installsuffix", "", "set package directory `suffix`")
63 flagDumpDep = flag.Bool("dumpdep", false, "dump symbol dependency graph")
64 flagRace = flag.Bool("race", false, "enable race detector")
65 flagMsan = flag.Bool("msan", false, "enable MSan interface")
66
67 flagFieldTrack = flag.String("k", "", "set field tracking `symbol`")
68 flagLibGCC = flag.String("libgcc", "", "compiler support lib for internal linking; use \"none\" to disable")
69 flagTmpdir = flag.String("tmpdir", "", "use `directory` for temporary files")
70
71 flagExtld = flag.String("extld", "", "use `linker` when linking in external mode")
72 flagExtldflags = flag.String("extldflags", "", "pass `flags` to external linker")
73 flagExtar = flag.String("extar", "", "archive program for buildmode=c-archive")
74
75 flagA = flag.Bool("a", false, "disassemble output")
76 FlagC = flag.Bool("c", false, "dump call graph")
77 FlagD = flag.Bool("d", false, "disable dynamic executable")
78 flagF = flag.Bool("f", false, "ignore version mismatch")
79 flagG = flag.Bool("g", false, "disable go package data checks")
80 flagH = flag.Bool("h", false, "halt on error")
81 flagN = flag.Bool("n", false, "dump symbol table")
82 FlagS = flag.Bool("s", false, "disable symbol table")
83 flagU = flag.Bool("u", false, "reject unsafe packages")
84 FlagW = flag.Bool("w", false, "disable DWARF generation")
85 Flag8 bool
86 flagInterpreter = flag.String("I", "", "use `linker` as ELF dynamic linker")
87 FlagDebugTramp = flag.Int("debugtramp", 0, "debug trampolines")
88 FlagStrictDups = flag.Int("strictdups", 0, "sanity check duplicate symbol contents during object file reading (1=warn 2=err).")
89
90 FlagRound = flag.Int("R", -1, "set address rounding `quantum`")
91 FlagTextAddr = flag.Int64("T", -1, "set text segment `address`")
92 flagEntrySymbol = flag.String("E", "", "set `entry` symbol name")
93
94 cpuprofile = flag.String("cpuprofile", "", "write cpu profile to `file`")
95 memprofile = flag.String("memprofile", "", "write memory profile to `file`")
96 memprofilerate = flag.Int64("memprofilerate", 0, "set runtime.MemProfileRate to `rate`")
97 )
98
99
100 func Main(arch *sys.Arch, theArch Arch) {
101 thearch = theArch
102 ctxt := linknew(arch)
103 ctxt.Bso = bufio.NewWriter(os.Stdout)
104
105
106
107
108 for _, arg := range os.Args {
109 if arg == "-crash_for_testing" {
110 os.Exit(2)
111 }
112 }
113
114 final := gorootFinal()
115 addstrdata1(ctxt, "runtime/internal/sys.DefaultGoroot="+final)
116 addstrdata1(ctxt, "cmd/internal/objabi.defaultGOROOT="+final)
117
118
119 if ctxt.Arch.Family == sys.AMD64 && objabi.GOOS == "plan9" {
120 flag.BoolVar(&Flag8, "8", false, "use 64-bit addresses in symbol table")
121 }
122 flagHeadType := flag.String("H", "", "set header `type`")
123 flag.BoolVar(&ctxt.linkShared, "linkshared", false, "link against installed Go shared libraries")
124 flag.Var(&ctxt.LinkMode, "linkmode", "set link `mode`")
125 flag.Var(&ctxt.BuildMode, "buildmode", "set build `mode`")
126 flag.BoolVar(&ctxt.compressDWARF, "compressdwarf", true, "compress DWARF if possible")
127 objabi.Flagfn1("B", "add an ELF NT_GNU_BUILD_ID `note` when using ELF", addbuildinfo)
128 objabi.Flagfn1("L", "add specified `directory` to library path", func(a string) { Lflag(ctxt, a) })
129 objabi.AddVersionFlag()
130 objabi.Flagfn1("X", "add string value `definition` of the form importpath.name=value", func(s string) { addstrdata1(ctxt, s) })
131 objabi.Flagcount("v", "print link trace", &ctxt.Debugvlog)
132 objabi.Flagfn1("importcfg", "read import configuration from `file`", ctxt.readImportCfg)
133
134 objabi.Flagparse(usage)
135
136 switch *flagHeadType {
137 case "":
138 case "windowsgui":
139 ctxt.HeadType = objabi.Hwindows
140 windowsgui = true
141 default:
142 if err := ctxt.HeadType.Set(*flagHeadType); err != nil {
143 Errorf(nil, "%v", err)
144 usage()
145 }
146 }
147
148 if objabi.Fieldtrack_enabled != 0 {
149 ctxt.Reachparent = make(map[*sym.Symbol]*sym.Symbol)
150 }
151 checkStrictDups = *FlagStrictDups
152
153 startProfile()
154 if ctxt.BuildMode == BuildModeUnset {
155 ctxt.BuildMode = BuildModeExe
156 }
157
158 if ctxt.BuildMode != BuildModeShared && flag.NArg() != 1 {
159 usage()
160 }
161
162 if *flagOutfile == "" {
163 *flagOutfile = "a.out"
164 if ctxt.HeadType == objabi.Hwindows {
165 *flagOutfile += ".exe"
166 }
167 }
168
169 interpreter = *flagInterpreter
170
171 libinit(ctxt)
172
173 if ctxt.HeadType == objabi.Hunknown {
174 ctxt.HeadType.Set(objabi.GOOS)
175 }
176
177 ctxt.computeTLSOffset()
178 thearch.Archinit(ctxt)
179
180 if ctxt.linkShared && !ctxt.IsELF {
181 Exitf("-linkshared can only be used on elf systems")
182 }
183
184 if ctxt.Debugvlog != 0 {
185 ctxt.Logf("HEADER = -H%d -T0x%x -R0x%x\n", ctxt.HeadType, uint64(*FlagTextAddr), uint32(*FlagRound))
186 }
187
188 switch ctxt.BuildMode {
189 case BuildModeShared:
190 for i := 0; i < flag.NArg(); i++ {
191 arg := flag.Arg(i)
192 parts := strings.SplitN(arg, "=", 2)
193 var pkgpath, file string
194 if len(parts) == 1 {
195 pkgpath, file = "main", arg
196 } else {
197 pkgpath, file = parts[0], parts[1]
198 }
199 pkglistfornote = append(pkglistfornote, pkgpath...)
200 pkglistfornote = append(pkglistfornote, '\n')
201 addlibpath(ctxt, "command line", "command line", file, pkgpath, "")
202 }
203 case BuildModePlugin:
204 addlibpath(ctxt, "command line", "command line", flag.Arg(0), *flagPluginPath, "")
205 default:
206 addlibpath(ctxt, "command line", "command line", flag.Arg(0), "main", "")
207 }
208 ctxt.loadlib()
209
210 ctxt.dostrdata()
211 deadcode(ctxt)
212 dwarfGenerateDebugInfo(ctxt)
213 if objabi.Fieldtrack_enabled != 0 {
214 fieldtrack(ctxt)
215 }
216 ctxt.mangleTypeSym()
217 ctxt.callgraph()
218
219 ctxt.doelf()
220 if ctxt.HeadType == objabi.Hdarwin {
221 ctxt.domacho()
222 }
223 ctxt.dostkcheck()
224 if ctxt.HeadType == objabi.Hwindows {
225 ctxt.dope()
226 ctxt.windynrelocsyms()
227 }
228 if ctxt.HeadType == objabi.Haix {
229 ctxt.doxcoff()
230 }
231
232 ctxt.addexport()
233 thearch.Gentext(ctxt)
234 ctxt.textbuildid()
235 ctxt.textaddress()
236 ctxt.pclntab()
237 ctxt.findfunctab()
238 ctxt.typelink()
239 ctxt.symtab()
240 ctxt.buildinfo()
241 ctxt.dodata()
242 order := ctxt.address()
243 dwarfcompress(ctxt)
244 filesize := ctxt.layout(order)
245
246
247
248
249
250
251
252 var outputMmapped bool
253 if ctxt.Arch.Family != sys.Wasm {
254
255
256 err := ctxt.Out.Mmap(filesize)
257 outputMmapped = err == nil
258 }
259 if outputMmapped {
260
261
262 thearch.Asmb(ctxt)
263 ctxt.reloc()
264 ctxt.Out.Munmap()
265 } else {
266
267
268 ctxt.reloc()
269 thearch.Asmb(ctxt)
270 }
271 thearch.Asmb2(ctxt)
272
273 ctxt.undef()
274 ctxt.hostlink()
275 ctxt.archive()
276 if ctxt.Debugvlog != 0 {
277 ctxt.Logf("%5.2f cpu time\n", Cputime())
278 ctxt.Logf("%d symbols\n", len(ctxt.Syms.Allsym))
279 ctxt.Logf("%d liveness data\n", liveness)
280 }
281
282 ctxt.Bso.Flush()
283
284 errorexit()
285 }
286
287 type Rpath struct {
288 set bool
289 val string
290 }
291
292 func (r *Rpath) Set(val string) error {
293 r.set = true
294 r.val = val
295 return nil
296 }
297
298 func (r *Rpath) String() string {
299 return r.val
300 }
301
302 func startProfile() {
303 if *cpuprofile != "" {
304 f, err := os.Create(*cpuprofile)
305 if err != nil {
306 log.Fatalf("%v", err)
307 }
308 if err := pprof.StartCPUProfile(f); err != nil {
309 log.Fatalf("%v", err)
310 }
311 AtExit(pprof.StopCPUProfile)
312 }
313 if *memprofile != "" {
314 if *memprofilerate != 0 {
315 runtime.MemProfileRate = int(*memprofilerate)
316 }
317 f, err := os.Create(*memprofile)
318 if err != nil {
319 log.Fatalf("%v", err)
320 }
321 AtExit(func() {
322
323 runtime.GC()
324
325
326
327 const writeLegacyFormat = 1
328 if err := pprof.Lookup("heap").WriteTo(f, writeLegacyFormat); err != nil {
329 log.Fatalf("%v", err)
330 }
331 })
332 }
333 }
334
View as plain text