Skip to content

Commit bd8e476

Browse files
committed
Avoid a temporary file when processing macOS fat archives
1 parent 047c7cc commit bd8e476

File tree

1 file changed

+34
-36
lines changed

1 file changed

+34
-36
lines changed

compiler/rustc_codegen_ssa/src/back/archive.rs

+34-36
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use tempfile::Builder as TempFileBuilder;
1414

1515
use std::error::Error;
1616
use std::fs::File;
17-
use std::io::{self, Write};
17+
use std::io;
1818
use std::path::{Path, PathBuf};
1919

2020
// Re-exporting for rustc_codegen_llvm::back::archive
@@ -116,51 +116,42 @@ impl<'a> ArArchiveBuilder<'a> {
116116
}
117117
}
118118

119-
fn try_filter_fat_archs(
119+
fn try_filter_fat_archs<'a>(
120120
archs: object::read::Result<&[impl FatArch]>,
121121
target_arch: object::Architecture,
122-
archive_path: &Path,
123-
archive_map_data: &[u8],
124-
) -> io::Result<Option<PathBuf>> {
122+
archive_map_data: &'a [u8],
123+
) -> io::Result<Option<(&'a [u8], u64)>> {
125124
let archs = archs.map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
126125

127126
let desired = match archs.iter().filter(|a| a.architecture() == target_arch).next() {
128127
Some(a) => a,
129128
None => return Ok(None),
130129
};
131130

132-
let (mut new_f, extracted_path) = tempfile::Builder::new()
133-
.suffix(archive_path.file_name().unwrap())
134-
.tempfile()?
135-
.keep()
136-
.unwrap();
137-
138-
new_f.write_all(
131+
Ok(Some((
139132
desired.data(archive_map_data).map_err(|e| io::Error::new(io::ErrorKind::Other, e))?,
140-
)?;
141-
142-
Ok(Some(extracted_path))
133+
desired.offset().into(),
134+
)))
143135
}
144136

145-
pub fn try_extract_macho_fat_archive(
137+
pub fn try_extract_macho_fat_archive<'a>(
146138
sess: &Session,
147-
archive_path: &Path,
148-
) -> io::Result<Option<PathBuf>> {
149-
let archive_map = unsafe { Mmap::map(File::open(&archive_path)?)? };
139+
archive_bytes: &'a [u8],
140+
) -> io::Result<Option<(&'a [u8], u64)>> {
150141
let target_arch = match sess.target.arch.as_ref() {
151142
"aarch64" => object::Architecture::Aarch64,
152143
"x86_64" => object::Architecture::X86_64,
153144
_ => return Ok(None),
154145
};
155146

156-
match object::macho::FatHeader::parse(&*archive_map) {
147+
match object::macho::FatHeader::parse(archive_bytes) {
157148
Ok(h) if h.magic.get(object::endian::BigEndian) == object::macho::FAT_MAGIC => {
158-
let archs = object::macho::FatHeader::parse_arch32(&*archive_map);
159-
try_filter_fat_archs(archs, target_arch, archive_path, &*archive_map)
149+
let archs = object::macho::FatHeader::parse_arch32(archive_bytes);
150+
try_filter_fat_archs(archs, target_arch, archive_bytes)
160151
}
161152
Ok(h) if h.magic.get(object::endian::BigEndian) == object::macho::FAT_MAGIC_64 => {
162-
let archs = object::macho::FatHeader::parse_arch64(&*archive_map);
163-
try_filter_fat_archs(archs, target_arch, archive_path, &*archive_map)
153+
let archs = object::macho::FatHeader::parse_arch64(archive_bytes);
154+
try_filter_fat_archs(archs, target_arch, archive_bytes)
164155
}
165156
// Not a FatHeader at all, just return None.
166157
_ => Ok(None),
@@ -173,21 +164,24 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
173164
archive_path: &Path,
174165
mut skip: Box<dyn FnMut(&str) -> bool + 'static>,
175166
) -> io::Result<()> {
176-
let mut archive_path = archive_path.to_path_buf();
177-
if self.sess.target.llvm_target.contains("-apple-macosx") {
178-
if let Some(new_archive_path) =
179-
try_extract_macho_fat_archive(&self.sess, &archive_path)?
180-
{
181-
archive_path = new_archive_path
182-
}
183-
}
184-
167+
let archive_map = unsafe { Mmap::map(File::open(&archive_path)?)? };
185168
if self.src_archives.iter().any(|archive| archive.0 == archive_path) {
186169
return Ok(());
187170
}
188171

189-
let archive_map = unsafe { Mmap::map(File::open(&archive_path)?)? };
190-
let archive = ArchiveFile::parse(&*archive_map)
172+
let (archive_bytes, offset) = if self.sess.target.llvm_target.contains("-apple-macosx") {
173+
if let Some((sub_archive, archive_offset)) =
174+
try_extract_macho_fat_archive(&self.sess, &*archive_map)?
175+
{
176+
(sub_archive, Some(archive_offset))
177+
} else {
178+
(&*archive_map, None)
179+
}
180+
} else {
181+
(&*archive_map, None)
182+
};
183+
184+
let archive = ArchiveFile::parse(&*archive_bytes)
191185
.map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?;
192186
let archive_index = self.src_archives.len();
193187

@@ -196,9 +190,13 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
196190
let file_name = String::from_utf8(entry.name().to_vec())
197191
.map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?;
198192
if !skip(&file_name) {
193+
let mut range = entry.file_range();
194+
if let Some(offset) = offset {
195+
range.0 += offset;
196+
}
199197
self.entries.push((
200198
file_name.into_bytes(),
201-
ArchiveEntry::FromArchive { archive_index, file_range: entry.file_range() },
199+
ArchiveEntry::FromArchive { archive_index, file_range: range },
202200
));
203201
}
204202
}

0 commit comments

Comments
 (0)