From 8fa800db61a78a6b7467ac2867ff20fc717a00be Mon Sep 17 00:00:00 2001 From: Daniel Cheng Date: Mon, 23 Oct 2023 19:59:36 -0700 Subject: [PATCH] Mark .rmeta files as /SAFESEH on x86 Windows. Chrome links .rlibs with /WHOLEARCHIVE or -Wl,--whole-archive to prevent the linker from discarding static initializers. This works well, except on Windows x86, where lld complains: error: /safeseh: lib.rmeta is not compatible with SEH The fix is simply to mark the .rmeta as SAFESEH aware. This is trivially true, since the metadata file does not contain any executable code. --- compiler/rustc_codegen_ssa/src/back/link.rs | 27 ++--------------- .../rustc_codegen_ssa/src/back/metadata.rs | 29 +++++++++++++++++++ tests/run-make/issue-96498/Makefile | 8 ----- tests/run-make/windows-safeseh/Makefile | 19 ++++++++++++ tests/run-make/windows-safeseh/bar.rs | 1 + tests/run-make/windows-safeseh/baz.rs | 4 +++ .../{issue-96498 => windows-safeseh}/foo.rs | 0 7 files changed, 55 insertions(+), 33 deletions(-) delete mode 100644 tests/run-make/issue-96498/Makefile create mode 100644 tests/run-make/windows-safeseh/Makefile create mode 100644 tests/run-make/windows-safeseh/bar.rs create mode 100644 tests/run-make/windows-safeseh/baz.rs rename tests/run-make/{issue-96498 => windows-safeseh}/foo.rs (100%) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index f16fe372a92c9..c0f6e7cb7b0b3 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 c6f4bd35e293f..cb60ed729c1bf 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 { 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 efdd328c671ed..0000000000000 --- 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 0000000000000..d6a403961d791 --- /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 0000000000000..f328e4d9d04c3 --- /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 0000000000000..8d5b9dc5aeafc --- /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 similarity index 100% rename from tests/run-make/issue-96498/foo.rs rename to tests/run-make/windows-safeseh/foo.rs