Skip to content

Commit a52b431

Browse files
authored
Unrolled build for rust-lang#130586
Rollup merge of rust-lang#130586 - dpaoliello:fixrawdylib, r=wesleywiser Set "symbol name" in raw-dylib import libraries to the decorated name `windows-rs` received a bug report that mixing raw-dylib generated and the Windows SDK import libraries was causing linker failures: <microsoft/windows-rs#3285> The root cause turned out to be rust-lang#124958, that is we are not including the decorated name in the import library and so the import name type is also not being correctly set. This change modifies the generation of import libraries to set the "symbol name" to the fully decorated name and correctly marks the import as being data vs function. Note that this also required some changes to how the symbol is named within Rust: for MSVC we now need to use the decorated name but for MinGW we still need to use partially decorated (or undecorated) name. Fixes rust-lang#124958 Passing i686 MSVC and MinGW build: <https://github.com/rust-lang/rust/actions/runs/11000433888?pr=130586> r? `@ChrisDenton`
2 parents 5b20c45 + b2fd8a0 commit a52b431

File tree

7 files changed

+95
-55
lines changed

7 files changed

+95
-55
lines changed

compiler/rustc_codegen_gcc/src/archive.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use std::path::Path;
22

33
use rustc_codegen_ssa::back::archive::{
44
ArArchiveBuilder, ArchiveBuilder, ArchiveBuilderBuilder, DEFAULT_OBJECT_READER,
5+
ImportLibraryItem,
56
};
67
use rustc_session::Session;
78

