about summary refs log tree commit diff
path: root/compiler/rustc_codegen_ssa
diff options
context:
space:
mode:
authorJubilee <workingjubilee@gmail.com>2024-11-07 18:48:20 -0800
committerGitHub <noreply@github.com>2024-11-07 18:48:20 -0800
commit60e8ab6ba8d005ff83d6e2e33e679375af5f74ec (patch)
tree042ba8b373029ef8762374dfbf23d898dce247d9 /compiler/rustc_codegen_ssa
parentb91a3a05609a46f73d23e0995ae7ebb4a4f429a5 (diff)
parentb2fd8a0192f6a69a4fb969ab3d005b577a524371 (diff)
downloadrust-60e8ab6ba8d005ff83d6e2e33e679375af5f74ec.tar.gz
rust-60e8ab6ba8d005ff83d6e2e33e679375af5f74ec.zip
Rollup merge of #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: <https://github.com/microsoft/windows-rs/issues/3285>

The root cause turned out to be #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 #124958

Passing i686 MSVC and MinGW build: <https://github.com/rust-lang/rust/actions/runs/11000433888?pr=130586>

r? `@ChrisDenton`
Diffstat (limited to 'compiler/rustc_codegen_ssa')
-rw-r--r--compiler/rustc_codegen_ssa/src/back/archive.rs63
-rw-r--r--compiler/rustc_codegen_ssa/src/back/link.rs35
-rw-r--r--compiler/rustc_codegen_ssa/src/common.rs9
3 files changed, 70 insertions, 37 deletions
diff --git a/compiler/rustc_codegen_ssa/src/back/archive.rs b/compiler/rustc_codegen_ssa/src/back/archive.rs
index 2f48c1fbf0d..e83bfa7b70d 100644
--- a/compiler/rustc_codegen_ssa/src/back/archive.rs
+++ b/compiler/rustc_codegen_ssa/src/back/archive.rs
@@ -26,6 +26,35 @@ use crate::errors::{
     DlltoolFailImportLibrary, ErrorCallingDllTool, ErrorCreatingImportLibrary, ErrorWritingDEFFile,
 };
 
