diff --git a/src/link/MachO.zig b/src/link/MachO.zig index 20c3b32512..f6ff03e92b 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -41,8 +41,6 @@ d_sym: ?DebugSymbols = null, /// For x86_64 that's 4KB, whereas for aarch64, that's 16KB. page_size: u16, -/// Mach-O header -header: ?macho.mach_header_64 = null, /// We commit 0x1000 = 4096 bytes of space to the header and /// the table of load commands. This should be plenty for any /// potential future extensions. @@ -128,7 +126,6 @@ offset_table: std.ArrayListUnmanaged(GOTEntry) = .{}, error_flags: File.ErrorFlags = File.ErrorFlags{}, offset_table_count_dirty: bool = false, -header_dirty: bool = false, load_commands_dirty: bool = false, rebase_info_dirty: bool = false, binding_info_dirty: bool = false, @@ -497,7 +494,6 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void { } assert(!self.offset_table_count_dirty); - assert(!self.header_dirty); assert(!self.load_commands_dirty); assert(!self.rebase_info_dirty); assert(!self.binding_info_dirty); @@ -1488,54 +1484,6 @@ pub fn populateMissingMetadata(self: *MachO) !void { .Lib => return error.TODOImplementWritingLibFiles, } - if (self.header == null) { - var header: macho.mach_header_64 = undefined; - header.magic = macho.MH_MAGIC_64; - - const CpuInfo = struct { - cpu_type: macho.cpu_type_t, - cpu_subtype: macho.cpu_subtype_t, - }; - - const cpu_info: CpuInfo = switch (self.base.options.target.cpu.arch) { - .aarch64 => .{ - .cpu_type = macho.CPU_TYPE_ARM64, - .cpu_subtype = macho.CPU_SUBTYPE_ARM_ALL, - }, - .x86_64 => .{ - .cpu_type = macho.CPU_TYPE_X86_64, - .cpu_subtype = macho.CPU_SUBTYPE_X86_64_ALL, - }, - else => return error.UnsupportedMachOArchitecture, - }; - header.cputype = cpu_info.cpu_type; - header.cpusubtype = cpu_info.cpu_subtype; - - const filetype: u32 = switch (self.base.options.output_mode) { - .Exe => macho.MH_EXECUTE, - .Obj => macho.MH_OBJECT, - .Lib => switch (self.base.options.link_mode) { - .Static => return error.TODOStaticLibMachOType, - .Dynamic => macho.MH_DYLIB, - }, - }; - header.filetype = filetype; - // These will get populated at the end of flushing the results to file. - header.ncmds = 0; - header.sizeofcmds = 0; - - switch (self.base.options.output_mode) { - .Exe => { - header.flags = macho.MH_NOUNDEFS | macho.MH_DYLDLINK | macho.MH_PIE; - }, - else => { - header.flags = 0; - }, - } - header.reserved = 0; - self.header = header; - self.header_dirty = true; - } if (self.pagezero_segment_cmd_index == null) { self.pagezero_segment_cmd_index = @intCast(u16, self.load_commands.items.len); try self.load_commands.append(self.base.allocator, .{ @@ -1543,7 +1491,6 @@ pub fn populateMissingMetadata(self: *MachO) !void { .vmsize = 0x100000000, // size always set to 4GB }), }); - self.header_dirty = true; self.load_commands_dirty = true; } if (self.text_segment_cmd_index == null) { @@ -1567,7 +1514,6 @@ pub fn populateMissingMetadata(self: *MachO) !void { .initprot = initprot, }), }); - self.header_dirty = true; self.load_commands_dirty = true; } if (self.text_section_index == null) { @@ -1592,7 +1538,6 @@ pub fn populateMissingMetadata(self: *MachO) !void { .@"align" = alignment, .flags = flags, }); - self.header_dirty = true; self.load_commands_dirty = true; } if (self.stubs_section_index == null) { @@ -1624,7 +1569,6 @@ pub fn populateMissingMetadata(self: *MachO) !void { .flags = flags, .reserved2 = stub_size, }); - self.header_dirty = true; self.load_commands_dirty = true; } if (self.stub_helper_section_index == null) { @@ -1650,7 +1594,6 @@ pub fn populateMissingMetadata(self: *MachO) !void { .@"align" = alignment, .flags = flags, }); - self.header_dirty = true; self.load_commands_dirty = true; } if (self.data_const_segment_cmd_index == null) { @@ -1674,7 +1617,6 @@ pub fn populateMissingMetadata(self: *MachO) !void { .initprot = initprot, }), }); - self.header_dirty = true; self.load_commands_dirty = true; } if (self.got_section_index == null) { @@ -1695,7 +1637,6 @@ pub fn populateMissingMetadata(self: *MachO) !void { .@"align" = 3, // 2^3 = @sizeOf(u64) .flags = flags, }); - self.header_dirty = true; self.load_commands_dirty = true; } if (self.data_segment_cmd_index == null) { @@ -1719,7 +1660,6 @@ pub fn populateMissingMetadata(self: *MachO) !void { .initprot = initprot, }), }); - self.header_dirty = true; self.load_commands_dirty = true; } if (self.la_symbol_ptr_section_index == null) { @@ -1740,7 +1680,6 @@ pub fn populateMissingMetadata(self: *MachO) !void { .@"align" = 3, // 2^3 = @sizeOf(u64) .flags = flags, }); - self.header_dirty = true; self.load_commands_dirty = true; } if (self.data_section_index == null) { @@ -1759,7 +1698,6 @@ pub fn populateMissingMetadata(self: *MachO) !void { .offset = @intCast(u32, off), .@"align" = 3, // 2^3 = @sizeOf(u64) }); - self.header_dirty = true; self.load_commands_dirty = true; } if (self.linkedit_segment_cmd_index == null) { @@ -1779,7 +1717,6 @@ pub fn populateMissingMetadata(self: *MachO) !void { .initprot = initprot, }), }); - self.header_dirty = true; self.load_commands_dirty = true; } if (self.dyld_info_cmd_index == null) { @@ -1826,7 +1763,6 @@ pub fn populateMissingMetadata(self: *MachO) !void { dyld.export_off = @intCast(u32, export_off); dyld.export_size = expected_size; - self.header_dirty = true; self.load_commands_dirty = true; } if (self.symtab_cmd_index == null) { @@ -1858,7 +1794,6 @@ pub fn populateMissingMetadata(self: *MachO) !void { symtab.stroff = @intCast(u32, strtab_off); symtab.strsize = @intCast(u32, strtab_size); - self.header_dirty = true; self.load_commands_dirty = true; self.string_table_dirty = true; } @@ -1895,7 +1830,6 @@ pub fn populateMissingMetadata(self: *MachO) !void { .nlocrel = 0, }, }); - self.header_dirty = true; self.load_commands_dirty = true; } if (self.dylinker_cmd_index == null) { @@ -1914,7 +1848,6 @@ pub fn populateMissingMetadata(self: *MachO) !void { mem.set(u8, dylinker_cmd.data, 0); mem.copy(u8, dylinker_cmd.data, mem.spanZ(DEFAULT_DYLD_PATH)); try self.load_commands.append(self.base.allocator, .{ .Dylinker = dylinker_cmd }); - self.header_dirty = true; self.load_commands_dirty = true; } if (self.libsystem_cmd_index == null) { @@ -1925,7 +1858,6 @@ pub fn populateMissingMetadata(self: *MachO) !void { try self.load_commands.append(self.base.allocator, .{ .Dylib = dylib_cmd }); - self.header_dirty = true; self.load_commands_dirty = true; } if (self.main_cmd_index == null) { @@ -1938,7 +1870,6 @@ pub fn populateMissingMetadata(self: *MachO) !void { .stacksize = 0, }, }); - self.header_dirty = true; self.load_commands_dirty = true; } if (self.version_min_cmd_index == null) { @@ -1960,7 +1891,6 @@ pub fn populateMissingMetadata(self: *MachO) !void { .sdk = version, }, }); - self.header_dirty = true; self.load_commands_dirty = true; } if (self.source_version_cmd_index == null) { @@ -1972,7 +1902,6 @@ pub fn populateMissingMetadata(self: *MachO) !void { .version = 0x0, }, }); - self.header_dirty = true; self.load_commands_dirty = true; } if (self.uuid_cmd_index == null) { @@ -1984,7 +1913,6 @@ pub fn populateMissingMetadata(self: *MachO) !void { }; std.crypto.random.bytes(&uuid_cmd.uuid); try self.load_commands.append(self.base.allocator, .{ .Uuid = uuid_cmd }); - self.header_dirty = true; self.load_commands_dirty = true; } if (self.code_signature_cmd_index == null) { @@ -1997,7 +1925,6 @@ pub fn populateMissingMetadata(self: *MachO) !void { .datasize = 0, }, }); - self.header_dirty = true; self.load_commands_dirty = true; } if (!self.nonlazy_imports.contains("dyld_stub_binder")) { @@ -3224,24 +3151,57 @@ fn writeLoadCommands(self: *MachO) !void { } const off = @sizeOf(macho.mach_header_64); + log.debug("writing {} load commands from 0x{x} to 0x{x}", .{ self.load_commands.items.len, off, off + sizeofcmds }); + try self.base.file.?.pwriteAll(buffer, off); self.load_commands_dirty = false; } /// Writes Mach-O file header. fn writeHeader(self: *MachO) !void { - if (!self.header_dirty) return; + var header = emptyHeader(.{ + .flags = macho.MH_NOUNDEFS | macho.MH_DYLDLINK | macho.MH_PIE | macho.MH_TWOLEVEL, + }); - self.header.?.ncmds = @intCast(u32, self.load_commands.items.len); - var sizeofcmds: u32 = 0; - for (self.load_commands.items) |cmd| { - sizeofcmds += cmd.cmdsize(); + switch (self.base.options.target.cpu.arch) { + .aarch64 => { + header.cputype = macho.CPU_TYPE_ARM64; + header.cpusubtype = macho.CPU_SUBTYPE_ARM_ALL; + }, + .x86_64 => { + header.cputype = macho.CPU_TYPE_X86_64; + header.cpusubtype = macho.CPU_SUBTYPE_X86_64_ALL; + }, + else => return error.UnsupportedCpuArchitecture, } - self.header.?.sizeofcmds = sizeofcmds; - log.debug("writing Mach-O header {}", .{self.header.?}); - try self.base.file.?.pwriteAll(mem.asBytes(&self.header.?), 0); - self.header_dirty = false; + + switch (self.base.options.output_mode) { + .Exe => { + header.filetype = macho.MH_EXECUTE; + }, + .Lib => { + // By this point, it can only be a dylib. + header.filetype = macho.MH_DYLIB; + header.flags |= macho.MH_NO_REEXPORTED_DYLIBS; + }, + else => unreachable, + } + + if (self.hasTlvDescriptors()) { + header.flags |= macho.MH_HAS_TLV_DESCRIPTORS; + } + + header.ncmds = @intCast(u32, self.load_commands.items.len); + header.sizeofcmds = 0; + + for (self.load_commands.items) |cmd| { + header.sizeofcmds += cmd.cmdsize(); + } + + log.debug("writing Mach-O header {}", .{header}); + + try self.base.file.?.pwriteAll(mem.asBytes(&header), 0); } pub fn padToIdeal(actual_size: anytype) @TypeOf(actual_size) { @@ -3249,3 +3209,7 @@ pub fn padToIdeal(actual_size: anytype) @TypeOf(actual_size) { return std.math.add(@TypeOf(actual_size), actual_size, actual_size / ideal_factor) catch std.math.maxInt(@TypeOf(actual_size)); } + +fn hasTlvDescriptors(_: *MachO) bool { + return false; +} diff --git a/src/link/MachO/DebugSymbols.zig b/src/link/MachO/DebugSymbols.zig index 684861ebf5..62c2faad4b 100644 --- a/src/link/MachO/DebugSymbols.zig +++ b/src/link/MachO/DebugSymbols.zig @@ -3,7 +3,7 @@ const DebugSymbols = @This(); const std = @import("std"); const assert = std.debug.assert; const fs = std.fs; -const log = std.log.scoped(.link); +const log = std.log.scoped(.dsym); const macho = std.macho; const mem = std.mem; const DW = std.dwarf; @@ -27,9 +27,6 @@ const page_size: u16 = 0x1000; base: *MachO, file: fs.File, -/// Mach header -header: ?macho.mach_header_64 = null, - /// Table of all load commands load_commands: std.ArrayListUnmanaged(LoadCommand) = .{}, /// __PAGEZERO segment @@ -78,7 +75,6 @@ dbg_info_decl_last: ?*TextBlock = null, /// Table of debug symbol names aka the debug string table. debug_string_table: std.ArrayListUnmanaged(u8) = .{}, -header_dirty: bool = false, load_commands_dirty: bool = false, string_table_dirty: bool = false, debug_string_table_dirty: bool = false, @@ -106,26 +102,10 @@ const min_nop_size = 2; /// You must call this function *after* `MachO.populateMissingMetadata()` /// has been called to get a viable debug symbols output. pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void { - if (self.header == null) { - const base_header = self.base.header.?; - var header: macho.mach_header_64 = undefined; - header.magic = macho.MH_MAGIC_64; - header.cputype = base_header.cputype; - header.cpusubtype = base_header.cpusubtype; - header.filetype = macho.MH_DSYM; - // These will get populated at the end of flushing the results to file. - header.ncmds = 0; - header.sizeofcmds = 0; - header.flags = 0; - header.reserved = 0; - self.header = header; - self.header_dirty = true; - } if (self.uuid_cmd_index == null) { const base_cmd = self.base.load_commands.items[self.base.uuid_cmd_index.?]; self.uuid_cmd_index = @intCast(u16, self.load_commands.items.len); try self.load_commands.append(allocator, base_cmd); - self.header_dirty = true; self.load_commands_dirty = true; } if (self.symtab_cmd_index == null) { @@ -134,11 +114,11 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void const symtab_size = base_cmd.nsyms * @sizeOf(macho.nlist_64); const symtab_off = self.findFreeSpaceLinkedit(symtab_size, @sizeOf(macho.nlist_64)); - log.debug("found dSym symbol table free space 0x{x} to 0x{x}", .{ symtab_off, symtab_off + symtab_size }); + log.debug("found symbol table free space 0x{x} to 0x{x}", .{ symtab_off, symtab_off + symtab_size }); const strtab_off = self.findFreeSpaceLinkedit(base_cmd.strsize, 1); - log.debug("found dSym string table free space 0x{x} to 0x{x}", .{ strtab_off, strtab_off + base_cmd.strsize }); + log.debug("found string table free space 0x{x} to 0x{x}", .{ strtab_off, strtab_off + base_cmd.strsize }); try self.load_commands.append(allocator, .{ .Symtab = .{ @@ -150,7 +130,6 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void .strsize = base_cmd.strsize, }, }); - self.header_dirty = true; self.load_commands_dirty = true; self.string_table_dirty = true; } @@ -159,7 +138,6 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void const base_cmd = self.base.load_commands.items[self.base.pagezero_segment_cmd_index.?].Segment; const cmd = try self.copySegmentCommand(allocator, base_cmd); try self.load_commands.append(allocator, .{ .Segment = cmd }); - self.header_dirty = true; self.load_commands_dirty = true; } if (self.text_segment_cmd_index == null) { @@ -167,7 +145,6 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void const base_cmd = self.base.load_commands.items[self.base.text_segment_cmd_index.?].Segment; const cmd = try self.copySegmentCommand(allocator, base_cmd); try self.load_commands.append(allocator, .{ .Segment = cmd }); - self.header_dirty = true; self.load_commands_dirty = true; } if (self.data_const_segment_cmd_index == null) outer: { @@ -176,7 +153,6 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void const base_cmd = self.base.load_commands.items[self.base.data_const_segment_cmd_index.?].Segment; const cmd = try self.copySegmentCommand(allocator, base_cmd); try self.load_commands.append(allocator, .{ .Segment = cmd }); - self.header_dirty = true; self.load_commands_dirty = true; } if (self.data_segment_cmd_index == null) outer: { @@ -185,7 +161,6 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void const base_cmd = self.base.load_commands.items[self.base.data_segment_cmd_index.?].Segment; const cmd = try self.copySegmentCommand(allocator, base_cmd); try self.load_commands.append(allocator, .{ .Segment = cmd }); - self.header_dirty = true; self.load_commands_dirty = true; } if (self.linkedit_segment_cmd_index == null) { @@ -196,7 +171,6 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void cmd.inner.fileoff = self.linkedit_off; cmd.inner.filesize = self.linkedit_size; try self.load_commands.append(allocator, .{ .Segment = cmd }); - self.header_dirty = true; self.load_commands_dirty = true; } if (self.dwarf_segment_cmd_index == null) { @@ -208,7 +182,7 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void const off = linkedit.inner.fileoff + linkedit.inner.filesize; const vmaddr = linkedit.inner.vmaddr + linkedit.inner.vmsize; - log.debug("found dSym __DWARF segment free space 0x{x} to 0x{x}", .{ off, off + needed_size }); + log.debug("found __DWARF segment free space 0x{x} to 0x{x}", .{ off, off + needed_size }); try self.load_commands.append(allocator, .{ .Segment = SegmentCommand.empty("__DWARF", .{ @@ -218,7 +192,6 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void .filesize = needed_size, }), }); - self.header_dirty = true; self.load_commands_dirty = true; } if (self.debug_str_section_index == null) { @@ -232,7 +205,6 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void .offset = @intCast(u32, dwarf_segment.inner.fileoff), .@"align" = 1, }); - self.header_dirty = true; self.load_commands_dirty = true; self.debug_string_table_dirty = true; } @@ -244,7 +216,7 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void const p_align = 1; const off = dwarf_segment.findFreeSpace(file_size_hint, p_align, null); - log.debug("found dSym __debug_info free space 0x{x} to 0x{x}", .{ off, off + file_size_hint }); + log.debug("found __debug_info free space 0x{x} to 0x{x}", .{ off, off + file_size_hint }); try dwarf_segment.addSection(allocator, "__debug_info", .{ .addr = dwarf_segment.inner.vmaddr + off - dwarf_segment.inner.fileoff, @@ -252,7 +224,6 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void .offset = @intCast(u32, off), .@"align" = p_align, }); - self.header_dirty = true; self.load_commands_dirty = true; self.debug_info_header_dirty = true; } @@ -264,7 +235,7 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void const p_align = 1; const off = dwarf_segment.findFreeSpace(file_size_hint, p_align, null); - log.debug("found dSym __debug_abbrev free space 0x{x} to 0x{x}", .{ off, off + file_size_hint }); + log.debug("found __debug_abbrev free space 0x{x} to 0x{x}", .{ off, off + file_size_hint }); try dwarf_segment.addSection(allocator, "__debug_abbrev", .{ .addr = dwarf_segment.inner.vmaddr + off - dwarf_segment.inner.fileoff, @@ -272,7 +243,6 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void .offset = @intCast(u32, off), .@"align" = p_align, }); - self.header_dirty = true; self.load_commands_dirty = true; self.debug_abbrev_section_dirty = true; } @@ -284,7 +254,7 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void const p_align = 16; const off = dwarf_segment.findFreeSpace(file_size_hint, p_align, null); - log.debug("found dSym __debug_aranges free space 0x{x} to 0x{x}", .{ off, off + file_size_hint }); + log.debug("found __debug_aranges free space 0x{x} to 0x{x}", .{ off, off + file_size_hint }); try dwarf_segment.addSection(allocator, "__debug_aranges", .{ .addr = dwarf_segment.inner.vmaddr + off - dwarf_segment.inner.fileoff, @@ -292,7 +262,6 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void .offset = @intCast(u32, off), .@"align" = p_align, }); - self.header_dirty = true; self.load_commands_dirty = true; self.debug_aranges_section_dirty = true; } @@ -304,7 +273,7 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void const p_align = 1; const off = dwarf_segment.findFreeSpace(file_size_hint, p_align, null); - log.debug("found dSym __debug_line free space 0x{x} to 0x{x}", .{ off, off + file_size_hint }); + log.debug("found __debug_line free space 0x{x} to 0x{x}", .{ off, off + file_size_hint }); try dwarf_segment.addSection(allocator, "__debug_line", .{ .addr = dwarf_segment.inner.vmaddr + off - dwarf_segment.inner.fileoff, @@ -312,7 +281,6 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void .offset = @intCast(u32, off), .@"align" = p_align, }); - self.header_dirty = true; self.load_commands_dirty = true; self.debug_line_header_dirty = true; } @@ -624,7 +592,6 @@ pub fn flushModule(self: *DebugSymbols, allocator: *Allocator, options: link.Opt try self.writeLoadCommands(allocator); try self.writeHeader(); - assert(!self.header_dirty); assert(!self.load_commands_dirty); assert(!self.string_table_dirty); assert(!self.debug_abbrev_section_dirty); @@ -716,23 +683,38 @@ fn writeLoadCommands(self: *DebugSymbols, allocator: *Allocator) !void { } const off = @sizeOf(macho.mach_header_64); - log.debug("writing {} dSym load commands from 0x{x} to 0x{x}", .{ self.load_commands.items.len, off, off + sizeofcmds }); + log.debug("writing {} load commands from 0x{x} to 0x{x}", .{ self.load_commands.items.len, off, off + sizeofcmds }); try self.file.pwriteAll(buffer, off); self.load_commands_dirty = false; } fn writeHeader(self: *DebugSymbols) !void { - if (!self.header_dirty) return; + var header = emptyHeader(.{ + .filetype = macho.MH_DSYM, + }); - self.header.?.ncmds = @intCast(u32, self.load_commands.items.len); - var sizeofcmds: u32 = 0; - for (self.load_commands.items) |cmd| { - sizeofcmds += cmd.cmdsize(); + switch (self.base.base.options.target.cpu.arch) { + .aarch64 => { + header.cputype = macho.CPU_TYPE_ARM64; + header.cpusubtype = macho.CPU_SUBTYPE_ARM_ALL; + }, + .x86_64 => { + header.cputype = macho.CPU_TYPE_X86_64; + header.cpusubtype = macho.CPU_SUBTYPE_X86_64_ALL; + }, + else => return error.UnsupportedCpuArchitecture, } - self.header.?.sizeofcmds = sizeofcmds; - log.debug("writing Mach-O dSym header {}", .{self.header.?}); - try self.file.pwriteAll(mem.asBytes(&self.header.?), 0); - self.header_dirty = false; + + header.ncmds = @intCast(u32, self.load_commands.items.len); + header.sizeofcmds = 0; + + for (self.load_commands.items) |cmd| { + header.sizeofcmds += cmd.cmdsize(); + } + + log.debug("writing Mach-O header {}", .{header}); + + try self.file.pwriteAll(mem.asBytes(&header), 0); } fn allocatedSizeLinkedit(self: *DebugSymbols, start: u64) u64 { @@ -798,7 +780,7 @@ fn relocateSymbolTable(self: *DebugSymbols) !void { const existing_size = symtab.nsyms * @sizeOf(macho.nlist_64); assert(new_symoff + existing_size <= self.linkedit_off + self.linkedit_size); // TODO expand LINKEDIT segment. - log.debug("relocating dSym symbol table from 0x{x}-0x{x} to 0x{x}-0x{x}", .{ + log.debug("relocating symbol table from 0x{x}-0x{x} to 0x{x}-0x{x}", .{ symtab.symoff, symtab.symoff + existing_size, new_symoff, @@ -820,7 +802,7 @@ pub fn writeLocalSymbol(self: *DebugSymbols, index: usize) !void { try self.relocateSymbolTable(); const symtab = &self.load_commands.items[self.symtab_cmd_index.?].Symtab; const off = symtab.symoff + @sizeOf(macho.nlist_64) * index; - log.debug("writing dSym local symbol {} at 0x{x}", .{ index, off }); + log.debug("writing local symbol {} at 0x{x}", .{ index, off }); try self.file.pwriteAll(mem.asBytes(&self.base.locals.items[index]), off); } @@ -839,7 +821,7 @@ fn writeStringTable(self: *DebugSymbols) !void { symtab.stroff = @intCast(u32, self.findFreeSpaceLinkedit(needed_size, 1)); } symtab.strsize = @intCast(u32, needed_size); - log.debug("writing dSym string table from 0x{x} to 0x{x}", .{ symtab.stroff, symtab.stroff + symtab.strsize }); + log.debug("writing string table from 0x{x} to 0x{x}", .{ symtab.stroff, symtab.stroff + symtab.strsize }); try self.file.pwriteAll(self.base.string_table.items, symtab.stroff); self.load_commands_dirty = true; diff --git a/src/link/MachO/Zld.zig b/src/link/MachO/Zld.zig index 454b5dbcfe..d223e04fd7 100644 --- a/src/link/MachO/Zld.zig +++ b/src/link/MachO/Zld.zig @@ -3132,54 +3132,44 @@ fn writeLoadCommands(self: *Zld) !void { } fn writeHeader(self: *Zld) !void { - var header: macho.mach_header_64 = undefined; - header.magic = macho.MH_MAGIC_64; + var header = emptyHeader(.{ + .flags = macho.MH_NOUNDEFS | macho.MH_DYLDLINK | macho.MH_PIE | macho.MH_TWOLEVEL, + }); - const CpuInfo = struct { - cpu_type: macho.cpu_type_t, - cpu_subtype: macho.cpu_subtype_t, - }; - - const cpu_info: CpuInfo = switch (self.target.?.cpu.arch) { - .aarch64 => .{ - .cpu_type = macho.CPU_TYPE_ARM64, - .cpu_subtype = macho.CPU_SUBTYPE_ARM_ALL, + switch (self.target.?.cpu.arch) { + .aarch64 => { + header.cputype = macho.CPU_TYPE_ARM64; + header.cpusubtype = macho.CPU_SUBTYPE_ARM_ALL; }, - .x86_64 => .{ - .cpu_type = macho.CPU_TYPE_X86_64, - .cpu_subtype = macho.CPU_SUBTYPE_X86_64_ALL, + .x86_64 => { + header.cputype = macho.CPU_TYPE_X86_64; + header.cpusubtype = macho.CPU_SUBTYPE_X86_64_ALL; }, else => return error.UnsupportedCpuArchitecture, - }; - header.cputype = cpu_info.cpu_type; - header.cpusubtype = cpu_info.cpu_subtype; + } switch (self.output.?.tag) { .exe => { header.filetype = macho.MH_EXECUTE; - header.flags = macho.MH_NOUNDEFS | macho.MH_DYLDLINK | macho.MH_PIE | macho.MH_TWOLEVEL; }, .dylib => { header.filetype = macho.MH_DYLIB; - header.flags = macho.MH_NOUNDEFS | - macho.MH_DYLDLINK | - macho.MH_PIE | - macho.MH_TWOLEVEL | - macho.MH_NO_REEXPORTED_DYLIBS; + header.flags |= macho.MH_NO_REEXPORTED_DYLIBS; }, } - header.reserved = 0; - if (self.tlv_section_index) |_| header.flags |= macho.MH_HAS_TLV_DESCRIPTORS; header.ncmds = @intCast(u32, self.load_commands.items.len); header.sizeofcmds = 0; + for (self.load_commands.items) |cmd| { header.sizeofcmds += cmd.cmdsize(); } + log.debug("writing Mach-O header {}", .{header}); + try self.file.?.pwriteAll(mem.asBytes(&header), 0); } diff --git a/src/link/MachO/commands.zig b/src/link/MachO/commands.zig index 6958b8d1e6..5919496526 100644 --- a/src/link/MachO/commands.zig +++ b/src/link/MachO/commands.zig @@ -11,6 +11,28 @@ const Allocator = std.mem.Allocator; const MachO = @import("../MachO.zig"); const padToIdeal = MachO.padToIdeal; +pub const HeaderArgs = struct { + magic: u32 = macho.MH_MAGIC_64, + cputype: macho.cpu_type_t = 0, + cpusubtype: macho.cpu_subtype_t = 0, + filetype: u32 = 0, + flags: u32 = 0, + reserved: u32 = 0, +}; + +pub fn emptyHeader(args: HeaderArgs) macho.mach_header_64 { + return .{ + .magic = args.magic, + .cputype = args.cputype, + .cpusubtype = args.cpusubtype, + .filetype = args.filetype, + .ncmds = 0, + .sizeofcmds = 0, + .flags = args.flags, + .reserved = args.reserved, + }; +} + pub const LoadCommand = union(enum) { Segment: SegmentCommand, DyldInfoOnly: macho.dyld_info_command,