| ... | ... | @@ -5715,28 +5715,46 @@ fn writeDyldInfoData(self: *MachO) !void { |
| 5715 | 5715 | |
| 5716 | 5716 | const seg = &self.load_commands.items[self.linkedit_segment_cmd_index.?].segment; |
| 5717 | 5717 | const dyld_info = &self.load_commands.items[self.dyld_info_cmd_index.?].dyld_info_only; |
| 5718 | |
| 5719 | const rebase_off = mem.alignForwardGeneric(u64, seg.inner.fileoff, @alignOf(u64)); |
| 5718 | 5720 | const rebase_size = try bind.rebaseInfoSize(rebase_pointers.items); |
| 5719 | | const bind_size = try bind.bindInfoSize(bind_pointers.items); |
| 5720 | | const lazy_bind_size = try bind.lazyBindInfoSize(lazy_bind_pointers.items); |
| 5721 | | const export_size = trie.size; |
| 5721 | dyld_info.rebase_off = @intCast(u32, rebase_off); |
| 5722 | dyld_info.rebase_size = @intCast(u32, rebase_size); |
| 5723 | log.debug("writing rebase info from 0x{x} to 0x{x}", .{ |
| 5724 | dyld_info.rebase_off, |
| 5725 | dyld_info.rebase_off + dyld_info.rebase_size, |
| 5726 | }); |
| 5722 | 5727 | |
| 5723 | | dyld_info.rebase_off = @intCast(u32, seg.inner.fileoff); |
| 5724 | | dyld_info.rebase_size = @intCast(u32, mem.alignForwardGeneric(u64, rebase_size, @alignOf(u64))); |
| 5725 | | seg.inner.filesize += dyld_info.rebase_size; |
| 5728 | const bind_off = mem.alignForwardGeneric(u64, dyld_info.rebase_off + dyld_info.rebase_size, @alignOf(u64)); |
| 5729 | const bind_size = try bind.bindInfoSize(bind_pointers.items); |
| 5730 | dyld_info.bind_off = @intCast(u32, bind_off); |
| 5731 | dyld_info.bind_size = @intCast(u32, bind_size); |
| 5732 | log.debug("writing bind info from 0x{x} to 0x{x}", .{ |
| 5733 | dyld_info.bind_off, |
| 5734 | dyld_info.bind_off + dyld_info.bind_size, |
| 5735 | }); |
| 5726 | 5736 | |
| 5727 | | dyld_info.bind_off = dyld_info.rebase_off + dyld_info.rebase_size; |
| 5728 | | dyld_info.bind_size = @intCast(u32, mem.alignForwardGeneric(u64, bind_size, @alignOf(u64))); |
| 5729 | | seg.inner.filesize += dyld_info.bind_size; |
| 5737 | const lazy_bind_off = mem.alignForwardGeneric(u64, dyld_info.bind_off + dyld_info.bind_size, @alignOf(u64)); |
| 5738 | const lazy_bind_size = try bind.lazyBindInfoSize(lazy_bind_pointers.items); |
| 5739 | dyld_info.lazy_bind_off = @intCast(u32, lazy_bind_off); |
| 5740 | dyld_info.lazy_bind_size = @intCast(u32, lazy_bind_size); |
| 5741 | log.debug("writing lazy bind info from 0x{x} to 0x{x}", .{ |
| 5742 | dyld_info.lazy_bind_off, |
| 5743 | dyld_info.lazy_bind_off + dyld_info.lazy_bind_size, |
| 5744 | }); |
| 5730 | 5745 | |
| 5731 | | dyld_info.lazy_bind_off = dyld_info.bind_off + dyld_info.bind_size; |
| 5732 | | dyld_info.lazy_bind_size = @intCast(u32, mem.alignForwardGeneric(u64, lazy_bind_size, @alignOf(u64))); |
| 5733 | | seg.inner.filesize += dyld_info.lazy_bind_size; |
| 5746 | const export_off = mem.alignForwardGeneric(u64, dyld_info.lazy_bind_off + dyld_info.lazy_bind_size, @alignOf(u64)); |
| 5747 | const export_size = trie.size; |
| 5748 | dyld_info.export_off = @intCast(u32, export_off); |
| 5749 | dyld_info.export_size = @intCast(u32, export_size); |
| 5750 | log.debug("writing export trie from 0x{x} to 0x{x}", .{ |
| 5751 | dyld_info.export_off, |
| 5752 | dyld_info.export_off + dyld_info.export_size, |
| 5753 | }); |
| 5734 | 5754 | |
| 5735 | | dyld_info.export_off = dyld_info.lazy_bind_off + dyld_info.lazy_bind_size; |
| 5736 | | dyld_info.export_size = @intCast(u32, mem.alignForwardGeneric(u64, export_size, @alignOf(u64))); |
| 5737 | | seg.inner.filesize += dyld_info.export_size; |
| 5755 | seg.inner.filesize = dyld_info.export_off + dyld_info.export_size - seg.inner.fileoff; |
| 5738 | 5756 | |
| 5739 | | const needed_size = dyld_info.rebase_size + dyld_info.bind_size + dyld_info.lazy_bind_size + dyld_info.export_size; |
| 5757 | const needed_size = dyld_info.export_off + dyld_info.export_size - dyld_info.rebase_off; |
| 5740 | 5758 | var buffer = try self.base.allocator.alloc(u8, needed_size); |
| 5741 | 5759 | defer self.base.allocator.free(buffer); |
| 5742 | 5760 | mem.set(u8, buffer, 0); |
| ... | ... | @@ -5744,14 +5762,15 @@ fn writeDyldInfoData(self: *MachO) !void { |
| 5744 | 5762 | var stream = std.io.fixedBufferStream(buffer); |
| 5745 | 5763 | const writer = stream.writer(); |
| 5746 | 5764 | |
| 5765 | const base_off = dyld_info.rebase_off; |
| 5747 | 5766 | try bind.writeRebaseInfo(rebase_pointers.items, writer); |
| 5748 | | try stream.seekBy(@intCast(i64, dyld_info.rebase_size) - @intCast(i64, rebase_size)); |
| 5767 | try stream.seekTo(dyld_info.bind_off - base_off); |
| 5749 | 5768 | |
| 5750 | 5769 | try bind.writeBindInfo(bind_pointers.items, writer); |
| 5751 | | try stream.seekBy(@intCast(i64, dyld_info.bind_size) - @intCast(i64, bind_size)); |
| 5770 | try stream.seekTo(dyld_info.lazy_bind_off - base_off); |
| 5752 | 5771 | |
| 5753 | 5772 | try bind.writeLazyBindInfo(lazy_bind_pointers.items, writer); |
| 5754 | | try stream.seekBy(@intCast(i64, dyld_info.lazy_bind_size) - @intCast(i64, lazy_bind_size)); |
| 5773 | try stream.seekTo(dyld_info.export_off - base_off); |
| 5755 | 5774 | |
| 5756 | 5775 | _ = try trie.write(writer); |
| 5757 | 5776 | |
| ... | ... | @@ -5762,7 +5781,7 @@ fn writeDyldInfoData(self: *MachO) !void { |
| 5762 | 5781 | |
| 5763 | 5782 | try self.base.file.?.pwriteAll(buffer, dyld_info.rebase_off); |
| 5764 | 5783 | try self.populateLazyBindOffsetsInStubHelper( |
| 5765 | | buffer[dyld_info.rebase_size + dyld_info.bind_size ..][0..dyld_info.lazy_bind_size], |
| 5784 | buffer[dyld_info.lazy_bind_off - base_off ..][0..dyld_info.lazy_bind_size], |
| 5766 | 5785 | ); |
| 5767 | 5786 | self.load_commands_dirty = true; |
| 5768 | 5787 | } |
| ... | ... | @@ -5932,32 +5951,31 @@ fn writeFunctionStarts(self: *MachO) !void { |
| 5932 | 5951 | } else break; |
| 5933 | 5952 | } |
| 5934 | 5953 | |
| 5935 | | const max_size = @intCast(usize, offsets.items.len * @sizeOf(u64)); |
| 5936 | | var buffer = try self.base.allocator.alloc(u8, max_size); |
| 5937 | | defer self.base.allocator.free(buffer); |
| 5938 | | mem.set(u8, buffer, 0); |
| 5954 | var buffer = std.ArrayList(u8).init(self.base.allocator); |
| 5955 | defer buffer.deinit(); |
| 5939 | 5956 | |
| 5940 | | var stream = std.io.fixedBufferStream(buffer); |
| 5941 | | const writer = stream.writer(); |
| 5957 | const max_size = @intCast(usize, offsets.items.len * @sizeOf(u64)); |
| 5958 | try buffer.ensureTotalCapacity(max_size); |
| 5942 | 5959 | |
| 5943 | 5960 | for (offsets.items) |offset| { |
| 5944 | | try std.leb.writeULEB128(writer, offset); |
| 5961 | try std.leb.writeULEB128(buffer.writer(), offset); |
| 5945 | 5962 | } |
| 5946 | 5963 | |
| 5947 | | const needed_size = @intCast(u32, mem.alignForwardGeneric(u64, stream.pos, @sizeOf(u64))); |
| 5948 | 5964 | const seg = &self.load_commands.items[self.linkedit_segment_cmd_index.?].segment; |
| 5949 | 5965 | const fn_cmd = &self.load_commands.items[self.function_starts_cmd_index.?].linkedit_data; |
| 5950 | 5966 | |
| 5951 | | fn_cmd.dataoff = @intCast(u32, seg.inner.fileoff + seg.inner.filesize); |
| 5952 | | fn_cmd.datasize = needed_size; |
| 5953 | | seg.inner.filesize += needed_size; |
| 5967 | const dataoff = mem.alignForwardGeneric(u64, seg.inner.fileoff + seg.inner.filesize, @alignOf(u64)); |
| 5968 | const datasize = buffer.items.len; |
| 5969 | fn_cmd.dataoff = @intCast(u32, dataoff); |
| 5970 | fn_cmd.datasize = @intCast(u32, datasize); |
| 5971 | seg.inner.filesize = fn_cmd.dataoff + fn_cmd.datasize - seg.inner.fileoff; |
| 5954 | 5972 | |
| 5955 | 5973 | log.debug("writing function starts info from 0x{x} to 0x{x}", .{ |
| 5956 | 5974 | fn_cmd.dataoff, |
| 5957 | 5975 | fn_cmd.dataoff + fn_cmd.datasize, |
| 5958 | 5976 | }); |
| 5959 | 5977 | |
| 5960 | | try self.base.file.?.pwriteAll(buffer[0..needed_size], fn_cmd.dataoff); |
| 5978 | try self.base.file.?.pwriteAll(buffer.items, fn_cmd.dataoff); |
| 5961 | 5979 | self.load_commands_dirty = true; |
| 5962 | 5980 | } |
| 5963 | 5981 | |
| ... | ... | @@ -6005,11 +6023,12 @@ fn writeDices(self: *MachO) !void { |
| 6005 | 6023 | |
| 6006 | 6024 | const seg = &self.load_commands.items[self.linkedit_segment_cmd_index.?].segment; |
| 6007 | 6025 | const dice_cmd = &self.load_commands.items[self.data_in_code_cmd_index.?].linkedit_data; |
| 6008 | | const needed_size = @intCast(u32, buf.items.len); |
| 6009 | 6026 | |
| 6010 | | dice_cmd.dataoff = @intCast(u32, seg.inner.fileoff + seg.inner.filesize); |
| 6011 | | dice_cmd.datasize = needed_size; |
| 6012 | | seg.inner.filesize += needed_size; |
| 6027 | const dataoff = mem.alignForwardGeneric(u64, seg.inner.fileoff + seg.inner.filesize, @alignOf(u64)); |
| 6028 | const datasize = buf.items.len; |
| 6029 | dice_cmd.dataoff = @intCast(u32, dataoff); |
| 6030 | dice_cmd.datasize = @intCast(u32, datasize); |
| 6031 | seg.inner.filesize = dice_cmd.dataoff + dice_cmd.datasize - seg.inner.fileoff; |
| 6013 | 6032 | |
| 6014 | 6033 | log.debug("writing data-in-code from 0x{x} to 0x{x}", .{ |
| 6015 | 6034 | dice_cmd.dataoff, |
| ... | ... | @@ -6026,7 +6045,8 @@ fn writeSymbolTable(self: *MachO) !void { |
| 6026 | 6045 | |
| 6027 | 6046 | const seg = &self.load_commands.items[self.linkedit_segment_cmd_index.?].segment; |
| 6028 | 6047 | const symtab = &self.load_commands.items[self.symtab_cmd_index.?].symtab; |
| 6029 | | symtab.symoff = @intCast(u32, seg.inner.fileoff + seg.inner.filesize); |
| 6048 | const symoff = mem.alignForwardGeneric(u64, seg.inner.fileoff + seg.inner.filesize, @alignOf(macho.nlist_64)); |
| 6049 | symtab.symoff = @intCast(u32, symoff); |
| 6030 | 6050 | |
| 6031 | 6051 | var locals = std.ArrayList(macho.nlist_64).init(self.base.allocator); |
| 6032 | 6052 | defer locals.deinit(); |
| ... | ... | @@ -6126,7 +6146,7 @@ fn writeSymbolTable(self: *MachO) !void { |
| 6126 | 6146 | try self.base.file.?.pwriteAll(mem.sliceAsBytes(undefs.items), undefs_off); |
| 6127 | 6147 | |
| 6128 | 6148 | symtab.nsyms = @intCast(u32, nlocals + nexports + nundefs); |
| 6129 | | seg.inner.filesize += locals_size + exports_size + undefs_size; |
| 6149 | seg.inner.filesize = symtab.symoff + symtab.nsyms * @sizeOf(macho.nlist_64) - seg.inner.fileoff; |
| 6130 | 6150 | |
| 6131 | 6151 | // Update dynamic symbol table. |
| 6132 | 6152 | const dysymtab = &self.load_commands.items[self.dysymtab_cmd_index.?].dysymtab; |
| ... | ... | @@ -6146,22 +6166,21 @@ fn writeSymbolTable(self: *MachO) !void { |
| 6146 | 6166 | const nstubs = @intCast(u32, self.stubs_table.keys().len); |
| 6147 | 6167 | const ngot_entries = @intCast(u32, self.got_entries_table.keys().len); |
| 6148 | 6168 | |
| 6149 | | dysymtab.indirectsymoff = @intCast(u32, seg.inner.fileoff + seg.inner.filesize); |
| 6169 | const indirectsymoff = mem.alignForwardGeneric(u64, seg.inner.fileoff + seg.inner.filesize, @alignOf(u64)); |
| 6170 | dysymtab.indirectsymoff = @intCast(u32, indirectsymoff); |
| 6150 | 6171 | dysymtab.nindirectsyms = nstubs * 2 + ngot_entries; |
| 6151 | 6172 | |
| 6152 | | const needed_size = dysymtab.nindirectsyms * @sizeOf(u32); |
| 6153 | | seg.inner.filesize += needed_size; |
| 6173 | seg.inner.filesize = dysymtab.indirectsymoff + dysymtab.nindirectsyms * @sizeOf(u32) - seg.inner.fileoff; |
| 6154 | 6174 | |
| 6155 | 6175 | log.debug("writing indirect symbol table from 0x{x} to 0x{x}", .{ |
| 6156 | 6176 | dysymtab.indirectsymoff, |
| 6157 | | dysymtab.indirectsymoff + needed_size, |
| 6177 | dysymtab.indirectsymoff + dysymtab.nindirectsyms * @sizeOf(u32), |
| 6158 | 6178 | }); |
| 6159 | 6179 | |
| 6160 | | var buf = try self.base.allocator.alloc(u8, needed_size); |
| 6161 | | defer self.base.allocator.free(buf); |
| 6162 | | |
| 6163 | | var stream = std.io.fixedBufferStream(buf); |
| 6164 | | var writer = stream.writer(); |
| 6180 | var buf = std.ArrayList(u8).init(self.base.allocator); |
| 6181 | defer buf.deinit(); |
| 6182 | try buf.ensureTotalCapacity(dysymtab.nindirectsyms * @sizeOf(u32)); |
| 6183 | const writer = buf.writer(); |
| 6165 | 6184 | |
| 6166 | 6185 | stubs.reserved1 = 0; |
| 6167 | 6186 | for (self.stubs_table.keys()) |key| { |
| ... | ... | @@ -6195,7 +6214,9 @@ fn writeSymbolTable(self: *MachO) !void { |
| 6195 | 6214 | } |
| 6196 | 6215 | } |
| 6197 | 6216 | |
| 6198 | | try self.base.file.?.pwriteAll(buf, dysymtab.indirectsymoff); |
| 6217 | assert(buf.items.len == dysymtab.nindirectsyms * @sizeOf(u32)); |
| 6218 | |
| 6219 | try self.base.file.?.pwriteAll(buf.items, dysymtab.indirectsymoff); |
| 6199 | 6220 | self.load_commands_dirty = true; |
| 6200 | 6221 | } |
| 6201 | 6222 | |
| ... | ... | @@ -6205,18 +6226,16 @@ fn writeStringTable(self: *MachO) !void { |
| 6205 | 6226 | |
| 6206 | 6227 | const seg = &self.load_commands.items[self.linkedit_segment_cmd_index.?].segment; |
| 6207 | 6228 | const symtab = &self.load_commands.items[self.symtab_cmd_index.?].symtab; |
| 6208 | | symtab.stroff = @intCast(u32, seg.inner.fileoff + seg.inner.filesize); |
| 6209 | | symtab.strsize = @intCast(u32, mem.alignForwardGeneric(u64, self.strtab.items.len, @alignOf(u64))); |
| 6210 | | seg.inner.filesize += symtab.strsize; |
| 6229 | const stroff = mem.alignForwardGeneric(u64, seg.inner.fileoff + seg.inner.filesize, @alignOf(u64)); |
| 6230 | const strsize = self.strtab.items.len; |
| 6231 | symtab.stroff = @intCast(u32, stroff); |
| 6232 | symtab.strsize = @intCast(u32, strsize); |
| 6233 | seg.inner.filesize = symtab.stroff + symtab.strsize - seg.inner.fileoff; |
| 6211 | 6234 | |
| 6212 | 6235 | log.debug("writing string table from 0x{x} to 0x{x}", .{ symtab.stroff, symtab.stroff + symtab.strsize }); |
| 6213 | 6236 | |
| 6214 | 6237 | try self.base.file.?.pwriteAll(self.strtab.items, symtab.stroff); |
| 6215 | 6238 | |
| 6216 | | if (symtab.strsize > self.strtab.items.len) { |
| 6217 | | // This is potentially the last section, so we need to pad it out. |
| 6218 | | try self.base.file.?.pwriteAll(&[_]u8{0}, seg.inner.fileoff + seg.inner.filesize - 1); |
| 6219 | | } |
| 6220 | 6239 | self.load_commands_dirty = true; |
| 6221 | 6240 | } |
| 6222 | 6241 | |
| ... | ... | @@ -6240,25 +6259,22 @@ fn writeCodeSignaturePadding(self: *MachO, code_sig: *CodeSignature) !void { |
| 6240 | 6259 | const tracy = trace(@src()); |
| 6241 | 6260 | defer tracy.end(); |
| 6242 | 6261 | |
| 6243 | | const linkedit_segment = &self.load_commands.items[self.linkedit_segment_cmd_index.?].segment; |
| 6244 | | const code_sig_cmd = &self.load_commands.items[self.code_signature_cmd_index.?].linkedit_data; |
| 6262 | const seg = &self.load_commands.items[self.linkedit_segment_cmd_index.?].segment; |
| 6263 | const cs_cmd = &self.load_commands.items[self.code_signature_cmd_index.?].linkedit_data; |
| 6245 | 6264 | // Code signature data has to be 16-bytes aligned for Apple tools to recognize the file |
| 6246 | 6265 | // https://github.com/opensource-apple/cctools/blob/fdb4825f303fd5c0751be524babd32958181b3ed/libstuff/checkout.c#L271 |
| 6247 | | const fileoff = mem.alignForwardGeneric(u64, linkedit_segment.inner.fileoff + linkedit_segment.inner.filesize, 16); |
| 6248 | | const padding = fileoff - (linkedit_segment.inner.fileoff + linkedit_segment.inner.filesize); |
| 6249 | | const needed_size = code_sig.estimateSize(fileoff); |
| 6250 | | code_sig_cmd.dataoff = @intCast(u32, fileoff); |
| 6251 | | code_sig_cmd.datasize = needed_size; |
| 6266 | const dataoff = mem.alignForwardGeneric(u64, seg.inner.fileoff + seg.inner.filesize, 16); |
| 6267 | const datasize = code_sig.estimateSize(dataoff); |
| 6268 | cs_cmd.dataoff = @intCast(u32, dataoff); |
| 6269 | cs_cmd.datasize = @intCast(u32, code_sig.estimateSize(dataoff)); |
| 6252 | 6270 | |
| 6253 | 6271 | // Advance size of __LINKEDIT segment |
| 6254 | | linkedit_segment.inner.filesize += needed_size + padding; |
| 6255 | | if (linkedit_segment.inner.vmsize < linkedit_segment.inner.filesize) { |
| 6256 | | linkedit_segment.inner.vmsize = mem.alignForwardGeneric(u64, linkedit_segment.inner.filesize, self.page_size); |
| 6257 | | } |
| 6258 | | log.debug("writing code signature padding from 0x{x} to 0x{x}", .{ fileoff, fileoff + needed_size }); |
| 6272 | seg.inner.filesize = cs_cmd.dataoff + cs_cmd.datasize - seg.inner.fileoff; |
| 6273 | seg.inner.vmsize = mem.alignForwardGeneric(u64, seg.inner.filesize, self.page_size); |
| 6274 | log.debug("writing code signature padding from 0x{x} to 0x{x}", .{ dataoff, dataoff + datasize }); |
| 6259 | 6275 | // Pad out the space. We need to do this to calculate valid hashes for everything in the file |
| 6260 | 6276 | // except for code signature data. |
| 6261 | | try self.base.file.?.pwriteAll(&[_]u8{0}, fileoff + needed_size - 1); |
| 6277 | try self.base.file.?.pwriteAll(&[_]u8{0}, dataoff + datasize - 1); |
| 6262 | 6278 | self.load_commands_dirty = true; |
| 6263 | 6279 | } |
| 6264 | 6280 | |