authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-07-15 17:54:09+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-07-22 16:58:20+02:00
log817939d20a097c195fc924398081e64556cc0aea
treef7fbb5817dd72f0196b9e541dcb84eab2c0186b6
parent61b4119a7d5862f58fc4a34024456e3feca292a5

macho: don't store GC roots globally

Instead, if dead-strip was requested, create a temp container and pass it around.

2 files changed, 62 insertions(+), 45 deletions(-)

src/link/MachO.zig+34-28
......@@ -243,8 +243,6 @@ unnamed_const_atoms: UnnamedConstTable = .{},
243243/// TODO consolidate this.
244244decls: std.AutoArrayHashMapUnmanaged(Module.Decl.Index, ?MatchingSection) = .{},
245245
246gc_roots: std.AutoHashMapUnmanaged(*Atom, void) = .{},
247
248246const Entry = struct {
249247 target: SymbolWithLoc,
250248 atom: *Atom,
......@@ -631,7 +629,8 @@ fn linkOneShot(self: *MachO, comp: *Compilation, prog_node: *std.Progress.Node)
631629 const tracy = trace(@src());
632630 defer tracy.end();
633631
634 var arena_allocator = std.heap.ArenaAllocator.init(self.base.allocator);
632 const gpa = self.base.allocator;
633 var arena_allocator = std.heap.ArenaAllocator.init(gpa);
635634 defer arena_allocator.deinit();
636635 const arena = arena_allocator.allocator();
637636
......@@ -676,6 +675,7 @@ fn linkOneShot(self: *MachO, comp: *Compilation, prog_node: *std.Progress.Node)
676675 const is_dyn_lib = self.base.options.link_mode == .Dynamic and is_lib;
677676 const is_exe_or_dyn_lib = is_dyn_lib or self.base.options.output_mode == .Exe;
678677 const stack_size = self.base.options.stack_size_override orelse 0;
678 const dead_strip = self.base.options.gc_sections orelse false;
679679
680680 const id_symlink_basename = "zld.id";
681681
......@@ -707,7 +707,7 @@ fn linkOneShot(self: *MachO, comp: *Compilation, prog_node: *std.Progress.Node)
707707 man.hash.addOptional(self.base.options.search_strategy);
708708 man.hash.addOptional(self.base.options.headerpad_size);
709709 man.hash.add(self.base.options.headerpad_max_install_names);
710 man.hash.add(self.base.options.gc_sections orelse false);
710 man.hash.add(dead_strip);
711711 man.hash.add(self.base.options.dead_strip_dylibs);
712712 man.hash.addListOfBytes(self.base.options.lib_dirs);
713713 man.hash.addListOfBytes(self.base.options.framework_dirs);
......@@ -790,14 +790,14 @@ fn linkOneShot(self: *MachO, comp: *Compilation, prog_node: *std.Progress.Node)
790790 .mode = link.determineMode(self.base.options),
791791 });
792792 // Index 0 is always a null symbol.
793 try self.locals.append(self.base.allocator, .{
793 try self.locals.append(gpa, .{
794794 .n_strx = 0,
795795 .n_type = 0,
796796 .n_sect = 0,
797797 .n_desc = 0,
798798 .n_value = 0,
799799 });
800 try self.strtab.buffer.append(self.base.allocator, 0);
800 try self.strtab.buffer.append(gpa, 0);
801801 try self.populateMissingMetadata();
802802
803803 var lib_not_found = false;
......@@ -964,10 +964,10 @@ fn linkOneShot(self: *MachO, comp: *Compilation, prog_node: *std.Progress.Node)
964964 .cmdsize = cmdsize,
965965 .path = @sizeOf(macho.rpath_command),
966966 });
967 rpath_cmd.data = try self.base.allocator.alloc(u8, cmdsize - rpath_cmd.inner.path);
967 rpath_cmd.data = try gpa.alloc(u8, cmdsize - rpath_cmd.inner.path);
968968 mem.set(u8, rpath_cmd.data, 0);
969969 mem.copy(u8, rpath_cmd.data, rpath);
970 try self.load_commands.append(self.base.allocator, .{ .rpath = rpath_cmd });
970 try self.load_commands.append(gpa, .{ .rpath = rpath_cmd });
971971 try rpath_table.putNoClobber(rpath, {});
972972 self.load_commands_dirty = true;
973973 }
......@@ -975,11 +975,11 @@ fn linkOneShot(self: *MachO, comp: *Compilation, prog_node: *std.Progress.Node)
975975 // code signature and entitlements
976976 if (self.base.options.entitlements) |path| {
977977 if (self.code_signature) |*csig| {
978 try csig.addEntitlements(self.base.allocator, path);
978 try csig.addEntitlements(gpa, path);
979979 csig.code_directory.ident = self.base.options.emit.?.sub_path;
980980 } else {
981981 var csig = CodeSignature.init(self.page_size);
982 try csig.addEntitlements(self.base.allocator, path);
982 try csig.addEntitlements(gpa, path);
983983 csig.code_directory.ident = self.base.options.emit.?.sub_path;
984984 self.code_signature = csig;
985985 }
......@@ -1033,10 +1033,8 @@ fn linkOneShot(self: *MachO, comp: *Compilation, prog_node: *std.Progress.Node)
10331033 try argv.append("-headerpad_max_install_names");
10341034 }
10351035
1036 if (self.base.options.gc_sections) |is_set| {
1037 if (is_set) {
1038 try argv.append("-dead_strip");
1039 }
1036 if (dead_strip) {
1037 try argv.append("-dead_strip");
10401038 }
10411039
10421040 if (self.base.options.dead_strip_dylibs) {
......@@ -1120,7 +1118,7 @@ fn linkOneShot(self: *MachO, comp: *Compilation, prog_node: *std.Progress.Node)
11201118 var dependent_libs = std.fifo.LinearFifo(struct {
11211119 id: Dylib.Id,
11221120 parent: u16,
1123 }, .Dynamic).init(self.base.allocator);
1121 }, .Dynamic).init(gpa);
11241122 defer dependent_libs.deinit();
11251123 try self.parseInputFiles(positionals.items, self.base.options.sysroot, &dependent_libs);
11261124 try self.parseAndForceLoadStaticArchives(must_link_archives.keys());
......@@ -1153,11 +1151,21 @@ fn linkOneShot(self: *MachO, comp: *Compilation, prog_node: *std.Progress.Node)
11531151
11541152 try self.createTentativeDefAtoms();
11551153
1156 for (self.objects.items) |*object, object_id| {
1157 try object.splitIntoAtomsOneShot(self, @intCast(u32, object_id));
1154 if (dead_strip) {
1155 var gc_roots = std.AutoHashMap(*Atom, void).init(gpa);
1156 defer gc_roots.deinit();
1157
1158 for (self.objects.items) |*object, object_id| {
1159 try object.splitIntoAtomsOneShot(self, @intCast(u32, object_id), &gc_roots);
1160 }
1161
1162 try self.gcAtoms(&gc_roots);
1163 } else {
1164 for (self.objects.items) |*object, object_id| {
1165 try object.splitIntoAtomsOneShot(self, @intCast(u32, object_id), null);
1166 }
11581167 }
11591168
1160 try self.gcAtoms();
11611169 try self.pruneAndSortSections();
11621170 try self.allocateSegments();
11631171 try self.allocateSymbols();
......@@ -1184,7 +1192,7 @@ fn linkOneShot(self: *MachO, comp: *Compilation, prog_node: *std.Progress.Node)
11841192 try self.writeLinkeditSegment();
11851193
11861194 if (self.code_signature) |*csig| {
1187 csig.clear(self.base.allocator);
1195 csig.clear(gpa);
11881196 csig.code_directory.ident = self.base.options.emit.?.sub_path;
11891197 // Preallocate space for the code signature.
11901198 // We need to do this at this stage so that we have the load commands with proper values
......@@ -3294,7 +3302,6 @@ pub fn deinit(self: *MachO) void {
32943302 self.locals.deinit(self.base.allocator);
32953303 self.locals_free_list.deinit(self.base.allocator);
32963304 self.unresolved.deinit(self.base.allocator);
3297 self.gc_roots.deinit(self.base.allocator);
32983305
32993306 for (self.objects.items) |*object| {
33003307 object.deinit(self.base.allocator);
......@@ -5447,9 +5454,8 @@ fn pruneAndSortSections(self: *MachO) !void {
54475454 self.sections_order_dirty = false;
54485455}
54495456
5450fn gcAtoms(self: *MachO) !void {
5451 const dead_strip = self.base.options.gc_sections orelse return;
5452 if (!dead_strip) return;
5457fn gcAtoms(self: *MachO, gc_roots: *std.AutoHashMap(*Atom, void)) !void {
5458 assert(self.base.options.gc_sections.?);
54535459
54545460 const gpa = self.base.allocator;
54555461
......@@ -5461,7 +5467,7 @@ fn gcAtoms(self: *MachO) !void {
54615467 log.debug("skipping {s}", .{self.getSymbolName(global)});
54625468 continue;
54635469 };
5464 _ = try self.gc_roots.getOrPut(gpa, gc_root);
5470 _ = try gc_roots.getOrPut(gc_root);
54655471 }
54665472
54675473 // Add any atom targeting an import as GC root
......@@ -5474,7 +5480,7 @@ fn gcAtoms(self: *MachO) !void {
54745480 if ((try rel.getTargetAtom(self)) == null) {
54755481 const target_sym = self.getSymbol(rel.target);
54765482 if (target_sym.undf()) {
5477 _ = try self.gc_roots.getOrPut(gpa, atom);
5483 _ = try gc_roots.getOrPut(atom);
54785484 break;
54795485 }
54805486 }
......@@ -5488,14 +5494,14 @@ fn gcAtoms(self: *MachO) !void {
54885494
54895495 var stack = std.ArrayList(*Atom).init(gpa);
54905496 defer stack.deinit();
5491 try stack.ensureUnusedCapacity(self.gc_roots.count());
5497 try stack.ensureUnusedCapacity(gc_roots.count());
54925498
54935499 var retained = std.AutoHashMap(*Atom, void).init(gpa);
54945500 defer retained.deinit();
5495 try retained.ensureUnusedCapacity(self.gc_roots.count());
5501 try retained.ensureUnusedCapacity(gc_roots.count());
54965502
54975503 log.debug("GC roots:", .{});
5498 var gc_roots_it = self.gc_roots.keyIterator();
5504 var gc_roots_it = gc_roots.keyIterator();
54995505 while (gc_roots_it.next()) |gc_root| {
55005506 self.logAtom(gc_root.*);
55015507
src/link/MachO/Object.zig+28-17
......@@ -360,7 +360,12 @@ fn filterDice(
360360}
361361
362362/// Splits object into atoms assuming one-shot linking mode.
363pub fn splitIntoAtomsOneShot(self: *Object, macho_file: *MachO, object_id: u32) !void {
363pub fn splitIntoAtomsOneShot(
364 self: *Object,
365 macho_file: *MachO,
366 object_id: u32,
367 gc_roots: ?*std.AutoHashMap(*Atom, void),
368) !void {
364369 assert(macho_file.mode == .one_shot);
365370
366371 const tracy = trace(@src());
......@@ -493,6 +498,7 @@ pub fn splitIntoAtomsOneShot(self: *Object, macho_file: *MachO, object_id: u32)
493498 &.{},
494499 match,
495500 sect,
501 gc_roots,
496502 );
497503 try macho_file.addAtomToSection(atom, match);
498504 }
......@@ -538,6 +544,7 @@ pub fn splitIntoAtomsOneShot(self: *Object, macho_file: *MachO, object_id: u32)
538544 atom_syms[1..],
539545 match,
540546 sect,
547 gc_roots,
541548 );
542549
543550 if (arch == .x86_64 and addr == sect.addr) {
......@@ -593,6 +600,7 @@ pub fn splitIntoAtomsOneShot(self: *Object, macho_file: *MachO, object_id: u32)
593600 filtered_syms,
594601 match,
595602 sect,
603 gc_roots,
596604 );
597605 try macho_file.addAtomToSection(atom, match);
598606 }
......@@ -611,6 +619,7 @@ fn createAtomFromSubsection(
611619 indexes: []const SymbolAtIndex,
612620 match: MatchingSection,
613621 sect: macho.section_64,
622 gc_roots: ?*std.AutoHashMap(*Atom, void),
614623) !*Atom {
615624 const gpa = macho_file.base.allocator;
616625 const sym = self.symtab.items[sym_index];
......@@ -715,23 +724,25 @@ fn createAtomFromSubsection(
715724 try self.atom_by_index_table.putNoClobber(gpa, inner_sym_index.index, atom);
716725 }
717726
718 const is_gc_root = blk: {
719 if (sect.isDontDeadStrip()) break :blk true;
720 if (sect.isDontDeadStripIfReferencesLive()) {
721 // TODO if isDontDeadStripIfReferencesLive we should analyse the edges
722 // before making it a GC root
723 break :blk true;
724 }
725 if (mem.eql(u8, "__StaticInit", sect.sectName())) break :blk true;
726 switch (sect.type_()) {
727 macho.S_MOD_INIT_FUNC_POINTERS,
728 macho.S_MOD_TERM_FUNC_POINTERS,
729 => break :blk true,
730 else => break :blk false,
727 if (gc_roots) |gcr| {
728 const is_gc_root = blk: {
729 if (sect.isDontDeadStrip()) break :blk true;
730 if (sect.isDontDeadStripIfReferencesLive()) {
731 // TODO if isDontDeadStripIfReferencesLive we should analyse the edges
732 // before making it a GC root
733 break :blk true;
734 }
735 if (mem.eql(u8, "__StaticInit", sect.sectName())) break :blk true;
736 switch (sect.type_()) {
737 macho.S_MOD_INIT_FUNC_POINTERS,
738 macho.S_MOD_TERM_FUNC_POINTERS,
739 => break :blk true,
740 else => break :blk false,
741 }
742 };
743 if (is_gc_root) {
744 try gcr.putNoClobber(atom, {});
731745 }
732 };
733 if (is_gc_root) {
734 try macho_file.gc_roots.putNoClobber(gpa, atom, {});
735746 }
736747
737748 return atom;