mirror of
https://github.com/ziglang/zig.git
synced 2026-01-03 03:53:20 +00:00
162 lines
4.5 KiB
Zig
162 lines
4.5 KiB
Zig
const MachO = @This();
|
|
|
|
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");
|
|
const File = link.File;
|
|
|
|
pub const base_tag: Tag = File.Tag.macho;
|
|
|
|
base: File,
|
|
|
|
entry_addr: ?u64 = null,
|
|
|
|
error_flags: File.ErrorFlags = File.ErrorFlags{},
|
|
|
|
pub const TextBlock = struct {
|
|
pub const empty = TextBlock{};
|
|
};
|
|
|
|
pub const SrcFn = struct {
|
|
pub const empty = SrcFn{};
|
|
};
|
|
|
|
pub fn openPath(allocator: *Allocator, dir: fs.Dir, sub_path: []const u8, options: link.Options) !*File {
|
|
assert(options.object_format == .macho);
|
|
|
|
const file = try dir.createFile(sub_path, .{ .truncate = false, .read = true, .mode = link.determineMode(options) });
|
|
errdefer file.close();
|
|
|
|
var macho_file = try allocator.create(MachO);
|
|
errdefer allocator.destroy(macho_file);
|
|
|
|
macho_file.* = openFile(allocator, file, options) catch |err| switch (err) {
|
|
error.IncrFailed => try createFile(allocator, file, options),
|
|
else => |e| return e,
|
|
};
|
|
|
|
return &macho_file.base;
|
|
}
|
|
|
|
/// Returns error.IncrFailed if incremental update could not be performed.
|
|
fn openFile(allocator: *Allocator, file: fs.File, options: link.Options) !MachO {
|
|
switch (options.output_mode) {
|
|
.Exe => {},
|
|
.Obj => {},
|
|
.Lib => return error.IncrFailed,
|
|
}
|
|
var self: MachO = .{
|
|
.base = .{
|
|
.file = file,
|
|
.tag = .macho,
|
|
.options = options,
|
|
.allocator = allocator,
|
|
},
|
|
};
|
|
errdefer self.deinit();
|
|
|
|
// TODO implement reading the macho file
|
|
return error.IncrFailed;
|
|
//try self.populateMissingMetadata();
|
|
//return self;
|
|
}
|
|
|
|
/// Truncates the existing file contents and overwrites the contents.
|
|
/// 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 => {},
|
|
.Obj => {},
|
|
.Lib => return error.TODOImplementWritingLibFiles,
|
|
}
|
|
|
|
var self: MachO = .{
|
|
.base = .{
|
|
.file = file,
|
|
.tag = .macho,
|
|
.options = options,
|
|
.allocator = allocator,
|
|
},
|
|
};
|
|
errdefer self.deinit();
|
|
|
|
return self;
|
|
}
|
|
|
|
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 {}
|
|
|
|
pub fn allocateDeclIndexes(self: *MachO, decl: *Module.Decl) !void {}
|
|
|
|
pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {}
|
|
|
|
pub fn updateDeclLineNumber(self: *MachO, module: *Module, decl: *const Module.Decl) !void {}
|
|
|
|
pub fn updateDeclExports(
|
|
self: *MachO,
|
|
module: *Module,
|
|
decl: *const Module.Decl,
|
|
exports: []const *Module.Export,
|
|
) !void {}
|
|
|
|
pub fn freeDecl(self: *MachO, decl: *Module.Decl) void {}
|