| ... | @@ -33,6 +33,7 @@ const LoadCommand = union(enum) { | ... | @@ -33,6 +33,7 @@ const LoadCommand = union(enum) { |
| 33 | Dylinker: macho.dylinker_command, | 33 | Dylinker: macho.dylinker_command, |
| 34 | Dylib: macho.dylib_command, | 34 | Dylib: macho.dylib_command, |
| 35 | EntryPoint: macho.entry_point_command, | 35 | EntryPoint: macho.entry_point_command, |
| | 36 | MinVersion: macho.version_min_command, |
| 36 | | 37 | |
| 37 | pub fn cmdsize(self: LoadCommand) u32 { | 38 | pub fn cmdsize(self: LoadCommand) u32 { |
| 38 | return switch (self) { | 39 | return switch (self) { |
| ... | @@ -44,6 +45,7 @@ const LoadCommand = union(enum) { | ... | @@ -44,6 +45,7 @@ const LoadCommand = union(enum) { |
| 44 | .Dylinker => |x| x.cmdsize, | 45 | .Dylinker => |x| x.cmdsize, |
| 45 | .Dylib => |x| x.cmdsize, | 46 | .Dylib => |x| x.cmdsize, |
| 46 | .EntryPoint => |x| x.cmdsize, | 47 | .EntryPoint => |x| x.cmdsize, |
| | 48 | .MinVersion => |x| x.cmdsize, |
| 47 | }; | 49 | }; |
| 48 | } | 50 | } |
| 49 | | 51 | |
| ... | @@ -57,6 +59,7 @@ const LoadCommand = union(enum) { | ... | @@ -57,6 +59,7 @@ const LoadCommand = union(enum) { |
| 57 | .Dylinker => |cmd| writeGeneric(cmd, file, offset), | 59 | .Dylinker => |cmd| writeGeneric(cmd, file, offset), |
| 58 | .Dylib => |cmd| writeGeneric(cmd, file, offset), | 60 | .Dylib => |cmd| writeGeneric(cmd, file, offset), |
| 59 | .EntryPoint => |cmd| writeGeneric(cmd, file, offset), | 61 | .EntryPoint => |cmd| writeGeneric(cmd, file, offset), |
| | 62 | .MinVersion => |cmd| writeGeneric(cmd, file, offset), |
| 60 | }; | 63 | }; |
| 61 | } | 64 | } |
| 62 | | 65 | |
| ... | @@ -96,6 +99,8 @@ function_starts_cmd_index: ?u16 = null, | ... | @@ -96,6 +99,8 @@ function_starts_cmd_index: ?u16 = null, |
| 96 | /// Specifies offset wrt __TEXT segment start address to the main entry point | 99 | /// Specifies offset wrt __TEXT segment start address to the main entry point |
| 97 | /// of the binary. | 100 | /// of the binary. |
| 98 | main_cmd_index: ?u16 = null, | 101 | main_cmd_index: ?u16 = null, |
| | 102 | /// Minimum OS version |
| | 103 | version_min_cmd_index: ?u16 = null, |
| 99 | | 104 | |
| 100 | /// Table of all sections | 105 | /// Table of all sections |
| 101 | sections: std.ArrayListUnmanaged(macho.section_64) = .{}, | 106 | sections: std.ArrayListUnmanaged(macho.section_64) = .{}, |
| ... | @@ -317,8 +322,6 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void { | ... | @@ -317,8 +322,6 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void { |
| 317 | try self.writeAllGlobalSymbols(); | 322 | try self.writeAllGlobalSymbols(); |
| 318 | try self.writeAllUndefSymbols(); | 323 | try self.writeAllUndefSymbols(); |
| 319 | | 324 | |
| 320 | try self.writeStringTable(); | | |
| 321 | | | |
| 322 | switch (self.base.options.output_mode) { | 325 | switch (self.base.options.output_mode) { |
| 323 | .Exe => { | 326 | .Exe => { |
| 324 | // Write export trie. | 327 | // Write export trie. |
| ... | @@ -379,8 +382,11 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void { | ... | @@ -379,8 +382,11 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void { |
| 379 | const nundefs = @intCast(u32, self.undef_symbols.items.len); | 382 | const nundefs = @intCast(u32, self.undef_symbols.items.len); |
| 380 | const symtab = &self.load_commands.items[self.symtab_cmd_index.?].Symtab; | 383 | const symtab = &self.load_commands.items[self.symtab_cmd_index.?].Symtab; |
| 381 | symtab.nsyms = nlocals + nglobals + nundefs; | 384 | symtab.nsyms = nlocals + nglobals + nundefs; |
| | 385 | symtab.stroff = symtab.symoff + symtab.nsyms * @sizeOf(macho.nlist_64); |
| 382 | } | 386 | } |
| 383 | | 387 | |
| | 388 | try self.writeStringTable(); |
| | 389 | |
| 384 | if (self.cmd_table_dirty) { | 390 | if (self.cmd_table_dirty) { |
| 385 | try self.writeCmdHeaders(); | 391 | try self.writeCmdHeaders(); |
| 386 | try self.writeMachOHeader(); | 392 | try self.writeMachOHeader(); |
| ... | @@ -1329,8 +1335,8 @@ pub fn populateMissingMetadata(self: *MachO) !void { | ... | @@ -1329,8 +1335,8 @@ pub fn populateMissingMetadata(self: *MachO) !void { |
| 1329 | self.libsystem_cmd_index = @intCast(u16, self.load_commands.items.len); | 1335 | self.libsystem_cmd_index = @intCast(u16, self.load_commands.items.len); |
| 1330 | const cmdsize = mem.alignForwardGeneric(u64, @sizeOf(macho.dylib_command) + mem.lenZ(LIB_SYSTEM_PATH), @sizeOf(u64)); | 1336 | const cmdsize = mem.alignForwardGeneric(u64, @sizeOf(macho.dylib_command) + mem.lenZ(LIB_SYSTEM_PATH), @sizeOf(u64)); |
| 1331 | // TODO Find a way to work out runtime version from the OS version triple stored in std.Target. | 1337 | // TODO Find a way to work out runtime version from the OS version triple stored in std.Target. |
| 1332 | // In the meantime, we're gonna hardcode to the minimum compatibility version of 1.0.0. | 1338 | // In the meantime, we're gonna hardcode to the minimum compatibility version of 0.0.0. |
| 1333 | const min_version = 0x10000; | 1339 | const min_version = 0x0; |
| 1334 | const dylib = .{ | 1340 | const dylib = .{ |
| 1335 | .name = @sizeOf(macho.dylib_command), | 1341 | .name = @sizeOf(macho.dylib_command), |
| 1336 | .timestamp = 2, // not sure why not simply 0; this is reverse engineered from Mach-O files | 1342 | .timestamp = 2, // not sure why not simply 0; this is reverse engineered from Mach-O files |
| ... | @@ -1359,6 +1365,18 @@ pub fn populateMissingMetadata(self: *MachO) !void { | ... | @@ -1359,6 +1365,18 @@ pub fn populateMissingMetadata(self: *MachO) !void { |
| 1359 | }); | 1365 | }); |
| 1360 | self.cmd_table_dirty = true; | 1366 | self.cmd_table_dirty = true; |
| 1361 | } | 1367 | } |
| | 1368 | if (self.version_min_cmd_index == null) { |
| | 1369 | self.version_min_cmd_index = @intCast(u16, self.load_commands.items.len); |
| | 1370 | try self.load_commands.append(self.base.allocator, .{ |
| | 1371 | // TODO allow for different targets and different versions |
| | 1372 | .MinVersion = .{ |
| | 1373 | .cmd = macho.LC_VERSION_MIN_MACOSX, |
| | 1374 | .cmdsize = @sizeOf(macho.version_min_command), |
| | 1375 | .version = 0xB0001, // 11.0.1 BigSur |
| | 1376 | .sdk = 0xB0001, // 11.0.1 BigSur |
| | 1377 | }, |
| | 1378 | }); |
| | 1379 | } |
| 1362 | { | 1380 | { |
| 1363 | const linkedit = &self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment; | 1381 | const linkedit = &self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment; |
| 1364 | const dyld_info = &self.load_commands.items[self.dyld_info_cmd_index.?].DyldInfo; | 1382 | const dyld_info = &self.load_commands.items[self.dyld_info_cmd_index.?].DyldInfo; |