Skip to content

Commit c30c74b

Browse files
committed
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.
1 parent 858a42b commit c30c74b

File tree

6 files changed

+51
-8
lines changed

6 files changed

+51
-8
lines changed

compiler/rustc_codegen_ssa/src/back/metadata.rs

+27
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,33 @@ pub fn create_wrapper_file(
430430
BinaryFormat::Coff => {
431431
file.section_mut(section).flags =
432432
SectionFlags::Coff { characteristics: pe::IMAGE_SCN_LNK_REMOVE };
433+
434+
// Disable mangling to avoid mangling the fixed symbol name for "@feat.00".
435+
// A metadata file has no other symbols, so this is safe.
436+
file.set_mangling(object::write::Mangling::None);
437+
438+
// Add feature flags to the object file. On MSVC this is optional but LLD will complain if
439+
// not present.
440+
let mut feature = 0;
441+
442+
if file.architecture() == Architecture::I386 {
443+
// Indicate that all SEH handlers are registered in .sxdata section.
444+
// We don't have generate any code, so we don't need .sxdata section but LLD still
445+
// expects us to set this bit (see #96498).
446+
// Reference: https://docs.microsoft.com/en-us/windows/win32/debug/pe-format
447+
feature |= 1;
448+
}
449+
450+
file.add_symbol(object::write::Symbol {
451+
name: "@feat.00".into(),
452+
value: feature,
453+
size: 0,
454+
kind: object::SymbolKind::Data,
455+
scope: object::SymbolScope::Compilation,
456+
weak: false,
457+
section: object::write::SymbolSection::Absolute,
458+
flags: object::SymbolFlags::None,
459+
});
433460
}
434461
BinaryFormat::Elf => {
435462
file.section_mut(section).flags =

tests/run-make/issue-96498/Makefile

-8
This file was deleted.
+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# only-windows
2+
# needs-rust-lld
3+
4+
include ../tools.mk
5+
6+
all: foo bar
7+
8+
# Ensure that LLD can link when an .rlib contains a synthetic object
9+
# file referencing exported or used symbols.
10+
foo:
11+
$(RUSTC) -C linker=rust-lld foo.rs
12+
13+
# Ensure that LLD can link when /WHOLEARCHIVE: is used with an .rlib.
14+
# Previously, lib.rmeta was not marked as (trivially) SAFESEH-aware.
15+
bar: baz
16+
$(RUSTC) -C linker=rust-lld -C link-arg=/WHOLEARCHIVE:libbaz.rlib bar.rs
17+
18+
baz:
19+
$(RUSTC) baz.rs

tests/run-make/windows-safeseh/bar.rs

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
fn main() {}

tests/run-make/windows-safeseh/baz.rs

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#![crate_type = "rlib"]
2+
3+
#[no_mangle]
4+
extern "C" fn baz() {}

0 commit comments

Comments
 (0)