mirror of
https://github.com/ziglang/zig.git
synced 2026-01-20 22:35:24 +00:00
Write out Mach-O header
This commit write out Mach-O header in the linker's `flush` method. The header currently only populates the magic number, filetype, and cpu info. Signed-off-by: Jakub Konka <kubkon@jakubkonka.com>
This commit is contained in:
parent
d139e44cfa
commit
e4b3da2720
@ -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;
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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 {}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user