1use std::ffi::{OsStr, OsString};
2use std::fs::{self, File};
3use std::io::prelude::*;
4use std::path::{Path, PathBuf};
5use std::{env, io, 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::{Abi, Arch, Cc, 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.abi == Abi::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.abi == Abi::Uwp) {
::core::panicking::panic("assertion failed: cmd.get_args().is_empty() || sess.target.abi == Abi::Uwp")
};assert!(cmd.get_args().is_empty() || sess.target.abi == Abi::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 LinkerFlavor::Ptx => Box::new(PtxLinker { cmd, sess }) as Box<dyn Linker>,
165 }
166}
167
168fn verbatim_args<L: Linker + ?Sized>(
178 l: &mut L,
179 args: impl IntoIterator<Item: AsRef<OsStr>>,
180) -> &mut L {
181 for arg in args {
182 l.cmd().arg(arg);
183 }
184 l
185}
186fn convert_link_args_to_cc_args(cmd: &mut Command, args: impl IntoIterator<Item: AsRef<OsStr>>) {
189 let mut combined_arg = OsString::from("-Wl");
190 for arg in args {
191 if arg.as_ref().as_encoded_bytes().contains(&b',') {
194 if combined_arg != OsStr::new("-Wl") {
196 cmd.arg(combined_arg);
197 combined_arg = OsString::from("-Wl");
199 }
200
201 cmd.arg("-Xlinker");
203 cmd.arg(arg);
204 } else {
205 combined_arg.push(",");
207 combined_arg.push(arg);
208 }
209 }
210 if combined_arg != OsStr::new("-Wl") {
212 cmd.arg(combined_arg);
213 }
214}
215fn link_args<L: Linker + ?Sized>(l: &mut L, args: impl IntoIterator<Item: AsRef<OsStr>>) -> &mut L {
218 if !l.is_cc() {
219 verbatim_args(l, args);
220 } else {
221 convert_link_args_to_cc_args(l.cmd(), args);
222 }
223 l
224}
225fn cc_args<L: Linker + ?Sized>(l: &mut L, args: impl IntoIterator<Item: AsRef<OsStr>>) -> &mut L {
228 if !l.is_cc() { ::core::panicking::panic("assertion failed: l.is_cc()") };assert!(l.is_cc());
229 verbatim_args(l, args)
230}
231fn link_or_cc_args<L: Linker + ?Sized>(
233 l: &mut L,
234 args: impl IntoIterator<Item: AsRef<OsStr>>,
235) -> &mut L {
236 verbatim_args(l, args)
237}
238
239macro_rules! generate_arg_methods {
240 ($($ty:ty)*) => { $(
241 impl $ty {
242 #[allow(unused)]
243 pub(crate) fn verbatim_args(&mut self, args: impl IntoIterator<Item: AsRef<OsStr>>) -> &mut Self {
244 verbatim_args(self, args)
245 }
246 #[allow(unused)]
247 pub(crate) fn verbatim_arg(&mut self, arg: impl AsRef<OsStr>) -> &mut Self {
248 verbatim_args(self, iter::once(arg))
249 }
250 #[allow(unused)]
251 pub(crate) fn link_args(&mut self, args: impl IntoIterator<Item: AsRef<OsStr>>) -> &mut Self {
252 link_args(self, args)
253 }
254 #[allow(unused)]
255 pub(crate) fn link_arg(&mut self, arg: impl AsRef<OsStr>) -> &mut Self {
256 link_args(self, iter::once(arg))
257 }
258 #[allow(unused)]
259 pub(crate) fn cc_args(&mut self, args: impl IntoIterator<Item: AsRef<OsStr>>) -> &mut Self {
260 cc_args(self, args)
261 }
262 #[allow(unused)]
263 pub(crate) fn cc_arg(&mut self, arg: impl AsRef<OsStr>) -> &mut Self {
264 cc_args(self, iter::once(arg))
265 }
266 #[allow(unused)]
267 pub(crate) fn link_or_cc_args(&mut self, args: impl IntoIterator<Item: AsRef<OsStr>>) -> &mut Self {
268 link_or_cc_args(self, args)
269 }
270 #[allow(unused)]
271 pub(crate) fn link_or_cc_arg(&mut self, arg: impl AsRef<OsStr>) -> &mut Self {
272 link_or_cc_args(self, iter::once(arg))
273 }
274 }
275 )* }
276}
277
278impl 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! {
279 GccLinker<'_>
280 MsvcLinker<'_>
281 EmLinker<'_>
282 WasmLd<'_>
283 L4Bender<'_>
284 AixLinker<'_>
285 LlbcLinker<'_>
286 PtxLinker<'_>
287 BpfLinker<'_>
288 dyn Linker + '_
289}
290
291pub(crate) trait Linker {
299 fn cmd(&mut self) -> &mut Command;
300 fn is_cc(&self) -> bool {
301 false
302 }
303 fn set_output_kind(
304 &mut self,
305 output_kind: LinkOutputKind,
306 crate_type: CrateType,
307 out_filename: &Path,
308 );
309 fn link_dylib_by_name(&mut self, _name: &str, _verbatim: bool, _as_needed: bool) {
310 ::rustc_middle::util::bug::bug_fmt(format_args!("dylib linked with unsupported linker"))bug!("dylib linked with unsupported linker")
311 }
312 fn link_dylib_by_path(&mut self, _path: &Path, _as_needed: bool) {
313 ::rustc_middle::util::bug::bug_fmt(format_args!("dylib linked with unsupported linker"))bug!("dylib linked with unsupported linker")
314 }
315 fn link_framework_by_name(&mut self, _name: &str, _verbatim: bool, _as_needed: bool) {
316 ::rustc_middle::util::bug::bug_fmt(format_args!("framework linked with unsupported linker"))bug!("framework linked with unsupported linker")
317 }
318 fn link_staticlib_by_name(&mut self, name: &str, verbatim: bool, whole_archive: bool);
319 fn link_staticlib_by_path(&mut self, path: &Path, whole_archive: bool);
320 fn include_path(&mut self, path: &Path) {
321 link_or_cc_args(link_or_cc_args(self, &["-L"]), &[path]);
322 }
323 fn framework_path(&mut self, _path: &Path) {
324 ::rustc_middle::util::bug::bug_fmt(format_args!("framework path set with unsupported linker"))bug!("framework path set with unsupported linker")
325 }
326 fn output_filename(&mut self, path: &Path) {
327 link_or_cc_args(link_or_cc_args(self, &["-o"]), &[path]);
328 }
329 fn add_object(&mut self, path: &Path) {
330 link_or_cc_args(self, &[path]);
331 }
332 fn gc_sections(&mut self, keep_metadata: bool);
333 fn full_relro(&mut self);
334 fn partial_relro(&mut self);
335 fn no_relro(&mut self);
336 fn optimize(&mut self);
337 fn pgo_gen(&mut self);
338 fn control_flow_guard(&mut self);
339 fn ehcont_guard(&mut self);
340 fn debuginfo(&mut self, strip: Strip, natvis_debugger_visualizers: &[PathBuf]);
341 fn no_crt_objects(&mut self);
342 fn no_default_libraries(&mut self);
343 fn export_symbols(
344 &mut self,
345 tmpdir: &Path,
346 crate_type: CrateType,
347 symbols: &[(String, SymbolExportKind)],
348 );
349 fn windows_subsystem(&mut self, subsystem: WindowsSubsystemKind);
350 fn linker_plugin_lto(&mut self);
351 fn add_eh_frame_header(&mut self) {}
352 fn add_no_exec(&mut self) {}
353 fn add_as_needed(&mut self) {}
354 fn reset_per_library_state(&mut self) {}
355}
356
357impl dyn Linker + '_ {
358 pub(crate) fn take_cmd(&mut self) -> Command {
359 mem::replace(self.cmd(), Command::new(""))
360 }
361}
362
363struct GccLinker<'a> {
364 cmd: Command,
365 sess: &'a Session,
366 target_cpu: &'a str,
367 hinted_static: Option<bool>, is_ld: bool,
370 is_gnu: bool,
371 uses_lld: bool,
372 codegen_backend: &'static str,
373}
374
375impl<'a> GccLinker<'a> {
376 fn takes_hints(&self) -> bool {
377 !self.sess.target.is_like_darwin && !self.sess.target.is_like_wasm
386 }
387
388 fn hint_static(&mut self) {
393 if !self.takes_hints() {
394 return;
395 }
396 if self.hinted_static != Some(true) {
397 self.link_arg("-Bstatic");
398 self.hinted_static = Some(true);
399 }
400 }
401
402 fn hint_dynamic(&mut self) {
403 if !self.takes_hints() {
404 return;
405 }
406 if self.hinted_static != Some(false) {
407 self.link_arg("-Bdynamic");
408 self.hinted_static = Some(false);
409 }
410 }
411
412 fn push_linker_plugin_lto_args(&mut self, plugin_path: Option<&OsStr>) {
413 if let Some(plugin_path) = plugin_path {
414 let mut arg = OsString::from("-plugin=");
415 arg.push(plugin_path);
416 self.link_arg(&arg);
417 }
418
419 let opt_level = match self.sess.opts.optimize {
420 config::OptLevel::No => "O0",
421 config::OptLevel::Less => "O1",
422 config::OptLevel::More | config::OptLevel::Size | config::OptLevel::SizeMin => "O2",
423 config::OptLevel::Aggressive => "O3",
424 };
425
426 if let Some(path) = &self.sess.opts.unstable_opts.profile_sample_use {
427 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()));
428 };
429 let prefix = if self.codegen_backend == "gcc" {
430 "-"
432 } else {
433 ""
434 };
435 self.link_args(&[
436 &::alloc::__export::must_use({
::alloc::fmt::format(format_args!("-plugin-opt={0}{1}", prefix,
opt_level))
})format!("-plugin-opt={prefix}{opt_level}"),
437 &::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),
438 ]);
439 }
440
441 fn build_dylib(&mut self, crate_type: CrateType, out_filename: &Path) {
442 if self.sess.target.is_like_darwin {
444 if self.is_cc() {
445 self.cc_arg("-dynamiclib");
447 } else {
448 self.link_arg("-dylib");
449 }
451
452 if self.sess.opts.cg.rpath || self.sess.opts.unstable_opts.osx_rpath_install_name {
457 let mut rpath = OsString::from("@rpath/");
458 rpath.push(out_filename.file_name().unwrap());
459 self.link_arg("-install_name").link_arg(rpath);
460 }
461 } else {
462 self.link_or_cc_arg("-shared");
463 if let Some(name) = out_filename.file_name() {
464 if self.sess.target.is_like_windows {
465 let (prefix, suffix) = self.sess.staticlib_components(false);
469 let mut implib_name = OsString::from(prefix);
470 implib_name.push(name);
471 implib_name.push(suffix);
472 let mut out_implib = OsString::from("--out-implib=");
473 out_implib.push(out_filename.with_file_name(implib_name));
474 self.link_arg(out_implib);
475 } else if crate_type == CrateType::Dylib {
476 let mut soname = OsString::from("-soname=");
480 soname.push(name);
481 self.link_arg(soname);
482 }
483 }
484 }
485 }
486
487 fn with_as_needed(&mut self, as_needed: bool, f: impl FnOnce(&mut Self)) {
488 if !as_needed {
489 if self.sess.target.is_like_darwin {
490 self.sess.dcx().emit_warn(errors::Ld64UnimplementedModifier);
494 } else if self.is_gnu && !self.sess.target.is_like_windows {
495 self.link_arg("--no-as-needed");
496 } else {
497 self.sess.dcx().emit_warn(errors::LinkerUnsupportedModifier);
498 }
499 }
500
501 f(self);
502
503 if !as_needed {
504 if self.sess.target.is_like_darwin {
505 } else if self.is_gnu && !self.sess.target.is_like_windows {
507 self.link_arg("--as-needed");
508 }
509 }
510 }
511}
512
513impl<'a> Linker for GccLinker<'a> {
514 fn cmd(&mut self) -> &mut Command {
515 &mut self.cmd
516 }
517
518 fn is_cc(&self) -> bool {
519 !self.is_ld
520 }
521
522 fn set_output_kind(
523 &mut self,
524 output_kind: LinkOutputKind,
525 crate_type: CrateType,
526 out_filename: &Path,
527 ) {
528 match output_kind {
529 LinkOutputKind::DynamicNoPicExe => {
530 if !self.is_ld && self.is_gnu {
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 control_flow_guard(&mut self) {}
735
736 fn ehcont_guard(&mut self) {}
737
738 fn debuginfo(&mut self, strip: Strip, _: &[PathBuf]) {
739 if self.sess.target.is_like_darwin {
741 return;
742 }
743
744 match strip {
745 Strip::None => {}
746 Strip::Debuginfo => {
747 if !self.sess.target.is_like_solaris {
752 self.link_arg("--strip-debug");
753 }
754 }
755 Strip::Symbols => {
756 self.link_arg("--strip-all");
757 }
758 }
759 match self.sess.opts.unstable_opts.debuginfo_compression {
760 config::DebugInfoCompression::None => {}
761 config::DebugInfoCompression::Zlib => {
762 self.link_arg("--compress-debug-sections=zlib");
763 }
764 config::DebugInfoCompression::Zstd => {
765 self.link_arg("--compress-debug-sections=zstd");
766 }
767 }
768 }
769
770 fn no_crt_objects(&mut self) {
771 if !self.is_ld {
772 self.cc_arg("-nostartfiles");
773 }
774 }
775
776 fn no_default_libraries(&mut self) {
777 if !self.is_ld {
778 self.cc_arg("-nodefaultlibs");
779 }
780 }
781
782 fn export_symbols(
783 &mut self,
784 tmpdir: &Path,
785 crate_type: CrateType,
786 symbols: &[(String, SymbolExportKind)],
787 ) {
788 if crate_type == CrateType::Executable {
790 let should_export_executable_symbols =
791 self.sess.opts.unstable_opts.export_executable_symbols;
792 if self.sess.target.override_export_symbols.is_none()
793 && !should_export_executable_symbols
794 {
795 return;
796 }
797 }
798
799 if !self.sess.target.limit_rdylib_exports {
804 return;
805 }
806
807 let path = tmpdir.join(if self.sess.target.is_like_windows { "list.def" } else { "list" });
808 {
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:808",
"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(808u32),
::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:");
809
810 if self.sess.target.is_like_darwin {
811 let res: io::Result<()> = try {
813 let mut f = File::create_buffered(&path)?;
814 for (sym, _) in symbols {
815 {
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:815",
"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(815u32),
::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}");
816 f.write_fmt(format_args!("_{0}\n", sym))writeln!(f, "_{sym}")?;
817 }
818 };
819 if let Err(error) = res {
820 self.sess.dcx().emit_fatal(errors::LibDefWriteFailure { error });
821 }
822 self.link_arg("-exported_symbols_list").link_arg(path);
823 } else if self.sess.target.is_like_windows {
824 let res: io::Result<()> = try {
825 let mut f = File::create_buffered(&path)?;
826
827 f.write_fmt(format_args!("EXPORTS\n"))writeln!(f, "EXPORTS")?;
830 for (symbol, kind) in symbols {
831 let kind_marker = if *kind == SymbolExportKind::Data { " DATA" } else { "" };
832 {
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:832",
"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(832u32),
::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}");
833 f.write_fmt(format_args!(" \"{0}\"{1}\n", symbol, kind_marker))writeln!(f, " \"{symbol}\"{kind_marker}")?;
836 }
837 };
838 if let Err(error) = res {
839 self.sess.dcx().emit_fatal(errors::LibDefWriteFailure { error });
840 }
841 self.link_arg(path);
842 } else if self.sess.target.is_like_wasm {
843 self.link_arg("--no-export-dynamic");
844 for (sym, _) in symbols {
845 self.link_arg("--export").link_arg(sym);
846 }
847 } else if crate_type == CrateType::Executable && !self.sess.target.is_like_solaris {
848 let res: io::Result<()> = try {
849 let mut f = File::create_buffered(&path)?;
850 f.write_fmt(format_args!("{{\n"))writeln!(f, "{{")?;
851 for (sym, _) in symbols {
852 {
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:852",
"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(852u32),
::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);
853 f.write_fmt(format_args!(" {0};\n", sym))writeln!(f, " {sym};")?;
854 }
855 f.write_fmt(format_args!("}};\n"))writeln!(f, "}};")?;
856 };
857 if let Err(error) = res {
858 self.sess.dcx().emit_fatal(errors::VersionScriptWriteFailure { error });
859 }
860 self.link_arg("--dynamic-list").link_arg(path);
861 } else {
862 let res: io::Result<()> = try {
864 let mut f = File::create_buffered(&path)?;
865 f.write_fmt(format_args!("{{\n"))writeln!(f, "{{")?;
866 if !symbols.is_empty() {
867 f.write_fmt(format_args!(" global:\n"))writeln!(f, " global:")?;
868 for (sym, _) in symbols {
869 {
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:869",
"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(869u32),
::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};");
870 f.write_fmt(format_args!(" {0};\n", sym))writeln!(f, " {sym};")?;
871 }
872 }
873 f.write_fmt(format_args!("\n local:\n *;\n}};\n"))writeln!(f, "\n local:\n *;\n}};")?;
874 };
875 if let Err(error) = res {
876 self.sess.dcx().emit_fatal(errors::VersionScriptWriteFailure { error });
877 }
878 if self.sess.target.is_like_solaris {
879 self.link_arg("-M").link_arg(path);
880 } else {
881 let mut arg = OsString::from("--version-script=");
882 arg.push(path);
883 self.link_arg(arg).link_arg("--no-undefined-version");
884 }
885 }
886 }
887
888 fn windows_subsystem(&mut self, subsystem: WindowsSubsystemKind) {
889 self.link_args(&["--subsystem", subsystem.as_str()]);
890 }
891
892 fn reset_per_library_state(&mut self) {
893 self.hint_dynamic(); }
895
896 fn linker_plugin_lto(&mut self) {
897 match self.sess.opts.cg.linker_plugin_lto {
898 LinkerPluginLto::Disabled => {
899 }
901 LinkerPluginLto::LinkerPluginAuto => {
902 self.push_linker_plugin_lto_args(None);
903 }
904 LinkerPluginLto::LinkerPlugin(ref path) => {
905 self.push_linker_plugin_lto_args(Some(path.as_os_str()));
906 }
907 }
908 }
909
910 fn add_eh_frame_header(&mut self) {
914 self.link_arg("--eh-frame-hdr");
915 }
916
917 fn add_no_exec(&mut self) {
918 if self.sess.target.is_like_windows {
919 self.link_arg("--nxcompat");
920 } else if self.is_gnu {
921 self.link_args(&["-z", "noexecstack"]);
922 }
923 }
924
925 fn add_as_needed(&mut self) {
926 if self.is_gnu && !self.sess.target.is_like_windows {
927 self.link_arg("--as-needed");
928 } else if self.sess.target.is_like_solaris {
929 self.link_args(&["-z", "ignore"]);
931 }
932 }
933}
934
935struct MsvcLinker<'a> {
936 cmd: Command,
937 sess: &'a Session,
938}
939
940impl<'a> Linker for MsvcLinker<'a> {
941 fn cmd(&mut self) -> &mut Command {
942 &mut self.cmd
943 }
944
945 fn set_output_kind(
946 &mut self,
947 output_kind: LinkOutputKind,
948 _crate_type: CrateType,
949 out_filename: &Path,
950 ) {
951 match output_kind {
952 LinkOutputKind::DynamicNoPicExe
953 | LinkOutputKind::DynamicPicExe
954 | LinkOutputKind::StaticNoPicExe
955 | LinkOutputKind::StaticPicExe => {}
956 LinkOutputKind::DynamicDylib | LinkOutputKind::StaticDylib => {
957 self.link_arg("/DLL");
958 let mut arg: OsString = "/IMPLIB:".into();
959 arg.push(out_filename.with_extension("dll.lib"));
960 self.link_arg(arg);
961 }
962 LinkOutputKind::WasiReactorExe => {
963 {
::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");
964 }
965 }
966 }
967
968 fn link_dylib_by_name(&mut self, name: &str, verbatim: bool, _as_needed: bool) {
969 if let Some(path) = try_find_native_dynamic_library(self.sess, name, verbatim) {
972 self.link_arg(path);
973 } else {
974 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" }));
975 }
976 }
977
978 fn link_dylib_by_path(&mut self, path: &Path, _as_needed: bool) {
979 let implib_path = path.with_extension("dll.lib");
982 if implib_path.exists() {
983 self.link_or_cc_arg(implib_path);
984 }
985 }
986
987 fn link_staticlib_by_name(&mut self, name: &str, verbatim: bool, whole_archive: bool) {
988 if let Some(path) = try_find_native_static_library(self.sess, name, verbatim) {
991 self.link_staticlib_by_path(&path, whole_archive);
992 } else {
993 let opts = if whole_archive { "/WHOLEARCHIVE:" } else { "" };
994 let (prefix, suffix) = self.sess.staticlib_components(verbatim);
995 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}"));
996 }
997 }
998
999 fn link_staticlib_by_path(&mut self, path: &Path, whole_archive: bool) {
1000 if !whole_archive {
1001 self.link_arg(path);
1002 } else {
1003 let mut arg = OsString::from("/WHOLEARCHIVE:");
1004 arg.push(path);
1005 self.link_arg(arg);
1006 }
1007 }
1008
1009 fn gc_sections(&mut self, _keep_metadata: bool) {
1010 if self.sess.opts.optimize != config::OptLevel::No {
1014 self.link_arg("/OPT:REF,ICF");
1015 } else {
1016 self.link_arg("/OPT:REF,NOICF");
1019 }
1020 }
1021
1022 fn full_relro(&mut self) {
1023 }
1025
1026 fn partial_relro(&mut self) {
1027 }
1029
1030 fn no_relro(&mut self) {
1031 }
1033
1034 fn no_crt_objects(&mut self) {
1035 }
1037
1038 fn no_default_libraries(&mut self) {
1039 self.link_arg("/NODEFAULTLIB");
1040 }
1041
1042 fn include_path(&mut self, path: &Path) {
1043 let mut arg = OsString::from("/LIBPATH:");
1044 arg.push(path);
1045 self.link_arg(&arg);
1046 }
1047
1048 fn output_filename(&mut self, path: &Path) {
1049 let mut arg = OsString::from("/OUT:");
1050 arg.push(path);
1051 self.link_arg(&arg);
1052 }
1053
1054 fn optimize(&mut self) {
1055 }
1057
1058 fn pgo_gen(&mut self) {
1059 }
1061
1062 fn control_flow_guard(&mut self) {
1063 self.link_arg("/guard:cf");
1064 }
1065
1066 fn ehcont_guard(&mut self) {
1067 if self.sess.target.pointer_width == 64 {
1068 self.link_arg("/guard:ehcont");
1069 }
1070 }
1071
1072 fn debuginfo(&mut self, _strip: Strip, natvis_debugger_visualizers: &[PathBuf]) {
1073 self.link_arg("/DEBUG");
1076
1077 self.link_arg("/PDBALTPATH:%_PDB%");
1085
1086 let natvis_dir_path = self.sess.opts.sysroot.path().join("lib\\rustlib\\etc");
1088 if let Ok(natvis_dir) = fs::read_dir(&natvis_dir_path) {
1089 for entry in natvis_dir {
1090 match entry {
1091 Ok(entry) => {
1092 let path = entry.path();
1093 if path.extension() == Some("natvis".as_ref()) {
1094 let mut arg = OsString::from("/NATVIS:");
1095 arg.push(path);
1096 self.link_arg(arg);
1097 }
1098 }
1099 Err(error) => {
1100 self.sess.dcx().emit_warn(errors::NoNatvisDirectory { error });
1101 }
1102 }
1103 }
1104 }
1105
1106 for path in natvis_debugger_visualizers {
1108 let mut arg = OsString::from("/NATVIS:");
1109 arg.push(path);
1110 self.link_arg(arg);
1111 }
1112 }
1113
1114 fn export_symbols(
1127 &mut self,
1128 tmpdir: &Path,
1129 crate_type: CrateType,
1130 symbols: &[(String, SymbolExportKind)],
1131 ) {
1132 if crate_type == CrateType::Executable {
1134 let should_export_executable_symbols =
1135 self.sess.opts.unstable_opts.export_executable_symbols;
1136 if !should_export_executable_symbols {
1137 return;
1138 }
1139 }
1140
1141 let path = tmpdir.join("lib.def");
1142 let res: io::Result<()> = try {
1143 let mut f = File::create_buffered(&path)?;
1144
1145 f.write_fmt(format_args!("LIBRARY\n"))writeln!(f, "LIBRARY")?;
1148 f.write_fmt(format_args!("EXPORTS\n"))writeln!(f, "EXPORTS")?;
1149 for (symbol, kind) in symbols {
1150 let kind_marker = if *kind == SymbolExportKind::Data { " DATA" } else { "" };
1151 {
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:1151",
"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(1151u32),
::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}");
1152 f.write_fmt(format_args!(" {0}{1}\n", symbol, kind_marker))writeln!(f, " {symbol}{kind_marker}")?;
1153 }
1154 };
1155 if let Err(error) = res {
1156 self.sess.dcx().emit_fatal(errors::LibDefWriteFailure { error });
1157 }
1158 let mut arg = OsString::from("/DEF:");
1159 arg.push(path);
1160 self.link_arg(&arg);
1161 }
1162
1163 fn windows_subsystem(&mut self, subsystem: WindowsSubsystemKind) {
1164 let subsystem = subsystem.as_str();
1165 self.link_arg(&::alloc::__export::must_use({
::alloc::fmt::format(format_args!("/SUBSYSTEM:{0}", subsystem))
})format!("/SUBSYSTEM:{subsystem}"));
1166
1167 if subsystem == "windows" {
1182 self.link_arg("/ENTRY:mainCRTStartup");
1183 }
1184 }
1185
1186 fn linker_plugin_lto(&mut self) {
1187 }
1189
1190 fn add_no_exec(&mut self) {
1191 self.link_arg("/NXCOMPAT");
1192 }
1193}
1194
1195struct EmLinker<'a> {
1196 cmd: Command,
1197 sess: &'a Session,
1198}
1199
1200impl<'a> Linker for EmLinker<'a> {
1201 fn cmd(&mut self) -> &mut Command {
1202 &mut self.cmd
1203 }
1204
1205 fn is_cc(&self) -> bool {
1206 true
1207 }
1208
1209 fn set_output_kind(
1210 &mut self,
1211 output_kind: LinkOutputKind,
1212 _crate_type: CrateType,
1213 _out_filename: &Path,
1214 ) {
1215 match output_kind {
1216 LinkOutputKind::DynamicNoPicExe | LinkOutputKind::DynamicPicExe => {
1217 self.cmd.arg("-sMAIN_MODULE=2");
1218 }
1219 LinkOutputKind::DynamicDylib | LinkOutputKind::StaticDylib => {
1220 self.cmd.arg("-sSIDE_MODULE=2");
1221 }
1222 LinkOutputKind::StaticNoPicExe | LinkOutputKind::StaticPicExe => {}
1224 LinkOutputKind::WasiReactorExe => {
1225 ::core::panicking::panic("internal error: entered unreachable code");unreachable!();
1226 }
1227 }
1228 }
1229
1230 fn link_dylib_by_name(&mut self, name: &str, _verbatim: bool, _as_needed: bool) {
1231 self.link_or_cc_args(&["-l", name]);
1233 }
1234
1235 fn link_dylib_by_path(&mut self, path: &Path, _as_needed: bool) {
1236 self.link_or_cc_arg(path);
1237 }
1238
1239 fn link_staticlib_by_name(&mut self, name: &str, _verbatim: bool, _whole_archive: bool) {
1240 self.link_or_cc_args(&["-l", name]);
1241 }
1242
1243 fn link_staticlib_by_path(&mut self, path: &Path, _whole_archive: bool) {
1244 self.link_or_cc_arg(path);
1245 }
1246
1247 fn full_relro(&mut self) {
1248 }
1250
1251 fn partial_relro(&mut self) {
1252 }
1254
1255 fn no_relro(&mut self) {
1256 }
1258
1259 fn gc_sections(&mut self, _keep_metadata: bool) {
1260 }
1262
1263 fn optimize(&mut self) {
1264 self.cc_arg(match self.sess.opts.optimize {
1266 OptLevel::No => "-O0",
1267 OptLevel::Less => "-O1",
1268 OptLevel::More => "-O2",
1269 OptLevel::Aggressive => "-O3",
1270 OptLevel::Size => "-Os",
1271 OptLevel::SizeMin => "-Oz",
1272 });
1273 }
1274
1275 fn pgo_gen(&mut self) {
1276 }
1278
1279 fn control_flow_guard(&mut self) {}
1280
1281 fn ehcont_guard(&mut self) {}
1282
1283 fn debuginfo(&mut self, _strip: Strip, _: &[PathBuf]) {
1284 self.cc_arg(match self.sess.opts.debuginfo {
1287 DebugInfo::None => "-g0",
1288 DebugInfo::Limited | DebugInfo::LineTablesOnly | DebugInfo::LineDirectivesOnly => {
1289 "--profiling-funcs"
1290 }
1291 DebugInfo::Full => "-g",
1292 });
1293 }
1294
1295 fn no_crt_objects(&mut self) {}
1296
1297 fn no_default_libraries(&mut self) {
1298 self.cc_arg("-nodefaultlibs");
1299 }
1300
1301 fn export_symbols(
1302 &mut self,
1303 _tmpdir: &Path,
1304 _crate_type: CrateType,
1305 symbols: &[(String, SymbolExportKind)],
1306 ) {
1307 {
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:1307",
"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(1307u32),
::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:");
1308
1309 self.cc_arg("-s");
1310
1311 let mut arg = OsString::from("EXPORTED_FUNCTIONS=");
1312 let encoded = serde_json::to_string(
1313 &symbols.iter().map(|(sym, _)| "_".to_owned() + sym).collect::<Vec<_>>(),
1314 )
1315 .unwrap();
1316 {
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:1316",
"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(1316u32),
::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}");
1317
1318 arg.push(encoded);
1319
1320 self.cc_arg(arg);
1321 }
1322
1323 fn windows_subsystem(&mut self, _subsystem: WindowsSubsystemKind) {
1324 }
1326
1327 fn linker_plugin_lto(&mut self) {
1328 }
1330}
1331
1332struct WasmLd<'a> {
1333 cmd: Command,
1334 sess: &'a Session,
1335}
1336
1337impl<'a> WasmLd<'a> {
1338 fn new(cmd: Command, sess: &'a Session) -> WasmLd<'a> {
1339 WasmLd { cmd, sess }
1340 }
1341}
1342
1343impl<'a> Linker for WasmLd<'a> {
1344 fn cmd(&mut self) -> &mut Command {
1345 &mut self.cmd
1346 }
1347
1348 fn set_output_kind(
1349 &mut self,
1350 output_kind: LinkOutputKind,
1351 _crate_type: CrateType,
1352 _out_filename: &Path,
1353 ) {
1354 match output_kind {
1355 LinkOutputKind::DynamicNoPicExe
1356 | LinkOutputKind::DynamicPicExe
1357 | LinkOutputKind::StaticNoPicExe
1358 | LinkOutputKind::StaticPicExe => {}
1359 LinkOutputKind::DynamicDylib | LinkOutputKind::StaticDylib => {
1360 self.link_arg("--no-entry");
1361 }
1362 LinkOutputKind::WasiReactorExe => {
1363 self.link_args(&["--entry", "_initialize"]);
1364 }
1365 }
1366 }
1367
1368 fn link_dylib_by_name(&mut self, name: &str, _verbatim: bool, _as_needed: bool) {
1369 self.link_or_cc_args(&["-l", name]);
1370 }
1371
1372 fn link_dylib_by_path(&mut self, path: &Path, _as_needed: bool) {
1373 self.link_or_cc_arg(path);
1374 }
1375
1376 fn link_staticlib_by_name(&mut self, name: &str, _verbatim: bool, whole_archive: bool) {
1377 if !whole_archive {
1378 self.link_or_cc_args(&["-l", name]);
1379 } else {
1380 self.link_arg("--whole-archive")
1381 .link_or_cc_args(&["-l", name])
1382 .link_arg("--no-whole-archive");
1383 }
1384 }
1385
1386 fn link_staticlib_by_path(&mut self, path: &Path, whole_archive: bool) {
1387 if !whole_archive {
1388 self.link_or_cc_arg(path);
1389 } else {
1390 self.link_arg("--whole-archive").link_or_cc_arg(path).link_arg("--no-whole-archive");
1391 }
1392 }
1393
1394 fn full_relro(&mut self) {}
1395
1396 fn partial_relro(&mut self) {}
1397
1398 fn no_relro(&mut self) {}
1399
1400 fn gc_sections(&mut self, _keep_metadata: bool) {
1401 self.link_arg("--gc-sections");
1402 }
1403
1404 fn optimize(&mut self) {
1405 self.link_arg(match self.sess.opts.optimize {
1408 OptLevel::No => "-O0",
1409 OptLevel::Less => "-O1",
1410 OptLevel::More => "-O2",
1411 OptLevel::Aggressive => "-O3",
1412 OptLevel::Size => "-O2",
1415 OptLevel::SizeMin => "-O2",
1416 });
1417 }
1418
1419 fn pgo_gen(&mut self) {}
1420
1421 fn debuginfo(&mut self, strip: Strip, _: &[PathBuf]) {
1422 match strip {
1423 Strip::None => {}
1424 Strip::Debuginfo => {
1425 self.link_arg("--strip-debug");
1426 }
1427 Strip::Symbols => {
1428 self.link_arg("--strip-all");
1429 }
1430 }
1431 }
1432
1433 fn control_flow_guard(&mut self) {}
1434
1435 fn ehcont_guard(&mut self) {}
1436
1437 fn no_crt_objects(&mut self) {}
1438
1439 fn no_default_libraries(&mut self) {}
1440
1441 fn export_symbols(
1442 &mut self,
1443 _tmpdir: &Path,
1444 _crate_type: CrateType,
1445 symbols: &[(String, SymbolExportKind)],
1446 ) {
1447 for (sym, _) in symbols {
1448 self.link_args(&["--export", sym]);
1449 }
1450
1451 if #[allow(non_exhaustive_omitted_patterns)] match self.sess.target.os {
Os::Unknown | Os::None => true,
_ => false,
}matches!(self.sess.target.os, Os::Unknown | Os::None) {
1456 self.link_args(&["--export=__heap_base", "--export=__data_end"]);
1457 }
1458 }
1459
1460 fn windows_subsystem(&mut self, _subsystem: WindowsSubsystemKind) {}
1461
1462 fn linker_plugin_lto(&mut self) {
1463 match self.sess.opts.cg.linker_plugin_lto {
1464 LinkerPluginLto::Disabled => {
1465 }
1467 LinkerPluginLto::LinkerPluginAuto => {
1468 self.push_linker_plugin_lto_args();
1469 }
1470 LinkerPluginLto::LinkerPlugin(_) => {
1471 self.push_linker_plugin_lto_args();
1472 }
1473 }
1474 }
1475}
1476
1477impl<'a> WasmLd<'a> {
1478 fn push_linker_plugin_lto_args(&mut self) {
1479 let opt_level = match self.sess.opts.optimize {
1480 config::OptLevel::No => "O0",
1481 config::OptLevel::Less => "O1",
1482 config::OptLevel::More => "O2",
1483 config::OptLevel::Aggressive => "O3",
1484 config::OptLevel::Size | config::OptLevel::SizeMin => "O2",
1486 };
1487 self.link_arg(&::alloc::__export::must_use({
::alloc::fmt::format(format_args!("--lto-{0}", opt_level))
})format!("--lto-{opt_level}"));
1488 }
1489}
1490
1491struct L4Bender<'a> {
1493 cmd: Command,
1494 sess: &'a Session,
1495 hinted_static: bool,
1496}
1497
1498impl<'a> Linker for L4Bender<'a> {
1499 fn cmd(&mut self) -> &mut Command {
1500 &mut self.cmd
1501 }
1502
1503 fn set_output_kind(
1504 &mut self,
1505 _output_kind: LinkOutputKind,
1506 _crate_type: CrateType,
1507 _out_filename: &Path,
1508 ) {
1509 }
1510
1511 fn link_staticlib_by_name(&mut self, name: &str, _verbatim: bool, whole_archive: bool) {
1512 self.hint_static();
1513 if !whole_archive {
1514 self.link_arg(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("-PC{0}", name))
})format!("-PC{name}"));
1515 } else {
1516 self.link_arg("--whole-archive")
1517 .link_or_cc_arg(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("-l{0}", name))
})format!("-l{name}"))
1518 .link_arg("--no-whole-archive");
1519 }
1520 }
1521
1522 fn link_staticlib_by_path(&mut self, path: &Path, whole_archive: bool) {
1523 self.hint_static();
1524 if !whole_archive {
1525 self.link_or_cc_arg(path);
1526 } else {
1527 self.link_arg("--whole-archive").link_or_cc_arg(path).link_arg("--no-whole-archive");
1528 }
1529 }
1530
1531 fn full_relro(&mut self) {
1532 self.link_args(&["-z", "relro", "-z", "now"]);
1533 }
1534
1535 fn partial_relro(&mut self) {
1536 self.link_args(&["-z", "relro"]);
1537 }
1538
1539 fn no_relro(&mut self) {
1540 self.link_args(&["-z", "norelro"]);
1541 }
1542
1543 fn gc_sections(&mut self, keep_metadata: bool) {
1544 if !keep_metadata {
1545 self.link_arg("--gc-sections");
1546 }
1547 }
1548
1549 fn optimize(&mut self) {
1550 if self.sess.opts.optimize == config::OptLevel::More
1553 || self.sess.opts.optimize == config::OptLevel::Aggressive
1554 {
1555 self.link_arg("-O1");
1556 }
1557 }
1558
1559 fn pgo_gen(&mut self) {}
1560
1561 fn debuginfo(&mut self, strip: Strip, _: &[PathBuf]) {
1562 match strip {
1563 Strip::None => {}
1564 Strip::Debuginfo => {
1565 self.link_arg("--strip-debug");
1566 }
1567 Strip::Symbols => {
1568 self.link_arg("--strip-all");
1569 }
1570 }
1571 }
1572
1573 fn no_default_libraries(&mut self) {
1574 self.cc_arg("-nostdlib");
1575 }
1576
1577 fn export_symbols(&mut self, _: &Path, _: CrateType, _: &[(String, SymbolExportKind)]) {
1578 self.sess.dcx().emit_warn(errors::L4BenderExportingSymbolsUnimplemented);
1580 }
1581
1582 fn windows_subsystem(&mut self, subsystem: WindowsSubsystemKind) {
1583 let subsystem = subsystem.as_str();
1584 self.link_arg(&::alloc::__export::must_use({
::alloc::fmt::format(format_args!("--subsystem {0}", subsystem))
})format!("--subsystem {subsystem}"));
1585 }
1586
1587 fn reset_per_library_state(&mut self) {
1588 self.hint_static(); }
1590
1591 fn linker_plugin_lto(&mut self) {}
1592
1593 fn control_flow_guard(&mut self) {}
1594
1595 fn ehcont_guard(&mut self) {}
1596
1597 fn no_crt_objects(&mut self) {}
1598}
1599
1600impl<'a> L4Bender<'a> {
1601 fn new(cmd: Command, sess: &'a Session) -> L4Bender<'a> {
1602 L4Bender { cmd, sess, hinted_static: false }
1603 }
1604
1605 fn hint_static(&mut self) {
1606 if !self.hinted_static {
1607 self.link_or_cc_arg("-static");
1608 self.hinted_static = true;
1609 }
1610 }
1611}
1612
1613struct AixLinker<'a> {
1615 cmd: Command,
1616 sess: &'a Session,
1617 hinted_static: Option<bool>,
1618}
1619
1620impl<'a> AixLinker<'a> {
1621 fn new(cmd: Command, sess: &'a Session) -> AixLinker<'a> {
1622 AixLinker { cmd, sess, hinted_static: None }
1623 }
1624
1625 fn hint_static(&mut self) {
1626 if self.hinted_static != Some(true) {
1627 self.link_arg("-bstatic");
1628 self.hinted_static = Some(true);
1629 }
1630 }
1631
1632 fn hint_dynamic(&mut self) {
1633 if self.hinted_static != Some(false) {
1634 self.link_arg("-bdynamic");
1635 self.hinted_static = Some(false);
1636 }
1637 }
1638
1639 fn build_dylib(&mut self, _out_filename: &Path) {
1640 self.link_args(&["-bM:SRE", "-bnoentry"]);
1641 self.link_arg("-bexpfull");
1644 }
1645}
1646
1647impl<'a> Linker for AixLinker<'a> {
1648 fn cmd(&mut self) -> &mut Command {
1649 &mut self.cmd
1650 }
1651
1652 fn set_output_kind(
1653 &mut self,
1654 output_kind: LinkOutputKind,
1655 _crate_type: CrateType,
1656 out_filename: &Path,
1657 ) {
1658 match output_kind {
1659 LinkOutputKind::DynamicDylib => {
1660 self.hint_dynamic();
1661 self.build_dylib(out_filename);
1662 }
1663 LinkOutputKind::StaticDylib => {
1664 self.hint_static();
1665 self.build_dylib(out_filename);
1666 }
1667 _ => {}
1668 }
1669 }
1670
1671 fn link_dylib_by_name(&mut self, name: &str, verbatim: bool, _as_needed: bool) {
1672 self.hint_dynamic();
1673 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}") });
1674 }
1675
1676 fn link_dylib_by_path(&mut self, path: &Path, _as_needed: bool) {
1677 self.hint_dynamic();
1678 self.link_or_cc_arg(path);
1679 }
1680
1681 fn link_staticlib_by_name(&mut self, name: &str, verbatim: bool, whole_archive: bool) {
1682 self.hint_static();
1683 if !whole_archive {
1684 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}") });
1685 } else {
1686 let mut arg = OsString::from("-bkeepfile:");
1687 arg.push(find_native_static_library(name, verbatim, self.sess));
1688 self.link_or_cc_arg(arg);
1689 }
1690 }
1691
1692 fn link_staticlib_by_path(&mut self, path: &Path, whole_archive: bool) {
1693 self.hint_static();
1694 if !whole_archive {
1695 self.link_or_cc_arg(path);
1696 } else {
1697 let mut arg = OsString::from("-bkeepfile:");
1698 arg.push(path);
1699 self.link_arg(arg);
1700 }
1701 }
1702
1703 fn full_relro(&mut self) {}
1704
1705 fn partial_relro(&mut self) {}
1706
1707 fn no_relro(&mut self) {}
1708
1709 fn gc_sections(&mut self, _keep_metadata: bool) {
1710 self.link_arg("-bgc");
1711 }
1712
1713 fn optimize(&mut self) {}
1714
1715 fn pgo_gen(&mut self) {
1716 self.link_arg("-bdbg:namedsects:ss");
1717 self.link_arg("-u");
1718 self.link_arg("__llvm_profile_runtime");
1719 }
1720
1721 fn control_flow_guard(&mut self) {}
1722
1723 fn ehcont_guard(&mut self) {}
1724
1725 fn debuginfo(&mut self, _: Strip, _: &[PathBuf]) {}
1726
1727 fn no_crt_objects(&mut self) {}
1728
1729 fn no_default_libraries(&mut self) {}
1730
1731 fn export_symbols(
1732 &mut self,
1733 tmpdir: &Path,
1734 _crate_type: CrateType,
1735 symbols: &[(String, SymbolExportKind)],
1736 ) {
1737 let path = tmpdir.join("list.exp");
1738 let res: io::Result<()> = try {
1739 let mut f = File::create_buffered(&path)?;
1740 for (symbol, _) in symbols {
1742 {
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:1742",
"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(1742u32),
::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}");
1743 f.write_fmt(format_args!(" {0}\n", symbol))writeln!(f, " {symbol}")?;
1744 }
1745 };
1746 if let Err(e) = res {
1747 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}"));
1748 }
1749 self.link_arg(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("-bE:{0}", path.to_str().unwrap()))
})format!("-bE:{}", path.to_str().unwrap()));
1750 }
1751
1752 fn windows_subsystem(&mut self, _subsystem: WindowsSubsystemKind) {}
1753
1754 fn reset_per_library_state(&mut self) {
1755 self.hint_dynamic();
1756 }
1757
1758 fn linker_plugin_lto(&mut self) {}
1759
1760 fn add_eh_frame_header(&mut self) {}
1761
1762 fn add_no_exec(&mut self) {}
1763
1764 fn add_as_needed(&mut self) {}
1765}
1766
1767fn for_each_exported_symbols_include_dep<'tcx>(
1768 tcx: TyCtxt<'tcx>,
1769 crate_type: CrateType,
1770 mut callback: impl FnMut(ExportedSymbol<'tcx>, SymbolExportInfo, CrateNum),
1771) {
1772 let formats = tcx.dependency_formats(());
1773 let deps = &formats[&crate_type];
1774
1775 for (cnum, dep_format) in deps.iter_enumerated() {
1776 if *dep_format == Linkage::Static {
1778 for &(symbol, info) in tcx.exported_non_generic_symbols(cnum).iter() {
1779 callback(symbol, info, cnum);
1780 }
1781 for &(symbol, info) in tcx.exported_generic_symbols(cnum).iter() {
1782 callback(symbol, info, cnum);
1783 }
1784 }
1785 }
1786}
1787
1788pub(crate) fn exported_symbols(
1789 tcx: TyCtxt<'_>,
1790 crate_type: CrateType,
1791) -> Vec<(String, SymbolExportKind)> {
1792 if let Some(ref exports) = tcx.sess.target.override_export_symbols {
1793 return exports
1794 .iter()
1795 .map(|name| {
1796 (
1797 name.to_string(),
1798 SymbolExportKind::Text,
1802 )
1803 })
1804 .collect();
1805 }
1806
1807 let mut symbols = if let CrateType::ProcMacro = crate_type {
1808 exported_symbols_for_proc_macro_crate(tcx)
1809 } else {
1810 exported_symbols_for_non_proc_macro(tcx, crate_type)
1811 };
1812
1813 if crate_type == CrateType::Dylib || crate_type == CrateType::ProcMacro {
1814 let metadata_symbol_name = exported_symbols::metadata_symbol_name(tcx);
1815 symbols.push((metadata_symbol_name, SymbolExportKind::Data));
1816 }
1817
1818 symbols
1819}
1820
1821fn exported_symbols_for_non_proc_macro(
1822 tcx: TyCtxt<'_>,
1823 crate_type: CrateType,
1824) -> Vec<(String, SymbolExportKind)> {
1825 let mut symbols = Vec::new();
1826 let export_threshold = symbol_export::crates_export_threshold(&[crate_type]);
1827 for_each_exported_symbols_include_dep(tcx, crate_type, |symbol, info, cnum| {
1828 if info.level.is_below_threshold(export_threshold) && !tcx.is_compiler_builtins(cnum) {
1832 symbols.push((
1833 symbol_export::exporting_symbol_name_for_instance_in_crate(tcx, symbol, cnum),
1834 info.kind,
1835 ));
1836 symbol_export::extend_exported_symbols(&mut symbols, tcx, symbol, cnum);
1837 }
1838 });
1839
1840 if export_threshold == SymbolExportLevel::Rust
1842 && needs_allocator_shim_for_linking(tcx.dependency_formats(()), crate_type)
1843 && let Some(kind) = tcx.allocator_kind(())
1844 {
1845 symbols.extend(allocator_shim_symbols(tcx, kind));
1846 }
1847
1848 symbols
1849}
1850
1851fn exported_symbols_for_proc_macro_crate(tcx: TyCtxt<'_>) -> Vec<(String, SymbolExportKind)> {
1852 if !tcx.sess.opts.output_types.should_codegen() {
1854 return Vec::new();
1855 }
1856
1857 let stable_crate_id = tcx.stable_crate_id(LOCAL_CRATE);
1858 let proc_macro_decls_name = tcx.sess.generate_proc_macro_decls_symbol(stable_crate_id);
1859
1860 <[_]>::into_vec(::alloc::boxed::box_new([(proc_macro_decls_name,
SymbolExportKind::Data)]))vec![(proc_macro_decls_name, SymbolExportKind::Data)]
1861}
1862
1863pub(crate) fn linked_symbols(
1864 tcx: TyCtxt<'_>,
1865 crate_type: CrateType,
1866) -> Vec<(String, SymbolExportKind)> {
1867 match crate_type {
1868 CrateType::Executable
1869 | CrateType::ProcMacro
1870 | CrateType::Cdylib
1871 | CrateType::Dylib
1872 | CrateType::Sdylib => (),
1873 CrateType::StaticLib | CrateType::Rlib => {
1874 return Vec::new();
1876 }
1877 }
1878
1879 match tcx.sess.lto() {
1880 Lto::No | Lto::ThinLocal => {}
1881 Lto::Thin | Lto::Fat => {
1882 return Vec::new();
1891 }
1892 }
1893
1894 let mut symbols = Vec::new();
1895
1896 let export_threshold = symbol_export::crates_export_threshold(&[crate_type]);
1897 for_each_exported_symbols_include_dep(tcx, crate_type, |symbol, info, cnum| {
1898 if info.level.is_below_threshold(export_threshold) && !tcx.is_compiler_builtins(cnum)
1899 || info.used
1900 || info.rustc_std_internal_symbol
1901 {
1902 symbols.push((
1903 symbol_export::linking_symbol_name_for_instance_in_crate(
1904 tcx, symbol, info.kind, cnum,
1905 ),
1906 info.kind,
1907 ));
1908 }
1909 });
1910
1911 symbols
1912}
1913
1914struct PtxLinker<'a> {
1917 cmd: Command,
1918 sess: &'a Session,
1919}
1920
1921impl<'a> Linker for PtxLinker<'a> {
1922 fn cmd(&mut self) -> &mut Command {
1923 &mut self.cmd
1924 }
1925
1926 fn set_output_kind(
1927 &mut self,
1928 _output_kind: LinkOutputKind,
1929 _crate_type: CrateType,
1930 _out_filename: &Path,
1931 ) {
1932 }
1933
1934 fn link_staticlib_by_name(&mut self, _name: &str, _verbatim: bool, _whole_archive: bool) {
1935 { ::core::panicking::panic_fmt(format_args!("staticlibs not supported")); }panic!("staticlibs not supported")
1936 }
1937
1938 fn link_staticlib_by_path(&mut self, path: &Path, _whole_archive: bool) {
1939 self.link_arg("--rlib").link_arg(path);
1940 }
1941
1942 fn debuginfo(&mut self, _strip: Strip, _: &[PathBuf]) {
1943 self.link_arg("--debug");
1944 }
1945
1946 fn add_object(&mut self, path: &Path) {
1947 self.link_arg("--bitcode").link_arg(path);
1948 }
1949
1950 fn optimize(&mut self) {
1951 match self.sess.lto() {
1952 Lto::Thin | Lto::Fat | Lto::ThinLocal => {
1953 self.link_arg("-Olto");
1954 }
1955
1956 Lto::No => {}
1957 }
1958 }
1959
1960 fn full_relro(&mut self) {}
1961
1962 fn partial_relro(&mut self) {}
1963
1964 fn no_relro(&mut self) {}
1965
1966 fn gc_sections(&mut self, _keep_metadata: bool) {}
1967
1968 fn pgo_gen(&mut self) {}
1969
1970 fn no_crt_objects(&mut self) {}
1971
1972 fn no_default_libraries(&mut self) {}
1973
1974 fn control_flow_guard(&mut self) {}
1975
1976 fn ehcont_guard(&mut self) {}
1977
1978 fn export_symbols(
1979 &mut self,
1980 _tmpdir: &Path,
1981 _crate_type: CrateType,
1982 _symbols: &[(String, SymbolExportKind)],
1983 ) {
1984 }
1985
1986 fn windows_subsystem(&mut self, _subsystem: WindowsSubsystemKind) {}
1987
1988 fn linker_plugin_lto(&mut self) {}
1989}
1990
1991struct LlbcLinker<'a> {
1993 cmd: Command,
1994 sess: &'a Session,
1995}
1996
1997impl<'a> Linker for LlbcLinker<'a> {
1998 fn cmd(&mut self) -> &mut Command {
1999 &mut self.cmd
2000 }
2001
2002 fn set_output_kind(
2003 &mut self,
2004 _output_kind: LinkOutputKind,
2005 _crate_type: CrateType,
2006 _out_filename: &Path,
2007 ) {
2008 }
2009
2010 fn link_staticlib_by_name(&mut self, _name: &str, _verbatim: bool, _whole_archive: bool) {
2011 { ::core::panicking::panic_fmt(format_args!("staticlibs not supported")); }panic!("staticlibs not supported")
2012 }
2013
2014 fn link_staticlib_by_path(&mut self, path: &Path, _whole_archive: bool) {
2015 self.link_or_cc_arg(path);
2016 }
2017
2018 fn debuginfo(&mut self, _strip: Strip, _: &[PathBuf]) {
2019 self.link_arg("--debug");
2020 }
2021
2022 fn optimize(&mut self) {
2023 self.link_arg(match self.sess.opts.optimize {
2024 OptLevel::No => "-O0",
2025 OptLevel::Less => "-O1",
2026 OptLevel::More => "-O2",
2027 OptLevel::Aggressive => "-O3",
2028 OptLevel::Size => "-Os",
2029 OptLevel::SizeMin => "-Oz",
2030 });
2031 }
2032
2033 fn full_relro(&mut self) {}
2034
2035 fn partial_relro(&mut self) {}
2036
2037 fn no_relro(&mut self) {}
2038
2039 fn gc_sections(&mut self, _keep_metadata: bool) {}
2040
2041 fn pgo_gen(&mut self) {}
2042
2043 fn no_crt_objects(&mut self) {}
2044
2045 fn no_default_libraries(&mut self) {}
2046
2047 fn control_flow_guard(&mut self) {}
2048
2049 fn ehcont_guard(&mut self) {}
2050
2051 fn export_symbols(
2052 &mut self,
2053 _tmpdir: &Path,
2054 _crate_type: CrateType,
2055 symbols: &[(String, SymbolExportKind)],
2056 ) {
2057 match _crate_type {
2058 CrateType::Cdylib => {
2059 for (sym, _) in symbols {
2060 self.link_args(&["--export-symbol", sym]);
2061 }
2062 }
2063 _ => (),
2064 }
2065 }
2066
2067 fn windows_subsystem(&mut self, _subsystem: WindowsSubsystemKind) {}
2068
2069 fn linker_plugin_lto(&mut self) {}
2070}
2071
2072struct BpfLinker<'a> {
2073 cmd: Command,
2074 sess: &'a Session,
2075}
2076
2077impl<'a> Linker for BpfLinker<'a> {
2078 fn cmd(&mut self) -> &mut Command {
2079 &mut self.cmd
2080 }
2081
2082 fn set_output_kind(
2083 &mut self,
2084 _output_kind: LinkOutputKind,
2085 _crate_type: CrateType,
2086 _out_filename: &Path,
2087 ) {
2088 }
2089
2090 fn link_staticlib_by_name(&mut self, _name: &str, _verbatim: bool, _whole_archive: bool) {
2091 self.sess.dcx().emit_fatal(errors::BpfStaticlibNotSupported)
2092 }
2093
2094 fn link_staticlib_by_path(&mut self, path: &Path, _whole_archive: bool) {
2095 self.link_or_cc_arg(path);
2096 }
2097
2098 fn debuginfo(&mut self, _strip: Strip, _: &[PathBuf]) {
2099 self.link_arg("--debug");
2100 }
2101
2102 fn optimize(&mut self) {
2103 self.link_arg(match self.sess.opts.optimize {
2104 OptLevel::No => "-O0",
2105 OptLevel::Less => "-O1",
2106 OptLevel::More => "-O2",
2107 OptLevel::Aggressive => "-O3",
2108 OptLevel::Size => "-Os",
2109 OptLevel::SizeMin => "-Oz",
2110 });
2111 }
2112
2113 fn full_relro(&mut self) {}
2114
2115 fn partial_relro(&mut self) {}
2116
2117 fn no_relro(&mut self) {}
2118
2119 fn gc_sections(&mut self, _keep_metadata: bool) {}
2120
2121 fn pgo_gen(&mut self) {}
2122
2123 fn no_crt_objects(&mut self) {}
2124
2125 fn no_default_libraries(&mut self) {}
2126
2127 fn control_flow_guard(&mut self) {}
2128
2129 fn ehcont_guard(&mut self) {}
2130
2131 fn export_symbols(
2132 &mut self,
2133 tmpdir: &Path,
2134 _crate_type: CrateType,
2135 symbols: &[(String, SymbolExportKind)],
2136 ) {
2137 let path = tmpdir.join("symbols");
2138 let res: io::Result<()> = try {
2139 let mut f = File::create_buffered(&path)?;
2140 for (sym, _) in symbols {
2141 f.write_fmt(format_args!("{0}\n", sym))writeln!(f, "{sym}")?;
2142 }
2143 };
2144 if let Err(error) = res {
2145 self.sess.dcx().emit_fatal(errors::SymbolFileWriteFailure { error });
2146 } else {
2147 self.link_arg("--export-symbols").link_arg(&path);
2148 }
2149 }
2150
2151 fn windows_subsystem(&mut self, _subsystem: WindowsSubsystemKind) {}
2152
2153 fn linker_plugin_lto(&mut self) {}
2154}