Skip to content

Commit ecbf0ac

Browse files
authored
Rollup merge of rust-lang#130808 - checkraisefold:fix-questionmark-linking, r=davidtwco
Fix linking for symbols starting with ? on i686-pc-windows-msvc When using the `export_name` attribute to specifically export a symbol beginning with a question mark on the `i686-pc-windows-msvc` target, that symbol will fail to link and throw a linker error 100% of the time. [Issue writeup.](rust-lang#44282 (comment)) Closes rust-lang#44282 I'm not sure if this is a proper solution, but [LLVM does the same check](https://github.com/llvm/llvm-project/blob/main/llvm/lib/IR/Mangler.cpp#L48-L49) which causes this issue, and is applied to [all 32- and 64-bit Windows COFF objects](https://github.com/llvm/llvm-project/blob/main/llvm/include/llvm/IR/DataLayout.h#L255-L257) (maybe the same patch should be applied for 64 bit windows as well then?). I am *more* unsure of whether this is the proper place for such a solution (and if the exact conditions of is_like_windows are proper for this usecase), or if the underscore should be stripped elsewhere, but it seems like the most correct place. I'm also unsure if there are any backwards compatibility ramifications here. There shouldn't be, because binaries with exported symbols starting with `?` for this target failed to link because of this issue anyway, but still.
2 parents 6365178 + 9c3b53d commit ecbf0ac

File tree

2 files changed

+28
-0
lines changed

2 files changed

+28
-0
lines changed

compiler/rustc_codegen_ssa/src/back/symbol_export.rs

+3
Original file line numberDiff line numberDiff line change
@@ -577,6 +577,9 @@ pub(crate) fn linking_symbol_name_for_instance_in_crate<'tcx>(
577577
}
578578

579579
let prefix = match &target.arch[..] {
580+
"x86" | "x86_64" if target.is_like_msvc && undecorated.starts_with("?") => {
581+
return undecorated;
582+
}
580583
"x86" => Some('_'),
581584
"x86_64" => None,
582585
"arm64ec" => Some('#'),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// This test ensures functions with an exported name beginning with a question mark
2+
// successfully compile and link.
3+
//
4+
// Regression test for <https://github.com/rust-lang/rust/issues/44282>
5+
6+
//@ build-pass
7+
//@ only-windows
8+
//@ only-x86
9+
// Reason: This test regards a linker issue which only applies to Windows.
10+
// Specifically, it only occurs due to Windows x86 name decoration, combined with
11+
// a mismatch between LLVM's decoration logic and Rust's (for `lib.def` generation)
12+
13+
#![crate_type = "cdylib"]
14+
15+
#[no_mangle]
16+
pub extern "C" fn decorated(a: i32, b: i32) -> i32 {
17+
1
18+
}
19+
20+
// This isn't just `?undecorated` because MSVC's linker fails if the decorated
21+
// symbol is not valid.
22+
#[export_name = "?undecorated@@YAXXZ"]
23+
pub extern "C" fn undecorated(a: i32, b: i32) -> i32 {
24+
2
25+
}

0 commit comments

Comments
 (0)