| ... | @@ -761,43 +761,34 @@ pub fn flush(self: *MachO, comp: *Compilation) !void { | ... | @@ -761,43 +761,34 @@ pub fn flush(self: *MachO, comp: *Compilation) !void { |
| 761 | try self.addDataInCodeLC(); | 761 | try self.addDataInCodeLC(); |
| 762 | try self.addCodeSignatureLC(); | 762 | try self.addCodeSignatureLC(); |
| 763 | | 763 | |
| 764 | if (use_stage1) { | 764 | try self.parseTextBlocks(); |
| 765 | try self.parseTextBlocks(); | 765 | try self.allocateGlobalSymbols(); |
| 766 | try self.allocateTextSegment(); | 766 | { |
| 767 | try self.allocateDataConstSegment(); | 767 | log.debug("locals:", .{}); |
| 768 | try self.allocateDataSegment(); | 768 | for (self.locals.items) |sym| { |
| 769 | self.allocateLinkeditSegment(); | 769 | log.debug(" {s}: {}", .{ self.getString(sym.n_strx), sym }); |
| 770 | try self.allocateTextBlocks(); | 770 | } |
| 771 | try self.flushZld(); | 771 | log.debug("globals:", .{}); |
| 772 | } else { | 772 | for (self.globals.items) |sym| { |
| 773 | try self.parseTextBlocks(); | 773 | log.debug(" {s}: {}", .{ self.getString(sym.n_strx), sym }); |
| 774 | try self.allocateGlobalSymbols(); | 774 | } |
| 775 | { | 775 | log.debug("undefs:", .{}); |
| 776 | log.debug("locals:", .{}); | 776 | for (self.undefs.items) |sym| { |
| 777 | for (self.locals.items) |sym| { | 777 | log.debug(" {s}: {}", .{ self.getString(sym.n_strx), sym }); |
| 778 | log.debug(" {s}: {}", .{ self.getString(sym.n_strx), sym }); | 778 | } |
| 779 | } | 779 | log.debug("unresolved:", .{}); |
| 780 | log.debug("globals:", .{}); | 780 | for (self.unresolved.keys()) |key| { |
| 781 | for (self.globals.items) |sym| { | 781 | log.debug(" {d} => {s}", .{ key, self.unresolved.get(key).? }); |
| 782 | log.debug(" {s}: {}", .{ self.getString(sym.n_strx), sym }); | 782 | } |
| 783 | } | 783 | log.debug("resolved:", .{}); |
| 784 | log.debug("undefs:", .{}); | 784 | var it = self.symbol_resolver.iterator(); |
| 785 | for (self.undefs.items) |sym| { | 785 | while (it.next()) |entry| { |
| 786 | log.debug(" {s}: {}", .{ self.getString(sym.n_strx), sym }); | 786 | log.debug(" {s} => {}", .{ self.getString(entry.key_ptr.*), entry.value_ptr.* }); |
| 787 | } | | |
| 788 | log.debug("unresolved:", .{}); | | |
| 789 | for (self.unresolved.keys()) |key| { | | |
| 790 | log.debug(" {d} => {s}", .{ key, self.unresolved.get(key).? }); | | |
| 791 | } | | |
| 792 | log.debug("resolved:", .{}); | | |
| 793 | var it = self.symbol_resolver.iterator(); | | |
| 794 | while (it.next()) |entry| { | | |
| 795 | log.debug(" {s} => {}", .{ self.getString(entry.key_ptr.*), entry.value_ptr.* }); | | |
| 796 | } | | |
| 797 | } | 787 | } |
| 798 | try self.writeAtoms(); | | |
| 799 | try self.flushModule(comp); | | |
| 800 | } | 788 | } |
| | 789 | try self.writeAtoms(); |
| | 790 | try self.writeDices(); |
| | 791 | try self.flushModule(comp); |
| 801 | } | 792 | } |
| 802 | | 793 | |
| 803 | if (!self.base.options.disable_lld_caching) { | 794 | if (!self.base.options.disable_lld_caching) { |
| ... | @@ -1638,248 +1629,6 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio | ... | @@ -1638,248 +1629,6 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1638 | return res; | 1629 | return res; |
| 1639 | } | 1630 | } |
| 1640 | | 1631 | |
| 1641 | fn allocateTextSegment(self: *MachO) !void { | | |
| 1642 | const seg = &self.load_commands.items[self.text_segment_cmd_index.?].Segment; | | |
| 1643 | const base_vmaddr = self.load_commands.items[self.pagezero_segment_cmd_index.?].Segment.inner.vmsize; | | |
| 1644 | seg.inner.fileoff = 0; | | |
| 1645 | seg.inner.vmaddr = base_vmaddr; | | |
| 1646 | | | |
| 1647 | var sizeofcmds: u64 = 0; | | |
| 1648 | for (self.load_commands.items) |lc| { | | |
| 1649 | sizeofcmds += lc.cmdsize(); | | |
| 1650 | } | | |
| 1651 | | | |
| 1652 | try self.allocateSegment(self.text_segment_cmd_index.?, @sizeOf(macho.mach_header_64) + sizeofcmds); | | |
| 1653 | | | |
| 1654 | // Shift all sections to the back to minimize jump size between __TEXT and __DATA segments. | | |
| 1655 | var min_alignment: u32 = 0; | | |
| 1656 | for (seg.sections.items) |sect| { | | |
| 1657 | const alignment = try math.powi(u32, 2, sect.@"align"); | | |
| 1658 | min_alignment = math.max(min_alignment, alignment); | | |
| 1659 | } | | |
| 1660 | | | |
| 1661 | assert(min_alignment > 0); | | |
| 1662 | const last_sect_idx = seg.sections.items.len - 1; | | |
| 1663 | const last_sect = seg.sections.items[last_sect_idx]; | | |
| 1664 | const shift: u32 = blk: { | | |
| 1665 | const diff = seg.inner.filesize - last_sect.offset - last_sect.size; | | |
| 1666 | const factor = @divTrunc(diff, min_alignment); | | |
| 1667 | break :blk @intCast(u32, factor * min_alignment); | | |
| 1668 | }; | | |
| 1669 | | | |
| 1670 | if (shift > 0) { | | |
| 1671 | for (seg.sections.items) |*sect| { | | |
| 1672 | sect.offset += shift; | | |
| 1673 | sect.addr += shift; | | |
| 1674 | } | | |
| 1675 | } | | |
| 1676 | } | | |
| 1677 | | | |
| 1678 | fn allocateDataConstSegment(self: *MachO) !void { | | |
| 1679 | const seg = &self.load_commands.items[self.data_const_segment_cmd_index.?].Segment; | | |
| 1680 | const text_seg = self.load_commands.items[self.text_segment_cmd_index.?].Segment; | | |
| 1681 | seg.inner.fileoff = text_seg.inner.fileoff + text_seg.inner.filesize; | | |
| 1682 | seg.inner.vmaddr = text_seg.inner.vmaddr + text_seg.inner.vmsize; | | |
| 1683 | try self.allocateSegment(self.data_const_segment_cmd_index.?, 0); | | |
| 1684 | } | | |
| 1685 | | | |
| 1686 | fn allocateDataSegment(self: *MachO) !void { | | |
| 1687 | const seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment; | | |
| 1688 | const data_const_seg = self.load_commands.items[self.data_const_segment_cmd_index.?].Segment; | | |
| 1689 | seg.inner.fileoff = data_const_seg.inner.fileoff + data_const_seg.inner.filesize; | | |
| 1690 | seg.inner.vmaddr = data_const_seg.inner.vmaddr + data_const_seg.inner.vmsize; | | |
| 1691 | try self.allocateSegment(self.data_segment_cmd_index.?, 0); | | |
| 1692 | } | | |
| 1693 | | | |
| 1694 | fn allocateLinkeditSegment(self: *MachO) void { | | |
| 1695 | const seg = &self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment; | | |
| 1696 | const data_seg = self.load_commands.items[self.data_segment_cmd_index.?].Segment; | | |
| 1697 | seg.inner.fileoff = data_seg.inner.fileoff + data_seg.inner.filesize; | | |
| 1698 | seg.inner.vmaddr = data_seg.inner.vmaddr + data_seg.inner.vmsize; | | |
| 1699 | } | | |
| 1700 | | | |
| 1701 | fn allocateSegment(self: *MachO, index: u16, offset: u64) !void { | | |
| 1702 | const seg = &self.load_commands.items[index].Segment; | | |
| 1703 | | | |
| 1704 | // Allocate the sections according to their alignment at the beginning of the segment. | | |
| 1705 | var start: u64 = offset; | | |
| 1706 | for (seg.sections.items) |*sect, sect_id| { | | |
| 1707 | const alignment = try math.powi(u32, 2, sect.@"align"); | | |
| 1708 | const start_aligned = mem.alignForwardGeneric(u64, start, alignment); | | |
| 1709 | const end_aligned = mem.alignForwardGeneric(u64, start_aligned + sect.size, alignment); | | |
| 1710 | const file_offset = @intCast(u32, seg.inner.fileoff + start_aligned); | | |
| 1711 | | | |
| 1712 | blk: { | | |
| 1713 | if (index == self.data_segment_cmd_index.?) { | | |
| 1714 | if (self.bss_section_index) |idx| { | | |
| 1715 | if (sect_id == idx) { | | |
| 1716 | self.bss_file_offset = file_offset; | | |
| 1717 | break :blk; | | |
| 1718 | } | | |
| 1719 | } | | |
| 1720 | if (self.tlv_bss_section_index) |idx| { | | |
| 1721 | if (sect_id == idx) { | | |
| 1722 | self.tlv_bss_file_offset = file_offset; | | |
| 1723 | break :blk; | | |
| 1724 | } | | |
| 1725 | } | | |
| 1726 | } | | |
| 1727 | sect.offset = @intCast(u32, seg.inner.fileoff + start_aligned); | | |
| 1728 | } | | |
| 1729 | | | |
| 1730 | sect.addr = seg.inner.vmaddr + start_aligned; | | |
| 1731 | start = end_aligned; | | |
| 1732 | } | | |
| 1733 | | | |
| 1734 | const seg_size_aligned = mem.alignForwardGeneric(u64, start, self.page_size); | | |
| 1735 | seg.inner.filesize = seg_size_aligned; | | |
| 1736 | seg.inner.vmsize = seg_size_aligned; | | |
| 1737 | } | | |
| 1738 | | | |
| 1739 | fn allocateTextBlocks(self: *MachO) !void { | | |
| 1740 | var it = self.blocks.iterator(); | | |
| 1741 | while (it.next()) |entry| { | | |
| 1742 | const match = entry.key_ptr.*; | | |
| 1743 | var block: *TextBlock = entry.value_ptr.*; | | |
| 1744 | | | |
| 1745 | // Find the first block | | |
| 1746 | while (block.prev) |prev| { | | |
| 1747 | block = prev; | | |
| 1748 | } | | |
| 1749 | | | |
| 1750 | const seg = self.load_commands.items[match.seg].Segment; | | |
| 1751 | const sect = seg.sections.items[match.sect]; | | |
| 1752 | | | |
| 1753 | var base_addr: u64 = sect.addr; | | |
| 1754 | const n_sect = @intCast(u8, self.section_ordinals.getIndex(match).? + 1); | | |
| 1755 | | | |
| 1756 | log.debug(" within section {s},{s}", .{ commands.segmentName(sect), commands.sectionName(sect) }); | | |
| 1757 | log.debug(" {}", .{sect}); | | |
| 1758 | | | |
| 1759 | while (true) { | | |
| 1760 | const block_alignment = try math.powi(u32, 2, block.alignment); | | |
| 1761 | base_addr = mem.alignForwardGeneric(u64, base_addr, block_alignment); | | |
| 1762 | | | |
| 1763 | const sym = &self.locals.items[block.local_sym_index]; | | |
| 1764 | sym.n_value = base_addr; | | |
| 1765 | sym.n_sect = n_sect; | | |
| 1766 | | | |
| 1767 | log.debug(" {s}: start=0x{x}, end=0x{x}, size={}, align={}", .{ | | |
| 1768 | self.getString(sym.n_strx), | | |
| 1769 | base_addr, | | |
| 1770 | base_addr + block.size, | | |
| 1771 | block.size, | | |
| 1772 | block.alignment, | | |
| 1773 | }); | | |
| 1774 | | | |
| 1775 | // Update each alias (if any) | | |
| 1776 | for (block.aliases.items) |index| { | | |
| 1777 | const alias_sym = &self.locals.items[index]; | | |
| 1778 | alias_sym.n_value = base_addr; | | |
| 1779 | alias_sym.n_sect = n_sect; | | |
| 1780 | } | | |
| 1781 | | | |
| 1782 | // Update each symbol contained within the TextBlock | | |
| 1783 | for (block.contained.items) |sym_at_off| { | | |
| 1784 | const contained_sym = &self.locals.items[sym_at_off.local_sym_index]; | | |
| 1785 | contained_sym.n_value = base_addr + sym_at_off.offset; | | |
| 1786 | contained_sym.n_sect = n_sect; | | |
| 1787 | } | | |
| 1788 | | | |
| 1789 | base_addr += block.size; | | |
| 1790 | | | |
| 1791 | if (block.next) |next| { | | |
| 1792 | block = next; | | |
| 1793 | } else break; | | |
| 1794 | } | | |
| 1795 | } | | |
| 1796 | | | |
| 1797 | // Update globals | | |
| 1798 | { | | |
| 1799 | var sym_it = self.symbol_resolver.valueIterator(); | | |
| 1800 | while (sym_it.next()) |resolv| { | | |
| 1801 | if (resolv.where != .global) continue; | | |
| 1802 | | | |
| 1803 | assert(resolv.local_sym_index != 0); | | |
| 1804 | const local_sym = self.locals.items[resolv.local_sym_index]; | | |
| 1805 | const sym = &self.globals.items[resolv.where_index]; | | |
| 1806 | sym.n_value = local_sym.n_value; | | |
| 1807 | sym.n_sect = local_sym.n_sect; | | |
| 1808 | } | | |
| 1809 | } | | |
| 1810 | } | | |
| 1811 | | | |
| 1812 | fn writeTextBlocks(self: *MachO) !void { | | |
| 1813 | var it = self.blocks.iterator(); | | |
| 1814 | while (it.next()) |entry| { | | |
| 1815 | const match = entry.key_ptr.*; | | |
| 1816 | var block: *TextBlock = entry.value_ptr.*; | | |
| 1817 | | | |
| 1818 | while (block.prev) |prev| { | | |
| 1819 | block = prev; | | |
| 1820 | } | | |
| 1821 | | | |
| 1822 | const seg = self.load_commands.items[match.seg].Segment; | | |
| 1823 | const sect = seg.sections.items[match.sect]; | | |
| 1824 | const sect_type = commands.sectionType(sect); | | |
| 1825 | | | |
| 1826 | log.debug(" for section {s},{s}", .{ commands.segmentName(sect), commands.sectionName(sect) }); | | |
| 1827 | log.debug(" {}", .{sect}); | | |
| 1828 | | | |
| 1829 | var code = try self.base.allocator.alloc(u8, sect.size); | | |
| 1830 | defer self.base.allocator.free(code); | | |
| 1831 | | | |
| 1832 | const file_offset: u64 = blk: { | | |
| 1833 | if (self.data_segment_cmd_index.? == match.seg) { | | |
| 1834 | if (self.bss_section_index) |idx| { | | |
| 1835 | if (idx == match.sect) break :blk self.bss_file_offset.?; | | |
| 1836 | } | | |
| 1837 | if (self.tlv_bss_section_index) |idx| { | | |
| 1838 | if (idx == match.sect) break :blk self.tlv_bss_file_offset.?; | | |
| 1839 | } | | |
| 1840 | } | | |
| 1841 | break :blk sect.offset; | | |
| 1842 | }; | | |
| 1843 | | | |
| 1844 | if (sect_type == macho.S_ZEROFILL or sect_type == macho.S_THREAD_LOCAL_ZEROFILL) { | | |
| 1845 | mem.set(u8, code, 0); | | |
| 1846 | } else { | | |
| 1847 | var base_off: u64 = 0; | | |
| 1848 | | | |
| 1849 | while (true) { | | |
| 1850 | const block_alignment = try math.powi(u32, 2, block.alignment); | | |
| 1851 | const aligned_base_off = mem.alignForwardGeneric(u64, base_off, block_alignment); | | |
| 1852 | | | |
| 1853 | const sym = self.locals.items[block.local_sym_index]; | | |
| 1854 | log.debug(" {s}: start=0x{x}, end=0x{x}, size={}, align={}", .{ | | |
| 1855 | self.getString(sym.n_strx), | | |
| 1856 | aligned_base_off, | | |
| 1857 | aligned_base_off + block.size, | | |
| 1858 | block.size, | | |
| 1859 | block.alignment, | | |
| 1860 | }); | | |
| 1861 | | | |
| 1862 | try block.resolveRelocs(self); | | |
| 1863 | mem.copy(u8, code[aligned_base_off..][0..block.size], block.code.items); | | |
| 1864 | | | |
| 1865 | // TODO NOP for machine code instead of just zeroing out | | |
| 1866 | const padding_len = aligned_base_off - base_off; | | |
| 1867 | mem.set(u8, code[base_off..][0..padding_len], 0); | | |
| 1868 | | | |
| 1869 | base_off = aligned_base_off + block.size; | | |
| 1870 | | | |
| 1871 | if (block.next) |next| { | | |
| 1872 | block = next; | | |
| 1873 | } else break; | | |
| 1874 | } | | |
| 1875 | | | |
| 1876 | mem.set(u8, code[base_off..], 0); | | |
| 1877 | } | | |
| 1878 | | | |
| 1879 | try self.base.file.?.pwriteAll(code, file_offset); | | |
| 1880 | } | | |
| 1881 | } | | |
| 1882 | | | |
| 1883 | pub fn createEmptyAtom(self: *MachO, local_sym_index: u32, size: u64, alignment: u32) !*TextBlock { | 1632 | pub fn createEmptyAtom(self: *MachO, local_sym_index: u32, size: u64, alignment: u32) !*TextBlock { |
| 1884 | const code = try self.base.allocator.alloc(u8, size); | 1633 | const code = try self.base.allocator.alloc(u8, size); |
| 1885 | defer self.base.allocator.free(code); | 1634 | defer self.base.allocator.free(code); |
| ... | @@ -2920,17 +2669,23 @@ fn parseTextBlocks(self: *MachO) !void { | ... | @@ -2920,17 +2669,23 @@ fn parseTextBlocks(self: *MachO) !void { |
| 2920 | } | 2669 | } |
| 2921 | | 2670 | |
| 2922 | fn addDataInCodeLC(self: *MachO) !void { | 2671 | fn addDataInCodeLC(self: *MachO) !void { |
| 2923 | if (self.data_in_code_cmd_index == null) { | 2672 | if (self.data_in_code_cmd_index != null) return; |
| 2924 | self.data_in_code_cmd_index = @intCast(u16, self.load_commands.items.len); | 2673 | self.data_in_code_cmd_index = @intCast(u16, self.load_commands.items.len); |
| 2925 | try self.load_commands.append(self.base.allocator, .{ | 2674 | try self.load_commands.append(self.base.allocator, .{ |
| 2926 | .LinkeditData = .{ | 2675 | .LinkeditData = .{ |
| 2927 | .cmd = macho.LC_DATA_IN_CODE, | 2676 | .cmd = macho.LC_DATA_IN_CODE, |
| 2928 | .cmdsize = @sizeOf(macho.linkedit_data_command), | 2677 | .cmdsize = @sizeOf(macho.linkedit_data_command), |
| 2929 | .dataoff = 0, | 2678 | .dataoff = 0, |
| 2930 | .datasize = 0, | 2679 | .datasize = 0, |
| 2931 | }, | 2680 | }, |
| 2932 | }); | 2681 | }); |
| 2933 | } | 2682 | const dice_cmd = &self.load_commands.items[self.data_in_code_cmd_index.?].LinkeditData; |
| | 2683 | const needed_size = 10 * @sizeOf(macho.data_in_code_entry); |
| | 2684 | const dataoff = self.findFreeSpaceLinkedit(needed_size, @alignOf(macho.data_in_code_entry), null); |
| | 2685 | log.debug("found data-in-code free space 0x{x} to 0x{x}", .{ dataoff, dataoff + needed_size }); |
| | 2686 | dice_cmd.dataoff = @intCast(u32, dataoff); |
| | 2687 | dice_cmd.datasize = needed_size; |
| | 2688 | self.load_commands_dirty = true; |
| 2934 | } | 2689 | } |
| 2935 | | 2690 | |
| 2936 | fn addCodeSignatureLC(self: *MachO) !void { | 2691 | fn addCodeSignatureLC(self: *MachO) !void { |
| ... | @@ -2982,42 +2737,6 @@ fn addLoadDylibLCs(self: *MachO) !void { | ... | @@ -2982,42 +2737,6 @@ fn addLoadDylibLCs(self: *MachO) !void { |
| 2982 | } | 2737 | } |
| 2983 | } | 2738 | } |
| 2984 | | 2739 | |
| 2985 | fn flushZld(self: *MachO) !void { | | |
| 2986 | try self.writeTextBlocks(); | | |
| 2987 | try self.setEntryPoint(); | | |
| 2988 | try self.writeRebaseInfoTableZld(); | | |
| 2989 | try self.writeBindInfoTableZld(); | | |
| 2990 | try self.writeLazyBindInfoTableZld(); | | |
| 2991 | try self.writeExportInfoZld(); | | |
| 2992 | try self.writeDices(); | | |
| 2993 | | | |
| 2994 | { | | |
| 2995 | const seg = &self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment; | | |
| 2996 | const symtab = &self.load_commands.items[self.symtab_cmd_index.?].Symtab; | | |
| 2997 | symtab.symoff = @intCast(u32, seg.inner.fileoff + seg.inner.filesize); | | |
| 2998 | } | | |
| 2999 | | | |
| 3000 | try self.writeSymbolTable(); | | |
| 3001 | try self.writeStringTableZld(); | | |
| 3002 | | | |
| 3003 | { | | |
| 3004 | // Seal __LINKEDIT size | | |
| 3005 | const seg = &self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment; | | |
| 3006 | seg.inner.vmsize = mem.alignForwardGeneric(u64, seg.inner.filesize, self.page_size); | | |
| 3007 | } | | |
| 3008 | | | |
| 3009 | if (self.requires_adhoc_codesig) { | | |
| 3010 | try self.writeCodeSignaturePadding(); | | |
| 3011 | } | | |
| 3012 | | | |
| 3013 | try self.writeLoadCommands(); | | |
| 3014 | try self.writeHeader(); | | |
| 3015 | | | |
| 3016 | if (self.requires_adhoc_codesig) { | | |
| 3017 | try self.writeCodeSignature(); | | |
| 3018 | } | | |
| 3019 | } | | |
| 3020 | | | |
| 3021 | fn setEntryPoint(self: *MachO) !void { | 2740 | fn setEntryPoint(self: *MachO) !void { |
| 3022 | if (self.base.options.output_mode != .Exe) return; | 2741 | if (self.base.options.output_mode != .Exe) return; |
| 3023 | | 2742 | |
| ... | @@ -3039,343 +2758,6 @@ fn setEntryPoint(self: *MachO) !void { | ... | @@ -3039,343 +2758,6 @@ fn setEntryPoint(self: *MachO) !void { |
| 3039 | self.load_commands_dirty = true; | 2758 | self.load_commands_dirty = true; |
| 3040 | } | 2759 | } |
| 3041 | | 2760 | |
| 3042 | fn writeRebaseInfoTableZld(self: *MachO) !void { | | |
| 3043 | var pointers = std.ArrayList(bind.Pointer).init(self.base.allocator); | | |
| 3044 | defer pointers.deinit(); | | |
| 3045 | | | |
| 3046 | { | | |
| 3047 | var it = self.blocks.iterator(); | | |
| 3048 | while (it.next()) |entry| { | | |
| 3049 | const match = entry.key_ptr.*; | | |
| 3050 | var block: *TextBlock = entry.value_ptr.*; | | |
| 3051 | | | |
| 3052 | if (match.seg == self.text_segment_cmd_index.?) continue; // __TEXT is non-writable | | |
| 3053 | | | |
| 3054 | const seg = self.load_commands.items[match.seg].Segment; | | |
| 3055 | | | |
| 3056 | while (true) { | | |
| 3057 | const sym = self.locals.items[block.local_sym_index]; | | |
| 3058 | const base_offset = sym.n_value - seg.inner.vmaddr; | | |
| 3059 | | | |
| 3060 | for (block.rebases.items) |offset| { | | |
| 3061 | try pointers.append(.{ | | |
| 3062 | .offset = base_offset + offset, | | |
| 3063 | .segment_id = match.seg, | | |
| 3064 | }); | | |
| 3065 | } | | |
| 3066 | | | |
| 3067 | if (block.prev) |prev| { | | |
| 3068 | block = prev; | | |
| 3069 | } else break; | | |
| 3070 | } | | |
| 3071 | } | | |
| 3072 | } | | |
| 3073 | | | |
| 3074 | const size = try bind.rebaseInfoSize(pointers.items); | | |
| 3075 | var buffer = try self.base.allocator.alloc(u8, @intCast(usize, size)); | | |
| 3076 | defer self.base.allocator.free(buffer); | | |
| 3077 | | | |
| 3078 | var stream = std.io.fixedBufferStream(buffer); | | |
| 3079 | try bind.writeRebaseInfo(pointers.items, stream.writer()); | | |
| 3080 | | | |
| 3081 | const seg = &self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment; | | |
| 3082 | const dyld_info = &self.load_commands.items[self.dyld_info_cmd_index.?].DyldInfoOnly; | | |
| 3083 | dyld_info.rebase_off = @intCast(u32, seg.inner.fileoff); | | |
| 3084 | dyld_info.rebase_size = @intCast(u32, mem.alignForwardGeneric(u64, buffer.len, @sizeOf(u64))); | | |
| 3085 | seg.inner.filesize += dyld_info.rebase_size; | | |
| 3086 | | | |
| 3087 | log.debug("writing rebase info from 0x{x} to 0x{x}", .{ dyld_info.rebase_off, dyld_info.rebase_off + dyld_info.rebase_size }); | | |
| 3088 | | | |
| 3089 | try self.base.file.?.pwriteAll(buffer, dyld_info.rebase_off); | | |
| 3090 | } | | |
| 3091 | | | |
| 3092 | fn writeBindInfoTableZld(self: *MachO) !void { | | |
| 3093 | var pointers = std.ArrayList(bind.Pointer).init(self.base.allocator); | | |
| 3094 | defer pointers.deinit(); | | |
| 3095 | | | |
| 3096 | { | | |
| 3097 | var it = self.blocks.iterator(); | | |
| 3098 | while (it.next()) |entry| { | | |
| 3099 | const match = entry.key_ptr.*; | | |
| 3100 | var block: *TextBlock = entry.value_ptr.*; | | |
| 3101 | | | |
| 3102 | if (match.seg == self.text_segment_cmd_index.?) continue; // __TEXT is non-writable | | |
| 3103 | | | |
| 3104 | const seg = self.load_commands.items[match.seg].Segment; | | |
| 3105 | | | |
| 3106 | while (true) { | | |
| 3107 | const sym = self.locals.items[block.local_sym_index]; | | |
| 3108 | const base_offset = sym.n_value - seg.inner.vmaddr; | | |
| 3109 | | | |
| 3110 | for (block.bindings.items) |binding| { | | |
| 3111 | const bind_sym = self.undefs.items[binding.local_sym_index]; | | |
| 3112 | try pointers.append(.{ | | |
| 3113 | .offset = binding.offset + base_offset, | | |
| 3114 | .segment_id = match.seg, | | |
| 3115 | .dylib_ordinal = @divExact(bind_sym.n_desc, macho.N_SYMBOL_RESOLVER), | | |
| 3116 | .name = self.getString(bind_sym.n_strx), | | |
| 3117 | }); | | |
| 3118 | } | | |
| 3119 | | | |
| 3120 | if (block.prev) |prev| { | | |
| 3121 | block = prev; | | |
| 3122 | } else break; | | |
| 3123 | } | | |
| 3124 | } | | |
| 3125 | } | | |
| 3126 | | | |
| 3127 | const size = try bind.bindInfoSize(pointers.items); | | |
| 3128 | var buffer = try self.base.allocator.alloc(u8, @intCast(usize, size)); | | |
| 3129 | defer self.base.allocator.free(buffer); | | |
| 3130 | | | |
| 3131 | var stream = std.io.fixedBufferStream(buffer); | | |
| 3132 | try bind.writeBindInfo(pointers.items, stream.writer()); | | |
| 3133 | | | |
| 3134 | const seg = &self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment; | | |
| 3135 | const dyld_info = &self.load_commands.items[self.dyld_info_cmd_index.?].DyldInfoOnly; | | |
| 3136 | dyld_info.bind_off = @intCast(u32, seg.inner.fileoff + seg.inner.filesize); | | |
| 3137 | dyld_info.bind_size = @intCast(u32, mem.alignForwardGeneric(u64, buffer.len, @alignOf(u64))); | | |
| 3138 | seg.inner.filesize += dyld_info.bind_size; | | |
| 3139 | | | |
| 3140 | log.debug("writing binding info from 0x{x} to 0x{x}", .{ dyld_info.bind_off, dyld_info.bind_off + dyld_info.bind_size }); | | |
| 3141 | | | |
| 3142 | try self.base.file.?.pwriteAll(buffer, dyld_info.bind_off); | | |
| 3143 | } | | |
| 3144 | | | |
| 3145 | fn writeLazyBindInfoTableZld(self: *MachO) !void { | | |
| 3146 | var pointers = std.ArrayList(bind.Pointer).init(self.base.allocator); | | |
| 3147 | defer pointers.deinit(); | | |
| 3148 | | | |
| 3149 | if (self.la_symbol_ptr_section_index) |sect| blk: { | | |
| 3150 | var atom = self.blocks.get(.{ | | |
| 3151 | .seg = self.data_segment_cmd_index.?, | | |
| 3152 | .sect = sect, | | |
| 3153 | }) orelse break :blk; | | |
| 3154 | const seg = self.load_commands.items[self.data_segment_cmd_index.?].Segment; | | |
| 3155 | | | |
| 3156 | while (true) { | | |
| 3157 | const sym = self.locals.items[atom.local_sym_index]; | | |
| 3158 | const base_offset = sym.n_value - seg.inner.vmaddr; | | |
| 3159 | | | |
| 3160 | for (atom.lazy_bindings.items) |binding| { | | |
| 3161 | const bind_sym = self.undefs.items[binding.local_sym_index]; | | |
| 3162 | try pointers.append(.{ | | |
| 3163 | .offset = binding.offset + base_offset, | | |
| 3164 | .segment_id = self.data_segment_cmd_index.?, | | |
| 3165 | .dylib_ordinal = @divExact(bind_sym.n_desc, macho.N_SYMBOL_RESOLVER), | | |
| 3166 | .name = self.getString(bind_sym.n_strx), | | |
| 3167 | }); | | |
| 3168 | } | | |
| 3169 | if (atom.prev) |prev| { | | |
| 3170 | atom = prev; | | |
| 3171 | } else break; | | |
| 3172 | } | | |
| 3173 | } | | |
| 3174 | | | |
| 3175 | const size = try bind.lazyBindInfoSize(pointers.items); | | |
| 3176 | var buffer = try self.base.allocator.alloc(u8, @intCast(usize, size)); | | |
| 3177 | defer self.base.allocator.free(buffer); | | |
| 3178 | | | |
| 3179 | var stream = std.io.fixedBufferStream(buffer); | | |
| 3180 | try bind.writeLazyBindInfo(pointers.items, stream.writer()); | | |
| 3181 | | | |
| 3182 | const seg = &self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment; | | |
| 3183 | const dyld_info = &self.load_commands.items[self.dyld_info_cmd_index.?].DyldInfoOnly; | | |
| 3184 | dyld_info.lazy_bind_off = @intCast(u32, seg.inner.fileoff + seg.inner.filesize); | | |
| 3185 | dyld_info.lazy_bind_size = @intCast(u32, mem.alignForwardGeneric(u64, buffer.len, @alignOf(u64))); | | |
| 3186 | seg.inner.filesize += dyld_info.lazy_bind_size; | | |
| 3187 | | | |
| 3188 | log.debug("writing lazy binding info from 0x{x} to 0x{x}", .{ dyld_info.lazy_bind_off, dyld_info.lazy_bind_off + dyld_info.lazy_bind_size }); | | |
| 3189 | | | |
| 3190 | try self.base.file.?.pwriteAll(buffer, dyld_info.lazy_bind_off); | | |
| 3191 | try self.populateLazyBindOffsetsInStubHelper(buffer); | | |
| 3192 | } | | |
| 3193 | | | |
| 3194 | fn writeExportInfoZld(self: *MachO) !void { | | |
| 3195 | var trie: Trie = .{}; | | |
| 3196 | defer trie.deinit(self.base.allocator); | | |
| 3197 | | | |
| 3198 | const text_segment = self.load_commands.items[self.text_segment_cmd_index.?].Segment; | | |
| 3199 | const base_address = text_segment.inner.vmaddr; | | |
| 3200 | | | |
| 3201 | // TODO handle macho.EXPORT_SYMBOL_FLAGS_REEXPORT and macho.EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER. | | |
| 3202 | log.debug("writing export trie", .{}); | | |
| 3203 | | | |
| 3204 | for (self.globals.items) |sym| { | | |
| 3205 | const sym_name = self.getString(sym.n_strx); | | |
| 3206 | log.debug(" | putting '{s}' defined at 0x{x}", .{ sym_name, sym.n_value }); | | |
| 3207 | | | |
| 3208 | try trie.put(self.base.allocator, .{ | | |
| 3209 | .name = sym_name, | | |
| 3210 | .vmaddr_offset = sym.n_value - base_address, | | |
| 3211 | .export_flags = macho.EXPORT_SYMBOL_FLAGS_KIND_REGULAR, | | |
| 3212 | }); | | |
| 3213 | } | | |
| 3214 | | | |
| 3215 | try trie.finalize(self.base.allocator); | | |
| 3216 | | | |
| 3217 | var buffer = try self.base.allocator.alloc(u8, @intCast(usize, trie.size)); | | |
| 3218 | defer self.base.allocator.free(buffer); | | |
| 3219 | | | |
| 3220 | var stream = std.io.fixedBufferStream(buffer); | | |
| 3221 | const nwritten = try trie.write(stream.writer()); | | |
| 3222 | assert(nwritten == trie.size); | | |
| 3223 | | | |
| 3224 | const seg = &self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment; | | |
| 3225 | const dyld_info = &self.load_commands.items[self.dyld_info_cmd_index.?].DyldInfoOnly; | | |
| 3226 | dyld_info.export_off = @intCast(u32, seg.inner.fileoff + seg.inner.filesize); | | |
| 3227 | dyld_info.export_size = @intCast(u32, mem.alignForwardGeneric(u64, buffer.len, @alignOf(u64))); | | |
| 3228 | seg.inner.filesize += dyld_info.export_size; | | |
| 3229 | | | |
| 3230 | log.debug("writing export info from 0x{x} to 0x{x}", .{ dyld_info.export_off, dyld_info.export_off + dyld_info.export_size }); | | |
| 3231 | | | |
| 3232 | try self.base.file.?.pwriteAll(buffer, dyld_info.export_off); | | |
| 3233 | } | | |
| 3234 | | | |
| 3235 | fn writeSymbolTable(self: *MachO) !void { | | |
| 3236 | const seg = &self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment; | | |
| 3237 | const symtab = &self.load_commands.items[self.symtab_cmd_index.?].Symtab; | | |
| 3238 | | | |
| 3239 | var locals = std.ArrayList(macho.nlist_64).init(self.base.allocator); | | |
| 3240 | defer locals.deinit(); | | |
| 3241 | try locals.appendSlice(self.locals.items); | | |
| 3242 | | | |
| 3243 | if (self.has_stabs) { | | |
| 3244 | for (self.objects.items) |object| { | | |
| 3245 | if (object.debug_info == null) continue; | | |
| 3246 | | | |
| 3247 | // Open scope | | |
| 3248 | try locals.ensureUnusedCapacity(3); | | |
| 3249 | locals.appendAssumeCapacity(.{ | | |
| 3250 | .n_strx = try self.makeString(object.tu_comp_dir.?), | | |
| 3251 | .n_type = macho.N_SO, | | |
| 3252 | .n_sect = 0, | | |
| 3253 | .n_desc = 0, | | |
| 3254 | .n_value = 0, | | |
| 3255 | }); | | |
| 3256 | locals.appendAssumeCapacity(.{ | | |
| 3257 | .n_strx = try self.makeString(object.tu_name.?), | | |
| 3258 | .n_type = macho.N_SO, | | |
| 3259 | .n_sect = 0, | | |
| 3260 | .n_desc = 0, | | |
| 3261 | .n_value = 0, | | |
| 3262 | }); | | |
| 3263 | locals.appendAssumeCapacity(.{ | | |
| 3264 | .n_strx = try self.makeString(object.name), | | |
| 3265 | .n_type = macho.N_OSO, | | |
| 3266 | .n_sect = 0, | | |
| 3267 | .n_desc = 1, | | |
| 3268 | .n_value = object.mtime orelse 0, | | |
| 3269 | }); | | |
| 3270 | | | |
| 3271 | for (object.text_blocks.items) |block| { | | |
| 3272 | if (block.stab) |stab| { | | |
| 3273 | const nlists = try stab.asNlists(block.local_sym_index, self); | | |
| 3274 | defer self.base.allocator.free(nlists); | | |
| 3275 | try locals.appendSlice(nlists); | | |
| 3276 | } else { | | |
| 3277 | for (block.contained.items) |sym_at_off| { | | |
| 3278 | const stab = sym_at_off.stab orelse continue; | | |
| 3279 | const nlists = try stab.asNlists(sym_at_off.local_sym_index, self); | | |
| 3280 | defer self.base.allocator.free(nlists); | | |
| 3281 | try locals.appendSlice(nlists); | | |
| 3282 | } | | |
| 3283 | } | | |
| 3284 | } | | |
| 3285 | | | |
| 3286 | // Close scope | | |
| 3287 | try locals.append(.{ | | |
| 3288 | .n_strx = 0, | | |
| 3289 | .n_type = macho.N_SO, | | |
| 3290 | .n_sect = 0, | | |
| 3291 | .n_desc = 0, | | |
| 3292 | .n_value = 0, | | |
| 3293 | }); | | |
| 3294 | } | | |
| 3295 | } | | |
| 3296 | | | |
| 3297 | const nlocals = locals.items.len; | | |
| 3298 | const nexports = self.globals.items.len; | | |
| 3299 | const nundefs = self.undefs.items.len; | | |
| 3300 | | | |
| 3301 | const locals_off = symtab.symoff; | | |
| 3302 | const locals_size = nlocals * @sizeOf(macho.nlist_64); | | |
| 3303 | log.debug("writing local symbols from 0x{x} to 0x{x}", .{ locals_off, locals_size + locals_off }); | | |
| 3304 | try self.base.file.?.pwriteAll(mem.sliceAsBytes(locals.items), locals_off); | | |
| 3305 | | | |
| 3306 | const exports_off = locals_off + locals_size; | | |
| 3307 | const exports_size = nexports * @sizeOf(macho.nlist_64); | | |
| 3308 | log.debug("writing exported symbols from 0x{x} to 0x{x}", .{ exports_off, exports_size + exports_off }); | | |
| 3309 | try self.base.file.?.pwriteAll(mem.sliceAsBytes(self.globals.items), exports_off); | | |
| 3310 | | | |
| 3311 | const undefs_off = exports_off + exports_size; | | |
| 3312 | const undefs_size = nundefs * @sizeOf(macho.nlist_64); | | |
| 3313 | log.debug("writing undefined symbols from 0x{x} to 0x{x}", .{ undefs_off, undefs_size + undefs_off }); | | |
| 3314 | try self.base.file.?.pwriteAll(mem.sliceAsBytes(self.undefs.items), undefs_off); | | |
| 3315 | | | |
| 3316 | symtab.nsyms = @intCast(u32, nlocals + nexports + nundefs); | | |
| 3317 | seg.inner.filesize += locals_size + exports_size + undefs_size; | | |
| 3318 | | | |
| 3319 | // Update dynamic symbol table. | | |
| 3320 | const dysymtab = &self.load_commands.items[self.dysymtab_cmd_index.?].Dysymtab; | | |
| 3321 | dysymtab.nlocalsym = @intCast(u32, nlocals); | | |
| 3322 | dysymtab.iextdefsym = dysymtab.nlocalsym; | | |
| 3323 | dysymtab.nextdefsym = @intCast(u32, nexports); | | |
| 3324 | dysymtab.iundefsym = dysymtab.nlocalsym + dysymtab.nextdefsym; | | |
| 3325 | dysymtab.nundefsym = @intCast(u32, nundefs); | | |
| 3326 | | | |
| 3327 | const text_segment = &self.load_commands.items[self.text_segment_cmd_index.?].Segment; | | |
| 3328 | const stubs = &text_segment.sections.items[self.stubs_section_index.?]; | | |
| 3329 | const data_const_segment = &self.load_commands.items[self.data_const_segment_cmd_index.?].Segment; | | |
| 3330 | const got = &data_const_segment.sections.items[self.got_section_index.?]; | | |
| 3331 | const data_segment = &self.load_commands.items[self.data_segment_cmd_index.?].Segment; | | |
| 3332 | const la_symbol_ptr = &data_segment.sections.items[self.la_symbol_ptr_section_index.?]; | | |
| 3333 | | | |
| 3334 | const nstubs = @intCast(u32, self.stubs_map.keys().len); | | |
| 3335 | const ngot_entries = @intCast(u32, self.got_entries_map.keys().len); | | |
| 3336 | | | |
| 3337 | dysymtab.indirectsymoff = @intCast(u32, seg.inner.fileoff + seg.inner.filesize); | | |
| 3338 | dysymtab.nindirectsyms = nstubs * 2 + ngot_entries; | | |
| 3339 | | | |
| 3340 | const needed_size = dysymtab.nindirectsyms * @sizeOf(u32); | | |
| 3341 | seg.inner.filesize += needed_size; | | |
| 3342 | | | |
| 3343 | log.debug("writing indirect symbol table from 0x{x} to 0x{x}", .{ | | |
| 3344 | dysymtab.indirectsymoff, | | |
| 3345 | dysymtab.indirectsymoff + needed_size, | | |
| 3346 | }); | | |
| 3347 | | | |
| 3348 | var buf = try self.base.allocator.alloc(u8, needed_size); | | |
| 3349 | defer self.base.allocator.free(buf); | | |
| 3350 | | | |
| 3351 | var stream = std.io.fixedBufferStream(buf); | | |
| 3352 | var writer = stream.writer(); | | |
| 3353 | | | |
| 3354 | stubs.reserved1 = 0; | | |
| 3355 | for (self.stubs_map.keys()) |key| { | | |
| 3356 | try writer.writeIntLittle(u32, dysymtab.iundefsym + key); | | |
| 3357 | } | | |
| 3358 | | | |
| 3359 | got.reserved1 = nstubs; | | |
| 3360 | for (self.got_entries_map.keys()) |key| { | | |
| 3361 | switch (key.where) { | | |
| 3362 | .undef => { | | |
| 3363 | try writer.writeIntLittle(u32, dysymtab.iundefsym + key.where_index); | | |
| 3364 | }, | | |
| 3365 | .local => { | | |
| 3366 | try writer.writeIntLittle(u32, macho.INDIRECT_SYMBOL_LOCAL); | | |
| 3367 | }, | | |
| 3368 | } | | |
| 3369 | } | | |
| 3370 | | | |
| 3371 | la_symbol_ptr.reserved1 = got.reserved1 + ngot_entries; | | |
| 3372 | for (self.stubs_map.keys()) |key| { | | |
| 3373 | try writer.writeIntLittle(u32, dysymtab.iundefsym + key); | | |
| 3374 | } | | |
| 3375 | | | |
| 3376 | try self.base.file.?.pwriteAll(buf, dysymtab.indirectsymoff); | | |
| 3377 | } | | |
| 3378 | | | |
| 3379 | pub fn deinit(self: *MachO) void { | 2761 | pub fn deinit(self: *MachO) void { |
| 3380 | if (build_options.have_llvm) { | 2762 | if (build_options.have_llvm) { |
| 3381 | if (self.llvm_object) |llvm_object| llvm_object.destroy(self.base.allocator); | 2763 | if (self.llvm_object) |llvm_object| llvm_object.destroy(self.base.allocator); |
| ... | @@ -3812,12 +3194,6 @@ fn placeDecl(self: *MachO, decl: *Module.Decl, code_len: usize) !*macho.nlist_64 | ... | @@ -3812,12 +3194,6 @@ fn placeDecl(self: *MachO, decl: *Module.Decl, code_len: usize) !*macho.nlist_64 |
| 3812 | try ds.writeLocalSymbol(decl.link.macho.local_sym_index); | 3194 | try ds.writeLocalSymbol(decl.link.macho.local_sym_index); |
| 3813 | } | 3195 | } |
| 3814 | | 3196 | |
| 3815 | // // Resolve relocations | | |
| 3816 | // try decl.link.macho.resolveRelocs(self); | | |
| 3817 | // // TODO this requires further investigation: should we dispose of resolved relocs, or keep them | | |
| 3818 | // // so that we can reapply them when moving/growing sections? | | |
| 3819 | // decl.link.macho.relocs.clearAndFree(self.base.allocator); | | |
| 3820 | | | |
| 3821 | return symbol; | 3197 | return symbol; |
| 3822 | } | 3198 | } |
| 3823 | | 3199 | |
| ... | @@ -5003,9 +4379,8 @@ fn writeIndirectSymbolTable(self: *MachO) !void { | ... | @@ -5003,9 +4379,8 @@ fn writeIndirectSymbolTable(self: *MachO) !void { |
| 5003 | fn writeDices(self: *MachO) !void { | 4379 | fn writeDices(self: *MachO) !void { |
| 5004 | if (!self.has_dices) return; | 4380 | if (!self.has_dices) return; |
| 5005 | | 4381 | |
| 5006 | const seg = &self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment; | 4382 | const tracy = trace(@src()); |
| 5007 | const dice_cmd = &self.load_commands.items[self.data_in_code_cmd_index.?].LinkeditData; | 4383 | defer tracy.end(); |
| 5008 | const fileoff = seg.inner.fileoff + seg.inner.filesize; | | |
| 5009 | | 4384 | |
| 5010 | var buf = std.ArrayList(u8).init(self.base.allocator); | 4385 | var buf = std.ArrayList(u8).init(self.base.allocator); |
| 5011 | defer buf.deinit(); | 4386 | defer buf.deinit(); |
| ... | @@ -5043,15 +4418,26 @@ fn writeDices(self: *MachO) !void { | ... | @@ -5043,15 +4418,26 @@ fn writeDices(self: *MachO) !void { |
| 5043 | } else break; | 4418 | } else break; |
| 5044 | } | 4419 | } |
| 5045 | | 4420 | |
| 5046 | const datasize = @intCast(u32, buf.items.len); | 4421 | const dice_cmd = &self.load_commands.items[self.data_in_code_cmd_index.?].LinkeditData; |
| 5047 | | 4422 | const allocated_size = self.allocatedSizeLinkedit(dice_cmd.dataoff); |
| 5048 | dice_cmd.dataoff = @intCast(u32, fileoff); | 4423 | const needed_size = @intCast(u32, buf.items.len); |
| 5049 | dice_cmd.datasize = datasize; | | |
| 5050 | seg.inner.filesize += datasize; | | |
| 5051 | | 4424 | |
| 5052 | log.debug("writing data-in-code from 0x{x} to 0x{x}", .{ fileoff, fileoff + datasize }); | 4425 | if (needed_size > allocated_size) { |
| | 4426 | dice_cmd.datasize = 0; |
| | 4427 | dice_cmd.dataoff = @intCast(u32, self.findFreeSpaceLinkedit( |
| | 4428 | needed_size, |
| | 4429 | @alignOf(macho.data_in_code_entry), |
| | 4430 | dice_cmd.dataoff, |
| | 4431 | )); |
| | 4432 | } |
| | 4433 | dice_cmd.datasize = needed_size; |
| | 4434 | log.debug("writing data-in-code from 0x{x} to 0x{x}", .{ |
| | 4435 | dice_cmd.dataoff, |
| | 4436 | dice_cmd.dataoff + dice_cmd.datasize, |
| | 4437 | }); |
| 5053 | | 4438 | |
| 5054 | try self.base.file.?.pwriteAll(buf.items, fileoff); | 4439 | try self.base.file.?.pwriteAll(buf.items, dice_cmd.dataoff); |
| | 4440 | self.load_commands_dirty = true; |
| 5055 | } | 4441 | } |
| 5056 | | 4442 | |
| 5057 | fn writeCodeSignaturePadding(self: *MachO) !void { | 4443 | fn writeCodeSignaturePadding(self: *MachO) !void { |
| ... | @@ -5130,7 +4516,7 @@ fn writeExportInfo(self: *MachO) !void { | ... | @@ -5130,7 +4516,7 @@ fn writeExportInfo(self: *MachO) !void { |
| 5130 | | 4516 | |
| 5131 | for (self.globals.items) |sym| { | 4517 | for (self.globals.items) |sym| { |
| 5132 | const sym_name = self.getString(sym.n_strx); | 4518 | const sym_name = self.getString(sym.n_strx); |
| 5133 | log.debug(" | putting '{s}' defined at 0x{x}", .{ sym_name, sym.n_value }); | 4519 | log.debug(" (putting '{s}' defined at 0x{x})", .{ sym_name, sym.n_value }); |
| 5134 | | 4520 | |
| 5135 | try trie.put(self.base.allocator, .{ | 4521 | try trie.put(self.base.allocator, .{ |
| 5136 | .name = sym_name, | 4522 | .name = sym_name, |
| ... | @@ -5453,30 +4839,16 @@ fn writeStringTable(self: *MachO) !void { | ... | @@ -5453,30 +4839,16 @@ fn writeStringTable(self: *MachO) !void { |
| 5453 | self.strtab_needs_relocation = false; | 4839 | self.strtab_needs_relocation = false; |
| 5454 | } | 4840 | } |
| 5455 | symtab.strsize = @intCast(u32, needed_size); | 4841 | symtab.strsize = @intCast(u32, needed_size); |
| 5456 | log.debug("writing string table from 0x{x} to 0x{x}", .{ symtab.stroff, symtab.stroff + symtab.strsize }); | 4842 | log.debug("writing string table from 0x{x} to 0x{x}", .{ |
| | 4843 | symtab.stroff, |
| | 4844 | symtab.stroff + symtab.strsize, |
| | 4845 | }); |
| 5457 | | 4846 | |
| 5458 | try self.base.file.?.pwriteAll(self.strtab.items, symtab.stroff); | 4847 | try self.base.file.?.pwriteAll(self.strtab.items, symtab.stroff); |
| 5459 | self.load_commands_dirty = true; | 4848 | self.load_commands_dirty = true; |
| 5460 | self.strtab_dirty = false; | 4849 | self.strtab_dirty = false; |
| 5461 | } | 4850 | } |
| 5462 | | 4851 | |
| 5463 | fn writeStringTableZld(self: *MachO) !void { | | |
| 5464 | const seg = &self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment; | | |
| 5465 | const symtab = &self.load_commands.items[self.symtab_cmd_index.?].Symtab; | | |
| 5466 | symtab.stroff = @intCast(u32, seg.inner.fileoff + seg.inner.filesize); | | |
| 5467 | symtab.strsize = @intCast(u32, mem.alignForwardGeneric(u64, self.strtab.items.len, @alignOf(u64))); | | |
| 5468 | seg.inner.filesize += symtab.strsize; | | |
| 5469 | | | |
| 5470 | log.debug("writing string table from 0x{x} to 0x{x}", .{ symtab.stroff, symtab.stroff + symtab.strsize }); | | |
| 5471 | | | |
| 5472 | try self.base.file.?.pwriteAll(self.strtab.items, symtab.stroff); | | |
| 5473 | | | |
| 5474 | if (symtab.strsize > self.strtab.items.len) { | | |
| 5475 | // This is potentially the last section, so we need to pad it out. | | |
| 5476 | try self.base.file.?.pwriteAll(&[_]u8{0}, seg.inner.fileoff + seg.inner.filesize - 1); | | |
| 5477 | } | | |
| 5478 | } | | |
| 5479 | | | |
| 5480 | fn updateLinkeditSegmentSizes(self: *MachO) !void { | 4852 | fn updateLinkeditSegmentSizes(self: *MachO) !void { |
| 5481 | if (!self.load_commands_dirty) return; | 4853 | if (!self.load_commands_dirty) return; |
| 5482 | | 4854 | |