1
1
//! Reading and writing of the rustc metadata for rlibs and dylibs
2
2
3
- use std:: convert:: TryFrom ;
4
3
use std:: fs:: File ;
4
+ use std:: ops:: Deref ;
5
5
use std:: path:: Path ;
6
6
7
7
use rustc_codegen_ssa:: METADATA_FILENAME ;
8
- use rustc_data_structures:: owning_ref:: OwningRef ;
8
+ use rustc_data_structures:: owning_ref:: { OwningRef , StableAddress } ;
9
9
use rustc_data_structures:: rustc_erase_owner;
10
10
use rustc_data_structures:: sync:: MetadataRef ;
11
11
use rustc_middle:: middle:: cstore:: { EncodedMetadata , MetadataLoader } ;
@@ -17,38 +17,56 @@ use crate::backend::WriteMetadata;
17
17
18
18
pub ( crate ) struct CraneliftMetadataLoader ;
19
19
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
+
20
43
impl MetadataLoader for CraneliftMetadataLoader {
21
44
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
+ }
34
54
}
35
- }
36
55
37
- Err ( "couldn't find metadata entry" . to_string ( ) )
56
+ Err ( "couldn't find metadata entry" . to_string ( ) )
57
+ } )
38
58
}
39
59
40
60
fn get_dylib_metadata ( & self , _target : & Target , path : & Path ) -> Result < MetadataRef , String > {
41
61
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
+ } )
52
70
}
53
71
}
54
72
0 commit comments