-
Notifications
You must be signed in to change notification settings - Fork 37
Fix linking on i686 MSVC when using bare linkers #242
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -181,6 +181,44 @@ fn create_object_file( | |
| abi_version, | ||
| e_flags, | ||
| }; | ||
|
|
||
| // Add the COFF `@feat.00` symbol used to communicate linker feature flags. | ||
| // | ||
| // When linking with /SAFESEH on x86, lld requires that all linker inputs be marked as safe | ||
| // exception handling compatible. Our metadata objects masquerade as regular COFF objects and | ||
| // are treated as linker inputs, so they need the flag too. | ||
| // | ||
| // This implementation mirrors the rustc's metadata object generation: | ||
| // <https://github.com/rust-lang/rust/blob/b90dc1e597db0bbc0cab0eccb39747b1a9d7e607/compiler/rustc_codegen_ssa/src/back/metadata.rs#L224-L252> | ||
| // | ||
| // See also: | ||
| // | ||
| // - <https://github.com/rust-lang/rust/issues/96498> | ||
| // - <https://learn.microsoft.com/en-us/windows/win32/debug/pe-format> | ||
| if binary_format == BinaryFormat::Coff { | ||
| // Disable mangling so the "@feat.00" symbol name is written verbatim. | ||
| // CoffI386 mangling adds a `_` prefix which would break this special symbol. | ||
| let original_mangling = file.mangling(); | ||
| file.set_mangling(write::Mangling::None); | ||
|
|
||
| let mut feature: u64 = 0; | ||
| if architecture == Architecture::I386 { | ||
| feature |= 1; // IMAGE_FILE_SAFE_EXCEPTION_HANDLER | ||
| } | ||
| file.add_symbol(Symbol { | ||
| name: b"@feat.00".to_vec(), | ||
| value: feature, | ||
| size: 0, | ||
| kind: SymbolKind::Data, | ||
| scope: SymbolScope::Compilation, | ||
| weak: false, | ||
| section: SymbolSection::Absolute, | ||
| flags: SymbolFlags::None, | ||
| }); | ||
|
Comment on lines
+204
to
+217
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't really know much about the implications of some fields, such as the
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Indeed the relevant reference is https://github.com/rust-lang/rust/blob/b90dc1e597db0bbc0cab0eccb39747b1a9d7e607/compiler/rustc_codegen_ssa/src/back/metadata.rs#L224-L252 I'll add a link in a comment. |
||
|
|
||
| file.set_mangling(original_mangling); | ||
| } | ||
|
|
||
| Some(file) | ||
| } | ||
|
|
||
|
|
@@ -344,6 +382,65 @@ windows | |
| assert_eq!(result.architecture(), Architecture::I386); | ||
| } | ||
|
|
||
| /// Verify that i686 COFF metadata objects contain an absolute `@feat.00` symbol with | ||
| /// `IMAGE_FILE_SAFE_EXCEPTION_HANDLER` (bit 0) set. | ||
| /// | ||
| /// See <https://github.com/rust-lang/rust/issues/96498> | ||
| #[test] | ||
| fn test_create_metadata_file_windows_msvc_i686_has_feat00() { | ||
| let rustc_output = br#"debug_assertions | ||
| target_arch="x86" | ||
| target_endian="little" | ||
| target_env="msvc" | ||
| target_family="windows" | ||
| target_feature="fxsr" | ||
| target_feature="sse" | ||
| target_feature="sse2" | ||
| target_os="windows" | ||
| target_pointer_width="32" | ||
| target_vendor="pc" | ||
| windows | ||
| "#; | ||
| let target_triple = "i686-pc-windows-msvc"; | ||
| let target_info = parse_rustc_target_info(rustc_output); | ||
| let contents = b"test audit data"; | ||
| let result = create_metadata_file( | ||
| &target_info, | ||
| target_triple, | ||
| contents, | ||
| "AUDITABLE_VERSION_INFO", | ||
| ) | ||
| .expect("should produce an object file for i686-pc-windows-msvc"); | ||
|
|
||
| // Parse the COFF symbol table and verify `@feat.00` has value bit0=1 and absolute section. | ||
| let symtab_ptr = u32::from_le_bytes(result[8..12].try_into().unwrap()) as usize; | ||
| let sym_count = u32::from_le_bytes(result[12..16].try_into().unwrap()) as usize; | ||
| let symbol_size = 18; | ||
|
|
||
| let feat = (0..sym_count).find_map(|i| { | ||
| let start = symtab_ptr + i * symbol_size; | ||
| let end = start + symbol_size; | ||
| let entry = result.get(start..end)?; | ||
| if &entry[0..8] != b"@feat.00" { | ||
| return None; | ||
| } | ||
| let value = u32::from_le_bytes(entry[8..12].try_into().unwrap()); | ||
| let section_number = i16::from_le_bytes(entry[12..14].try_into().unwrap()); | ||
| Some((value, section_number)) | ||
| }); | ||
|
|
||
| let (value, section_number) = feat.expect("COFF object for i686 must contain @feat.00"); | ||
| assert_eq!( | ||
| value & 1, | ||
| 1, | ||
| "@feat.00 must set IMAGE_FILE_SAFE_EXCEPTION_HANDLER on i686" | ||
| ); | ||
| assert_eq!( | ||
| section_number, -1, | ||
| "@feat.00 must be an absolute COFF symbol (section number -1)" | ||
| ); | ||
| } | ||
|
|
||
| #[test] | ||
| fn test_create_object_file_windows_gnu() { | ||
| let rustc_output = br#"debug_assertions | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.