From bd8e476d8bd85b6d60a0de7694d154b4a74f5133 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sat, 3 Dec 2022 13:46:14 -0500 Subject: [PATCH] Avoid a temporary file when processing macOS fat archives --- .../rustc_codegen_ssa/src/back/archive.rs | 70 +++++++++---------- 1 file changed, 34 insertions(+), 36 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/archive.rs b/compiler/rustc_codegen_ssa/src/back/archive.rs index 58558fb8c4ba2..5266d8858d47d 100644 --- a/compiler/rustc_codegen_ssa/src/back/archive.rs +++ b/compiler/rustc_codegen_ssa/src/back/archive.rs @@ -14,7 +14,7 @@ use tempfile::Builder as TempFileBuilder; use std::error::Error; use std::fs::File; -use std::io::{self, Write}; +use std::io; use std::path::{Path, PathBuf}; // Re-exporting for rustc_codegen_llvm::back::archive @@ -116,12 +116,11 @@ impl<'a> ArArchiveBuilder<'a> { } } -fn try_filter_fat_archs( +fn try_filter_fat_archs<'a>( archs: object::read::Result<&[impl FatArch]>, target_arch: object::Architecture, - archive_path: &Path, - archive_map_data: &[u8], -) -> io::Result> { + archive_map_data: &'a [u8], +) -> io::Result> { let archs = archs.map_err(|e| io::Error::new(io::ErrorKind::Other, e))?; let desired = match archs.iter().filter(|a| a.architecture() == target_arch).next() { @@ -129,38 +128,30 @@ fn try_filter_fat_archs( None => return Ok(None), }; - let (mut new_f, extracted_path) = tempfile::Builder::new() - .suffix(archive_path.file_name().unwrap()) - .tempfile()? - .keep() - .unwrap(); - - new_f.write_all( + Ok(Some(( desired.data(archive_map_data).map_err(|e| io::Error::new(io::ErrorKind::Other, e))?, - )?; - - Ok(Some(extracted_path)) + desired.offset().into(), + ))) } -pub fn try_extract_macho_fat_archive( +pub fn try_extract_macho_fat_archive<'a>( sess: &Session, - archive_path: &Path, -) -> io::Result> { - let archive_map = unsafe { Mmap::map(File::open(&archive_path)?)? }; + archive_bytes: &'a [u8], +) -> io::Result> { let target_arch = match sess.target.arch.as_ref() { "aarch64" => object::Architecture::Aarch64, "x86_64" => object::Architecture::X86_64, _ => return Ok(None), }; - match object::macho::FatHeader::parse(&*archive_map) { + match object::macho::FatHeader::parse(archive_bytes) { Ok(h) if h.magic.get(object::endian::BigEndian) == object::macho::FAT_MAGIC => { - let archs = object::macho::FatHeader::parse_arch32(&*archive_map); - try_filter_fat_archs(archs, target_arch, archive_path, &*archive_map) + let archs = object::macho::FatHeader::parse_arch32(archive_bytes); + try_filter_fat_archs(archs, target_arch, archive_bytes) } Ok(h) if h.magic.get(object::endian::BigEndian) == object::macho::FAT_MAGIC_64 => { - let archs = object::macho::FatHeader::parse_arch64(&*archive_map); - try_filter_fat_archs(archs, target_arch, archive_path, &*archive_map) + let archs = object::macho::FatHeader::parse_arch64(archive_bytes); + try_filter_fat_archs(archs, target_arch, archive_bytes) } // Not a FatHeader at all, just return None. _ => Ok(None), @@ -173,21 +164,24 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> { archive_path: &Path, mut skip: Box bool + 'static>, ) -> io::Result<()> { - let mut archive_path = archive_path.to_path_buf(); - if self.sess.target.llvm_target.contains("-apple-macosx") { - if let Some(new_archive_path) = - try_extract_macho_fat_archive(&self.sess, &archive_path)? - { - archive_path = new_archive_path - } - } - + let archive_map = unsafe { Mmap::map(File::open(&archive_path)?)? }; if self.src_archives.iter().any(|archive| archive.0 == archive_path) { return Ok(()); } - let archive_map = unsafe { Mmap::map(File::open(&archive_path)?)? }; - let archive = ArchiveFile::parse(&*archive_map) + let (archive_bytes, offset) = if self.sess.target.llvm_target.contains("-apple-macosx") { + if let Some((sub_archive, archive_offset)) = + try_extract_macho_fat_archive(&self.sess, &*archive_map)? + { + (sub_archive, Some(archive_offset)) + } else { + (&*archive_map, None) + } + } else { + (&*archive_map, None) + }; + + let archive = ArchiveFile::parse(&*archive_bytes) .map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?; let archive_index = self.src_archives.len(); @@ -196,9 +190,13 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> { let file_name = String::from_utf8(entry.name().to_vec()) .map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?; if !skip(&file_name) { + let mut range = entry.file_range(); + if let Some(offset) = offset { + range.0 += offset; + } self.entries.push(( file_name.into_bytes(), - ArchiveEntry::FromArchive { archive_index, file_range: entry.file_range() }, + ArchiveEntry::FromArchive { archive_index, file_range: range }, )); } }