diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-18 02:49:42 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-18 02:49:42 +0000 |
commit | 837b550238aa671a591ccf282dddeab29cadb206 (patch) | |
tree | 914b6b8862bace72bd3245ca184d374b08d8a672 /compiler/rustc_codegen_ssa/src/back/metadata.rs | |
parent | Adding debian version 1.70.0+dfsg2-1. (diff) | |
download | rustc-837b550238aa671a591ccf282dddeab29cadb206.tar.xz rustc-837b550238aa671a591ccf282dddeab29cadb206.zip |
Merging upstream version 1.71.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_codegen_ssa/src/back/metadata.rs')
-rw-r--r-- | compiler/rustc_codegen_ssa/src/back/metadata.rs | 91 |
1 files changed, 86 insertions, 5 deletions
diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs index d5d843702..ad27b854d 100644 --- a/compiler/rustc_codegen_ssa/src/back/metadata.rs +++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs @@ -12,9 +12,9 @@ use object::{ use snap::write::FrameEncoder; +use object::elf::NT_GNU_PROPERTY_TYPE_0; use rustc_data_structures::memmap::Mmap; -use rustc_data_structures::owned_slice::try_slice_owned; -use rustc_data_structures::sync::MetadataRef; +use rustc_data_structures::owned_slice::{try_slice_owned, OwnedSlice}; use rustc_metadata::fs::METADATA_FILENAME; use rustc_metadata::EncodedMetadata; use rustc_session::cstore::MetadataLoader; @@ -38,7 +38,7 @@ pub struct DefaultMetadataLoader; fn load_metadata_with( path: &Path, f: impl for<'a> FnOnce(&'a [u8]) -> Result<&'a [u8], String>, -) -> Result<MetadataRef, String> { +) -> Result<OwnedSlice, String> { let file = File::open(path).map_err(|e| format!("failed to open file '{}': {}", path.display(), e))?; @@ -48,7 +48,7 @@ fn load_metadata_with( } impl MetadataLoader for DefaultMetadataLoader { - fn get_rlib_metadata(&self, _target: &Target, path: &Path) -> Result<MetadataRef, String> { + fn get_rlib_metadata(&self, _target: &Target, path: &Path) -> Result<OwnedSlice, String> { load_metadata_with(path, |data| { let archive = object::read::archive::ArchiveFile::parse(&*data) .map_err(|e| format!("failed to parse rlib '{}': {}", path.display(), e))?; @@ -68,7 +68,7 @@ impl MetadataLoader for DefaultMetadataLoader { }) } - fn get_dylib_metadata(&self, _target: &Target, path: &Path) -> Result<MetadataRef, String> { + fn get_dylib_metadata(&self, _target: &Target, path: &Path) -> Result<OwnedSlice, String> { load_metadata_with(path, |data| search_for_section(path, data, ".rustc")) } } @@ -93,6 +93,54 @@ pub(super) fn search_for_section<'a>( .map_err(|e| format!("failed to read {} section in '{}': {}", section, path.display(), e)) } +fn add_gnu_property_note( + file: &mut write::Object<'static>, + architecture: Architecture, + binary_format: BinaryFormat, + endianness: Endianness, +) { + // check bti protection + if binary_format != BinaryFormat::Elf + || !matches!(architecture, Architecture::X86_64 | Architecture::Aarch64) + { + return; + } + + let section = file.add_section( + file.segment_name(StandardSegment::Data).to_vec(), + b".note.gnu.property".to_vec(), + SectionKind::Note, + ); + let mut data: Vec<u8> = Vec::new(); + let n_namsz: u32 = 4; // Size of the n_name field + let n_descsz: u32 = 16; // Size of the n_desc field + let n_type: u32 = NT_GNU_PROPERTY_TYPE_0; // Type of note descriptor + let header_values = [n_namsz, n_descsz, n_type]; + header_values.iter().for_each(|v| { + data.extend_from_slice(&match endianness { + Endianness::Little => v.to_le_bytes(), + Endianness::Big => v.to_be_bytes(), + }) + }); + data.extend_from_slice(b"GNU\0"); // Owner of the program property note + let pr_type: u32 = match architecture { + Architecture::X86_64 => 0xc0000002, + Architecture::Aarch64 => 0xc0000000, + _ => unreachable!(), + }; + let pr_datasz: u32 = 4; //size of the pr_data field + let pr_data: u32 = 3; //program property descriptor + let pr_padding: u32 = 0; + let property_values = [pr_type, pr_datasz, pr_data, pr_padding]; + property_values.iter().for_each(|v| { + data.extend_from_slice(&match endianness { + Endianness::Little => v.to_le_bytes(), + Endianness::Big => v.to_be_bytes(), + }) + }); + file.append_section_data(section, &data, 8); +} + pub(crate) fn create_object_file(sess: &Session) -> Option<write::Object<'static>> { let endianness = match sess.target.options.endian { Endian::Little => Endianness::Little, @@ -140,6 +188,11 @@ pub(crate) fn create_object_file(sess: &Session) -> Option<write::Object<'static }; let mut file = write::Object::new(binary_format, architecture, endianness); + if sess.target.is_like_osx { + if let Some(build_version) = macho_object_build_version_for_target(&sess.target) { + file.set_macho_build_version(build_version) + } + } let e_flags = match architecture { Architecture::Mips => { let arch = match sess.target.options.cpu.as_ref() { @@ -205,10 +258,38 @@ pub(crate) fn create_object_file(sess: &Session) -> Option<write::Object<'static _ => elf::ELFOSABI_NONE, }; let abi_version = 0; + add_gnu_property_note(&mut file, architecture, binary_format, endianness); file.flags = FileFlags::Elf { os_abi, abi_version, e_flags }; Some(file) } +/// Apple's LD, when linking for Mac Catalyst, requires object files to +/// contain information about what they were built for (LC_BUILD_VERSION): +/// the platform (macOS/watchOS etc), minimum OS version, and SDK version. +/// This returns a `MachOBuildVersion` if necessary for the target. +fn macho_object_build_version_for_target( + target: &Target, +) -> Option<object::write::MachOBuildVersion> { + if !target.llvm_target.ends_with("-macabi") { + return None; + } + /// The `object` crate demands "X.Y.Z encoded in nibbles as xxxx.yy.zz" + /// e.g. minOS 14.0 = 0x000E0000, or SDK 16.2 = 0x00100200 + fn pack_version((major, minor): (u32, u32)) -> u32 { + (major << 16) | (minor << 8) + } + + let platform = object::macho::PLATFORM_MACCATALYST; + let min_os = (14, 0); + let sdk = (16, 2); + + let mut build_version = object::write::MachOBuildVersion::default(); + build_version.platform = platform; + build_version.minos = pack_version(min_os); + build_version.sdk = pack_version(sdk); + Some(build_version) +} + pub enum MetadataPosition { First, Last, |