Commit e4b3da2720
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;
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;
+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(.link, "flushing. no_entry_point_found = true\n", .{});
+ self.error_flags.no_entry_point_found = true;
+ } else {
+ log.debug(.link, "flushing. no_entry_point_found = false\n", .{});
+ self.error_flags.no_entry_point_found = false;
+ try self.writeMachOHeader();
+ }
+}
pub fn deinit(self: *MachO) void {}
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,