@@ -176,6 +176,7 @@ cfg_if::cfg_if! {
176
176
use std:: os:: unix:: prelude:: * ;
177
177
use std:: ffi:: { OsStr , CStr } ;
178
178
use object:: { Bytes , NativeEndian } ;
179
+ use object:: macho;
179
180
use object:: read:: macho:: { MachHeader , Section , Segment as _, Nlist } ;
180
181
181
182
#[ cfg( target_pointer_width = "32" ) ]
@@ -248,6 +249,69 @@ cfg_if::cfg_if! {
248
249
}
249
250
}
250
251
252
+ fn find_header( mut data: Bytes <' _>) -> Option <( & ' _ Mach , Bytes <' _>) > {
253
+ use object:: endian:: BigEndian ;
254
+
255
+ let desired_cpu = || {
256
+ if cfg!( target_arch = "x86" ) {
257
+ Some ( macho:: CPU_TYPE_X86 )
258
+ } else if cfg!( target_arch = "x86_64" ) {
259
+ Some ( macho:: CPU_TYPE_X86_64 )
260
+ } else if cfg!( target_arch = "arm" ) {
261
+ Some ( macho:: CPU_TYPE_ARM )
262
+ } else if cfg!( target_arch = "aarch64" ) {
263
+ Some ( macho:: CPU_TYPE_ARM64 )
264
+ } else {
265
+ None
266
+ }
267
+ } ;
268
+
269
+ match data. clone( ) . read:: <object:: endian:: U32 <NativeEndian >>( ) . ok( ) ?. get( NativeEndian ) {
270
+ macho:: MH_MAGIC_64
271
+ | macho:: MH_MAGIC
272
+ | macho:: MH_CIGAM_64
273
+ | macho:: MH_CIGAM => { }
274
+
275
+ macho:: FAT_MAGIC
276
+ | macho:: FAT_CIGAM => {
277
+ let mut header_data = data;
278
+ let endian = BigEndian ;
279
+ let header = header_data. read:: <macho:: FatHeader >( ) . ok( ) ?;
280
+ let nfat = header. nfat_arch. get( endian) ;
281
+ let arch = ( 0 ..nfat)
282
+ . filter_map( |_| header_data. read:: <macho:: FatArch32 >( ) . ok( ) )
283
+ . find( |arch| desired_cpu( ) == Some ( arch. cputype. get( endian) ) ) ?;
284
+ let offset = arch. offset. get( endian) ;
285
+ let size = arch. size. get( endian) ;
286
+ data = data. read_bytes_at(
287
+ offset. try_into( ) . ok( ) ?,
288
+ size. try_into( ) . ok( ) ?,
289
+ ) . ok( ) ?;
290
+ }
291
+
292
+ macho:: FAT_MAGIC_64
293
+ | macho:: FAT_CIGAM_64 => {
294
+ let mut header_data = data;
295
+ let endian = BigEndian ;
296
+ let header = header_data. read:: <macho:: FatHeader >( ) . ok( ) ?;
297
+ let nfat = header. nfat_arch. get( endian) ;
298
+ let arch = ( 0 ..nfat)
299
+ . filter_map( |_| header_data. read:: <macho:: FatArch64 >( ) . ok( ) )
300
+ . find( |arch| desired_cpu( ) == Some ( arch. cputype. get( endian) ) ) ?;
301
+ let offset = arch. offset. get( endian) ;
302
+ let size = arch. size. get( endian) ;
303
+ data = data. read_bytes_at(
304
+ offset. try_into( ) . ok( ) ?,
305
+ size. try_into( ) . ok( ) ?,
306
+ ) . ok( ) ?;
307
+ }
308
+
309
+ _ => return None ,
310
+ }
311
+
312
+ Mach :: parse( data) . ok( ) . map( |h| ( h, data) )
313
+ }
314
+
251
315
#[ allow( deprecated) ]
252
316
fn native_libraries( ) -> Vec <Library > {
253
317
let mut ret = Vec :: new( ) ;
@@ -476,8 +540,7 @@ impl Mapping {
476
540
// First up we need to load the unique UUID which is stored in the macho
477
541
// header of the file we're reading, specified at `path`.
478
542
let map = mmap ( path) ?;
479
- let data = Bytes ( & map) ;
480
- let macho = Mach :: parse ( data) . ok ( ) ?;
543
+ let ( macho, data) = find_header ( Bytes ( & map) ) ?;
481
544
let endian = macho. endian ( ) . ok ( ) ?;
482
545
let uuid = macho. uuid ( endian, data) . ok ( ) ??;
483
546
@@ -513,8 +576,7 @@ impl Mapping {
513
576
for entry in dir. read_dir ( ) . ok ( ) ? {
514
577
let entry = entry. ok ( ) ?;
515
578
let map = mmap ( & entry. path ( ) ) ?;
516
- let data = Bytes ( & map) ;
517
- let macho = Mach :: parse ( data) . ok ( ) ?;
579
+ let ( macho, data) = find_header ( Bytes ( & map) ) ?;
518
580
let endian = macho. endian ( ) . ok ( ) ?;
519
581
let entry_uuid = macho. uuid ( endian, data) . ok ( ) ??;
520
582
if entry_uuid != uuid {
0 commit comments