authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2020-11-12 21:07:06+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2020-11-26 11:50:09+01:00
log72310db1da792aae05edffe96082d97bb04cf7e5
tree726c7c1d6d6c8692b784a1518868d9bc4b7780be
parent58365c4e79479157bb0b4c2d66ad96c9a394651d

stage2 MachO: add min OS version load cmd


2 files changed, 39 insertions(+), 4 deletions(-)

lib/std/macho.zig+17
......@@ -705,6 +705,23 @@ pub const relocation_info = packed struct {
705705 r_type: u4,
706706};
707707
708/// The version_min_command contains the min OS version on which this
709/// binary was built to run.
710pub const version_min_command = extern struct {
711 /// LC_VERSION_MIN_MACOSX or LC_VERSION_MIN_IPHONEOS or LC_VERSION_MIN_WATCHOS
712 /// or LC_VERSION_MIN_TVOS
713 cmd: u32,
714
715 /// sizeof(struct min_version_command)
716 cmdsize: u32,
717
718 /// X.Y.Z is encoded in nibbles xxxx.yy.zz
719 version: u32,
720
721 /// X.Y.Z is encoded in nibbles xxxx.yy.zz
722 sdk: u32,
723};
724
708725/// After MacOS X 10.1 when a new load command is added that is required to be
709726/// understood by the dynamic linker for the image to execute properly the
710727/// LC_REQ_DYLD bit will be or'ed into the load command constant. If the dynamic
src/link/MachO.zig+22-4
......@@ -33,6 +33,7 @@ const LoadCommand = union(enum) {
3333 Dylinker: macho.dylinker_command,
3434 Dylib: macho.dylib_command,
3535 EntryPoint: macho.entry_point_command,
36 MinVersion: macho.version_min_command,
3637
3738 pub fn cmdsize(self: LoadCommand) u32 {
3839 return switch (self) {
......@@ -44,6 +45,7 @@ const LoadCommand = union(enum) {
4445 .Dylinker => |x| x.cmdsize,
4546 .Dylib => |x| x.cmdsize,
4647 .EntryPoint => |x| x.cmdsize,
48 .MinVersion => |x| x.cmdsize,
4749 };
4850 }
4951
......@@ -57,6 +59,7 @@ const LoadCommand = union(enum) {
5759 .Dylinker => |cmd| writeGeneric(cmd, file, offset),
5860 .Dylib => |cmd| writeGeneric(cmd, file, offset),
5961 .EntryPoint => |cmd| writeGeneric(cmd, file, offset),
62 .MinVersion => |cmd| writeGeneric(cmd, file, offset),
6063 };
6164 }
6265
......@@ -96,6 +99,8 @@ function_starts_cmd_index: ?u16 = null,
9699/// Specifies offset wrt __TEXT segment start address to the main entry point
97100/// of the binary.
98101main_cmd_index: ?u16 = null,
102/// Minimum OS version
103version_min_cmd_index: ?u16 = null,
99104
100105/// Table of all sections
101106sections: std.ArrayListUnmanaged(macho.section_64) = .{},
......@@ -317,8 +322,6 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {
317322 try self.writeAllGlobalSymbols();
318323 try self.writeAllUndefSymbols();
319324
320 try self.writeStringTable();
321
322325 switch (self.base.options.output_mode) {
323326 .Exe => {
324327 // Write export trie.
......@@ -379,8 +382,11 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {
379382 const nundefs = @intCast(u32, self.undef_symbols.items.len);
380383 const symtab = &self.load_commands.items[self.symtab_cmd_index.?].Symtab;
381384 symtab.nsyms = nlocals + nglobals + nundefs;
385 symtab.stroff = symtab.symoff + symtab.nsyms * @sizeOf(macho.nlist_64);
382386 }
383387
388 try self.writeStringTable();
389
384390 if (self.cmd_table_dirty) {
385391 try self.writeCmdHeaders();
386392 try self.writeMachOHeader();
......@@ -1329,8 +1335,8 @@ pub fn populateMissingMetadata(self: *MachO) !void {
13291335 self.libsystem_cmd_index = @intCast(u16, self.load_commands.items.len);
13301336 const cmdsize = mem.alignForwardGeneric(u64, @sizeOf(macho.dylib_command) + mem.lenZ(LIB_SYSTEM_PATH), @sizeOf(u64));
13311337 // 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.
1333 const min_version = 0x10000;
1338 // In the meantime, we're gonna hardcode to the minimum compatibility version of 0.0.0.
1339 const min_version = 0x0;
13341340 const dylib = .{
13351341 .name = @sizeOf(macho.dylib_command),
13361342 .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 {
13591365 });
13601366 self.cmd_table_dirty = true;
13611367 }
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 }
13621380 {
13631381 const linkedit = &self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment;
13641382 const dyld_info = &self.load_commands.items[self.dyld_info_cmd_index.?].DyldInfo;