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