| ... | @@ -110,6 +110,8 @@ main_cmd_index: ?u16 = null, | ... | @@ -110,6 +110,8 @@ main_cmd_index: ?u16 = null, |
| 110 | version_min_cmd_index: ?u16 = null, | 110 | version_min_cmd_index: ?u16 = null, |
| 111 | /// Source version | 111 | /// Source version |
| 112 | source_version_cmd_index: ?u16 = null, | 112 | source_version_cmd_index: ?u16 = null, |
| | 113 | /// Code signature |
| | 114 | code_signature_cmd_index: ?u16 = null, |
| 113 | | 115 | |
| 114 | /// Table of all sections | 116 | /// Table of all sections |
| 115 | sections: std.ArrayListUnmanaged(macho.section_64) = .{}, | 117 | sections: std.ArrayListUnmanaged(macho.section_64) = .{}, |
| ... | @@ -401,6 +403,15 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void { | ... | @@ -401,6 +403,15 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void { |
| 401 | | 403 | |
| 402 | // TODO remove when we add our own codesigning mechanism | 404 | // TODO remove when we add our own codesigning mechanism |
| 403 | try self.writeStringTable(); | 405 | try self.writeStringTable(); |
| | 406 | try self.codeSign(); |
| | 407 | |
| | 408 | { |
| | 409 | // TODO rework how we preallocate space for the entire __LINKEDIT segment instead of |
| | 410 | // doing dynamic updates like this. |
| | 411 | const linkedit = &self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment; |
| | 412 | const code_sig = &self.load_commands.items[self.code_signature_cmd_index.?].LinkeditData; |
| | 413 | linkedit.filesize = code_sig.dataoff + code_sig.datasize - linkedit.fileoff; |
| | 414 | } |
| 404 | | 415 | |
| 405 | if (self.cmd_table_dirty) { | 416 | if (self.cmd_table_dirty) { |
| 406 | try self.writeCmdHeaders(); | 417 | try self.writeCmdHeaders(); |
| ... | @@ -1413,6 +1424,17 @@ pub fn populateMissingMetadata(self: *MachO) !void { | ... | @@ -1413,6 +1424,17 @@ pub fn populateMissingMetadata(self: *MachO) !void { |
| 1413 | }, | 1424 | }, |
| 1414 | }); | 1425 | }); |
| 1415 | } | 1426 | } |
| | 1427 | if (self.code_signature_cmd_index == null) { |
| | 1428 | self.code_signature_cmd_index = @intCast(u16, self.load_commands.items.len); |
| | 1429 | try self.load_commands.append(self.base.allocator, .{ |
| | 1430 | .LinkeditData = .{ |
| | 1431 | .cmd = macho.LC_CODE_SIGNATURE, |
| | 1432 | .cmdsize = @sizeOf(macho.linkedit_data_command), |
| | 1433 | .dataoff = 0, |
| | 1434 | .datasize = 0, |
| | 1435 | }, |
| | 1436 | }); |
| | 1437 | } |
| 1416 | { | 1438 | { |
| 1417 | const linkedit = &self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment; | 1439 | const linkedit = &self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment; |
| 1418 | const dyld_info = &self.load_commands.items[self.dyld_info_cmd_index.?].DyldInfo; | 1440 | const dyld_info = &self.load_commands.items[self.dyld_info_cmd_index.?].DyldInfo; |
| ... | @@ -1458,6 +1480,17 @@ pub fn populateMissingMetadata(self: *MachO) !void { | ... | @@ -1458,6 +1480,17 @@ pub fn populateMissingMetadata(self: *MachO) !void { |
| 1458 | linkedit.vmsize += segment_size; | 1480 | linkedit.vmsize += segment_size; |
| 1459 | } | 1481 | } |
| 1460 | } | 1482 | } |
| | 1483 | { |
| | 1484 | const linkedit = &self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment; |
| | 1485 | const code_sig = &self.load_commands.items[self.code_signature_cmd_index.?].LinkeditData; |
| | 1486 | if (code_sig.dataoff == 0) { |
| | 1487 | const file_size = 0x1000; // TODO what is a good guesstimate for initial code signature? |
| | 1488 | const off = @intCast(u32, self.findFreeSpace(file_size, self.page_size)); |
| | 1489 | log.debug("found code signature free space 0x{x} to 0x{x}\n", .{ off, off + file_size }); |
| | 1490 | code_sig.dataoff = off; |
| | 1491 | code_sig.datasize = file_size; |
| | 1492 | } |
| | 1493 | } |
| 1461 | if (self.dyld_stub_binder_index == null) { | 1494 | if (self.dyld_stub_binder_index == null) { |
| 1462 | self.dyld_stub_binder_index = @intCast(u16, self.undef_symbols.items.len); | 1495 | self.dyld_stub_binder_index = @intCast(u16, self.undef_symbols.items.len); |
| 1463 | const name = try self.makeString("dyld_stub_binder"); | 1496 | const name = try self.makeString("dyld_stub_binder"); |
| ... | @@ -1722,6 +1755,16 @@ fn writeAllUndefSymbols(self: *MachO) !void { | ... | @@ -1722,6 +1755,16 @@ fn writeAllUndefSymbols(self: *MachO) !void { |
| 1722 | try self.base.file.?.pwriteAll(mem.sliceAsBytes(self.undef_symbols.items), off); | 1755 | try self.base.file.?.pwriteAll(mem.sliceAsBytes(self.undef_symbols.items), off); |
| 1723 | } | 1756 | } |
| 1724 | | 1757 | |
| | 1758 | fn codeSign(self: *MachO) !void { |
| | 1759 | const code_sig_cmd = &self.load_commands.items[self.code_signature_cmd_index.?].LinkeditData; |
| | 1760 | const symtab = &self.load_commands.items[self.symtab_cmd_index.?].Symtab; |
| | 1761 | const off = mem.alignForwardGeneric(u32, symtab.stroff + symtab.strsize, @sizeOf(u64)); |
| | 1762 | symtab.strsize = off - symtab.stroff; |
| | 1763 | code_sig_cmd.dataoff = off; |
| | 1764 | // TODO add actual code signing mechanism |
| | 1765 | try self.base.file.?.pwriteAll(&[_]u8{ 0 }, code_sig_cmd.dataoff + code_sig_cmd.datasize - 1); |
| | 1766 | } |
| | 1767 | |
| 1725 | fn writeExportTrie(self: *MachO) !void { | 1768 | fn writeExportTrie(self: *MachO) !void { |
| 1726 | if (self.global_symbols.items.len == 0) return; // No exports, nothing to do. | 1769 | if (self.global_symbols.items.len == 0) return; // No exports, nothing to do. |
| 1727 | | 1770 | |
| ... | @@ -1763,11 +1806,6 @@ fn writeStringTable(self: *MachO) !void { | ... | @@ -1763,11 +1806,6 @@ fn writeStringTable(self: *MachO) !void { |
| 1763 | log.debug("writing string table from 0x{x} to 0x{x}\n", .{ symtab.stroff, symtab.stroff + symtab.strsize }); | 1806 | log.debug("writing string table from 0x{x} to 0x{x}\n", .{ symtab.stroff, symtab.stroff + symtab.strsize }); |
| 1764 | | 1807 | |
| 1765 | try self.base.file.?.pwriteAll(self.string_table.items, symtab.stroff); | 1808 | try self.base.file.?.pwriteAll(self.string_table.items, symtab.stroff); |
| 1766 | | | |
| 1767 | // TODO rework how we preallocate space for the entire __LINKEDIT segment instead of | | |
| 1768 | // doing dynamic updates like this. | | |
| 1769 | const linkedit = &self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment; | | |
| 1770 | linkedit.filesize = symtab.stroff + symtab.strsize - linkedit.fileoff; | | |
| 1771 | } | 1809 | } |
| 1772 | | 1810 | |
| 1773 | fn writeCmdHeaders(self: *MachO) !void { | 1811 | fn writeCmdHeaders(self: *MachO) !void { |