Primary MachO writing
This commit is contained in:
parent
4fe18ffaa8
commit
dacb9334e5
24
.github/workflows/ci.yml
vendored
24
.github/workflows/ci.yml
vendored
@ -18,18 +18,18 @@ jobs:
|
|||||||
- name: Build and test
|
- name: Build and test
|
||||||
run: |
|
run: |
|
||||||
./project.sh test all
|
./project.sh test all
|
||||||
# macos_build_and_test:
|
macos_build_and_test:
|
||||||
# runs-on: macos-latest
|
runs-on: macos-latest
|
||||||
# timeout-minutes: 15
|
timeout-minutes: 15
|
||||||
# steps:
|
steps:
|
||||||
# - name: Checkout
|
- name: Checkout
|
||||||
# uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
# - name: Install LLVM
|
- name: Install LLVM
|
||||||
# run: |
|
run: |
|
||||||
# brew list llvm || brew install llvm
|
brew list llvm || brew install llvm
|
||||||
# - name: Build and test
|
- name: Build and test
|
||||||
# run: |
|
run: |
|
||||||
# ./project.sh test all
|
./project.sh test all
|
||||||
windows_build_and_test:
|
windows_build_and_test:
|
||||||
runs-on: windows-latest
|
runs-on: windows-latest
|
||||||
timeout-minutes: 15
|
timeout-minutes: 15
|
||||||
|
@ -3061,6 +3061,19 @@ may_be_unused fn void run_command(Arena* arena, CStringSlice arguments, char* en
|
|||||||
if (CreateProcessA(0, bytes, 0, 0, handle_inheritance, 0, 0, 0, &startup_info, &process_information))
|
if (CreateProcessA(0, bytes, 0, 0, handle_inheritance, 0, 0, 0, &startup_info, &process_information))
|
||||||
{
|
{
|
||||||
WaitForSingleObject(process_information.hProcess, INFINITE);
|
WaitForSingleObject(process_information.hProcess, INFINITE);
|
||||||
|
DWORD exit_code;
|
||||||
|
if (GetExitCodeProcess(process_information.hProcess, &exit_code))
|
||||||
|
{
|
||||||
|
if (exit_code != 0)
|
||||||
|
{
|
||||||
|
fail();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fail();
|
||||||
|
}
|
||||||
|
|
||||||
CloseHandle(process_information.hProcess);
|
CloseHandle(process_information.hProcess);
|
||||||
CloseHandle(process_information.hThread);
|
CloseHandle(process_information.hThread);
|
||||||
}
|
}
|
||||||
@ -3233,7 +3246,6 @@ may_be_unused fn u8* vb_append_bytes(VirtualBuffer(u8*) vb, Slice(u8) bytes)
|
|||||||
#define vb_ensure_capacity(a, count) vb_generic_ensure_capacity((VirtualBuffer(u8)*)(a), sizeof(*((a)->pointer)), count)
|
#define vb_ensure_capacity(a, count) vb_generic_ensure_capacity((VirtualBuffer(u8)*)(a), sizeof(*((a)->pointer)), count)
|
||||||
#define vb_add_array(vb, arr) memcpy(vb_add(vb, sizeof(arr)), arr, sizeof(arr))
|
#define vb_add_array(vb, arr) memcpy(vb_add(vb, sizeof(arr)), arr, sizeof(arr))
|
||||||
|
|
||||||
|
|
||||||
may_be_unused fn Hash32 hash32_fib_end(Hash32 hash)
|
may_be_unused fn Hash32 hash32_fib_end(Hash32 hash)
|
||||||
{
|
{
|
||||||
auto result = truncate(Hash32, (hash * 11400714819323198485ull) >> 32);
|
auto result = truncate(Hash32, (hash * 11400714819323198485ull) >> 32);
|
||||||
|
599
bootstrap/main.c
599
bootstrap/main.c
@ -7960,10 +7960,13 @@ STRUCT(SymbolRelocation)
|
|||||||
};
|
};
|
||||||
decl_vb(SymbolRelocation);
|
decl_vb(SymbolRelocation);
|
||||||
|
|
||||||
may_be_unused fn void write_elf(Thread* thread, ObjectOptions options)
|
STRUCT(FileBuffer)
|
||||||
{
|
{
|
||||||
unused(thread);
|
VirtualBuffer(u8) buffer;
|
||||||
|
};
|
||||||
|
|
||||||
|
may_be_unused fn String write_elf(Thread* thread, ObjectOptions options)
|
||||||
|
{
|
||||||
ELFBuilder builder_stack = {};
|
ELFBuilder builder_stack = {};
|
||||||
ELFBuilder* restrict builder = &builder_stack;
|
ELFBuilder* restrict builder = &builder_stack;
|
||||||
// Initialization
|
// Initialization
|
||||||
@ -10672,17 +10675,7 @@ may_be_unused fn void write_elf(Thread* thread, ObjectOptions options)
|
|||||||
|
|
||||||
assert(dynamic_relocation_count == expected_dynamic_relocation_count);
|
assert(dynamic_relocation_count == expected_dynamic_relocation_count);
|
||||||
|
|
||||||
{
|
return (String) { builder->file.pointer, builder->file.length };
|
||||||
auto fd = os_file_open(options.exe_path, (OSFileOpenFlags) {
|
|
||||||
.write = 1,
|
|
||||||
.truncate = 1,
|
|
||||||
.create = 1,
|
|
||||||
.executable = 1,
|
|
||||||
});
|
|
||||||
assert(os_file_descriptor_is_valid(fd));
|
|
||||||
os_file_write(fd, (String) { builder->file.pointer, builder->file.length });
|
|
||||||
os_file_close(fd);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
STRUCT(DOSHeader)
|
STRUCT(DOSHeader)
|
||||||
@ -10909,7 +10902,7 @@ fn COFFSectionName coff_section_name(String name)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
may_be_unused fn void write_pe(Thread* thread, ObjectOptions options)
|
may_be_unused fn String write_pe(Thread* thread, ObjectOptions options)
|
||||||
{
|
{
|
||||||
VirtualBuffer(u8) file = {};
|
VirtualBuffer(u8) file = {};
|
||||||
auto* mz = "MZ";
|
auto* mz = "MZ";
|
||||||
@ -11138,36 +11131,7 @@ may_be_unused fn void write_pe(Thread* thread, ObjectOptions options)
|
|||||||
unused(thread);
|
unused(thread);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
{
|
return (String){ file.pointer, file.length };
|
||||||
auto fd = os_file_open(options.exe_path, (OSFileOpenFlags) {
|
|
||||||
.write = 1,
|
|
||||||
.truncate = 1,
|
|
||||||
.create = 1,
|
|
||||||
.executable = 1,
|
|
||||||
});
|
|
||||||
#if _WIN32
|
|
||||||
if (!os_file_descriptor_is_valid(fd))
|
|
||||||
{
|
|
||||||
auto err = GetLastError();
|
|
||||||
LPSTR lpMsgBuf;
|
|
||||||
DWORD bufSize = FormatMessageA(
|
|
||||||
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
|
||||||
NULL,
|
|
||||||
err,
|
|
||||||
LANG_NEUTRAL, // Use default language
|
|
||||||
(LPSTR)&lpMsgBuf,
|
|
||||||
0,
|
|
||||||
NULL
|
|
||||||
);
|
|
||||||
unused(bufSize);
|
|
||||||
print("Error opening file \"{s}\": {cstr}\n", options.exe_path, lpMsgBuf);
|
|
||||||
fail();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
assert(os_file_descriptor_is_valid(fd));
|
|
||||||
os_file_write(fd, (String) { file.pointer, file.length });
|
|
||||||
os_file_close(fd);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn void subsume_node_without_killing(Thread* thread, NodeIndex old_node_index, NodeIndex new_node_index)
|
fn void subsume_node_without_killing(Thread* thread, NodeIndex old_node_index, NodeIndex new_node_index)
|
||||||
@ -13378,12 +13342,512 @@ fn u8 operand_equal(MachineOperand a, MachineOperand b)
|
|||||||
return (a.id == MACHINE_OPERAND_GPR || a.id == MACHINE_OPERAND_XMM) ? a.register_value == b.register_value : 0;
|
return (a.id == MACHINE_OPERAND_GPR || a.id == MACHINE_OPERAND_XMM) ? a.register_value == b.register_value : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
may_be_unused fn void write_macho(Thread* restrict thread, const ObjectOptions * const restrict options, char** envp)
|
typedef enum MachOCpuType : u32
|
||||||
|
{
|
||||||
|
MACHO_CPU_X86 = 7,
|
||||||
|
MACHO_CPU_ARM = 12,
|
||||||
|
MACHO_CPU_X86_64 = MACHO_CPU_X86 | 0x1000000,
|
||||||
|
MACHO_CPU_ARM64 = MACHO_CPU_ARM | 0x1000000,
|
||||||
|
MACHO_CPU_ANY = 0xffffffff,
|
||||||
|
} MachOCpuType;
|
||||||
|
|
||||||
|
typedef enum MachOFileType : u32
|
||||||
|
{
|
||||||
|
MACHO_FILE_OBJECT = 1,
|
||||||
|
MACHO_FILE_EXECUTABLE = 2,
|
||||||
|
MACHO_FILE_FVM_LIB = 3,
|
||||||
|
MACHO_FILE_CORE = 4,
|
||||||
|
MACHO_FILE_PRELOAD = 5,
|
||||||
|
MACHO_FILE_DYLIB = 6,
|
||||||
|
MACHO_FILE_DYLINKER = 7,
|
||||||
|
MACHO_FILE_BUNDLE = 8,
|
||||||
|
MACHO_FILE_DYLIB_STUB = 9,
|
||||||
|
MACHO_FILE_DSYM = 10,
|
||||||
|
MACHO_FILE_KEXT_BUNDLE = 11,
|
||||||
|
} MachOFileType;
|
||||||
|
|
||||||
|
STRUCT(MachOFlags)
|
||||||
|
{
|
||||||
|
u32 no_undefined:1;
|
||||||
|
u32 incremental_link:1;
|
||||||
|
u32 dyld_link:1;
|
||||||
|
u32 binary_data_load:1;
|
||||||
|
u32 prebound:1;
|
||||||
|
u32 split_segments:1;
|
||||||
|
u32 lazy_init:1;
|
||||||
|
u32 two_level:1;
|
||||||
|
u32 force_flat:1;
|
||||||
|
u32 no_multi_definitions:1;
|
||||||
|
u32 no_fix_prebinding:1;
|
||||||
|
u32 prebindable:1;
|
||||||
|
u32 all_mods_bound:1;
|
||||||
|
u32 sub_sections_via_symbols:1;
|
||||||
|
u32 canonical:1;
|
||||||
|
u32 weak_defines:1;
|
||||||
|
u32 binds_to_weak:1;
|
||||||
|
u32 allow_stack_execution:1;
|
||||||
|
u32 root_safe:1;
|
||||||
|
u32 setuid_safe:1;
|
||||||
|
u32 no_reexported_dylibs:1;
|
||||||
|
u32 pie:1;
|
||||||
|
u32 dead_strippable_dylib:1;
|
||||||
|
u32 has_tlv_descriptors:1;
|
||||||
|
u32 no_heap_execution:1;
|
||||||
|
u32 app_extension_safe:1;
|
||||||
|
u32 n_list_out_of_sync_with_dyldinof:1;
|
||||||
|
u32 simulator_support:1;
|
||||||
|
u32 padding:3;
|
||||||
|
u32 dyld_cache:1;
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(sizeof(MachOFlags) == sizeof(u32));
|
||||||
|
|
||||||
|
STRUCT(MachOHeader)
|
||||||
|
{
|
||||||
|
u32 magic;
|
||||||
|
MachOCpuType cpu_type;
|
||||||
|
u32 sub_cpu_type:24;
|
||||||
|
u32 padding:7;
|
||||||
|
u32 lib64:1;
|
||||||
|
MachOFileType file_type;
|
||||||
|
u32 command_count;
|
||||||
|
u32 command_total_size;
|
||||||
|
MachOFlags flags;
|
||||||
|
u32 reserved;
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(sizeof(MachOHeader) == 0x20);
|
||||||
|
|
||||||
|
typedef enum MachOLoadCommandId : u32
|
||||||
|
{
|
||||||
|
LC_SEGMENT = 0x00000001,
|
||||||
|
LC_SYMTAB = 0x00000002,
|
||||||
|
LC_SYMSEG = 0x00000003,
|
||||||
|
LC_THREAD = 0x00000004,
|
||||||
|
LC_UNIXTHREAD = 0x00000005,
|
||||||
|
LC_LOADFVMLIB = 0x00000006,
|
||||||
|
LC_IDFVMLIB = 0x00000007,
|
||||||
|
LC_IDENT = 0x00000008,
|
||||||
|
LC_FVMFILE = 0x00000009,
|
||||||
|
LC_PREPAGE = 0x0000000A,
|
||||||
|
LC_DYSYMTAB = 0x0000000B,
|
||||||
|
LC_LOAD_DYLIB = 0x0000000C,
|
||||||
|
LC_ID_DYLIB = 0x0000000D,
|
||||||
|
LC_LOAD_DYLINKER = 0x0000000E,
|
||||||
|
LC_ID_DYLINKER = 0x0000000F,
|
||||||
|
LC_PREBOUND_DYLIB = 0x00000010,
|
||||||
|
LC_ROUTINES = 0x00000011,
|
||||||
|
LC_SUB_FRAMEWORK = 0x00000012,
|
||||||
|
LC_SUB_UMBRELLA = 0x00000013,
|
||||||
|
LC_SUB_CLIENT = 0x00000014,
|
||||||
|
LC_SUB_LIBRARY = 0x00000015,
|
||||||
|
LC_TWOLEVEL_HINTS = 0x00000016,
|
||||||
|
LC_PREBIND_CKSUM = 0x00000017,
|
||||||
|
LC_LOAD_WEAK_DYLIB = 0x80000018,
|
||||||
|
LC_SEGMENT_64 = 0x00000019,
|
||||||
|
LC_ROUTINES_64 = 0x0000001A,
|
||||||
|
LC_UUID = 0x0000001B,
|
||||||
|
LC_RPATH = 0x8000001C,
|
||||||
|
LC_CODE_SIGNATURE = 0x0000001D,
|
||||||
|
LC_SEGMENT_SPLIT_INFO = 0x0000001E,
|
||||||
|
LC_REEXPORT_DYLIB = 0x8000001F,
|
||||||
|
LC_LAZY_LOAD_DYLIB = 0x00000020,
|
||||||
|
LC_ENCRYPTION_INFO = 0x00000021,
|
||||||
|
LC_DYLD_INFO = 0x00000022,
|
||||||
|
LC_DYLD_INFO_ONLY = 0x80000022,
|
||||||
|
LC_LOAD_UPWARD_DYLIB = 0x80000023,
|
||||||
|
LC_VERSION_MIN_MACOSX = 0x00000024,
|
||||||
|
LC_VERSION_MIN_IPHONEOS = 0x00000025,
|
||||||
|
LC_FUNCTION_STARTS = 0x00000026,
|
||||||
|
LC_DYLD_ENVIRONMENT = 0x00000027,
|
||||||
|
LC_MAIN = 0x80000028,
|
||||||
|
LC_DATA_IN_CODE = 0x00000029,
|
||||||
|
LC_SOURCE_VERSION = 0x0000002A,
|
||||||
|
LC_DYLIB_CODE_SIGN_DRS = 0x0000002B,
|
||||||
|
LC_ENCRYPTION_INFO_64 = 0x0000002C,
|
||||||
|
LC_LINKER_OPTION = 0x0000002D,
|
||||||
|
LC_LINKER_OPTIMIZATION_HINT = 0x0000002E,
|
||||||
|
LC_VERSION_MIN_TVOS = 0x0000002F,
|
||||||
|
LC_VERSION_MIN_WATCHOS = 0x00000030,
|
||||||
|
LC_NOTE = 0x00000031,
|
||||||
|
LC_BUILD_VERSION = 0x00000032,
|
||||||
|
LC_DYLD_EXPORTS_TRIE = 0x80000033,
|
||||||
|
LC_DYLD_CHAINED_FIXUPS = 0x80000034,
|
||||||
|
LC_FILESET_ENTRY = 0x80000035,
|
||||||
|
LC_ATOM_INFO = 0x00000036,
|
||||||
|
} MachOLoadCommandId;
|
||||||
|
|
||||||
|
STRUCT(MachOName16)
|
||||||
|
{
|
||||||
|
u8 name[16];
|
||||||
|
};
|
||||||
|
|
||||||
|
fn MachOName16 macho_name16(String string)
|
||||||
|
{
|
||||||
|
MachOName16 result = {};
|
||||||
|
assert(string.length <= array_length(result.name));
|
||||||
|
memcpy(result.name, string.pointer, string.length);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
STRUCT(MachOSegment)
|
||||||
|
{
|
||||||
|
MachOName16 name;
|
||||||
|
u64 memory_address;
|
||||||
|
u64 memory_size;
|
||||||
|
u64 file_offset;
|
||||||
|
u64 file_size;
|
||||||
|
u32 max_protection;
|
||||||
|
u32 initial_protection;
|
||||||
|
u32 section_count;
|
||||||
|
u32 flags;
|
||||||
|
};
|
||||||
|
static_assert(sizeof(MachOSegment) == 64);
|
||||||
|
|
||||||
|
STRUCT(MachOCommand)
|
||||||
|
{
|
||||||
|
MachOLoadCommandId id;
|
||||||
|
u32 command_size;
|
||||||
|
};
|
||||||
|
static_assert(sizeof(MachOCommand) == 8);
|
||||||
|
|
||||||
|
STRUCT(MachOSection)
|
||||||
|
{
|
||||||
|
MachOName16 section_name;
|
||||||
|
MachOName16 segment_name;
|
||||||
|
u64 address;
|
||||||
|
u64 size;
|
||||||
|
u32 offset;
|
||||||
|
u32 alignment;
|
||||||
|
u32 relocation_offset;
|
||||||
|
u32 relocation_count;
|
||||||
|
u32 flags;
|
||||||
|
u8 reserved[12];
|
||||||
|
};
|
||||||
|
static_assert(sizeof(MachOSection) == 0x50);
|
||||||
|
|
||||||
|
#define vb_copy_struct(vb, s) *vb_add_struct(&file, typeof(s)) = s
|
||||||
|
|
||||||
|
may_be_unused fn String write_macho(Thread* restrict thread, ObjectOptions options)
|
||||||
{
|
{
|
||||||
unused(thread);
|
unused(thread);
|
||||||
unused(options);
|
unused(options);
|
||||||
unused(envp);
|
VirtualBuffer(u8) file = {};
|
||||||
todo();
|
MachOHeader header = {
|
||||||
|
.magic = 0xfeedfacf,
|
||||||
|
.cpu_type = MACHO_CPU_ARM64,
|
||||||
|
.file_type = MACHO_FILE_EXECUTABLE,
|
||||||
|
.command_count = 15,
|
||||||
|
.command_total_size = 688,
|
||||||
|
.flags = {
|
||||||
|
.no_undefined = 1,
|
||||||
|
.dyld_link = 1,
|
||||||
|
.two_level = 1,
|
||||||
|
.pie = 1,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
vb_copy_struct(&file, header);
|
||||||
|
|
||||||
|
MachOCommand page_zero_command = {
|
||||||
|
.id = LC_SEGMENT_64,
|
||||||
|
.command_size = sizeof(MachOCommand) + sizeof(MachOSegment),
|
||||||
|
};
|
||||||
|
vb_copy_struct(&file, page_zero_command);
|
||||||
|
|
||||||
|
MachOSegment page_zero_segment = {
|
||||||
|
.name = macho_name16(strlit("__PAGEZERO")),
|
||||||
|
.memory_size = GB(4),
|
||||||
|
};
|
||||||
|
vb_copy_struct(&file, page_zero_segment);
|
||||||
|
|
||||||
|
MachOCommand text_command = {
|
||||||
|
.id = LC_SEGMENT_64,
|
||||||
|
.command_size = 232,
|
||||||
|
};
|
||||||
|
vb_copy_struct(&file, text_command);
|
||||||
|
|
||||||
|
MachOSection text_section = {
|
||||||
|
.section_name = macho_name16(strlit("__text")),
|
||||||
|
.segment_name = macho_name16(strlit("__TEXT")),
|
||||||
|
.address = 0x100003fa0,
|
||||||
|
.size = 8,
|
||||||
|
.offset = 16288,
|
||||||
|
.alignment = 2,
|
||||||
|
.relocation_offset = 0,
|
||||||
|
.relocation_count = 0,
|
||||||
|
.flags = 0x80000400,
|
||||||
|
};
|
||||||
|
|
||||||
|
MachOSection unwind_info_section = {
|
||||||
|
.section_name = macho_name16(strlit("__unwind_info")),
|
||||||
|
.segment_name = macho_name16(strlit("__TEXT")),
|
||||||
|
.address = 0x100003fa8,
|
||||||
|
.size = 88,
|
||||||
|
.offset = 16296,
|
||||||
|
.alignment = 2,
|
||||||
|
.relocation_offset = 0,
|
||||||
|
.relocation_count = 0,
|
||||||
|
.flags = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
MachOSegment text_segment = {
|
||||||
|
.name = macho_name16(strlit("__TEXT")),
|
||||||
|
.memory_address = GB(4),
|
||||||
|
.memory_size = KB(16),
|
||||||
|
.file_offset = 0,
|
||||||
|
.file_size = KB(16),
|
||||||
|
.max_protection = 5,
|
||||||
|
.initial_protection = 5,
|
||||||
|
.section_count = 2,
|
||||||
|
.flags = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
vb_copy_struct(&file, text_segment);
|
||||||
|
|
||||||
|
assert(file.length == 0xb0);
|
||||||
|
vb_copy_struct(&file, text_section);
|
||||||
|
vb_align(&file, 0x10);
|
||||||
|
vb_copy_struct(&file, unwind_info_section);
|
||||||
|
|
||||||
|
MachOCommand linkedit_command = {
|
||||||
|
.id = LC_SEGMENT_64,
|
||||||
|
.command_size = sizeof(MachOCommand) + sizeof(MachOSegment),
|
||||||
|
};
|
||||||
|
vb_copy_struct(&file, linkedit_command);
|
||||||
|
|
||||||
|
MachOSegment linkedit_segment = {
|
||||||
|
.name = macho_name16(strlit("__LINKEDIT")),
|
||||||
|
.memory_address = 0x100004000,
|
||||||
|
.memory_size = KB(16),
|
||||||
|
.file_offset = KB(16),
|
||||||
|
.file_size = 688,
|
||||||
|
.max_protection = 1,
|
||||||
|
.initial_protection = 1,
|
||||||
|
.section_count = 0,
|
||||||
|
.flags = 0,
|
||||||
|
};
|
||||||
|
vb_copy_struct(&file, linkedit_segment);
|
||||||
|
|
||||||
|
MachOCommand chained_fixups_command = {
|
||||||
|
.id = LC_DYLD_CHAINED_FIXUPS,
|
||||||
|
.command_size = 16,
|
||||||
|
};
|
||||||
|
vb_copy_struct(&file, chained_fixups_command);
|
||||||
|
|
||||||
|
{
|
||||||
|
u8 blob[] = { 0x00, 0x40, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, };
|
||||||
|
vb_add_array(&file, blob);
|
||||||
|
}
|
||||||
|
|
||||||
|
MachOCommand exports_trie_command = {
|
||||||
|
.id = LC_DYLD_EXPORTS_TRIE,
|
||||||
|
.command_size = 16,
|
||||||
|
};
|
||||||
|
vb_copy_struct(&file, exports_trie_command);
|
||||||
|
|
||||||
|
{
|
||||||
|
u8 blob[] = { 0x38, 0x40, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, };
|
||||||
|
vb_add_array(&file, blob);
|
||||||
|
}
|
||||||
|
|
||||||
|
MachOCommand symtab_command = {
|
||||||
|
.id = LC_SYMTAB,
|
||||||
|
.command_size = 24,
|
||||||
|
};
|
||||||
|
vb_copy_struct(&file, symtab_command);
|
||||||
|
|
||||||
|
{
|
||||||
|
u8 blob[] = { 0x70, 0x40, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x20, 0x41, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, };
|
||||||
|
vb_add_array(&file, blob);
|
||||||
|
}
|
||||||
|
|
||||||
|
MachOCommand dysymtab_command = {
|
||||||
|
.id = LC_DYSYMTAB,
|
||||||
|
.command_size = 80,
|
||||||
|
};
|
||||||
|
vb_copy_struct(&file, dysymtab_command);
|
||||||
|
|
||||||
|
{
|
||||||
|
u8 blob[] = {
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
|
||||||
|
0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||||
|
};
|
||||||
|
vb_add_array(&file, blob);
|
||||||
|
}
|
||||||
|
|
||||||
|
MachOCommand load_dylinker_command = {
|
||||||
|
.id = LC_LOAD_DYLINKER,
|
||||||
|
.command_size = 32,
|
||||||
|
};
|
||||||
|
vb_copy_struct(&file, load_dylinker_command);
|
||||||
|
|
||||||
|
{
|
||||||
|
u8 blob[] = { 0x0C, 0x00, 0x00, 0x00, 0x2F, 0x75, 0x73, 0x72, 0x2F, 0x6C, 0x69, 0x62, 0x2F, 0x64, 0x79, 0x6C, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, };
|
||||||
|
vb_add_array(&file, blob);
|
||||||
|
}
|
||||||
|
|
||||||
|
MachOCommand uuid_command = {
|
||||||
|
.id = LC_UUID,
|
||||||
|
.command_size = 24,
|
||||||
|
};
|
||||||
|
vb_copy_struct(&file, uuid_command);
|
||||||
|
|
||||||
|
{
|
||||||
|
u8 uuid[] = { 0x9C, 0x6F, 0xC9, 0x12, 0xED, 0x7F, 0x39, 0x3A, 0x99, 0xA7, 0x93, 0x4B, 0xF6, 0xD1, 0x4D, 0xA1, };
|
||||||
|
vb_add_array(&file, uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
MachOCommand build_version_command = {
|
||||||
|
.id = LC_BUILD_VERSION,
|
||||||
|
.command_size = 32,
|
||||||
|
};
|
||||||
|
vb_copy_struct(&file, build_version_command);
|
||||||
|
|
||||||
|
{
|
||||||
|
u8 blob[] = { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x07, 0x5B, 0x04, };
|
||||||
|
vb_add_array(&file, blob);
|
||||||
|
}
|
||||||
|
|
||||||
|
MachOCommand source_version_command = {
|
||||||
|
.id = LC_SOURCE_VERSION,
|
||||||
|
.command_size = 16,
|
||||||
|
};
|
||||||
|
vb_copy_struct(&file, source_version_command);
|
||||||
|
|
||||||
|
{
|
||||||
|
u8 blob[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, };
|
||||||
|
vb_add_array(&file, blob);
|
||||||
|
}
|
||||||
|
|
||||||
|
MachOCommand main_command = {
|
||||||
|
.id = LC_MAIN,
|
||||||
|
.command_size = 24,
|
||||||
|
};
|
||||||
|
vb_copy_struct(&file, main_command);
|
||||||
|
|
||||||
|
{
|
||||||
|
u8 blob[] = { 0xA0, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, };
|
||||||
|
vb_add_array(&file, blob);
|
||||||
|
}
|
||||||
|
|
||||||
|
MachOCommand function_starts_command = {
|
||||||
|
.id = LC_FUNCTION_STARTS,
|
||||||
|
.command_size = 16,
|
||||||
|
};
|
||||||
|
vb_copy_struct(&file, function_starts_command);
|
||||||
|
|
||||||
|
{
|
||||||
|
u8 blob[] = { 0x68, 0x40, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, };
|
||||||
|
vb_add_array(&file, blob);
|
||||||
|
}
|
||||||
|
|
||||||
|
MachOCommand data_in_code_command = {
|
||||||
|
.id = LC_DATA_IN_CODE,
|
||||||
|
.command_size = 16,
|
||||||
|
};
|
||||||
|
vb_copy_struct(&file, data_in_code_command);
|
||||||
|
{
|
||||||
|
u8 blob[] = { 0x70, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, };
|
||||||
|
vb_add_array(&file, blob);
|
||||||
|
}
|
||||||
|
|
||||||
|
MachOCommand code_signature_command = {
|
||||||
|
.id = LC_CODE_SIGNATURE,
|
||||||
|
.command_size = 16,
|
||||||
|
};
|
||||||
|
vb_copy_struct(&file, code_signature_command);
|
||||||
|
|
||||||
|
{
|
||||||
|
u8 blob[] = {
|
||||||
|
0x90, 0x41, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00,
|
||||||
|
};
|
||||||
|
vb_add_array(&file, blob);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pad
|
||||||
|
unused(vb_add(&file, text_section.offset - file.length));
|
||||||
|
|
||||||
|
u8 text_section_content[] = { 0x00, 0x00, 0x80, 0x52, 0xC0, 0x03, 0x5F, 0xD6, };
|
||||||
|
vb_add_array(&file, text_section_content);
|
||||||
|
|
||||||
|
u8 unwind_info_section_content[] = {
|
||||||
|
0x01, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xA0, 0x3F, 0x00, 0x00,
|
||||||
|
0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0xA8, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x03, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x01, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
};
|
||||||
|
vb_add_array(&file, unwind_info_section_content);
|
||||||
|
|
||||||
|
vb_align(&file, 0x4000);
|
||||||
|
|
||||||
|
u8 linkedit_segment_content[] = {
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x5F, 0x00, 0x12, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0xA0, 0x7F, 0x00, 0x00, 0x02, 0x5F, 0x6D, 0x68, 0x5F,
|
||||||
|
0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x5F, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x00, 0x09,
|
||||||
|
0x6D, 0x61, 0x69, 0x6E, 0x00, 0x0D, 0x00, 0x00, 0xA0, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x01, 0x00, 0x00, 0x00, 0x64, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x1C, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x32, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x42, 0x00, 0x00, 0x00, 0x66, 0x00, 0x01, 0x00, 0xC1, 0x6A, 0x00, 0x67, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x01, 0x00, 0x00, 0x00, 0x2E, 0x01, 0x00, 0x00, 0xA0, 0x3F, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||||
|
0x16, 0x00, 0x00, 0x00, 0x24, 0x01, 0x00, 0x00, 0xA0, 0x3F, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||||
|
0x01, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x01, 0x00, 0x00, 0x00, 0x4E, 0x01, 0x00, 0x00, 0xA0, 0x3F, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||||
|
0x01, 0x00, 0x00, 0x00, 0x64, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x02, 0x00, 0x00, 0x00, 0x0F, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||||
|
0x16, 0x00, 0x00, 0x00, 0x0F, 0x01, 0x00, 0x00, 0xA0, 0x3F, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||||
|
0x20, 0x00, 0x5F, 0x5F, 0x6D, 0x68, 0x5F, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x5F, 0x68,
|
||||||
|
0x65, 0x61, 0x64, 0x65, 0x72, 0x00, 0x5F, 0x6D, 0x61, 0x69, 0x6E, 0x00, 0x2F, 0x55, 0x73, 0x65,
|
||||||
|
0x72, 0x73, 0x2F, 0x64, 0x61, 0x76, 0x69, 0x64, 0x2F, 0x6D, 0x69, 0x6E, 0x69, 0x6D, 0x61, 0x6C,
|
||||||
|
0x2F, 0x00, 0x6D, 0x69, 0x6E, 0x69, 0x6D, 0x61, 0x6C, 0x5F, 0x6D, 0x61, 0x63, 0x6F, 0x73, 0x2E,
|
||||||
|
0x63, 0x00, 0x2F, 0x55, 0x73, 0x65, 0x72, 0x73, 0x2F, 0x64, 0x61, 0x76, 0x69, 0x64, 0x2F, 0x6D,
|
||||||
|
0x69, 0x6E, 0x69, 0x6D, 0x61, 0x6C, 0x2F, 0x6D, 0x69, 0x6E, 0x69, 0x6D, 0x61, 0x6C, 0x5F, 0x6D,
|
||||||
|
0x61, 0x63, 0x6F, 0x73, 0x2E, 0x6F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0xFA, 0xDE, 0x0C, 0xC0, 0x00, 0x00, 0x01, 0x1A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x14, 0xFA, 0xDE, 0x0C, 0x02, 0x00, 0x00, 0x01, 0x06, 0x00, 0x02, 0x04, 0x00,
|
||||||
|
0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x41, 0x90, 0x20, 0x02, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x6D, 0x69, 0x6E, 0x69,
|
||||||
|
0x6D, 0x61, 0x6C, 0x5F, 0x6D, 0x61, 0x63, 0x6F, 0x73, 0x00, 0x29, 0x0B, 0x00, 0xDF, 0x14, 0xC1,
|
||||||
|
0xD7, 0x61, 0x76, 0xD6, 0xF1, 0xC4, 0x26, 0x31, 0xFC, 0xD7, 0x84, 0x22, 0x15, 0x80, 0xEB, 0xF4,
|
||||||
|
0x62, 0x35, 0xD2, 0xC9, 0xF0, 0xE4, 0xA7, 0x6B, 0x9E, 0x1D, 0xAD, 0x7F, 0xAC, 0xB2, 0x58, 0x6F,
|
||||||
|
0xC6, 0xE9, 0x66, 0xC0, 0x04, 0xD7, 0xD1, 0xD1, 0x6B, 0x02, 0x4F, 0x58, 0x05, 0xFF, 0x7C, 0xB4,
|
||||||
|
0x7C, 0x7A, 0x85, 0xDA, 0xBD, 0x8B, 0x48, 0x89, 0x2C, 0xA7, 0xAD, 0x7F, 0xAC, 0xB2, 0x58, 0x6F,
|
||||||
|
0xC6, 0xE9, 0x66, 0xC0, 0x04, 0xD7, 0xD1, 0xD1, 0x6B, 0x02, 0x4F, 0x58, 0x05, 0xFF, 0x7C, 0xB4,
|
||||||
|
0x7C, 0x7A, 0x85, 0xDA, 0xBD, 0x8B, 0x48, 0x89, 0x2C, 0xA7, 0xB2, 0x8A, 0x42, 0xCA, 0x3E, 0x6B,
|
||||||
|
0xB1, 0x77, 0x13, 0x4F, 0xAB, 0xB6, 0xBD, 0xE2, 0x2E, 0xFD, 0xD4, 0x30, 0x73, 0x08, 0x83, 0x9F,
|
||||||
|
0xEC, 0x51, 0x51, 0x2E, 0xCD, 0x15, 0xD0, 0xA2, 0x37, 0x03, 0x4F, 0x6C, 0xF0, 0xCF, 0x98, 0xAE,
|
||||||
|
0x46, 0xE9, 0x51, 0x8A, 0x78, 0xC3, 0x8A, 0x49, 0xF4, 0xA0, 0xBC, 0x62, 0x94, 0x68, 0xFD, 0xDE,
|
||||||
|
0xA6, 0x9A, 0x08, 0xAD, 0x02, 0xF7, 0x1C, 0xD4, 0x19, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
};
|
||||||
|
|
||||||
|
vb_add_array(&file, linkedit_segment_content);
|
||||||
|
|
||||||
|
#define CHECK 0
|
||||||
|
#if CHECK
|
||||||
|
auto foo = file_read(thread->arena, strlit("C:/Users/David/dev/minimal_macos/minimal_macos"));
|
||||||
|
assert(file.length == foo.length);
|
||||||
|
|
||||||
|
for (u32 i = 0; i < file.length; i += 1)
|
||||||
|
{
|
||||||
|
auto mine = file.pointer[i];
|
||||||
|
auto original = foo.pointer[i];
|
||||||
|
assert(mine == original);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return (String) { file.pointer, file.length };
|
||||||
}
|
}
|
||||||
|
|
||||||
fn void code_generation(Thread* restrict thread, CodegenOptions options)
|
fn void code_generation(Thread* restrict thread, CodegenOptions options)
|
||||||
@ -14179,21 +14643,54 @@ fn void code_generation(Thread* restrict thread, CodegenOptions options)
|
|||||||
case COMPILER_BACKEND_MACHINE:
|
case COMPILER_BACKEND_MACHINE:
|
||||||
{
|
{
|
||||||
auto code_slice = (Slice(u8)) { .pointer = code.pointer, .length = code.length, };
|
auto code_slice = (Slice(u8)) { .pointer = code.pointer, .length = code.length, };
|
||||||
auto object_options = (ObjectOptions) {
|
auto options = (ObjectOptions) {
|
||||||
.object_path = object_path,
|
.object_path = object_path,
|
||||||
.exe_path = exe_path,
|
.exe_path = exe_path,
|
||||||
.code = code_slice,
|
.code = code_slice,
|
||||||
.dynamic = 1,
|
.dynamic = 1,
|
||||||
};
|
};
|
||||||
|
String executable =
|
||||||
#if _WIN32
|
#if _WIN32
|
||||||
write_pe(thread, object_options);
|
write_pe(thread, options);
|
||||||
#elif defined(__APPLE__)
|
#elif defined(__APPLE__)
|
||||||
write_macho(thread, object_options, envp);
|
write_macho(thread, options);
|
||||||
#elif defined(__linux__)
|
#elif defined(__linux__)
|
||||||
write_elf(thread, object_options);
|
write_elf(thread, options);
|
||||||
#else
|
#else
|
||||||
todo();
|
todo();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
{
|
||||||
|
auto fd = os_file_open(options.exe_path, (OSFileOpenFlags) {
|
||||||
|
.write = 1,
|
||||||
|
.truncate = 1,
|
||||||
|
.create = 1,
|
||||||
|
.executable = 1,
|
||||||
|
});
|
||||||
|
#if _WIN32
|
||||||
|
if (!os_file_descriptor_is_valid(fd))
|
||||||
|
{
|
||||||
|
auto err = GetLastError();
|
||||||
|
LPSTR lpMsgBuf;
|
||||||
|
DWORD bufSize = FormatMessageA(
|
||||||
|
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||||
|
NULL,
|
||||||
|
err,
|
||||||
|
LANG_NEUTRAL, // Use default language
|
||||||
|
(LPSTR)&lpMsgBuf,
|
||||||
|
0,
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
unused(bufSize);
|
||||||
|
print("Error opening file \"{s}\": {cstr}\n", options.exe_path, lpMsgBuf);
|
||||||
|
fail();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
assert(os_file_descriptor_is_valid(fd));
|
||||||
|
os_file_write(fd, (String) { executable.pointer, executable.length });
|
||||||
|
os_file_close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user