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_middle::bug;
11use rustc_middle::middle::dependency_format::Linkage;
12use rustc_middle::middle::exported_symbols::{
13 self, ExportedSymbol, SymbolExportInfo, SymbolExportKind, SymbolExportLevel,
14};
15use rustc_middle::ty::{SymbolName, TyCtxt};
16use rustc_session::Session;
17use rustc_session::config::{self, CrateType, DebugInfo, LinkerPluginLto, Lto, OptLevel, Strip};
18use rustc_target::spec::{Arch, Cc, CfgAbi, LinkOutputKind, LinkerFlavor, Lld, Os};
19use tracing::{debug, warn};
20
21use super::command::Command;
22use super::symbol_export;
23use crate::back::link::{
24 find_native_static_library, try_find_native_dynamic_library, try_find_native_static_library,
25};
26use crate::back::symbol_export::allocator_shim_symbols;
27use crate::base::needs_allocator_shim_for_linking;
28use crate::{SymbolExport, diagnostics};
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};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("arch is not supported")
as &dyn ::tracing::field::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};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("MSVC root path lib location not found")
as &dyn ::tracing::field::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};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("link.exe not found")
as &dyn ::tracing::field::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::Aix => {
141 Box::new(AixLinker::new(cmd, sess)) as Box<dyn Linker>
142 }
143 LinkerFlavor::WasmLld(Cc::No) => Box::new(WasmLd::new(cmd, sess)) as Box<dyn Linker>,
144 LinkerFlavor::Gnu(cc, _)
145 | LinkerFlavor::Darwin(cc, _)
146 | LinkerFlavor::WasmLld(cc)
147 | LinkerFlavor::Unix(cc) => Box::new(GccLinker {
148 cmd,
149 sess,
150 target_cpu,
151 hinted_static: None,
152 is_ld: cc == Cc::No,
153 is_gnu: flavor.is_gnu(),
154 uses_lld: flavor.uses_lld(),
155 codegen_backend,
156 }) as Box<dyn Linker>,
157 LinkerFlavor::Msvc(..) => Box::new(MsvcLinker { cmd, sess }) as Box<dyn Linker>,
158 LinkerFlavor::EmCc => Box::new(EmLinker { cmd, sess }) as Box<dyn Linker>,
159 LinkerFlavor::Bpf => Box::new(BpfLinker { cmd, sess }) as Box<dyn Linker>,
160 LinkerFlavor::Llbc => Box::new(LlbcLinker { cmd, sess }) as Box<dyn Linker>,
161 }
162}
163
164fn verbatim_args<L: Linker + ?Sized>(
174 l: &mut L,
175 args: impl IntoIterator<Item: AsRef<OsStr>>,
176) -> &mut L {
177 for arg in args {
178 l.cmd().arg(arg);
179 }
180 l
181}
182fn convert_link_args_to_cc_args(cmd: &mut Command, args: impl IntoIterator<Item: AsRef<OsStr>>) {
185 let mut combined_arg = OsString::from("-Wl");
186 for arg in args {
187 if arg.as_ref().as_encoded_bytes().contains(&b',') {
190 if combined_arg != OsStr::new("-Wl") {
192 cmd.arg(combined_arg);
193 combined_arg = OsString::from("-Wl");
195 }
196
197 cmd.arg("-Xlinker");
199 cmd.arg(arg);
200 } else {
201 combined_arg.push(",");
203 combined_arg.push(arg);
204 }
205 }
206 if combined_arg != OsStr::new("-Wl") {
208 cmd.arg(combined_arg);
209 }
210}
211fn link_args<L: Linker + ?Sized>(l: &mut L, args: impl IntoIterator<Item: AsRef<OsStr>>) -> &mut L {
214 if !l.is_cc() {
215 verbatim_args(l, args);
216 } else {
217 convert_link_args_to_cc_args(l.cmd(), args);
218 }
219 l
220}
221fn cc_args<L: Linker + ?Sized>(l: &mut L, args: impl IntoIterator<Item: AsRef<OsStr>>) -> &mut L {
224 if !l.is_cc() { ::core::panicking::panic("assertion failed: l.is_cc()") };assert!(l.is_cc());
225 verbatim_args(l, args)
226}
227fn link_or_cc_args<L: Linker + ?Sized>(
229 l: &mut L,
230 args: impl IntoIterator<Item: AsRef<OsStr>>,
231) -> &mut L {
232 verbatim_args(l, args)
233}
234
235macro_rules! generate_arg_methods {
236 ($($ty:ty)*) => { $(
237 impl $ty {
238 #[allow(unused)]
239 pub(crate) fn verbatim_args(&mut self, args: impl IntoIterator<Item: AsRef<OsStr>>) -> &mut Self {
240 verbatim_args(self, args)
241 }
242 #[allow(unused)]
243 pub(crate) fn verbatim_arg(&mut self, arg: impl AsRef<OsStr>) -> &mut Self {
244 verbatim_args(self, iter::once(arg))
245 }
246 #[allow(unused)]
247 pub(crate) fn link_args(&mut self, args: impl IntoIterator<Item: AsRef<OsStr>>) -> &mut Self {
248 link_args(self, args)
249 }
250 #[allow(unused)]
251 pub(crate) fn link_arg(&mut self, arg: impl AsRef<OsStr>) -> &mut Self {
252 link_args(self, iter::once(arg))
253 }
254 #[allow(unused)]
255 pub(crate) fn cc_args(&mut self, args: impl IntoIterator<Item: AsRef<OsStr>>) -> &mut Self {
256 cc_args(self, args)
257 }
258 #[allow(unused)]
259 pub(crate) fn cc_arg(&mut self, arg: impl AsRef<OsStr>) -> &mut Self {
260 cc_args(self, iter::once(arg))
261 }
262 #[allow(unused)]
263 pub(crate) fn link_or_cc_args(&mut self, args: impl IntoIterator<Item: AsRef<OsStr>>) -> &mut Self {
264 link_or_cc_args(self, args)
265 }
266 #[allow(unused)]
267 pub(crate) fn link_or_cc_arg(&mut self, arg: impl AsRef<OsStr>) -> &mut Self {
268 link_or_cc_args(self, iter::once(arg))
269 }
270 }
271 )* }
272}
273
274impl 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! {
275 GccLinker<'_>
276 MsvcLinker<'_>
277 EmLinker<'_>
278 WasmLd<'_>
279 AixLinker<'_>
280 LlbcLinker<'_>
281 BpfLinker<'_>
282 dyn Linker + '_
283}
284
285pub(crate) trait Linker {
293 fn cmd(&mut self) -> &mut Command;
294 fn is_cc(&self) -> bool {
295 false
296 }
297 fn set_output_kind(
298 &mut self,
299 output_kind: LinkOutputKind,
300 crate_type: CrateType,
301 out_filename: &Path,
302 );
303 fn link_dylib_by_name(&mut self, _name: &str, _verbatim: bool, _as_needed: bool) {
304 ::rustc_middle::util::bug::bug_fmt(format_args!("dylib linked with unsupported linker"))bug!("dylib linked with unsupported linker")
305 }
306 fn link_dylib_by_path(&mut self, _path: &Path, _as_needed: bool) {
307 ::rustc_middle::util::bug::bug_fmt(format_args!("dylib linked with unsupported linker"))bug!("dylib linked with unsupported linker")
308 }
309 fn link_framework_by_name(&mut self, _name: &str, _verbatim: bool, _as_needed: bool) {
310 ::rustc_middle::util::bug::bug_fmt(format_args!("framework linked with unsupported linker"))bug!("framework linked with unsupported linker")
311 }
312 fn link_staticlib_by_name(&mut self, name: &str, verbatim: bool, whole_archive: bool);
313 fn link_staticlib_by_path(&mut self, path: &Path, whole_archive: bool);
314 fn include_path(&mut self, path: &Path) {
315 link_or_cc_args(link_or_cc_args(self, &["-L"]), &[path]);
316 }
317 fn framework_path(&mut self, _path: &Path) {
318 ::rustc_middle::util::bug::bug_fmt(format_args!("framework path set with unsupported linker"))bug!("framework path set with unsupported linker")
319 }
320 fn output_filename(&mut self, path: &Path) {
321 link_or_cc_args(link_or_cc_args(self, &["-o"]), &[path]);
322 }
323 fn add_object(&mut self, path: &Path) {
324 link_or_cc_args(self, &[path]);
325 }
326 fn gc_sections(&mut self, keep_metadata: bool);
327 fn full_relro(&mut self);
328 fn partial_relro(&mut self);
329 fn no_relro(&mut self);
330 fn optimize(&mut self);
331 fn pgo_gen(&mut self);
332 fn control_flow_guard(&mut self);
333 fn ehcont_guard(&mut self);
334 fn debuginfo(&mut self, strip: Strip, natvis_debugger_visualizers: &[PathBuf]);
335 fn no_crt_objects(&mut self);
336 fn no_default_libraries(&mut self);
337 fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType, symbols: &[SymbolExport]);
338 fn windows_subsystem(&mut self, subsystem: WindowsSubsystemKind);
339 fn linker_plugin_lto(&mut self);
340 fn add_eh_frame_header(&mut self) {}
341 fn add_no_exec(&mut self) {}
342 fn add_as_needed(&mut self) {}
343 fn reset_per_library_state(&mut self) {}
344 fn enable_profiling(&mut self) {}
345}
346
347impl dyn Linker + '_ {
348 pub(crate) fn take_cmd(&mut self) -> Command {
349 mem::replace(self.cmd(), Command::new(""))
350 }
351}
352
353struct GccLinker<'a> {
354 cmd: Command,
355 sess: &'a Session,
356 target_cpu: &'a str,
357 hinted_static: Option<bool>, is_ld: bool,
360 is_gnu: bool,
361 uses_lld: bool,
362 codegen_backend: &'static str,
363}
364
365impl<'a> GccLinker<'a> {
366 fn takes_hints(&self) -> bool {
367 !self.sess.target.is_like_darwin && !self.sess.target.is_like_wasm
376 }
377
378 fn hint_static(&mut self) {
383 if !self.takes_hints() {
384 return;
385 }
386 if self.hinted_static != Some(true) {
387 self.link_arg("-Bstatic");
388 self.hinted_static = Some(true);
389 }
390 }
391
392 fn hint_dynamic(&mut self) {
393 if !self.takes_hints() {
394 return;
395 }
396 if self.hinted_static != Some(false) {
397 self.link_arg("-Bdynamic");
398 self.hinted_static = Some(false);
399 }
400 }
401
402 fn push_linker_plugin_lto_args(&mut self, plugin_path: Option<&OsStr>) {
403 if let Some(plugin_path) = plugin_path {
404 let mut arg = OsString::from("-plugin=");
405 arg.push(plugin_path);
406 self.link_arg(&arg);
407 }
408
409 let opt_level = match self.sess.opts.optimize {
410 config::OptLevel::No => "O0",
411 config::OptLevel::Less => "O1",
412 config::OptLevel::More | config::OptLevel::Size | config::OptLevel::SizeMin => "O2",
413 config::OptLevel::Aggressive => "O3",
414 };
415
416 if let Some(path) = &self.sess.opts.unstable_opts.profile_sample_use {
417 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()));
418 };
419 let prefix = if self.codegen_backend == "gcc" {
420 "-"
422 } else {
423 ""
424 };
425 self.link_args(&[
426 &::alloc::__export::must_use({
::alloc::fmt::format(format_args!("-plugin-opt={0}{1}", prefix,
opt_level))
})format!("-plugin-opt={prefix}{opt_level}"),
427 &::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),
428 ]);
429 }
430
431 fn build_dylib(&mut self, crate_type: CrateType, out_filename: &Path) {
432 if self.sess.target.is_like_darwin {
434 if self.is_cc() {
435 self.cc_arg("-dynamiclib");
437 } else {
438 self.link_arg("-dylib");
439 }
441
442 if self.sess.opts.cg.rpath || self.sess.opts.unstable_opts.osx_rpath_install_name {
447 let mut rpath = OsString::from("@rpath/");
448 rpath.push(out_filename.file_name().unwrap());
449 self.link_arg("-install_name").link_arg(rpath);
450 }
451 } else {
452 self.link_or_cc_arg("-shared");
453 if let Some(name) = out_filename.file_name() {
454 if self.sess.target.is_like_windows {
455 let (prefix, suffix) = self.sess.staticlib_components(false);
459 let mut implib_name = OsString::from(prefix);
460 implib_name.push(name);
461 implib_name.push(suffix);
462 let mut out_implib = OsString::from("--out-implib=");
463 out_implib.push(out_filename.with_file_name(implib_name));
464 self.link_arg(out_implib);
465 } else if crate_type == CrateType::Dylib {
466 let mut soname = OsString::from("-soname=");
470 soname.push(name);
471 self.link_arg(soname);
472 }
473 }
474 }
475 }
476
477 fn with_as_needed(&mut self, as_needed: bool, f: impl FnOnce(&mut Self)) {
478 if !as_needed {
479 if self.sess.target.is_like_darwin {
480 self.sess.dcx().emit_warn(diagnostics::Ld64UnimplementedModifier);
484 } else if self.is_gnu && !self.sess.target.is_like_windows {
485 self.link_arg("--no-as-needed");
486 } else {
487 self.sess.dcx().emit_warn(diagnostics::LinkerUnsupportedModifier);
488 }
489 }
490
491 f(self);
492
493 if !as_needed {
494 if self.sess.target.is_like_darwin {
495 } else if self.is_gnu && !self.sess.target.is_like_windows {
497 self.link_arg("--as-needed");
498 }
499 }
500 }
501}
502
503impl<'a> Linker for GccLinker<'a> {
504 fn cmd(&mut self) -> &mut Command {
505 &mut self.cmd
506 }
507
508 fn is_cc(&self) -> bool {
509 !self.is_ld
510 }
511
512 fn set_output_kind(
513 &mut self,
514 output_kind: LinkOutputKind,
515 crate_type: CrateType,
516 out_filename: &Path,
517 ) {
518 match output_kind {
519 LinkOutputKind::DynamicNoPicExe => {
520 if !self.is_ld && self.is_gnu && !self.sess.target.is_like_windows {
522 self.cc_arg("-no-pie");
523 }
524 }
525 LinkOutputKind::DynamicPicExe => {
526 if !self.sess.target.is_like_windows {
528 self.link_or_cc_arg("-pie");
530 }
531 }
532 LinkOutputKind::StaticNoPicExe => {
533 self.link_or_cc_arg("-static");
535 if !self.is_ld && self.is_gnu && !self.sess.target.is_like_windows {
537 self.cc_arg("-no-pie");
538 }
539 }
540 LinkOutputKind::StaticPicExe => {
541 if !self.is_ld {
542 self.cc_arg("-static-pie");
545 } else {
546 self.link_args(&["-static", "-pie", "--no-dynamic-linker", "-z", "text"]);
552 }
553 }
554 LinkOutputKind::DynamicDylib => self.build_dylib(crate_type, out_filename),
555 LinkOutputKind::StaticDylib => {
556 self.link_or_cc_arg("-static");
557 self.build_dylib(crate_type, out_filename);
558 }
559 LinkOutputKind::WasiReactorExe => {
560 self.link_args(&["--entry", "_initialize"]);
561 }
562 }
563
564 if self.sess.target.os == Os::VxWorks
570 && #[allow(non_exhaustive_omitted_patterns)] match output_kind {
LinkOutputKind::StaticNoPicExe | LinkOutputKind::StaticPicExe |
LinkOutputKind::StaticDylib => true,
_ => false,
}matches!(
571 output_kind,
572 LinkOutputKind::StaticNoPicExe
573 | LinkOutputKind::StaticPicExe
574 | LinkOutputKind::StaticDylib
575 )
576 {
577 self.cc_arg("--static-crt");
578 }
579
580 if self.sess.target.arch == Arch::Avr && !self.uses_lld {
586 self.verbatim_arg(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("-mmcu={0}", self.target_cpu))
})format!("-mmcu={}", self.target_cpu));
587 }
588 }
589
590 fn link_dylib_by_name(&mut self, name: &str, verbatim: bool, as_needed: bool) {
591 if self.sess.target.os == Os::Illumos && name == "c" {
592 return;
598 }
599 self.hint_dynamic();
600 self.with_as_needed(as_needed, |this| {
601 let colon = if verbatim && this.is_gnu { ":" } else { "" };
602 this.link_or_cc_arg(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("-l{0}{1}", colon, name))
})format!("-l{colon}{name}"));
603 });
604 }
605
606 fn link_dylib_by_path(&mut self, path: &Path, as_needed: bool) {
607 self.hint_dynamic();
608 self.with_as_needed(as_needed, |this| {
609 this.link_or_cc_arg(path);
610 })
611 }
612
613 fn link_framework_by_name(&mut self, name: &str, _verbatim: bool, as_needed: bool) {
614 self.hint_dynamic();
615 if !as_needed {
616 self.sess.dcx().emit_warn(diagnostics::Ld64UnimplementedModifier);
620 }
621 self.link_or_cc_args(&["-framework", name]);
622 }
623
624 fn link_staticlib_by_name(&mut self, name: &str, verbatim: bool, whole_archive: bool) {
625 self.hint_static();
626 let colon = if verbatim && self.is_gnu { ":" } else { "" };
627 if !whole_archive {
628 self.link_or_cc_arg(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("-l{0}{1}", colon, name))
})format!("-l{colon}{name}"));
629 } else if self.sess.target.is_like_darwin {
630 self.link_arg("-force_load");
633 self.link_arg(find_native_static_library(name, verbatim, self.sess));
634 } else {
635 self.link_arg("--whole-archive")
636 .link_or_cc_arg(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("-l{0}{1}", colon, name))
})format!("-l{colon}{name}"))
637 .link_arg("--no-whole-archive");
638 }
639 }
640
641 fn link_staticlib_by_path(&mut self, path: &Path, whole_archive: bool) {
642 self.hint_static();
643 if !whole_archive {
644 self.link_or_cc_arg(path);
645 } else if self.sess.target.is_like_darwin {
646 self.link_arg("-force_load").link_arg(path);
647 } else {
648 self.link_arg("--whole-archive").link_arg(path).link_arg("--no-whole-archive");
649 }
650 }
651
652 fn framework_path(&mut self, path: &Path) {
653 self.link_or_cc_arg("-F").link_or_cc_arg(path);
654 }
655 fn full_relro(&mut self) {
656 self.link_args(&["-z", "relro", "-z", "now"]);
657 }
658 fn partial_relro(&mut self) {
659 self.link_args(&["-z", "relro"]);
660 }
661 fn no_relro(&mut self) {
662 self.link_args(&["-z", "norelro"]);
663 }
664
665 fn gc_sections(&mut self, keep_metadata: bool) {
666 if self.sess.target.is_like_darwin {
681 self.link_arg("-dead_strip");
682
683 } else if (self.is_gnu || self.sess.target.is_like_wasm) && !keep_metadata {
689 self.link_arg("--gc-sections");
690 }
691 }
692
693 fn optimize(&mut self) {
694 if !self.is_gnu && !self.sess.target.is_like_wasm {
695 return;
696 }
697
698 if self.sess.opts.optimize == config::OptLevel::More
701 || self.sess.opts.optimize == config::OptLevel::Aggressive
702 {
703 self.link_arg("-O1");
704 }
705 }
706
707 fn pgo_gen(&mut self) {
708 if !self.is_gnu {
709 return;
710 }
711
712 self.link_or_cc_args(&["-u", "__llvm_profile_runtime"]);
724 }
725
726 fn enable_profiling(&mut self) {
727 if !self.is_ld {
730 self.cc_arg("-pg");
731 if self.sess.target.is_like_windows {
734 self.cc_arg("-lgmon");
735 self.cc_arg("-lkernel32");
736 self.cc_arg("-lmsvcrt");
737 }
738 }
739 }
740
741 fn control_flow_guard(&mut self) {}
742
743 fn ehcont_guard(&mut self) {}
744
745 fn debuginfo(&mut self, strip: Strip, _: &[PathBuf]) {
746 if self.sess.target.is_like_darwin {
748 return;
749 }
750
751 match strip {
752 Strip::None => {}
753 Strip::Debuginfo => {
754 if !self.sess.target.is_like_solaris {
759 self.link_arg("--strip-debug");
760 }
761 }
762 Strip::Symbols => {
763 self.link_arg("--strip-all");
764 }
765 }
766 match self.sess.opts.unstable_opts.debuginfo_compression {
767 config::DebugInfoCompression::None => {}
768 config::DebugInfoCompression::Zlib => {
769 self.link_arg("--compress-debug-sections=zlib");
770 }
771 config::DebugInfoCompression::Zstd => {
772 self.link_arg("--compress-debug-sections=zstd");
773 }
774 }
775 }
776
777 fn no_crt_objects(&mut self) {
778 if !self.is_ld {
779 self.cc_arg("-nostartfiles");
780 }
781 }
782
783 fn no_default_libraries(&mut self) {
784 if !self.is_ld {
785 self.cc_arg("-nodefaultlibs");
786 }
787 }
788
789 fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType, symbols: &[SymbolExport]) {
790 if crate_type == CrateType::Executable {
792 let should_export_executable_symbols =
793 self.sess.opts.unstable_opts.export_executable_symbols;
794 if self.sess.target.override_export_symbols.is_none()
795 && !should_export_executable_symbols
796 {
797 return;
798 }
799 }
800
801 if !self.sess.target.limit_rdylib_exports {
806 return;
807 }
808
809 let path = tmpdir.join(if self.sess.target.is_like_windows { "list.def" } else { "list" });
810 {
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:810",
"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(810u32),
::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};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("EXPORTED SYMBOLS:")
as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!("EXPORTED SYMBOLS:");
811
812 if self.sess.target.is_like_darwin {
813 let res = try {
815 let mut f = File::create_buffered(&path)?;
816 for sym in symbols {
817 {
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:817",
"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(817u32),
::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};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!(" _{0}",
sym.name) as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!(" _{}", sym.name);
818 f.write_fmt(format_args!("_{0}\n", sym.name))writeln!(f, "_{}", sym.name)?;
819 }
820 };
821 if let Err(error) = res {
822 self.sess.dcx().emit_fatal(diagnostics::LibDefWriteFailure { error });
823 }
824 self.link_arg("-exported_symbols_list").link_arg(path);
825 } else if self.sess.target.is_like_windows {
826 let res = try {
827 let mut f = File::create_buffered(&path)?;
828
829 f.write_fmt(format_args!("EXPORTS\n"))writeln!(f, "EXPORTS")?;
832 for symbol in symbols {
833 let kind_marker =
834 if symbol.kind == SymbolExportKind::Data { " DATA" } else { "" };
835 {
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:835",
"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(835u32),
::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};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!(" _{0}",
symbol.name) as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!(" _{}", symbol.name);
836 f.write_fmt(format_args!(" \"{0}\"{1}\n", symbol.name, kind_marker))writeln!(f, " \"{}\"{kind_marker}", symbol.name)?;
839 }
840 };
841 if let Err(error) = res {
842 self.sess.dcx().emit_fatal(diagnostics::LibDefWriteFailure { error });
843 }
844 self.link_arg(path);
845 } else if self.sess.target.is_like_wasm {
846 self.link_arg("--no-export-dynamic");
847 for sym in symbols {
848 self.link_arg("--export").link_arg(&sym.name);
849 }
850 } else if crate_type == CrateType::Executable && !self.sess.target.is_like_solaris {
851 let res = try {
852 let mut f = File::create_buffered(&path)?;
853 f.write_fmt(format_args!("{{\n"))writeln!(f, "{{")?;
854 for sym in symbols {
855 {
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:855",
"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(855u32),
::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};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("{0}",
sym.name) as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!("{}", sym.name);
856 f.write_fmt(format_args!(" {0};\n", sym.name))writeln!(f, " {};", sym.name)?;
857 }
858 f.write_fmt(format_args!("}};\n"))writeln!(f, "}};")?;
859 };
860 if let Err(error) = res {
861 self.sess.dcx().emit_fatal(diagnostics::VersionScriptWriteFailure { error });
862 }
863 self.link_arg("--dynamic-list").link_arg(path);
864 } else {
865 let res = try {
867 let mut f = File::create_buffered(&path)?;
868 f.write_fmt(format_args!("{{\n"))writeln!(f, "{{")?;
869 if !symbols.is_empty() {
870 f.write_fmt(format_args!(" global:\n"))writeln!(f, " global:")?;
871 for sym in symbols {
872 {
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:872",
"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(872u32),
::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};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!(" {0};",
sym.name) as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!(" {};", sym.name);
873 f.write_fmt(format_args!(" {0};\n", sym.name))writeln!(f, " {};", sym.name)?;
874 }
875 }
876 f.write_fmt(format_args!("\n local:\n *;\n}};\n"))writeln!(f, "\n local:\n *;\n}};")?;
877 };
878 if let Err(error) = res {
879 self.sess.dcx().emit_fatal(diagnostics::VersionScriptWriteFailure { error });
880 }
881 if self.sess.target.is_like_solaris {
882 self.link_arg("-M").link_arg(path);
883 } else {
884 let mut arg = OsString::from("--version-script=");
885 arg.push(path);
886 self.link_arg(arg).link_arg("--no-undefined-version");
887 }
888 }
889 }
890
891 fn windows_subsystem(&mut self, subsystem: WindowsSubsystemKind) {
892 self.link_args(&["--subsystem", subsystem.as_str()]);
893 }
894
895 fn reset_per_library_state(&mut self) {
896 self.hint_dynamic(); }
898
899 fn linker_plugin_lto(&mut self) {
900 match self.sess.opts.cg.linker_plugin_lto {
901 LinkerPluginLto::Disabled => {
902 }
904 LinkerPluginLto::LinkerPluginAuto => {
905 self.push_linker_plugin_lto_args(None);
906 }
907 LinkerPluginLto::LinkerPlugin(ref path) => {
908 self.push_linker_plugin_lto_args(Some(path.as_os_str()));
909 }
910 }
911 }
912
913 fn add_eh_frame_header(&mut self) {
917 self.link_arg("--eh-frame-hdr");
918 }
919
920 fn add_no_exec(&mut self) {
921 if self.sess.target.is_like_windows {
922 self.link_arg("--nxcompat");
923 } else if self.is_gnu {
924 self.link_args(&["-z", "noexecstack"]);
925 }
926 }
927
928 fn add_as_needed(&mut self) {
929 if self.is_gnu && !self.sess.target.is_like_windows {
930 self.link_arg("--as-needed");
931 } else if self.sess.target.is_like_solaris {
932 self.link_args(&["-z", "ignore"]);
934 }
935 }
936}
937
938struct MsvcLinker<'a> {
939 cmd: Command,
940 sess: &'a Session,
941}
942
943impl<'a> Linker for MsvcLinker<'a> {
944 fn cmd(&mut self) -> &mut Command {
945 &mut self.cmd
946 }
947
948 fn set_output_kind(
949 &mut self,
950 output_kind: LinkOutputKind,
951 _crate_type: CrateType,
952 out_filename: &Path,
953 ) {
954 match output_kind {
955 LinkOutputKind::DynamicNoPicExe
956 | LinkOutputKind::DynamicPicExe
957 | LinkOutputKind::StaticNoPicExe
958 | LinkOutputKind::StaticPicExe => {}
959 LinkOutputKind::DynamicDylib | LinkOutputKind::StaticDylib => {
960 self.link_arg("/DLL");
961 let mut arg: OsString = "/IMPLIB:".into();
962 arg.push(out_filename.with_extension("dll.lib"));
963 self.link_arg(arg);
964 }
965 LinkOutputKind::WasiReactorExe => {
966 {
::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");
967 }
968 }
969 }
970
971 fn link_dylib_by_name(&mut self, name: &str, verbatim: bool, _as_needed: bool) {
972 if let Some(path) = try_find_native_dynamic_library(self.sess, name, verbatim) {
975 self.link_arg(path);
976 } else {
977 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" }));
978 }
979 }
980
981 fn link_dylib_by_path(&mut self, path: &Path, _as_needed: bool) {
982 let implib_path = path.with_extension("dll.lib");
985 if implib_path.exists() {
986 self.link_or_cc_arg(implib_path);
987 }
988 }
989
990 fn link_staticlib_by_name(&mut self, name: &str, verbatim: bool, whole_archive: bool) {
991 if let Some(path) = try_find_native_static_library(self.sess, name, verbatim) {
994 self.link_staticlib_by_path(&path, whole_archive);
995 } else {
996 let opts = if whole_archive { "/WHOLEARCHIVE:" } else { "" };
997 let (prefix, suffix) = self.sess.staticlib_components(verbatim);
998 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}"));
999 }
1000 }
1001
1002 fn link_staticlib_by_path(&mut self, path: &Path, whole_archive: bool) {
1003 if !whole_archive {
1004 self.link_arg(path);
1005 } else {
1006 let mut arg = OsString::from("/WHOLEARCHIVE:");
1007 arg.push(path);
1008 self.link_arg(arg);
1009 }
1010 }
1011
1012 fn gc_sections(&mut self, _keep_metadata: bool) {
1013 if self.sess.opts.optimize != config::OptLevel::No {
1017 self.link_arg("/OPT:REF,ICF");
1018 } else {
1019 self.link_arg("/OPT:REF,NOICF");
1022 }
1023 }
1024
1025 fn full_relro(&mut self) {
1026 }
1028
1029 fn partial_relro(&mut self) {
1030 }
1032
1033 fn no_relro(&mut self) {
1034 }
1036
1037 fn no_crt_objects(&mut self) {
1038 }
1040
1041 fn no_default_libraries(&mut self) {
1042 self.link_arg("/NODEFAULTLIB");
1043 }
1044
1045 fn include_path(&mut self, path: &Path) {
1046 let mut arg = OsString::from("/LIBPATH:");
1047 arg.push(path);
1048 self.link_arg(&arg);
1049 }
1050
1051 fn output_filename(&mut self, path: &Path) {
1052 let mut arg = OsString::from("/OUT:");
1053 arg.push(path);
1054 self.link_arg(&arg);
1055 }
1056
1057 fn optimize(&mut self) {
1058 }
1060
1061 fn pgo_gen(&mut self) {
1062 }
1064
1065 fn control_flow_guard(&mut self) {
1066 self.link_arg("/guard:cf");
1067 }
1068
1069 fn ehcont_guard(&mut self) {
1070 if self.sess.target.pointer_width == 64 {
1071 self.link_arg("/guard:ehcont");
1072 }
1073 }
1074
1075 fn debuginfo(&mut self, _strip: Strip, natvis_debugger_visualizers: &[PathBuf]) {
1076 self.link_arg("/DEBUG");
1079
1080 self.link_arg("/PDBALTPATH:%_PDB%");
1088
1089 let natvis_dir_path = self.sess.opts.sysroot.path().join("lib\\rustlib\\etc");
1091 if let Ok(natvis_dir) = fs::read_dir(&natvis_dir_path) {
1092 for entry in natvis_dir {
1093 match entry {
1094 Ok(entry) => {
1095 let path = entry.path();
1096 if path.extension() == Some("natvis".as_ref()) {
1097 let mut arg = OsString::from("/NATVIS:");
1098 arg.push(path);
1099 self.link_arg(arg);
1100 }
1101 }
1102 Err(error) => {
1103 self.sess.dcx().emit_warn(diagnostics::NoNatvisDirectory { error });
1104 }
1105 }
1106 }
1107 }
1108
1109 for path in natvis_debugger_visualizers {
1111 let mut arg = OsString::from("/NATVIS:");
1112 arg.push(path);
1113 self.link_arg(arg);
1114 }
1115 }
1116
1117 fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType, _symbols: &[SymbolExport]) {
1118 if crate_type == CrateType::Executable {
1122 let should_export_executable_symbols =
1123 self.sess.opts.unstable_opts.export_executable_symbols;
1124 if !should_export_executable_symbols {
1125 return;
1126 }
1127 }
1128
1129 let path = tmpdir.join("lib.def");
1130 let res = try {
1131 let mut f = File::create_buffered(&path)?;
1132 f.write_fmt(format_args!("LIBRARY\n"))writeln!(f, "LIBRARY")?;
1133 f.write_fmt(format_args!("EXPORTS\n"))writeln!(f, "EXPORTS")?;
1134 };
1135 if let Err(error) = res {
1136 self.sess.dcx().emit_fatal(diagnostics::LibDefWriteFailure { error });
1137 }
1138 let mut arg = OsString::from("/DEF:");
1139 arg.push(path);
1140 self.link_arg(&arg);
1141 }
1142
1143 fn windows_subsystem(&mut self, subsystem: WindowsSubsystemKind) {
1144 let subsystem = subsystem.as_str();
1145 self.link_arg(&::alloc::__export::must_use({
::alloc::fmt::format(format_args!("/SUBSYSTEM:{0}", subsystem))
})format!("/SUBSYSTEM:{subsystem}"));
1146
1147 if subsystem == "windows" {
1162 self.link_arg("/ENTRY:mainCRTStartup");
1163 }
1164 }
1165
1166 fn linker_plugin_lto(&mut self) {
1167 }
1169
1170 fn add_no_exec(&mut self) {
1171 self.link_arg("/NXCOMPAT");
1172 }
1173}
1174
1175struct EmLinker<'a> {
1176 cmd: Command,
1177 sess: &'a Session,
1178}
1179
1180impl<'a> Linker for EmLinker<'a> {
1181 fn cmd(&mut self) -> &mut Command {
1182 &mut self.cmd
1183 }
1184
1185 fn is_cc(&self) -> bool {
1186 true
1187 }
1188
1189 fn set_output_kind(
1190 &mut self,
1191 output_kind: LinkOutputKind,
1192 _crate_type: CrateType,
1193 _out_filename: &Path,
1194 ) {
1195 match output_kind {
1196 LinkOutputKind::DynamicNoPicExe | LinkOutputKind::DynamicPicExe => {
1197 self.cmd.arg("-sMAIN_MODULE=2");
1198 }
1199 LinkOutputKind::DynamicDylib | LinkOutputKind::StaticDylib => {
1200 self.cmd.arg("-sSIDE_MODULE=2");
1201 }
1202 LinkOutputKind::StaticNoPicExe | LinkOutputKind::StaticPicExe => {}
1204 LinkOutputKind::WasiReactorExe => {
1205 ::core::panicking::panic("internal error: entered unreachable code");unreachable!();
1206 }
1207 }
1208 }
1209
1210 fn link_dylib_by_name(&mut self, name: &str, _verbatim: bool, _as_needed: bool) {
1211 self.link_or_cc_args(&["-l", name]);
1213 }
1214
1215 fn link_dylib_by_path(&mut self, path: &Path, _as_needed: bool) {
1216 self.link_or_cc_arg(path);
1217 }
1218
1219 fn link_staticlib_by_name(&mut self, name: &str, _verbatim: bool, _whole_archive: bool) {
1220 self.link_or_cc_args(&["-l", name]);
1221 }
1222
1223 fn link_staticlib_by_path(&mut self, path: &Path, _whole_archive: bool) {
1224 self.link_or_cc_arg(path);
1225 }
1226
1227 fn full_relro(&mut self) {
1228 }
1230
1231 fn partial_relro(&mut self) {
1232 }
1234
1235 fn no_relro(&mut self) {
1236 }
1238
1239 fn gc_sections(&mut self, _keep_metadata: bool) {
1240 }
1242
1243 fn optimize(&mut self) {
1244 self.cc_arg(match self.sess.opts.optimize {
1246 OptLevel::No => "-O0",
1247 OptLevel::Less => "-O1",
1248 OptLevel::More => "-O2",
1249 OptLevel::Aggressive => "-O3",
1250 OptLevel::Size => "-Os",
1251 OptLevel::SizeMin => "-Oz",
1252 });
1253 }
1254
1255 fn pgo_gen(&mut self) {
1256 }
1258
1259 fn control_flow_guard(&mut self) {}
1260
1261 fn ehcont_guard(&mut self) {}
1262
1263 fn debuginfo(&mut self, _strip: Strip, _: &[PathBuf]) {
1264 self.cc_arg(match self.sess.opts.debuginfo {
1267 DebugInfo::None => "-g0",
1268 DebugInfo::Limited | DebugInfo::LineTablesOnly | DebugInfo::LineDirectivesOnly => {
1269 "--profiling-funcs"
1270 }
1271 DebugInfo::Full => "-g",
1272 });
1273 }
1274
1275 fn no_crt_objects(&mut self) {}
1276
1277 fn no_default_libraries(&mut self) {
1278 self.cc_arg("-nodefaultlibs");
1279 }
1280
1281 fn export_symbols(&mut self, _tmpdir: &Path, _crate_type: CrateType, symbols: &[SymbolExport]) {
1282 {
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:1282",
"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(1282u32),
::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};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("EXPORTED SYMBOLS:")
as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!("EXPORTED SYMBOLS:");
1283
1284 self.cc_arg("-s");
1285
1286 let entry_name = self.sess.target.entry_name.as_ref();
1292 let mut arg = OsString::from("EXPORTED_FUNCTIONS=");
1293 let encoded = serde_json::to_string(
1294 &symbols
1295 .iter()
1296 .map(|sym| {
1297 if sym.name == entry_name {
1298 "_main".to_owned()
1299 } else {
1300 "_".to_owned() + &sym.name
1301 }
1302 })
1303 .collect::<Vec<_>>(),
1304 )
1305 .unwrap();
1306 {
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:1306",
"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(1306u32),
::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};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("{0}",
encoded) as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!("{encoded}");
1307
1308 arg.push(encoded);
1309
1310 self.cc_arg(arg);
1311 }
1312
1313 fn windows_subsystem(&mut self, _subsystem: WindowsSubsystemKind) {
1314 }
1316
1317 fn linker_plugin_lto(&mut self) {
1318 }
1320}
1321
1322struct WasmLd<'a> {
1323 cmd: Command,
1324 sess: &'a Session,
1325}
1326
1327impl<'a> WasmLd<'a> {
1328 fn new(cmd: Command, sess: &'a Session) -> WasmLd<'a> {
1329 WasmLd { cmd, sess }
1330 }
1331}
1332
1333impl<'a> Linker for WasmLd<'a> {
1334 fn cmd(&mut self) -> &mut Command {
1335 &mut self.cmd
1336 }
1337
1338 fn set_output_kind(
1339 &mut self,
1340 output_kind: LinkOutputKind,
1341 _crate_type: CrateType,
1342 _out_filename: &Path,
1343 ) {
1344 match output_kind {
1345 LinkOutputKind::DynamicNoPicExe
1346 | LinkOutputKind::DynamicPicExe
1347 | LinkOutputKind::StaticNoPicExe
1348 | LinkOutputKind::StaticPicExe => {}
1349 LinkOutputKind::DynamicDylib | LinkOutputKind::StaticDylib => {
1350 self.link_arg("--no-entry");
1351 }
1352 LinkOutputKind::WasiReactorExe => {
1353 self.link_args(&["--entry", "_initialize"]);
1354 }
1355 }
1356 }
1357
1358 fn link_dylib_by_name(&mut self, name: &str, _verbatim: bool, _as_needed: bool) {
1359 self.link_or_cc_args(&["-l", name]);
1360 }
1361
1362 fn link_dylib_by_path(&mut self, path: &Path, _as_needed: bool) {
1363 self.link_or_cc_arg(path);
1364 }
1365
1366 fn link_staticlib_by_name(&mut self, name: &str, _verbatim: bool, whole_archive: bool) {
1367 if !whole_archive {
1368 self.link_or_cc_args(&["-l", name]);
1369 } else {
1370 self.link_arg("--whole-archive")
1371 .link_or_cc_args(&["-l", name])
1372 .link_arg("--no-whole-archive");
1373 }
1374 }
1375
1376 fn link_staticlib_by_path(&mut self, path: &Path, whole_archive: bool) {
1377 if !whole_archive {
1378 self.link_or_cc_arg(path);
1379 } else {
1380 self.link_arg("--whole-archive").link_or_cc_arg(path).link_arg("--no-whole-archive");
1381 }
1382 }
1383
1384 fn full_relro(&mut self) {}
1385
1386 fn partial_relro(&mut self) {}
1387
1388 fn no_relro(&mut self) {}
1389
1390 fn gc_sections(&mut self, _keep_metadata: bool) {
1391 self.link_arg("--gc-sections");
1392 }
1393
1394 fn optimize(&mut self) {
1395 self.link_arg(match self.sess.opts.optimize {
1398 OptLevel::No => "-O0",
1399 OptLevel::Less => "-O1",
1400 OptLevel::More => "-O2",
1401 OptLevel::Aggressive => "-O3",
1402 OptLevel::Size => "-O2",
1405 OptLevel::SizeMin => "-O2",
1406 });
1407 }
1408
1409 fn pgo_gen(&mut self) {}
1410
1411 fn debuginfo(&mut self, strip: Strip, _: &[PathBuf]) {
1412 match strip {
1413 Strip::None => {}
1414 Strip::Debuginfo => {
1415 self.link_arg("--strip-debug");
1416 }
1417 Strip::Symbols => {
1418 self.link_arg("--strip-all");
1419 }
1420 }
1421 }
1422
1423 fn control_flow_guard(&mut self) {}
1424
1425 fn ehcont_guard(&mut self) {}
1426
1427 fn no_crt_objects(&mut self) {}
1428
1429 fn no_default_libraries(&mut self) {}
1430
1431 fn export_symbols(&mut self, _tmpdir: &Path, _crate_type: CrateType, symbols: &[SymbolExport]) {
1432 for sym in symbols {
1433 self.link_args(&["--export", &sym.name]);
1434 }
1435 }
1436
1437 fn windows_subsystem(&mut self, _subsystem: WindowsSubsystemKind) {}
1438
1439 fn linker_plugin_lto(&mut self) {
1440 match self.sess.opts.cg.linker_plugin_lto {
1441 LinkerPluginLto::Disabled => {
1442 }
1444 LinkerPluginLto::LinkerPluginAuto => {
1445 self.push_linker_plugin_lto_args();
1446 }
1447 LinkerPluginLto::LinkerPlugin(_) => {
1448 self.push_linker_plugin_lto_args();
1449 }
1450 }
1451 }
1452}
1453
1454impl<'a> WasmLd<'a> {
1455 fn push_linker_plugin_lto_args(&mut self) {
1456 let opt_level = match self.sess.opts.optimize {
1457 config::OptLevel::No => "O0",
1458 config::OptLevel::Less => "O1",
1459 config::OptLevel::More => "O2",
1460 config::OptLevel::Aggressive => "O3",
1461 config::OptLevel::Size | config::OptLevel::SizeMin => "O2",
1463 };
1464 self.link_arg(&::alloc::__export::must_use({
::alloc::fmt::format(format_args!("--lto-{0}", opt_level))
})format!("--lto-{opt_level}"));
1465 }
1466}
1467
1468struct AixLinker<'a> {
1470 cmd: Command,
1471 sess: &'a Session,
1472 hinted_static: Option<bool>,
1473}
1474
1475impl<'a> AixLinker<'a> {
1476 fn new(cmd: Command, sess: &'a Session) -> AixLinker<'a> {
1477 AixLinker { cmd, sess, hinted_static: None }
1478 }
1479
1480 fn hint_static(&mut self) {
1481 if self.hinted_static != Some(true) {
1482 self.link_arg("-bstatic");
1483 self.hinted_static = Some(true);
1484 }
1485 }
1486
1487 fn hint_dynamic(&mut self) {
1488 if self.hinted_static != Some(false) {
1489 self.link_arg("-bdynamic");
1490 self.hinted_static = Some(false);
1491 }
1492 }
1493
1494 fn build_dylib(&mut self, _out_filename: &Path) {
1495 self.link_args(&["-bM:SRE", "-bnoentry"]);
1496 self.link_arg("-bexpfull");
1499 }
1500}
1501
1502impl<'a> Linker for AixLinker<'a> {
1503 fn cmd(&mut self) -> &mut Command {
1504 &mut self.cmd
1505 }
1506
1507 fn set_output_kind(
1508 &mut self,
1509 output_kind: LinkOutputKind,
1510 _crate_type: CrateType,
1511 out_filename: &Path,
1512 ) {
1513 match output_kind {
1514 LinkOutputKind::DynamicDylib => {
1515 self.hint_dynamic();
1516 self.build_dylib(out_filename);
1517 }
1518 LinkOutputKind::StaticDylib => {
1519 self.hint_static();
1520 self.build_dylib(out_filename);
1521 }
1522 _ => {}
1523 }
1524 }
1525
1526 fn link_dylib_by_name(&mut self, name: &str, verbatim: bool, _as_needed: bool) {
1527 self.hint_dynamic();
1528 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}") });
1529 }
1530
1531 fn link_dylib_by_path(&mut self, path: &Path, _as_needed: bool) {
1532 self.hint_dynamic();
1533 self.link_or_cc_arg(path);
1534 }
1535
1536 fn link_staticlib_by_name(&mut self, name: &str, verbatim: bool, whole_archive: bool) {
1537 self.hint_static();
1538 if !whole_archive {
1539 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}") });
1540 } else {
1541 let mut arg = OsString::from("-bkeepfile:");
1542 arg.push(find_native_static_library(name, verbatim, self.sess));
1543 self.link_or_cc_arg(arg);
1544 }
1545 }
1546
1547 fn link_staticlib_by_path(&mut self, path: &Path, whole_archive: bool) {
1548 self.hint_static();
1549 if !whole_archive {
1550 self.link_or_cc_arg(path);
1551 } else {
1552 let mut arg = OsString::from("-bkeepfile:");
1553 arg.push(path);
1554 self.link_arg(arg);
1555 }
1556 }
1557
1558 fn full_relro(&mut self) {}
1559
1560 fn partial_relro(&mut self) {}
1561
1562 fn no_relro(&mut self) {}
1563
1564 fn gc_sections(&mut self, _keep_metadata: bool) {
1565 self.link_arg("-bgc");
1566 }
1567
1568 fn optimize(&mut self) {}
1569
1570 fn pgo_gen(&mut self) {
1571 self.link_arg("-bdbg:namedsects:ss");
1572 self.link_arg("-u");
1573 self.link_arg("__llvm_profile_runtime");
1574 }
1575
1576 fn control_flow_guard(&mut self) {}
1577
1578 fn ehcont_guard(&mut self) {}
1579
1580 fn debuginfo(&mut self, _: Strip, _: &[PathBuf]) {}
1581
1582 fn no_crt_objects(&mut self) {}
1583
1584 fn no_default_libraries(&mut self) {}
1585
1586 fn export_symbols(&mut self, tmpdir: &Path, _crate_type: CrateType, symbols: &[SymbolExport]) {
1587 let path = tmpdir.join("list.exp");
1588 let res = try {
1589 let mut f = File::create_buffered(&path)?;
1590 for symbol in symbols {
1592 {
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:1592",
"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(1592u32),
::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};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!(" _{0}",
symbol.name) as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!(" _{}", symbol.name);
1593 f.write_fmt(format_args!(" {0}\n", symbol.name))writeln!(f, " {}", symbol.name)?;
1594 }
1595 };
1596 if let Err(e) = res {
1597 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}"));
1598 }
1599 self.link_arg(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("-bE:{0}", path.to_str().unwrap()))
})format!("-bE:{}", path.to_str().unwrap()));
1600 }
1601
1602 fn windows_subsystem(&mut self, _subsystem: WindowsSubsystemKind) {}
1603
1604 fn reset_per_library_state(&mut self) {
1605 self.hint_dynamic();
1606 }
1607
1608 fn linker_plugin_lto(&mut self) {}
1609
1610 fn add_eh_frame_header(&mut self) {}
1611
1612 fn add_no_exec(&mut self) {}
1613
1614 fn add_as_needed(&mut self) {}
1615}
1616
1617fn for_each_exported_symbols_include_dep<'tcx>(
1618 tcx: TyCtxt<'tcx>,
1619 crate_type: CrateType,
1620 mut callback: impl FnMut(ExportedSymbol<'tcx>, SymbolExportInfo, CrateNum),
1621) {
1622 let formats = tcx.dependency_formats(());
1623 let deps = &formats[&crate_type];
1624
1625 for (cnum, dep_format) in deps.iter_enumerated() {
1626 if *dep_format == Linkage::Static {
1628 for &(symbol, info) in tcx.exported_non_generic_symbols(cnum).iter() {
1629 callback(symbol, info, cnum);
1630 }
1631 for &(symbol, info) in tcx.exported_generic_symbols(cnum).iter() {
1632 callback(symbol, info, cnum);
1633 }
1634 }
1635 }
1636}
1637
1638fn symbol_export_from_exported_symbol<'tcx>(
1639 tcx: TyCtxt<'tcx>,
1640 symbol: ExportedSymbol<'tcx>,
1641 kind: SymbolExportKind,
1642 cnum: CrateNum,
1643) -> SymbolExport {
1644 let name = symbol_export::exporting_symbol_name_for_instance_in_crate(tcx, symbol, cnum);
1645 let link_name =
1646 symbol_export::linking_symbol_name_for_instance_in_crate(tcx, symbol, kind, cnum);
1647 SymbolExport::with_link_name(name, kind, link_name)
1648}
1649
1650fn symbol_export_from_raw_name(
1651 tcx: TyCtxt<'_>,
1652 name: String,
1653 kind: SymbolExportKind,
1654) -> SymbolExport {
1655 let symbol = ExportedSymbol::NoDefId(SymbolName::new(tcx, &name));
1656 let link_name =
1657 symbol_export::linking_symbol_name_for_instance_in_crate(tcx, symbol, kind, LOCAL_CRATE);
1658 SymbolExport::with_link_name(name, kind, link_name)
1659}
1660
1661pub(crate) fn exported_symbols(tcx: TyCtxt<'_>, crate_type: CrateType) -> Vec<SymbolExport> {
1662 if let Some(ref exports) = tcx.sess.target.override_export_symbols {
1663 return exports
1664 .iter()
1665 .map(|name| {
1666 symbol_export_from_raw_name(
1667 tcx,
1668 name.to_string(),
1669 SymbolExportKind::Text,
1673 )
1674 })
1675 .collect();
1676 }
1677
1678 let mut symbols = if let CrateType::ProcMacro = crate_type {
1679 exported_symbols_for_proc_macro_crate(tcx)
1680 } else {
1681 exported_symbols_for_non_proc_macro(tcx, crate_type)
1682 };
1683
1684 if (crate_type == CrateType::Dylib || crate_type == CrateType::ProcMacro)
1689 && !tcx.sess.target.is_like_wasm
1690 {
1691 let metadata_symbol_name = exported_symbols::metadata_symbol_name(tcx);
1692 symbols.push(symbol_export_from_raw_name(
1693 tcx,
1694 metadata_symbol_name,
1695 SymbolExportKind::Data,
1696 ));
1697 }
1698
1699 symbols
1700}
1701
1702fn exported_symbols_for_non_proc_macro(
1703 tcx: TyCtxt<'_>,
1704 crate_type: CrateType,
1705) -> Vec<SymbolExport> {
1706 let mut symbols = Vec::new();
1707 let export_threshold = symbol_export::crates_export_threshold(&[crate_type]);
1708 for_each_exported_symbols_include_dep(tcx, crate_type, |symbol, info, cnum| {
1709 if info.level.is_below_threshold(export_threshold) && !tcx.is_compiler_builtins(cnum) {
1713 symbols.push(symbol_export_from_exported_symbol(tcx, symbol, info.kind, cnum));
1714 symbol_export::extend_exported_symbols(&mut symbols, tcx, symbol, cnum);
1715 }
1716 });
1717
1718 if export_threshold == SymbolExportLevel::Rust
1720 && needs_allocator_shim_for_linking(tcx.dependency_formats(()), crate_type)
1721 && let Some(kind) = tcx.allocator_kind(())
1722 {
1723 symbols.extend(
1724 allocator_shim_symbols(tcx, kind)
1725 .map(|(name, kind)| symbol_export_from_raw_name(tcx, name, kind)),
1726 );
1727 }
1728
1729 symbols
1730}
1731
1732fn exported_symbols_for_proc_macro_crate(tcx: TyCtxt<'_>) -> Vec<SymbolExport> {
1733 if !tcx.sess.opts.output_types.should_codegen() {
1735 return Vec::new();
1736 }
1737
1738 let stable_crate_id = tcx.stable_crate_id(LOCAL_CRATE);
1739 let proc_macro_decls_name = rustc_session::generate_proc_macro_decls_symbol(stable_crate_id);
1740
1741 ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[symbol_export_from_raw_name(tcx, proc_macro_decls_name,
SymbolExportKind::Data)]))vec![symbol_export_from_raw_name(tcx, proc_macro_decls_name, SymbolExportKind::Data)]
1742}
1743
1744pub(crate) fn linked_symbols(
1745 tcx: TyCtxt<'_>,
1746 crate_type: CrateType,
1747) -> Vec<(String, SymbolExportKind)> {
1748 match crate_type {
1749 CrateType::Executable
1750 | CrateType::ProcMacro
1751 | CrateType::Cdylib
1752 | CrateType::Dylib
1753 | CrateType::Sdylib => (),
1754 CrateType::StaticLib | CrateType::Rlib => {
1755 return Vec::new();
1757 }
1758 }
1759
1760 match tcx.sess.lto() {
1761 Lto::No | Lto::ThinLocal => {}
1762 Lto::Thin | Lto::Fat => {
1763 return Vec::new();
1772 }
1773 }
1774
1775 let mut symbols = Vec::new();
1776
1777 let export_threshold = symbol_export::crates_export_threshold(&[crate_type]);
1778 for_each_exported_symbols_include_dep(tcx, crate_type, |symbol, info, cnum| {
1779 if info.level.is_below_threshold(export_threshold) && !tcx.is_compiler_builtins(cnum)
1780 || info.used
1781 || info.rustc_std_internal_symbol
1782 {
1783 symbols.push((
1784 symbol_export::linking_symbol_name_for_instance_in_crate(
1785 tcx, symbol, info.kind, cnum,
1786 ),
1787 info.kind,
1788 ));
1789 }
1790 });
1791
1792 symbols
1793}
1794
1795struct LlbcLinker<'a> {
1797 cmd: Command,
1798 sess: &'a Session,
1799}
1800
1801impl<'a> Linker for LlbcLinker<'a> {
1802 fn cmd(&mut self) -> &mut Command {
1803 &mut self.cmd
1804 }
1805
1806 fn set_output_kind(
1807 &mut self,
1808 _output_kind: LinkOutputKind,
1809 _crate_type: CrateType,
1810 _out_filename: &Path,
1811 ) {
1812 }
1813
1814 fn link_staticlib_by_name(&mut self, _name: &str, _verbatim: bool, _whole_archive: bool) {
1815 { ::core::panicking::panic_fmt(format_args!("staticlibs not supported")); }panic!("staticlibs not supported")
1816 }
1817
1818 fn link_staticlib_by_path(&mut self, path: &Path, _whole_archive: bool) {
1819 self.link_or_cc_arg(path);
1820 }
1821
1822 fn debuginfo(&mut self, strip: Strip, _: &[PathBuf]) {
1823 match strip {
1824 Strip::None => {
1825 self.link_arg("--debug");
1826 }
1827 Strip::Debuginfo | Strip::Symbols => {}
1828 }
1829 }
1830
1831 fn optimize(&mut self) {
1832 self.link_arg(match self.sess.opts.optimize {
1833 OptLevel::No => "-O0",
1834 OptLevel::Less => "-O1",
1835 OptLevel::More => "-O2",
1836 OptLevel::Aggressive => "-O3",
1837 OptLevel::Size => "-Os",
1838 OptLevel::SizeMin => "-Oz",
1839 });
1840 }
1841
1842 fn full_relro(&mut self) {}
1843
1844 fn partial_relro(&mut self) {}
1845
1846 fn no_relro(&mut self) {}
1847
1848 fn gc_sections(&mut self, _keep_metadata: bool) {}
1849
1850 fn pgo_gen(&mut self) {}
1851
1852 fn no_crt_objects(&mut self) {}
1853
1854 fn no_default_libraries(&mut self) {}
1855
1856 fn control_flow_guard(&mut self) {}
1857
1858 fn ehcont_guard(&mut self) {}
1859
1860 fn export_symbols(&mut self, _tmpdir: &Path, _crate_type: CrateType, symbols: &[SymbolExport]) {
1861 match _crate_type {
1862 CrateType::Cdylib => {
1863 for sym in symbols {
1864 self.link_args(&["--export-symbol", &sym.name]);
1865 }
1866 }
1867 _ => (),
1868 }
1869 }
1870
1871 fn windows_subsystem(&mut self, _subsystem: WindowsSubsystemKind) {}
1872
1873 fn linker_plugin_lto(&mut self) {}
1874}
1875
1876struct BpfLinker<'a> {
1877 cmd: Command,
1878 sess: &'a Session,
1879}
1880
1881impl<'a> Linker for BpfLinker<'a> {
1882 fn cmd(&mut self) -> &mut Command {
1883 &mut self.cmd
1884 }
1885
1886 fn set_output_kind(
1887 &mut self,
1888 _output_kind: LinkOutputKind,
1889 _crate_type: CrateType,
1890 _out_filename: &Path,
1891 ) {
1892 }
1893
1894 fn link_staticlib_by_name(&mut self, _name: &str, _verbatim: bool, _whole_archive: bool) {
1895 self.sess.dcx().emit_fatal(diagnostics::BpfStaticlibNotSupported)
1896 }
1897
1898 fn link_staticlib_by_path(&mut self, path: &Path, _whole_archive: bool) {
1899 self.link_or_cc_arg(path);
1900 }
1901
1902 fn debuginfo(&mut self, _strip: Strip, _: &[PathBuf]) {
1903 self.link_arg("--debug");
1904 }
1905
1906 fn optimize(&mut self) {
1907 self.link_arg(match self.sess.opts.optimize {
1908 OptLevel::No => "-O0",
1909 OptLevel::Less => "-O1",
1910 OptLevel::More => "-O2",
1911 OptLevel::Aggressive => "-O3",
1912 OptLevel::Size => "-Os",
1913 OptLevel::SizeMin => "-Oz",
1914 });
1915 }
1916
1917 fn full_relro(&mut self) {}
1918
1919 fn partial_relro(&mut self) {}
1920
1921 fn no_relro(&mut self) {}
1922
1923 fn gc_sections(&mut self, _keep_metadata: bool) {}
1924
1925 fn pgo_gen(&mut self) {}
1926
1927 fn no_crt_objects(&mut self) {}
1928
1929 fn no_default_libraries(&mut self) {}
1930
1931 fn control_flow_guard(&mut self) {}
1932
1933 fn ehcont_guard(&mut self) {}
1934
1935 fn export_symbols(&mut self, tmpdir: &Path, _crate_type: CrateType, symbols: &[SymbolExport]) {
1936 let path = tmpdir.join("symbols");
1937 let res = try {
1938 let mut f = File::create_buffered(&path)?;
1939 for sym in symbols {
1940 f.write_fmt(format_args!("{0}\n", sym.name))writeln!(f, "{}", sym.name)?;
1941 }
1942 };
1943 if let Err(error) = res {
1944 self.sess.dcx().emit_fatal(diagnostics::SymbolFileWriteFailure { error });
1945 } else {
1946 self.link_arg("--export-symbols").link_arg(&path);
1947 }
1948 }
1949
1950 fn windows_subsystem(&mut self, _subsystem: WindowsSubsystemKind) {}
1951
1952 fn linker_plugin_lto(&mut self) {}
1953}