diff --git a/src/link/MachO.zig b/src/link/MachO.zig index ac07e5c687..de723639f1 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -33,14 +33,19 @@ data_segment_cmd_index: ?u8 = null, linkedit_segment_cmd_index: ?u8 = null, text_section_index: ?u8 = null, +data_const_section_index: ?u8 = null, +data_section_index: ?u8 = null, +bss_section_index: ?u8 = null, +thread_vars_section_index: ?u8 = null, +thread_data_section_index: ?u8 = null, +thread_bss_section_index: ?u8 = null, +eh_frame_section_index: ?u8 = null, +unwind_info_section_index: ?u8 = null, stubs_section_index: ?u8 = null, stub_helper_section_index: ?u8 = null, got_section_index: ?u8 = null, -data_const_section_index: ?u8 = null, la_symbol_ptr_section_index: ?u8 = null, -data_section_index: ?u8 = null, -thread_vars_section_index: ?u8 = null, -thread_data_section_index: ?u8 = null, +tlv_ptr_section_index: ?u8 = null, locals: std.ArrayListUnmanaged(macho.nlist_64) = .{}, globals: std.ArrayListUnmanaged(SymbolWithLoc) = .{}, diff --git a/src/link/MachO/Atom.zig b/src/link/MachO/Atom.zig index 411c42c4dd..73099184e0 100644 --- a/src/link/MachO/Atom.zig +++ b/src/link/MachO/Atom.zig @@ -244,13 +244,16 @@ pub fn getOutputSection(zld: *Zld, sect: macho.section_64) !?u8 { .{}, ); } else if (mem.eql(u8, sectname, "__data")) { - break :blk zld.getSectionByName("__DATA", "__data") orelse try MachO.initSection( - gpa, - zld, - "__DATA", - "__data", - .{}, - ); + if (zld.data_section_index == null) { + zld.data_section_index = try MachO.initSection( + gpa, + zld, + "__DATA", + "__data", + .{}, + ); + } + break :blk zld.data_section_index.?; } } break :blk zld.getSectionByName(segname, sectname) orelse try MachO.initSection( @@ -264,6 +267,35 @@ pub fn getOutputSection(zld: *Zld, sect: macho.section_64) !?u8 { else => break :blk null, } }; + + // TODO we can do this directly in the selection logic above. + // Or is it not worth it? + if (zld.data_const_section_index == null) { + if (zld.getSectionByName("__DATA_CONST", "__const")) |index| { + zld.data_const_section_index = index; + } + } + if (zld.thread_vars_section_index == null) { + if (zld.getSectionByName("__DATA", "__thread_vars")) |index| { + zld.thread_vars_section_index = index; + } + } + if (zld.thread_data_section_index == null) { + if (zld.getSectionByName("__DATA", "__thread_data")) |index| { + zld.thread_data_section_index = index; + } + } + if (zld.thread_bss_section_index == null) { + if (zld.getSectionByName("__DATA", "__thread_bss")) |index| { + zld.thread_bss_section_index = index; + } + } + if (zld.bss_section_index == null) { + if (zld.getSectionByName("__DATA", "__bss")) |index| { + zld.bss_section_index = index; + } + } + return res; } @@ -662,9 +694,9 @@ pub fn getRelocTargetAddress(zld: *Zld, target: SymbolWithLoc, is_tlv: bool) !u6 // * wrt to __thread_data if defined, then // * wrt to __thread_bss const sect_id: u16 = sect_id: { - if (zld.getSectionByName("__DATA", "__thread_data")) |i| { + if (zld.thread_data_section_index) |i| { break :sect_id i; - } else if (zld.getSectionByName("__DATA", "__thread_bss")) |i| { + } else if (zld.thread_bss_section_index) |i| { break :sect_id i; } else { log.err("threadlocal variables present but no initializer sections found", .{}); diff --git a/src/link/MachO/Object.zig b/src/link/MachO/Object.zig index 5042fe9849..3ab62ec191 100644 --- a/src/link/MachO/Object.zig +++ b/src/link/MachO/Object.zig @@ -687,8 +687,8 @@ fn parseEhFrameSection(self: *Object, zld: *Zld, object_id: u32) !void { const gpa = zld.gpa; - if (zld.getSectionByName("__TEXT", "__eh_frame") == null) { - _ = try MachO.initSection(gpa, zld, "__TEXT", "__eh_frame", .{}); + if (zld.eh_frame_section_index == null) { + zld.eh_frame_section_index = try MachO.initSection(gpa, zld, "__TEXT", "__eh_frame", .{}); } const cpu_arch = zld.options.target.cpu.arch; @@ -788,8 +788,14 @@ fn parseUnwindInfo(self: *Object, zld: *Zld, object_id: u32) !void { // approach. However, we will only synthesise DWARF records and nothing more. For this reason, // we still create the output `__TEXT,__unwind_info` section. if (self.hasEhFrameRecords()) { - if (zld.getSectionByName("__TEXT", "__unwind_info") == null) { - _ = try MachO.initSection(gpa, zld, "__TEXT", "__unwind_info", .{}); + if (zld.unwind_info_section_index == null) { + zld.unwind_info_section_index = try MachO.initSection( + gpa, + zld, + "__TEXT", + "__unwind_info", + .{}, + ); } } return; @@ -797,8 +803,8 @@ fn parseUnwindInfo(self: *Object, zld: *Zld, object_id: u32) !void { log.debug("parsing unwind info in {s}", .{self.name}); - if (zld.getSectionByName("__TEXT", "__unwind_info") == null) { - _ = try MachO.initSection(gpa, zld, "__TEXT", "__unwind_info", .{}); + if (zld.unwind_info_section_index == null) { + zld.unwind_info_section_index = try MachO.initSection(gpa, zld, "__TEXT", "__unwind_info", .{}); } const unwind_records = self.getUnwindRecords(); diff --git a/src/link/MachO/UnwindInfo.zig b/src/link/MachO/UnwindInfo.zig index 53d7c149be..3cd72fd64e 100644 --- a/src/link/MachO/UnwindInfo.zig +++ b/src/link/MachO/UnwindInfo.zig @@ -204,7 +204,7 @@ pub fn deinit(info: *UnwindInfo) void { } pub fn scanRelocs(zld: *Zld) !void { - if (zld.getSectionByName("__TEXT", "__unwind_info") == null) return; + if (zld.unwind_info_section_index == null) return; const cpu_arch = zld.options.target.cpu.arch; for (zld.objects.items, 0..) |*object, object_id| { @@ -233,7 +233,7 @@ pub fn scanRelocs(zld: *Zld) !void { } pub fn collect(info: *UnwindInfo, zld: *Zld) !void { - if (zld.getSectionByName("__TEXT", "__unwind_info") == null) return; + if (zld.unwind_info_section_index == null) return; const cpu_arch = zld.options.target.cpu.arch; @@ -551,7 +551,7 @@ fn collectPersonalityFromDwarf( } pub fn calcSectionSize(info: UnwindInfo, zld: *Zld) !void { - const sect_id = zld.getSectionByName("__TEXT", "__unwind_info") orelse return; + const sect_id = zld.unwind_info_section_index orelse return; const sect = &zld.sections.items(.header)[sect_id]; sect.@"align" = 2; sect.size = info.calcRequiredSize(); @@ -570,7 +570,7 @@ fn calcRequiredSize(info: UnwindInfo) usize { } pub fn write(info: *UnwindInfo, zld: *Zld) !void { - const sect_id = zld.getSectionByName("__TEXT", "__unwind_info") orelse return; + const sect_id = zld.unwind_info_section_index orelse return; const sect = &zld.sections.items(.header)[sect_id]; const seg_id = zld.sections.items(.segment_index)[sect_id]; const seg = zld.segments.items[seg_id]; diff --git a/src/link/MachO/eh_frame.zig b/src/link/MachO/eh_frame.zig index 5d267af5ff..2bcf23bff5 100644 --- a/src/link/MachO/eh_frame.zig +++ b/src/link/MachO/eh_frame.zig @@ -46,7 +46,7 @@ pub fn scanRelocs(zld: *Zld) !void { } pub fn calcSectionSize(zld: *Zld, unwind_info: *const UnwindInfo) !void { - const sect_id = zld.getSectionByName("__TEXT", "__eh_frame") orelse return; + const sect_id = zld.eh_frame_section_index orelse return; const sect = &zld.sections.items(.header)[sect_id]; sect.@"align" = 3; sect.size = 0; @@ -97,7 +97,7 @@ pub fn calcSectionSize(zld: *Zld, unwind_info: *const UnwindInfo) !void { } pub fn write(zld: *Zld, unwind_info: *UnwindInfo) !void { - const sect_id = zld.getSectionByName("__TEXT", "__eh_frame") orelse return; + const sect_id = zld.eh_frame_section_index orelse return; const sect = zld.sections.items(.header)[sect_id]; const seg_id = zld.sections.items(.segment_index)[sect_id]; const seg = zld.segments.items[seg_id]; diff --git a/src/link/MachO/zld.zig b/src/link/MachO/zld.zig index c607c80f45..28a8e9b8a8 100644 --- a/src/link/MachO/zld.zig +++ b/src/link/MachO/zld.zig @@ -74,6 +74,14 @@ pub const Zld = struct { linkedit_segment_cmd_index: ?u8 = null, text_section_index: ?u8 = null, + data_const_section_index: ?u8 = null, + data_section_index: ?u8 = null, + bss_section_index: ?u8 = null, + thread_vars_section_index: ?u8 = null, + thread_data_section_index: ?u8 = null, + thread_bss_section_index: ?u8 = null, + eh_frame_section_index: ?u8 = null, + unwind_info_section_index: ?u8 = null, got_section_index: ?u8 = null, tlv_ptr_section_index: ?u8 = null, stubs_section_index: ?u8 = null, @@ -142,9 +150,10 @@ pub const Zld = struct { const sym = self.getSymbolPtr(.{ .sym_index = sym_index }); sym.n_type = macho.N_SECT; - const sect_id = self.getSectionByName("__DATA", "__data") orelse - try MachO.initSection(self.gpa, self, "__DATA", "__data", .{}); - sym.n_sect = sect_id + 1; + if (self.data_section_index == null) { + self.data_section_index = try MachO.initSection(self.gpa, self, "__DATA", "__data", .{}); + } + sym.n_sect = self.data_section_index.? + 1; self.dyld_private_atom_index = atom_index; self.addAtomToSection(atom_index); @@ -166,13 +175,17 @@ pub const Zld = struct { // text blocks for each tentative definition. const size = sym.n_value; const alignment = (sym.n_desc >> 8) & 0x0f; - const sect_id = self.getSectionByName("__DATA", "__bss") orelse - try MachO.initSection(gpa, self, "__DATA", "__bss", .{ .flags = macho.S_ZEROFILL }); + + if (self.bss_section_index == null) { + self.bss_section_index = try MachO.initSection(gpa, self, "__DATA", "__bss", .{ + .flags = macho.S_ZEROFILL, + }); + } sym.* = .{ .n_strx = sym.n_strx, .n_type = macho.N_SECT | macho.N_EXT, - .n_sect = sect_id + 1, + .n_sect = self.bss_section_index.? + 1, .n_desc = 0, .n_value = 0, }; @@ -768,7 +781,7 @@ pub const Zld = struct { const atom_index = self.dyld_private_atom_index orelse return; const atom = self.getAtom(atom_index); const sym = self.getSymbol(atom.getSymbolWithLoc()); - const sect_id = self.getSectionByName("__DATA", "__data").?; + const sect_id = self.data_section_index.?; const header = self.sections.items(.header)[sect_id]; const offset = sym.n_value - header.addr + header.offset; log.debug("writing __dyld_private at offset 0x{x}", .{offset}); @@ -918,6 +931,14 @@ pub const Zld = struct { }); for (&[_]*?u8{ &self.text_section_index, + &self.data_const_section_index, + &self.data_section_index, + &self.bss_section_index, + &self.thread_vars_section_index, + &self.thread_data_section_index, + &self.thread_bss_section_index, + &self.eh_frame_section_index, + &self.unwind_info_section_index, &self.got_section_index, &self.tlv_ptr_section_index, &self.stubs_section_index, @@ -951,6 +972,14 @@ pub const Zld = struct { for (&[_]*?u8{ &self.text_section_index, + &self.data_const_section_index, + &self.data_section_index, + &self.bss_section_index, + &self.thread_vars_section_index, + &self.thread_data_section_index, + &self.thread_bss_section_index, + &self.eh_frame_section_index, + &self.unwind_info_section_index, &self.got_section_index, &self.tlv_ptr_section_index, &self.stubs_section_index, @@ -1964,7 +1993,7 @@ pub const Zld = struct { else => unreachable, } - if (self.getSectionByName("__DATA", "__thread_vars")) |sect_id| { + if (self.thread_vars_section_index) |sect_id| { header.flags |= macho.MH_HAS_TLV_DESCRIPTORS; if (self.sections.items(.header)[sect_id].size > 0) { header.flags |= macho.MH_HAS_TLV_DESCRIPTORS;