authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-07-01 10:34:46+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-07-15 18:49:46+02:00
log9c3ebe0216306b5e346ec52959de41d1b4d504d9
tree23dd11a4fdb7a8fadbd2ea3b7c6837ec2baef928
parente08f7ba8896ad64a696424cff9b9c0963a7a4a0b

zld: clean up logic for creating mach header


4 files changed, 117 insertions(+), 159 deletions(-)

src/link/MachO.zig+45-81
...@@ -41,8 +41,6 @@ d_sym: ?DebugSymbols = null,...@@ -41,8 +41,6 @@ d_sym: ?DebugSymbols = null,
41/// For x86_64 that's 4KB, whereas for aarch64, that's 16KB.41/// For x86_64 that's 4KB, whereas for aarch64, that's 16KB.
42page_size: u16,42page_size: u16,
4343
44/// Mach-O header
45header: ?macho.mach_header_64 = null,
46/// We commit 0x1000 = 4096 bytes of space to the header and44/// We commit 0x1000 = 4096 bytes of space to the header and
47/// the table of load commands. This should be plenty for any45/// the table of load commands. This should be plenty for any
48/// potential future extensions.46/// potential future extensions.
...@@ -128,7 +126,6 @@ offset_table: std.ArrayListUnmanaged(GOTEntry) = .{},...@@ -128,7 +126,6 @@ offset_table: std.ArrayListUnmanaged(GOTEntry) = .{},
128error_flags: File.ErrorFlags = File.ErrorFlags{},126error_flags: File.ErrorFlags = File.ErrorFlags{},
129127
130offset_table_count_dirty: bool = false,128offset_table_count_dirty: bool = false,
131header_dirty: bool = false,
132load_commands_dirty: bool = false,129load_commands_dirty: bool = false,
133rebase_info_dirty: bool = false,130rebase_info_dirty: bool = false,
134binding_info_dirty: bool = false,131binding_info_dirty: bool = false,
...@@ -497,7 +494,6 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {...@@ -497,7 +494,6 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {
497 }494 }
498495
499 assert(!self.offset_table_count_dirty);496 assert(!self.offset_table_count_dirty);
500 assert(!self.header_dirty);
501 assert(!self.load_commands_dirty);497 assert(!self.load_commands_dirty);
502 assert(!self.rebase_info_dirty);498 assert(!self.rebase_info_dirty);
503 assert(!self.binding_info_dirty);499 assert(!self.binding_info_dirty);
...@@ -1488,54 +1484,6 @@ pub fn populateMissingMetadata(self: *MachO) !void {...@@ -1488,54 +1484,6 @@ pub fn populateMissingMetadata(self: *MachO) !void {
1488 .Lib => return error.TODOImplementWritingLibFiles,1484 .Lib => return error.TODOImplementWritingLibFiles,
1489 }1485 }
14901486
1491 if (self.header == null) {
1492 var header: macho.mach_header_64 = undefined;
1493 header.magic = macho.MH_MAGIC_64;
1494
1495 const CpuInfo = struct {
1496 cpu_type: macho.cpu_type_t,
1497 cpu_subtype: macho.cpu_subtype_t,
1498 };
1499
1500 const cpu_info: CpuInfo = switch (self.base.options.target.cpu.arch) {
1501 .aarch64 => .{
1502 .cpu_type = macho.CPU_TYPE_ARM64,
1503 .cpu_subtype = macho.CPU_SUBTYPE_ARM_ALL,
1504 },
1505 .x86_64 => .{
1506 .cpu_type = macho.CPU_TYPE_X86_64,
1507 .cpu_subtype = macho.CPU_SUBTYPE_X86_64_ALL,
1508 },
1509 else => return error.UnsupportedMachOArchitecture,
1510 };
1511 header.cputype = cpu_info.cpu_type;
1512 header.cpusubtype = cpu_info.cpu_subtype;
1513
1514 const filetype: u32 = switch (self.base.options.output_mode) {
1515 .Exe => macho.MH_EXECUTE,
1516 .Obj => macho.MH_OBJECT,
1517 .Lib => switch (self.base.options.link_mode) {
1518 .Static => return error.TODOStaticLibMachOType,
1519 .Dynamic => macho.MH_DYLIB,
1520 },
1521 };
1522 header.filetype = filetype;
1523 // These will get populated at the end of flushing the results to file.
1524 header.ncmds = 0;
1525 header.sizeofcmds = 0;
1526
1527 switch (self.base.options.output_mode) {
1528 .Exe => {
1529 header.flags = macho.MH_NOUNDEFS | macho.MH_DYLDLINK | macho.MH_PIE;
1530 },
1531 else => {
1532 header.flags = 0;
1533 },
1534 }
1535 header.reserved = 0;
1536 self.header = header;
1537 self.header_dirty = true;
1538 }
1539 if (self.pagezero_segment_cmd_index == null) {1487 if (self.pagezero_segment_cmd_index == null) {
1540 self.pagezero_segment_cmd_index = @intCast(u16, self.load_commands.items.len);1488 self.pagezero_segment_cmd_index = @intCast(u16, self.load_commands.items.len);
1541 try self.load_commands.append(self.base.allocator, .{1489 try self.load_commands.append(self.base.allocator, .{
...@@ -1543,7 +1491,6 @@ pub fn populateMissingMetadata(self: *MachO) !void {...@@ -1543,7 +1491,6 @@ pub fn populateMissingMetadata(self: *MachO) !void {
1543 .vmsize = 0x100000000, // size always set to 4GB1491 .vmsize = 0x100000000, // size always set to 4GB
1544 }),1492 }),
1545 });1493 });
1546 self.header_dirty = true;
1547 self.load_commands_dirty = true;1494 self.load_commands_dirty = true;
1548 }1495 }
1549 if (self.text_segment_cmd_index == null) {1496 if (self.text_segment_cmd_index == null) {
...@@ -1567,7 +1514,6 @@ pub fn populateMissingMetadata(self: *MachO) !void {...@@ -1567,7 +1514,6 @@ pub fn populateMissingMetadata(self: *MachO) !void {
1567 .initprot = initprot,1514 .initprot = initprot,
1568 }),1515 }),
1569 });1516 });
1570 self.header_dirty = true;
1571 self.load_commands_dirty = true;1517 self.load_commands_dirty = true;
1572 }1518 }
1573 if (self.text_section_index == null) {1519 if (self.text_section_index == null) {
...@@ -1592,7 +1538,6 @@ pub fn populateMissingMetadata(self: *MachO) !void {...@@ -1592,7 +1538,6 @@ pub fn populateMissingMetadata(self: *MachO) !void {
1592 .@"align" = alignment,1538 .@"align" = alignment,
1593 .flags = flags,1539 .flags = flags,
1594 });1540 });
1595 self.header_dirty = true;
1596 self.load_commands_dirty = true;1541 self.load_commands_dirty = true;
1597 }1542 }
1598 if (self.stubs_section_index == null) {1543 if (self.stubs_section_index == null) {
...@@ -1624,7 +1569,6 @@ pub fn populateMissingMetadata(self: *MachO) !void {...@@ -1624,7 +1569,6 @@ pub fn populateMissingMetadata(self: *MachO) !void {
1624 .flags = flags,1569 .flags = flags,
1625 .reserved2 = stub_size,1570 .reserved2 = stub_size,
1626 });1571 });
1627 self.header_dirty = true;
1628 self.load_commands_dirty = true;1572 self.load_commands_dirty = true;
1629 }1573 }
1630 if (self.stub_helper_section_index == null) {1574 if (self.stub_helper_section_index == null) {
...@@ -1650,7 +1594,6 @@ pub fn populateMissingMetadata(self: *MachO) !void {...@@ -1650,7 +1594,6 @@ pub fn populateMissingMetadata(self: *MachO) !void {
1650 .@"align" = alignment,1594 .@"align" = alignment,
1651 .flags = flags,1595 .flags = flags,
1652 });1596 });
1653 self.header_dirty = true;
1654 self.load_commands_dirty = true;1597 self.load_commands_dirty = true;
1655 }1598 }
1656 if (self.data_const_segment_cmd_index == null) {1599 if (self.data_const_segment_cmd_index == null) {
...@@ -1674,7 +1617,6 @@ pub fn populateMissingMetadata(self: *MachO) !void {...@@ -1674,7 +1617,6 @@ pub fn populateMissingMetadata(self: *MachO) !void {
1674 .initprot = initprot,1617 .initprot = initprot,
1675 }),1618 }),
1676 });1619 });
1677 self.header_dirty = true;
1678 self.load_commands_dirty = true;1620 self.load_commands_dirty = true;
1679 }1621 }
1680 if (self.got_section_index == null) {1622 if (self.got_section_index == null) {
...@@ -1695,7 +1637,6 @@ pub fn populateMissingMetadata(self: *MachO) !void {...@@ -1695,7 +1637,6 @@ pub fn populateMissingMetadata(self: *MachO) !void {
1695 .@"align" = 3, // 2^3 = @sizeOf(u64)1637 .@"align" = 3, // 2^3 = @sizeOf(u64)
1696 .flags = flags,1638 .flags = flags,
1697 });1639 });
1698 self.header_dirty = true;
1699 self.load_commands_dirty = true;1640 self.load_commands_dirty = true;
1700 }1641 }
1701 if (self.data_segment_cmd_index == null) {1642 if (self.data_segment_cmd_index == null) {
...@@ -1719,7 +1660,6 @@ pub fn populateMissingMetadata(self: *MachO) !void {...@@ -1719,7 +1660,6 @@ pub fn populateMissingMetadata(self: *MachO) !void {
1719 .initprot = initprot,1660 .initprot = initprot,
1720 }),1661 }),
1721 });1662 });
1722 self.header_dirty = true;
1723 self.load_commands_dirty = true;1663 self.load_commands_dirty = true;
1724 }1664 }
1725 if (self.la_symbol_ptr_section_index == null) {1665 if (self.la_symbol_ptr_section_index == null) {
...@@ -1740,7 +1680,6 @@ pub fn populateMissingMetadata(self: *MachO) !void {...@@ -1740,7 +1680,6 @@ pub fn populateMissingMetadata(self: *MachO) !void {
1740 .@"align" = 3, // 2^3 = @sizeOf(u64)1680 .@"align" = 3, // 2^3 = @sizeOf(u64)
1741 .flags = flags,1681 .flags = flags,
1742 });1682 });
1743 self.header_dirty = true;
1744 self.load_commands_dirty = true;1683 self.load_commands_dirty = true;
1745 }1684 }
1746 if (self.data_section_index == null) {1685 if (self.data_section_index == null) {
...@@ -1759,7 +1698,6 @@ pub fn populateMissingMetadata(self: *MachO) !void {...@@ -1759,7 +1698,6 @@ pub fn populateMissingMetadata(self: *MachO) !void {
1759 .offset = @intCast(u32, off),1698 .offset = @intCast(u32, off),
1760 .@"align" = 3, // 2^3 = @sizeOf(u64)1699 .@"align" = 3, // 2^3 = @sizeOf(u64)
1761 });1700 });
1762 self.header_dirty = true;
1763 self.load_commands_dirty = true;1701 self.load_commands_dirty = true;
1764 }1702 }
1765 if (self.linkedit_segment_cmd_index == null) {1703 if (self.linkedit_segment_cmd_index == null) {
...@@ -1779,7 +1717,6 @@ pub fn populateMissingMetadata(self: *MachO) !void {...@@ -1779,7 +1717,6 @@ pub fn populateMissingMetadata(self: *MachO) !void {
1779 .initprot = initprot,1717 .initprot = initprot,
1780 }),1718 }),
1781 });1719 });
1782 self.header_dirty = true;
1783 self.load_commands_dirty = true;1720 self.load_commands_dirty = true;
1784 }1721 }
1785 if (self.dyld_info_cmd_index == null) {1722 if (self.dyld_info_cmd_index == null) {
...@@ -1826,7 +1763,6 @@ pub fn populateMissingMetadata(self: *MachO) !void {...@@ -1826,7 +1763,6 @@ pub fn populateMissingMetadata(self: *MachO) !void {
1826 dyld.export_off = @intCast(u32, export_off);1763 dyld.export_off = @intCast(u32, export_off);
1827 dyld.export_size = expected_size;1764 dyld.export_size = expected_size;
18281765
1829 self.header_dirty = true;
1830 self.load_commands_dirty = true;1766 self.load_commands_dirty = true;
1831 }1767 }
1832 if (self.symtab_cmd_index == null) {1768 if (self.symtab_cmd_index == null) {
...@@ -1858,7 +1794,6 @@ pub fn populateMissingMetadata(self: *MachO) !void {...@@ -1858,7 +1794,6 @@ pub fn populateMissingMetadata(self: *MachO) !void {
1858 symtab.stroff = @intCast(u32, strtab_off);1794 symtab.stroff = @intCast(u32, strtab_off);
1859 symtab.strsize = @intCast(u32, strtab_size);1795 symtab.strsize = @intCast(u32, strtab_size);
18601796
1861 self.header_dirty = true;
1862 self.load_commands_dirty = true;1797 self.load_commands_dirty = true;
1863 self.string_table_dirty = true;1798 self.string_table_dirty = true;
1864 }1799 }
...@@ -1895,7 +1830,6 @@ pub fn populateMissingMetadata(self: *MachO) !void {...@@ -1895,7 +1830,6 @@ pub fn populateMissingMetadata(self: *MachO) !void {
1895 .nlocrel = 0,1830 .nlocrel = 0,
1896 },1831 },
1897 });1832 });
1898 self.header_dirty = true;
1899 self.load_commands_dirty = true;1833 self.load_commands_dirty = true;
1900 }1834 }
1901 if (self.dylinker_cmd_index == null) {1835 if (self.dylinker_cmd_index == null) {
...@@ -1914,7 +1848,6 @@ pub fn populateMissingMetadata(self: *MachO) !void {...@@ -1914,7 +1848,6 @@ pub fn populateMissingMetadata(self: *MachO) !void {
1914 mem.set(u8, dylinker_cmd.data, 0);1848 mem.set(u8, dylinker_cmd.data, 0);
1915 mem.copy(u8, dylinker_cmd.data, mem.spanZ(DEFAULT_DYLD_PATH));1849 mem.copy(u8, dylinker_cmd.data, mem.spanZ(DEFAULT_DYLD_PATH));
1916 try self.load_commands.append(self.base.allocator, .{ .Dylinker = dylinker_cmd });1850 try self.load_commands.append(self.base.allocator, .{ .Dylinker = dylinker_cmd });
1917 self.header_dirty = true;
1918 self.load_commands_dirty = true;1851 self.load_commands_dirty = true;
1919 }1852 }
1920 if (self.libsystem_cmd_index == null) {1853 if (self.libsystem_cmd_index == null) {
...@@ -1925,7 +1858,6 @@ pub fn populateMissingMetadata(self: *MachO) !void {...@@ -1925,7 +1858,6 @@ pub fn populateMissingMetadata(self: *MachO) !void {
19251858
1926 try self.load_commands.append(self.base.allocator, .{ .Dylib = dylib_cmd });1859 try self.load_commands.append(self.base.allocator, .{ .Dylib = dylib_cmd });
19271860
1928 self.header_dirty = true;
1929 self.load_commands_dirty = true;1861 self.load_commands_dirty = true;
1930 }1862 }
1931 if (self.main_cmd_index == null) {1863 if (self.main_cmd_index == null) {
...@@ -1938,7 +1870,6 @@ pub fn populateMissingMetadata(self: *MachO) !void {...@@ -1938,7 +1870,6 @@ pub fn populateMissingMetadata(self: *MachO) !void {
1938 .stacksize = 0,1870 .stacksize = 0,
1939 },1871 },
1940 });1872 });
1941 self.header_dirty = true;
1942 self.load_commands_dirty = true;1873 self.load_commands_dirty = true;
1943 }1874 }
1944 if (self.version_min_cmd_index == null) {1875 if (self.version_min_cmd_index == null) {
...@@ -1960,7 +1891,6 @@ pub fn populateMissingMetadata(self: *MachO) !void {...@@ -1960,7 +1891,6 @@ pub fn populateMissingMetadata(self: *MachO) !void {
1960 .sdk = version,1891 .sdk = version,
1961 },1892 },
1962 });1893 });
1963 self.header_dirty = true;
1964 self.load_commands_dirty = true;1894 self.load_commands_dirty = true;
1965 }1895 }
1966 if (self.source_version_cmd_index == null) {1896 if (self.source_version_cmd_index == null) {
...@@ -1972,7 +1902,6 @@ pub fn populateMissingMetadata(self: *MachO) !void {...@@ -1972,7 +1902,6 @@ pub fn populateMissingMetadata(self: *MachO) !void {
1972 .version = 0x0,1902 .version = 0x0,
1973 },1903 },
1974 });1904 });
1975 self.header_dirty = true;
1976 self.load_commands_dirty = true;1905 self.load_commands_dirty = true;
1977 }1906 }
1978 if (self.uuid_cmd_index == null) {1907 if (self.uuid_cmd_index == null) {
...@@ -1984,7 +1913,6 @@ pub fn populateMissingMetadata(self: *MachO) !void {...@@ -1984,7 +1913,6 @@ pub fn populateMissingMetadata(self: *MachO) !void {
1984 };1913 };
1985 std.crypto.random.bytes(&uuid_cmd.uuid);1914 std.crypto.random.bytes(&uuid_cmd.uuid);
1986 try self.load_commands.append(self.base.allocator, .{ .Uuid = uuid_cmd });1915 try self.load_commands.append(self.base.allocator, .{ .Uuid = uuid_cmd });
1987 self.header_dirty = true;
1988 self.load_commands_dirty = true;1916 self.load_commands_dirty = true;
1989 }1917 }
1990 if (self.code_signature_cmd_index == null) {1918 if (self.code_signature_cmd_index == null) {
...@@ -1997,7 +1925,6 @@ pub fn populateMissingMetadata(self: *MachO) !void {...@@ -1997,7 +1925,6 @@ pub fn populateMissingMetadata(self: *MachO) !void {
1997 .datasize = 0,1925 .datasize = 0,
1998 },1926 },
1999 });1927 });
2000 self.header_dirty = true;
2001 self.load_commands_dirty = true;1928 self.load_commands_dirty = true;
2002 }1929 }
2003 if (!self.nonlazy_imports.contains("dyld_stub_binder")) {1930 if (!self.nonlazy_imports.contains("dyld_stub_binder")) {
...@@ -3224,24 +3151,57 @@ fn writeLoadCommands(self: *MachO) !void {...@@ -3224,24 +3151,57 @@ fn writeLoadCommands(self: *MachO) !void {
3224 }3151 }
32253152
3226 const off = @sizeOf(macho.mach_header_64);3153 const off = @sizeOf(macho.mach_header_64);
3154
3227 log.debug("writing {} load commands from 0x{x} to 0x{x}", .{ self.load_commands.items.len, off, off + sizeofcmds });3155 log.debug("writing {} load commands from 0x{x} to 0x{x}", .{ self.load_commands.items.len, off, off + sizeofcmds });
3156
3228 try self.base.file.?.pwriteAll(buffer, off);3157 try self.base.file.?.pwriteAll(buffer, off);
3229 self.load_commands_dirty = false;3158 self.load_commands_dirty = false;
3230}3159}
32313160
3232/// Writes Mach-O file header.3161/// Writes Mach-O file header.
3233fn writeHeader(self: *MachO) !void {3162fn writeHeader(self: *MachO) !void {
3234 if (!self.header_dirty) return;3163 var header = emptyHeader(.{
3164 .flags = macho.MH_NOUNDEFS | macho.MH_DYLDLINK | macho.MH_PIE | macho.MH_TWOLEVEL,
3165 });
3166
3167 switch (self.base.options.target.cpu.arch) {
3168 .aarch64 => {
3169 header.cputype = macho.CPU_TYPE_ARM64;
3170 header.cpusubtype = macho.CPU_SUBTYPE_ARM_ALL;
3171 },
3172 .x86_64 => {
3173 header.cputype = macho.CPU_TYPE_X86_64;
3174 header.cpusubtype = macho.CPU_SUBTYPE_X86_64_ALL;
3175 },
3176 else => return error.UnsupportedCpuArchitecture,
3177 }
3178
3179 switch (self.base.options.output_mode) {
3180 .Exe => {
3181 header.filetype = macho.MH_EXECUTE;
3182 },
3183 .Lib => {
3184 // By this point, it can only be a dylib.
3185 header.filetype = macho.MH_DYLIB;
3186 header.flags |= macho.MH_NO_REEXPORTED_DYLIBS;
3187 },
3188 else => unreachable,
3189 }
3190
3191 if (self.hasTlvDescriptors()) {
3192 header.flags |= macho.MH_HAS_TLV_DESCRIPTORS;
3193 }
3194
3195 header.ncmds = @intCast(u32, self.load_commands.items.len);
3196 header.sizeofcmds = 0;
32353197
3236 self.header.?.ncmds = @intCast(u32, self.load_commands.items.len);
3237 var sizeofcmds: u32 = 0;
3238 for (self.load_commands.items) |cmd| {3198 for (self.load_commands.items) |cmd| {
3239 sizeofcmds += cmd.cmdsize();3199 header.sizeofcmds += cmd.cmdsize();
3240 }3200 }
3241 self.header.?.sizeofcmds = sizeofcmds;3201
3242 log.debug("writing Mach-O header {}", .{self.header.?});3202 log.debug("writing Mach-O header {}", .{header});
3243 try self.base.file.?.pwriteAll(mem.asBytes(&self.header.?), 0);3203
3244 self.header_dirty = false;3204 try self.base.file.?.pwriteAll(mem.asBytes(&header), 0);
3245}3205}
32463206
3247pub fn padToIdeal(actual_size: anytype) @TypeOf(actual_size) {3207pub fn padToIdeal(actual_size: anytype) @TypeOf(actual_size) {
...@@ -3249,3 +3209,7 @@ pub fn padToIdeal(actual_size: anytype) @TypeOf(actual_size) {...@@ -3249,3 +3209,7 @@ pub fn padToIdeal(actual_size: anytype) @TypeOf(actual_size) {
3249 return std.math.add(@TypeOf(actual_size), actual_size, actual_size / ideal_factor) catch3209 return std.math.add(@TypeOf(actual_size), actual_size, actual_size / ideal_factor) catch
3250 std.math.maxInt(@TypeOf(actual_size));3210 std.math.maxInt(@TypeOf(actual_size));
3251}3211}
3212
3213fn hasTlvDescriptors(_: *MachO) bool {
3214 return false;
3215}
src/link/MachO/DebugSymbols.zig+35-53
...@@ -3,7 +3,7 @@ const DebugSymbols = @This();...@@ -3,7 +3,7 @@ const DebugSymbols = @This();
3const std = @import("std");3const std = @import("std");
4const assert = std.debug.assert;4const assert = std.debug.assert;
5const fs = std.fs;5const fs = std.fs;
6const log = std.log.scoped(.link);6const log = std.log.scoped(.dsym);
7const macho = std.macho;7const macho = std.macho;
8const mem = std.mem;8const mem = std.mem;
9const DW = std.dwarf;9const DW = std.dwarf;
...@@ -27,9 +27,6 @@ const page_size: u16 = 0x1000;...@@ -27,9 +27,6 @@ const page_size: u16 = 0x1000;
27base: *MachO,27base: *MachO,
28file: fs.File,28file: fs.File,
2929
30/// Mach header
31header: ?macho.mach_header_64 = null,
32
33/// Table of all load commands30/// Table of all load commands
34load_commands: std.ArrayListUnmanaged(LoadCommand) = .{},31load_commands: std.ArrayListUnmanaged(LoadCommand) = .{},
35/// __PAGEZERO segment32/// __PAGEZERO segment
...@@ -78,7 +75,6 @@ dbg_info_decl_last: ?*TextBlock = null,...@@ -78,7 +75,6 @@ dbg_info_decl_last: ?*TextBlock = null,
78/// Table of debug symbol names aka the debug string table.75/// Table of debug symbol names aka the debug string table.
79debug_string_table: std.ArrayListUnmanaged(u8) = .{},76debug_string_table: std.ArrayListUnmanaged(u8) = .{},
8077
81header_dirty: bool = false,
82load_commands_dirty: bool = false,78load_commands_dirty: bool = false,
83string_table_dirty: bool = false,79string_table_dirty: bool = false,
84debug_string_table_dirty: bool = false,80debug_string_table_dirty: bool = false,
...@@ -106,26 +102,10 @@ const min_nop_size = 2;...@@ -106,26 +102,10 @@ const min_nop_size = 2;
106/// You must call this function *after* `MachO.populateMissingMetadata()`102/// You must call this function *after* `MachO.populateMissingMetadata()`
107/// has been called to get a viable debug symbols output.103/// has been called to get a viable debug symbols output.
108pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void {104pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void {
109 if (self.header == null) {
110 const base_header = self.base.header.?;
111 var header: macho.mach_header_64 = undefined;
112 header.magic = macho.MH_MAGIC_64;
113 header.cputype = base_header.cputype;
114 header.cpusubtype = base_header.cpusubtype;
115 header.filetype = macho.MH_DSYM;
116 // These will get populated at the end of flushing the results to file.
117 header.ncmds = 0;
118 header.sizeofcmds = 0;
119 header.flags = 0;
120 header.reserved = 0;
121 self.header = header;
122 self.header_dirty = true;
123 }
124 if (self.uuid_cmd_index == null) {105 if (self.uuid_cmd_index == null) {
125 const base_cmd = self.base.load_commands.items[self.base.uuid_cmd_index.?];106 const base_cmd = self.base.load_commands.items[self.base.uuid_cmd_index.?];
126 self.uuid_cmd_index = @intCast(u16, self.load_commands.items.len);107 self.uuid_cmd_index = @intCast(u16, self.load_commands.items.len);
127 try self.load_commands.append(allocator, base_cmd);108 try self.load_commands.append(allocator, base_cmd);
128 self.header_dirty = true;
129 self.load_commands_dirty = true;109 self.load_commands_dirty = true;
130 }110 }
131 if (self.symtab_cmd_index == null) {111 if (self.symtab_cmd_index == null) {
...@@ -134,11 +114,11 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void...@@ -134,11 +114,11 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void
134 const symtab_size = base_cmd.nsyms * @sizeOf(macho.nlist_64);114 const symtab_size = base_cmd.nsyms * @sizeOf(macho.nlist_64);
135 const symtab_off = self.findFreeSpaceLinkedit(symtab_size, @sizeOf(macho.nlist_64));115 const symtab_off = self.findFreeSpaceLinkedit(symtab_size, @sizeOf(macho.nlist_64));
136116
137 log.debug("found dSym symbol table free space 0x{x} to 0x{x}", .{ symtab_off, symtab_off + symtab_size });117 log.debug("found symbol table free space 0x{x} to 0x{x}", .{ symtab_off, symtab_off + symtab_size });
138118
139 const strtab_off = self.findFreeSpaceLinkedit(base_cmd.strsize, 1);119 const strtab_off = self.findFreeSpaceLinkedit(base_cmd.strsize, 1);
140120
141 log.debug("found dSym string table free space 0x{x} to 0x{x}", .{ strtab_off, strtab_off + base_cmd.strsize });121 log.debug("found string table free space 0x{x} to 0x{x}", .{ strtab_off, strtab_off + base_cmd.strsize });
142122
143 try self.load_commands.append(allocator, .{123 try self.load_commands.append(allocator, .{
144 .Symtab = .{124 .Symtab = .{
...@@ -150,7 +130,6 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void...@@ -150,7 +130,6 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void
150 .strsize = base_cmd.strsize,130 .strsize = base_cmd.strsize,
151 },131 },
152 });132 });
153 self.header_dirty = true;
154 self.load_commands_dirty = true;133 self.load_commands_dirty = true;
155 self.string_table_dirty = true;134 self.string_table_dirty = true;
156 }135 }
...@@ -159,7 +138,6 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void...@@ -159,7 +138,6 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void
159 const base_cmd = self.base.load_commands.items[self.base.pagezero_segment_cmd_index.?].Segment;138 const base_cmd = self.base.load_commands.items[self.base.pagezero_segment_cmd_index.?].Segment;
160 const cmd = try self.copySegmentCommand(allocator, base_cmd);139 const cmd = try self.copySegmentCommand(allocator, base_cmd);
161 try self.load_commands.append(allocator, .{ .Segment = cmd });140 try self.load_commands.append(allocator, .{ .Segment = cmd });
162 self.header_dirty = true;
163 self.load_commands_dirty = true;141 self.load_commands_dirty = true;
164 }142 }
165 if (self.text_segment_cmd_index == null) {143 if (self.text_segment_cmd_index == null) {
...@@ -167,7 +145,6 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void...@@ -167,7 +145,6 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void
167 const base_cmd = self.base.load_commands.items[self.base.text_segment_cmd_index.?].Segment;145 const base_cmd = self.base.load_commands.items[self.base.text_segment_cmd_index.?].Segment;
168 const cmd = try self.copySegmentCommand(allocator, base_cmd);146 const cmd = try self.copySegmentCommand(allocator, base_cmd);
169 try self.load_commands.append(allocator, .{ .Segment = cmd });147 try self.load_commands.append(allocator, .{ .Segment = cmd });
170 self.header_dirty = true;
171 self.load_commands_dirty = true;148 self.load_commands_dirty = true;
172 }149 }
173 if (self.data_const_segment_cmd_index == null) outer: {150 if (self.data_const_segment_cmd_index == null) outer: {
...@@ -176,7 +153,6 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void...@@ -176,7 +153,6 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void
176 const base_cmd = self.base.load_commands.items[self.base.data_const_segment_cmd_index.?].Segment;153 const base_cmd = self.base.load_commands.items[self.base.data_const_segment_cmd_index.?].Segment;
177 const cmd = try self.copySegmentCommand(allocator, base_cmd);154 const cmd = try self.copySegmentCommand(allocator, base_cmd);
178 try self.load_commands.append(allocator, .{ .Segment = cmd });155 try self.load_commands.append(allocator, .{ .Segment = cmd });
179 self.header_dirty = true;
180 self.load_commands_dirty = true;156 self.load_commands_dirty = true;
181 }157 }
182 if (self.data_segment_cmd_index == null) outer: {158 if (self.data_segment_cmd_index == null) outer: {
...@@ -185,7 +161,6 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void...@@ -185,7 +161,6 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void
185 const base_cmd = self.base.load_commands.items[self.base.data_segment_cmd_index.?].Segment;161 const base_cmd = self.base.load_commands.items[self.base.data_segment_cmd_index.?].Segment;
186 const cmd = try self.copySegmentCommand(allocator, base_cmd);162 const cmd = try self.copySegmentCommand(allocator, base_cmd);
187 try self.load_commands.append(allocator, .{ .Segment = cmd });163 try self.load_commands.append(allocator, .{ .Segment = cmd });
188 self.header_dirty = true;
189 self.load_commands_dirty = true;164 self.load_commands_dirty = true;
190 }165 }
191 if (self.linkedit_segment_cmd_index == null) {166 if (self.linkedit_segment_cmd_index == null) {
...@@ -196,7 +171,6 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void...@@ -196,7 +171,6 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void
196 cmd.inner.fileoff = self.linkedit_off;171 cmd.inner.fileoff = self.linkedit_off;
197 cmd.inner.filesize = self.linkedit_size;172 cmd.inner.filesize = self.linkedit_size;
198 try self.load_commands.append(allocator, .{ .Segment = cmd });173 try self.load_commands.append(allocator, .{ .Segment = cmd });
199 self.header_dirty = true;
200 self.load_commands_dirty = true;174 self.load_commands_dirty = true;
201 }175 }
202 if (self.dwarf_segment_cmd_index == null) {176 if (self.dwarf_segment_cmd_index == null) {
...@@ -208,7 +182,7 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void...@@ -208,7 +182,7 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void
208 const off = linkedit.inner.fileoff + linkedit.inner.filesize;182 const off = linkedit.inner.fileoff + linkedit.inner.filesize;
209 const vmaddr = linkedit.inner.vmaddr + linkedit.inner.vmsize;183 const vmaddr = linkedit.inner.vmaddr + linkedit.inner.vmsize;
210184
211 log.debug("found dSym __DWARF segment free space 0x{x} to 0x{x}", .{ off, off + needed_size });185 log.debug("found __DWARF segment free space 0x{x} to 0x{x}", .{ off, off + needed_size });
212186
213 try self.load_commands.append(allocator, .{187 try self.load_commands.append(allocator, .{
214 .Segment = SegmentCommand.empty("__DWARF", .{188 .Segment = SegmentCommand.empty("__DWARF", .{
...@@ -218,7 +192,6 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void...@@ -218,7 +192,6 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void
218 .filesize = needed_size,192 .filesize = needed_size,
219 }),193 }),
220 });194 });
221 self.header_dirty = true;
222 self.load_commands_dirty = true;195 self.load_commands_dirty = true;
223 }196 }
224 if (self.debug_str_section_index == null) {197 if (self.debug_str_section_index == null) {
...@@ -232,7 +205,6 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void...@@ -232,7 +205,6 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void
232 .offset = @intCast(u32, dwarf_segment.inner.fileoff),205 .offset = @intCast(u32, dwarf_segment.inner.fileoff),
233 .@"align" = 1,206 .@"align" = 1,
234 });207 });
235 self.header_dirty = true;
236 self.load_commands_dirty = true;208 self.load_commands_dirty = true;
237 self.debug_string_table_dirty = true;209 self.debug_string_table_dirty = true;
238 }210 }
...@@ -244,7 +216,7 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void...@@ -244,7 +216,7 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void
244 const p_align = 1;216 const p_align = 1;
245 const off = dwarf_segment.findFreeSpace(file_size_hint, p_align, null);217 const off = dwarf_segment.findFreeSpace(file_size_hint, p_align, null);
246218
247 log.debug("found dSym __debug_info free space 0x{x} to 0x{x}", .{ off, off + file_size_hint });219 log.debug("found __debug_info free space 0x{x} to 0x{x}", .{ off, off + file_size_hint });
248220
249 try dwarf_segment.addSection(allocator, "__debug_info", .{221 try dwarf_segment.addSection(allocator, "__debug_info", .{
250 .addr = dwarf_segment.inner.vmaddr + off - dwarf_segment.inner.fileoff,222 .addr = dwarf_segment.inner.vmaddr + off - dwarf_segment.inner.fileoff,
...@@ -252,7 +224,6 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void...@@ -252,7 +224,6 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void
252 .offset = @intCast(u32, off),224 .offset = @intCast(u32, off),
253 .@"align" = p_align,225 .@"align" = p_align,
254 });226 });
255 self.header_dirty = true;
256 self.load_commands_dirty = true;227 self.load_commands_dirty = true;
257 self.debug_info_header_dirty = true;228 self.debug_info_header_dirty = true;
258 }229 }
...@@ -264,7 +235,7 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void...@@ -264,7 +235,7 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void
264 const p_align = 1;235 const p_align = 1;
265 const off = dwarf_segment.findFreeSpace(file_size_hint, p_align, null);236 const off = dwarf_segment.findFreeSpace(file_size_hint, p_align, null);
266237
267 log.debug("found dSym __debug_abbrev free space 0x{x} to 0x{x}", .{ off, off + file_size_hint });238 log.debug("found __debug_abbrev free space 0x{x} to 0x{x}", .{ off, off + file_size_hint });
268239
269 try dwarf_segment.addSection(allocator, "__debug_abbrev", .{240 try dwarf_segment.addSection(allocator, "__debug_abbrev", .{
270 .addr = dwarf_segment.inner.vmaddr + off - dwarf_segment.inner.fileoff,241 .addr = dwarf_segment.inner.vmaddr + off - dwarf_segment.inner.fileoff,
...@@ -272,7 +243,6 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void...@@ -272,7 +243,6 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void
272 .offset = @intCast(u32, off),243 .offset = @intCast(u32, off),
273 .@"align" = p_align,244 .@"align" = p_align,
274 });245 });
275 self.header_dirty = true;
276 self.load_commands_dirty = true;246 self.load_commands_dirty = true;
277 self.debug_abbrev_section_dirty = true;247 self.debug_abbrev_section_dirty = true;
278 }248 }
...@@ -284,7 +254,7 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void...@@ -284,7 +254,7 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void
284 const p_align = 16;254 const p_align = 16;
285 const off = dwarf_segment.findFreeSpace(file_size_hint, p_align, null);255 const off = dwarf_segment.findFreeSpace(file_size_hint, p_align, null);
286256
287 log.debug("found dSym __debug_aranges free space 0x{x} to 0x{x}", .{ off, off + file_size_hint });257 log.debug("found __debug_aranges free space 0x{x} to 0x{x}", .{ off, off + file_size_hint });
288258
289 try dwarf_segment.addSection(allocator, "__debug_aranges", .{259 try dwarf_segment.addSection(allocator, "__debug_aranges", .{
290 .addr = dwarf_segment.inner.vmaddr + off - dwarf_segment.inner.fileoff,260 .addr = dwarf_segment.inner.vmaddr + off - dwarf_segment.inner.fileoff,
...@@ -292,7 +262,6 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void...@@ -292,7 +262,6 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void
292 .offset = @intCast(u32, off),262 .offset = @intCast(u32, off),
293 .@"align" = p_align,263 .@"align" = p_align,
294 });264 });
295 self.header_dirty = true;
296 self.load_commands_dirty = true;265 self.load_commands_dirty = true;
297 self.debug_aranges_section_dirty = true;266 self.debug_aranges_section_dirty = true;
298 }267 }
...@@ -304,7 +273,7 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void...@@ -304,7 +273,7 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void
304 const p_align = 1;273 const p_align = 1;
305 const off = dwarf_segment.findFreeSpace(file_size_hint, p_align, null);274 const off = dwarf_segment.findFreeSpace(file_size_hint, p_align, null);
306275
307 log.debug("found dSym __debug_line free space 0x{x} to 0x{x}", .{ off, off + file_size_hint });276 log.debug("found __debug_line free space 0x{x} to 0x{x}", .{ off, off + file_size_hint });
308277
309 try dwarf_segment.addSection(allocator, "__debug_line", .{278 try dwarf_segment.addSection(allocator, "__debug_line", .{
310 .addr = dwarf_segment.inner.vmaddr + off - dwarf_segment.inner.fileoff,279 .addr = dwarf_segment.inner.vmaddr + off - dwarf_segment.inner.fileoff,
...@@ -312,7 +281,6 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void...@@ -312,7 +281,6 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void
312 .offset = @intCast(u32, off),281 .offset = @intCast(u32, off),
313 .@"align" = p_align,282 .@"align" = p_align,
314 });283 });
315 self.header_dirty = true;
316 self.load_commands_dirty = true;284 self.load_commands_dirty = true;
317 self.debug_line_header_dirty = true;285 self.debug_line_header_dirty = true;
318 }286 }
...@@ -624,7 +592,6 @@ pub fn flushModule(self: *DebugSymbols, allocator: *Allocator, options: link.Opt...@@ -624,7 +592,6 @@ pub fn flushModule(self: *DebugSymbols, allocator: *Allocator, options: link.Opt
624 try self.writeLoadCommands(allocator);592 try self.writeLoadCommands(allocator);
625 try self.writeHeader();593 try self.writeHeader();
626594
627 assert(!self.header_dirty);
628 assert(!self.load_commands_dirty);595 assert(!self.load_commands_dirty);
629 assert(!self.string_table_dirty);596 assert(!self.string_table_dirty);
630 assert(!self.debug_abbrev_section_dirty);597 assert(!self.debug_abbrev_section_dirty);
...@@ -716,23 +683,38 @@ fn writeLoadCommands(self: *DebugSymbols, allocator: *Allocator) !void {...@@ -716,23 +683,38 @@ fn writeLoadCommands(self: *DebugSymbols, allocator: *Allocator) !void {
716 }683 }
717684
718 const off = @sizeOf(macho.mach_header_64);685 const off = @sizeOf(macho.mach_header_64);
719 log.debug("writing {} dSym load commands from 0x{x} to 0x{x}", .{ self.load_commands.items.len, off, off + sizeofcmds });686 log.debug("writing {} load commands from 0x{x} to 0x{x}", .{ self.load_commands.items.len, off, off + sizeofcmds });
720 try self.file.pwriteAll(buffer, off);687 try self.file.pwriteAll(buffer, off);
721 self.load_commands_dirty = false;688 self.load_commands_dirty = false;
722}689}
723690
724fn writeHeader(self: *DebugSymbols) !void {691fn writeHeader(self: *DebugSymbols) !void {
725 if (!self.header_dirty) return;692 var header = emptyHeader(.{
693 .filetype = macho.MH_DSYM,
694 });
695
696 switch (self.base.base.options.target.cpu.arch) {
697 .aarch64 => {
698 header.cputype = macho.CPU_TYPE_ARM64;
699 header.cpusubtype = macho.CPU_SUBTYPE_ARM_ALL;
700 },
701 .x86_64 => {
702 header.cputype = macho.CPU_TYPE_X86_64;
703 header.cpusubtype = macho.CPU_SUBTYPE_X86_64_ALL;
704 },
705 else => return error.UnsupportedCpuArchitecture,
706 }
707
708 header.ncmds = @intCast(u32, self.load_commands.items.len);
709 header.sizeofcmds = 0;
726710
727 self.header.?.ncmds = @intCast(u32, self.load_commands.items.len);
728 var sizeofcmds: u32 = 0;
729 for (self.load_commands.items) |cmd| {711 for (self.load_commands.items) |cmd| {
730 sizeofcmds += cmd.cmdsize();712 header.sizeofcmds += cmd.cmdsize();
731 }713 }
732 self.header.?.sizeofcmds = sizeofcmds;714
733 log.debug("writing Mach-O dSym header {}", .{self.header.?});715 log.debug("writing Mach-O header {}", .{header});
734 try self.file.pwriteAll(mem.asBytes(&self.header.?), 0);716
735 self.header_dirty = false;717 try self.file.pwriteAll(mem.asBytes(&header), 0);
736}718}
737719
738fn allocatedSizeLinkedit(self: *DebugSymbols, start: u64) u64 {720fn allocatedSizeLinkedit(self: *DebugSymbols, start: u64) u64 {
...@@ -798,7 +780,7 @@ fn relocateSymbolTable(self: *DebugSymbols) !void {...@@ -798,7 +780,7 @@ fn relocateSymbolTable(self: *DebugSymbols) !void {
798 const existing_size = symtab.nsyms * @sizeOf(macho.nlist_64);780 const existing_size = symtab.nsyms * @sizeOf(macho.nlist_64);
799781
800 assert(new_symoff + existing_size <= self.linkedit_off + self.linkedit_size); // TODO expand LINKEDIT segment.782 assert(new_symoff + existing_size <= self.linkedit_off + self.linkedit_size); // TODO expand LINKEDIT segment.
801 log.debug("relocating dSym symbol table from 0x{x}-0x{x} to 0x{x}-0x{x}", .{783 log.debug("relocating symbol table from 0x{x}-0x{x} to 0x{x}-0x{x}", .{
802 symtab.symoff,784 symtab.symoff,
803 symtab.symoff + existing_size,785 symtab.symoff + existing_size,
804 new_symoff,786 new_symoff,
...@@ -820,7 +802,7 @@ pub fn writeLocalSymbol(self: *DebugSymbols, index: usize) !void {...@@ -820,7 +802,7 @@ pub fn writeLocalSymbol(self: *DebugSymbols, index: usize) !void {
820 try self.relocateSymbolTable();802 try self.relocateSymbolTable();
821 const symtab = &self.load_commands.items[self.symtab_cmd_index.?].Symtab;803 const symtab = &self.load_commands.items[self.symtab_cmd_index.?].Symtab;
822 const off = symtab.symoff + @sizeOf(macho.nlist_64) * index;804 const off = symtab.symoff + @sizeOf(macho.nlist_64) * index;
823 log.debug("writing dSym local symbol {} at 0x{x}", .{ index, off });805 log.debug("writing local symbol {} at 0x{x}", .{ index, off });
824 try self.file.pwriteAll(mem.asBytes(&self.base.locals.items[index]), off);806 try self.file.pwriteAll(mem.asBytes(&self.base.locals.items[index]), off);
825}807}
826808
...@@ -839,7 +821,7 @@ fn writeStringTable(self: *DebugSymbols) !void {...@@ -839,7 +821,7 @@ fn writeStringTable(self: *DebugSymbols) !void {
839 symtab.stroff = @intCast(u32, self.findFreeSpaceLinkedit(needed_size, 1));821 symtab.stroff = @intCast(u32, self.findFreeSpaceLinkedit(needed_size, 1));
840 }822 }
841 symtab.strsize = @intCast(u32, needed_size);823 symtab.strsize = @intCast(u32, needed_size);
842 log.debug("writing dSym string table from 0x{x} to 0x{x}", .{ symtab.stroff, symtab.stroff + symtab.strsize });824 log.debug("writing string table from 0x{x} to 0x{x}", .{ symtab.stroff, symtab.stroff + symtab.strsize });
843825
844 try self.file.pwriteAll(self.base.string_table.items, symtab.stroff);826 try self.file.pwriteAll(self.base.string_table.items, symtab.stroff);
845 self.load_commands_dirty = true;827 self.load_commands_dirty = true;
src/link/MachO/Zld.zig+15-25
...@@ -3132,54 +3132,44 @@ fn writeLoadCommands(self: *Zld) !void {...@@ -3132,54 +3132,44 @@ fn writeLoadCommands(self: *Zld) !void {
3132}3132}
31333133
3134fn writeHeader(self: *Zld) !void {3134fn writeHeader(self: *Zld) !void {
3135 var header: macho.mach_header_64 = undefined;3135 var header = emptyHeader(.{
3136 header.magic = macho.MH_MAGIC_64;3136 .flags = macho.MH_NOUNDEFS | macho.MH_DYLDLINK | macho.MH_PIE | macho.MH_TWOLEVEL,
31373137 });
3138 const CpuInfo = struct {
3139 cpu_type: macho.cpu_type_t,
3140 cpu_subtype: macho.cpu_subtype_t,
3141 };
31423138
3143 const cpu_info: CpuInfo = switch (self.target.?.cpu.arch) {3139 switch (self.target.?.cpu.arch) {
3144 .aarch64 => .{3140 .aarch64 => {
3145 .cpu_type = macho.CPU_TYPE_ARM64,3141 header.cputype = macho.CPU_TYPE_ARM64;
3146 .cpu_subtype = macho.CPU_SUBTYPE_ARM_ALL,3142 header.cpusubtype = macho.CPU_SUBTYPE_ARM_ALL;
3147 },3143 },
3148 .x86_64 => .{3144 .x86_64 => {
3149 .cpu_type = macho.CPU_TYPE_X86_64,3145 header.cputype = macho.CPU_TYPE_X86_64;
3150 .cpu_subtype = macho.CPU_SUBTYPE_X86_64_ALL,3146 header.cpusubtype = macho.CPU_SUBTYPE_X86_64_ALL;
3151 },3147 },
3152 else => return error.UnsupportedCpuArchitecture,3148 else => return error.UnsupportedCpuArchitecture,
3153 };3149 }
3154 header.cputype = cpu_info.cpu_type;
3155 header.cpusubtype = cpu_info.cpu_subtype;
31563150
3157 switch (self.output.?.tag) {3151 switch (self.output.?.tag) {
3158 .exe => {3152 .exe => {
3159 header.filetype = macho.MH_EXECUTE;3153 header.filetype = macho.MH_EXECUTE;
3160 header.flags = macho.MH_NOUNDEFS | macho.MH_DYLDLINK | macho.MH_PIE | macho.MH_TWOLEVEL;
3161 },3154 },
3162 .dylib => {3155 .dylib => {
3163 header.filetype = macho.MH_DYLIB;3156 header.filetype = macho.MH_DYLIB;
3164 header.flags = macho.MH_NOUNDEFS |3157 header.flags |= macho.MH_NO_REEXPORTED_DYLIBS;
3165 macho.MH_DYLDLINK |
3166 macho.MH_PIE |
3167 macho.MH_TWOLEVEL |
3168 macho.MH_NO_REEXPORTED_DYLIBS;
3169 },3158 },
3170 }3159 }
31713160
3172 header.reserved = 0;
3173
3174 if (self.tlv_section_index) |_|3161 if (self.tlv_section_index) |_|
3175 header.flags |= macho.MH_HAS_TLV_DESCRIPTORS;3162 header.flags |= macho.MH_HAS_TLV_DESCRIPTORS;
31763163
3177 header.ncmds = @intCast(u32, self.load_commands.items.len);3164 header.ncmds = @intCast(u32, self.load_commands.items.len);
3178 header.sizeofcmds = 0;3165 header.sizeofcmds = 0;
3166
3179 for (self.load_commands.items) |cmd| {3167 for (self.load_commands.items) |cmd| {
3180 header.sizeofcmds += cmd.cmdsize();3168 header.sizeofcmds += cmd.cmdsize();
3181 }3169 }
3170
3182 log.debug("writing Mach-O header {}", .{header});3171 log.debug("writing Mach-O header {}", .{header});
3172
3183 try self.file.?.pwriteAll(mem.asBytes(&header), 0);3173 try self.file.?.pwriteAll(mem.asBytes(&header), 0);
3184}3174}
31853175
src/link/MachO/commands.zig+22
...@@ -11,6 +11,28 @@ const Allocator = std.mem.Allocator;...@@ -11,6 +11,28 @@ const Allocator = std.mem.Allocator;
11const MachO = @import("../MachO.zig");11const MachO = @import("../MachO.zig");
12const padToIdeal = MachO.padToIdeal;12const padToIdeal = MachO.padToIdeal;
1313
14pub const HeaderArgs = struct {
15 magic: u32 = macho.MH_MAGIC_64,
16 cputype: macho.cpu_type_t = 0,
17 cpusubtype: macho.cpu_subtype_t = 0,
18 filetype: u32 = 0,
19 flags: u32 = 0,
20 reserved: u32 = 0,
21};
22
23pub fn emptyHeader(args: HeaderArgs) macho.mach_header_64 {
24 return .{
25 .magic = args.magic,
26 .cputype = args.cputype,
27 .cpusubtype = args.cpusubtype,
28 .filetype = args.filetype,
29 .ncmds = 0,
30 .sizeofcmds = 0,
31 .flags = args.flags,
32 .reserved = args.reserved,
33 };
34}
35
14pub const LoadCommand = union(enum) {36pub const LoadCommand = union(enum) {
15 Segment: SegmentCommand,37 Segment: SegmentCommand,
16 DyldInfoOnly: macho.dyld_info_command,38 DyldInfoOnly: macho.dyld_info_command,