1use std::ffi::{OsStr, OsString};
2use std::fs::{self, File};
3use std::io::prelude::*;
4use std::path::{Path, PathBuf};
5use std::{env, iter, mem, str};
6
7use find_msvc_tools;
8use rustc_hir::attrs::WindowsSubsystemKind;
9use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
10use rustc_metadata::{
11 find_native_static_library, try_find_native_dynamic_library, try_find_native_static_library,
12};
13use rustc_middle::bug;
14use rustc_middle::middle::dependency_format::Linkage;
15use rustc_middle::middle::exported_symbols::{
16 self, ExportedSymbol, SymbolExportInfo, SymbolExportKind, SymbolExportLevel,
17};
18use rustc_middle::ty::TyCtxt;
19use rustc_session::Session;
20use rustc_session::config::{self, CrateType, DebugInfo, LinkerPluginLto, Lto, OptLevel, Strip};
21use rustc_target::spec::{Arch, Cc, CfgAbi, LinkOutputKind, LinkerFlavor, Lld, Os};
22use tracing::{debug, warn};
23
24use super::command::Command;
25use super::symbol_export;
26use crate::back::symbol_export::allocator_shim_symbols;
27use crate::base::needs_allocator_shim_for_linking;
28use crate::errors;
29
30#[cfg(test)]
31mod tests;
32
33pub(crate) fn disable_localization(linker: &mut Command) {
39 linker.env("LC_ALL", "C");
42 linker.env("VSLANG", "1033");
44}
45
46pub(crate) fn get_linker<'a>(
50 sess: &'a Session,
51 linker: &Path,
52 flavor: LinkerFlavor,
53 self_contained: bool,
54 target_cpu: &'a str,
55 codegen_backend: &'static str,
56) -> Box<dyn Linker + 'a> {
57 let msvc_tool = find_msvc_tools::find_tool(sess.target.arch.desc(), "link.exe");
58
59 let mut cmd = match linker.to_str() {
68 Some(linker) if falsecfg!(windows) && linker.ends_with(".bat") => Command::bat_script(linker),
69 _ => match flavor {
70 LinkerFlavor::Gnu(Cc::No, Lld::Yes)
71 | LinkerFlavor::Darwin(Cc::No, Lld::Yes)
72 | LinkerFlavor::WasmLld(Cc::No)
73 | LinkerFlavor::Msvc(Lld::Yes) => Command::lld(linker, flavor.lld_flavor()),
74 LinkerFlavor::Msvc(Lld::No)
75 if sess.opts.cg.linker.is_none() && sess.target.linker.is_none() =>
76 {
77 Command::new(msvc_tool.as_ref().map_or(linker, |t| t.path()))
78 }
79 _ => Command::new(linker),
80 },
81 };
82
83 let t = &sess.target;
87 if #[allow(non_exhaustive_omitted_patterns)] match flavor {
LinkerFlavor::Msvc(..) => true,
_ => false,
}matches!(flavor, LinkerFlavor::Msvc(..)) && t.cfg_abi == CfgAbi::Uwp {
88 if let Some(ref tool) = msvc_tool {
89 let original_path = tool.path();
90 if let Some(root_lib_path) = original_path.ancestors().nth(4) {
91 let arch = match t.arch {
92 Arch::X86_64 => Some("x64"),
93 Arch::X86 => Some("x86"),
94 Arch::AArch64 => Some("arm64"),
95 Arch::Arm => Some("arm"),
96 _ => None,
97 };
98 if let Some(ref a) = arch {
99 let mut arg = OsString::from("/LIBPATH:");
101 arg.push(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}\\lib\\{1}\\store",
root_lib_path.display(), a))
})format!("{}\\lib\\{}\\store", root_lib_path.display(), a));
102 cmd.arg(&arg);
103 } else {
104 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_codegen_ssa/src/back/linker.rs:104",
"rustc_codegen_ssa::back::linker", ::tracing::Level::WARN,
::tracing_core::__macro_support::Option::Some("compiler/rustc_codegen_ssa/src/back/linker.rs"),
::tracing_core::__macro_support::Option::Some(104u32),
::tracing_core::__macro_support::Option::Some("rustc_codegen_ssa::back::linker"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::WARN <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::WARN <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("arch is not supported")
as &dyn Value))])
});
} else { ; }
};warn!("arch is not supported");
105 }
106 } else {
107 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_codegen_ssa/src/back/linker.rs:107",
"rustc_codegen_ssa::back::linker", ::tracing::Level::WARN,
::tracing_core::__macro_support::Option::Some("compiler/rustc_codegen_ssa/src/back/linker.rs"),
::tracing_core::__macro_support::Option::Some(107u32),
::tracing_core::__macro_support::Option::Some("rustc_codegen_ssa::back::linker"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::WARN <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::WARN <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("MSVC root path lib location not found")
as &dyn Value))])
});
} else { ; }
};warn!("MSVC root path lib location not found");
108 }
109 } else {
110 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_codegen_ssa/src/back/linker.rs:110",
"rustc_codegen_ssa::back::linker", ::tracing::Level::WARN,
::tracing_core::__macro_support::Option::Some("compiler/rustc_codegen_ssa/src/back/linker.rs"),
::tracing_core::__macro_support::Option::Some(110u32),
::tracing_core::__macro_support::Option::Some("rustc_codegen_ssa::back::linker"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::WARN <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::WARN <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("link.exe not found")
as &dyn Value))])
});
} else { ; }
};warn!("link.exe not found");
111 }
112 }
113
114 let mut new_path = sess.get_tools_search_paths(self_contained);
117 let mut msvc_changed_path = false;
118 if sess.target.is_like_msvc
119 && let Some(ref tool) = msvc_tool
120 {
121 for (k, v) in tool.env() {
122 if k == "PATH" {
123 new_path.extend(env::split_paths(v));
124 msvc_changed_path = true;
125 } else {
126 cmd.env(k, v);
127 }
128 }
129 }
130
131 if !msvc_changed_path && let Some(path) = env::var_os("PATH") {
132 new_path.extend(env::split_paths(&path));
133 }
134 cmd.env("PATH", env::join_paths(new_path).unwrap());
135
136 if !(cmd.get_args().is_empty() || sess.target.cfg_abi == CfgAbi::Uwp) {
::core::panicking::panic("assertion failed: cmd.get_args().is_empty() || sess.target.cfg_abi == CfgAbi::Uwp")
};assert!(cmd.get_args().is_empty() || sess.target.cfg_abi == CfgAbi::Uwp);
139 match flavor {
140 LinkerFlavor::Unix(Cc::No) if sess.target.os == Os::L4Re => {
141 Box::new(L4Bender::new(cmd, sess)) as Box<dyn Linker>
142 }
143 LinkerFlavor::Unix(Cc::No) if sess.target.os == Os::Aix => {
144 Box::new(AixLinker::new(cmd, sess)) as Box<dyn Linker>
145 }
146 LinkerFlavor::WasmLld(Cc::No) => Box::new(WasmLd::new(cmd, sess)) as Box<dyn Linker>,
147 LinkerFlavor::Gnu(cc, _)
148 | LinkerFlavor::Darwin(cc, _)
149 | LinkerFlavor::WasmLld(cc)
150 | LinkerFlavor::Unix(cc) => Box::new(GccLinker {
151 cmd,
152 sess,
153 target_cpu,
154 hinted_static: None,
155 is_ld: cc == Cc::No,
156 is_gnu: flavor.is_gnu(),
157 uses_lld: flavor.uses_lld(),
158 codegen_backend,
159 }) as Box<dyn Linker>,
160 LinkerFlavor::Msvc(..) => Box::new(MsvcLinker { cmd, sess }) as Box<dyn Linker>,
161 LinkerFlavor::EmCc => Box::new(EmLinker { cmd, sess }) as Box<dyn Linker>,
162 LinkerFlavor::Bpf => Box::new(BpfLinker { cmd, sess }) as Box<dyn Linker>,
163 LinkerFlavor::Llbc => Box::new(LlbcLinker { cmd, sess }) as Box<dyn Linker>,
164 }
165}
166
167fn verbatim_args<L: Linker + ?Sized>(
177 l: &mut L,
178 args: impl IntoIterator<Item: AsRef<OsStr>>,
179) -> &mut L {
180 for arg in args {
181 l.cmd().arg(arg);
182 }
183 l
184}
185fn convert_link_args_to_cc_args(cmd: &mut Command, args: impl IntoIterator<Item: AsRef<OsStr>>) {
188 let mut combined_arg = OsString::from("-Wl");
189 for arg in args {
190 if arg.as_ref().as_encoded_bytes().contains(&b',') {
193 if combined_arg != OsStr::new("-Wl") {
195 cmd.arg(combined_arg);
196 combined_arg = OsString::from("-Wl");
198 }
199
200 cmd.arg("-Xlinker");
202 cmd.arg(arg);
203 } else {
204 combined_arg.push(",");
206 combined_arg.push(arg);
207 }
208 }
209 if combined_arg != OsStr::new("-Wl") {
211 cmd.arg(combined_arg);
212 }
213}
214fn link_args<L: Linker + ?Sized>(l: &mut L, args: impl IntoIterator<Item: AsRef<OsStr>>) -> &mut L {
217 if !l.is_cc() {
218 verbatim_args(l, args);
219 } else {
220 convert_link_args_to_cc_args(l.cmd(), args);
221 }
222 l
223}
224fn cc_args<L: Linker + ?Sized>(l: &mut L, args: impl IntoIterator<Item: AsRef<OsStr>>) -> &mut L {
227 if !l.is_cc() { ::core::panicking::panic("assertion failed: l.is_cc()") };assert!(l.is_cc());
228 verbatim_args(l, args)
229}
230fn link_or_cc_args<L: Linker + ?Sized>(
232 l: &mut L,
233 args: impl IntoIterator<Item: AsRef<OsStr>>,
234) -> &mut L {
235 verbatim_args(l, args)
236}
237
238macro_rules! generate_arg_methods {
239 ($($ty:ty)*) => { $(
240 impl $ty {
241 #[allow(unused)]
242 pub(crate) fn verbatim_args(&mut self, args: impl IntoIterator<Item: AsRef<OsStr>>) -> &mut Self {
243 verbatim_args(self, args)
244 }
245 #[allow(unused)]
246 pub(crate) fn verbatim_arg(&mut self, arg: impl AsRef<OsStr>) -> &mut Self {
247 verbatim_args(self, iter::once(arg))
248 }
249 #[allow(unused)]
250 pub(crate) fn link_args(&mut self, args: impl IntoIterator<Item: AsRef<OsStr>>) -> &mut Self {
251 link_args(self, args)
252 }
253 #[allow(unused)]
254 pub(crate) fn link_arg(&mut self, arg: impl AsRef<OsStr>) -> &mut Self {
255 link_args(self, iter::once(arg))
256 }
257 #[allow(unused)]
258 pub(crate) fn cc_args(&mut self, args: impl IntoIterator<Item: AsRef<OsStr>>) -> &mut Self {
259 cc_args(self, args)
260 }
261 #[allow(unused)]
262 pub(crate) fn cc_arg(&mut self, arg: impl AsRef<OsStr>) -> &mut Self {
263 cc_args(self, iter::once(arg))
264 }
265 #[allow(unused)]
266 pub(crate) fn link_or_cc_args(&mut self, args: impl IntoIterator<Item: AsRef<OsStr>>) -> &mut Self {
267 link_or_cc_args(self, args)
268 }
269 #[allow(unused)]
270 pub(crate) fn link_or_cc_arg(&mut self, arg: impl AsRef<OsStr>) -> &mut Self {
271 link_or_cc_args(self, iter::once(arg))
272 }
273 }
274 )* }
275}
276
277impl dyn Linker + '_ {
#[allow(unused)]
pub(crate) fn verbatim_args(&mut self,
args: impl IntoIterator<Item : AsRef<OsStr>>) -> &mut Self {
verbatim_args(self, args)
}
#[allow(unused)]
pub(crate) fn verbatim_arg(&mut self, arg: impl AsRef<OsStr>)
-> &mut Self {
verbatim_args(self, iter::once(arg))
}
#[allow(unused)]
pub(crate) fn link_args(&mut self,
args: impl IntoIterator<Item : AsRef<OsStr>>) -> &mut Self {
link_args(self, args)
}
#[allow(unused)]
pub(crate) fn link_arg(&mut self, arg: impl AsRef<OsStr>) -> &mut Self {
link_args(self, iter::once(arg))
}
#[allow(unused)]
pub(crate) fn cc_args(&mut self,
args: impl IntoIterator<Item : AsRef<OsStr>>) -> &mut Self {
cc_args(self, args)
}
#[allow(unused)]
pub(crate) fn cc_arg(&mut self, arg: impl AsRef<OsStr>) -> &mut Self {
cc_args(self, iter::once(arg))
}
#[allow(unused)]
pub(crate) fn link_or_cc_args(&mut self,
args: impl IntoIterator<Item : AsRef<OsStr>>) -> &mut Self {
link_or_cc_args(self, args)
}
#[allow(unused)]
pub(crate) fn link_or_cc_arg(&mut self, arg: impl AsRef<OsStr>)
-> &mut Self {
link_or_cc_args(self, iter::once(arg))
}
}generate_arg_methods! {
278 GccLinker<'_>
279 MsvcLinker<'_>
280 EmLinker<'_>
281 WasmLd<'_>
282 L4Bender<'_>
283 AixLinker<'_>
284 LlbcLinker<'_>
285 BpfLinker<'_>
286 dyn Linker + '_
287}
288
289pub(crate) trait Linker {
297 fn cmd(&mut self) -> &mut Command;
298 fn is_cc(&self) -> bool {
299 false
300 }
301 fn set_output_kind(
302 &mut self,
303 output_kind: LinkOutputKind,
304 crate_type: CrateType,
305 out_filename: &Path,
306 );
307 fn link_dylib_by_name(&mut self, _name: &str, _verbatim: bool, _as_needed: bool) {
308 ::rustc_middle::util::bug::bug_fmt(format_args!("dylib linked with unsupported linker"))bug!("dylib linked with unsupported linker")
309 }
310 fn link_dylib_by_path(&mut self, _path: &Path, _as_needed: bool) {
311 ::rustc_middle::util::bug::bug_fmt(format_args!("dylib linked with unsupported linker"))bug!("dylib linked with unsupported linker")
312 }
313 fn link_framework_by_name(&mut self, _name: &str, _verbatim: bool, _as_needed: bool) {
314 ::rustc_middle::util::bug::bug_fmt(format_args!("framework linked with unsupported linker"))bug!("framework linked with unsupported linker")
315 }
316 fn link_staticlib_by_name(&mut self, name: &str, verbatim: bool, whole_archive: bool);
317 fn link_staticlib_by_path(&mut self, path: &Path, whole_archive: bool);
318 fn include_path(&mut self, path: &Path) {
319 link_or_cc_args(link_or_cc_args(self, &["-L"]), &[path]);
320 }
321 fn framework_path(&mut self, _path: &Path) {
322 ::rustc_middle::util::bug::bug_fmt(format_args!("framework path set with unsupported linker"))bug!("framework path set with unsupported linker")
323 }
324 fn output_filename(&mut self, path: &Path) {
325 link_or_cc_args(link_or_cc_args(self, &["-o"]), &[path]);
326 }
327 fn add_object(&mut self, path: &Path) {
328 link_or_cc_args(self, &[path]);
329 }
330 fn gc_sections(&mut self, keep_metadata: bool);
331 fn full_relro(&mut self);
332 fn partial_relro(&mut self);
333 fn no_relro(&mut self);
334 fn optimize(&mut self);
335 fn pgo_gen(&mut self);
336 fn control_flow_guard(&mut self);
337 fn ehcont_guard(&mut self);
338 fn debuginfo(&mut self, strip: Strip, natvis_debugger_visualizers: &[PathBuf]);
339 fn no_crt_objects(&mut self);
340 fn no_default_libraries(&mut self);
341 fn export_symbols(
342 &mut self,
343 tmpdir: &Path,
344 crate_type: CrateType,
345 symbols: &[(String, SymbolExportKind)],
346 );
347 fn windows_subsystem(&mut self, subsystem: WindowsSubsystemKind);
348 fn linker_plugin_lto(&mut self);
349 fn add_eh_frame_header(&mut self) {}
350 fn add_no_exec(&mut self) {}
351 fn add_as_needed(&mut self) {}
352 fn reset_per_library_state(&mut self) {}
353 fn enable_profiling(&mut self) {}
354}
355
356impl dyn Linker + '_ {
357 pub(crate) fn take_cmd(&mut self) -> Command {
358 mem::replace(self.cmd(), Command::new(""))
359 }
360}
361
362struct GccLinker<'a> {
363 cmd: Command,
364 sess: &'a Session,
365 target_cpu: &'a str,
366 hinted_static: Option<bool>, is_ld: bool,
369 is_gnu: bool,
370 uses_lld: bool,
371 codegen_backend: &'static str,
372}
373
374impl<'a> GccLinker<'a> {
375 fn takes_hints(&self) -> bool {
376 !self.sess.target.is_like_darwin && !self.sess.target.is_like_wasm
385 }
386
387 fn hint_static(&mut self) {
392 if !self.takes_hints() {
393 return;
394 }
395 if self.hinted_static != Some(true) {
396 self.link_arg("-Bstatic");
397 self.hinted_static = Some(true);
398 }
399 }
400
401 fn hint_dynamic(&mut self) {
402 if !self.takes_hints() {
403 return;
404 }
405 if self.hinted_static != Some(false) {
406 self.link_arg("-Bdynamic");
407 self.hinted_static = Some(false);
408 }
409 }
410
411 fn push_linker_plugin_lto_args(&mut self, plugin_path: Option<&OsStr>) {
412 if let Some(plugin_path) = plugin_path {
413 let mut arg = OsString::from("-plugin=");
414 arg.push(plugin_path);
415 self.link_arg(&arg);
416 }
417
418 let opt_level = match self.sess.opts.optimize {
419 config::OptLevel::No => "O0",
420 config::OptLevel::Less => "O1",
421 config::OptLevel::More | config::OptLevel::Size | config::OptLevel::SizeMin => "O2",
422 config::OptLevel::Aggressive => "O3",
423 };
424
425 if let Some(path) = &self.sess.opts.unstable_opts.profile_sample_use {
426 self.link_arg(&::alloc::__export::must_use({
::alloc::fmt::format(format_args!("-plugin-opt=sample-profile={0}",
path.display()))
})format!("-plugin-opt=sample-profile={}", path.display()));
427 };
428 let prefix = if self.codegen_backend == "gcc" {
429 "-"
431 } else {
432 ""
433 };
434 self.link_args(&[
435 &::alloc::__export::must_use({
::alloc::fmt::format(format_args!("-plugin-opt={0}{1}", prefix,
opt_level))
})format!("-plugin-opt={prefix}{opt_level}"),
436 &::alloc::__export::must_use({
::alloc::fmt::format(format_args!("-plugin-opt={1}mcpu={0}",
self.target_cpu, prefix))
})format!("-plugin-opt={prefix}mcpu={}", self.target_cpu),
437 ]);
438 }
439
440 fn build_dylib(&mut self, crate_type: CrateType, out_filename: &Path) {
441 if self.sess.target.is_like_darwin {
443 if self.is_cc() {
444 self.cc_arg("-dynamiclib");
446 } else {
447 self.link_arg("-dylib");
448 }
450
451 if self.sess.opts.cg.rpath || self.sess.opts.unstable_opts.osx_rpath_install_name {
456 let mut rpath = OsString::from("@rpath/");
457 rpath.push(out_filename.file_name().unwrap());
458 self.link_arg("-install_name").link_arg(rpath);
459 }
460 } else {
461 self.link_or_cc_arg("-shared");
462 if let Some(name) = out_filename.file_name() {
463 if self.sess.target.is_like_windows {
464 let (prefix, suffix) = self.sess.staticlib_components(false);
468 let mut implib_name = OsString::from(prefix);
469 implib_name.push(name);
470 implib_name.push(suffix);
471 let mut out_implib = OsString::from("--out-implib=");
472 out_implib.push(out_filename.with_file_name(implib_name));
473 self.link_arg(out_implib);
474 } else if crate_type == CrateType::Dylib {
475 let mut soname = OsString::from("-soname=");
479 soname.push(name);
480 self.link_arg(soname);
481 }
482 }
483 }
484 }
485
486 fn with_as_needed(&mut self, as_needed: bool, f: impl FnOnce(&mut Self)) {
487 if !as_needed {
488 if self.sess.target.is_like_darwin {
489 self.sess.dcx().emit_warn(errors::Ld64UnimplementedModifier);
493 } else if self.is_gnu && !self.sess.target.is_like_windows {
494 self.link_arg("--no-as-needed");
495 } else {
496 self.sess.dcx().emit_warn(errors::LinkerUnsupportedModifier);
497 }
498 }
499
500 f(self);
501
502 if !as_needed {
503 if self.sess.target.is_like_darwin {
504 } else if self.is_gnu && !self.sess.target.is_like_windows {
506 self.link_arg("--as-needed");
507 }
508 }
509 }
510}
511
512impl<'a> Linker for GccLinker<'a> {
513 fn cmd(&mut self) -> &mut Command {
514 &mut self.cmd
515 }
516
517 fn is_cc(&self) -> bool {
518 !self.is_ld
519 }
520
521 fn set_output_kind(
522 &mut self,
523 output_kind: LinkOutputKind,
524 crate_type: CrateType,
525 out_filename: &Path,
526 ) {
527 match output_kind {
528 LinkOutputKind::DynamicNoPicExe => {
529 if !self.is_ld && self.is_gnu && !self.sess.target.is_like_windows {
531 self.cc_arg("-no-pie");
532 }
533 }
534 LinkOutputKind::DynamicPicExe => {
535 if !self.sess.target.is_like_windows {
537 self.link_or_cc_arg("-pie");
539 }
540 }
541 LinkOutputKind::StaticNoPicExe => {
542 self.link_or_cc_arg("-static");
544 if !self.is_ld && self.is_gnu {
545 self.cc_arg("-no-pie");
546 }
547 }
548 LinkOutputKind::StaticPicExe => {
549 if !self.is_ld {
550 self.cc_arg("-static-pie");
553 } else {
554 self.link_args(&["-static", "-pie", "--no-dynamic-linker", "-z", "text"]);
560 }
561 }
562 LinkOutputKind::DynamicDylib => self.build_dylib(crate_type, out_filename),
563 LinkOutputKind::StaticDylib => {
564 self.link_or_cc_arg("-static");
565 self.build_dylib(crate_type, out_filename);
566 }
567 LinkOutputKind::WasiReactorExe => {
568 self.link_args(&["--entry", "_initialize"]);
569 }
570 }
571
572 if self.sess.target.os == Os::VxWorks
578 && #[allow(non_exhaustive_omitted_patterns)] match output_kind {
LinkOutputKind::StaticNoPicExe | LinkOutputKind::StaticPicExe |
LinkOutputKind::StaticDylib => true,
_ => false,
}matches!(
579 output_kind,
580 LinkOutputKind::StaticNoPicExe
581 | LinkOutputKind::StaticPicExe
582 | LinkOutputKind::StaticDylib
583 )
584 {
585 self.cc_arg("--static-crt");
586 }
587
588 if self.sess.target.arch == Arch::Avr && !self.uses_lld {
594 self.verbatim_arg(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("-mmcu={0}", self.target_cpu))
})format!("-mmcu={}", self.target_cpu));
595 }
596 }
597
598 fn link_dylib_by_name(&mut self, name: &str, verbatim: bool, as_needed: bool) {
599 if self.sess.target.os == Os::Illumos && name == "c" {
600 return;
606 }
607 self.hint_dynamic();
608 self.with_as_needed(as_needed, |this| {
609 let colon = if verbatim && this.is_gnu { ":" } else { "" };
610 this.link_or_cc_arg(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("-l{0}{1}", colon, name))
})format!("-l{colon}{name}"));
611 });
612 }
613
614 fn link_dylib_by_path(&mut self, path: &Path, as_needed: bool) {
615 self.hint_dynamic();
616 self.with_as_needed(as_needed, |this| {
617 this.link_or_cc_arg(path);
618 })
619 }
620
621 fn link_framework_by_name(&mut self, name: &str, _verbatim: bool, as_needed: bool) {
622 self.hint_dynamic();
623 if !as_needed {
624 self.sess.dcx().emit_warn(errors::Ld64UnimplementedModifier);
628 }
629 self.link_or_cc_args(&["-framework", name]);
630 }
631
632 fn link_staticlib_by_name(&mut self, name: &str, verbatim: bool, whole_archive: bool) {
633 self.hint_static();
634 let colon = if verbatim && self.is_gnu { ":" } else { "" };
635 if !whole_archive {
636 self.link_or_cc_arg(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("-l{0}{1}", colon, name))
})format!("-l{colon}{name}"));
637 } else if self.sess.target.is_like_darwin {
638 self.link_arg("-force_load");
641 self.link_arg(find_native_static_library(name, verbatim, self.sess));
642 } else {
643 self.link_arg("--whole-archive")
644 .link_or_cc_arg(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("-l{0}{1}", colon, name))
})format!("-l{colon}{name}"))
645 .link_arg("--no-whole-archive");
646 }
647 }
648
649 fn link_staticlib_by_path(&mut self, path: &Path, whole_archive: bool) {
650 self.hint_static();
651 if !whole_archive {
652 self.link_or_cc_arg(path);
653 } else if self.sess.target.is_like_darwin {
654 self.link_arg("-force_load").link_arg(path);
655 } else {
656 self.link_arg("--whole-archive").link_arg(path).link_arg("--no-whole-archive");
657 }
658 }
659
660 fn framework_path(&mut self, path: &Path) {
661 self.link_or_cc_arg("-F").link_or_cc_arg(path);
662 }
663 fn full_relro(&mut self) {
664 self.link_args(&["-z", "relro", "-z", "now"]);
665 }
666 fn partial_relro(&mut self) {
667 self.link_args(&["-z", "relro"]);
668 }
669 fn no_relro(&mut self) {
670 self.link_args(&["-z", "norelro"]);
671 }
672
673 fn gc_sections(&mut self, keep_metadata: bool) {
674 if self.sess.target.is_like_darwin {
689 self.link_arg("-dead_strip");
690
691 } else if (self.is_gnu || self.sess.target.is_like_wasm) && !keep_metadata {
697 self.link_arg("--gc-sections");
698 }
699 }
700
701 fn optimize(&mut self) {
702 if !self.is_gnu && !self.sess.target.is_like_wasm {
703 return;
704 }
705
706 if self.sess.opts.optimize == config::OptLevel::More
709 || self.sess.opts.optimize == config::OptLevel::Aggressive
710 {
711 self.link_arg("-O1");
712 }
713 }
714
715 fn pgo_gen(&mut self) {
716 if !self.is_gnu {
717 return;
718 }
719
720 self.link_or_cc_args(&["-u", "__llvm_profile_runtime"]);
732 }
733
734 fn enable_profiling(&mut self) {
735 if !self.is_ld {
738 self.cc_arg("-pg");
739 if self.sess.target.is_like_windows {
742 self.cc_arg("-lgmon");
743 self.cc_arg("-lkernel32");
744 self.cc_arg("-lmsvcrt");
745 }
746 }
747 }
748
749 fn control_flow_guard(&mut self) {}
750
751 fn ehcont_guard(&mut self) {}
752
753 fn debuginfo(&mut self, strip: Strip, _: &[PathBuf]) {
754 if self.sess.target.is_like_darwin {
756 return;
757 }
758
759 match strip {
760 Strip::None => {}
761 Strip::Debuginfo => {
762 if !self.sess.target.is_like_solaris {
767 self.link_arg("--strip-debug");
768 }
769 }
770 Strip::Symbols => {
771 self.link_arg("--strip-all");
772 }
773 }
774 match self.sess.opts.unstable_opts.debuginfo_compression {
775 config::DebugInfoCompression::None => {}
776 config::DebugInfoCompression::Zlib => {
777 self.link_arg("--compress-debug-sections=zlib");
778 }
779 config::DebugInfoCompression::Zstd => {
780 self.link_arg("--compress-debug-sections=zstd");
781 }
782 }
783 }
784
785 fn no_crt_objects(&mut self) {
786 if !self.is_ld {
787 self.cc_arg("-nostartfiles");
788 }
789 }
790
791 fn no_default_libraries(&mut self) {
792 if !self.is_ld {
793 self.cc_arg("-nodefaultlibs");
794 }
795 }
796
797 fn export_symbols(
798 &mut self,
799 tmpdir: &Path,
800 crate_type: CrateType,
801 symbols: &[(String, SymbolExportKind)],
802 ) {
803 if crate_type == CrateType::Executable {
805 let should_export_executable_symbols =
806 self.sess.opts.unstable_opts.export_executable_symbols;
807 if self.sess.target.override_export_symbols.is_none()
808 && !should_export_executable_symbols
809 {
810 return;
811 }
812 }
813
814 if !self.sess.target.limit_rdylib_exports {
819 return;
820 }
821
822 let path = tmpdir.join(if self.sess.target.is_like_windows { "list.def" } else { "list" });
823 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_codegen_ssa/src/back/linker.rs:823",
"rustc_codegen_ssa::back::linker", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_codegen_ssa/src/back/linker.rs"),
::tracing_core::__macro_support::Option::Some(823u32),
::tracing_core::__macro_support::Option::Some("rustc_codegen_ssa::back::linker"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("EXPORTED SYMBOLS:")
as &dyn Value))])
});
} else { ; }
};debug!("EXPORTED SYMBOLS:");
824
825 if self.sess.target.is_like_darwin {
826 let res = try {
828 let mut f = File::create_buffered(&path)?;
829 for (sym, _) in symbols {
830 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_codegen_ssa/src/back/linker.rs:830",
"rustc_codegen_ssa::back::linker", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_codegen_ssa/src/back/linker.rs"),
::tracing_core::__macro_support::Option::Some(830u32),
::tracing_core::__macro_support::Option::Some("rustc_codegen_ssa::back::linker"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!(" _{0}",
sym) as &dyn Value))])
});
} else { ; }
};debug!(" _{sym}");
831 f.write_fmt(format_args!("_{0}\n", sym))writeln!(f, "_{sym}")?;
832 }
833 };
834 if let Err(error) = res {
835 self.sess.dcx().emit_fatal(errors::LibDefWriteFailure { error });
836 }
837 self.link_arg("-exported_symbols_list").link_arg(path);
838 } else if self.sess.target.is_like_windows {
839 let res = try {
840 let mut f = File::create_buffered(&path)?;
841
842 f.write_fmt(format_args!("EXPORTS\n"))writeln!(f, "EXPORTS")?;
845 for (symbol, kind) in symbols {
846 let kind_marker = if *kind == SymbolExportKind::Data { " DATA" } else { "" };
847 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_codegen_ssa/src/back/linker.rs:847",
"rustc_codegen_ssa::back::linker", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_codegen_ssa/src/back/linker.rs"),
::tracing_core::__macro_support::Option::Some(847u32),
::tracing_core::__macro_support::Option::Some("rustc_codegen_ssa::back::linker"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!(" _{0}",
symbol) as &dyn Value))])
});
} else { ; }
};debug!(" _{symbol}");
848 f.write_fmt(format_args!(" \"{0}\"{1}\n", symbol, kind_marker))writeln!(f, " \"{symbol}\"{kind_marker}")?;
851 }
852 };
853 if let Err(error) = res {
854 self.sess.dcx().emit_fatal(errors::LibDefWriteFailure { error });
855 }
856 self.link_arg(path);
857 } else if self.sess.target.is_like_wasm {
858 self.link_arg("--no-export-dynamic");
859 for (sym, _) in symbols {
860 self.link_arg("--export").link_arg(sym);
861 }
862 } else if crate_type == CrateType::Executable && !self.sess.target.is_like_solaris {
863 let res = try {
864 let mut f = File::create_buffered(&path)?;
865 f.write_fmt(format_args!("{{\n"))writeln!(f, "{{")?;
866 for (sym, _) in symbols {
867 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_codegen_ssa/src/back/linker.rs:867",
"rustc_codegen_ssa::back::linker", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_codegen_ssa/src/back/linker.rs"),
::tracing_core::__macro_support::Option::Some(867u32),
::tracing_core::__macro_support::Option::Some("rustc_codegen_ssa::back::linker"),
::tracing_core::field::FieldSet::new(&["sym"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&sym as
&dyn Value))])
});
} else { ; }
};debug!(sym);
868 f.write_fmt(format_args!(" {0};\n", sym))writeln!(f, " {sym};")?;
869 }
870 f.write_fmt(format_args!("}};\n"))writeln!(f, "}};")?;
871 };
872 if let Err(error) = res {
873 self.sess.dcx().emit_fatal(errors::VersionScriptWriteFailure { error });
874 }
875 self.link_arg("--dynamic-list").link_arg(path);
876 } else {
877 let res = try {
879 let mut f = File::create_buffered(&path)?;
880 f.write_fmt(format_args!("{{\n"))writeln!(f, "{{")?;
881 if !symbols.is_empty() {
882 f.write_fmt(format_args!(" global:\n"))writeln!(f, " global:")?;
883 for (sym, _) in symbols {
884 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_codegen_ssa/src/back/linker.rs:884",
"rustc_codegen_ssa::back::linker", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_codegen_ssa/src/back/linker.rs"),
::tracing_core::__macro_support::Option::Some(884u32),
::tracing_core::__macro_support::Option::Some("rustc_codegen_ssa::back::linker"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!(" {0};",
sym) as &dyn Value))])
});
} else { ; }
};debug!(" {sym};");
885 f.write_fmt(format_args!(" {0};\n", sym))writeln!(f, " {sym};")?;
886 }
887 }
888 f.write_fmt(format_args!("\n local:\n *;\n}};\n"))writeln!(f, "\n local:\n *;\n}};")?;
889 };
890 if let Err(error) = res {
891 self.sess.dcx().emit_fatal(errors::VersionScriptWriteFailure { error });
892 }
893 if self.sess.target.is_like_solaris {
894 self.link_arg("-M").link_arg(path);
895 } else {
896 let mut arg = OsString::from("--version-script=");
897 arg.push(path);
898 self.link_arg(arg).link_arg("--no-undefined-version");
899 }
900 }
901 }
902
903 fn windows_subsystem(&mut self, subsystem: WindowsSubsystemKind) {
904 self.link_args(&["--subsystem", subsystem.as_str()]);
905 }
906
907 fn reset_per_library_state(&mut self) {
908 self.hint_dynamic(); }
910
911 fn linker_plugin_lto(&mut self) {
912 match self.sess.opts.cg.linker_plugin_lto {
913 LinkerPluginLto::Disabled => {
914 }
916 LinkerPluginLto::LinkerPluginAuto => {
917 self.push_linker_plugin_lto_args(None);
918 }
919 LinkerPluginLto::LinkerPlugin(ref path) => {
920 self.push_linker_plugin_lto_args(Some(path.as_os_str()));
921 }
922 }
923 }
924
925 fn add_eh_frame_header(&mut self) {
929 self.link_arg("--eh-frame-hdr");
930 }
931
932 fn add_no_exec(&mut self) {
933 if self.sess.target.is_like_windows {
934 self.link_arg("--nxcompat");
935 } else if self.is_gnu {
936 self.link_args(&["-z", "noexecstack"]);
937 }
938 }
939
940 fn add_as_needed(&mut self) {
941 if self.is_gnu && !self.sess.target.is_like_windows {
942 self.link_arg("--as-needed");
943 } else if self.sess.target.is_like_solaris {
944 self.link_args(&["-z", "ignore"]);
946 }
947 }
948}
949
950struct MsvcLinker<'a> {
951 cmd: Command,
952 sess: &'a Session,
953}
954
955impl<'a> Linker for MsvcLinker<'a> {
956 fn cmd(&mut self) -> &mut Command {
957 &mut self.cmd
958 }
959
960 fn set_output_kind(
961 &mut self,
962 output_kind: LinkOutputKind,
963 _crate_type: CrateType,
964 out_filename: &Path,
965 ) {
966 match output_kind {
967 LinkOutputKind::DynamicNoPicExe
968 | LinkOutputKind::DynamicPicExe
969 | LinkOutputKind::StaticNoPicExe
970 | LinkOutputKind::StaticPicExe => {}
971 LinkOutputKind::DynamicDylib | LinkOutputKind::StaticDylib => {
972 self.link_arg("/DLL");
973 let mut arg: OsString = "/IMPLIB:".into();
974 arg.push(out_filename.with_extension("dll.lib"));
975 self.link_arg(arg);
976 }
977 LinkOutputKind::WasiReactorExe => {
978 {
::core::panicking::panic_fmt(format_args!("can\'t link as reactor on non-wasi target"));
};panic!("can't link as reactor on non-wasi target");
979 }
980 }
981 }
982
983 fn link_dylib_by_name(&mut self, name: &str, verbatim: bool, _as_needed: bool) {
984 if let Some(path) = try_find_native_dynamic_library(self.sess, name, verbatim) {
987 self.link_arg(path);
988 } else {
989 self.link_arg(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}{1}", name,
if verbatim { "" } else { ".lib" }))
})format!("{}{}", name, if verbatim { "" } else { ".lib" }));
990 }
991 }
992
993 fn link_dylib_by_path(&mut self, path: &Path, _as_needed: bool) {
994 let implib_path = path.with_extension("dll.lib");
997 if implib_path.exists() {
998 self.link_or_cc_arg(implib_path);
999 }
1000 }
1001
1002 fn link_staticlib_by_name(&mut self, name: &str, verbatim: bool, whole_archive: bool) {
1003 if let Some(path) = try_find_native_static_library(self.sess, name, verbatim) {
1006 self.link_staticlib_by_path(&path, whole_archive);
1007 } else {
1008 let opts = if whole_archive { "/WHOLEARCHIVE:" } else { "" };
1009 let (prefix, suffix) = self.sess.staticlib_components(verbatim);
1010 self.link_arg(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}{1}{2}{3}", opts, prefix, name,
suffix))
})format!("{opts}{prefix}{name}{suffix}"));
1011 }
1012 }
1013
1014 fn link_staticlib_by_path(&mut self, path: &Path, whole_archive: bool) {
1015 if !whole_archive {
1016 self.link_arg(path);
1017 } else {
1018 let mut arg = OsString::from("/WHOLEARCHIVE:");
1019 arg.push(path);
1020 self.link_arg(arg);
1021 }
1022 }
1023
1024 fn gc_sections(&mut self, _keep_metadata: bool) {
1025 if self.sess.opts.optimize != config::OptLevel::No {
1029 self.link_arg("/OPT:REF,ICF");
1030 } else {
1031 self.link_arg("/OPT:REF,NOICF");
1034 }
1035 }
1036
1037 fn full_relro(&mut self) {
1038 }
1040
1041 fn partial_relro(&mut self) {
1042 }
1044
1045 fn no_relro(&mut self) {
1046 }
1048
1049 fn no_crt_objects(&mut self) {
1050 }
1052
1053 fn no_default_libraries(&mut self) {
1054 self.link_arg("/NODEFAULTLIB");
1055 }
1056
1057 fn include_path(&mut self, path: &Path) {
1058 let mut arg = OsString::from("/LIBPATH:");
1059 arg.push(path);
1060 self.link_arg(&arg);
1061 }
1062
1063 fn output_filename(&mut self, path: &Path) {
1064 let mut arg = OsString::from("/OUT:");
1065 arg.push(path);
1066 self.link_arg(&arg);
1067 }
1068
1069 fn optimize(&mut self) {
1070 }
1072
1073 fn pgo_gen(&mut self) {
1074 }
1076
1077 fn control_flow_guard(&mut self) {
1078 self.link_arg("/guard:cf");
1079 }
1080
1081 fn ehcont_guard(&mut self) {
1082 if self.sess.target.pointer_width == 64 {
1083 self.link_arg("/guard:ehcont");
1084 }
1085 }
1086
1087 fn debuginfo(&mut self, _strip: Strip, natvis_debugger_visualizers: &[PathBuf]) {
1088 self.link_arg("/DEBUG");
1091
1092 self.link_arg("/PDBALTPATH:%_PDB%");
1100
1101 let natvis_dir_path = self.sess.opts.sysroot.path().join("lib\\rustlib\\etc");
1103 if let Ok(natvis_dir) = fs::read_dir(&natvis_dir_path) {
1104 for entry in natvis_dir {
1105 match entry {
1106 Ok(entry) => {
1107 let path = entry.path();
1108 if path.extension() == Some("natvis".as_ref()) {
1109 let mut arg = OsString::from("/NATVIS:");
1110 arg.push(path);
1111 self.link_arg(arg);
1112 }
1113 }
1114 Err(error) => {
1115 self.sess.dcx().emit_warn(errors::NoNatvisDirectory { error });
1116 }
1117 }
1118 }
1119 }
1120
1121 for path in natvis_debugger_visualizers {
1123 let mut arg = OsString::from("/NATVIS:");
1124 arg.push(path);
1125 self.link_arg(arg);
1126 }
1127 }
1128
1129 fn export_symbols(
1142 &mut self,
1143 tmpdir: &Path,
1144 crate_type: CrateType,
1145 symbols: &[(String, SymbolExportKind)],
1146 ) {
1147 if crate_type == CrateType::Executable {
1149 let should_export_executable_symbols =
1150 self.sess.opts.unstable_opts.export_executable_symbols;
1151 if !should_export_executable_symbols {
1152 return;
1153 }
1154 }
1155
1156 let path = tmpdir.join("lib.def");
1157 let res = try {
1158 let mut f = File::create_buffered(&path)?;
1159
1160 f.write_fmt(format_args!("LIBRARY\n"))writeln!(f, "LIBRARY")?;
1163 f.write_fmt(format_args!("EXPORTS\n"))writeln!(f, "EXPORTS")?;
1164 for (symbol, kind) in symbols {
1165 let kind_marker = if *kind == SymbolExportKind::Data { " DATA" } else { "" };
1166 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_codegen_ssa/src/back/linker.rs:1166",
"rustc_codegen_ssa::back::linker", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_codegen_ssa/src/back/linker.rs"),
::tracing_core::__macro_support::Option::Some(1166u32),
::tracing_core::__macro_support::Option::Some("rustc_codegen_ssa::back::linker"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!(" _{0}",
symbol) as &dyn Value))])
});
} else { ; }
};debug!(" _{symbol}");
1167 f.write_fmt(format_args!(" {0}{1}\n", symbol, kind_marker))writeln!(f, " {symbol}{kind_marker}")?;
1168 }
1169 };
1170 if let Err(error) = res {
1171 self.sess.dcx().emit_fatal(errors::LibDefWriteFailure { error });
1172 }
1173 let mut arg = OsString::from("/DEF:");
1174 arg.push(path);
1175 self.link_arg(&arg);
1176 }
1177
1178 fn windows_subsystem(&mut self, subsystem: WindowsSubsystemKind) {
1179 let subsystem = subsystem.as_str();
1180 self.link_arg(&::alloc::__export::must_use({
::alloc::fmt::format(format_args!("/SUBSYSTEM:{0}", subsystem))
})format!("/SUBSYSTEM:{subsystem}"));
1181
1182 if subsystem == "windows" {
1197 self.link_arg("/ENTRY:mainCRTStartup");
1198 }
1199 }
1200
1201 fn linker_plugin_lto(&mut self) {
1202 }
1204
1205 fn add_no_exec(&mut self) {
1206 self.link_arg("/NXCOMPAT");
1207 }
1208}
1209
1210struct EmLinker<'a> {
1211 cmd: Command,
1212 sess: &'a Session,
1213}
1214
1215impl<'a> Linker for EmLinker<'a> {
1216 fn cmd(&mut self) -> &mut Command {
1217 &mut self.cmd
1218 }
1219
1220 fn is_cc(&self) -> bool {
1221 true
1222 }
1223
1224 fn set_output_kind(
1225 &mut self,
1226 output_kind: LinkOutputKind,
1227 _crate_type: CrateType,
1228 _out_filename: &Path,
1229 ) {
1230 match output_kind {
1231 LinkOutputKind::DynamicNoPicExe | LinkOutputKind::DynamicPicExe => {
1232 self.cmd.arg("-sMAIN_MODULE=2");
1233 }
1234 LinkOutputKind::DynamicDylib | LinkOutputKind::StaticDylib => {
1235 self.cmd.arg("-sSIDE_MODULE=2");
1236 }
1237 LinkOutputKind::StaticNoPicExe | LinkOutputKind::StaticPicExe => {}
1239 LinkOutputKind::WasiReactorExe => {
1240 ::core::panicking::panic("internal error: entered unreachable code");unreachable!();
1241 }
1242 }
1243 }
1244
1245 fn link_dylib_by_name(&mut self, name: &str, _verbatim: bool, _as_needed: bool) {
1246 self.link_or_cc_args(&["-l", name]);
1248 }
1249
1250 fn link_dylib_by_path(&mut self, path: &Path, _as_needed: bool) {
1251 self.link_or_cc_arg(path);
1252 }
1253
1254 fn link_staticlib_by_name(&mut self, name: &str, _verbatim: bool, _whole_archive: bool) {
1255 self.link_or_cc_args(&["-l", name]);
1256 }
1257
1258 fn link_staticlib_by_path(&mut self, path: &Path, _whole_archive: bool) {
1259 self.link_or_cc_arg(path);
1260 }
1261
1262 fn full_relro(&mut self) {
1263 }
1265
1266 fn partial_relro(&mut self) {
1267 }
1269
1270 fn no_relro(&mut self) {
1271 }
1273
1274 fn gc_sections(&mut self, _keep_metadata: bool) {
1275 }
1277
1278 fn optimize(&mut self) {
1279 self.cc_arg(match self.sess.opts.optimize {
1281 OptLevel::No => "-O0",
1282 OptLevel::Less => "-O1",
1283 OptLevel::More => "-O2",
1284 OptLevel::Aggressive => "-O3",
1285 OptLevel::Size => "-Os",
1286 OptLevel::SizeMin => "-Oz",
1287 });
1288 }
1289
1290 fn pgo_gen(&mut self) {
1291 }
1293
1294 fn control_flow_guard(&mut self) {}
1295
1296 fn ehcont_guard(&mut self) {}
1297
1298 fn debuginfo(&mut self, _strip: Strip, _: &[PathBuf]) {
1299 self.cc_arg(match self.sess.opts.debuginfo {
1302 DebugInfo::None => "-g0",
1303 DebugInfo::Limited | DebugInfo::LineTablesOnly | DebugInfo::LineDirectivesOnly => {
1304 "--profiling-funcs"
1305 }
1306 DebugInfo::Full => "-g",
1307 });
1308 }
1309
1310 fn no_crt_objects(&mut self) {}
1311
1312 fn no_default_libraries(&mut self) {
1313 self.cc_arg("-nodefaultlibs");
1314 }
1315
1316 fn export_symbols(
1317 &mut self,
1318 _tmpdir: &Path,
1319 _crate_type: CrateType,
1320 symbols: &[(String, SymbolExportKind)],
1321 ) {
1322 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_codegen_ssa/src/back/linker.rs:1322",
"rustc_codegen_ssa::back::linker", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_codegen_ssa/src/back/linker.rs"),
::tracing_core::__macro_support::Option::Some(1322u32),
::tracing_core::__macro_support::Option::Some("rustc_codegen_ssa::back::linker"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("EXPORTED SYMBOLS:")
as &dyn Value))])
});
} else { ; }
};debug!("EXPORTED SYMBOLS:");
1323
1324 self.cc_arg("-s");
1325
1326 let mut arg = OsString::from("EXPORTED_FUNCTIONS=");
1327 let encoded = serde_json::to_string(
1328 &symbols.iter().map(|(sym, _)| "_".to_owned() + sym).collect::<Vec<_>>(),
1329 )
1330 .unwrap();
1331 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_codegen_ssa/src/back/linker.rs:1331",
"rustc_codegen_ssa::back::linker", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_codegen_ssa/src/back/linker.rs"),
::tracing_core::__macro_support::Option::Some(1331u32),
::tracing_core::__macro_support::Option::Some("rustc_codegen_ssa::back::linker"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("{0}",
encoded) as &dyn Value))])
});
} else { ; }
};debug!("{encoded}");
1332
1333 arg.push(encoded);
1334
1335 self.cc_arg(arg);
1336 }
1337
1338 fn windows_subsystem(&mut self, _subsystem: WindowsSubsystemKind) {
1339 }
1341
1342 fn linker_plugin_lto(&mut self) {
1343 }
1345}
1346
1347struct WasmLd<'a> {
1348 cmd: Command,
1349 sess: &'a Session,
1350}
1351
1352impl<'a> WasmLd<'a> {
1353 fn new(cmd: Command, sess: &'a Session) -> WasmLd<'a> {
1354 WasmLd { cmd, sess }
1355 }
1356}
1357
1358impl<'a> Linker for WasmLd<'a> {
1359 fn cmd(&mut self) -> &mut Command {
1360 &mut self.cmd
1361 }
1362
1363 fn set_output_kind(
1364 &mut self,
1365 output_kind: LinkOutputKind,
1366 _crate_type: CrateType,
1367 _out_filename: &Path,
1368 ) {
1369 match output_kind {
1370 LinkOutputKind::DynamicNoPicExe
1371 | LinkOutputKind::DynamicPicExe
1372 | LinkOutputKind::StaticNoPicExe
1373 | LinkOutputKind::StaticPicExe => {}
1374 LinkOutputKind::DynamicDylib | LinkOutputKind::StaticDylib => {
1375 self.link_arg("--no-entry");
1376 }
1377 LinkOutputKind::WasiReactorExe => {
1378 self.link_args(&["--entry", "_initialize"]);
1379 }
1380 }
1381 }
1382
1383 fn link_dylib_by_name(&mut self, name: &str, _verbatim: bool, _as_needed: bool) {
1384 self.link_or_cc_args(&["-l", name]);
1385 }
1386
1387 fn link_dylib_by_path(&mut self, path: &Path, _as_needed: bool) {
1388 self.link_or_cc_arg(path);
1389 }
1390
1391 fn link_staticlib_by_name(&mut self, name: &str, _verbatim: bool, whole_archive: bool) {
1392 if !whole_archive {
1393 self.link_or_cc_args(&["-l", name]);
1394 } else {
1395 self.link_arg("--whole-archive")
1396 .link_or_cc_args(&["-l", name])
1397 .link_arg("--no-whole-archive");
1398 }
1399 }
1400
1401 fn link_staticlib_by_path(&mut self, path: &Path, whole_archive: bool) {
1402 if !whole_archive {
1403 self.link_or_cc_arg(path);
1404 } else {
1405 self.link_arg("--whole-archive").link_or_cc_arg(path).link_arg("--no-whole-archive");
1406 }
1407 }
1408
1409 fn full_relro(&mut self) {}
1410
1411 fn partial_relro(&mut self) {}
1412
1413 fn no_relro(&mut self) {}
1414
1415 fn gc_sections(&mut self, _keep_metadata: bool) {
1416 self.link_arg("--gc-sections");
1417 }
1418
1419 fn optimize(&mut self) {
1420 self.link_arg(match self.sess.opts.optimize {
1423 OptLevel::No => "-O0",
1424 OptLevel::Less => "-O1",
1425 OptLevel::More => "-O2",
1426 OptLevel::Aggressive => "-O3",
1427 OptLevel::Size => "-O2",
1430 OptLevel::SizeMin => "-O2",
1431 });
1432 }
1433
1434 fn pgo_gen(&mut self) {}
1435
1436 fn debuginfo(&mut self, strip: Strip, _: &[PathBuf]) {
1437 match strip {
1438 Strip::None => {}
1439 Strip::Debuginfo => {
1440 self.link_arg("--strip-debug");
1441 }
1442 Strip::Symbols => {
1443 self.link_arg("--strip-all");
1444 }
1445 }
1446 }
1447
1448 fn control_flow_guard(&mut self) {}
1449
1450 fn ehcont_guard(&mut self) {}
1451
1452 fn no_crt_objects(&mut self) {}
1453
1454 fn no_default_libraries(&mut self) {}
1455
1456 fn export_symbols(
1457 &mut self,
1458 _tmpdir: &Path,
1459 _crate_type: CrateType,
1460 symbols: &[(String, SymbolExportKind)],
1461 ) {
1462 for (sym, _) in symbols {
1463 self.link_args(&["--export", sym]);
1464 }
1465 }
1466
1467 fn windows_subsystem(&mut self, _subsystem: WindowsSubsystemKind) {}
1468
1469 fn linker_plugin_lto(&mut self) {
1470 match self.sess.opts.cg.linker_plugin_lto {
1471 LinkerPluginLto::Disabled => {
1472 }
1474 LinkerPluginLto::LinkerPluginAuto => {
1475 self.push_linker_plugin_lto_args();
1476 }
1477 LinkerPluginLto::LinkerPlugin(_) => {
1478 self.push_linker_plugin_lto_args();
1479 }
1480 }
1481 }
1482}
1483
1484impl<'a> WasmLd<'a> {
1485 fn push_linker_plugin_lto_args(&mut self) {
1486 let opt_level = match self.sess.opts.optimize {
1487 config::OptLevel::No => "O0",
1488 config::OptLevel::Less => "O1",
1489 config::OptLevel::More => "O2",
1490 config::OptLevel::Aggressive => "O3",
1491 config::OptLevel::Size | config::OptLevel::SizeMin => "O2",
1493 };
1494 self.link_arg(&::alloc::__export::must_use({
::alloc::fmt::format(format_args!("--lto-{0}", opt_level))
})format!("--lto-{opt_level}"));
1495 }
1496}
1497
1498struct L4Bender<'a> {
1500 cmd: Command,
1501 sess: &'a Session,
1502 hinted_static: bool,
1503}
1504
1505impl<'a> Linker for L4Bender<'a> {
1506 fn cmd(&mut self) -> &mut Command {
1507 &mut self.cmd
1508 }
1509
1510 fn set_output_kind(
1511 &mut self,
1512 _output_kind: LinkOutputKind,
1513 _crate_type: CrateType,
1514 _out_filename: &Path,
1515 ) {
1516 }
1517
1518 fn link_staticlib_by_name(&mut self, name: &str, _verbatim: bool, whole_archive: bool) {
1519 self.hint_static();
1520 if !whole_archive {
1521 self.link_arg(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("-PC{0}", name))
})format!("-PC{name}"));
1522 } else {
1523 self.link_arg("--whole-archive")
1524 .link_or_cc_arg(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("-l{0}", name))
})format!("-l{name}"))
1525 .link_arg("--no-whole-archive");
1526 }
1527 }
1528
1529 fn link_staticlib_by_path(&mut self, path: &Path, whole_archive: bool) {
1530 self.hint_static();
1531 if !whole_archive {
1532 self.link_or_cc_arg(path);
1533 } else {
1534 self.link_arg("--whole-archive").link_or_cc_arg(path).link_arg("--no-whole-archive");
1535 }
1536 }
1537
1538 fn full_relro(&mut self) {
1539 self.link_args(&["-z", "relro", "-z", "now"]);
1540 }
1541
1542 fn partial_relro(&mut self) {
1543 self.link_args(&["-z", "relro"]);
1544 }
1545
1546 fn no_relro(&mut self) {
1547 self.link_args(&["-z", "norelro"]);
1548 }
1549
1550 fn gc_sections(&mut self, keep_metadata: bool) {
1551 if !keep_metadata {
1552 self.link_arg("--gc-sections");
1553 }
1554 }
1555
1556 fn optimize(&mut self) {
1557 if self.sess.opts.optimize == config::OptLevel::More
1560 || self.sess.opts.optimize == config::OptLevel::Aggressive
1561 {
1562 self.link_arg("-O1");
1563 }
1564 }
1565
1566 fn pgo_gen(&mut self) {}
1567
1568 fn debuginfo(&mut self, strip: Strip, _: &[PathBuf]) {
1569 match strip {
1570 Strip::None => {}
1571 Strip::Debuginfo => {
1572 self.link_arg("--strip-debug");
1573 }
1574 Strip::Symbols => {
1575 self.link_arg("--strip-all");
1576 }
1577 }
1578 }
1579
1580 fn no_default_libraries(&mut self) {
1581 self.cc_arg("-nostdlib");
1582 }
1583
1584 fn export_symbols(&mut self, _: &Path, _: CrateType, _: &[(String, SymbolExportKind)]) {
1585 self.sess.dcx().emit_warn(errors::L4BenderExportingSymbolsUnimplemented);
1587 }
1588
1589 fn windows_subsystem(&mut self, subsystem: WindowsSubsystemKind) {
1590 let subsystem = subsystem.as_str();
1591 self.link_arg(&::alloc::__export::must_use({
::alloc::fmt::format(format_args!("--subsystem {0}", subsystem))
})format!("--subsystem {subsystem}"));
1592 }
1593
1594 fn reset_per_library_state(&mut self) {
1595 self.hint_static(); }
1597
1598 fn linker_plugin_lto(&mut self) {}
1599
1600 fn control_flow_guard(&mut self) {}
1601
1602 fn ehcont_guard(&mut self) {}
1603
1604 fn no_crt_objects(&mut self) {}
1605}
1606
1607impl<'a> L4Bender<'a> {
1608 fn new(cmd: Command, sess: &'a Session) -> L4Bender<'a> {
1609 L4Bender { cmd, sess, hinted_static: false }
1610 }
1611
1612 fn hint_static(&mut self) {
1613 if !self.hinted_static {
1614 self.link_or_cc_arg("-static");
1615 self.hinted_static = true;
1616 }
1617 }
1618}
1619
1620struct AixLinker<'a> {
1622 cmd: Command,
1623 sess: &'a Session,
1624 hinted_static: Option<bool>,
1625}
1626
1627impl<'a> AixLinker<'a> {
1628 fn new(cmd: Command, sess: &'a Session) -> AixLinker<'a> {
1629 AixLinker { cmd, sess, hinted_static: None }
1630 }
1631
1632 fn hint_static(&mut self) {
1633 if self.hinted_static != Some(true) {
1634 self.link_arg("-bstatic");
1635 self.hinted_static = Some(true);
1636 }
1637 }
1638
1639 fn hint_dynamic(&mut self) {
1640 if self.hinted_static != Some(false) {
1641 self.link_arg("-bdynamic");
1642 self.hinted_static = Some(false);
1643 }
1644 }
1645
1646 fn build_dylib(&mut self, _out_filename: &Path) {
1647 self.link_args(&["-bM:SRE", "-bnoentry"]);
1648 self.link_arg("-bexpfull");
1651 }
1652}
1653
1654impl<'a> Linker for AixLinker<'a> {
1655 fn cmd(&mut self) -> &mut Command {
1656 &mut self.cmd
1657 }
1658
1659 fn set_output_kind(
1660 &mut self,
1661 output_kind: LinkOutputKind,
1662 _crate_type: CrateType,
1663 out_filename: &Path,
1664 ) {
1665 match output_kind {
1666 LinkOutputKind::DynamicDylib => {
1667 self.hint_dynamic();
1668 self.build_dylib(out_filename);
1669 }
1670 LinkOutputKind::StaticDylib => {
1671 self.hint_static();
1672 self.build_dylib(out_filename);
1673 }
1674 _ => {}
1675 }
1676 }
1677
1678 fn link_dylib_by_name(&mut self, name: &str, verbatim: bool, _as_needed: bool) {
1679 self.hint_dynamic();
1680 self.link_or_cc_arg(if verbatim { String::from(name) } else { ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("-l{0}", name))
})format!("-l{name}") });
1681 }
1682
1683 fn link_dylib_by_path(&mut self, path: &Path, _as_needed: bool) {
1684 self.hint_dynamic();
1685 self.link_or_cc_arg(path);
1686 }
1687
1688 fn link_staticlib_by_name(&mut self, name: &str, verbatim: bool, whole_archive: bool) {
1689 self.hint_static();
1690 if !whole_archive {
1691 self.link_or_cc_arg(if verbatim { String::from(name) } else { ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("-l{0}", name))
})format!("-l{name}") });
1692 } else {
1693 let mut arg = OsString::from("-bkeepfile:");
1694 arg.push(find_native_static_library(name, verbatim, self.sess));
1695 self.link_or_cc_arg(arg);
1696 }
1697 }
1698
1699 fn link_staticlib_by_path(&mut self, path: &Path, whole_archive: bool) {
1700 self.hint_static();
1701 if !whole_archive {
1702 self.link_or_cc_arg(path);
1703 } else {
1704 let mut arg = OsString::from("-bkeepfile:");
1705 arg.push(path);
1706 self.link_arg(arg);
1707 }
1708 }
1709
1710 fn full_relro(&mut self) {}
1711
1712 fn partial_relro(&mut self) {}
1713
1714 fn no_relro(&mut self) {}
1715
1716 fn gc_sections(&mut self, _keep_metadata: bool) {
1717 self.link_arg("-bgc");
1718 }
1719
1720 fn optimize(&mut self) {}
1721
1722 fn pgo_gen(&mut self) {
1723 self.link_arg("-bdbg:namedsects:ss");
1724 self.link_arg("-u");
1725 self.link_arg("__llvm_profile_runtime");
1726 }
1727
1728 fn control_flow_guard(&mut self) {}
1729
1730 fn ehcont_guard(&mut self) {}
1731
1732 fn debuginfo(&mut self, _: Strip, _: &[PathBuf]) {}
1733
1734 fn no_crt_objects(&mut self) {}
1735
1736 fn no_default_libraries(&mut self) {}
1737
1738 fn export_symbols(
1739 &mut self,
1740 tmpdir: &Path,
1741 _crate_type: CrateType,
1742 symbols: &[(String, SymbolExportKind)],
1743 ) {
1744 let path = tmpdir.join("list.exp");
1745 let res = try {
1746 let mut f = File::create_buffered(&path)?;
1747 for (symbol, _) in symbols {
1749 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_codegen_ssa/src/back/linker.rs:1749",
"rustc_codegen_ssa::back::linker", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_codegen_ssa/src/back/linker.rs"),
::tracing_core::__macro_support::Option::Some(1749u32),
::tracing_core::__macro_support::Option::Some("rustc_codegen_ssa::back::linker"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!(" _{0}",
symbol) as &dyn Value))])
});
} else { ; }
};debug!(" _{symbol}");
1750 f.write_fmt(format_args!(" {0}\n", symbol))writeln!(f, " {symbol}")?;
1751 }
1752 };
1753 if let Err(e) = res {
1754 self.sess.dcx().fatal(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("failed to write export file: {0}",
e))
})format!("failed to write export file: {e}"));
1755 }
1756 self.link_arg(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("-bE:{0}", path.to_str().unwrap()))
})format!("-bE:{}", path.to_str().unwrap()));
1757 }
1758
1759 fn windows_subsystem(&mut self, _subsystem: WindowsSubsystemKind) {}
1760
1761 fn reset_per_library_state(&mut self) {
1762 self.hint_dynamic();
1763 }
1764
1765 fn linker_plugin_lto(&mut self) {}
1766
1767 fn add_eh_frame_header(&mut self) {}
1768
1769 fn add_no_exec(&mut self) {}
1770
1771 fn add_as_needed(&mut self) {}
1772}
1773
1774fn for_each_exported_symbols_include_dep<'tcx>(
1775 tcx: TyCtxt<'tcx>,
1776 crate_type: CrateType,
1777 mut callback: impl FnMut(ExportedSymbol<'tcx>, SymbolExportInfo, CrateNum),
1778) {
1779 let formats = tcx.dependency_formats(());
1780 let deps = &formats[&crate_type];
1781
1782 for (cnum, dep_format) in deps.iter_enumerated() {
1783 if *dep_format == Linkage::Static {
1785 for &(symbol, info) in tcx.exported_non_generic_symbols(cnum).iter() {
1786 callback(symbol, info, cnum);
1787 }
1788 for &(symbol, info) in tcx.exported_generic_symbols(cnum).iter() {
1789 callback(symbol, info, cnum);
1790 }
1791 }
1792 }
1793}
1794
1795pub(crate) fn exported_symbols(
1796 tcx: TyCtxt<'_>,
1797 crate_type: CrateType,
1798) -> Vec<(String, SymbolExportKind)> {
1799 if let Some(ref exports) = tcx.sess.target.override_export_symbols {
1800 return exports
1801 .iter()
1802 .map(|name| {
1803 (
1804 name.to_string(),
1805 SymbolExportKind::Text,
1809 )
1810 })
1811 .collect();
1812 }
1813
1814 let mut symbols = if let CrateType::ProcMacro = crate_type {
1815 exported_symbols_for_proc_macro_crate(tcx)
1816 } else {
1817 exported_symbols_for_non_proc_macro(tcx, crate_type)
1818 };
1819
1820 if crate_type == CrateType::Dylib || crate_type == CrateType::ProcMacro {
1821 let metadata_symbol_name = exported_symbols::metadata_symbol_name(tcx);
1822 symbols.push((metadata_symbol_name, SymbolExportKind::Data));
1823 }
1824
1825 symbols
1826}
1827
1828fn exported_symbols_for_non_proc_macro(
1829 tcx: TyCtxt<'_>,
1830 crate_type: CrateType,
1831) -> Vec<(String, SymbolExportKind)> {
1832 let mut symbols = Vec::new();
1833 let export_threshold = symbol_export::crates_export_threshold(&[crate_type]);
1834 for_each_exported_symbols_include_dep(tcx, crate_type, |symbol, info, cnum| {
1835 if info.level.is_below_threshold(export_threshold) && !tcx.is_compiler_builtins(cnum) {
1839 symbols.push((
1840 symbol_export::exporting_symbol_name_for_instance_in_crate(tcx, symbol, cnum),
1841 info.kind,
1842 ));
1843 symbol_export::extend_exported_symbols(&mut symbols, tcx, symbol, cnum);
1844 }
1845 });
1846
1847 if export_threshold == SymbolExportLevel::Rust
1849 && needs_allocator_shim_for_linking(tcx.dependency_formats(()), crate_type)
1850 && let Some(kind) = tcx.allocator_kind(())
1851 {
1852 symbols.extend(allocator_shim_symbols(tcx, kind));
1853 }
1854
1855 symbols
1856}
1857
1858fn exported_symbols_for_proc_macro_crate(tcx: TyCtxt<'_>) -> Vec<(String, SymbolExportKind)> {
1859 if !tcx.sess.opts.output_types.should_codegen() {
1861 return Vec::new();
1862 }
1863
1864 let stable_crate_id = tcx.stable_crate_id(LOCAL_CRATE);
1865 let proc_macro_decls_name = tcx.sess.generate_proc_macro_decls_symbol(stable_crate_id);
1866
1867 ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[(proc_macro_decls_name, SymbolExportKind::Data)]))vec![(proc_macro_decls_name, SymbolExportKind::Data)]
1868}
1869
1870pub(crate) fn linked_symbols(
1871 tcx: TyCtxt<'_>,
1872 crate_type: CrateType,
1873) -> Vec<(String, SymbolExportKind)> {
1874 match crate_type {
1875 CrateType::Executable
1876 | CrateType::ProcMacro
1877 | CrateType::Cdylib
1878 | CrateType::Dylib
1879 | CrateType::Sdylib => (),
1880 CrateType::StaticLib | CrateType::Rlib => {
1881 return Vec::new();
1883 }
1884 }
1885
1886 match tcx.sess.lto() {
1887 Lto::No | Lto::ThinLocal => {}
1888 Lto::Thin | Lto::Fat => {
1889 return Vec::new();
1898 }
1899 }
1900
1901 let mut symbols = Vec::new();
1902
1903 let export_threshold = symbol_export::crates_export_threshold(&[crate_type]);
1904 for_each_exported_symbols_include_dep(tcx, crate_type, |symbol, info, cnum| {
1905 if info.level.is_below_threshold(export_threshold) && !tcx.is_compiler_builtins(cnum)
1906 || info.used
1907 || info.rustc_std_internal_symbol
1908 {
1909 symbols.push((
1910 symbol_export::linking_symbol_name_for_instance_in_crate(
1911 tcx, symbol, info.kind, cnum,
1912 ),
1913 info.kind,
1914 ));
1915 }
1916 });
1917
1918 symbols
1919}
1920
1921struct LlbcLinker<'a> {
1923 cmd: Command,
1924 sess: &'a Session,
1925}
1926
1927impl<'a> Linker for LlbcLinker<'a> {
1928 fn cmd(&mut self) -> &mut Command {
1929 &mut self.cmd
1930 }
1931
1932 fn set_output_kind(
1933 &mut self,
1934 _output_kind: LinkOutputKind,
1935 _crate_type: CrateType,
1936 _out_filename: &Path,
1937 ) {
1938 }
1939
1940 fn link_staticlib_by_name(&mut self, _name: &str, _verbatim: bool, _whole_archive: bool) {
1941 { ::core::panicking::panic_fmt(format_args!("staticlibs not supported")); }panic!("staticlibs not supported")
1942 }
1943
1944 fn link_staticlib_by_path(&mut self, path: &Path, _whole_archive: bool) {
1945 self.link_or_cc_arg(path);
1946 }
1947
1948 fn debuginfo(&mut self, _strip: Strip, _: &[PathBuf]) {
1949 self.link_arg("--debug");
1950 }
1951
1952 fn optimize(&mut self) {
1953 self.link_arg(match self.sess.opts.optimize {
1954 OptLevel::No => "-O0",
1955 OptLevel::Less => "-O1",
1956 OptLevel::More => "-O2",
1957 OptLevel::Aggressive => "-O3",
1958 OptLevel::Size => "-Os",
1959 OptLevel::SizeMin => "-Oz",
1960 });
1961 }
1962
1963 fn full_relro(&mut self) {}
1964
1965 fn partial_relro(&mut self) {}
1966
1967 fn no_relro(&mut self) {}
1968
1969 fn gc_sections(&mut self, _keep_metadata: bool) {}
1970
1971 fn pgo_gen(&mut self) {}
1972
1973 fn no_crt_objects(&mut self) {}
1974
1975 fn no_default_libraries(&mut self) {}
1976
1977 fn control_flow_guard(&mut self) {}
1978
1979 fn ehcont_guard(&mut self) {}
1980
1981 fn export_symbols(
1982 &mut self,
1983 _tmpdir: &Path,
1984 _crate_type: CrateType,
1985 symbols: &[(String, SymbolExportKind)],
1986 ) {
1987 match _crate_type {
1988 CrateType::Cdylib => {
1989 for (sym, _) in symbols {
1990 self.link_args(&["--export-symbol", sym]);
1991 }
1992 }
1993 _ => (),
1994 }
1995 }
1996
1997 fn windows_subsystem(&mut self, _subsystem: WindowsSubsystemKind) {}
1998
1999 fn linker_plugin_lto(&mut self) {}
2000}
2001
2002struct BpfLinker<'a> {
2003 cmd: Command,
2004 sess: &'a Session,
2005}
2006
2007impl<'a> Linker for BpfLinker<'a> {
2008 fn cmd(&mut self) -> &mut Command {
2009 &mut self.cmd
2010 }
2011
2012 fn set_output_kind(
2013 &mut self,
2014 _output_kind: LinkOutputKind,
2015 _crate_type: CrateType,
2016 _out_filename: &Path,
2017 ) {
2018 }
2019
2020 fn link_staticlib_by_name(&mut self, _name: &str, _verbatim: bool, _whole_archive: bool) {
2021 self.sess.dcx().emit_fatal(errors::BpfStaticlibNotSupported)
2022 }
2023
2024 fn link_staticlib_by_path(&mut self, path: &Path, _whole_archive: bool) {
2025 self.link_or_cc_arg(path);
2026 }
2027
2028 fn debuginfo(&mut self, _strip: Strip, _: &[PathBuf]) {
2029 self.link_arg("--debug");
2030 }
2031
2032 fn optimize(&mut self) {
2033 self.link_arg(match self.sess.opts.optimize {
2034 OptLevel::No => "-O0",
2035 OptLevel::Less => "-O1",
2036 OptLevel::More => "-O2",
2037 OptLevel::Aggressive => "-O3",
2038 OptLevel::Size => "-Os",
2039 OptLevel::SizeMin => "-Oz",
2040 });
2041 }
2042
2043 fn full_relro(&mut self) {}
2044
2045 fn partial_relro(&mut self) {}
2046
2047 fn no_relro(&mut self) {}
2048
2049 fn gc_sections(&mut self, _keep_metadata: bool) {}
2050
2051 fn pgo_gen(&mut self) {}
2052
2053 fn no_crt_objects(&mut self) {}
2054
2055 fn no_default_libraries(&mut self) {}
2056
2057 fn control_flow_guard(&mut self) {}
2058
2059 fn ehcont_guard(&mut self) {}
2060
2061 fn export_symbols(
2062 &mut self,
2063 tmpdir: &Path,
2064 _crate_type: CrateType,
2065 symbols: &[(String, SymbolExportKind)],
2066 ) {
2067 let path = tmpdir.join("symbols");
2068 let res = try {
2069 let mut f = File::create_buffered(&path)?;
2070 for (sym, _) in symbols {
2071 f.write_fmt(format_args!("{0}\n", sym))writeln!(f, "{sym}")?;
2072 }
2073 };
2074 if let Err(error) = res {
2075 self.sess.dcx().emit_fatal(errors::SymbolFileWriteFailure { error });
2076 } else {
2077 self.link_arg("--export-symbols").link_arg(&path);
2078 }
2079 }
2080
2081 fn windows_subsystem(&mut self, _subsystem: WindowsSubsystemKind) {}
2082
2083 fn linker_plugin_lto(&mut self) {}
2084}