@@ -7,9 +7,10 @@ use std::io::{BufRead, BufReader};
77use std:: path:: { Path , PathBuf } ;
88use std:: process:: { Command , Stdio } ;
99
10- use object:: read:: archive:: { ArchiveFile , ArchiveMember } ;
10+ use object:: read:: archive:: ArchiveFile ;
1111use 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 ,
1314} ;
1415use serde_json:: Value ;
1516
@@ -25,9 +26,10 @@ Cargo will get invoked with `CARGO_ARGS` and the specified target. All output
2526
2627If TARGET is not specified, the host target is used.
2728
28- check ARCHIVE_PATHS ...
29+ check PATHS ...
2930
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.
3133" ;
3234
3335fn main ( ) {
@@ -71,7 +73,7 @@ fn check_paths<P: AsRef<Path>>(paths: &[P]) {
7173 for path in paths {
7274 let path = path. as_ref ( ) ;
7375 println ! ( "Checking {}" , path. display( ) ) ;
74- let archive = Archive :: from_path ( path) ;
76+ let archive = BinFile :: from_path ( path) ;
7577
7678 verify_no_duplicates ( & archive) ;
7779 verify_core_symbols ( & archive) ;
@@ -174,7 +176,7 @@ struct SymInfo {
174176}
175177
176178impl SymInfo {
177- fn new ( sym : & Symbol , obj : & ObjFile , member : & ArchiveMember ) -> Self {
179+ fn new ( sym : & Symbol , obj : & ObjFile , obj_path : & str ) -> Self {
178180 // Include the section name if possible. Fall back to the `Section` debug impl if not.
179181 let section = sym. section ( ) ;
180182 let section_name = sym
@@ -196,7 +198,7 @@ impl SymInfo {
196198 is_weak : sym. is_weak ( ) ,
197199 is_common : sym. is_common ( ) ,
198200 address : sym. address ( ) ,
199- object : String :: from_utf8_lossy ( member . name ( ) ) . into_owned ( ) ,
201+ object : obj_path . to_owned ( ) ,
200202 }
201203 }
202204}
@@ -206,7 +208,7 @@ impl SymInfo {
206208/// Note that this will also locate cases where a symbol is weakly defined in more than one place.
207209/// Technically there are no linker errors that will come from this, but it keeps our binary more
208210/// straightforward and saves some distribution size.
209- fn verify_no_duplicates ( archive : & Archive ) {
211+ fn verify_no_duplicates ( archive : & BinFile ) {
210212 let mut syms = BTreeMap :: < String , SymInfo > :: new ( ) ;
211213 let mut dups = Vec :: new ( ) ;
212214 let mut found_any = false ;
@@ -263,7 +265,7 @@ fn verify_no_duplicates(archive: &Archive) {
263265}
264266
265267/// 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 ) {
267269 let mut defined = BTreeSet :: new ( ) ;
268270 let mut undefined = Vec :: new ( ) ;
269271 let mut has_symbols = false ;
@@ -298,39 +300,63 @@ fn verify_core_symbols(archive: &Archive) {
298300}
299301
300302/// Thin wrapper for owning data used by `object`.
301- struct Archive {
303+ struct BinFile {
304+ path : PathBuf ,
302305 data : Vec < u8 > ,
303306}
304307
305- impl Archive {
308+ impl BinFile {
306309 fn from_path ( path : & Path ) -> Self {
307310 Self {
311+ path : path. to_owned ( ) ,
308312 data : fs:: read ( path) . expect ( "reading file failed" ) ,
309313 }
310314 }
311315
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 ( ) )
314318 }
315319
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 ;
327340 }
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+ ) ;
328354 }
329355
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 ) ) ;
334360 } ) ;
335361 }
336362}
0 commit comments