| ... | @@ -1,4 +1,6 @@ | ... | @@ -1,4 +1,6 @@ |
| 1 | const CodeSignature = @This(); | 1 | const CodeSignature = @This(); |
| | 2 | const Compilation = @import("../../Compilation.zig"); |
| | 3 | const WaitGroup = @import("../../WaitGroup.zig"); |
| 2 | | 4 | |
| 3 | const std = @import("std"); | 5 | const std = @import("std"); |
| 4 | const assert = std.debug.assert; | 6 | const assert = std.debug.assert; |
| ... | @@ -258,17 +260,19 @@ pub const WriteOpts = struct { | ... | @@ -258,17 +260,19 @@ pub const WriteOpts = struct { |
| 258 | | 260 | |
| 259 | pub fn writeAdhocSignature( | 261 | pub fn writeAdhocSignature( |
| 260 | self: *CodeSignature, | 262 | self: *CodeSignature, |
| 261 | allocator: Allocator, | 263 | comp: *const Compilation, |
| 262 | opts: WriteOpts, | 264 | opts: WriteOpts, |
| 263 | writer: anytype, | 265 | writer: anytype, |
| 264 | ) !void { | 266 | ) !void { |
| | 267 | const gpa = comp.gpa; |
| | 268 | |
| 265 | var header: macho.SuperBlob = .{ | 269 | var header: macho.SuperBlob = .{ |
| 266 | .magic = macho.CSMAGIC_EMBEDDED_SIGNATURE, | 270 | .magic = macho.CSMAGIC_EMBEDDED_SIGNATURE, |
| 267 | .length = @sizeOf(macho.SuperBlob), | 271 | .length = @sizeOf(macho.SuperBlob), |
| 268 | .count = 0, | 272 | .count = 0, |
| 269 | }; | 273 | }; |
| 270 | | 274 | |
| 271 | var blobs = std.ArrayList(Blob).init(allocator); | 275 | var blobs = std.ArrayList(Blob).init(gpa); |
| 272 | defer blobs.deinit(); | 276 | defer blobs.deinit(); |
| 273 | | 277 | |
| 274 | self.code_directory.inner.execSegBase = opts.exec_seg_base; | 278 | self.code_directory.inner.execSegBase = opts.exec_seg_base; |
| ... | @@ -276,37 +280,49 @@ pub fn writeAdhocSignature( | ... | @@ -276,37 +280,49 @@ pub fn writeAdhocSignature( |
| 276 | self.code_directory.inner.execSegFlags = if (opts.output_mode == .Exe) macho.CS_EXECSEG_MAIN_BINARY else 0; | 280 | self.code_directory.inner.execSegFlags = if (opts.output_mode == .Exe) macho.CS_EXECSEG_MAIN_BINARY else 0; |
| 277 | self.code_directory.inner.codeLimit = opts.file_size; | 281 | self.code_directory.inner.codeLimit = opts.file_size; |
| 278 | | 282 | |
| 279 | const total_pages = mem.alignForward(opts.file_size, self.page_size) / self.page_size; | 283 | const total_pages = @intCast(u32, 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 | | 284 | |
| 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; |
| 285 | | 288 | |
| 286 | // Calculate hash for each page (in file) and write it to the buffer | 289 | // Calculate hash for each page (in file) and write it to the buffer |
| 287 | var hash: [hash_size]u8 = undefined; | 290 | var wg: WaitGroup = .{}; |
| 288 | var i: usize = 0; | 291 | { |
| 289 | while (i < total_pages) : (i += 1) { | 292 | const buffer = try gpa.alloc(u8, self.page_size * total_pages); |
| 290 | const fstart = i * self.page_size; | 293 | defer gpa.free(buffer); |
| 291 | const fsize = if (fstart + self.page_size > opts.file_size) | 294 | |
| 292 | opts.file_size - fstart | 295 | const results = try gpa.alloc(fs.File.PReadError!usize, total_pages); |
| 293 | else | 296 | defer gpa.free(results); |
| 294 | self.page_size; | 297 | { |
| 295 | const len = try opts.file.preadAll(buffer, fstart); | 298 | wg.reset(); |
| 296 | assert(fsize <= len); | 299 | defer wg.wait(); |
| 297 | | 300 | |
| 298 | Sha256.hash(buffer[0..fsize], &hash, .{}); | 301 | var i: usize = 0; |
| 299 | | 302 | while (i < total_pages) : (i += 1) { |
| 300 | self.code_directory.code_slots.appendAssumeCapacity(hash); | 303 | const fstart = i * self.page_size; |
| 301 | self.code_directory.inner.nCodeSlots += 1; | 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; |
| 302 | } | 316 | } |
| 303 | | 317 | |
| 304 | try blobs.append(.{ .code_directory = &self.code_directory }); | 318 | try blobs.append(.{ .code_directory = &self.code_directory }); |
| 305 | header.length += @sizeOf(macho.BlobIndex); | 319 | header.length += @sizeOf(macho.BlobIndex); |
| 306 | header.count += 1; | 320 | header.count += 1; |
| 307 | | 321 | |
| | 322 | var hash: [hash_size]u8 = undefined; |
| | 323 | |
| 308 | if (self.requirements) |*req| { | 324 | if (self.requirements) |*req| { |
| 309 | var buf = std.ArrayList(u8).init(allocator); | 325 | var buf = std.ArrayList(u8).init(gpa); |
| 310 | defer buf.deinit(); | 326 | defer buf.deinit(); |
| 311 | try req.write(buf.writer()); | 327 | try req.write(buf.writer()); |
| 312 | Sha256.hash(buf.items, &hash, .{}); | 328 | Sha256.hash(buf.items, &hash, .{}); |
| ... | @@ -318,7 +334,7 @@ pub fn writeAdhocSignature( | ... | @@ -318,7 +334,7 @@ pub fn writeAdhocSignature( |
| 318 | } | 334 | } |
| 319 | | 335 | |
| 320 | if (self.entitlements) |*ents| { | 336 | if (self.entitlements) |*ents| { |
| 321 | var buf = std.ArrayList(u8).init(allocator); | 337 | var buf = std.ArrayList(u8).init(gpa); |
| 322 | defer buf.deinit(); | 338 | defer buf.deinit(); |
| 323 | try ents.write(buf.writer()); | 339 | try ents.write(buf.writer()); |
| 324 | Sha256.hash(buf.items, &hash, .{}); | 340 | Sha256.hash(buf.items, &hash, .{}); |
| ... | @@ -356,6 +372,19 @@ pub fn writeAdhocSignature( | ... | @@ -356,6 +372,19 @@ pub fn writeAdhocSignature( |
| 356 | } | 372 | } |
| 357 | } | 373 | } |
| 358 | | 374 | |
| | 375 | fn 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 | |
| 359 | pub fn size(self: CodeSignature) u32 { | 388 | pub fn size(self: CodeSignature) u32 { |
| 360 | var ssize: u32 = @sizeOf(macho.SuperBlob) + @sizeOf(macho.BlobIndex) + self.code_directory.size(); | 389 | var ssize: u32 = @sizeOf(macho.SuperBlob) + @sizeOf(macho.BlobIndex) + self.code_directory.size(); |
| 361 | if (self.requirements) |req| { | 390 | if (self.requirements) |req| { |