Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit bdee317

Browse files
Auto merge of #142742 - dpaoliello:arm64eclinking, r=<try>
[win][aarch64] Fix linking statics on Arm64EC, take 2 Arm64EC builds recently started to fail due to the linker not finding a symbol: ``` symbols.o : error LNK2001: unresolved external symbol #_ZN3std9panicking11EMPTY_PANIC17hc8d2b903527827f1E (EC Symbol) C:\Code\hello-world\target\arm64ec-pc-windows-msvc\debug\deps\hello_world.exe : fatal error LNK1120: 1 unresolved externals ``` It turns out that `EMPTY_PANIC` is a new static variable that was being exported then imported from the standard library, but when exporting LLVM didn't prepend the name with `#` (as only functions are prefixed with this character), whereas Rust was prefixing with `#` when attempting to import it. The fix is to have Rust not prefix statics with `#` when importing. Adding tests discovered another issue: we need to correctly mark static exported from dylibs with `DATA`, otherwise MSVC's linker assumes they are functions and complains that there is no exit thunk for them. Fixes #138541 Resurrects #140176 now that #141061 is merged, which removes the incompatibility with `__rust_no_alloc_shim_is_unstable`. r? `@wesleywiser` CC `@bjorn3` -- try-job: x86_64-msvc-* try-job: x86_64-mingw-* try-job: dist-aarch64-msvc
2 parents 18491d5 + fec0e2a commit bdee317

File tree

9 files changed

+197
-52
lines changed

9 files changed

+197
-52
lines changed

‎compiler/rustc_codegen_ssa/src/back/linker.rs

Lines changed: 101 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,12 @@ pub(crate) trait Linker {
337337
fn debuginfo(&mut self, strip: Strip, natvis_debugger_visualizers: &[PathBuf]);
338338
fn no_crt_objects(&mut self);
339339
fn no_default_libraries(&mut self);
340-
fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType, symbols: &[String]);
340+
fn export_symbols(
341+
&mut self,
342+
tmpdir: &Path,
343+
crate_type: CrateType,
344+
symbols: &[(String, SymbolExportKind)],
345+
);
341346
fn subsystem(&mut self, subsystem: &str);
342347
fn linker_plugin_lto(&mut self);
343348
fn add_eh_frame_header(&mut self) {}
@@ -770,7 +775,12 @@ impl<'a> Linker for GccLinker<'a> {
770775
}
771776
}
772777

