11//! Reading and writing of the rustc metadata for rlibs and dylibs
22
3- use std:: convert:: TryFrom ;
43use std:: fs:: File ;
4+ use std:: ops:: Deref ;
55use std:: path:: Path ;
66
77use rustc_codegen_ssa:: METADATA_FILENAME ;
8- use rustc_data_structures:: owning_ref:: OwningRef ;
8+ use rustc_data_structures:: owning_ref:: { OwningRef , StableAddress } ;
99use rustc_data_structures:: rustc_erase_owner;
1010use rustc_data_structures:: sync:: MetadataRef ;
1111use rustc_middle:: middle:: cstore:: { EncodedMetadata , MetadataLoader } ;
@@ -17,38 +17,56 @@ use crate::backend::WriteMetadata;
1717
1818pub ( crate ) struct CraneliftMetadataLoader ;
1919
20+ struct StableMmap ( memmap2:: Mmap ) ;
21+
22+ impl Deref for StableMmap {
23+ type Target = [ u8 ] ;
24+
25+ fn deref ( & self ) -> & [ u8 ] {
26+ & * self . 0
27+ }
28+ }
29+
30+ unsafe impl StableAddress for StableMmap { }
31+
32+ fn load_metadata_with (
33+ path : & Path ,
34+ f : impl for < ' a > FnOnce ( & ' a [ u8 ] ) -> Result < & ' a [ u8 ] , String > ,
35+ ) -> Result < MetadataRef , String > {
36+ let file = File :: open ( path) . map_err ( |e| format ! ( "{:?}" , e) ) ?;
37+ let data = unsafe { memmap2:: MmapOptions :: new ( ) . map_copy_read_only ( & file) }
38+ . map_err ( |e| format ! ( "{:?}" , e) ) ?;
39+ let metadata = OwningRef :: new ( StableMmap ( data) ) . try_map ( f) ?;
40+ return Ok ( rustc_erase_owner ! ( metadata. map_owner_box( ) ) ) ;
41+ }
42+
2043impl MetadataLoader for CraneliftMetadataLoader {
2144 fn get_rlib_metadata ( & self , _target : & Target , path : & Path ) -> Result < MetadataRef , String > {
22- let mut archive = ar:: Archive :: new ( File :: open ( path) . map_err ( |e| format ! ( "{:?}" , e) ) ?) ;
23- // Iterate over all entries in the archive:
24- while let Some ( entry_result) = archive. next_entry ( ) {
25- let mut entry = entry_result. map_err ( |e| format ! ( "{:?}" , e) ) ?;
26- if entry. header ( ) . identifier ( ) == METADATA_FILENAME . as_bytes ( ) {
27- let mut buf = Vec :: with_capacity (
28- usize:: try_from ( entry. header ( ) . size ( ) )
29- . expect ( "Rlib metadata file too big to load into memory." ) ,
30- ) ;
31- :: std:: io:: copy ( & mut entry, & mut buf) . map_err ( |e| format ! ( "{:?}" , e) ) ?;
32- let buf: OwningRef < Vec < u8 > , [ u8 ] > = OwningRef :: new ( buf) ;
33- return Ok ( rustc_erase_owner ! ( buf. map_owner_box( ) ) ) ;
45+ load_metadata_with ( path, |data| {
46+ let archive = object:: read:: archive:: ArchiveFile :: parse ( & * data)
47+ . map_err ( |e| format ! ( "{:?}" , e) ) ?;
48+
49+ for entry_result in archive. members ( ) {
50+ let entry = entry_result. map_err ( |e| format ! ( "{:?}" , e) ) ?;
51+ if entry. name ( ) == METADATA_FILENAME . as_bytes ( ) {
52+ return Ok ( entry. data ( ) ) ;
53+ }
3454 }
35- }
3655
37- Err ( "couldn't find metadata entry" . to_string ( ) )
56+ Err ( "couldn't find metadata entry" . to_string ( ) )
57+ } )
3858 }
3959
4060 fn get_dylib_metadata ( & self , _target : & Target , path : & Path ) -> Result < MetadataRef , String > {
4161 use object:: { Object , ObjectSection } ;
42- let file = std:: fs:: read ( path) . map_err ( |e| format ! ( "read:{:?}" , e) ) ?;
43- let file = object:: File :: parse ( & file) . map_err ( |e| format ! ( "parse: {:?}" , e) ) ?;
44- let buf = file
45- . section_by_name ( ".rustc" )
46- . ok_or ( "no .rustc section" ) ?
47- . data ( )
48- . map_err ( |e| format ! ( "failed to read .rustc section: {:?}" , e) ) ?
49- . to_owned ( ) ;
50- let buf: OwningRef < Vec < u8 > , [ u8 ] > = OwningRef :: new ( buf) ;
51- Ok ( rustc_erase_owner ! ( buf. map_owner_box( ) ) )
62+
63+ load_metadata_with ( path, |data| {
64+ let file = object:: File :: parse ( & data) . map_err ( |e| format ! ( "parse: {:?}" , e) ) ?;
65+ file. section_by_name ( ".rustc" )
66+ . ok_or ( "no .rustc section" ) ?
67+ . data ( )
68+ . map_err ( |e| format ! ( "failed to read .rustc section: {:?}" , e) )
69+ } )
5270 }
5371}
5472
0 commit comments