Skip to content

Commit fcd6eeb

Browse files
author
ligma
committed
refactored
1 parent 9e21e44 commit fcd6eeb

File tree

3 files changed

+47
-48
lines changed

3 files changed

+47
-48
lines changed

src/header.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use std::io::Read;
33

44
use byteorder::ReadBytesExt;
55

6+
#[derive(Debug)]
67
pub enum MachHeader {
78
MH32(MachHeader32),
89
MH64(MachHeader64),
@@ -31,6 +32,7 @@ impl MachHeader {
3132
}
3233
}
3334

35+
#[derive(Debug)]
3436
#[repr(C)]
3537
pub struct MachHeader32 {
3638
pub magic: u32,
@@ -57,6 +59,7 @@ impl MachHeader32 {
5759
}
5860
}
5961

62+
#[derive(Debug)]
6063
#[repr(C)]
6164
pub struct MachHeader64 {
6265
pub magic: u32,

src/main.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,11 @@ struct Args {
3232
load_commands: bool,
3333
}
3434

35+
// TODO: createt a new mod called "error.rs" which main will send errors to in order to be handled
3536
fn main() {
3637
let args = Args::parse();
3738
let mach_o = match File::open(&args.file.as_path()) {
38-
Ok(mut file) => parser::parse(&mut file),
39+
Ok(mut file) => parser::parse(&mut file).unwrap(),
3940
Err(e) => panic!("Error: Could not open input file for reading! {}", e),
4041
};
4142

src/parser.rs

Lines changed: 42 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -9,58 +9,58 @@ use crate::load_commands::*;
99
use crate::mach_o::MachO;
1010
use 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

4643
fn 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

5451
fn 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

111105
fn 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

Comments
 (0)