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