| ... | @@ -158,8 +158,8 @@ stub_preamble_sym_index: ?u32 = null, | ... | @@ -158,8 +158,8 @@ stub_preamble_sym_index: ?u32 = null, |
| 158 | strtab: std.ArrayListUnmanaged(u8) = .{}, | 158 | strtab: std.ArrayListUnmanaged(u8) = .{}, |
| 159 | strtab_dir: std.HashMapUnmanaged(u32, u32, StringIndexContext, std.hash_map.default_max_load_percentage) = .{}, | 159 | strtab_dir: std.HashMapUnmanaged(u32, u32, StringIndexContext, std.hash_map.default_max_load_percentage) = .{}, |
| 160 | | 160 | |
| 161 | got_entries_map: std.AutoArrayHashMapUnmanaged(GotIndirectionKey, *TextBlock) = .{}, | 161 | got_entries_map: std.AutoArrayHashMapUnmanaged(GotIndirectionKey, *Atom) = .{}, |
| 162 | stubs_map: std.AutoArrayHashMapUnmanaged(u32, *TextBlock) = .{}, | 162 | stubs_map: std.AutoArrayHashMapUnmanaged(u32, *Atom) = .{}, |
| 163 | | 163 | |
| 164 | error_flags: File.ErrorFlags = File.ErrorFlags{}, | 164 | error_flags: File.ErrorFlags = File.ErrorFlags{}, |
| 165 | | 165 | |
| ... | @@ -171,12 +171,12 @@ has_stabs: bool = false, | ... | @@ -171,12 +171,12 @@ has_stabs: bool = false, |
| 171 | | 171 | |
| 172 | section_ordinals: std.AutoArrayHashMapUnmanaged(MatchingSection, void) = .{}, | 172 | section_ordinals: std.AutoArrayHashMapUnmanaged(MatchingSection, void) = .{}, |
| 173 | | 173 | |
| 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 |
| 175 | /// positives, as functions grow and shrink over time, only sometimes being added | 175 | /// positives, as functions grow and shrink over time, only sometimes being added |
| 176 | /// or removed from the freelist. | 176 | /// or removed from the freelist. |
| 177 | /// | 177 | /// |
| 178 | /// A text block has surplus capacity when its overcapacity value is greater than | 178 | /// An atom has surplus capacity when its overcapacity value is greater than |
| 179 | /// padToIdeal(minimum_text_block_size). That is, when it has so | 179 | /// padToIdeal(minimum_atom_size). That is, when it has so |
| 180 | /// much extra capacity, that we could fit a small new symbol in it, itself with | 180 | /// much extra capacity, that we could fit a small new symbol in it, itself with |
| 181 | /// ideal_capacity or more. | 181 | /// ideal_capacity or more. |
| 182 | /// | 182 | /// |
| ... | @@ -184,23 +184,23 @@ section_ordinals: std.AutoArrayHashMapUnmanaged(MatchingSection, void) = .{}, | ... | @@ -184,23 +184,23 @@ section_ordinals: std.AutoArrayHashMapUnmanaged(MatchingSection, void) = .{}, |
| 184 | /// | 184 | /// |
| 185 | /// Overcapacity is measured by actual_capacity - ideal_capacity. Note that | 185 | /// Overcapacity is measured by actual_capacity - ideal_capacity. Note that |
| 186 | /// overcapacity can be negative. A simple way to have negative overcapacity is to | 186 | /// 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 |
| 188 | /// by 1 byte. It will then have -1 overcapacity. | 188 | /// by 1 byte. It will then have -1 overcapacity. |
| 189 | block_free_lists: std.AutoHashMapUnmanaged(MatchingSection, std.ArrayListUnmanaged(*TextBlock)) = .{}, | 189 | atom_free_lists: std.AutoHashMapUnmanaged(MatchingSection, std.ArrayListUnmanaged(*Atom)) = .{}, |
| 190 | | 190 | |
| 191 | /// Pointer to the last allocated text block | 191 | /// Pointer to the last allocated atom |
| 192 | blocks: std.AutoHashMapUnmanaged(MatchingSection, *TextBlock) = .{}, | 192 | atoms: std.AutoHashMapUnmanaged(MatchingSection, *Atom) = .{}, |
| 193 | | 193 | |
| 194 | /// List of TextBlocks that are owned directly by the linker. | 194 | /// List of atoms that are owned directly by the linker. |
| 195 | /// Currently these are only TextBlocks that are the result of linking | 195 | /// Currently these are only atoms that are the result of linking |
| 196 | /// object files. TextBlock which take part in incremental linking are | 196 | /// object files. Atoms which take part in incremental linking are |
| 197 | /// at present owned by Module.Decl. | 197 | /// at present owned by Module.Decl. |
| 198 | /// TODO consolidate this. | 198 | /// TODO consolidate this. |
| 199 | managed_blocks: std.ArrayListUnmanaged(*TextBlock) = .{}, | 199 | managed_atoms: std.ArrayListUnmanaged(*Atom) = .{}, |
| 200 | | 200 | |
| 201 | /// Table of Decls that are currently alive. | 201 | /// Table of Decls that are currently alive. |
| 202 | /// We store them here so that we can properly dispose of any allocated | 202 | /// 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. |
| 204 | /// TODO consolidate this. | 204 | /// TODO consolidate this. |
| 205 | decls: std.AutoArrayHashMapUnmanaged(*Module.Decl, void) = .{}, | 205 | decls: std.AutoArrayHashMapUnmanaged(*Module.Decl, void) = .{}, |
| 206 | | 206 | |
| ... | @@ -768,31 +768,8 @@ pub fn flush(self: *MachO, comp: *Compilation) !void { | ... | @@ -768,31 +768,8 @@ pub fn flush(self: *MachO, comp: *Compilation) !void { |
| 768 | try self.addDataInCodeLC(); | 768 | try self.addDataInCodeLC(); |
| 769 | try self.addCodeSignatureLC(); | 769 | try self.addCodeSignatureLC(); |
| 770 | | 770 | |
| 771 | try self.parseTextBlocks(); | 771 | try self.parseObjectsIntoAtoms(); |
| 772 | try self.allocateGlobalSymbols(); | 772 | 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 | } | | |
| 796 | try self.writeAtoms(); | 773 | try self.writeAtoms(); |
| 797 | | 774 | |
| 798 | if (self.bss_section_index) |idx| { | 775 | if (self.bss_section_index) |idx| { |
| ... | @@ -1637,87 +1614,24 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio | ... | @@ -1637,87 +1614,24 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1637 | return res; | 1614 | return res; |
| 1638 | } | 1615 | } |
| 1639 | | 1616 | |
| 1640 | pub fn createEmptyAtom(self: *MachO, local_sym_index: u32, size: u64, alignment: u32) !*TextBlock { | 1617 | pub fn createEmptyAtom(self: *MachO, local_sym_index: u32, size: u64, alignment: u32) !*Atom { |
| 1641 | const code = try self.base.allocator.alloc(u8, size); | 1618 | const code = try self.base.allocator.alloc(u8, size); |
| 1642 | defer self.base.allocator.free(code); | 1619 | defer self.base.allocator.free(code); |
| 1643 | mem.set(u8, code, 0); | 1620 | mem.set(u8, code, 0); |
| 1644 | | 1621 | |
| 1645 | const atom = try self.base.allocator.create(TextBlock); | 1622 | const atom = try self.base.allocator.create(Atom); |
| 1646 | errdefer self.base.allocator.destroy(atom); | 1623 | errdefer self.base.allocator.destroy(atom); |
| 1647 | atom.* = TextBlock.empty; | 1624 | atom.* = Atom.empty; |
| 1648 | atom.local_sym_index = local_sym_index; | 1625 | atom.local_sym_index = local_sym_index; |
| 1649 | atom.size = size; | 1626 | atom.size = size; |
| 1650 | atom.alignment = alignment; | 1627 | atom.alignment = alignment; |
| 1651 | try atom.code.appendSlice(self.base.allocator, code); | 1628 | 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); |
| 1653 | | 1630 | |
| 1654 | return atom; | 1631 | return atom; |
| 1655 | } | 1632 | } |
| 1656 | | 1633 | |
| 1657 | pub fn allocateAtom(self: *MachO, atom: *TextBlock, match: MatchingSection) !u64 { | 1634 | pub fn writeAtom(self: *MachO, atom: *Atom, match: MatchingSection) !void { |
| 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 | | | |
| 1720 | pub fn writeAtom(self: *MachO, atom: *TextBlock, match: MatchingSection) !void { | | |
| 1721 | const seg = self.load_commands.items[match.seg].Segment; | 1635 | const seg = self.load_commands.items[match.seg].Segment; |
| 1722 | const sect = seg.sections.items[match.sect]; | 1636 | const sect = seg.sections.items[match.sect]; |
| 1723 | const sym = self.locals.items[atom.local_sym_index]; | 1637 | const sym = self.locals.items[atom.local_sym_index]; |
| ... | @@ -1728,7 +1642,7 @@ pub fn writeAtom(self: *MachO, atom: *TextBlock, match: MatchingSection) !void { | ... | @@ -1728,7 +1642,7 @@ pub fn writeAtom(self: *MachO, atom: *TextBlock, match: MatchingSection) !void { |
| 1728 | } | 1642 | } |
| 1729 | | 1643 | |
| 1730 | fn allocateLocalSymbols(self: *MachO, match: MatchingSection, offset: i64) !void { | 1644 | fn 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; |
| 1732 | | 1646 | |
| 1733 | while (true) { | 1647 | while (true) { |
| 1734 | const atom_sym = &self.locals.items[atom.local_sym_index]; | 1648 | const atom_sym = &self.locals.items[atom.local_sym_index]; |
| ... | @@ -1751,8 +1665,6 @@ fn allocateLocalSymbols(self: *MachO, match: MatchingSection, offset: i64) !void | ... | @@ -1751,8 +1665,6 @@ fn allocateLocalSymbols(self: *MachO, match: MatchingSection, offset: i64) !void |
| 1751 | } | 1665 | } |
| 1752 | | 1666 | |
| 1753 | fn allocateGlobalSymbols(self: *MachO) !void { | 1667 | fn 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. | | |
| 1756 | var sym_it = self.symbol_resolver.valueIterator(); | 1668 | var sym_it = self.symbol_resolver.valueIterator(); |
| 1757 | while (sym_it.next()) |resolv| { | 1669 | while (sym_it.next()) |resolv| { |
| 1758 | if (resolv.where != .global) continue; | 1670 | if (resolv.where != .global) continue; |
| ... | @@ -1770,12 +1682,14 @@ fn writeAtoms(self: *MachO) !void { | ... | @@ -1770,12 +1682,14 @@ fn writeAtoms(self: *MachO) !void { |
| 1770 | defer buffer.deinit(); | 1682 | defer buffer.deinit(); |
| 1771 | var file_offset: ?u64 = null; | 1683 | var file_offset: ?u64 = null; |
| 1772 | | 1684 | |
| 1773 | var it = self.blocks.iterator(); | 1685 | var it = self.atoms.iterator(); |
| 1774 | while (it.next()) |entry| { | 1686 | while (it.next()) |entry| { |
| 1775 | const match = entry.key_ptr.*; | 1687 | const match = entry.key_ptr.*; |
| 1776 | const seg = self.load_commands.items[match.seg].Segment; | 1688 | const seg = self.load_commands.items[match.seg].Segment; |
| 1777 | const sect = seg.sections.items[match.sect]; | 1689 | 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) }); |
| 1779 | | 1693 | |
| 1780 | while (atom.prev) |prev| { | 1694 | while (atom.prev) |prev| { |
| 1781 | atom = prev; | 1695 | atom = prev; |
| ... | @@ -1789,6 +1703,8 @@ fn writeAtoms(self: *MachO) !void { | ... | @@ -1789,6 +1703,8 @@ fn writeAtoms(self: *MachO) !void { |
| 1789 | break :blk next_sym.n_value - (atom_sym.n_value + atom.size); | 1703 | break :blk next_sym.n_value - (atom_sym.n_value + atom.size); |
| 1790 | } else 0; | 1704 | } else 0; |
| 1791 | | 1705 | |
| | 1706 | log.debug(" (adding atom {s} to buffer: {})", .{ self.getString(atom_sym.n_strx), atom_sym }); |
| | 1707 | |
| 1792 | try atom.resolveRelocs(self); | 1708 | try atom.resolveRelocs(self); |
| 1793 | try buffer.appendSlice(atom.code.items); | 1709 | try buffer.appendSlice(atom.code.items); |
| 1794 | try buffer.ensureUnusedCapacity(padding_size); | 1710 | try buffer.ensureUnusedCapacity(padding_size); |
| ... | @@ -1824,7 +1740,7 @@ fn writeAtoms(self: *MachO) !void { | ... | @@ -1824,7 +1740,7 @@ fn writeAtoms(self: *MachO) !void { |
| 1824 | } | 1740 | } |
| 1825 | } | 1741 | } |
| 1826 | | 1742 | |
| 1827 | pub fn createGotAtom(self: *MachO, key: GotIndirectionKey) !*TextBlock { | 1743 | pub fn createGotAtom(self: *MachO, key: GotIndirectionKey) !*Atom { |
| 1828 | const local_sym_index = @intCast(u32, self.locals.items.len); | 1744 | const local_sym_index = @intCast(u32, self.locals.items.len); |
| 1829 | try self.locals.append(self.base.allocator, .{ | 1745 | try self.locals.append(self.base.allocator, .{ |
| 1830 | .n_strx = try self.makeString("l_zld_got_entry"), | 1746 | .n_strx = try self.makeString("l_zld_got_entry"), |
| ... | @@ -1860,7 +1776,7 @@ pub fn createGotAtom(self: *MachO, key: GotIndirectionKey) !*TextBlock { | ... | @@ -1860,7 +1776,7 @@ pub fn createGotAtom(self: *MachO, key: GotIndirectionKey) !*TextBlock { |
| 1860 | return atom; | 1776 | return atom; |
| 1861 | } | 1777 | } |
| 1862 | | 1778 | |
| 1863 | fn createDyldPrivateAtom(self: *MachO) !*TextBlock { | 1779 | fn createDyldPrivateAtom(self: *MachO) !*Atom { |
| 1864 | const local_sym_index = @intCast(u32, self.locals.items.len); | 1780 | const local_sym_index = @intCast(u32, self.locals.items.len); |
| 1865 | try self.locals.append(self.base.allocator, .{ | 1781 | try self.locals.append(self.base.allocator, .{ |
| 1866 | .n_strx = try self.makeString("l_zld_dyld_private"), | 1782 | .n_strx = try self.makeString("l_zld_dyld_private"), |
| ... | @@ -1873,7 +1789,7 @@ fn createDyldPrivateAtom(self: *MachO) !*TextBlock { | ... | @@ -1873,7 +1789,7 @@ fn createDyldPrivateAtom(self: *MachO) !*TextBlock { |
| 1873 | return self.createEmptyAtom(local_sym_index, @sizeOf(u64), 3); | 1789 | return self.createEmptyAtom(local_sym_index, @sizeOf(u64), 3); |
| 1874 | } | 1790 | } |
| 1875 | | 1791 | |
| 1876 | fn createStubHelperPreambleAtom(self: *MachO) !*TextBlock { | 1792 | fn createStubHelperPreambleAtom(self: *MachO) !*Atom { |
| 1877 | const arch = self.base.options.target.cpu.arch; | 1793 | const arch = self.base.options.target.cpu.arch; |
| 1878 | const size: u64 = switch (arch) { | 1794 | const size: u64 = switch (arch) { |
| 1879 | .x86_64 => 15, | 1795 | .x86_64 => 15, |
| ... | @@ -2006,7 +1922,7 @@ fn createStubHelperPreambleAtom(self: *MachO) !*TextBlock { | ... | @@ -2006,7 +1922,7 @@ fn createStubHelperPreambleAtom(self: *MachO) !*TextBlock { |
| 2006 | return atom; | 1922 | return atom; |
| 2007 | } | 1923 | } |
| 2008 | | 1924 | |
| 2009 | pub fn createStubHelperAtom(self: *MachO) !*TextBlock { | 1925 | pub fn createStubHelperAtom(self: *MachO) !*Atom { |
| 2010 | const arch = self.base.options.target.cpu.arch; | 1926 | const arch = self.base.options.target.cpu.arch; |
| 2011 | const stub_size: u4 = switch (arch) { | 1927 | const stub_size: u4 = switch (arch) { |
| 2012 | .x86_64 => 10, | 1928 | .x86_64 => 10, |
| ... | @@ -2072,7 +1988,7 @@ pub fn createStubHelperAtom(self: *MachO) !*TextBlock { | ... | @@ -2072,7 +1988,7 @@ pub fn createStubHelperAtom(self: *MachO) !*TextBlock { |
| 2072 | return atom; | 1988 | return atom; |
| 2073 | } | 1989 | } |
| 2074 | | 1990 | |
| 2075 | pub fn createLazyPointerAtom(self: *MachO, stub_sym_index: u32, lazy_binding_sym_index: u32) !*TextBlock { | 1991 | pub fn createLazyPointerAtom(self: *MachO, stub_sym_index: u32, lazy_binding_sym_index: u32) !*Atom { |
| 2076 | const local_sym_index = @intCast(u32, self.locals.items.len); | 1992 | const local_sym_index = @intCast(u32, self.locals.items.len); |
| 2077 | try self.locals.append(self.base.allocator, .{ | 1993 | try self.locals.append(self.base.allocator, .{ |
| 2078 | .n_strx = try self.makeString("l_zld_lazy_ptr"), | 1994 | .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 | ... | @@ -2102,7 +2018,7 @@ pub fn createLazyPointerAtom(self: *MachO, stub_sym_index: u32, lazy_binding_sym |
| 2102 | return atom; | 2018 | return atom; |
| 2103 | } | 2019 | } |
| 2104 | | 2020 | |
| 2105 | pub fn createStubAtom(self: *MachO, laptr_sym_index: u32) !*TextBlock { | 2021 | pub fn createStubAtom(self: *MachO, laptr_sym_index: u32) !*Atom { |
| 2106 | const arch = self.base.options.target.cpu.arch; | 2022 | const arch = self.base.options.target.cpu.arch; |
| 2107 | const alignment: u2 = switch (arch) { | 2023 | const alignment: u2 = switch (arch) { |
| 2108 | .x86_64 => 0, | 2024 | .x86_64 => 0, |
| ... | @@ -2273,14 +2189,6 @@ fn resolveSymbolsInObject( | ... | @@ -2273,14 +2189,6 @@ fn resolveSymbolsInObject( |
| 2273 | continue; | 2189 | continue; |
| 2274 | }, | 2190 | }, |
| 2275 | .undef => { | 2191 | .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 | // }; | | |
| 2284 | _ = self.unresolved.fetchSwapRemove(resolv.where_index); | 2192 | _ = self.unresolved.fetchSwapRemove(resolv.where_index); |
| 2285 | }, | 2193 | }, |
| 2286 | } | 2194 | } |
| ... | @@ -2437,23 +2345,36 @@ fn resolveSymbols(self: *MachO) !void { | ... | @@ -2437,23 +2345,36 @@ fn resolveSymbols(self: *MachO) !void { |
| 2437 | resolv.local_sym_index = local_sym_index; | 2345 | resolv.local_sym_index = local_sym_index; |
| 2438 | | 2346 | |
| 2439 | const atom = try self.createEmptyAtom(local_sym_index, size, alignment); | 2347 | 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; |
| 2441 | } | 2351 | } |
| 2442 | | 2352 | |
| 2443 | try self.resolveDyldStubBinder(); | 2353 | try self.resolveDyldStubBinder(); |
| 2444 | { | 2354 | { |
| 2445 | const atom = try self.createDyldPrivateAtom(); | 2355 | const match = MatchingSection{ |
| 2446 | _ = try self.allocateAtom(atom, .{ | | |
| 2447 | .seg = self.data_segment_cmd_index.?, | 2356 | .seg = self.data_segment_cmd_index.?, |
| 2448 | .sect = self.data_section_index.?, | 2357 | .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 }); |
| 2450 | } | 2365 | } |
| 2451 | { | 2366 | { |
| 2452 | const atom = try self.createStubHelperPreambleAtom(); | 2367 | const match = MatchingSection{ |
| 2453 | _ = try self.allocateAtom(atom, .{ | | |
| 2454 | .seg = self.text_segment_cmd_index.?, | 2368 | .seg = self.text_segment_cmd_index.?, |
| 2455 | .sect = self.stub_helper_section_index.?, | 2369 | .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 }); |
| 2457 | } | 2378 | } |
| 2458 | | 2379 | |
| 2459 | // Third pass, resolve symbols in dynamic libraries. | 2380 | // Third pass, resolve symbols in dynamic libraries. |
| ... | @@ -2483,30 +2404,45 @@ fn resolveSymbols(self: *MachO) !void { | ... | @@ -2483,30 +2404,45 @@ fn resolveSymbols(self: *MachO) !void { |
| 2483 | .stub => { | 2404 | .stub => { |
| 2484 | if (self.stubs_map.contains(resolv.where_index)) break :outer_blk; | 2405 | if (self.stubs_map.contains(resolv.where_index)) break :outer_blk; |
| 2485 | const stub_helper_atom = blk: { | 2406 | const stub_helper_atom = blk: { |
| 2486 | const atom = try self.createStubHelperAtom(); | 2407 | const match = MatchingSection{ |
| 2487 | _ = try self.allocateAtom(atom, .{ | | |
| 2488 | .seg = self.text_segment_cmd_index.?, | 2408 | .seg = self.text_segment_cmd_index.?, |
| 2489 | .sect = self.stub_helper_section_index.?, | 2409 | .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); |
| 2491 | break :blk atom; | 2417 | break :blk atom; |
| 2492 | }; | 2418 | }; |
| 2493 | const laptr_atom = blk: { | 2419 | const laptr_atom = blk: { |
| | 2420 | const match = MatchingSection{ |
| | 2421 | .seg = self.data_segment_cmd_index.?, |
| | 2422 | .sect = self.la_symbol_ptr_section_index.?, |
| | 2423 | }; |
| 2494 | const atom = try self.createLazyPointerAtom( | 2424 | const atom = try self.createLazyPointerAtom( |
| 2495 | stub_helper_atom.local_sym_index, | 2425 | stub_helper_atom.local_sym_index, |
| 2496 | resolv.where_index, | 2426 | resolv.where_index, |
| 2497 | ); | 2427 | ); |
| 2498 | _ = try self.allocateAtom(atom, .{ | 2428 | const atom_sym = &self.locals.items[atom.local_sym_index]; |
| 2499 | .seg = self.data_segment_cmd_index.?, | 2429 | const alignment = try math.powi(u32, 2, atom.alignment); |
| 2500 | .sect = self.la_symbol_ptr_section_index.?, | 2430 | const vaddr = try self.allocateAtom(atom, atom.size, alignment, match); |
| 2501 | }); | 2431 | atom_sym.n_value = vaddr; |
| | 2432 | atom_sym.n_sect = @intCast(u8, self.section_ordinals.getIndex(match).? + 1); |
| 2502 | break :blk atom; | 2433 | break :blk atom; |
| 2503 | }; | 2434 | }; |
| 2504 | const stub_atom = blk: { | 2435 | const stub_atom = blk: { |
| 2505 | const atom = try self.createStubAtom(laptr_atom.local_sym_index); | 2436 | const match = MatchingSection{ |
| 2506 | _ = try self.allocateAtom(atom, .{ | | |
| 2507 | .seg = self.text_segment_cmd_index.?, | 2437 | .seg = self.text_segment_cmd_index.?, |
| 2508 | .sect = self.stubs_section_index.?, | 2438 | .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); |
| 2510 | break :blk atom; | 2446 | break :blk atom; |
| 2511 | }; | 2447 | }; |
| 2512 | try self.stubs_map.putNoClobber(self.base.allocator, resolv.where_index, stub_atom); | 2448 | try self.stubs_map.putNoClobber(self.base.allocator, resolv.where_index, stub_atom); |
| ... | @@ -2565,7 +2501,10 @@ fn resolveSymbols(self: *MachO) !void { | ... | @@ -2565,7 +2501,10 @@ fn resolveSymbols(self: *MachO) !void { |
| 2565 | // TODO perhaps we should special-case special symbols? Create a separate | 2501 | // TODO perhaps we should special-case special symbols? Create a separate |
| 2566 | // linked list of atoms? | 2502 | // linked list of atoms? |
| 2567 | const atom = try self.createEmptyAtom(local_sym_index, 0, 0); | 2503 | 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. |
| 2569 | } | 2508 | } |
| 2570 | | 2509 | |
| 2571 | for (self.unresolved.keys()) |index| { | 2510 | for (self.unresolved.keys()) |index| { |
| ... | @@ -2632,10 +2571,14 @@ fn resolveDyldStubBinder(self: *MachO) !void { | ... | @@ -2632,10 +2571,14 @@ fn resolveDyldStubBinder(self: *MachO) !void { |
| 2632 | .seg = self.data_const_segment_cmd_index.?, | 2571 | .seg = self.data_const_segment_cmd_index.?, |
| 2633 | .sect = self.got_section_index.?, | 2572 | .sect = self.got_section_index.?, |
| 2634 | }; | 2573 | }; |
| 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 }); |
| 2636 | } | 2579 | } |
| 2637 | | 2580 | |
| 2638 | fn parseTextBlocks(self: *MachO) !void { | 2581 | fn parseObjectsIntoAtoms(self: *MachO) !void { |
| 2639 | var parsed_atoms = Object.ParsedAtoms.init(self.base.allocator); | 2582 | var parsed_atoms = Object.ParsedAtoms.init(self.base.allocator); |
| 2640 | defer parsed_atoms.deinit(); | 2583 | defer parsed_atoms.deinit(); |
| 2641 | | 2584 | |
| ... | @@ -2710,7 +2653,7 @@ fn parseTextBlocks(self: *MachO) !void { | ... | @@ -2710,7 +2653,7 @@ fn parseTextBlocks(self: *MachO) !void { |
| 2710 | metadata.alignment, | 2653 | metadata.alignment, |
| 2711 | }); | 2654 | }); |
| 2712 | | 2655 | |
| 2713 | const sect_size = if (self.blocks.get(match)) |last| blk: { | 2656 | const sect_size = if (self.atoms.get(match)) |last| blk: { |
| 2714 | const last_atom_sym = self.locals.items[last.local_sym_index]; | 2657 | const last_atom_sym = self.locals.items[last.local_sym_index]; |
| 2715 | break :blk last_atom_sym.n_value + last.size - sect.addr; | 2658 | break :blk last_atom_sym.n_value + last.size - sect.addr; |
| 2716 | } else 0; | 2659 | } else 0; |
| ... | @@ -2720,7 +2663,7 @@ fn parseTextBlocks(self: *MachO) !void { | ... | @@ -2720,7 +2663,7 @@ fn parseTextBlocks(self: *MachO) !void { |
| 2720 | try self.growSection(match, needed_size); | 2663 | try self.growSection(match, needed_size); |
| 2721 | sect.size = needed_size; | 2664 | sect.size = needed_size; |
| 2722 | | 2665 | |
| 2723 | var base_vaddr = if (self.blocks.get(match)) |last| blk: { | 2666 | var base_vaddr = if (self.atoms.get(match)) |last| blk: { |
| 2724 | const last_atom_sym = self.locals.items[last.local_sym_index]; | 2667 | const last_atom_sym = self.locals.items[last.local_sym_index]; |
| 2725 | break :blk last_atom_sym.n_value + last.size; | 2668 | break :blk last_atom_sym.n_value + last.size; |
| 2726 | } else sect.addr; | 2669 | } else sect.addr; |
| ... | @@ -2750,7 +2693,7 @@ fn parseTextBlocks(self: *MachO) !void { | ... | @@ -2750,7 +2693,7 @@ fn parseTextBlocks(self: *MachO) !void { |
| 2750 | alias_sym.n_sect = n_sect; | 2693 | alias_sym.n_sect = n_sect; |
| 2751 | } | 2694 | } |
| 2752 | | 2695 | |
| 2753 | // Update each symbol contained within the TextBlock | 2696 | // Update each symbol contained within the atom |
| 2754 | for (atom.contained.items) |sym_at_off| { | 2697 | for (atom.contained.items) |sym_at_off| { |
| 2755 | const contained_sym = &self.locals.items[sym_at_off.local_sym_index]; | 2698 | const contained_sym = &self.locals.items[sym_at_off.local_sym_index]; |
| 2756 | contained_sym.n_value = base_vaddr + sym_at_off.offset; | 2699 | contained_sym.n_value = base_vaddr + sym_at_off.offset; |
| ... | @@ -2764,13 +2707,13 @@ fn parseTextBlocks(self: *MachO) !void { | ... | @@ -2764,13 +2707,13 @@ fn parseTextBlocks(self: *MachO) !void { |
| 2764 | } else break; | 2707 | } else break; |
| 2765 | } | 2708 | } |
| 2766 | | 2709 | |
| 2767 | if (self.blocks.getPtr(match)) |last| { | 2710 | if (self.atoms.getPtr(match)) |last| { |
| 2768 | const first_atom = first_atoms.get(match).?; | 2711 | const first_atom = first_atoms.get(match).?; |
| 2769 | last.*.next = first_atom; | 2712 | last.*.next = first_atom; |
| 2770 | first_atom.prev = last.*; | 2713 | first_atom.prev = last.*; |
| 2771 | last.* = first_atom; | 2714 | last.* = first_atom; |
| 2772 | } | 2715 | } |
| 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).?); |
| 2774 | } | 2717 | } |
| 2775 | } | 2718 | } |
| 2776 | | 2719 | |
| ... | @@ -2905,18 +2848,18 @@ pub fn deinit(self: *MachO) void { | ... | @@ -2905,18 +2848,18 @@ pub fn deinit(self: *MachO) void { |
| 2905 | } | 2848 | } |
| 2906 | self.load_commands.deinit(self.base.allocator); | 2849 | self.load_commands.deinit(self.base.allocator); |
| 2907 | | 2850 | |
| 2908 | for (self.managed_blocks.items) |block| { | 2851 | for (self.managed_atoms.items) |atom| { |
| 2909 | block.deinit(self.base.allocator); | 2852 | atom.deinit(self.base.allocator); |
| 2910 | self.base.allocator.destroy(block); | 2853 | self.base.allocator.destroy(atom); |
| 2911 | } | 2854 | } |
| 2912 | self.managed_blocks.deinit(self.base.allocator); | 2855 | self.managed_atoms.deinit(self.base.allocator); |
| 2913 | self.blocks.deinit(self.base.allocator); | 2856 | self.atoms.deinit(self.base.allocator); |
| 2914 | { | 2857 | { |
| 2915 | var it = self.block_free_lists.valueIterator(); | 2858 | var it = self.atom_free_lists.valueIterator(); |
| 2916 | while (it.next()) |free_list| { | 2859 | while (it.next()) |free_list| { |
| 2917 | free_list.deinit(self.base.allocator); | 2860 | free_list.deinit(self.base.allocator); |
| 2918 | } | 2861 | } |
| 2919 | self.block_free_lists.deinit(self.base.allocator); | 2862 | self.atom_free_lists.deinit(self.base.allocator); |
| 2920 | } | 2863 | } |
| 2921 | for (self.decls.keys()) |decl| { | 2864 | for (self.decls.keys()) |decl| { |
| 2922 | decl.link.macho.deinit(self.base.allocator); | 2865 | decl.link.macho.deinit(self.base.allocator); |
| ... | @@ -2936,25 +2879,21 @@ pub fn closeFiles(self: MachO) void { | ... | @@ -2936,25 +2879,21 @@ pub fn closeFiles(self: MachO) void { |
| 2936 | } | 2879 | } |
| 2937 | } | 2880 | } |
| 2938 | | 2881 | |
| 2939 | fn freeTextBlock(self: *MachO, text_block: *TextBlock) void { | 2882 | fn freeAtom(self: *MachO, atom: *Atom, match: MatchingSection) void { |
| 2940 | log.debug("freeTextBlock {*}", .{text_block}); | 2883 | log.debug("freeAtom {*}", .{atom}); |
| 2941 | text_block.deinit(self.base.allocator); | 2884 | atom.deinit(self.base.allocator); |
| 2942 | | 2885 | |
| 2943 | const match = MatchingSection{ | 2886 | const free_list = self.atom_free_lists.getPtr(match).?; |
| 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).?; | | |
| 2948 | var already_have_free_list_node = false; | 2887 | var already_have_free_list_node = false; |
| 2949 | { | 2888 | { |
| 2950 | var i: usize = 0; | 2889 | var i: usize = 0; |
| 2951 | // TODO turn text_block_free_list into a hash map | 2890 | // TODO turn free_list into a hash map |
| 2952 | while (i < text_block_free_list.items.len) { | 2891 | while (i < free_list.items.len) { |
| 2953 | if (text_block_free_list.items[i] == text_block) { | 2892 | if (free_list.items[i] == atom) { |
| 2954 | _ = text_block_free_list.swapRemove(i); | 2893 | _ = free_list.swapRemove(i); |
| 2955 | continue; | 2894 | continue; |
| 2956 | } | 2895 | } |
| 2957 | if (text_block_free_list.items[i] == text_block.prev) { | 2896 | if (free_list.items[i] == atom.prev) { |
| 2958 | already_have_free_list_node = true; | 2897 | already_have_free_list_node = true; |
| 2959 | } | 2898 | } |
| 2960 | i += 1; | 2899 | i += 1; |
| ... | @@ -2962,72 +2901,73 @@ fn freeTextBlock(self: *MachO, text_block: *TextBlock) void { | ... | @@ -2962,72 +2901,73 @@ fn freeTextBlock(self: *MachO, text_block: *TextBlock) void { |
| 2962 | } | 2901 | } |
| 2963 | // TODO process free list for dbg info just like we do above for vaddrs | 2902 | // TODO process free list for dbg info just like we do above for vaddrs |
| 2964 | | 2903 | |
| 2965 | if (self.blocks.getPtr(match)) |last_text_block| { | 2904 | if (self.atoms.getPtr(match)) |last_atom| { |
| 2966 | if (last_text_block.* == text_block) { | 2905 | if (last_atom.* == atom) { |
| 2967 | if (text_block.prev) |prev| { | 2906 | if (atom.prev) |prev| { |
| 2968 | // TODO shrink the __text section size here | 2907 | // TODO shrink the section size here |
| 2969 | last_text_block.* = prev; | 2908 | last_atom.* = prev; |
| 2970 | } | 2909 | } |
| 2971 | } | 2910 | } |
| 2972 | } | 2911 | } |
| 2973 | | 2912 | |
| 2974 | if (self.d_sym) |*ds| { | 2913 | if (self.d_sym) |*ds| { |
| 2975 | if (ds.dbg_info_decl_first == text_block) { | 2914 | if (ds.dbg_info_decl_first == atom) { |
| 2976 | ds.dbg_info_decl_first = text_block.dbg_info_next; | 2915 | ds.dbg_info_decl_first = atom.dbg_info_next; |
| 2977 | } | 2916 | } |
| 2978 | if (ds.dbg_info_decl_last == text_block) { | 2917 | if (ds.dbg_info_decl_last == atom) { |
| 2979 | // TODO shrink the .debug_info section size here | 2918 | // 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; |
| 2981 | } | 2920 | } |
| 2982 | } | 2921 | } |
| 2983 | | 2922 | |
| 2984 | if (text_block.prev) |prev| { | 2923 | if (atom.prev) |prev| { |
| 2985 | prev.next = text_block.next; | 2924 | prev.next = atom.next; |
| 2986 | | 2925 | |
| 2987 | if (!already_have_free_list_node and prev.freeListEligible(self.*)) { | 2926 | if (!already_have_free_list_node and prev.freeListEligible(self.*)) { |
| 2988 | // The free list is heuristics, it doesn't have to be perfect, so we can ignore | 2927 | // The free list is heuristics, it doesn't have to be perfect, so we can ignore |
| 2989 | // the OOM here. | 2928 | // the OOM here. |
| 2990 | text_block_free_list.append(self.base.allocator, prev) catch {}; | 2929 | free_list.append(self.base.allocator, prev) catch {}; |
| 2991 | } | 2930 | } |
| 2992 | } else { | 2931 | } else { |
| 2993 | text_block.prev = null; | 2932 | atom.prev = null; |
| 2994 | } | 2933 | } |
| 2995 | | 2934 | |
| 2996 | if (text_block.next) |next| { | 2935 | if (atom.next) |next| { |
| 2997 | next.prev = text_block.prev; | 2936 | next.prev = atom.prev; |
| 2998 | } else { | 2937 | } else { |
| 2999 | text_block.next = null; | 2938 | atom.next = null; |
| 3000 | } | 2939 | } |
| 3001 | | 2940 | |
| 3002 | if (text_block.dbg_info_prev) |prev| { | 2941 | if (atom.dbg_info_prev) |prev| { |
| 3003 | prev.dbg_info_next = text_block.dbg_info_next; | 2942 | prev.dbg_info_next = atom.dbg_info_next; |
| 3004 | | 2943 | |
| 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 |
| 3006 | } else { | 2945 | } else { |
| 3007 | text_block.dbg_info_prev = null; | 2946 | atom.dbg_info_prev = null; |
| 3008 | } | 2947 | } |
| 3009 | | 2948 | |
| 3010 | if (text_block.dbg_info_next) |next| { | 2949 | if (atom.dbg_info_next) |next| { |
| 3011 | next.dbg_info_prev = text_block.dbg_info_prev; | 2950 | next.dbg_info_prev = atom.dbg_info_prev; |
| 3012 | } else { | 2951 | } else { |
| 3013 | text_block.dbg_info_next = null; | 2952 | atom.dbg_info_next = null; |
| 3014 | } | 2953 | } |
| 3015 | } | 2954 | } |
| 3016 | | 2955 | |
| 3017 | fn shrinkTextBlock(self: *MachO, text_block: *TextBlock, new_block_size: u64) void { | 2956 | fn shrinkAtom(self: *MachO, atom: *Atom, new_block_size: u64, match: MatchingSection) void { |
| 3018 | _ = self; | 2957 | _ = self; |
| 3019 | _ = text_block; | 2958 | _ = atom; |
| 3020 | _ = new_block_size; | 2959 | _ = new_block_size; |
| | 2960 | _ = match; |
| 3021 | // TODO check the new capacity, and if it crosses the size threshold into a big enough | 2961 | // TODO check the new capacity, and if it crosses the size threshold into a big enough |
| 3022 | // capacity, insert a free list node for it. | 2962 | // capacity, insert a free list node for it. |
| 3023 | } | 2963 | } |
| 3024 | | 2964 | |
| 3025 | fn growTextBlock(self: *MachO, text_block: *TextBlock, new_block_size: u64, alignment: u64) !u64 { | 2965 | fn growAtom(self: *MachO, atom: *Atom, new_atom_size: u64, alignment: u64, match: MatchingSection) !u64 { |
| 3026 | const sym = self.locals.items[text_block.local_sym_index]; | 2966 | const sym = self.locals.items[atom.local_sym_index]; |
| 3027 | const align_ok = mem.alignBackwardGeneric(u64, sym.n_value, alignment) == sym.n_value; | 2967 | 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.*); |
| 3029 | if (!need_realloc) return sym.n_value; | 2969 | 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); |
| 3031 | } | 2971 | } |
| 3032 | | 2972 | |
| 3033 | pub fn allocateDeclIndexes(self: *MachO, decl: *Module.Decl) !void { | 2973 | pub 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 | ... | @@ -3112,7 +3052,7 @@ pub fn updateFunc(self: *MachO, module: *Module, func: *Module.Fn, air: Air, liv |
| 3112 | // in a different, smarter, more automatic way somewhere else, in a more centralised | 3052 | // in a different, smarter, more automatic way somewhere else, in a more centralised |
| 3113 | // way than this. | 3053 | // way than this. |
| 3114 | // If we don't clear the buffers here, we are up for some nasty surprises when | 3054 | // 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(). |
| 3116 | decl.link.macho.code.clearAndFree(self.base.allocator); | 3056 | decl.link.macho.code.clearAndFree(self.base.allocator); |
| 3117 | try decl.link.macho.code.appendSlice(self.base.allocator, code_buffer.items); | 3057 | try decl.link.macho.code.appendSlice(self.base.allocator, code_buffer.items); |
| 3118 | }, | 3058 | }, |
| ... | @@ -3202,7 +3142,7 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void { | ... | @@ -3202,7 +3142,7 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void { |
| 3202 | // in a different, smarter, more automatic way somewhere else, in a more centralised | 3142 | // in a different, smarter, more automatic way somewhere else, in a more centralised |
| 3203 | // way than this. | 3143 | // way than this. |
| 3204 | // If we don't clear the buffers here, we are up for some nasty surprises when | 3144 | // 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(). |
| 3206 | decl.link.macho.code.clearAndFree(self.base.allocator); | 3146 | decl.link.macho.code.clearAndFree(self.base.allocator); |
| 3207 | try decl.link.macho.code.appendSlice(self.base.allocator, code_buffer.items); | 3147 | try decl.link.macho.code.appendSlice(self.base.allocator, code_buffer.items); |
| 3208 | break :blk decl.link.macho.code.items; | 3148 | break :blk decl.link.macho.code.items; |
| ... | @@ -3231,7 +3171,10 @@ fn placeDecl(self: *MachO, decl: *Module.Decl, code_len: usize) !*macho.nlist_64 | ... | @@ -3231,7 +3171,10 @@ fn placeDecl(self: *MachO, decl: *Module.Decl, code_len: usize) !*macho.nlist_64 |
| 3231 | const capacity = decl.link.macho.capacity(self.*); | 3171 | const capacity = decl.link.macho.capacity(self.*); |
| 3232 | const need_realloc = code_len > capacity or !mem.isAlignedGeneric(u64, symbol.n_value, required_alignment); | 3172 | const need_realloc = code_len > capacity or !mem.isAlignedGeneric(u64, symbol.n_value, required_alignment); |
| 3233 | if (need_realloc) { | 3173 | 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 | }); |
| 3235 | | 3178 | |
| 3236 | log.debug("growing {s} and moving from 0x{x} to 0x{x}", .{ decl.name, symbol.n_value, vaddr }); | 3179 | log.debug("growing {s} and moving from 0x{x} to 0x{x}", .{ decl.name, symbol.n_value, vaddr }); |
| 3237 | | 3180 | |
| ... | @@ -3241,15 +3184,24 @@ fn placeDecl(self: *MachO, decl: *Module.Decl, code_len: usize) !*macho.nlist_64 | ... | @@ -3241,15 +3184,24 @@ fn placeDecl(self: *MachO, decl: *Module.Decl, code_len: usize) !*macho.nlist_64 |
| 3241 | .where = .local, | 3184 | .where = .local, |
| 3242 | .where_index = decl.link.macho.local_sym_index, | 3185 | .where_index = decl.link.macho.local_sym_index, |
| 3243 | }) orelse unreachable; | 3186 | }) 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, .{ |
| 3245 | .seg = self.data_const_segment_cmd_index.?, | 3189 | .seg = self.data_const_segment_cmd_index.?, |
| 3246 | .sect = self.got_section_index.?, | 3190 | .sect = self.got_section_index.?, |
| 3247 | }); | 3191 | }); |
| | 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); |
| 3248 | } | 3197 | } |
| 3249 | | 3198 | |
| 3250 | symbol.n_value = vaddr; | 3199 | symbol.n_value = vaddr; |
| 3251 | } else if (code_len < decl.link.macho.size) { | 3200 | } 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 | }); |
| 3253 | } | 3205 | } |
| 3254 | decl.link.macho.size = code_len; | 3206 | decl.link.macho.size = code_len; |
| 3255 | | 3207 | |
| ... | @@ -3265,11 +3217,17 @@ fn placeDecl(self: *MachO, decl: *Module.Decl, code_len: usize) !*macho.nlist_64 | ... | @@ -3265,11 +3217,17 @@ fn placeDecl(self: *MachO, decl: *Module.Decl, code_len: usize) !*macho.nlist_64 |
| 3265 | defer self.base.allocator.free(decl_name); | 3217 | defer self.base.allocator.free(decl_name); |
| 3266 | | 3218 | |
| 3267 | const name_str_index = try self.makeString(decl_name); | 3219 | 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 | }); |
| 3269 | | 3224 | |
| 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 }); |
| 3271 | | 3226 | |
| 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 | }); |
| 3273 | | 3231 | |
| 3274 | symbol.* = .{ | 3232 | symbol.* = .{ |
| 3275 | .n_strx = name_str_index, | 3233 | .n_strx = name_str_index, |
| ... | @@ -3282,10 +3240,16 @@ fn placeDecl(self: *MachO, decl: *Module.Decl, code_len: usize) !*macho.nlist_64 | ... | @@ -3282,10 +3240,16 @@ fn placeDecl(self: *MachO, decl: *Module.Decl, code_len: usize) !*macho.nlist_64 |
| 3282 | .where = .local, | 3240 | .where = .local, |
| 3283 | .where_index = decl.link.macho.local_sym_index, | 3241 | .where_index = decl.link.macho.local_sym_index, |
| 3284 | }) orelse unreachable; | 3242 | }) 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, .{ |
| 3286 | .seg = self.data_const_segment_cmd_index.?, | 3245 | .seg = self.data_const_segment_cmd_index.?, |
| 3287 | .sect = self.got_section_index.?, | 3246 | .sect = self.got_section_index.?, |
| 3288 | }); | 3247 | }); |
| | 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); |
| 3289 | } | 3253 | } |
| 3290 | | 3254 | |
| 3291 | return symbol; | 3255 | return symbol; |
| ... | @@ -3402,7 +3366,10 @@ pub fn freeDecl(self: *MachO, decl: *Module.Decl) void { | ... | @@ -3402,7 +3366,10 @@ pub fn freeDecl(self: *MachO, decl: *Module.Decl) void { |
| 3402 | log.debug("freeDecl {*}", .{decl}); | 3366 | log.debug("freeDecl {*}", .{decl}); |
| 3403 | _ = self.decls.swapRemove(decl); | 3367 | _ = self.decls.swapRemove(decl); |
| 3404 | // Appending to free lists is allowed to fail because the free lists are heuristics based anyway. | 3368 | // 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 | }); |
| 3406 | if (decl.link.macho.local_sym_index != 0) { | 3373 | if (decl.link.macho.local_sym_index != 0) { |
| 3407 | self.locals_free_list.append(self.base.allocator, decl.link.macho.local_sym_index) catch {}; | 3374 | self.locals_free_list.append(self.base.allocator, decl.link.macho.local_sym_index) catch {}; |
| 3408 | | 3375 | |
| ... | @@ -3412,7 +3379,7 @@ pub fn freeDecl(self: *MachO, decl: *Module.Decl) void { | ... | @@ -3412,7 +3379,7 @@ pub fn freeDecl(self: *MachO, decl: *Module.Decl) void { |
| 3412 | decl.link.macho.local_sym_index = 0; | 3379 | decl.link.macho.local_sym_index = 0; |
| 3413 | } | 3380 | } |
| 3414 | if (self.d_sym) |*ds| { | 3381 | 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 |
| 3416 | // out since the same thing is desired for both. | 3383 | // out since the same thing is desired for both. |
| 3417 | _ = ds.dbg_line_fn_free_list.remove(&decl.fn_link.macho); | 3384 | _ = ds.dbg_line_fn_free_list.remove(&decl.fn_link.macho); |
| 3418 | if (decl.fn_link.macho.prev) |prev| { | 3385 | if (decl.fn_link.macho.prev) |prev| { |
| ... | @@ -3947,7 +3914,7 @@ fn allocateSection( | ... | @@ -3947,7 +3914,7 @@ fn allocateSection( |
| 3947 | .sect = index, | 3914 | .sect = index, |
| 3948 | }; | 3915 | }; |
| 3949 | _ = try self.section_ordinals.getOrPut(self.base.allocator, match); | 3916 | _ = 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, .{}); |
| 3951 | | 3918 | |
| 3952 | self.load_commands_dirty = true; | 3919 | self.load_commands_dirty = true; |
| 3953 | self.sections_order_dirty = true; | 3920 | self.sections_order_dirty = true; |
| ... | @@ -4113,106 +4080,105 @@ fn getSectionMaxAlignment(self: *MachO, segment_id: u16, start_sect_id: u16) !u3 | ... | @@ -4113,106 +4080,105 @@ fn getSectionMaxAlignment(self: *MachO, segment_id: u16, start_sect_id: u16) !u3 |
| 4113 | return max_alignment; | 4080 | return max_alignment; |
| 4114 | } | 4081 | } |
| 4115 | | 4082 | |
| 4116 | fn allocateTextBlock(self: *MachO, text_block: *TextBlock, new_block_size: u64, alignment: u64) !u64 { | 4083 | fn allocateAtom(self: *MachO, atom: *Atom, new_atom_size: u64, alignment: u64, match: MatchingSection) !u64 { |
| 4117 | const text_segment = &self.load_commands.items[self.text_segment_cmd_index.?].Segment; | 4084 | const seg = &self.load_commands.items[match.seg].Segment; |
| 4118 | const text_section = &text_segment.sections.items[self.text_section_index.?]; | 4085 | const sect = &seg.sections.items[match.sect]; |
| 4119 | const match = MatchingSection{ | 4086 | var free_list = self.atom_free_lists.get(match).?; |
| 4120 | .seg = self.text_segment_cmd_index.?, | 4087 | const needs_padding = match.seg == self.text_segment_cmd_index.? and match.sect == self.text_section_index.?; |
| 4121 | .sect = self.text_section_index.?, | 4088 | const new_atom_ideal_capacity = if (needs_padding) padToIdeal(new_atom_size) else new_atom_size; |
| 4122 | }; | | |
| 4123 | var text_block_free_list = self.block_free_lists.get(match).?; | | |
| 4124 | const new_block_ideal_capacity = padToIdeal(new_block_size); | | |
| 4125 | | 4089 | |
| 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, |
| 4127 | // and possibly removing a free list node. | 4091 | // and possibly removing a free list node. |
| 4128 | // It would be simpler to do it inside the for loop below, but that would cause a | 4092 | // It would be simpler to do it inside the for loop below, but that would cause a |
| 4129 | // problem if an error was returned later in the function. So this action | 4093 | // problem if an error was returned later in the function. So this action |
| 4130 | // is actually carried out at the end of the function, when errors are no longer possible. | 4094 | // 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; |
| 4132 | var free_list_removal: ?usize = null; | 4096 | var free_list_removal: ?usize = null; |
| 4133 | | 4097 | |
| 4134 | // First we look for an appropriately sized free list node. | 4098 | // First we look for an appropriately sized free list node. |
| 4135 | // The list is unordered. We'll just take the first thing that works. | 4099 | // The list is unordered. We'll just take the first thing that works. |
| 4136 | var vaddr = blk: { | 4100 | var vaddr = blk: { |
| 4137 | var i: usize = 0; | 4101 | var i: usize = 0; |
| 4138 | while (i < text_block_free_list.items.len) { | 4102 | while (i < free_list.items.len) { |
| 4139 | const big_block = text_block_free_list.items[i]; | 4103 | const big_atom = free_list.items[i]; |
| 4140 | // We now have a pointer to a live text block that has too much capacity. | 4104 | // We now have a pointer to a live atom that has too much capacity. |
| 4141 | // Is it enough that we could fit this new text block? | 4105 | // Is it enough that we could fit this new atom? |
| 4142 | const sym = self.locals.items[big_block.local_sym_index]; | 4106 | const sym = self.locals.items[big_atom.local_sym_index]; |
| 4143 | const capacity = big_block.capacity(self.*); | 4107 | const capacity = big_atom.capacity(self.*); |
| 4144 | const ideal_capacity = padToIdeal(capacity); | 4108 | const ideal_capacity = if (needs_padding) padToIdeal(capacity) else capacity; |
| 4145 | const ideal_capacity_end_vaddr = sym.n_value + ideal_capacity; | 4109 | const ideal_capacity_end_vaddr = sym.n_value + ideal_capacity; |
| 4146 | const capacity_end_vaddr = sym.n_value + capacity; | 4110 | 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; |
| 4148 | const new_start_vaddr = mem.alignBackwardGeneric(u64, new_start_vaddr_unaligned, alignment); | 4112 | const new_start_vaddr = mem.alignBackwardGeneric(u64, new_start_vaddr_unaligned, alignment); |
| 4149 | if (new_start_vaddr < ideal_capacity_end_vaddr) { | 4113 | if (new_start_vaddr < ideal_capacity_end_vaddr) { |
| 4150 | // Additional bookkeeping here to notice if this free list node | 4114 | // 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 |
| 4152 | // more of the extra capacity. | 4116 | // more of the extra capacity. |
| 4153 | if (!big_block.freeListEligible(self.*)) { | 4117 | if (!big_atom.freeListEligible(self.*)) { |
| 4154 | const bl = text_block_free_list.swapRemove(i); | 4118 | const bl = free_list.swapRemove(i); |
| 4155 | bl.deinit(self.base.allocator); | 4119 | bl.deinit(self.base.allocator); |
| 4156 | } else { | 4120 | } else { |
| 4157 | i += 1; | 4121 | i += 1; |
| 4158 | } | 4122 | } |
| 4159 | continue; | 4123 | continue; |
| 4160 | } | 4124 | } |
| 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 |
| 4162 | // remaining question is whether there is still yet enough capacity left | 4126 | // remaining question is whether there is still yet enough capacity left |
| 4163 | // over for there to still be a free list node. | 4127 | // over for there to still be a free list node. |
| 4164 | const remaining_capacity = new_start_vaddr - ideal_capacity_end_vaddr; | 4128 | const remaining_capacity = new_start_vaddr - ideal_capacity_end_vaddr; |
| 4165 | const keep_free_list_node = remaining_capacity >= min_text_capacity; | 4129 | const keep_free_list_node = remaining_capacity >= min_text_capacity; |
| 4166 | | 4130 | |
| 4167 | // Set up the metadata to be updated, after errors are no longer possible. | 4131 | // Set up the metadata to be updated, after errors are no longer possible. |
| 4168 | block_placement = big_block; | 4132 | atom_placement = big_atom; |
| 4169 | if (!keep_free_list_node) { | 4133 | if (!keep_free_list_node) { |
| 4170 | free_list_removal = i; | 4134 | free_list_removal = i; |
| 4171 | } | 4135 | } |
| 4172 | break :blk new_start_vaddr; | 4136 | break :blk new_start_vaddr; |
| 4173 | } else if (self.blocks.get(match)) |last| { | 4137 | } else if (self.atoms.get(match)) |last| { |
| 4174 | const last_symbol = self.locals.items[last.local_sym_index]; | 4138 | const last_symbol = self.locals.items[last.local_sym_index]; |
| 4175 | // TODO We should pad out the excess capacity with NOPs. For executables, | 4139 | const ideal_capacity = if (needs_padding) padToIdeal(last.size) else last.size; |
| 4176 | // no padding seems to be OK, but it will probably not be for objects. | | |
| 4177 | const ideal_capacity = padToIdeal(last.size); | | |
| 4178 | const ideal_capacity_end_vaddr = last_symbol.n_value + ideal_capacity; | 4140 | const ideal_capacity_end_vaddr = last_symbol.n_value + ideal_capacity; |
| 4179 | const new_start_vaddr = mem.alignForwardGeneric(u64, ideal_capacity_end_vaddr, alignment); | 4141 | const new_start_vaddr = mem.alignForwardGeneric(u64, ideal_capacity_end_vaddr, alignment); |
| 4180 | block_placement = last; | 4142 | atom_placement = last; |
| 4181 | break :blk new_start_vaddr; | 4143 | break :blk new_start_vaddr; |
| 4182 | } else { | 4144 | } else { |
| 4183 | break :blk text_section.addr; | 4145 | break :blk mem.alignForwardGeneric(u64, sect.addr, alignment); |
| 4184 | } | 4146 | } |
| 4185 | }; | 4147 | }; |
| 4186 | | 4148 | |
| 4187 | const expand_text_section = block_placement == null or block_placement.?.next == null; | 4149 | const expand_section = atom_placement == null or atom_placement.?.next == null; |
| 4188 | if (expand_text_section) { | 4150 | if (expand_section) { |
| 4189 | const needed_size = @intCast(u32, (vaddr + new_block_size) - text_section.addr); | 4151 | const needed_size = @intCast(u32, (vaddr + new_atom_size) - sect.addr); |
| 4190 | try self.growSection(match, needed_size); | 4152 | try self.growSection(match, needed_size); |
| 4191 | _ = try self.blocks.put(self.base.allocator, match, text_block); | 4153 | _ = try self.atoms.put(self.base.allocator, match, atom); |
| 4192 | text_section.size = needed_size; | 4154 | sect.size = needed_size; |
| 4193 | self.load_commands_dirty = true; | 4155 | self.load_commands_dirty = true; |
| 4194 | } | 4156 | } |
| 4195 | const align_pow = @intCast(u32, math.log2(alignment)); | 4157 | const align_pow = @intCast(u32, math.log2(alignment)); |
| 4196 | text_section.@"align" = math.max(text_section.@"align", align_pow); | 4158 | if (sect.@"align" < align_pow) { |
| 4197 | text_block.size = new_block_size; | 4159 | sect.@"align" = align_pow; |
| | 4160 | self.load_commands_dirty = true; |
| | 4161 | } |
| | 4162 | atom.size = new_atom_size; |
| | 4163 | atom.alignment = align_pow; |
| 4198 | | 4164 | |
| 4199 | if (text_block.prev) |prev| { | 4165 | if (atom.prev) |prev| { |
| 4200 | prev.next = text_block.next; | 4166 | prev.next = atom.next; |
| 4201 | } | 4167 | } |
| 4202 | if (text_block.next) |next| { | 4168 | if (atom.next) |next| { |
| 4203 | next.prev = text_block.prev; | 4169 | next.prev = atom.prev; |
| 4204 | } | 4170 | } |
| 4205 | | 4171 | |
| 4206 | if (block_placement) |big_block| { | 4172 | if (atom_placement) |big_atom| { |
| 4207 | text_block.prev = big_block; | 4173 | atom.prev = big_atom; |
| 4208 | text_block.next = big_block.next; | 4174 | atom.next = big_atom.next; |
| 4209 | big_block.next = text_block; | 4175 | big_atom.next = atom; |
| 4210 | } else { | 4176 | } else { |
| 4211 | text_block.prev = null; | 4177 | atom.prev = null; |
| 4212 | text_block.next = null; | 4178 | atom.next = null; |
| 4213 | } | 4179 | } |
| 4214 | if (free_list_removal) |i| { | 4180 | if (free_list_removal) |i| { |
| 4215 | _ = text_block_free_list.swapRemove(i); | 4181 | _ = free_list.swapRemove(i); |
| 4216 | } | 4182 | } |
| 4217 | | 4183 | |
| 4218 | return vaddr; | 4184 | return vaddr; |
| ... | @@ -4319,10 +4285,10 @@ fn writeDyldInfoData(self: *MachO) !void { | ... | @@ -4319,10 +4285,10 @@ fn writeDyldInfoData(self: *MachO) !void { |
| 4319 | defer lazy_bind_pointers.deinit(); | 4285 | defer lazy_bind_pointers.deinit(); |
| 4320 | | 4286 | |
| 4321 | { | 4287 | { |
| 4322 | var it = self.blocks.iterator(); | 4288 | var it = self.atoms.iterator(); |
| 4323 | while (it.next()) |entry| { | 4289 | while (it.next()) |entry| { |
| 4324 | const match = entry.key_ptr.*; | 4290 | const match = entry.key_ptr.*; |
| 4325 | var atom: *TextBlock = entry.value_ptr.*; | 4291 | var atom: *Atom = entry.value_ptr.*; |
| 4326 | | 4292 | |
| 4327 | if (match.seg == self.text_segment_cmd_index.?) continue; // __TEXT is non-writable | 4293 | if (match.seg == self.text_segment_cmd_index.?) continue; // __TEXT is non-writable |
| 4328 | | 4294 | |
| ... | @@ -4444,7 +4410,7 @@ fn writeDyldInfoData(self: *MachO) !void { | ... | @@ -4444,7 +4410,7 @@ fn writeDyldInfoData(self: *MachO) !void { |
| 4444 | } | 4410 | } |
| 4445 | | 4411 | |
| 4446 | fn populateLazyBindOffsetsInStubHelper(self: *MachO, buffer: []const u8) !void { | 4412 | fn populateLazyBindOffsetsInStubHelper(self: *MachO, buffer: []const u8) !void { |
| 4447 | const last_atom = self.blocks.get(.{ | 4413 | const last_atom = self.atoms.get(.{ |
| 4448 | .seg = self.text_segment_cmd_index.?, | 4414 | .seg = self.text_segment_cmd_index.?, |
| 4449 | .sect = self.stub_helper_section_index.?, | 4415 | .sect = self.stub_helper_section_index.?, |
| 4450 | }) orelse return; | 4416 | }) orelse return; |
| ... | @@ -4538,25 +4504,25 @@ fn writeDices(self: *MachO) !void { | ... | @@ -4538,25 +4504,25 @@ fn writeDices(self: *MachO) !void { |
| 4538 | var buf = std.ArrayList(u8).init(self.base.allocator); | 4504 | var buf = std.ArrayList(u8).init(self.base.allocator); |
| 4539 | defer buf.deinit(); | 4505 | defer buf.deinit(); |
| 4540 | | 4506 | |
| 4541 | var block: *TextBlock = self.blocks.get(.{ | 4507 | var atom: *Atom = self.atoms.get(.{ |
| 4542 | .seg = self.text_segment_cmd_index orelse return, | 4508 | .seg = self.text_segment_cmd_index orelse return, |
| 4543 | .sect = self.text_section_index orelse return, | 4509 | .sect = self.text_section_index orelse return, |
| 4544 | }) orelse return; | 4510 | }) orelse return; |
| 4545 | | 4511 | |
| 4546 | while (block.prev) |prev| { | 4512 | while (atom.prev) |prev| { |
| 4547 | block = prev; | 4513 | atom = prev; |
| 4548 | } | 4514 | } |
| 4549 | | 4515 | |
| 4550 | const text_seg = self.load_commands.items[self.text_segment_cmd_index.?].Segment; | 4516 | const text_seg = self.load_commands.items[self.text_segment_cmd_index.?].Segment; |
| 4551 | const text_sect = text_seg.sections.items[self.text_section_index.?]; | 4517 | const text_sect = text_seg.sections.items[self.text_section_index.?]; |
| 4552 | | 4518 | |
| 4553 | while (true) { | 4519 | while (true) { |
| 4554 | if (block.dices.items.len > 0) { | 4520 | if (atom.dices.items.len > 0) { |
| 4555 | const sym = self.locals.items[block.local_sym_index]; | 4521 | const sym = self.locals.items[atom.local_sym_index]; |
| 4556 | const base_off = try math.cast(u32, sym.n_value - text_sect.addr + text_sect.offset); | 4522 | const base_off = try math.cast(u32, sym.n_value - text_sect.addr + text_sect.offset); |
| 4557 | | 4523 | |
| 4558 | try buf.ensureUnusedCapacity(block.dices.items.len * @sizeOf(macho.data_in_code_entry)); | 4524 | try buf.ensureUnusedCapacity(atom.dices.items.len * @sizeOf(macho.data_in_code_entry)); |
| 4559 | for (block.dices.items) |dice| { | 4525 | for (atom.dices.items) |dice| { |
| 4560 | const rebased_dice = macho.data_in_code_entry{ | 4526 | const rebased_dice = macho.data_in_code_entry{ |
| 4561 | .offset = base_off + dice.offset, | 4527 | .offset = base_off + dice.offset, |
| 4562 | .length = dice.length, | 4528 | .length = dice.length, |
| ... | @@ -4566,8 +4532,8 @@ fn writeDices(self: *MachO) !void { | ... | @@ -4566,8 +4532,8 @@ fn writeDices(self: *MachO) !void { |
| 4566 | } | 4532 | } |
| 4567 | } | 4533 | } |
| 4568 | | 4534 | |
| 4569 | if (block.next) |next| { | 4535 | if (atom.next) |next| { |
| 4570 | block = next; | 4536 | atom = next; |
| 4571 | } else break; | 4537 | } else break; |
| 4572 | } | 4538 | } |
| 4573 | | 4539 | |