authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2020-10-11 16:03:39+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2020-10-13 08:38:17+02:00
logadfd298e44be707541b13e2d8f1edc5b237fa674
tree49009639aa28ca9c2fc7f5594ebe1a49fb805521
parent951721343f0e04f39df0a049b93c774c3cde0741

Do not rewrite paths to dyld and libSystem unless changed


1 files changed, 26 insertions(+), 13 deletions(-)

src/link/MachO.zig+26-13
...@@ -133,6 +133,8 @@ offset_table: std.ArrayListUnmanaged(u64) = .{},...@@ -133,6 +133,8 @@ offset_table: std.ArrayListUnmanaged(u64) = .{},
133error_flags: File.ErrorFlags = File.ErrorFlags{},133error_flags: File.ErrorFlags = File.ErrorFlags{},
134134
135cmd_table_dirty: bool = false,135cmd_table_dirty: bool = false,
136dylinker_cmd_dirty: bool = false,
137libsystem_cmd_dirty: bool = false,
136138
137/// A list of text blocks that have surplus capacity. This list can have false139/// A list of text blocks that have surplus capacity. This list can have false
138/// positives, as functions grow and shrink over time, only sometimes being added140/// positives, as functions grow and shrink over time, only sometimes being added
...@@ -318,14 +320,12 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {...@@ -318,14 +320,12 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {
318 .Exe => {320 .Exe => {
319 // Write export trie.321 // Write export trie.
320 try self.writeExportTrie();322 try self.writeExportTrie();
321
322 if (self.entry_addr) |addr| {323 if (self.entry_addr) |addr| {
323 // Update LC_MAIN with entry offset324 // Update LC_MAIN with entry offset.
324 const text_segment = self.load_commands.items[self.text_segment_cmd_index.?].Segment;325 const text_segment = self.load_commands.items[self.text_segment_cmd_index.?].Segment;
325 const main_cmd = &self.load_commands.items[self.main_cmd_index.?].EntryPoint;326 const main_cmd = &self.load_commands.items[self.main_cmd_index.?].EntryPoint;
326 main_cmd.entryoff = addr - text_segment.vmaddr;327 main_cmd.entryoff = addr - text_segment.vmaddr;
327 }328 }
328
329 {329 {
330 // Update dynamic symbol table.330 // Update dynamic symbol table.
331 const nlocals = @intCast(u32, self.local_symbols.items.len);331 const nlocals = @intCast(u32, self.local_symbols.items.len);
...@@ -338,7 +338,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {...@@ -338,7 +338,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {
338 dysymtab.iundefsym = nlocals + nglobals;338 dysymtab.iundefsym = nlocals + nglobals;
339 dysymtab.nundefsym = nundefs;339 dysymtab.nundefsym = nundefs;
340 }340 }
341 {341 if (self.dylinker_cmd_dirty) {
342 // Write path to dyld loader.342 // Write path to dyld loader.
343 var off: usize = @sizeOf(macho.mach_header_64);343 var off: usize = @sizeOf(macho.mach_header_64);
344 for (self.load_commands.items) |cmd| {344 for (self.load_commands.items) |cmd| {
...@@ -349,8 +349,9 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {...@@ -349,8 +349,9 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {
349 off += cmd.name;349 off += cmd.name;
350 log.debug("writing LC_LOAD_DYLINKER path to dyld at 0x{x}\n", .{off});350 log.debug("writing LC_LOAD_DYLINKER path to dyld at 0x{x}\n", .{off});
351 try self.base.file.?.pwriteAll(mem.spanZ(DEFAULT_DYLD_PATH), off);351 try self.base.file.?.pwriteAll(mem.spanZ(DEFAULT_DYLD_PATH), off);
352 self.dylinker_cmd_dirty = false;
352 }353 }
353 {354 if (self.libsystem_cmd_dirty) {
354 // Write path to libSystem.355 // Write path to libSystem.
355 var off: usize = @sizeOf(macho.mach_header_64);356 var off: usize = @sizeOf(macho.mach_header_64);
356 for (self.load_commands.items) |cmd| {357 for (self.load_commands.items) |cmd| {
...@@ -361,6 +362,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {...@@ -361,6 +362,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {
361 off += cmd.dylib.name;362 off += cmd.dylib.name;
362 log.debug("writing LC_LOAD_DYLIB path to libSystem at 0x{x}\n", .{off});363 log.debug("writing LC_LOAD_DYLIB path to libSystem at 0x{x}\n", .{off});
363 try self.base.file.?.pwriteAll(mem.spanZ(LIB_SYSTEM_PATH), off);364 try self.base.file.?.pwriteAll(mem.spanZ(LIB_SYSTEM_PATH), off);
365 self.libsystem_cmd_dirty = false;
364 }366 }
365 },367 },
366 .Obj => {},368 .Obj => {},
...@@ -376,7 +378,11 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {...@@ -376,7 +378,11 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {
376 symtab.nsyms = nlocals + nglobals + nundefs;378 symtab.nsyms = nlocals + nglobals + nundefs;
377 }379 }
378380
379 if (self.cmd_table_dirty) try self.writeCmdHeaders();381 if (self.cmd_table_dirty) {
382 try self.writeCmdHeaders();
383 try self.writeMachOHeader();
384 self.cmd_table_dirty = false;
385 }
380386
381 if (self.entry_addr == null and self.base.options.output_mode == .Exe) {387 if (self.entry_addr == null and self.base.options.output_mode == .Exe) {
382 log.debug("flushing. no_entry_point_found = true\n", .{});388 log.debug("flushing. no_entry_point_found = true\n", .{});
...@@ -384,8 +390,11 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {...@@ -384,8 +390,11 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {
384 } else {390 } else {
385 log.debug("flushing. no_entry_point_found = false\n", .{});391 log.debug("flushing. no_entry_point_found = false\n", .{});
386 self.error_flags.no_entry_point_found = false;392 self.error_flags.no_entry_point_found = false;
387 try self.writeMachOHeader();
388 }393 }
394
395 assert(!self.cmd_table_dirty);
396 assert(!self.dylinker_cmd_dirty);
397 assert(!self.libsystem_cmd_dirty);
389}398}
390399
391fn linkWithLLD(self: *MachO, comp: *Compilation) !void {400fn linkWithLLD(self: *MachO, comp: *Compilation) !void {
...@@ -846,7 +855,7 @@ pub fn allocateDeclIndexes(self: *MachO, decl: *Module.Decl) !void {...@@ -846,7 +855,7 @@ pub fn allocateDeclIndexes(self: *MachO, decl: *Module.Decl) !void {
846 try self.offset_table.ensureCapacity(self.base.allocator, self.offset_table.items.len + 1);855 try self.offset_table.ensureCapacity(self.base.allocator, self.offset_table.items.len + 1);
847856
848 if (self.local_symbol_free_list.popOrNull()) |i| {857 if (self.local_symbol_free_list.popOrNull()) |i| {
849 log.debug("reusing symbol index {} for {}\n", .{i, decl.name});858 log.debug("reusing symbol index {} for {}\n", .{ i, decl.name });
850 decl.link.macho.local_sym_index = i;859 decl.link.macho.local_sym_index = i;
851 } else {860 } else {
852 log.debug("allocating symbol index {} for {}\n", .{ self.local_symbols.items.len, decl.name });861 log.debug("allocating symbol index {} for {}\n", .{ self.local_symbols.items.len, decl.name });
...@@ -980,6 +989,7 @@ pub fn updateDeclExports(...@@ -980,6 +989,7 @@ pub fn updateDeclExports(
980 .Strong => blk: {989 .Strong => blk: {
981 if (mem.eql(u8, exp.options.name, "_start")) {990 if (mem.eql(u8, exp.options.name, "_start")) {
982 self.entry_addr = decl_sym.n_value;991 self.entry_addr = decl_sym.n_value;
992 self.cmd_table_dirty = true; // TODO This should be handled more granularly instead of invalidating all commands.
983 }993 }
984 break :blk macho.REFERENCE_FLAG_DEFINED;994 break :blk macho.REFERENCE_FLAG_DEFINED;
985 },995 },
...@@ -1121,6 +1131,7 @@ pub fn populateMissingMetadata(self: *MachO) !void {...@@ -1121,6 +1131,7 @@ pub fn populateMissingMetadata(self: *MachO) !void {
11211131
1122 text_segment.vmsize = file_size + off; // We add off here since __TEXT segment includes everything prior to __text section.1132 text_segment.vmsize = file_size + off; // We add off here since __TEXT segment includes everything prior to __text section.
1123 text_segment.filesize = file_size + off;1133 text_segment.filesize = file_size + off;
1134 self.cmd_table_dirty = true;
1124 }1135 }
1125 if (self.data_segment_cmd_index == null) {1136 if (self.data_segment_cmd_index == null) {
1126 self.data_segment_cmd_index = @intCast(u16, self.load_commands.items.len);1137 self.data_segment_cmd_index = @intCast(u16, self.load_commands.items.len);
...@@ -1173,6 +1184,7 @@ pub fn populateMissingMetadata(self: *MachO) !void {...@@ -1173,6 +1184,7 @@ pub fn populateMissingMetadata(self: *MachO) !void {
1173 data_segment.vmsize = segment_size;1184 data_segment.vmsize = segment_size;
1174 data_segment.filesize = segment_size;1185 data_segment.filesize = segment_size;
1175 data_segment.fileoff = off;1186 data_segment.fileoff = off;
1187 self.cmd_table_dirty = true;
1176 }1188 }
1177 if (self.linkedit_segment_cmd_index == null) {1189 if (self.linkedit_segment_cmd_index == null) {
1178 self.linkedit_segment_cmd_index = @intCast(u16, self.load_commands.items.len);1190 self.linkedit_segment_cmd_index = @intCast(u16, self.load_commands.items.len);
...@@ -1268,6 +1280,7 @@ pub fn populateMissingMetadata(self: *MachO) !void {...@@ -1268,6 +1280,7 @@ pub fn populateMissingMetadata(self: *MachO) !void {
1268 },1280 },
1269 });1281 });
1270 self.cmd_table_dirty = true;1282 self.cmd_table_dirty = true;
1283 self.dylinker_cmd_dirty = true;
1271 }1284 }
1272 if (self.libsystem_cmd_index == null) {1285 if (self.libsystem_cmd_index == null) {
1273 self.libsystem_cmd_index = @intCast(u16, self.load_commands.items.len);1286 self.libsystem_cmd_index = @intCast(u16, self.load_commands.items.len);
...@@ -1289,6 +1302,7 @@ pub fn populateMissingMetadata(self: *MachO) !void {...@@ -1289,6 +1302,7 @@ pub fn populateMissingMetadata(self: *MachO) !void {
1289 },1302 },
1290 });1303 });
1291 self.cmd_table_dirty = true;1304 self.cmd_table_dirty = true;
1305 self.libsystem_cmd_dirty = true;
1292 }1306 }
1293 if (self.main_cmd_index == null) {1307 if (self.main_cmd_index == null) {
1294 self.main_cmd_index = @intCast(u16, self.load_commands.items.len);1308 self.main_cmd_index = @intCast(u16, self.load_commands.items.len);
...@@ -1407,8 +1421,7 @@ fn allocateTextBlock(self: *MachO, text_block: *TextBlock, new_block_size: u64,...@@ -1407,8 +1421,7 @@ fn allocateTextBlock(self: *MachO, text_block: *TextBlock, new_block_size: u64,
1407 free_list_removal = i;1421 free_list_removal = i;
1408 }1422 }
1409 break :blk new_start_vaddr;1423 break :blk new_start_vaddr;
1410 }1424 } else if (self.last_text_block) |last| {
1411 else if (self.last_text_block) |last| {
1412 const last_symbol = self.local_symbols.items[last.local_sym_index];1425 const last_symbol = self.local_symbols.items[last.local_sym_index];
1413 // TODO We should pad out the excess capacity with NOPs. For executables,1426 // TODO We should pad out the excess capacity with NOPs. For executables,
1414 // no padding seems to be OK, but it will probably not be for objects.1427 // no padding seems to be OK, but it will probably not be for objects.
...@@ -1431,7 +1444,7 @@ fn allocateTextBlock(self: *MachO, text_block: *TextBlock, new_block_size: u64,...@@ -1431,7 +1444,7 @@ fn allocateTextBlock(self: *MachO, text_block: *TextBlock, new_block_size: u64,
1431 self.last_text_block = text_block;1444 self.last_text_block = text_block;
1432 text_section.size = needed_size;1445 text_section.size = needed_size;
14331446
1434 self.cmd_table_dirty = true;1447 self.cmd_table_dirty = true; // TODO Make more granular.
1435 }1448 }
1436 text_block.size = new_block_size;1449 text_block.size = new_block_size;
14371450
...@@ -1684,7 +1697,7 @@ fn writeCmdHeaders(self: *MachO) !void {...@@ -1684,7 +1697,7 @@ fn writeCmdHeaders(self: *MachO) !void {
1684 return error.TODOImplementWritingObjFiles;1697 return error.TODOImplementWritingObjFiles;
1685 };1698 };
1686 const idx = self.text_section_index.?;1699 const idx = self.text_section_index.?;
1687 log.debug("writing text section {} at 0x{x}\n", .{ self.sections.items[idx .. idx + 1], off });1700 log.debug("writing text section header at 0x{x}\n", .{off});
1688 try self.base.file.?.pwriteAll(mem.sliceAsBytes(self.sections.items[idx .. idx + 1]), off);1701 try self.base.file.?.pwriteAll(mem.sliceAsBytes(self.sections.items[idx .. idx + 1]), off);
1689 }1702 }
1690 {1703 {
...@@ -1702,7 +1715,7 @@ fn writeCmdHeaders(self: *MachO) !void {...@@ -1702,7 +1715,7 @@ fn writeCmdHeaders(self: *MachO) !void {
1702 return error.TODOImplementWritingObjFiles;1715 return error.TODOImplementWritingObjFiles;
1703 };1716 };
1704 const idx = self.got_section_index.?;1717 const idx = self.got_section_index.?;
1705 log.debug("writing got section {} at 0x{x}\n", .{ self.sections.items[idx .. idx + 1], off });1718 log.debug("writing got section header at 0x{x}\n", .{off});
1706 try self.base.file.?.pwriteAll(mem.sliceAsBytes(self.sections.items[idx .. idx + 1]), off);1719 try self.base.file.?.pwriteAll(mem.sliceAsBytes(self.sections.items[idx .. idx + 1]), off);
1707 }1720 }
1708}1721}