diff options
Diffstat (limited to 'lib/spack/external/macholib/mach_o.py')
-rw-r--r-- | lib/spack/external/macholib/mach_o.py | 1665 |
1 files changed, 1665 insertions, 0 deletions
diff --git a/lib/spack/external/macholib/mach_o.py b/lib/spack/external/macholib/mach_o.py new file mode 100644 index 0000000000..7c5803d939 --- /dev/null +++ b/lib/spack/external/macholib/mach_o.py @@ -0,0 +1,1665 @@ +""" +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 p_uint32, p_uint64, Structure, p_long, pypackable +from macholib.ptypes import p_int64, p_short, p_uint8, p_int32, p_ulong + +_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", + 8: "CPU_SUBTYPE_X86_64_H", +} + +# 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", + 11: "CPU_SUBTYPE_ARM_V7S", + 12: "CPU_SUBTYPE_ARM_V7K", + 13: "CPU_SUBTYPE_ARM_V8", + 14: "CPU_SUBTYPE_ARM_V6M", + 15: "CPU_SUBTYPE_ARM_V7M", + 16: "CPU_SUBTYPE_ARM_V7EM", +} + +ARM64_SUBTYPE = { + 0: "CPU_SUBTYPE_ARM64_ALL", + 1: "CPU_SUBTYPE_ARM64_V8", +} + +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 == 12 | _CPU_ARCH_ABI64: + subtype = ARM64_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, + MH_APP_EXTENSION_SAFE +) = map((1).__lshift__, range(26)) + +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_APP_EXTENSION_SAFE: 'MH_APP_EXTENSION_SAFE', +} + +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', + MH_APP_EXTENSION_SAFE: + 'the code was linked for use in an application extension.', +} + + +class mach_version_helper(Structure): + _fields_ = ( + ('_version', p_uint32), + ) + + @property + def major(self): + return self._version >> 16 & 0xffff + + @major.setter + def major(self, v): + self._version = (self._version & 0xffff) | (v << 16) + + @property + def minor(self): + return self._version >> 8 & 0xff + + @minor.setter + def minor(self, v): + self._version = (self._version & 0xffff00ff) | (v << 8) + + @property + def rev(self): + return self._version & 0xff + + @rev.setter + def rev(self, v): + return (self._version & 0xffffff00) | v + + 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 +LC_LINKER_OPTIMIZATION_HINT = 0x2e +LC_VERSION_MIN_TVOS = 0x2f +LC_VERSION_MIN_WATCHOS = 0x30 +LC_NOTE = 0x31 +LC_BUILD_VERSION = 0x32 + + +# 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): + 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 +SG_PROTECTED_VERSION_1 = 0x8 + + +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 +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 + +FLAG_SECTION_TYPES = { + S_REGULAR: "S_REGULAR", + S_ZEROFILL: "S_ZEROFILL", + S_CSTRING_LITERALS: "S_CSTRING_LITERALS", + S_4BYTE_LITERALS: "S_4BYTE_LITERALS", + S_8BYTE_LITERALS: "S_8BYTE_LITERALS", + S_LITERAL_POINTERS: "S_LITERAL_POINTERS", + S_NON_LAZY_SYMBOL_POINTERS: "S_NON_LAZY_SYMBOL_POINTERS", + S_LAZY_SYMBOL_POINTERS: "S_LAZY_SYMBOL_POINTERS", + S_SYMBOL_STUBS: "S_SYMBOL_STUBS", + S_MOD_INIT_FUNC_POINTERS: "S_MOD_INIT_FUNC_POINTERS", + S_MOD_TERM_FUNC_POINTERS: "S_MOD_TERM_FUNC_POINTERS", + S_COALESCED: "S_COALESCED", + S_GB_ZEROFILL: "S_GB_ZEROFILL", + S_INTERPOSING: "S_INTERPOSING", + S_16BYTE_LITERALS: "S_16BYTE_LITERALS", + S_DTRACE_DOF: "S_DTRACE_DOF", + S_LAZY_DYLIB_SYMBOL_POINTERS: "S_LAZY_DYLIB_SYMBOL_POINTERS", + S_THREAD_LOCAL_REGULAR: "S_THREAD_LOCAL_REGULAR", + S_THREAD_LOCAL_ZEROFILL: "S_THREAD_LOCAL_ZEROFILL", + S_THREAD_LOCAL_VARIABLES: "S_THREAD_LOCAL_VARIABLES", + S_THREAD_LOCAL_VARIABLE_POINTERS: "S_THREAD_LOCAL_VARIABLE_POINTERS", + S_THREAD_LOCAL_INIT_FUNCTION_POINTERS: + "S_THREAD_LOCAL_INIT_FUNCTION_POINTERS" +} + +SECTION_ATTRIBUTES_USR = 0xff000000 +S_ATTR_PURE_INSTRUCTIONS = 0x80000000 +S_ATTR_NO_TOC = 0x40000000 +S_ATTR_STRIP_STATIC_SYMS = 0x20000000 +S_ATTR_NO_DEAD_STRIP = 0x10000000 +S_ATTR_LIVE_SUPPORT = 0x08000000 +S_ATTR_SELF_MODIFYING_CODE = 0x04000000 +S_ATTR_DEBUG = 0x02000000 + +SECTION_ATTRIBUTES_SYS = 0x00ffff00 +S_ATTR_SOME_INSTRUCTIONS = 0x00000400 +S_ATTR_EXT_RELOC = 0x00000200 +S_ATTR_LOC_RELOC = 0x00000100 + +FLAG_SECTION_ATTRIBUTES = { + S_ATTR_PURE_INSTRUCTIONS: "S_ATTR_PURE_INSTRUCTIONS", + S_ATTR_NO_TOC: "S_ATTR_NO_TOC", + S_ATTR_STRIP_STATIC_SYMS: "S_ATTR_STRIP_STATIC_SYMS", + S_ATTR_NO_DEAD_STRIP: "S_ATTR_NO_DEAD_STRIP", + S_ATTR_LIVE_SUPPORT: "S_ATTR_LIVE_SUPPORT", + S_ATTR_SELF_MODIFYING_CODE: "S_ATTR_SELF_MODIFYING_CODE", + S_ATTR_DEBUG: "S_ATTR_DEBUG", + S_ATTR_SOME_INSTRUCTIONS: "S_ATTR_SOME_INSTRUCTIONS", + S_ATTR_EXT_RELOC: "S_ATTR_EXT_RELOC", + S_ATTR_LOC_RELOC: "S_ATTR_LOC_RELOC" +} + +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" +SEG_IMPORT = "__IMPORT" + +# +# 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_ = ( + ('flavor', p_uint32), + ('count', p_uint32) + ) + + def describe(self): + s = {} + s['flavor'] = int(self.flavor) + s['count'] = int(self.count) + return s + + +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 + ('sdk', p_uint32), + ) + + def describe(self): + v = int(self.version) + v3 = v & 0xFF + v = v >> 8 + v2 = v & 0xFF + v = v >> 8 + v1 = v & 0xFFFF + s = int(self.sdk) + s3 = s & 0xFF + s = s >> 8 + s2 = s & 0xFF + s = s >> 8 + s1 = s & 0xFFFF + return { + 'version': str(int(v1)) + "." + str(int(v2)) + "." + str(int(v3)), + 'sdk': str(int(s1)) + "." + str(int(s2)) + "." + str(int(s3)) + } + + +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 note_command (Structure): + _fields_ = ( + ('data_owner', p_str16), + ('offset', p_uint64), + ('size', p_uint64), + ) + + +class build_version_command (Structure): + _fields_ = ( + ('platform', p_uint32), + ('minos', p_uint32), + ('sdk', p_uint32), + ('ntools', p_uint32), + ) + + # XXX: Add computed field for accessing 'tools' array + + +class build_tool_version (Structure): + _fields_ = ( + ('tool', p_uint32), + ('version', p_uint32), + ) + + +class data_in_code_entry (Structure): + _fields_ = ( + ('offset', p_uint32), + ('length', p_uint32), + ('kind', p_uint32), + ) + + def describe(self): + return { + 'offset': self.offset, 'length': self.length, 'kind': self.kind} + + +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 + +DATA_IN_CODE_KINDS = { + DICE_KIND_DATA: 'DICE_KIND_DATA', + DICE_KIND_JUMP_TABLE8: 'DICE_KIND_JUMP_TABLE8', + DICE_KIND_JUMP_TABLE16: 'DICE_KIND_JUMP_TABLE16', + DICE_KIND_JUMP_TABLE32: 'DICE_KIND_JUMP_TABLE32', + DICE_KIND_ABS_JUMP_TABLE32: 'DICE_KIND_ABS_JUMP_TABLE32', +} + + +class tlv_descriptor (Structure): + _fields_ = ( + ('thunk', p_long), # Actually a pointer to a function + ('key', p_ulong), + ('offset', p_ulong), + ) + + def describe(self): + return {'thunk': self.thunk, 'key': self.key, 'offset': self.offset} + + +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_LINKER_OPTIMIZATION_HINT: linkedit_data_command, + LC_VERSION_MIN_TVOS: version_min_command, + LC_VERSION_MIN_WATCHOS: version_min_command, + LC_NOTE: note_command, + LC_BUILD_VERSION: build_version_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', + LC_LINKER_OPTIMIZATION_HINT: 'LC_LINKER_OPTIMIZATION_HINT', + LC_VERSION_MIN_TVOS: 'LC_VERSION_MIN_TVOS', + LC_VERSION_MIN_WATCHOS: 'LC_VERSION_MIN_WATCHOS', + LC_NOTE: 'LC_NOTE', + LC_BUILD_VERSION: 'LC_BUILD_VERSION', +} + + +# 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 + + +class relocation_info(Structure): + # XXX: Need to add code for decoding the bitfield! + _fields_ = ( + ('r_address', p_uint32), + ('_r_bitfield', p_uint32), + ) + + def _describe(self): + return ( + ('r_address', self.r_address), + ('_r_bitfield', self._r_bitfield), + ) + + +def GET_COMM_ALIGN(n_desc): + return (n_desc >> 8) & 0x0f + + +def SET_COMM_ALIGN(n_desc, align): + return (n_desc & 0xf0ff) | ((align & 0x0f) << 8) + + +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_NO_DEAD_STRIP = 0x0020 +N_DESC_DISCARDED = 0x0020 +N_WEAK_REF = 0x0040 +N_WEAK_DEF = 0x0080 +N_REF_TO_WEAK = 0x0080 +N_ARM_THUMB_DEF = 0x0008 +N_SYMBOL_RESOLVER = 0x0100 +N_ALT_ENTRY = 0x0200 + +# /usr/include/mach-o/fat.h +FAT_MAGIC = 0xcafebabe +FAT_CIGAM = 0xbebafeca +FAT_MAGIC_64 = 0xcafebabf +FAT_CIGAM_64 = 0xbfbafeca + + +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), + ) + + +class fat_arch64(Structure): + _fields_ = ( + ('cputype', cpu_type_t), + ('cpusubtype', cpu_subtype_t), + ('offset', p_uint64), + ('size', p_uint64), + ('align', p_uint32), + ('reserved', p_uint32), + ) + + +REBASE_TYPE_POINTER = 1 # noqa: E221 +REBASE_TYPE_TEXT_ABSOLUTE32 = 2 # noqa: E221 +REBASE_TYPE_TEXT_PCREL32 = 3 # noqa: E221 + +REBASE_OPCODE_MASK = 0xF0 # noqa: E221 +REBASE_IMMEDIATE_MASK = 0x0F # noqa: E221 +REBASE_OPCODE_DONE = 0x00 # noqa: E221 +REBASE_OPCODE_SET_TYPE_IMM = 0x10 # noqa: E221 +REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB = 0x20 # noqa: E221 +REBASE_OPCODE_ADD_ADDR_ULEB = 0x30 # noqa: E221 +REBASE_OPCODE_ADD_ADDR_IMM_SCALED = 0x40 # noqa: E221 +REBASE_OPCODE_DO_REBASE_IMM_TIMES = 0x50 # noqa: E221 +REBASE_OPCODE_DO_REBASE_ULEB_TIMES = 0x60 # noqa: E221 +REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB = 0x70 # noqa: E221 +REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB = 0x80 # noqa: E221 + +BIND_TYPE_POINTER = 1 # noqa: E221 +BIND_TYPE_TEXT_ABSOLUTE32 = 2 # noqa: E221 +BIND_TYPE_TEXT_PCREL32 = 3 # noqa: E221 + +BIND_SPECIAL_DYLIB_SELF = 0 # noqa: E221 +BIND_SPECIAL_DYLIB_MAIN_EXECUTABLE = -1 # noqa: E221 +BIND_SPECIAL_DYLIB_FLAT_LOOKUP = -2 # noqa: E221 + +BIND_SYMBOL_FLAGS_WEAK_IMPORT = 0x1 # noqa: E221 +BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION = 0x8 # noqa: E221 + +BIND_OPCODE_MASK = 0xF0 # noqa: E221 +BIND_IMMEDIATE_MASK = 0x0F # noqa: E221 +BIND_OPCODE_DONE = 0x00 # noqa: E221 +BIND_OPCODE_SET_DYLIB_ORDINAL_IMM = 0x10 # noqa: E221 +BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB = 0x20 # noqa: E221 +BIND_OPCODE_SET_DYLIB_SPECIAL_IMM = 0x30 # noqa: E221 +BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM = 0x40 # noqa: E221 +BIND_OPCODE_SET_TYPE_IMM = 0x50 # noqa: E221 +BIND_OPCODE_SET_ADDEND_SLEB = 0x60 # noqa: E221 +BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB = 0x70 # noqa: E221 +BIND_OPCODE_ADD_ADDR_ULEB = 0x80 # noqa: E221 +BIND_OPCODE_DO_BIND = 0x90 # noqa: E221 +BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB = 0xA0 # noqa: E221 +BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED = 0xB0 # noqa: E221 +BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB = 0xC0 # noqa: E221 + +EXPORT_SYMBOL_FLAGS_KIND_MASK = 0x03 # noqa: E221 +EXPORT_SYMBOL_FLAGS_KIND_REGULAR = 0x00 # noqa: E221 +EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL = 0x01 # noqa: E221 +EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION = 0x04 # noqa: E221 +EXPORT_SYMBOL_FLAGS_REEXPORT = 0x08 # noqa: E221 +EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER = 0x10 # noqa: E221 + +PLATFORM_MACOS = 1 +PLATFORM_IOS = 2 +PLATFORM_TVOS = 3 +PLATFORM_WATCHOS = 4 +PLATFORM_BRIDGEOS = 5 +PLATFORM_IOSMAC = 6 +PLATFORM_IOSSIMULATOR = 7 +PLATFORM_TVOSSIMULATOR = 8 +PLATFORM_WATCHOSSIMULATOR = 9 + +PLATFORM_NAMES = { + PLATFORM_MACOS: 'macOS', + PLATFORM_IOS: 'iOS', + PLATFORM_TVOS: 'tvOS', + PLATFORM_WATCHOS: 'watchOS', + PLATFORM_BRIDGEOS: 'bridgeOS', + PLATFORM_IOSMAC: 'ios-on-mac', + PLATFORM_IOSSIMULATOR: 'iOS simulator', + PLATFORM_TVOSSIMULATOR: 'tvOS simulator', + PLATFORM_WATCHOSSIMULATOR: 'watchOS simulator', +} + +TOOL_CLANG = 1 +TOOL_SWIFT = 2 +TOOL_LD = 3 + +TOOL_NAMES = { + TOOL_CLANG: 'clang', + TOOL_SWIFT: 'swift', + TOOL_LD: 'ld', +} |