use std::mem;
use std::fmt;
use std::fs::File;
use std::io::{self, Seek, Read};
use std::io::SeekFrom::Start;
pub const MH_NOUNDEFS: u32 = 0x1;
pub const MH_INCRLINK: u32 = 0x2;
pub const MH_DYLDLINK: u32 = 0x4;
pub const MH_BINDATLOAD: u32 = 0x8;
pub const MH_PREBOUND: u32 = 0x10;
pub const MH_SPLIT_SEGS: u32 = 0x20;
pub const MH_LAZY_INIT: u32 = 0x40;
pub const MH_TWOLEVEL: u32 = 0x80;
pub const MH_FORCE_FLAT: u32 = 0x100;
pub const MH_NOMULTIDEFS: u32 = 0x200;
pub const MH_NOFIXPREBINDING: u32 = 0x400;
pub const MH_PREBINDABLE: u32 = 0x800;
pub const MH_ALLMODSBOUND: u32 = 0x1000;
pub const MH_SUBSECTIONS_VIA_SYMBOLS: u32 = 0x2000;
pub const MH_CANONICAL: u32 = 0x4000;
pub const MH_WEAK_DEFINES: u32 = 0x8000;
pub const MH_BINDS_TO_WEAK: u32 = 0x10000;
pub const MH_ALLOW_STACK_EXECUTION: u32 = 0x20000;
pub const MH_ROOT_SAFE: u32 = 0x40000;
pub const MH_SETUID_SAFE: u32 = 0x80000;
pub const MH_NO_REEXPORTED_DYLIBS: u32 = 0x100000;
pub const MH_PIE: u32 = 0x200000;
pub const MH_DEAD_STRIPPABLE_DYLIB: u32 = 0x400000;
pub const MH_HAS_TLV_DESCRIPTORS: u32 = 0x800000;
pub const MH_NO_HEAP_EXECUTION: u32 = 0x1000000;
pub const MH_APP_EXTENSION_SAFE: u32 = 0x2000000;
#[inline(always)]
pub fn flag_to_str(flag: u32) -> &'static str {
match flag {
MH_NOUNDEFS => "MH_NOUNDEFS",
MH_INCRLINK => "MH_INCRLINK",
MH_DYLDLINK => "MH_DYLDLINK",
MH_BINDATLOAD => "MH_BINDATLOAD",
MH_PREBOUND => "MH_PREBOUND",
MH_SPLIT_SEGS => "MH_SPLIT_SEGS",
MH_LAZY_INIT => "MH_LAZY_INIT",
MH_TWOLEVEL => "MH_TWOLEVEL",
MH_FORCE_FLAT => "MH_FORCE_FLAT",
MH_NOMULTIDEFS => "MH_NOMULTIDEFS",
MH_NOFIXPREBINDING => "MH_NOFIXPREBINDING",
MH_PREBINDABLE => "MH_PREBINDABLE ",
MH_ALLMODSBOUND => "MH_ALLMODSBOUND",
MH_SUBSECTIONS_VIA_SYMBOLS => "MH_SUBSECTIONS_VIA_SYMBOLS",
MH_CANONICAL => "MH_CANONICAL",
MH_WEAK_DEFINES => "MH_WEAK_DEFINES",
MH_BINDS_TO_WEAK => "MH_BINDS_TO_WEAK",
MH_ALLOW_STACK_EXECUTION => "MH_ALLOW_STACK_EXECUTION",
MH_ROOT_SAFE => "MH_ROOT_SAFE",
MH_SETUID_SAFE => "MH_SETUID_SAFE",
MH_NO_REEXPORTED_DYLIBS => "MH_NO_REEXPORTED_DYLIBS",
MH_PIE => "MH_PIE",
MH_DEAD_STRIPPABLE_DYLIB => "MH_DEAD_STRIPPABLE_DYLIB",
MH_HAS_TLV_DESCRIPTORS => "MH_HAS_TLV_DESCRIPTORS",
MH_NO_HEAP_EXECUTION => "MH_NO_HEAP_EXECUTION",
MH_APP_EXTENSION_SAFE => "MH_APP_EXTENSION_SAFE",
_ => "UNKNOWN FLAG",
}
}
pub const MH_MAGIC: u32 = 0xfeedface;
pub const MH_CIGAM: u32 = 0xcefaedfe;
pub const MH_MAGIC_64: u32 = 0xfeedfacf;
pub const MH_CIGAM_64: u32 = 0xcffaedfe;
pub const MH_OBJECT: u32 = 0x1;
pub const MH_EXECUTE: u32 = 0x2;
pub const MH_FVMLIB: u32 = 0x3;
pub const MH_CORE: u32 = 0x4;
pub const MH_PRELOAD: u32 = 0x5;
pub const MH_DYLIB: u32 = 0x6;
pub const MH_DYLINKER: u32 = 0x7;
pub const MH_BUNDLE: u32 = 0x8;
pub const MH_DYLIB_STUB: u32 = 0x9;
pub const MH_DSYM: u32 = 0xa;
pub const MH_KEXT_BUNDLE: u32 = 0xb;
pub fn filetype_to_str(filetype: u32) -> &'static str {
match filetype {
MH_OBJECT => "OBJECT",
MH_EXECUTE => "EXECUTE",
MH_FVMLIB => "FVMLIB",
MH_CORE => "CORE",
MH_PRELOAD => "PRELOAD",
MH_DYLIB => "DYLIB",
MH_DYLINKER => "DYLINKER",
MH_BUNDLE => "BUNDLE",
MH_DYLIB_STUB => "DYLIB_STUB",
MH_DSYM => "DSYM",
MH_KEXT_BUNDLE => "KEXT_BUNDLE",
_ => "UNKNOWN FILETYPE",
}
}
#[repr(C)]
#[derive(Clone, Copy, Default)]
pub struct Header {
pub magic: u32,
pub cputype: u32,
pub cpusubtype: u8,
pub padding1: u8,
pub padding2: u8,
pub caps: u8,
pub filetype: u32,
pub ncmds: u32,
pub sizeofcmds: u32,
pub flags: u32,
pub reserved: u32,
}
pub const SIZEOF_MACH_HEADER: usize = 32;
impl fmt::Debug for Header {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f,
"0x{:x} {} {} 0x{:x} {} {} {} 0x{:x} 0x{:x}",
self.magic,
self.cputype,
self.cpusubtype,
self.caps,
filetype_to_str(self.filetype),
self.ncmds,
self.sizeofcmds,
self.flags,
self.reserved)
}
}
impl Header {
pub fn from_bytes(bytes: &[u8; SIZEOF_MACH_HEADER]) -> &Header {
let header: &Header = unsafe { mem::transmute(bytes) };
header
}
pub fn from_fd(fd: &mut File, offset: u64) -> io::Result<Header> {
let mut header = [0; SIZEOF_MACH_HEADER];
try!(fd.seek(Start(offset)));
try!(fd.read(&mut header));
Ok(*Header::from_bytes(&header))
}
}