authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-08-01 18:42:18+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-08-03 21:19:41+02:00
log7bba3d330ad90026e8b79cae9940a1e878628119
tree817665887546a5b1a568206c951d6c3e900de1f0
parentbb532584bc569edb563b757c658fd743731837ec

macho: cleanup output section selection logic

Cache only section indexes used by the linker for synthetic sections and/or incremental codepath.

2 files changed, 154 insertions(+), 477 deletions(-)

src/link/MachO.zig+151-475
...@@ -121,48 +121,12 @@ data_const_segment_cmd_index: ?u8 = null,...@@ -121,48 +121,12 @@ data_const_segment_cmd_index: ?u8 = null,
121data_segment_cmd_index: ?u8 = null,121data_segment_cmd_index: ?u8 = null,
122linkedit_segment_cmd_index: ?u8 = null,122linkedit_segment_cmd_index: ?u8 = null,
123123
124// __TEXT segment sections
125text_section_index: ?u8 = null,124text_section_index: ?u8 = null,
126stubs_section_index: ?u8 = null,125stubs_section_index: ?u8 = null,
127stub_helper_section_index: ?u8 = null,126stub_helper_section_index: ?u8 = null,
128text_const_section_index: ?u8 = null,
129cstring_section_index: ?u8 = null,
130ustring_section_index: ?u8 = null,
131gcc_except_tab_section_index: ?u8 = null,
132unwind_info_section_index: ?u8 = null,
133eh_frame_section_index: ?u8 = null,
134
135objc_methlist_section_index: ?u8 = null,
136objc_methname_section_index: ?u8 = null,
137objc_methtype_section_index: ?u8 = null,
138objc_classname_section_index: ?u8 = null,
139
140// __DATA_CONST segment sections
141got_section_index: ?u8 = null,127got_section_index: ?u8 = null,
142mod_init_func_section_index: ?u8 = null,
143mod_term_func_section_index: ?u8 = null,
144data_const_section_index: ?u8 = null,
145
146objc_cfstring_section_index: ?u8 = null,
147objc_classlist_section_index: ?u8 = null,
148objc_imageinfo_section_index: ?u8 = null,
149
150// __DATA segment sections
151tlv_section_index: ?u8 = null,
152tlv_data_section_index: ?u8 = null,
153tlv_bss_section_index: ?u8 = null,
154tlv_ptrs_section_index: ?u8 = null,
155la_symbol_ptr_section_index: ?u8 = null,128la_symbol_ptr_section_index: ?u8 = null,
156data_section_index: ?u8 = null,129data_section_index: ?u8 = null,
157bss_section_index: ?u8 = null,
158
159objc_const_section_index: ?u8 = null,
160objc_selrefs_section_index: ?u8 = null,
161objc_classrefs_section_index: ?u8 = null,
162objc_data_section_index: ?u8 = null,
163
164rustc_section_index: ?u8 = null,
165rustc_section_size: u64 = 0,
166130
167locals: std.ArrayListUnmanaged(macho.nlist_64) = .{},131locals: std.ArrayListUnmanaged(macho.nlist_64) = .{},
168globals: std.StringArrayHashMapUnmanaged(SymbolWithLoc) = .{},132globals: std.StringArrayHashMapUnmanaged(SymbolWithLoc) = .{},
...@@ -547,14 +511,15 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No...@@ -547,14 +511,15 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No
547511
548 try self.createMhExecuteHeaderSymbol();512 try self.createMhExecuteHeaderSymbol();
549 try self.resolveDyldStubBinder();513 try self.resolveDyldStubBinder();
550 try self.createDyldPrivateAtom();
551 try self.createStubHelperPreambleAtom();
552 try self.resolveSymbolsInDylibs();514 try self.resolveSymbolsInDylibs();
553515
554 if (self.unresolved.count() > 0) {516 if (self.unresolved.count() > 0) {
555 return error.UndefinedSymbolReference;517 return error.UndefinedSymbolReference;
556 }518 }
557519
520 try self.createDyldPrivateAtom();
521 try self.createStubHelperPreambleAtom();
522
558 try self.allocateSpecialSymbols();523 try self.allocateSpecialSymbols();
559524
560 if (build_options.enable_logging) {525 if (build_options.enable_logging) {
...@@ -1140,7 +1105,6 @@ fn linkOneShot(self: *MachO, comp: *Compilation, prog_node: *std.Progress.Node)...@@ -1140,7 +1105,6 @@ fn linkOneShot(self: *MachO, comp: *Compilation, prog_node: *std.Progress.Node)
11401105
1141 try self.resolveSymbolsInArchives();1106 try self.resolveSymbolsInArchives();
1142 try self.resolveDyldStubBinder();1107 try self.resolveDyldStubBinder();
1143 try self.createDyldPrivateAtom();
1144 try self.resolveSymbolsInDylibs();1108 try self.resolveSymbolsInDylibs();
1145 try self.createMhExecuteHeaderSymbol();1109 try self.createMhExecuteHeaderSymbol();
1146 try self.createDsoHandleSymbol();1110 try self.createDsoHandleSymbol();
...@@ -1160,8 +1124,9 @@ fn linkOneShot(self: *MachO, comp: *Compilation, prog_node: *std.Progress.Node)...@@ -1160,8 +1124,9 @@ fn linkOneShot(self: *MachO, comp: *Compilation, prog_node: *std.Progress.Node)
1160 try object.scanInputSections(self);1124 try object.scanInputSections(self);
1161 }1125 }
11621126
1163 try self.createStubHelperPreambleAtom();1127 try self.createDyldPrivateAtom();
1164 try self.createTentativeDefAtoms();1128 try self.createTentativeDefAtoms();
1129 try self.createStubHelperPreambleAtom();
11651130
1166 for (self.objects.items) |*object, object_id| {1131 for (self.objects.items) |*object, object_id| {
1167 try object.splitIntoAtomsOneShot(self, @intCast(u32, object_id));1132 try object.splitIntoAtomsOneShot(self, @intCast(u32, object_id));
...@@ -1184,11 +1149,6 @@ fn linkOneShot(self: *MachO, comp: *Compilation, prog_node: *std.Progress.Node)...@@ -1184,11 +1149,6 @@ fn linkOneShot(self: *MachO, comp: *Compilation, prog_node: *std.Progress.Node)
11841149
1185 try self.writeAtomsOneShot();1150 try self.writeAtomsOneShot();
11861151
1187 if (self.rustc_section_index) |id| {
1188 const header = &self.sections.items(.header)[id];
1189 header.size = self.rustc_section_size;
1190 }
1191
1192 var lc_buffer = std.ArrayList(u8).init(arena);1152 var lc_buffer = std.ArrayList(u8).init(arena);
1193 const lc_writer = lc_buffer.writer();1153 const lc_writer = lc_buffer.writer();
1194 var ncmds: u32 = 0;1154 var ncmds: u32 = 0;
...@@ -1696,417 +1656,142 @@ pub fn getOutputSection(self: *MachO, sect: macho.section_64) !?u8 {...@@ -1696,417 +1656,142 @@ pub fn getOutputSection(self: *MachO, sect: macho.section_64) !?u8 {
1696 const segname = sect.segName();1656 const segname = sect.segName();
1697 const sectname = sect.sectName();1657 const sectname = sect.sectName();
1698 const res: ?u8 = blk: {1658 const res: ?u8 = blk: {
1659 if (mem.eql(u8, "__LLVM", segname)) {
1660 log.debug("TODO LLVM section: type 0x{x}, name '{s},{s}'", .{
1661 sect.flags, segname, sectname,
1662 });
1663 break :blk null;
1664 }
1665
1666 if (sect.isCode()) {
1667 if (self.text_section_index == null) {
1668 self.text_section_index = try self.initSection(
1669 "__TEXT",
1670 "__text",
1671 sect.size,
1672 sect.@"align",
1673 .{
1674 .flags = macho.S_REGULAR |
1675 macho.S_ATTR_PURE_INSTRUCTIONS |
1676 macho.S_ATTR_SOME_INSTRUCTIONS,
1677 },
1678 );
1679 }
1680 break :blk self.text_section_index.?;
1681 }
1682
1683 if (sect.isDebug()) {
1684 // TODO debug attributes
1685 if (mem.eql(u8, "__LD", segname) and mem.eql(u8, "__compact_unwind", sectname)) {
1686 log.debug("TODO compact unwind section: type 0x{x}, name '{s},{s}'", .{
1687 sect.flags, segname, sectname,
1688 });
1689 }
1690 break :blk null;
1691 }
1692
1699 switch (sect.@"type"()) {1693 switch (sect.@"type"()) {
1700 macho.S_4BYTE_LITERALS, macho.S_8BYTE_LITERALS, macho.S_16BYTE_LITERALS => {1694 macho.S_4BYTE_LITERALS,
1701 if (self.text_const_section_index == null) {1695 macho.S_8BYTE_LITERALS,
1702 self.text_const_section_index = try self.initSection(1696 macho.S_16BYTE_LITERALS,
1703 self.text_segment_cmd_index.?,1697 => {
1704 "__const",1698 break :blk self.getSectionByName("__TEXT", "__const") orelse try self.initSection(
1705 sect.size,1699 "__TEXT",
1706 sect.@"align",1700 "__const",
1707 .{},1701 sect.size,
1708 );1702 sect.@"align",
1709 }1703 .{},
1710 break :blk self.text_const_section_index.?;1704 );
1711 },1705 },
1712 macho.S_CSTRING_LITERALS => {1706 macho.S_CSTRING_LITERALS => {
1713 if (mem.eql(u8, sectname, "__objc_methname")) {1707 if (mem.startsWith(u8, sectname, "__objc")) {
1714 // TODO it seems the common values within the sections in objects are deduplicated/merged1708 break :blk self.getSectionByName(segname, sectname) orelse try self.initSection(
1715 // on merging the sections' contents.1709 segname,
1716 if (self.objc_methname_section_index == null) {1710 sectname,
1717 self.objc_methname_section_index = try self.initSection(
1718 self.text_segment_cmd_index.?,
1719 "__objc_methname",
1720 sect.size,
1721 sect.@"align",
1722 .{},
1723 );
1724 }
1725 break :blk self.objc_methname_section_index.?;
1726 } else if (mem.eql(u8, sectname, "__objc_methtype")) {
1727 if (self.objc_methtype_section_index == null) {
1728 self.objc_methtype_section_index = try self.initSection(
1729 self.text_segment_cmd_index.?,
1730 "__objc_methtype",
1731 sect.size,
1732 sect.@"align",
1733 .{},
1734 );
1735 }
1736 break :blk self.objc_methtype_section_index.?;
1737 } else if (mem.eql(u8, sectname, "__objc_classname")) {
1738 if (self.objc_classname_section_index == null) {
1739 self.objc_classname_section_index = try self.initSection(
1740 self.text_segment_cmd_index.?,
1741 "__objc_classname",
1742 sect.size,
1743 sect.@"align",
1744 .{},
1745 );
1746 }
1747 break :blk self.objc_classname_section_index.?;
1748 }
1749
1750 if (self.cstring_section_index == null) {
1751 self.cstring_section_index = try self.initSection(
1752 self.text_segment_cmd_index.?,
1753 "__cstring",
1754 sect.size,1711 sect.size,
1755 sect.@"align",1712 sect.@"align",
1756 .{1713 .{},
1757 .flags = macho.S_CSTRING_LITERALS,
1758 },
1759 );
1760 }
1761 break :blk self.cstring_section_index.?;
1762 },
1763 macho.S_LITERAL_POINTERS => {
1764 if (mem.eql(u8, segname, "__DATA") and mem.eql(u8, sectname, "__objc_selrefs")) {
1765 if (self.objc_selrefs_section_index == null) {
1766 self.objc_selrefs_section_index = try self.initSection(
1767 self.data_segment_cmd_index.?,
1768 "__objc_selrefs",
1769 sect.size,
1770 sect.@"align",
1771 .{
1772 .flags = macho.S_LITERAL_POINTERS,
1773 },
1774 );
1775 }
1776 break :blk self.objc_selrefs_section_index.?;
1777 } else {
1778 // TODO investigate
1779 break :blk null;
1780 }
1781 },
1782 macho.S_MOD_INIT_FUNC_POINTERS => {
1783 if (self.mod_init_func_section_index == null) {
1784 self.mod_init_func_section_index = try self.initSection(
1785 self.data_const_segment_cmd_index.?,
1786 "__mod_init_func",
1787 sect.size,
1788 sect.@"align",
1789 .{
1790 .flags = macho.S_MOD_INIT_FUNC_POINTERS,
1791 },
1792 );
1793 }
1794 break :blk self.mod_init_func_section_index.?;
1795 },
1796 macho.S_MOD_TERM_FUNC_POINTERS => {
1797 if (self.mod_term_func_section_index == null) {
1798 self.mod_term_func_section_index = try self.initSection(
1799 self.data_const_segment_cmd_index.?,
1800 "__mod_term_func",
1801 sect.size,
1802 sect.@"align",
1803 .{
1804 .flags = macho.S_MOD_TERM_FUNC_POINTERS,
1805 },
1806 );
1807 }
1808 break :blk self.mod_term_func_section_index.?;
1809 },
1810 macho.S_ZEROFILL => {
1811 if (self.bss_section_index == null) {
1812 self.bss_section_index = try self.initSection(
1813 self.data_segment_cmd_index.?,
1814 "__bss",
1815 sect.size,
1816 sect.@"align",
1817 .{
1818 .flags = macho.S_ZEROFILL,
1819 },
1820 );
1821 }
1822 break :blk self.bss_section_index.?;
1823 },
1824 macho.S_THREAD_LOCAL_VARIABLES => {
1825 if (self.tlv_section_index == null) {
1826 self.tlv_section_index = try self.initSection(
1827 self.data_segment_cmd_index.?,
1828 "__thread_vars",
1829 sect.size,
1830 sect.@"align",
1831 .{
1832 .flags = macho.S_THREAD_LOCAL_VARIABLES,
1833 },
1834 );
1835 }
1836 break :blk self.tlv_section_index.?;
1837 },
1838 macho.S_THREAD_LOCAL_VARIABLE_POINTERS => {
1839 if (self.tlv_ptrs_section_index == null) {
1840 self.tlv_ptrs_section_index = try self.initSection(
1841 self.data_segment_cmd_index.?,
1842 "__thread_ptrs",
1843 sect.size,
1844 sect.@"align",
1845 .{
1846 .flags = macho.S_THREAD_LOCAL_VARIABLE_POINTERS,
1847 },
1848 );1714 );
1849 }1715 }
1850 break :blk self.tlv_ptrs_section_index.?;1716 break :blk self.getSectionByName("__TEXT", "__cstring") orelse try self.initSection(
1717 "__TEXT",
1718 "__cstring",
1719 sect.size,
1720 sect.@"align",
1721 .{ .flags = macho.S_CSTRING_LITERALS },
1722 );
1851 },1723 },
1852 macho.S_THREAD_LOCAL_REGULAR => {1724 macho.S_MOD_INIT_FUNC_POINTERS,
1853 if (self.tlv_data_section_index == null) {1725 macho.S_MOD_TERM_FUNC_POINTERS,
1854 self.tlv_data_section_index = try self.initSection(1726 => {
1855 self.data_segment_cmd_index.?,1727 break :blk self.getSectionByName("__DATA_CONST", sectname) orelse try self.initSection(
1856 "__thread_data",1728 "__DATA_CONST",
1857 sect.size,1729 sectname,
1858 sect.@"align",1730 sect.size,
1859 .{1731 sect.@"align",
1860 .flags = macho.S_THREAD_LOCAL_REGULAR,1732 .{ .flags = sect.flags },
1861 },1733 );
1862 );
1863 }
1864 break :blk self.tlv_data_section_index.?;
1865 },1734 },
1866 macho.S_THREAD_LOCAL_ZEROFILL => {1735 macho.S_LITERAL_POINTERS,
1867 if (self.tlv_bss_section_index == null) {1736 macho.S_ZEROFILL,
1868 self.tlv_bss_section_index = try self.initSection(1737 macho.S_THREAD_LOCAL_VARIABLES,
1869 self.data_segment_cmd_index.?,1738 macho.S_THREAD_LOCAL_VARIABLE_POINTERS,
1870 "__thread_bss",1739 macho.S_THREAD_LOCAL_REGULAR,
1871 sect.size,1740 macho.S_THREAD_LOCAL_ZEROFILL,
1872 sect.@"align",1741 => {
1873 .{1742 break :blk self.getSectionByName(segname, sectname) orelse try self.initSection(
1874 .flags = macho.S_THREAD_LOCAL_ZEROFILL,1743 segname,
1875 },1744 sectname,
1876 );1745 sect.size,
1877 }1746 sect.@"align",
1878 break :blk self.tlv_bss_section_index.?;1747 .{ .flags = sect.flags },
1748 );
1879 },1749 },
1880 macho.S_COALESCED => {1750 macho.S_COALESCED => {
1881 if (mem.eql(u8, "__TEXT", segname) and mem.eql(u8, "__eh_frame", sectname)) {1751 break :blk self.getSectionByName(segname, sectname) orelse try self.initSection(
1882 // TODO I believe __eh_frame is currently part of __unwind_info section1752 segname,
1883 // in the latest ld64 output.1753 sectname,
1884 if (self.eh_frame_section_index == null) {1754 sect.size,
1885 self.eh_frame_section_index = try self.initSection(1755 sect.@"align",
1886 self.text_segment_cmd_index.?,1756 .{},
1887 "__eh_frame",1757 );
1888 sect.size,
1889 sect.@"align",
1890 .{},
1891 );
1892 }
1893 break :blk self.eh_frame_section_index.?;
1894 }
1895
1896 // TODO audit this: is this the right mapping?
1897 if (self.data_const_section_index == null) {
1898 self.data_const_section_index = try self.initSection(
1899 self.data_const_segment_cmd_index.?,
1900 "__const",
1901 sect.size,
1902 sect.@"align",
1903 .{},
1904 );
1905 }
1906
1907 break :blk self.data_const_section_index.?;
1908 },1758 },
1909 macho.S_REGULAR => {1759 macho.S_REGULAR => {
1910 if (sect.isCode()) {
1911 if (self.text_section_index == null) {
1912 self.text_section_index = try self.initSection(
1913 self.text_segment_cmd_index.?,
1914 "__text",
1915 sect.size,
1916 sect.@"align",
1917 .{
1918 .flags = macho.S_REGULAR |
1919 macho.S_ATTR_PURE_INSTRUCTIONS |
1920 macho.S_ATTR_SOME_INSTRUCTIONS,
1921 },
1922 );
1923 }
1924 break :blk self.text_section_index.?;
1925 }
1926 if (sect.isDebug()) {
1927 // TODO debug attributes
1928 if (mem.eql(u8, "__LD", segname) and mem.eql(u8, "__compact_unwind", sectname)) {
1929 log.debug("TODO compact unwind section: type 0x{x}, name '{s},{s}'", .{
1930 sect.flags, segname, sectname,
1931 });
1932 }
1933 break :blk null;
1934 }
1935
1936 if (mem.eql(u8, segname, "__TEXT")) {1760 if (mem.eql(u8, segname, "__TEXT")) {
1937 if (mem.eql(u8, sectname, "__ustring")) {1761 if (mem.eql(u8, sectname, "__rodata") or
1938 if (self.ustring_section_index == null) {
1939 self.ustring_section_index = try self.initSection(
1940 self.text_segment_cmd_index.?,
1941 "__ustring",
1942 sect.size,
1943 sect.@"align",
1944 .{},
1945 );
1946 }
1947 break :blk self.ustring_section_index.?;
1948 } else if (mem.eql(u8, sectname, "__gcc_except_tab")) {
1949 if (self.gcc_except_tab_section_index == null) {
1950 self.gcc_except_tab_section_index = try self.initSection(
1951 self.text_segment_cmd_index.?,
1952 "__gcc_except_tab",
1953 sect.size,
1954 sect.@"align",
1955 .{},
1956 );
1957 }
1958 break :blk self.gcc_except_tab_section_index.?;
1959 } else if (mem.eql(u8, sectname, "__objc_methlist")) {
1960 if (self.objc_methlist_section_index == null) {
1961 self.objc_methlist_section_index = try self.initSection(
1962 self.text_segment_cmd_index.?,
1963 "__objc_methlist",
1964 sect.size,
1965 sect.@"align",
1966 .{},
1967 );
1968 }
1969 break :blk self.objc_methlist_section_index.?;
1970 } else if (mem.eql(u8, sectname, "__rodata") or
1971 mem.eql(u8, sectname, "__typelink") or1762 mem.eql(u8, sectname, "__typelink") or
1972 mem.eql(u8, sectname, "__itablink") or1763 mem.eql(u8, sectname, "__itablink") or
1973 mem.eql(u8, sectname, "__gosymtab") or1764 mem.eql(u8, sectname, "__gosymtab") or
1974 mem.eql(u8, sectname, "__gopclntab"))1765 mem.eql(u8, sectname, "__gopclntab"))
1975 {1766 {
1976 if (self.data_const_section_index == null) {1767 break :blk self.getSectionByName("__DATA_CONST", "__const") orelse try self.initSection(
1977 self.data_const_section_index = try self.initSection(1768 "__DATA_CONST",
1978 self.data_const_segment_cmd_index.?,
1979 "__const",
1980 sect.size,
1981 sect.@"align",
1982 .{},
1983 );
1984 }
1985 break :blk self.data_const_section_index.?;
1986 } else {
1987 if (self.text_const_section_index == null) {
1988 self.text_const_section_index = try self.initSection(
1989 self.text_segment_cmd_index.?,
1990 "__const",
1991 sect.size,
1992 sect.@"align",
1993 .{},
1994 );
1995 }
1996 break :blk self.text_const_section_index.?;
1997 }
1998 }
1999
2000 if (mem.eql(u8, segname, "__DATA_CONST")) {
2001 if (self.data_const_section_index == null) {
2002 self.data_const_section_index = try self.initSection(
2003 self.data_const_segment_cmd_index.?,
2004 "__const",1769 "__const",
2005 sect.size,1770 sect.size,
2006 sect.@"align",1771 sect.@"align",
2007 .{},1772 .{},
2008 );1773 );
2009 }1774 }
2010 break :blk self.data_const_section_index.?;
2011 }1775 }
2012
2013 if (mem.eql(u8, segname, "__DATA")) {1776 if (mem.eql(u8, segname, "__DATA")) {
2014 if (mem.eql(u8, sectname, "__const")) {1777 if (mem.eql(u8, sectname, "__const") or
2015 if (self.data_const_section_index == null) {1778 mem.eql(u8, sectname, "__cfstring") or
2016 self.data_const_section_index = try self.initSection(1779 mem.eql(u8, sectname, "__objc_classlist") or
2017 self.data_const_segment_cmd_index.?,1780 mem.eql(u8, sectname, "__objc_imageinfo"))
2018 "__const",1781 {
2019 sect.size,1782 break :blk self.getSectionByName("__DATA_CONST", sectname) orelse
2020 sect.@"align",1783 try self.initSection(
2021 .{},1784 "__DATA_CONST",
2022 );1785 sectname,
2023 }1786 sect.size,
2024 break :blk self.data_const_section_index.?;1787 sect.@"align",
2025 } else if (mem.eql(u8, sectname, "__cfstring")) {1788 .{},
2026 if (self.objc_cfstring_section_index == null) {1789 );
2027 self.objc_cfstring_section_index = try self.initSection(1790 } else if (mem.eql(u8, sectname, "__data")) {
2028 self.data_const_segment_cmd_index.?,
2029 "__cfstring",
2030 sect.size,
2031 sect.@"align",
2032 .{},
2033 );
2034 }
2035 break :blk self.objc_cfstring_section_index.?;
2036 } else if (mem.eql(u8, sectname, "__objc_classlist")) {
2037 if (self.objc_classlist_section_index == null) {
2038 self.objc_classlist_section_index = try self.initSection(
2039 self.data_const_segment_cmd_index.?,
2040 "__objc_classlist",
2041 sect.size,
2042 sect.@"align",
2043 .{},
2044 );
2045 }
2046 break :blk self.objc_classlist_section_index.?;
2047 } else if (mem.eql(u8, sectname, "__objc_imageinfo")) {
2048 if (self.objc_imageinfo_section_index == null) {
2049 self.objc_imageinfo_section_index = try self.initSection(
2050 self.data_const_segment_cmd_index.?,
2051 "__objc_imageinfo",
2052 sect.size,
2053 sect.@"align",
2054 .{},
2055 );
2056 }
2057 break :blk self.objc_imageinfo_section_index.?;
2058 } else if (mem.eql(u8, sectname, "__objc_const")) {
2059 if (self.objc_const_section_index == null) {
2060 self.objc_const_section_index = try self.initSection(
2061 self.data_segment_cmd_index.?,
2062 "__objc_const",
2063 sect.size,
2064 sect.@"align",
2065 .{},
2066 );
2067 }
2068 break :blk self.objc_const_section_index.?;
2069 } else if (mem.eql(u8, sectname, "__objc_classrefs")) {
2070 if (self.objc_classrefs_section_index == null) {
2071 self.objc_classrefs_section_index = try self.initSection(
2072 self.data_segment_cmd_index.?,
2073 "__objc_classrefs",
2074 sect.size,
2075 sect.@"align",
2076 .{},
2077 );
2078 }
2079 break :blk self.objc_classrefs_section_index.?;
2080 } else if (mem.eql(u8, sectname, "__objc_data")) {
2081 if (self.objc_data_section_index == null) {
2082 self.objc_data_section_index = try self.initSection(
2083 self.data_segment_cmd_index.?,
2084 "__objc_data",
2085 sect.size,
2086 sect.@"align",
2087 .{},
2088 );
2089 }
2090 break :blk self.objc_data_section_index.?;
2091 } else if (mem.eql(u8, sectname, ".rustc")) {
2092 if (self.rustc_section_index == null) {
2093 self.rustc_section_index = try self.initSection(
2094 self.data_segment_cmd_index.?,
2095 ".rustc",
2096 sect.size,
2097 sect.@"align",
2098 .{},
2099 );
2100 // We need to preserve the section size for rustc to properly
2101 // decompress the metadata.
2102 self.rustc_section_size = sect.size;
2103 }
2104 break :blk self.rustc_section_index.?;
2105 } else {
2106 if (self.data_section_index == null) {1791 if (self.data_section_index == null) {
2107 self.data_section_index = try self.initSection(1792 self.data_section_index = try self.initSection(
2108 self.data_segment_cmd_index.?,1793 segname,
2109 "__data",1794 sectname,
2110 sect.size,1795 sect.size,
2111 sect.@"align",1796 sect.@"align",
2112 .{},1797 .{},
...@@ -2115,14 +1800,13 @@ pub fn getOutputSection(self: *MachO, sect: macho.section_64) !?u8 {...@@ -2115,14 +1800,13 @@ pub fn getOutputSection(self: *MachO, sect: macho.section_64) !?u8 {
2115 break :blk self.data_section_index.?;1800 break :blk self.data_section_index.?;
2116 }1801 }
2117 }1802 }
21181803 break :blk self.getSectionByName(segname, sectname) orelse try self.initSection(
2119 if (mem.eql(u8, "__LLVM", segname) and mem.eql(u8, "__asm", sectname)) {1804 segname,
2120 log.debug("TODO LLVM asm section: type 0x{x}, name '{s},{s}'", .{1805 sectname,
2121 sect.flags, segname, sectname,1806 sect.size,
2122 });1807 sect.@"align",
2123 }1808 .{},
21241809 );
2125 break :blk null;
2126 },1810 },
2127 else => break :blk null,1811 else => break :blk null,
2128 }1812 }
...@@ -2774,11 +2458,16 @@ fn createTentativeDefAtoms(self: *MachO) !void {...@@ -2774,11 +2458,16 @@ fn createTentativeDefAtoms(self: *MachO) !void {
2774 // text blocks for each tentative definition.2458 // text blocks for each tentative definition.
2775 const size = sym.n_value;2459 const size = sym.n_value;
2776 const alignment = (sym.n_desc >> 8) & 0x0f;2460 const alignment = (sym.n_desc >> 8) & 0x0f;
2461 const n_sect = (try self.getOutputSection(.{
2462 .segname = makeStaticString("__DATA"),
2463 .sectname = makeStaticString("__bss"),
2464 .flags = macho.S_ZEROFILL,
2465 })).?;
27772466
2778 sym.* = .{2467 sym.* = .{
2779 .n_strx = sym.n_strx,2468 .n_strx = sym.n_strx,
2780 .n_type = macho.N_SECT | macho.N_EXT,2469 .n_type = macho.N_SECT | macho.N_EXT,
2781 .n_sect = 0,2470 .n_sect = n_sect,
2782 .n_desc = 0,2471 .n_desc = 0,
2783 .n_value = 0,2472 .n_value = 0,
2784 };2473 };
...@@ -2786,7 +2475,7 @@ fn createTentativeDefAtoms(self: *MachO) !void {...@@ -2786,7 +2475,7 @@ fn createTentativeDefAtoms(self: *MachO) !void {
2786 const atom = try MachO.createEmptyAtom(gpa, global.sym_index, size, alignment);2475 const atom = try MachO.createEmptyAtom(gpa, global.sym_index, size, alignment);
2787 atom.file = global.file;2476 atom.file = global.file;
27882477
2789 try self.allocateAtomCommon(atom, self.bss_section_index.?);2478 try self.allocateAtomCommon(atom, n_sect);
27902479
2791 if (global.file) |file| {2480 if (global.file) |file| {
2792 const object = &self.objects.items[file];2481 const object = &self.objects.items[file];
...@@ -4174,7 +3863,8 @@ pub fn deleteExport(self: *MachO, exp: Export) void {...@@ -4174,7 +3863,8 @@ pub fn deleteExport(self: *MachO, exp: Export) void {
4174fn freeUnnamedConsts(self: *MachO, decl_index: Module.Decl.Index) void {3863fn freeUnnamedConsts(self: *MachO, decl_index: Module.Decl.Index) void {
4175 const unnamed_consts = self.unnamed_const_atoms.getPtr(decl_index) orelse return;3864 const unnamed_consts = self.unnamed_const_atoms.getPtr(decl_index) orelse return;
4176 for (unnamed_consts.items) |atom| {3865 for (unnamed_consts.items) |atom| {
4177 self.freeAtom(atom, self.text_const_section_index.?, true);3866 const sect_id = atom.getSymbol(self).n_sect;
3867 self.freeAtom(atom, sect_id, true);
4178 self.locals_free_list.append(self.base.allocator, atom.sym_index) catch {};3868 self.locals_free_list.append(self.base.allocator, atom.sym_index) catch {};
4179 self.locals.items[atom.sym_index].n_type = 0;3869 self.locals.items[atom.sym_index].n_type = 0;
4180 _ = self.atom_by_index_table.remove(atom.sym_index);3870 _ = self.atom_by_index_table.remove(atom.sym_index);
...@@ -4307,7 +3997,7 @@ fn populateMissingMetadata(self: *MachO) !void {...@@ -4307,7 +3997,7 @@ fn populateMissingMetadata(self: *MachO) !void {
4307 };3997 };
4308 const needed_size = if (self.mode == .incremental) self.base.options.program_code_size_hint else 0;3998 const needed_size = if (self.mode == .incremental) self.base.options.program_code_size_hint else 0;
4309 self.text_section_index = try self.initSection(3999 self.text_section_index = try self.initSection(
4310 self.text_segment_cmd_index.?,4000 "__TEXT",
4311 "__text",4001 "__text",
4312 needed_size,4002 needed_size,
4313 alignment,4003 alignment,
...@@ -4330,7 +4020,7 @@ fn populateMissingMetadata(self: *MachO) !void {...@@ -4330,7 +4020,7 @@ fn populateMissingMetadata(self: *MachO) !void {
4330 };4020 };
4331 const needed_size = if (self.mode == .incremental) stub_size * self.base.options.symbol_count_hint else 0;4021 const needed_size = if (self.mode == .incremental) stub_size * self.base.options.symbol_count_hint else 0;
4332 self.stubs_section_index = try self.initSection(4022 self.stubs_section_index = try self.initSection(
4333 self.text_segment_cmd_index.?,4023 "__TEXT",
4334 "__stubs",4024 "__stubs",
4335 needed_size,4025 needed_size,
4336 alignment,4026 alignment,
...@@ -4362,7 +4052,7 @@ fn populateMissingMetadata(self: *MachO) !void {...@@ -4362,7 +4052,7 @@ fn populateMissingMetadata(self: *MachO) !void {
4362 else4052 else
4363 0;4053 0;
4364 self.stub_helper_section_index = try self.initSection(4054 self.stub_helper_section_index = try self.initSection(
4365 self.text_segment_cmd_index.?,4055 "__TEXT",
4366 "__stub_helper",4056 "__stub_helper",
4367 needed_size,4057 needed_size,
4368 alignment,4058 alignment,
...@@ -4407,7 +4097,7 @@ fn populateMissingMetadata(self: *MachO) !void {...@@ -4407,7 +4097,7 @@ fn populateMissingMetadata(self: *MachO) !void {
4407 0;4097 0;
4408 const alignment: u16 = 3; // 2^3 = @sizeOf(u64)4098 const alignment: u16 = 3; // 2^3 = @sizeOf(u64)
4409 self.got_section_index = try self.initSection(4099 self.got_section_index = try self.initSection(
4410 self.data_const_segment_cmd_index.?,4100 "__DATA_CONST",
4411 "__got",4101 "__got",
4412 needed_size,4102 needed_size,
4413 alignment,4103 alignment,
...@@ -4452,7 +4142,7 @@ fn populateMissingMetadata(self: *MachO) !void {...@@ -4452,7 +4142,7 @@ fn populateMissingMetadata(self: *MachO) !void {
4452 0;4142 0;
4453 const alignment: u16 = 3; // 2^3 = @sizeOf(u64)4143 const alignment: u16 = 3; // 2^3 = @sizeOf(u64)
4454 self.la_symbol_ptr_section_index = try self.initSection(4144 self.la_symbol_ptr_section_index = try self.initSection(
4455 self.data_segment_cmd_index.?,4145 "__DATA",
4456 "__la_symbol_ptr",4146 "__la_symbol_ptr",
4457 needed_size,4147 needed_size,
4458 alignment,4148 alignment,
...@@ -4469,7 +4159,7 @@ fn populateMissingMetadata(self: *MachO) !void {...@@ -4469,7 +4159,7 @@ fn populateMissingMetadata(self: *MachO) !void {
4469 0;4159 0;
4470 const alignment: u16 = 3; // 2^3 = @sizeOf(u64)4160 const alignment: u16 = 3; // 2^3 = @sizeOf(u64)
4471 self.data_section_index = try self.initSection(4161 self.data_section_index = try self.initSection(
4472 self.data_segment_cmd_index.?,4162 "__DATA",
4473 "__data",4163 "__data",
4474 needed_size,4164 needed_size,
4475 alignment,4165 alignment,
...@@ -4701,12 +4391,13 @@ const InitSectionOpts = struct {...@@ -4701,12 +4391,13 @@ const InitSectionOpts = struct {
47014391
4702fn initSection(4392fn initSection(
4703 self: *MachO,4393 self: *MachO,
4704 segment_id: u8,4394 segname: []const u8,
4705 sectname: []const u8,4395 sectname: []const u8,
4706 size: u64,4396 size: u64,
4707 alignment: u32,4397 alignment: u32,
4708 opts: InitSectionOpts,4398 opts: InitSectionOpts,
4709) !u8 {4399) !u8 {
4400 const segment_id = self.getSegmentByName(segname).?;
4710 const seg = &self.segments.items[segment_id];4401 const seg = &self.segments.items[segment_id];
4711 const index = try self.insertSection(segment_id, .{4402 const index = try self.insertSection(segment_id, .{
4712 .sectname = makeStaticString(sectname),4403 .sectname = makeStaticString(sectname),
...@@ -4779,42 +4470,13 @@ fn insertSection(self: *MachO, segment_index: u8, header: macho.section_64) !u8...@@ -4779,42 +4470,13 @@ fn insertSection(self: *MachO, segment_index: u8, header: macho.section_64) !u8
4779 header.sectName(),4470 header.sectName(),
4780 insertion_index,4471 insertion_index,
4781 });4472 });
4782 // TODO slim it down
4783 for (&[_]*?u8{4473 for (&[_]*?u8{
4784 // __TEXT
4785 &self.text_section_index,4474 &self.text_section_index,
4786 &self.stubs_section_index,4475 &self.stubs_section_index,
4787 &self.stub_helper_section_index,4476 &self.stub_helper_section_index,
4788 &self.gcc_except_tab_section_index,
4789 &self.cstring_section_index,
4790 &self.ustring_section_index,
4791 &self.text_const_section_index,
4792 &self.objc_methlist_section_index,
4793 &self.objc_methname_section_index,
4794 &self.objc_methtype_section_index,
4795 &self.objc_classname_section_index,
4796 &self.eh_frame_section_index,
4797 // __DATA_CONST
4798 &self.got_section_index,4477 &self.got_section_index,
4799 &self.mod_init_func_section_index,
4800 &self.mod_term_func_section_index,
4801 &self.data_const_section_index,
4802 &self.objc_cfstring_section_index,
4803 &self.objc_classlist_section_index,
4804 &self.objc_imageinfo_section_index,
4805 // __DATA
4806 &self.rustc_section_index,
4807 &self.la_symbol_ptr_section_index,4478 &self.la_symbol_ptr_section_index,
4808 &self.objc_const_section_index,
4809 &self.objc_selrefs_section_index,
4810 &self.objc_classrefs_section_index,
4811 &self.objc_data_section_index,
4812 &self.data_section_index,4479 &self.data_section_index,
4813 &self.tlv_section_index,
4814 &self.tlv_ptrs_section_index,
4815 &self.tlv_data_section_index,
4816 &self.tlv_bss_section_index,
4817 &self.bss_section_index,
4818 }) |maybe_index| {4480 }) |maybe_index| {
4819 const index = maybe_index.* orelse continue;4481 const index = maybe_index.* orelse continue;
4820 if (insertion_index <= index) maybe_index.* = index + 1;4482 if (insertion_index <= index) maybe_index.* = index + 1;
...@@ -6017,7 +5679,7 @@ fn writeHeader(self: *MachO, ncmds: u32, sizeofcmds: u32) !void {...@@ -6017,7 +5679,7 @@ fn writeHeader(self: *MachO, ncmds: u32, sizeofcmds: u32) !void {
6017 else => unreachable,5679 else => unreachable,
6018 }5680 }
60195681
6020 if (self.tlv_section_index) |_| {5682 if (self.getSectionByName("__DATA", "__thread_vars")) |_| {
6021 header.flags |= macho.MH_HAS_TLV_DESCRIPTORS;5683 header.flags |= macho.MH_HAS_TLV_DESCRIPTORS;
6022 }5684 }
60235685
...@@ -6042,6 +5704,20 @@ pub fn makeStaticString(bytes: []const u8) [16]u8 {...@@ -6042,6 +5704,20 @@ pub fn makeStaticString(bytes: []const u8) [16]u8 {
6042 return buf;5704 return buf;
6043}5705}
60445706
5707fn getSegmentByName(self: MachO, segname: []const u8) ?u8 {
5708 for (self.segments.items) |seg, i| {
5709 if (mem.eql(u8, segname, seg.segName())) return @intCast(u8, i);
5710 } else return null;
5711}
5712
5713pub fn getSectionByName(self: MachO, segname: []const u8, sectname: []const u8) ?u8 {
5714 // TODO investigate caching with a hashmap
5715 for (self.sections.items(.header)) |header, i| {
5716 if (mem.eql(u8, header.segName(), segname) and mem.eql(u8, header.sectName(), sectname))
5717 return @intCast(u8, i);
5718 } else return null;
5719}
5720
6045fn getSectionIndexes(self: MachO, segment_index: u8) struct { start: u8, end: u8 } {5721fn getSectionIndexes(self: MachO, segment_index: u8) struct { start: u8, end: u8 } {
6046 var start: u8 = 0;5722 var start: u8 = 0;
6047 const nsects = for (self.segments.items) |seg, i| {5723 const nsects = for (self.segments.items) |seg, i| {
src/link/MachO/Atom.zig+3-2
...@@ -529,6 +529,7 @@ fn addStub(target: MachO.SymbolWithLoc, context: RelocContext) !void {...@@ -529,6 +529,7 @@ fn addStub(target: MachO.SymbolWithLoc, context: RelocContext) !void {
529 if (context.macho_file.stubs_table.contains(target)) return;529 if (context.macho_file.stubs_table.contains(target)) return;
530530
531 const stub_index = try context.macho_file.allocateStubEntry(target);531 const stub_index = try context.macho_file.allocateStubEntry(target);
532
532 const stub_helper_atom = try context.macho_file.createStubHelperAtom();533 const stub_helper_atom = try context.macho_file.createStubHelperAtom();
533 const laptr_atom = try context.macho_file.createLazyPointerAtom(stub_helper_atom.sym_index, target);534 const laptr_atom = try context.macho_file.createLazyPointerAtom(stub_helper_atom.sym_index, target);
534 const stub_atom = try context.macho_file.createStubAtom(laptr_atom.sym_index);535 const stub_atom = try context.macho_file.createStubAtom(laptr_atom.sym_index);
...@@ -601,9 +602,9 @@ pub fn resolveRelocs(self: *Atom, macho_file: *MachO) !void {...@@ -601,9 +602,9 @@ pub fn resolveRelocs(self: *Atom, macho_file: *MachO) !void {
601 // * wrt to __thread_data if defined, then602 // * wrt to __thread_data if defined, then
602 // * wrt to __thread_bss603 // * wrt to __thread_bss
603 const sect_id: u16 = sect_id: {604 const sect_id: u16 = sect_id: {
604 if (macho_file.tlv_data_section_index) |i| {605 if (macho_file.getSectionByName("__DATA", "__thread_data")) |i| {
605 break :sect_id i;606 break :sect_id i;
606 } else if (macho_file.tlv_bss_section_index) |i| {607 } else if (macho_file.getSectionByName("__DATA", "__thread_bss")) |i| {
607 break :sect_id i;608 break :sect_id i;
608 } else {609 } else {
609 log.err("threadlocal variables present but no initializer sections found", .{});610 log.err("threadlocal variables present but no initializer sections found", .{});