@@ -9,58 +9,58 @@ use crate::load_commands::*;
99use crate :: mach_o:: MachO ;
1010use crate :: memory_utils:: { advance_to_next_load_command, get_file_offset} ;
1111
12- pub fn parse < R : Read + Seek > ( file : & mut R ) -> MachO {
13- let magic = file. read_u32 :: < BigEndian > ( ) . unwrap ( ) ;
12+ pub fn parse < R : Read + Seek > ( file : & mut R ) -> io:: Result < MachO > {
13+ let magic = file. read_u32 :: < BigEndian > ( ) ?;
14+ check_magic_number ( magic) ?;
1415
15- // TODO: use high order function to execute_with_endian(<func>, <magic>) to minimize boilerplate
16- let header = match magic {
17- MH_MAGIC | MH_MAGIC_64 => match parse_header :: < R , BigEndian > ( file, magic) {
18- Ok ( header ) => header,
19- Err ( e ) => panic ! ( "Error on header parsing: {}" , e ) ,
16+ let ( header , load_commands ) = match magic {
17+ MH_MAGIC | MH_MAGIC_64 => {
18+ let header = parse_header :: < R , BigEndian > ( file, magic) ? ;
19+ let load_commands = parse_load_commands :: < R , BigEndian > ( file , & header) ? ;
20+ ( header, load_commands )
2021 } ,
21- MH_CIGAM | MH_CIGAM_64 => match parse_header :: < R , LittleEndian > ( file, magic) {
22- Ok ( header) => header,
23- Err ( e) => panic ! ( "Error on header parsing: {}" , e) ,
22+ MH_CIGAM | MH_CIGAM_64 => {
23+ let header = parse_header :: < R , LittleEndian > ( file, magic) ?;
24+ let load_commands = parse_load_commands :: < R , LittleEndian > ( file, & header) ?;
25+ ( header, load_commands)
2426 } ,
25- _ => panic ! ( "Invalid magic number!" ) ,
27+ _ => unreachable ! ( ) ,
2628 } ;
2729
28- let load_commands = match magic {
29- MH_MAGIC | MH_MAGIC_64 => match parse_load_commands :: < R , BigEndian > ( file, & header) {
30- Ok ( load_commands) => load_commands,
31- Err ( e) => panic ! ( "Error on load commands parsing: {}" , e) ,
32- } ,
33- MH_CIGAM | MH_CIGAM_64 => match parse_load_commands :: < R , LittleEndian > ( file, & header) {
34- Ok ( load_commands) => load_commands,
35- Err ( e) => panic ! ( "Error on load commands parsing: {}" , e) ,
36- } ,
37- _ => panic ! ( "Invalid magic number!" ) ,
38- } ;
39-
40- MachO {
30+ Ok ( MachO {
4131 header,
4232 load_commands,
33+ } )
34+ }
35+
36+ fn check_magic_number ( magic : u32 ) -> io:: Result < ( ) > {
37+ match magic {
38+ MH_MAGIC | MH_MAGIC_64 | MH_CIGAM | MH_CIGAM_64 => Ok ( ( ) ) ,
39+ _ => Err ( io:: Error :: new ( io:: ErrorKind :: InvalidData , "Invalid Mach-O magic number" ) )
4340 }
4441}
4542
4643fn parse_header < R : Read + Seek , E : ByteOrder > ( file : & mut R , magic : u32 ) -> io:: Result < MachHeader > {
4744 match magic {
4845 MH_MAGIC | MH_CIGAM => MachHeader32 :: from_file :: < R , E > ( file, magic) ,
4946 MH_MAGIC_64 | MH_CIGAM_64 => MachHeader64 :: from_file :: < R , E > ( file, magic) ,
50- _ => return Err ( io :: Error :: new ( io :: ErrorKind :: InvalidData , "Invalid magic number!" ) )
47+ _ => unreachable ! ( ) ,
5148 }
5249}
5350
5451fn parse_load_commands < R : Read + Seek , E : ByteOrder > ( file : & mut R , header : & MachHeader ) -> io:: Result < ( Vec < LoadCommand > , Vec < LcStr > ) > {
5552 let mut load_commands: Vec < LoadCommand > = Vec :: new ( ) ;
5653 let mut load_commands_strings: Vec < LcStr > = Vec :: new ( ) ;
54+
5755 for _ in 0 ..header. ncmds ( ) {
5856 let offset = get_file_offset ( file) ?;
5957 let load_command_prefix = LoadCommandPrefix :: from_file :: < R , E > ( file) ?;
6058 let load_command = parse_command :: < R , E > ( file, & load_command_prefix) ?;
6159 let load_command_string = parse_load_command_string :: < R , E > ( file, & load_command, offset, load_command_prefix. cmdsize ) ?;
60+
6261 load_commands. push ( load_command) ;
6362 load_commands_strings. push ( load_command_string) ;
63+
6464 advance_to_next_load_command ( file, offset, load_command_prefix. cmdsize as u64 ) ?;
6565 }
6666 Ok ( ( load_commands, load_commands_strings) )
@@ -72,11 +72,7 @@ fn parse_command<R: Read, E: ByteOrder>(file: &mut R, load_command_prefix: &Load
7272 LC_SYMTAB => SymtabCommand :: from_file :: < R , E > ( file, load_command_prefix) ,
7373 LC_SYMSEG => SymsegCommand :: from_file :: < R , E > ( file, load_command_prefix) ,
7474 LC_THREAD | LC_UNIXTHREAD => ThreadCommand :: from_file :: < E > ( load_command_prefix) ,
75- // TODO: LC_LOADFVMLIB => (Maybe implement?),
76- // TODO: LC_IDFVMLIB => (Maybe implement?),
7775 LC_IDENT => IdentCommand :: from_file :: < E > ( load_command_prefix) ,
78- // TODO: LC_FVMFILE => (skip. apple's internal use),
79- // TODO: LC_PREPAGE => (skip. apple's internal use),
8076 LC_DYSYMTAB => DynSymtabCommand :: from_file :: < R , E > ( file, load_command_prefix) ,
8177 LC_LOAD_DYLIB | LC_ID_DYLIB | LC_LOAD_WEAK_DYLIB | LC_REEXPORT_DYLIB => DylibCommand :: from_file :: < R , E > ( file, load_command_prefix) ,
8278 LC_LOAD_DYLINKER | LC_ID_DYLINKER | LC_DYLD_ENVIRONMENT => DylinkerCommand :: from_file :: < R , E > ( file, load_command_prefix) ,
@@ -93,39 +89,38 @@ fn parse_command<R: Read, E: ByteOrder>(file: &mut R, load_command_prefix: &Load
9389 LC_UUID => UuidCommand :: from_file :: < R , E > ( file, load_command_prefix) ,
9490 LC_RPATH => RpathCommand :: from_file :: < R , E > ( file, load_command_prefix) ,
9591 LC_CODE_SIGNATURE | LC_SEGMENT_SPLIT_INFO | LC_FUNCTION_STARTS | LC_DATA_IN_CODE | LC_DYLIB_CODE_SIGN_DRS | LC_LINKER_OPTIMIZATION_HINT => LinkeditDataCommand :: from_file :: < R , E > ( file, load_command_prefix) ,
96- // TODO: LC_LAZY_LOAD_DYLIB => (Maybe implement?),
9792 LC_ENCRYPTION_INFO => EncryptionInfoCommand32 :: from_file :: < R , E > ( file, load_command_prefix) ,
9893 LC_DYLD_INFO | LC_DYLD_INFO_ONLY => DyldInfoCommand :: from_file :: < R , E > ( file, load_command_prefix) ,
99- // TODO: LC_LOAD_UPWARD_DYLIB => (Maybe implement?),
10094 LC_VERSION_MIN_MACOSX | LC_VERSION_MIN_IPHONEOS | LC_VERSION_MIN_TVOS | LC_VERSION_MIN_WATCHOS => SegmentCommand32 :: from_file :: < R , E > ( file, load_command_prefix) ,
10195 LC_MAIN => EntryPointCommand :: from_file :: < R , E > ( file, load_command_prefix) ,
10296 LC_SOURCE_VERSION => SourceVersionCommand :: from_file :: < R , E > ( file, load_command_prefix) ,
10397 LC_ENCRYPTION_INFO_64 => EncryptionInfoCommand64 :: from_file :: < R , E > ( file, load_command_prefix) ,
10498 LC_LINKER_OPTION => LinkerOptionCommand :: from_file :: < R , E > ( file, load_command_prefix) ,
10599 LC_NOTE => NoteCommand :: from_file :: < R , E > ( file, load_command_prefix) ,
106100 LC_BUILD_VERSION => BuildVersionCommand :: from_file :: < R , E > ( file, load_command_prefix) ,
107- _ => return Err ( io:: Error :: new ( io:: ErrorKind :: InvalidData , "unknown load command type!" , ) )
101+ _ => Err ( io:: Error :: new ( io:: ErrorKind :: InvalidData , "unknown load command type!" ) )
108102 }
109103}
110104
111105fn parse_load_command_string < R : Read + Seek , E : ByteOrder > ( file : & mut R , load_command : & LoadCommand , lc_offset : u64 , cmdsize : u32 ) -> io:: Result < LcStr > {
112106 let mut load_command_string = Vec :: new ( ) ;
113107 match load_command {
114- LoadCommand :: DylibCommand ( _) => { }
115- LoadCommand :: SubFrameWorkCommand ( _) => { }
116- LoadCommand :: SubClientCommand ( _) => { }
117- LoadCommand :: SubUmbrellaCommand ( _) => { }
118- LoadCommand :: SubLibraryCommand ( _) => { }
119- LoadCommand :: PreboundDylibCommand ( _) => { }
120- LoadCommand :: DylinkerCommand ( _) => { }
121- LoadCommand :: RpathCommand ( _) => { }
122- _ => return Ok ( load_command_string)
123- }
124- let remaining_size = get_load_command_remaining_size ( lc_offset, cmdsize as u64 , get_file_offset ( file) ?) ?;
125- if remaining_size > 0 {
126- for _ in 0 ..remaining_size {
127- load_command_string. push ( file. read_u8 ( ) ?) ;
128- }
108+ LoadCommand :: DylibCommand ( _) |
109+ LoadCommand :: SubFrameWorkCommand ( _) |
110+ LoadCommand :: SubClientCommand ( _) |
111+ LoadCommand :: SubUmbrellaCommand ( _) |
112+ LoadCommand :: SubLibraryCommand ( _) |
113+ LoadCommand :: PreboundDylibCommand ( _) |
114+ LoadCommand :: DylinkerCommand ( _) |
115+ LoadCommand :: RpathCommand ( _) => {
116+ let remaining_size = get_load_command_remaining_size ( lc_offset, cmdsize as u64 , get_file_offset ( file) ?) ?;
117+ if remaining_size > 0 {
118+ for _ in 0 ..remaining_size {
119+ load_command_string. push ( file. read_u8 ( ) ?) ;
120+ }
121+ }
122+ } ,
123+ _ => { }
129124 }
130125 Ok ( load_command_string)
131126}
0 commit comments