Skip to content

Commit

Permalink
Mark .rmeta files as /SAFESEH on x86 Windows.
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
zetafunction committed Oct 24, 2023
1 parent 858a42b commit c30c74b
Show file tree
Hide file tree
Showing 6 changed files with 51 additions and 8 deletions.
27 changes: 27 additions & 0 deletions compiler/rustc_codegen_ssa/src/back/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,33 @@ pub fn create_wrapper_file(
BinaryFormat::Coff => {
file.section_mut(section).flags =
SectionFlags::Coff { characteristics: pe::IMAGE_SCN_LNK_REMOVE };

// Disable mangling to avoid mangling the fixed symbol name for "@feat.00".
// A metadata file has no other symbols, so this is safe.
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() == 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,
});
}
BinaryFormat::Elf => {
file.section_mut(section).flags =
Expand Down
8 changes: 0 additions & 8 deletions tests/run-make/issue-96498/Makefile

This file was deleted.

19 changes: 19 additions & 0 deletions tests/run-make/windows-safeseh/Makefile
Original file line number Diff line number Diff line change
@@ -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
1 change: 1 addition & 0 deletions tests/run-make/windows-safeseh/bar.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
fn main() {}
4 changes: 4 additions & 0 deletions tests/run-make/windows-safeseh/baz.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#![crate_type = "rlib"]

#[no_mangle]
extern "C" fn baz() {}
File renamed without changes.

0 comments on commit c30c74b

Please sign in to comment.