Commit d9ce7a021b

Jakub Konka <kubkon@jakubkonka.com>
2020-12-27 10:59:54
macho: copy snapshots of segment commands
1 parent a7bae1b
Changed files (2)
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, &sect.sectname, &base_sect.sectname);
+        mem.copy(u8, &sect.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;
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;