diff --git a/src/link/MachO.zig b/src/link/MachO.zig index 510d7b74fb..90c4757979 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -1427,7 +1427,7 @@ pub fn populateMissingMetadata(self: *MachO) !void { .addr = text_segment.inner.vmaddr + off, .size = needed_size, .offset = @intCast(u32, off), - .@"align" = @sizeOf(u64), + .@"align" = 3, // 2^@sizeOf(u64) .reloff = 0, .nreloc = 0, .flags = flags, @@ -1749,8 +1749,14 @@ fn allocateTextBlock(self: *MachO, text_block: *TextBlock, new_block_size: u64, self.last_text_block = text_block; text_section.size = needed_size; - self.load_commands_dirty = true; // TODO Make more granular. + + if (self.d_sym) |*ds| { + const debug_text_seg = &ds.load_commands.items[ds.text_segment_cmd_index.?].Segment; + const debug_text_sect = &debug_text_seg.sections.items[ds.text_section_index.?]; + debug_text_sect.size = needed_size; + ds.load_commands_dirty = true; + } } text_block.size = new_block_size; diff --git a/src/link/MachO/DebugSymbols.zig b/src/link/MachO/DebugSymbols.zig index 3882eaca69..22d7e04fef 100644 --- a/src/link/MachO/DebugSymbols.zig +++ b/src/link/MachO/DebugSymbols.zig @@ -26,17 +26,20 @@ load_commands: std.ArrayListUnmanaged(LoadCommand) = .{}, pagezero_segment_cmd_index: ?u16 = null, /// __TEXT segment text_segment_cmd_index: ?u16 = null, -/// __DWARF segment -dwarf_segment_cmd_index: ?u16 = null, /// __DATA segment data_segment_cmd_index: ?u16 = null, /// __LINKEDIT segment linkedit_segment_cmd_index: ?u16 = null, +/// __DWARF segment +dwarf_segment_cmd_index: ?u16 = null, /// Symbol table symtab_cmd_index: ?u16 = null, /// UUID load command uuid_cmd_index: ?u16 = null, +/// Index into __TEXT,__text section. +text_section_index: ?u16 = null, + header_dirty: bool = false, load_commands_dirty: bool = false, @@ -58,6 +61,22 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void 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); + const base_cmd = self.base.load_commands.items[self.base.pagezero_segment_cmd_index.?].Segment; + try self.copySegmentCommand(allocator, base_cmd); + } + if (self.text_segment_cmd_index == null) { + self.text_segment_cmd_index = @intCast(u16, self.load_commands.items.len); + const base_cmd = self.base.load_commands.items[self.base.text_segment_cmd_index.?].Segment; + try self.copySegmentCommand(allocator, base_cmd); + } + if (self.data_segment_cmd_index == null) outer: { + if (self.base.data_segment_cmd_index == null) break :outer; // __DATA is optional + self.data_segment_cmd_index = @intCast(u16, self.load_commands.items.len); + const base_cmd = self.base.load_commands.items[self.base.data_segment_cmd_index.?].Segment; + try self.copySegmentCommand(allocator, base_cmd); + } 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); @@ -81,6 +100,53 @@ pub fn deinit(self: *DebugSymbols, allocator: *Allocator) void { self.file.close(); } +fn copySegmentCommand(self: *DebugSymbols, allocator: *Allocator, base_cmd: SegmentCommand) !void { + var cmd = SegmentCommand.empty(.{ + .cmd = macho.LC_SEGMENT_64, + .cmdsize = base_cmd.inner.cmdsize, + .segname = undefined, + .vmaddr = base_cmd.inner.vmaddr, + .vmsize = base_cmd.inner.vmsize, + .fileoff = 0, + .filesize = 0, + .maxprot = base_cmd.inner.maxprot, + .initprot = base_cmd.inner.initprot, + .nsects = base_cmd.inner.nsects, + .flags = base_cmd.inner.flags, + }); + mem.copy(u8, &cmd.inner.segname, &base_cmd.inner.segname); + + try cmd.sections.ensureCapacity(allocator, cmd.inner.nsects); + for (base_cmd.sections.items) |base_sect, i| { + var sect = macho.section_64{ + .sectname = undefined, + .segname = undefined, + .addr = base_sect.addr, + .size = base_sect.size, + .offset = 0, + .@"align" = base_sect.@"align", + .reloff = 0, + .nreloc = 0, + .flags = base_sect.flags, + .reserved1 = base_sect.reserved1, + .reserved2 = base_sect.reserved2, + .reserved3 = base_sect.reserved3, + }; + mem.copy(u8, §.sectname, &base_sect.sectname); + mem.copy(u8, §.segname, &base_sect.segname); + + if (self.base.text_section_index.? == i) { + self.text_section_index = @intCast(u16, i); + } + + cmd.sections.appendAssumeCapacity(sect); + } + + try self.load_commands.append(allocator, .{ .Segment = cmd }); + self.header_dirty = true; + self.load_commands_dirty = true; +} + /// Writes all load commands and section headers. fn writeLoadCommands(self: *DebugSymbols, allocator: *Allocator) !void { if (!self.load_commands_dirty) return;