macho_core/format/
macho.rs1use crate::error::{Error, Result};
2use crate::format::ParseLimits;
3use crate::format::constants::MachoHeaderFlags;
4use crate::format::io::pod::{self, RawMachHeader32, RawMachHeader64};
5use crate::model::header::*;
6use crate::model::macho_file::MachoFile;
7
8pub fn parse_macho_file(data: &[u8]) -> Result<MachoFile<'_>> {
10 parse_macho_file_with_limits(data, &ParseLimits::default())
11}
12
13pub(crate) fn parse_macho_file_with_limits<'data>(
14 data: &'data [u8],
15 limits: &ParseLimits,
16) -> Result<MachoFile<'data>> {
17 if data.len() < 4 {
18 return Err(Error::format("file too small for Mach-O magic"));
19 }
20
21 let magic_val = u32::from_ne_bytes(data[0..4].try_into().unwrap());
22 let magic = MagicNumber::from_u32(magic_val)?;
23 let endian = magic.endian();
24 let bitness = magic.bitness();
25
26 let header = match bitness {
27 Bitness::Bits32 => {
28 let raw: RawMachHeader32 = pod::read_pod(data, 0)?;
29 MachoHeader {
30 magic,
31 cpu_type: CpuType(endian.interpret_i32(raw.cputype)),
32 cpu_subtype: CpuSubtype(endian.interpret_i32(raw.cpusubtype)),
33 file_type: FileType::from_u32(endian.interpret_u32(raw.filetype)),
34 ncmds: endian.interpret_u32(raw.ncmds),
35 sizeofcmds: endian.interpret_u32(raw.sizeofcmds),
36 flags: MachoHeaderFlags::from_bits_truncate(endian.interpret_u32(raw.flags)),
37 reserved: 0,
38 }
39 }
40 Bitness::Bits64 => {
41 let raw: RawMachHeader64 = pod::read_pod(data, 0)?;
42 MachoHeader {
43 magic,
44 cpu_type: CpuType(endian.interpret_i32(raw.cputype)),
45 cpu_subtype: CpuSubtype(endian.interpret_i32(raw.cpusubtype)),
46 file_type: FileType::from_u32(endian.interpret_u32(raw.filetype)),
47 ncmds: endian.interpret_u32(raw.ncmds),
48 sizeofcmds: endian.interpret_u32(raw.sizeofcmds),
49 flags: MachoHeaderFlags::from_bits_truncate(endian.interpret_u32(raw.flags)),
50 reserved: endian.interpret_u32(raw.reserved),
51 }
52 }
53 };
54
55 let lc_offset = bitness.header_size();
56 let (load_commands, segments) = crate::format::load_commands::parse_load_commands_with_limits(
57 data,
58 endian,
59 lc_offset,
60 header.ncmds,
61 header.sizeofcmds,
62 limits,
63 )?;
64
65 MachoFile::new(data, header, load_commands, segments, endian, bitness)
66}