@@ -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
@@ -71,7 +72,7 @@ fn check_paths<P: AsRef<Path>>(paths: &[P]) {
7172 for path in paths {
7273 let path = path. as_ref ( ) ;
7374 println ! ( "Checking {}" , path. display( ) ) ;
74- let archive = Archive :: from_path ( path) ;
75+ let archive = BinFile :: from_path ( path) ;
7576
7677 verify_no_duplicates ( & archive) ;
7778 verify_core_symbols ( & archive) ;
@@ -174,7 +175,7 @@ struct SymInfo {
174175}
175176
176177impl SymInfo {
177- fn new ( sym : & Symbol , obj : & ObjFile , member : & ArchiveMember ) -> Self {
178+ fn new ( sym : & Symbol , obj : & ObjFile , obj_path : & str ) -> Self {
178179 // Include the section name if possible. Fall back to the `Section` debug impl if not.
179180 let section = sym. section ( ) ;
180181 let section_name = sym
@@ -196,7 +197,7 @@ impl SymInfo {
196197 is_weak : sym. is_weak ( ) ,
197198 is_common : sym. is_common ( ) ,
198199 address : sym. address ( ) ,
199- object : String :: from_utf8_lossy ( member . name ( ) ) . into_owned ( ) ,
200+ object : obj_path . to_owned ( ) ,
200201 }
201202 }
202203}
@@ -206,7 +207,7 @@ impl SymInfo {
206207/// Note that this will also locate cases where a symbol is weakly defined in more than one place.
207208/// Technically there are no linker errors that will come from this, but it keeps our binary more
208209/// straightforward and saves some distribution size.
209- fn verify_no_duplicates ( archive : & Archive ) {
210+ fn verify_no_duplicates ( archive : & BinFile ) {
210211 let mut syms = BTreeMap :: < String , SymInfo > :: new ( ) ;
211212 let mut dups = Vec :: new ( ) ;
212213 let mut found_any = false ;
@@ -263,7 +264,7 @@ fn verify_no_duplicates(archive: &Archive) {
263264}
264265
265266/// 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 ) {
267268 let mut defined = BTreeSet :: new ( ) ;
268269 let mut undefined = Vec :: new ( ) ;
269270 let mut has_symbols = false ;
@@ -298,39 +299,63 @@ fn verify_core_symbols(archive: &Archive) {
298299}
299300
300301/// Thin wrapper for owning data used by `object`.
301- struct Archive {
302+ struct BinFile {
303+ path : PathBuf ,
302304 data : Vec < u8 > ,
303305}
304306
305- impl Archive {
307+ impl BinFile {
306308 fn from_path ( path : & Path ) -> Self {
307309 Self {
310+ path : path. to_owned ( ) ,
308311 data : fs:: read ( path) . expect ( "reading file failed" ) ,
309312 }
310313 }
311314
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 ( ) )
314317 }
315318
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 ;
327339 }
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+ ) ;
328353 }
329354
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 ) ) ;
334359 } ) ;
335360 }
336361}
0 commit comments