authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-09-11 01:18:37+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-09-11 02:03:25+02:00
log31dcb0dde71e7c6968a9ee902782783b139c4900
treeb832dbe9b676a6e248c8c09409749d7582218466
parent6e0c3950b8115e1e274214447763733b3d3055d6

macho: change all occurrences of TextBlock into Atom

and unify allocateAtom with allocateTextBlock.

1 files changed, 237 insertions(+), 271 deletions(-)

src/link/MachO.zig+237-271
......@@ -158,8 +158,8 @@ stub_preamble_sym_index: ?u32 = null,
158158strtab: std.ArrayListUnmanaged(u8) = .{},
159159strtab_dir: std.HashMapUnmanaged(u32, u32, StringIndexContext, std.hash_map.default_max_load_percentage) = .{},
160160
161got_entries_map: std.AutoArrayHashMapUnmanaged(GotIndirectionKey, *TextBlock) = .{},
162stubs_map: std.AutoArrayHashMapUnmanaged(u32, *TextBlock) = .{},
161got_entries_map: std.AutoArrayHashMapUnmanaged(GotIndirectionKey, *Atom) = .{},
162stubs_map: std.AutoArrayHashMapUnmanaged(u32, *Atom) = .{},
163163
164164error_flags: File.ErrorFlags = File.ErrorFlags{},
165165
......@@ -171,12 +171,12 @@ has_stabs: bool = false,
171171
172172section_ordinals: std.AutoArrayHashMapUnmanaged(MatchingSection, void) = .{},
173173
174/// A list of text blocks that have surplus capacity. This list can have false
174/// A list of atoms that have surplus capacity. This list can have false
175175/// positives, as functions grow and shrink over time, only sometimes being added
176176/// or removed from the freelist.
177177///
178/// A text block has surplus capacity when its overcapacity value is greater than
179/// padToIdeal(minimum_text_block_size). That is, when it has so
178/// An atom has surplus capacity when its overcapacity value is greater than
179/// padToIdeal(minimum_atom_size). That is, when it has so
180180/// much extra capacity, that we could fit a small new symbol in it, itself with
181181/// ideal_capacity or more.
182182///
......@@ -184,23 +184,23 @@ section_ordinals: std.AutoArrayHashMapUnmanaged(MatchingSection, void) = .{},
184184///
185185/// Overcapacity is measured by actual_capacity - ideal_capacity. Note that
186186/// overcapacity can be negative. A simple way to have negative overcapacity is to
187/// allocate a fresh text block, which will have ideal capacity, and then grow it
187/// allocate a fresh atom, which will have ideal capacity, and then grow it
188188/// by 1 byte. It will then have -1 overcapacity.
189block_free_lists: std.AutoHashMapUnmanaged(MatchingSection, std.ArrayListUnmanaged(*TextBlock)) = .{},
189atom_free_lists: std.AutoHashMapUnmanaged(MatchingSection, std.ArrayListUnmanaged(*Atom)) = .{},
190190
191/// Pointer to the last allocated text block
192blocks: std.AutoHashMapUnmanaged(MatchingSection, *TextBlock) = .{},
191/// Pointer to the last allocated atom
192atoms: std.AutoHashMapUnmanaged(MatchingSection, *Atom) = .{},
193193
194/// List of TextBlocks that are owned directly by the linker.
195/// Currently these are only TextBlocks that are the result of linking
196/// object files. TextBlock which take part in incremental linking are
194/// List of atoms that are owned directly by the linker.
195/// Currently these are only atoms that are the result of linking
196/// object files. Atoms which take part in incremental linking are
197197/// at present owned by Module.Decl.
198198/// TODO consolidate this.
199managed_blocks: std.ArrayListUnmanaged(*TextBlock) = .{},
199managed_atoms: std.ArrayListUnmanaged(*Atom) = .{},
200200
201201/// Table of Decls that are currently alive.
202202/// We store them here so that we can properly dispose of any allocated
203/// memory within the TextBlock in the incremental linker.
203/// memory within the atom in the incremental linker.
204204/// TODO consolidate this.
205205decls: std.AutoArrayHashMapUnmanaged(*Module.Decl, void) = .{},
206206
......@@ -768,31 +768,8 @@ pub fn flush(self: *MachO, comp: *Compilation) !void {
768768 try self.addDataInCodeLC();
769769 try self.addCodeSignatureLC();
770770
771 try self.parseTextBlocks();
771 try self.parseObjectsIntoAtoms();
772772 try self.allocateGlobalSymbols();
773 {
774 log.debug("locals:", .{});
775 for (self.locals.items) |sym| {
776 log.debug(" {s}: {}", .{ self.getString(sym.n_strx), sym });
777 }
778 log.debug("globals:", .{});
779 for (self.globals.items) |sym| {
780 log.debug(" {s}: {}", .{ self.getString(sym.n_strx), sym });
781 }
782 log.debug("undefs:", .{});
783 for (self.undefs.items) |sym| {
784 log.debug(" {s}: {}", .{ self.getString(sym.n_strx), sym });
785 }
786 log.debug("unresolved:", .{});
787 for (self.unresolved.keys()) |key| {
788 log.debug(" {d} => {s}", .{ key, self.unresolved.get(key).? });
789 }
790 log.debug("resolved:", .{});
791 var it = self.symbol_resolver.iterator();
792 while (it.next()) |entry| {
793 log.debug(" {s} => {}", .{ self.getString(entry.key_ptr.*), entry.value_ptr.* });
794 }
795 }
796773 try self.writeAtoms();
797774
798775 if (self.bss_section_index) |idx| {
......@@ -1637,87 +1614,24 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
16371614 return res;
16381615}
16391616
1640pub fn createEmptyAtom(self: *MachO, local_sym_index: u32, size: u64, alignment: u32) !*TextBlock {
1617pub fn createEmptyAtom(self: *MachO, local_sym_index: u32, size: u64, alignment: u32) !*Atom {
16411618 const code = try self.base.allocator.alloc(u8, size);
16421619 defer self.base.allocator.free(code);
16431620 mem.set(u8, code, 0);
16441621
1645 const atom = try self.base.allocator.create(TextBlock);
1622 const atom = try self.base.allocator.create(Atom);
16461623 errdefer self.base.allocator.destroy(atom);
1647 atom.* = TextBlock.empty;
1624 atom.* = Atom.empty;
16481625 atom.local_sym_index = local_sym_index;
16491626 atom.size = size;
16501627 atom.alignment = alignment;
16511628 try atom.code.appendSlice(self.base.allocator, code);
1652 try self.managed_blocks.append(self.base.allocator, atom);
1629 try self.managed_atoms.append(self.base.allocator, atom);
16531630
16541631 return atom;
16551632}
16561633
1657pub fn allocateAtom(self: *MachO, atom: *TextBlock, match: MatchingSection) !u64 {
1658 const seg = &self.load_commands.items[match.seg].Segment;
1659 const sect = &seg.sections.items[match.sect];
1660
1661 const sym = &self.locals.items[atom.local_sym_index];
1662 const needs_padding = match.seg == self.text_segment_cmd_index.? and match.sect == self.text_section_index.?;
1663
1664 var atom_placement: ?*TextBlock = null;
1665 const atom_alignment = try math.powi(u32, 2, atom.alignment);
1666
1667 // TODO converge with `allocateTextBlock` and handle free list
1668 var vaddr = if (self.blocks.get(match)) |last| blk: {
1669 const last_atom_sym = self.locals.items[last.local_sym_index];
1670 const ideal_capacity = if (needs_padding) padToIdeal(last.size) else last.size;
1671 const ideal_capacity_end_vaddr = last_atom_sym.n_value + ideal_capacity;
1672 const new_start_vaddr = mem.alignForwardGeneric(u64, ideal_capacity_end_vaddr, atom_alignment);
1673 atom_placement = last;
1674 break :blk new_start_vaddr;
1675 } else mem.alignForwardGeneric(u64, sect.addr, atom_alignment);
1676
1677 // TODO what if the section which was preallocated is not aligned to the maximum (section) alignment?
1678 // Should we move the section?
1679
1680 log.debug("allocating atom for symbol {s} at address 0x{x}", .{ self.getString(sym.n_strx), vaddr });
1681
1682 const expand_section = atom_placement == null or atom_placement.?.next == null;
1683 if (expand_section) {
1684 const needed_size = @intCast(u32, (vaddr + atom.size) - sect.addr);
1685 try self.growSection(match, needed_size);
1686 sect.size = needed_size;
1687 self.load_commands_dirty = true;
1688 }
1689 sect.@"align" = math.max(sect.@"align", atom.alignment);
1690
1691 const n_sect = @intCast(u8, self.section_ordinals.getIndex(match).? + 1);
1692 sym.n_value = vaddr;
1693 sym.n_sect = n_sect;
1694
1695 // Update each alias (if any)
1696 for (atom.aliases.items) |index| {
1697 const alias_sym = &self.locals.items[index];
1698 alias_sym.n_value = vaddr;
1699 alias_sym.n_sect = n_sect;
1700 }
1701
1702 // Update each symbol contained within the TextBlock
1703 for (atom.contained.items) |sym_at_off| {
1704 const contained_sym = &self.locals.items[sym_at_off.local_sym_index];
1705 contained_sym.n_value = vaddr + sym_at_off.offset;
1706 contained_sym.n_sect = n_sect;
1707 }
1708
1709 if (self.blocks.getPtr(match)) |last| {
1710 last.*.next = atom;
1711 atom.prev = last.*;
1712 last.* = atom;
1713 } else {
1714 try self.blocks.putNoClobber(self.base.allocator, match, atom);
1715 }
1716
1717 return vaddr;
1718}
1719
1720pub fn writeAtom(self: *MachO, atom: *TextBlock, match: MatchingSection) !void {
1634pub fn writeAtom(self: *MachO, atom: *Atom, match: MatchingSection) !void {
17211635 const seg = self.load_commands.items[match.seg].Segment;
17221636 const sect = seg.sections.items[match.sect];
17231637 const sym = self.locals.items[atom.local_sym_index];
......@@ -1728,7 +1642,7 @@ pub fn writeAtom(self: *MachO, atom: *TextBlock, match: MatchingSection) !void {
17281642}
17291643
17301644fn allocateLocalSymbols(self: *MachO, match: MatchingSection, offset: i64) !void {
1731 var atom = self.blocks.get(match) orelse return;
1645 var atom = self.atoms.get(match) orelse return;
17321646
17331647 while (true) {
17341648 const atom_sym = &self.locals.items[atom.local_sym_index];
......@@ -1751,8 +1665,6 @@ fn allocateLocalSymbols(self: *MachO, match: MatchingSection, offset: i64) !void
17511665}
17521666
17531667fn allocateGlobalSymbols(self: *MachO) !void {
1754 // TODO should we do this in `allocateAtom` (or similar)? Then, we would need to
1755 // store the link atom -> globals somewhere.
17561668 var sym_it = self.symbol_resolver.valueIterator();
17571669 while (sym_it.next()) |resolv| {
17581670 if (resolv.where != .global) continue;
......@@ -1770,12 +1682,14 @@ fn writeAtoms(self: *MachO) !void {
17701682 defer buffer.deinit();
17711683 var file_offset: ?u64 = null;
17721684
1773 var it = self.blocks.iterator();
1685 var it = self.atoms.iterator();
17741686 while (it.next()) |entry| {
17751687 const match = entry.key_ptr.*;
17761688 const seg = self.load_commands.items[match.seg].Segment;
17771689 const sect = seg.sections.items[match.sect];
1778 var atom: *TextBlock = entry.value_ptr.*;
1690 var atom: *Atom = entry.value_ptr.*;
1691
1692 log.debug("writing atoms in {s},{s}", .{ commands.segmentName(sect), commands.sectionName(sect) });
17791693
17801694 while (atom.prev) |prev| {
17811695 atom = prev;
......@@ -1789,6 +1703,8 @@ fn writeAtoms(self: *MachO) !void {
17891703 break :blk next_sym.n_value - (atom_sym.n_value + atom.size);
17901704 } else 0;
17911705
1706 log.debug(" (adding atom {s} to buffer: {})", .{ self.getString(atom_sym.n_strx), atom_sym });
1707
17921708 try atom.resolveRelocs(self);
17931709 try buffer.appendSlice(atom.code.items);
17941710 try buffer.ensureUnusedCapacity(padding_size);
......@@ -1824,7 +1740,7 @@ fn writeAtoms(self: *MachO) !void {
18241740 }
18251741}
18261742
1827pub fn createGotAtom(self: *MachO, key: GotIndirectionKey) !*TextBlock {
1743pub fn createGotAtom(self: *MachO, key: GotIndirectionKey) !*Atom {
18281744 const local_sym_index = @intCast(u32, self.locals.items.len);
18291745 try self.locals.append(self.base.allocator, .{
18301746 .n_strx = try self.makeString("l_zld_got_entry"),
......@@ -1860,7 +1776,7 @@ pub fn createGotAtom(self: *MachO, key: GotIndirectionKey) !*TextBlock {
18601776 return atom;
18611777}
18621778
1863fn createDyldPrivateAtom(self: *MachO) !*TextBlock {
1779fn createDyldPrivateAtom(self: *MachO) !*Atom {
18641780 const local_sym_index = @intCast(u32, self.locals.items.len);
18651781 try self.locals.append(self.base.allocator, .{
18661782 .n_strx = try self.makeString("l_zld_dyld_private"),
......@@ -1873,7 +1789,7 @@ fn createDyldPrivateAtom(self: *MachO) !*TextBlock {
18731789 return self.createEmptyAtom(local_sym_index, @sizeOf(u64), 3);
18741790}
18751791
1876fn createStubHelperPreambleAtom(self: *MachO) !*TextBlock {
1792fn createStubHelperPreambleAtom(self: *MachO) !*Atom {
18771793 const arch = self.base.options.target.cpu.arch;
18781794 const size: u64 = switch (arch) {
18791795 .x86_64 => 15,
......@@ -2006,7 +1922,7 @@ fn createStubHelperPreambleAtom(self: *MachO) !*TextBlock {
20061922 return atom;
20071923}
20081924
2009pub fn createStubHelperAtom(self: *MachO) !*TextBlock {
1925pub fn createStubHelperAtom(self: *MachO) !*Atom {
20101926 const arch = self.base.options.target.cpu.arch;
20111927 const stub_size: u4 = switch (arch) {
20121928 .x86_64 => 10,
......@@ -2072,7 +1988,7 @@ pub fn createStubHelperAtom(self: *MachO) !*TextBlock {
20721988 return atom;
20731989}
20741990
2075pub fn createLazyPointerAtom(self: *MachO, stub_sym_index: u32, lazy_binding_sym_index: u32) !*TextBlock {
1991pub fn createLazyPointerAtom(self: *MachO, stub_sym_index: u32, lazy_binding_sym_index: u32) !*Atom {
20761992 const local_sym_index = @intCast(u32, self.locals.items.len);
20771993 try self.locals.append(self.base.allocator, .{
20781994 .n_strx = try self.makeString("l_zld_lazy_ptr"),
......@@ -2102,7 +2018,7 @@ pub fn createLazyPointerAtom(self: *MachO, stub_sym_index: u32, lazy_binding_sym
21022018 return atom;
21032019}
21042020
2105pub fn createStubAtom(self: *MachO, laptr_sym_index: u32) !*TextBlock {
2021pub fn createStubAtom(self: *MachO, laptr_sym_index: u32) !*Atom {
21062022 const arch = self.base.options.target.cpu.arch;
21072023 const alignment: u2 = switch (arch) {
21082024 .x86_64 => 0,
......@@ -2273,14 +2189,6 @@ fn resolveSymbolsInObject(
22732189 continue;
22742190 },
22752191 .undef => {
2276 // const undef = &self.undefs.items[resolv.where_index];
2277 // undef.* = .{
2278 // .n_strx = 0,
2279 // .n_type = macho.N_UNDF,
2280 // .n_sect = 0,
2281 // .n_desc = 0,
2282 // .n_value = 0,
2283 // };
22842192 _ = self.unresolved.fetchSwapRemove(resolv.where_index);
22852193 },
22862194 }
......@@ -2437,23 +2345,36 @@ fn resolveSymbols(self: *MachO) !void {
24372345 resolv.local_sym_index = local_sym_index;
24382346
24392347 const atom = try self.createEmptyAtom(local_sym_index, size, alignment);
2440 _ = try self.allocateAtom(atom, match);
2348 const alignment_pow_2 = try math.powi(u32, 2, alignment);
2349 const vaddr = try self.allocateAtom(atom, size, alignment_pow_2, match);
2350 sym.n_value = vaddr;
24412351 }
24422352
24432353 try self.resolveDyldStubBinder();
24442354 {
2445 const atom = try self.createDyldPrivateAtom();
2446 _ = try self.allocateAtom(atom, .{
2355 const match = MatchingSection{
24472356 .seg = self.data_segment_cmd_index.?,
24482357 .sect = self.data_section_index.?,
2449 });
2358 };
2359 const atom = try self.createDyldPrivateAtom();
2360 const sym = &self.locals.items[atom.local_sym_index];
2361 const vaddr = try self.allocateAtom(atom, @sizeOf(u64), 8, match);
2362 sym.n_value = vaddr;
2363 sym.n_sect = @intCast(u8, self.section_ordinals.getIndex(match).? + 1);
2364 log.debug("allocated {s} atom at 0x{x}", .{ self.getString(sym.n_strx), vaddr });
24502365 }
24512366 {
2452 const atom = try self.createStubHelperPreambleAtom();
2453 _ = try self.allocateAtom(atom, .{
2367 const match = MatchingSection{
24542368 .seg = self.text_segment_cmd_index.?,
24552369 .sect = self.stub_helper_section_index.?,
2456 });
2370 };
2371 const atom = try self.createStubHelperPreambleAtom();
2372 const sym = &self.locals.items[atom.local_sym_index];
2373 const alignment = try math.powi(u32, 2, atom.alignment);
2374 const vaddr = try self.allocateAtom(atom, atom.size, alignment, match);
2375 sym.n_value = vaddr;
2376 sym.n_sect = @intCast(u8, self.section_ordinals.getIndex(match).? + 1);
2377 log.debug("allocated {s} atom at 0x{x}", .{ self.getString(sym.n_strx), vaddr });
24572378 }
24582379
24592380 // Third pass, resolve symbols in dynamic libraries.
......@@ -2483,30 +2404,45 @@ fn resolveSymbols(self: *MachO) !void {
24832404 .stub => {
24842405 if (self.stubs_map.contains(resolv.where_index)) break :outer_blk;
24852406 const stub_helper_atom = blk: {
2486 const atom = try self.createStubHelperAtom();
2487 _ = try self.allocateAtom(atom, .{
2407 const match = MatchingSection{
24882408 .seg = self.text_segment_cmd_index.?,
24892409 .sect = self.stub_helper_section_index.?,
2490 });
2410 };
2411 const atom = try self.createStubHelperAtom();
2412 const atom_sym = &self.locals.items[atom.local_sym_index];
2413 const alignment = try math.powi(u32, 2, atom.alignment);
2414 const vaddr = try self.allocateAtom(atom, atom.size, alignment, match);
2415 atom_sym.n_value = vaddr;
2416 atom_sym.n_sect = @intCast(u8, self.section_ordinals.getIndex(match).? + 1);
24912417 break :blk atom;
24922418 };
24932419 const laptr_atom = blk: {
2420 const match = MatchingSection{
2421 .seg = self.data_segment_cmd_index.?,
2422 .sect = self.la_symbol_ptr_section_index.?,
2423 };
24942424 const atom = try self.createLazyPointerAtom(
24952425 stub_helper_atom.local_sym_index,
24962426 resolv.where_index,
24972427 );
2498 _ = try self.allocateAtom(atom, .{
2499 .seg = self.data_segment_cmd_index.?,
2500 .sect = self.la_symbol_ptr_section_index.?,
2501 });
2428 const atom_sym = &self.locals.items[atom.local_sym_index];
2429 const alignment = try math.powi(u32, 2, atom.alignment);
2430 const vaddr = try self.allocateAtom(atom, atom.size, alignment, match);
2431 atom_sym.n_value = vaddr;
2432 atom_sym.n_sect = @intCast(u8, self.section_ordinals.getIndex(match).? + 1);
25022433 break :blk atom;
25032434 };
25042435 const stub_atom = blk: {
2505 const atom = try self.createStubAtom(laptr_atom.local_sym_index);
2506 _ = try self.allocateAtom(atom, .{
2436 const match = MatchingSection{
25072437 .seg = self.text_segment_cmd_index.?,
25082438 .sect = self.stubs_section_index.?,
2509 });
2439 };
2440 const atom = try self.createStubAtom(laptr_atom.local_sym_index);
2441 const atom_sym = &self.locals.items[atom.local_sym_index];
2442 const alignment = try math.powi(u32, 2, atom.alignment);
2443 const vaddr = try self.allocateAtom(atom, atom.size, alignment, match);
2444 atom_sym.n_value = vaddr;
2445 atom_sym.n_sect = @intCast(u8, self.section_ordinals.getIndex(match).? + 1);
25102446 break :blk atom;
25112447 };
25122448 try self.stubs_map.putNoClobber(self.base.allocator, resolv.where_index, stub_atom);
......@@ -2565,7 +2501,10 @@ fn resolveSymbols(self: *MachO) !void {
25652501 // TODO perhaps we should special-case special symbols? Create a separate
25662502 // linked list of atoms?
25672503 const atom = try self.createEmptyAtom(local_sym_index, 0, 0);
2568 _ = try self.allocateAtom(atom, match);
2504 const sym = &self.locals.items[local_sym_index];
2505 const vaddr = try self.allocateAtom(atom, 0, 1, match);
2506 sym.n_value = vaddr;
2507 atom.dirty = false; // We don't really want to write it to file.
25692508 }
25702509
25712510 for (self.unresolved.keys()) |index| {
......@@ -2632,10 +2571,14 @@ fn resolveDyldStubBinder(self: *MachO) !void {
26322571 .seg = self.data_const_segment_cmd_index.?,
26332572 .sect = self.got_section_index.?,
26342573 };
2635 _ = try self.allocateAtom(atom, match);
2574 const atom_sym = &self.locals.items[atom.local_sym_index];
2575 const vaddr = try self.allocateAtom(atom, @sizeOf(u64), 8, match);
2576 atom_sym.n_value = vaddr;
2577 atom_sym.n_sect = @intCast(u8, self.section_ordinals.getIndex(match).? + 1);
2578 log.debug("allocated {s} atom at 0x{x}", .{ self.getString(sym.n_strx), vaddr });
26362579}
26372580
2638fn parseTextBlocks(self: *MachO) !void {
2581fn parseObjectsIntoAtoms(self: *MachO) !void {
26392582 var parsed_atoms = Object.ParsedAtoms.init(self.base.allocator);
26402583 defer parsed_atoms.deinit();
26412584
......@@ -2710,7 +2653,7 @@ fn parseTextBlocks(self: *MachO) !void {
27102653 metadata.alignment,
27112654 });
27122655
2713 const sect_size = if (self.blocks.get(match)) |last| blk: {
2656 const sect_size = if (self.atoms.get(match)) |last| blk: {
27142657 const last_atom_sym = self.locals.items[last.local_sym_index];
27152658 break :blk last_atom_sym.n_value + last.size - sect.addr;
27162659 } else 0;
......@@ -2720,7 +2663,7 @@ fn parseTextBlocks(self: *MachO) !void {
27202663 try self.growSection(match, needed_size);
27212664 sect.size = needed_size;
27222665
2723 var base_vaddr = if (self.blocks.get(match)) |last| blk: {
2666 var base_vaddr = if (self.atoms.get(match)) |last| blk: {
27242667 const last_atom_sym = self.locals.items[last.local_sym_index];
27252668 break :blk last_atom_sym.n_value + last.size;
27262669 } else sect.addr;
......@@ -2750,7 +2693,7 @@ fn parseTextBlocks(self: *MachO) !void {
27502693 alias_sym.n_sect = n_sect;
27512694 }
27522695
2753 // Update each symbol contained within the TextBlock
2696 // Update each symbol contained within the atom
27542697 for (atom.contained.items) |sym_at_off| {
27552698 const contained_sym = &self.locals.items[sym_at_off.local_sym_index];
27562699 contained_sym.n_value = base_vaddr + sym_at_off.offset;
......@@ -2764,13 +2707,13 @@ fn parseTextBlocks(self: *MachO) !void {
27642707 } else break;
27652708 }
27662709
2767 if (self.blocks.getPtr(match)) |last| {
2710 if (self.atoms.getPtr(match)) |last| {
27682711 const first_atom = first_atoms.get(match).?;
27692712 last.*.next = first_atom;
27702713 first_atom.prev = last.*;
27712714 last.* = first_atom;
27722715 }
2773 _ = try self.blocks.put(self.base.allocator, match, parsed_atoms.get(match).?);
2716 _ = try self.atoms.put(self.base.allocator, match, parsed_atoms.get(match).?);
27742717 }
27752718}
27762719
......@@ -2905,18 +2848,18 @@ pub fn deinit(self: *MachO) void {
29052848 }
29062849 self.load_commands.deinit(self.base.allocator);
29072850
2908 for (self.managed_blocks.items) |block| {
2909 block.deinit(self.base.allocator);
2910 self.base.allocator.destroy(block);
2851 for (self.managed_atoms.items) |atom| {
2852 atom.deinit(self.base.allocator);
2853 self.base.allocator.destroy(atom);
29112854 }
2912 self.managed_blocks.deinit(self.base.allocator);
2913 self.blocks.deinit(self.base.allocator);
2855 self.managed_atoms.deinit(self.base.allocator);
2856 self.atoms.deinit(self.base.allocator);
29142857 {
2915 var it = self.block_free_lists.valueIterator();
2858 var it = self.atom_free_lists.valueIterator();
29162859 while (it.next()) |free_list| {
29172860 free_list.deinit(self.base.allocator);
29182861 }
2919 self.block_free_lists.deinit(self.base.allocator);
2862 self.atom_free_lists.deinit(self.base.allocator);
29202863 }
29212864 for (self.decls.keys()) |decl| {
29222865 decl.link.macho.deinit(self.base.allocator);
......@@ -2936,25 +2879,21 @@ pub fn closeFiles(self: MachO) void {
29362879 }
29372880}
29382881
2939fn freeTextBlock(self: *MachO, text_block: *TextBlock) void {
2940 log.debug("freeTextBlock {*}", .{text_block});
2941 text_block.deinit(self.base.allocator);
2882fn freeAtom(self: *MachO, atom: *Atom, match: MatchingSection) void {
2883 log.debug("freeAtom {*}", .{atom});
2884 atom.deinit(self.base.allocator);
29422885
2943 const match = MatchingSection{
2944 .seg = self.text_segment_cmd_index.?,
2945 .sect = self.text_section_index.?,
2946 };
2947 const text_block_free_list = self.block_free_lists.getPtr(match).?;
2886 const free_list = self.atom_free_lists.getPtr(match).?;
29482887 var already_have_free_list_node = false;
29492888 {
29502889 var i: usize = 0;
2951 // TODO turn text_block_free_list into a hash map
2952 while (i < text_block_free_list.items.len) {
2953 if (text_block_free_list.items[i] == text_block) {
2954 _ = text_block_free_list.swapRemove(i);
2890 // TODO turn free_list into a hash map
2891 while (i < free_list.items.len) {
2892 if (free_list.items[i] == atom) {
2893 _ = free_list.swapRemove(i);
29552894 continue;
29562895 }
2957 if (text_block_free_list.items[i] == text_block.prev) {
2896 if (free_list.items[i] == atom.prev) {
29582897 already_have_free_list_node = true;
29592898 }
29602899 i += 1;
......@@ -2962,72 +2901,73 @@ fn freeTextBlock(self: *MachO, text_block: *TextBlock) void {
29622901 }
29632902 // TODO process free list for dbg info just like we do above for vaddrs
29642903
2965 if (self.blocks.getPtr(match)) |last_text_block| {
2966 if (last_text_block.* == text_block) {
2967 if (text_block.prev) |prev| {
2968 // TODO shrink the __text section size here
2969 last_text_block.* = prev;
2904 if (self.atoms.getPtr(match)) |last_atom| {
2905 if (last_atom.* == atom) {
2906 if (atom.prev) |prev| {
2907 // TODO shrink the section size here
2908 last_atom.* = prev;
29702909 }
29712910 }
29722911 }
29732912
29742913 if (self.d_sym) |*ds| {
2975 if (ds.dbg_info_decl_first == text_block) {
2976 ds.dbg_info_decl_first = text_block.dbg_info_next;
2914 if (ds.dbg_info_decl_first == atom) {
2915 ds.dbg_info_decl_first = atom.dbg_info_next;
29772916 }
2978 if (ds.dbg_info_decl_last == text_block) {
2917 if (ds.dbg_info_decl_last == atom) {
29792918 // TODO shrink the .debug_info section size here
2980 ds.dbg_info_decl_last = text_block.dbg_info_prev;
2919 ds.dbg_info_decl_last = atom.dbg_info_prev;
29812920 }
29822921 }
29832922
2984 if (text_block.prev) |prev| {
2985 prev.next = text_block.next;
2923 if (atom.prev) |prev| {
2924 prev.next = atom.next;
29862925
29872926 if (!already_have_free_list_node and prev.freeListEligible(self.*)) {
29882927 // The free list is heuristics, it doesn't have to be perfect, so we can ignore
29892928 // the OOM here.
2990 text_block_free_list.append(self.base.allocator, prev) catch {};
2929 free_list.append(self.base.allocator, prev) catch {};
29912930 }
29922931 } else {
2993 text_block.prev = null;
2932 atom.prev = null;
29942933 }
29952934
2996 if (text_block.next) |next| {
2997 next.prev = text_block.prev;
2935 if (atom.next) |next| {
2936 next.prev = atom.prev;
29982937 } else {
2999 text_block.next = null;
2938 atom.next = null;
30002939 }
30012940
3002 if (text_block.dbg_info_prev) |prev| {
3003 prev.dbg_info_next = text_block.dbg_info_next;
2941 if (atom.dbg_info_prev) |prev| {
2942 prev.dbg_info_next = atom.dbg_info_next;
30042943
3005 // TODO the free list logic like we do for text blocks above
2944 // TODO the free list logic like we do for atoms above
30062945 } else {
3007 text_block.dbg_info_prev = null;
2946 atom.dbg_info_prev = null;
30082947 }
30092948
3010 if (text_block.dbg_info_next) |next| {
3011 next.dbg_info_prev = text_block.dbg_info_prev;
2949 if (atom.dbg_info_next) |next| {
2950 next.dbg_info_prev = atom.dbg_info_prev;
30122951 } else {
3013 text_block.dbg_info_next = null;
2952 atom.dbg_info_next = null;
30142953 }
30152954}
30162955
3017fn shrinkTextBlock(self: *MachO, text_block: *TextBlock, new_block_size: u64) void {
2956fn shrinkAtom(self: *MachO, atom: *Atom, new_block_size: u64, match: MatchingSection) void {
30182957 _ = self;
3019 _ = text_block;
2958 _ = atom;
30202959 _ = new_block_size;
2960 _ = match;
30212961 // TODO check the new capacity, and if it crosses the size threshold into a big enough
30222962 // capacity, insert a free list node for it.
30232963}
30242964
3025fn growTextBlock(self: *MachO, text_block: *TextBlock, new_block_size: u64, alignment: u64) !u64 {
3026 const sym = self.locals.items[text_block.local_sym_index];
2965fn growAtom(self: *MachO, atom: *Atom, new_atom_size: u64, alignment: u64, match: MatchingSection) !u64 {
2966 const sym = self.locals.items[atom.local_sym_index];
30272967 const align_ok = mem.alignBackwardGeneric(u64, sym.n_value, alignment) == sym.n_value;
3028 const need_realloc = !align_ok or new_block_size > text_block.capacity(self.*);
2968 const need_realloc = !align_ok or new_atom_size > atom.capacity(self.*);
30292969 if (!need_realloc) return sym.n_value;
3030 return self.allocateTextBlock(text_block, new_block_size, alignment);
2970 return self.allocateAtom(atom, new_atom_size, alignment, match);
30312971}
30322972
30332973pub fn allocateDeclIndexes(self: *MachO, decl: *Module.Decl) !void {
......@@ -3112,7 +3052,7 @@ pub fn updateFunc(self: *MachO, module: *Module, func: *Module.Fn, air: Air, liv
31123052 // in a different, smarter, more automatic way somewhere else, in a more centralised
31133053 // way than this.
31143054 // If we don't clear the buffers here, we are up for some nasty surprises when
3115 // this TextBlock is reused later on and was not freed by freeTextBlock().
3055 // this atom is reused later on and was not freed by freeAtom().
31163056 decl.link.macho.code.clearAndFree(self.base.allocator);
31173057 try decl.link.macho.code.appendSlice(self.base.allocator, code_buffer.items);
31183058 },
......@@ -3202,7 +3142,7 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {
32023142 // in a different, smarter, more automatic way somewhere else, in a more centralised
32033143 // way than this.
32043144 // If we don't clear the buffers here, we are up for some nasty surprises when
3205 // this TextBlock is reused later on and was not freed by freeTextBlock().
3145 // this atom is reused later on and was not freed by freeAtom().
32063146 decl.link.macho.code.clearAndFree(self.base.allocator);
32073147 try decl.link.macho.code.appendSlice(self.base.allocator, code_buffer.items);
32083148 break :blk decl.link.macho.code.items;
......@@ -3231,7 +3171,10 @@ fn placeDecl(self: *MachO, decl: *Module.Decl, code_len: usize) !*macho.nlist_64
32313171 const capacity = decl.link.macho.capacity(self.*);
32323172 const need_realloc = code_len > capacity or !mem.isAlignedGeneric(u64, symbol.n_value, required_alignment);
32333173 if (need_realloc) {
3234 const vaddr = try self.growTextBlock(&decl.link.macho, code_len, required_alignment);
3174 const vaddr = try self.growAtom(&decl.link.macho, code_len, required_alignment, .{
3175 .seg = self.text_segment_cmd_index.?,
3176 .sect = self.text_section_index.?,
3177 });
32353178
32363179 log.debug("growing {s} and moving from 0x{x} to 0x{x}", .{ decl.name, symbol.n_value, vaddr });
32373180
......@@ -3241,15 +3184,24 @@ fn placeDecl(self: *MachO, decl: *Module.Decl, code_len: usize) !*macho.nlist_64
32413184 .where = .local,
32423185 .where_index = decl.link.macho.local_sym_index,
32433186 }) orelse unreachable;
3244 _ = try self.allocateAtom(got_atom, .{
3187 const got_sym = &self.locals.items[got_atom.local_sym_index];
3188 const got_vaddr = try self.allocateAtom(got_atom, @sizeOf(u64), 8, .{
32453189 .seg = self.data_const_segment_cmd_index.?,
32463190 .sect = self.got_section_index.?,
32473191 });
3192 got_sym.n_value = got_vaddr;
3193 got_sym.n_sect = @intCast(u8, self.section_ordinals.getIndex(.{
3194 .seg = self.data_const_segment_cmd_index.?,
3195 .sect = self.got_section_index.?,
3196 }).? + 1);
32483197 }
32493198
32503199 symbol.n_value = vaddr;
32513200 } else if (code_len < decl.link.macho.size) {
3252 self.shrinkTextBlock(&decl.link.macho, code_len);
3201 self.shrinkAtom(&decl.link.macho, code_len, .{
3202 .seg = self.text_segment_cmd_index.?,
3203 .sect = self.text_section_index.?,
3204 });
32533205 }
32543206 decl.link.macho.size = code_len;
32553207
......@@ -3265,11 +3217,17 @@ fn placeDecl(self: *MachO, decl: *Module.Decl, code_len: usize) !*macho.nlist_64
32653217 defer self.base.allocator.free(decl_name);
32663218
32673219 const name_str_index = try self.makeString(decl_name);
3268 const addr = try self.allocateTextBlock(&decl.link.macho, code_len, required_alignment);
3220 const addr = try self.allocateAtom(&decl.link.macho, code_len, required_alignment, .{
3221 .seg = self.text_segment_cmd_index.?,
3222 .sect = self.text_section_index.?,
3223 });
32693224
3270 log.debug("allocated text block for {s} at 0x{x}", .{ decl_name, addr });
3225 log.debug("allocated atom for {s} at 0x{x}", .{ decl_name, addr });
32713226
3272 errdefer self.freeTextBlock(&decl.link.macho);
3227 errdefer self.freeAtom(&decl.link.macho, .{
3228 .seg = self.text_segment_cmd_index.?,
3229 .sect = self.text_section_index.?,
3230 });
32733231
32743232 symbol.* = .{
32753233 .n_strx = name_str_index,
......@@ -3282,10 +3240,16 @@ fn placeDecl(self: *MachO, decl: *Module.Decl, code_len: usize) !*macho.nlist_64
32823240 .where = .local,
32833241 .where_index = decl.link.macho.local_sym_index,
32843242 }) orelse unreachable;
3285 _ = try self.allocateAtom(got_atom, .{
3243 const got_sym = &self.locals.items[got_atom.local_sym_index];
3244 const vaddr = try self.allocateAtom(got_atom, @sizeOf(u64), 8, .{
32863245 .seg = self.data_const_segment_cmd_index.?,
32873246 .sect = self.got_section_index.?,
32883247 });
3248 got_sym.n_value = vaddr;
3249 got_sym.n_sect = @intCast(u8, self.section_ordinals.getIndex(.{
3250 .seg = self.data_const_segment_cmd_index.?,
3251 .sect = self.got_section_index.?,
3252 }).? + 1);
32893253 }
32903254
32913255 return symbol;
......@@ -3402,7 +3366,10 @@ pub fn freeDecl(self: *MachO, decl: *Module.Decl) void {
34023366 log.debug("freeDecl {*}", .{decl});
34033367 _ = self.decls.swapRemove(decl);
34043368 // Appending to free lists is allowed to fail because the free lists are heuristics based anyway.
3405 self.freeTextBlock(&decl.link.macho);
3369 self.freeAtom(&decl.link.macho, .{
3370 .seg = self.text_segment_cmd_index.?,
3371 .sect = self.text_section_index.?,
3372 });
34063373 if (decl.link.macho.local_sym_index != 0) {
34073374 self.locals_free_list.append(self.base.allocator, decl.link.macho.local_sym_index) catch {};
34083375
......@@ -3412,7 +3379,7 @@ pub fn freeDecl(self: *MachO, decl: *Module.Decl) void {
34123379 decl.link.macho.local_sym_index = 0;
34133380 }
34143381 if (self.d_sym) |*ds| {
3415 // TODO make this logic match freeTextBlock. Maybe abstract the logic
3382 // TODO make this logic match freeAtom. Maybe abstract the logic
34163383 // out since the same thing is desired for both.
34173384 _ = ds.dbg_line_fn_free_list.remove(&decl.fn_link.macho);
34183385 if (decl.fn_link.macho.prev) |prev| {
......@@ -3947,7 +3914,7 @@ fn allocateSection(
39473914 .sect = index,
39483915 };
39493916 _ = try self.section_ordinals.getOrPut(self.base.allocator, match);
3950 try self.block_free_lists.putNoClobber(self.base.allocator, match, .{});
3917 try self.atom_free_lists.putNoClobber(self.base.allocator, match, .{});
39513918
39523919 self.load_commands_dirty = true;
39533920 self.sections_order_dirty = true;
......@@ -4113,106 +4080,105 @@ fn getSectionMaxAlignment(self: *MachO, segment_id: u16, start_sect_id: u16) !u3
41134080 return max_alignment;
41144081}
41154082
4116fn allocateTextBlock(self: *MachO, text_block: *TextBlock, new_block_size: u64, alignment: u64) !u64 {
4117 const text_segment = &self.load_commands.items[self.text_segment_cmd_index.?].Segment;
4118 const text_section = &text_segment.sections.items[self.text_section_index.?];
4119 const match = MatchingSection{
4120 .seg = self.text_segment_cmd_index.?,
4121 .sect = self.text_section_index.?,
4122 };
4123 var text_block_free_list = self.block_free_lists.get(match).?;
4124 const new_block_ideal_capacity = padToIdeal(new_block_size);
4083fn allocateAtom(self: *MachO, atom: *Atom, new_atom_size: u64, alignment: u64, match: MatchingSection) !u64 {
4084 const seg = &self.load_commands.items[match.seg].Segment;
4085 const sect = &seg.sections.items[match.sect];
4086 var free_list = self.atom_free_lists.get(match).?;
4087 const needs_padding = match.seg == self.text_segment_cmd_index.? and match.sect == self.text_section_index.?;
4088 const new_atom_ideal_capacity = if (needs_padding) padToIdeal(new_atom_size) else new_atom_size;
41254089
4126 // We use these to indicate our intention to update metadata, placing the new block,
4090 // We use these to indicate our intention to update metadata, placing the new atom,
41274091 // and possibly removing a free list node.
41284092 // It would be simpler to do it inside the for loop below, but that would cause a
41294093 // problem if an error was returned later in the function. So this action
41304094 // is actually carried out at the end of the function, when errors are no longer possible.
4131 var block_placement: ?*TextBlock = null;
4095 var atom_placement: ?*Atom = null;
41324096 var free_list_removal: ?usize = null;
41334097
41344098 // First we look for an appropriately sized free list node.
41354099 // The list is unordered. We'll just take the first thing that works.
41364100 var vaddr = blk: {
41374101 var i: usize = 0;
4138 while (i < text_block_free_list.items.len) {
4139 const big_block = text_block_free_list.items[i];
4140 // We now have a pointer to a live text block that has too much capacity.
4141 // Is it enough that we could fit this new text block?
4142 const sym = self.locals.items[big_block.local_sym_index];
4143 const capacity = big_block.capacity(self.*);
4144 const ideal_capacity = padToIdeal(capacity);
4102 while (i < free_list.items.len) {
4103 const big_atom = free_list.items[i];
4104 // We now have a pointer to a live atom that has too much capacity.
4105 // Is it enough that we could fit this new atom?
4106 const sym = self.locals.items[big_atom.local_sym_index];
4107 const capacity = big_atom.capacity(self.*);
4108 const ideal_capacity = if (needs_padding) padToIdeal(capacity) else capacity;
41454109 const ideal_capacity_end_vaddr = sym.n_value + ideal_capacity;
41464110 const capacity_end_vaddr = sym.n_value + capacity;
4147 const new_start_vaddr_unaligned = capacity_end_vaddr - new_block_ideal_capacity;
4111 const new_start_vaddr_unaligned = capacity_end_vaddr - new_atom_ideal_capacity;
41484112 const new_start_vaddr = mem.alignBackwardGeneric(u64, new_start_vaddr_unaligned, alignment);
41494113 if (new_start_vaddr < ideal_capacity_end_vaddr) {
41504114 // Additional bookkeeping here to notice if this free list node
4151 // should be deleted because the block that it points to has grown to take up
4115 // should be deleted because the atom that it points to has grown to take up
41524116 // more of the extra capacity.
4153 if (!big_block.freeListEligible(self.*)) {
4154 const bl = text_block_free_list.swapRemove(i);
4117 if (!big_atom.freeListEligible(self.*)) {
4118 const bl = free_list.swapRemove(i);
41554119 bl.deinit(self.base.allocator);
41564120 } else {
41574121 i += 1;
41584122 }
41594123 continue;
41604124 }
4161 // At this point we know that we will place the new block here. But the
4125 // At this point we know that we will place the new atom here. But the
41624126 // remaining question is whether there is still yet enough capacity left
41634127 // over for there to still be a free list node.
41644128 const remaining_capacity = new_start_vaddr - ideal_capacity_end_vaddr;
41654129 const keep_free_list_node = remaining_capacity >= min_text_capacity;
41664130
41674131 // Set up the metadata to be updated, after errors are no longer possible.
4168 block_placement = big_block;
4132 atom_placement = big_atom;
41694133 if (!keep_free_list_node) {
41704134 free_list_removal = i;
41714135 }
41724136 break :blk new_start_vaddr;
4173 } else if (self.blocks.get(match)) |last| {
4137 } else if (self.atoms.get(match)) |last| {
41744138 const last_symbol = self.locals.items[last.local_sym_index];
4175 // TODO We should pad out the excess capacity with NOPs. For executables,
4176 // no padding seems to be OK, but it will probably not be for objects.
4177 const ideal_capacity = padToIdeal(last.size);
4139 const ideal_capacity = if (needs_padding) padToIdeal(last.size) else last.size;
41784140 const ideal_capacity_end_vaddr = last_symbol.n_value + ideal_capacity;
41794141 const new_start_vaddr = mem.alignForwardGeneric(u64, ideal_capacity_end_vaddr, alignment);
4180 block_placement = last;
4142 atom_placement = last;
41814143 break :blk new_start_vaddr;
41824144 } else {
4183 break :blk text_section.addr;
4145 break :blk mem.alignForwardGeneric(u64, sect.addr, alignment);
41844146 }
41854147 };
41864148
4187 const expand_text_section = block_placement == null or block_placement.?.next == null;
4188 if (expand_text_section) {
4189 const needed_size = @intCast(u32, (vaddr + new_block_size) - text_section.addr);
4149 const expand_section = atom_placement == null or atom_placement.?.next == null;
4150 if (expand_section) {
4151 const needed_size = @intCast(u32, (vaddr + new_atom_size) - sect.addr);
41904152 try self.growSection(match, needed_size);
4191 _ = try self.blocks.put(self.base.allocator, match, text_block);
4192 text_section.size = needed_size;
4153 _ = try self.atoms.put(self.base.allocator, match, atom);
4154 sect.size = needed_size;
41934155 self.load_commands_dirty = true;
41944156 }
41954157 const align_pow = @intCast(u32, math.log2(alignment));
4196 text_section.@"align" = math.max(text_section.@"align", align_pow);
4197 text_block.size = new_block_size;
4158 if (sect.@"align" < align_pow) {
4159 sect.@"align" = align_pow;
4160 self.load_commands_dirty = true;
4161 }
4162 atom.size = new_atom_size;
4163 atom.alignment = align_pow;
41984164
4199 if (text_block.prev) |prev| {
4200 prev.next = text_block.next;
4165 if (atom.prev) |prev| {
4166 prev.next = atom.next;
42014167 }
4202 if (text_block.next) |next| {
4203 next.prev = text_block.prev;
4168 if (atom.next) |next| {
4169 next.prev = atom.prev;
42044170 }
42054171
4206 if (block_placement) |big_block| {
4207 text_block.prev = big_block;
4208 text_block.next = big_block.next;
4209 big_block.next = text_block;
4172 if (atom_placement) |big_atom| {
4173 atom.prev = big_atom;
4174 atom.next = big_atom.next;
4175 big_atom.next = atom;
42104176 } else {
4211 text_block.prev = null;
4212 text_block.next = null;
4177 atom.prev = null;
4178 atom.next = null;
42134179 }
42144180 if (free_list_removal) |i| {
4215 _ = text_block_free_list.swapRemove(i);
4181 _ = free_list.swapRemove(i);
42164182 }
42174183
42184184 return vaddr;
......@@ -4319,10 +4285,10 @@ fn writeDyldInfoData(self: *MachO) !void {
43194285 defer lazy_bind_pointers.deinit();
43204286
43214287 {
4322 var it = self.blocks.iterator();
4288 var it = self.atoms.iterator();
43234289 while (it.next()) |entry| {
43244290 const match = entry.key_ptr.*;
4325 var atom: *TextBlock = entry.value_ptr.*;
4291 var atom: *Atom = entry.value_ptr.*;
43264292
43274293 if (match.seg == self.text_segment_cmd_index.?) continue; // __TEXT is non-writable
43284294
......@@ -4444,7 +4410,7 @@ fn writeDyldInfoData(self: *MachO) !void {
44444410}
44454411
44464412fn populateLazyBindOffsetsInStubHelper(self: *MachO, buffer: []const u8) !void {
4447 const last_atom = self.blocks.get(.{
4413 const last_atom = self.atoms.get(.{
44484414 .seg = self.text_segment_cmd_index.?,
44494415 .sect = self.stub_helper_section_index.?,
44504416 }) orelse return;
......@@ -4538,25 +4504,25 @@ fn writeDices(self: *MachO) !void {
45384504 var buf = std.ArrayList(u8).init(self.base.allocator);
45394505 defer buf.deinit();
45404506
4541 var block: *TextBlock = self.blocks.get(.{
4507 var atom: *Atom = self.atoms.get(.{
45424508 .seg = self.text_segment_cmd_index orelse return,
45434509 .sect = self.text_section_index orelse return,
45444510 }) orelse return;
45454511
4546 while (block.prev) |prev| {
4547 block = prev;
4512 while (atom.prev) |prev| {
4513 atom = prev;
45484514 }
45494515
45504516 const text_seg = self.load_commands.items[self.text_segment_cmd_index.?].Segment;
45514517 const text_sect = text_seg.sections.items[self.text_section_index.?];
45524518
45534519 while (true) {
4554 if (block.dices.items.len > 0) {
4555 const sym = self.locals.items[block.local_sym_index];
4520 if (atom.dices.items.len > 0) {
4521 const sym = self.locals.items[atom.local_sym_index];
45564522 const base_off = try math.cast(u32, sym.n_value - text_sect.addr + text_sect.offset);
45574523
4558 try buf.ensureUnusedCapacity(block.dices.items.len * @sizeOf(macho.data_in_code_entry));
4559 for (block.dices.items) |dice| {
4524 try buf.ensureUnusedCapacity(atom.dices.items.len * @sizeOf(macho.data_in_code_entry));
4525 for (atom.dices.items) |dice| {
45604526 const rebased_dice = macho.data_in_code_entry{
45614527 .offset = base_off + dice.offset,
45624528 .length = dice.length,
......@@ -4566,8 +4532,8 @@ fn writeDices(self: *MachO) !void {
45664532 }
45674533 }
45684534
4569 if (block.next) |next| {
4570 block = next;
4535 if (atom.next) |next| {
4536 atom = next;
45714537 } else break;
45724538 }
45734539