Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mark .rmeta files as /SAFESEH on x86 Windows. #117115

Merged
merged 1 commit into from
Oct 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 2 additions & 25 deletions compiler/rustc_codegen_ssa/src/back/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down
29 changes: 29 additions & 0 deletions compiler/rustc_codegen_ssa/src/back/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
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() {}
Loading