@@ -16,7 +17,7 @@ impl ArchiveBuilderBuilder for ArArchiveBuilderBuilder {
1617
&self,
1718
_sess: &Session,
1819
_lib_name: &str,
19-
_import_name_and_ordinal_vector: Vec<(String, Option<u16>)>,
20+
_items: Vec<ImportLibraryItem>,
2021
_output_path: &Path,
2122
) {
2223
unimplemented!("creating dll imports is not yet supported");

compiler/rustc_codegen_llvm/src/callee.rs

+16-9
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,22 @@ pub(crate) fn get_fn<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'t
4444
let llfn = if tcx.sess.target.arch == "x86"
4545
&& let Some(dllimport) = crate::common::get_dllimport(tcx, instance_def_id, sym)
4646
{
47+
// When calling functions in generated import libraries, MSVC needs
48+
// the fully decorated name (as would have been in the declaring
49+
// object file), but MinGW wants the name as exported (as would be
50+
// in the def file) which may be missing decorations.
51+
let mingw_gnu_toolchain = common::is_mingw_gnu_toolchain(&tcx.sess.target);
52+
let llfn = cx.declare_fn(
53+
&common::i686_decorated_name(
54+
dllimport,
55+
mingw_gnu_toolchain,
56+
true,
57+
!mingw_gnu_toolchain,
58+
),
59+
fn_abi,
60+
Some(instance),
61+
);
62+
4763
// Fix for https://github.com/rust-lang/rust/issues/104453
4864
// On x86 Windows, LLVM uses 'L' as the prefix for any private
4965
// global symbols, so when we create an undecorated function symbol
@@ -55,15 +71,6 @@ pub(crate) fn get_fn<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'t
5571
// LLVM will prefix the name with `__imp_`. Ideally, we'd like the
5672
// existing logic below to set the Storage Class, but it has an
5773
// exemption for MinGW for backwards compatibility.
58-
let llfn = cx.declare_fn(
59-
&common::i686_decorated_name(
60-
dllimport,
61-
common::is_mingw_gnu_toolchain(&tcx.sess.target),
62-
true,
63-
),
64-
fn_abi,
65-
Some(instance),
66-
);
6774
unsafe {
6875
llvm::LLVMSetDLLStorageClass(llfn, llvm::DLLStorageClass::DllImport);
6976
}

compiler/rustc_codegen_llvm/src/consts.rs

+2-8
Original file line numberDiff line numberDiff line change
@@ -194,16 +194,10 @@ fn check_and_apply_linkage<'ll, 'tcx>(
194194
unsafe { llvm::LLVMSetInitializer(g2, g1) };
195195
g2
196196
} else if cx.tcx.sess.target.arch == "x86"
197+
&& common::is_mingw_gnu_toolchain(&cx.tcx.sess.target)
197198
&& let Some(dllimport) = crate::common::get_dllimport(cx.tcx, def_id, sym)
198199
{
199-
cx.declare_global(
200-
&common::i686_decorated_name(
201-
dllimport,
202-
common::is_mingw_gnu_toolchain(&cx.tcx.sess.target),
203-
true,
204-
),
205-
llty,
206-
)
200+
cx.declare_global(&common::i686_decorated_name(dllimport, true, true, false), llty)
207201
} else {
208202
// Generate an external declaration.
209203
// FIXME(nagisa): investigate whether it can be changed into define_global

compiler/rustc_codegen_ssa/src/back/archive.rs

+37-26
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,35 @@ use crate::errors::{
2626
DlltoolFailImportLibrary, ErrorCallingDllTool, ErrorCreatingImportLibrary, ErrorWritingDEFFile,
2727
};
2828

29+
/// An item to be included in an import library.
30+
/// This is a slimmed down version of `COFFShortExport` from `ar-archive-writer`.
31+
pub struct ImportLibraryItem {
32+
/// The name to be exported.
33+
pub name: String,
34+
/// The ordinal to be exported, if any.
35+
pub ordinal: Option<u16>,
36+
/// The original, decorated name if `name` is not decorated.
37+
pub symbol_name: Option<String>,
38+
/// True if this is a data export, false if it is a function export.
39+
pub is_data: bool,
40+
}
41+
42+
impl From<ImportLibraryItem> for COFFShortExport {
43+
fn from(item: ImportLibraryItem) -> Self {
44+
COFFShortExport {
45+
name: item.name,
46+
ext_name: None,
47+
symbol_name: item.symbol_name,
48+
alias_target: None,
49+
ordinal: item.ordinal.unwrap_or(0),
50+
noname: item.ordinal.is_some(),
51+
data: item.is_data,
52+
private: false,
53+
constant: false,
54+
}
55+
}
56+
}
57+
2958
pub trait ArchiveBuilderBuilder {
3059
fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box<dyn ArchiveBuilder + 'a>;
3160

@@ -38,7 +67,7 @@ pub trait ArchiveBuilderBuilder {
3867
&self,
3968
sess: &Session,
4069
lib_name: &str,
41-
import_name_and_ordinal_vector: Vec<(String, Option<u16>)>,
70+
items: Vec<ImportLibraryItem>,
4271
output_path: &Path,
4372
) {
4473
if common::is_mingw_gnu_toolchain(&sess.target) {
@@ -47,21 +76,16 @@ pub trait ArchiveBuilderBuilder {
4776
// that loaded but crashed with an AV upon calling one of the imported
4877
// functions. Therefore, use binutils to create the import library instead,
4978
// by writing a .DEF file to the temp dir and calling binutils's dlltool.
50-
create_mingw_dll_import_lib(
51-
sess,
52-
lib_name,
53-
import_name_and_ordinal_vector,
54-
output_path,
55-
);
79+
create_mingw_dll_import_lib(sess, lib_name, items, output_path);
5680
} else {
5781
trace!("creating import library");
5882
trace!(" dll_name {:#?}", lib_name);
5983
trace!(" output_path {}", output_path.display());
6084
trace!(
6185
" import names: {}",
62-
import_name_and_ordinal_vector
86+
items
6387
.iter()
64-
.map(|(name, _ordinal)| name.clone())
88+
.map(|ImportLibraryItem { name, .. }| name.clone())
6589
.collect::<Vec<_>>()
6690
.join(", "),
6791
);
@@ -79,20 +103,7 @@ pub trait ArchiveBuilderBuilder {
79103
.emit_fatal(ErrorCreatingImportLibrary { lib_name, error: error.to_string() }),
80104
};
81105

82-
let exports = import_name_and_ordinal_vector
83-
.iter()
84-
.map(|(name, ordinal)| COFFShortExport {
85-
name: name.to_string(),
86-
ext_name: None,
87-
symbol_name: None,
88-
alias_target: None,
89-
ordinal: ordinal.unwrap_or(0),
90-
noname: ordinal.is_some(),
91-
data: false,
92-
private: false,
93-
constant: false,
94-
})
95-
.collect::<Vec<_>>();
106+
let exports = items.into_iter().map(Into::into).collect::<Vec<_>>();
96107
let machine = match &*sess.target.arch {
97108
"x86_64" => MachineTypes::AMD64,
98109
"x86" => MachineTypes::I386,
@@ -160,16 +171,16 @@ pub trait ArchiveBuilderBuilder {
160171
fn create_mingw_dll_import_lib(
161172
sess: &Session,
162173
lib_name: &str,
163-
import_name_and_ordinal_vector: Vec<(String, Option<u16>)>,
174+
items: Vec<ImportLibraryItem>,
164175
output_path: &Path,
165176
) {
166177
let def_file_path = output_path.with_extension("def");
167178

168179
let def_file_content = format!(
169180
"EXPORTS\n{}",
170-
import_name_and_ordinal_vector
181+
items
171182
.into_iter()
172-
.map(|(name, ordinal)| {
183+
.map(|ImportLibraryItem { name, ordinal, .. }| {
173184
match ordinal {
174185
Some(n) => format!("{name} @{n} NONAME"),
175186
None => name,

compiler/rustc_codegen_ssa/src/back/link.rs

+27-8
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ use rustc_target::spec::{
4545
use tempfile::Builder as TempFileBuilder;
4646
use tracing::{debug, info, warn};
4747

48-
use super::archive::{ArchiveBuilder, ArchiveBuilderBuilder};
48+
use super::archive::{ArchiveBuilder, ArchiveBuilderBuilder, ImportLibraryItem};
4949
use super::command::Command;
5050
use super::linker::{self, Linker};
5151
use super::metadata::{MetadataPosition, create_wrapper_file};
@@ -495,24 +495,43 @@ fn create_dll_import_libs<'a>(
495495

496496
let mingw_gnu_toolchain = common::is_mingw_gnu_toolchain(&sess.target);
497497

498-
let import_name_and_ordinal_vector: Vec<(String, Option<u16>)> = raw_dylib_imports
498+
let items: Vec<ImportLibraryItem> = raw_dylib_imports
499499
.iter()
500500
.map(|import: &DllImport| {
501501
if sess.target.arch == "x86" {
502-
(
503-
common::i686_decorated_name(import, mingw_gnu_toolchain, false),
504-
import.ordinal(),
505-
)
502+
ImportLibraryItem {
503+
name: common::i686_decorated_name(
504+
import,
505+
mingw_gnu_toolchain,
506+
false,
507+
false,
508+
),
509+
ordinal: import.ordinal(),
510+
symbol_name: import.is_missing_decorations().then(|| {
511+
common::i686_decorated_name(
512+
import,
513+
mingw_gnu_toolchain,
514+
false,
515+
true,
516+
)
517+
}),
518+
is_data: !import.is_fn,
519+
}
506520
} else {
507-
(import.name.to_string(), import.ordinal())
521+
ImportLibraryItem {
522+
name: import.name.to_string(),
523+
ordinal: import.ordinal(),
524+
symbol_name: None,
525+
is_data: !import.is_fn,
526+
}
508527
}
509528
})
510529
.collect();
511530

512531
archive_builder_builder.create_dll_import_lib(
513532
sess,
514533
&raw_dylib_name,
515-
import_name_and_ordinal_vector,
534+
items,
516535
&output_path,
517536
);
518537

compiler/rustc_codegen_ssa/src/common.rs

+6-3
Original file line numberDiff line numberDiff line change
@@ -187,12 +187,15 @@ pub fn i686_decorated_name(
187187
dll_import: &DllImport,
188188
mingw: bool,
189189
disable_name_mangling: bool,
190+
force_fully_decorated: bool,
190191
) -> String {
191192
let name = dll_import.name.as_str();
192193

193-
let (add_prefix, add_suffix) = match dll_import.import_name_type {
194-
Some(PeImportNameType::NoPrefix) => (false, true),
195-
Some(PeImportNameType::Undecorated) => (false, false),
194+
let (add_prefix, add_suffix) = match (force_fully_decorated, dll_import.import_name_type) {
195+
// No prefix is a bit weird, in that LLVM/ar_archive_writer won't emit it, so we will
196+
// ignore `force_fully_decorated` and always partially decorate it.
197+
(_, Some(PeImportNameType::NoPrefix)) => (false, true),
198+
(false, Some(PeImportNameType::Undecorated)) => (false, false),
196199
_ => (true, true),
197200
};
198201

compiler/rustc_session/src/cstore.rs

+5
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,11 @@ impl DllImport {
130130
None
131131
}
132132
}
133+
134+
pub fn is_missing_decorations(&self) -> bool {
135+
self.import_name_type == Some(PeImportNameType::Undecorated)
136+
|| self.import_name_type == Some(PeImportNameType::NoPrefix)
137+
}
133138
}
134139

135140
/// Calling convention for a function defined in an external library.

0 commit comments

Comments
 (0)