1
1
//! Creation of ar archives like for the lib and staticlib crate type
2
2
3
3
use std:: collections:: BTreeMap ;
4
+ use std:: convert:: TryFrom ;
4
5
use std:: fs:: File ;
6
+ use std:: io:: { self , Read , Seek } ;
5
7
use std:: path:: { Path , PathBuf } ;
6
8
7
9
use rustc_codegen_ssa:: back:: archive:: { find_library, ArchiveBuilder } ;
8
10
use rustc_codegen_ssa:: METADATA_FILENAME ;
9
11
use rustc_session:: Session ;
10
12
11
- use object:: { Object , ObjectSymbol , SymbolKind } ;
13
+ use object:: read:: archive:: ArchiveFile ;
14
+ use object:: { Object , ObjectSymbol , ReadCache , SymbolKind } ;
12
15
13
16
#[ derive( Debug ) ]
14
17
enum ArchiveEntry {
15
- FromArchive { archive_index : usize , entry_index : usize } ,
18
+ FromArchive { archive_index : usize , file_range : ( u64 , u64 ) } ,
16
19
File ( PathBuf ) ,
17
20
}
18
21
@@ -23,7 +26,7 @@ pub(crate) struct ArArchiveBuilder<'a> {
23
26
use_gnu_style_archive : bool ,
24
27
no_builtin_ranlib : bool ,
25
28
26
- src_archives : Vec < ( PathBuf , ar :: Archive < File > ) > ,
29
+ src_archives : Vec < File > ,
27
30
// Don't use `HashMap` here, as the order is important. `rust.metadata.bin` must always be at
28
31
// the end of an archive for linkers to not get confused.
29
32
entries : Vec < ( String , ArchiveEntry ) > ,
@@ -34,20 +37,19 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
34
37
use rustc_codegen_ssa:: back:: link:: archive_search_paths;
35
38
36
39
let ( src_archives, entries) = if let Some ( input) = input {
37
- let mut archive = ar:: Archive :: new ( File :: open ( input) . unwrap ( ) ) ;
40
+ let read_cache = ReadCache :: new ( File :: open ( input) . unwrap ( ) ) ;
41
+ let archive = ArchiveFile :: parse ( & read_cache) . unwrap ( ) ;
38
42
let mut entries = Vec :: new ( ) ;
39
43
40
- let mut i = 0 ;
41
- while let Some ( entry) = archive. next_entry ( ) {
44
+ for entry in archive. members ( ) {
42
45
let entry = entry. unwrap ( ) ;
43
46
entries. push ( (
44
- String :: from_utf8 ( entry. header ( ) . identifier ( ) . to_vec ( ) ) . unwrap ( ) ,
45
- ArchiveEntry :: FromArchive { archive_index : 0 , entry_index : i } ,
47
+ String :: from_utf8 ( entry. name ( ) . to_vec ( ) ) . unwrap ( ) ,
48
+ ArchiveEntry :: FromArchive { archive_index : 0 , file_range : entry . file_range ( ) } ,
46
49
) ) ;
47
- i += 1 ;
48
50
}
49
51
50
- ( vec ! [ ( input . to_owned ( ) , archive ) ] , entries)
52
+ ( vec ! [ read_cache . into_inner ( ) ] , entries)
51
53
} else {
52
54
( vec ! [ ] , Vec :: new ( ) )
53
55
} ;
@@ -98,7 +100,7 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
98
100
name : & str ,
99
101
lto : bool ,
100
102
skip_objects : bool ,
101
- ) -> std :: io:: Result < ( ) > {
103
+ ) -> io:: Result < ( ) > {
102
104
let obj_start = name. to_owned ( ) ;
103
105
104
106
self . add_archive ( rlib. to_owned ( ) , move |fname : & str | {
@@ -141,14 +143,14 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
141
143
// FIXME only read the symbol table of the object files to avoid having to keep all
142
144
// object files in memory at once, or read them twice.
143
145
let data = match entry {
144
- ArchiveEntry :: FromArchive { archive_index, entry_index } => {
146
+ ArchiveEntry :: FromArchive { archive_index, file_range } => {
145
147
// FIXME read symbols from symtab
146
- use std :: io :: Read ;
147
- let ( ref _src_archive_path , ref mut src_archive ) =
148
- self . src_archives [ archive_index ] ;
149
- let mut entry = src_archive . jump_to_entry ( entry_index ) . unwrap ( ) ;
150
- let mut data = Vec :: new ( ) ;
151
- entry . read_to_end ( & mut data ) . unwrap ( ) ;
148
+ let src_read_cache = & mut self . src_archives [ archive_index ] ;
149
+
150
+ src_read_cache . seek ( io :: SeekFrom :: Start ( file_range . 0 ) ) . unwrap ( ) ;
151
+ let mut data = std :: vec :: from_elem ( 0 , usize :: try_from ( file_range . 1 ) . unwrap ( ) ) ;
152
+ src_read_cache . read_exact ( & mut data) . unwrap ( ) ;
153
+
152
154
data
153
155
}
154
156
ArchiveEntry :: File ( file) => std:: fs:: read ( file) . unwrap_or_else ( |err| {
@@ -266,26 +268,27 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
266
268
}
267
269
268
270
impl < ' a > ArArchiveBuilder < ' a > {
269
- fn add_archive < F > ( & mut self , archive_path : PathBuf , mut skip : F ) -> std :: io:: Result < ( ) >
271
+ fn add_archive < F > ( & mut self , archive_path : PathBuf , mut skip : F ) -> io:: Result < ( ) >
270
272
where
271
273
F : FnMut ( & str ) -> bool + ' static ,
272
274
{
273
- let mut archive = ar:: Archive :: new ( std:: fs:: File :: open ( & archive_path) ?) ;
275
+ let read_cache = ReadCache :: new ( std:: fs:: File :: open ( & archive_path) ?) ;
276
+ let archive = ArchiveFile :: parse ( & read_cache) . unwrap ( ) ;
274
277
let archive_index = self . src_archives . len ( ) ;
275
278
276
- let mut i = 0 ;
277
- while let Some ( entry) = archive. next_entry ( ) {
278
- let entry = entry?;
279
- let file_name = String :: from_utf8 ( entry. header ( ) . identifier ( ) . to_vec ( ) )
280
- . map_err ( |err| std:: io:: Error :: new ( std:: io:: ErrorKind :: InvalidData , err) ) ?;
279
+ for entry in archive. members ( ) {
280
+ let entry = entry. map_err ( |err| io:: Error :: new ( io:: ErrorKind :: InvalidData , err) ) ?;
281
+ let file_name = String :: from_utf8 ( entry. name ( ) . to_vec ( ) )
282
+ . map_err ( |err| io:: Error :: new ( io:: ErrorKind :: InvalidData , err) ) ?;
281
283
if !skip ( & file_name) {
282
- self . entries
283
- . push ( ( file_name, ArchiveEntry :: FromArchive { archive_index, entry_index : i } ) ) ;
284
+ self . entries . push ( (
285
+ file_name,
286
+ ArchiveEntry :: FromArchive { archive_index, file_range : entry. file_range ( ) } ,
287
+ ) ) ;
284
288
}
285
- i += 1 ;
286
289
}
287
290
288
- self . src_archives . push ( ( archive_path , archive ) ) ;
291
+ self . src_archives . push ( read_cache . into_inner ( ) ) ;
289
292
Ok ( ( ) )
290
293
}
291
294
}
0 commit comments