about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-01-28 04:02:25 +0000
committerbors <bors@rust-lang.org>2023-01-28 04:02:25 +0000
commit252741673b9c2b06267cd3a036d77489e92f963a (patch)
treee84a2f4ee63c69322b28040f06a04283c13d847b /compiler
parent6cd6bad51fb34a0d89e97c27814041fe4d0838b5 (diff)
parentde363d54c40a378717881240e719f5f7223ba376 (diff)
downloadrust-252741673b9c2b06267cd3a036d77489e92f963a.tar.gz
rust-252741673b9c2b06267cd3a036d77489e92f963a.zip
Auto merge of #107360 - bjorn3:fix_thin_archive_reading, r=wesleywiser
Fix thin archive reading

This includes a revert of https://github.com/rust-lang/rust/pull/105221 to restore fat archive reading with LlvmArchiveBuilder.

Should fix #107162, #107334 and https://github.com/google/shaderc-rs/issues/133
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_codegen_llvm/src/back/archive.rs18
-rw-r--r--compiler/rustc_codegen_ssa/src/back/archive.rs70
2 files changed, 49 insertions, 39 deletions
diff --git a/compiler/rustc_codegen_llvm/src/back/archive.rs b/compiler/rustc_codegen_llvm/src/back/archive.rs
index 426f57c0608..58ca87524de 100644
--- a/compiler/rustc_codegen_llvm/src/back/archive.rs
+++ b/compiler/rustc_codegen_llvm/src/back/archive.rs
@@ -15,8 +15,8 @@ use crate::errors::{
 use crate::llvm::archive_ro::{ArchiveRO, Child};
 use crate::llvm::{self, ArchiveKind, LLVMMachineType, LLVMRustCOFFShortExport};
 use rustc_codegen_ssa::back::archive::{
-    get_native_object_symbols, ArArchiveBuilder, ArchiveBuildFailure, ArchiveBuilder,
-    ArchiveBuilderBuilder, UnknownArchiveKind,
+    get_native_object_symbols, try_extract_macho_fat_archive, ArArchiveBuilder,
+    ArchiveBuildFailure, ArchiveBuilder, ArchiveBuilderBuilder, UnknownArchiveKind,
 };
 
 use rustc_session::cstore::DllImport;
@@ -66,7 +66,13 @@ impl<'a> ArchiveBuilder<'a> for LlvmArchiveBuilder<'a> {
         archive: &Path,
         skip: Box<dyn FnMut(&str) -> bool + 'static>,
     ) -> io::Result<()> {
-        let archive_ro = match ArchiveRO::open(archive) {
+        let mut archive = archive.to_path_buf();
+        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,
             Err(e) => return Err(io::Error::new(io::ErrorKind::Other, e)),
         };
@@ -74,7 +80,7 @@ impl<'a> ArchiveBuilder<'a> for LlvmArchiveBuilder<'a> {
             return Ok(());
         }
         self.additions.push(Addition::Archive {
-            path: archive.to_path_buf(),
+            path: archive,
             archive: archive_ro,
             skip: Box::new(skip),
         });
@@ -102,7 +108,9 @@ pub struct LlvmArchiveBuilderBuilder;
 
 impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder {
     fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box<dyn ArchiveBuilder<'a> + 'a> {
-        if sess.target.arch == "wasm32" || sess.target.arch == "wasm64" {
+        // FIXME use ArArchiveBuilder on most targets again once reading thin archives is
+        // implemented
+        if true || sess.target.arch == "wasm32" || sess.target.arch == "wasm64" {
             Box::new(LlvmArchiveBuilder { sess, additions: Vec::new() })
         } else {
             Box::new(ArArchiveBuilder::new(sess, get_llvm_object_symbols))
diff --git a/compiler/rustc_codegen_ssa/src/back/archive.rs b/compiler/rustc_codegen_ssa/src/back/archive.rs
index 6eb120157da..d3cd085cfb6 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;
+use std::io::{self, Write};
 use std::path::{Path, PathBuf};
 
 // Re-exporting for rustc_codegen_llvm::back::archive
@@ -116,11 +116,12 @@ impl<'a> ArArchiveBuilder<'a> {
     }
 }
 
-fn try_filter_fat_archs<'a>(
+fn try_filter_fat_archs(
     archs: object::read::Result<&[impl FatArch]>,
     target_arch: object::Architecture,
-    archive_map_data: &'a [u8],
-) -> io::Result<Option<(&'a [u8], u64)>> {
+    archive_path: &Path,
+    archive_map_data: &[u8],
+) -> io::Result<Option<PathBuf>> {
     let archs = archs.map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
 
     let desired = match archs.iter().find(|a| a.architecture() == target_arch) {
@@ -128,30 +129,38 @@ fn try_filter_fat_archs<'a>(
         None => return Ok(None),
     };
 
-    Ok(Some((
+    let (mut new_f, extracted_path) = tempfile::Builder::new()
+        .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.offset().into(),
-    )))
+    )?;
+
+    Ok(Some(extracted_path))
 }
 
-pub fn try_extract_macho_fat_archive<'a>(
+pub fn try_extract_macho_fat_archive(
     sess: &Session,
-    archive_bytes: &'a [u8],
-) -> io::Result<Option<(&'a [u8], u64)>> {
+    archive_path: &Path,
+) -> io::Result<Option<PathBuf>> {
+    let archive_map = unsafe { Mmap::map(File::open(&archive_path)?)? };
     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_bytes) {
+    match object::macho::FatHeader::parse(&*archive_map) {
         Ok(h) if h.magic.get(object::endian::BigEndian) == object::macho::FAT_MAGIC => {
-            let archs = object::macho::FatHeader::parse_arch32(archive_bytes);
-            try_filter_fat_archs(archs, target_arch, archive_bytes)
+            let archs = object::macho::FatHeader::parse_arch32(&*archive_map);
+            try_filter_fat_archs(archs, target_arch, archive_path, &*archive_map)
         }
         Ok(h) if h.magic.get(object::endian::BigEndian) == object::macho::FAT_MAGIC_64 => {
-            let archs = object::macho::FatHeader::parse_arch64(archive_bytes);
-            try_filter_fat_archs(archs, target_arch, archive_bytes)
+            let archs = object::macho::FatHeader::parse_arch64(&*archive_map);
+            try_filter_fat_archs(archs, target_arch, archive_path, &*archive_map)
         }
         // Not a FatHeader at all, just return None.
         _ => Ok(None),
@@ -164,24 +173,21 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
         archive_path: &Path,
         mut skip: Box<dyn FnMut(&str) -> bool + 'static>,
     ) -> io::Result<()> {
-        let archive_map = unsafe { Mmap::map(File::open(&archive_path)?)? };
+        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
+            }
+        }
+
         if self.src_archives.iter().any(|archive| archive.0 == archive_path) {
             return Ok(());
         }
 
-        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)
+        let archive_map = unsafe { Mmap::map(File::open(&archive_path)?)? };
+        let archive = ArchiveFile::parse(&*archive_map)
             .map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?;
         let archive_index = self.src_archives.len();
 
@@ -190,13 +196,9 @@ 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: range },
+                    ArchiveEntry::FromArchive { archive_index, file_range: entry.file_range() },
                 ));
             }
         }