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