diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2021-06-21 11:11:19 +0200 |
|---|---|---|
| committer | Jakub Konka <kubkon@jakubkonka.com> | 2021-06-24 18:53:42 +0200 |
| commit | 852e1ed23cb5cfdb687a52c39fa9c60be3159730 (patch) | |
| tree | 2ba86d658697c66801b3f0fe6951e6288a110b4c /src | |
| parent | 72f2f68938d626299e2bb5aa3b8932a45d4ae778 (diff) | |
| download | zig-852e1ed23cb5cfdb687a52c39fa9c60be3159730.tar.gz zig-852e1ed23cb5cfdb687a52c39fa9c60be3159730.zip | |
zld+stage2: refactor creating segments and sections
Move the logic into default-init structs part of constructors in
`SegmentCommand` struct in `commands.zig` module.
Diffstat (limited to 'src')
| -rw-r--r-- | src/link/MachO.zig | 105 | ||||
| -rw-r--r-- | src/link/MachO/DebugSymbols.zig | 66 | ||||
| -rw-r--r-- | src/link/MachO/Stub.zig | 60 | ||||
| -rw-r--r-- | src/link/MachO/Zld.zig | 411 | ||||
| -rw-r--r-- | src/link/MachO/commands.zig | 74 |
5 files changed, 172 insertions, 544 deletions
diff --git a/src/link/MachO.zig b/src/link/MachO.zig index c16957b97d..cc00cafe3e 100644 --- a/src/link/MachO.zig +++ b/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 }); diff --git a/src/link/MachO/DebugSymbols.zig b/src/link/MachO/DebugSymbols.zig index 2b10f3307b..c26ce889ae 100644 --- a/src/link/MachO/DebugSymbols.zig +++ b/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, diff --git a/src/link/MachO/Stub.zig b/src/link/MachO/Stub.zig index 6111690a7d..d71c454c79 100644 --- a/src/link/MachO/Stub.zig +++ b/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, {}); + } } } } diff --git a/src/link/MachO/Zld.zig b/src/link/MachO/Zld.zig index 0a9d209c61..3f30379ca5 100644 --- a/src/link/MachO/Zld.zig +++ b/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 }); diff --git a/src/link/MachO/commands.zig b/src/link/MachO/commands.zig index 8bceb64f1e..6ad1964483 100644 --- a/src/link/MachO/commands.zig +++ b/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()); |
