Commit 852e1ed23c

Jakub Konka <kubkon@jakubkonka.com>
2021-06-21 11:11:19
zld+stage2: refactor creating segments and sections
Move the logic into default-init structs part of constructors in `SegmentCommand` struct in `commands.zig` module.
1 parent 72f2f68
src/link/MachO/commands.zig
@@ -9,7 +9,6 @@ const assert = std.debug.assert;
 
 const Allocator = std.mem.Allocator;
 const MachO = @import("../MachO.zig");
-const makeStaticString = MachO.makeStaticString;
 const padToIdeal = MachO.padToIdeal;
 
 pub const LoadCommand = union(enum) {
@@ -187,12 +186,70 @@ pub const SegmentCommand = struct {
     inner: macho.segment_command_64,
     sections: std.ArrayListUnmanaged(macho.section_64) = .{},
 
-    pub fn empty(inner: macho.segment_command_64) SegmentCommand {
-        return .{ .inner = inner };
+    const SegmentOptions = struct {
+        cmdsize: u32 = @sizeOf(macho.segment_command_64),
+        vmaddr: u64 = 0,
+        vmsize: u64 = 0,
+        fileoff: u64 = 0,
+        filesize: u64 = 0,
+        maxprot: macho.vm_prot_t = macho.VM_PROT_NONE,
+        initprot: macho.vm_prot_t = macho.VM_PROT_NONE,
+        nsects: u32 = 0,
+        flags: u32 = 0,
+    };
+
+    pub fn empty(comptime segname: []const u8, opts: SegmentOptions) SegmentCommand {
+        return .{
+            .inner = .{
+                .cmd = macho.LC_SEGMENT_64,
+                .cmdsize = opts.cmdsize,
+                .segname = makeStaticString(segname),
+                .vmaddr = opts.vmaddr,
+                .vmsize = opts.vmsize,
+                .fileoff = opts.fileoff,
+                .filesize = opts.filesize,
+                .maxprot = opts.maxprot,
+                .initprot = opts.initprot,
+                .nsects = opts.nsects,
+                .flags = opts.flags,
+            },
+        };
     }
 
-    pub fn addSection(self: *SegmentCommand, alloc: *Allocator, section: macho.section_64) !void {
-        try self.sections.append(alloc, section);
+    const SectionOptions = struct {
+        addr: u64 = 0,
+        size: u64 = 0,
+        offset: u32 = 0,
+        @"align": u32 = 0,
+        reloff: u32 = 0,
+        nreloc: u32 = 0,
+        flags: u32 = macho.S_REGULAR,
+        reserved1: u32 = 0,
+        reserved2: u32 = 0,
+        reserved3: u32 = 0,
+    };
+
+    pub fn addSection(
+        self: *SegmentCommand,
+        alloc: *Allocator,
+        comptime sectname: []const u8,
+        comptime segname: []const u8,
+        opts: SectionOptions,
+    ) !void {
+        try self.sections.append(alloc, .{
+            .sectname = makeStaticString(sectname),
+            .segname = makeStaticString(segname),
+            .addr = opts.addr,
+            .size = opts.size,
+            .offset = opts.offset,
+            .@"align" = opts.@"align",
+            .reloff = opts.reloff,
+            .nreloc = opts.nreloc,
+            .flags = opts.flags,
+            .reserved1 = opts.reserved1,
+            .reserved2 = opts.reserved2,
+            .reserved3 = opts.reserved3,
+        });
         self.inner.cmdsize += @sizeOf(macho.section_64);
         self.inner.nsects += 1;
     }
@@ -338,6 +395,13 @@ pub fn createLoadDylibCommand(
     return dylib_cmd;
 }
 
+fn makeStaticString(bytes: []const u8) [16]u8 {
+    var buf = [_]u8{0} ** 16;
+    assert(bytes.len <= buf.len);
+    mem.copy(u8, &buf, bytes);
+    return buf;
+}
+
 fn testRead(allocator: *Allocator, buffer: []const u8, expected: anytype) !void {
     var stream = io.fixedBufferStream(buffer);
     var given = try LoadCommand.read(allocator, stream.reader());
src/link/MachO/DebugSymbols.zig
@@ -19,7 +19,6 @@ const MachO = @import("../MachO.zig");
 const SrcFn = MachO.SrcFn;
 const TextBlock = MachO.TextBlock;
 const padToIdeal = MachO.padToIdeal;
-const makeStaticString = MachO.makeStaticString;
 
 usingnamespace @import("commands.zig");
 
@@ -212,18 +211,11 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void
         log.debug("found dSym __DWARF segment free space 0x{x} to 0x{x}", .{ off, off + needed_size });
 
         try self.load_commands.append(allocator, .{
-            .Segment = SegmentCommand.empty(.{
-                .cmd = macho.LC_SEGMENT_64,
-                .cmdsize = @sizeOf(macho.segment_command_64),
-                .segname = makeStaticString("__DWARF"),
+            .Segment = SegmentCommand.empty("__DWARF", .{
                 .vmaddr = vmaddr,
                 .vmsize = needed_size,
                 .fileoff = off,
                 .filesize = needed_size,
-                .maxprot = 0,
-                .initprot = 0,
-                .nsects = 0,
-                .flags = 0,
             }),
         });
         self.header_dirty = true;
@@ -234,19 +226,11 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void
         self.debug_str_section_index = @intCast(u16, dwarf_segment.sections.items.len);
         assert(self.debug_string_table.items.len == 0);
 
-        try dwarf_segment.addSection(allocator, .{
-            .sectname = makeStaticString("__debug_str"),
-            .segname = makeStaticString("__DWARF"),
+        try dwarf_segment.addSection(allocator, "__debug_str", "__DWARF", .{
             .addr = dwarf_segment.inner.vmaddr,
             .size = @intCast(u32, self.debug_string_table.items.len),
             .offset = @intCast(u32, dwarf_segment.inner.fileoff),
             .@"align" = 1,
-            .reloff = 0,
-            .nreloc = 0,
-            .flags = macho.S_REGULAR,
-            .reserved1 = 0,
-            .reserved2 = 0,
-            .reserved3 = 0,
         });
         self.header_dirty = true;
         self.load_commands_dirty = true;
@@ -262,19 +246,11 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void
 
         log.debug("found dSym __debug_info free space 0x{x} to 0x{x}", .{ off, off + file_size_hint });
 
-        try dwarf_segment.addSection(allocator, .{
-            .sectname = makeStaticString("__debug_info"),
-            .segname = makeStaticString("__DWARF"),
+        try dwarf_segment.addSection(allocator, "__debug_info", "__DWARF", .{
             .addr = dwarf_segment.inner.vmaddr + off - dwarf_segment.inner.fileoff,
             .size = file_size_hint,
             .offset = @intCast(u32, off),
             .@"align" = p_align,
-            .reloff = 0,
-            .nreloc = 0,
-            .flags = macho.S_REGULAR,
-            .reserved1 = 0,
-            .reserved2 = 0,
-            .reserved3 = 0,
         });
         self.header_dirty = true;
         self.load_commands_dirty = true;
@@ -290,19 +266,11 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void
 
         log.debug("found dSym __debug_abbrev free space 0x{x} to 0x{x}", .{ off, off + file_size_hint });
 
-        try dwarf_segment.addSection(allocator, .{
-            .sectname = makeStaticString("__debug_abbrev"),
-            .segname = makeStaticString("__DWARF"),
+        try dwarf_segment.addSection(allocator, "__debug_abbrev", "__DWARF", .{
             .addr = dwarf_segment.inner.vmaddr + off - dwarf_segment.inner.fileoff,
             .size = file_size_hint,
             .offset = @intCast(u32, off),
             .@"align" = p_align,
-            .reloff = 0,
-            .nreloc = 0,
-            .flags = macho.S_REGULAR,
-            .reserved1 = 0,
-            .reserved2 = 0,
-            .reserved3 = 0,
         });
         self.header_dirty = true;
         self.load_commands_dirty = true;
@@ -318,19 +286,11 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void
 
         log.debug("found dSym __debug_aranges free space 0x{x} to 0x{x}", .{ off, off + file_size_hint });
 
-        try dwarf_segment.addSection(allocator, .{
-            .sectname = makeStaticString("__debug_aranges"),
-            .segname = makeStaticString("__DWARF"),
+        try dwarf_segment.addSection(allocator, "__debug_aranges", "__DWARF", .{
             .addr = dwarf_segment.inner.vmaddr + off - dwarf_segment.inner.fileoff,
             .size = file_size_hint,
             .offset = @intCast(u32, off),
             .@"align" = p_align,
-            .reloff = 0,
-            .nreloc = 0,
-            .flags = macho.S_REGULAR,
-            .reserved1 = 0,
-            .reserved2 = 0,
-            .reserved3 = 0,
         });
         self.header_dirty = true;
         self.load_commands_dirty = true;
@@ -346,19 +306,11 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void
 
         log.debug("found dSym __debug_line free space 0x{x} to 0x{x}", .{ off, off + file_size_hint });
 
-        try dwarf_segment.addSection(allocator, .{
-            .sectname = makeStaticString("__debug_line"),
-            .segname = makeStaticString("__DWARF"),
+        try dwarf_segment.addSection(allocator, "__debug_line", "__DWARF", .{
             .addr = dwarf_segment.inner.vmaddr + off - dwarf_segment.inner.fileoff,
             .size = file_size_hint,
             .offset = @intCast(u32, off),
             .@"align" = p_align,
-            .reloff = 0,
-            .nreloc = 0,
-            .flags = macho.S_REGULAR,
-            .reserved1 = 0,
-            .reserved2 = 0,
-            .reserved3 = 0,
         });
         self.header_dirty = true;
         self.load_commands_dirty = true;
@@ -692,14 +644,10 @@ pub fn deinit(self: *DebugSymbols, allocator: *Allocator) void {
 }
 
 fn copySegmentCommand(self: *DebugSymbols, allocator: *Allocator, base_cmd: SegmentCommand) !SegmentCommand {
-    var cmd = SegmentCommand.empty(.{
-        .cmd = macho.LC_SEGMENT_64,
+    var cmd = SegmentCommand.empty("", .{
         .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,
src/link/MachO/Stub.zig
@@ -60,7 +60,7 @@ pub fn parse(self: *Stub) !void {
     const lib_stub = self.lib_stub orelse return error.EmptyStubFile;
     if (lib_stub.inner.len == 0) return error.EmptyStubFile;
 
-    log.warn("parsing shared library from stub '{s}'", .{self.name.?});
+    log.debug("parsing shared library from stub '{s}'", .{self.name.?});
 
     const umbrella_lib = lib_stub.inner[0];
     self.id = .{
@@ -93,14 +93,26 @@ pub fn parse(self: *Stub) !void {
 
                 if (exp.objc_classes) |classes| {
                     for (classes) |sym_name| {
-                        log.warn("    | {s}", .{sym_name});
-                        const actual_sym_name = try std.fmt.allocPrint(
-                            self.allocator,
-                            "_OBJC_CLASS_$_{s}",
-                            .{sym_name},
-                        );
-                        if (self.symbols.contains(actual_sym_name)) continue;
-                        try self.symbols.putNoClobber(self.allocator, actual_sym_name, {});
+                        log.debug("    | {s}", .{sym_name});
+                        {
+                            const actual_sym_name = try std.fmt.allocPrint(
+                                self.allocator,
+                                "_OBJC_CLASS_$_{s}",
+                                .{sym_name},
+                            );
+                            if (self.symbols.contains(actual_sym_name)) continue;
+                            try self.symbols.putNoClobber(self.allocator, actual_sym_name, {});
+                        }
+
+                        {
+                            const actual_sym_name = try std.fmt.allocPrint(
+                                self.allocator,
+                                "_OBJC_METACLASS_$_{s}",
+                                .{sym_name},
+                            );
+                            if (self.symbols.contains(actual_sym_name)) continue;
+                            try self.symbols.putNoClobber(self.allocator, actual_sym_name, {});
+                        }
                     }
                 }
             }
@@ -118,16 +130,28 @@ pub fn parse(self: *Stub) !void {
         }
 
         if (stub.objc_classes) |classes| {
-            log.warn("  | objc_classes", .{});
+            log.debug("  | objc_classes", .{});
             for (classes) |sym_name| {
-                log.warn("    | {s}", .{sym_name});
-                const actual_sym_name = try std.fmt.allocPrint(
-                    self.allocator,
-                    "_OBJC_METACLASS_$_{s}",
-                    .{sym_name},
-                );
-                if (self.symbols.contains(actual_sym_name)) continue;
-                try self.symbols.putNoClobber(self.allocator, actual_sym_name, {});
+                log.debug("    | {s}", .{sym_name});
+                {
+                    const actual_sym_name = try std.fmt.allocPrint(
+                        self.allocator,
+                        "_OBJC_CLASS_$_{s}",
+                        .{sym_name},
+                    );
+                    if (self.symbols.contains(actual_sym_name)) continue;
+                    try self.symbols.putNoClobber(self.allocator, actual_sym_name, {});
+                }
+
+                {
+                    const actual_sym_name = try std.fmt.allocPrint(
+                        self.allocator,
+                        "_OBJC_METACLASS_$_{s}",
+                        .{sym_name},
+                    );
+                    if (self.symbols.contains(actual_sym_name)) continue;
+                    try self.symbols.putNoClobber(self.allocator, actual_sym_name, {});
+                }
             }
         }
     }
src/link/MachO/Zld.zig
@@ -79,6 +79,8 @@ mod_init_func_section_index: ?u16 = null,
 mod_term_func_section_index: ?u16 = null,
 data_const_section_index: ?u16 = null,
 
+objc_cfstring_section_index: ?u16 = null,
+
 // __DATA segment sections
 tlv_section_index: ?u16 = null,
 tlv_data_section_index: ?u16 = null,
@@ -515,39 +517,15 @@ fn updateMetadata(self: *Zld) !void {
                     if (self.text_const_section_index != null) continue;
 
                     self.text_const_section_index = @intCast(u16, text_seg.sections.items.len);
-                    try text_seg.addSection(self.allocator, .{
-                        .sectname = makeStaticString("__const"),
-                        .segname = makeStaticString("__TEXT"),
-                        .addr = 0,
-                        .size = 0,
-                        .offset = 0,
-                        .@"align" = 0,
-                        .reloff = 0,
-                        .nreloc = 0,
-                        .flags = macho.S_REGULAR,
-                        .reserved1 = 0,
-                        .reserved2 = 0,
-                        .reserved3 = 0,
-                    });
+                    try text_seg.addSection(self.allocator, "__const", "__TEXT", .{});
                     continue;
                 },
                 macho.S_CSTRING_LITERALS => {
                     if (self.cstring_section_index != null) continue;
 
                     self.cstring_section_index = @intCast(u16, text_seg.sections.items.len);
-                    try text_seg.addSection(self.allocator, .{
-                        .sectname = makeStaticString("__cstring"),
-                        .segname = makeStaticString("__TEXT"),
-                        .addr = 0,
-                        .size = 0,
-                        .offset = 0,
-                        .@"align" = 0,
-                        .reloff = 0,
-                        .nreloc = 0,
+                    try text_seg.addSection(self.allocator, "__cstring", "__TEXT", .{
                         .flags = macho.S_CSTRING_LITERALS,
-                        .reserved1 = 0,
-                        .reserved2 = 0,
-                        .reserved3 = 0,
                     });
                     continue;
                 },
@@ -555,19 +533,8 @@ fn updateMetadata(self: *Zld) !void {
                     if (self.mod_init_func_section_index != null) continue;
 
                     self.mod_init_func_section_index = @intCast(u16, data_const_seg.sections.items.len);
-                    try data_const_seg.addSection(self.allocator, .{
-                        .sectname = makeStaticString("__mod_init_func"),
-                        .segname = makeStaticString("__DATA_CONST"),
-                        .addr = 0,
-                        .size = 0,
-                        .offset = 0,
-                        .@"align" = 0,
-                        .reloff = 0,
-                        .nreloc = 0,
+                    try data_const_seg.addSection(self.allocator, "__mod_init_func", "__DATA_CONST", .{
                         .flags = macho.S_MOD_INIT_FUNC_POINTERS,
-                        .reserved1 = 0,
-                        .reserved2 = 0,
-                        .reserved3 = 0,
                     });
                     continue;
                 },
@@ -575,19 +542,8 @@ fn updateMetadata(self: *Zld) !void {
                     if (self.mod_term_func_section_index != null) continue;
 
                     self.mod_term_func_section_index = @intCast(u16, data_const_seg.sections.items.len);
-                    try data_const_seg.addSection(self.allocator, .{
-                        .sectname = makeStaticString("__mod_term_func"),
-                        .segname = makeStaticString("__DATA_CONST"),
-                        .addr = 0,
-                        .size = 0,
-                        .offset = 0,
-                        .@"align" = 0,
-                        .reloff = 0,
-                        .nreloc = 0,
+                    try data_const_seg.addSection(self.allocator, "__mod_term_func", "__DATA_CONST", .{
                         .flags = macho.S_MOD_TERM_FUNC_POINTERS,
-                        .reserved1 = 0,
-                        .reserved2 = 0,
-                        .reserved3 = 0,
                     });
                     continue;
                 },
@@ -596,37 +552,15 @@ fn updateMetadata(self: *Zld) !void {
                         if (self.common_section_index != null) continue;
 
                         self.common_section_index = @intCast(u16, data_seg.sections.items.len);
-                        try data_seg.addSection(self.allocator, .{
-                            .sectname = makeStaticString("__common"),
-                            .segname = makeStaticString("__DATA"),
-                            .addr = 0,
-                            .size = 0,
-                            .offset = 0,
-                            .@"align" = 0,
-                            .reloff = 0,
-                            .nreloc = 0,
+                        try data_seg.addSection(self.allocator, "__common", "__DATA", .{
                             .flags = macho.S_ZEROFILL,
-                            .reserved1 = 0,
-                            .reserved2 = 0,
-                            .reserved3 = 0,
                         });
                     } else {
                         if (self.bss_section_index != null) continue;
 
                         self.bss_section_index = @intCast(u16, data_seg.sections.items.len);
-                        try data_seg.addSection(self.allocator, .{
-                            .sectname = makeStaticString("__bss"),
-                            .segname = makeStaticString("__DATA"),
-                            .addr = 0,
-                            .size = 0,
-                            .offset = 0,
-                            .@"align" = 0,
-                            .reloff = 0,
-                            .nreloc = 0,
+                        try data_seg.addSection(self.allocator, "__bss", "__DATA", .{
                             .flags = macho.S_ZEROFILL,
-                            .reserved1 = 0,
-                            .reserved2 = 0,
-                            .reserved3 = 0,
                         });
                     }
                     continue;
@@ -635,19 +569,8 @@ fn updateMetadata(self: *Zld) !void {
                     if (self.tlv_section_index != null) continue;
 
                     self.tlv_section_index = @intCast(u16, data_seg.sections.items.len);
-                    try data_seg.addSection(self.allocator, .{
-                        .sectname = makeStaticString("__thread_vars"),
-                        .segname = makeStaticString("__DATA"),
-                        .addr = 0,
-                        .size = 0,
-                        .offset = 0,
-                        .@"align" = 0,
-                        .reloff = 0,
-                        .nreloc = 0,
+                    try data_seg.addSection(self.allocator, "__thread_vars", "__DATA", .{
                         .flags = macho.S_THREAD_LOCAL_VARIABLES,
-                        .reserved1 = 0,
-                        .reserved2 = 0,
-                        .reserved3 = 0,
                     });
                     continue;
                 },
@@ -655,19 +578,8 @@ fn updateMetadata(self: *Zld) !void {
                     if (self.tlv_data_section_index != null) continue;
 
                     self.tlv_data_section_index = @intCast(u16, data_seg.sections.items.len);
-                    try data_seg.addSection(self.allocator, .{
-                        .sectname = makeStaticString("__thread_data"),
-                        .segname = makeStaticString("__DATA"),
-                        .addr = 0,
-                        .size = 0,
-                        .offset = 0,
-                        .@"align" = 0,
-                        .reloff = 0,
-                        .nreloc = 0,
+                    try data_seg.addSection(self.allocator, "__thread_data", "__DATA", .{
                         .flags = macho.S_THREAD_LOCAL_REGULAR,
-                        .reserved1 = 0,
-                        .reserved2 = 0,
-                        .reserved3 = 0,
                     });
                     continue;
                 },
@@ -675,19 +587,8 @@ fn updateMetadata(self: *Zld) !void {
                     if (self.tlv_bss_section_index != null) continue;
 
                     self.tlv_bss_section_index = @intCast(u16, data_seg.sections.items.len);
-                    try data_seg.addSection(self.allocator, .{
-                        .sectname = makeStaticString("__thread_bss"),
-                        .segname = makeStaticString("__DATA"),
-                        .addr = 0,
-                        .size = 0,
-                        .offset = 0,
-                        .@"align" = 0,
-                        .reloff = 0,
-                        .nreloc = 0,
+                    try data_seg.addSection(self.allocator, "__thread_bss", "__DATA", .{
                         .flags = macho.S_THREAD_LOCAL_ZEROFILL,
-                        .reserved1 = 0,
-                        .reserved2 = 0,
-                        .reserved3 = 0,
                     });
                     continue;
                 },
@@ -698,20 +599,7 @@ fn updateMetadata(self: *Zld) !void {
                         if (self.eh_frame_section_index != null) continue;
 
                         self.eh_frame_section_index = @intCast(u16, text_seg.sections.items.len);
-                        try text_seg.addSection(self.allocator, .{
-                            .sectname = makeStaticString("__eh_frame"),
-                            .segname = makeStaticString("__TEXT"),
-                            .addr = 0,
-                            .size = 0,
-                            .offset = 0,
-                            .@"align" = 0,
-                            .reloff = 0,
-                            .nreloc = 0,
-                            .flags = macho.S_REGULAR,
-                            .reserved1 = 0,
-                            .reserved2 = 0,
-                            .reserved3 = 0,
-                        });
+                        try text_seg.addSection(self.allocator, "__eh_frame", "__TEXT", .{});
                         continue;
                     }
 
@@ -719,20 +607,7 @@ fn updateMetadata(self: *Zld) !void {
                     if (self.data_const_section_index != null) continue;
 
                     self.data_const_section_index = @intCast(u16, data_const_seg.sections.items.len);
-                    try data_const_seg.addSection(self.allocator, .{
-                        .sectname = makeStaticString("__const"),
-                        .segname = makeStaticString("__DATA_CONST"),
-                        .addr = 0,
-                        .size = 0,
-                        .offset = 0,
-                        .@"align" = 0,
-                        .reloff = 0,
-                        .nreloc = 0,
-                        .flags = macho.S_REGULAR,
-                        .reserved1 = 0,
-                        .reserved2 = 0,
-                        .reserved3 = 0,
-                    });
+                    try data_const_seg.addSection(self.allocator, "__const", "__DATA_CONST", .{});
                     continue;
                 },
                 macho.S_REGULAR => {
@@ -740,19 +615,8 @@ fn updateMetadata(self: *Zld) !void {
                         if (self.text_section_index != null) continue;
 
                         self.text_section_index = @intCast(u16, text_seg.sections.items.len);
-                        try text_seg.addSection(self.allocator, .{
-                            .sectname = makeStaticString("__text"),
-                            .segname = makeStaticString("__TEXT"),
-                            .addr = 0,
-                            .size = 0,
-                            .offset = 0,
-                            .@"align" = 0,
-                            .reloff = 0,
-                            .nreloc = 0,
+                        try text_seg.addSection(self.allocator, "__text", "__TEXT", .{
                             .flags = macho.S_REGULAR | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS,
-                            .reserved1 = 0,
-                            .reserved2 = 0,
-                            .reserved3 = 0,
                         });
                         continue;
                     }
@@ -771,56 +635,17 @@ fn updateMetadata(self: *Zld) !void {
                             if (self.ustring_section_index != null) continue;
 
                             self.ustring_section_index = @intCast(u16, text_seg.sections.items.len);
-                            try text_seg.addSection(self.allocator, .{
-                                .sectname = makeStaticString("__ustring"),
-                                .segname = makeStaticString("__TEXT"),
-                                .addr = 0,
-                                .size = 0,
-                                .offset = 0,
-                                .@"align" = 0,
-                                .reloff = 0,
-                                .nreloc = 0,
-                                .flags = macho.S_REGULAR,
-                                .reserved1 = 0,
-                                .reserved2 = 0,
-                                .reserved3 = 0,
-                            });
+                            try text_seg.addSection(self.allocator, "__ustring", "__TEXT", .{});
                         } else if (mem.eql(u8, sectname, "__gcc_except_tab")) {
                             if (self.gcc_except_tab_section_index != null) continue;
 
                             self.gcc_except_tab_section_index = @intCast(u16, text_seg.sections.items.len);
-                            try text_seg.addSection(self.allocator, .{
-                                .sectname = makeStaticString("__gcc_except_tab"),
-                                .segname = makeStaticString("__TEXT"),
-                                .addr = 0,
-                                .size = 0,
-                                .offset = 0,
-                                .@"align" = 0,
-                                .reloff = 0,
-                                .nreloc = 0,
-                                .flags = macho.S_REGULAR,
-                                .reserved1 = 0,
-                                .reserved2 = 0,
-                                .reserved3 = 0,
-                            });
+                            try text_seg.addSection(self.allocator, "__gcc_except_tab", "__TEXT", .{});
                         } else {
                             if (self.text_const_section_index != null) continue;
 
                             self.text_const_section_index = @intCast(u16, text_seg.sections.items.len);
-                            try text_seg.addSection(self.allocator, .{
-                                .sectname = makeStaticString("__const"),
-                                .segname = makeStaticString("__TEXT"),
-                                .addr = 0,
-                                .size = 0,
-                                .offset = 0,
-                                .@"align" = 0,
-                                .reloff = 0,
-                                .nreloc = 0,
-                                .flags = macho.S_REGULAR,
-                                .reserved1 = 0,
-                                .reserved2 = 0,
-                                .reserved3 = 0,
-                            });
+                            try text_seg.addSection(self.allocator, "__const", "__TEXT", .{});
                         }
                         continue;
                     }
@@ -829,20 +654,7 @@ fn updateMetadata(self: *Zld) !void {
                         if (self.data_const_section_index != null) continue;
 
                         self.data_const_section_index = @intCast(u16, data_const_seg.sections.items.len);
-                        try data_const_seg.addSection(self.allocator, .{
-                            .sectname = makeStaticString("__const"),
-                            .segname = makeStaticString("__DATA_CONST"),
-                            .addr = 0,
-                            .size = 0,
-                            .offset = 0,
-                            .@"align" = 0,
-                            .reloff = 0,
-                            .nreloc = 0,
-                            .flags = macho.S_REGULAR,
-                            .reserved1 = 0,
-                            .reserved2 = 0,
-                            .reserved3 = 0,
-                        });
+                        try data_const_seg.addSection(self.allocator, "__const", "__DATA_CONST", .{});
                         continue;
                     }
 
@@ -851,38 +663,17 @@ fn updateMetadata(self: *Zld) !void {
                             if (self.data_const_section_index != null) continue;
 
                             self.data_const_section_index = @intCast(u16, data_const_seg.sections.items.len);
-                            try data_const_seg.addSection(self.allocator, .{
-                                .sectname = makeStaticString("__const"),
-                                .segname = makeStaticString("__DATA_CONST"),
-                                .addr = 0,
-                                .size = 0,
-                                .offset = 0,
-                                .@"align" = 0,
-                                .reloff = 0,
-                                .nreloc = 0,
-                                .flags = macho.S_REGULAR,
-                                .reserved1 = 0,
-                                .reserved2 = 0,
-                                .reserved3 = 0,
-                            });
+                            try data_const_seg.addSection(self.allocator, "__const", "__DATA_CONST", .{});
+                        } else if (mem.eql(u8, sectname, "__cfstring")) {
+                            if (self.objc_cfstring_section_index != null) continue;
+
+                            self.objc_cfstring_section_index = @intCast(u16, data_const_seg.sections.items.len);
+                            try data_const_seg.addSection(self.allocator, "__cfstring", "__DATA_CONST", .{});
                         } else {
                             if (self.data_section_index != null) continue;
 
                             self.data_section_index = @intCast(u16, data_seg.sections.items.len);
-                            try data_seg.addSection(self.allocator, .{
-                                .sectname = makeStaticString("__data"),
-                                .segname = makeStaticString("__DATA"),
-                                .addr = 0,
-                                .size = 0,
-                                .offset = 0,
-                                .@"align" = 0,
-                                .reloff = 0,
-                                .nreloc = 0,
-                                .flags = macho.S_REGULAR,
-                                .reserved1 = 0,
-                                .reserved2 = 0,
-                                .reserved3 = 0,
-                            });
+                            try data_seg.addSection(self.allocator, "__data", "__DATA", .{});
                         }
 
                         continue;
@@ -932,19 +723,8 @@ fn updateMetadata(self: *Zld) !void {
         const data_seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
         const common_section_index = self.common_section_index orelse ind: {
             self.common_section_index = @intCast(u16, data_seg.sections.items.len);
-            try data_seg.addSection(self.allocator, .{
-                .sectname = makeStaticString("__common"),
-                .segname = makeStaticString("__DATA"),
-                .addr = 0,
-                .size = 0,
-                .offset = 0,
-                .@"align" = 0,
-                .reloff = 0,
-                .nreloc = 0,
+            try data_seg.addSection(self.allocator, "__common", "__DATA", .{
                 .flags = macho.S_ZEROFILL,
-                .reserved1 = 0,
-                .reserved2 = 0,
-                .reserved3 = 0,
             });
             break :ind self.common_section_index.?;
         };
@@ -1136,6 +916,11 @@ fn getMatchingSection(self: *Zld, sect: Object.Section) ?MatchingSection {
                             .seg = self.data_const_segment_cmd_index.?,
                             .sect = self.data_const_section_index.?,
                         };
+                    } else if (mem.eql(u8, sectname, "__cfstring")) {
+                        break :blk .{
+                            .seg = self.data_const_segment_cmd_index.?,
+                            .sect = self.objc_cfstring_section_index.?,
+                        };
                     }
                     break :blk .{
                         .seg = self.data_segment_cmd_index.?,
@@ -1200,6 +985,7 @@ fn sortSections(self: *Zld) !void {
             &self.mod_init_func_section_index,
             &self.mod_term_func_section_index,
             &self.data_const_section_index,
+            &self.objc_cfstring_section_index,
         };
         for (indices) |maybe_index| {
             const new_index: u16 = if (maybe_index.*) |index| blk: {
@@ -2240,18 +2026,8 @@ fn populateMetadata(self: *Zld) !void {
     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.allocator, .{
-            .Segment = SegmentCommand.empty(.{
-                .cmd = macho.LC_SEGMENT_64,
-                .cmdsize = @sizeOf(macho.segment_command_64),
-                .segname = makeStaticString("__PAGEZERO"),
-                .vmaddr = 0,
+            .Segment = SegmentCommand.empty("__PAGEZERO", .{
                 .vmsize = 0x100000000, // size always set to 4GB
-                .fileoff = 0,
-                .filesize = 0,
-                .maxprot = 0,
-                .initprot = 0,
-                .nsects = 0,
-                .flags = 0,
             }),
         });
     }
@@ -2259,18 +2035,10 @@ fn populateMetadata(self: *Zld) !void {
     if (self.text_segment_cmd_index == null) {
         self.text_segment_cmd_index = @intCast(u16, self.load_commands.items.len);
         try self.load_commands.append(self.allocator, .{
-            .Segment = SegmentCommand.empty(.{
-                .cmd = macho.LC_SEGMENT_64,
-                .cmdsize = @sizeOf(macho.segment_command_64),
-                .segname = makeStaticString("__TEXT"),
+            .Segment = SegmentCommand.empty("__TEXT", .{
                 .vmaddr = 0x100000000, // always starts at 4GB
-                .vmsize = 0,
-                .fileoff = 0,
-                .filesize = 0,
                 .maxprot = macho.VM_PROT_READ | macho.VM_PROT_EXECUTE,
                 .initprot = macho.VM_PROT_READ | macho.VM_PROT_EXECUTE,
-                .nsects = 0,
-                .flags = 0,
             }),
         });
     }
@@ -2283,19 +2051,9 @@ fn populateMetadata(self: *Zld) !void {
             .aarch64 => 2,
             else => unreachable, // unhandled architecture type
         };
-        try text_seg.addSection(self.allocator, .{
-            .sectname = makeStaticString("__text"),
-            .segname = makeStaticString("__TEXT"),
-            .addr = 0,
-            .size = 0,
-            .offset = 0,
+        try text_seg.addSection(self.allocator, "__text", "__TEXT", .{
             .@"align" = alignment,
-            .reloff = 0,
-            .nreloc = 0,
             .flags = macho.S_REGULAR | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS,
-            .reserved1 = 0,
-            .reserved2 = 0,
-            .reserved3 = 0,
         });
     }
 
@@ -2312,19 +2070,10 @@ fn populateMetadata(self: *Zld) !void {
             .aarch64 => 3 * @sizeOf(u32),
             else => unreachable, // unhandled architecture type
         };
-        try text_seg.addSection(self.allocator, .{
-            .sectname = makeStaticString("__stubs"),
-            .segname = makeStaticString("__TEXT"),
-            .addr = 0,
-            .size = 0,
-            .offset = 0,
+        try text_seg.addSection(self.allocator, "__stubs", "__TEXT", .{
             .@"align" = alignment,
-            .reloff = 0,
-            .nreloc = 0,
             .flags = macho.S_SYMBOL_STUBS | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS,
-            .reserved1 = 0,
             .reserved2 = stub_size,
-            .reserved3 = 0,
         });
     }
 
@@ -2341,37 +2090,19 @@ fn populateMetadata(self: *Zld) !void {
             .aarch64 => 6 * @sizeOf(u32),
             else => unreachable,
         };
-        try text_seg.addSection(self.allocator, .{
-            .sectname = makeStaticString("__stub_helper"),
-            .segname = makeStaticString("__TEXT"),
-            .addr = 0,
+        try text_seg.addSection(self.allocator, "__stub_helper", "__TEXT", .{
             .size = stub_helper_size,
-            .offset = 0,
             .@"align" = alignment,
-            .reloff = 0,
-            .nreloc = 0,
             .flags = macho.S_REGULAR | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS,
-            .reserved1 = 0,
-            .reserved2 = 0,
-            .reserved3 = 0,
         });
     }
 
     if (self.data_const_segment_cmd_index == null) {
         self.data_const_segment_cmd_index = @intCast(u16, self.load_commands.items.len);
         try self.load_commands.append(self.allocator, .{
-            .Segment = SegmentCommand.empty(.{
-                .cmd = macho.LC_SEGMENT_64,
-                .cmdsize = @sizeOf(macho.segment_command_64),
-                .segname = makeStaticString("__DATA_CONST"),
-                .vmaddr = 0,
-                .vmsize = 0,
-                .fileoff = 0,
-                .filesize = 0,
+            .Segment = SegmentCommand.empty("__DATA_CONST", .{
                 .maxprot = macho.VM_PROT_READ | macho.VM_PROT_WRITE,
                 .initprot = macho.VM_PROT_READ | macho.VM_PROT_WRITE,
-                .nsects = 0,
-                .flags = 0,
             }),
         });
     }
@@ -2379,37 +2110,18 @@ fn populateMetadata(self: *Zld) !void {
     if (self.got_section_index == null) {
         const data_const_seg = &self.load_commands.items[self.data_const_segment_cmd_index.?].Segment;
         self.got_section_index = @intCast(u16, data_const_seg.sections.items.len);
-        try data_const_seg.addSection(self.allocator, .{
-            .sectname = makeStaticString("__got"),
-            .segname = makeStaticString("__DATA_CONST"),
-            .addr = 0,
-            .size = 0,
-            .offset = 0,
+        try data_const_seg.addSection(self.allocator, "__got", "__DATA_CONST", .{
             .@"align" = 3, // 2^3 = @sizeOf(u64)
-            .reloff = 0,
-            .nreloc = 0,
             .flags = macho.S_NON_LAZY_SYMBOL_POINTERS,
-            .reserved1 = 0,
-            .reserved2 = 0,
-            .reserved3 = 0,
         });
     }
 
     if (self.data_segment_cmd_index == null) {
         self.data_segment_cmd_index = @intCast(u16, self.load_commands.items.len);
         try self.load_commands.append(self.allocator, .{
-            .Segment = SegmentCommand.empty(.{
-                .cmd = macho.LC_SEGMENT_64,
-                .cmdsize = @sizeOf(macho.segment_command_64),
-                .segname = makeStaticString("__DATA"),
-                .vmaddr = 0,
-                .vmsize = 0,
-                .fileoff = 0,
-                .filesize = 0,
+            .Segment = SegmentCommand.empty("__DATA", .{
                 .maxprot = macho.VM_PROT_READ | macho.VM_PROT_WRITE,
                 .initprot = macho.VM_PROT_READ | macho.VM_PROT_WRITE,
-                .nsects = 0,
-                .flags = 0,
             }),
         });
     }
@@ -2417,56 +2129,26 @@ fn populateMetadata(self: *Zld) !void {
     if (self.la_symbol_ptr_section_index == null) {
         const data_seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
         self.la_symbol_ptr_section_index = @intCast(u16, data_seg.sections.items.len);
-        try data_seg.addSection(self.allocator, .{
-            .sectname = makeStaticString("__la_symbol_ptr"),
-            .segname = makeStaticString("__DATA"),
-            .addr = 0,
-            .size = 0,
-            .offset = 0,
+        try data_seg.addSection(self.allocator, "__la_symbol_ptr", "__DATA", .{
             .@"align" = 3, // 2^3 = @sizeOf(u64)
-            .reloff = 0,
-            .nreloc = 0,
             .flags = macho.S_LAZY_SYMBOL_POINTERS,
-            .reserved1 = 0,
-            .reserved2 = 0,
-            .reserved3 = 0,
         });
     }
 
     if (self.data_section_index == null) {
         const data_seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
         self.data_section_index = @intCast(u16, data_seg.sections.items.len);
-        try data_seg.addSection(self.allocator, .{
-            .sectname = makeStaticString("__data"),
-            .segname = makeStaticString("__DATA"),
-            .addr = 0,
-            .size = 0,
-            .offset = 0,
+        try data_seg.addSection(self.allocator, "__data", "__DATA", .{
             .@"align" = 3, // 2^3 = @sizeOf(u64)
-            .reloff = 0,
-            .nreloc = 0,
-            .flags = macho.S_REGULAR,
-            .reserved1 = 0,
-            .reserved2 = 0,
-            .reserved3 = 0,
         });
     }
 
     if (self.linkedit_segment_cmd_index == null) {
         self.linkedit_segment_cmd_index = @intCast(u16, self.load_commands.items.len);
         try self.load_commands.append(self.allocator, .{
-            .Segment = SegmentCommand.empty(.{
-                .cmd = macho.LC_SEGMENT_64,
-                .cmdsize = @sizeOf(macho.segment_command_64),
-                .segname = makeStaticString("__LINKEDIT"),
-                .vmaddr = 0,
-                .vmsize = 0,
-                .fileoff = 0,
-                .filesize = 0,
+            .Segment = SegmentCommand.empty("__LINKEDIT", .{
                 .maxprot = macho.VM_PROT_READ,
                 .initprot = macho.VM_PROT_READ,
-                .nsects = 0,
-                .flags = 0,
             }),
         });
     }
@@ -3469,13 +3151,6 @@ fn writeHeader(self: *Zld) !void {
     try self.file.?.pwriteAll(mem.asBytes(&header), 0);
 }
 
-pub fn makeStaticString(bytes: []const u8) [16]u8 {
-    var buf = [_]u8{0} ** 16;
-    assert(bytes.len <= buf.len);
-    mem.copy(u8, &buf, bytes);
-    return buf;
-}
-
 fn makeString(self: *Zld, bytes: []const u8) !u32 {
     if (self.strtab_dir.get(bytes)) |offset| {
         log.debug("reusing '{s}' from string table at offset 0x{x}", .{ bytes, offset });
src/link/MachO.zig
@@ -1779,18 +1779,8 @@ pub fn populateMissingMetadata(self: *MachO) !void {
     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, .{
-            .Segment = SegmentCommand.empty(.{
-                .cmd = macho.LC_SEGMENT_64,
-                .cmdsize = @sizeOf(macho.segment_command_64),
-                .segname = makeStaticString("__PAGEZERO"),
-                .vmaddr = 0,
+            .Segment = SegmentCommand.empty("__PAGEZERO", .{
                 .vmsize = 0x100000000, // size always set to 4GB
-                .fileoff = 0,
-                .filesize = 0,
-                .maxprot = 0,
-                .initprot = 0,
-                .nsects = 0,
-                .flags = 0,
             }),
         });
         self.header_dirty = true;
@@ -1809,18 +1799,12 @@ pub fn populateMissingMetadata(self: *MachO) !void {
         log.debug("found __TEXT segment free space 0x{x} to 0x{x}", .{ 0, needed_size });
 
         try self.load_commands.append(self.base.allocator, .{
-            .Segment = SegmentCommand.empty(.{
-                .cmd = macho.LC_SEGMENT_64,
-                .cmdsize = @sizeOf(macho.segment_command_64),
-                .segname = makeStaticString("__TEXT"),
+            .Segment = SegmentCommand.empty("__TEXT", .{
                 .vmaddr = 0x100000000, // always starts at 4GB
                 .vmsize = needed_size,
-                .fileoff = 0,
                 .filesize = needed_size,
                 .maxprot = maxprot,
                 .initprot = initprot,
-                .nsects = 0,
-                .flags = 0,
             }),
         });
         self.header_dirty = true;
@@ -1841,19 +1825,12 @@ pub fn populateMissingMetadata(self: *MachO) !void {
 
         log.debug("found __text section free space 0x{x} to 0x{x}", .{ off, off + needed_size });
 
-        try text_segment.addSection(self.base.allocator, .{
-            .sectname = makeStaticString("__text"),
-            .segname = makeStaticString("__TEXT"),
+        try text_segment.addSection(self.base.allocator, "__text", "__TEXT", .{
             .addr = text_segment.inner.vmaddr + off,
             .size = @intCast(u32, needed_size),
             .offset = @intCast(u32, off),
             .@"align" = alignment,
-            .reloff = 0,
-            .nreloc = 0,
             .flags = flags,
-            .reserved1 = 0,
-            .reserved2 = 0,
-            .reserved3 = 0,
         });
         self.header_dirty = true;
         self.load_commands_dirty = true;
@@ -1879,19 +1856,13 @@ pub fn populateMissingMetadata(self: *MachO) !void {
 
         log.debug("found __stubs section free space 0x{x} to 0x{x}", .{ off, off + needed_size });
 
-        try text_segment.addSection(self.base.allocator, .{
-            .sectname = makeStaticString("__stubs"),
-            .segname = makeStaticString("__TEXT"),
+        try text_segment.addSection(self.base.allocator, "__stubs", "__TEXT", .{
             .addr = text_segment.inner.vmaddr + off,
             .size = needed_size,
             .offset = @intCast(u32, off),
             .@"align" = alignment,
-            .reloff = 0,
-            .nreloc = 0,
             .flags = flags,
-            .reserved1 = 0,
             .reserved2 = stub_size,
-            .reserved3 = 0,
         });
         self.header_dirty = true;
         self.load_commands_dirty = true;
@@ -1912,19 +1883,12 @@ pub fn populateMissingMetadata(self: *MachO) !void {
 
         log.debug("found __stub_helper section free space 0x{x} to 0x{x}", .{ off, off + needed_size });
 
-        try text_segment.addSection(self.base.allocator, .{
-            .sectname = makeStaticString("__stub_helper"),
-            .segname = makeStaticString("__TEXT"),
+        try text_segment.addSection(self.base.allocator, "__stub_helper", "__TEXT", .{
             .addr = text_segment.inner.vmaddr + off,
             .size = needed_size,
             .offset = @intCast(u32, off),
             .@"align" = alignment,
-            .reloff = 0,
-            .nreloc = 0,
             .flags = flags,
-            .reserved1 = 0,
-            .reserved2 = 0,
-            .reserved3 = 0,
         });
         self.header_dirty = true;
         self.load_commands_dirty = true;
@@ -1941,18 +1905,13 @@ pub fn populateMissingMetadata(self: *MachO) !void {
         log.debug("found __DATA_CONST segment free space 0x{x} to 0x{x}", .{ address_and_offset.offset, address_and_offset.offset + needed_size });
 
         try self.load_commands.append(self.base.allocator, .{
-            .Segment = SegmentCommand.empty(.{
-                .cmd = macho.LC_SEGMENT_64,
-                .cmdsize = @sizeOf(macho.segment_command_64),
-                .segname = makeStaticString("__DATA_CONST"),
+            .Segment = SegmentCommand.empty("__DATA_CONST", .{
                 .vmaddr = address_and_offset.address,
                 .vmsize = needed_size,
                 .fileoff = address_and_offset.offset,
                 .filesize = needed_size,
                 .maxprot = maxprot,
                 .initprot = initprot,
-                .nsects = 0,
-                .flags = 0,
             }),
         });
         self.header_dirty = true;
@@ -1969,19 +1928,12 @@ pub fn populateMissingMetadata(self: *MachO) !void {
 
         log.debug("found __got section free space 0x{x} to 0x{x}", .{ off, off + needed_size });
 
-        try dc_segment.addSection(self.base.allocator, .{
-            .sectname = makeStaticString("__got"),
-            .segname = makeStaticString("__DATA_CONST"),
+        try dc_segment.addSection(self.base.allocator, "__got", "__DATA_CONST", .{
             .addr = dc_segment.inner.vmaddr + off - dc_segment.inner.fileoff,
             .size = needed_size,
             .offset = @intCast(u32, off),
             .@"align" = 3, // 2^3 = @sizeOf(u64)
-            .reloff = 0,
-            .nreloc = 0,
             .flags = flags,
-            .reserved1 = 0,
-            .reserved2 = 0,
-            .reserved3 = 0,
         });
         self.header_dirty = true;
         self.load_commands_dirty = true;
@@ -1998,18 +1950,13 @@ pub fn populateMissingMetadata(self: *MachO) !void {
         log.debug("found __DATA segment free space 0x{x} to 0x{x}", .{ address_and_offset.offset, address_and_offset.offset + needed_size });
 
         try self.load_commands.append(self.base.allocator, .{
-            .Segment = SegmentCommand.empty(.{
-                .cmd = macho.LC_SEGMENT_64,
-                .cmdsize = @sizeOf(macho.segment_command_64),
-                .segname = makeStaticString("__DATA"),
+            .Segment = SegmentCommand.empty("__DATA", .{
                 .vmaddr = address_and_offset.address,
                 .vmsize = needed_size,
                 .fileoff = address_and_offset.offset,
                 .filesize = needed_size,
                 .maxprot = maxprot,
                 .initprot = initprot,
-                .nsects = 0,
-                .flags = 0,
             }),
         });
         self.header_dirty = true;
@@ -2026,19 +1973,12 @@ pub fn populateMissingMetadata(self: *MachO) !void {
 
         log.debug("found __la_symbol_ptr section free space 0x{x} to 0x{x}", .{ off, off + needed_size });
 
-        try data_segment.addSection(self.base.allocator, .{
-            .sectname = makeStaticString("__la_symbol_ptr"),
-            .segname = makeStaticString("__DATA"),
+        try data_segment.addSection(self.base.allocator, "__la_symbol_ptr", "__DATA", .{
             .addr = data_segment.inner.vmaddr + off - data_segment.inner.fileoff,
             .size = needed_size,
             .offset = @intCast(u32, off),
             .@"align" = 3, // 2^3 = @sizeOf(u64)
-            .reloff = 0,
-            .nreloc = 0,
             .flags = flags,
-            .reserved1 = 0,
-            .reserved2 = 0,
-            .reserved3 = 0,
         });
         self.header_dirty = true;
         self.load_commands_dirty = true;
@@ -2047,26 +1987,17 @@ pub fn populateMissingMetadata(self: *MachO) !void {
         const data_segment = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
         self.data_section_index = @intCast(u16, data_segment.sections.items.len);
 
-        const flags = macho.S_REGULAR;
         const needed_size = @sizeOf(u64) * self.base.options.symbol_count_hint;
         const off = data_segment.findFreeSpace(needed_size, @alignOf(u64), null);
         assert(off + needed_size <= data_segment.inner.fileoff + data_segment.inner.filesize); // TODO Must expand __DATA segment.
 
         log.debug("found __data section free space 0x{x} to 0x{x}", .{ off, off + needed_size });
 
-        try data_segment.addSection(self.base.allocator, .{
-            .sectname = makeStaticString("__data"),
-            .segname = makeStaticString("__DATA"),
+        try data_segment.addSection(self.base.allocator, "__data", "__DATA", .{
             .addr = data_segment.inner.vmaddr + off - data_segment.inner.fileoff,
             .size = needed_size,
             .offset = @intCast(u32, off),
             .@"align" = 3, // 2^3 = @sizeOf(u64)
-            .reloff = 0,
-            .nreloc = 0,
-            .flags = flags,
-            .reserved1 = 0,
-            .reserved2 = 0,
-            .reserved3 = 0,
         });
         self.header_dirty = true;
         self.load_commands_dirty = true;
@@ -2081,18 +2012,11 @@ pub fn populateMissingMetadata(self: *MachO) !void {
         log.debug("found __LINKEDIT segment free space at 0x{x}", .{address_and_offset.offset});
 
         try self.load_commands.append(self.base.allocator, .{
-            .Segment = SegmentCommand.empty(.{
-                .cmd = macho.LC_SEGMENT_64,
-                .cmdsize = @sizeOf(macho.segment_command_64),
-                .segname = makeStaticString("__LINKEDIT"),
+            .Segment = SegmentCommand.empty("__LINKEDIT", .{
                 .vmaddr = address_and_offset.address,
-                .vmsize = 0,
                 .fileoff = address_and_offset.offset,
-                .filesize = 0,
                 .maxprot = maxprot,
                 .initprot = initprot,
-                .nsects = 0,
-                .flags = 0,
             }),
         });
         self.header_dirty = true;
@@ -2450,13 +2374,6 @@ fn allocateTextBlock(self: *MachO, text_block: *TextBlock, new_block_size: u64,
     return vaddr;
 }
 
-pub fn makeStaticString(comptime bytes: []const u8) [16]u8 {
-    var buf = [_]u8{0} ** 16;
-    if (bytes.len > buf.len) @compileError("string too long; max 16 bytes");
-    mem.copy(u8, &buf, bytes);
-    return buf;
-}
-
 fn makeString(self: *MachO, bytes: []const u8) !u32 {
     if (self.string_table_directory.get(bytes)) |offset| {
         log.debug("reusing '{s}' from string table at offset 0x{x}", .{ bytes, offset });