1 /** 2 * Mach-O object file format 3 * 4 * Translated to D from mach.h 5 */ 6 7 module dmd.backend.mach; 8 9 // Online documentation: https://dlang.org/phobos/dmd_backend_mach.html 10 11 @safe: 12 13 alias cpu_type_t = int; 14 alias cpu_subtype_t = int; 15 alias vm_prot_t = int; 16 17 enum 18 { 19 // magic 20 MH_MAGIC = 0xfeedface, 21 MH_CIGAM = 0xcefaedfe, 22 23 // cputype 24 CPU_TYPE_I386 = cast(cpu_type_t)7, 25 CPU_TYPE_X86_64 = cast(cpu_type_t)7 | 0x1000000, 26 CPU_TYPE_POWERPC = cast(cpu_type_t)18, 27 CPU_TYPE_POWERPC64 = CPU_TYPE_POWERPC | 0x1000000, 28 29 // cpusubtype 30 CPU_SUBTYPE_POWERPC_ALL = cast(cpu_subtype_t)0, 31 CPU_SUBTYPE_I386_ALL = cast(cpu_subtype_t)3, 32 33 // filetype 34 MH_OBJECT = 1, 35 MH_EXECUTE = 2, 36 MH_BUNDLE = 8, 37 MH_DYLIB = 6, 38 MH_PRELOAD = 5, 39 MH_CORE = 4, 40 MH_DYLINKER = 7, 41 MH_DSYM = 10, 42 43 // flags 44 MH_NOUNDEFS = 1, 45 MH_INCRLINK = 2, 46 MH_DYLDLINK = 4, 47 MH_TWOLEVEL = 0x80, 48 MH_BINDATLOAD = 8, 49 MH_PREBOUND = 0x10, 50 MH_PREBINDABLE = 0x800, 51 MH_NOFIXPREBINDING = 0x400, 52 MH_ALLMODSBOUND = 0x1000, 53 MH_CANONICAL = 0x4000, 54 MH_SPLIT_SEGS = 0x20, 55 MH_FORCE_FLAT = 0x100, 56 MH_SUBSECTIONS_VIA_SYMBOLS = 0x2000, 57 MH_NOMULTIDEFS = 0x200, 58 } 59 60 struct mach_header 61 { 62 uint magic; 63 cpu_type_t cputype; 64 cpu_subtype_t cpusubtype; 65 uint filetype; 66 uint ncmds; 67 uint sizeofcmds; 68 uint flags; 69 } 70 71 enum 72 { 73 // magic 74 MH_MAGIC_64 = 0xfeedfacf, 75 MH_CIGAM_64 = 0xcffaedfe, 76 } 77 78 struct mach_header_64 79 { 80 uint magic; 81 cpu_type_t cputype; 82 cpu_subtype_t cpusubtype; 83 uint filetype; 84 uint ncmds; 85 uint sizeofcmds; 86 uint flags; 87 uint reserved; 88 } 89 90 enum 91 { 92 // cmd 93 LC_SEGMENT = 1, 94 LC_SYMTAB = 2, 95 LC_DYSYMTAB = 11, 96 LC_SEGMENT_64 = 0x19, 97 } 98 99 struct load_command 100 { 101 uint cmd; 102 uint cmdsize; 103 } 104 105 struct uuid_command 106 { 107 uint cmd; 108 uint cmdsize; 109 ubyte[16] uuid; 110 } 111 112 enum 113 { 114 // flags 115 SG_HIGHVM = 1, 116 SG_FVMLIB = 2, 117 SG_NORELOC = 4, 118 SG_PROTECTED_VERSION_1 = 8, 119 } 120 121 struct segment_command 122 { 123 uint cmd; 124 uint cmdsize; 125 char[16] segname; 126 uint vmaddr; 127 uint vmsize; 128 uint fileoff; 129 uint filesize; 130 vm_prot_t maxprot; 131 vm_prot_t initprot; 132 uint nsects; 133 uint flags; 134 } 135 136 struct segment_command_64 137 { 138 uint cmd; 139 uint cmdsize; 140 char[16] segname; 141 ulong vmaddr; 142 ulong vmsize; 143 ulong fileoff; 144 ulong filesize; 145 vm_prot_t maxprot; 146 vm_prot_t initprot; 147 uint nsects; 148 uint flags; 149 } 150 151 enum 152 { 153 // flags 154 SECTION_TYPE = 0xFF, 155 SECTION_ATTRIBUTES = 0xFFFFFF00, 156 157 S_REGULAR = 0, 158 S_ZEROFILL = 1, 159 S_CSTRING_LITERALS = 2, 160 S_4BYTE_LITERALS = 3, 161 S_8BYTE_LITERALS = 4, 162 S_LITERAL_POINTERS = 5, 163 164 S_NON_LAZY_SYMBOL_POINTERS = 6, 165 S_LAZY_SYMBOL_POINTERS = 7, 166 S_SYMBOL_STUBS = 8, 167 S_MOD_INIT_FUNC_POINTERS = 9, 168 S_MOD_TERM_FUNC_POINTERS = 10, 169 S_COALESCED = 11, 170 S_GB_ZEROFILL = 12, 171 S_INTERPOSING = 13, 172 S_16BYTE_LITERALS = 14, 173 S_DTRACE_DOF = 15, 174 175 S_THREAD_LOCAL_REGULAR = 0x11, // template of initial values for TLVs 176 S_THREAD_LOCAL_ZEROFILL = 0x12, // template of initial values for TLVs 177 S_THREAD_LOCAL_VARIABLES = 0x13, // TLV descriptors 178 179 SECTION_ATTRIBUTES_USR = 0xFF000000, 180 S_ATTR_PURE_INSTRUCTIONS = 0x80000000, 181 S_ATTR_NO_TOC = 0x40000000, 182 S_ATTR_STRIP_STATIC_SYMS = 0x20000000, 183 S_ATTR_NO_DEAD_STRIP = 0x10000000, 184 S_ATTR_LIVE_SUPPORT = 0x8000000, 185 S_ATTR_SELF_MODIFYING_CODE = 0x4000000, 186 S_ATTR_DEBUG = 0x2000000, 187 188 SECTION_ATTRIBUTES_SYS = 0xFFFF00, 189 S_ATTR_SOME_INSTRUCTIONS = 0x000400, 190 S_ATTR_EXT_RELOC = 0x000200, 191 S_ATTR_LOC_RELOC = 0x000100, 192 } 193 194 struct section 195 { 196 char[16] sectname; 197 char[16] segname; 198 uint addr; 199 uint size; 200 uint offset; 201 uint _align; 202 uint reloff; 203 uint nreloc; 204 uint flags; 205 206 uint reserved1; 207 uint reserved2; 208 } 209 210 struct section_64 211 { 212 char[16] sectname; 213 char[16] segname; 214 ulong addr; 215 ulong size; 216 uint offset; 217 uint _align; 218 uint reloff; 219 uint nreloc; 220 uint flags; 221 uint reserved1; 222 uint reserved2; 223 uint reserved3; 224 } 225 226 struct twolevel_hints_command 227 { 228 uint cmd; 229 uint cmdsize; 230 uint offset; 231 uint nhints; 232 } 233 234 struct twolevel_hint 235 { 236 version (all) 237 { 238 uint xxx; 239 } 240 else 241 { 242 // uint isub_image:8, itoc:24; 243 } 244 } 245 246 struct symtab_command 247 { 248 uint cmd; 249 uint cmdsize; 250 uint symoff; 251 uint nsyms; 252 uint stroff; 253 uint strsize; 254 } 255 256 enum 257 { 258 // n_type 259 N_EXT = 1, 260 N_STAB = 0xE0, 261 N_PEXT = 0x10, 262 N_TYPE = 0x0E, 263 N_UNDF = 0, 264 N_ABS = 2, 265 N_INDR = 10, 266 N_PBUD = 12, 267 N_SECT = 14, 268 } 269 270 enum 271 { 272 // n_desc 273 N_ARM_THUMB_DEF = 8, 274 N_NO_DEAD_STRIP = 0x20, 275 N_DESC_DISCARDED = 0x20, 276 N_WEAK_REF = 0x40, 277 N_WEAK_DEF = 0x80, 278 N_REF_TO_WEAK = 0x80, 279 N_SYMBOL_RESOLVER = 0x100, 280 } 281 282 enum 283 { 284 // n_desc 285 REFERENCE_FLAG_UNDEFINED_NON_LAZY = 0, 286 REFERENCE_FLAG_UNDEFINED_LAZY = 1, 287 REFERENCE_FLAG_DEFINED = 2, 288 REFERENCE_FLAG_PRIVATE_DEFINED = 3, 289 REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY = 4, 290 REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY = 5, 291 } 292 293 struct nlist 294 { 295 union 296 { 297 int n_strx; 298 } 299 ubyte n_type; 300 ubyte n_sect; 301 short n_desc; 302 uint n_value; 303 } 304 305 struct nlist_64 306 { 307 union 308 { 309 uint n_strx; 310 } 311 ubyte n_type; 312 ubyte n_sect; 313 ushort n_desc; 314 ulong n_value; 315 } 316 317 struct dysymtab_command 318 { 319 uint cmd; 320 uint cmdsize; 321 uint ilocalsym; 322 uint nlocalsym; 323 uint iextdefsym; 324 uint nextdefsym; 325 uint iundefsym; 326 uint nundefsym; 327 uint tocoff; 328 uint ntoc; 329 uint modtaboff; 330 uint nmodtab; 331 uint extrefsymoff; 332 uint nextrefsyms; 333 uint indirectsymoff; 334 uint nindirectsyms; 335 uint extreloff; 336 uint nextrel; 337 uint locreloff; 338 uint nlocrel; 339 } 340 341 enum 342 { 343 // r_address 344 R_SCATTERED = 0x80000000, 345 346 // r_type 347 // for i386 348 GENERIC_RELOC_VANILLA = 0, 349 GENERIC_RELOC_PAIR = 1, 350 GENERIC_RELOC_SECTDIFF = 2, 351 GENERIC_RELOC_PB_LA_PTR = 3, 352 GENERIC_RELOC_LOCAL_SECTDIFF = 4, 353 354 // for x86_64 355 X86_64_RELOC_UNSIGNED = 0, 356 X86_64_RELOC_SIGNED = 1, 357 X86_64_RELOC_BRANCH = 2, 358 X86_64_RELOC_GOT_LOAD = 3, 359 X86_64_RELOC_GOT = 4, 360 X86_64_RELOC_SUBTRACTOR = 5, 361 X86_64_RELOC_SIGNED_1 = 6, 362 X86_64_RELOC_SIGNED_2 = 7, 363 X86_64_RELOC_SIGNED_4 = 8, 364 X86_64_RELOC_TLV = 9, // for thread local variables 365 } 366 367 struct relocation_info 368 { 369 int r_address; 370 371 /* LITTLE_ENDIAN for x86 372 * uint r_symbolnum:24, 373 * r_pcrel :1, 374 * r_length :2, 375 * r_extern :1, 376 * r_type :4; 377 */ 378 uint xxx; 379 nothrow: 380 void r_symbolnum(uint r) { assert(!(r & ~0x00FF_FFFF)); xxx = (xxx & ~0x00FF_FFFF) | r; } 381 void r_pcrel (uint r) { assert(!(r & ~1)); xxx = (xxx & ~0x0100_0000) | (r << 24); } 382 void r_length (uint r) { assert(!(r & ~3)); xxx = (xxx & ~0x0600_0000) | (r << (24 + 1)); } 383 void r_extern (uint r) { assert(!(r & ~1)); xxx = (xxx & ~0x0800_0000) | (r << (24 + 1 + 2)); } 384 void r_type (uint r) { assert(!(r & ~0xF)); xxx = (xxx & ~0xF000_0000) | (r << (24 + 1 + 2 + 1)); } 385 386 uint r_pcrel() { return (xxx >> 24) & 1; } 387 } 388 389 struct scattered_relocation_info 390 { 391 /* LITTLE_ENDIAN for x86 392 * uint r_address :24, 393 * r_type :4, 394 * r_length :2, 395 * r_pcrel :1, 396 * r_scattered:1; 397 */ 398 uint xxx; 399 nothrow: 400 void r_address (uint r) { assert(!(r & ~0x00FF_FFFF)); xxx = (xxx & ~0x00FF_FFFF) | r; } 401 void r_type (uint r) { assert(!(r & ~0xF)); xxx = (xxx & ~0x0F00_0000) | (r << 24); } 402 void r_length (uint r) { assert(!(r & ~3)); xxx = (xxx & ~0x3000_0000) | (r << (24 + 4)); } 403 void r_pcrel (uint r) { assert(!(r & ~1)); xxx = (xxx & ~0x4000_0000) | (r << (24 + 4 + 2)); } 404 void r_scattered(uint r) { assert(!(r & ~1)); xxx = (xxx & ~0x8000_0000) | (r << (24 + 4 + 2 + 1)); } 405 406 uint r_pcrel() { return (xxx >> (24 + 4 + 2)) & 1; } 407 408 int r_value; 409 }