Skip to content

Commit 2527416

Browse files
committed
Auto merge of #107360 - bjorn3:fix_thin_archive_reading, r=wesleywiser
Fix thin archive reading This includes a revert of #105221 to restore fat archive reading with LlvmArchiveBuilder. Should fix #107162, #107334 and google/shaderc-rs#133
2 parents 6cd6bad + de363d5 commit 2527416

File tree

2 files changed

+49
-39
lines changed

2 files changed

+49
-39
lines changed

compiler/rustc_codegen_llvm/src/back/archive.rs

+13-5
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ use crate::errors::{
1515
use crate::llvm::archive_ro::{ArchiveRO, Child};
1616
use crate::llvm::{self, ArchiveKind, LLVMMachineType, LLVMRustCOFFShortExport};
1717
use rustc_codegen_ssa::back::archive::{
18-
get_native_object_symbols, ArArchiveBuilder, ArchiveBuildFailure, ArchiveBuilder,
19-
ArchiveBuilderBuilder, UnknownArchiveKind,
18+
get_native_object_symbols, try_extract_macho_fat_archive, ArArchiveBuilder,
19+
ArchiveBuildFailure, ArchiveBuilder, ArchiveBuilderBuilder, UnknownArchiveKind,
2020
};
2121

2222
use rustc_session::cstore::DllImport;
@@ -66,15 +66,21 @@ impl<'a> ArchiveBuilder<'a> for LlvmArchiveBuilder<'a> {
6666
archive: &Path,
6767
skip: Box<dyn FnMut(&str) -> bool + 'static>,
6868
) -> io::Result<()> {
69-
let archive_ro = match ArchiveRO::open(archive) {
69+
let mut archive = archive.to_path_buf();
70+
if self.sess.target.llvm_target.contains("-apple-macosx") {
71+
if let Some(new_archive) = try_extract_macho_fat_archive(&self.sess, &archive)? {
72+
archive = new_archive
73+
}
74+
}
75+
let archive_ro = match ArchiveRO::open(&archive) {
7076
Ok(ar) => ar,
7177
Err(e) => return Err(io::Error::new(io::ErrorKind::Other, e)),
7278
};
7379
if self.additions.iter().any(|ar| ar.path() == archive) {
7480
return Ok(());
7581
}
7682
self.additions.push(Addition::Archive {
77-
path: archive.to_path_buf(),
83+
path: archive,
7884
archive: archive_ro,
7985
skip: Box::new(skip),
8086
});
@@ -102,7 +108,9 @@ pub struct LlvmArchiveBuilderBuilder;
102108

103109
impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder {
104110
fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box<dyn ArchiveBuilder<'a> + 'a> {
105-
if sess.target.arch == "wasm32" || sess.target.arch == "wasm64" {
111+
// FIXME use ArArchiveBuilder on most targets again once reading thin archives is
112+
// implemented
113+
if true || sess.target.arch == "wasm32" || sess.target.arch == "wasm64" {
106114
Box::new(LlvmArchiveBuilder { sess, additions: Vec::new() })
107115
} else {
108116
Box::new(ArArchiveBuilder::new(sess, get_llvm_object_symbols))

compiler/rustc_codegen_ssa/src/back/archive.rs

+36-34
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;
17+
use std::io::{self, Write};
1818
use std::path::{Path, PathBuf};
1919

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

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

126127
let desired = match archs.iter().find(|a| a.architecture() == target_arch) {
127128
Some(a) => a,
128129
None => return Ok(None),
129130
};
130131

131-
Ok(Some((
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(
132139
desired.data(archive_map_data).map_err(|e| io::Error::new(io::ErrorKind::Other, e))?,
133-
desired.offset().into(),
134-
)))
140+
)?;
141+
142+
Ok(Some(extracted_path))
135143
}
136144

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

147-
match object::macho::FatHeader::parse(archive_bytes) {
156+
match object::macho::FatHeader::parse(&*archive_map) {
148157
Ok(h) if h.magic.get(object::endian::BigEndian) == object::macho::FAT_MAGIC => {
149-
let archs = object::macho::FatHeader::parse_arch32(archive_bytes);
150-
try_filter_fat_archs(archs, target_arch, archive_bytes)
158+
let archs = object::macho::FatHeader::parse_arch32(&*archive_map);
159+
try_filter_fat_archs(archs, target_arch, archive_path, &*archive_map)
151160
}
152161
Ok(h) if h.magic.get(object::endian::BigEndian) == object::macho::FAT_MAGIC_64 => {
153-
let archs = object::macho::FatHeader::parse_arch64(archive_bytes);
154-
try_filter_fat_archs(archs, target_arch, archive_bytes)
162+
let archs = object::macho::FatHeader::parse_arch64(&*archive_map);
163+
try_filter_fat_archs(archs, target_arch, archive_path, &*archive_map)
155164
}
156165
// Not a FatHeader at all, just return None.
157166
_ => Ok(None),
@@ -164,24 +173,21 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
164173
archive_path: &Path,
165174
mut skip: Box<dyn FnMut(&str) -> bool + 'static>,
166175
) -> io::Result<()> {
167-
let archive_map = unsafe { Mmap::map(File::open(&archive_path)?)? };
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+
168185
if self.src_archives.iter().any(|archive| archive.0 == archive_path) {
169186
return Ok(());
170187
}
171188

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)
189+
let archive_map = unsafe { Mmap::map(File::open(&archive_path)?)? };
190+
let archive = ArchiveFile::parse(&*archive_map)
185191
.map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?;
186192
let archive_index = self.src_archives.len();
187193

@@ -190,13 +196,9 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
190196
let file_name = String::from_utf8(entry.name().to_vec())
191197
.map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?;
192198
if !skip(&file_name) {
193-
let mut range = entry.file_range();
194-
if let Some(offset) = offset {
195-
range.0 += offset;
196-
}
197199
self.entries.push((
198200
file_name.into_bytes(),
199-
ArchiveEntry::FromArchive { archive_index, file_range: range },
201+
ArchiveEntry::FromArchive { archive_index, file_range: entry.file_range() },
200202
));
201203
}
202204
}

0 commit comments

Comments
 (0)