@@ -7,9 +7,10 @@ use std::io::{BufRead, BufReader};
7
7
use std:: path:: { Path , PathBuf } ;
8
8
use std:: process:: { Command , Stdio } ;
9
9
10
- use object:: read:: archive:: { ArchiveFile , ArchiveMember } ;
10
+ use object:: read:: archive:: ArchiveFile ;
11
11
use object:: {
12
- File as ObjFile , Object , ObjectSection , ObjectSymbol , Symbol , SymbolKind , SymbolScope ,
12
+ File as ObjFile , Object , ObjectSection , ObjectSymbol , Result as ObjResult , Symbol , SymbolKind ,
13
+ SymbolScope ,
13
14
} ;
14
15
use serde_json:: Value ;
15
16
@@ -71,7 +72,7 @@ fn check_paths<P: AsRef<Path>>(paths: &[P]) {
71
72
for path in paths {
72
73
let path = path. as_ref ( ) ;
73
74
println ! ( "Checking {}" , path. display( ) ) ;
74
- let archive = Archive :: from_path ( path) ;
75
+ let archive = BinFile :: from_path ( path) ;
75
76
76
77
verify_no_duplicates ( & archive) ;
77
78
verify_core_symbols ( & archive) ;
@@ -174,7 +175,7 @@ struct SymInfo {
174
175
}
175
176
176
177
impl SymInfo {
177
- fn new ( sym : & Symbol , obj : & ObjFile , member : & ArchiveMember ) -> Self {
178
+ fn new ( sym : & Symbol , obj : & ObjFile , obj_path : & str ) -> Self {
178
179
// Include the section name if possible. Fall back to the `Section` debug impl if not.
179
180
let section = sym. section ( ) ;
180
181
let section_name = sym
@@ -196,7 +197,7 @@ impl SymInfo {
196
197
is_weak : sym. is_weak ( ) ,
197
198
is_common : sym. is_common ( ) ,
198
199
address : sym. address ( ) ,
199
- object : String :: from_utf8_lossy ( member . name ( ) ) . into_owned ( ) ,
200
+ object : obj_path . to_owned ( ) ,
200
201
}
201
202
}
202
203
}
@@ -206,7 +207,7 @@ impl SymInfo {
206
207
/// Note that this will also locate cases where a symbol is weakly defined in more than one place.
207
208
/// Technically there are no linker errors that will come from this, but it keeps our binary more
208
209
/// straightforward and saves some distribution size.
209
- fn verify_no_duplicates ( archive : & Archive ) {
210
+ fn verify_no_duplicates ( archive : & BinFile ) {
210
211
let mut syms = BTreeMap :: < String , SymInfo > :: new ( ) ;
211
212
let mut dups = Vec :: new ( ) ;
212
213
let mut found_any = false ;
@@ -263,7 +264,7 @@ fn verify_no_duplicates(archive: &Archive) {
263
264
}
264
265
265
266
/// Ensure that there are no references to symbols from `core` that aren't also (somehow) defined.
266
- fn verify_core_symbols ( archive : & Archive ) {
267
+ fn verify_core_symbols ( archive : & BinFile ) {
267
268
let mut defined = BTreeSet :: new ( ) ;
268
269
let mut undefined = Vec :: new ( ) ;
269
270
let mut has_symbols = false ;
@@ -298,39 +299,63 @@ fn verify_core_symbols(archive: &Archive) {
298
299
}
299
300
300
301
/// Thin wrapper for owning data used by `object`.
301
- struct Archive {
302
+ struct BinFile {
303
+ path : PathBuf ,
302
304
data : Vec < u8 > ,
303
305
}
304
306
305
- impl Archive {
307
+ impl BinFile {
306
308
fn from_path ( path : & Path ) -> Self {
307
309
Self {
310
+ path : path. to_owned ( ) ,
308
311
data : fs:: read ( path) . expect ( "reading file failed" ) ,
309
312
}
310
313
}
311
314
312
- fn file ( & self ) -> ArchiveFile < ' _ > {
313
- ArchiveFile :: parse ( self . data . as_slice ( ) ) . expect ( "archive parse failed" )
315
+ fn as_archive_file ( & self ) -> ObjResult < ArchiveFile < ' _ > > {
316
+ ArchiveFile :: parse ( self . data . as_slice ( ) )
314
317
}
315
318
316
- /// For a given archive, do something with each object file.
317
- fn for_each_object ( & self , mut f : impl FnMut ( ObjFile , & ArchiveMember ) ) {
318
- let archive = self . file ( ) ;
319
-
320
- for member in archive. members ( ) {
321
- let member = member. expect ( "failed to access member" ) ;
322
- let obj_data = member
323
- . data ( self . data . as_slice ( ) )
324
- . expect ( "failed to access object" ) ;
325
- let obj = ObjFile :: parse ( obj_data) . expect ( "failed to parse object" ) ;
326
- f ( obj, & member) ;
319
+ fn as_obj_file ( & self ) -> ObjResult < ObjFile < ' _ > > {
320
+ ObjFile :: parse ( self . data . as_slice ( ) )
321
+ }
322
+
323
+ /// For a given archive, do something with each object file. For an object file, do
324
+ /// something once.
325
+ fn for_each_object ( & self , mut f : impl FnMut ( ObjFile , & str ) ) {
326
+ // Try as an archive first.
327
+ let as_archive = self . as_archive_file ( ) ;
328
+ if let Ok ( archive) = as_archive {
329
+ for member in archive. members ( ) {
330
+ let member = member. expect ( "failed to access member" ) ;
331
+ let obj_data = member
332
+ . data ( self . data . as_slice ( ) )
333
+ . expect ( "failed to access object" ) ;
334
+ let obj = ObjFile :: parse ( obj_data) . expect ( "failed to parse object" ) ;
335
+ f ( obj, & String :: from_utf8_lossy ( member. name ( ) ) ) ;
336
+ }
337
+
338
+ return ;
327
339
}
340
+
341
+ // Fall back to parsing as an object file.
342
+ let as_obj = self . as_obj_file ( ) ;
343
+ if let Ok ( obj) = as_obj {
344
+ f ( obj, & self . path . to_string_lossy ( ) ) ;
345
+ return ;
346
+ }
347
+
348
+ panic ! (
349
+ "failed to parse as either archive or object file: {:?}, {:?}" ,
350
+ as_archive. unwrap_err( ) ,
351
+ as_obj. unwrap_err( ) ,
352
+ ) ;
328
353
}
329
354
330
- /// For a given archive, do something with each symbol.
331
- fn for_each_symbol ( & self , mut f : impl FnMut ( Symbol , & ObjFile , & ArchiveMember ) ) {
332
- self . for_each_object ( |obj, member | {
333
- obj. symbols ( ) . for_each ( |sym| f ( sym, & obj, member ) ) ;
355
+ /// D something with each symbol in an archive or object file .
356
+ fn for_each_symbol ( & self , mut f : impl FnMut ( Symbol , & ObjFile , & str ) ) {
357
+ self . for_each_object ( |obj, obj_path | {
358
+ obj. symbols ( ) . for_each ( |sym| f ( sym, & obj, obj_path ) ) ;
334
359
} ) ;
335
360
}
336
361
}
0 commit comments