authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-10-23 11:35:03-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-10-23 11:35:03-07:00
loga3033c7bd9ec26abd2f831cf75eb85f06590deed
tree4b293310f5f669efbc00e14fa6e92656a509a15a
parent0ae60f7236e4da0c234f59f3671f742695d54905
parent2f37278540e4783a236a2c095fc905e613fccf1d
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #13267 from ziglang/macho-threaded-sha256

link.MachO: multi-thread first round of sha256 hashing

3 files changed, 64 insertions(+), 30 deletions(-)

src/link/MachO.zig+3-3
......@@ -625,7 +625,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No
625625 try self.writeHeader(ncmds, @intCast(u32, lc_buffer.items.len + headers_buf.items.len));
626626
627627 if (codesig) |*csig| {
628 try self.writeCodeSignature(csig, codesig_offset.?); // code signing always comes last
628 try self.writeCodeSignature(comp, csig, codesig_offset.?); // code signing always comes last
629629 }
630630
631631 if (self.d_sym) |*d_sym| {
......@@ -4037,13 +4037,13 @@ fn writeCodeSignaturePadding(
40374037 return @intCast(u32, offset);
40384038}
40394039
4040fn writeCodeSignature(self: *MachO, code_sig: *CodeSignature, offset: u32) !void {
4040fn writeCodeSignature(self: *MachO, comp: *const Compilation, code_sig: *CodeSignature, offset: u32) !void {
40414041 const seg = self.getSegment(self.text_section_index.?);
40424042
40434043 var buffer = std.ArrayList(u8).init(self.base.allocator);
40444044 defer buffer.deinit();
40454045 try buffer.ensureTotalCapacityPrecise(code_sig.size());
4046 try code_sig.writeAdhocSignature(self.base.allocator, .{
4046 try code_sig.writeAdhocSignature(comp, .{
40474047 .file = self.base.file.?,
40484048 .exec_seg_base = seg.fileoff,
40494049 .exec_seg_limit = seg.filesize,
src/link/MachO/CodeSignature.zig+53-24
......@@ -1,4 +1,6 @@
11const CodeSignature = @This();
2const Compilation = @import("../../Compilation.zig");
3const WaitGroup = @import("../../WaitGroup.zig");
24
35const std = @import("std");
46const assert = std.debug.assert;
......@@ -258,17 +260,19 @@ pub const WriteOpts = struct {
258260
259261pub fn writeAdhocSignature(
260262 self: *CodeSignature,
261 allocator: Allocator,
263 comp: *const Compilation,
262264 opts: WriteOpts,
263265 writer: anytype,
264266) !void {
267 const gpa = comp.gpa;
268
265269 var header: macho.SuperBlob = .{
266270 .magic = macho.CSMAGIC_EMBEDDED_SIGNATURE,
267271 .length = @sizeOf(macho.SuperBlob),
268272 .count = 0,
269273 };
270274
271 var blobs = std.ArrayList(Blob).init(allocator);
275 var blobs = std.ArrayList(Blob).init(gpa);
272276 defer blobs.deinit();
273277
274278 self.code_directory.inner.execSegBase = opts.exec_seg_base;
......@@ -276,37 +280,49 @@ pub fn writeAdhocSignature(
276280 self.code_directory.inner.execSegFlags = if (opts.output_mode == .Exe) macho.CS_EXECSEG_MAIN_BINARY else 0;
277281 self.code_directory.inner.codeLimit = opts.file_size;
278282
279 const total_pages = mem.alignForward(opts.file_size, self.page_size) / self.page_size;
280
281 var buffer = try allocator.alloc(u8, self.page_size);
282 defer allocator.free(buffer);
283 const total_pages = @intCast(u32, mem.alignForward(opts.file_size, self.page_size) / self.page_size);
283284
284 try self.code_directory.code_slots.ensureTotalCapacityPrecise(allocator, total_pages);
285 try self.code_directory.code_slots.ensureTotalCapacityPrecise(gpa, total_pages);
286 self.code_directory.code_slots.items.len = total_pages;
287 self.code_directory.inner.nCodeSlots = total_pages;
285288
286289 // Calculate hash for each page (in file) and write it to the buffer
287 var hash: [hash_size]u8 = undefined;
288 var i: usize = 0;
289 while (i < total_pages) : (i += 1) {
290 const fstart = i * self.page_size;
291 const fsize = if (fstart + self.page_size > opts.file_size)
292 opts.file_size - fstart
293 else
294 self.page_size;
295 const len = try opts.file.preadAll(buffer, fstart);
296 assert(fsize <= len);
297
298 Sha256.hash(buffer[0..fsize], &hash, .{});
299
300 self.code_directory.code_slots.appendAssumeCapacity(hash);
301 self.code_directory.inner.nCodeSlots += 1;
290 var wg: WaitGroup = .{};
291 {
292 const buffer = try gpa.alloc(u8, self.page_size * total_pages);
293 defer gpa.free(buffer);
294
295 const results = try gpa.alloc(fs.File.PReadError!usize, total_pages);
296 defer gpa.free(results);
297 {
298 wg.reset();
299 defer wg.wait();
300
301 var i: usize = 0;
302 while (i < total_pages) : (i += 1) {
303 const fstart = i * self.page_size;
304 const fsize = if (fstart + self.page_size > opts.file_size)
305 opts.file_size - fstart
306 else
307 self.page_size;
308 const out_hash = &self.code_directory.code_slots.items[i];
309 wg.start();
310 try comp.thread_pool.spawn(workerSha256Hash, .{
311 opts.file, fstart, buffer[fstart..][0..fsize], out_hash, &results[i], &wg,
312 });
313 }
314 }
315 for (results) |result| _ = try result;
302316 }
303317
304318 try blobs.append(.{ .code_directory = &self.code_directory });
305319 header.length += @sizeOf(macho.BlobIndex);
306320 header.count += 1;
307321
322 var hash: [hash_size]u8 = undefined;
323
308324 if (self.requirements) |*req| {
309 var buf = std.ArrayList(u8).init(allocator);
325 var buf = std.ArrayList(u8).init(gpa);
310326 defer buf.deinit();
311327 try req.write(buf.writer());
312328 Sha256.hash(buf.items, &hash, .{});
......@@ -318,7 +334,7 @@ pub fn writeAdhocSignature(
318334 }
319335
320336 if (self.entitlements) |*ents| {
321 var buf = std.ArrayList(u8).init(allocator);
337 var buf = std.ArrayList(u8).init(gpa);
322338 defer buf.deinit();
323339 try ents.write(buf.writer());
324340 Sha256.hash(buf.items, &hash, .{});
......@@ -356,6 +372,19 @@ pub fn writeAdhocSignature(
356372 }
357373}
358374
375fn workerSha256Hash(
376 file: fs.File,
377 fstart: usize,
378 buffer: []u8,
379 hash: *[hash_size]u8,
380 err: *fs.File.PReadError!usize,
381 wg: *WaitGroup,
382) void {
383 defer wg.finish();
384 err.* = file.preadAll(buffer, fstart);
385 Sha256.hash(buffer, hash, .{});
386}
387
359388pub fn size(self: CodeSignature) u32 {
360389 var ssize: u32 = @sizeOf(macho.SuperBlob) + @sizeOf(macho.BlobIndex) + self.code_directory.size();
361390 if (self.requirements) |req| {
src/link/MachO/zld.zig+8-3
......@@ -3035,14 +3035,19 @@ pub const Zld = struct {
30353035 return @intCast(u32, offset);
30363036 }
30373037
3038 fn writeCodeSignature(self: *Zld, code_sig: *CodeSignature, offset: u32) !void {
3038 fn writeCodeSignature(
3039 self: *Zld,
3040 comp: *const Compilation,
3041 code_sig: *CodeSignature,
3042 offset: u32,
3043 ) !void {
30393044 const seg_id = self.getSegmentByName("__TEXT").?;
30403045 const seg = self.segments.items[seg_id];
30413046
30423047 var buffer = std.ArrayList(u8).init(self.gpa);
30433048 defer buffer.deinit();
30443049 try buffer.ensureTotalCapacityPrecise(code_sig.size());
3045 try code_sig.writeAdhocSignature(self.gpa, .{
3050 try code_sig.writeAdhocSignature(comp, .{
30463051 .file = self.file,
30473052 .exec_seg_base = seg.fileoff,
30483053 .exec_seg_limit = seg.filesize,
......@@ -4379,7 +4384,7 @@ pub fn linkWithZld(macho_file: *MachO, comp: *Compilation, prog_node: *std.Progr
43794384 try zld.writeHeader(ncmds, @intCast(u32, lc_buffer.items.len + headers_buf.items.len));
43804385
43814386 if (codesig) |*csig| {
4382 try zld.writeCodeSignature(csig, codesig_offset.?); // code signing always comes last
4387 try zld.writeCodeSignature(comp, csig, codesig_offset.?); // code signing always comes last
43834388 }
43844389 }
43854390