| ... | ... | @@ -1649,117 +1649,103 @@ pub fn createEmptyAtom(self: *MachO, local_sym_index: u32, size: u64, alignment: |
| 1649 | 1649 | pub fn allocateAtom(self: *MachO, atom: *TextBlock, match: MatchingSection) !u64 { |
| 1650 | 1650 | const seg = &self.load_commands.items[match.seg].Segment; |
| 1651 | 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; |
| 1675 | | |
| 1676 | | // TODO converge with `allocateTextBlock` and handle free list |
| 1677 | | var vaddr = if (self.blocks.get(match)) |last| blk: { |
| 1678 | | const last_atom_sym = self.locals.items[last.local_sym_index]; |
| 1679 | | const ideal_capacity = if (needs_padding) padToIdeal(last.size) else last.size; |
| 1680 | | const ideal_capacity_end_vaddr = last_atom_sym.n_value + ideal_capacity; |
| 1681 | | const last_atom_alignment = try math.powi(u32, 2, atom.alignment); |
| 1682 | | const new_start_vaddr = mem.alignForwardGeneric(u64, ideal_capacity_end_vaddr, last_atom_alignment); |
| 1683 | | atom_placement = last; |
| 1684 | | break :blk new_start_vaddr; |
| 1685 | | } else sect.addr; |
| 1686 | | |
| 1687 | | log.debug("allocating atom for symbol {s} at address 0x{x}", .{ self.getString(sym.n_strx), vaddr }); |
| 1688 | | |
| 1689 | | const expand_section = atom_placement == null or atom_placement.?.next == null; |
| 1690 | | if (expand_section) { |
| 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 | | }); |
| 1653 | const sym = &self.locals.items[atom.local_sym_index]; |
| 1654 | // Padding is not required for pointer-type sections and any synthetic sections such as |
| 1655 | // stubs or stub_helper. |
| 1656 | // TODO audit this. |
| 1657 | const needs_padding = switch (commands.sectionType(sect.*)) { |
| 1658 | macho.S_SYMBOL_STUBS, |
| 1659 | macho.S_NON_LAZY_SYMBOL_POINTERS, |
| 1660 | macho.S_LAZY_SYMBOL_POINTERS, |
| 1661 | macho.S_LITERAL_POINTERS, |
| 1662 | macho.S_THREAD_LOCAL_VARIABLES, |
| 1663 | => false, |
| 1664 | else => blk: { |
| 1665 | if (match.seg == self.text_segment_cmd_index.? and |
| 1666 | match.sect == self.stub_helper_section_index.?) break :blk false; |
| 1667 | break :blk true; |
| 1668 | }, |
| 1669 | }; |
| 1711 | 1670 | |
| 1712 | | if (needed_size > max_size) { |
| 1713 | | const old_base_addr = sect.addr; |
| 1714 | | sect.size = 0; |
| 1715 | | const padding: ?u64 = if (match.seg == self.text_segment_cmd_index.?) self.header_pad else null; |
| 1716 | | const new_offset = @intCast(u32, seg.findFreeSpace(needed_size, atom.alignment, padding)); |
| 1717 | | sect.offset = new_offset; |
| 1718 | | sect.addr = seg.inner.vmaddr + sect.offset - seg.inner.fileoff; |
| 1719 | | log.debug(" (found new {s},{s} free space from 0x{x} to 0x{x})", .{ |
| 1720 | | commands.segmentName(sect.*), |
| 1721 | | commands.sectionName(sect.*), |
| 1722 | | new_offset, |
| 1723 | | new_offset + needed_size, |
| 1724 | | }); |
| 1725 | | try self.allocateLocalSymbols(match, old_base_addr); |
| 1726 | | vaddr = @intCast( |
| 1727 | | u64, |
| 1728 | | @intCast(i64, vaddr) + @intCast(i64, sect.addr) - @intCast(i64, old_base_addr), |
| 1729 | | ); |
| 1671 | var atom_placement: ?*TextBlock = null; |
| 1672 | |
| 1673 | // TODO converge with `allocateTextBlock` and handle free list |
| 1674 | var vaddr = if (self.blocks.get(match)) |last| blk: { |
| 1675 | const last_atom_sym = self.locals.items[last.local_sym_index]; |
| 1676 | const ideal_capacity = if (needs_padding) padToIdeal(last.size) else last.size; |
| 1677 | const ideal_capacity_end_vaddr = last_atom_sym.n_value + ideal_capacity; |
| 1678 | const last_atom_alignment = try math.powi(u32, 2, atom.alignment); |
| 1679 | const new_start_vaddr = mem.alignForwardGeneric(u64, ideal_capacity_end_vaddr, last_atom_alignment); |
| 1680 | atom_placement = last; |
| 1681 | break :blk new_start_vaddr; |
| 1682 | } else sect.addr; |
| 1683 | |
| 1684 | log.debug("allocating atom for symbol {s} at address 0x{x}", .{ self.getString(sym.n_strx), vaddr }); |
| 1685 | |
| 1686 | const expand_section = atom_placement == null or atom_placement.?.next == null; |
| 1687 | if (expand_section) { |
| 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; |
| 1754 | | } else { |
| 1755 | | const new_alignment = math.max(sect.@"align", atom.alignment); |
| 1756 | | const new_alignment_pow_2 = try math.powi(u32, 2, new_alignment); |
| 1757 | | const new_size = mem.alignForwardGeneric(u64, sect.size, new_alignment_pow_2) + atom.size; |
| 1758 | | sect.size = new_size; |
| 1759 | | sect.@"align" = new_alignment; |
| 1760 | | break :outer 0; |
| 1709 | if (needed_size > max_size) { |
| 1710 | const old_base_addr = sect.addr; |
| 1711 | sect.size = 0; |
| 1712 | const padding: ?u64 = if (match.seg == self.text_segment_cmd_index.?) self.header_pad else null; |
| 1713 | const new_offset = @intCast(u32, seg.findFreeSpace(needed_size, atom.alignment, padding)); |
| 1714 | sect.offset = new_offset; |
| 1715 | sect.addr = seg.inner.vmaddr + sect.offset - seg.inner.fileoff; |
| 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 | 1750 | if (self.blocks.getPtr(match)) |last| { |
| 1765 | 1751 | last.*.next = atom; |
| ... | ... | @@ -3899,22 +3885,19 @@ fn allocateSection( |
| 3899 | 3885 | .reserved2 = opts.reserved2, |
| 3900 | 3886 | }; |
| 3901 | 3887 | |
| 3902 | | const use_stage1 = build_options.is_stage1 and self.base.options.use_stage1; |
| 3903 | | if (!use_stage1) { |
| 3904 | | const alignment_pow_2 = try math.powi(u32, 2, alignment); |
| 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 | | }); |
| 3888 | const alignment_pow_2 = try math.powi(u32, 2, alignment); |
| 3889 | const padding: ?u64 = if (segment_id == self.text_segment_cmd_index.?) self.header_pad else null; |
| 3890 | const off = seg.findFreeSpace(size, alignment_pow_2, padding); |
| 3914 | 3891 | |
| 3915 | | sect.addr = seg.inner.vmaddr + off - seg.inner.fileoff; |
| 3916 | | sect.offset = @intCast(u32, off); |
| 3917 | | } |
| 3892 | log.debug("found {s},{s} section free space 0x{x} to 0x{x}", .{ |
| 3893 | commands.segmentName(sect), |
| 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 | 3902 | const index = @intCast(u16, seg.sections.items.len); |
| 3920 | 3903 | try seg.sections.append(self.base.allocator, sect); |