#![allow(missing_docs)]
#[cfg(feature = "names")]
use crate::constants::{ConstantNames, FlagNames};
use crate::endian::{BigEndian, Endian, U16, U32, U64};
use crate::pod::Pod;
#[cfg(feature = "names")]
#[derive(Debug)]
#[non_exhaustive]
pub struct Names {
pub cpusubtype: &'static FlagNames<CpuSubtype>,
pub reloc: &'static ConstantNames<RelocationType>,
}
#[cfg(feature = "names")]
pub const fn names() -> &'static Names {
Base::names()
}
#[cfg(feature = "names")]
pub const fn machine_names(cputype: CpuType) -> &'static Names {
match cputype {
CPU_TYPE_X86 => X86::names(),
CPU_TYPE_X86_64 => X86_64::names(),
CPU_TYPE_ARM => Arm::names(),
CPU_TYPE_ARM64 => Arm64::names(),
CPU_TYPE_ARM64_32 => Arm64_32::names(),
CPU_TYPE_POWERPC | CPU_TYPE_POWERPC64 => Ppc::names(),
_ => Base::names(),
}
}
names! {
struct Base;
flags cpusubtype = NAMES_CPU_SUBTYPE;
consts reloc: RelocationType(u8) = {};
}
names! {
struct X86(Base);
flags cpusubtype = NAMES_CPU_SUBTYPE_X86;
consts reloc = NAMES_GENERIC_RELOC;
}
names! {
struct X86_64(Base);
flags cpusubtype = NAMES_CPU_SUBTYPE_X86_64;
consts reloc = NAMES_X86_64_RELOC;
}
names! {
struct Arm(Base);
flags cpusubtype = NAMES_CPU_SUBTYPE_ARM;
consts reloc = NAMES_ARM_RELOC;
}
names! {
struct Arm64(Base);
flags cpusubtype = NAMES_CPU_SUBTYPE_ARM64;
consts reloc = NAMES_ARM64_RELOC;
}
names! {
struct Arm64_32(Base);
flags cpusubtype = NAMES_CPU_SUBTYPE_ARM64_32;
consts reloc = NAMES_ARM64_RELOC;
}
names! {
struct Ppc(Base);
flags cpusubtype = NAMES_CPU_SUBTYPE_POWERPC;
consts reloc = NAMES_PPC_RELOC;
}
pub const CPU_ARCH_MASK: u32 = 0xff00_0000;
pub const CPU_ARCH_ABI64: u32 = 0x0100_0000;
pub const CPU_ARCH_ABI64_32: u32 = 0x0200_0000;
newtype!(
struct CpuType(u32);
);
newtype_constant_names!(NAMES_CPU_TYPE: CpuType(u32) = {
CPU_TYPE_ANY = !0,
CPU_TYPE_VAX = 1,
CPU_TYPE_MC680X0 = 6,
CPU_TYPE_X86 = 7,
CPU_TYPE_I386 = CPU_TYPE_X86.0,
CPU_TYPE_X86_64 = CPU_TYPE_X86.0 | CPU_ARCH_ABI64,
CPU_TYPE_MIPS = 8,
CPU_TYPE_MC98000 = 10,
CPU_TYPE_HPPA = 11,
CPU_TYPE_ARM = 12,
CPU_TYPE_ARM64 = CPU_TYPE_ARM.0 | CPU_ARCH_ABI64,
CPU_TYPE_ARM64_32 = CPU_TYPE_ARM.0 | CPU_ARCH_ABI64_32,
CPU_TYPE_MC88000 = 13,
CPU_TYPE_SPARC = 14,
CPU_TYPE_I860 = 15,
CPU_TYPE_ALPHA = 16,
CPU_TYPE_POWERPC = 18,
CPU_TYPE_POWERPC64 = CPU_TYPE_POWERPC.0 | CPU_ARCH_ABI64,
});
newtype!(
struct CpuSubtypeId(u32);
);
impl core::fmt::Debug for CpuSubtypeId {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{:#x}", self)
}
}
newtype!(
struct CpuSubtype(u32);
);
impl CpuSubtype {
pub fn id(self) -> CpuSubtypeId {
CpuSubtypeId(self.0 & !CPU_SUBTYPE_MASK)
}
pub fn with_id(self, id: CpuSubtypeId) -> CpuSubtype {
CpuSubtype(self.0 & CPU_SUBTYPE_MASK | id.0 & !CPU_SUBTYPE_MASK)
}
}
impl From<CpuSubtypeId> for CpuSubtype {
fn from(s: CpuSubtypeId) -> Self {
CpuSubtype(s.0)
}
}
impl From<CpuSubtype> for CpuSubtypeId {
fn from(value: CpuSubtype) -> Self {
value.id()
}
}
impl core::ops::BitOr<CpuSubtype> for CpuSubtypeId {
type Output = CpuSubtype;
fn bitor(self, rhs: CpuSubtype) -> CpuSubtype {
rhs.with_id(self)
}
}
pub const CPU_SUBTYPE_MASK: u32 = 0xff00_0000;
newtype_flag_names!(NAMES_CPU_SUBTYPE: CpuSubtype(u32) = {
CPU_SUBTYPE_LIB64 = 0x8000_0000,
});
pub const CPU_SUBTYPE_ANY: CpuSubtype = CpuSubtype(!0);
pub const CPU_SUBTYPE_MULTIPLE: CpuSubtype = CpuSubtype(!0);
newtype_consts!(CpuSubtypeId = {
CPU_SUBTYPE_LITTLE_ENDIAN = 0,
CPU_SUBTYPE_BIG_ENDIAN = 1,
});
newtype_consts!(CpuSubtypeId = {
CPU_SUBTYPE_VAX_ALL = 0,
CPU_SUBTYPE_VAX780 = 1,
CPU_SUBTYPE_VAX785 = 2,
CPU_SUBTYPE_VAX750 = 3,
CPU_SUBTYPE_VAX730 = 4,
CPU_SUBTYPE_UVAXI = 5,
CPU_SUBTYPE_UVAXII = 6,
CPU_SUBTYPE_VAX8200 = 7,
CPU_SUBTYPE_VAX8500 = 8,
CPU_SUBTYPE_VAX8600 = 9,
CPU_SUBTYPE_VAX8650 = 10,
CPU_SUBTYPE_VAX8800 = 11,
CPU_SUBTYPE_UVAXIII = 12,
});
newtype_consts!(CpuSubtypeId = {
CPU_SUBTYPE_MC680X0_ALL = 1,
CPU_SUBTYPE_MC68030 = 1,
CPU_SUBTYPE_MC68040 = 2,
CPU_SUBTYPE_MC68030_ONLY = 3,
});
#[inline]
pub const fn cpu_subtype_intel(f: u32, m: u32) -> u32 {
f + (m << 4)
}
newtype_consts!(CpuSubtypeId = {
CPU_SUBTYPE_I386_ALL = cpu_subtype_intel(3, 0),
CPU_SUBTYPE_386 = cpu_subtype_intel(3, 0),
CPU_SUBTYPE_486 = cpu_subtype_intel(4, 0),
CPU_SUBTYPE_486SX = cpu_subtype_intel(4, 8),
CPU_SUBTYPE_586 = cpu_subtype_intel(5, 0),
CPU_SUBTYPE_PENT = cpu_subtype_intel(5, 0),
CPU_SUBTYPE_PENTPRO = cpu_subtype_intel(6, 1),
CPU_SUBTYPE_PENTII_M3 = cpu_subtype_intel(6, 3),
CPU_SUBTYPE_PENTII_M5 = cpu_subtype_intel(6, 5),
CPU_SUBTYPE_CELERON = cpu_subtype_intel(7, 6),
CPU_SUBTYPE_CELERON_MOBILE = cpu_subtype_intel(7, 7),
CPU_SUBTYPE_PENTIUM_3 = cpu_subtype_intel(8, 0),
CPU_SUBTYPE_PENTIUM_3_M = cpu_subtype_intel(8, 1),
CPU_SUBTYPE_PENTIUM_3_XEON = cpu_subtype_intel(8, 2),
CPU_SUBTYPE_PENTIUM_M = cpu_subtype_intel(9, 0),
CPU_SUBTYPE_PENTIUM_4 = cpu_subtype_intel(10, 0),
CPU_SUBTYPE_PENTIUM_4_M = cpu_subtype_intel(10, 1),
CPU_SUBTYPE_ITANIUM = cpu_subtype_intel(11, 0),
CPU_SUBTYPE_ITANIUM_2 = cpu_subtype_intel(11, 1),
CPU_SUBTYPE_XEON = cpu_subtype_intel(12, 0),
CPU_SUBTYPE_XEON_MP = cpu_subtype_intel(12, 1),
});
#[inline]
pub const fn cpu_subtype_intel_family(x: CpuSubtypeId) -> u32 {
x.0 & 15
}
pub const CPU_SUBTYPE_INTEL_FAMILY_MAX: u32 = 15;
#[inline]
pub const fn cpu_subtype_intel_model(x: CpuSubtypeId) -> u32 {
x.0 >> 4
}
pub const CPU_SUBTYPE_INTEL_MODEL_ALL: u32 = 0;
flag_names!(NAMES_CPU_SUBTYPE_X86: CpuSubtype(u32) = NAMES_CPU_SUBTYPE + {
_ = !CPU_SUBTYPE_MASK => NAMES_CPU_SUBTYPE_ID_X86,
});
constant_names!(NAMES_CPU_SUBTYPE_ID_X86: CpuSubtypeId(u32) = {
CPU_SUBTYPE_X86_ALL = 3,
CPU_SUBTYPE_X86_ARCH1 = 4,
});
flag_names!(NAMES_CPU_SUBTYPE_X86_64: CpuSubtype(u32) = NAMES_CPU_SUBTYPE + {
_ = !CPU_SUBTYPE_MASK => NAMES_CPU_SUBTYPE_ID_X86_64,
});
constant_names!(NAMES_CPU_SUBTYPE_ID_X86_64: CpuSubtypeId(u32) = {
CPU_SUBTYPE_X86_64_ALL = 3,
CPU_SUBTYPE_X86_64_H = 8,
});
newtype_consts!(CpuSubtypeId = {
CPU_SUBTYPE_MIPS_ALL = 0,
CPU_SUBTYPE_MIPS_R2300 = 1,
CPU_SUBTYPE_MIPS_R2600 = 2,
CPU_SUBTYPE_MIPS_R2800 = 3,
CPU_SUBTYPE_MIPS_R2000A = 4,
CPU_SUBTYPE_MIPS_R2000 = 5,
CPU_SUBTYPE_MIPS_R3000A = 6,
CPU_SUBTYPE_MIPS_R3000 = 7,
});
newtype_consts!(CpuSubtypeId = {
CPU_SUBTYPE_MC98000_ALL = 0,
CPU_SUBTYPE_MC98601 = 1,
});
newtype_consts!(CpuSubtypeId = {
CPU_SUBTYPE_HPPA_ALL = 0,
CPU_SUBTYPE_HPPA_7100 = 0,
CPU_SUBTYPE_HPPA_7100LC = 1,
});
newtype_consts!(CpuSubtypeId = {
CPU_SUBTYPE_MC88000_ALL = 0,
CPU_SUBTYPE_MC88100 = 1,
CPU_SUBTYPE_MC88110 = 2,
});
newtype_consts!(CpuSubtypeId = {
CPU_SUBTYPE_SPARC_ALL = 0,
});
newtype_consts!(CpuSubtypeId = {
CPU_SUBTYPE_I860_ALL = 0,
CPU_SUBTYPE_I860_860 = 1,
});
flag_names!(NAMES_CPU_SUBTYPE_POWERPC: CpuSubtype(u32) = NAMES_CPU_SUBTYPE + {
_ = !CPU_SUBTYPE_MASK => NAMES_CPU_SUBTYPE_ID_POWERPC,
});
constant_names!(NAMES_CPU_SUBTYPE_ID_POWERPC: CpuSubtypeId(u32) = {
CPU_SUBTYPE_POWERPC_ALL = 0,
CPU_SUBTYPE_POWERPC_601 = 1,
CPU_SUBTYPE_POWERPC_602 = 2,
CPU_SUBTYPE_POWERPC_603 = 3,
CPU_SUBTYPE_POWERPC_603E = 4,
CPU_SUBTYPE_POWERPC_603EV = 5,
CPU_SUBTYPE_POWERPC_604 = 6,
CPU_SUBTYPE_POWERPC_604E = 7,
CPU_SUBTYPE_POWERPC_620 = 8,
CPU_SUBTYPE_POWERPC_750 = 9,
CPU_SUBTYPE_POWERPC_7400 = 10,
CPU_SUBTYPE_POWERPC_7450 = 11,
CPU_SUBTYPE_POWERPC_970 = 100,
});
flag_names!(NAMES_CPU_SUBTYPE_ARM: CpuSubtype(u32) = NAMES_CPU_SUBTYPE + {
_ = !CPU_SUBTYPE_MASK => NAMES_CPU_SUBTYPE_ID_ARM,
});
constant_names!(NAMES_CPU_SUBTYPE_ID_ARM: CpuSubtypeId(u32) = {
CPU_SUBTYPE_ARM_ALL = 0,
CPU_SUBTYPE_ARM_V4T = 5,
CPU_SUBTYPE_ARM_V6 = 6,
CPU_SUBTYPE_ARM_V5TEJ = 7,
CPU_SUBTYPE_ARM_XSCALE = 8,
CPU_SUBTYPE_ARM_V7 = 9,
CPU_SUBTYPE_ARM_V7F = 10,
CPU_SUBTYPE_ARM_V7S = 11,
CPU_SUBTYPE_ARM_V7K = 12,
CPU_SUBTYPE_ARM_V8 = 13,
CPU_SUBTYPE_ARM_V6M = 14,
CPU_SUBTYPE_ARM_V7M = 15,
CPU_SUBTYPE_ARM_V7EM = 16,
CPU_SUBTYPE_ARM_V8M = 17,
CPU_SUBTYPE_ARM_V8M_MAIN = CPU_SUBTYPE_ARM_V8M.0,
CPU_SUBTYPE_ARM_V8M_BASE = 18,
CPU_SUBTYPE_ARM_V8_1M_MAIN = 19,
});
flag_names!(NAMES_CPU_SUBTYPE_ARM64: CpuSubtype(u32) = {
CPU_SUBTYPE_PTRAUTH_ABI = 0x8000_0000,
_ = !CPU_SUBTYPE_MASK => NAMES_CPU_SUBTYPE_ID_ARM64,
});
constant_names!(NAMES_CPU_SUBTYPE_ID_ARM64: CpuSubtypeId(u32) = {
CPU_SUBTYPE_ARM64_ALL = 0,
CPU_SUBTYPE_ARM64_V8 = 1,
CPU_SUBTYPE_ARM64E = 2,
});
pub const CPU_SUBTYPE_ARM64_PTR_AUTH_MASK: u32 = 0x0f000000;
impl CpuSubtype {
#[inline]
pub const fn arm64_ptr_auth_version(self) -> u32 {
(self.0 & CPU_SUBTYPE_ARM64_PTR_AUTH_MASK) >> 24
}
#[inline]
pub const fn with_arm64_ptr_auth_version(self, version: u32) -> CpuSubtype {
CpuSubtype(
self.0 & !CPU_SUBTYPE_ARM64_PTR_AUTH_MASK
| (version << 24) & CPU_SUBTYPE_ARM64_PTR_AUTH_MASK,
)
}
}
flag_names!(NAMES_CPU_SUBTYPE_ARM64_32: CpuSubtype(u32) = NAMES_CPU_SUBTYPE + {
_ = !CPU_SUBTYPE_MASK => NAMES_CPU_SUBTYPE_ID_ARM64_32,
});
constant_names!(NAMES_CPU_SUBTYPE_ID_ARM64_32: CpuSubtypeId(u32) = {
CPU_SUBTYPE_ARM64_32_ALL = 0,
CPU_SUBTYPE_ARM64_32_V8 = 1,
});
newtype!(
struct VmProt(u32);
);
newtype_flag_names!(NAMES_VM_PROT: VmProt(u32) = {
VM_PROT_READ = 0x01,
VM_PROT_WRITE = 0x02,
VM_PROT_EXECUTE = 0x04,
});
#[repr(u8)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum PtrauthKey {
IA = 0,
IB = 1,
DA = 2,
DB = 3,
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct DyldCacheHeader<E: Endian> {
pub magic: [u8; 16],
pub mapping_offset: U32<E>,
pub mapping_count: U32<E>,
pub images_offset_old: U32<E>,
pub images_count_old: U32<E>,
pub dyld_base_address: U64<E>,
pub code_signature_offset: U64<E>,
pub code_signature_size: U64<E>,
pub slide_info_offset_unused: U64<E>,
pub slide_info_size_unused: U64<E>,
pub local_symbols_offset: U64<E>,
pub local_symbols_size: U64<E>,
pub uuid: [u8; 16],
pub cache_type: U64<E>,
pub branch_pools_offset: U32<E>,
pub branch_pools_count: U32<E>,
pub dyld_in_cache_mh: U64<E>,
pub dyld_in_cache_entry: U64<E>,
pub images_text_offset: U64<E>,
pub images_text_count: U64<E>,
pub patch_info_addr: U64<E>,
pub patch_info_size: U64<E>,
pub other_image_group_addr_unused: U64<E>,
pub other_image_group_size_unused: U64<E>,
pub prog_closures_addr: U64<E>,
pub prog_closures_size: U64<E>,
pub prog_closures_trie_addr: U64<E>,
pub prog_closures_trie_size: U64<E>,
pub platform: U32<E>,
pub flags: U32<E>,
pub shared_region_start: U64<E>,
pub shared_region_size: U64<E>,
pub max_slide: U64<E>,
pub dylibs_image_array_addr: U64<E>,
pub dylibs_image_array_size: U64<E>,
pub dylibs_trie_addr: U64<E>,
pub dylibs_trie_size: U64<E>,
pub other_image_array_addr: U64<E>,
pub other_image_array_size: U64<E>,
pub other_trie_addr: U64<E>,
pub other_trie_size: U64<E>,
pub mapping_with_slide_offset: U32<E>,
pub mapping_with_slide_count: U32<E>,
pub dylibs_pbl_state_array_addr_unused: U64<E>,
pub dylibs_pbl_set_addr: U64<E>,
pub programs_pbl_set_pool_addr: U64<E>,
pub programs_pbl_set_pool_size: U64<E>,
pub program_trie_addr: U64<E>,
pub program_trie_size: U32<E>,
pub os_version: U32<E>,
pub alt_platform: U32<E>,
pub alt_os_version: U32<E>,
pub swift_opts_offset: U64<E>,
pub swift_opts_size: U64<E>,
pub sub_cache_array_offset: U32<E>,
pub sub_cache_array_count: U32<E>,
pub symbol_file_uuid: [u8; 16],
pub rosetta_read_only_addr: U64<E>,
pub rosetta_read_only_size: U64<E>,
pub rosetta_read_write_addr: U64<E>,
pub rosetta_read_write_size: U64<E>,
pub images_offset: U32<E>,
pub images_count: U32<E>,
pub cache_sub_type: U32<E>,
padding1: [u8; 4],
pub objc_opts_offset: U64<E>,
pub objc_opts_size: U64<E>,
pub cache_atlas_offset: U64<E>,
pub cache_atlas_size: U64<E>,
pub dynamic_data_offset: U64<E>,
pub dynamic_data_max_size: U64<E>,
pub tpro_mappings_offset: U32<E>,
pub tpro_mappings_count: U32<E>,
pub function_variant_info_addr: U64<E>,
pub function_variant_info_size: U64<E>,
pub prewarming_data_offset: U64<E>,
pub prewarming_data_size: U64<E>,
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct DyldCacheMappingInfo<E: Endian> {
pub address: U64<E>,
pub size: U64<E>,
pub file_offset: U64<E>,
pub max_prot: U32<E, VmProt>,
pub init_prot: U32<E, VmProt>,
}
newtype!(
struct DyldCacheMappingFlags(u64);
);
newtype_flag_names!(NAMES_DYLD_CACHE_MAPPING: DyldCacheMappingFlags(u64) = {
DYLD_CACHE_MAPPING_AUTH_DATA = 1 << 0,
DYLD_CACHE_MAPPING_DIRTY_DATA = 1 << 1,
DYLD_CACHE_MAPPING_CONST_DATA = 1 << 2,
DYLD_CACHE_MAPPING_TEXT_STUBS = 1 << 3,
DYLD_CACHE_DYNAMIC_CONFIG_DATA = 1 << 4,
DYLD_CACHE_READ_ONLY_DATA = 1 << 5,
DYLD_CACHE_MAPPING_CONST_TPRO_DATA = 1 << 6,
});
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct DyldCacheMappingAndSlideInfo<E: Endian> {
pub address: U64<E>,
pub size: U64<E>,
pub file_offset: U64<E>,
pub slide_info_file_offset: U64<E>,
pub slide_info_file_size: U64<E>,
pub flags: U64<E, DyldCacheMappingFlags>,
pub max_prot: U32<E, VmProt>,
pub init_prot: U32<E, VmProt>,
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct DyldCacheTproMappingInfo<E: Endian> {
pub unslid_address: U64<E>,
pub size: U64<E>,
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct DyldCacheImageInfo<E: Endian> {
pub address: U64<E>,
pub mod_time: U64<E>,
pub inode: U64<E>,
pub path_file_offset: U32<E>,
pub pad: U32<E>,
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct DyldCacheSlideInfo2<E: Endian> {
pub version: U32<E>, pub page_size: U32<E>, pub page_starts_offset: U32<E>,
pub page_starts_count: U32<E>,
pub page_extras_offset: U32<E>,
pub page_extras_count: U32<E>,
pub delta_mask: U64<E>, pub value_add: U64<E>,
}
pub const DYLD_CACHE_SLIDE_PAGE_ATTRS: u16 = 0xC000;
pub const DYLD_CACHE_SLIDE_PAGE_ATTR_EXTRA: u16 = 0x8000;
pub const DYLD_CACHE_SLIDE_PAGE_ATTR_NO_REBASE: u16 = 0x4000;
pub const DYLD_CACHE_SLIDE_PAGE_ATTR_END: u16 = 0x8000;
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct DyldCacheSlideInfo3<E: Endian> {
pub version: U32<E>, pub page_size: U32<E>, pub page_starts_count: U32<E>,
reserved1: [u8; 4],
pub auth_value_add: U64<E>,
}
pub const DYLD_CACHE_SLIDE_V3_PAGE_ATTR_NO_REBASE: u16 = 0xFFFF;
#[derive(Debug, Clone, Copy)]
pub struct DyldCacheSlidePointer3(pub u64);
impl DyldCacheSlidePointer3 {
pub fn is_auth(&self) -> bool {
((self.0 >> 63) & 1) != 0
}
pub fn target(&self) -> u64 {
self.0 & ((1 << 43) - 1)
}
pub fn high8(&self) -> u64 {
(self.0 >> 43) & 0xff
}
pub fn runtime_offset(&self) -> u64 {
self.0 & ((1 << 32) - 1)
}
pub fn diversity(&self) -> u16 {
((self.0 >> 32) & 0xffff) as u16
}
pub fn addr_div(&self) -> bool {
((self.0 >> 48) & 1) != 0
}
pub fn key(&self) -> u8 {
((self.0 >> 49) & 3) as u8
}
pub fn next(&self) -> u64 {
(self.0 >> 51) & ((1 << 11) - 1)
}
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct DyldCacheSlideInfo5<E: Endian> {
pub version: U32<E>, pub page_size: U32<E>, pub page_starts_count: U32<E>,
reserved1: [u8; 4],
pub value_add: U64<E>,
}
pub const DYLD_CACHE_SLIDE_V5_PAGE_ATTR_NO_REBASE: u16 = 0xFFFF;
#[derive(Debug, Clone, Copy)]
pub struct DyldCacheSlidePointer5(pub u64);
impl DyldCacheSlidePointer5 {
pub fn is_auth(&self) -> bool {
((self.0 >> 63) & 1) != 0
}
pub fn runtime_offset(&self) -> u64 {
self.0 & 0x3_ffff_ffff
}
pub fn high8(&self) -> u64 {
(self.0 >> 34) & 0xff
}
pub fn diversity(&self) -> u16 {
((self.0 >> 34) & 0xffff) as u16
}
pub fn addr_div(&self) -> bool {
((self.0 >> 50) & 1) != 0
}
pub fn key_is_data(&self) -> bool {
((self.0 >> 51) & 1) != 0
}
pub fn next(&self) -> u64 {
(self.0 >> 52) & 0x7ff
}
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct DyldSubCacheEntryV1<E: Endian> {
pub uuid: [u8; 16],
pub cache_vm_offset: U64<E>,
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct DyldSubCacheEntryV2<E: Endian> {
pub uuid: [u8; 16],
pub cache_vm_offset: U64<E>,
pub file_suffix: [u8; 32],
}
pub const FAT_MAGIC: u32 = 0xcafe_babe;
pub const FAT_CIGAM: u32 = 0xbeba_feca;
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct FatHeader {
pub magic: U32<BigEndian>,
pub nfat_arch: U32<BigEndian>,
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct FatArch32 {
pub cputype: U32<BigEndian, CpuType>,
pub cpusubtype: U32<BigEndian, CpuSubtype>,
pub offset: U32<BigEndian>,
pub size: U32<BigEndian>,
pub align: U32<BigEndian>,
}
pub const FAT_MAGIC_64: u32 = 0xcafe_babf;
pub const FAT_CIGAM_64: u32 = 0xbfba_feca;
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct FatArch64 {
pub cputype: U32<BigEndian, CpuType>,
pub cpusubtype: U32<BigEndian, CpuSubtype>,
pub offset: U64<BigEndian>,
pub size: U64<BigEndian>,
pub align: U32<BigEndian>,
pub reserved: U32<BigEndian>,
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct MachHeader32<E: Endian> {
pub magic: U32<BigEndian>,
pub cputype: U32<E, CpuType>,
pub cpusubtype: U32<E, CpuSubtype>,
pub filetype: U32<E, FileType>,
pub ncmds: U32<E>,
pub sizeofcmds: U32<E>,
pub flags: U32<E, FileFlags>,
}
pub const MH_MAGIC: u32 = 0xfeed_face;
pub const MH_CIGAM: u32 = 0xcefa_edfe;
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct MachHeader64<E: Endian> {
pub magic: U32<BigEndian>,
pub cputype: U32<E, CpuType>,
pub cpusubtype: U32<E, CpuSubtype>,
pub filetype: U32<E, FileType>,
pub ncmds: U32<E>,
pub sizeofcmds: U32<E>,
pub flags: U32<E, FileFlags>,
pub reserved: U32<E>,
}
pub const MH_MAGIC_64: u32 = 0xfeed_facf;
pub const MH_CIGAM_64: u32 = 0xcffa_edfe;
newtype!(
struct FileType(u32);
);
newtype_constant_names!(NAMES_MH_TYPE: FileType(u32) = {
MH_OBJECT = 0x1,
MH_EXECUTE = 0x2,
MH_FVMLIB = 0x3,
MH_CORE = 0x4,
MH_PRELOAD = 0x5,
MH_DYLIB = 0x6,
MH_DYLINKER = 0x7,
MH_BUNDLE = 0x8,
MH_DYLIB_STUB = 0x9,
MH_DSYM = 0xa,
MH_KEXT_BUNDLE = 0xb,
MH_FILESET = 0xc,
MH_GPU_EXECUTE = 0xd,
MH_GPU_DYLIB = 0xe,
});
newtype!(
struct FileFlags(u32);
);
newtype_flag_names!(NAMES_MH_FLAGS: FileFlags(u32) = {
MH_NOUNDEFS = 0x1,
MH_INCRLINK = 0x2,
MH_DYLDLINK = 0x4,
MH_BINDATLOAD = 0x8,
MH_PREBOUND = 0x10,
MH_SPLIT_SEGS = 0x20,
MH_LAZY_INIT = 0x40,
MH_TWOLEVEL = 0x80,
MH_FORCE_FLAT = 0x100,
MH_NOMULTIDEFS = 0x200,
MH_NOFIXPREBINDING = 0x400,
MH_PREBINDABLE = 0x800,
MH_ALLMODSBOUND = 0x1000,
MH_SUBSECTIONS_VIA_SYMBOLS = 0x2000,
MH_CANONICAL = 0x4000,
MH_WEAK_DEFINES = 0x8000,
MH_BINDS_TO_WEAK = 0x10000,
MH_ALLOW_STACK_EXECUTION = 0x20000,
MH_ROOT_SAFE = 0x40000,
MH_SETUID_SAFE = 0x80000,
MH_NO_REEXPORTED_DYLIBS = 0x10_0000,
MH_PIE = 0x20_0000,
MH_DEAD_STRIPPABLE_DYLIB = 0x40_0000,
MH_HAS_TLV_DESCRIPTORS = 0x80_0000,
MH_NO_HEAP_EXECUTION = 0x100_0000,
MH_APP_EXTENSION_SAFE = 0x0200_0000,
MH_NLIST_OUTOFSYNC_WITH_DYLDINFO = 0x0400_0000,
MH_SIM_SUPPORT = 0x0800_0000,
MH_IMPLICIT_PAGEZERO = 0x1000_0000,
MH_DYLIB_IN_CACHE = 0x8000_0000,
});
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct LoadCommand<E: Endian> {
pub cmd: U32<E, LoadCommandType>,
pub cmdsize: U32<E>,
}
pub const LC_REQ_DYLD: u32 = 0x8000_0000;
newtype!(
struct LoadCommandType(u32);
);
newtype_constant_names!(NAMES_LC_TYPE: LoadCommandType(u32) = {
LC_SEGMENT = 0x1,
LC_SYMTAB = 0x2,
LC_SYMSEG = 0x3,
LC_THREAD = 0x4,
LC_UNIXTHREAD = 0x5,
LC_LOADFVMLIB = 0x6,
LC_IDFVMLIB = 0x7,
LC_IDENT = 0x8,
LC_FVMFILE = 0x9,
LC_PREPAGE = 0xa,
LC_DYSYMTAB = 0xb,
LC_LOAD_DYLIB = 0xc,
LC_ID_DYLIB = 0xd,
LC_LOAD_DYLINKER = 0xe,
LC_ID_DYLINKER = 0xf,
LC_PREBOUND_DYLIB = 0x10,
LC_ROUTINES = 0x11,
LC_SUB_FRAMEWORK = 0x12,
LC_SUB_UMBRELLA = 0x13,
LC_SUB_CLIENT = 0x14,
LC_SUB_LIBRARY = 0x15,
LC_TWOLEVEL_HINTS = 0x16,
LC_PREBIND_CKSUM = 0x17,
LC_LOAD_WEAK_DYLIB = 0x18 | LC_REQ_DYLD,
LC_SEGMENT_64 = 0x19,
LC_ROUTINES_64 = 0x1a,
LC_UUID = 0x1b,
LC_RPATH = 0x1c | LC_REQ_DYLD,
LC_CODE_SIGNATURE = 0x1d,
LC_SEGMENT_SPLIT_INFO = 0x1e,
LC_REEXPORT_DYLIB = 0x1f | LC_REQ_DYLD,
LC_LAZY_LOAD_DYLIB = 0x20,
LC_ENCRYPTION_INFO = 0x21,
LC_DYLD_INFO = 0x22,
LC_DYLD_INFO_ONLY = 0x22 | LC_REQ_DYLD,
LC_LOAD_UPWARD_DYLIB = 0x23 | LC_REQ_DYLD,
LC_VERSION_MIN_MACOSX = 0x24,
LC_VERSION_MIN_IPHONEOS = 0x25,
LC_FUNCTION_STARTS = 0x26,
LC_DYLD_ENVIRONMENT = 0x27,
LC_MAIN = 0x28 | LC_REQ_DYLD,
LC_DATA_IN_CODE = 0x29,
LC_SOURCE_VERSION = 0x2A,
LC_DYLIB_CODE_SIGN_DRS = 0x2B,
LC_ENCRYPTION_INFO_64 = 0x2C,
LC_LINKER_OPTION = 0x2D,
LC_LINKER_OPTIMIZATION_HINT = 0x2E,
LC_VERSION_MIN_TVOS = 0x2F,
LC_VERSION_MIN_WATCHOS = 0x30,
LC_NOTE = 0x31,
LC_BUILD_VERSION = 0x32,
LC_DYLD_EXPORTS_TRIE = 0x33 | LC_REQ_DYLD,
LC_DYLD_CHAINED_FIXUPS = 0x34 | LC_REQ_DYLD,
LC_FILESET_ENTRY = 0x35 | LC_REQ_DYLD,
LC_ATOM_INFO = 0x36,
LC_FUNCTION_VARIANTS = 0x37,
LC_FUNCTION_VARIANT_FIXUPS = 0x38,
LC_TARGET_TRIPLE = 0x39,
});
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct LcStr<E: Endian> {
pub offset: U32<E>,
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct SegmentCommand32<E: Endian> {
pub cmd: U32<E, LoadCommandType>,
pub cmdsize: U32<E>,
pub segname: [u8; 16],
pub vmaddr: U32<E>,
pub vmsize: U32<E>,
pub fileoff: U32<E>,
pub filesize: U32<E>,
pub maxprot: U32<E, VmProt>,
pub initprot: U32<E, VmProt>,
pub nsects: U32<E>,
pub flags: U32<E, SegmentFlags>,
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct SegmentCommand64<E: Endian> {
pub cmd: U32<E, LoadCommandType>,
pub cmdsize: U32<E>,
pub segname: [u8; 16],
pub vmaddr: U64<E>,
pub vmsize: U64<E>,
pub fileoff: U64<E>,
pub filesize: U64<E>,
pub maxprot: U32<E, VmProt>,
pub initprot: U32<E, VmProt>,
pub nsects: U32<E>,
pub flags: U32<E, SegmentFlags>,
}
newtype!(
struct SegmentFlags(u32);
);
newtype_flag_names!(NAMES_SG: SegmentFlags(u32) = {
SG_HIGHVM = 0x1,
SG_FVMLIB = 0x2,
SG_NORELOC = 0x4,
SG_PROTECTED_VERSION_1 = 0x8,
SG_READ_ONLY = 0x10,
});
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct Section32<E: Endian> {
pub sectname: [u8; 16],
pub segname: [u8; 16],
pub addr: U32<E>,
pub size: U32<E>,
pub offset: U32<E>,
pub align: U32<E>,
pub reloff: U32<E>,
pub nreloc: U32<E>,
pub flags: U32<E, SectionFlags>,
pub reserved1: U32<E>,
pub reserved2: U32<E>,
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct Section64<E: Endian> {
pub sectname: [u8; 16],
pub segname: [u8; 16],
pub addr: U64<E>,
pub size: U64<E>,
pub offset: U32<E>,
pub align: U32<E>,
pub reloff: U32<E>,
pub nreloc: U32<E>,
pub flags: U32<E, SectionFlags>,
pub reserved1: U32<E>,
pub reserved2: U32<E>,
pub reserved3: U32<E>,
}
pub const SECTION_TYPE: u32 = 0x0000_00ff;
pub const SECTION_ATTRIBUTES: u32 = 0xffff_ff00;
newtype!(
struct SectionFlags(u32);
);
impl SectionFlags {
pub fn typ(self) -> SectionType {
SectionType((self.0 & SECTION_TYPE) as u8)
}
pub const fn with_type(self, typ: SectionType) -> SectionFlags {
SectionFlags(self.0 & !SECTION_TYPE | typ.0 as u32)
}
}
newtype!(
struct SectionType(u8);
);
impl SectionType {
pub const fn to_flags(self) -> SectionFlags {
SectionFlags(self.0 as u32)
}
}
impl From<SectionType> for SectionFlags {
fn from(typ: SectionType) -> Self {
SectionFlags(u32::from(typ.0))
}
}
impl From<SectionFlags> for SectionType {
fn from(flags: SectionFlags) -> Self {
flags.typ()
}
}
impl core::ops::BitOr<SectionFlags> for SectionType {
type Output = SectionFlags;
fn bitor(self, attrs: SectionFlags) -> SectionFlags {
attrs.with_type(self)
}
}
newtype_constant_names!(NAMES_S_TYPE: SectionType(u8) = {
S_REGULAR = 0x0,
S_ZEROFILL = 0x1,
S_CSTRING_LITERALS = 0x2,
S_4BYTE_LITERALS = 0x3,
S_8BYTE_LITERALS = 0x4,
S_LITERAL_POINTERS = 0x5,
S_NON_LAZY_SYMBOL_POINTERS = 0x6,
S_LAZY_SYMBOL_POINTERS = 0x7,
S_SYMBOL_STUBS = 0x8,
S_MOD_INIT_FUNC_POINTERS = 0x9,
S_MOD_TERM_FUNC_POINTERS = 0xa,
S_COALESCED = 0xb,
S_GB_ZEROFILL = 0xc,
S_INTERPOSING = 0xd,
S_16BYTE_LITERALS = 0xe,
S_DTRACE_DOF = 0xf,
S_LAZY_DYLIB_SYMBOL_POINTERS = 0x10,
S_THREAD_LOCAL_REGULAR = 0x11,
S_THREAD_LOCAL_ZEROFILL = 0x12,
S_THREAD_LOCAL_VARIABLES = 0x13,
S_THREAD_LOCAL_VARIABLE_POINTERS = 0x14,
S_THREAD_LOCAL_INIT_FUNCTION_POINTERS = 0x15,
S_INIT_FUNC_OFFSETS = 0x16,
});
newtype_flag_names!(NAMES_S: SectionFlags(u32) = {
_ = SECTION_TYPE => NAMES_S_TYPE,
S_ATTR_PURE_INSTRUCTIONS = 0x8000_0000,
S_ATTR_NO_TOC = 0x4000_0000,
S_ATTR_STRIP_STATIC_SYMS = 0x2000_0000,
S_ATTR_NO_DEAD_STRIP = 0x1000_0000,
S_ATTR_LIVE_SUPPORT = 0x0800_0000,
S_ATTR_SELF_MODIFYING_CODE = 0x0400_0000,
S_ATTR_DEBUG = 0x0200_0000,
S_ATTR_SOME_INSTRUCTIONS = 0x0000_0400,
S_ATTR_EXT_RELOC = 0x0000_0200,
S_ATTR_LOC_RELOC = 0x0000_0100,
});
pub const SECTION_ATTRIBUTES_USR: u32 = 0xff00_0000;
pub const SECTION_ATTRIBUTES_SYS: u32 = 0x00ff_ff00;
pub const SEG_PAGEZERO: &str = "__PAGEZERO";
pub const SEG_TEXT: &str = "__TEXT";
pub const SECT_TEXT: &str = "__text";
pub const SECT_FVMLIB_INIT0: &str = "__fvmlib_init0";
pub const SECT_FVMLIB_INIT1: &str = "__fvmlib_init1";
pub const SEG_DATA: &str = "__DATA";
pub const SECT_DATA: &str = "__data";
pub const SECT_BSS: &str = "__bss";
pub const SECT_COMMON: &str = "__common";
pub const SEG_OBJC: &str = "__OBJC";
pub const SECT_OBJC_SYMBOLS: &str = "__symbol_table";
pub const SECT_OBJC_MODULES: &str = "__module_info";
pub const SECT_OBJC_STRINGS: &str = "__selector_strs";
pub const SECT_OBJC_REFS: &str = "__selector_refs";
pub const SEG_ICON: &str = "__ICON";
pub const SECT_ICON_HEADER: &str = "__header";
pub const SECT_ICON_TIFF: &str = "__tiff";
pub const SEG_LINKEDIT: &str = "__LINKEDIT";
pub const SEG_LINKINFO: &str = "__LINKINFO";
pub const SEG_UNIXSTACK: &str = "__UNIXSTACK";
pub const SEG_IMPORT: &str = "__IMPORT";
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct Fvmlib<E: Endian> {
pub name: LcStr<E>,
pub minor_version: U32<E>,
pub header_addr: U32<E>,
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct FvmlibCommand<E: Endian> {
pub cmd: U32<E, LoadCommandType>,
pub cmdsize: U32<E>,
pub fvmlib: Fvmlib<E>,
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct Dylib<E: Endian> {
pub name: LcStr<E>,
pub timestamp: U32<E>,
pub current_version: U32<E, Version>,
pub compatibility_version: U32<E, Version>,
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct DylibCommand<E: Endian> {
pub cmd: U32<E, LoadCommandType>,
pub cmdsize: U32<E>,
pub dylib: Dylib<E>,
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct DylibUseCommand<E: Endian> {
pub cmd: U32<E, LoadCommandType>,
pub cmdsize: U32<E>,
pub nameoff: U32<E>,
pub marker: U32<E>,
pub current_version: U32<E, Version>,
pub compat_version: U32<E, Version>,
pub flags: U32<E, DylibUseFlags>,
}
newtype!(
struct DylibUseFlags(u32);
);
newtype_flag_names!(NAMES_DYLIB_USE: DylibUseFlags(u32) = {
DYLIB_USE_WEAK_LINK = 0x01,
DYLIB_USE_REEXPORT = 0x02,
DYLIB_USE_UPWARD = 0x04,
DYLIB_USE_DELAYED_INIT = 0x08,
});
pub const DYLIB_USE_MARKER: u32 = 0x1a741800;
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct SubFrameworkCommand<E: Endian> {
pub cmd: U32<E, LoadCommandType>,
pub cmdsize: U32<E>,
pub umbrella: LcStr<E>,
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct SubClientCommand<E: Endian> {
pub cmd: U32<E, LoadCommandType>,
pub cmdsize: U32<E>,
pub client: LcStr<E>,
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct SubUmbrellaCommand<E: Endian> {
pub cmd: U32<E, LoadCommandType>,
pub cmdsize: U32<E>,
pub sub_umbrella: LcStr<E>,
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct SubLibraryCommand<E: Endian> {
pub cmd: U32<E, LoadCommandType>,
pub cmdsize: U32<E>,
pub sub_library: LcStr<E>,
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct PreboundDylibCommand<E: Endian> {
pub cmd: U32<E, LoadCommandType>,
pub cmdsize: U32<E>,
pub name: LcStr<E>,
pub nmodules: U32<E>,
pub linked_modules: LcStr<E>,
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct DylinkerCommand<E: Endian> {
pub cmd: U32<E, LoadCommandType>,
pub cmdsize: U32<E>,
pub name: LcStr<E>,
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct ThreadCommand<E: Endian> {
pub cmd: U32<E, LoadCommandType>,
pub cmdsize: U32<E>,
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct RoutinesCommand32<E: Endian> {
pub cmd: U32<E, LoadCommandType>,
pub cmdsize: U32<E>,
pub init_address: U32<E>,
pub init_module: U32<E>,
pub reserved1: U32<E>,
pub reserved2: U32<E>,
pub reserved3: U32<E>,
pub reserved4: U32<E>,
pub reserved5: U32<E>,
pub reserved6: U32<E>,
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct RoutinesCommand64<E: Endian> {
pub cmd: U32<E, LoadCommandType>,
pub cmdsize: U32<E>,
pub init_address: U64<E>,
pub init_module: U64<E>,
pub reserved1: U64<E>,
pub reserved2: U64<E>,
pub reserved3: U64<E>,
pub reserved4: U64<E>,
pub reserved5: U64<E>,
pub reserved6: U64<E>,
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct SymtabCommand<E: Endian> {
pub cmd: U32<E, LoadCommandType>,
pub cmdsize: U32<E>,
pub symoff: U32<E>,
pub nsyms: U32<E>,
pub stroff: U32<E>,
pub strsize: U32<E>,
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct DysymtabCommand<E: Endian> {
pub cmd: U32<E, LoadCommandType>,
pub cmdsize: U32<E>,
pub ilocalsym: U32<E>,
pub nlocalsym: U32<E>,
pub iextdefsym: U32<E>,
pub nextdefsym: U32<E>,
pub iundefsym: U32<E>,
pub nundefsym: U32<E>,
pub tocoff: U32<E>,
pub ntoc: U32<E>,
pub modtaboff: U32<E>,
pub nmodtab: U32<E>,
pub extrefsymoff: U32<E>,
pub nextrefsyms: U32<E>,
pub indirectsymoff: U32<E>,
pub nindirectsyms: U32<E>,
pub extreloff: U32<E>,
pub nextrel: U32<E>,
pub locreloff: U32<E>,
pub nlocrel: U32<E>,
}
newtype!(
struct IndirectSymbol(u32);
);
newtype_flag_names!(NAMES_INDIRECT_SYMBOL: IndirectSymbol(u32) = {
INDIRECT_SYMBOL_LOCAL = 0x8000_0000,
INDIRECT_SYMBOL_ABS = 0x4000_0000,
});
impl IndirectSymbol {
pub fn is_local(self) -> bool {
self.contains(INDIRECT_SYMBOL_LOCAL)
}
pub fn is_abs(self) -> bool {
self.contains(INDIRECT_SYMBOL_ABS)
}
pub fn index(self) -> Option<u32> {
if self.intersects(INDIRECT_SYMBOL_LOCAL | INDIRECT_SYMBOL_ABS) {
None
} else {
Some(self.0)
}
}
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct DylibTableOfContents<E: Endian> {
pub symbol_index: U32<E>,
pub module_index: U32<E>,
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct DylibModule32<E: Endian> {
pub module_name: U32<E>,
pub iextdefsym: U32<E>,
pub nextdefsym: U32<E>,
pub irefsym: U32<E>,
pub nrefsym: U32<E>,
pub ilocalsym: U32<E>,
pub nlocalsym: U32<E>,
pub iextrel: U32<E>,
pub nextrel: U32<E>,
pub iinit_iterm: U32<E>,
pub ninit_nterm: U32<E>,
pub objc_module_info_addr: U32<E>,
pub objc_module_info_size: U32<E>,
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct DylibModule64<E: Endian> {
pub module_name: U32<E>,
pub iextdefsym: U32<E>,
pub nextdefsym: U32<E>,
pub irefsym: U32<E>,
pub nrefsym: U32<E>,
pub ilocalsym: U32<E>,
pub nlocalsym: U32<E>,
pub iextrel: U32<E>,
pub nextrel: U32<E>,
pub iinit_iterm: U32<E>,
pub ninit_nterm: U32<E>,
pub objc_module_info_size: U32<E>,
pub objc_module_info_addr: U64<E>,
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct DylibReference<E: Endian> {
pub bitfield: U32<E>,
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct TwolevelHintsCommand<E: Endian> {
pub cmd: U32<E, LoadCommandType>,
pub cmdsize: U32<E>,
pub offset: U32<E>,
pub nhints: U32<E>,
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct TwolevelHint<E: Endian> {
pub bitfield: U32<E>,
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct PrebindCksumCommand<E: Endian> {
pub cmd: U32<E, LoadCommandType>,
pub cmdsize: U32<E>,
pub cksum: U32<E>,
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct UuidCommand<E: Endian> {
pub cmd: U32<E, LoadCommandType>,
pub cmdsize: U32<E>,
pub uuid: [u8; 16],
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct RpathCommand<E: Endian> {
pub cmd: U32<E, LoadCommandType>,
pub cmdsize: U32<E>,
pub path: LcStr<E>,
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct TargetTripleCommand<E: Endian> {
pub cmd: U32<E, LoadCommandType>,
pub cmdsize: U32<E>,
pub triple: LcStr<E>,
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct LinkeditDataCommand<E: Endian> {
pub cmd: U32<E, LoadCommandType>,
pub cmdsize: U32<E>,
pub dataoff: U32<E>,
pub datasize: U32<E>,
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct EncryptionInfoCommand32<E: Endian> {
pub cmd: U32<E, LoadCommandType>,
pub cmdsize: U32<E>,
pub cryptoff: U32<E>,
pub cryptsize: U32<E>,
pub cryptid: U32<E>,
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct EncryptionInfoCommand64<E: Endian> {
pub cmd: U32<E, LoadCommandType>,
pub cmdsize: U32<E>,
pub cryptoff: U32<E>,
pub cryptsize: U32<E>,
pub cryptid: U32<E>,
pub pad: U32<E>,
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct VersionMinCommand<E: Endian> {
pub cmd: U32<E, LoadCommandType>,
pub cmdsize: U32<E>,
pub version: U32<E, Version>,
pub sdk: U32<E, Version>,
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct BuildVersionCommand<E: Endian> {
pub cmd: U32<E, LoadCommandType>,
pub cmdsize: U32<E>,
pub platform: U32<E, Platform>,
pub minos: U32<E, Version>,
pub sdk: U32<E, Version>,
pub ntools: U32<E>,
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct BuildToolVersion<E: Endian> {
pub tool: U32<E, Tool>,
pub version: U32<E, Version>,
}
newtype!(
struct Version(u32);
);
impl Version {
pub fn new(major: u16, minor: u8, update: u8) -> Self {
Version(u32::from(major) << 16 | u32::from(minor) << 8 | u32::from(update))
}
pub fn major(self) -> u16 {
(self.0 >> 16) as u16
}
pub fn minor(self) -> u8 {
(self.0 >> 8) as u8
}
pub fn update(self) -> u8 {
self.0 as u8
}
}
impl core::fmt::Debug for Version {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{}.{}.{}", self.major(), self.minor(), self.update())
}
}
impl core::fmt::Display for Version {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{}.{}.{}", self.major(), self.minor(), self.update())
}
}
newtype!(
struct Platform(u32);
);
newtype_constant_names!(NAMES_PLATFORM: Platform(u32) = {
PLATFORM_UNKNOWN = 0,
PLATFORM_ANY = 0xFFFFFFFF,
PLATFORM_MACOS = 1,
PLATFORM_IOS = 2,
PLATFORM_TVOS = 3,
PLATFORM_WATCHOS = 4,
PLATFORM_BRIDGEOS = 5,
PLATFORM_MACCATALYST = 6,
PLATFORM_IOSSIMULATOR = 7,
PLATFORM_TVOSSIMULATOR = 8,
PLATFORM_WATCHOSSIMULATOR = 9,
PLATFORM_DRIVERKIT = 10,
PLATFORM_VISIONOS = 11,
PLATFORM_VISIONOSSIMULATOR = 12,
PLATFORM_XROS = PLATFORM_VISIONOS.0,
PLATFORM_XROSSIMULATOR = PLATFORM_VISIONOSSIMULATOR.0,
PLATFORM_FIRMWARE = 13,
PLATFORM_SEPOS = 14,
PLATFORM_MACOS_EXCLAVECORE = 15,
PLATFORM_MACOS_EXCLAVEKIT = 16,
PLATFORM_IOS_EXCLAVECORE = 17,
PLATFORM_IOS_EXCLAVEKIT = 18,
PLATFORM_TVOS_EXCLAVECORE = 19,
PLATFORM_TVOS_EXCLAVEKIT = 20,
PLATFORM_WATCHOS_EXCLAVECORE = 21,
PLATFORM_WATCHOS_EXCLAVEKIT = 22,
PLATFORM_VISIONOS_EXCLAVECORE = 23,
PLATFORM_VISIONOS_EXCLAVEKIT = 24,
});
newtype!(
struct Tool(u32);
);
newtype_constant_names!(NAMES_TOOL: Tool(u32) = {
TOOL_CLANG = 1,
TOOL_SWIFT = 2,
TOOL_LD = 3,
TOOL_METAL = 1024,
TOOL_AIRLLD = 1025,
TOOL_AIRNT = 1026,
TOOL_AIRNT_PLUGIN = 1027,
TOOL_AIRPACK = 1028,
TOOL_GPUARCHIVER = 1031,
TOOL_METAL_FRAMEWORK = 1032,
});
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct DyldInfoCommand<E: Endian> {
pub cmd: U32<E, LoadCommandType>,
pub cmdsize: U32<E>,
pub rebase_off: U32<E>,
pub rebase_size: U32<E>,
pub bind_off: U32<E>,
pub bind_size: U32<E>,
pub weak_bind_off: U32<E>,
pub weak_bind_size: U32<E>,
pub lazy_bind_off: U32<E>,
pub lazy_bind_size: U32<E>,
pub export_off: U32<E>,
pub export_size: U32<E>,
}
newtype!(
struct RebaseType(u8);
);
newtype_constant_names!(NAMES_REBASE_TYPE: RebaseType(u8) = {
REBASE_TYPE_POINTER = 1,
REBASE_TYPE_TEXT_ABSOLUTE32 = 2,
REBASE_TYPE_TEXT_PCREL32 = 3,
});
newtype!(
struct RebaseOpcode(u8);
);
pub const REBASE_OPCODE_MASK: u8 = 0xF0;
pub const REBASE_IMMEDIATE_MASK: u8 = 0x0F;
newtype_constant_names!(NAMES_REBASE_OPCODE: RebaseOpcode(u8) = {
REBASE_OPCODE_DONE = 0x00,
REBASE_OPCODE_SET_TYPE_IMM = 0x10,
REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB = 0x20,
REBASE_OPCODE_ADD_ADDR_ULEB = 0x30,
REBASE_OPCODE_ADD_ADDR_IMM_SCALED = 0x40,
REBASE_OPCODE_DO_REBASE_IMM_TIMES = 0x50,
REBASE_OPCODE_DO_REBASE_ULEB_TIMES = 0x60,
REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB = 0x70,
REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB = 0x80,
});
newtype!(
struct BindType(u8);
);
newtype_constant_names!(NAMES_BIND_TYPE: BindType(u8) = {
BIND_TYPE_POINTER = 1,
BIND_TYPE_TEXT_ABSOLUTE32 = 2,
BIND_TYPE_TEXT_PCREL32 = 3,
});
newtype!(
struct BindDylib(i32);
);
impl BindDylib {
pub fn is_special(self) -> bool {
self.0 <= 0
}
pub fn index(self) -> Option<u32> {
if self.0 <= 0 {
None
} else {
Some(self.0 as u32)
}
}
}
newtype_constant_names!(NAMES_BIND_DYLIB: BindDylib(i32) = {
BIND_SPECIAL_DYLIB_SELF = 0,
BIND_SPECIAL_DYLIB_MAIN_EXECUTABLE = -1,
BIND_SPECIAL_DYLIB_FLAT_LOOKUP = -2,
BIND_SPECIAL_DYLIB_WEAK_LOOKUP = -3,
});
newtype!(
struct BindSymbolFlags(u8);
);
newtype_flag_names!(NAMES_BIND_SYMBOL_FLAGS: BindSymbolFlags(u8) = {
BIND_SYMBOL_FLAGS_WEAK_IMPORT = 0x1,
BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION = 0x8,
});
newtype!(
struct BindOpcode(u8);
);
pub const BIND_OPCODE_MASK: u8 = 0xF0;
pub const BIND_IMMEDIATE_MASK: u8 = 0x0F;
newtype_constant_names!(NAMES_BIND_OPCODE: BindOpcode(u8) = {
BIND_OPCODE_DONE = 0x00,
BIND_OPCODE_SET_DYLIB_ORDINAL_IMM = 0x10,
BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB = 0x20,
BIND_OPCODE_SET_DYLIB_SPECIAL_IMM = 0x30,
BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM = 0x40,
BIND_OPCODE_SET_TYPE_IMM = 0x50,
BIND_OPCODE_SET_ADDEND_SLEB = 0x60,
BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB = 0x70,
BIND_OPCODE_ADD_ADDR_ULEB = 0x80,
BIND_OPCODE_DO_BIND = 0x90,
BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB = 0xA0,
BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED = 0xB0,
BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB = 0xC0,
BIND_OPCODE_THREADED = 0xD0,
});
newtype!(
struct BindSubopcodeThreaded(u8);
);
newtype_constant_names!(NAMES_BIND_SUBOPCODE_THREADED: BindSubopcodeThreaded(u8) = {
BIND_SUBOPCODE_THREADED_SET_BIND_ORDINAL_TABLE_SIZE_ULEB = 0x00,
BIND_SUBOPCODE_THREADED_APPLY = 0x01,
});
newtype!(
struct ExportSymbolKind(u8);
);
newtype_constant_names!(NAMES_EXPORT_SYMBOL_KIND: ExportSymbolKind(u8) = {
EXPORT_SYMBOL_FLAGS_KIND_REGULAR = 0x00,
EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL = 0x01,
EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE = 0x02,
});
newtype!(
struct ExportSymbolFlags(u64);
);
newtype_flag_names!(NAMES_EXPORT_SYMBOL_FLAGS: ExportSymbolFlags(u64) = {
EXPORT_SYMBOL_FLAGS_KIND_MASK = 0x03 => NAMES_EXPORT_SYMBOL_KIND,
EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION = 0x04,
EXPORT_SYMBOL_FLAGS_REEXPORT = 0x08,
EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER = 0x10,
EXPORT_SYMBOL_FLAGS_STATIC_RESOLVER = 0x20,
});
impl ExportSymbolFlags {
pub fn has_unknown_bits(self) -> bool {
self.0 & !0x3f != 0
}
pub fn kind(self) -> ExportSymbolKind {
ExportSymbolKind((self.0 & EXPORT_SYMBOL_FLAGS_KIND_MASK) as u8)
}
pub fn with_kind(self, kind: ExportSymbolKind) -> ExportSymbolFlags {
ExportSymbolFlags(
self.0 & !EXPORT_SYMBOL_FLAGS_KIND_MASK
| u64::from(kind.0) & EXPORT_SYMBOL_FLAGS_KIND_MASK,
)
}
}
impl From<ExportSymbolKind> for ExportSymbolFlags {
fn from(value: ExportSymbolKind) -> Self {
ExportSymbolFlags(u64::from(value.0))
}
}
impl From<ExportSymbolFlags> for ExportSymbolKind {
fn from(value: ExportSymbolFlags) -> Self {
value.kind()
}
}
impl core::ops::BitOr<ExportSymbolFlags> for ExportSymbolKind {
type Output = ExportSymbolFlags;
fn bitor(self, flags: ExportSymbolFlags) -> ExportSymbolFlags {
flags.with_kind(self)
}
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct LinkerOptionCommand<E: Endian> {
pub cmd: U32<E, LoadCommandType>,
pub cmdsize: U32<E>,
pub count: U32<E>,
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct SymsegCommand<E: Endian> {
pub cmd: U32<E, LoadCommandType>,
pub cmdsize: U32<E>,
pub offset: U32<E>,
pub size: U32<E>,
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct IdentCommand<E: Endian> {
pub cmd: U32<E, LoadCommandType>,
pub cmdsize: U32<E>,
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct FvmfileCommand<E: Endian> {
pub cmd: U32<E, LoadCommandType>,
pub cmdsize: U32<E>,
pub name: LcStr<E>,
pub header_addr: U32<E>,
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct EntryPointCommand<E: Endian> {
pub cmd: U32<E, LoadCommandType>,
pub cmdsize: U32<E>,
pub entryoff: U64<E>,
pub stacksize: U64<E>,
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct SourceVersionCommand<E: Endian> {
pub cmd: U32<E, LoadCommandType>,
pub cmdsize: U32<E>,
pub version: U64<E>,
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct DataInCodeEntry<E: Endian> {
pub offset: U32<E>,
pub length: U16<E>,
pub kind: U16<E, DiceKind>,
}
newtype!(
struct DiceKind(u16);
);
newtype_constant_names!(NAMES_DICE_KIND: DiceKind(u16) = {
DICE_KIND_DATA = 0x0001,
DICE_KIND_JUMP_TABLE8 = 0x0002,
DICE_KIND_JUMP_TABLE16 = 0x0003,
DICE_KIND_JUMP_TABLE32 = 0x0004,
DICE_KIND_ABS_JUMP_TABLE32 = 0x0005,
});
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct NoteCommand<E: Endian> {
pub cmd: U32<E, LoadCommandType>,
pub cmdsize: U32<E>,
pub data_owner: [u8; 16],
pub offset: U64<E>,
pub size: U64<E>,
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct FilesetEntryCommand<E: Endian> {
pub cmd: U32<E, LoadCommandType>,
pub cmdsize: U32<E>,
pub vmaddr: U64<E>,
pub fileoff: U64<E>,
pub entry_id: LcStr<E>,
pub reserved: U32<E>,
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct Nlist32<E: Endian> {
pub n_strx: U32<E>,
pub n_type: SymbolFlags,
pub n_sect: u8,
pub n_desc: U16<E, SymbolDesc>,
pub n_value: U32<E>,
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct Nlist64<E: Endian> {
pub n_strx: U32<E>,
pub n_type: SymbolFlags,
pub n_sect: u8,
pub n_desc: U16<E, SymbolDesc>,
pub n_value: U64<E>,
}
newtype!(
#[repr(transparent)]
struct SymbolFlags(u8);
);
impl SymbolFlags {
pub fn is_stab(self) -> bool {
self.0 & N_STAB != 0
}
pub fn stab(self) -> Option<SymbolStab> {
if self.is_stab() {
Some(SymbolStab(self.0))
} else {
None
}
}
pub fn typ(self) -> SymbolType {
SymbolType(self.0 & N_TYPE)
}
pub fn with_type(self, typ: SymbolType) -> SymbolFlags {
SymbolFlags(self.0 & !N_TYPE | typ.0 & N_TYPE)
}
pub fn is_ext(self) -> bool {
self.contains(N_EXT)
}
pub fn is_pext(self) -> bool {
self.contains(N_EXT | N_PEXT)
}
}
pub const N_STAB: u8 = 0xe0;
newtype_flag_names!(NAMES_N: SymbolFlags(u8) = {
N_PEXT = 0x10,
N_TYPE = 0x0e => NAMES_N_TYPE,
N_EXT = 0x01,
});
newtype!(
struct SymbolType(u8);
);
impl From<SymbolType> for SymbolFlags {
fn from(value: SymbolType) -> Self {
SymbolFlags(value.0)
}
}
impl From<SymbolFlags> for SymbolType {
fn from(value: SymbolFlags) -> Self {
value.typ()
}
}
impl core::ops::BitOr<SymbolFlags> for SymbolType {
type Output = SymbolFlags;
fn bitor(self, flags: SymbolFlags) -> SymbolFlags {
flags.with_type(self)
}
}
newtype_constant_names!(NAMES_N_TYPE: SymbolType(u8) = {
N_UNDF = 0x0,
N_ABS = 0x2,
N_SECT = 0xe,
N_PBUD = 0xc,
N_INDR = 0xa,
});
pub const NO_SECT: u8 = 0;
pub const MAX_SECT: u8 = 255;
newtype!(
struct SymbolDesc(u16);
);
newtype_flag_names!(SymbolDesc(u16) = {});
impl SymbolDesc {
#[cfg(feature = "names")]
pub const NAMES_DEFINED: &'static FlagNames<SymbolDesc> = &NAMES_N_DESC_DEFINED;
#[cfg(feature = "names")]
pub const NAMES_UNDEFINED: &'static FlagNames<SymbolDesc> = &NAMES_N_DESC_UNDEFINED;
pub fn reference(self) -> SymbolReference {
SymbolReference((self.0 & REFERENCE_TYPE) as u8)
}
pub fn with_reference(self, reference: SymbolReference) -> SymbolDesc {
SymbolDesc((self.0 & !REFERENCE_TYPE) | (u16::from(reference.0)))
}
pub fn library(self) -> SymbolLibrary {
SymbolLibrary((self.0 >> 8) as u8)
}
pub fn with_library(self, ordinal: SymbolLibrary) -> SymbolDesc {
SymbolDesc((self.0 & 0x00ff) | (u16::from(ordinal.0) << 8))
}
pub fn common_alignment(self) -> u8 {
((self.0 >> 8) & 0x0f) as u8
}
pub fn with_common_alignment(self, alignment: u8) -> SymbolDesc {
debug_assert_eq!(alignment & !0xf, 0);
SymbolDesc((self.0 & 0xf0ff) | (u16::from(alignment & 0xf) << 8))
}
}
newtype!(
struct SymbolReference(u8);
);
impl From<SymbolReference> for SymbolDesc {
fn from(value: SymbolReference) -> Self {
SymbolDesc(u16::from(value.0))
}
}
pub const REFERENCE_TYPE: u16 = 0x7;
newtype_constant_names!(NAMES_REFERENCE: SymbolReference(u8) = {
REFERENCE_FLAG_UNDEFINED_NON_LAZY = 0,
REFERENCE_FLAG_UNDEFINED_LAZY = 1,
REFERENCE_FLAG_DEFINED = 2,
REFERENCE_FLAG_PRIVATE_DEFINED = 3,
REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY = 4,
REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY = 5,
});
newtype!(
struct SymbolLibrary(u8);
);
impl SymbolLibrary {
pub fn is_reserved(self) -> bool {
self == SELF_LIBRARY_ORDINAL || self.0 > MAX_LIBRARY_ORDINAL
}
pub fn index(self) -> Option<u8> {
if self.is_reserved() {
None
} else {
Some(self.0)
}
}
}
impl From<SymbolLibrary> for SymbolDesc {
fn from(value: SymbolLibrary) -> Self {
SymbolDesc(u16::from(value.0) << 8)
}
}
pub const MAX_LIBRARY_ORDINAL: u8 = 0xfd;
newtype_constant_names!(NAMES_ORDINAL: SymbolLibrary(u8) = {
SELF_LIBRARY_ORDINAL = 0x0,
DYNAMIC_LOOKUP_ORDINAL = 0xfe,
EXECUTABLE_ORDINAL = 0xff,
});
flag_names!(NAMES_N_DESC_DEFINED: SymbolDesc(u16) = {
N_ARM_THUMB_DEF = 0x0008,
REFERENCED_DYNAMICALLY = 0x0010,
N_NO_DEAD_STRIP = 0x0020,
N_DESC_DISCARDED = 0x0020,
N_WEAK_DEF = 0x0080,
N_SYMBOL_RESOLVER = 0x0100,
N_ALT_ENTRY = 0x0200,
N_COLD_FUNC = 0x0400,
});
flag_names!(NAMES_N_DESC_UNDEFINED: SymbolDesc(u16) = {
N_WEAK_REF = 0x0040,
N_REF_TO_WEAK = 0x0080,
});
newtype!(
struct SymbolStab(u8);
);
newtype_constant_names!(NAMES_N_STAB: SymbolStab(u8) = {
N_GSYM = 0x20,
N_FNAME = 0x22,
N_FUN = 0x24,
N_STSYM = 0x26,
N_LCSYM = 0x28,
N_BNSYM = 0x2e,
N_AST = 0x32,
N_OPT = 0x3c,
N_RSYM = 0x40,
N_SLINE = 0x44,
N_ENSYM = 0x4e,
N_SSYM = 0x60,
N_SO = 0x64,
N_OSO = 0x66,
N_LIB = 0x68,
N_LSYM = 0x80,
N_BINCL = 0x82,
N_SOL = 0x84,
N_PARAMS = 0x86,
N_VERSION = 0x88,
N_OLEVEL = 0x8A,
N_PSYM = 0xa0,
N_EINCL = 0xa2,
N_ENTRY = 0xa4,
N_LBRAC = 0xc0,
N_EXCL = 0xc2,
N_RBRAC = 0xe0,
N_BCOMM = 0xe2,
N_ECOMM = 0xe4,
N_ECOML = 0xe8,
N_LENG = 0xfe,
N_PC = 0x30,
});
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct Relocation<E: Endian> {
pub r_word0: U32<E>,
pub r_word1: U32<E>,
}
impl<E: Endian> Relocation<E> {
#[inline]
pub fn r_scattered(self, endian: E, cputype: CpuType) -> bool {
if cputype == CPU_TYPE_X86_64 {
false
} else {
self.r_word0.get(endian) & R_SCATTERED != 0
}
}
pub fn info(self, endian: E) -> RelocationInfo {
let r_address = self.r_word0.get(endian);
let r_word1 = self.r_word1.get(endian);
if endian.is_little_endian() {
RelocationInfo {
r_address,
r_symbolnum: r_word1 & 0x00ff_ffff,
r_pcrel: ((r_word1 >> 24) & 0x1) != 0,
r_length: ((r_word1 >> 25) & 0x3) as u8,
r_extern: ((r_word1 >> 27) & 0x1) != 0,
r_type: RelocationType((r_word1 >> 28) as u8),
}
} else {
RelocationInfo {
r_address,
r_symbolnum: r_word1 >> 8,
r_pcrel: ((r_word1 >> 7) & 0x1) != 0,
r_length: ((r_word1 >> 5) & 0x3) as u8,
r_extern: ((r_word1 >> 4) & 0x1) != 0,
r_type: RelocationType((r_word1 & 0xf) as u8),
}
}
}
pub fn scattered_info(self, endian: E) -> ScatteredRelocationInfo {
let r_word0 = self.r_word0.get(endian);
let r_value = self.r_word1.get(endian);
ScatteredRelocationInfo {
r_address: r_word0 & 0x00ff_ffff,
r_type: RelocationType(((r_word0 >> 24) & 0xf) as u8),
r_length: ((r_word0 >> 28) & 0x3) as u8,
r_pcrel: ((r_word0 >> 30) & 0x1) != 0,
r_value,
}
}
}
#[derive(Debug, Clone, Copy)]
pub struct RelocationInfo {
pub r_address: u32,
pub r_symbolnum: u32,
pub r_pcrel: bool,
pub r_length: u8,
pub r_extern: bool,
pub r_type: RelocationType,
}
impl RelocationInfo {
pub fn relocation<E: Endian>(self, endian: E) -> Relocation<E> {
let r_word0 = U32::new(endian, self.r_address);
let r_word1 = U32::new(
endian,
if endian.is_little_endian() {
self.r_symbolnum & 0x00ff_ffff
| u32::from(self.r_pcrel) << 24
| u32::from(self.r_length & 0x3) << 25
| u32::from(self.r_extern) << 27
| u32::from(self.r_type.0) << 28
} else {
self.r_symbolnum >> 8
| u32::from(self.r_pcrel) << 7
| u32::from(self.r_length & 0x3) << 5
| u32::from(self.r_extern) << 4
| u32::from(self.r_type.0) & 0xf
},
);
Relocation { r_word0, r_word1 }
}
}
pub const R_ABS: u32 = 0;
pub const R_SCATTERED: u32 = 0x8000_0000;
#[derive(Debug, Clone, Copy)]
pub struct ScatteredRelocationInfo {
pub r_address: u32,
pub r_type: RelocationType,
pub r_length: u8,
pub r_pcrel: bool,
pub r_value: u32,
}
impl ScatteredRelocationInfo {
pub fn relocation<E: Endian>(self, endian: E) -> Relocation<E> {
let r_word0 = U32::new(
endian,
self.r_address & 0x00ff_ffff
| u32::from(self.r_type.0 & 0xf) << 24
| u32::from(self.r_length & 0x3) << 28
| u32::from(self.r_pcrel) << 30
| R_SCATTERED,
);
let r_word1 = U32::new(endian, self.r_value);
Relocation { r_word0, r_word1 }
}
}
newtype!(
struct RelocationType(u8);
);
newtype_constant_names!(RelocationType(u8) = {});
constant_names!(
pub NAMES_GENERIC_RELOC: RelocationType(u8) = {
GENERIC_RELOC_VANILLA = 0,
GENERIC_RELOC_PAIR = 1,
GENERIC_RELOC_SECTDIFF = 2,
GENERIC_RELOC_PB_LA_PTR = 3,
GENERIC_RELOC_LOCAL_SECTDIFF = 4,
GENERIC_RELOC_TLV = 5,
});
constant_names!(
pub NAMES_ARM_RELOC: RelocationType(u8) = {
ARM_RELOC_VANILLA = 0,
ARM_RELOC_PAIR = 1,
ARM_RELOC_SECTDIFF = 2,
ARM_RELOC_LOCAL_SECTDIFF = 3,
ARM_RELOC_PB_LA_PTR = 4,
ARM_RELOC_BR24 = 5,
ARM_THUMB_RELOC_BR22 = 6,
ARM_THUMB_32BIT_BRANCH = 7,
ARM_RELOC_HALF = 8,
ARM_RELOC_HALF_SECTDIFF = 9,
});
constant_names!(
pub NAMES_ARM64_RELOC: RelocationType(u8) = {
ARM64_RELOC_UNSIGNED = 0,
ARM64_RELOC_SUBTRACTOR = 1,
ARM64_RELOC_BRANCH26 = 2,
ARM64_RELOC_PAGE21 = 3,
ARM64_RELOC_PAGEOFF12 = 4,
ARM64_RELOC_GOT_LOAD_PAGE21 = 5,
ARM64_RELOC_GOT_LOAD_PAGEOFF12 = 6,
ARM64_RELOC_POINTER_TO_GOT = 7,
ARM64_RELOC_TLVP_LOAD_PAGE21 = 8,
ARM64_RELOC_TLVP_LOAD_PAGEOFF12 = 9,
ARM64_RELOC_ADDEND = 10,
ARM64_RELOC_AUTHENTICATED_POINTER = 11,
});
constant_names!(
pub NAMES_PPC_RELOC: RelocationType(u8) = {
PPC_RELOC_VANILLA = 0,
PPC_RELOC_PAIR = 1,
PPC_RELOC_BR14 = 2,
PPC_RELOC_BR24 = 3,
PPC_RELOC_HI16 = 4,
PPC_RELOC_LO16 = 5,
PPC_RELOC_HA16 = 6,
PPC_RELOC_LO14 = 7,
PPC_RELOC_SECTDIFF = 8,
PPC_RELOC_PB_LA_PTR = 9,
PPC_RELOC_HI16_SECTDIFF = 10,
PPC_RELOC_LO16_SECTDIFF = 11,
PPC_RELOC_HA16_SECTDIFF = 12,
PPC_RELOC_JBSR = 13,
PPC_RELOC_LO14_SECTDIFF = 14,
PPC_RELOC_LOCAL_SECTDIFF = 15,
});
constant_names!(
pub NAMES_X86_64_RELOC: RelocationType(u8) = {
X86_64_RELOC_UNSIGNED = 0,
X86_64_RELOC_SIGNED = 1,
X86_64_RELOC_BRANCH = 2,
X86_64_RELOC_GOT_LOAD = 3,
X86_64_RELOC_GOT = 4,
X86_64_RELOC_SUBTRACTOR = 5,
X86_64_RELOC_SIGNED_1 = 6,
X86_64_RELOC_SIGNED_2 = 7,
X86_64_RELOC_SIGNED_4 = 8,
X86_64_RELOC_TLV = 9,
});
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct DyldChainedFixupsHeader<E: Endian> {
pub fixups_version: U32<E>,
pub starts_offset: U32<E>,
pub imports_offset: U32<E>,
pub symbols_offset: U32<E>,
pub imports_count: U32<E>,
pub imports_format: U32<E, DyldChainedImportFormat>,
pub symbols_format: U32<E>,
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct DyldChainedStartsInImage<E: Endian> {
pub seg_count: U32<E>,
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct DyldChainedStartsInSegment<E: Endian> {
pub size: U32<E>,
pub page_size: U16<E>,
pub pointer_format: U16<E, DyldChainedPtrFormat>,
pub segment_offset: U64<E>,
pub max_valid_pointer: U32<E>,
pub page_count: U16<E>,
}
pub const DYLD_CHAINED_PTR_START_NONE: u16 = 0xFFFF;
pub const DYLD_CHAINED_PTR_START_MULTI: u16 = 0x8000;
pub const DYLD_CHAINED_PTR_START_LAST: u16 = 0x8000;
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct DyldChainedStartsOffsets<E: Endian> {
pub pointer_format: U32<E, DyldChainedPtrFormat>,
pub starts_count: U32<E>,
}
newtype!(
struct DyldChainedPtrFormat(u16);
);
newtype_constant_names!(NAMES_DYLD_CHAINED_PTR: DyldChainedPtrFormat(u16) = {
DYLD_CHAINED_PTR_ARM64E = 1,
DYLD_CHAINED_PTR_64 = 2,
DYLD_CHAINED_PTR_32 = 3,
DYLD_CHAINED_PTR_32_CACHE = 4,
DYLD_CHAINED_PTR_32_FIRMWARE = 5,
DYLD_CHAINED_PTR_64_OFFSET = 6,
DYLD_CHAINED_PTR_ARM64E_KERNEL = 7,
DYLD_CHAINED_PTR_ARM64E_OFFSET = 7,
DYLD_CHAINED_PTR_64_KERNEL_CACHE = 8,
DYLD_CHAINED_PTR_ARM64E_USERLAND = 9,
DYLD_CHAINED_PTR_ARM64E_FIRMWARE = 10,
DYLD_CHAINED_PTR_X86_64_KERNEL_CACHE = 11,
DYLD_CHAINED_PTR_ARM64E_USERLAND24 = 12,
DYLD_CHAINED_PTR_ARM64E_SHARED_CACHE = 13,
DYLD_CHAINED_PTR_ARM64E_SEGMENTED = 14,
});
#[derive(Debug, Clone, Copy)]
pub struct DyldChainedPtrArm64e(pub u64);
impl DyldChainedPtrArm64e {
pub fn next(self) -> u64 {
(self.0 >> 51) & ((1 << 11) - 1)
}
pub fn is_bind(self) -> bool {
(self.0 >> 62) & 1 != 0
}
pub fn is_auth(self) -> bool {
(self.0 >> 63) & 1 != 0
}
pub fn bind(self) -> DyldChainedPtrArm64eBind {
DyldChainedPtrArm64eBind(self.0)
}
pub fn auth_bind(self) -> DyldChainedPtrArm64eAuthBind {
DyldChainedPtrArm64eAuthBind(self.0)
}
pub fn rebase(self) -> DyldChainedPtrArm64eRebase {
DyldChainedPtrArm64eRebase(self.0)
}
pub fn auth_rebase(self) -> DyldChainedPtrArm64eAuthRebase {
DyldChainedPtrArm64eAuthRebase(self.0)
}
pub fn bind24(self) -> DyldChainedPtrArm64eBind24 {
DyldChainedPtrArm64eBind24(self.0)
}
pub fn auth_bind24(self) -> DyldChainedPtrArm64eAuthBind24 {
DyldChainedPtrArm64eAuthBind24(self.0)
}
}
#[derive(Debug, Clone, Copy)]
pub struct DyldChainedPtrArm64eRebase(pub u64);
impl DyldChainedPtrArm64eRebase {
pub fn target(self) -> u64 {
self.0 & ((1 << 43) - 1)
}
pub fn high8(self) -> u64 {
(self.0 >> 43) & 0xff
}
}
#[derive(Debug, Clone, Copy)]
pub struct DyldChainedPtrArm64eAuthRebase(pub u64);
impl DyldChainedPtrArm64eAuthRebase {
pub fn runtime_offset(self) -> u64 {
self.0 & ((1 << 32) - 1)
}
pub fn diversity(self) -> u16 {
((self.0 >> 32) & 0xffff) as u16
}
pub fn addr_div(self) -> bool {
(self.0 >> 48) & 1 != 0
}
pub fn key(self) -> u8 {
((self.0 >> 49) & 3) as u8
}
}
#[derive(Debug, Clone, Copy)]
pub struct DyldChainedPtrArm64eBind(pub u64);
impl DyldChainedPtrArm64eBind {
pub fn ordinal(self) -> u32 {
(self.0 & 0xffff) as u32
}
pub fn addend(self) -> i32 {
((self.0 >> 19) as i32) >> 13
}
}
#[derive(Debug, Clone, Copy)]
pub struct DyldChainedPtrArm64eAuthBind(pub u64);
impl DyldChainedPtrArm64eAuthBind {
pub fn ordinal(self) -> u32 {
(self.0 & 0xffff) as u32
}
pub fn diversity(self) -> u16 {
((self.0 >> 32) & 0xffff) as u16
}
pub fn addr_div(self) -> bool {
(self.0 >> 48) & 1 != 0
}
pub fn key(self) -> u8 {
((self.0 >> 49) & 3) as u8
}
}
#[derive(Debug, Clone, Copy)]
pub struct DyldChainedPtrArm64eBind24(pub u64);
impl DyldChainedPtrArm64eBind24 {
pub fn ordinal(self) -> u32 {
(self.0 & ((1 << 24) - 1)) as u32
}
pub fn addend(self) -> i32 {
((self.0 >> 19) as i32) >> 13
}
}
#[derive(Debug, Clone, Copy)]
pub struct DyldChainedPtrArm64eAuthBind24(pub u64);
impl DyldChainedPtrArm64eAuthBind24 {
pub fn ordinal(self) -> u32 {
(self.0 & ((1 << 24) - 1)) as u32
}
pub fn diversity(self) -> u16 {
((self.0 >> 32) & 0xffff) as u16
}
pub fn addr_div(self) -> bool {
(self.0 >> 48) & 1 != 0
}
pub fn key(self) -> u8 {
((self.0 >> 49) & 3) as u8
}
}
#[derive(Debug, Clone, Copy)]
pub struct DyldChainedPtrArm64eSegmentedRebase(pub u64);
impl DyldChainedPtrArm64eSegmentedRebase {
pub fn next(self) -> u64 {
(self.0 >> 51) & ((1 << 12) - 1)
}
pub fn is_auth(self) -> bool {
(self.0 >> 63) & 1 != 0
}
pub fn target_seg_offset(self) -> u64 {
self.0 & ((1 << 28) - 1)
}
pub fn target_seg_index(self) -> u8 {
((self.0 >> 28) & 0xf) as u8
}
pub fn diversity(self) -> u16 {
((self.0 >> 32) & 0xffff) as u16
}
pub fn addr_div(self) -> bool {
(self.0 >> 48) & 1 != 0
}
pub fn key(self) -> u8 {
((self.0 >> 49) & 3) as u8
}
}
#[derive(Debug, Clone, Copy)]
pub struct DyldChainedPtr64(pub u64);
impl DyldChainedPtr64 {
pub fn next(self) -> u64 {
(self.0 >> 51) & ((1 << 12) - 1)
}
pub fn is_bind(self) -> bool {
(self.0 >> 63) & 1 != 0
}
pub fn bind(self) -> DyldChainedPtr64Bind {
DyldChainedPtr64Bind(self.0)
}
pub fn rebase(self) -> DyldChainedPtr64Rebase {
DyldChainedPtr64Rebase(self.0)
}
}
#[derive(Debug, Clone, Copy)]
pub struct DyldChainedPtr64Rebase(pub u64);
impl DyldChainedPtr64Rebase {
pub fn target(self) -> u64 {
self.0 & ((1 << 36) - 1)
}
pub fn high8(self) -> u64 {
(self.0 >> 36) & 0xff
}
}
#[derive(Debug, Clone, Copy)]
pub struct DyldChainedPtr64Bind(pub u64);
impl DyldChainedPtr64Bind {
pub fn ordinal(self) -> u32 {
(self.0 & ((1 << 24) - 1)) as u32
}
pub fn addend(self) -> i32 {
((self.0 >> 24) & 0xff) as i32
}
}
#[derive(Debug, Clone, Copy)]
pub struct DyldChainedPtr64KernelCacheRebase(pub u64);
impl DyldChainedPtr64KernelCacheRebase {
pub fn next(self) -> u64 {
(self.0 >> 51) & ((1 << 12) - 1)
}
pub fn is_auth(self) -> bool {
(self.0 >> 63) & 1 != 0
}
pub fn target(self) -> u64 {
self.0 & ((1 << 30) - 1)
}
pub fn cache_level(self) -> u8 {
((self.0 >> 30) & 3) as u8
}
pub fn diversity(self) -> u16 {
((self.0 >> 32) & 0xffff) as u16
}
pub fn addr_div(self) -> bool {
(self.0 >> 48) & 1 != 0
}
pub fn key(self) -> u8 {
((self.0 >> 49) & 3) as u8
}
}
#[derive(Debug, Clone, Copy)]
pub struct DyldChainedPtr32(pub u32);
impl DyldChainedPtr32 {
pub fn next(self) -> u32 {
(self.0 >> 26) & ((1 << 5) - 1)
}
pub fn is_bind(self) -> bool {
(self.0 >> 31) & 1 != 0
}
pub fn bind(self) -> DyldChainedPtr32Bind {
DyldChainedPtr32Bind(self.0)
}
pub fn rebase(self) -> DyldChainedPtr32Rebase {
DyldChainedPtr32Rebase(self.0)
}
}
#[derive(Debug, Clone, Copy)]
pub struct DyldChainedPtr32Rebase(pub u32);
impl DyldChainedPtr32Rebase {
pub fn target(self) -> u32 {
self.0 & ((1 << 26) - 1)
}
}
#[derive(Debug, Clone, Copy)]
pub struct DyldChainedPtr32Bind(pub u32);
impl DyldChainedPtr32Bind {
pub fn ordinal(self) -> u32 {
self.0 & ((1 << 20) - 1)
}
pub fn addend(self) -> i32 {
((self.0 >> 20) & ((1 << 6) - 1)) as i32
}
}
#[derive(Debug, Clone, Copy)]
pub struct DyldChainedPtr32CacheRebase(pub u32);
impl DyldChainedPtr32CacheRebase {
pub fn target(self) -> u32 {
self.0 & ((1 << 30) - 1)
}
pub fn next(self) -> u32 {
(self.0 >> 30) & ((1 << 2) - 1)
}
}
#[derive(Debug, Clone, Copy)]
pub struct DyldChainedPtr32FirmwareRebase(pub u32);
impl DyldChainedPtr32FirmwareRebase {
pub fn target(self) -> u32 {
self.0 & ((1 << 26) - 1)
}
pub fn next(self) -> u32 {
(self.0 >> 26) & ((1 << 6) - 1)
}
}
#[derive(Debug, Clone, Copy)]
pub struct DyldChainedPtrArm64eSharedCache(pub u64);
impl DyldChainedPtrArm64eSharedCache {
pub fn next(self) -> u64 {
(self.0 >> 52) & ((1 << 11) - 1)
}
pub fn is_auth(self) -> bool {
(self.0 >> 63) & 1 != 0
}
pub fn rebase(self) -> DyldChainedPtrArm64eSharedCacheRebase {
DyldChainedPtrArm64eSharedCacheRebase(self.0)
}
pub fn auth_rebase(self) -> DyldChainedPtrArm64eSharedCacheAuthRebase {
DyldChainedPtrArm64eSharedCacheAuthRebase(self.0)
}
}
#[derive(Debug, Clone, Copy)]
pub struct DyldChainedPtrArm64eSharedCacheRebase(pub u64);
impl DyldChainedPtrArm64eSharedCacheRebase {
pub fn runtime_offset(self) -> u64 {
self.0 & ((1 << 34) - 1)
}
pub fn high8(self) -> u64 {
(self.0 >> 34) & 0xff
}
}
#[derive(Debug, Clone, Copy)]
pub struct DyldChainedPtrArm64eSharedCacheAuthRebase(pub u64);
impl DyldChainedPtrArm64eSharedCacheAuthRebase {
pub fn runtime_offset(self) -> u64 {
self.0 & ((1 << 34) - 1)
}
pub fn diversity(self) -> u16 {
((self.0 >> 34) & 0xffff) as u16
}
pub fn addr_div(self) -> bool {
(self.0 >> 50) & 1 != 0
}
pub fn key_is_data(self) -> bool {
(self.0 >> 51) & 1 != 0
}
}
newtype!(
struct DyldChainedImportFormat(u32);
);
newtype_constant_names!(NAMES_DYLD_CHAINED_IMPORT_FORMAT: DyldChainedImportFormat(u32) = {
DYLD_CHAINED_IMPORT = 1,
DYLD_CHAINED_IMPORT_ADDEND = 2,
DYLD_CHAINED_IMPORT_ADDEND64 = 3,
});
newtype!(
#[derive(Debug)]
struct DyldChainedImport32(u32);
);
impl DyldChainedImport32 {
pub fn lib_ordinal(self) -> u8 {
(self.0 & 0xff) as u8
}
pub fn dylib(self) -> BindDylib {
let lib_ordinal = self.lib_ordinal();
if lib_ordinal > 0xf0 {
BindDylib((lib_ordinal as i8).into())
} else {
BindDylib(lib_ordinal.into())
}
}
pub fn weak_import(self) -> bool {
(self.0 >> 8) & 1 != 0
}
pub fn name_offset(self) -> u32 {
self.0 >> 9
}
}
newtype!(
#[derive(Debug)]
struct DyldChainedImport64(u64);
);
impl DyldChainedImport64 {
pub fn lib_ordinal(self) -> u16 {
(self.0 & 0xffff) as u16
}
pub fn dylib(self) -> BindDylib {
let lib_ordinal = self.lib_ordinal();
if lib_ordinal > 0xfff0 {
BindDylib((lib_ordinal as i16).into())
} else {
BindDylib(lib_ordinal.into())
}
}
pub fn weak_import(self) -> bool {
(self.0 >> 16) & 1 != 0
}
pub fn name_offset(self) -> u32 {
(self.0 >> 32) as u32
}
}
newtype!(
struct CsFlags(u32);
);
newtype_flag_names!(NAMES_CS: CsFlags(u32) = {
CS_VALID = 0x00000001,
CS_ADHOC = 0x00000002,
CS_GET_TASK_ALLOW = 0x00000004,
CS_INSTALLER = 0x00000008,
CS_FORCED_LV = 0x00000010,
CS_INVALID_ALLOWED = 0x00000020,
CS_HARD = 0x00000100,
CS_KILL = 0x00000200,
CS_CHECK_EXPIRATION = 0x00000400,
CS_RESTRICT = 0x00000800,
CS_ENFORCEMENT = 0x00001000,
CS_REQUIRE_LV = 0x00002000,
CS_ENTITLEMENTS_VALIDATED = 0x00004000,
CS_NVRAM_UNRESTRICTED = 0x00008000,
CS_RUNTIME = 0x00010000,
CS_LINKER_SIGNED = 0x00020000,
CS_EXEC_SET_HARD = 0x00100000,
CS_EXEC_SET_KILL = 0x00200000,
CS_EXEC_SET_ENFORCEMENT = 0x00400000,
CS_EXEC_INHERIT_SIP = 0x00800000,
CS_KILLED = 0x01000000,
CS_NO_UNTRUSTED_HELPERS = 0x02000000,
CS_DYLD_PLATFORM = CS_NO_UNTRUSTED_HELPERS.0,
CS_PLATFORM_BINARY = 0x04000000,
CS_PLATFORM_PATH = 0x08000000,
CS_DEBUGGED = 0x10000000,
CS_SIGNED = 0x20000000,
CS_DEV_CODE = 0x40000000,
CS_DATAVAULT_CONTROLLER = 0x80000000,
});
pub const CS_ALLOWED_MACHO: CsFlags = CS_ADHOC
.with(CS_HARD)
.with(CS_KILL)
.with(CS_CHECK_EXPIRATION)
.with(CS_RESTRICT)
.with(CS_ENFORCEMENT)
.with(CS_REQUIRE_LV)
.with(CS_RUNTIME)
.with(CS_LINKER_SIGNED);
pub const CS_ENTITLEMENT_FLAGS: CsFlags = CS_GET_TASK_ALLOW
.with(CS_INSTALLER)
.with(CS_DATAVAULT_CONTROLLER)
.with(CS_NVRAM_UNRESTRICTED);
newtype!(
struct CsExecSegFlags(u64);
);
newtype_flag_names!(NAMES_CS_EXECSEG: CsExecSegFlags(u64) = {
CS_EXECSEG_MAIN_BINARY = 0x1,
CS_EXECSEG_ALLOW_UNSIGNED = 0x10,
CS_EXECSEG_DEBUGGER = 0x20,
CS_EXECSEG_JIT = 0x40,
CS_EXECSEG_SKIP_LV = 0x80,
CS_EXECSEG_CAN_LOAD_CDHASH = 0x100,
CS_EXECSEG_CAN_EXEC_CDHASH = 0x200,
});
pub const CSMAGIC_REQUIREMENT: u32 = 0xfade0c00;
pub const CSMAGIC_REQUIREMENTS: u32 = 0xfade0c01;
pub const CSMAGIC_CODEDIRECTORY: u32 = 0xfade0c02;
pub const CSMAGIC_EMBEDDED_SIGNATURE: u32 = 0xfade0cc0;
pub const CSMAGIC_EMBEDDED_SIGNATURE_OLD: u32 = 0xfade0b02;
pub const CSMAGIC_EMBEDDED_ENTITLEMENTS: u32 = 0xfade7171;
pub const CSMAGIC_EMBEDDED_DER_ENTITLEMENTS: u32 = 0xfade7172;
pub const CSMAGIC_DETACHED_SIGNATURE: u32 = 0xfade0cc1;
pub const CSMAGIC_BLOBWRAPPER: u32 = 0xfade0b01;
pub const CSMAGIC_EMBEDDED_LAUNCH_CONSTRAINT: u32 = 0xfade8181;
newtype!(
struct CsVersion(u32);
);
newtype_constant_names!(NAMES_CS_SUPPORT: CsVersion(u32) = {
CS_SUPPORTSSCATTER = 0x20100,
CS_SUPPORTSTEAMID = 0x20200,
CS_SUPPORTSCODELIMIT64 = 0x20300,
CS_SUPPORTSEXECSEG = 0x20400,
CS_SUPPORTSRUNTIME = 0x20500,
CS_SUPPORTSLINKAGE = 0x20600,
});
newtype!(
struct CsSlot(u32);
);
newtype_constant_names!(NAMES_CSSLOT: CsSlot(u32) = {
CSSLOT_CODEDIRECTORY = 0,
CSSLOT_INFOSLOT = 1,
CSSLOT_REQUIREMENTS = 2,
CSSLOT_RESOURCEDIR = 3,
CSSLOT_APPLICATION = 4,
CSSLOT_ENTITLEMENTS = 5,
CSSLOT_DER_ENTITLEMENTS = 7,
CSSLOT_LAUNCH_CONSTRAINT_SELF = 8,
CSSLOT_LAUNCH_CONSTRAINT_PARENT = 9,
CSSLOT_LAUNCH_CONSTRAINT_RESPONSIBLE = 10,
CSSLOT_LIBRARY_CONSTRAINT = 11,
CSSLOT_SIGNATURESLOT = 0x10000,
CSSLOT_IDENTIFICATIONSLOT = 0x10001,
CSSLOT_TICKETSLOT = 0x10002,
});
impl CsSlot {
pub fn is_alternate_codedirectory(self) -> bool {
matches!(
self.0,
CSSLOT_ALTERNATE_CODEDIRECTORIES..CSSLOT_ALTERNATE_CODEDIRECTORY_LIMIT
)
}
}
pub const CSSLOT_ALTERNATE_CODEDIRECTORIES: u32 = 0x1000;
pub const CSSLOT_ALTERNATE_CODEDIRECTORY_MAX: u32 = 5;
pub const CSSLOT_ALTERNATE_CODEDIRECTORY_LIMIT: u32 =
CSSLOT_ALTERNATE_CODEDIRECTORIES + CSSLOT_ALTERNATE_CODEDIRECTORY_MAX;
newtype!(
#[repr(C)]
struct CsHashType(u8);
);
newtype_constant_names!(NAMES_CS_HASHTYPE: CsHashType(u8) = {
CS_HASHTYPE_SHA1 = 1,
CS_HASHTYPE_SHA256 = 2,
CS_HASHTYPE_SHA256_TRUNCATED = 3,
CS_HASHTYPE_SHA384 = 4,
});
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct CsCodeDirectoryV0 {
pub magic: U32<BigEndian>,
pub length: U32<BigEndian>,
pub version: U32<BigEndian, CsVersion>,
pub flags: U32<BigEndian, CsFlags>,
pub hash_offset: U32<BigEndian>,
pub ident_offset: U32<BigEndian>,
pub n_special_slots: U32<BigEndian>,
pub n_code_slots: U32<BigEndian>,
pub code_limit: U32<BigEndian>,
pub hash_size: u8,
pub hash_type: CsHashType,
pub platform: u8,
pub page_size: u8,
pub spare2: U32<BigEndian>,
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct CsCodeDirectoryV1 {
pub scatter_offset: U32<BigEndian>,
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct CsCodeDirectoryV2 {
pub team_offset: U32<BigEndian>,
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct CsCodeDirectoryV3 {
pub spare3: U32<BigEndian>,
pub code_limit64: U64<BigEndian>,
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct CsCodeDirectoryV4 {
pub exec_seg_base: U64<BigEndian>,
pub exec_seg_limit: U64<BigEndian>,
pub exec_seg_flags: U64<BigEndian, CsExecSegFlags>,
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct CsBlobIndex {
pub slot: U32<BigEndian, CsSlot>,
pub offset: U32<BigEndian>,
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct CsSuperBlob {
pub magic: U32<BigEndian>,
pub length: U32<BigEndian>,
pub count: U32<BigEndian>,
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct CsGenericBlob {
pub magic: U32<BigEndian>,
pub length: U32<BigEndian>,
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct CsScatter {
pub count: U32<BigEndian>,
pub base: U32<BigEndian>,
pub target_offset: U64<BigEndian>,
pub spare: U64<BigEndian>,
}
unsafe_impl_pod!(FatHeader, FatArch32, FatArch64,);
unsafe_impl_endian_pod!(
DyldCacheHeader,
DyldCacheMappingInfo,
DyldCacheMappingAndSlideInfo,
DyldCacheTproMappingInfo,
DyldCacheImageInfo,
DyldCacheSlideInfo2,
DyldCacheSlideInfo3,
DyldCacheSlideInfo5,
DyldSubCacheEntryV1,
DyldSubCacheEntryV2,
MachHeader32,
MachHeader64,
LoadCommand,
LcStr,
SegmentCommand32,
SegmentCommand64,
Section32,
Section64,
Fvmlib,
FvmlibCommand,
Dylib,
DylibCommand,
DylibUseCommand,
SubFrameworkCommand,
SubClientCommand,
SubUmbrellaCommand,
SubLibraryCommand,
PreboundDylibCommand,
DylinkerCommand,
ThreadCommand,
RoutinesCommand32,
RoutinesCommand64,
SymtabCommand,
DysymtabCommand,
DylibTableOfContents,
DylibModule32,
DylibModule64,
DylibReference,
TwolevelHintsCommand,
TwolevelHint,
PrebindCksumCommand,
UuidCommand,
RpathCommand,
TargetTripleCommand,
LinkeditDataCommand,
EncryptionInfoCommand32,
EncryptionInfoCommand64,
VersionMinCommand,
BuildVersionCommand,
BuildToolVersion,
DyldInfoCommand,
DyldChainedFixupsHeader,
DyldChainedStartsInImage,
DyldChainedStartsInSegment,
DyldChainedStartsOffsets,
LinkerOptionCommand,
SymsegCommand,
IdentCommand,
FvmfileCommand,
EntryPointCommand,
SourceVersionCommand,
DataInCodeEntry,
NoteCommand,
FilesetEntryCommand,
Nlist32,
Nlist64,
Relocation,
);
unsafe_impl_pod!(
CsBlobIndex,
CsSuperBlob,
CsCodeDirectoryV0,
CsCodeDirectoryV1,
CsCodeDirectoryV2,
CsCodeDirectoryV3,
CsCodeDirectoryV4,
CsGenericBlob,
CsScatter,
);