summaryrefslogtreecommitdiffstats
path: root/python/macholib/macholib/mach_o.py
diff options
context:
space:
mode:
Diffstat (limited to 'python/macholib/macholib/mach_o.py')
-rw-r--r--python/macholib/macholib/mach_o.py1311
1 files changed, 1311 insertions, 0 deletions
diff --git a/python/macholib/macholib/mach_o.py b/python/macholib/macholib/mach_o.py
new file mode 100644
index 000000000..1a85c75cf
--- /dev/null
+++ b/python/macholib/macholib/mach_o.py
@@ -0,0 +1,1311 @@
+"""
+Other than changing the load commands in such a way that they do not
+contain the load command itself, this is largely a by-hand conversion
+of the C headers. Hopefully everything in here should be at least as
+obvious as the C headers, and you should be using the C headers as a real
+reference because the documentation didn't come along for the ride.
+
+Doing much of anything with the symbol tables or segments is really
+not covered at this point.
+
+See /usr/include/mach-o and friends.
+"""
+import time
+
+from macholib.ptypes import *
+
+
+_CPU_ARCH_ABI64 = 0x01000000
+
+CPU_TYPE_NAMES = {
+ -1: 'ANY',
+ 1: 'VAX',
+ 6: 'MC680x0',
+ 7: 'i386',
+ _CPU_ARCH_ABI64 | 7: 'x86_64',
+ 8: 'MIPS',
+ 10: 'MC98000',
+ 11: 'HPPA',
+ 12: 'ARM',
+ _CPU_ARCH_ABI64 | 12: 'ARM64',
+ 13: 'MC88000',
+ 14: 'SPARC',
+ 15: 'i860',
+ 16: 'Alpha',
+ 18: 'PowerPC',
+ _CPU_ARCH_ABI64 | 18: 'PowerPC64',
+}
+
+INTEL64_SUBTYPE = {
+ 3 : "CPU_SUBTYPE_X86_64_ALL",
+ 4 : "CPU_SUBTYPE_X86_ARCH1"
+}
+
+#define CPU_SUBTYPE_INTEL(f, m) ((cpu_subtype_t) (f) + ((m) << 4))
+INTEL_SUBTYPE = {
+ 0 : "CPU_SUBTYPE_INTEL_MODEL_ALL",
+ 1 : "CPU_THREADTYPE_INTEL_HTT",
+ 3 : "CPU_SUBTYPE_I386_ALL",
+ 4 : "CPU_SUBTYPE_486",
+ 5 : "CPU_SUBTYPE_586",
+ 8 : "CPU_SUBTYPE_PENTIUM_3",
+ 9 : "CPU_SUBTYPE_PENTIUM_M",
+ 10 : "CPU_SUBTYPE_PENTIUM_4",
+ 11 : "CPU_SUBTYPE_ITANIUM",
+ 12 : "CPU_SUBTYPE_XEON",
+ 34 : "CPU_SUBTYPE_XEON_MP",
+ 42 : "CPU_SUBTYPE_PENTIUM_4_M",
+ 43 : "CPU_SUBTYPE_ITANIUM_2",
+ 38 : "CPU_SUBTYPE_PENTPRO",
+ 40 : "CPU_SUBTYPE_PENTIUM_3_M",
+ 52 : "CPU_SUBTYPE_PENTIUM_3_XEON",
+ 102 : "CPU_SUBTYPE_PENTII_M3",
+ 132 : "CPU_SUBTYPE_486SX",
+ 166 : "CPU_SUBTYPE_PENTII_M5",
+ 199 : "CPU_SUBTYPE_CELERON",
+ 231 : "CPU_SUBTYPE_CELERON_MOBILE"
+}
+
+MC680_SUBTYPE = {
+ 1 : "CPU_SUBTYPE_MC680x0_ALL",
+ 2 : "CPU_SUBTYPE_MC68040",
+ 3 : "CPU_SUBTYPE_MC68030_ONLY"
+}
+
+MIPS_SUBTYPE = {
+ 0 : "CPU_SUBTYPE_MIPS_ALL",
+ 1 : "CPU_SUBTYPE_MIPS_R2300",
+ 2 : "CPU_SUBTYPE_MIPS_R2600",
+ 3 : "CPU_SUBTYPE_MIPS_R2800",
+ 4 : "CPU_SUBTYPE_MIPS_R2000a",
+ 5 : "CPU_SUBTYPE_MIPS_R2000",
+ 6 : "CPU_SUBTYPE_MIPS_R3000a",
+ 7 : "CPU_SUBTYPE_MIPS_R3000"
+}
+
+MC98000_SUBTYPE = {
+ 0 : "CPU_SUBTYPE_MC98000_ALL",
+ 1 : "CPU_SUBTYPE_MC98601"
+}
+
+HPPA_SUBTYPE = {
+ 0 : "CPU_SUBTYPE_HPPA_7100",
+ 1 : "CPU_SUBTYPE_HPPA_7100LC"
+}
+
+MC88_SUBTYPE = {
+ 0 : "CPU_SUBTYPE_MC88000_ALL",
+ 1 : "CPU_SUBTYPE_MC88100",
+ 2 : "CPU_SUBTYPE_MC88110"
+}
+
+SPARC_SUBTYPE = {
+ 0 : "CPU_SUBTYPE_SPARC_ALL"
+}
+
+I860_SUBTYPE = {
+ 0 : "CPU_SUBTYPE_I860_ALL",
+ 1 : "CPU_SUBTYPE_I860_860"
+}
+
+POWERPC_SUBTYPE = {
+ 0 : "CPU_SUBTYPE_POWERPC_ALL",
+ 1 : "CPU_SUBTYPE_POWERPC_601",
+ 2 : "CPU_SUBTYPE_POWERPC_602",
+ 3 : "CPU_SUBTYPE_POWERPC_603",
+ 4 : "CPU_SUBTYPE_POWERPC_603e",
+ 5 : "CPU_SUBTYPE_POWERPC_603ev",
+ 6 : "CPU_SUBTYPE_POWERPC_604",
+ 7 : "CPU_SUBTYPE_POWERPC_604e",
+ 8 : "CPU_SUBTYPE_POWERPC_620",
+ 9 : "CPU_SUBTYPE_POWERPC_750",
+ 10 : "CPU_SUBTYPE_POWERPC_7400",
+ 11 : "CPU_SUBTYPE_POWERPC_7450",
+ 100 : "CPU_SUBTYPE_POWERPC_970"
+}
+
+ARM_SUBTYPE = {
+ 0 : "CPU_SUBTYPE_ARM_ALL12",
+ 5 : "CPU_SUBTYPE_ARM_V4T",
+ 6 : "CPU_SUBTYPE_ARM_V6",
+ 7 : "CPU_SUBTYPE_ARM_V5TEJ",
+ 8 : "CPU_SUBTYPE_ARM_XSCALE",
+ 9 : "CPU_SUBTYPE_ARM_V7",
+ 10 : "CPU_SUBTYPE_ARM_V7F",
+ 12 : "CPU_SUBTYPE_ARM_V7K"
+}
+
+VAX_SUBTYPE = {
+ 0 : "CPU_SUBTYPE_VAX_ALL",
+ 1 : "CPU_SUBTYPE_VAX780",
+ 2 : "CPU_SUBTYPE_VAX785",
+ 3 : "CPU_SUBTYPE_VAX750",
+ 4 : "CPU_SUBTYPE_VAX730",
+ 5 : "CPU_SUBTYPE_UVAXI",
+ 6 : "CPU_SUBTYPE_UVAXII",
+ 7 : "CPU_SUBTYPE_VAX8200",
+ 8 : "CPU_SUBTYPE_VAX8500",
+ 9 : "CPU_SUBTYPE_VAX8600",
+ 10 : "CPU_SUBTYPE_VAX8650",
+ 11 : "CPU_SUBTYPE_VAX8800",
+ 12 : "CPU_SUBTYPE_UVAXIII",
+}
+
+
+def get_cpu_subtype(cpu_type, cpu_subtype):
+ st = cpu_subtype & 0x0fffffff
+
+ if cpu_type == 1:
+ subtype = VAX_SUBTYPE.get(st, st)
+ elif cpu_type == 6:
+ subtype = MC680_SUBTYPE.get(st, st)
+ elif cpu_type == 7:
+ subtype = INTEL_SUBTYPE.get(st, st)
+ elif cpu_type == 7 | _CPU_ARCH_ABI64:
+ subtype = INTEL64_SUBTYPE.get(st, st)
+ elif cpu_type == 8:
+ subtype = MIPS_SUBTYPE.get(st, st)
+ elif cpu_type == 10:
+ subtype = MC98000_SUBTYPE.get(st, st)
+ elif cpu_type == 11:
+ subtype = HPPA_SUBTYPE.get(st, st)
+ elif cpu_type == 12:
+ subtype = ARM_SUBTYPE.get(st, st)
+ elif cpu_type == 13:
+ subtype = MC88_SUBTYPE.get(st, st)
+ elif cpu_type == 14:
+ subtype = SPARC_SUBTYPE.get(st, st)
+ elif cpu_type == 15:
+ subtype = I860_SUBTYPE.get(st, st)
+ elif cpu_type == 16:
+ subtype = MIPS_SUBTYPE.get(st, st)
+ elif cpu_type == 18:
+ subtype = POWERPC_SUBTYPE.get(st, st)
+ elif cpu_type == 18 | _CPU_ARCH_ABI64:
+ subtype = POWERPC_SUBTYPE.get(st, st)
+ else:
+ subtype = str(st)
+
+ return subtype
+
+
+_MH_EXECUTE_SYM = "__mh_execute_header"
+MH_EXECUTE_SYM = "_mh_execute_header"
+_MH_BUNDLE_SYM = "__mh_bundle_header"
+MH_BUNDLE_SYM = "_mh_bundle_header"
+_MH_DYLIB_SYM = "__mh_dylib_header"
+MH_DYLIB_SYM = "_mh_dylib_header"
+_MH_DYLINKER_SYM = "__mh_dylinker_header"
+MH_DYLINKER_SYM = "_mh_dylinker_header"
+
+(
+ MH_OBJECT, MH_EXECUTE, MH_FVMLIB, MH_CORE, MH_PRELOAD, MH_DYLIB,
+ MH_DYLINKER, MH_BUNDLE, MH_DYLIB_STUB, MH_DSYM
+) = range(0x1, 0xb)
+
+(
+ MH_NOUNDEFS, MH_INCRLINK, MH_DYLDLINK, MH_BINDATLOAD, MH_PREBOUND,
+ MH_SPLIT_SEGS, MH_LAZY_INIT, MH_TWOLEVEL, MH_FORCE_FLAT, MH_NOMULTIDEFS,
+ MH_NOFIXPREBINDING, MH_PREBINDABLE, MH_ALLMODSBOUND, MH_SUBSECTIONS_VIA_SYMBOLS,
+ MH_CANONICAL, MH_WEAK_DEFINES, MH_BINDS_TO_WEAK, MH_ALLOW_STACK_EXECUTION,
+ MH_ROOT_SAFE, MH_SETUID_SAFE, MH_NO_REEXPORTED_DYLIBS, MH_PIE,
+ MH_DEAD_STRIPPABLE_DYLIB, MH_HAS_TLV_DESCRIPTORS, MH_NO_HEAP_EXECUTION
+) = map((1).__lshift__, range(25))
+
+MH_MAGIC = 0xfeedface
+MH_CIGAM = 0xcefaedfe
+MH_MAGIC_64 = 0xfeedfacf
+MH_CIGAM_64 = 0xcffaedfe
+
+integer_t = p_int32
+cpu_type_t = integer_t
+cpu_subtype_t = p_uint32
+
+MH_FILETYPE_NAMES = {
+ MH_OBJECT: 'relocatable object',
+ MH_EXECUTE: 'demand paged executable',
+ MH_FVMLIB: 'fixed vm shared library',
+ MH_CORE: 'core',
+ MH_PRELOAD: 'preloaded executable',
+ MH_DYLIB: 'dynamically bound shared library',
+ MH_DYLINKER: 'dynamic link editor',
+ MH_BUNDLE: 'dynamically bound bundle',
+ MH_DYLIB_STUB: 'shared library stub for static linking',
+ MH_DSYM: 'symbol information',
+}
+
+MH_FILETYPE_SHORTNAMES = {
+ 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_FLAGS_NAMES = {
+ 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_FLAGS_DESCRIPTIONS = {
+ MH_NOUNDEFS: 'no undefined references',
+ MH_INCRLINK: 'output of an incremental link',
+ MH_DYLDLINK: 'input for the dynamic linker',
+ MH_BINDATLOAD: 'undefined references bound dynamically when loaded',
+ MH_PREBOUND: 'dynamic undefined references prebound',
+ MH_SPLIT_SEGS: 'split read-only and read-write segments',
+ MH_LAZY_INIT: '(obsolete)',
+ MH_TWOLEVEL: 'using two-level name space bindings',
+ MH_FORCE_FLAT: 'forcing all imagges to use flat name space bindings',
+ MH_NOMULTIDEFS: 'umbrella guarantees no multiple definitions',
+ MH_NOFIXPREBINDING: 'do not notify prebinding agent about this executable',
+ MH_PREBINDABLE: 'the binary is not prebound but can have its prebinding redone',
+ MH_ALLMODSBOUND: 'indicates that this binary binds to all two-level namespace modules of its dependent libraries',
+ MH_SUBSECTIONS_VIA_SYMBOLS: 'safe to divide up the sections into sub-sections via symbols for dead code stripping',
+ MH_CANONICAL: 'the binary has been canonicalized via the unprebind operation',
+ MH_WEAK_DEFINES: 'the final linked image contains external weak symbols',
+ MH_BINDS_TO_WEAK: 'the final linked image uses weak symbols',
+ MH_ALLOW_STACK_EXECUTION: 'all stacks in the task will be given stack execution privilege',
+ MH_ROOT_SAFE: 'the binary declares it is safe for use in processes with uid zero',
+ MH_SETUID_SAFE: 'the binary declares it is safe for use in processes when issetugid() is true',
+ MH_NO_REEXPORTED_DYLIBS: 'the static linker does not need to examine dependent dylibs to see if any are re-exported',
+ MH_PIE: 'the OS will load the main executable at a random address',
+ MH_DEAD_STRIPPABLE_DYLIB: 'the static linker will automatically not create a LC_LOAD_DYLIB load command to the dylib if no symbols are being referenced from the dylib',
+ MH_HAS_TLV_DESCRIPTORS: 'contains a section of type S_THREAD_LOCAL_VARIABLES',
+ MH_NO_HEAP_EXECUTION: 'the OS will run the main executable with a non-executable heap even on platforms that don\'t require it',
+}
+
+class mach_version_helper(Structure):
+ _fields_ = (
+ ('major', p_ushort),
+ ('minor', p_uint8),
+ ('rev', p_uint8),
+ )
+ def __str__(self):
+ return '%s.%s.%s' % (self.major, self.minor, self.rev)
+
+class mach_timestamp_helper(p_uint32):
+ def __str__(self):
+ return time.ctime(self)
+
+def read_struct(f, s, **kw):
+ return s.from_fileobj(f, **kw)
+
+class mach_header(Structure):
+ _fields_ = (
+ ('magic', p_uint32),
+ ('cputype', cpu_type_t),
+ ('cpusubtype', cpu_subtype_t),
+ ('filetype', p_uint32),
+ ('ncmds', p_uint32),
+ ('sizeofcmds', p_uint32),
+ ('flags', p_uint32),
+ )
+ def _describe(self):
+ bit = 1
+ flags = self.flags
+ dflags = []
+ while flags and bit < (1<<32):
+ if flags & bit:
+ dflags.append({'name': MH_FLAGS_NAMES.get(bit, str(bit)), 'description': MH_FLAGS_DESCRIPTIONS.get(bit, str(bit))})
+ flags = flags ^ bit
+ bit <<= 1
+ return (
+ ('magic', int(self.magic)),
+ ('cputype_string', CPU_TYPE_NAMES.get(self.cputype, self.cputype)),
+ ('cputype', int(self.cputype)),
+ ('cpusubtype_string', get_cpu_subtype(self.cputype, self.cpusubtype)),
+ ('cpusubtype', int(self.cpusubtype)),
+ ('filetype_string', MH_FILETYPE_NAMES.get(self.filetype, self.filetype)),
+ ('filetype', int(self.filetype)),
+ ('ncmds', self.ncmds),
+ ('sizeofcmds', self.sizeofcmds),
+ ('flags', dflags),
+ ('raw_flags', int(self.flags))
+ )
+
+class mach_header_64(mach_header):
+ _fields_ = mach_header._fields_ + (('reserved', p_uint32),)
+
+class load_command(Structure):
+ _fields_ = (
+ ('cmd', p_uint32),
+ ('cmdsize', p_uint32),
+ )
+
+ def get_cmd_name(self):
+ return LC_NAMES.get(self.cmd, self.cmd)
+
+LC_REQ_DYLD = 0x80000000
+
+(
+ LC_SEGMENT, LC_SYMTAB, LC_SYMSEG, LC_THREAD, LC_UNIXTHREAD, LC_LOADFVMLIB,
+ LC_IDFVMLIB, LC_IDENT, LC_FVMFILE, LC_PREPAGE, LC_DYSYMTAB, LC_LOAD_DYLIB,
+ LC_ID_DYLIB, LC_LOAD_DYLINKER, LC_ID_DYLINKER, LC_PREBOUND_DYLIB,
+ LC_ROUTINES, LC_SUB_FRAMEWORK, LC_SUB_UMBRELLA, LC_SUB_CLIENT,
+ LC_SUB_LIBRARY, LC_TWOLEVEL_HINTS, LC_PREBIND_CKSUM
+) = range(0x1, 0x18)
+
+LC_LOAD_WEAK_DYLIB = LC_REQ_DYLD | 0x18
+
+LC_SEGMENT_64 = 0x19
+LC_ROUTINES_64 = 0x1a
+LC_UUID = 0x1b
+LC_RPATH = (0x1c | LC_REQ_DYLD)
+LC_CODE_SIGNATURE = 0x1d
+LC_CODE_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
+
+
+# this is really a union.. but whatever
+class lc_str(p_uint32):
+ pass
+
+p_str16 = pypackable('p_str16', bytes, '16s')
+
+vm_prot_t = p_int32
+class segment_command(Structure):
+ _fields_ = (
+ ('segname', p_str16),
+ ('vmaddr', p_uint32),
+ ('vmsize', p_uint32),
+ ('fileoff', p_uint32),
+ ('filesize', p_uint32),
+ ('maxprot', vm_prot_t),
+ ('initprot', vm_prot_t),
+ ('nsects', p_uint32), # read the section structures ?
+ ('flags', p_uint32),
+ )
+
+ def describe(self):
+ segname = self.segname
+ s = {}
+ s['segname'] = self.segname.rstrip('\x00')
+ s['vmaddr'] = int(self.vmaddr)
+ s['vmsize'] = int(self.vmsize)
+ s['fileoff'] = int(self.fileoff)
+ s['filesize'] = int(self.filesize)
+ s['initprot'] = self.get_initial_virtual_memory_protections()
+ s['initprot_raw'] = int(self.initprot)
+ s['maxprot'] = self.get_max_virtual_memory_protections()
+ s['maxprot_raw'] = int(self.maxprot)
+ s['nsects'] = int(self.nsects)
+ s['flags'] = self.flags
+ return s
+
+ def get_initial_virtual_memory_protections(self):
+ vm = []
+ if self.initprot == 0:
+ vm.append("VM_PROT_NONE")
+ if self.initprot & 1:
+ vm.append("VM_PROT_READ")
+ if self.initprot & 2:
+ vm.append("VM_PROT_WRITE")
+ if self.initprot & 4:
+ vm.append("VM_PROT_EXECUTE")
+ return vm
+
+ def get_max_virtual_memory_protections(self):
+ vm = []
+ if self.maxprot == 0:
+ vm.append("VM_PROT_NONE")
+ if self.maxprot & 1:
+ vm.append("VM_PROT_READ")
+ if self.maxprot & 2:
+ vm.append("VM_PROT_WRITE")
+ if self.maxprot & 4:
+ vm.append("VM_PROT_EXECUTE")
+ return vm
+
+class segment_command_64(Structure):
+ _fields_ = (
+ ('segname', p_str16),
+ ('vmaddr', p_uint64),
+ ('vmsize', p_uint64),
+ ('fileoff', p_uint64),
+ ('filesize', p_uint64),
+ ('maxprot', vm_prot_t),
+ ('initprot', vm_prot_t),
+ ('nsects', p_uint32), # read the section structures ?
+ ('flags', p_uint32),
+ )
+
+ def describe(self):
+ s = {}
+ s['segname'] = self.segname.rstrip('\x00')
+ s['vmaddr'] = int(self.vmaddr)
+ s['vmsize'] = int(self.vmsize)
+ s['fileoff'] = int(self.fileoff)
+ s['filesize'] = int(self.filesize)
+ s['initprot'] = self.get_initial_virtual_memory_protections()
+ s['initprot_raw'] = int(self.initprot)
+ s['maxprot'] = self.get_max_virtual_memory_protections()
+ s['maxprot_raw'] = int(self.maxprot)
+ s['nsects'] = int(self.nsects)
+ s['flags'] = self.flags
+ return s
+
+ def get_initial_virtual_memory_protections(self):
+ vm = []
+ if self.initprot == 0:
+ vm.append("VM_PROT_NONE")
+ if self.initprot & 1:
+ vm.append("VM_PROT_READ")
+ if self.initprot & 2:
+ vm.append("VM_PROT_WRITE")
+ if self.initprot & 4:
+ vm.append("VM_PROT_EXECUTE")
+ return vm
+
+ def get_max_virtual_memory_protections(self):
+ vm = []
+ if self.maxprot == 0:
+ vm.append("VM_PROT_NONE")
+ if self.maxprot & 1:
+ vm.append("VM_PROT_READ")
+ if self.maxprot & 2:
+ vm.append("VM_PROT_WRITE")
+ if self.maxprot & 4:
+ vm.append("VM_PROT_EXECUTE")
+ return vm
+
+
+SG_HIGHVM = 0x1
+SG_FVMLIB = 0x2
+SG_NORELOC = 0x4
+
+class section(Structure):
+ _fields_ = (
+ ('sectname', p_str16),
+ ('segname', p_str16),
+ ('addr', p_uint32),
+ ('size', p_uint32),
+ ('offset', p_uint32),
+ ('align', p_uint32),
+ ('reloff', p_uint32),
+ ('nreloc', p_uint32),
+ ('flags', p_uint32),
+ ('reserved1', p_uint32),
+ ('reserved2', p_uint32),
+ )
+
+ def describe(self):
+ s = {}
+ s['sectname'] = self.sectname.rstrip('\x00')
+ s['segname'] = self.segname.rstrip('\x00')
+ s['addr'] = int(self.addr)
+ s['size'] = int(self.size)
+ s['offset'] = int(self.offset)
+ s['align'] = int(self.align)
+ s['reloff'] = int(self.reloff)
+ s['nreloc'] = int(self.nreloc)
+ f = {}
+ f['type'] = FLAG_SECTION_TYPES[int(self.flags) & 0xff]
+ f['attributes'] = []
+ for k in FLAG_SECTION_ATTRIBUTES:
+ if k & self.flags:
+ f['attributes'].append(FLAG_SECTION_ATTRIBUTES[k])
+ if not f['attributes']:
+ del f['attributes']
+ s['flags'] = f
+ s['reserved1'] = int(self.reserved1)
+ s['reserved2'] = int(self.reserved2)
+ return s
+
+ def add_section_data(self, data):
+ self.section_data = data
+
+class section_64(Structure):
+ _fields_ = (
+ ('sectname', p_str16),
+ ('segname', p_str16),
+ ('addr', p_uint64),
+ ('size', p_uint64),
+ ('offset', p_uint32),
+ ('align', p_uint32),
+ ('reloff', p_uint32),
+ ('nreloc', p_uint32),
+ ('flags', p_uint32),
+ ('reserved1', p_uint32),
+ ('reserved2', p_uint32),
+ ('reserved3', p_uint32),
+ )
+
+ def describe(self):
+ s = {}
+ s['sectname'] = self.sectname.rstrip('\x00')
+ s['segname'] = self.segname.rstrip('\x00')
+ s['addr'] = int(self.addr)
+ s['size'] = int(self.size)
+ s['offset'] = int(self.offset)
+ s['align'] = int(self.align)
+ s['reloff'] = int(self.reloff)
+ s['nreloc'] = int(self.nreloc)
+ f = {}
+ f['type'] = FLAG_SECTION_TYPES[int(self.flags) & 0xff]
+ f['attributes'] = []
+ for k in FLAG_SECTION_ATTRIBUTES:
+ if k & self.flags:
+ f['attributes'].append(FLAG_SECTION_ATTRIBUTES[k])
+ if not f['attributes']:
+ del f['attributes']
+ s['flags'] = f
+ s['reserved1'] = int(self.reserved1)
+ s['reserved2'] = int(self.reserved2)
+ s['reserved3'] = int(self.reserved3)
+ return s
+
+ def add_section_data(self, data):
+ self.section_data = data
+
+SECTION_TYPE = 0xff
+SECTION_ATTRIBUTES = 0xffffff00
+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
+
+FLAG_SECTION_TYPES = {
+ 0x0 : "S_REGULAR",
+ 0x1 : "S_ZEROFILL",
+ 0x2 : "S_CSTRING_LITERALS",
+ 0x3 : "S_4BYTE_LITERALS",
+ 0x4 : "S_8BYTE_LITERALS",
+ 0x5 : "S_LITERAL_POINTERS",
+ 0x6 : "S_NON_LAZY_SYMBOL_POINTERS",
+ 0x7 : "S_LAZY_SYMBOL_POINTERS",
+ 0x8 : "S_SYMBOL_STUBS",
+ 0x9 : "S_MOD_INIT_FUNC_POINTERS",
+ 0xa : "S_MOD_TERM_FUNC_POINTERS",
+ 0xb : "S_COALESCED",
+ 0xc : "S_GB_ZEROFILL",
+ 0xd : "S_INTERPOSING",
+ 0xe : "S_16BYTE_LITERALS",
+ 0xf : "S_DTRACE_DOF",
+ 0x10 : "S_LAZY_DYLIB_SYMBOL_POINTERS",
+ 0x11 : "S_THREAD_LOCAL_REGULAR",
+ 0x12 : "S_THREAD_LOCAL_ZEROFILL",
+ 0x13 : "S_THREAD_LOCAL_VARIABLES",
+ 0x14 : "S_THREAD_LOCAL_VARIABLE_POINTERS",
+ 0x15 : "S_THREAD_LOCAL_INIT_FUNCTION_POINTERS"
+}
+
+
+FLAG_SECTION_ATTRIBUTES = {
+ 0x80000000 : "S_ATTR_PURE_INSTRUCTIONS",
+ 0x40000000 : "S_ATTR_NO_TOC",
+ 0x20000000 : "S_ATTR_STRIP_STATIC_SYMS",
+ 0x10000000 : "S_ATTR_NO_DEAD_STRIP",
+ 0x08000000 : "S_ATTR_LIVE_SUPPORT",
+ 0x04000000 : "S_ATTR_SELF_MODIFYING_CODE",
+ 0x02000000 : "S_ATTR_DEBUG",
+ 0x00000400 : "S_ATTR_SOME_INSTRUCTIONS",
+ 0x00000200 : "S_ATTR_EXT_RELOC",
+ 0x00000100 : "S_ATTR_LOC_RELOC"
+}
+
+SECTION_ATTRIBUTES_USR = 0xff000000
+S_ATTR_PURE_INSTRUCTIONS = 0x80000000
+S_ATTR_NO_TOC = 0x40000000
+S_ATTR_STRIP_STATIC_SYMS = 0x20000000
+SECTION_ATTRIBUTES_SYS = 0x00ffff00
+S_ATTR_SOME_INSTRUCTIONS = 0x00000400
+S_ATTR_EXT_RELOC = 0x00000200
+S_ATTR_LOC_RELOC = 0x00000100
+
+
+SEG_PAGEZERO = "__PAGEZERO"
+SEG_TEXT = "__TEXT"
+SECT_TEXT = "__text"
+SECT_FVMLIB_INIT0 = "__fvmlib_init0"
+SECT_FVMLIB_INIT1 = "__fvmlib_init1"
+SEG_DATA = "__DATA"
+SECT_DATA = "__data"
+SECT_BSS = "__bss"
+SECT_COMMON = "__common"
+SEG_OBJC = "__OBJC"
+SECT_OBJC_SYMBOLS = "__symbol_table"
+SECT_OBJC_MODULES = "__module_info"
+SECT_OBJC_STRINGS = "__selector_strs"
+SECT_OBJC_REFS = "__selector_refs"
+SEG_ICON = "__ICON"
+SECT_ICON_HEADER = "__header"
+SECT_ICON_TIFF = "__tiff"
+SEG_LINKEDIT = "__LINKEDIT"
+SEG_UNIXSTACK = "__UNIXSTACK"
+
+#
+# I really should remove all these _command classes because they
+# are no different. I decided to keep the load commands separate,
+# so classes like fvmlib and fvmlib_command are equivalent.
+#
+
+class fvmlib(Structure):
+ _fields_ = (
+ ('name', lc_str),
+ ('minor_version', mach_version_helper),
+ ('header_addr', p_uint32),
+ )
+
+class fvmlib_command(Structure):
+ _fields_ = fvmlib._fields_
+
+ def describe(self):
+ s = {}
+ s['header_addr'] = int(self.header_addr)
+ return s
+
+class dylib(Structure):
+ _fields_ = (
+ ('name', lc_str),
+ ('timestamp', mach_timestamp_helper),
+ ('current_version', mach_version_helper),
+ ('compatibility_version', mach_version_helper),
+ )
+
+# merged dylib structure
+class dylib_command(Structure):
+ _fields_ = dylib._fields_
+
+ def describe(self):
+ s = {}
+ s['timestamp'] = str(self.timestamp)
+ s['current_version'] = str(self.current_version)
+ s['compatibility_version'] = str(self.compatibility_version)
+ return s
+
+class sub_framework_command(Structure):
+ _fields_ = (
+ ('umbrella', lc_str),
+ )
+
+ def describe(self):
+ return {}
+
+class sub_client_command(Structure):
+ _fields_ = (
+ ('client', lc_str),
+ )
+
+ def describe(self):
+ return {}
+
+class sub_umbrella_command(Structure):
+ _fields_ = (
+ ('sub_umbrella', lc_str),
+ )
+
+ def describe(self):
+ return {}
+
+class sub_library_command(Structure):
+ _fields_ = (
+ ('sub_library', lc_str),
+ )
+
+ def describe(self):
+ return {}
+
+class prebound_dylib_command(Structure):
+ _fields_ = (
+ ('name', lc_str),
+ ('nmodules', p_uint32),
+ ('linked_modules', lc_str),
+ )
+
+ def describe(self):
+ return {'nmodules': int(self.nmodules)}
+
+class dylinker_command(Structure):
+ _fields_ = (
+ ('name', lc_str),
+ )
+
+ def describe(self):
+ return {}
+
+class thread_command(Structure):
+ _fields_ = (
+ )
+
+ def describe(self):
+ return {}
+
+class entry_point_command(Structure):
+ _fields_ = (
+ ('entryoff', p_uint64),
+ ('stacksize', p_uint64),
+ )
+
+ def describe(self):
+ s = {}
+ s['entryoff'] = int(self.entryoff)
+ s['stacksize'] = int(self.stacksize)
+ return s
+
+class routines_command(Structure):
+ _fields_ = (
+ ('init_address', p_uint32),
+ ('init_module', p_uint32),
+ ('reserved1', p_uint32),
+ ('reserved2', p_uint32),
+ ('reserved3', p_uint32),
+ ('reserved4', p_uint32),
+ ('reserved5', p_uint32),
+ ('reserved6', p_uint32),
+ )
+
+ def describe(self):
+ s = {}
+ s['init_address'] = int(self.init_address)
+ s['init_module'] = int(self.init_module)
+ s['reserved1'] = int(self.reserved1)
+ s['reserved2'] = int(self.reserved2)
+ s['reserved3'] = int(self.reserved3)
+ s['reserved4'] = int(self.reserved4)
+ s['reserved5'] = int(self.reserved5)
+ s['reserved6'] = int(self.reserved6)
+ return s
+
+class routines_command_64(Structure):
+ _fields_ = (
+ ('init_address', p_uint64),
+ ('init_module', p_uint64),
+ ('reserved1', p_uint64),
+ ('reserved2', p_uint64),
+ ('reserved3', p_uint64),
+ ('reserved4', p_uint64),
+ ('reserved5', p_uint64),
+ ('reserved6', p_uint64),
+ )
+
+ def describe(self):
+ s = {}
+ s['init_address'] = int(self.init_address)
+ s['init_module'] = int(self.init_module)
+ s['reserved1'] = int(self.reserved1)
+ s['reserved2'] = int(self.reserved2)
+ s['reserved3'] = int(self.reserved3)
+ s['reserved4'] = int(self.reserved4)
+ s['reserved5'] = int(self.reserved5)
+ s['reserved6'] = int(self.reserved6)
+ return s
+
+class symtab_command(Structure):
+ _fields_ = (
+ ('symoff', p_uint32),
+ ('nsyms', p_uint32),
+ ('stroff', p_uint32),
+ ('strsize', p_uint32),
+ )
+
+ def describe(self):
+ s = {}
+ s['symoff'] = int(self.symoff)
+ s['nsyms'] = int(self.nsyms)
+ s['stroff'] = int(self.stroff)
+ s['strsize'] = int(self.strsize)
+ return s
+
+
+class dysymtab_command(Structure):
+ _fields_ = (
+ ('ilocalsym', p_uint32),
+ ('nlocalsym', p_uint32),
+ ('iextdefsym', p_uint32),
+ ('nextdefsym', p_uint32),
+ ('iundefsym', p_uint32),
+ ('nundefsym', p_uint32),
+ ('tocoff', p_uint32),
+ ('ntoc', p_uint32),
+ ('modtaboff', p_uint32),
+ ('nmodtab', p_uint32),
+ ('extrefsymoff', p_uint32),
+ ('nextrefsyms', p_uint32),
+ ('indirectsymoff', p_uint32),
+ ('nindirectsyms', p_uint32),
+ ('extreloff', p_uint32),
+ ('nextrel', p_uint32),
+ ('locreloff', p_uint32),
+ ('nlocrel', p_uint32),
+ )
+
+ def describe(self):
+ dys = {}
+ dys['ilocalsym'] = int(self.ilocalsym)
+ dys['nlocalsym'] = int(self.nlocalsym)
+ dys['iextdefsym'] = int(self.iextdefsym)
+ dys['nextdefsym'] = int(self.nextdefsym)
+ dys['iundefsym'] = int(self.iundefsym)
+ dys['nundefsym'] = int(self.nundefsym)
+ dys['tocoff'] = int(self.tocoff)
+ dys['ntoc'] = int(self.ntoc)
+ dys['modtaboff'] = int(self.modtaboff)
+ dys['nmodtab'] = int(self.nmodtab)
+ dys['extrefsymoff'] = int(self.extrefsymoff)
+ dys['nextrefsyms'] = int(self.nextrefsyms)
+ dys['indirectsymoff'] = int(self.indirectsymoff)
+ dys['nindirectsyms'] = int(self.nindirectsyms)
+ dys['extreloff'] = int(self.extreloff)
+ dys['nextrel'] = int(self.nextrel)
+ dys['locreloff'] = int(self.locreloff)
+ dys['nlocrel'] = int(self.nlocrel)
+ return dys
+
+INDIRECT_SYMBOL_LOCAL = 0x80000000
+INDIRECT_SYMBOL_ABS = 0x40000000
+
+class dylib_table_of_contents(Structure):
+ _fields_ = (
+ ('symbol_index', p_uint32),
+ ('module_index', p_uint32),
+ )
+
+class dylib_module(Structure):
+ _fields_ = (
+ ('module_name', p_uint32),
+ ('iextdefsym', p_uint32),
+ ('nextdefsym', p_uint32),
+ ('irefsym', p_uint32),
+ ('nrefsym', p_uint32),
+ ('ilocalsym', p_uint32),
+ ('nlocalsym', p_uint32),
+ ('iextrel', p_uint32),
+ ('nextrel', p_uint32),
+ ('iinit_iterm', p_uint32),
+ ('ninit_nterm', p_uint32),
+ ('objc_module_info_addr', p_uint32),
+ ('objc_module_info_size', p_uint32),
+ )
+
+class dylib_module_64(Structure):
+ _fields_ = (
+ ('module_name', p_uint32),
+ ('iextdefsym', p_uint32),
+ ('nextdefsym', p_uint32),
+ ('irefsym', p_uint32),
+ ('nrefsym', p_uint32),
+ ('ilocalsym', p_uint32),
+ ('nlocalsym', p_uint32),
+ ('iextrel', p_uint32),
+ ('nextrel', p_uint32),
+ ('iinit_iterm', p_uint32),
+ ('ninit_nterm', p_uint32),
+ ('objc_module_info_size', p_uint32),
+ ('objc_module_info_addr', p_uint64),
+ )
+
+class dylib_reference(Structure):
+ _fields_ = (
+ # XXX - ick, fix
+ ('isym_flags', p_uint32),
+ #('isym', p_uint8 * 3),
+ #('flags', p_uint8),
+ )
+
+class twolevel_hints_command(Structure):
+ _fields_ = (
+ ('offset', p_uint32),
+ ('nhints', p_uint32),
+ )
+
+ def describe(self):
+ s = {}
+ s['offset'] = int(self.offset)
+ s['nhints'] = int(self.nhints)
+ return s
+
+class twolevel_hint(Structure):
+ _fields_ = (
+ # XXX - ick, fix
+ ('isub_image_itoc', p_uint32),
+ #('isub_image', p_uint8),
+ #('itoc', p_uint8 * 3),
+ )
+
+class prebind_cksum_command(Structure):
+ _fields_ = (
+ ('cksum', p_uint32),
+ )
+
+ def describe(self):
+ return {'cksum': int(self.cksum)}
+
+class symseg_command(Structure):
+ _fields_ = (
+ ('offset', p_uint32),
+ ('size', p_uint32),
+ )
+
+ def describe(self):
+ s = {}
+ s['offset'] = int(self.offset)
+ s['size'] = int(self.size)
+
+class ident_command(Structure):
+ _fields_ = (
+ )
+
+ def describe(self):
+ return {}
+
+class fvmfile_command(Structure):
+ _fields_ = (
+ ('name', lc_str),
+ ('header_addr', p_uint32),
+ )
+
+ def describe(self):
+ return {'header_addr': int(self.header_addr)}
+
+class uuid_command (Structure):
+ _fields_ = (
+ ('uuid', p_str16),
+ )
+
+ def describe(self):
+ return {'uuid': self.uuid.rstrip('\x00')}
+
+class rpath_command (Structure):
+ _fields_ = (
+ ('path', lc_str),
+ )
+
+ def describe(self):
+ return {}
+
+
+class linkedit_data_command (Structure):
+ _fields_ = (
+ ('dataoff', p_uint32),
+ ('datasize', p_uint32),
+ )
+
+ def describe(self):
+ s = {}
+ s['dataoff'] = int(self.dataoff)
+ s['datasize'] = int(self.datasize)
+ return s
+
+
+class version_min_command (Structure):
+ _fields_ = (
+ ('version', p_uint32), # X.Y.Z is encoded in nibbles xxxx.yy.zz
+ ('reserved', p_uint32),
+ )
+
+ def describe(self):
+ v = int(self.version)
+ v3 = v & 0xFF
+ v = v >> 8
+ v2 = v & 0xFF
+ v = v >> 8
+ v1 = v & 0xFFFF
+ return {'version': str(int(v1)) + "." + str(int(v2)) + "." + str(int(v3))}
+
+class source_version_command (Structure):
+ _fields_ = (
+ ('version', p_uint64),
+ )
+
+ def describe(self):
+ v = int(self.version)
+ a = v >> 40
+ b = (v >> 30) & 0x3ff
+ c = (v >> 20) & 0x3ff
+ d = (v >> 10) & 0x3ff
+ e = v & 0x3ff
+ r = str(a)+'.'+str(b)+'.'+str(c)+'.'+str(d)+'.'+str(e)
+ return {'version': r}
+
+class encryption_info_command (Structure):
+ _fields_ = (
+ ('cryptoff', p_uint32),
+ ('cryptsize', p_uint32),
+ ('cryptid', p_uint32),
+ )
+
+ def describe(self):
+ s = {}
+ s['cryptoff'] = int(self.cryptoff)
+ s['cryptsize'] = int(self.cryptsize)
+ s['cryptid'] = int(self.cryptid)
+ return s
+
+class encryption_info_command_64 (Structure):
+ _fields_ = (
+ ('cryptoff', p_uint32),
+ ('cryptsize', p_uint32),
+ ('cryptid', p_uint32),
+ ('pad', p_uint32),
+ )
+
+ def describe(self):
+ s = {}
+ s['cryptoff'] = int(self.cryptoff)
+ s['cryptsize'] = int(self.cryptsize)
+ s['cryptid'] = int(self.cryptid)
+ s['pad'] = int(self.pad)
+ return s
+
+
+class dyld_info_command (Structure):
+ _fields_ = (
+ ('rebase_off', p_uint32),
+ ('rebase_size', p_uint32),
+ ('bind_off', p_uint32),
+ ('bind_size', p_uint32),
+ ('weak_bind_off', p_uint32),
+ ('weak_bind_size', p_uint32),
+ ('lazy_bind_off', p_uint32),
+ ('lazy_bind_size', p_uint32),
+ ('export_off', p_uint32),
+ ('export_size', p_uint32),
+ )
+
+ def describe(self):
+ dyld = {}
+ dyld['rebase_off'] = int(self.rebase_off)
+ dyld['rebase_size'] = int(self.rebase_size)
+ dyld['bind_off'] = int(self.bind_off)
+ dyld['bind_size'] = int(self.bind_size)
+ dyld['weak_bind_off'] = int(self.weak_bind_off)
+ dyld['weak_bind_size'] = int(self.weak_bind_size)
+ dyld['lazy_bind_off'] = int(self.lazy_bind_off)
+ dyld['lazy_bind_size'] = int(self.lazy_bind_size)
+ dyld['export_off'] = int(self.export_off)
+ dyld['export_size'] = int(self.export_size)
+ return dyld
+
+class linker_option_command (Structure):
+ _fields_ = (
+ ('count', p_uint32),
+ )
+
+ def describe(self):
+ return {'count': int(self.count)}
+
+
+LC_REGISTRY = {
+ LC_SEGMENT: segment_command,
+ LC_IDFVMLIB: fvmlib_command,
+ LC_LOADFVMLIB: fvmlib_command,
+ LC_ID_DYLIB: dylib_command,
+ LC_LOAD_DYLIB: dylib_command,
+ LC_LOAD_WEAK_DYLIB: dylib_command,
+ LC_SUB_FRAMEWORK: sub_framework_command,
+ LC_SUB_CLIENT: sub_client_command,
+ LC_SUB_UMBRELLA: sub_umbrella_command,
+ LC_SUB_LIBRARY: sub_library_command,
+ LC_PREBOUND_DYLIB: prebound_dylib_command,
+ LC_ID_DYLINKER: dylinker_command,
+ LC_LOAD_DYLINKER: dylinker_command,
+ LC_THREAD: thread_command,
+ LC_UNIXTHREAD: thread_command,
+ LC_ROUTINES: routines_command,
+ LC_SYMTAB: symtab_command,
+ LC_DYSYMTAB: dysymtab_command,
+ LC_TWOLEVEL_HINTS: twolevel_hints_command,
+ LC_PREBIND_CKSUM: prebind_cksum_command,
+ LC_SYMSEG: symseg_command,
+ LC_IDENT: ident_command,
+ LC_FVMFILE: fvmfile_command,
+ LC_SEGMENT_64: segment_command_64,
+ LC_ROUTINES_64: routines_command_64,
+ LC_UUID: uuid_command,
+ LC_RPATH: rpath_command,
+ LC_CODE_SIGNATURE: linkedit_data_command,
+ LC_CODE_SEGMENT_SPLIT_INFO: linkedit_data_command,
+ LC_REEXPORT_DYLIB: dylib_command,
+ LC_LAZY_LOAD_DYLIB: dylib_command,
+ LC_ENCRYPTION_INFO: encryption_info_command,
+ LC_DYLD_INFO: dyld_info_command,
+ LC_DYLD_INFO_ONLY: dyld_info_command,
+ LC_LOAD_UPWARD_DYLIB: dylib_command,
+ LC_VERSION_MIN_MACOSX: version_min_command,
+ LC_VERSION_MIN_IPHONEOS: version_min_command,
+ LC_FUNCTION_STARTS: linkedit_data_command,
+ LC_DYLD_ENVIRONMENT: dylinker_command,
+ LC_MAIN: entry_point_command,
+ LC_DATA_IN_CODE: linkedit_data_command,
+ LC_SOURCE_VERSION: source_version_command,
+ LC_DYLIB_CODE_SIGN_DRS: linkedit_data_command,
+ LC_ENCRYPTION_INFO_64: encryption_info_command_64,
+ LC_LINKER_OPTION: linker_option_command,
+}
+
+LC_NAMES = {
+ LC_SEGMENT: 'LC_SEGMENT',
+ LC_IDFVMLIB: 'LC_IDFVMLIB',
+ LC_LOADFVMLIB: 'LC_LOADFVMLIB',
+ LC_ID_DYLIB: 'LC_ID_DYLIB',
+ LC_LOAD_DYLIB: 'LC_LOAD_DYLIB',
+ LC_LOAD_WEAK_DYLIB: 'LC_LOAD_WEAK_DYLIB',
+ LC_SUB_FRAMEWORK: 'LC_SUB_FRAMEWORK',
+ LC_SUB_CLIENT: 'LC_SUB_CLIENT',
+ LC_SUB_UMBRELLA: 'LC_SUB_UMBRELLA',
+ LC_SUB_LIBRARY: 'LC_SUB_LIBRARY',
+ LC_PREBOUND_DYLIB: 'LC_PREBOUND_DYLIB',
+ LC_ID_DYLINKER: 'LC_ID_DYLINKER',
+ LC_LOAD_DYLINKER: 'LC_LOAD_DYLINKER',
+ LC_THREAD: 'LC_THREAD',
+ LC_UNIXTHREAD: 'LC_UNIXTHREAD',
+ LC_ROUTINES: 'LC_ROUTINES',
+ LC_SYMTAB: 'LC_SYMTAB',
+ LC_DYSYMTAB: 'LC_DYSYMTAB',
+ LC_TWOLEVEL_HINTS: 'LC_TWOLEVEL_HINTS',
+ LC_PREBIND_CKSUM: 'LC_PREBIND_CKSUM',
+ LC_SYMSEG: 'LC_SYMSEG',
+ LC_IDENT: 'LC_IDENT',
+ LC_FVMFILE: 'LC_FVMFILE',
+ LC_SEGMENT_64: 'LC_SEGMENT_64',
+ LC_ROUTINES_64: 'LC_ROUTINES_64',
+ LC_UUID: 'LC_UUID',
+ LC_RPATH: 'LC_RPATH',
+ LC_CODE_SIGNATURE: 'LC_CODE_SIGNATURE',
+ LC_CODE_SEGMENT_SPLIT_INFO: 'LC_CODE_SEGMENT_SPLIT_INFO',
+ LC_REEXPORT_DYLIB: 'LC_REEXPORT_DYLIB',
+ LC_LAZY_LOAD_DYLIB: 'LC_LAZY_LOAD_DYLIB',
+ LC_ENCRYPTION_INFO: 'LC_ENCRYPTION_INFO',
+ LC_DYLD_INFO: 'LC_DYLD_INFO',
+ LC_DYLD_INFO_ONLY: 'LC_DYLD_INFO_ONLY',
+ LC_LOAD_UPWARD_DYLIB: 'LC_LOAD_UPWARD_DYLIB',
+ LC_VERSION_MIN_MACOSX: 'LC_VERSION_MIN_MACOSX',
+ LC_VERSION_MIN_IPHONEOS: 'LC_VERSION_MIN_IPHONEOS',
+ LC_FUNCTION_STARTS: 'LC_FUNCTION_STARTS',
+ LC_DYLD_ENVIRONMENT: 'LC_DYLD_ENVIRONMENT',
+ LC_MAIN: 'LC_MAIN',
+ LC_DATA_IN_CODE: 'LC_DATA_IN_CODE',
+ LC_SOURCE_VERSION: 'LC_SOURCE_VERSION',
+ LC_DYLIB_CODE_SIGN_DRS: 'LC_DYLIB_CODE_SIGN_DRS',
+}
+
+
+#this is another union.
+class n_un(p_int32):
+ pass
+
+class nlist(Structure):
+ _fields_ = (
+ ('n_un', n_un),
+ ('n_type', p_uint8),
+ ('n_sect', p_uint8),
+ ('n_desc', p_short),
+ ('n_value', p_uint32),
+ )
+
+class nlist_64(Structure):
+ _fields_ = [
+ ('n_un', n_un),
+ ('n_type', p_uint8),
+ ('n_sect', p_uint8),
+ ('n_desc', p_short),
+ ('n_value', p_int64),
+ ]
+
+N_STAB = 0xe0
+N_PEXT = 0x10
+N_TYPE = 0x0e
+N_EXT = 0x01
+
+N_UNDF = 0x0
+N_ABS = 0x2
+N_SECT = 0xe
+N_PBUD = 0xc
+N_INDR = 0xa
+
+NO_SECT = 0
+MAX_SECT = 255
+
+REFERENCE_TYPE = 0xf
+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
+
+REFERENCED_DYNAMICALLY = 0x0010
+
+def GET_LIBRARY_ORDINAL(n_desc):
+ return (((n_desc) >> 8) & 0xff)
+
+def SET_LIBRARY_ORDINAL(n_desc, ordinal):
+ return (((n_desc) & 0x00ff) | (((ordinal & 0xff) << 8)))
+
+SELF_LIBRARY_ORDINAL = 0x0
+MAX_LIBRARY_ORDINAL = 0xfd
+DYNAMIC_LOOKUP_ORDINAL = 0xfe
+EXECUTABLE_ORDINAL = 0xff
+
+N_DESC_DISCARDED = 0x0020
+N_WEAK_REF = 0x0040
+N_WEAK_DEF = 0x0080
+
+# /usr/include/mach-o/fat.h
+FAT_MAGIC = 0xcafebabe
+class fat_header(Structure):
+ _fields_ = (
+ ('magic', p_uint32),
+ ('nfat_arch', p_uint32),
+ )
+
+class fat_arch(Structure):
+ _fields_ = (
+ ('cputype', cpu_type_t),
+ ('cpusubtype', cpu_subtype_t),
+ ('offset', p_uint32),
+ ('size', p_uint32),
+ ('align', p_uint32),
+ )