about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_codegen_ssa/src/back/link.rs27
-rw-r--r--compiler/rustc_codegen_ssa/src/back/metadata.rs29
-rw-r--r--tests/run-make/issue-96498/Makefile8
-rw-r--r--tests/run-make/windows-safeseh/Makefile19
-rw-r--r--tests/run-make/windows-safeseh/bar.rs1
-rw-r--r--tests/run-make/windows-safeseh/baz.rs4
-rw-r--r--tests/run-make/windows-safeseh/foo.rs (renamed from tests/run-make/issue-96498/foo.rs)0
7 files changed, 55 insertions, 33 deletions
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index f16fe372a92..c0f6e7cb7b0 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -1889,37 +1889,14 @@ fn add_linked_symbol_object(
         return;
     };
 
-    // NOTE(nbdd0121): MSVC will hang if the input object file contains no sections,
-    // so add an empty section.
     if file.format() == object::BinaryFormat::Coff {
+        // NOTE(nbdd0121): MSVC will hang if the input object file contains no sections,
+        // so add an empty section.
         file.add_section(Vec::new(), ".text".into(), object::SectionKind::Text);
 
         // We handle the name decoration of COFF targets in `symbol_export.rs`, so disable the
         // default mangler in `object` crate.
         file.set_mangling(object::write::Mangling::None);
-
-        // Add feature flags to the object file. On MSVC this is optional but LLD will complain if
-        // not present.
-        let mut feature = 0;
-
-        if file.architecture() == object::Architecture::I386 {
-            // Indicate that all SEH handlers are registered in .sxdata section.
-            // We don't have generate any code, so we don't need .sxdata section but LLD still
-            // expects us to set this bit (see #96498).
-            // Reference: https://docs.microsoft.com/en-us/windows/win32/debug/pe-format
-            feature |= 1;
-        }
-
-        file.add_symbol(object::write::Symbol {
-            name: "@feat.00".into(),
-            value: feature,
-            size: 0,
-            kind: object::SymbolKind::Data,
-            scope: object::SymbolScope::Compilation,
-            weak: false,
-            section: object::write::SymbolSection::Absolute,
-            flags: object::SymbolFlags::None,
-        });
     }
 
     for (sym, kind) in symbols.iter() {
diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs
index c6f4bd35e29..cb60ed729c1 100644
--- a/compiler/rustc_codegen_ssa/src/back/metadata.rs
+++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs
@@ -228,6 +228,35 @@ pub(crate) fn create_object_file(sess: &Session) -> Option<write::Object<'static
     if sess.target.is_like_osx {
         file.set_macho_build_version(macho_object_build_version_for_target(&sess.target))
     }
+    if binary_format == BinaryFormat::Coff {
+        // Disable the default mangler to avoid mangling the special "@feat.00" symbol name.
+        let original_mangling = file.mangling();
+        file.set_mangling(object::write::Mangling::None);
+
+        let mut feature = 0;
+
+        if file.architecture() == object::Architecture::I386 {
+            // When linking with /SAFESEH on x86, lld requires that all linker inputs be marked as
+            // safe exception handling compatible. Metadata files masquerade as regular COFF
+            // objects and are treated as linker inputs, despite containing no actual code. Thus,
+            // they still need to be marked as safe exception handling compatible. See #96498.
+            // Reference: https://docs.microsoft.com/en-us/windows/win32/debug/pe-format
+            feature |= 1;
+        }
+
+        file.add_symbol(object::write::Symbol {
+            name: "@feat.00".into(),
+            value: feature,
+            size: 0,
+            kind: object::SymbolKind::Data,
+            scope: object::SymbolScope::Compilation,
+            weak: false,
+            section: object::write::SymbolSection::Absolute,
+            flags: object::SymbolFlags::None,
+        });
+
+        file.set_mangling(original_mangling);
+    }
     let e_flags = match architecture {
         Architecture::Mips => {
             let arch = match sess.target.options.cpu.as_ref() {
diff --git a/tests/run-make/issue-96498/Makefile b/tests/run-make/issue-96498/Makefile
deleted file mode 100644
index efdd328c671..00000000000
--- a/tests/run-make/issue-96498/Makefile
+++ /dev/null
@@ -1,8 +0,0 @@
-# only-windows
-# needs-rust-lld
-
-include ../tools.mk
-
-# Ensure that LLD can link
-all:
-	$(RUSTC) -C linker=rust-lld foo.rs
diff --git a/tests/run-make/windows-safeseh/Makefile b/tests/run-make/windows-safeseh/Makefile
new file mode 100644
index 00000000000..d6a403961d7
--- /dev/null
+++ b/tests/run-make/windows-safeseh/Makefile
@@ -0,0 +1,19 @@
+# only-windows
+# needs-rust-lld
+
+include ../tools.mk
+
+all: foo bar
+
+# Ensure that LLD can link when an .rlib contains a synthetic object
+# file referencing exported or used symbols.
+foo:
+	$(RUSTC) -C linker=rust-lld foo.rs
+
+# Ensure that LLD can link when /WHOLEARCHIVE: is used with an .rlib.
+# Previously, lib.rmeta was not marked as (trivially) SAFESEH-aware.
+bar: baz
+	$(RUSTC) -C linker=rust-lld -C link-arg=/WHOLEARCHIVE:libbaz.rlib bar.rs
+
+baz:
+	$(RUSTC) baz.rs
diff --git a/tests/run-make/windows-safeseh/bar.rs b/tests/run-make/windows-safeseh/bar.rs
new file mode 100644
index 00000000000..f328e4d9d04
--- /dev/null
+++ b/tests/run-make/windows-safeseh/bar.rs
@@ -0,0 +1 @@
+fn main() {}
diff --git a/tests/run-make/windows-safeseh/baz.rs b/tests/run-make/windows-safeseh/baz.rs
new file mode 100644
index 00000000000..8d5b9dc5aea
--- /dev/null
+++ b/tests/run-make/windows-safeseh/baz.rs
@@ -0,0 +1,4 @@
+#![crate_type = "rlib"]
+
+#[no_mangle]
+extern "C" fn baz() {}
diff --git a/tests/run-make/issue-96498/foo.rs b/tests/run-make/windows-safeseh/foo.rs
index 93ac3641b09..93ac3641b09 100644
--- a/tests/run-make/issue-96498/foo.rs
+++ b/tests/run-make/windows-safeseh/foo.rs