authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2020-11-19 18:52:48+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2020-11-26 11:50:09+01:00
log403dc50ff77a319d8d1e4ceb60bcb254e4f17f06
treeb77002b45a5aa4cc538a617c0f3537985af18ddd
parentbbc4ee3f175d8b6c3bf8f6bdf03a7ce05b2935ea

stage2 macho: preallocate empty code sig space


1 files changed, 43 insertions(+), 5 deletions(-)

src/link/MachO.zig+43-5
...@@ -110,6 +110,8 @@ main_cmd_index: ?u16 = null,...@@ -110,6 +110,8 @@ main_cmd_index: ?u16 = null,
110version_min_cmd_index: ?u16 = null,110version_min_cmd_index: ?u16 = null,
111/// Source version111/// Source version
112source_version_cmd_index: ?u16 = null,112source_version_cmd_index: ?u16 = null,
113/// Code signature
114code_signature_cmd_index: ?u16 = null,
113115
114/// Table of all sections116/// Table of all sections
115sections: std.ArrayListUnmanaged(macho.section_64) = .{},117sections: 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 {
401403
402 // TODO remove when we add our own codesigning mechanism404 // 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 }
404415
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}
17241757
1758fn 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
1725fn writeExportTrie(self: *MachO) !void {1768fn 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.
17271770
...@@ -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 });
17641807
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}
17721810
1773fn writeCmdHeaders(self: *MachO) !void {1811fn writeCmdHeaders(self: *MachO) !void {