segmentcmds[0] = (struct segment_command_64){ .cmd = LC_SEGMENT_64, .cmdsize = sizeof(segmentcmds[0]) + sizeof(section0s), .segname = SEG_PAGEZERO, .vmaddr = 0, .vmsize = vmaddr, .fileoff = 0, .filesize = 0, .maxprot = VM_PROT_NONE, .initprot = VM_PROT_NONE, .nsects = ARRAYSIZE(section0s), .flags = 0, }; segmentcmds[1] = (struct segment_command_64){ .cmd = LC_SEGMENT_64, .cmdsize = sizeof(segmentcmds[1]) + sizeof(section1s), .segname = SEG_TEXT, .vmaddr = vmaddr + text_start_off, .vmsize = ALIGN(text_total_size, PAGE_SIZE), .fileoff = text_start_off, .filesize = ALIGN(text_total_size, PAGE_SIZE), .maxprot = VM_PROT_EXECUTE | VM_PROT_READ, .initprot = VM_PROT_EXECUTE | VM_PROT_READ, .nsects = ARRAYSIZE(section1s), .flags = 0, }; segmentcmds[2] = (struct segment_command_64){ .cmd = LC_SEGMENT_64, .cmdsize = sizeof(segmentcmds[2]) + sizeof(section2s), .segname = "__DATA_CONST", .vmaddr = vmaddr + data_start_off, .vmsize = ALIGN(data_total_size, PAGE_SIZE), .fileoff = data_start_off, .filesize = ALIGN(data_total_size, PAGE_SIZE), .maxprot = VM_PROT_WRITE | VM_PROT_READ, .initprot = VM_PROT_WRITE | VM_PROT_READ, .nsects = ARRAYSIZE(section2s), .flags = SG_READ_ONLY, }; uint64_t linkedit_total_size = sizeof(dyld_chained_fixups); #ifdef OUTPUT_SYMBTAB linkedit_total_size += sizeof(symbols) + sizeof(indirectsym) + sizeof(symstring); #endif segmentcmds[3] = (struct segment_command_64){ .cmd = LC_SEGMENT_64, .cmdsize = sizeof(segmentcmds[3]) + sizeof(section3s), .segname = SEG_LINKEDIT, .vmaddr = vmaddr + linkedit_start_off, .vmsize = ALIGN(linkedit_total_size, PAGE_SIZE), .fileoff = linkedit_start_off, .filesize = linkedit_total_size, .maxprot = VM_PROT_READ, .initprot = VM_PROT_READ, .nsects = ARRAYSIZE(section3s), .flags = 0, }; const uint32_t dyld_chained_fixups_off = linkedit_start_off; dyldchainedfixupcmd = (struct linkedit_data_command){ .cmd = LC_DYLD_CHAINED_FIXUPS, .cmdsize = sizeof(dyldchainedfixupcmd), .dataoff = dyld_chained_fixups_off, .datasize = sizeof(dyld_chained_fixups), }; const uint32_t symtab_off = dyld_chained_fixups_off + sizeof(dyld_chained_fixups); #ifdef OUTPUT_SYMBTAB const uint32_t indirectsym_off = symtab_off + sizeof(symbols); const uint32_t symstring_off = indirectsym_off + sizeof(indirectsym); symtabcmd = (struct symtab_command){ .cmd = LC_SYMTAB, .cmdsize = sizeof(symtabcmd), .symoff = symtab_off, .nsyms = ARRAYSIZE(symbols), .stroff = symstring_off, .strsize = sizeof(symstring), }; dysymtabcmd = (struct dysymtab_command){ .cmd = LC_DYSYMTAB, .cmdsize = sizeof(dysymtabcmd), .ilocalsym = 0, .nlocalsym = nlocalsym, .iextdefsym = 0 + nlocalsym, .nextdefsym = nextdefsym, .iundefsym = 0 + nlocalsym + nextdefsym, .nundefsym = nundefsym, .tocoff = 0x00000000, .ntoc = 0x00000000, .modtaboff = 0x00000000, .nmodtab = 0x00000000, .extrefsymoff = 0x00000000, .nextrefsyms = 0x00000000, .indirectsymoff = indirectsym_off, .nindirectsyms = ARRAYSIZE(indirectsym), .extreloff = 0x00000000, .nextrel = 0x00000000, .locreloff = 0x00000000, .nlocrel = 0x00000000, }; #endif loaddylinkercmd = (struct dylinker_command){ .cmd = LC_LOAD_DYLINKER, .cmdsize = sizeof(loaddylinkercmd) + sizeof(dylinker_name), .name = sizeof(loaddylinkercmd), }; entrypointcmd = (struct entry_point_command){ .cmd = LC_MAIN, .cmdsize = sizeof(entrypointcmd), .entryoff = entryoff, .stacksize = 0x0000000000000000, }; loaddyldcmd = (struct dylib_command){ .cmd = LC_LOAD_DYLIB, .cmdsize = sizeof(loaddyldcmd) + sizeof(loaddylib_name), { .name = sizeof(struct dylib_command), .timestamp = 0x00000002, .current_version = 0x05470000, .compatibility_version = 0x00010000, }, };
header = (struct mach_header_64){ .magic = MH_MAGIC_64, .cputype = CPU_TYPE_ARM64, .cpusubtype = 0, .filetype = MH_EXECUTE, .ncmds = ARRAYSIZE(load_commands), .sizeofcmds = sizeofcmds, .flags = MH_NOUNDEFS | MH_DYLDLINK | MH_TWOLEVEL | MH_PIE, };
|