+/// An item to be included in an import library.
+/// This is a slimmed down version of `COFFShortExport` from `ar-archive-writer`.
+pub struct ImportLibraryItem {
+    /// The name to be exported.
+    pub name: String,
+    /// The ordinal to be exported, if any.
+    pub ordinal: Option<u16>,
+    /// The original, decorated name if `name` is not decorated.
+    pub symbol_name: Option<String>,
+    /// True if this is a data export, false if it is a function export.
+    pub is_data: bool,
+}
+
+impl From<ImportLibraryItem> for COFFShortExport {
+    fn from(item: ImportLibraryItem) -> Self {
+        COFFShortExport {
+            name: item.name,
+            ext_name: None,
+            symbol_name: item.symbol_name,
+            alias_target: None,
+            ordinal: item.ordinal.unwrap_or(0),
+            noname: item.ordinal.is_some(),
+            data: item.is_data,
+            private: false,
+            constant: false,
+        }
+    }
+}
+
 pub trait ArchiveBuilderBuilder {
     fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box<dyn ArchiveBuilder + 'a>;
 
@@ -38,7 +67,7 @@ pub trait ArchiveBuilderBuilder {
         &self,
         sess: &Session,
         lib_name: &str,
-        import_name_and_ordinal_vector: Vec<(String, Option<u16>)>,
+        items: Vec<ImportLibraryItem>,
         output_path: &Path,
     ) {
         if common::is_mingw_gnu_toolchain(&sess.target) {
@@ -47,21 +76,16 @@ pub trait ArchiveBuilderBuilder {
             // that loaded but crashed with an AV upon calling one of the imported
             // functions. Therefore, use binutils to create the import library instead,
             // by writing a .DEF file to the temp dir and calling binutils's dlltool.
-            create_mingw_dll_import_lib(
-                sess,
-                lib_name,
-                import_name_and_ordinal_vector,
-                output_path,
-            );
+            create_mingw_dll_import_lib(sess, lib_name, items, output_path);
         } else {
             trace!("creating import library");
             trace!("  dll_name {:#?}", lib_name);
             trace!("  output_path {}", output_path.display());
             trace!(
                 "  import names: {}",
-                import_name_and_ordinal_vector
+                items
                     .iter()
-                    .map(|(name, _ordinal)| name.clone())
+                    .map(|ImportLibraryItem { name, .. }| name.clone())
                     .collect::<Vec<_>>()
                     .join(", "),
             );
@@ -79,20 +103,7 @@ pub trait ArchiveBuilderBuilder {
                     .emit_fatal(ErrorCreatingImportLibrary { lib_name, error: error.to_string() }),
             };
 
-            let exports = import_name_and_ordinal_vector
-                .iter()
-                .map(|(name, ordinal)| COFFShortExport {
-                    name: name.to_string(),
-                    ext_name: None,
-                    symbol_name: None,
-                    alias_target: None,
-                    ordinal: ordinal.unwrap_or(0),
-                    noname: ordinal.is_some(),
-                    data: false,
-                    private: false,
-                    constant: false,
-                })
-                .collect::<Vec<_>>();
+            let exports = items.into_iter().map(Into::into).collect::<Vec<_>>();
             let machine = match &*sess.target.arch {
                 "x86_64" => MachineTypes::AMD64,
                 "x86" => MachineTypes::I386,
@@ -160,16 +171,16 @@ pub trait ArchiveBuilderBuilder {
 fn create_mingw_dll_import_lib(
     sess: &Session,
     lib_name: &str,
-    import_name_and_ordinal_vector: Vec<(String, Option<u16>)>,
+    items: Vec<ImportLibraryItem>,
     output_path: &Path,
 ) {
     let def_file_path = output_path.with_extension("def");
 
     let def_file_content = format!(
         "EXPORTS\n{}",
-        import_name_and_ordinal_vector
+        items
             .into_iter()
-            .map(|(name, ordinal)| {
+            .map(|ImportLibraryItem { name, ordinal, .. }| {
                 match ordinal {
                     Some(n) => format!("{name} @{n} NONAME"),
                     None => name,
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index 44581cfa64b..8f754debaf0 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -45,7 +45,7 @@ use rustc_target::spec::{
 use tempfile::Builder as TempFileBuilder;
 use tracing::{debug, info, warn};
 
-use super::archive::{ArchiveBuilder, ArchiveBuilderBuilder};
+use super::archive::{ArchiveBuilder, ArchiveBuilderBuilder, ImportLibraryItem};
 use super::command::Command;
 use super::linker::{self, Linker};
 use super::metadata::{MetadataPosition, create_wrapper_file};
@@ -495,16 +495,35 @@ fn create_dll_import_libs<'a>(
 
             let mingw_gnu_toolchain = common::is_mingw_gnu_toolchain(&sess.target);
 
-            let import_name_and_ordinal_vector: Vec<(String, Option<u16>)> = raw_dylib_imports
+            let items: Vec<ImportLibraryItem> = raw_dylib_imports
                 .iter()
                 .map(|import: &DllImport| {
                     if sess.target.arch == "x86" {
-                        (
-                            common::i686_decorated_name(import, mingw_gnu_toolchain, false),
-                            import.ordinal(),
-                        )
+                        ImportLibraryItem {
+                            name: common::i686_decorated_name(
+                                import,
+                                mingw_gnu_toolchain,
+                                false,
+                                false,
+                            ),
+                            ordinal: import.ordinal(),
+                            symbol_name: import.is_missing_decorations().then(|| {
+                                common::i686_decorated_name(
+                                    import,
+                                    mingw_gnu_toolchain,
+                                    false,
+                                    true,
+                                )
+                            }),
+                            is_data: !import.is_fn,
+                        }
                     } else {
-                        (import.name.to_string(), import.ordinal())
+                        ImportLibraryItem {
+                            name: import.name.to_string(),
+                            ordinal: import.ordinal(),
+                            symbol_name: None,
+                            is_data: !import.is_fn,
+                        }
                     }
                 })
                 .collect();
@@ -512,7 +531,7 @@ fn create_dll_import_libs<'a>(
             archive_builder_builder.create_dll_import_lib(
                 sess,
                 &raw_dylib_name,
-                import_name_and_ordinal_vector,
+                items,
                 &output_path,
             );
 
diff --git a/compiler/rustc_codegen_ssa/src/common.rs b/compiler/rustc_codegen_ssa/src/common.rs
index 582a2a87e48..965bd34ac14 100644
--- a/compiler/rustc_codegen_ssa/src/common.rs
+++ b/compiler/rustc_codegen_ssa/src/common.rs
@@ -187,12 +187,15 @@ pub fn i686_decorated_name(
     dll_import: &DllImport,
     mingw: bool,
     disable_name_mangling: bool,
+    force_fully_decorated: bool,
 ) -> String {
     let name = dll_import.name.as_str();
 
-    let (add_prefix, add_suffix) = match dll_import.import_name_type {
-        Some(PeImportNameType::NoPrefix) => (false, true),
-        Some(PeImportNameType::Undecorated) => (false, false),
+    let (add_prefix, add_suffix) = match (force_fully_decorated, dll_import.import_name_type) {
+        // No prefix is a bit weird, in that LLVM/ar_archive_writer won't emit it, so we will
+        // ignore `force_fully_decorated` and always partially decorate it.
+        (_, Some(PeImportNameType::NoPrefix)) => (false, true),
+        (false, Some(PeImportNameType::Undecorated)) => (false, false),
         _ => (true, true),
     };