| author | |
| committer | |
| log | 550ebcce9abe9db9453509b38820756a1fff8391 |
| tree | 41398a47cd5ea6a95f4bd4abdc5f0708b16ba525 |
| parent | 4aa8462cc936820bc2c81ea1f3cfc613ff07a9f7 |
Otherwise, we were prematurely committing `__LINKEDIT` segment LC
with outdated size (i.e., without code signature being taken into account).
This would scaffold into strict validation failures by Apple tooling.2 files changed, 47 insertions(+), 41 deletions(-)
src/link/MachO.zig+24-21| ... | @@ -558,6 +558,28 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No | ... | @@ -558,6 +558,28 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No |
| 558 | 558 | ||
| 559 | try self.writeLinkeditSegmentData(); | 559 | try self.writeLinkeditSegmentData(); |
| 560 | 560 | ||
| 561 | const target = self.base.options.target; | ||
| 562 | const requires_codesig = blk: { | ||
| 563 | if (self.base.options.entitlements) |_| break :blk true; | ||
| 564 | if (target.cpu.arch == .aarch64 and (target.os.tag == .macos or target.abi == .simulator)) | ||
| 565 | break :blk true; | ||
| 566 | break :blk false; | ||
| 567 | }; | ||
| 568 | var codesig: ?CodeSignature = if (requires_codesig) blk: { | ||
| 569 | // Preallocate space for the code signature. | ||
| 570 | // We need to do this at this stage so that we have the load commands with proper values | ||
| 571 | // written out to the file. | ||
| 572 | // The most important here is to have the correct vm and filesize of the __LINKEDIT segment | ||
| 573 | // where the code signature goes into. | ||
| 574 | var codesig = CodeSignature.init(self.page_size); | ||
| 575 | codesig.code_directory.ident = self.base.options.emit.?.sub_path; | ||
| 576 | if (self.base.options.entitlements) |path| { | ||
| 577 | try codesig.addEntitlements(arena, path); | ||
| 578 | } | ||
| 579 | try self.writeCodeSignaturePadding(&codesig); | ||
| 580 | break :blk codesig; | ||
| 581 | } else null; | ||
| 582 | |||
| 561 | // Write load commands | 583 | // Write load commands |
| 562 | var lc_buffer = std.ArrayList(u8).init(arena); | 584 | var lc_buffer = std.ArrayList(u8).init(arena); |
| 563 | const lc_writer = lc_buffer.writer(); | 585 | const lc_writer = lc_buffer.writer(); |
| ... | @@ -606,28 +628,9 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No | ... | @@ -606,28 +628,9 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No |
| 606 | 628 | ||
| 607 | try load_commands.writeLoadDylibLCs(self.dylibs.items, self.referenced_dylibs.keys(), lc_writer); | 629 | try load_commands.writeLoadDylibLCs(self.dylibs.items, self.referenced_dylibs.keys(), lc_writer); |
| 608 | 630 | ||
| 609 | const target = self.base.options.target; | 631 | if (requires_codesig) { |
| 610 | const requires_codesig = blk: { | ||
| 611 | if (self.base.options.entitlements) |_| break :blk true; | ||
| 612 | if (target.cpu.arch == .aarch64 and (target.os.tag == .macos or target.abi == .simulator)) | ||
| 613 | break :blk true; | ||
| 614 | break :blk false; | ||
| 615 | }; | ||
| 616 | var codesig: ?CodeSignature = if (requires_codesig) blk: { | ||
| 617 | // Preallocate space for the code signature. | ||
| 618 | // We need to do this at this stage so that we have the load commands with proper values | ||
| 619 | // written out to the file. | ||
| 620 | // The most important here is to have the correct vm and filesize of the __LINKEDIT segment | ||
| 621 | // where the code signature goes into. | ||
| 622 | var codesig = CodeSignature.init(self.page_size); | ||
| 623 | codesig.code_directory.ident = self.base.options.emit.?.sub_path; | ||
| 624 | if (self.base.options.entitlements) |path| { | ||
| 625 | try codesig.addEntitlements(arena, path); | ||
| 626 | } | ||
| 627 | try self.writeCodeSignaturePadding(&codesig); | ||
| 628 | try lc_writer.writeStruct(self.codesig_cmd); | 632 | try lc_writer.writeStruct(self.codesig_cmd); |
| 629 | break :blk codesig; | 633 | } |
| 630 | } else null; | ||
| 631 | 634 | ||
| 632 | try self.base.file.?.pwriteAll(lc_buffer.items, @sizeOf(macho.mach_header_64)); | 635 | try self.base.file.?.pwriteAll(lc_buffer.items, @sizeOf(macho.mach_header_64)); |
| 633 | 636 |
src/link/MachO/zld.zig+23-20| ... | @@ -4100,6 +4100,27 @@ pub fn linkWithZld(macho_file: *MachO, comp: *Compilation, prog_node: *std.Progr | ... | @@ -4100,6 +4100,27 @@ pub fn linkWithZld(macho_file: *MachO, comp: *Compilation, prog_node: *std.Progr |
| 4100 | } | 4100 | } |
| 4101 | } | 4101 | } |
| 4102 | 4102 | ||
| 4103 | // Write code signature padding if required | ||
| 4104 | const requires_codesig = blk: { | ||
| 4105 | if (options.entitlements) |_| break :blk true; | ||
| 4106 | if (cpu_arch == .aarch64 and (os_tag == .macos or abi == .simulator)) break :blk true; | ||
| 4107 | break :blk false; | ||
| 4108 | }; | ||
| 4109 | var codesig: ?CodeSignature = if (requires_codesig) blk: { | ||
| 4110 | // Preallocate space for the code signature. | ||
| 4111 | // We need to do this at this stage so that we have the load commands with proper values | ||
| 4112 | // written out to the file. | ||
| 4113 | // The most important here is to have the correct vm and filesize of the __LINKEDIT segment | ||
| 4114 | // where the code signature goes into. | ||
| 4115 | var codesig = CodeSignature.init(page_size); | ||
| 4116 | codesig.code_directory.ident = fs.path.basename(full_out_path); | ||
| 4117 | if (options.entitlements) |path| { | ||
| 4118 | try codesig.addEntitlements(arena, path); | ||
| 4119 | } | ||
| 4120 | try zld.writeCodeSignaturePadding(&codesig); | ||
| 4121 | break :blk codesig; | ||
| 4122 | } else null; | ||
| 4123 | |||
| 4103 | // Write load commands | 4124 | // Write load commands |
| 4104 | var lc_buffer = std.ArrayList(u8).init(arena); | 4125 | var lc_buffer = std.ArrayList(u8).init(arena); |
| 4105 | const lc_writer = lc_buffer.writer(); | 4126 | const lc_writer = lc_buffer.writer(); |
| ... | @@ -4142,29 +4163,11 @@ pub fn linkWithZld(macho_file: *MachO, comp: *Compilation, prog_node: *std.Progr | ... | @@ -4142,29 +4163,11 @@ pub fn linkWithZld(macho_file: *MachO, comp: *Compilation, prog_node: *std.Progr |
| 4142 | 4163 | ||
| 4143 | try load_commands.writeLoadDylibLCs(zld.dylibs.items, zld.referenced_dylibs.keys(), lc_writer); | 4164 | try load_commands.writeLoadDylibLCs(zld.dylibs.items, zld.referenced_dylibs.keys(), lc_writer); |
| 4144 | 4165 | ||
| 4145 | const requires_codesig = blk: { | ||
| 4146 | if (options.entitlements) |_| break :blk true; | ||
| 4147 | if (cpu_arch == .aarch64 and (os_tag == .macos or abi == .simulator)) break :blk true; | ||
| 4148 | break :blk false; | ||
| 4149 | }; | ||
| 4150 | var codesig_cmd_offset: ?u32 = null; | 4166 | var codesig_cmd_offset: ?u32 = null; |
| 4151 | var codesig: ?CodeSignature = if (requires_codesig) blk: { | 4167 | if (requires_codesig) { |
| 4152 | // Preallocate space for the code signature. | ||
| 4153 | // We need to do this at this stage so that we have the load commands with proper values | ||
| 4154 | // written out to the file. | ||
| 4155 | // The most important here is to have the correct vm and filesize of the __LINKEDIT segment | ||
| 4156 | // where the code signature goes into. | ||
| 4157 | var codesig = CodeSignature.init(page_size); | ||
| 4158 | codesig.code_directory.ident = fs.path.basename(full_out_path); | ||
| 4159 | if (options.entitlements) |path| { | ||
| 4160 | try codesig.addEntitlements(gpa, path); | ||
| 4161 | } | ||
| 4162 | try zld.writeCodeSignaturePadding(&codesig); | ||
| 4163 | codesig_cmd_offset = @sizeOf(macho.mach_header_64) + @intCast(u32, lc_buffer.items.len); | 4168 | codesig_cmd_offset = @sizeOf(macho.mach_header_64) + @intCast(u32, lc_buffer.items.len); |
| 4164 | try lc_writer.writeStruct(zld.codesig_cmd); | 4169 | try lc_writer.writeStruct(zld.codesig_cmd); |
| 4165 | break :blk codesig; | 4170 | } |
| 4166 | } else null; | ||
| 4167 | defer if (codesig) |*csig| csig.deinit(gpa); | ||
| 4168 | 4171 | ||
| 4169 | const ncmds = load_commands.calcNumOfLCs(lc_buffer.items); | 4172 | const ncmds = load_commands.calcNumOfLCs(lc_buffer.items); |
| 4170 | try zld.file.pwriteAll(lc_buffer.items, @sizeOf(macho.mach_header_64)); | 4173 | try zld.file.pwriteAll(lc_buffer.items, @sizeOf(macho.mach_header_64)); |