33
33
{
34
34
pub ( super ) endian : Mach :: Endian ,
35
35
pub ( super ) data : R ,
36
+ pub ( super ) header_offset : u64 ,
36
37
pub ( super ) header : & ' data Mach ,
37
38
pub ( super ) sections : Vec < MachOSectionInternal < ' data , Mach > > ,
38
39
pub ( super ) symbols : SymbolTable < ' data , Mach > ,
@@ -45,13 +46,21 @@ where
45
46
{
46
47
/// Parse the raw Mach-O file data.
47
48
pub fn parse ( data : R ) -> Result < Self > {
48
- let header = Mach :: parse ( data) ?;
49
+ Self :: parse_at_offset ( data, 0 )
50
+ }
51
+
52
+ /// Parse the raw Mach-O file data at an arbitrary offset inside the input data.
53
+ /// This can be used for parsing Mach-O images inside the dyld shared cache,
54
+ /// where multiple images, located at different offsets, share the same address
55
+ /// space.
56
+ pub fn parse_at_offset ( data : R , header_offset : u64 ) -> Result < Self > {
57
+ let header = Mach :: parse ( data, header_offset) ?;
49
58
let endian = header. endian ( ) ?;
50
59
51
60
let mut symbols = SymbolTable :: default ( ) ;
52
61
// Build a list of sections to make some operations more efficient.
53
62
let mut sections = Vec :: new ( ) ;
54
- if let Ok ( mut commands) = header. load_commands ( endian, data) {
63
+ if let Ok ( mut commands) = header. load_commands ( endian, data, header_offset ) {
55
64
while let Ok ( Some ( command) ) = commands. next ( ) {
56
65
if let Some ( ( segment, section_data) ) = Mach :: Segment :: from_command ( command) ? {
57
66
for section in segment. sections ( endian, section_data) ? {
67
76
Ok ( MachOFile {
68
77
endian,
69
78
header,
79
+ header_offset,
70
80
sections,
71
81
symbols,
72
82
data,
@@ -137,7 +147,7 @@ where
137
147
file : self ,
138
148
commands : self
139
149
. header
140
- . load_commands ( self . endian , self . data )
150
+ . load_commands ( self . endian , self . data , self . header_offset )
141
151
. ok ( )
142
152
. unwrap_or_else ( Default :: default) ,
143
153
}
@@ -240,7 +250,9 @@ where
240
250
if twolevel {
241
251
libraries. push ( & [ ] [ ..] ) ;
242
252
}
243
- let mut commands = self . header . load_commands ( self . endian , self . data ) ?;
253
+ let mut commands = self
254
+ . header
255
+ . load_commands ( self . endian , self . data , self . header_offset ) ?;
244
256
while let Some ( command) = commands. next ( ) ? {
245
257
if let Some ( command) = command. dysymtab ( ) ? {
246
258
dysymtab = Some ( command) ;
@@ -278,7 +290,9 @@ where
278
290
279
291
fn exports ( & self ) -> Result < Vec < Export < ' data > > > {
280
292
let mut dysymtab = None ;
281
- let mut commands = self . header . load_commands ( self . endian , self . data ) ?;
293
+ let mut commands = self
294
+ . header
295
+ . load_commands ( self . endian , self . data , self . header_offset ) ?;
282
296
while let Some ( command) = commands. next ( ) ? {
283
297
if let Some ( command) = command. dysymtab ( ) ? {
284
298
dysymtab = Some ( command) ;
@@ -313,11 +327,14 @@ where
313
327
}
314
328
315
329
fn mach_uuid ( & self ) -> Result < Option < [ u8 ; 16 ] > > {
316
- self . header . uuid ( self . endian , self . data )
330
+ self . header . uuid ( self . endian , self . data , self . header_offset )
317
331
}
318
332
319
333
fn entry ( & self ) -> u64 {
320
- if let Ok ( mut commands) = self . header . load_commands ( self . endian , self . data ) {
334
+ if let Ok ( mut commands) =
335
+ self . header
336
+ . load_commands ( self . endian , self . data , self . header_offset )
337
+ {
321
338
while let Ok ( Some ( command) ) = commands. next ( ) {
322
339
if let Ok ( Some ( command) ) = command. entry_point ( ) {
323
340
return command. entryoff . get ( self . endian ) ;
@@ -480,9 +497,9 @@ pub trait MachHeader: Debug + Pod {
480
497
/// Read the file header.
481
498
///
482
499
/// Also checks that the magic field in the file header is a supported format.
483
- fn parse < ' data , R : ReadRef < ' data > > ( data : R ) -> read:: Result < & ' data Self > {
500
+ fn parse < ' data , R : ReadRef < ' data > > ( data : R , offset : u64 ) -> read:: Result < & ' data Self > {
484
501
let header = data
485
- . read_at :: < Self > ( 0 )
502
+ . read_at :: < Self > ( offset )
486
503
. read_error ( "Invalid Mach-O header size or alignment" ) ?;
487
504
if !header. is_supported ( ) {
488
505
return Err ( Error ( "Unsupported Mach-O header" ) ) ;
@@ -502,10 +519,11 @@ pub trait MachHeader: Debug + Pod {
502
519
& self ,
503
520
endian : Self :: Endian ,
504
521
data : R ,
522
+ header_offset : u64 ,
505
523
) -> Result < LoadCommandIterator < ' data , Self :: Endian > > {
506
524
let data = data
507
525
. read_bytes_at (
508
- mem:: size_of :: < Self > ( ) as u64 ,
526
+ header_offset + mem:: size_of :: < Self > ( ) as u64 ,
509
527
self . sizeofcmds ( endian) . into ( ) ,
510
528
)
511
529
. read_error ( "Invalid Mach-O load command table size" ) ?;
@@ -517,8 +535,9 @@ pub trait MachHeader: Debug + Pod {
517
535
& self ,
518
536
endian : Self :: Endian ,
519
537
data : R ,
538
+ header_offset : u64 ,
520
539
) -> Result < Option < [ u8 ; 16 ] > > {
521
- let mut commands = self . load_commands ( endian, data) ?;
540
+ let mut commands = self . load_commands ( endian, data, header_offset ) ?;
522
541
while let Some ( command) = commands. next ( ) ? {
523
542
if let Ok ( Some ( uuid) ) = command. uuid ( ) {
524
543
return Ok ( Some ( uuid. uuid ) ) ;
0 commit comments