| ... | ... | @@ -10,8 +10,6 @@ const testing = std.testing; |
| 10 | 10 | const Allocator = mem.Allocator; |
| 11 | 11 | const Sha256 = std.crypto.hash.sha2.Sha256; |
| 12 | 12 | |
| 13 | | const MachO = @import("../MachO.zig"); |
| 14 | | |
| 15 | 13 | const hash_size: u8 = 32; |
| 16 | 14 | const page_size: u16 = 0x1000; |
| 17 | 15 | |
| ... | ... | @@ -52,7 +50,7 @@ const CodeDirectory = struct { |
| 52 | 50 | } |
| 53 | 51 | }; |
| 54 | 52 | |
| 55 | | alloc: *Allocator, |
| 53 | allocator: *Allocator, |
| 56 | 54 | inner: macho.SuperBlob = .{ |
| 57 | 55 | .magic = macho.CSMAGIC_EMBEDDED_SIGNATURE, |
| 58 | 56 | .length = @sizeOf(macho.SuperBlob), |
| ... | ... | @@ -60,13 +58,11 @@ inner: macho.SuperBlob = .{ |
| 60 | 58 | }, |
| 61 | 59 | cdir: ?CodeDirectory = null, |
| 62 | 60 | |
| 63 | | pub fn init(alloc: *Allocator) CodeSignature { |
| 64 | | return .{ |
| 65 | | .alloc = alloc, |
| 66 | | }; |
| 61 | pub fn init(allocator: *Allocator) CodeSignature { |
| 62 | return .{ .allocator = allocator }; |
| 67 | 63 | } |
| 68 | 64 | |
| 69 | | pub fn calcAdhocSignatureFile( |
| 65 | pub fn calcAdhocSignature( |
| 70 | 66 | self: *CodeSignature, |
| 71 | 67 | file: fs.File, |
| 72 | 68 | id: []const u8, |
| ... | ... | @@ -107,10 +103,10 @@ pub fn calcAdhocSignatureFile( |
| 107 | 103 | const total_pages = mem.alignForward(file_size, page_size) / page_size; |
| 108 | 104 | |
| 109 | 105 | var hash: [hash_size]u8 = undefined; |
| 110 | | var buffer = try self.alloc.alloc(u8, page_size); |
| 111 | | defer self.alloc.free(buffer); |
| 106 | var buffer = try self.allocator.alloc(u8, page_size); |
| 107 | defer self.allocator.free(buffer); |
| 112 | 108 | |
| 113 | | try cdir.data.ensureCapacity(self.alloc, total_pages * hash_size + id.len + 1); |
| 109 | try cdir.data.ensureCapacity(self.allocator, total_pages * hash_size + id.len + 1); |
| 114 | 110 | |
| 115 | 111 | // 1. Save the identifier and update offsets |
| 116 | 112 | cdir.inner.identOffset = cdir.inner.length; |
| ... | ... | @@ -142,80 +138,6 @@ pub fn calcAdhocSignatureFile( |
| 142 | 138 | self.cdir = cdir; |
| 143 | 139 | } |
| 144 | 140 | |
| 145 | | pub fn calcAdhocSignature(self: *CodeSignature, bin_file: *const MachO) !void { |
| 146 | | const text_segment = bin_file.load_commands.items[bin_file.text_segment_cmd_index.?].Segment; |
| 147 | | const code_sig_cmd = bin_file.load_commands.items[bin_file.code_signature_cmd_index.?].LinkeditData; |
| 148 | | |
| 149 | | const execSegBase: u64 = text_segment.inner.fileoff; |
| 150 | | const execSegLimit: u64 = text_segment.inner.filesize; |
| 151 | | const execSegFlags: u64 = if (bin_file.base.options.output_mode == .Exe) macho.CS_EXECSEG_MAIN_BINARY else 0; |
| 152 | | const file_size = code_sig_cmd.dataoff; |
| 153 | | var cdir = CodeDirectory{ |
| 154 | | .inner = .{ |
| 155 | | .magic = macho.CSMAGIC_CODEDIRECTORY, |
| 156 | | .length = @sizeOf(macho.CodeDirectory), |
| 157 | | .version = macho.CS_SUPPORTSEXECSEG, |
| 158 | | .flags = macho.CS_ADHOC, |
| 159 | | .hashOffset = 0, |
| 160 | | .identOffset = 0, |
| 161 | | .nSpecialSlots = 0, |
| 162 | | .nCodeSlots = 0, |
| 163 | | .codeLimit = @intCast(u32, file_size), |
| 164 | | .hashSize = hash_size, |
| 165 | | .hashType = macho.CS_HASHTYPE_SHA256, |
| 166 | | .platform = 0, |
| 167 | | .pageSize = @truncate(u8, std.math.log2(page_size)), |
| 168 | | .spare2 = 0, |
| 169 | | .scatterOffset = 0, |
| 170 | | .teamOffset = 0, |
| 171 | | .spare3 = 0, |
| 172 | | .codeLimit64 = 0, |
| 173 | | .execSegBase = execSegBase, |
| 174 | | .execSegLimit = execSegLimit, |
| 175 | | .execSegFlags = execSegFlags, |
| 176 | | }, |
| 177 | | }; |
| 178 | | |
| 179 | | const total_pages = mem.alignForward(file_size, page_size) / page_size; |
| 180 | | |
| 181 | | var hash: [hash_size]u8 = undefined; |
| 182 | | var buffer = try bin_file.base.allocator.alloc(u8, page_size); |
| 183 | | defer bin_file.base.allocator.free(buffer); |
| 184 | | const macho_file = bin_file.base.file.?; |
| 185 | | |
| 186 | | const id = bin_file.base.options.emit.?.sub_path; |
| 187 | | try cdir.data.ensureCapacity(self.alloc, total_pages * hash_size + id.len + 1); |
| 188 | | |
| 189 | | // 1. Save the identifier and update offsets |
| 190 | | cdir.inner.identOffset = cdir.inner.length; |
| 191 | | cdir.data.appendSliceAssumeCapacity(id); |
| 192 | | cdir.data.appendAssumeCapacity(0); |
| 193 | | |
| 194 | | // 2. Calculate hash for each page (in file) and write it to the buffer |
| 195 | | // TODO figure out how we can cache several hashes since we won't update |
| 196 | | // every page during incremental linking |
| 197 | | cdir.inner.hashOffset = cdir.inner.identOffset + @intCast(u32, id.len) + 1; |
| 198 | | var i: usize = 0; |
| 199 | | while (i < total_pages) : (i += 1) { |
| 200 | | const fstart = i * page_size; |
| 201 | | const fsize = if (fstart + page_size > file_size) file_size - fstart else page_size; |
| 202 | | const len = try macho_file.preadAll(buffer, fstart); |
| 203 | | assert(fsize <= len); |
| 204 | | |
| 205 | | Sha256.hash(buffer[0..fsize], &hash, .{}); |
| 206 | | |
| 207 | | cdir.data.appendSliceAssumeCapacity(hash[0..]); |
| 208 | | cdir.inner.nCodeSlots += 1; |
| 209 | | } |
| 210 | | |
| 211 | | // 3. Update CodeDirectory length |
| 212 | | cdir.inner.length += @intCast(u32, cdir.data.items.len); |
| 213 | | |
| 214 | | self.inner.length += @sizeOf(macho.BlobIndex) + cdir.size(); |
| 215 | | self.inner.count = 1; |
| 216 | | self.cdir = cdir; |
| 217 | | } |
| 218 | | |
| 219 | 141 | pub fn size(self: CodeSignature) u32 { |
| 220 | 142 | return self.inner.length; |
| 221 | 143 | } |
| ... | ... | @@ -230,7 +152,7 @@ pub fn write(self: CodeSignature, buffer: []u8) void { |
| 230 | 152 | |
| 231 | 153 | pub fn deinit(self: *CodeSignature) void { |
| 232 | 154 | if (self.cdir) |*cdir| { |
| 233 | | cdir.data.deinit(self.alloc); |
| 155 | cdir.data.deinit(self.allocator); |
| 234 | 156 | } |
| 235 | 157 | } |
| 236 | 158 | |