| ... | @@ -1649,117 +1649,103 @@ pub fn createEmptyAtom(self: *MachO, local_sym_index: u32, size: u64, alignment: | ... | @@ -1649,117 +1649,103 @@ pub fn createEmptyAtom(self: *MachO, local_sym_index: u32, size: u64, alignment: |
| 1649 | pub fn allocateAtom(self: *MachO, atom: *TextBlock, match: MatchingSection) !u64 { | 1649 | pub fn allocateAtom(self: *MachO, atom: *TextBlock, match: MatchingSection) !u64 { |
| 1650 | const seg = &self.load_commands.items[match.seg].Segment; | 1650 | const seg = &self.load_commands.items[match.seg].Segment; |
| 1651 | const sect = &seg.sections.items[match.sect]; | 1651 | const sect = &seg.sections.items[match.sect]; |
| 1652 | const use_stage1 = build_options.is_stage1 and self.base.options.use_stage1; | | |
| 1653 | | | |
| 1654 | const vaddr = outer: { | | |
| 1655 | if (!use_stage1) { | | |
| 1656 | const sym = &self.locals.items[atom.local_sym_index]; | | |
| 1657 | // Padding is not required for pointer-type sections and any synthetic sections such as | | |
| 1658 | // stubs or stub_helper. | | |
| 1659 | // TODO audit this. | | |
| 1660 | const needs_padding = switch (commands.sectionType(sect.*)) { | | |
| 1661 | macho.S_SYMBOL_STUBS, | | |
| 1662 | macho.S_NON_LAZY_SYMBOL_POINTERS, | | |
| 1663 | macho.S_LAZY_SYMBOL_POINTERS, | | |
| 1664 | macho.S_LITERAL_POINTERS, | | |
| 1665 | macho.S_THREAD_LOCAL_VARIABLES, | | |
| 1666 | => false, | | |
| 1667 | else => blk: { | | |
| 1668 | if (match.seg == self.text_segment_cmd_index.? and | | |
| 1669 | match.sect == self.stub_helper_section_index.?) break :blk false; | | |
| 1670 | break :blk true; | | |
| 1671 | }, | | |
| 1672 | }; | | |
| 1673 | | 1652 | |
| 1674 | var atom_placement: ?*TextBlock = null; | 1653 | const sym = &self.locals.items[atom.local_sym_index]; |
| 1675 | | 1654 | // Padding is not required for pointer-type sections and any synthetic sections such as |
| 1676 | // TODO converge with `allocateTextBlock` and handle free list | 1655 | // stubs or stub_helper. |
| 1677 | var vaddr = if (self.blocks.get(match)) |last| blk: { | 1656 | // TODO audit this. |
| 1678 | const last_atom_sym = self.locals.items[last.local_sym_index]; | 1657 | const needs_padding = switch (commands.sectionType(sect.*)) { |
| 1679 | const ideal_capacity = if (needs_padding) padToIdeal(last.size) else last.size; | 1658 | macho.S_SYMBOL_STUBS, |
| 1680 | const ideal_capacity_end_vaddr = last_atom_sym.n_value + ideal_capacity; | 1659 | macho.S_NON_LAZY_SYMBOL_POINTERS, |
| 1681 | const last_atom_alignment = try math.powi(u32, 2, atom.alignment); | 1660 | macho.S_LAZY_SYMBOL_POINTERS, |
| 1682 | const new_start_vaddr = mem.alignForwardGeneric(u64, ideal_capacity_end_vaddr, last_atom_alignment); | 1661 | macho.S_LITERAL_POINTERS, |
| 1683 | atom_placement = last; | 1662 | macho.S_THREAD_LOCAL_VARIABLES, |
| 1684 | break :blk new_start_vaddr; | 1663 | => false, |
| 1685 | } else sect.addr; | 1664 | else => blk: { |
| 1686 | | 1665 | if (match.seg == self.text_segment_cmd_index.? and |
| 1687 | log.debug("allocating atom for symbol {s} at address 0x{x}", .{ self.getString(sym.n_strx), vaddr }); | 1666 | match.sect == self.stub_helper_section_index.?) break :blk false; |
| 1688 | | 1667 | break :blk true; |
| 1689 | const expand_section = atom_placement == null or atom_placement.?.next == null; | 1668 | }, |
| 1690 | if (expand_section) { | 1669 | }; |
| 1691 | const needed_size = (vaddr + atom.size) - sect.addr; | | |
| 1692 | const sect_offset: u64 = blk: { | | |
| 1693 | if (self.data_segment_cmd_index.? == match.seg) { | | |
| 1694 | if (self.bss_section_index) |idx| { | | |
| 1695 | if (idx == match.sect) break :blk self.bss_file_offset.?; | | |
| 1696 | } | | |
| 1697 | if (self.tlv_bss_section_index) |idx| { | | |
| 1698 | if (idx == match.sect) break :blk self.tlv_bss_file_offset.?; | | |
| 1699 | } | | |
| 1700 | } | | |
| 1701 | break :blk sect.offset; | | |
| 1702 | }; | | |
| 1703 | const file_offset = sect_offset + vaddr - sect.addr; | | |
| 1704 | const max_size = seg.allocatedSize(file_offset); | | |
| 1705 | log.debug(" (section {s},{s} needed size 0x{x}, max available size 0x{x})", .{ | | |
| 1706 | commands.segmentName(sect.*), | | |
| 1707 | commands.sectionName(sect.*), | | |
| 1708 | needed_size, | | |
| 1709 | max_size, | | |
| 1710 | }); | | |
| 1711 | | 1670 | |
| 1712 | if (needed_size > max_size) { | 1671 | var atom_placement: ?*TextBlock = null; |
| 1713 | const old_base_addr = sect.addr; | 1672 | |
| 1714 | sect.size = 0; | 1673 | // TODO converge with `allocateTextBlock` and handle free list |
| 1715 | const padding: ?u64 = if (match.seg == self.text_segment_cmd_index.?) self.header_pad else null; | 1674 | var vaddr = if (self.blocks.get(match)) |last| blk: { |
| 1716 | const new_offset = @intCast(u32, seg.findFreeSpace(needed_size, atom.alignment, padding)); | 1675 | const last_atom_sym = self.locals.items[last.local_sym_index]; |
| 1717 | sect.offset = new_offset; | 1676 | const ideal_capacity = if (needs_padding) padToIdeal(last.size) else last.size; |
| 1718 | sect.addr = seg.inner.vmaddr + sect.offset - seg.inner.fileoff; | 1677 | const ideal_capacity_end_vaddr = last_atom_sym.n_value + ideal_capacity; |
| 1719 | log.debug(" (found new {s},{s} free space from 0x{x} to 0x{x})", .{ | 1678 | const last_atom_alignment = try math.powi(u32, 2, atom.alignment); |
| 1720 | commands.segmentName(sect.*), | 1679 | const new_start_vaddr = mem.alignForwardGeneric(u64, ideal_capacity_end_vaddr, last_atom_alignment); |
| 1721 | commands.sectionName(sect.*), | 1680 | atom_placement = last; |
| 1722 | new_offset, | 1681 | break :blk new_start_vaddr; |
| 1723 | new_offset + needed_size, | 1682 | } else sect.addr; |
| 1724 | }); | 1683 | |
| 1725 | try self.allocateLocalSymbols(match, old_base_addr); | 1684 | log.debug("allocating atom for symbol {s} at address 0x{x}", .{ self.getString(sym.n_strx), vaddr }); |
| 1726 | vaddr = @intCast( | 1685 | |
| 1727 | u64, | 1686 | const expand_section = atom_placement == null or atom_placement.?.next == null; |
| 1728 | @intCast(i64, vaddr) + @intCast(i64, sect.addr) - @intCast(i64, old_base_addr), | 1687 | if (expand_section) { |
| 1729 | ); | 1688 | const needed_size = (vaddr + atom.size) - sect.addr; |
| | 1689 | const sect_offset: u64 = blk: { |
| | 1690 | if (self.data_segment_cmd_index.? == match.seg) { |
| | 1691 | if (self.bss_section_index) |idx| { |
| | 1692 | if (idx == match.sect) break :blk self.bss_file_offset.?; |
| | 1693 | } |
| | 1694 | if (self.tlv_bss_section_index) |idx| { |
| | 1695 | if (idx == match.sect) break :blk self.tlv_bss_file_offset.?; |
| 1730 | } | 1696 | } |
| 1731 | | | |
| 1732 | sect.size = needed_size; | | |
| 1733 | self.load_commands_dirty = true; | | |
| 1734 | } | | |
| 1735 | const n_sect = @intCast(u8, self.section_ordinals.getIndex(match).? + 1); | | |
| 1736 | sym.n_value = vaddr; | | |
| 1737 | sym.n_sect = n_sect; | | |
| 1738 | | | |
| 1739 | // Update each alias (if any) | | |
| 1740 | for (atom.aliases.items) |index| { | | |
| 1741 | const alias_sym = &self.locals.items[index]; | | |
| 1742 | alias_sym.n_value = vaddr; | | |
| 1743 | alias_sym.n_sect = n_sect; | | |
| 1744 | } | | |
| 1745 | | | |
| 1746 | // Update each symbol contained within the TextBlock | | |
| 1747 | for (atom.contained.items) |sym_at_off| { | | |
| 1748 | const contained_sym = &self.locals.items[sym_at_off.local_sym_index]; | | |
| 1749 | contained_sym.n_value = vaddr + sym_at_off.offset; | | |
| 1750 | contained_sym.n_sect = n_sect; | | |
| 1751 | } | 1697 | } |
| | 1698 | break :blk sect.offset; |
| | 1699 | }; |
| | 1700 | const file_offset = sect_offset + vaddr - sect.addr; |
| | 1701 | const max_size = seg.allocatedSize(file_offset); |
| | 1702 | log.debug(" (section {s},{s} needed size 0x{x}, max available size 0x{x})", .{ |
| | 1703 | commands.segmentName(sect.*), |
| | 1704 | commands.sectionName(sect.*), |
| | 1705 | needed_size, |
| | 1706 | max_size, |
| | 1707 | }); |
| 1752 | | 1708 | |
| 1753 | break :outer vaddr; | 1709 | if (needed_size > max_size) { |
| 1754 | } else { | 1710 | const old_base_addr = sect.addr; |
| 1755 | const new_alignment = math.max(sect.@"align", atom.alignment); | 1711 | sect.size = 0; |
| 1756 | const new_alignment_pow_2 = try math.powi(u32, 2, new_alignment); | 1712 | const padding: ?u64 = if (match.seg == self.text_segment_cmd_index.?) self.header_pad else null; |
| 1757 | const new_size = mem.alignForwardGeneric(u64, sect.size, new_alignment_pow_2) + atom.size; | 1713 | const new_offset = @intCast(u32, seg.findFreeSpace(needed_size, atom.alignment, padding)); |
| 1758 | sect.size = new_size; | 1714 | sect.offset = new_offset; |
| 1759 | sect.@"align" = new_alignment; | 1715 | sect.addr = seg.inner.vmaddr + sect.offset - seg.inner.fileoff; |
| 1760 | break :outer 0; | 1716 | log.debug(" (found new {s},{s} free space from 0x{x} to 0x{x})", .{ |
| | 1717 | commands.segmentName(sect.*), |
| | 1718 | commands.sectionName(sect.*), |
| | 1719 | new_offset, |
| | 1720 | new_offset + needed_size, |
| | 1721 | }); |
| | 1722 | try self.allocateLocalSymbols(match, old_base_addr); |
| | 1723 | vaddr = @intCast( |
| | 1724 | u64, |
| | 1725 | @intCast(i64, vaddr) + @intCast(i64, sect.addr) - @intCast(i64, old_base_addr), |
| | 1726 | ); |
| 1761 | } | 1727 | } |
| 1762 | }; | 1728 | |
| | 1729 | sect.size = needed_size; |
| | 1730 | self.load_commands_dirty = true; |
| | 1731 | } |
| | 1732 | const n_sect = @intCast(u8, self.section_ordinals.getIndex(match).? + 1); |
| | 1733 | sym.n_value = vaddr; |
| | 1734 | sym.n_sect = n_sect; |
| | 1735 | |
| | 1736 | // Update each alias (if any) |
| | 1737 | for (atom.aliases.items) |index| { |
| | 1738 | const alias_sym = &self.locals.items[index]; |
| | 1739 | alias_sym.n_value = vaddr; |
| | 1740 | alias_sym.n_sect = n_sect; |
| | 1741 | } |
| | 1742 | |
| | 1743 | // Update each symbol contained within the TextBlock |
| | 1744 | for (atom.contained.items) |sym_at_off| { |
| | 1745 | const contained_sym = &self.locals.items[sym_at_off.local_sym_index]; |
| | 1746 | contained_sym.n_value = vaddr + sym_at_off.offset; |
| | 1747 | contained_sym.n_sect = n_sect; |
| | 1748 | } |
| 1763 | | 1749 | |
| 1764 | if (self.blocks.getPtr(match)) |last| { | 1750 | if (self.blocks.getPtr(match)) |last| { |
| 1765 | last.*.next = atom; | 1751 | last.*.next = atom; |
| ... | @@ -3899,22 +3885,19 @@ fn allocateSection( | ... | @@ -3899,22 +3885,19 @@ fn allocateSection( |
| 3899 | .reserved2 = opts.reserved2, | 3885 | .reserved2 = opts.reserved2, |
| 3900 | }; | 3886 | }; |
| 3901 | | 3887 | |
| 3902 | const use_stage1 = build_options.is_stage1 and self.base.options.use_stage1; | 3888 | const alignment_pow_2 = try math.powi(u32, 2, alignment); |
| 3903 | if (!use_stage1) { | 3889 | const padding: ?u64 = if (segment_id == self.text_segment_cmd_index.?) self.header_pad else null; |
| 3904 | const alignment_pow_2 = try math.powi(u32, 2, alignment); | 3890 | const off = seg.findFreeSpace(size, alignment_pow_2, padding); |
| 3905 | const padding: ?u64 = if (segment_id == self.text_segment_cmd_index.?) self.header_pad else null; | | |
| 3906 | const off = seg.findFreeSpace(size, alignment_pow_2, padding); | | |
| 3907 | | | |
| 3908 | log.debug("found {s},{s} section free space 0x{x} to 0x{x}", .{ | | |
| 3909 | commands.segmentName(sect), | | |
| 3910 | commands.sectionName(sect), | | |
| 3911 | off, | | |
| 3912 | off + size, | | |
| 3913 | }); | | |
| 3914 | | 3891 | |
| 3915 | sect.addr = seg.inner.vmaddr + off - seg.inner.fileoff; | 3892 | log.debug("found {s},{s} section free space 0x{x} to 0x{x}", .{ |
| 3916 | sect.offset = @intCast(u32, off); | 3893 | commands.segmentName(sect), |
| 3917 | } | 3894 | commands.sectionName(sect), |
| | 3895 | off, |
| | 3896 | off + size, |
| | 3897 | }); |
| | 3898 | |
| | 3899 | sect.addr = seg.inner.vmaddr + off - seg.inner.fileoff; |
| | 3900 | sect.offset = @intCast(u32, off); |
| 3918 | | 3901 | |
| 3919 | const index = @intCast(u16, seg.sections.items.len); | 3902 | const index = @intCast(u16, seg.sections.items.len); |
| 3920 | try seg.sections.append(self.base.allocator, sect); | 3903 | try seg.sections.append(self.base.allocator, sect); |