From 700768498488dbae1c737b484f330b86f116cb62 Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Thu, 5 Aug 2021 16:57:59 +0200 Subject: [PATCH] macho: swap out VERSION_MIN for BUILD_VERSION this makes the app successfully run on the iOS simluator! --- lib/std/macho.zig | 15 ++++++ src/link/MachO.zig | 99 +++++++++++++++++++++++-------------- src/link/MachO/Dylib.zig | 3 ++ src/link/MachO/commands.zig | 8 +++ 4 files changed, 87 insertions(+), 38 deletions(-) diff --git a/lib/std/macho.zig b/lib/std/macho.zig index cb030e941e..14be755a70 100644 --- a/lib/std/macho.zig +++ b/lib/std/macho.zig @@ -116,6 +116,21 @@ pub const build_tool_version = extern struct { version: u32, }; +pub const PLATFORM_MACOS: u32 = 0x1; +pub const PLATFORM_IOS: u32 = 0x2; +pub const PLATFORM_TVOS: u32 = 0x3; +pub const PLATFORM_WATCHOS: u32 = 0x4; +pub const PLATFORM_BRIDGEOS: u32 = 0x5; +pub const PLATFORM_MACCATALYST: u32 = 0x6; +pub const PLATFORM_IOSSIMULATOR: u32 = 0x7; +pub const PLATFORM_TVOSSIMULATOR: u32 = 0x8; +pub const PLATFORM_WATCHOSSIMULATOR: u32 = 0x9; +pub const PLATFORM_DRIVERKIT: u32 = 0x10; + +pub const TOOL_CLANG: u32 = 0x1; +pub const TOOL_SWIFT: u32 = 0x2; +pub const TOOL_LD: u32 = 0x3; + /// The entry_point_command is a replacement for thread_command. /// It is used for main executables to specify the location (file offset) /// of main(). If -stack_size was used at link time, the stacksize diff --git a/src/link/MachO.zig b/src/link/MachO.zig index 81f0808dc7..886c3a33e2 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -82,8 +82,8 @@ data_in_code_cmd_index: ?u16 = null, function_starts_cmd_index: ?u16 = null, main_cmd_index: ?u16 = null, dylib_id_cmd_index: ?u16 = null, -version_min_cmd_index: ?u16 = null, source_version_cmd_index: ?u16 = null, +build_version_cmd_index: ?u16 = null, uuid_cmd_index: ?u16 = null, code_signature_cmd_index: ?u16 = null, /// Path to libSystem @@ -2716,27 +2716,6 @@ fn populateMetadata(self: *MachO) !void { try self.load_commands.append(self.base.allocator, .{ .Dylib = dylib_cmd }); } - if (self.version_min_cmd_index == null) { - self.version_min_cmd_index = @intCast(u16, self.load_commands.items.len); - const cmd: u32 = switch (self.base.options.target.os.tag) { - .macos => macho.LC_VERSION_MIN_MACOSX, - .ios => macho.LC_VERSION_MIN_IPHONEOS, - .tvos => macho.LC_VERSION_MIN_TVOS, - .watchos => macho.LC_VERSION_MIN_WATCHOS, - else => unreachable, // wrong OS - }; - const ver = self.base.options.target.os.version_range.semver.min; - const version = ver.major << 16 | ver.minor << 8 | ver.patch; - try self.load_commands.append(self.base.allocator, .{ - .VersionMin = .{ - .cmd = cmd, - .cmdsize = @sizeOf(macho.version_min_command), - .version = version, - .sdk = version, - }, - }); - } - if (self.source_version_cmd_index == null) { self.source_version_cmd_index = @intCast(u16, self.load_commands.items.len); try self.load_commands.append(self.base.allocator, .{ @@ -2748,6 +2727,39 @@ fn populateMetadata(self: *MachO) !void { }); } + if (self.build_version_cmd_index == null) { + self.build_version_cmd_index = @intCast(u16, self.load_commands.items.len); + const cmdsize = @intCast(u32, mem.alignForwardGeneric( + u64, + @sizeOf(macho.build_version_command) + @sizeOf(macho.build_tool_version), + @sizeOf(u64), + )); + const ver = self.base.options.target.os.version_range.semver.min; + const version = ver.major << 16 | ver.minor << 8 | ver.patch; + var cmd = commands.emptyGenericCommandWithData(macho.build_version_command{ + .cmd = macho.LC_BUILD_VERSION, + .cmdsize = cmdsize, + .platform = switch (self.base.options.target.os.tag) { + .macos => macho.PLATFORM_MACOS, + .ios => macho.PLATFORM_IOSSIMULATOR, + .watchos => macho.PLATFORM_WATCHOS, + .tvos => macho.PLATFORM_TVOS, + else => unreachable, + }, + .minos = version, + .sdk = version, + .ntools = 1, + }); + const ld_ver = macho.build_tool_version{ + .tool = macho.TOOL_LD, + .version = 0x0, + }; + cmd.data = try self.base.allocator.alloc(u8, cmdsize - @sizeOf(macho.build_version_command)); + mem.set(u8, cmd.data, 0); + mem.copy(u8, cmd.data, mem.asBytes(&ld_ver)); + try self.load_commands.append(self.base.allocator, .{ .BuildVersion = cmd }); + } + if (self.uuid_cmd_index == null) { self.uuid_cmd_index = @intCast(u16, self.load_commands.items.len); var uuid_cmd: macho.uuid_command = .{ @@ -4334,26 +4346,37 @@ pub fn populateMissingMetadata(self: *MachO) !void { }); self.load_commands_dirty = true; } - if (self.version_min_cmd_index == null) { - self.version_min_cmd_index = @intCast(u16, self.load_commands.items.len); - const cmd: u32 = switch (self.base.options.target.os.tag) { - .macos => macho.LC_VERSION_MIN_MACOSX, - .ios => macho.LC_VERSION_MIN_IPHONEOS, - .tvos => macho.LC_VERSION_MIN_TVOS, - .watchos => macho.LC_VERSION_MIN_WATCHOS, - else => unreachable, // wrong OS - }; + if (self.build_version_cmd_index == null) { + self.build_version_cmd_index = @intCast(u16, self.load_commands.items.len); + const cmdsize = @intCast(u32, mem.alignForwardGeneric( + u64, + @sizeOf(macho.build_version_command) + @sizeOf(macho.build_tool_version), + @sizeOf(u64), + )); const ver = self.base.options.target.os.version_range.semver.min; const version = ver.major << 16 | ver.minor << 8 | ver.patch; - try self.load_commands.append(self.base.allocator, .{ - .VersionMin = .{ - .cmd = cmd, - .cmdsize = @sizeOf(macho.version_min_command), - .version = version, - .sdk = version, + var cmd = commands.emptyGenericCommandWithData(macho.build_version_command{ + .cmd = macho.LC_BUILD_VERSION, + .cmdsize = cmdsize, + .platform = switch (self.base.options.target.os.tag) { + .macos => macho.PLATFORM_MACOS, + .ios => macho.PLATFORM_IOSSIMULATOR, + .watchos => macho.PLATFORM_WATCHOS, + .tvos => macho.PLATFORM_TVOS, + else => unreachable, }, + .minos = version, + .sdk = version, + .ntools = 1, }); - self.load_commands_dirty = true; + const ld_ver = macho.build_tool_version{ + .tool = macho.TOOL_LD, + .version = 0x0, + }; + cmd.data = try self.base.allocator.alloc(u8, cmdsize - @sizeOf(macho.build_version_command)); + mem.set(u8, cmd.data, 0); + mem.copy(u8, cmd.data, mem.asBytes(&ld_ver)); + try self.load_commands.append(self.base.allocator, .{ .BuildVersion = cmd }); } if (self.source_version_cmd_index == null) { self.source_version_cmd_index = @intCast(u16, self.load_commands.items.len); diff --git a/src/link/MachO/Dylib.zig b/src/link/MachO/Dylib.zig index 580159a13c..3dcccf6710 100644 --- a/src/link/MachO/Dylib.zig +++ b/src/link/MachO/Dylib.zig @@ -340,6 +340,9 @@ fn targetToAppleString(allocator: *Allocator, target: std.Target) ![]const u8 { .x86_64 => "x86_64", else => unreachable, }; + if (target.os.tag == .ios) { + return std.fmt.allocPrint(allocator, "{s}-{s}-simulator", .{ arch, @tagName(target.os.tag) }); + } return std.fmt.allocPrint(allocator, "{s}-{s}", .{ arch, @tagName(target.os.tag) }); } diff --git a/src/link/MachO/commands.zig b/src/link/MachO/commands.zig index f7a2fd3eda..b4515da966 100644 --- a/src/link/MachO/commands.zig +++ b/src/link/MachO/commands.zig @@ -43,6 +43,7 @@ pub const LoadCommand = union(enum) { Main: macho.entry_point_command, VersionMin: macho.version_min_command, SourceVersion: macho.source_version_command, + BuildVersion: GenericCommandWithData(macho.build_version_command), Uuid: macho.uuid_command, LinkeditData: macho.linkedit_data_command, Rpath: GenericCommandWithData(macho.rpath_command), @@ -97,6 +98,9 @@ pub const LoadCommand = union(enum) { macho.LC_SOURCE_VERSION => LoadCommand{ .SourceVersion = try stream.reader().readStruct(macho.source_version_command), }, + macho.LC_BUILD_VERSION => LoadCommand{ + .BuildVersion = try GenericCommandWithData(macho.build_version_command).read(allocator, stream.reader()), + }, macho.LC_UUID => LoadCommand{ .Uuid = try stream.reader().readStruct(macho.uuid_command), }, @@ -129,6 +133,7 @@ pub const LoadCommand = union(enum) { .Dylinker => |x| x.write(writer), .Dylib => |x| x.write(writer), .Rpath => |x| x.write(writer), + .BuildVersion => |x| x.write(writer), .Unknown => |x| x.write(writer), }; } @@ -147,6 +152,7 @@ pub const LoadCommand = union(enum) { .Dylinker => |x| x.inner.cmd, .Dylib => |x| x.inner.cmd, .Rpath => |x| x.inner.cmd, + .BuildVersion => |x| x.inner.cmd, .Unknown => |x| x.inner.cmd, }; } @@ -165,6 +171,7 @@ pub const LoadCommand = union(enum) { .Dylinker => |x| x.inner.cmdsize, .Dylib => |x| x.inner.cmdsize, .Rpath => |x| x.inner.cmdsize, + .BuildVersion => |x| x.inner.cmdsize, .Unknown => |x| x.inner.cmdsize, }; } @@ -193,6 +200,7 @@ pub const LoadCommand = union(enum) { .Main => |x| meta.eql(x, other.Main), .VersionMin => |x| meta.eql(x, other.VersionMin), .SourceVersion => |x| meta.eql(x, other.SourceVersion), + .BuildVersion => |x| x.eql(other.BuildVersion), .Uuid => |x| meta.eql(x, other.Uuid), .LinkeditData => |x| meta.eql(x, other.LinkeditData), .Segment => |x| x.eql(other.Segment),