aboutsummaryrefslogtreecommitdiff
path: root/src/link/MachO/CodeSignature.zig
diff options
context:
space:
mode:
authorJakub Konka <kubkon@jakubkonka.com>2023-08-31 07:50:29 +0200
committerGitHub <noreply@github.com>2023-08-31 07:50:29 +0200
commitf4c9e19bc3213c2bc7e03d7b06d7129882f39f6c (patch)
tree79d343002bb63a44f8ab0dbac0c9f4ec54078c3a /src/link/MachO/CodeSignature.zig
parente2ff486de5f3aceb21730e1feabbaf9b03432660 (diff)
parent19a1332ca140274d03e57d31fda7748a8a3641ba (diff)
downloadzig-f4c9e19bc3213c2bc7e03d7b06d7129882f39f6c.tar.gz
zig-f4c9e19bc3213c2bc7e03d7b06d7129882f39f6c.zip
Merge pull request #17020 from ziglang/macho-versions
macho: big-ish refactor and report errors to the user using Zig's API
Diffstat (limited to 'src/link/MachO/CodeSignature.zig')
-rw-r--r--src/link/MachO/CodeSignature.zig364
1 files changed, 182 insertions, 182 deletions
diff --git a/src/link/MachO/CodeSignature.zig b/src/link/MachO/CodeSignature.zig
index f527ca3581..973d9a2591 100644
--- a/src/link/MachO/CodeSignature.zig
+++ b/src/link/MachO/CodeSignature.zig
@@ -1,17 +1,175 @@
-const CodeSignature = @This();
+page_size: u16,
+code_directory: CodeDirectory,
+requirements: ?Requirements = null,
+entitlements: ?Entitlements = null,
+signature: ?Signature = null,
-const std = @import("std");
-const assert = std.debug.assert;
-const fs = std.fs;
-const log = std.log.scoped(.link);
-const macho = std.macho;
-const mem = std.mem;
-const testing = std.testing;
+pub fn init(page_size: u16) CodeSignature {
+ return .{
+ .page_size = page_size,
+ .code_directory = CodeDirectory.init(page_size),
+ };
+}
-const Allocator = mem.Allocator;
-const Compilation = @import("../../Compilation.zig");
-const Hasher = @import("hasher.zig").ParallelHasher;
-const Sha256 = std.crypto.hash.sha2.Sha256;
+pub fn deinit(self: *CodeSignature, allocator: Allocator) void {
+ self.code_directory.deinit(allocator);
+ if (self.requirements) |*req| {
+ req.deinit(allocator);
+ }
+ if (self.entitlements) |*ents| {
+ ents.deinit(allocator);
+ }
+ if (self.signature) |*sig| {
+ sig.deinit(allocator);
+ }
+}
+
+pub fn addEntitlements(self: *CodeSignature, allocator: Allocator, path: []const u8) !void {
+ const file = try fs.cwd().openFile(path, .{});
+ defer file.close();
+ const inner = try file.readToEndAlloc(allocator, std.math.maxInt(u32));
+ self.entitlements = .{ .inner = inner };
+}
+
+pub const WriteOpts = struct {
+ file: fs.File,
+ exec_seg_base: u64,
+ exec_seg_limit: u64,
+ file_size: u32,
+ output_mode: std.builtin.OutputMode,
+};
+
+pub fn writeAdhocSignature(
+ self: *CodeSignature,
+ comp: *const Compilation,
+ opts: WriteOpts,
+ writer: anytype,
+) !void {
+ const gpa = comp.gpa;
+
+ var header: macho.SuperBlob = .{
+ .magic = macho.CSMAGIC_EMBEDDED_SIGNATURE,
+ .length = @sizeOf(macho.SuperBlob),
+ .count = 0,
+ };
+
+ var blobs = std.ArrayList(Blob).init(gpa);
+ defer blobs.deinit();
+
+ self.code_directory.inner.execSegBase = opts.exec_seg_base;
+ self.code_directory.inner.execSegLimit = opts.exec_seg_limit;
+ self.code_directory.inner.execSegFlags = if (opts.output_mode == .Exe) macho.CS_EXECSEG_MAIN_BINARY else 0;
+ self.code_directory.inner.codeLimit = opts.file_size;
+
+ const total_pages = @as(u32, @intCast(mem.alignForward(usize, opts.file_size, self.page_size) / self.page_size));
+
+ try self.code_directory.code_slots.ensureTotalCapacityPrecise(gpa, total_pages);
+ self.code_directory.code_slots.items.len = total_pages;
+ self.code_directory.inner.nCodeSlots = total_pages;
+
+ // Calculate hash for each page (in file) and write it to the buffer
+ var hasher = Hasher(Sha256){ .allocator = gpa, .thread_pool = comp.thread_pool };
+ try hasher.hash(opts.file, self.code_directory.code_slots.items, .{
+ .chunk_size = self.page_size,
+ .max_file_size = opts.file_size,
+ });
+
+ try blobs.append(.{ .code_directory = &self.code_directory });
+ header.length += @sizeOf(macho.BlobIndex);
+ header.count += 1;
+
+ var hash: [hash_size]u8 = undefined;
+
+ if (self.requirements) |*req| {
+ var buf = std.ArrayList(u8).init(gpa);
+ defer buf.deinit();
+ try req.write(buf.writer());
+ Sha256.hash(buf.items, &hash, .{});
+ self.code_directory.addSpecialHash(req.slotType(), hash);
+
+ try blobs.append(.{ .requirements = req });
+ header.count += 1;
+ header.length += @sizeOf(macho.BlobIndex) + req.size();
+ }
+
+ if (self.entitlements) |*ents| {
+ var buf = std.ArrayList(u8).init(gpa);
+ defer buf.deinit();
+ try ents.write(buf.writer());
+ Sha256.hash(buf.items, &hash, .{});
+ self.code_directory.addSpecialHash(ents.slotType(), hash);
+
+ try blobs.append(.{ .entitlements = ents });
+ header.count += 1;
+ header.length += @sizeOf(macho.BlobIndex) + ents.size();
+ }
+
+ if (self.signature) |*sig| {
+ try blobs.append(.{ .signature = sig });
+ header.count += 1;
+ header.length += @sizeOf(macho.BlobIndex) + sig.size();
+ }
+
+ self.code_directory.inner.hashOffset =
+ @sizeOf(macho.CodeDirectory) + @as(u32, @intCast(self.code_directory.ident.len + 1 + self.code_directory.inner.nSpecialSlots * hash_size));
+ self.code_directory.inner.length = self.code_directory.size();
+ header.length += self.code_directory.size();
+
+ try writer.writeIntBig(u32, header.magic);
+ try writer.writeIntBig(u32, header.length);
+ try writer.writeIntBig(u32, header.count);
+
+ var offset: u32 = @sizeOf(macho.SuperBlob) + @sizeOf(macho.BlobIndex) * @as(u32, @intCast(blobs.items.len));
+ for (blobs.items) |blob| {
+ try writer.writeIntBig(u32, blob.slotType());
+ try writer.writeIntBig(u32, offset);
+ offset += blob.size();
+ }
+
+ for (blobs.items) |blob| {
+ try blob.write(writer);
+ }
+}
+
+pub fn size(self: CodeSignature) u32 {
+ var ssize: u32 = @sizeOf(macho.SuperBlob) + @sizeOf(macho.BlobIndex) + self.code_directory.size();
+ if (self.requirements) |req| {
+ ssize += @sizeOf(macho.BlobIndex) + req.size();
+ }
+ if (self.entitlements) |ent| {
+ ssize += @sizeOf(macho.BlobIndex) + ent.size();
+ }
+ if (self.signature) |sig| {
+ ssize += @sizeOf(macho.BlobIndex) + sig.size();
+ }
+ return ssize;
+}
+
+pub fn estimateSize(self: CodeSignature, file_size: u64) u32 {
+ var ssize: u64 = @sizeOf(macho.SuperBlob) + @sizeOf(macho.BlobIndex) + self.code_directory.size();
+ // Approx code slots
+ const total_pages = mem.alignForward(u64, file_size, self.page_size) / self.page_size;
+ ssize += total_pages * hash_size;
+ var n_special_slots: u32 = 0;
+ if (self.requirements) |req| {
+ ssize += @sizeOf(macho.BlobIndex) + req.size();
+ n_special_slots = @max(n_special_slots, req.slotType());
+ }
+ if (self.entitlements) |ent| {
+ ssize += @sizeOf(macho.BlobIndex) + ent.size() + hash_size;
+ n_special_slots = @max(n_special_slots, ent.slotType());
+ }
+ if (self.signature) |sig| {
+ ssize += @sizeOf(macho.BlobIndex) + sig.size();
+ }
+ ssize += n_special_slots * hash_size;
+ return @as(u32, @intCast(mem.alignForward(u64, ssize, @sizeOf(u64))));
+}
+
+pub fn clear(self: *CodeSignature, allocator: Allocator) void {
+ self.code_directory.deinit(allocator);
+ self.code_directory = CodeDirectory.init(self.page_size);
+}
const hash_size = Sha256.digest_length;
@@ -218,175 +376,17 @@ const Signature = struct {
}
};
-page_size: u16,
-code_directory: CodeDirectory,
-requirements: ?Requirements = null,
-entitlements: ?Entitlements = null,
-signature: ?Signature = null,
-
-pub fn init(page_size: u16) CodeSignature {
- return .{
- .page_size = page_size,
- .code_directory = CodeDirectory.init(page_size),
- };
-}
-
-pub fn deinit(self: *CodeSignature, allocator: Allocator) void {
- self.code_directory.deinit(allocator);
- if (self.requirements) |*req| {
- req.deinit(allocator);
- }
- if (self.entitlements) |*ents| {
- ents.deinit(allocator);
- }
- if (self.signature) |*sig| {
- sig.deinit(allocator);
- }
-}
-
-pub fn addEntitlements(self: *CodeSignature, allocator: Allocator, path: []const u8) !void {
- const file = try fs.cwd().openFile(path, .{});
- defer file.close();
- const inner = try file.readToEndAlloc(allocator, std.math.maxInt(u32));
- self.entitlements = .{ .inner = inner };
-}
-
-pub const WriteOpts = struct {
- file: fs.File,
- exec_seg_base: u64,
- exec_seg_limit: u64,
- file_size: u32,
- output_mode: std.builtin.OutputMode,
-};
-
-pub fn writeAdhocSignature(
- self: *CodeSignature,
- comp: *const Compilation,
- opts: WriteOpts,
- writer: anytype,
-) !void {
- const gpa = comp.gpa;
-
- var header: macho.SuperBlob = .{
- .magic = macho.CSMAGIC_EMBEDDED_SIGNATURE,
- .length = @sizeOf(macho.SuperBlob),
- .count = 0,
- };
-
- var blobs = std.ArrayList(Blob).init(gpa);
- defer blobs.deinit();
-
- self.code_directory.inner.execSegBase = opts.exec_seg_base;
- self.code_directory.inner.execSegLimit = opts.exec_seg_limit;
- self.code_directory.inner.execSegFlags = if (opts.output_mode == .Exe) macho.CS_EXECSEG_MAIN_BINARY else 0;
- self.code_directory.inner.codeLimit = opts.file_size;
-
- const total_pages = @as(u32, @intCast(mem.alignForward(usize, opts.file_size, self.page_size) / self.page_size));
-
- try self.code_directory.code_slots.ensureTotalCapacityPrecise(gpa, total_pages);
- self.code_directory.code_slots.items.len = total_pages;
- self.code_directory.inner.nCodeSlots = total_pages;
-
- // Calculate hash for each page (in file) and write it to the buffer
- var hasher = Hasher(Sha256){ .allocator = gpa, .thread_pool = comp.thread_pool };
- try hasher.hash(opts.file, self.code_directory.code_slots.items, .{
- .chunk_size = self.page_size,
- .max_file_size = opts.file_size,
- });
-
- try blobs.append(.{ .code_directory = &self.code_directory });
- header.length += @sizeOf(macho.BlobIndex);
- header.count += 1;
-
- var hash: [hash_size]u8 = undefined;
-
- if (self.requirements) |*req| {
- var buf = std.ArrayList(u8).init(gpa);
- defer buf.deinit();
- try req.write(buf.writer());
- Sha256.hash(buf.items, &hash, .{});
- self.code_directory.addSpecialHash(req.slotType(), hash);
-
- try blobs.append(.{ .requirements = req });
- header.count += 1;
- header.length += @sizeOf(macho.BlobIndex) + req.size();
- }
-
- if (self.entitlements) |*ents| {
- var buf = std.ArrayList(u8).init(gpa);
- defer buf.deinit();
- try ents.write(buf.writer());
- Sha256.hash(buf.items, &hash, .{});
- self.code_directory.addSpecialHash(ents.slotType(), hash);
-
- try blobs.append(.{ .entitlements = ents });
- header.count += 1;
- header.length += @sizeOf(macho.BlobIndex) + ents.size();
- }
-
- if (self.signature) |*sig| {
- try blobs.append(.{ .signature = sig });
- header.count += 1;
- header.length += @sizeOf(macho.BlobIndex) + sig.size();
- }
-
- self.code_directory.inner.hashOffset =
- @sizeOf(macho.CodeDirectory) + @as(u32, @intCast(self.code_directory.ident.len + 1 + self.code_directory.inner.nSpecialSlots * hash_size));
- self.code_directory.inner.length = self.code_directory.size();
- header.length += self.code_directory.size();
-
- try writer.writeIntBig(u32, header.magic);
- try writer.writeIntBig(u32, header.length);
- try writer.writeIntBig(u32, header.count);
-
- var offset: u32 = @sizeOf(macho.SuperBlob) + @sizeOf(macho.BlobIndex) * @as(u32, @intCast(blobs.items.len));
- for (blobs.items) |blob| {
- try writer.writeIntBig(u32, blob.slotType());
- try writer.writeIntBig(u32, offset);
- offset += blob.size();
- }
-
- for (blobs.items) |blob| {
- try blob.write(writer);
- }
-}
-
-pub fn size(self: CodeSignature) u32 {
- var ssize: u32 = @sizeOf(macho.SuperBlob) + @sizeOf(macho.BlobIndex) + self.code_directory.size();
- if (self.requirements) |req| {
- ssize += @sizeOf(macho.BlobIndex) + req.size();
- }
- if (self.entitlements) |ent| {
- ssize += @sizeOf(macho.BlobIndex) + ent.size();
- }
- if (self.signature) |sig| {
- ssize += @sizeOf(macho.BlobIndex) + sig.size();
- }
- return ssize;
-}
+const CodeSignature = @This();
-pub fn estimateSize(self: CodeSignature, file_size: u64) u32 {
- var ssize: u64 = @sizeOf(macho.SuperBlob) + @sizeOf(macho.BlobIndex) + self.code_directory.size();
- // Approx code slots
- const total_pages = mem.alignForward(u64, file_size, self.page_size) / self.page_size;
- ssize += total_pages * hash_size;
- var n_special_slots: u32 = 0;
- if (self.requirements) |req| {
- ssize += @sizeOf(macho.BlobIndex) + req.size();
- n_special_slots = @max(n_special_slots, req.slotType());
- }
- if (self.entitlements) |ent| {
- ssize += @sizeOf(macho.BlobIndex) + ent.size() + hash_size;
- n_special_slots = @max(n_special_slots, ent.slotType());
- }
- if (self.signature) |sig| {
- ssize += @sizeOf(macho.BlobIndex) + sig.size();
- }
- ssize += n_special_slots * hash_size;
- return @as(u32, @intCast(mem.alignForward(u64, ssize, @sizeOf(u64))));
-}
+const std = @import("std");
+const assert = std.debug.assert;
+const fs = std.fs;
+const log = std.log.scoped(.link);
+const macho = std.macho;
+const mem = std.mem;
+const testing = std.testing;
-pub fn clear(self: *CodeSignature, allocator: Allocator) void {
- self.code_directory.deinit(allocator);
- self.code_directory = CodeDirectory.init(self.page_size);
-}
+const Allocator = mem.Allocator;
+const Compilation = @import("../../Compilation.zig");
+const Hasher = @import("hasher.zig").ParallelHasher;
+const Sha256 = std.crypto.hash.sha2.Sha256;