aboutsummaryrefslogtreecommitdiff
path: root/src/link/MachO/CodeSignature.zig
diff options
context:
space:
mode:
authorJakub Konka <kubkon@jakubkonka.com>2020-11-28 14:51:31 +0100
committerJakub Konka <kubkon@jakubkonka.com>2020-12-01 10:49:31 +0100
commitc25b3593e726108cb7f208ef538df6979aeb41e1 (patch)
tree27f8d6d0e77f694fae18cb460c57cafdf2cb7e63 /src/link/MachO/CodeSignature.zig
parent545721ccd1e7297719fc53dfde99fa046fb3edef (diff)
downloadzig-c25b3593e726108cb7f208ef538df6979aeb41e1.tar.gz
zig-c25b3593e726108cb7f208ef538df6979aeb41e1.zip
lld: add code signature to lld output
Diffstat (limited to 'src/link/MachO/CodeSignature.zig')
-rw-r--r--src/link/MachO/CodeSignature.zig77
1 files changed, 77 insertions, 0 deletions
diff --git a/src/link/MachO/CodeSignature.zig b/src/link/MachO/CodeSignature.zig
index 6262315eb8..1cef7803f5 100644
--- a/src/link/MachO/CodeSignature.zig
+++ b/src/link/MachO/CodeSignature.zig
@@ -2,6 +2,7 @@ const CodeSignature = @This();
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;
@@ -65,6 +66,82 @@ pub fn init(alloc: *Allocator) CodeSignature {
};
}
+pub fn calcAdhocSignatureFile(
+ self: *CodeSignature,
+ file: fs.File,
+ id: []const u8,
+ text_segment: macho.segment_command_64,
+ code_sig_cmd: macho.linkedit_data_command,
+ output_mode: std.builtin.OutputMode,
+) !void {
+ const execSegBase: u64 = text_segment.fileoff;
+ const execSegLimit: u64 = text_segment.filesize;
+ const execSegFlags: u64 = if (output_mode == .Exe) macho.CS_EXECSEG_MAIN_BINARY else 0;
+ const file_size = code_sig_cmd.dataoff;
+ var cdir = CodeDirectory{
+ .inner = .{
+ .magic = macho.CSMAGIC_CODEDIRECTORY,
+ .length = @sizeOf(macho.CodeDirectory),
+ .version = macho.CS_SUPPORTSEXECSEG,
+ .flags = macho.CS_ADHOC,
+ .hashOffset = 0,
+ .identOffset = 0,
+ .nSpecialSlots = 0,
+ .nCodeSlots = 0,
+ .codeLimit = @intCast(u32, file_size),
+ .hashSize = hash_size,
+ .hashType = macho.CS_HASHTYPE_SHA256,
+ .platform = 0,
+ .pageSize = @truncate(u8, std.math.log2(page_size)),
+ .spare2 = 0,
+ .scatterOffset = 0,
+ .teamOffset = 0,
+ .spare3 = 0,
+ .codeLimit64 = 0,
+ .execSegBase = execSegBase,
+ .execSegLimit = execSegLimit,
+ .execSegFlags = execSegFlags,
+ },
+ };
+
+ const total_pages = mem.alignForward(file_size, page_size) / page_size;
+
+ var hash: [hash_size]u8 = undefined;
+ var buffer = try self.alloc.alloc(u8, page_size);
+ defer self.alloc.free(buffer);
+
+ try cdir.data.ensureCapacity(self.alloc, total_pages * hash_size + id.len + 1);
+
+ // 1. Save the identifier and update offsets
+ cdir.inner.identOffset = cdir.inner.length;
+ cdir.data.appendSliceAssumeCapacity(id);
+ cdir.data.appendAssumeCapacity(0);
+
+ // 2. Calculate hash for each page (in file) and write it to the buffer
+ // TODO figure out how we can cache several hashes since we won't update
+ // every page during incremental linking
+ cdir.inner.hashOffset = cdir.inner.identOffset + @intCast(u32, id.len) + 1;
+ var i: usize = 0;
+ while (i < total_pages) : (i += 1) {
+ const fstart = i * page_size;
+ const fsize = if (fstart + page_size > file_size) file_size - fstart else page_size;
+ const len = try file.preadAll(buffer, fstart);
+ assert(fsize <= len);
+
+ Sha256.hash(buffer[0..fsize], &hash, .{});
+
+ cdir.data.appendSliceAssumeCapacity(hash[0..]);
+ cdir.inner.nCodeSlots += 1;
+ }
+
+ // 3. Update CodeDirectory length
+ cdir.inner.length += @intCast(u32, cdir.data.items.len);
+
+ self.inner.length += @sizeOf(macho.BlobIndex) + cdir.size();
+ self.inner.count = 1;
+ self.cdir = cdir;
+}
+
pub fn calcAdhocSignature(self: *CodeSignature, bin_file: *const MachO) !void {
const text_segment = bin_file.load_commands.items[bin_file.text_segment_cmd_index.?].Segment;
const code_sig_cmd = bin_file.load_commands.items[bin_file.code_signature_cmd_index.?].LinkeditData;