773-
fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType, symbols: &[String]) {
778+
fn export_symbols(
779+
&mut self,
780+
tmpdir: &Path,
781+
crate_type: CrateType,
782+
symbols: &[(String, SymbolExportKind)],
783+
) {
774784
// Symbol visibility in object files typically takes care of this.
775785
if crate_type == CrateType::Executable {
776786
let should_export_executable_symbols =
@@ -799,7 +809,7 @@ impl<'a> Linker for GccLinker<'a> {
799809
// Write a plain, newline-separated list of symbols
800810
let res: io::Result<()> = try {
801811
let mut f = File::create_buffered(&path)?;
802-
for sym in symbols {
812+
for (sym, _) in symbols {
803813
debug!(" _{sym}");
804814
writeln!(f, "_{sym}")?;
805815
}
@@ -814,11 +824,12 @@ impl<'a> Linker for GccLinker<'a> {
814824
// .def file similar to MSVC one but without LIBRARY section
815825
// because LD doesn't like when it's empty
816826
writeln!(f, "EXPORTS")?;
817-
for symbol in symbols {
827+
for (symbol, kind) in symbols {
828+
let kind_marker = if *kind == SymbolExportKind::Data { " DATA" } else { "" };
818829
debug!(" _{symbol}");
819830
// Quote the name in case it's reserved by linker in some way
820831
// (this accounts for names with dots in particular).
821-
writeln!(f, " \"{symbol}\"")?;
832+
writeln!(f, " \"{symbol}\"{kind_marker}")?;
822833
}
823834
};
824835
if let Err(error) = res {
@@ -831,7 +842,7 @@ impl<'a> Linker for GccLinker<'a> {
831842
writeln!(f, "{{")?;
832843
if !symbols.is_empty() {
833844
writeln!(f, " global:")?;
834-
for sym in symbols {
845+
for (sym, _) in symbols {
835846
debug!(" {sym};");
836847
writeln!(f, " {sym};")?;
837848
}
@@ -1098,7 +1109,12 @@ impl<'a> Linker for MsvcLinker<'a> {
10981109
// crates. Upstream rlibs may be linked statically to this dynamic library,
10991110
// in which case they may continue to transitively be used and hence need
11001111
// their symbols exported.
1101-
fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType, symbols: &[String]) {
1112+
fn export_symbols(
1113+
&mut self,
1114+
tmpdir: &Path,
1115+
crate_type: CrateType,
1116+
symbols: &[(String, SymbolExportKind)],
1117+
) {
11021118
// Symbol visibility takes care of this typically
11031119
if crate_type == CrateType::Executable {
11041120
let should_export_executable_symbols =
@@ -1116,9 +1132,10 @@ impl<'a> Linker for MsvcLinker<'a> {
11161132
// straight to exports.
11171133
writeln!(f, "LIBRARY")?;
11181134
writeln!(f, "EXPORTS")?;
1119-
for symbol in symbols {
1135+
for (symbol, kind) in symbols {
1136+
let kind_marker = if *kind == SymbolExportKind::Data { " DATA" } else { "" };
11201137
debug!(" _{symbol}");
1121-
writeln!(f, " {symbol}")?;
1138+
writeln!(f, " {symbol}{kind_marker}")?;
11221139
}
11231140
};
11241141
if let Err(error) = res {
@@ -1259,14 +1276,19 @@ impl<'a> Linker for EmLinker<'a> {
12591276
self.cc_arg("-nodefaultlibs");
12601277
}
12611278

1262-
fn export_symbols(&mut self, _tmpdir: &Path, _crate_type: CrateType, symbols: &[String]) {
1279+
fn export_symbols(
1280+
&mut self,
1281+
_tmpdir: &Path,
1282+
_crate_type: CrateType,
1283+
symbols: &[(String, SymbolExportKind)],
1284+
) {
12631285
debug!("EXPORTED SYMBOLS:");
12641286

12651287
self.cc_arg("-s");
12661288

12671289
let mut arg = OsString::from("EXPORTED_FUNCTIONS=");
12681290
let encoded = serde_json::to_string(
1269-
&symbols.iter().map(|sym| "_".to_owned() + sym).collect::<Vec<_>>(),
1291+
&symbols.iter().map(|(sym, _)| "_".to_owned() + sym).collect::<Vec<_>>(),
12701292
)
12711293
.unwrap();
12721294
debug!("{encoded}");
@@ -1428,8 +1450,13 @@ impl<'a> Linker for WasmLd<'a> {
14281450

14291451
fn no_default_libraries(&mut self) {}
14301452

1431-
fn export_symbols(&mut self, _tmpdir: &Path, _crate_type: CrateType, symbols: &[String]) {
1432-
for sym in symbols {
1453+
fn export_symbols(
1454+
&mut self,
1455+
_tmpdir: &Path,
1456+
_crate_type: CrateType,
1457+
symbols: &[(String, SymbolExportKind)],
1458+
) {
1459+
for (sym, _) in symbols {
14331460
self.link_args(&["--export", sym]);
14341461
}
14351462

@@ -1563,7 +1590,7 @@ impl<'a> Linker for L4Bender<'a> {
15631590
self.cc_arg("-nostdlib");
15641591
}
15651592

1566-
fn export_symbols(&mut self, _: &Path, _: CrateType, _: &[String]) {
1593+
fn export_symbols(&mut self, _: &Path, _: CrateType, _: &[(String,SymbolExportKind)]) {
15671594
// ToDo, not implemented, copy from GCC
15681595
self.sess.dcx().emit_warn(errors::L4BenderExportingSymbolsUnimplemented);
15691596
}
@@ -1720,12 +1747,17 @@ impl<'a> Linker for AixLinker<'a> {
17201747

17211748
fn no_default_libraries(&mut self) {}
17221749

1723-
fn export_symbols(&mut self, tmpdir: &Path, _crate_type: CrateType, symbols: &[String]) {
1750+
fn export_symbols(
1751+
&mut self,
1752+
tmpdir: &Path,
1753+
_crate_type: CrateType,
1754+
symbols: &[(String, SymbolExportKind)],
1755+
) {
17241756
let path = tmpdir.join("list.exp");
17251757
let res: io::Result<()> = try {
17261758
let mut f = File::create_buffered(&path)?;
17271759
// FIXME: use llvm-nm to generate export list.
1728-
for symbol in symbols {
1760+
for (symbol, _) in symbols {
17291761
debug!(" _{symbol}");
17301762
writeln!(f, " {symbol}")?;
17311763
}
@@ -1769,9 +1801,23 @@ fn for_each_exported_symbols_include_dep<'tcx>(
17691801
}
17701802
}
17711803

1772-
pub(crate) fn exported_symbols(tcx: TyCtxt<'_>, crate_type: CrateType) -> Vec<String> {
1804+
pub(crate) fn exported_symbols(
1805+
tcx: TyCtxt<'_>,
1806+
crate_type: CrateType,
1807+
) -> Vec<(String, SymbolExportKind)> {
17731808
if let Some(ref exports) = tcx.sess.target.override_export_symbols {
1774-
return exports.iter().map(ToString::to_string).collect();
1809+
return exports
1810+
.iter()
1811+
.map(|name| {
1812+
(
1813+
name.to_string(),
1814+
// FIXME use the correct export kind for this symbol. override_export_symbols
1815+
// can't directly specify the SymbolExportKind as it is defined in rustc_middle
1816+
// which rustc_target can't depend on.
1817+
SymbolExportKind::Text,
1818+
)
1819+
})
1820+
.collect();
17751821
}
17761822

17771823
if let CrateType::ProcMacro = crate_type {
@@ -1781,25 +1827,29 @@ pub(crate) fn exported_symbols(tcx: TyCtxt<'_>, crate_type: CrateType) -> Vec<St
17811827
}
17821828
}
17831829

1784-
fn exported_symbols_for_non_proc_macro(tcx: TyCtxt<'_>, crate_type: CrateType) -> Vec<String> {
1830+
fn exported_symbols_for_non_proc_macro(
1831+
tcx: TyCtxt<'_>,
1832+
crate_type: CrateType,
1833+
) -> Vec<(String, SymbolExportKind)> {
17851834
let mut symbols = Vec::new();
17861835
let export_threshold = symbol_export::crates_export_threshold(&[crate_type]);
17871836
for_each_exported_symbols_include_dep(tcx, crate_type, |symbol, info, cnum| {
17881837
// Do not export mangled symbols from cdylibs and don't attempt to export compiler-builtins
17891838
// from any cdylib. The latter doesn't work anyway as we use hidden visibility for
17901839
// compiler-builtins. Most linkers silently ignore it, but ld64 gives a warning.
17911840
if info.level.is_below_threshold(export_threshold) && !tcx.is_compiler_builtins(cnum) {
1792-
symbols.push(symbol_export::exporting_symbol_name_for_instance_in_crate(
1793-
tcx, symbol, cnum,
1841+
symbols.push((
1842+
symbol_export::exporting_symbol_name_for_instance_in_crate(tcx, symbol, cnum),
1843+
info.kind,
17941844
));
1795-
symbol_export::extend_exported_symbols(&mut symbols, tcx, symbol, cnum);
1845+
symbol_export::extend_exported_symbols(&mut symbols, tcx, symbol, info,cnum);
17961846
}
17971847
});
17981848

17991849
symbols
18001850
}
18011851

1802-
fn exported_symbols_for_proc_macro_crate(tcx: TyCtxt<'_>) -> Vec<String> {
1852+
fn exported_symbols_for_proc_macro_crate(tcx: TyCtxt<'_>) -> Vec<(String,SymbolExportKind)> {
18031853
// `exported_symbols` will be empty when !should_codegen.
18041854
if !tcx.sess.opts.output_types.should_codegen() {
18051855
return Vec::new();
@@ -1809,7 +1859,10 @@ fn exported_symbols_for_proc_macro_crate(tcx: TyCtxt<'_>) -> Vec<String> {
18091859
let proc_macro_decls_name = tcx.sess.generate_proc_macro_decls_symbol(stable_crate_id);
18101860
let metadata_symbol_name = exported_symbols::metadata_symbol_name(tcx);
18111861

1812-
vec![proc_macro_decls_name, metadata_symbol_name]
1862+
vec![
1863+
(proc_macro_decls_name, SymbolExportKind::Text),
1864+
(metadata_symbol_name, SymbolExportKind::Text),
1865+
]
18131866
}
18141867

18151868
pub(crate) fn linked_symbols(
@@ -1831,7 +1884,9 @@ pub(crate) fn linked_symbols(
18311884
|| info.used
18321885
{
18331886
symbols.push((
1834-
symbol_export::linking_symbol_name_for_instance_in_crate(tcx, symbol, cnum),
1887+
symbol_export::linking_symbol_name_for_instance_in_crate(
1888+
tcx, symbol, info.kind, cnum,
1889+
),
18351890
info.kind,
18361891
));
18371892
}
@@ -1906,7 +1961,13 @@ impl<'a> Linker for PtxLinker<'a> {
19061961

19071962
fn ehcont_guard(&mut self) {}
19081963

1909-
fn export_symbols(&mut self, _tmpdir: &Path, _crate_type: CrateType, _symbols: &[String]) {}
1964+
fn export_symbols(
1965+
&mut self,
1966+
_tmpdir: &Path,
1967+
_crate_type: CrateType,
1968+
_symbols: &[(String, SymbolExportKind)],
1969+
) {
1970+
}
19101971

19111972
fn subsystem(&mut self, _subsystem: &str) {}
19121973

@@ -1975,10 +2036,15 @@ impl<'a> Linker for LlbcLinker<'a> {
19752036

19762037
fn ehcont_guard(&mut self) {}
19772038

1978-
fn export_symbols(&mut self, _tmpdir: &Path, _crate_type: CrateType, symbols: &[String]) {
2039+
fn export_symbols(
2040+
&mut self,
2041+
_tmpdir: &Path,
2042+
_crate_type: CrateType,
2043+
symbols: &[(String, SymbolExportKind)],
2044+
) {
19792045
match _crate_type {
19802046
CrateType::Cdylib => {
1981-
for sym in symbols {
2047+
for (sym, _) in symbols {
19822048
self.link_args(&["--export-symbol", sym]);
19832049
}
19842050
}
@@ -2052,11 +2118,16 @@ impl<'a> Linker for BpfLinker<'a> {
20522118

20532119
fn ehcont_guard(&mut self) {}
20542120

2055-
fn export_symbols(&mut self, tmpdir: &Path, _crate_type: CrateType, symbols: &[String]) {
2121+
fn export_symbols(
2122+
&mut self,
2123+
tmpdir: &Path,
2124+
_crate_type: CrateType,
2125+
symbols: &[(String, SymbolExportKind)],
2126+
) {
20562127
let path = tmpdir.join("symbols");
20572128
let res: io::Result<()> = try {
20582129
let mut f = File::create_buffered(&path)?;
2059-
for sym in symbols {
2130+
for (sym, _) in symbols {
20602131
writeln!(f, "{sym}")?;
20612132
}
20622133
};

‎compiler/rustc_codegen_ssa/src/back/symbol_export.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -680,6 +680,7 @@ fn calling_convention_for_symbol<'tcx>(
680680
pub(crate) fn linking_symbol_name_for_instance_in_crate<'tcx>(
681681
tcx: TyCtxt<'tcx>,
682682
symbol: ExportedSymbol<'tcx>,
683+
export_kind: SymbolExportKind,
683684
instantiating_crate: CrateNum,
684685
) -> String {
685686
let mut undecorated = symbol_name_for_instance_in_crate(tcx, symbol, instantiating_crate);
@@ -700,8 +701,9 @@ pub(crate) fn linking_symbol_name_for_instance_in_crate<'tcx>(
700701
let prefix = match &target.arch[..] {
701702
"x86" => Some('_'),
702703
"x86_64" => None,
703-
"arm64ec" => Some('#'),
704-
// Only x86/64 use symbol decorations.
704+
// Only functions are decorated for arm64ec.
705+
"arm64ec" if export_kind == SymbolExportKind::Text => Some('#'),
706+
// Only x86/64 and arm64ec use symbol decorations.
705707
_ => return undecorated,
706708
};
707709

@@ -741,9 +743,10 @@ pub(crate) fn exporting_symbol_name_for_instance_in_crate<'tcx>(
741743
/// Add it to the symbols list for all kernel functions, so that it is exported in the linked
742744
/// object.
743745
pub(crate) fn extend_exported_symbols<'tcx>(
744-
symbols: &mut Vec<String>,
746+
symbols: &mut Vec<(String,SymbolExportKind)>,
745747
tcx: TyCtxt<'tcx>,
746748
symbol: ExportedSymbol<'tcx>,
749+
info: SymbolExportInfo,
747750
instantiating_crate: CrateNum,
748751
) {
749752
let (callconv, _) = calling_convention_for_symbol(tcx, symbol);
@@ -755,7 +758,7 @@ pub(crate) fn extend_exported_symbols<'tcx>(
755758
let undecorated = symbol_name_for_instance_in_crate(tcx, symbol, instantiating_crate);
756759

757760
// Add the symbol for the kernel descriptor (with .kd suffix)
758-
symbols.push(format!("{undecorated}.kd"));
761+
symbols.push((format!("{undecorated}.kd"), info.kind));
759762
}
760763

761764
fn maybe_emutls_symbol_name<'tcx>(

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /