1# This file is part of PeachPy package and is licensed under the Simplified BSD license.
2#    See license.rst for the full text of the license.
3
4from enum import IntEnum
5
6
7class FileType(IntEnum):
8    # No file type
9    null = 0
10    # Relocatable file
11    object = 1
12    # Executable file
13    executable = 2
14    # Fixed VM shared library (?)
15    fixed_vm_library = 3
16    # Core dump file
17    core_dump = 4
18    # Preloaded executable file
19    preloaded_executable = 5
20    # Dynamically bound shared library
21    dynamic_library = 6
22    # Dynamic linker (dyld)
23    dynamic_linker = 7
24    # Dynamically bound bundle file
25    dynamic_bundle = 8
26    # Shared library stub for build-time linking (no section content)
27    dynamic_library_stub = 9
28    # Companion file with debug sections only
29    debug_symbols = 10
30    # Kernel-mode driver
31    kext_bundle = 11
32
33
34class CpuType(IntEnum):
35    x86 = 0x00000007
36    x86_64 = 0x01000007
37    arm = 0x0000000C
38    arm64 = 0x0100000C
39    ppc = 0x00000012
40    ppc64 = 0x01000012
41
42    abi64 = 0x01000000
43
44
45class PPCCpuSubType(IntEnum):
46    all = 0
47    # PowerPC G3
48    powerpc750 = 9
49    # PowerPC G4
50    powerpc7400 = 10
51    # PowerPC G4+
52    powerpc7450 = 11
53    # PowerPC G5
54    powerpc970 = 100
55
56
57class X86CpuSubType(IntEnum):
58    all = 3
59
60
61class ARMCpuSubType(IntEnum):
62    all = 0
63    # ARM 1176
64    v6 = 6
65    # ARM Cortex-A8
66    v7 = 9
67    # Cortex-A9 (ARMv7 + MP extension + NEON-HP, de-facto useless, removed from Clang)
68    v7f = 10
69    # Swift (ARMv7 + MP extension + VFPv4/NEONv2 + DIV)
70    v7s = 11
71    # Marvell Kirkwood (ARMv7 + XScale extension + WMMXv2 + Armada extension, no NEON)
72    v7k = 12
73    # Cyclone
74    v8 = 13
75
76
77class ARM64CpuSubType(IntEnum):
78    all = 0
79    # Cyclone
80    v8 = 1
81
82
83class MachHeader:
84    def __init__(self, abi):
85        import peachpy.x86_64
86        import peachpy.arm
87
88        self.abi = abi
89        self.size = {4: 28, 8: 32}[abi.pointer_size]
90        if abi == peachpy.x86_64.abi.system_v_x86_64_abi:
91            # 64-bit
92            self.magic = 0xFEEDFACF
93            self.cpu_type = CpuType.x86_64
94            self.cpu_subtype = X86CpuSubType.all
95        else:
96            raise ValueError("Unsupported ABI: %s" % str(abi))
97        self.file_type = FileType.object
98        self.commands_count = 0
99        self.commands_size = 0
100        self.flags = 0
101
102    @staticmethod
103    def get_size(abi):
104        from peachpy.abi import ABI
105        assert isinstance(abi, ABI)
106        assert abi.pointer_size in [4, 8]
107
108        return {4: 24, 8: 32}[abi.pointer_size]
109
110    def encode(self, encoder):
111        bytes = encoder.uint32(self.magic) + \
112            encoder.uint32(self.cpu_type) + \
113            encoder.uint32(self.cpu_subtype) + \
114            encoder.uint32(self.file_type) + \
115            encoder.uint32(self.commands_count) + \
116            encoder.uint32(self.commands_size) + \
117            encoder.uint32(self.flags)
118        if self.abi.pointer_size == 8:
119            bytes += bytearray(4)
120        return bytes
121