authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-07-15 12:58:42+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-07-22 16:58:20+02:00
log35a5a4a0e45b4a92d6f7d0428fe1a4b64815edb9
treee11630a2318c2042a151f74c5d3efb2cd8dd5a07
parentd80fcc8a0b5594a6eb0fb409f4e5e5f949eec2fe

macho: fix marking sections for pruning in GC


1 files changed, 42 insertions(+), 36 deletions(-)

src/link/MachO.zig+42-36
......@@ -244,7 +244,6 @@ unnamed_const_atoms: UnnamedConstTable = .{},
244244decls: std.AutoArrayHashMapUnmanaged(Module.Decl.Index, ?MatchingSection) = .{},
245245
246246gc_roots: std.AutoHashMapUnmanaged(*Atom, void) = .{},
247gc_sections: std.AutoHashMapUnmanaged(MatchingSection, void) = .{},
248247
249248const Entry = struct {
250249 target: SymbolWithLoc,
......@@ -3296,7 +3295,6 @@ pub fn deinit(self: *MachO) void {
32963295 self.locals_free_list.deinit(self.base.allocator);
32973296 self.unresolved.deinit(self.base.allocator);
32983297 self.gc_roots.deinit(self.base.allocator);
3299 self.gc_sections.deinit(self.base.allocator);
33003298
33013299 for (self.objects.items) |*object| {
33023300 object.deinit(self.base.allocator);
......@@ -5333,35 +5331,6 @@ fn pruneAndSortSectionsInSegment(self: *MachO, maybe_seg_id: *?u16, indices: []*
53335331 for (indices) |maybe_index| {
53345332 const old_idx = maybe_index.* orelse continue;
53355333 const sect = &sections[old_idx];
5336
5337 // Recalculate section alignment and size if required.
5338 const match = MatchingSection{
5339 .seg = seg_id,
5340 .sect = old_idx,
5341 };
5342 if (self.gc_sections.get(match)) |_| blk: {
5343 sect.@"align" = 0;
5344 sect.size = 0;
5345
5346 var atom = self.atoms.get(match) orelse break :blk;
5347
5348 while (atom.prev) |prev| {
5349 atom = prev;
5350 }
5351
5352 while (true) {
5353 const atom_alignment = try math.powi(u32, 2, atom.alignment);
5354 const aligned_end_addr = mem.alignForwardGeneric(u64, sect.size, atom_alignment);
5355 const padding = aligned_end_addr - sect.size;
5356 sect.size += padding + atom.size;
5357 sect.@"align" = @maximum(sect.@"align", atom.alignment);
5358
5359 if (atom.next) |next| {
5360 atom = next;
5361 } else break;
5362 }
5363 }
5364
53655334 if (sect.size == 0) {
53665335 log.debug("pruning section {s},{s}", .{ sect.segName(), sect.sectName() });
53675336 maybe_index.* = null;
......@@ -5550,6 +5519,11 @@ fn gcAtoms(self: *MachO) !void {
55505519 }
55515520 }
55525521
5522 // Any section that ends up here will be updated, that is,
5523 // its size and alignment recalculated.
5524 var gc_sections = std.AutoHashMap(MatchingSection, void).init(gpa);
5525 defer gc_sections.deinit();
5526
55535527 atoms_it = self.atoms.iterator();
55545528 while (atoms_it.next()) |entry| {
55555529 const match = entry.key_ptr.*;
......@@ -5602,18 +5576,22 @@ fn gcAtoms(self: *MachO) !void {
56025576 // account any padding that might have been left here.
56035577 sect.size -= atom.size;
56045578
5579 _ = try gc_sections.put(match, {});
5580
56055581 if (atom.prev) |prev| {
56065582 prev.next = atom.next;
56075583 }
56085584 if (atom.next) |next| {
56095585 next.prev = atom.prev;
56105586 } else {
5611 // TODO I think a null would be better here.
5612 // The section will be GCed in the next step.
5613 entry.value_ptr.* = if (atom.prev) |prev| prev else undefined;
5587 if (atom.prev) |prev| {
5588 entry.value_ptr.* = prev;
5589 } else {
5590 // The section will be GCed in the next step.
5591 entry.value_ptr.* = undefined;
5592 sect.size = 0;
5593 }
56145594 }
5615
5616 _ = try self.gc_sections.getOrPut(gpa, match);
56175595 }
56185596
56195597 if (orig_prev) |prev| {
......@@ -5621,6 +5599,34 @@ fn gcAtoms(self: *MachO) !void {
56215599 } else break;
56225600 }
56235601 }
5602
5603 var gc_sections_it = gc_sections.iterator();
5604 while (gc_sections_it.next()) |entry| {
5605 const match = entry.key_ptr.*;
5606 const sect = self.getSectionPtr(match);
5607 if (sect.size == 0) continue; // Pruning happens automatically in next step.
5608
5609 sect.@"align" = 0;
5610 sect.size = 0;
5611
5612 var atom = self.atoms.get(match).?;
5613
5614 while (atom.prev) |prev| {
5615 atom = prev;
5616 }
5617
5618 while (true) {
5619 const atom_alignment = try math.powi(u32, 2, atom.alignment);
5620 const aligned_end_addr = mem.alignForwardGeneric(u64, sect.size, atom_alignment);
5621 const padding = aligned_end_addr - sect.size;
5622 sect.size += padding + atom.size;
5623 sect.@"align" = @maximum(sect.@"align", atom.alignment);
5624
5625 if (atom.next) |next| {
5626 atom = next;
5627 } else break;
5628 }
5629 }
56245630}
56255631
56265632fn updateSectionOrdinals(self: *MachO) !void {