1665 lines
48 KiB
Python
1665 lines
48 KiB
Python
"""
|
|
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',
|
|
}
|