#include <mach-o/loader.h> #include <mach-o/nlist.h> #include <mach-o/reloc.h> #include <mach-o/arm64/reloc.h> #include <string.h> #include <unistd.h>
int main(void) { static const uint32_t CODE[10] = { 0xa9bf7bfd, 0xd28001c2, 0x90000001, 0x91000021, 0x52800020, 0x94000000, 0x2a1f03e0, 0xa8c17bfd, 0xd65f03c0, };
static const char RODATA[16] = "Hello, world!\n";
static const char strtab[] = "\0" "_main\0" "msg\0" "_write\0"; int null_nameofs = 0; int main_nameofs = null_nameofs + strlen("") + 1; int msg_nameofs = main_nameofs + strlen("_main") + 1; int write_nameofs = msg_nameofs + strlen("msg") + 1;
struct mach_header_64 header; struct segment_command_64 segmentcmd; struct build_version_command buildversioncmd; struct symtab_command symtabcmd; struct section_64 sections[2]; struct nlist_64 symbols[3]; struct relocation_info relocs[3];
uint32_t size_of_cmds = sizeof(segmentcmd) + sizeof(sections) + sizeof(buildversioncmd) + sizeof(symtabcmd); uint64_t text_start_addr = 0; uint64_t text_start_off = sizeof(header) + size_of_cmds; uint64_t rodata_start_addr = sizeof(CODE); uint64_t rodata_start_off = text_start_off + sizeof(CODE); uint64_t reloc_start_off = rodata_start_off + sizeof(RODATA); uint64_t symbol_start_off = reloc_start_off + sizeof(relocs); uint64_t str_start_off = symbol_start_off + sizeof(symbols);
sections[0] = (struct section_64){ .sectname = "__text", .segname = "__TEXT", .addr = text_start_addr, .size = sizeof(CODE), .offset = text_start_off, .align = 2, .reloff = reloc_start_off, .nreloc = sizeof(relocs) / sizeof(*relocs), .flags = S_ATTR_PURE_INSTRUCTIONS | S_ATTR_SOME_INSTRUCTIONS, }; sections[1] = (struct section_64){ .sectname = "__const", .segname = "__DATA", .addr = rodata_start_addr, .size = sizeof(RODATA), .offset = rodata_start_off, .align = 0, .reloff = 0, .nreloc = 0, .flags = 0, };
symbols[0] = (struct nlist_64){ .n_un = { main_nameofs }, .n_type = N_SECT | N_EXT, .n_sect = 1, .n_desc = 0, .n_value = text_start_addr, }; symbols[1] = (struct nlist_64){ .n_un = { msg_nameofs }, .n_type = N_SECT, .n_sect = 2, .n_desc = 0, .n_value = rodata_start_addr, }; symbols[2] = (struct nlist_64){ .n_un = { write_nameofs }, .n_type = N_EXT, .n_sect = 0, .n_desc = 0, .n_value = 0, };
relocs[0] = (struct relocation_info){ .r_address = 0x000008, .r_symbolnum = 1, .r_pcrel = 1, .r_length = 2, .r_extern = 1, .r_type = ARM64_RELOC_PAGE21, }; relocs[1] = (struct relocation_info){ .r_address = 0x00000c, .r_symbolnum = 1, .r_pcrel = 0, .r_length = 2, .r_extern = 1, .r_type = ARM64_RELOC_PAGEOFF12, }; relocs[2] = (struct relocation_info){ .r_address = 0x000014, .r_symbolnum = 2, .r_pcrel = 1, .r_length = 2, .r_extern = 1, .r_type = ARM64_RELOC_BRANCH26, };
header = (struct mach_header_64){ .magic = MH_MAGIC_64, .cputype = CPU_TYPE_ARM64, .cpusubtype = 0, .filetype = MH_OBJECT, .ncmds = 3, .sizeofcmds = size_of_cmds, .flags = MH_SUBSECTIONS_VIA_SYMBOLS, }; segmentcmd = (struct segment_command_64){ .cmd = LC_SEGMENT_64, .cmdsize = sizeof(segmentcmd) + sizeof(sections), .segname = "", .vmaddr = 0, .vmsize = sizeof(CODE) + sizeof(RODATA), .fileoff = text_start_off, .filesize = sizeof(CODE) + sizeof(RODATA), .maxprot = 7, .initprot = 7, .nsects = sizeof(sections) / sizeof(*sections), .flags = 0, }; buildversioncmd = (struct build_version_command){ .cmd = LC_BUILD_VERSION, .cmdsize = sizeof(buildversioncmd), .platform = PLATFORM_MACOS, .minos = 0x000e0000, .sdk = 0x000e0500, .ntools = 0, }; symtabcmd = (struct symtab_command){ .cmd = LC_SYMTAB, .cmdsize = sizeof(symtabcmd), .symoff = symbol_start_off, .nsyms = sizeof(symbols) / sizeof(*symbols), .stroff = str_start_off, .strsize = sizeof(strtab), };
int fd = STDOUT_FILENO; write(fd, &header, sizeof(header)); write(fd, &segmentcmd, sizeof(segmentcmd)); write(fd, sections, sizeof(sections)); write(fd, &buildversioncmd, sizeof(buildversioncmd)); write(fd, &symtabcmd, sizeof(symtabcmd)); write(fd, &CODE, sizeof(CODE)); write(fd, &RODATA, sizeof(RODATA)); write(fd, &relocs, sizeof(relocs)); write(fd, &symbols, sizeof(symbols)); write(fd, &strtab, sizeof(strtab));
return 0; }
|