Auto merge of #105221 - alex:fat-archive-cleanup, r=bjorn3

Avoid a temporary file when processing macOS fat archives

r? `@bjorn3`
This commit is contained in:
bors 2022-12-14 06:51:50 +00:00
commit dc30b92cc5
2 changed files with 38 additions and 46 deletions

View File

@ -15,8 +15,8 @@
use crate::llvm::archive_ro::{ArchiveRO, Child}; use crate::llvm::archive_ro::{ArchiveRO, Child};
use crate::llvm::{self, ArchiveKind, LLVMMachineType, LLVMRustCOFFShortExport}; use crate::llvm::{self, ArchiveKind, LLVMMachineType, LLVMRustCOFFShortExport};
use rustc_codegen_ssa::back::archive::{ use rustc_codegen_ssa::back::archive::{
get_native_object_symbols, try_extract_macho_fat_archive, ArArchiveBuilder, get_native_object_symbols, ArArchiveBuilder, ArchiveBuildFailure, ArchiveBuilder,
ArchiveBuildFailure, ArchiveBuilder, ArchiveBuilderBuilder, UnknownArchiveKind, ArchiveBuilderBuilder, UnknownArchiveKind,
}; };
use rustc_session::cstore::DllImport; use rustc_session::cstore::DllImport;
@ -66,13 +66,7 @@ fn add_archive(
archive: &Path, archive: &Path,
skip: Box<dyn FnMut(&str) -> bool + 'static>, skip: Box<dyn FnMut(&str) -> bool + 'static>,
) -> io::Result<()> { ) -> io::Result<()> {
let mut archive = archive.to_path_buf(); let archive_ro = match ArchiveRO::open(archive) {
if self.sess.target.llvm_target.contains("-apple-macosx") {
if let Some(new_archive) = try_extract_macho_fat_archive(&self.sess, &archive)? {
archive = new_archive
}
}
let archive_ro = match ArchiveRO::open(&archive) {
Ok(ar) => ar, Ok(ar) => ar,
Err(e) => return Err(io::Error::new(io::ErrorKind::Other, e)), Err(e) => return Err(io::Error::new(io::ErrorKind::Other, e)),
}; };
@ -80,7 +74,7 @@ fn add_archive(
return Ok(()); return Ok(());
} }
self.additions.push(Addition::Archive { self.additions.push(Addition::Archive {
path: archive, path: archive.to_path_buf(),
archive: archive_ro, archive: archive_ro,
skip: Box::new(skip), skip: Box::new(skip),
}); });

View File

@ -14,7 +14,7 @@
use std::error::Error; use std::error::Error;
use std::fs::File; use std::fs::File;
use std::io::{self, Write}; use std::io;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
// Re-exporting for rustc_codegen_llvm::back::archive // Re-exporting for rustc_codegen_llvm::back::archive
@ -116,12 +116,11 @@ pub fn new(
} }
} }
fn try_filter_fat_archs( fn try_filter_fat_archs<'a>(
archs: object::read::Result<&[impl FatArch]>, archs: object::read::Result<&[impl FatArch]>,
target_arch: object::Architecture, target_arch: object::Architecture,
archive_path: &Path, archive_map_data: &'a [u8],
archive_map_data: &[u8], ) -> io::Result<Option<(&'a [u8], u64)>> {
) -> io::Result<Option<PathBuf>> {
let archs = archs.map_err(|e| io::Error::new(io::ErrorKind::Other, e))?; 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() { 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), None => return Ok(None),
}; };
let (mut new_f, extracted_path) = tempfile::Builder::new() Ok(Some((
.suffix(archive_path.file_name().unwrap())
.tempfile()?
.keep()
.unwrap();
new_f.write_all(
desired.data(archive_map_data).map_err(|e| io::Error::new(io::ErrorKind::Other, e))?, desired.data(archive_map_data).map_err(|e| io::Error::new(io::ErrorKind::Other, e))?,
)?; desired.offset().into(),
)))
Ok(Some(extracted_path))
} }
pub fn try_extract_macho_fat_archive( pub fn try_extract_macho_fat_archive<'a>(
sess: &Session, sess: &Session,
archive_path: &Path, archive_bytes: &'a [u8],
) -> io::Result<Option<PathBuf>> { ) -> io::Result<Option<(&'a [u8], u64)>> {
let archive_map = unsafe { Mmap::map(File::open(&archive_path)?)? };
let target_arch = match sess.target.arch.as_ref() { let target_arch = match sess.target.arch.as_ref() {
"aarch64" => object::Architecture::Aarch64, "aarch64" => object::Architecture::Aarch64,
"x86_64" => object::Architecture::X86_64, "x86_64" => object::Architecture::X86_64,
_ => return Ok(None), _ => 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 => { Ok(h) if h.magic.get(object::endian::BigEndian) == object::macho::FAT_MAGIC => {
let archs = object::macho::FatHeader::parse_arch32(&*archive_map); let archs = object::macho::FatHeader::parse_arch32(archive_bytes);
try_filter_fat_archs(archs, target_arch, archive_path, &*archive_map) try_filter_fat_archs(archs, target_arch, archive_bytes)
} }
Ok(h) if h.magic.get(object::endian::BigEndian) == object::macho::FAT_MAGIC_64 => { Ok(h) if h.magic.get(object::endian::BigEndian) == object::macho::FAT_MAGIC_64 => {
let archs = object::macho::FatHeader::parse_arch64(&*archive_map); let archs = object::macho::FatHeader::parse_arch64(archive_bytes);
try_filter_fat_archs(archs, target_arch, archive_path, &*archive_map) try_filter_fat_archs(archs, target_arch, archive_bytes)
} }
// Not a FatHeader at all, just return None. // Not a FatHeader at all, just return None.
_ => Ok(None), _ => Ok(None),
@ -173,21 +164,24 @@ fn add_archive(
archive_path: &Path, archive_path: &Path,
mut skip: Box<dyn FnMut(&str) -> bool + 'static>, mut skip: Box<dyn FnMut(&str) -> bool + 'static>,
) -> io::Result<()> { ) -> io::Result<()> {
let mut archive_path = archive_path.to_path_buf(); let archive_map = unsafe { Mmap::map(File::open(&archive_path)?)? };
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
}
}
if self.src_archives.iter().any(|archive| archive.0 == archive_path) { if self.src_archives.iter().any(|archive| archive.0 == archive_path) {
return Ok(()); return Ok(());
} }
let archive_map = unsafe { Mmap::map(File::open(&archive_path)?)? }; let (archive_bytes, offset) = if self.sess.target.llvm_target.contains("-apple-macosx") {
let archive = ArchiveFile::parse(&*archive_map) 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))?; .map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?;
let archive_index = self.src_archives.len(); let archive_index = self.src_archives.len();
@ -196,9 +190,13 @@ fn add_archive(
let file_name = String::from_utf8(entry.name().to_vec()) let file_name = String::from_utf8(entry.name().to_vec())
.map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?; .map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?;
if !skip(&file_name) { if !skip(&file_name) {
let mut range = entry.file_range();
if let Some(offset) = offset {
range.0 += offset;
}
self.entries.push(( self.entries.push((
file_name.into_bytes(), file_name.into_bytes(),
ArchiveEntry::FromArchive { archive_index, file_range: entry.file_range() }, ArchiveEntry::FromArchive { archive_index, file_range: range },
)); ));
} }
} }