1*515bc8c1Sserge-sans-paille#!/usr/bin/env python 2525cd59fSSerge Gueltonfrom __future__ import print_function 36a23d212SGreg Clayton 46a23d212SGreg Claytonimport cmd 56a23d212SGreg Claytonimport dict_utils 66a23d212SGreg Claytonimport file_extract 76a23d212SGreg Claytonimport optparse 86a23d212SGreg Claytonimport re 96a23d212SGreg Claytonimport struct 106a23d212SGreg Claytonimport string 113a22c3ccSSerge Gueltonimport io 126a23d212SGreg Claytonimport sys 136a23d212SGreg Claytonimport uuid 146a23d212SGreg Clayton 156a23d212SGreg Clayton# Mach header "magic" constants 166a23d212SGreg ClaytonMH_MAGIC = 0xfeedface 176a23d212SGreg ClaytonMH_CIGAM = 0xcefaedfe 186a23d212SGreg ClaytonMH_MAGIC_64 = 0xfeedfacf 196a23d212SGreg ClaytonMH_CIGAM_64 = 0xcffaedfe 206a23d212SGreg ClaytonFAT_MAGIC = 0xcafebabe 216a23d212SGreg ClaytonFAT_CIGAM = 0xbebafeca 226a23d212SGreg Clayton 236a23d212SGreg Clayton# Mach haeder "filetype" constants 246a23d212SGreg ClaytonMH_OBJECT = 0x00000001 256a23d212SGreg ClaytonMH_EXECUTE = 0x00000002 266a23d212SGreg ClaytonMH_FVMLIB = 0x00000003 276a23d212SGreg ClaytonMH_CORE = 0x00000004 286a23d212SGreg ClaytonMH_PRELOAD = 0x00000005 296a23d212SGreg ClaytonMH_DYLIB = 0x00000006 306a23d212SGreg ClaytonMH_DYLINKER = 0x00000007 316a23d212SGreg ClaytonMH_BUNDLE = 0x00000008 326a23d212SGreg ClaytonMH_DYLIB_STUB = 0x00000009 336a23d212SGreg ClaytonMH_DSYM = 0x0000000a 346a23d212SGreg ClaytonMH_KEXT_BUNDLE = 0x0000000b 356a23d212SGreg Clayton 366a23d212SGreg Clayton# Mach haeder "flag" constant bits 376a23d212SGreg ClaytonMH_NOUNDEFS = 0x00000001 386a23d212SGreg ClaytonMH_INCRLINK = 0x00000002 396a23d212SGreg ClaytonMH_DYLDLINK = 0x00000004 406a23d212SGreg ClaytonMH_BINDATLOAD = 0x00000008 416a23d212SGreg ClaytonMH_PREBOUND = 0x00000010 426a23d212SGreg ClaytonMH_SPLIT_SEGS = 0x00000020 436a23d212SGreg ClaytonMH_LAZY_INIT = 0x00000040 446a23d212SGreg ClaytonMH_TWOLEVEL = 0x00000080 456a23d212SGreg ClaytonMH_FORCE_FLAT = 0x00000100 466a23d212SGreg ClaytonMH_NOMULTIDEFS = 0x00000200 476a23d212SGreg ClaytonMH_NOFIXPREBINDING = 0x00000400 486a23d212SGreg ClaytonMH_PREBINDABLE = 0x00000800 496a23d212SGreg ClaytonMH_ALLMODSBOUND = 0x00001000 506a23d212SGreg ClaytonMH_SUBSECTIONS_VIA_SYMBOLS = 0x00002000 516a23d212SGreg ClaytonMH_CANONICAL = 0x00004000 526a23d212SGreg ClaytonMH_WEAK_DEFINES = 0x00008000 536a23d212SGreg ClaytonMH_BINDS_TO_WEAK = 0x00010000 546a23d212SGreg ClaytonMH_ALLOW_STACK_EXECUTION = 0x00020000 556a23d212SGreg ClaytonMH_ROOT_SAFE = 0x00040000 566a23d212SGreg ClaytonMH_SETUID_SAFE = 0x00080000 576a23d212SGreg ClaytonMH_NO_REEXPORTED_DYLIBS = 0x00100000 586a23d212SGreg ClaytonMH_PIE = 0x00200000 596a23d212SGreg ClaytonMH_DEAD_STRIPPABLE_DYLIB = 0x00400000 606a23d212SGreg ClaytonMH_HAS_TLV_DESCRIPTORS = 0x00800000 616a23d212SGreg ClaytonMH_NO_HEAP_EXECUTION = 0x01000000 626a23d212SGreg Clayton 636a23d212SGreg Clayton# Mach load command constants 646a23d212SGreg ClaytonLC_REQ_DYLD = 0x80000000 656a23d212SGreg ClaytonLC_SEGMENT = 0x00000001 666a23d212SGreg ClaytonLC_SYMTAB = 0x00000002 676a23d212SGreg ClaytonLC_SYMSEG = 0x00000003 686a23d212SGreg ClaytonLC_THREAD = 0x00000004 696a23d212SGreg ClaytonLC_UNIXTHREAD = 0x00000005 706a23d212SGreg ClaytonLC_LOADFVMLIB = 0x00000006 716a23d212SGreg ClaytonLC_IDFVMLIB = 0x00000007 726a23d212SGreg ClaytonLC_IDENT = 0x00000008 736a23d212SGreg ClaytonLC_FVMFILE = 0x00000009 746a23d212SGreg ClaytonLC_PREPAGE = 0x0000000a 756a23d212SGreg ClaytonLC_DYSYMTAB = 0x0000000b 766a23d212SGreg ClaytonLC_LOAD_DYLIB = 0x0000000c 776a23d212SGreg ClaytonLC_ID_DYLIB = 0x0000000d 786a23d212SGreg ClaytonLC_LOAD_DYLINKER = 0x0000000e 796a23d212SGreg ClaytonLC_ID_DYLINKER = 0x0000000f 806a23d212SGreg ClaytonLC_PREBOUND_DYLIB = 0x00000010 816a23d212SGreg ClaytonLC_ROUTINES = 0x00000011 826a23d212SGreg ClaytonLC_SUB_FRAMEWORK = 0x00000012 836a23d212SGreg ClaytonLC_SUB_UMBRELLA = 0x00000013 846a23d212SGreg ClaytonLC_SUB_CLIENT = 0x00000014 856a23d212SGreg ClaytonLC_SUB_LIBRARY = 0x00000015 866a23d212SGreg ClaytonLC_TWOLEVEL_HINTS = 0x00000016 876a23d212SGreg ClaytonLC_PREBIND_CKSUM = 0x00000017 886a23d212SGreg ClaytonLC_LOAD_WEAK_DYLIB = 0x00000018 | LC_REQ_DYLD 896a23d212SGreg ClaytonLC_SEGMENT_64 = 0x00000019 906a23d212SGreg ClaytonLC_ROUTINES_64 = 0x0000001a 916a23d212SGreg ClaytonLC_UUID = 0x0000001b 926a23d212SGreg ClaytonLC_RPATH = 0x0000001c | LC_REQ_DYLD 936a23d212SGreg ClaytonLC_CODE_SIGNATURE = 0x0000001d 946a23d212SGreg ClaytonLC_SEGMENT_SPLIT_INFO = 0x0000001e 956a23d212SGreg ClaytonLC_REEXPORT_DYLIB = 0x0000001f | LC_REQ_DYLD 966a23d212SGreg ClaytonLC_LAZY_LOAD_DYLIB = 0x00000020 976a23d212SGreg ClaytonLC_ENCRYPTION_INFO = 0x00000021 986a23d212SGreg ClaytonLC_DYLD_INFO = 0x00000022 996a23d212SGreg ClaytonLC_DYLD_INFO_ONLY = 0x00000022 | LC_REQ_DYLD 1006a23d212SGreg ClaytonLC_LOAD_UPWARD_DYLIB = 0x00000023 | LC_REQ_DYLD 1016a23d212SGreg ClaytonLC_VERSION_MIN_MACOSX = 0x00000024 1026a23d212SGreg ClaytonLC_VERSION_MIN_IPHONEOS = 0x00000025 1036a23d212SGreg ClaytonLC_FUNCTION_STARTS = 0x00000026 1046a23d212SGreg ClaytonLC_DYLD_ENVIRONMENT = 0x00000027 1056a23d212SGreg Clayton 1066a23d212SGreg Clayton# Mach CPU constants 1076a23d212SGreg ClaytonCPU_ARCH_MASK = 0xff000000 1086a23d212SGreg ClaytonCPU_ARCH_ABI64 = 0x01000000 1096a23d212SGreg ClaytonCPU_TYPE_ANY = 0xffffffff 1106a23d212SGreg ClaytonCPU_TYPE_VAX = 1 1116a23d212SGreg ClaytonCPU_TYPE_MC680x0 = 6 1126a23d212SGreg ClaytonCPU_TYPE_I386 = 7 1136a23d212SGreg ClaytonCPU_TYPE_X86_64 = CPU_TYPE_I386 | CPU_ARCH_ABI64 1146a23d212SGreg ClaytonCPU_TYPE_MIPS = 8 1156a23d212SGreg ClaytonCPU_TYPE_MC98000 = 10 1166a23d212SGreg ClaytonCPU_TYPE_HPPA = 11 1176a23d212SGreg ClaytonCPU_TYPE_ARM = 12 1186a23d212SGreg ClaytonCPU_TYPE_MC88000 = 13 1196a23d212SGreg ClaytonCPU_TYPE_SPARC = 14 1206a23d212SGreg ClaytonCPU_TYPE_I860 = 15 1216a23d212SGreg ClaytonCPU_TYPE_ALPHA = 16 1226a23d212SGreg ClaytonCPU_TYPE_POWERPC = 18 1236a23d212SGreg ClaytonCPU_TYPE_POWERPC64 = CPU_TYPE_POWERPC | CPU_ARCH_ABI64 1246a23d212SGreg Clayton 1256a23d212SGreg Clayton# VM protection constants 1266a23d212SGreg ClaytonVM_PROT_READ = 1 1276a23d212SGreg ClaytonVM_PROT_WRITE = 2 1286a23d212SGreg ClaytonVM_PROT_EXECUTE = 4 1296a23d212SGreg Clayton 1306a23d212SGreg Clayton# VM protection constants 1316a23d212SGreg ClaytonN_STAB = 0xe0 1326a23d212SGreg ClaytonN_PEXT = 0x10 1336a23d212SGreg ClaytonN_TYPE = 0x0e 1346a23d212SGreg ClaytonN_EXT = 0x01 1356a23d212SGreg Clayton 1366a23d212SGreg Clayton# Values for nlist N_TYPE bits of the "Mach.NList.type" field. 1376a23d212SGreg ClaytonN_UNDF = 0x0 1386a23d212SGreg ClaytonN_ABS = 0x2 1396a23d212SGreg ClaytonN_SECT = 0xe 1406a23d212SGreg ClaytonN_PBUD = 0xc 1416a23d212SGreg ClaytonN_INDR = 0xa 1426a23d212SGreg Clayton 1436a23d212SGreg Clayton# Section indexes for the "Mach.NList.sect_idx" fields 1446a23d212SGreg ClaytonNO_SECT = 0 1456a23d212SGreg ClaytonMAX_SECT = 255 1466a23d212SGreg Clayton 1476a23d212SGreg Clayton# Stab defines 1486a23d212SGreg ClaytonN_GSYM = 0x20 1496a23d212SGreg ClaytonN_FNAME = 0x22 1506a23d212SGreg ClaytonN_FUN = 0x24 1516a23d212SGreg ClaytonN_STSYM = 0x26 1526a23d212SGreg ClaytonN_LCSYM = 0x28 1536a23d212SGreg ClaytonN_BNSYM = 0x2e 1546a23d212SGreg ClaytonN_OPT = 0x3c 1556a23d212SGreg ClaytonN_RSYM = 0x40 1566a23d212SGreg ClaytonN_SLINE = 0x44 1576a23d212SGreg ClaytonN_ENSYM = 0x4e 1586a23d212SGreg ClaytonN_SSYM = 0x60 1596a23d212SGreg ClaytonN_SO = 0x64 1606a23d212SGreg ClaytonN_OSO = 0x66 1616a23d212SGreg ClaytonN_LSYM = 0x80 1626a23d212SGreg ClaytonN_BINCL = 0x82 1636a23d212SGreg ClaytonN_SOL = 0x84 1646a23d212SGreg ClaytonN_PARAMS = 0x86 1656a23d212SGreg ClaytonN_VERSION = 0x88 1666a23d212SGreg ClaytonN_OLEVEL = 0x8A 1676a23d212SGreg ClaytonN_PSYM = 0xa0 1686a23d212SGreg ClaytonN_EINCL = 0xa2 1696a23d212SGreg ClaytonN_ENTRY = 0xa4 1706a23d212SGreg ClaytonN_LBRAC = 0xc0 1716a23d212SGreg ClaytonN_EXCL = 0xc2 1726a23d212SGreg ClaytonN_RBRAC = 0xe0 1736a23d212SGreg ClaytonN_BCOMM = 0xe2 1746a23d212SGreg ClaytonN_ECOMM = 0xe4 1756a23d212SGreg ClaytonN_ECOML = 0xe8 1766a23d212SGreg ClaytonN_LENG = 0xfe 1776a23d212SGreg Clayton 1786a23d212SGreg Claytonvm_prot_names = ['---', 'r--', '-w-', 'rw-', '--x', 'r-x', '-wx', 'rwx'] 1796a23d212SGreg Clayton 180b9c1b51eSKate Stone 1816a23d212SGreg Claytondef dump_memory(base_addr, data, hex_bytes_len, num_per_line): 1826a23d212SGreg Clayton hex_bytes = data.encode('hex') 1836a23d212SGreg Clayton if hex_bytes_len == -1: 1846a23d212SGreg Clayton hex_bytes_len = len(hex_bytes) 1856a23d212SGreg Clayton addr = base_addr 1866a23d212SGreg Clayton ascii_str = '' 1876a23d212SGreg Clayton i = 0 1886a23d212SGreg Clayton while i < hex_bytes_len: 1896a23d212SGreg Clayton if ((i / 2) % num_per_line) == 0: 1906a23d212SGreg Clayton if i > 0: 191525cd59fSSerge Guelton print(' %s' % (ascii_str)) 1926a23d212SGreg Clayton ascii_str = '' 193525cd59fSSerge Guelton print('0x%8.8x:' % (addr + i), end=' ') 1946a23d212SGreg Clayton hex_byte = hex_bytes[i:i + 2] 195525cd59fSSerge Guelton print(hex_byte, end=' ') 1966a23d212SGreg Clayton int_byte = int(hex_byte, 16) 1976a23d212SGreg Clayton ascii_char = '%c' % (int_byte) 1986a23d212SGreg Clayton if int_byte >= 32 and int_byte < 127: 1996a23d212SGreg Clayton ascii_str += ascii_char 2006a23d212SGreg Clayton else: 2016a23d212SGreg Clayton ascii_str += '.' 2026a23d212SGreg Clayton i = i + 2 2036a23d212SGreg Clayton if ascii_str: 2046a23d212SGreg Clayton if (i / 2) % num_per_line: 2056a23d212SGreg Clayton padding = num_per_line - ((i / 2) % num_per_line) 2066a23d212SGreg Clayton else: 2076a23d212SGreg Clayton padding = 0 208525cd59fSSerge Guelton print('%*s%s' % (padding * 3 + 1, '', ascii_str)) 209525cd59fSSerge Guelton print() 2106a23d212SGreg Clayton 2116a23d212SGreg Clayton 2126a23d212SGreg Claytonclass TerminalColors: 2136a23d212SGreg Clayton '''Simple terminal colors class''' 214b9c1b51eSKate Stone 2156a23d212SGreg Clayton def __init__(self, enabled=True): 2166a23d212SGreg Clayton # TODO: discover terminal type from "file" and disable if 2176a23d212SGreg Clayton # it can't handle the color codes 2186a23d212SGreg Clayton self.enabled = enabled 2196a23d212SGreg Clayton 2206a23d212SGreg Clayton def reset(self): 2216a23d212SGreg Clayton '''Reset all terminal colors and formatting.''' 2226a23d212SGreg Clayton if self.enabled: 223b9c1b51eSKate Stone return "\x1b[0m" 2246a23d212SGreg Clayton return '' 2256a23d212SGreg Clayton 2266a23d212SGreg Clayton def bold(self, on=True): 227d93c4a33SBruce Mitchener '''Enable or disable bold depending on the "on" parameter.''' 2286a23d212SGreg Clayton if self.enabled: 2296a23d212SGreg Clayton if on: 230b9c1b51eSKate Stone return "\x1b[1m" 2316a23d212SGreg Clayton else: 232b9c1b51eSKate Stone return "\x1b[22m" 2336a23d212SGreg Clayton return '' 2346a23d212SGreg Clayton 2356a23d212SGreg Clayton def italics(self, on=True): 236d93c4a33SBruce Mitchener '''Enable or disable italics depending on the "on" parameter.''' 2376a23d212SGreg Clayton if self.enabled: 2386a23d212SGreg Clayton if on: 239b9c1b51eSKate Stone return "\x1b[3m" 2406a23d212SGreg Clayton else: 241b9c1b51eSKate Stone return "\x1b[23m" 2426a23d212SGreg Clayton return '' 2436a23d212SGreg Clayton 2446a23d212SGreg Clayton def underline(self, on=True): 245d93c4a33SBruce Mitchener '''Enable or disable underline depending on the "on" parameter.''' 2466a23d212SGreg Clayton if self.enabled: 2476a23d212SGreg Clayton if on: 248b9c1b51eSKate Stone return "\x1b[4m" 2496a23d212SGreg Clayton else: 250b9c1b51eSKate Stone return "\x1b[24m" 2516a23d212SGreg Clayton return '' 2526a23d212SGreg Clayton 2536a23d212SGreg Clayton def inverse(self, on=True): 254d93c4a33SBruce Mitchener '''Enable or disable inverse depending on the "on" parameter.''' 2556a23d212SGreg Clayton if self.enabled: 2566a23d212SGreg Clayton if on: 257b9c1b51eSKate Stone return "\x1b[7m" 2586a23d212SGreg Clayton else: 259b9c1b51eSKate Stone return "\x1b[27m" 2606a23d212SGreg Clayton return '' 2616a23d212SGreg Clayton 2626a23d212SGreg Clayton def strike(self, on=True): 263d93c4a33SBruce Mitchener '''Enable or disable strike through depending on the "on" parameter.''' 2646a23d212SGreg Clayton if self.enabled: 2656a23d212SGreg Clayton if on: 266b9c1b51eSKate Stone return "\x1b[9m" 2676a23d212SGreg Clayton else: 268b9c1b51eSKate Stone return "\x1b[29m" 2696a23d212SGreg Clayton return '' 2706a23d212SGreg Clayton 2716a23d212SGreg Clayton def black(self, fg=True): 2726a23d212SGreg Clayton '''Set the foreground or background color to black. 2736a23d212SGreg Clayton The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.''' 2746a23d212SGreg Clayton if self.enabled: 2756a23d212SGreg Clayton if fg: 276b9c1b51eSKate Stone return "\x1b[30m" 2776a23d212SGreg Clayton else: 278b9c1b51eSKate Stone return "\x1b[40m" 2796a23d212SGreg Clayton return '' 2806a23d212SGreg Clayton 2816a23d212SGreg Clayton def red(self, fg=True): 2826a23d212SGreg Clayton '''Set the foreground or background color to red. 2836a23d212SGreg Clayton The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.''' 2846a23d212SGreg Clayton if self.enabled: 2856a23d212SGreg Clayton if fg: 286b9c1b51eSKate Stone return "\x1b[31m" 2876a23d212SGreg Clayton else: 288b9c1b51eSKate Stone return "\x1b[41m" 2896a23d212SGreg Clayton return '' 2906a23d212SGreg Clayton 2916a23d212SGreg Clayton def green(self, fg=True): 2926a23d212SGreg Clayton '''Set the foreground or background color to green. 2936a23d212SGreg Clayton The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.''' 2946a23d212SGreg Clayton if self.enabled: 2956a23d212SGreg Clayton if fg: 296b9c1b51eSKate Stone return "\x1b[32m" 2976a23d212SGreg Clayton else: 298b9c1b51eSKate Stone return "\x1b[42m" 2996a23d212SGreg Clayton return '' 3006a23d212SGreg Clayton 3016a23d212SGreg Clayton def yellow(self, fg=True): 3026a23d212SGreg Clayton '''Set the foreground or background color to yellow. 3036a23d212SGreg Clayton The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.''' 3046a23d212SGreg Clayton if self.enabled: 3056a23d212SGreg Clayton if fg: 306b9c1b51eSKate Stone return "\x1b[43m" 3076a23d212SGreg Clayton else: 308b9c1b51eSKate Stone return "\x1b[33m" 3096a23d212SGreg Clayton return '' 3106a23d212SGreg Clayton 3116a23d212SGreg Clayton def blue(self, fg=True): 3126a23d212SGreg Clayton '''Set the foreground or background color to blue. 3136a23d212SGreg Clayton The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.''' 3146a23d212SGreg Clayton if self.enabled: 3156a23d212SGreg Clayton if fg: 316b9c1b51eSKate Stone return "\x1b[34m" 3176a23d212SGreg Clayton else: 318b9c1b51eSKate Stone return "\x1b[44m" 3196a23d212SGreg Clayton return '' 3206a23d212SGreg Clayton 3216a23d212SGreg Clayton def magenta(self, fg=True): 3226a23d212SGreg Clayton '''Set the foreground or background color to magenta. 3236a23d212SGreg Clayton The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.''' 3246a23d212SGreg Clayton if self.enabled: 3256a23d212SGreg Clayton if fg: 326b9c1b51eSKate Stone return "\x1b[35m" 3276a23d212SGreg Clayton else: 328b9c1b51eSKate Stone return "\x1b[45m" 3296a23d212SGreg Clayton return '' 3306a23d212SGreg Clayton 3316a23d212SGreg Clayton def cyan(self, fg=True): 3326a23d212SGreg Clayton '''Set the foreground or background color to cyan. 3336a23d212SGreg Clayton The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.''' 3346a23d212SGreg Clayton if self.enabled: 3356a23d212SGreg Clayton if fg: 336b9c1b51eSKate Stone return "\x1b[36m" 3376a23d212SGreg Clayton else: 338b9c1b51eSKate Stone return "\x1b[46m" 3396a23d212SGreg Clayton return '' 3406a23d212SGreg Clayton 3416a23d212SGreg Clayton def white(self, fg=True): 3426a23d212SGreg Clayton '''Set the foreground or background color to white. 3436a23d212SGreg Clayton The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.''' 3446a23d212SGreg Clayton if self.enabled: 3456a23d212SGreg Clayton if fg: 346b9c1b51eSKate Stone return "\x1b[37m" 3476a23d212SGreg Clayton else: 348b9c1b51eSKate Stone return "\x1b[47m" 3496a23d212SGreg Clayton return '' 3506a23d212SGreg Clayton 3516a23d212SGreg Clayton def default(self, fg=True): 3526a23d212SGreg Clayton '''Set the foreground or background color to the default. 3536a23d212SGreg Clayton The foreground color will be set if "fg" tests True. The background color will be set if "fg" tests False.''' 3546a23d212SGreg Clayton if self.enabled: 3556a23d212SGreg Clayton if fg: 356b9c1b51eSKate Stone return "\x1b[39m" 3576a23d212SGreg Clayton else: 358b9c1b51eSKate Stone return "\x1b[49m" 3596a23d212SGreg Clayton return '' 3606a23d212SGreg Clayton 361b9c1b51eSKate Stone 3626a23d212SGreg Claytondef swap_unpack_char(): 3636a23d212SGreg Clayton """Returns the unpack prefix that will for non-native endian-ness.""" 3646a23d212SGreg Clayton if struct.pack('H', 1).startswith("\x00"): 3656a23d212SGreg Clayton return '<' 3666a23d212SGreg Clayton return '>' 3676a23d212SGreg Clayton 3686a23d212SGreg Clayton 3696a23d212SGreg Claytondef dump_hex_bytes(addr, s, bytes_per_line=16): 3706a23d212SGreg Clayton i = 0 3716a23d212SGreg Clayton line = '' 3726a23d212SGreg Clayton for ch in s: 3736a23d212SGreg Clayton if (i % bytes_per_line) == 0: 3746a23d212SGreg Clayton if line: 375525cd59fSSerge Guelton print(line) 3766a23d212SGreg Clayton line = '%#8.8x: ' % (addr + i) 3776a23d212SGreg Clayton line += "%02X " % ord(ch) 3786a23d212SGreg Clayton i += 1 379525cd59fSSerge Guelton print(line) 3806a23d212SGreg Clayton 381b9c1b51eSKate Stone 3826a23d212SGreg Claytondef dump_hex_byte_string_diff(addr, a, b, bytes_per_line=16): 3836a23d212SGreg Clayton i = 0 3846a23d212SGreg Clayton line = '' 3856a23d212SGreg Clayton a_len = len(a) 3866a23d212SGreg Clayton b_len = len(b) 3876a23d212SGreg Clayton if a_len < b_len: 3886a23d212SGreg Clayton max_len = b_len 3896a23d212SGreg Clayton else: 3906a23d212SGreg Clayton max_len = a_len 3916a23d212SGreg Clayton tty_colors = TerminalColors(True) 3926a23d212SGreg Clayton for i in range(max_len): 3936a23d212SGreg Clayton ch = None 3946a23d212SGreg Clayton if i < a_len: 3956a23d212SGreg Clayton ch_a = a[i] 3966a23d212SGreg Clayton ch = ch_a 3976a23d212SGreg Clayton else: 3986a23d212SGreg Clayton ch_a = None 3996a23d212SGreg Clayton if i < b_len: 4006a23d212SGreg Clayton ch_b = b[i] 4016a23d212SGreg Clayton if not ch: 4026a23d212SGreg Clayton ch = ch_b 4036a23d212SGreg Clayton else: 4046a23d212SGreg Clayton ch_b = None 4056a23d212SGreg Clayton mismatch = ch_a != ch_b 4066a23d212SGreg Clayton if (i % bytes_per_line) == 0: 4076a23d212SGreg Clayton if line: 408525cd59fSSerge Guelton print(line) 4096a23d212SGreg Clayton line = '%#8.8x: ' % (addr + i) 410b9c1b51eSKate Stone if mismatch: 411b9c1b51eSKate Stone line += tty_colors.red() 4126a23d212SGreg Clayton line += "%02X " % ord(ch) 413b9c1b51eSKate Stone if mismatch: 414b9c1b51eSKate Stone line += tty_colors.default() 4156a23d212SGreg Clayton i += 1 4166a23d212SGreg Clayton 417525cd59fSSerge Guelton print(line) 4186a23d212SGreg Clayton 419b9c1b51eSKate Stone 4206a23d212SGreg Claytonclass Mach: 4216a23d212SGreg Clayton """Class that does everything mach-o related""" 4226a23d212SGreg Clayton 4236a23d212SGreg Clayton class Arch: 4246a23d212SGreg Clayton """Class that implements mach-o architectures""" 4256a23d212SGreg Clayton 4266a23d212SGreg Clayton def __init__(self, c=0, s=0): 4276a23d212SGreg Clayton self.cpu = c 4286a23d212SGreg Clayton self.sub = s 4296a23d212SGreg Clayton 4306a23d212SGreg Clayton def set_cpu_type(self, c): 4316a23d212SGreg Clayton self.cpu = c 432b9c1b51eSKate Stone 4336a23d212SGreg Clayton def set_cpu_subtype(self, s): 4346a23d212SGreg Clayton self.sub = s 435b9c1b51eSKate Stone 4366a23d212SGreg Clayton def set_arch(self, c, s): 4376a23d212SGreg Clayton self.cpu = c 4386a23d212SGreg Clayton self.sub = s 439b9c1b51eSKate Stone 4406a23d212SGreg Clayton def is_64_bit(self): 4416a23d212SGreg Clayton return (self.cpu & CPU_ARCH_ABI64) != 0 4426a23d212SGreg Clayton 4436a23d212SGreg Clayton cpu_infos = [ 4446a23d212SGreg Clayton ["arm", CPU_TYPE_ARM, CPU_TYPE_ANY], 4456a23d212SGreg Clayton ["arm", CPU_TYPE_ARM, 0], 4466a23d212SGreg Clayton ["armv4", CPU_TYPE_ARM, 5], 4476a23d212SGreg Clayton ["armv6", CPU_TYPE_ARM, 6], 4486a23d212SGreg Clayton ["armv5", CPU_TYPE_ARM, 7], 4496a23d212SGreg Clayton ["xscale", CPU_TYPE_ARM, 8], 4506a23d212SGreg Clayton ["armv7", CPU_TYPE_ARM, 9], 4516a23d212SGreg Clayton ["armv7f", CPU_TYPE_ARM, 10], 4526a23d212SGreg Clayton ["armv7s", CPU_TYPE_ARM, 11], 4536a23d212SGreg Clayton ["armv7k", CPU_TYPE_ARM, 12], 4546a23d212SGreg Clayton ["armv7m", CPU_TYPE_ARM, 15], 4556a23d212SGreg Clayton ["armv7em", CPU_TYPE_ARM, 16], 4566a23d212SGreg Clayton ["ppc", CPU_TYPE_POWERPC, CPU_TYPE_ANY], 4576a23d212SGreg Clayton ["ppc", CPU_TYPE_POWERPC, 0], 4586a23d212SGreg Clayton ["ppc601", CPU_TYPE_POWERPC, 1], 4596a23d212SGreg Clayton ["ppc602", CPU_TYPE_POWERPC, 2], 4606a23d212SGreg Clayton ["ppc603", CPU_TYPE_POWERPC, 3], 4616a23d212SGreg Clayton ["ppc603e", CPU_TYPE_POWERPC, 4], 4626a23d212SGreg Clayton ["ppc603ev", CPU_TYPE_POWERPC, 5], 4636a23d212SGreg Clayton ["ppc604", CPU_TYPE_POWERPC, 6], 4646a23d212SGreg Clayton ["ppc604e", CPU_TYPE_POWERPC, 7], 4656a23d212SGreg Clayton ["ppc620", CPU_TYPE_POWERPC, 8], 4666a23d212SGreg Clayton ["ppc750", CPU_TYPE_POWERPC, 9], 4676a23d212SGreg Clayton ["ppc7400", CPU_TYPE_POWERPC, 10], 4686a23d212SGreg Clayton ["ppc7450", CPU_TYPE_POWERPC, 11], 4696a23d212SGreg Clayton ["ppc970", CPU_TYPE_POWERPC, 100], 4706a23d212SGreg Clayton ["ppc64", CPU_TYPE_POWERPC64, 0], 4716a23d212SGreg Clayton ["ppc970-64", CPU_TYPE_POWERPC64, 100], 4726a23d212SGreg Clayton ["i386", CPU_TYPE_I386, 3], 4736a23d212SGreg Clayton ["i486", CPU_TYPE_I386, 4], 4746a23d212SGreg Clayton ["i486sx", CPU_TYPE_I386, 0x84], 4756a23d212SGreg Clayton ["i386", CPU_TYPE_I386, CPU_TYPE_ANY], 4766a23d212SGreg Clayton ["x86_64", CPU_TYPE_X86_64, 3], 4776a23d212SGreg Clayton ["x86_64", CPU_TYPE_X86_64, CPU_TYPE_ANY], 4786a23d212SGreg Clayton ] 4796a23d212SGreg Clayton 4806a23d212SGreg Clayton def __str__(self): 4816a23d212SGreg Clayton for info in self.cpu_infos: 4826a23d212SGreg Clayton if self.cpu == info[1] and (self.sub & 0x00ffffff) == info[2]: 4836a23d212SGreg Clayton return info[0] 4846a23d212SGreg Clayton return "{0}.{1}".format(self.cpu, self.sub) 4856a23d212SGreg Clayton 4866a23d212SGreg Clayton class Magic(dict_utils.Enum): 4876a23d212SGreg Clayton 4886a23d212SGreg Clayton enum = { 4896a23d212SGreg Clayton 'MH_MAGIC': MH_MAGIC, 4906a23d212SGreg Clayton 'MH_CIGAM': MH_CIGAM, 4916a23d212SGreg Clayton 'MH_MAGIC_64': MH_MAGIC_64, 4926a23d212SGreg Clayton 'MH_CIGAM_64': MH_CIGAM_64, 4936a23d212SGreg Clayton 'FAT_MAGIC': FAT_MAGIC, 4946a23d212SGreg Clayton 'FAT_CIGAM': FAT_CIGAM 4956a23d212SGreg Clayton } 4966a23d212SGreg Clayton 4976a23d212SGreg Clayton def __init__(self, initial_value=0): 4986a23d212SGreg Clayton dict_utils.Enum.__init__(self, initial_value, self.enum) 4996a23d212SGreg Clayton 5006a23d212SGreg Clayton def is_skinny_mach_file(self): 5016a23d212SGreg Clayton return self.value == MH_MAGIC or self.value == MH_CIGAM or self.value == MH_MAGIC_64 or self.value == MH_CIGAM_64 5026a23d212SGreg Clayton 5036a23d212SGreg Clayton def is_universal_mach_file(self): 5046a23d212SGreg Clayton return self.value == FAT_MAGIC or self.value == FAT_CIGAM 5056a23d212SGreg Clayton 5066a23d212SGreg Clayton def unpack(self, data): 5076a23d212SGreg Clayton data.set_byte_order('native') 508b9c1b51eSKate Stone self.value = data.get_uint32() 5096a23d212SGreg Clayton 5106a23d212SGreg Clayton def get_byte_order(self): 5116a23d212SGreg Clayton if self.value == MH_CIGAM or self.value == MH_CIGAM_64 or self.value == FAT_CIGAM: 5126a23d212SGreg Clayton return swap_unpack_char() 5136a23d212SGreg Clayton else: 5146a23d212SGreg Clayton return '=' 5156a23d212SGreg Clayton 5166a23d212SGreg Clayton def is_64_bit(self): 5176a23d212SGreg Clayton return self.value == MH_MAGIC_64 or self.value == MH_CIGAM_64 5186a23d212SGreg Clayton 5196a23d212SGreg Clayton def __init__(self): 5206a23d212SGreg Clayton self.magic = Mach.Magic() 5216a23d212SGreg Clayton self.content = None 5226a23d212SGreg Clayton self.path = None 5236a23d212SGreg Clayton 5246a23d212SGreg Clayton def extract(self, path, extractor): 525b9c1b51eSKate Stone self.path = path 5266a23d212SGreg Clayton self.unpack(extractor) 5276a23d212SGreg Clayton 5286a23d212SGreg Clayton def parse(self, path): 529b9c1b51eSKate Stone self.path = path 5306a23d212SGreg Clayton try: 5316a23d212SGreg Clayton f = open(self.path) 5326a23d212SGreg Clayton file_extractor = file_extract.FileExtract(f, '=') 5336a23d212SGreg Clayton self.unpack(file_extractor) 5346a23d212SGreg Clayton # f.close() 535b9c1b51eSKate Stone except IOError as xxx_todo_changeme: 536b9c1b51eSKate Stone (errno, strerror) = xxx_todo_changeme.args 537525cd59fSSerge Guelton print("I/O error({0}): {1}".format(errno, strerror)) 5386a23d212SGreg Clayton except ValueError: 539525cd59fSSerge Guelton print("Could not convert data to an integer.") 5406a23d212SGreg Clayton except: 541525cd59fSSerge Guelton print("Unexpected error:", sys.exc_info()[0]) 5426a23d212SGreg Clayton raise 5436a23d212SGreg Clayton 5446a23d212SGreg Clayton def compare(self, rhs): 5456a23d212SGreg Clayton self.content.compare(rhs.content) 5466a23d212SGreg Clayton 5476a23d212SGreg Clayton def dump(self, options=None): 5486a23d212SGreg Clayton self.content.dump(options) 5496a23d212SGreg Clayton 5506a23d212SGreg Clayton def dump_header(self, dump_description=True, options=None): 5516a23d212SGreg Clayton self.content.dump_header(dump_description, options) 5526a23d212SGreg Clayton 5536a23d212SGreg Clayton def dump_load_commands(self, dump_description=True, options=None): 5546a23d212SGreg Clayton self.content.dump_load_commands(dump_description, options) 5556a23d212SGreg Clayton 5566a23d212SGreg Clayton def dump_sections(self, dump_description=True, options=None): 5576a23d212SGreg Clayton self.content.dump_sections(dump_description, options) 5586a23d212SGreg Clayton 5596a23d212SGreg Clayton def dump_section_contents(self, options): 5606a23d212SGreg Clayton self.content.dump_section_contents(options) 5616a23d212SGreg Clayton 5626a23d212SGreg Clayton def dump_symtab(self, dump_description=True, options=None): 5636a23d212SGreg Clayton self.content.dump_symtab(dump_description, options) 5646a23d212SGreg Clayton 5656a23d212SGreg Clayton def dump_symbol_names_matching_regex(self, regex, file=None): 5666a23d212SGreg Clayton self.content.dump_symbol_names_matching_regex(regex, file) 5676a23d212SGreg Clayton 5686a23d212SGreg Clayton def description(self): 5696a23d212SGreg Clayton return self.content.description() 5706a23d212SGreg Clayton 5716a23d212SGreg Clayton def unpack(self, data): 5726a23d212SGreg Clayton self.magic.unpack(data) 5736a23d212SGreg Clayton if self.magic.is_skinny_mach_file(): 5746a23d212SGreg Clayton self.content = Mach.Skinny(self.path) 5756a23d212SGreg Clayton elif self.magic.is_universal_mach_file(): 5766a23d212SGreg Clayton self.content = Mach.Universal(self.path) 5776a23d212SGreg Clayton else: 5786a23d212SGreg Clayton self.content = None 5796a23d212SGreg Clayton 580b9c1b51eSKate Stone if self.content is not None: 5816a23d212SGreg Clayton self.content.unpack(data, self.magic) 5826a23d212SGreg Clayton 5836a23d212SGreg Clayton def is_valid(self): 584b9c1b51eSKate Stone return self.content is not None 5856a23d212SGreg Clayton 5866a23d212SGreg Clayton class Universal: 5876a23d212SGreg Clayton 5886a23d212SGreg Clayton def __init__(self, path): 5896a23d212SGreg Clayton self.path = path 5906a23d212SGreg Clayton self.type = 'universal' 5916a23d212SGreg Clayton self.file_off = 0 5926a23d212SGreg Clayton self.magic = None 5936a23d212SGreg Clayton self.nfat_arch = 0 5946a23d212SGreg Clayton self.archs = list() 5956a23d212SGreg Clayton 5966a23d212SGreg Clayton def description(self): 5976a23d212SGreg Clayton s = '%#8.8x: %s (' % (self.file_off, self.path) 5986a23d212SGreg Clayton archs_string = '' 5996a23d212SGreg Clayton for arch in self.archs: 6006a23d212SGreg Clayton if len(archs_string): 6016a23d212SGreg Clayton archs_string += ', ' 6026a23d212SGreg Clayton archs_string += '%s' % arch.arch 6036a23d212SGreg Clayton s += archs_string 6046a23d212SGreg Clayton s += ')' 6056a23d212SGreg Clayton return s 6066a23d212SGreg Clayton 6076a23d212SGreg Clayton def unpack(self, data, magic=None): 6086a23d212SGreg Clayton self.file_off = data.tell() 6096a23d212SGreg Clayton if magic is None: 6106a23d212SGreg Clayton self.magic = Mach.Magic() 6116a23d212SGreg Clayton self.magic.unpack(data) 6126a23d212SGreg Clayton else: 6136a23d212SGreg Clayton self.magic = magic 6146a23d212SGreg Clayton self.file_off = self.file_off - 4 6156a23d212SGreg Clayton # Universal headers are always in big endian 6166a23d212SGreg Clayton data.set_byte_order('big') 6176a23d212SGreg Clayton self.nfat_arch = data.get_uint32() 6186a23d212SGreg Clayton for i in range(self.nfat_arch): 6196a23d212SGreg Clayton self.archs.append(Mach.Universal.ArchInfo()) 6206a23d212SGreg Clayton self.archs[i].unpack(data) 6216a23d212SGreg Clayton for i in range(self.nfat_arch): 6226a23d212SGreg Clayton self.archs[i].mach = Mach.Skinny(self.path) 6236a23d212SGreg Clayton data.seek(self.archs[i].offset, 0) 6246a23d212SGreg Clayton skinny_magic = Mach.Magic() 6256a23d212SGreg Clayton skinny_magic.unpack(data) 6266a23d212SGreg Clayton self.archs[i].mach.unpack(data, skinny_magic) 6276a23d212SGreg Clayton 6286a23d212SGreg Clayton def compare(self, rhs): 629525cd59fSSerge Guelton print('error: comparing two universal files is not supported yet') 6306a23d212SGreg Clayton return False 6316a23d212SGreg Clayton 6326a23d212SGreg Clayton def dump(self, options): 6336a23d212SGreg Clayton if options.dump_header: 634525cd59fSSerge Guelton print() 635525cd59fSSerge Guelton print("Universal Mach File: magic = %s, nfat_arch = %u" % (self.magic, self.nfat_arch)) 636525cd59fSSerge Guelton print() 6376a23d212SGreg Clayton if self.nfat_arch > 0: 6386a23d212SGreg Clayton if options.dump_header: 6396a23d212SGreg Clayton self.archs[0].dump_header(True, options) 6406a23d212SGreg Clayton for i in range(self.nfat_arch): 6416a23d212SGreg Clayton self.archs[i].dump_flat(options) 6426a23d212SGreg Clayton if options.dump_header: 643525cd59fSSerge Guelton print() 6446a23d212SGreg Clayton for i in range(self.nfat_arch): 6456a23d212SGreg Clayton self.archs[i].mach.dump(options) 6466a23d212SGreg Clayton 6476a23d212SGreg Clayton def dump_header(self, dump_description=True, options=None): 6486a23d212SGreg Clayton if dump_description: 649525cd59fSSerge Guelton print(self.description()) 6506a23d212SGreg Clayton for i in range(self.nfat_arch): 6516a23d212SGreg Clayton self.archs[i].mach.dump_header(True, options) 652525cd59fSSerge Guelton print() 6536a23d212SGreg Clayton 6546a23d212SGreg Clayton def dump_load_commands(self, dump_description=True, options=None): 6556a23d212SGreg Clayton if dump_description: 656525cd59fSSerge Guelton print(self.description()) 6576a23d212SGreg Clayton for i in range(self.nfat_arch): 6586a23d212SGreg Clayton self.archs[i].mach.dump_load_commands(True, options) 659525cd59fSSerge Guelton print() 6606a23d212SGreg Clayton 6616a23d212SGreg Clayton def dump_sections(self, dump_description=True, options=None): 6626a23d212SGreg Clayton if dump_description: 663525cd59fSSerge Guelton print(self.description()) 6646a23d212SGreg Clayton for i in range(self.nfat_arch): 6656a23d212SGreg Clayton self.archs[i].mach.dump_sections(True, options) 666525cd59fSSerge Guelton print() 6676a23d212SGreg Clayton 6686a23d212SGreg Clayton def dump_section_contents(self, options): 6696a23d212SGreg Clayton for i in range(self.nfat_arch): 6706a23d212SGreg Clayton self.archs[i].mach.dump_section_contents(options) 671525cd59fSSerge Guelton print() 6726a23d212SGreg Clayton 6736a23d212SGreg Clayton def dump_symtab(self, dump_description=True, options=None): 6746a23d212SGreg Clayton if dump_description: 675525cd59fSSerge Guelton print(self.description()) 6766a23d212SGreg Clayton for i in range(self.nfat_arch): 6776a23d212SGreg Clayton self.archs[i].mach.dump_symtab(True, options) 678525cd59fSSerge Guelton print() 6796a23d212SGreg Clayton 6806a23d212SGreg Clayton def dump_symbol_names_matching_regex(self, regex, file=None): 6816a23d212SGreg Clayton for i in range(self.nfat_arch): 682b9c1b51eSKate Stone self.archs[i].mach.dump_symbol_names_matching_regex( 683b9c1b51eSKate Stone regex, file) 6846a23d212SGreg Clayton 6856a23d212SGreg Clayton class ArchInfo: 6866a23d212SGreg Clayton 6876a23d212SGreg Clayton def __init__(self): 6886a23d212SGreg Clayton self.arch = Mach.Arch(0, 0) 6896a23d212SGreg Clayton self.offset = 0 6906a23d212SGreg Clayton self.size = 0 6916a23d212SGreg Clayton self.align = 0 6926a23d212SGreg Clayton self.mach = None 6936a23d212SGreg Clayton 6946a23d212SGreg Clayton def unpack(self, data): 6956a23d212SGreg Clayton # Universal headers are always in big endian 6966a23d212SGreg Clayton data.set_byte_order('big') 697b9c1b51eSKate Stone self.arch.cpu, self.arch.sub, self.offset, self.size, self.align = data.get_n_uint32( 698b9c1b51eSKate Stone 5) 6996a23d212SGreg Clayton 7006a23d212SGreg Clayton def dump_header(self, dump_description=True, options=None): 7016a23d212SGreg Clayton if options.verbose: 702525cd59fSSerge Guelton print("CPU SUBTYPE OFFSET SIZE ALIGN") 703525cd59fSSerge Guelton print("---------- ---------- ---------- ---------- ----------") 7046a23d212SGreg Clayton else: 705525cd59fSSerge Guelton print("ARCH FILEOFFSET FILESIZE ALIGN") 706525cd59fSSerge Guelton print("---------- ---------- ---------- ----------") 707b9c1b51eSKate Stone 7086a23d212SGreg Clayton def dump_flat(self, options): 7096a23d212SGreg Clayton if options.verbose: 710525cd59fSSerge Guelton print("%#8.8x %#8.8x %#8.8x %#8.8x %#8.8x" % (self.arch.cpu, self.arch.sub, self.offset, self.size, self.align)) 7116a23d212SGreg Clayton else: 712525cd59fSSerge Guelton print("%-10s %#8.8x %#8.8x %#8.8x" % (self.arch, self.offset, self.size, self.align)) 713b9c1b51eSKate Stone 7146a23d212SGreg Clayton def dump(self): 715525cd59fSSerge Guelton print(" cputype: %#8.8x" % self.arch.cpu) 716525cd59fSSerge Guelton print("cpusubtype: %#8.8x" % self.arch.sub) 717525cd59fSSerge Guelton print(" offset: %#8.8x" % self.offset) 718525cd59fSSerge Guelton print(" size: %#8.8x" % self.size) 719525cd59fSSerge Guelton print(" align: %#8.8x" % self.align) 720b9c1b51eSKate Stone 7216a23d212SGreg Clayton def __str__(self): 722b9c1b51eSKate Stone return "Mach.Universal.ArchInfo: %#8.8x %#8.8x %#8.8x %#8.8x %#8.8x" % ( 723b9c1b51eSKate Stone self.arch.cpu, self.arch.sub, self.offset, self.size, self.align) 724b9c1b51eSKate Stone 7256a23d212SGreg Clayton def __repr__(self): 726b9c1b51eSKate Stone return "Mach.Universal.ArchInfo: %#8.8x %#8.8x %#8.8x %#8.8x %#8.8x" % ( 727b9c1b51eSKate Stone self.arch.cpu, self.arch.sub, self.offset, self.size, self.align) 7286a23d212SGreg Clayton 7296a23d212SGreg Clayton class Flags: 7306a23d212SGreg Clayton 7316a23d212SGreg Clayton def __init__(self, b): 7326a23d212SGreg Clayton self.bits = b 7336a23d212SGreg Clayton 7346a23d212SGreg Clayton def __str__(self): 7356a23d212SGreg Clayton s = '' 7366a23d212SGreg Clayton if self.bits & MH_NOUNDEFS: 7376a23d212SGreg Clayton s += 'MH_NOUNDEFS | ' 7386a23d212SGreg Clayton if self.bits & MH_INCRLINK: 7396a23d212SGreg Clayton s += 'MH_INCRLINK | ' 7406a23d212SGreg Clayton if self.bits & MH_DYLDLINK: 7416a23d212SGreg Clayton s += 'MH_DYLDLINK | ' 7426a23d212SGreg Clayton if self.bits & MH_BINDATLOAD: 7436a23d212SGreg Clayton s += 'MH_BINDATLOAD | ' 7446a23d212SGreg Clayton if self.bits & MH_PREBOUND: 7456a23d212SGreg Clayton s += 'MH_PREBOUND | ' 7466a23d212SGreg Clayton if self.bits & MH_SPLIT_SEGS: 7476a23d212SGreg Clayton s += 'MH_SPLIT_SEGS | ' 7486a23d212SGreg Clayton if self.bits & MH_LAZY_INIT: 7496a23d212SGreg Clayton s += 'MH_LAZY_INIT | ' 7506a23d212SGreg Clayton if self.bits & MH_TWOLEVEL: 7516a23d212SGreg Clayton s += 'MH_TWOLEVEL | ' 7526a23d212SGreg Clayton if self.bits & MH_FORCE_FLAT: 7536a23d212SGreg Clayton s += 'MH_FORCE_FLAT | ' 7546a23d212SGreg Clayton if self.bits & MH_NOMULTIDEFS: 7556a23d212SGreg Clayton s += 'MH_NOMULTIDEFS | ' 7566a23d212SGreg Clayton if self.bits & MH_NOFIXPREBINDING: 7576a23d212SGreg Clayton s += 'MH_NOFIXPREBINDING | ' 7586a23d212SGreg Clayton if self.bits & MH_PREBINDABLE: 7596a23d212SGreg Clayton s += 'MH_PREBINDABLE | ' 7606a23d212SGreg Clayton if self.bits & MH_ALLMODSBOUND: 7616a23d212SGreg Clayton s += 'MH_ALLMODSBOUND | ' 7626a23d212SGreg Clayton if self.bits & MH_SUBSECTIONS_VIA_SYMBOLS: 7636a23d212SGreg Clayton s += 'MH_SUBSECTIONS_VIA_SYMBOLS | ' 7646a23d212SGreg Clayton if self.bits & MH_CANONICAL: 7656a23d212SGreg Clayton s += 'MH_CANONICAL | ' 7666a23d212SGreg Clayton if self.bits & MH_WEAK_DEFINES: 7676a23d212SGreg Clayton s += 'MH_WEAK_DEFINES | ' 7686a23d212SGreg Clayton if self.bits & MH_BINDS_TO_WEAK: 7696a23d212SGreg Clayton s += 'MH_BINDS_TO_WEAK | ' 7706a23d212SGreg Clayton if self.bits & MH_ALLOW_STACK_EXECUTION: 7716a23d212SGreg Clayton s += 'MH_ALLOW_STACK_EXECUTION | ' 7726a23d212SGreg Clayton if self.bits & MH_ROOT_SAFE: 7736a23d212SGreg Clayton s += 'MH_ROOT_SAFE | ' 7746a23d212SGreg Clayton if self.bits & MH_SETUID_SAFE: 7756a23d212SGreg Clayton s += 'MH_SETUID_SAFE | ' 7766a23d212SGreg Clayton if self.bits & MH_NO_REEXPORTED_DYLIBS: 7776a23d212SGreg Clayton s += 'MH_NO_REEXPORTED_DYLIBS | ' 7786a23d212SGreg Clayton if self.bits & MH_PIE: 7796a23d212SGreg Clayton s += 'MH_PIE | ' 7806a23d212SGreg Clayton if self.bits & MH_DEAD_STRIPPABLE_DYLIB: 7816a23d212SGreg Clayton s += 'MH_DEAD_STRIPPABLE_DYLIB | ' 7826a23d212SGreg Clayton if self.bits & MH_HAS_TLV_DESCRIPTORS: 7836a23d212SGreg Clayton s += 'MH_HAS_TLV_DESCRIPTORS | ' 7846a23d212SGreg Clayton if self.bits & MH_NO_HEAP_EXECUTION: 7856a23d212SGreg Clayton s += 'MH_NO_HEAP_EXECUTION | ' 7866a23d212SGreg Clayton # Strip the trailing " |" if we have any flags 7876a23d212SGreg Clayton if len(s) > 0: 7886a23d212SGreg Clayton s = s[0:-2] 7896a23d212SGreg Clayton return s 7906a23d212SGreg Clayton 7916a23d212SGreg Clayton class FileType(dict_utils.Enum): 7926a23d212SGreg Clayton 7936a23d212SGreg Clayton enum = { 7946a23d212SGreg Clayton 'MH_OBJECT': MH_OBJECT, 7956a23d212SGreg Clayton 'MH_EXECUTE': MH_EXECUTE, 7966a23d212SGreg Clayton 'MH_FVMLIB': MH_FVMLIB, 7976a23d212SGreg Clayton 'MH_CORE': MH_CORE, 7986a23d212SGreg Clayton 'MH_PRELOAD': MH_PRELOAD, 7996a23d212SGreg Clayton 'MH_DYLIB': MH_DYLIB, 8006a23d212SGreg Clayton 'MH_DYLINKER': MH_DYLINKER, 8016a23d212SGreg Clayton 'MH_BUNDLE': MH_BUNDLE, 8026a23d212SGreg Clayton 'MH_DYLIB_STUB': MH_DYLIB_STUB, 8036a23d212SGreg Clayton 'MH_DSYM': MH_DSYM, 8046a23d212SGreg Clayton 'MH_KEXT_BUNDLE': MH_KEXT_BUNDLE 8056a23d212SGreg Clayton } 8066a23d212SGreg Clayton 8076a23d212SGreg Clayton def __init__(self, initial_value=0): 8086a23d212SGreg Clayton dict_utils.Enum.__init__(self, initial_value, self.enum) 8096a23d212SGreg Clayton 8106a23d212SGreg Clayton class Skinny: 8116a23d212SGreg Clayton 8126a23d212SGreg Clayton def __init__(self, path): 8136a23d212SGreg Clayton self.path = path 8146a23d212SGreg Clayton self.type = 'skinny' 8156a23d212SGreg Clayton self.data = None 8166a23d212SGreg Clayton self.file_off = 0 8176a23d212SGreg Clayton self.magic = 0 8186a23d212SGreg Clayton self.arch = Mach.Arch(0, 0) 8196a23d212SGreg Clayton self.filetype = Mach.FileType(0) 8206a23d212SGreg Clayton self.ncmds = 0 8216a23d212SGreg Clayton self.sizeofcmds = 0 8226a23d212SGreg Clayton self.flags = Mach.Flags(0) 8236a23d212SGreg Clayton self.uuid = None 8246a23d212SGreg Clayton self.commands = list() 8256a23d212SGreg Clayton self.segments = list() 8266a23d212SGreg Clayton self.sections = list() 8276a23d212SGreg Clayton self.symbols = list() 8286a23d212SGreg Clayton self.sections.append(Mach.Section()) 8296a23d212SGreg Clayton 8306a23d212SGreg Clayton def description(self): 8316a23d212SGreg Clayton return '%#8.8x: %s (%s)' % (self.file_off, self.path, self.arch) 8326a23d212SGreg Clayton 8336a23d212SGreg Clayton def unpack(self, data, magic=None): 8346a23d212SGreg Clayton self.data = data 8356a23d212SGreg Clayton self.file_off = data.tell() 8366a23d212SGreg Clayton if magic is None: 8376a23d212SGreg Clayton self.magic = Mach.Magic() 8386a23d212SGreg Clayton self.magic.unpack(data) 8396a23d212SGreg Clayton else: 8406a23d212SGreg Clayton self.magic = magic 8416a23d212SGreg Clayton self.file_off = self.file_off - 4 8426a23d212SGreg Clayton data.set_byte_order(self.magic.get_byte_order()) 843b9c1b51eSKate Stone self.arch.cpu, self.arch.sub, self.filetype.value, self.ncmds, self.sizeofcmds, bits = data.get_n_uint32( 844b9c1b51eSKate Stone 6) 8456a23d212SGreg Clayton self.flags.bits = bits 8466a23d212SGreg Clayton 8476a23d212SGreg Clayton if self.is_64_bit(): 8486a23d212SGreg Clayton data.get_uint32() # Skip reserved word in mach_header_64 8496a23d212SGreg Clayton 8506a23d212SGreg Clayton for i in range(0, self.ncmds): 8516a23d212SGreg Clayton lc = self.unpack_load_command(data) 8526a23d212SGreg Clayton self.commands.append(lc) 8536a23d212SGreg Clayton 8546a23d212SGreg Clayton def get_data(self): 8556a23d212SGreg Clayton if self.data: 8566a23d212SGreg Clayton self.data.set_byte_order(self.magic.get_byte_order()) 8576a23d212SGreg Clayton return self.data 8586a23d212SGreg Clayton return None 8596a23d212SGreg Clayton 8606a23d212SGreg Clayton def unpack_load_command(self, data): 8616a23d212SGreg Clayton lc = Mach.LoadCommand() 8626a23d212SGreg Clayton lc.unpack(self, data) 863b9c1b51eSKate Stone lc_command = lc.command.get_enum_value() 8646a23d212SGreg Clayton if (lc_command == LC_SEGMENT or 8656a23d212SGreg Clayton lc_command == LC_SEGMENT_64): 8666a23d212SGreg Clayton lc = Mach.SegmentLoadCommand(lc) 8676a23d212SGreg Clayton lc.unpack(self, data) 8686a23d212SGreg Clayton elif (lc_command == LC_LOAD_DYLIB or 8696a23d212SGreg Clayton lc_command == LC_ID_DYLIB or 8706a23d212SGreg Clayton lc_command == LC_LOAD_WEAK_DYLIB or 8716a23d212SGreg Clayton lc_command == LC_REEXPORT_DYLIB): 8726a23d212SGreg Clayton lc = Mach.DylibLoadCommand(lc) 8736a23d212SGreg Clayton lc.unpack(self, data) 8746a23d212SGreg Clayton elif (lc_command == LC_LOAD_DYLINKER or 8756a23d212SGreg Clayton lc_command == LC_SUB_FRAMEWORK or 8766a23d212SGreg Clayton lc_command == LC_SUB_CLIENT or 8776a23d212SGreg Clayton lc_command == LC_SUB_UMBRELLA or 8786a23d212SGreg Clayton lc_command == LC_SUB_LIBRARY or 8796a23d212SGreg Clayton lc_command == LC_ID_DYLINKER or 8806a23d212SGreg Clayton lc_command == LC_RPATH): 8816a23d212SGreg Clayton lc = Mach.LoadDYLDLoadCommand(lc) 8826a23d212SGreg Clayton lc.unpack(self, data) 8836a23d212SGreg Clayton elif (lc_command == LC_DYLD_INFO_ONLY): 8846a23d212SGreg Clayton lc = Mach.DYLDInfoOnlyLoadCommand(lc) 8856a23d212SGreg Clayton lc.unpack(self, data) 8866a23d212SGreg Clayton elif (lc_command == LC_SYMTAB): 8876a23d212SGreg Clayton lc = Mach.SymtabLoadCommand(lc) 8886a23d212SGreg Clayton lc.unpack(self, data) 8896a23d212SGreg Clayton elif (lc_command == LC_DYSYMTAB): 8906a23d212SGreg Clayton lc = Mach.DYLDSymtabLoadCommand(lc) 8916a23d212SGreg Clayton lc.unpack(self, data) 8926a23d212SGreg Clayton elif (lc_command == LC_UUID): 8936a23d212SGreg Clayton lc = Mach.UUIDLoadCommand(lc) 8946a23d212SGreg Clayton lc.unpack(self, data) 8956a23d212SGreg Clayton elif (lc_command == LC_CODE_SIGNATURE or 8966a23d212SGreg Clayton lc_command == LC_SEGMENT_SPLIT_INFO or 8976a23d212SGreg Clayton lc_command == LC_FUNCTION_STARTS): 8986a23d212SGreg Clayton lc = Mach.DataBlobLoadCommand(lc) 8996a23d212SGreg Clayton lc.unpack(self, data) 9006a23d212SGreg Clayton elif (lc_command == LC_UNIXTHREAD): 9016a23d212SGreg Clayton lc = Mach.UnixThreadLoadCommand(lc) 9026a23d212SGreg Clayton lc.unpack(self, data) 9036a23d212SGreg Clayton elif (lc_command == LC_ENCRYPTION_INFO): 9046a23d212SGreg Clayton lc = Mach.EncryptionInfoLoadCommand(lc) 9056a23d212SGreg Clayton lc.unpack(self, data) 9066a23d212SGreg Clayton lc.skip(data) 9076a23d212SGreg Clayton return lc 9086a23d212SGreg Clayton 9096a23d212SGreg Clayton def compare(self, rhs): 910525cd59fSSerge Guelton print("\nComparing:") 911525cd59fSSerge Guelton print("a) %s %s" % (self.arch, self.path)) 912525cd59fSSerge Guelton print("b) %s %s" % (rhs.arch, rhs.path)) 9136a23d212SGreg Clayton result = True 9146a23d212SGreg Clayton if self.type == rhs.type: 9156a23d212SGreg Clayton for lhs_section in self.sections[1:]: 9166a23d212SGreg Clayton rhs_section = rhs.get_section_by_section(lhs_section) 9176a23d212SGreg Clayton if rhs_section: 918525cd59fSSerge Guelton print('comparing %s.%s...' % (lhs_section.segname, lhs_section.sectname), end=' ') 9196a23d212SGreg Clayton sys.stdout.flush() 9206a23d212SGreg Clayton lhs_data = lhs_section.get_contents(self) 9216a23d212SGreg Clayton rhs_data = rhs_section.get_contents(rhs) 9226a23d212SGreg Clayton if lhs_data and rhs_data: 9236a23d212SGreg Clayton if lhs_data == rhs_data: 924525cd59fSSerge Guelton print('ok') 9256a23d212SGreg Clayton else: 9266a23d212SGreg Clayton lhs_data_len = len(lhs_data) 9276a23d212SGreg Clayton rhs_data_len = len(rhs_data) 9286a23d212SGreg Clayton # if lhs_data_len < rhs_data_len: 9296a23d212SGreg Clayton # if lhs_data == rhs_data[0:lhs_data_len]: 9306a23d212SGreg Clayton # print 'section data for %s matches the first %u bytes' % (lhs_section.sectname, lhs_data_len) 9316a23d212SGreg Clayton # else: 9326a23d212SGreg Clayton # # TODO: check padding 9336a23d212SGreg Clayton # result = False 9346a23d212SGreg Clayton # elif lhs_data_len > rhs_data_len: 9356a23d212SGreg Clayton # if lhs_data[0:rhs_data_len] == rhs_data: 9366a23d212SGreg Clayton # print 'section data for %s matches the first %u bytes' % (lhs_section.sectname, lhs_data_len) 9376a23d212SGreg Clayton # else: 9386a23d212SGreg Clayton # # TODO: check padding 9396a23d212SGreg Clayton # result = False 9406a23d212SGreg Clayton # else: 9416a23d212SGreg Clayton result = False 942525cd59fSSerge Guelton print('error: sections differ') 9436a23d212SGreg Clayton # print 'a) %s' % (lhs_section) 9446a23d212SGreg Clayton # dump_hex_byte_string_diff(0, lhs_data, rhs_data) 9456a23d212SGreg Clayton # print 'b) %s' % (rhs_section) 9466a23d212SGreg Clayton # dump_hex_byte_string_diff(0, rhs_data, lhs_data) 9476a23d212SGreg Clayton elif lhs_data and not rhs_data: 948525cd59fSSerge Guelton print('error: section data missing from b:') 949525cd59fSSerge Guelton print('a) %s' % (lhs_section)) 950525cd59fSSerge Guelton print('b) %s' % (rhs_section)) 9516a23d212SGreg Clayton result = False 9526a23d212SGreg Clayton elif not lhs_data and rhs_data: 953525cd59fSSerge Guelton print('error: section data missing from a:') 954525cd59fSSerge Guelton print('a) %s' % (lhs_section)) 955525cd59fSSerge Guelton print('b) %s' % (rhs_section)) 9566a23d212SGreg Clayton result = False 9576a23d212SGreg Clayton elif lhs_section.offset or rhs_section.offset: 958525cd59fSSerge Guelton print('error: section data missing for both a and b:') 959525cd59fSSerge Guelton print('a) %s' % (lhs_section)) 960525cd59fSSerge Guelton print('b) %s' % (rhs_section)) 9616a23d212SGreg Clayton result = False 9626a23d212SGreg Clayton else: 963525cd59fSSerge Guelton print('ok') 9646a23d212SGreg Clayton else: 9656a23d212SGreg Clayton result = False 966525cd59fSSerge Guelton print('error: section %s is missing in %s' % (lhs_section.sectname, rhs.path)) 9676a23d212SGreg Clayton else: 968e9264b74SKazuaki Ishizaki print('error: comparing a %s mach-o file with a %s mach-o file is not supported' % (self.type, rhs.type)) 9696a23d212SGreg Clayton result = False 9706a23d212SGreg Clayton if not result: 971525cd59fSSerge Guelton print('error: mach files differ') 9726a23d212SGreg Clayton return result 973b9c1b51eSKate Stone 9746a23d212SGreg Clayton def dump_header(self, dump_description=True, options=None): 9756a23d212SGreg Clayton if options.verbose: 976525cd59fSSerge Guelton print("MAGIC CPU SUBTYPE FILETYPE NUM CMDS SIZE CMDS FLAGS") 977525cd59fSSerge Guelton print("---------- ---------- ---------- ---------- -------- ---------- ----------") 9786a23d212SGreg Clayton else: 979525cd59fSSerge Guelton print("MAGIC ARCH FILETYPE NUM CMDS SIZE CMDS FLAGS") 980525cd59fSSerge Guelton print("------------ ---------- -------------- -------- ---------- ----------") 9816a23d212SGreg Clayton 9826a23d212SGreg Clayton def dump_flat(self, options): 9836a23d212SGreg Clayton if options.verbose: 984525cd59fSSerge Guelton print("%#8.8x %#8.8x %#8.8x %#8.8x %#8u %#8.8x %#8.8x" % (self.magic, self.arch.cpu, self.arch.sub, self.filetype.value, self.ncmds, self.sizeofcmds, self.flags.bits)) 9856a23d212SGreg Clayton else: 986525cd59fSSerge Guelton print("%-12s %-10s %-14s %#8u %#8.8x %s" % (self.magic, self.arch, self.filetype, self.ncmds, self.sizeofcmds, self.flags)) 9876a23d212SGreg Clayton 9886a23d212SGreg Clayton def dump(self, options): 9896a23d212SGreg Clayton if options.dump_header: 9906a23d212SGreg Clayton self.dump_header(True, options) 9916a23d212SGreg Clayton if options.dump_load_commands: 9926a23d212SGreg Clayton self.dump_load_commands(False, options) 9936a23d212SGreg Clayton if options.dump_sections: 9946a23d212SGreg Clayton self.dump_sections(False, options) 9956a23d212SGreg Clayton if options.section_names: 9966a23d212SGreg Clayton self.dump_section_contents(options) 9976a23d212SGreg Clayton if options.dump_symtab: 9986a23d212SGreg Clayton self.get_symtab() 9996a23d212SGreg Clayton if len(self.symbols): 10006a23d212SGreg Clayton self.dump_sections(False, options) 10016a23d212SGreg Clayton else: 1002525cd59fSSerge Guelton print("No symbols") 10036a23d212SGreg Clayton if options.find_mangled: 10046a23d212SGreg Clayton self.dump_symbol_names_matching_regex(re.compile('^_?_Z')) 10056a23d212SGreg Clayton 10066a23d212SGreg Clayton def dump_header(self, dump_description=True, options=None): 10076a23d212SGreg Clayton if dump_description: 1008525cd59fSSerge Guelton print(self.description()) 1009525cd59fSSerge Guelton print("Mach Header") 1010525cd59fSSerge Guelton print(" magic: %#8.8x %s" % (self.magic.value, self.magic)) 1011525cd59fSSerge Guelton print(" cputype: %#8.8x %s" % (self.arch.cpu, self.arch)) 1012525cd59fSSerge Guelton print(" cpusubtype: %#8.8x" % self.arch.sub) 1013525cd59fSSerge Guelton print(" filetype: %#8.8x %s" % (self.filetype.get_enum_value(), self.filetype.get_enum_name())) 1014525cd59fSSerge Guelton print(" ncmds: %#8.8x %u" % (self.ncmds, self.ncmds)) 1015525cd59fSSerge Guelton print(" sizeofcmds: %#8.8x" % self.sizeofcmds) 1016525cd59fSSerge Guelton print(" flags: %#8.8x %s" % (self.flags.bits, self.flags)) 10176a23d212SGreg Clayton 10186a23d212SGreg Clayton def dump_load_commands(self, dump_description=True, options=None): 10196a23d212SGreg Clayton if dump_description: 1020525cd59fSSerge Guelton print(self.description()) 10216a23d212SGreg Clayton for lc in self.commands: 1022525cd59fSSerge Guelton print(lc) 10236a23d212SGreg Clayton 10246a23d212SGreg Clayton def get_section_by_name(self, name): 10256a23d212SGreg Clayton for section in self.sections: 10266a23d212SGreg Clayton if section.sectname and section.sectname == name: 10276a23d212SGreg Clayton return section 10286a23d212SGreg Clayton return None 10296a23d212SGreg Clayton 10306a23d212SGreg Clayton def get_section_by_section(self, other_section): 10316a23d212SGreg Clayton for section in self.sections: 10326a23d212SGreg Clayton if section.sectname == other_section.sectname and section.segname == other_section.segname: 10336a23d212SGreg Clayton return section 10346a23d212SGreg Clayton return None 10356a23d212SGreg Clayton 10366a23d212SGreg Clayton def dump_sections(self, dump_description=True, options=None): 10376a23d212SGreg Clayton if dump_description: 1038525cd59fSSerge Guelton print(self.description()) 10396a23d212SGreg Clayton num_sections = len(self.sections) 10406a23d212SGreg Clayton if num_sections > 1: 10416a23d212SGreg Clayton self.sections[1].dump_header() 10426a23d212SGreg Clayton for sect_idx in range(1, num_sections): 1043525cd59fSSerge Guelton print("%s" % self.sections[sect_idx]) 10446a23d212SGreg Clayton 10456a23d212SGreg Clayton def dump_section_contents(self, options): 10466a23d212SGreg Clayton saved_section_to_disk = False 10476a23d212SGreg Clayton for sectname in options.section_names: 10486a23d212SGreg Clayton section = self.get_section_by_name(sectname) 10496a23d212SGreg Clayton if section: 10506a23d212SGreg Clayton sect_bytes = section.get_contents(self) 10516a23d212SGreg Clayton if options.outfile: 10526a23d212SGreg Clayton if not saved_section_to_disk: 10536a23d212SGreg Clayton outfile = open(options.outfile, 'w') 10546a23d212SGreg Clayton if options.extract_modules: 10556a23d212SGreg Clayton # print "Extracting modules from mach file..." 1056b9c1b51eSKate Stone data = file_extract.FileExtract( 10573a22c3ccSSerge Guelton io.BytesIO(sect_bytes), self.data.byte_order) 10586a23d212SGreg Clayton version = data.get_uint32() 10596a23d212SGreg Clayton num_modules = data.get_uint32() 1060b9c1b51eSKate Stone # print "version = %u, num_modules = %u" % 1061b9c1b51eSKate Stone # (version, num_modules) 10626a23d212SGreg Clayton for i in range(num_modules): 10636a23d212SGreg Clayton data_offset = data.get_uint64() 10646a23d212SGreg Clayton data_size = data.get_uint64() 10656a23d212SGreg Clayton name_offset = data.get_uint32() 10666a23d212SGreg Clayton language = data.get_uint32() 10676a23d212SGreg Clayton flags = data.get_uint32() 10686a23d212SGreg Clayton data.seek(name_offset) 10696a23d212SGreg Clayton module_name = data.get_c_string() 1070b9c1b51eSKate Stone # print "module[%u] data_offset = %#16.16x, 1071b9c1b51eSKate Stone # data_size = %#16.16x, name_offset = 1072b9c1b51eSKate Stone # %#16.16x (%s), language = %u, flags = 1073b9c1b51eSKate Stone # %#x" % (i, data_offset, data_size, 1074b9c1b51eSKate Stone # name_offset, module_name, language, 1075b9c1b51eSKate Stone # flags) 10766a23d212SGreg Clayton data.seek(data_offset) 10776a23d212SGreg Clayton outfile.write(data.read_size(data_size)) 10786a23d212SGreg Clayton else: 1079525cd59fSSerge Guelton print("Saving section %s to '%s'" % (sectname, options.outfile)) 10806a23d212SGreg Clayton outfile.write(sect_bytes) 10816a23d212SGreg Clayton outfile.close() 10826a23d212SGreg Clayton saved_section_to_disk = True 10836a23d212SGreg Clayton else: 1084525cd59fSSerge Guelton print("error: you can only save a single section to disk at a time, skipping section '%s'" % (sectname)) 10856a23d212SGreg Clayton else: 1086525cd59fSSerge Guelton print('section %s:\n' % (sectname)) 10876a23d212SGreg Clayton section.dump_header() 1088525cd59fSSerge Guelton print('%s\n' % (section)) 10896a23d212SGreg Clayton dump_memory(0, sect_bytes, options.max_count, 16) 10906a23d212SGreg Clayton else: 1091525cd59fSSerge Guelton print('error: no section named "%s" was found' % (sectname)) 10926a23d212SGreg Clayton 10936a23d212SGreg Clayton def get_segment(self, segname): 10946a23d212SGreg Clayton if len(self.segments) == 1 and self.segments[0].segname == '': 10956a23d212SGreg Clayton return self.segments[0] 10966a23d212SGreg Clayton for segment in self.segments: 10976a23d212SGreg Clayton if segment.segname == segname: 10986a23d212SGreg Clayton return segment 10996a23d212SGreg Clayton return None 11006a23d212SGreg Clayton 11016a23d212SGreg Clayton def get_first_load_command(self, lc_enum_value): 11026a23d212SGreg Clayton for lc in self.commands: 11036a23d212SGreg Clayton if lc.command.value == lc_enum_value: 11046a23d212SGreg Clayton return lc 11056a23d212SGreg Clayton return None 11066a23d212SGreg Clayton 11076a23d212SGreg Clayton def get_symtab(self): 11086a23d212SGreg Clayton if self.data and not self.symbols: 11096a23d212SGreg Clayton lc_symtab = self.get_first_load_command(LC_SYMTAB) 11106a23d212SGreg Clayton if lc_symtab: 11116a23d212SGreg Clayton symtab_offset = self.file_off 11126a23d212SGreg Clayton if self.data.is_in_memory(): 11136a23d212SGreg Clayton linkedit_segment = self.get_segment('__LINKEDIT') 11146a23d212SGreg Clayton if linkedit_segment: 11156a23d212SGreg Clayton linkedit_vmaddr = linkedit_segment.vmaddr 11166a23d212SGreg Clayton linkedit_fileoff = linkedit_segment.fileoff 11176a23d212SGreg Clayton symtab_offset = linkedit_vmaddr + lc_symtab.symoff - linkedit_fileoff 11186a23d212SGreg Clayton symtab_offset = linkedit_vmaddr + lc_symtab.stroff - linkedit_fileoff 11196a23d212SGreg Clayton else: 11206a23d212SGreg Clayton symtab_offset += lc_symtab.symoff 11216a23d212SGreg Clayton 11226a23d212SGreg Clayton self.data.seek(symtab_offset) 11236a23d212SGreg Clayton is_64 = self.is_64_bit() 11246a23d212SGreg Clayton for i in range(lc_symtab.nsyms): 11256a23d212SGreg Clayton nlist = Mach.NList() 11266a23d212SGreg Clayton nlist.unpack(self, self.data, lc_symtab) 11276a23d212SGreg Clayton self.symbols.append(nlist) 11286a23d212SGreg Clayton else: 1129525cd59fSSerge Guelton print("no LC_SYMTAB") 11306a23d212SGreg Clayton 11316a23d212SGreg Clayton def dump_symtab(self, dump_description=True, options=None): 11326a23d212SGreg Clayton self.get_symtab() 11336a23d212SGreg Clayton if dump_description: 1134525cd59fSSerge Guelton print(self.description()) 11356a23d212SGreg Clayton for i, symbol in enumerate(self.symbols): 1136525cd59fSSerge Guelton print('[%5u] %s' % (i, symbol)) 11376a23d212SGreg Clayton 11386a23d212SGreg Clayton def dump_symbol_names_matching_regex(self, regex, file=None): 11396a23d212SGreg Clayton self.get_symtab() 11406a23d212SGreg Clayton for symbol in self.symbols: 11416a23d212SGreg Clayton if symbol.name and regex.search(symbol.name): 1142525cd59fSSerge Guelton print(symbol.name) 11436a23d212SGreg Clayton if file: 11446a23d212SGreg Clayton file.write('%s\n' % (symbol.name)) 11456a23d212SGreg Clayton 11466a23d212SGreg Clayton def is_64_bit(self): 11476a23d212SGreg Clayton return self.magic.is_64_bit() 11486a23d212SGreg Clayton 11496a23d212SGreg Clayton class LoadCommand: 1150b9c1b51eSKate Stone 11516a23d212SGreg Clayton class Command(dict_utils.Enum): 11526a23d212SGreg Clayton enum = { 11536a23d212SGreg Clayton 'LC_SEGMENT': LC_SEGMENT, 11546a23d212SGreg Clayton 'LC_SYMTAB': LC_SYMTAB, 11556a23d212SGreg Clayton 'LC_SYMSEG': LC_SYMSEG, 11566a23d212SGreg Clayton 'LC_THREAD': LC_THREAD, 11576a23d212SGreg Clayton 'LC_UNIXTHREAD': LC_UNIXTHREAD, 11586a23d212SGreg Clayton 'LC_LOADFVMLIB': LC_LOADFVMLIB, 11596a23d212SGreg Clayton 'LC_IDFVMLIB': LC_IDFVMLIB, 11606a23d212SGreg Clayton 'LC_IDENT': LC_IDENT, 11616a23d212SGreg Clayton 'LC_FVMFILE': LC_FVMFILE, 11626a23d212SGreg Clayton 'LC_PREPAGE': LC_PREPAGE, 11636a23d212SGreg Clayton 'LC_DYSYMTAB': LC_DYSYMTAB, 11646a23d212SGreg Clayton 'LC_LOAD_DYLIB': LC_LOAD_DYLIB, 11656a23d212SGreg Clayton 'LC_ID_DYLIB': LC_ID_DYLIB, 11666a23d212SGreg Clayton 'LC_LOAD_DYLINKER': LC_LOAD_DYLINKER, 11676a23d212SGreg Clayton 'LC_ID_DYLINKER': LC_ID_DYLINKER, 11686a23d212SGreg Clayton 'LC_PREBOUND_DYLIB': LC_PREBOUND_DYLIB, 11696a23d212SGreg Clayton 'LC_ROUTINES': LC_ROUTINES, 11706a23d212SGreg Clayton 'LC_SUB_FRAMEWORK': LC_SUB_FRAMEWORK, 11716a23d212SGreg Clayton 'LC_SUB_UMBRELLA': LC_SUB_UMBRELLA, 11726a23d212SGreg Clayton 'LC_SUB_CLIENT': LC_SUB_CLIENT, 11736a23d212SGreg Clayton 'LC_SUB_LIBRARY': LC_SUB_LIBRARY, 11746a23d212SGreg Clayton 'LC_TWOLEVEL_HINTS': LC_TWOLEVEL_HINTS, 11756a23d212SGreg Clayton 'LC_PREBIND_CKSUM': LC_PREBIND_CKSUM, 11766a23d212SGreg Clayton 'LC_LOAD_WEAK_DYLIB': LC_LOAD_WEAK_DYLIB, 11776a23d212SGreg Clayton 'LC_SEGMENT_64': LC_SEGMENT_64, 11786a23d212SGreg Clayton 'LC_ROUTINES_64': LC_ROUTINES_64, 11796a23d212SGreg Clayton 'LC_UUID': LC_UUID, 11806a23d212SGreg Clayton 'LC_RPATH': LC_RPATH, 11816a23d212SGreg Clayton 'LC_CODE_SIGNATURE': LC_CODE_SIGNATURE, 11826a23d212SGreg Clayton 'LC_SEGMENT_SPLIT_INFO': LC_SEGMENT_SPLIT_INFO, 11836a23d212SGreg Clayton 'LC_REEXPORT_DYLIB': LC_REEXPORT_DYLIB, 11846a23d212SGreg Clayton 'LC_LAZY_LOAD_DYLIB': LC_LAZY_LOAD_DYLIB, 11856a23d212SGreg Clayton 'LC_ENCRYPTION_INFO': LC_ENCRYPTION_INFO, 11866a23d212SGreg Clayton 'LC_DYLD_INFO': LC_DYLD_INFO, 11876a23d212SGreg Clayton 'LC_DYLD_INFO_ONLY': LC_DYLD_INFO_ONLY, 11886a23d212SGreg Clayton 'LC_LOAD_UPWARD_DYLIB': LC_LOAD_UPWARD_DYLIB, 11896a23d212SGreg Clayton 'LC_VERSION_MIN_MACOSX': LC_VERSION_MIN_MACOSX, 11906a23d212SGreg Clayton 'LC_VERSION_MIN_IPHONEOS': LC_VERSION_MIN_IPHONEOS, 11916a23d212SGreg Clayton 'LC_FUNCTION_STARTS': LC_FUNCTION_STARTS, 11926a23d212SGreg Clayton 'LC_DYLD_ENVIRONMENT': LC_DYLD_ENVIRONMENT 11936a23d212SGreg Clayton } 11946a23d212SGreg Clayton 11956a23d212SGreg Clayton def __init__(self, initial_value=0): 11966a23d212SGreg Clayton dict_utils.Enum.__init__(self, initial_value, self.enum) 11976a23d212SGreg Clayton 11986a23d212SGreg Clayton def __init__(self, c=None, l=0, o=0): 1199b9c1b51eSKate Stone if c is not None: 12006a23d212SGreg Clayton self.command = c 12016a23d212SGreg Clayton else: 12026a23d212SGreg Clayton self.command = Mach.LoadCommand.Command(0) 12036a23d212SGreg Clayton self.length = l 12046a23d212SGreg Clayton self.file_off = o 12056a23d212SGreg Clayton 12066a23d212SGreg Clayton def unpack(self, mach_file, data): 12076a23d212SGreg Clayton self.file_off = data.tell() 12086a23d212SGreg Clayton self.command.value, self.length = data.get_n_uint32(2) 12096a23d212SGreg Clayton 12106a23d212SGreg Clayton def skip(self, data): 12116a23d212SGreg Clayton data.seek(self.file_off + self.length, 0) 12126a23d212SGreg Clayton 12136a23d212SGreg Clayton def __str__(self): 12146a23d212SGreg Clayton lc_name = self.command.get_enum_name() 1215b9c1b51eSKate Stone return '%#8.8x: <%#4.4x> %-24s' % (self.file_off, 1216b9c1b51eSKate Stone self.length, lc_name) 12176a23d212SGreg Clayton 12186a23d212SGreg Clayton class Section: 12196a23d212SGreg Clayton 12206a23d212SGreg Clayton def __init__(self): 12216a23d212SGreg Clayton self.index = 0 12226a23d212SGreg Clayton self.is_64 = False 12236a23d212SGreg Clayton self.sectname = None 12246a23d212SGreg Clayton self.segname = None 12256a23d212SGreg Clayton self.addr = 0 12266a23d212SGreg Clayton self.size = 0 12276a23d212SGreg Clayton self.offset = 0 12286a23d212SGreg Clayton self.align = 0 12296a23d212SGreg Clayton self.reloff = 0 12306a23d212SGreg Clayton self.nreloc = 0 12316a23d212SGreg Clayton self.flags = 0 12326a23d212SGreg Clayton self.reserved1 = 0 12336a23d212SGreg Clayton self.reserved2 = 0 12346a23d212SGreg Clayton self.reserved3 = 0 12356a23d212SGreg Clayton 12366a23d212SGreg Clayton def unpack(self, is_64, data): 12376a23d212SGreg Clayton self.is_64 = is_64 12386a23d212SGreg Clayton self.sectname = data.get_fixed_length_c_string(16, '', True) 12396a23d212SGreg Clayton self.segname = data.get_fixed_length_c_string(16, '', True) 12406a23d212SGreg Clayton if self.is_64: 12416a23d212SGreg Clayton self.addr, self.size = data.get_n_uint64(2) 1242b9c1b51eSKate Stone self.offset, self.align, self.reloff, self.nreloc, self.flags, self.reserved1, self.reserved2, self.reserved3 = data.get_n_uint32( 1243b9c1b51eSKate Stone 8) 12446a23d212SGreg Clayton else: 12456a23d212SGreg Clayton self.addr, self.size = data.get_n_uint32(2) 1246b9c1b51eSKate Stone self.offset, self.align, self.reloff, self.nreloc, self.flags, self.reserved1, self.reserved2 = data.get_n_uint32( 1247b9c1b51eSKate Stone 7) 12486a23d212SGreg Clayton 12496a23d212SGreg Clayton def dump_header(self): 12506a23d212SGreg Clayton if self.is_64: 1251525cd59fSSerge Guelton print("INDEX ADDRESS SIZE OFFSET ALIGN RELOFF NRELOC FLAGS RESERVED1 RESERVED2 RESERVED3 NAME") 1252525cd59fSSerge Guelton print("===== ------------------ ------------------ ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------------------") 12536a23d212SGreg Clayton else: 1254525cd59fSSerge Guelton print("INDEX ADDRESS SIZE OFFSET ALIGN RELOFF NRELOC FLAGS RESERVED1 RESERVED2 NAME") 1255525cd59fSSerge Guelton print("===== ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------------------") 12566a23d212SGreg Clayton 12576a23d212SGreg Clayton def __str__(self): 12586a23d212SGreg Clayton if self.is_64: 1259b9c1b51eSKate Stone return "[%3u] %#16.16x %#16.16x %#8.8x %#8.8x %#8.8x %#8.8x %#8.8x %#8.8x %#8.8x %#8.8x %s.%s" % ( 1260b9c1b51eSKate Stone self.index, self.addr, self.size, self.offset, self.align, self.reloff, self.nreloc, self.flags, self.reserved1, self.reserved2, self.reserved3, self.segname, self.sectname) 12616a23d212SGreg Clayton else: 1262b9c1b51eSKate Stone return "[%3u] %#8.8x %#8.8x %#8.8x %#8.8x %#8.8x %#8.8x %#8.8x %#8.8x %#8.8x %s.%s" % ( 1263b9c1b51eSKate Stone self.index, self.addr, self.size, self.offset, self.align, self.reloff, self.nreloc, self.flags, self.reserved1, self.reserved2, self.segname, self.sectname) 12646a23d212SGreg Clayton 12656a23d212SGreg Clayton def get_contents(self, mach_file): 12666a23d212SGreg Clayton '''Get the section contents as a python string''' 1267b9c1b51eSKate Stone if self.size > 0 and mach_file.get_segment( 1268b9c1b51eSKate Stone self.segname).filesize > 0: 12696a23d212SGreg Clayton data = mach_file.get_data() 12706a23d212SGreg Clayton if data: 12716a23d212SGreg Clayton section_data_offset = mach_file.file_off + self.offset 1272b9c1b51eSKate Stone # print '%s.%s is at offset 0x%x with size 0x%x' % 1273b9c1b51eSKate Stone # (self.segname, self.sectname, section_data_offset, 1274b9c1b51eSKate Stone # self.size) 12756a23d212SGreg Clayton data.push_offset_and_seek(section_data_offset) 12766a23d212SGreg Clayton bytes = data.read_size(self.size) 12776a23d212SGreg Clayton data.pop_offset_and_seek() 12786a23d212SGreg Clayton return bytes 12796a23d212SGreg Clayton return None 12806a23d212SGreg Clayton 12816a23d212SGreg Clayton class DylibLoadCommand(LoadCommand): 1282b9c1b51eSKate Stone 12836a23d212SGreg Clayton def __init__(self, lc): 12846a23d212SGreg Clayton Mach.LoadCommand.__init__(self, lc.command, lc.length, lc.file_off) 12856a23d212SGreg Clayton self.name = None 12866a23d212SGreg Clayton self.timestamp = 0 12876a23d212SGreg Clayton self.current_version = 0 12886a23d212SGreg Clayton self.compatibility_version = 0 12896a23d212SGreg Clayton 12906a23d212SGreg Clayton def unpack(self, mach_file, data): 12916a23d212SGreg Clayton byte_order_char = mach_file.magic.get_byte_order() 1292b9c1b51eSKate Stone name_offset, self.timestamp, self.current_version, self.compatibility_version = data.get_n_uint32( 1293b9c1b51eSKate Stone 4) 12946a23d212SGreg Clayton data.seek(self.file_off + name_offset, 0) 12956a23d212SGreg Clayton self.name = data.get_fixed_length_c_string(self.length - 24) 12966a23d212SGreg Clayton 12976a23d212SGreg Clayton def __str__(self): 1298b9c1b51eSKate Stone s = Mach.LoadCommand.__str__(self) 1299b9c1b51eSKate Stone s += "%#8.8x %#8.8x %#8.8x " % (self.timestamp, 1300b9c1b51eSKate Stone self.current_version, 1301b9c1b51eSKate Stone self.compatibility_version) 13026a23d212SGreg Clayton s += self.name 13036a23d212SGreg Clayton return s 13046a23d212SGreg Clayton 13056a23d212SGreg Clayton class LoadDYLDLoadCommand(LoadCommand): 1306b9c1b51eSKate Stone 13076a23d212SGreg Clayton def __init__(self, lc): 13086a23d212SGreg Clayton Mach.LoadCommand.__init__(self, lc.command, lc.length, lc.file_off) 13096a23d212SGreg Clayton self.name = None 13106a23d212SGreg Clayton 13116a23d212SGreg Clayton def unpack(self, mach_file, data): 13126a23d212SGreg Clayton data.get_uint32() 13136a23d212SGreg Clayton self.name = data.get_fixed_length_c_string(self.length - 12) 13146a23d212SGreg Clayton 13156a23d212SGreg Clayton def __str__(self): 1316b9c1b51eSKate Stone s = Mach.LoadCommand.__str__(self) 13176a23d212SGreg Clayton s += "%s" % self.name 13186a23d212SGreg Clayton return s 13196a23d212SGreg Clayton 13206a23d212SGreg Clayton class UnixThreadLoadCommand(LoadCommand): 1321b9c1b51eSKate Stone 13226a23d212SGreg Clayton class ThreadState: 1323b9c1b51eSKate Stone 13246a23d212SGreg Clayton def __init__(self): 13256a23d212SGreg Clayton self.flavor = 0 13266a23d212SGreg Clayton self.count = 0 13276a23d212SGreg Clayton self.register_values = list() 13286a23d212SGreg Clayton 13296a23d212SGreg Clayton def unpack(self, data): 13306a23d212SGreg Clayton self.flavor, self.count = data.get_n_uint32(2) 13316a23d212SGreg Clayton self.register_values = data.get_n_uint32(self.count) 13326a23d212SGreg Clayton 13336a23d212SGreg Clayton def __str__(self): 1334b9c1b51eSKate Stone s = "flavor = %u, count = %u, regs =" % ( 1335b9c1b51eSKate Stone self.flavor, self.count) 13366a23d212SGreg Clayton i = 0 13376a23d212SGreg Clayton for register_value in self.register_values: 13386a23d212SGreg Clayton if i % 8 == 0: 13396a23d212SGreg Clayton s += "\n " 13406a23d212SGreg Clayton s += " %#8.8x" % register_value 13416a23d212SGreg Clayton i += 1 13426a23d212SGreg Clayton return s 13436a23d212SGreg Clayton 13446a23d212SGreg Clayton def __init__(self, lc): 13456a23d212SGreg Clayton Mach.LoadCommand.__init__(self, lc.command, lc.length, lc.file_off) 13466a23d212SGreg Clayton self.reg_sets = list() 13476a23d212SGreg Clayton 13486a23d212SGreg Clayton def unpack(self, mach_file, data): 13496a23d212SGreg Clayton reg_set = Mach.UnixThreadLoadCommand.ThreadState() 13506a23d212SGreg Clayton reg_set.unpack(data) 13516a23d212SGreg Clayton self.reg_sets.append(reg_set) 13526a23d212SGreg Clayton 13536a23d212SGreg Clayton def __str__(self): 1354b9c1b51eSKate Stone s = Mach.LoadCommand.__str__(self) 13556a23d212SGreg Clayton for reg_set in self.reg_sets: 13566a23d212SGreg Clayton s += "%s" % reg_set 13576a23d212SGreg Clayton return s 13586a23d212SGreg Clayton 13596a23d212SGreg Clayton class DYLDInfoOnlyLoadCommand(LoadCommand): 1360b9c1b51eSKate Stone 13616a23d212SGreg Clayton def __init__(self, lc): 13626a23d212SGreg Clayton Mach.LoadCommand.__init__(self, lc.command, lc.length, lc.file_off) 13636a23d212SGreg Clayton self.rebase_off = 0 13646a23d212SGreg Clayton self.rebase_size = 0 13656a23d212SGreg Clayton self.bind_off = 0 13666a23d212SGreg Clayton self.bind_size = 0 13676a23d212SGreg Clayton self.weak_bind_off = 0 13686a23d212SGreg Clayton self.weak_bind_size = 0 13696a23d212SGreg Clayton self.lazy_bind_off = 0 13706a23d212SGreg Clayton self.lazy_bind_size = 0 13716a23d212SGreg Clayton self.export_off = 0 13726a23d212SGreg Clayton self.export_size = 0 13736a23d212SGreg Clayton 13746a23d212SGreg Clayton def unpack(self, mach_file, data): 13756a23d212SGreg Clayton byte_order_char = mach_file.magic.get_byte_order() 1376b9c1b51eSKate Stone self.rebase_off, self.rebase_size, self.bind_off, self.bind_size, self.weak_bind_off, self.weak_bind_size, self.lazy_bind_off, self.lazy_bind_size, self.export_off, self.export_size = data.get_n_uint32( 1377b9c1b51eSKate Stone 10) 13786a23d212SGreg Clayton 13796a23d212SGreg Clayton def __str__(self): 1380b9c1b51eSKate Stone s = Mach.LoadCommand.__str__(self) 1381b9c1b51eSKate Stone s += "rebase_off = %#8.8x, rebase_size = %u, " % ( 1382b9c1b51eSKate Stone self.rebase_off, self.rebase_size) 1383b9c1b51eSKate Stone s += "bind_off = %#8.8x, bind_size = %u, " % ( 1384b9c1b51eSKate Stone self.bind_off, self.bind_size) 1385b9c1b51eSKate Stone s += "weak_bind_off = %#8.8x, weak_bind_size = %u, " % ( 1386b9c1b51eSKate Stone self.weak_bind_off, self.weak_bind_size) 1387b9c1b51eSKate Stone s += "lazy_bind_off = %#8.8x, lazy_bind_size = %u, " % ( 1388b9c1b51eSKate Stone self.lazy_bind_off, self.lazy_bind_size) 1389b9c1b51eSKate Stone s += "export_off = %#8.8x, export_size = %u, " % ( 1390b9c1b51eSKate Stone self.export_off, self.export_size) 13916a23d212SGreg Clayton return s 13926a23d212SGreg Clayton 13936a23d212SGreg Clayton class DYLDSymtabLoadCommand(LoadCommand): 1394b9c1b51eSKate Stone 13956a23d212SGreg Clayton def __init__(self, lc): 13966a23d212SGreg Clayton Mach.LoadCommand.__init__(self, lc.command, lc.length, lc.file_off) 13976a23d212SGreg Clayton self.ilocalsym = 0 13986a23d212SGreg Clayton self.nlocalsym = 0 13996a23d212SGreg Clayton self.iextdefsym = 0 14006a23d212SGreg Clayton self.nextdefsym = 0 14016a23d212SGreg Clayton self.iundefsym = 0 14026a23d212SGreg Clayton self.nundefsym = 0 14036a23d212SGreg Clayton self.tocoff = 0 14046a23d212SGreg Clayton self.ntoc = 0 14056a23d212SGreg Clayton self.modtaboff = 0 14066a23d212SGreg Clayton self.nmodtab = 0 14076a23d212SGreg Clayton self.extrefsymoff = 0 14086a23d212SGreg Clayton self.nextrefsyms = 0 14096a23d212SGreg Clayton self.indirectsymoff = 0 14106a23d212SGreg Clayton self.nindirectsyms = 0 14116a23d212SGreg Clayton self.extreloff = 0 14126a23d212SGreg Clayton self.nextrel = 0 14136a23d212SGreg Clayton self.locreloff = 0 14146a23d212SGreg Clayton self.nlocrel = 0 14156a23d212SGreg Clayton 14166a23d212SGreg Clayton def unpack(self, mach_file, data): 14176a23d212SGreg Clayton byte_order_char = mach_file.magic.get_byte_order() 1418b9c1b51eSKate Stone self.ilocalsym, self.nlocalsym, self.iextdefsym, self.nextdefsym, self.iundefsym, self.nundefsym, self.tocoff, self.ntoc, self.modtaboff, self.nmodtab, self.extrefsymoff, self.nextrefsyms, self.indirectsymoff, self.nindirectsyms, self.extreloff, self.nextrel, self.locreloff, self.nlocrel = data.get_n_uint32( 1419b9c1b51eSKate Stone 18) 14206a23d212SGreg Clayton 14216a23d212SGreg Clayton def __str__(self): 1422b9c1b51eSKate Stone s = Mach.LoadCommand.__str__(self) 14236a23d212SGreg Clayton # s += "ilocalsym = %u, nlocalsym = %u, " % (self.ilocalsym, self.nlocalsym) 14246a23d212SGreg Clayton # s += "iextdefsym = %u, nextdefsym = %u, " % (self.iextdefsym, self.nextdefsym) 14256a23d212SGreg Clayton # s += "iundefsym %u, nundefsym = %u, " % (self.iundefsym, self.nundefsym) 14266a23d212SGreg Clayton # s += "tocoff = %#8.8x, ntoc = %u, " % (self.tocoff, self.ntoc) 14276a23d212SGreg Clayton # s += "modtaboff = %#8.8x, nmodtab = %u, " % (self.modtaboff, self.nmodtab) 14286a23d212SGreg Clayton # s += "extrefsymoff = %#8.8x, nextrefsyms = %u, " % (self.extrefsymoff, self.nextrefsyms) 14296a23d212SGreg Clayton # s += "indirectsymoff = %#8.8x, nindirectsyms = %u, " % (self.indirectsymoff, self.nindirectsyms) 14306a23d212SGreg Clayton # s += "extreloff = %#8.8x, nextrel = %u, " % (self.extreloff, self.nextrel) 1431b9c1b51eSKate Stone # s += "locreloff = %#8.8x, nlocrel = %u" % (self.locreloff, 1432b9c1b51eSKate Stone # self.nlocrel) 1433b9c1b51eSKate Stone s += "ilocalsym = %-10u, nlocalsym = %u\n" % ( 1434b9c1b51eSKate Stone self.ilocalsym, self.nlocalsym) 1435b9c1b51eSKate Stone s += " iextdefsym = %-10u, nextdefsym = %u\n" % ( 1436b9c1b51eSKate Stone self.iextdefsym, self.nextdefsym) 1437b9c1b51eSKate Stone s += " iundefsym = %-10u, nundefsym = %u\n" % ( 1438b9c1b51eSKate Stone self.iundefsym, self.nundefsym) 1439b9c1b51eSKate Stone s += " tocoff = %#8.8x, ntoc = %u\n" % ( 1440b9c1b51eSKate Stone self.tocoff, self.ntoc) 1441b9c1b51eSKate Stone s += " modtaboff = %#8.8x, nmodtab = %u\n" % ( 1442b9c1b51eSKate Stone self.modtaboff, self.nmodtab) 1443b9c1b51eSKate Stone s += " extrefsymoff = %#8.8x, nextrefsyms = %u\n" % ( 1444b9c1b51eSKate Stone self.extrefsymoff, self.nextrefsyms) 1445b9c1b51eSKate Stone s += " indirectsymoff = %#8.8x, nindirectsyms = %u\n" % ( 1446b9c1b51eSKate Stone self.indirectsymoff, self.nindirectsyms) 1447b9c1b51eSKate Stone s += " extreloff = %#8.8x, nextrel = %u\n" % ( 1448b9c1b51eSKate Stone self.extreloff, self.nextrel) 1449b9c1b51eSKate Stone s += " locreloff = %#8.8x, nlocrel = %u" % ( 1450b9c1b51eSKate Stone self.locreloff, self.nlocrel) 14516a23d212SGreg Clayton return s 14526a23d212SGreg Clayton 14536a23d212SGreg Clayton class SymtabLoadCommand(LoadCommand): 1454b9c1b51eSKate Stone 14556a23d212SGreg Clayton def __init__(self, lc): 14566a23d212SGreg Clayton Mach.LoadCommand.__init__(self, lc.command, lc.length, lc.file_off) 14576a23d212SGreg Clayton self.symoff = 0 14586a23d212SGreg Clayton self.nsyms = 0 14596a23d212SGreg Clayton self.stroff = 0 14606a23d212SGreg Clayton self.strsize = 0 14616a23d212SGreg Clayton 14626a23d212SGreg Clayton def unpack(self, mach_file, data): 14636a23d212SGreg Clayton byte_order_char = mach_file.magic.get_byte_order() 1464b9c1b51eSKate Stone self.symoff, self.nsyms, self.stroff, self.strsize = data.get_n_uint32( 1465b9c1b51eSKate Stone 4) 14666a23d212SGreg Clayton 14676a23d212SGreg Clayton def __str__(self): 1468b9c1b51eSKate Stone s = Mach.LoadCommand.__str__(self) 1469b9c1b51eSKate Stone s += "symoff = %#8.8x, nsyms = %u, stroff = %#8.8x, strsize = %u" % ( 1470b9c1b51eSKate Stone self.symoff, self.nsyms, self.stroff, self.strsize) 14716a23d212SGreg Clayton return s 14726a23d212SGreg Clayton 14736a23d212SGreg Clayton class UUIDLoadCommand(LoadCommand): 1474b9c1b51eSKate Stone 14756a23d212SGreg Clayton def __init__(self, lc): 14766a23d212SGreg Clayton Mach.LoadCommand.__init__(self, lc.command, lc.length, lc.file_off) 14776a23d212SGreg Clayton self.uuid = None 14786a23d212SGreg Clayton 14796a23d212SGreg Clayton def unpack(self, mach_file, data): 14806a23d212SGreg Clayton uuid_data = data.get_n_uint8(16) 14816a23d212SGreg Clayton uuid_str = '' 14826a23d212SGreg Clayton for byte in uuid_data: 14836a23d212SGreg Clayton uuid_str += '%2.2x' % byte 14846a23d212SGreg Clayton self.uuid = uuid.UUID(uuid_str) 14856a23d212SGreg Clayton mach_file.uuid = self.uuid 14866a23d212SGreg Clayton 14876a23d212SGreg Clayton def __str__(self): 1488b9c1b51eSKate Stone s = Mach.LoadCommand.__str__(self) 14896a23d212SGreg Clayton s += self.uuid.__str__() 14906a23d212SGreg Clayton return s 14916a23d212SGreg Clayton 14926a23d212SGreg Clayton class DataBlobLoadCommand(LoadCommand): 1493b9c1b51eSKate Stone 14946a23d212SGreg Clayton def __init__(self, lc): 14956a23d212SGreg Clayton Mach.LoadCommand.__init__(self, lc.command, lc.length, lc.file_off) 14966a23d212SGreg Clayton self.dataoff = 0 14976a23d212SGreg Clayton self.datasize = 0 14986a23d212SGreg Clayton 14996a23d212SGreg Clayton def unpack(self, mach_file, data): 15006a23d212SGreg Clayton byte_order_char = mach_file.magic.get_byte_order() 15016a23d212SGreg Clayton self.dataoff, self.datasize = data.get_n_uint32(2) 15026a23d212SGreg Clayton 15036a23d212SGreg Clayton def __str__(self): 1504b9c1b51eSKate Stone s = Mach.LoadCommand.__str__(self) 1505b9c1b51eSKate Stone s += "dataoff = %#8.8x, datasize = %u" % ( 1506b9c1b51eSKate Stone self.dataoff, self.datasize) 15076a23d212SGreg Clayton return s 15086a23d212SGreg Clayton 15096a23d212SGreg Clayton class EncryptionInfoLoadCommand(LoadCommand): 1510b9c1b51eSKate Stone 15116a23d212SGreg Clayton def __init__(self, lc): 15126a23d212SGreg Clayton Mach.LoadCommand.__init__(self, lc.command, lc.length, lc.file_off) 15136a23d212SGreg Clayton self.cryptoff = 0 15146a23d212SGreg Clayton self.cryptsize = 0 15156a23d212SGreg Clayton self.cryptid = 0 15166a23d212SGreg Clayton 15176a23d212SGreg Clayton def unpack(self, mach_file, data): 15186a23d212SGreg Clayton byte_order_char = mach_file.magic.get_byte_order() 15196a23d212SGreg Clayton self.cryptoff, self.cryptsize, self.cryptid = data.get_n_uint32(3) 15206a23d212SGreg Clayton 15216a23d212SGreg Clayton def __str__(self): 1522b9c1b51eSKate Stone s = Mach.LoadCommand.__str__(self) 1523b9c1b51eSKate Stone s += "file-range = [%#8.8x - %#8.8x), cryptsize = %u, cryptid = %u" % ( 1524b9c1b51eSKate Stone self.cryptoff, self.cryptoff + self.cryptsize, self.cryptsize, self.cryptid) 15256a23d212SGreg Clayton return s 15266a23d212SGreg Clayton 15276a23d212SGreg Clayton class SegmentLoadCommand(LoadCommand): 15286a23d212SGreg Clayton 15296a23d212SGreg Clayton def __init__(self, lc): 15306a23d212SGreg Clayton Mach.LoadCommand.__init__(self, lc.command, lc.length, lc.file_off) 15316a23d212SGreg Clayton self.segname = None 15326a23d212SGreg Clayton self.vmaddr = 0 15336a23d212SGreg Clayton self.vmsize = 0 15346a23d212SGreg Clayton self.fileoff = 0 15356a23d212SGreg Clayton self.filesize = 0 15366a23d212SGreg Clayton self.maxprot = 0 15376a23d212SGreg Clayton self.initprot = 0 15386a23d212SGreg Clayton self.nsects = 0 15396a23d212SGreg Clayton self.flags = 0 15406a23d212SGreg Clayton 15416a23d212SGreg Clayton def unpack(self, mach_file, data): 1542b9c1b51eSKate Stone is_64 = self.command.get_enum_value() == LC_SEGMENT_64 15436a23d212SGreg Clayton self.segname = data.get_fixed_length_c_string(16, '', True) 15446a23d212SGreg Clayton if is_64: 1545b9c1b51eSKate Stone self.vmaddr, self.vmsize, self.fileoff, self.filesize = data.get_n_uint64( 1546b9c1b51eSKate Stone 4) 15476a23d212SGreg Clayton else: 1548b9c1b51eSKate Stone self.vmaddr, self.vmsize, self.fileoff, self.filesize = data.get_n_uint32( 1549b9c1b51eSKate Stone 4) 1550b9c1b51eSKate Stone self.maxprot, self.initprot, self.nsects, self.flags = data.get_n_uint32( 1551b9c1b51eSKate Stone 4) 15526a23d212SGreg Clayton mach_file.segments.append(self) 15536a23d212SGreg Clayton for i in range(self.nsects): 15546a23d212SGreg Clayton section = Mach.Section() 15556a23d212SGreg Clayton section.unpack(is_64, data) 15566a23d212SGreg Clayton section.index = len(mach_file.sections) 15576a23d212SGreg Clayton mach_file.sections.append(section) 15586a23d212SGreg Clayton 15596a23d212SGreg Clayton def __str__(self): 1560b9c1b51eSKate Stone s = Mach.LoadCommand.__str__(self) 15616a23d212SGreg Clayton if self.command.get_enum_value() == LC_SEGMENT: 1562b9c1b51eSKate Stone s += "%#8.8x %#8.8x %#8.8x %#8.8x " % ( 1563b9c1b51eSKate Stone self.vmaddr, self.vmsize, self.fileoff, self.filesize) 15646a23d212SGreg Clayton else: 1565b9c1b51eSKate Stone s += "%#16.16x %#16.16x %#16.16x %#16.16x " % ( 1566b9c1b51eSKate Stone self.vmaddr, self.vmsize, self.fileoff, self.filesize) 1567b9c1b51eSKate Stone s += "%s %s %3u %#8.8x" % (vm_prot_names[self.maxprot], vm_prot_names[ 1568b9c1b51eSKate Stone self.initprot], self.nsects, self.flags) 15696a23d212SGreg Clayton s += ' ' + self.segname 15706a23d212SGreg Clayton return s 15716a23d212SGreg Clayton 15726a23d212SGreg Clayton class NList: 1573b9c1b51eSKate Stone 15746a23d212SGreg Clayton class Type: 1575b9c1b51eSKate Stone 15766a23d212SGreg Clayton class Stab(dict_utils.Enum): 15776a23d212SGreg Clayton enum = { 15786a23d212SGreg Clayton 'N_GSYM': N_GSYM, 15796a23d212SGreg Clayton 'N_FNAME': N_FNAME, 15806a23d212SGreg Clayton 'N_FUN': N_FUN, 15816a23d212SGreg Clayton 'N_STSYM': N_STSYM, 15826a23d212SGreg Clayton 'N_LCSYM': N_LCSYM, 15836a23d212SGreg Clayton 'N_BNSYM': N_BNSYM, 15846a23d212SGreg Clayton 'N_OPT': N_OPT, 15856a23d212SGreg Clayton 'N_RSYM': N_RSYM, 15866a23d212SGreg Clayton 'N_SLINE': N_SLINE, 15876a23d212SGreg Clayton 'N_ENSYM': N_ENSYM, 15886a23d212SGreg Clayton 'N_SSYM': N_SSYM, 15896a23d212SGreg Clayton 'N_SO': N_SO, 15906a23d212SGreg Clayton 'N_OSO': N_OSO, 15916a23d212SGreg Clayton 'N_LSYM': N_LSYM, 15926a23d212SGreg Clayton 'N_BINCL': N_BINCL, 15936a23d212SGreg Clayton 'N_SOL': N_SOL, 15946a23d212SGreg Clayton 'N_PARAMS': N_PARAMS, 15956a23d212SGreg Clayton 'N_VERSION': N_VERSION, 15966a23d212SGreg Clayton 'N_OLEVEL': N_OLEVEL, 15976a23d212SGreg Clayton 'N_PSYM': N_PSYM, 15986a23d212SGreg Clayton 'N_EINCL': N_EINCL, 15996a23d212SGreg Clayton 'N_ENTRY': N_ENTRY, 16006a23d212SGreg Clayton 'N_LBRAC': N_LBRAC, 16016a23d212SGreg Clayton 'N_EXCL': N_EXCL, 16026a23d212SGreg Clayton 'N_RBRAC': N_RBRAC, 16036a23d212SGreg Clayton 'N_BCOMM': N_BCOMM, 16046a23d212SGreg Clayton 'N_ECOMM': N_ECOMM, 16056a23d212SGreg Clayton 'N_ECOML': N_ECOML, 16066a23d212SGreg Clayton 'N_LENG': N_LENG 16076a23d212SGreg Clayton } 16086a23d212SGreg Clayton 16096a23d212SGreg Clayton def __init__(self, magic=0): 16106a23d212SGreg Clayton dict_utils.Enum.__init__(self, magic, self.enum) 16116a23d212SGreg Clayton 16126a23d212SGreg Clayton def __init__(self, t=0): 16136a23d212SGreg Clayton self.value = t 16146a23d212SGreg Clayton 16156a23d212SGreg Clayton def __str__(self): 16166a23d212SGreg Clayton n_type = self.value 16176a23d212SGreg Clayton if n_type & N_STAB: 16186a23d212SGreg Clayton stab = Mach.NList.Type.Stab(self.value) 16196a23d212SGreg Clayton return '%s' % stab 16206a23d212SGreg Clayton else: 16216a23d212SGreg Clayton type = self.value & N_TYPE 16226a23d212SGreg Clayton type_str = '' 16236a23d212SGreg Clayton if type == N_UNDF: 16246a23d212SGreg Clayton type_str = 'N_UNDF' 16256a23d212SGreg Clayton elif type == N_ABS: 16266a23d212SGreg Clayton type_str = 'N_ABS ' 16276a23d212SGreg Clayton elif type == N_SECT: 16286a23d212SGreg Clayton type_str = 'N_SECT' 16296a23d212SGreg Clayton elif type == N_PBUD: 16306a23d212SGreg Clayton type_str = 'N_PBUD' 16316a23d212SGreg Clayton elif type == N_INDR: 16326a23d212SGreg Clayton type_str = 'N_INDR' 16336a23d212SGreg Clayton else: 16346a23d212SGreg Clayton type_str = "??? (%#2.2x)" % type 16356a23d212SGreg Clayton if n_type & N_PEXT: 16366a23d212SGreg Clayton type_str += ' | PEXT' 16376a23d212SGreg Clayton if n_type & N_EXT: 16386a23d212SGreg Clayton type_str += ' | EXT ' 16396a23d212SGreg Clayton return type_str 16406a23d212SGreg Clayton 16416a23d212SGreg Clayton def __init__(self): 16426a23d212SGreg Clayton self.index = 0 16436a23d212SGreg Clayton self.name_offset = 0 16446a23d212SGreg Clayton self.name = 0 16456a23d212SGreg Clayton self.type = Mach.NList.Type() 16466a23d212SGreg Clayton self.sect_idx = 0 16476a23d212SGreg Clayton self.desc = 0 16486a23d212SGreg Clayton self.value = 0 16496a23d212SGreg Clayton 16506a23d212SGreg Clayton def unpack(self, mach_file, data, symtab_lc): 16516a23d212SGreg Clayton self.index = len(mach_file.symbols) 16526a23d212SGreg Clayton self.name_offset = data.get_uint32() 16536a23d212SGreg Clayton self.type.value, self.sect_idx = data.get_n_uint8(2) 16546a23d212SGreg Clayton self.desc = data.get_uint16() 16556a23d212SGreg Clayton if mach_file.is_64_bit(): 16566a23d212SGreg Clayton self.value = data.get_uint64() 16576a23d212SGreg Clayton else: 16586a23d212SGreg Clayton self.value = data.get_uint32() 1659b9c1b51eSKate Stone data.push_offset_and_seek( 1660b9c1b51eSKate Stone mach_file.file_off + 1661b9c1b51eSKate Stone symtab_lc.stroff + 1662b9c1b51eSKate Stone self.name_offset) 16636a23d212SGreg Clayton # print "get string for symbol[%u]" % self.index 16646a23d212SGreg Clayton self.name = data.get_c_string() 16656a23d212SGreg Clayton data.pop_offset_and_seek() 16666a23d212SGreg Clayton 16676a23d212SGreg Clayton def __str__(self): 16686a23d212SGreg Clayton name_display = '' 16696a23d212SGreg Clayton if len(self.name): 16706a23d212SGreg Clayton name_display = ' "%s"' % self.name 1671b9c1b51eSKate Stone return '%#8.8x %#2.2x (%-20s) %#2.2x %#4.4x %16.16x%s' % (self.name_offset, 1672b9c1b51eSKate Stone self.type.value, self.type, self.sect_idx, self.desc, self.value, name_display) 16736a23d212SGreg Clayton 16746a23d212SGreg Clayton class Interactive(cmd.Cmd): 16756a23d212SGreg Clayton '''Interactive command interpreter to mach-o files.''' 16766a23d212SGreg Clayton 16776a23d212SGreg Clayton def __init__(self, mach, options): 16786a23d212SGreg Clayton cmd.Cmd.__init__(self) 16796a23d212SGreg Clayton self.intro = 'Interactive mach-o command interpreter' 16806a23d212SGreg Clayton self.prompt = 'mach-o: %s %% ' % mach.path 16816a23d212SGreg Clayton self.mach = mach 16826a23d212SGreg Clayton self.options = options 16836a23d212SGreg Clayton 16846a23d212SGreg Clayton def default(self, line): 16856a23d212SGreg Clayton '''Catch all for unknown command, which will exit the interpreter.''' 1686525cd59fSSerge Guelton print("uknown command: %s" % line) 16876a23d212SGreg Clayton return True 16886a23d212SGreg Clayton 16896a23d212SGreg Clayton def do_q(self, line): 16906a23d212SGreg Clayton '''Quit command''' 16916a23d212SGreg Clayton return True 16926a23d212SGreg Clayton 16936a23d212SGreg Clayton def do_quit(self, line): 16946a23d212SGreg Clayton '''Quit command''' 16956a23d212SGreg Clayton return True 16966a23d212SGreg Clayton 16976a23d212SGreg Clayton def do_header(self, line): 16986a23d212SGreg Clayton '''Dump mach-o file headers''' 16996a23d212SGreg Clayton self.mach.dump_header(True, self.options) 17006a23d212SGreg Clayton return False 17016a23d212SGreg Clayton 17026a23d212SGreg Clayton def do_load(self, line): 17036a23d212SGreg Clayton '''Dump all mach-o load commands''' 17046a23d212SGreg Clayton self.mach.dump_load_commands(True, self.options) 17056a23d212SGreg Clayton return False 17066a23d212SGreg Clayton 17076a23d212SGreg Clayton def do_sections(self, line): 17086a23d212SGreg Clayton '''Dump all mach-o sections''' 17096a23d212SGreg Clayton self.mach.dump_sections(True, self.options) 17106a23d212SGreg Clayton return False 17116a23d212SGreg Clayton 17126a23d212SGreg Clayton def do_symtab(self, line): 17136a23d212SGreg Clayton '''Dump all mach-o symbols in the symbol table''' 17146a23d212SGreg Clayton self.mach.dump_symtab(True, self.options) 17156a23d212SGreg Clayton return False 17166a23d212SGreg Clayton 17176a23d212SGreg Claytonif __name__ == '__main__': 1718b9c1b51eSKate Stone parser = optparse.OptionParser( 1719b9c1b51eSKate Stone description='A script that parses skinny and universal mach-o files.') 1720b9c1b51eSKate Stone parser.add_option( 1721b9c1b51eSKate Stone '--arch', 1722b9c1b51eSKate Stone '-a', 1723b9c1b51eSKate Stone type='string', 1724b9c1b51eSKate Stone metavar='arch', 1725b9c1b51eSKate Stone dest='archs', 1726b9c1b51eSKate Stone action='append', 1727b9c1b51eSKate Stone help='specify one or more architectures by name') 1728b9c1b51eSKate Stone parser.add_option( 1729b9c1b51eSKate Stone '-v', 1730b9c1b51eSKate Stone '--verbose', 1731b9c1b51eSKate Stone action='store_true', 1732b9c1b51eSKate Stone dest='verbose', 1733b9c1b51eSKate Stone help='display verbose debug info', 1734b9c1b51eSKate Stone default=False) 1735b9c1b51eSKate Stone parser.add_option( 1736b9c1b51eSKate Stone '-H', 1737b9c1b51eSKate Stone '--header', 1738b9c1b51eSKate Stone action='store_true', 1739b9c1b51eSKate Stone dest='dump_header', 1740b9c1b51eSKate Stone help='dump the mach-o file header', 1741b9c1b51eSKate Stone default=False) 1742b9c1b51eSKate Stone parser.add_option( 1743b9c1b51eSKate Stone '-l', 1744b9c1b51eSKate Stone '--load-commands', 1745b9c1b51eSKate Stone action='store_true', 1746b9c1b51eSKate Stone dest='dump_load_commands', 1747b9c1b51eSKate Stone help='dump the mach-o load commands', 1748b9c1b51eSKate Stone default=False) 1749b9c1b51eSKate Stone parser.add_option( 1750b9c1b51eSKate Stone '-s', 1751b9c1b51eSKate Stone '--symtab', 1752b9c1b51eSKate Stone action='store_true', 1753b9c1b51eSKate Stone dest='dump_symtab', 1754b9c1b51eSKate Stone help='dump the mach-o symbol table', 1755b9c1b51eSKate Stone default=False) 1756b9c1b51eSKate Stone parser.add_option( 1757b9c1b51eSKate Stone '-S', 1758b9c1b51eSKate Stone '--sections', 1759b9c1b51eSKate Stone action='store_true', 1760b9c1b51eSKate Stone dest='dump_sections', 1761b9c1b51eSKate Stone help='dump the mach-o sections', 1762b9c1b51eSKate Stone default=False) 1763b9c1b51eSKate Stone parser.add_option( 1764b9c1b51eSKate Stone '--section', 1765b9c1b51eSKate Stone type='string', 1766b9c1b51eSKate Stone metavar='sectname', 1767b9c1b51eSKate Stone dest='section_names', 1768b9c1b51eSKate Stone action='append', 1769b9c1b51eSKate Stone help='Specify one or more section names to dump', 1770b9c1b51eSKate Stone default=[]) 1771b9c1b51eSKate Stone parser.add_option( 1772b9c1b51eSKate Stone '-o', 1773b9c1b51eSKate Stone '--out', 1774b9c1b51eSKate Stone type='string', 1775b9c1b51eSKate Stone dest='outfile', 1776b9c1b51eSKate Stone help='Used in conjunction with the --section=NAME option to save a single section\'s data to disk.', 1777b9c1b51eSKate Stone default=False) 1778b9c1b51eSKate Stone parser.add_option( 1779b9c1b51eSKate Stone '-i', 1780b9c1b51eSKate Stone '--interactive', 1781b9c1b51eSKate Stone action='store_true', 1782b9c1b51eSKate Stone dest='interactive', 1783b9c1b51eSKate Stone help='enable interactive mode', 1784b9c1b51eSKate Stone default=False) 1785b9c1b51eSKate Stone parser.add_option( 1786b9c1b51eSKate Stone '-m', 1787b9c1b51eSKate Stone '--mangled', 1788b9c1b51eSKate Stone action='store_true', 1789b9c1b51eSKate Stone dest='find_mangled', 1790b9c1b51eSKate Stone help='dump all mangled names in a mach file', 1791b9c1b51eSKate Stone default=False) 1792b9c1b51eSKate Stone parser.add_option( 1793b9c1b51eSKate Stone '-c', 1794b9c1b51eSKate Stone '--compare', 1795b9c1b51eSKate Stone action='store_true', 1796b9c1b51eSKate Stone dest='compare', 1797b9c1b51eSKate Stone help='compare two mach files', 1798b9c1b51eSKate Stone default=False) 1799b9c1b51eSKate Stone parser.add_option( 1800b9c1b51eSKate Stone '-M', 1801b9c1b51eSKate Stone '--extract-modules', 1802b9c1b51eSKate Stone action='store_true', 1803b9c1b51eSKate Stone dest='extract_modules', 1804b9c1b51eSKate Stone help='Extract modules from file', 1805b9c1b51eSKate Stone default=False) 1806b9c1b51eSKate Stone parser.add_option( 1807b9c1b51eSKate Stone '-C', 1808b9c1b51eSKate Stone '--count', 1809b9c1b51eSKate Stone type='int', 1810b9c1b51eSKate Stone dest='max_count', 1811b9c1b51eSKate Stone help='Sets the max byte count when dumping section data', 1812b9c1b51eSKate Stone default=-1) 18136a23d212SGreg Clayton 18146a23d212SGreg Clayton (options, mach_files) = parser.parse_args() 18156a23d212SGreg Clayton if options.extract_modules: 18166a23d212SGreg Clayton if options.section_names: 1817525cd59fSSerge Guelton print("error: can't use --section option with the --extract-modules option") 18186a23d212SGreg Clayton exit(1) 18196a23d212SGreg Clayton if not options.outfile: 1820525cd59fSSerge Guelton print("error: the --output=FILE option must be specified with the --extract-modules option") 18216a23d212SGreg Clayton exit(1) 18226a23d212SGreg Clayton options.section_names.append("__apple_ast") 18236a23d212SGreg Clayton if options.compare: 18246a23d212SGreg Clayton if len(mach_files) == 2: 18256a23d212SGreg Clayton mach_a = Mach() 18266a23d212SGreg Clayton mach_b = Mach() 18276a23d212SGreg Clayton mach_a.parse(mach_files[0]) 18286a23d212SGreg Clayton mach_b.parse(mach_files[1]) 18296a23d212SGreg Clayton mach_a.compare(mach_b) 18306a23d212SGreg Clayton else: 1831525cd59fSSerge Guelton print('error: --compare takes two mach files as arguments') 18326a23d212SGreg Clayton else: 18336a23d212SGreg Clayton if not (options.dump_header or options.dump_load_commands or options.dump_symtab or options.dump_sections or options.find_mangled or options.section_names): 18346a23d212SGreg Clayton options.dump_header = True 18356a23d212SGreg Clayton options.dump_load_commands = True 18366a23d212SGreg Clayton if options.verbose: 1837525cd59fSSerge Guelton print('options', options) 1838525cd59fSSerge Guelton print('mach_files', mach_files) 18396a23d212SGreg Clayton for path in mach_files: 18406a23d212SGreg Clayton mach = Mach() 18416a23d212SGreg Clayton mach.parse(path) 18426a23d212SGreg Clayton if options.interactive: 18436a23d212SGreg Clayton interpreter = Mach.Interactive(mach, options) 18446a23d212SGreg Clayton interpreter.cmdloop() 18456a23d212SGreg Clayton else: 18466a23d212SGreg Clayton mach.dump(options) 1847