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 = .{},...@@ -244,7 +244,6 @@ unnamed_const_atoms: UnnamedConstTable = .{},
244decls: std.AutoArrayHashMapUnmanaged(Module.Decl.Index, ?MatchingSection) = .{},244decls: std.AutoArrayHashMapUnmanaged(Module.Decl.Index, ?MatchingSection) = .{},
245245
246gc_roots: std.AutoHashMapUnmanaged(*Atom, void) = .{},246gc_roots: std.AutoHashMapUnmanaged(*Atom, void) = .{},
247gc_sections: std.AutoHashMapUnmanaged(MatchingSection, void) = .{},
248247
249const Entry = struct {248const Entry = struct {
250 target: SymbolWithLoc,249 target: SymbolWithLoc,
...@@ -3296,7 +3295,6 @@ pub fn deinit(self: *MachO) void {...@@ -3296,7 +3295,6 @@ pub fn deinit(self: *MachO) void {
3296 self.locals_free_list.deinit(self.base.allocator);3295 self.locals_free_list.deinit(self.base.allocator);
3297 self.unresolved.deinit(self.base.allocator);3296 self.unresolved.deinit(self.base.allocator);
3298 self.gc_roots.deinit(self.base.allocator);3297 self.gc_roots.deinit(self.base.allocator);
3299 self.gc_sections.deinit(self.base.allocator);
33003298
3301 for (self.objects.items) |*object| {3299 for (self.objects.items) |*object| {
3302 object.deinit(self.base.allocator);3300 object.deinit(self.base.allocator);
...@@ -5333,35 +5331,6 @@ fn pruneAndSortSectionsInSegment(self: *MachO, maybe_seg_id: *?u16, indices: []*...@@ -5333,35 +5331,6 @@ fn pruneAndSortSectionsInSegment(self: *MachO, maybe_seg_id: *?u16, indices: []*
5333 for (indices) |maybe_index| {5331 for (indices) |maybe_index| {
5334 const old_idx = maybe_index.* orelse continue;5332 const old_idx = maybe_index.* orelse continue;
5335 const sect = &sections[old_idx];5333 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
5365 if (sect.size == 0) {5334 if (sect.size == 0) {
5366 log.debug("pruning section {s},{s}", .{ sect.segName(), sect.sectName() });5335 log.debug("pruning section {s},{s}", .{ sect.segName(), sect.sectName() });
5367 maybe_index.* = null;5336 maybe_index.* = null;
...@@ -5550,6 +5519,11 @@ fn gcAtoms(self: *MachO) !void {...@@ -5550,6 +5519,11 @@ fn gcAtoms(self: *MachO) !void {
5550 }5519 }
5551 }5520 }
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
5553 atoms_it = self.atoms.iterator();5527 atoms_it = self.atoms.iterator();
5554 while (atoms_it.next()) |entry| {5528 while (atoms_it.next()) |entry| {
5555 const match = entry.key_ptr.*;5529 const match = entry.key_ptr.*;
...@@ -5602,18 +5576,22 @@ fn gcAtoms(self: *MachO) !void {...@@ -5602,18 +5576,22 @@ fn gcAtoms(self: *MachO) !void {
5602 // account any padding that might have been left here.5576 // account any padding that might have been left here.
5603 sect.size -= atom.size;5577 sect.size -= atom.size;
56045578
5579 _ = try gc_sections.put(match, {});
5580
5605 if (atom.prev) |prev| {5581 if (atom.prev) |prev| {
5606 prev.next = atom.next;5582 prev.next = atom.next;
5607 }5583 }
5608 if (atom.next) |next| {5584 if (atom.next) |next| {
5609 next.prev = atom.prev;5585 next.prev = atom.prev;
5610 } else {5586 } else {
5611 // TODO I think a null would be better here.5587 if (atom.prev) |prev| {
5612 // The section will be GCed in the next step.5588 entry.value_ptr.* = prev;
5613 entry.value_ptr.* = if (atom.prev) |prev| prev else undefined;5589 } else {
5590 // The section will be GCed in the next step.
5591 entry.value_ptr.* = undefined;
5592 sect.size = 0;
5593 }
5614 }5594 }
5615
5616 _ = try self.gc_sections.getOrPut(gpa, match);
5617 }5595 }
56185596
5619 if (orig_prev) |prev| {5597 if (orig_prev) |prev| {
...@@ -5621,6 +5599,34 @@ fn gcAtoms(self: *MachO) !void {...@@ -5621,6 +5599,34 @@ fn gcAtoms(self: *MachO) !void {
5621 } else break;5599 } else break;
5622 }5600 }
5623 }5601 }
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 }
5624}5630}
56255631
5626fn updateSectionOrdinals(self: *MachO) !void {5632fn updateSectionOrdinals(self: *MachO) !void {