]> git.lizzy.rs Git - rust.git/blob - src/librustc_codegen_ssa/back/linker.rs
Rollup merge of #64838 - GuillaumeGomez:long-err-explanation-e0550, r=oli-obk
[rust.git] / src / librustc_codegen_ssa / back / linker.rs
1 use super::symbol_export;
2 use super::command::Command;
3 use super::archive;
4
5 use rustc_data_structures::fx::FxHashMap;
6 use std::ffi::{OsStr, OsString};
7 use std::fs::{self, File};
8 use std::io::prelude::*;
9 use std::io::{self, BufWriter};
10 use std::path::{Path, PathBuf};
11
12 use rustc::hir::def_id::{LOCAL_CRATE, CrateNum};
13 use rustc::middle::dependency_format::Linkage;
14 use rustc::session::Session;
15 use rustc::session::config::{self, CrateType, OptLevel, DebugInfo,
16                              LinkerPluginLto, Lto};
17 use rustc::middle::exported_symbols::ExportedSymbol;
18 use rustc::ty::TyCtxt;
19 use rustc_target::spec::{LinkerFlavor, LldFlavor};
20 use rustc_serialize::{json, Encoder};
21 use syntax::symbol::Symbol;
22
23 /// For all the linkers we support, and information they might
24 /// need out of the shared crate context before we get rid of it.
25 pub struct LinkerInfo {
26     exports: FxHashMap<CrateType, Vec<String>>,
27 }
28
29 impl LinkerInfo {
30     pub fn new(tcx: TyCtxt<'_>) -> LinkerInfo {
31         LinkerInfo {
32             exports: tcx.sess.crate_types.borrow().iter().map(|&c| {
33                 (c, exported_symbols(tcx, c))
34             }).collect(),
35         }
36     }
37
38     pub fn to_linker<'a>(
39         &'a self,
40         cmd: Command,
41         sess: &'a Session,
42         flavor: LinkerFlavor,
43         target_cpu: &'a str,
44     ) -> Box<dyn Linker+'a> {
45         match flavor {
46             LinkerFlavor::Lld(LldFlavor::Link) |
47             LinkerFlavor::Msvc => {
48                 Box::new(MsvcLinker {
49                     cmd,
50                     sess,
51                     info: self
52                 }) as Box<dyn Linker>
53             }
54             LinkerFlavor::Em =>  {
55                 Box::new(EmLinker {
56                     cmd,
57                     sess,
58                     info: self
59                 }) as Box<dyn Linker>
60             }
61             LinkerFlavor::Gcc =>  {
62                 Box::new(GccLinker {
63                     cmd,
64                     sess,
65                     info: self,
66                     hinted_static: false,
67                     is_ld: false,
68                     target_cpu,
69                 }) as Box<dyn Linker>
70             }
71
72             LinkerFlavor::Lld(LldFlavor::Ld) |
73             LinkerFlavor::Lld(LldFlavor::Ld64) |
74             LinkerFlavor::Ld => {
75                 Box::new(GccLinker {
76                     cmd,
77                     sess,
78                     info: self,
79                     hinted_static: false,
80                     is_ld: true,
81                     target_cpu,
82                 }) as Box<dyn Linker>
83             }
84
85             LinkerFlavor::Lld(LldFlavor::Wasm) => {
86                 Box::new(WasmLd::new(cmd, sess, self)) as Box<dyn Linker>
87             }
88
89             LinkerFlavor::PtxLinker => {
90                 Box::new(PtxLinker { cmd, sess }) as Box<dyn Linker>
91             }
92         }
93     }
94 }
95
96 /// Linker abstraction used by `back::link` to build up the command to invoke a
97 /// linker.
98 ///
99 /// This trait is the total list of requirements needed by `back::link` and
100 /// represents the meaning of each option being passed down. This trait is then
101 /// used to dispatch on whether a GNU-like linker (generally `ld.exe`) or an
102 /// MSVC linker (e.g., `link.exe`) is being used.
103 pub trait Linker {
104     fn link_dylib(&mut self, lib: Symbol);
105     fn link_rust_dylib(&mut self, lib: Symbol, path: &Path);
106     fn link_framework(&mut self, framework: Symbol);
107     fn link_staticlib(&mut self, lib: Symbol);
108     fn link_rlib(&mut self, lib: &Path);
109     fn link_whole_rlib(&mut self, lib: &Path);
110     fn link_whole_staticlib(&mut self, lib: Symbol, search_path: &[PathBuf]);
111     fn include_path(&mut self, path: &Path);
112     fn framework_path(&mut self, path: &Path);
113     fn output_filename(&mut self, path: &Path);
114     fn add_object(&mut self, path: &Path);
115     fn gc_sections(&mut self, keep_metadata: bool);
116     fn position_independent_executable(&mut self);
117     fn no_position_independent_executable(&mut self);
118     fn full_relro(&mut self);
119     fn partial_relro(&mut self);
120     fn no_relro(&mut self);
121     fn optimize(&mut self);
122     fn pgo_gen(&mut self);
123     fn debuginfo(&mut self);
124     fn no_default_libraries(&mut self);
125     fn build_dylib(&mut self, out_filename: &Path);
126     fn build_static_executable(&mut self);
127     fn args(&mut self, args: &[String]);
128     fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType);
129     fn subsystem(&mut self, subsystem: &str);
130     fn group_start(&mut self);
131     fn group_end(&mut self);
132     fn linker_plugin_lto(&mut self);
133     // Should have been finalize(self), but we don't support self-by-value on trait objects (yet?).
134     fn finalize(&mut self) -> Command;
135 }
136
137 pub struct GccLinker<'a> {
138     cmd: Command,
139     sess: &'a Session,
140     info: &'a LinkerInfo,
141     hinted_static: bool, // Keeps track of the current hinting mode.
142     // Link as ld
143     is_ld: bool,
144     target_cpu: &'a str,
145 }
146
147 impl<'a> GccLinker<'a> {
148     /// Argument that must be passed *directly* to the linker
149     ///
150     /// These arguments need to be prepended with `-Wl`, when a GCC-style linker is used.
151     fn linker_arg<S>(&mut self, arg: S) -> &mut Self
152         where S: AsRef<OsStr>
153     {
154         if !self.is_ld {
155             let mut os = OsString::from("-Wl,");
156             os.push(arg.as_ref());
157             self.cmd.arg(os);
158         } else {
159             self.cmd.arg(arg);
160         }
161         self
162     }
163
164     fn takes_hints(&self) -> bool {
165         // Really this function only returns true if the underlying linker
166         // configured for a compiler is binutils `ld.bfd` and `ld.gold`. We
167         // don't really have a foolproof way to detect that, so rule out some
168         // platforms where currently this is guaranteed to *not* be the case:
169         //
170         // * On OSX they have their own linker, not binutils'
171         // * For WebAssembly the only functional linker is LLD, which doesn't
172         //   support hint flags
173         !self.sess.target.target.options.is_like_osx &&
174             self.sess.target.target.arch != "wasm32"
175     }
176
177     // Some platforms take hints about whether a library is static or dynamic.
178     // For those that support this, we ensure we pass the option if the library
179     // was flagged "static" (most defaults are dynamic) to ensure that if
180     // libfoo.a and libfoo.so both exist that the right one is chosen.
181     fn hint_static(&mut self) {
182         if !self.takes_hints() { return }
183         if !self.hinted_static {
184             self.linker_arg("-Bstatic");
185             self.hinted_static = true;
186         }
187     }
188
189     fn hint_dynamic(&mut self) {
190         if !self.takes_hints() { return }
191         if self.hinted_static {
192             self.linker_arg("-Bdynamic");
193             self.hinted_static = false;
194         }
195     }
196
197     fn push_linker_plugin_lto_args(&mut self, plugin_path: Option<&OsStr>) {
198         if let Some(plugin_path) = plugin_path {
199             let mut arg = OsString::from("-plugin=");
200             arg.push(plugin_path);
201             self.linker_arg(&arg);
202         }
203
204         let opt_level = match self.sess.opts.optimize {
205             config::OptLevel::No => "O0",
206             config::OptLevel::Less => "O1",
207             config::OptLevel::Default => "O2",
208             config::OptLevel::Aggressive => "O3",
209             config::OptLevel::Size => "Os",
210             config::OptLevel::SizeMin => "Oz",
211         };
212
213         self.linker_arg(&format!("-plugin-opt={}", opt_level));
214         let target_cpu = self.target_cpu;
215         self.linker_arg(&format!("-plugin-opt=mcpu={}", target_cpu));
216     }
217 }
218
219 impl<'a> Linker for GccLinker<'a> {
220     fn link_dylib(&mut self, lib: Symbol) {
221         self.hint_dynamic();
222         self.cmd.arg(format!("-l{}", lib));
223     }
224     fn link_staticlib(&mut self, lib: Symbol) {
225         self.hint_static();
226         self.cmd.arg(format!("-l{}", lib));
227     }
228     fn link_rlib(&mut self, lib: &Path) { self.hint_static(); self.cmd.arg(lib); }
229     fn include_path(&mut self, path: &Path) { self.cmd.arg("-L").arg(path); }
230     fn framework_path(&mut self, path: &Path) { self.cmd.arg("-F").arg(path); }
231     fn output_filename(&mut self, path: &Path) { self.cmd.arg("-o").arg(path); }
232     fn add_object(&mut self, path: &Path) { self.cmd.arg(path); }
233     fn position_independent_executable(&mut self) { self.cmd.arg("-pie"); }
234     fn no_position_independent_executable(&mut self) { self.cmd.arg("-no-pie"); }
235     fn full_relro(&mut self) { self.linker_arg("-zrelro"); self.linker_arg("-znow"); }
236     fn partial_relro(&mut self) { self.linker_arg("-zrelro"); }
237     fn no_relro(&mut self) { self.linker_arg("-znorelro"); }
238     fn build_static_executable(&mut self) { self.cmd.arg("-static"); }
239     fn args(&mut self, args: &[String]) { self.cmd.args(args); }
240
241     fn link_rust_dylib(&mut self, lib: Symbol, _path: &Path) {
242         self.hint_dynamic();
243         self.cmd.arg(format!("-l{}", lib));
244     }
245
246     fn link_framework(&mut self, framework: Symbol) {
247         self.hint_dynamic();
248         self.cmd.arg("-framework").sym_arg(framework);
249     }
250
251     // Here we explicitly ask that the entire archive is included into the
252     // result artifact. For more details see #15460, but the gist is that
253     // the linker will strip away any unused objects in the archive if we
254     // don't otherwise explicitly reference them. This can occur for
255     // libraries which are just providing bindings, libraries with generic
256     // functions, etc.
257     fn link_whole_staticlib(&mut self, lib: Symbol, search_path: &[PathBuf]) {
258         self.hint_static();
259         let target = &self.sess.target.target;
260         if !target.options.is_like_osx {
261             self.linker_arg("--whole-archive").cmd.arg(format!("-l{}", lib));
262             self.linker_arg("--no-whole-archive");
263         } else {
264             // -force_load is the macOS equivalent of --whole-archive, but it
265             // involves passing the full path to the library to link.
266             self.linker_arg("-force_load");
267             let lib = archive::find_library(lib, search_path, &self.sess);
268             self.linker_arg(&lib);
269         }
270     }
271
272     fn link_whole_rlib(&mut self, lib: &Path) {
273         self.hint_static();
274         if self.sess.target.target.options.is_like_osx {
275             self.linker_arg("-force_load");
276             self.linker_arg(&lib);
277         } else {
278             self.linker_arg("--whole-archive").cmd.arg(lib);
279             self.linker_arg("--no-whole-archive");
280         }
281     }
282
283     fn gc_sections(&mut self, keep_metadata: bool) {
284         // The dead_strip option to the linker specifies that functions and data
285         // unreachable by the entry point will be removed. This is quite useful
286         // with Rust's compilation model of compiling libraries at a time into
287         // one object file. For example, this brings hello world from 1.7MB to
288         // 458K.
289         //
290         // Note that this is done for both executables and dynamic libraries. We
291         // won't get much benefit from dylibs because LLVM will have already
292         // stripped away as much as it could. This has not been seen to impact
293         // link times negatively.
294         //
295         // -dead_strip can't be part of the pre_link_args because it's also used
296         // for partial linking when using multiple codegen units (-r).  So we
297         // insert it here.
298         if self.sess.target.target.options.is_like_osx {
299             self.linker_arg("-dead_strip");
300         } else if self.sess.target.target.options.is_like_solaris {
301             self.linker_arg("-zignore");
302
303         // If we're building a dylib, we don't use --gc-sections because LLVM
304         // has already done the best it can do, and we also don't want to
305         // eliminate the metadata. If we're building an executable, however,
306         // --gc-sections drops the size of hello world from 1.8MB to 597K, a 67%
307         // reduction.
308         } else if !keep_metadata {
309             self.linker_arg("--gc-sections");
310         }
311     }
312
313     fn optimize(&mut self) {
314         if !self.sess.target.target.options.linker_is_gnu { return }
315
316         // GNU-style linkers support optimization with -O. GNU ld doesn't
317         // need a numeric argument, but other linkers do.
318         if self.sess.opts.optimize == config::OptLevel::Default ||
319            self.sess.opts.optimize == config::OptLevel::Aggressive {
320             self.linker_arg("-O1");
321         }
322     }
323
324     fn pgo_gen(&mut self) {
325         if !self.sess.target.target.options.linker_is_gnu { return }
326
327         // If we're doing PGO generation stuff and on a GNU-like linker, use the
328         // "-u" flag to properly pull in the profiler runtime bits.
329         //
330         // This is because LLVM otherwise won't add the needed initialization
331         // for us on Linux (though the extra flag should be harmless if it
332         // does).
333         //
334         // See https://reviews.llvm.org/D14033 and https://reviews.llvm.org/D14030.
335         //
336         // Though it may be worth to try to revert those changes upstream, since
337         // the overhead of the initialization should be minor.
338         self.cmd.arg("-u");
339         self.cmd.arg("__llvm_profile_runtime");
340     }
341
342     fn debuginfo(&mut self) {
343         if let DebugInfo::None = self.sess.opts.debuginfo {
344             // If we are building without debuginfo enabled and we were called with
345             // `-Zstrip-debuginfo-if-disabled=yes`, tell the linker to strip any debuginfo
346             // found when linking to get rid of symbols from libstd.
347             if let Some(true) = self.sess.opts.debugging_opts.strip_debuginfo_if_disabled {
348                 self.linker_arg("-S");
349             }
350         };
351     }
352
353     fn no_default_libraries(&mut self) {
354         if !self.is_ld {
355             self.cmd.arg("-nodefaultlibs");
356         }
357     }
358
359     fn build_dylib(&mut self, out_filename: &Path) {
360         // On mac we need to tell the linker to let this library be rpathed
361         if self.sess.target.target.options.is_like_osx {
362             self.cmd.arg("-dynamiclib");
363             self.linker_arg("-dylib");
364
365             // Note that the `osx_rpath_install_name` option here is a hack
366             // purely to support rustbuild right now, we should get a more
367             // principled solution at some point to force the compiler to pass
368             // the right `-Wl,-install_name` with an `@rpath` in it.
369             if self.sess.opts.cg.rpath || self.sess.opts.debugging_opts.osx_rpath_install_name {
370                 self.linker_arg("-install_name");
371                 let mut v = OsString::from("@rpath/");
372                 v.push(out_filename.file_name().unwrap());
373                 self.linker_arg(&v);
374             }
375         } else {
376             self.cmd.arg("-shared");
377             if self.sess.target.target.options.is_like_windows {
378                 // The output filename already contains `dll_suffix` so
379                 // the resulting import library will have a name in the
380                 // form of libfoo.dll.a
381                 let implib_name = out_filename
382                     .file_name()
383                     .and_then(|file| file.to_str())
384                     .map(|file| format!("{}{}{}",
385                          self.sess.target.target.options.staticlib_prefix,
386                          file,
387                          self.sess.target.target.options.staticlib_suffix));
388                 if let Some(implib_name) = implib_name {
389                     let implib = out_filename
390                         .parent()
391                         .map(|dir| dir.join(&implib_name));
392                     if let Some(implib) = implib {
393                         self.linker_arg(&format!("--out-implib,{}", (*implib).to_str().unwrap()));
394                     }
395                 }
396             }
397         }
398     }
399
400     fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType) {
401         // Symbol visibility in object files typically takes care of this.
402         if crate_type == CrateType::Executable {
403             return;
404         }
405
406         // We manually create a list of exported symbols to ensure we don't expose any more.
407         // The object files have far more public symbols than we actually want to export,
408         // so we hide them all here.
409
410         if !self.sess.target.target.options.limit_rdylib_exports {
411             return;
412         }
413
414         if crate_type == CrateType::ProcMacro {
415             return
416         }
417
418         let mut arg = OsString::new();
419         let path = tmpdir.join("list");
420
421         debug!("EXPORTED SYMBOLS:");
422
423         if self.sess.target.target.options.is_like_osx {
424             // Write a plain, newline-separated list of symbols
425             let res: io::Result<()> = try {
426                 let mut f = BufWriter::new(File::create(&path)?);
427                 for sym in self.info.exports[&crate_type].iter() {
428                     debug!("  _{}", sym);
429                     writeln!(f, "_{}", sym)?;
430                 }
431             };
432             if let Err(e) = res {
433                 self.sess.fatal(&format!("failed to write lib.def file: {}", e));
434             }
435         } else {
436             // Write an LD version script
437             let res: io::Result<()> = try {
438                 let mut f = BufWriter::new(File::create(&path)?);
439                 writeln!(f, "{{")?;
440                 if !self.info.exports[&crate_type].is_empty() {
441                     writeln!(f, "  global:")?;
442                     for sym in self.info.exports[&crate_type].iter() {
443                         debug!("    {};", sym);
444                         writeln!(f, "    {};", sym)?;
445                     }
446                 }
447                 writeln!(f, "\n  local:\n    *;\n}};")?;
448             };
449             if let Err(e) = res {
450                 self.sess.fatal(&format!("failed to write version script: {}", e));
451             }
452         }
453
454         if self.sess.target.target.options.is_like_osx {
455             if !self.is_ld {
456                 arg.push("-Wl,")
457             }
458             arg.push("-exported_symbols_list,");
459         } else if self.sess.target.target.options.is_like_solaris {
460             if !self.is_ld {
461                 arg.push("-Wl,")
462             }
463             arg.push("-M,");
464         } else {
465             if !self.is_ld {
466                 arg.push("-Wl,")
467             }
468             arg.push("--version-script=");
469         }
470
471         arg.push(&path);
472         self.cmd.arg(arg);
473     }
474
475     fn subsystem(&mut self, subsystem: &str) {
476         self.linker_arg("--subsystem");
477         self.linker_arg(&subsystem);
478     }
479
480     fn finalize(&mut self) -> Command {
481         self.hint_dynamic(); // Reset to default before returning the composed command line.
482
483         ::std::mem::replace(&mut self.cmd, Command::new(""))
484     }
485
486     fn group_start(&mut self) {
487         if self.takes_hints() {
488             self.linker_arg("--start-group");
489         }
490     }
491
492     fn group_end(&mut self) {
493         if self.takes_hints() {
494             self.linker_arg("--end-group");
495         }
496     }
497
498     fn linker_plugin_lto(&mut self) {
499         match self.sess.opts.cg.linker_plugin_lto {
500             LinkerPluginLto::Disabled => {
501                 // Nothing to do
502             }
503             LinkerPluginLto::LinkerPluginAuto => {
504                 self.push_linker_plugin_lto_args(None);
505             }
506             LinkerPluginLto::LinkerPlugin(ref path) => {
507                 self.push_linker_plugin_lto_args(Some(path.as_os_str()));
508             }
509         }
510     }
511 }
512
513 pub struct MsvcLinker<'a> {
514     cmd: Command,
515     sess: &'a Session,
516     info: &'a LinkerInfo
517 }
518
519 impl<'a> Linker for MsvcLinker<'a> {
520     fn link_rlib(&mut self, lib: &Path) { self.cmd.arg(lib); }
521     fn add_object(&mut self, path: &Path) { self.cmd.arg(path); }
522     fn args(&mut self, args: &[String]) { self.cmd.args(args); }
523
524     fn build_dylib(&mut self, out_filename: &Path) {
525         self.cmd.arg("/DLL");
526         let mut arg: OsString = "/IMPLIB:".into();
527         arg.push(out_filename.with_extension("dll.lib"));
528         self.cmd.arg(arg);
529     }
530
531     fn build_static_executable(&mut self) {
532         // noop
533     }
534
535     fn gc_sections(&mut self, _keep_metadata: bool) {
536         // MSVC's ICF (Identical COMDAT Folding) link optimization is
537         // slow for Rust and thus we disable it by default when not in
538         // optimization build.
539         if self.sess.opts.optimize != config::OptLevel::No {
540             self.cmd.arg("/OPT:REF,ICF");
541         } else {
542             // It is necessary to specify NOICF here, because /OPT:REF
543             // implies ICF by default.
544             self.cmd.arg("/OPT:REF,NOICF");
545         }
546     }
547
548     fn link_dylib(&mut self, lib: Symbol) {
549         self.cmd.arg(&format!("{}.lib", lib));
550     }
551
552     fn link_rust_dylib(&mut self, lib: Symbol, path: &Path) {
553         // When producing a dll, the MSVC linker may not actually emit a
554         // `foo.lib` file if the dll doesn't actually export any symbols, so we
555         // check to see if the file is there and just omit linking to it if it's
556         // not present.
557         let name = format!("{}.dll.lib", lib);
558         if fs::metadata(&path.join(&name)).is_ok() {
559             self.cmd.arg(name);
560         }
561     }
562
563     fn link_staticlib(&mut self, lib: Symbol) {
564         self.cmd.arg(&format!("{}.lib", lib));
565     }
566
567     fn position_independent_executable(&mut self) {
568         // noop
569     }
570
571     fn no_position_independent_executable(&mut self) {
572         // noop
573     }
574
575     fn full_relro(&mut self) {
576         // noop
577     }
578
579     fn partial_relro(&mut self) {
580         // noop
581     }
582
583     fn no_relro(&mut self) {
584         // noop
585     }
586
587     fn no_default_libraries(&mut self) {
588         // Currently we don't pass the /NODEFAULTLIB flag to the linker on MSVC
589         // as there's been trouble in the past of linking the C++ standard
590         // library required by LLVM. This likely needs to happen one day, but
591         // in general Windows is also a more controlled environment than
592         // Unix, so it's not necessarily as critical that this be implemented.
593         //
594         // Note that there are also some licensing worries about statically
595         // linking some libraries which require a specific agreement, so it may
596         // not ever be possible for us to pass this flag.
597     }
598
599     fn include_path(&mut self, path: &Path) {
600         let mut arg = OsString::from("/LIBPATH:");
601         arg.push(path);
602         self.cmd.arg(&arg);
603     }
604
605     fn output_filename(&mut self, path: &Path) {
606         let mut arg = OsString::from("/OUT:");
607         arg.push(path);
608         self.cmd.arg(&arg);
609     }
610
611     fn framework_path(&mut self, _path: &Path) {
612         bug!("frameworks are not supported on windows")
613     }
614     fn link_framework(&mut self, _framework: Symbol) {
615         bug!("frameworks are not supported on windows")
616     }
617
618     fn link_whole_staticlib(&mut self, lib: Symbol, _search_path: &[PathBuf]) {
619         // not supported?
620         self.link_staticlib(lib);
621     }
622     fn link_whole_rlib(&mut self, path: &Path) {
623         // not supported?
624         self.link_rlib(path);
625     }
626     fn optimize(&mut self) {
627         // Needs more investigation of `/OPT` arguments
628     }
629
630     fn pgo_gen(&mut self) {
631         // Nothing needed here.
632     }
633
634     fn debuginfo(&mut self) {
635         // This will cause the Microsoft linker to generate a PDB file
636         // from the CodeView line tables in the object files.
637         self.cmd.arg("/DEBUG");
638
639         // This will cause the Microsoft linker to embed .natvis info into the PDB file
640         let natvis_dir_path = self.sess.sysroot.join("lib\\rustlib\\etc");
641         if let Ok(natvis_dir) = fs::read_dir(&natvis_dir_path) {
642             for entry in natvis_dir {
643                 match entry {
644                     Ok(entry) => {
645                         let path = entry.path();
646                         if path.extension() == Some("natvis".as_ref()) {
647                             let mut arg = OsString::from("/NATVIS:");
648                             arg.push(path);
649                             self.cmd.arg(arg);
650                         }
651                     },
652                     Err(err) => {
653                         self.sess.warn(&format!("error enumerating natvis directory: {}", err));
654                     },
655                 }
656             }
657         }
658     }
659
660     // Currently the compiler doesn't use `dllexport` (an LLVM attribute) to
661     // export symbols from a dynamic library. When building a dynamic library,
662     // however, we're going to want some symbols exported, so this function
663     // generates a DEF file which lists all the symbols.
664     //
665     // The linker will read this `*.def` file and export all the symbols from
666     // the dynamic library. Note that this is not as simple as just exporting
667     // all the symbols in the current crate (as specified by `codegen.reachable`)
668     // but rather we also need to possibly export the symbols of upstream
669     // crates. Upstream rlibs may be linked statically to this dynamic library,
670     // in which case they may continue to transitively be used and hence need
671     // their symbols exported.
672     fn export_symbols(&mut self,
673                       tmpdir: &Path,
674                       crate_type: CrateType) {
675         // Symbol visibility takes care of this typically
676         if crate_type == CrateType::Executable {
677             return;
678         }
679
680         let path = tmpdir.join("lib.def");
681         let res: io::Result<()> = try {
682             let mut f = BufWriter::new(File::create(&path)?);
683
684             // Start off with the standard module name header and then go
685             // straight to exports.
686             writeln!(f, "LIBRARY")?;
687             writeln!(f, "EXPORTS")?;
688             for symbol in self.info.exports[&crate_type].iter() {
689                 debug!("  _{}", symbol);
690                 writeln!(f, "  {}", symbol)?;
691             }
692         };
693         if let Err(e) = res {
694             self.sess.fatal(&format!("failed to write lib.def file: {}", e));
695         }
696         let mut arg = OsString::from("/DEF:");
697         arg.push(path);
698         self.cmd.arg(&arg);
699     }
700
701     fn subsystem(&mut self, subsystem: &str) {
702         // Note that previous passes of the compiler validated this subsystem,
703         // so we just blindly pass it to the linker.
704         self.cmd.arg(&format!("/SUBSYSTEM:{}", subsystem));
705
706         // Windows has two subsystems we're interested in right now, the console
707         // and windows subsystems. These both implicitly have different entry
708         // points (starting symbols). The console entry point starts with
709         // `mainCRTStartup` and the windows entry point starts with
710         // `WinMainCRTStartup`. These entry points, defined in system libraries,
711         // will then later probe for either `main` or `WinMain`, respectively to
712         // start the application.
713         //
714         // In Rust we just always generate a `main` function so we want control
715         // to always start there, so we force the entry point on the windows
716         // subsystem to be `mainCRTStartup` to get everything booted up
717         // correctly.
718         //
719         // For more information see RFC #1665
720         if subsystem == "windows" {
721             self.cmd.arg("/ENTRY:mainCRTStartup");
722         }
723     }
724
725     fn finalize(&mut self) -> Command {
726         ::std::mem::replace(&mut self.cmd, Command::new(""))
727     }
728
729     // MSVC doesn't need group indicators
730     fn group_start(&mut self) {}
731     fn group_end(&mut self) {}
732
733     fn linker_plugin_lto(&mut self) {
734         // Do nothing
735     }
736 }
737
738 pub struct EmLinker<'a> {
739     cmd: Command,
740     sess: &'a Session,
741     info: &'a LinkerInfo
742 }
743
744 impl<'a> Linker for EmLinker<'a> {
745     fn include_path(&mut self, path: &Path) {
746         self.cmd.arg("-L").arg(path);
747     }
748
749     fn link_staticlib(&mut self, lib: Symbol) {
750         self.cmd.arg("-l").sym_arg(lib);
751     }
752
753     fn output_filename(&mut self, path: &Path) {
754         self.cmd.arg("-o").arg(path);
755     }
756
757     fn add_object(&mut self, path: &Path) {
758         self.cmd.arg(path);
759     }
760
761     fn link_dylib(&mut self, lib: Symbol) {
762         // Emscripten always links statically
763         self.link_staticlib(lib);
764     }
765
766     fn link_whole_staticlib(&mut self, lib: Symbol, _search_path: &[PathBuf]) {
767         // not supported?
768         self.link_staticlib(lib);
769     }
770
771     fn link_whole_rlib(&mut self, lib: &Path) {
772         // not supported?
773         self.link_rlib(lib);
774     }
775
776     fn link_rust_dylib(&mut self, lib: Symbol, _path: &Path) {
777         self.link_dylib(lib);
778     }
779
780     fn link_rlib(&mut self, lib: &Path) {
781         self.add_object(lib);
782     }
783
784     fn position_independent_executable(&mut self) {
785         // noop
786     }
787
788     fn no_position_independent_executable(&mut self) {
789         // noop
790     }
791
792     fn full_relro(&mut self) {
793         // noop
794     }
795
796     fn partial_relro(&mut self) {
797         // noop
798     }
799
800     fn no_relro(&mut self) {
801         // noop
802     }
803
804     fn args(&mut self, args: &[String]) {
805         self.cmd.args(args);
806     }
807
808     fn framework_path(&mut self, _path: &Path) {
809         bug!("frameworks are not supported on Emscripten")
810     }
811
812     fn link_framework(&mut self, _framework: Symbol) {
813         bug!("frameworks are not supported on Emscripten")
814     }
815
816     fn gc_sections(&mut self, _keep_metadata: bool) {
817         // noop
818     }
819
820     fn optimize(&mut self) {
821         // Emscripten performs own optimizations
822         self.cmd.arg(match self.sess.opts.optimize {
823             OptLevel::No => "-O0",
824             OptLevel::Less => "-O1",
825             OptLevel::Default => "-O2",
826             OptLevel::Aggressive => "-O3",
827             OptLevel::Size => "-Os",
828             OptLevel::SizeMin => "-Oz"
829         });
830         // Unusable until https://github.com/rust-lang/rust/issues/38454 is resolved
831         self.cmd.args(&["--memory-init-file", "0"]);
832     }
833
834     fn pgo_gen(&mut self) {
835         // noop, but maybe we need something like the gnu linker?
836     }
837
838     fn debuginfo(&mut self) {
839         // Preserve names or generate source maps depending on debug info
840         self.cmd.arg(match self.sess.opts.debuginfo {
841             DebugInfo::None => "-g0",
842             DebugInfo::Limited => "-g3",
843             DebugInfo::Full => "-g4"
844         });
845     }
846
847     fn no_default_libraries(&mut self) {
848         self.cmd.args(&["-s", "DEFAULT_LIBRARY_FUNCS_TO_INCLUDE=[]"]);
849     }
850
851     fn build_dylib(&mut self, _out_filename: &Path) {
852         bug!("building dynamic library is unsupported on Emscripten")
853     }
854
855     fn build_static_executable(&mut self) {
856         // noop
857     }
858
859     fn export_symbols(&mut self, _tmpdir: &Path, crate_type: CrateType) {
860         let symbols = &self.info.exports[&crate_type];
861
862         debug!("EXPORTED SYMBOLS:");
863
864         self.cmd.arg("-s");
865
866         let mut arg = OsString::from("EXPORTED_FUNCTIONS=");
867         let mut encoded = String::new();
868
869         {
870             let mut encoder = json::Encoder::new(&mut encoded);
871             let res = encoder.emit_seq(symbols.len(), |encoder| {
872                 for (i, sym) in symbols.iter().enumerate() {
873                     encoder.emit_seq_elt(i, |encoder| {
874                         encoder.emit_str(&("_".to_owned() + sym))
875                     })?;
876                 }
877                 Ok(())
878             });
879             if let Err(e) = res {
880                 self.sess.fatal(&format!("failed to encode exported symbols: {}", e));
881             }
882         }
883         debug!("{}", encoded);
884         arg.push(encoded);
885
886         self.cmd.arg(arg);
887     }
888
889     fn subsystem(&mut self, _subsystem: &str) {
890         // noop
891     }
892
893     fn finalize(&mut self) -> Command {
894         ::std::mem::replace(&mut self.cmd, Command::new(""))
895     }
896
897     // Appears not necessary on Emscripten
898     fn group_start(&mut self) {}
899     fn group_end(&mut self) {}
900
901     fn linker_plugin_lto(&mut self) {
902         // Do nothing
903     }
904 }
905
906 pub struct WasmLd<'a> {
907     cmd: Command,
908     sess: &'a Session,
909     info: &'a LinkerInfo,
910 }
911
912 impl<'a> WasmLd<'a> {
913     fn new(mut cmd: Command, sess: &'a Session, info: &'a LinkerInfo) -> WasmLd<'a> {
914         // If the atomics feature is enabled for wasm then we need a whole bunch
915         // of flags:
916         //
917         // * `--shared-memory` - the link won't even succeed without this, flags
918         //   the one linear memory as `shared`
919         //
920         // * `--max-memory=1G` - when specifying a shared memory this must also
921         //   be specified. We conservatively choose 1GB but users should be able
922         //   to override this with `-C link-arg`.
923         //
924         // * `--import-memory` - it doesn't make much sense for memory to be
925         //   exported in a threaded module because typically you're
926         //   sharing memory and instantiating the module multiple times. As a
927         //   result if it were exported then we'd just have no sharing.
928         //
929         // * `--passive-segments` - all memory segments should be passive to
930         //   prevent each module instantiation from reinitializing memory.
931         //
932         // * `--export=__wasm_init_memory` - when using `--passive-segments` the
933         //   linker will synthesize this function, and so we need to make sure
934         //   that our usage of `--export` below won't accidentally cause this
935         //   function to get deleted.
936         //
937         // * `--export=*tls*` - when `#[thread_local]` symbols are used these
938         //   symbols are how the TLS segments are initialized and configured.
939         let atomics = sess.opts.cg.target_feature.contains("+atomics") ||
940             sess.target.target.options.features.contains("+atomics");
941         if atomics {
942             cmd.arg("--shared-memory");
943             cmd.arg("--max-memory=1073741824");
944             cmd.arg("--import-memory");
945             cmd.arg("--passive-segments");
946             cmd.arg("--export=__wasm_init_memory");
947             cmd.arg("--export=__wasm_init_tls");
948             cmd.arg("--export=__tls_size");
949             cmd.arg("--export=__tls_align");
950             cmd.arg("--export=__tls_base");
951         }
952         WasmLd { cmd, sess, info }
953     }
954 }
955
956 impl<'a> Linker for WasmLd<'a> {
957     fn link_dylib(&mut self, lib: Symbol) {
958         self.cmd.arg("-l").sym_arg(lib);
959     }
960
961     fn link_staticlib(&mut self, lib: Symbol) {
962         self.cmd.arg("-l").sym_arg(lib);
963     }
964
965     fn link_rlib(&mut self, lib: &Path) {
966         self.cmd.arg(lib);
967     }
968
969     fn include_path(&mut self, path: &Path) {
970         self.cmd.arg("-L").arg(path);
971     }
972
973     fn framework_path(&mut self, _path: &Path) {
974         panic!("frameworks not supported")
975     }
976
977     fn output_filename(&mut self, path: &Path) {
978         self.cmd.arg("-o").arg(path);
979     }
980
981     fn add_object(&mut self, path: &Path) {
982         self.cmd.arg(path);
983     }
984
985     fn position_independent_executable(&mut self) {
986     }
987
988     fn full_relro(&mut self) {
989     }
990
991     fn partial_relro(&mut self) {
992     }
993
994     fn no_relro(&mut self) {
995     }
996
997     fn build_static_executable(&mut self) {
998     }
999
1000     fn args(&mut self, args: &[String]) {
1001         self.cmd.args(args);
1002     }
1003
1004     fn link_rust_dylib(&mut self, lib: Symbol, _path: &Path) {
1005         self.cmd.arg("-l").sym_arg(lib);
1006     }
1007
1008     fn link_framework(&mut self, _framework: Symbol) {
1009         panic!("frameworks not supported")
1010     }
1011
1012     fn link_whole_staticlib(&mut self, lib: Symbol, _search_path: &[PathBuf]) {
1013         self.cmd.arg("-l").sym_arg(lib);
1014     }
1015
1016     fn link_whole_rlib(&mut self, lib: &Path) {
1017         self.cmd.arg(lib);
1018     }
1019
1020     fn gc_sections(&mut self, _keep_metadata: bool) {
1021         self.cmd.arg("--gc-sections");
1022     }
1023
1024     fn optimize(&mut self) {
1025         self.cmd.arg(match self.sess.opts.optimize {
1026             OptLevel::No => "-O0",
1027             OptLevel::Less => "-O1",
1028             OptLevel::Default => "-O2",
1029             OptLevel::Aggressive => "-O3",
1030             // Currently LLD doesn't support `Os` and `Oz`, so pass through `O2`
1031             // instead.
1032             OptLevel::Size => "-O2",
1033             OptLevel::SizeMin => "-O2"
1034         });
1035     }
1036
1037     fn pgo_gen(&mut self) {
1038     }
1039
1040     fn debuginfo(&mut self) {
1041     }
1042
1043     fn no_default_libraries(&mut self) {
1044     }
1045
1046     fn build_dylib(&mut self, _out_filename: &Path) {
1047         self.cmd.arg("--no-entry");
1048     }
1049
1050     fn export_symbols(&mut self, _tmpdir: &Path, crate_type: CrateType) {
1051         for sym in self.info.exports[&crate_type].iter() {
1052             self.cmd.arg("--export").arg(&sym);
1053         }
1054
1055         // LLD will hide these otherwise-internal symbols since our `--export`
1056         // list above is a whitelist of what to export. Various bits and pieces
1057         // of tooling use this, so be sure these symbols make their way out of
1058         // the linker as well.
1059         self.cmd.arg("--export=__heap_base");
1060         self.cmd.arg("--export=__data_end");
1061     }
1062
1063     fn subsystem(&mut self, _subsystem: &str) {
1064     }
1065
1066     fn no_position_independent_executable(&mut self) {
1067     }
1068
1069     fn finalize(&mut self) -> Command {
1070         ::std::mem::replace(&mut self.cmd, Command::new(""))
1071     }
1072
1073     // Not needed for now with LLD
1074     fn group_start(&mut self) {}
1075     fn group_end(&mut self) {}
1076
1077     fn linker_plugin_lto(&mut self) {
1078         // Do nothing for now
1079     }
1080 }
1081
1082 fn exported_symbols(tcx: TyCtxt<'_>, crate_type: CrateType) -> Vec<String> {
1083     if let Some(ref exports) = tcx.sess.target.target.options.override_export_symbols {
1084         return exports.clone()
1085     }
1086
1087     let mut symbols = Vec::new();
1088
1089     let export_threshold = symbol_export::crates_export_threshold(&[crate_type]);
1090     for &(symbol, level) in tcx.exported_symbols(LOCAL_CRATE).iter() {
1091         if level.is_below_threshold(export_threshold) {
1092             symbols.push(symbol.symbol_name(tcx).to_string());
1093         }
1094     }
1095
1096     let formats = tcx.dependency_formats(LOCAL_CRATE);
1097     let deps = formats.iter().filter_map(|(t, list)| {
1098         if *t == crate_type {
1099             Some(list)
1100         } else {
1101             None
1102         }
1103     }).next().unwrap();
1104
1105     for (index, dep_format) in deps.iter().enumerate() {
1106         let cnum = CrateNum::new(index + 1);
1107         // For each dependency that we are linking to statically ...
1108         if *dep_format == Linkage::Static {
1109             // ... we add its symbol list to our export list.
1110             for &(symbol, level) in tcx.exported_symbols(cnum).iter() {
1111                 if !level.is_below_threshold(export_threshold) {
1112                     continue;
1113                 }
1114
1115                 // Do not export generic symbols from upstream crates in linked
1116                 // artifact (notably the `dylib` crate type). The main reason
1117                 // for this is that `symbol_name` is actually wrong for generic
1118                 // symbols because it guesses the name we'd give them locally
1119                 // rather than the name it has upstream (depending on
1120                 // `share_generics` settings and such).
1121                 //
1122                 // To fix that issue we just say that linked artifacts, aka
1123                 // `dylib`s, never export generic symbols and they aren't
1124                 // available to downstream crates. (the not available part is
1125                 // handled elsewhere).
1126                 if let ExportedSymbol::Generic(..) = symbol {
1127                     continue;
1128                 }
1129
1130                 symbols.push(symbol.symbol_name(tcx).to_string());
1131             }
1132         }
1133     }
1134
1135     symbols
1136 }
1137
1138 /// Much simplified and explicit CLI for the NVPTX linker. The linker operates
1139 /// with bitcode and uses LLVM backend to generate a PTX assembly.
1140 pub struct PtxLinker<'a> {
1141     cmd: Command,
1142     sess: &'a Session,
1143 }
1144
1145 impl<'a> Linker for PtxLinker<'a> {
1146     fn link_rlib(&mut self, path: &Path) {
1147         self.cmd.arg("--rlib").arg(path);
1148     }
1149
1150     fn link_whole_rlib(&mut self, path: &Path) {
1151         self.cmd.arg("--rlib").arg(path);
1152     }
1153
1154     fn include_path(&mut self, path: &Path) {
1155         self.cmd.arg("-L").arg(path);
1156     }
1157
1158     fn debuginfo(&mut self) {
1159         self.cmd.arg("--debug");
1160     }
1161
1162     fn add_object(&mut self, path: &Path) {
1163         self.cmd.arg("--bitcode").arg(path);
1164     }
1165
1166     fn args(&mut self, args: &[String]) {
1167         self.cmd.args(args);
1168     }
1169
1170     fn optimize(&mut self) {
1171         match self.sess.lto() {
1172             Lto::Thin | Lto::Fat | Lto::ThinLocal => {
1173                 self.cmd.arg("-Olto");
1174             },
1175
1176             Lto::No => { },
1177         };
1178     }
1179
1180     fn output_filename(&mut self, path: &Path) {
1181         self.cmd.arg("-o").arg(path);
1182     }
1183
1184     fn finalize(&mut self) -> Command {
1185         // Provide the linker with fallback to internal `target-cpu`.
1186         self.cmd.arg("--fallback-arch").arg(match self.sess.opts.cg.target_cpu {
1187             Some(ref s) => s,
1188             None => &self.sess.target.target.options.cpu
1189         });
1190
1191         ::std::mem::replace(&mut self.cmd, Command::new(""))
1192     }
1193
1194     fn link_dylib(&mut self, _lib: Symbol) {
1195         panic!("external dylibs not supported")
1196     }
1197
1198     fn link_rust_dylib(&mut self, _lib: Symbol, _path: &Path) {
1199         panic!("external dylibs not supported")
1200     }
1201
1202     fn link_staticlib(&mut self, _lib: Symbol) {
1203         panic!("staticlibs not supported")
1204     }
1205
1206     fn link_whole_staticlib(&mut self, _lib: Symbol, _search_path: &[PathBuf]) {
1207         panic!("staticlibs not supported")
1208     }
1209
1210     fn framework_path(&mut self, _path: &Path) {
1211         panic!("frameworks not supported")
1212     }
1213
1214     fn link_framework(&mut self, _framework: Symbol) {
1215         panic!("frameworks not supported")
1216     }
1217
1218     fn position_independent_executable(&mut self) {
1219     }
1220
1221     fn full_relro(&mut self) {
1222     }
1223
1224     fn partial_relro(&mut self) {
1225     }
1226
1227     fn no_relro(&mut self) {
1228     }
1229
1230     fn build_static_executable(&mut self) {
1231     }
1232
1233     fn gc_sections(&mut self, _keep_metadata: bool) {
1234     }
1235
1236     fn pgo_gen(&mut self) {
1237     }
1238
1239     fn no_default_libraries(&mut self) {
1240     }
1241
1242     fn build_dylib(&mut self, _out_filename: &Path) {
1243     }
1244
1245     fn export_symbols(&mut self, _tmpdir: &Path, _crate_type: CrateType) {
1246     }
1247
1248     fn subsystem(&mut self, _subsystem: &str) {
1249     }
1250
1251     fn no_position_independent_executable(&mut self) {
1252     }
1253
1254     fn group_start(&mut self) {
1255     }
1256
1257     fn group_end(&mut self) {
1258     }
1259
1260     fn linker_plugin_lto(&mut self) {
1261     }
1262 }