diff options
| -rw-r--r-- | lib/std/macho.zig | 12 | ||||
| -rw-r--r-- | src-self-hosted/link.zig | 1 | ||||
| -rw-r--r-- | src-self-hosted/link/MachO.zig | 74 |
3 files changed, 83 insertions, 4 deletions
diff --git a/lib/std/macho.zig b/lib/std/macho.zig index a499a93675..950283b59f 100644 --- a/lib/std/macho.zig +++ b/lib/std/macho.zig @@ -703,3 +703,15 @@ pub const cpu_type_t = integer_t; pub const cpu_subtype_t = integer_t; pub const integer_t = c_int; pub const vm_prot_t = c_int; + +/// CPU type targeting 64-bit Intel-based Macs +pub const CPU_TYPE_X86_64: cpu_type_t = 0x01000007; + +/// CPU type targeting 64-bit ARM-based Macs +pub const CPU_TYPE_ARM64: cpu_type_t = 0x0100000C; + +/// All Intel-based Macs +pub const CPU_SUBTYPE_X86_64_ALL: cpu_subtype_t = 0x3; + +/// All ARM-based Macs +pub const CPU_SUBTYPE_ARM_ALL: cpu_subtype_t = 0x0; diff --git a/src-self-hosted/link.zig b/src-self-hosted/link.zig index 2f786609b7..39e6d27c58 100644 --- a/src-self-hosted/link.zig +++ b/src-self-hosted/link.zig @@ -40,7 +40,6 @@ pub const Options = struct { program_code_size_hint: u64 = 256 * 1024, }; - pub const File = struct { pub const LinkBlock = union { elf: Elf.TextBlock, diff --git a/src-self-hosted/link/MachO.zig b/src-self-hosted/link/MachO.zig index 49e365d203..e2a84d8ceb 100644 --- a/src-self-hosted/link/MachO.zig +++ b/src-self-hosted/link/MachO.zig @@ -4,6 +4,8 @@ const std = @import("std"); const Allocator = std.mem.Allocator; const assert = std.debug.assert; const fs = std.fs; +const log = std.log.scoped(.link); +const macho = std.macho; const Module = @import("../Module.zig"); const link = @import("../link.zig"); @@ -13,6 +15,8 @@ pub const base_tag: Tag = File.Tag.macho; base: File, +entry_addr: ?u64 = null, + error_flags: File.ErrorFlags = File.ErrorFlags{}, pub const TextBlock = struct { @@ -67,13 +71,77 @@ fn openFile(allocator: *Allocator, file: fs.File, options: link.Options) !MachO /// Returns an error if `file` is not already open with +read +write +seek abilities. fn createFile(allocator: *Allocator, file: fs.File, options: link.Options) !MachO { switch (options.output_mode) { - .Exe => return error.TODOImplementWritingMachOExeFiles, - .Obj => return error.TODOImplementWritingMachOObjFiles, + .Exe => {}, + .Obj => {}, .Lib => return error.TODOImplementWritingLibFiles, } + + var self: MachO = .{ + .base = .{ + .file = file, + .tag = .macho, + .options = options, + .allocator = allocator, + }, + }; + errdefer self.deinit(); + + return self; } -pub fn flush(self: *MachO, module: *Module) !void {} +fn writeMachOHeader(self: *MachO) !void { + var hdr: macho.mach_header_64 = undefined; + hdr.magic = macho.MH_MAGIC_64; + + const CpuInfo = struct { + cpu_type: macho.cpu_type_t, + cpu_subtype: macho.cpu_subtype_t, + }; + + const cpu_info: CpuInfo = switch (self.base.options.target.cpu.arch) { + .aarch64 => .{ + .cpu_type = macho.CPU_TYPE_ARM64, + .cpu_subtype = macho.CPU_SUBTYPE_ARM_ALL, + }, + .x86_64 => .{ + .cpu_type = macho.CPU_TYPE_X86_64, + .cpu_subtype = macho.CPU_SUBTYPE_X86_64_ALL, + }, + else => return error.UnsupportedMachOArchitecture, + }; + hdr.cputype = cpu_info.cpu_type; + hdr.cpusubtype = cpu_info.cpu_subtype; + + const filetype: u32 = switch (self.base.options.output_mode) { + .Exe => macho.MH_EXECUTE, + .Obj => macho.MH_OBJECT, + .Lib => switch (self.base.options.link_mode) { + .Static => return error.TODOStaticLibMachOType, + .Dynamic => macho.MH_DYLIB, + }, + }; + hdr.filetype = filetype; + + // TODO the rest of the header + hdr.ncmds = 0; + hdr.sizeofcmds = 0; + hdr.flags = 0; + hdr.reserved = 0; + + try self.base.file.?.pwriteAll(@ptrCast([*]const u8, &hdr)[0..@sizeOf(macho.mach_header_64)], 0); +} + +pub fn flush(self: *MachO, module: *Module) !void { + // TODO implement flush + if (self.entry_addr == null and self.base.options.output_mode == .Exe) { + log.debug("flushing. no_entry_point_found = true\n", .{}); + self.error_flags.no_entry_point_found = true; + } else { + log.debug("flushing. no_entry_point_found = false\n", .{}); + self.error_flags.no_entry_point_found = false; + try self.writeMachOHeader(); + } +} pub fn deinit(self: *MachO) void {} |
