]> git.lizzy.rs Git - rust.git/blobdiff - src/metadata.rs
Add custom driver
[rust.git] / src / metadata.rs
index 56ce208a71aa3d819dc4bcb56566bb256b1fc77e..93cff5711d937ec4234ac44efb01bce1847ba33a 100644 (file)
@@ -1,15 +1,20 @@
+//! Reading and writing of the rustc metadata for rlibs and dylibs
+
+use std::convert::TryFrom;
 use std::fs::File;
 use std::path::Path;
 
-use rustc::session::config;
-use rustc::ty::TyCtxt;
-use rustc::middle::cstore::{EncodedMetadata, MetadataLoader};
 use rustc_codegen_ssa::METADATA_FILENAME;
 use rustc_data_structures::owning_ref::{self, OwningRef};
 use rustc_data_structures::rustc_erase_owner;
+use rustc_middle::middle::cstore::{EncodedMetadata, MetadataLoader};
+use rustc_middle::ty::TyCtxt;
+use rustc_session::config;
 use rustc_target::spec::Target;
 
-pub struct CraneliftMetadataLoader;
+use crate::backend::WriteMetadata;
+
+pub(crate) struct CraneliftMetadataLoader;
 
 impl MetadataLoader for CraneliftMetadataLoader {
     fn get_rlib_metadata(
@@ -22,7 +27,10 @@ fn get_rlib_metadata(
         while let Some(entry_result) = archive.next_entry() {
             let mut entry = entry_result.map_err(|e| format!("{:?}", e))?;
             if entry.header().identifier() == METADATA_FILENAME.as_bytes() {
-                let mut buf = Vec::new();
+                let mut buf = Vec::with_capacity(
+                    usize::try_from(entry.header().size())
+                        .expect("Rlib metadata file too big to load into memory."),
+                );
                 ::std::io::copy(&mut entry, &mut buf).map_err(|e| format!("{:?}", e))?;
                 let buf: OwningRef<Vec<u8>, [u8]> = OwningRef::new(buf).into();
                 return Ok(rustc_erase_owner!(buf.map_owner_box()));
@@ -38,43 +46,50 @@ fn get_dylib_metadata(
         _target: &Target,
         path: &Path,
     ) -> Result<owning_ref::ErasedBoxRef<[u8]>, String> {
-        use object::Object;
+        use object::{Object, ObjectSection};
         let file = std::fs::read(path).map_err(|e| format!("read:{:?}", e))?;
         let file = object::File::parse(&file).map_err(|e| format!("parse: {:?}", e))?;
-        let buf = file.section_data_by_name(".rustc").ok_or("no .rustc section")?.into_owned();
+        let buf = file
+            .section_by_name(".rustc")
+            .ok_or("no .rustc section")?
+            .data()
+            .map_err(|e| format!("failed to read .rustc section: {:?}", e))?
+            .to_owned();
         let buf: OwningRef<Vec<u8>, [u8]> = OwningRef::new(buf).into();
         Ok(rustc_erase_owner!(buf.map_owner_box()))
     }
 }
 
 // Adapted from https://github.com/rust-lang/rust/blob/da573206f87b5510de4b0ee1a9c044127e409bd3/src/librustc_codegen_llvm/base.rs#L47-L112
-pub fn write_metadata<'a, 'gcx>(
-    tcx: TyCtxt<'a, 'gcx, 'gcx>,
-    artifact: &mut faerie::Artifact
+pub(crate) fn write_metadata<P: WriteMetadata>(
+    tcx: TyCtxt<'_>,
+    product: &mut P,
 ) -> EncodedMetadata {
+    use snap::write::FrameEncoder;
     use std::io::Write;
-    use flate2::Compression;
-    use flate2::write::DeflateEncoder;
 
     #[derive(PartialEq, Eq, PartialOrd, Ord)]
     enum MetadataKind {
         None,
         Uncompressed,
-        Compressed
+        Compressed,
     }
 
-    let kind = tcx.sess.crate_types.borrow().iter().map(|ty| {
-        match *ty {
-            config::CrateType::Executable |
-            config::CrateType::Staticlib |
-            config::CrateType::Cdylib => MetadataKind::None,
+    let kind = tcx
+        .sess
+        .crate_types()
+        .iter()
+        .map(|ty| match *ty {
+            config::CrateType::Executable
+            | config::CrateType::Staticlib
+            | config::CrateType::Cdylib => MetadataKind::None,
 
             config::CrateType::Rlib => MetadataKind::Uncompressed,
 
-            config::CrateType::Dylib |
-            config::CrateType::ProcMacro => MetadataKind::Compressed,
-        }
-    }).max().unwrap_or(MetadataKind::None);
+            config::CrateType::Dylib | config::CrateType::ProcMacro => MetadataKind::Compressed,
+        })
+        .max()
+        .unwrap_or(MetadataKind::None);
 
     if kind == MetadataKind::None {
         return EncodedMetadata::new();
@@ -87,20 +102,15 @@ enum MetadataKind {
 
     assert!(kind == MetadataKind::Compressed);
     let mut compressed = tcx.metadata_encoding_version();
-    DeflateEncoder::new(&mut compressed, Compression::fast())
-        .write_all(&metadata.raw_data).unwrap();
-
-    artifact.declare(".rustc", faerie::Decl::section(faerie::SectionKind::Data)).unwrap();
-    artifact.define_with_symbols(".rustc", compressed, {
-        let mut map = std::collections::BTreeMap::new();
-        // FIXME implement faerie elf backend section custom symbols
-        // For MachO this is necessary to prevent the linker from throwing away the .rustc section,
-        // but for ELF it isn't.
-        if tcx.sess.target.target.options.is_like_osx {
-            map.insert(rustc::middle::exported_symbols::metadata_symbol_name(tcx), 0);
-        }
-        map
-    }).unwrap();
+    FrameEncoder::new(&mut compressed)
+        .write_all(&metadata.raw_data)
+        .unwrap();
+
+    product.add_rustc_section(
+        rustc_middle::middle::exported_symbols::metadata_symbol_name(tcx),
+        compressed,
+        tcx.sess.target.target.options.is_like_osx,
+    );
 
     metadata
 }