1 #pragma once
2 
3 #include "Types.h"
4 
5 namespace Macho
6 {
7 	enum
8 	{
9 		MH_MAGIC    = 0xFEEDFACE,
10 		MH_MAGIC_64 = 0xFEEDFACF,
11 		MH_CIGAM    = 0xCEFAEDFE,
12 	};
13 
14 	enum CPU_ARCH
15 	{
16 		CPU_ARCH_ABI64 = 0x01000000,
17 	};
18 
19 	enum CPU_TYPE
20 	{
21 		CPU_TYPE_I386  = 0x07,
22 		CPU_TYPE_ARM   = 0x0C,
23 		CPU_TYPE_ARM64 = CPU_ARCH_ABI64 | CPU_TYPE_ARM,
24 	};
25 
26 	enum CPU_SUBTYPE_I386
27 	{
28 		CPU_SUBTYPE_I386_ALL = 0x03,
29 	};
30 
31 	enum CPU_SUBTYPE_ARM
32 	{
33 		CPU_SUBTYPE_ARM_V6  = 0x06,
34 		CPU_SUBTYPE_ARM_V7  = 0x09,
35 		CPU_SUBTYPE_ARM_V7S = 0x0B
36 	};
37 
38 	enum CPU_SUBTYPE_ARM64
39 	{
40 		CPU_SUBTYPE_ARM64_ALL = 0,
41 	};
42 
43 	enum FILE_TYPE
44 	{
45 		MH_OBJECT = 0x01,
46 	};
47 
48 	enum HEADER_FLAGS
49 	{
50 		MH_SPLIT_SEGS  = 0x0020,
51 		MH_NOMULTIDEFS = 0x2000,
52 	};
53 
54 	enum SECTION_FLAGS
55 	{
56 		S_ATTR_SOME_INSTRUCTIONS = 0x00000400,
57 		S_ATTR_PURE_INSTRUCTIONS = 0x80000000,
58 	};
59 
60 	enum LOAD_COMMAND
61 	{
62 		LC_SEGMENT    = 0x0001,
63 		LC_SYMTAB     = 0x0002,
64 		LC_SEGMENT_64 = 0x0019
65 	};
66 
67 	enum RELOC_TYPE
68 	{
69 		GENERIC_RELOC_VANILLA   = 0,
70 		GENERIC_RELOC_PAIR      = 1,
71 
72 		ARM_RELOC_VANILLA       = GENERIC_RELOC_VANILLA,
73 		ARM_RELOC_PAIR          = GENERIC_RELOC_PAIR,
74 		ARM_RELOC_HALF          = 8,
75 
76 		ARM64_RELOC_BRANCH26    = 2
77 	};
78 
79 	struct MACH_HEADER
80 	{
81 		uint32    magic;
82 		uint32    cpuType;
83 		uint32    cpuSubType;
84 		uint32    fileType;
85 		uint32    commandCount;
86 		uint32    sizeofCommands;
87 		uint32    flags;
88 	};
89 	static_assert(sizeof(MACH_HEADER) == 0x1C, "Size of MACH_HEADER structure must be 28 bytes.");
90 
91 	struct MACH_HEADER_64
92 	{
93 		uint32    magic;
94 		uint32    cpuType;
95 		uint32    cpuSubType;
96 		uint32    fileType;
97 		uint32    commandCount;
98 		uint32    sizeofCommands;
99 		uint32    flags;
100 		uint32    reserved;
101 	};
102 	static_assert(sizeof(MACH_HEADER_64) == 0x20, "Size of MACH_HEADER_64 structure must be 32 bytes.");
103 
104 	struct COMMAND
105 	{
106 		uint32    cmd;
107 		uint32    cmdSize;
108 	};
109 
110 	struct SEGMENT_COMMAND : public COMMAND
111 	{
112 		char      name[0x10];
113 		uint32    vmAddress;
114 		uint32    vmSize;
115 		uint32    fileOffset;
116 		uint32    fileSize;
117 		uint32    maxProtection;
118 		uint32    initProtection;
119 		uint32    sectionCount;
120 		uint32    flags;
121 	};
122 	static_assert(sizeof(SEGMENT_COMMAND) == 0x38, "Size of SEGMENT_COMMAND structure must be 48 bytes.");
123 
124 	struct SEGMENT_COMMAND_64 : public COMMAND
125 	{
126 		char      name[0x10];
127 		uint64    vmAddress;
128 		uint64    vmSize;
129 		uint64    fileOffset;
130 		uint64    fileSize;
131 		uint32    maxProtection;
132 		uint32    initProtection;
133 		uint32    sectionCount;
134 		uint32    flags;
135 	};
136 	static_assert(sizeof(SEGMENT_COMMAND_64) == 0x48, "Size of SEGMENT_COMMAND_64 structure must be 72 bytes.");
137 
138 	struct SECTION
139 	{
140 		char      sectionName[0x10];
141 		char      segmentName[0x10];
142 		uint32    address;
143 		uint32    size;
144 		uint32    offset;
145 		uint32    align;
146 		uint32    relocationOffset;
147 		uint32    relocationCount;
148 		uint32    flags;
149 		uint32    reserved1;
150 		uint32    reserved2;
151 	};
152 	static_assert(sizeof(SECTION) == 0x44, "Size of SECTION structure must be 68 bytes.");
153 
154 	struct SECTION_64
155 	{
156 		char      sectionName[16];
157 		char      segmentName[16];
158 		uint64    address;
159 		uint64    size;
160 		uint32    offset;
161 		uint32    align;
162 		uint32    relocationOffset;
163 		uint32    relocationCount;
164 		uint32    flags;
165 		uint32    reserved1;
166 		uint32    reserved2;
167 		uint32    reserved3;
168 	};
169 	static_assert(sizeof(SECTION_64) == 0x50, "Size of SECTION_64 structure must be 80 bytes.");
170 
171 	struct SYMTAB_COMMAND : public COMMAND
172 	{
173 		uint32    symbolsOffset;
174 		uint32    symbolCount;
175 		uint32    stringsOffset;
176 		uint32    stringsSize;
177 	};
178 	static_assert(sizeof(SYMTAB_COMMAND) == 0x18, "Size of SYMTAB_COMMAND structure must be 24 bytes.");
179 
180 	struct NLIST
181 	{
182 		uint32    stringTableIndex;
183 		uint8     type;
184 		uint8     section;
185 		uint16    desc;
186 		uint32    value;
187 	};
188 	static_assert(sizeof(NLIST) == 0xC, "Size of NLIST structure must be 12 bytes.");
189 
190 	struct NLIST_64
191 	{
192 		uint32    stringTableIndex;
193 		uint8     type;
194 		uint8     section;
195 		uint16    desc;
196 		uint64    value;
197 	};
198 	static_assert(sizeof(NLIST_64) == 0x10, "Size of NLIST_64 structure must be 16 bytes.");
199 
200 	struct RELOCATION_INFO
201 	{
202 		uint32          address;
203 		unsigned int    symbolIndex : 24;
204 		unsigned int    pcRel       : 1;
205 		unsigned int    length      : 2;
206 		unsigned int    isExtern    : 1;
207 		unsigned int    type        : 4;
208 	};
209 	static_assert(sizeof(RELOCATION_INFO) == 0x08, "Size of RELOCATION_INFO structure must be 8 bytes.");
210 }
211