diff --git a/src/link/MachO.zig b/src/link/MachO.zig index 10961d145e..467b75c69c 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -2739,6 +2739,34 @@ fn calcPagezeroSize(self: *MachO) u64 { return aligned_pagezero_vmsize; } +const InitSectionOpts = struct { + flags: u32 = macho.S_REGULAR, + reserved1: u32 = 0, + reserved2: u32 = 0, +}; + +pub fn initSection( + gpa: Allocator, + ctx: anytype, + segname: []const u8, + sectname: []const u8, + opts: InitSectionOpts, +) !u8 { + log.debug("creating section '{s},{s}'", .{ segname, sectname }); + const index = @as(u8, @intCast(ctx.sections.slice().len)); + try ctx.sections.append(gpa, .{ + .segment_index = undefined, // Segments will be created automatically later down the pipeline + .header = .{ + .sectname = makeStaticString(sectname), + .segname = makeStaticString(segname), + .flags = opts.flags, + .reserved1 = opts.reserved1, + .reserved2 = opts.reserved2, + }, + }); + return index; +} + fn allocateSection(self: *MachO, segname: []const u8, sectname: []const u8, opts: struct { size: u64 = 0, alignment: u32 = 0, @@ -2751,7 +2779,6 @@ fn allocateSection(self: *MachO, segname: []const u8, sectname: []const u8, opts // In incremental context, we create one section per segment pairing. This way, // we can move the segment in raw file as we please. const segment_id = @as(u8, @intCast(self.segments.items.len)); - const section_id = @as(u8, @intCast(self.sections.slice().len)); const vmaddr = blk: { const prev_segment = self.segments.items[segment_id - 1]; break :blk mem.alignForward(u64, prev_segment.vmaddr + prev_segment.vmsize, page_size); @@ -2782,23 +2809,18 @@ fn allocateSection(self: *MachO, segname: []const u8, sectname: []const u8, opts .cmdsize = @sizeOf(macho.segment_command_64) + @sizeOf(macho.section_64), }; - var section = macho.section_64{ - .sectname = makeStaticString(sectname), - .segname = makeStaticString(segname), - .addr = mem.alignForward(u64, vmaddr, opts.alignment), - .offset = mem.alignForward(u32, @as(u32, @intCast(off)), opts.alignment), - .size = opts.size, - .@"align" = math.log2(opts.alignment), + const sect_id = try initSection(gpa, self, sectname, segname, .{ .flags = opts.flags, .reserved2 = opts.reserved2, - }; + }); + const section = &self.sections.items(.header)[sect_id]; + section.addr = mem.alignForward(u64, vmaddr, opts.alignment); + section.offset = mem.alignForward(u32, @as(u32, @intCast(off)), opts.alignment); + section.size = opts.size; + section.@"align" = math.log2(opts.alignment); assert(!section.isZerofill()); // TODO zerofill sections - try self.sections.append(gpa, .{ - .segment_index = segment_id, - .header = section, - }); - return section_id; + return sect_id; } fn growSection(self: *MachO, sect_id: u8, needed_size: u64) !void { diff --git a/src/link/MachO/Atom.zig b/src/link/MachO/Atom.zig index eb5e76462f..fe118e0e3a 100644 --- a/src/link/MachO/Atom.zig +++ b/src/link/MachO/Atom.zig @@ -106,6 +106,7 @@ pub fn freeListEligible(self: Atom, macho_file: *MachO) bool { } pub fn getOutputSection(zld: *Zld, sect: macho.section_64) !?u8 { + const gpa = zld.gpa; const segname = sect.segName(); const sectname = sect.sectName(); const res: ?u8 = blk: { @@ -126,7 +127,9 @@ pub fn getOutputSection(zld: *Zld, sect: macho.section_64) !?u8 { if (sect.isCode()) { if (zld.text_section_index == null) { - zld.text_section_index = try zld.initSection( + zld.text_section_index = try MachO.initSection( + gpa, + zld, "__TEXT", "__text", .{ @@ -148,7 +151,9 @@ pub fn getOutputSection(zld: *Zld, sect: macho.section_64) !?u8 { macho.S_8BYTE_LITERALS, macho.S_16BYTE_LITERALS, => { - break :blk zld.getSectionByName("__TEXT", "__const") orelse try zld.initSection( + break :blk zld.getSectionByName("__TEXT", "__const") orelse try MachO.initSection( + gpa, + zld, "__TEXT", "__const", .{}, @@ -156,13 +161,17 @@ pub fn getOutputSection(zld: *Zld, sect: macho.section_64) !?u8 { }, macho.S_CSTRING_LITERALS => { if (mem.startsWith(u8, sectname, "__objc")) { - break :blk zld.getSectionByName(segname, sectname) orelse try zld.initSection( + break :blk zld.getSectionByName(segname, sectname) orelse try MachO.initSection( + gpa, + zld, segname, sectname, .{}, ); } - break :blk zld.getSectionByName("__TEXT", "__cstring") orelse try zld.initSection( + break :blk zld.getSectionByName("__TEXT", "__cstring") orelse try MachO.initSection( + gpa, + zld, "__TEXT", "__cstring", .{ .flags = macho.S_CSTRING_LITERALS }, @@ -171,7 +180,9 @@ pub fn getOutputSection(zld: *Zld, sect: macho.section_64) !?u8 { macho.S_MOD_INIT_FUNC_POINTERS, macho.S_MOD_TERM_FUNC_POINTERS, => { - break :blk zld.getSectionByName("__DATA_CONST", sectname) orelse try zld.initSection( + break :blk zld.getSectionByName("__DATA_CONST", sectname) orelse try MachO.initSection( + gpa, + zld, "__DATA_CONST", sectname, .{ .flags = sect.flags }, @@ -184,14 +195,19 @@ pub fn getOutputSection(zld: *Zld, sect: macho.section_64) !?u8 { macho.S_THREAD_LOCAL_REGULAR, macho.S_THREAD_LOCAL_ZEROFILL, => { - break :blk zld.getSectionByName(segname, sectname) orelse try zld.initSection( + break :blk zld.getSectionByName(segname, sectname) orelse try MachO.initSection( + gpa, + zld, segname, sectname, .{ .flags = sect.flags }, ); }, macho.S_COALESCED => { - break :blk zld.getSectionByName(segname, sectname) orelse try zld.initSection( + break :blk zld.getSectionByName(segname, sectname) orelse try MachO.initSection( + gpa, + zld, + segname, sectname, .{}, @@ -205,7 +221,9 @@ pub fn getOutputSection(zld: *Zld, sect: macho.section_64) !?u8 { mem.eql(u8, sectname, "__gosymtab") or mem.eql(u8, sectname, "__gopclntab")) { - break :blk zld.getSectionByName("__TEXT", sectname) orelse try zld.initSection( + break :blk zld.getSectionByName("__TEXT", sectname) orelse try MachO.initSection( + gpa, + zld, "__TEXT", sectname, .{}, @@ -218,20 +236,26 @@ pub fn getOutputSection(zld: *Zld, sect: macho.section_64) !?u8 { mem.eql(u8, sectname, "__objc_classlist") or mem.eql(u8, sectname, "__objc_imageinfo")) { - break :blk zld.getSectionByName("__DATA_CONST", sectname) orelse try zld.initSection( + break :blk zld.getSectionByName("__DATA_CONST", sectname) orelse try MachO.initSection( + gpa, + zld, "__DATA_CONST", sectname, .{}, ); } else if (mem.eql(u8, sectname, "__data")) { - break :blk zld.getSectionByName("__DATA", "__data") orelse try zld.initSection( + break :blk zld.getSectionByName("__DATA", "__data") orelse try MachO.initSection( + gpa, + zld, "__DATA", "__data", .{}, ); } } - break :blk zld.getSectionByName(segname, sectname) orelse try zld.initSection( + break :blk zld.getSectionByName(segname, sectname) orelse try MachO.initSection( + gpa, + zld, segname, sectname, .{}, diff --git a/src/link/MachO/Object.zig b/src/link/MachO/Object.zig index c9f32aa4fd..2eee9f5787 100644 --- a/src/link/MachO/Object.zig +++ b/src/link/MachO/Object.zig @@ -685,11 +685,12 @@ fn parseEhFrameSection(self: *Object, zld: *Zld, object_id: u32) !void { log.debug("parsing __TEXT,__eh_frame section", .{}); + const gpa = zld.gpa; + if (zld.getSectionByName("__TEXT", "__eh_frame") == null) { - _ = try zld.initSection("__TEXT", "__eh_frame", .{}); + _ = try MachO.initSection(gpa, zld, "__TEXT", "__eh_frame", .{}); } - const gpa = zld.gpa; const cpu_arch = zld.options.target.cpu.arch; try self.parseRelocs(gpa, sect_id); const relocs = self.getRelocs(sect_id); @@ -779,6 +780,8 @@ fn parseEhFrameSection(self: *Object, zld: *Zld, object_id: u32) !void { } fn parseUnwindInfo(self: *Object, zld: *Zld, object_id: u32) !void { + const gpa = zld.gpa; + const cpu_arch = zld.options.target.cpu.arch; const sect_id = self.unwind_info_sect_id orelse { // If it so happens that the object had `__eh_frame` section defined but no `__compact_unwind`, // we will try fully synthesising unwind info records to somewhat match Apple ld's @@ -786,7 +789,7 @@ fn parseUnwindInfo(self: *Object, zld: *Zld, object_id: u32) !void { // we still create the output `__TEXT,__unwind_info` section. if (self.hasEhFrameRecords()) { if (zld.getSectionByName("__TEXT", "__unwind_info") == null) { - _ = try zld.initSection("__TEXT", "__unwind_info", .{}); + _ = try MachO.initSection(gpa, zld, "__TEXT", "__unwind_info", .{}); } } return; @@ -794,11 +797,8 @@ fn parseUnwindInfo(self: *Object, zld: *Zld, object_id: u32) !void { log.debug("parsing unwind info in {s}", .{self.name}); - const gpa = zld.gpa; - const cpu_arch = zld.options.target.cpu.arch; - if (zld.getSectionByName("__TEXT", "__unwind_info") == null) { - _ = try zld.initSection("__TEXT", "__unwind_info", .{}); + _ = try MachO.initSection(gpa, zld, "__TEXT", "__unwind_info", .{}); } const unwind_records = self.getUnwindRecords(); diff --git a/src/link/MachO/zld.zig b/src/link/MachO/zld.zig index d4dd599d2d..5bfff40405 100644 --- a/src/link/MachO/zld.zig +++ b/src/link/MachO/zld.zig @@ -141,7 +141,7 @@ pub const Zld = struct { sym.n_type = macho.N_SECT; const sect_id = self.getSectionByName("__DATA", "__data") orelse - try self.initSection("__DATA", "__data", .{}); + try MachO.initSection(self.gpa, self, "__DATA", "__data", .{}); sym.n_sect = sect_id + 1; self.dyld_private_atom_index = atom_index; @@ -165,7 +165,7 @@ pub const Zld = struct { const size = sym.n_value; const alignment = (sym.n_desc >> 8) & 0x0f; const sect_id = self.getSectionByName("__DATA", "__bss") orelse - try self.initSection("__DATA", "__bss", .{ .flags = macho.S_ZEROFILL }); + try MachO.initSection(gpa, self, "__DATA", "__bss", .{ .flags = macho.S_ZEROFILL }); sym.* = .{ .n_strx = sym.n_strx, @@ -619,7 +619,7 @@ pub const Zld = struct { if (self.got_table.lookup.contains(target)) return; _ = try self.got_table.allocateEntry(self.gpa, target); if (self.got_section_index == null) { - self.got_section_index = try self.initSection("__DATA_CONST", "__got", .{ + self.got_section_index = try MachO.initSection(self.gpa, self, "__DATA_CONST", "__got", .{ .flags = macho.S_NON_LAZY_SYMBOL_POINTERS, }); } @@ -629,7 +629,7 @@ pub const Zld = struct { if (self.tlv_ptr_table.lookup.contains(target)) return; _ = try self.tlv_ptr_table.allocateEntry(self.gpa, target); if (self.tlv_ptr_section_index == null) { - self.tlv_ptr_section_index = try self.initSection("__DATA", "__thread_ptrs", .{ + self.tlv_ptr_section_index = try MachO.initSection(self.gpa, self, "__DATA", "__thread_ptrs", .{ .flags = macho.S_THREAD_LOCAL_VARIABLE_POINTERS, }); } @@ -639,18 +639,18 @@ pub const Zld = struct { if (self.stubs_table.lookup.contains(target)) return; _ = try self.stubs_table.allocateEntry(self.gpa, target); if (self.stubs_section_index == null) { - self.stubs_section_index = try self.initSection("__TEXT", "__stubs", .{ + self.stubs_section_index = try MachO.initSection(self.gpa, self, "__TEXT", "__stubs", .{ .flags = macho.S_SYMBOL_STUBS | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS, .reserved2 = stubs.stubSize(self.options.target.cpu.arch), }); - self.stub_helper_section_index = try self.initSection("__TEXT", "__stub_helper", .{ + self.stub_helper_section_index = try MachO.initSection(self.gpa, self, "__TEXT", "__stub_helper", .{ .flags = macho.S_REGULAR | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS, }); - self.la_symbol_ptr_section_index = try self.initSection("__DATA", "__la_symbol_ptr", .{ + self.la_symbol_ptr_section_index = try MachO.initSection(self.gpa, self, "__DATA", "__la_symbol_ptr", .{ .flags = macho.S_LAZY_SYMBOL_POINTERS, }); } @@ -1152,34 +1152,6 @@ pub const Zld = struct { segment.vmsize = mem.alignForward(u64, segment.vmsize, page_size); } - const InitSectionOpts = struct { - flags: u32 = macho.S_REGULAR, - reserved1: u32 = 0, - reserved2: u32 = 0, - }; - - pub fn initSection( - self: *Zld, - segname: []const u8, - sectname: []const u8, - opts: InitSectionOpts, - ) !u8 { - const gpa = self.gpa; - log.debug("creating section '{s},{s}'", .{ segname, sectname }); - const index = @as(u8, @intCast(self.sections.slice().len)); - try self.sections.append(gpa, .{ - .segment_index = undefined, // Segments will be created automatically later down the pipeline - .header = .{ - .sectname = makeStaticString(sectname), - .segname = makeStaticString(segname), - .flags = opts.flags, - .reserved1 = opts.reserved1, - .reserved2 = opts.reserved2, - }, - }); - return index; - } - fn writeSegmentHeaders(self: *Zld, writer: anytype) !void { for (self.segments.items, 0..) |seg, i| { const indexes = self.getSectionIndexes(@as(u8, @intCast(i)));